1dde8a05bSUgen J.S. Antsilevich /* 2dde8a05bSUgen J.S. Antsilevich * Copyright (c) 1995 Ugen J.S.Antsilevich 3dde8a05bSUgen J.S. Antsilevich * 4dde8a05bSUgen J.S. Antsilevich * Redistribution and use in source forms, with and without modification, 5dde8a05bSUgen J.S. Antsilevich * are permitted provided that this entire comment appears intact. 6dde8a05bSUgen J.S. Antsilevich * 7dde8a05bSUgen J.S. Antsilevich * Redistribution in binary form may occur without any restrictions. 8dde8a05bSUgen J.S. Antsilevich * Obviously, it would be nice if you gave credit where credit is due 9dde8a05bSUgen J.S. Antsilevich * but requiring it would be too onerous. 10dde8a05bSUgen J.S. Antsilevich * 11dde8a05bSUgen J.S. Antsilevich * This software is provided ``AS IS'' without any warranties of any kind. 12dde8a05bSUgen J.S. Antsilevich * 13dde8a05bSUgen J.S. Antsilevich * Snoop stuff. 14dde8a05bSUgen J.S. Antsilevich */ 15dde8a05bSUgen J.S. Antsilevich 16dde8a05bSUgen J.S. Antsilevich #include "snp.h" 17dde8a05bSUgen J.S. Antsilevich 18019b4d63SUgen J.S. Antsilevich #if NSNP > 0 19dde8a05bSUgen J.S. Antsilevich 20dde8a05bSUgen J.S. Antsilevich #include <sys/param.h> 21dde8a05bSUgen J.S. Antsilevich #include <sys/systm.h> 22dde8a05bSUgen J.S. Antsilevich #include <sys/ioctl.h> 23dde8a05bSUgen J.S. Antsilevich #include <sys/ioctl_compat.h> /* Oooh..We need O/NTTYDISC */ 24dde8a05bSUgen J.S. Antsilevich #include <sys/proc.h> 25dde8a05bSUgen J.S. Antsilevich #define TTYDEFCHARS 26dde8a05bSUgen J.S. Antsilevich #include <sys/tty.h> 27dde8a05bSUgen J.S. Antsilevich #undef TTYDEFCHARS 28dde8a05bSUgen J.S. Antsilevich #include <sys/file.h> 29dde8a05bSUgen J.S. Antsilevich #include <sys/conf.h> 30dde8a05bSUgen J.S. Antsilevich #include <sys/uio.h> 31dde8a05bSUgen J.S. Antsilevich #include <sys/kernel.h> 32dde8a05bSUgen J.S. Antsilevich #include <sys/malloc.h> 33dde8a05bSUgen J.S. Antsilevich 34dde8a05bSUgen J.S. Antsilevich #include <sys/snoop.h> 35dde8a05bSUgen J.S. Antsilevich 3653ac6efbSJulian Elischer #ifdef JREMOD 3753ac6efbSJulian Elischer #ifdef DEVFS 3853ac6efbSJulian Elischer #include <sys/devfsext.h> 3953ac6efbSJulian Elischer #endif /*DEVFS*/ 4053ac6efbSJulian Elischer #define CDEV_MAJOR 53 4153ac6efbSJulian Elischer #endif /*JREMOD*/ 4253ac6efbSJulian Elischer 43dde8a05bSUgen J.S. Antsilevich #ifndef MIN 44dde8a05bSUgen J.S. Antsilevich #define MIN(a,b) (((a)<(b))?(a):(b)) 45dde8a05bSUgen J.S. Antsilevich #endif 46dde8a05bSUgen J.S. Antsilevich 47dde8a05bSUgen J.S. Antsilevich static struct snoop snoopsw[NSNP]; 48dde8a05bSUgen J.S. Antsilevich 4977f77631SPaul Traina static struct tty * 5077f77631SPaul Traina devtotty (dev) 5177f77631SPaul Traina dev_t dev; 5277f77631SPaul Traina { 5377f77631SPaul Traina if (major(dev) > nchrdev) 5477f77631SPaul Traina return (NULL); /* no such device available */ 5577f77631SPaul Traina 5677f77631SPaul Traina return (*cdevsw[major(dev)].d_devtotty)(dev); 5777f77631SPaul Traina } 5877f77631SPaul Traina 590739a0dcSUgen J.S. Antsilevich #define SNP_INPUT_BUF 5 /* This is even too much,the maximal 600739a0dcSUgen J.S. Antsilevich * interactive mode write is 3 bytes 610739a0dcSUgen J.S. Antsilevich * length for function keys... 620739a0dcSUgen J.S. Antsilevich */ 630739a0dcSUgen J.S. Antsilevich 640739a0dcSUgen J.S. Antsilevich int 650739a0dcSUgen J.S. Antsilevich snpwrite(dev, uio, flag) 660739a0dcSUgen J.S. Antsilevich dev_t dev; 670739a0dcSUgen J.S. Antsilevich struct uio *uio; 680739a0dcSUgen J.S. Antsilevich int flag; 690739a0dcSUgen J.S. Antsilevich { 700739a0dcSUgen J.S. Antsilevich int unit = minor(dev), len, i, error; 710739a0dcSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 720739a0dcSUgen J.S. Antsilevich struct tty *tp; 730739a0dcSUgen J.S. Antsilevich char c[SNP_INPUT_BUF]; 740739a0dcSUgen J.S. Antsilevich 750739a0dcSUgen J.S. Antsilevich if (snp->snp_tty == NULL) 760739a0dcSUgen J.S. Antsilevich return (EIO); 770739a0dcSUgen J.S. Antsilevich 780739a0dcSUgen J.S. Antsilevich tp = snp->snp_tty; 790739a0dcSUgen J.S. Antsilevich 800739a0dcSUgen J.S. Antsilevich if ((tp->t_sc == snp) && (tp->t_state & TS_SNOOP) && 810739a0dcSUgen J.S. Antsilevich (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) 820739a0dcSUgen J.S. Antsilevich goto tty_input; 830739a0dcSUgen J.S. Antsilevich 840739a0dcSUgen J.S. Antsilevich printf("Snoop: attempt to write to bad tty.\n"); 850739a0dcSUgen J.S. Antsilevich return (EIO); 860739a0dcSUgen J.S. Antsilevich 870739a0dcSUgen J.S. Antsilevich tty_input: 880739a0dcSUgen J.S. Antsilevich if (!(tp->t_state & TS_ISOPEN)) 890739a0dcSUgen J.S. Antsilevich return (EIO); 900739a0dcSUgen J.S. Antsilevich 910739a0dcSUgen J.S. Antsilevich while (uio->uio_resid > 0) { 920739a0dcSUgen J.S. Antsilevich len = MIN(uio->uio_resid,SNP_INPUT_BUF); 930739a0dcSUgen J.S. Antsilevich if ((error = uiomove(c, len, uio)) != 0) 940739a0dcSUgen J.S. Antsilevich return (error); 950739a0dcSUgen J.S. Antsilevich for (i=0;i<len;i++) { 960739a0dcSUgen J.S. Antsilevich if (ttyinput(c[i] , tp)) 970739a0dcSUgen J.S. Antsilevich return (EIO); 980739a0dcSUgen J.S. Antsilevich } 990739a0dcSUgen J.S. Antsilevich } 1000739a0dcSUgen J.S. Antsilevich return 0; 1010739a0dcSUgen J.S. Antsilevich 1020739a0dcSUgen J.S. Antsilevich } 1030739a0dcSUgen J.S. Antsilevich 1040739a0dcSUgen J.S. Antsilevich 105dde8a05bSUgen J.S. Antsilevich int 106dde8a05bSUgen J.S. Antsilevich snpread(dev, uio, flag) 107dde8a05bSUgen J.S. Antsilevich dev_t dev; 108dde8a05bSUgen J.S. Antsilevich struct uio *uio; 109dde8a05bSUgen J.S. Antsilevich int flag; 110dde8a05bSUgen J.S. Antsilevich { 111dde8a05bSUgen J.S. Antsilevich int unit = minor(dev), s; 112dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 113dde8a05bSUgen J.S. Antsilevich int len, n, nblen, error = 0; 114dde8a05bSUgen J.S. Antsilevich caddr_t from; 115dde8a05bSUgen J.S. Antsilevich char *nbuf; 116dde8a05bSUgen J.S. Antsilevich 117dde8a05bSUgen J.S. Antsilevich #ifdef DIAGNOSTIC 118dde8a05bSUgen J.S. Antsilevich if ((snp->snp_len + snp->snp_base) > snp->snp_blen) 119dde8a05bSUgen J.S. Antsilevich panic("snoop buffer error"); 120dde8a05bSUgen J.S. Antsilevich #endif 12177f77631SPaul Traina 1220739a0dcSUgen J.S. Antsilevich if (snp->snp_tty == NULL) 123dde8a05bSUgen J.S. Antsilevich return (EIO); 124dde8a05bSUgen J.S. Antsilevich 125dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_RWAIT; 126dde8a05bSUgen J.S. Antsilevich 127dde8a05bSUgen J.S. Antsilevich do { 128dde8a05bSUgen J.S. Antsilevich if (snp->snp_len == 0) { 129dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_NBIO) { 130dde8a05bSUgen J.S. Antsilevich return EWOULDBLOCK; 131dde8a05bSUgen J.S. Antsilevich } 132dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_RWAIT; 133dde8a05bSUgen J.S. Antsilevich tsleep((caddr_t) snp, (PZERO + 1) | PCATCH, "snoopread", 0); 134dde8a05bSUgen J.S. Antsilevich } 135dde8a05bSUgen J.S. Antsilevich } while (snp->snp_len == 0); 136dde8a05bSUgen J.S. Antsilevich 137019b4d63SUgen J.S. Antsilevich n = snp->snp_len; 138dde8a05bSUgen J.S. Antsilevich 139dde8a05bSUgen J.S. Antsilevich while (snp->snp_len > 0 && uio->uio_resid > 0 && error == 0) { 140dde8a05bSUgen J.S. Antsilevich len = MIN(uio->uio_resid, snp->snp_len); 141dde8a05bSUgen J.S. Antsilevich from = (caddr_t) (snp->snp_buf + snp->snp_base); 142dde8a05bSUgen J.S. Antsilevich if (len == 0) 143dde8a05bSUgen J.S. Antsilevich break; 144dde8a05bSUgen J.S. Antsilevich 145dde8a05bSUgen J.S. Antsilevich error = uiomove(from, len, uio); 146dde8a05bSUgen J.S. Antsilevich snp->snp_base += len; 147dde8a05bSUgen J.S. Antsilevich snp->snp_len -= len; 148dde8a05bSUgen J.S. Antsilevich } 149019b4d63SUgen J.S. Antsilevich if ((snp->snp_flags & SNOOP_OFLOW) && (n < snp->snp_len)) { 150dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_OFLOW; 151019b4d63SUgen J.S. Antsilevich } 152dde8a05bSUgen J.S. Antsilevich s = spltty(); 153dde8a05bSUgen J.S. Antsilevich nblen = snp->snp_blen; 154dde8a05bSUgen J.S. Antsilevich if (((nblen / 2) >= SNOOP_MINLEN) && (nblen / 2) >= snp->snp_len) { 155dde8a05bSUgen J.S. Antsilevich while (((nblen / 2) >= snp->snp_len) && ((nblen / 2) >= SNOOP_MINLEN)) 156dde8a05bSUgen J.S. Antsilevich nblen = nblen / 2; 157dde8a05bSUgen J.S. Antsilevich if (nbuf = malloc(nblen, M_TTYS, M_NOWAIT)) { 158dde8a05bSUgen J.S. Antsilevich bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 159dde8a05bSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 160dde8a05bSUgen J.S. Antsilevich snp->snp_buf = nbuf; 161dde8a05bSUgen J.S. Antsilevich snp->snp_blen = nblen; 162dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 163dde8a05bSUgen J.S. Antsilevich } 164dde8a05bSUgen J.S. Antsilevich } 165dde8a05bSUgen J.S. Antsilevich splx(s); 166dde8a05bSUgen J.S. Antsilevich 167dde8a05bSUgen J.S. Antsilevich return error; 168dde8a05bSUgen J.S. Antsilevich } 169dde8a05bSUgen J.S. Antsilevich 1700739a0dcSUgen J.S. Antsilevich int 1710739a0dcSUgen J.S. Antsilevich snpinc(snp, c) 1720739a0dcSUgen J.S. Antsilevich struct snoop *snp; 1730739a0dcSUgen J.S. Antsilevich char c; 1740739a0dcSUgen J.S. Antsilevich { 1750739a0dcSUgen J.S. Antsilevich char buf[1]; 1760739a0dcSUgen J.S. Antsilevich 1770739a0dcSUgen J.S. Antsilevich buf[0]=c; 1780739a0dcSUgen J.S. Antsilevich return (snpin(snp,buf,1)); 1790739a0dcSUgen J.S. Antsilevich } 1800739a0dcSUgen J.S. Antsilevich 181dde8a05bSUgen J.S. Antsilevich 182dde8a05bSUgen J.S. Antsilevich int 183dde8a05bSUgen J.S. Antsilevich snpin(snp, buf, n) 184dde8a05bSUgen J.S. Antsilevich struct snoop *snp; 185dde8a05bSUgen J.S. Antsilevich char *buf; 186dde8a05bSUgen J.S. Antsilevich int n; 187dde8a05bSUgen J.S. Antsilevich { 188dde8a05bSUgen J.S. Antsilevich int s_free, s_tail; 189dde8a05bSUgen J.S. Antsilevich int s, len, nblen; 190dde8a05bSUgen J.S. Antsilevich caddr_t from, to; 191dde8a05bSUgen J.S. Antsilevich char *nbuf; 192dde8a05bSUgen J.S. Antsilevich 193dde8a05bSUgen J.S. Antsilevich 194dde8a05bSUgen J.S. Antsilevich if (n == 0) 195dde8a05bSUgen J.S. Antsilevich return 0; 196dde8a05bSUgen J.S. Antsilevich 197dde8a05bSUgen J.S. Antsilevich #ifdef DIAGNOSTIC 198dde8a05bSUgen J.S. Antsilevich if (n < 0) 199dde8a05bSUgen J.S. Antsilevich panic("bad snoop char count"); 200dde8a05bSUgen J.S. Antsilevich 201019b4d63SUgen J.S. Antsilevich if (!(snp->snp_flags & SNOOP_OPEN)) { 202019b4d63SUgen J.S. Antsilevich printf("Snoop: data coming to closed device.\n"); 203019b4d63SUgen J.S. Antsilevich return 0; 204dde8a05bSUgen J.S. Antsilevich } 205019b4d63SUgen J.S. Antsilevich #endif 206019b4d63SUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_DOWN) { 207019b4d63SUgen J.S. Antsilevich printf("Snoop: more data to down interface.\n"); 208019b4d63SUgen J.S. Antsilevich return 0; 209019b4d63SUgen J.S. Antsilevich } 210964587caSUgen J.S. Antsilevich 211019b4d63SUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_OFLOW) { 212019b4d63SUgen J.S. Antsilevich printf("Snoop: buffer overflow.\n"); 213019b4d63SUgen J.S. Antsilevich /* 214019b4d63SUgen J.S. Antsilevich * On overflow we just repeat the standart close 215019b4d63SUgen J.S. Antsilevich * procedure...yes , this is waste of space but.. Then next 216019b4d63SUgen J.S. Antsilevich * read from device will fail if one would recall he is 217019b4d63SUgen J.S. Antsilevich * snooping and retry... 218019b4d63SUgen J.S. Antsilevich */ 219dde8a05bSUgen J.S. Antsilevich 220964587caSUgen J.S. Antsilevich return (snpdown(snp)); 221019b4d63SUgen J.S. Antsilevich } 222019b4d63SUgen J.S. Antsilevich s_tail = snp->snp_blen - (snp->snp_len + snp->snp_base); 223019b4d63SUgen J.S. Antsilevich s_free = snp->snp_blen - snp->snp_len; 224dde8a05bSUgen J.S. Antsilevich 225dde8a05bSUgen J.S. Antsilevich 226dde8a05bSUgen J.S. Antsilevich if (n > s_free) { 227dde8a05bSUgen J.S. Antsilevich s = spltty(); 228dde8a05bSUgen J.S. Antsilevich nblen = snp->snp_blen; 229dde8a05bSUgen J.S. Antsilevich while ((n > s_free) && ((nblen * 2) <= SNOOP_MAXLEN)) { 230dde8a05bSUgen J.S. Antsilevich nblen = snp->snp_blen * 2; 231dde8a05bSUgen J.S. Antsilevich s_free = nblen - (snp->snp_len + snp->snp_base); 232dde8a05bSUgen J.S. Antsilevich } 233dde8a05bSUgen J.S. Antsilevich if ((n <= s_free) && (nbuf = malloc(nblen, M_TTYS, M_NOWAIT))) { 234dde8a05bSUgen J.S. Antsilevich bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 235dde8a05bSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 236dde8a05bSUgen J.S. Antsilevich snp->snp_buf = nbuf; 237dde8a05bSUgen J.S. Antsilevich snp->snp_blen = nblen; 238dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 239dde8a05bSUgen J.S. Antsilevich } else { 240dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_OFLOW; 241dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_RWAIT) { 242dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_RWAIT; 243dde8a05bSUgen J.S. Antsilevich wakeup((caddr_t) snp); 244dde8a05bSUgen J.S. Antsilevich } 245dde8a05bSUgen J.S. Antsilevich splx(s); 246dde8a05bSUgen J.S. Antsilevich return 0; 247dde8a05bSUgen J.S. Antsilevich } 248dde8a05bSUgen J.S. Antsilevich splx(s); 249dde8a05bSUgen J.S. Antsilevich } 250dde8a05bSUgen J.S. Antsilevich if (n > s_tail) { 251dde8a05bSUgen J.S. Antsilevich from = (caddr_t) (snp->snp_buf + snp->snp_base); 252dde8a05bSUgen J.S. Antsilevich to = (caddr_t) (snp->snp_buf); 253dde8a05bSUgen J.S. Antsilevich len = snp->snp_len; 254dde8a05bSUgen J.S. Antsilevich bcopy(from, to, len); 255dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 256dde8a05bSUgen J.S. Antsilevich } 257dde8a05bSUgen J.S. Antsilevich to = (caddr_t) (snp->snp_buf + snp->snp_base + snp->snp_len); 258dde8a05bSUgen J.S. Antsilevich bcopy(buf, to, n); 259dde8a05bSUgen J.S. Antsilevich snp->snp_len += n; 260dde8a05bSUgen J.S. Antsilevich 261dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_RWAIT) { 262dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_RWAIT; 263dde8a05bSUgen J.S. Antsilevich wakeup((caddr_t) snp); 264dde8a05bSUgen J.S. Antsilevich } 265dde8a05bSUgen J.S. Antsilevich selwakeup(&snp->snp_sel); 266dde8a05bSUgen J.S. Antsilevich snp->snp_sel.si_pid = 0; 267dde8a05bSUgen J.S. Antsilevich 268dde8a05bSUgen J.S. Antsilevich return n; 269dde8a05bSUgen J.S. Antsilevich } 270dde8a05bSUgen J.S. Antsilevich 271dde8a05bSUgen J.S. Antsilevich int 272dde8a05bSUgen J.S. Antsilevich snpopen(dev, flag, mode, p) 273dde8a05bSUgen J.S. Antsilevich dev_t dev; 274dde8a05bSUgen J.S. Antsilevich int flag, mode; 275dde8a05bSUgen J.S. Antsilevich struct proc *p; 276dde8a05bSUgen J.S. Antsilevich { 277dde8a05bSUgen J.S. Antsilevich struct snoop *snp; 278dde8a05bSUgen J.S. Antsilevich register int unit, error; 279dde8a05bSUgen J.S. Antsilevich 280dde8a05bSUgen J.S. Antsilevich if (error = suser(p->p_ucred, &p->p_acflag)) 281dde8a05bSUgen J.S. Antsilevich return (error); 282dde8a05bSUgen J.S. Antsilevich 283dde8a05bSUgen J.S. Antsilevich if ((unit = minor(dev)) >= NSNP) 284dde8a05bSUgen J.S. Antsilevich return (ENXIO); 28577f77631SPaul Traina 286dde8a05bSUgen J.S. Antsilevich snp = &snoopsw[unit]; 28777f77631SPaul Traina 288dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_OPEN) 289dde8a05bSUgen J.S. Antsilevich return (ENXIO); 29077f77631SPaul Traina 291019b4d63SUgen J.S. Antsilevich /* 292019b4d63SUgen J.S. Antsilevich * We intentionally do not OR flags with SNOOP_OPEN,but set them so 293019b4d63SUgen J.S. Antsilevich * all previous settings (especially SNOOP_OFLOW) will be cleared. 294019b4d63SUgen J.S. Antsilevich */ 295019b4d63SUgen J.S. Antsilevich snp->snp_flags = SNOOP_OPEN; 296dde8a05bSUgen J.S. Antsilevich 297dde8a05bSUgen J.S. Antsilevich snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 298dde8a05bSUgen J.S. Antsilevich snp->snp_blen = SNOOP_MINLEN; 299dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 300dde8a05bSUgen J.S. Antsilevich snp->snp_len = 0; 301dde8a05bSUgen J.S. Antsilevich 302dde8a05bSUgen J.S. Antsilevich /* 3030739a0dcSUgen J.S. Antsilevich * snp_tty == NULL is for inactive snoop devices. 304dde8a05bSUgen J.S. Antsilevich */ 3050739a0dcSUgen J.S. Antsilevich snp->snp_tty = NULL; 30677f77631SPaul Traina snp->snp_target = -1; 307dde8a05bSUgen J.S. Antsilevich return (0); 308dde8a05bSUgen J.S. Antsilevich } 309dde8a05bSUgen J.S. Antsilevich 310019b4d63SUgen J.S. Antsilevich 311019b4d63SUgen J.S. Antsilevich int 312019b4d63SUgen J.S. Antsilevich snp_detach(snp) 313019b4d63SUgen J.S. Antsilevich struct snoop *snp; 314019b4d63SUgen J.S. Antsilevich { 315019b4d63SUgen J.S. Antsilevich struct tty *tp; 316019b4d63SUgen J.S. Antsilevich 317019b4d63SUgen J.S. Antsilevich snp->snp_base = 0; 318019b4d63SUgen J.S. Antsilevich snp->snp_len = 0; 319019b4d63SUgen J.S. Antsilevich 320019b4d63SUgen J.S. Antsilevich /* 321019b4d63SUgen J.S. Antsilevich * If line disc. changed we do not touch this pointer,SLIP/PPP will 322019b4d63SUgen J.S. Antsilevich * change it anyway. 323019b4d63SUgen J.S. Antsilevich */ 324019b4d63SUgen J.S. Antsilevich 3250739a0dcSUgen J.S. Antsilevich if (snp->snp_tty == NULL) 326964587caSUgen J.S. Antsilevich goto detach_notty; 327019b4d63SUgen J.S. Antsilevich 3280739a0dcSUgen J.S. Antsilevich tp = snp->snp_tty; 329019b4d63SUgen J.S. Antsilevich 33077f77631SPaul Traina if (tp && (tp->t_sc == snp) && (tp->t_state & TS_SNOOP) && 331019b4d63SUgen J.S. Antsilevich (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) { 332019b4d63SUgen J.S. Antsilevich tp->t_sc = NULL; 333019b4d63SUgen J.S. Antsilevich tp->t_state &= ~TS_SNOOP; 334019b4d63SUgen J.S. Antsilevich } else 335019b4d63SUgen J.S. Antsilevich printf("Snoop: bad attached tty data.\n"); 336019b4d63SUgen J.S. Antsilevich 3370739a0dcSUgen J.S. Antsilevich snp->snp_tty = NULL; 33877f77631SPaul Traina snp->snp_target = -1; 339019b4d63SUgen J.S. Antsilevich 340964587caSUgen J.S. Antsilevich detach_notty: 341019b4d63SUgen J.S. Antsilevich selwakeup(&snp->snp_sel); 342019b4d63SUgen J.S. Antsilevich snp->snp_sel.si_pid = 0; 343019b4d63SUgen J.S. Antsilevich 344019b4d63SUgen J.S. Antsilevich return (0); 345019b4d63SUgen J.S. Antsilevich } 346019b4d63SUgen J.S. Antsilevich 347dde8a05bSUgen J.S. Antsilevich int 34860039670SBruce Evans snpclose(dev, flags, fmt, p) 349dde8a05bSUgen J.S. Antsilevich dev_t dev; 35060039670SBruce Evans int flags; 35160039670SBruce Evans int fmt; 35260039670SBruce Evans struct proc *p; 353dde8a05bSUgen J.S. Antsilevich { 354dde8a05bSUgen J.S. Antsilevich register int unit = minor(dev); 355dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 356dde8a05bSUgen J.S. Antsilevich 357dde8a05bSUgen J.S. Antsilevich snp->snp_blen = 0; 358dde8a05bSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 359019b4d63SUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_OPEN; 360dde8a05bSUgen J.S. Antsilevich 361019b4d63SUgen J.S. Antsilevich return (snp_detach(snp)); 362dde8a05bSUgen J.S. Antsilevich } 363dde8a05bSUgen J.S. Antsilevich 364964587caSUgen J.S. Antsilevich int 365964587caSUgen J.S. Antsilevich snpdown(snp) 366964587caSUgen J.S. Antsilevich struct snoop *snp; 367964587caSUgen J.S. Antsilevich { 368964587caSUgen J.S. Antsilevich snp->snp_blen = SNOOP_MINLEN; 369964587caSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 370964587caSUgen J.S. Antsilevich snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 371964587caSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_DOWN; 372dde8a05bSUgen J.S. Antsilevich 373964587caSUgen J.S. Antsilevich return (snp_detach(snp)); 374964587caSUgen J.S. Antsilevich } 375dde8a05bSUgen J.S. Antsilevich 376dde8a05bSUgen J.S. Antsilevich 377dde8a05bSUgen J.S. Antsilevich int 37860039670SBruce Evans snpioctl(dev, cmd, data, flags, p) 379dde8a05bSUgen J.S. Antsilevich dev_t dev; 380dde8a05bSUgen J.S. Antsilevich int cmd; 381dde8a05bSUgen J.S. Antsilevich caddr_t data; 38260039670SBruce Evans int flags; 38360039670SBruce Evans struct proc *p; 384dde8a05bSUgen J.S. Antsilevich { 385dde8a05bSUgen J.S. Antsilevich int unit = minor(dev), s; 38677f77631SPaul Traina dev_t tdev; 387dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 388dde8a05bSUgen J.S. Antsilevich struct tty *tp, *tpo; 389dde8a05bSUgen J.S. Antsilevich 390dde8a05bSUgen J.S. Antsilevich switch (cmd) { 391dde8a05bSUgen J.S. Antsilevich case SNPSTTY: 39277f77631SPaul Traina tdev = *((dev_t *) data); 39377f77631SPaul Traina if (tdev == -1) 394964587caSUgen J.S. Antsilevich return (snpdown(snp)); 395964587caSUgen J.S. Antsilevich 39677f77631SPaul Traina tp = devtotty(tdev); 39777f77631SPaul Traina if (!tp) 398dde8a05bSUgen J.S. Antsilevich return (EINVAL); 399dde8a05bSUgen J.S. Antsilevich 40077f77631SPaul Traina if ((tp->t_sc != (caddr_t) snp) && (tp->t_state & TS_SNOOP)) 401dde8a05bSUgen J.S. Antsilevich return (EBUSY); 402dde8a05bSUgen J.S. Antsilevich 40377f77631SPaul Traina if ((tp->t_line != OTTYDISC) && (tp->t_line != NTTYDISC)) 404dde8a05bSUgen J.S. Antsilevich return (EBUSY); 405dde8a05bSUgen J.S. Antsilevich 406dde8a05bSUgen J.S. Antsilevich s = spltty(); 40777f77631SPaul Traina 40877f77631SPaul Traina if (snp->snp_target == -1) { 4090739a0dcSUgen J.S. Antsilevich tpo = snp->snp_tty; 41077f77631SPaul Traina if (tpo) 411dde8a05bSUgen J.S. Antsilevich tpo->t_state &= ~TS_SNOOP; 412dde8a05bSUgen J.S. Antsilevich } 41377f77631SPaul Traina 414dde8a05bSUgen J.S. Antsilevich tp->t_sc = (caddr_t) snp; 415dde8a05bSUgen J.S. Antsilevich tp->t_state |= TS_SNOOP; 4160739a0dcSUgen J.S. Antsilevich snp->snp_tty = tp; 41777f77631SPaul Traina snp->snp_target = tdev; 41877f77631SPaul Traina 419964587caSUgen J.S. Antsilevich /* 420964587caSUgen J.S. Antsilevich * Clean overflow and down flags - 421964587caSUgen J.S. Antsilevich * we'll have a chance to get them in the future :))) 422964587caSUgen J.S. Antsilevich */ 423964587caSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_OFLOW; 424019b4d63SUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_DOWN; 425dde8a05bSUgen J.S. Antsilevich splx(s); 426dde8a05bSUgen J.S. Antsilevich break; 42777f77631SPaul Traina 428dde8a05bSUgen J.S. Antsilevich case SNPGTTY: 4290739a0dcSUgen J.S. Antsilevich /* 4300739a0dcSUgen J.S. Antsilevich * We keep snp_target field specially to make 4310739a0dcSUgen J.S. Antsilevich * SNPGTTY happy,else we can't know what is device 4320739a0dcSUgen J.S. Antsilevich * major/minor for tty. 4330739a0dcSUgen J.S. Antsilevich */ 43477f77631SPaul Traina *((dev_t *) data) = snp->snp_target; 435dde8a05bSUgen J.S. Antsilevich break; 436dde8a05bSUgen J.S. Antsilevich 437dde8a05bSUgen J.S. Antsilevich case FIONBIO: 438dde8a05bSUgen J.S. Antsilevich if (*(int *) data) 439dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_NBIO; 440dde8a05bSUgen J.S. Antsilevich else 441dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_NBIO; 442dde8a05bSUgen J.S. Antsilevich break; 44377f77631SPaul Traina 444dde8a05bSUgen J.S. Antsilevich case FIOASYNC: 445dde8a05bSUgen J.S. Antsilevich if (*(int *) data) 446dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_ASYNC; 447dde8a05bSUgen J.S. Antsilevich else 448dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_ASYNC; 449dde8a05bSUgen J.S. Antsilevich break; 45077f77631SPaul Traina 451dde8a05bSUgen J.S. Antsilevich case FIONREAD: 452dde8a05bSUgen J.S. Antsilevich s = spltty(); 4530739a0dcSUgen J.S. Antsilevich if (snp->snp_tty != NULL) 454dde8a05bSUgen J.S. Antsilevich *(int *) data = snp->snp_len; 455dde8a05bSUgen J.S. Antsilevich else 456964587caSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_DOWN) { 457964587caSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_OFLOW) 458964587caSUgen J.S. Antsilevich *(int *) data = SNP_OFLOW; 459964587caSUgen J.S. Antsilevich else 460964587caSUgen J.S. Antsilevich *(int *) data = SNP_TTYCLOSE; 461964587caSUgen J.S. Antsilevich } else { 462964587caSUgen J.S. Antsilevich *(int *) data = SNP_DETACH; 463964587caSUgen J.S. Antsilevich } 464dde8a05bSUgen J.S. Antsilevich splx(s); 465dde8a05bSUgen J.S. Antsilevich break; 46677f77631SPaul Traina 467dde8a05bSUgen J.S. Antsilevich default: 468dde8a05bSUgen J.S. Antsilevich return (ENOTTY); 469dde8a05bSUgen J.S. Antsilevich } 470dde8a05bSUgen J.S. Antsilevich return (0); 471dde8a05bSUgen J.S. Antsilevich } 472dde8a05bSUgen J.S. Antsilevich 473dde8a05bSUgen J.S. Antsilevich 474dde8a05bSUgen J.S. Antsilevich int 475dde8a05bSUgen J.S. Antsilevich snpselect(dev, rw, p) 476dde8a05bSUgen J.S. Antsilevich dev_t dev; 477dde8a05bSUgen J.S. Antsilevich int rw; 478dde8a05bSUgen J.S. Antsilevich struct proc *p; 479dde8a05bSUgen J.S. Antsilevich { 480a98ca469SPoul-Henning Kamp int unit = minor(dev); 481dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 482dde8a05bSUgen J.S. Antsilevich 48377f77631SPaul Traina if (rw != FREAD) 4840739a0dcSUgen J.S. Antsilevich return 1; 48577f77631SPaul Traina 48677f77631SPaul Traina if (snp->snp_len > 0) 487dde8a05bSUgen J.S. Antsilevich return 1; 48877f77631SPaul Traina 489019b4d63SUgen J.S. Antsilevich /* 490019b4d63SUgen J.S. Antsilevich * If snoop is down,we don't want to select() forever so we return 1. 491019b4d63SUgen J.S. Antsilevich * Caller should see if we down via FIONREAD ioctl().The last should 492019b4d63SUgen J.S. Antsilevich * return -1 to indicate down state. 493019b4d63SUgen J.S. Antsilevich */ 49477f77631SPaul Traina if (snp->snp_flags & SNOOP_DOWN) 495019b4d63SUgen J.S. Antsilevich return 1; 49677f77631SPaul Traina 497dde8a05bSUgen J.S. Antsilevich selrecord(p, &snp->snp_sel); 498dde8a05bSUgen J.S. Antsilevich return 0; 499dde8a05bSUgen J.S. Antsilevich } 500dde8a05bSUgen J.S. Antsilevich 50153ac6efbSJulian Elischer #ifdef JREMOD 50253ac6efbSJulian Elischer struct cdevsw snp_cdevsw = 50353ac6efbSJulian Elischer { snpopen, snpclose, snpread, snpwrite, /*53*/ 50453ac6efbSJulian Elischer snpioctl, nostop, nullreset, nodevtotty,/* snoop */ 50553ac6efbSJulian Elischer snpselect, nommap, NULL }; 50653ac6efbSJulian Elischer 50753ac6efbSJulian Elischer static snp_devsw_installed = 0; 50853ac6efbSJulian Elischer 50953ac6efbSJulian Elischer static void snp_drvinit(void *unused) 51053ac6efbSJulian Elischer { 51153ac6efbSJulian Elischer dev_t dev; 51253ac6efbSJulian Elischer 51353ac6efbSJulian Elischer if( ! snp_devsw_installed ) { 51453ac6efbSJulian Elischer dev = makedev(CDEV_MAJOR,0); 51553ac6efbSJulian Elischer cdevsw_add(&dev,&snp_cdevsw,NULL); 51653ac6efbSJulian Elischer snp_devsw_installed = 1; 51753ac6efbSJulian Elischer #ifdef DEVFS 51853ac6efbSJulian Elischer { 51953ac6efbSJulian Elischer int x; 52053ac6efbSJulian Elischer /* default for a simple device with no probe routine (usually delete this) */ 52153ac6efbSJulian Elischer x=devfs_add_devsw( 52253ac6efbSJulian Elischer /* path name devsw minor type uid gid perm*/ 52353ac6efbSJulian Elischer "/", "snp", major(dev), 0, DV_CHR, 0, 0, 0600); 52453ac6efbSJulian Elischer } 52553ac6efbSJulian Elischer #endif 52653ac6efbSJulian Elischer } 5277198bf47SJulian Elischer } 52853ac6efbSJulian Elischer 52953ac6efbSJulian Elischer SYSINIT(snpdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,snp_drvinit,NULL) 53053ac6efbSJulian Elischer 53153ac6efbSJulian Elischer #endif /* JREMOD */ 53253ac6efbSJulian Elischer 533dde8a05bSUgen J.S. Antsilevich #endif 534