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 36dde8a05bSUgen J.S. Antsilevich #ifndef MIN 37dde8a05bSUgen J.S. Antsilevich #define MIN(a,b) (((a)<(b))?(a):(b)) 38dde8a05bSUgen J.S. Antsilevich #endif 39dde8a05bSUgen J.S. Antsilevich 40dde8a05bSUgen J.S. Antsilevich static struct snoop snoopsw[NSNP]; 41dde8a05bSUgen J.S. Antsilevich 4277f77631SPaul Traina static struct tty * 4377f77631SPaul Traina devtotty (dev) 4477f77631SPaul Traina dev_t dev; 4577f77631SPaul Traina { 4677f77631SPaul Traina if (major(dev) > nchrdev) 4777f77631SPaul Traina return (NULL); /* no such device available */ 4877f77631SPaul Traina 4977f77631SPaul Traina return (*cdevsw[major(dev)].d_devtotty)(dev); 5077f77631SPaul Traina } 5177f77631SPaul Traina 52dde8a05bSUgen J.S. Antsilevich int 53dde8a05bSUgen J.S. Antsilevich snpread(dev, uio, flag) 54dde8a05bSUgen J.S. Antsilevich dev_t dev; 55dde8a05bSUgen J.S. Antsilevich struct uio *uio; 56dde8a05bSUgen J.S. Antsilevich int flag; 57dde8a05bSUgen J.S. Antsilevich { 58dde8a05bSUgen J.S. Antsilevich int unit = minor(dev), s; 59dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 60dde8a05bSUgen J.S. Antsilevich int len, n, nblen, error = 0; 61dde8a05bSUgen J.S. Antsilevich caddr_t from; 62dde8a05bSUgen J.S. Antsilevich char *nbuf; 63dde8a05bSUgen J.S. Antsilevich 64dde8a05bSUgen J.S. Antsilevich #ifdef DIAGNOSTIC 65dde8a05bSUgen J.S. Antsilevich if ((snp->snp_len + snp->snp_base) > snp->snp_blen) 66dde8a05bSUgen J.S. Antsilevich panic("snoop buffer error"); 67dde8a05bSUgen J.S. Antsilevich #endif 6877f77631SPaul Traina 6977f77631SPaul Traina if (snp->snp_target == -1) 70dde8a05bSUgen J.S. Antsilevich return (EIO); 71dde8a05bSUgen J.S. Antsilevich 72dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_RWAIT; 73dde8a05bSUgen J.S. Antsilevich 74dde8a05bSUgen J.S. Antsilevich do { 75dde8a05bSUgen J.S. Antsilevich if (snp->snp_len == 0) { 76dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_NBIO) { 77dde8a05bSUgen J.S. Antsilevich return EWOULDBLOCK; 78dde8a05bSUgen J.S. Antsilevich } 79dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_RWAIT; 80dde8a05bSUgen J.S. Antsilevich tsleep((caddr_t) snp, (PZERO + 1) | PCATCH, "snoopread", 0); 81dde8a05bSUgen J.S. Antsilevich } 82dde8a05bSUgen J.S. Antsilevich } while (snp->snp_len == 0); 83dde8a05bSUgen J.S. Antsilevich 84019b4d63SUgen J.S. Antsilevich n = snp->snp_len; 85dde8a05bSUgen J.S. Antsilevich 86dde8a05bSUgen J.S. Antsilevich while (snp->snp_len > 0 && uio->uio_resid > 0 && error == 0) { 87dde8a05bSUgen J.S. Antsilevich len = MIN(uio->uio_resid, snp->snp_len); 88dde8a05bSUgen J.S. Antsilevich from = (caddr_t) (snp->snp_buf + snp->snp_base); 89dde8a05bSUgen J.S. Antsilevich if (len == 0) 90dde8a05bSUgen J.S. Antsilevich break; 91dde8a05bSUgen J.S. Antsilevich 92dde8a05bSUgen J.S. Antsilevich error = uiomove(from, len, uio); 93dde8a05bSUgen J.S. Antsilevich snp->snp_base += len; 94dde8a05bSUgen J.S. Antsilevich snp->snp_len -= len; 95dde8a05bSUgen J.S. Antsilevich } 96019b4d63SUgen J.S. Antsilevich if ((snp->snp_flags & SNOOP_OFLOW) && (n < snp->snp_len)) { 97dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_OFLOW; 98019b4d63SUgen J.S. Antsilevich } 99dde8a05bSUgen J.S. Antsilevich s = spltty(); 100dde8a05bSUgen J.S. Antsilevich nblen = snp->snp_blen; 101dde8a05bSUgen J.S. Antsilevich if (((nblen / 2) >= SNOOP_MINLEN) && (nblen / 2) >= snp->snp_len) { 102dde8a05bSUgen J.S. Antsilevich while (((nblen / 2) >= snp->snp_len) && ((nblen / 2) >= SNOOP_MINLEN)) 103dde8a05bSUgen J.S. Antsilevich nblen = nblen / 2; 104dde8a05bSUgen J.S. Antsilevich if (nbuf = malloc(nblen, M_TTYS, M_NOWAIT)) { 105dde8a05bSUgen J.S. Antsilevich bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 106dde8a05bSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 107dde8a05bSUgen J.S. Antsilevich snp->snp_buf = nbuf; 108dde8a05bSUgen J.S. Antsilevich snp->snp_blen = nblen; 109dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 110dde8a05bSUgen J.S. Antsilevich } 111dde8a05bSUgen J.S. Antsilevich } 112dde8a05bSUgen J.S. Antsilevich splx(s); 113dde8a05bSUgen J.S. Antsilevich 114dde8a05bSUgen J.S. Antsilevich return error; 115dde8a05bSUgen J.S. Antsilevich } 116dde8a05bSUgen J.S. Antsilevich 117dde8a05bSUgen J.S. Antsilevich 118dde8a05bSUgen J.S. Antsilevich int 119dde8a05bSUgen J.S. Antsilevich snpin(snp, buf, n) 120dde8a05bSUgen J.S. Antsilevich struct snoop *snp; 121dde8a05bSUgen J.S. Antsilevich char *buf; 122dde8a05bSUgen J.S. Antsilevich int n; 123dde8a05bSUgen J.S. Antsilevich { 124dde8a05bSUgen J.S. Antsilevich int s_free, s_tail; 125dde8a05bSUgen J.S. Antsilevich int s, len, nblen; 126dde8a05bSUgen J.S. Antsilevich caddr_t from, to; 127dde8a05bSUgen J.S. Antsilevich char *nbuf; 128dde8a05bSUgen J.S. Antsilevich struct tty *tp; 129dde8a05bSUgen J.S. Antsilevich 130dde8a05bSUgen J.S. Antsilevich 131dde8a05bSUgen J.S. Antsilevich if (n == 0) 132dde8a05bSUgen J.S. Antsilevich return 0; 133dde8a05bSUgen J.S. Antsilevich 134dde8a05bSUgen J.S. Antsilevich #ifdef DIAGNOSTIC 135dde8a05bSUgen J.S. Antsilevich if (n < 0) 136dde8a05bSUgen J.S. Antsilevich panic("bad snoop char count"); 137dde8a05bSUgen J.S. Antsilevich 138019b4d63SUgen J.S. Antsilevich if (!(snp->snp_flags & SNOOP_OPEN)) { 139019b4d63SUgen J.S. Antsilevich printf("Snoop: data coming to closed device.\n"); 140019b4d63SUgen J.S. Antsilevich return 0; 141dde8a05bSUgen J.S. Antsilevich } 142019b4d63SUgen J.S. Antsilevich #endif 143019b4d63SUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_DOWN) { 144019b4d63SUgen J.S. Antsilevich printf("Snoop: more data to down interface.\n"); 145019b4d63SUgen J.S. Antsilevich return 0; 146019b4d63SUgen J.S. Antsilevich } 147964587caSUgen J.S. Antsilevich 148019b4d63SUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_OFLOW) { 149019b4d63SUgen J.S. Antsilevich printf("Snoop: buffer overflow.\n"); 150019b4d63SUgen J.S. Antsilevich /* 151019b4d63SUgen J.S. Antsilevich * On overflow we just repeat the standart close 152019b4d63SUgen J.S. Antsilevich * procedure...yes , this is waste of space but.. Then next 153019b4d63SUgen J.S. Antsilevich * read from device will fail if one would recall he is 154019b4d63SUgen J.S. Antsilevich * snooping and retry... 155019b4d63SUgen J.S. Antsilevich */ 156dde8a05bSUgen J.S. Antsilevich 157964587caSUgen J.S. Antsilevich return (snpdown(snp)); 158019b4d63SUgen J.S. Antsilevich } 159019b4d63SUgen J.S. Antsilevich s_tail = snp->snp_blen - (snp->snp_len + snp->snp_base); 160019b4d63SUgen J.S. Antsilevich s_free = snp->snp_blen - snp->snp_len; 161dde8a05bSUgen J.S. Antsilevich 162dde8a05bSUgen J.S. Antsilevich 163dde8a05bSUgen J.S. Antsilevich if (n > s_free) { 164dde8a05bSUgen J.S. Antsilevich s = spltty(); 165dde8a05bSUgen J.S. Antsilevich nblen = snp->snp_blen; 166dde8a05bSUgen J.S. Antsilevich while ((n > s_free) && ((nblen * 2) <= SNOOP_MAXLEN)) { 167dde8a05bSUgen J.S. Antsilevich nblen = snp->snp_blen * 2; 168dde8a05bSUgen J.S. Antsilevich s_free = nblen - (snp->snp_len + snp->snp_base); 169dde8a05bSUgen J.S. Antsilevich } 170dde8a05bSUgen J.S. Antsilevich if ((n <= s_free) && (nbuf = malloc(nblen, M_TTYS, M_NOWAIT))) { 171dde8a05bSUgen J.S. Antsilevich bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 172dde8a05bSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 173dde8a05bSUgen J.S. Antsilevich snp->snp_buf = nbuf; 174dde8a05bSUgen J.S. Antsilevich snp->snp_blen = nblen; 175dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 176dde8a05bSUgen J.S. Antsilevich } else { 177dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_OFLOW; 178dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_RWAIT) { 179dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_RWAIT; 180dde8a05bSUgen J.S. Antsilevich wakeup((caddr_t) snp); 181dde8a05bSUgen J.S. Antsilevich } 182dde8a05bSUgen J.S. Antsilevich splx(s); 183dde8a05bSUgen J.S. Antsilevich return 0; 184dde8a05bSUgen J.S. Antsilevich } 185dde8a05bSUgen J.S. Antsilevich splx(s); 186dde8a05bSUgen J.S. Antsilevich } 187dde8a05bSUgen J.S. Antsilevich if (n > s_tail) { 188dde8a05bSUgen J.S. Antsilevich from = (caddr_t) (snp->snp_buf + snp->snp_base); 189dde8a05bSUgen J.S. Antsilevich to = (caddr_t) (snp->snp_buf); 190dde8a05bSUgen J.S. Antsilevich len = snp->snp_len; 191dde8a05bSUgen J.S. Antsilevich bcopy(from, to, len); 192dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 193dde8a05bSUgen J.S. Antsilevich } 194dde8a05bSUgen J.S. Antsilevich to = (caddr_t) (snp->snp_buf + snp->snp_base + snp->snp_len); 195dde8a05bSUgen J.S. Antsilevich bcopy(buf, to, n); 196dde8a05bSUgen J.S. Antsilevich snp->snp_len += n; 197dde8a05bSUgen J.S. Antsilevich 198dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_RWAIT) { 199dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_RWAIT; 200dde8a05bSUgen J.S. Antsilevich wakeup((caddr_t) snp); 201dde8a05bSUgen J.S. Antsilevich } 202dde8a05bSUgen J.S. Antsilevich selwakeup(&snp->snp_sel); 203dde8a05bSUgen J.S. Antsilevich snp->snp_sel.si_pid = 0; 204dde8a05bSUgen J.S. Antsilevich 205dde8a05bSUgen J.S. Antsilevich return n; 206dde8a05bSUgen J.S. Antsilevich } 207dde8a05bSUgen J.S. Antsilevich 208dde8a05bSUgen J.S. Antsilevich int 209dde8a05bSUgen J.S. Antsilevich snpopen(dev, flag, mode, p) 210dde8a05bSUgen J.S. Antsilevich dev_t dev; 211dde8a05bSUgen J.S. Antsilevich int flag, mode; 212dde8a05bSUgen J.S. Antsilevich struct proc *p; 213dde8a05bSUgen J.S. Antsilevich { 214dde8a05bSUgen J.S. Antsilevich struct snoop *snp; 215dde8a05bSUgen J.S. Antsilevich register int unit, error; 216dde8a05bSUgen J.S. Antsilevich 217dde8a05bSUgen J.S. Antsilevich if (error = suser(p->p_ucred, &p->p_acflag)) 218dde8a05bSUgen J.S. Antsilevich return (error); 219dde8a05bSUgen J.S. Antsilevich 220dde8a05bSUgen J.S. Antsilevich if ((unit = minor(dev)) >= NSNP) 221dde8a05bSUgen J.S. Antsilevich return (ENXIO); 22277f77631SPaul Traina 223dde8a05bSUgen J.S. Antsilevich snp = &snoopsw[unit]; 22477f77631SPaul Traina 225dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_OPEN) 226dde8a05bSUgen J.S. Antsilevich return (ENXIO); 22777f77631SPaul Traina 228019b4d63SUgen J.S. Antsilevich /* 229019b4d63SUgen J.S. Antsilevich * We intentionally do not OR flags with SNOOP_OPEN,but set them so 230019b4d63SUgen J.S. Antsilevich * all previous settings (especially SNOOP_OFLOW) will be cleared. 231019b4d63SUgen J.S. Antsilevich */ 232019b4d63SUgen J.S. Antsilevich snp->snp_flags = SNOOP_OPEN; 233dde8a05bSUgen J.S. Antsilevich 234dde8a05bSUgen J.S. Antsilevich snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 235dde8a05bSUgen J.S. Antsilevich snp->snp_blen = SNOOP_MINLEN; 236dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 237dde8a05bSUgen J.S. Antsilevich snp->snp_len = 0; 238dde8a05bSUgen J.S. Antsilevich 239dde8a05bSUgen J.S. Antsilevich /* 240019b4d63SUgen J.S. Antsilevich * unit == -1 is for inactive snoop devices. 241dde8a05bSUgen J.S. Antsilevich */ 24277f77631SPaul Traina snp->snp_target = -1; 243dde8a05bSUgen J.S. Antsilevich return (0); 244dde8a05bSUgen J.S. Antsilevich } 245dde8a05bSUgen J.S. Antsilevich 246019b4d63SUgen J.S. Antsilevich 247019b4d63SUgen J.S. Antsilevich int 248019b4d63SUgen J.S. Antsilevich snp_detach(snp) 249019b4d63SUgen J.S. Antsilevich struct snoop *snp; 250019b4d63SUgen J.S. Antsilevich { 251019b4d63SUgen J.S. Antsilevich struct tty *tp; 252019b4d63SUgen J.S. Antsilevich 253019b4d63SUgen J.S. Antsilevich snp->snp_base = 0; 254019b4d63SUgen J.S. Antsilevich snp->snp_len = 0; 255019b4d63SUgen J.S. Antsilevich 256019b4d63SUgen J.S. Antsilevich /* 257019b4d63SUgen J.S. Antsilevich * If line disc. changed we do not touch this pointer,SLIP/PPP will 258019b4d63SUgen J.S. Antsilevich * change it anyway. 259019b4d63SUgen J.S. Antsilevich */ 260019b4d63SUgen J.S. Antsilevich 26177f77631SPaul Traina if (snp->snp_target == -1) 262964587caSUgen J.S. Antsilevich goto detach_notty; 263019b4d63SUgen J.S. Antsilevich 26477f77631SPaul Traina tp = devtotty(snp->snp_target); 265019b4d63SUgen J.S. Antsilevich 26677f77631SPaul Traina if (tp && (tp->t_sc == snp) && (tp->t_state & TS_SNOOP) && 267019b4d63SUgen J.S. Antsilevich (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) { 268019b4d63SUgen J.S. Antsilevich tp->t_sc = NULL; 269019b4d63SUgen J.S. Antsilevich tp->t_state &= ~TS_SNOOP; 270019b4d63SUgen J.S. Antsilevich } else 271019b4d63SUgen J.S. Antsilevich printf("Snoop: bad attached tty data.\n"); 272019b4d63SUgen J.S. Antsilevich 27377f77631SPaul Traina snp->snp_target = -1; 274019b4d63SUgen J.S. Antsilevich 275964587caSUgen J.S. Antsilevich detach_notty: 276019b4d63SUgen J.S. Antsilevich selwakeup(&snp->snp_sel); 277019b4d63SUgen J.S. Antsilevich snp->snp_sel.si_pid = 0; 278019b4d63SUgen J.S. Antsilevich 279019b4d63SUgen J.S. Antsilevich return (0); 280019b4d63SUgen J.S. Antsilevich } 281019b4d63SUgen J.S. Antsilevich 282dde8a05bSUgen J.S. Antsilevich int 283dde8a05bSUgen J.S. Antsilevich snpclose(dev, flag) 284dde8a05bSUgen J.S. Antsilevich dev_t dev; 285dde8a05bSUgen J.S. Antsilevich int flag; 286dde8a05bSUgen J.S. Antsilevich { 287dde8a05bSUgen J.S. Antsilevich register int unit = minor(dev); 288dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 289dde8a05bSUgen J.S. Antsilevich 290dde8a05bSUgen J.S. Antsilevich snp->snp_blen = 0; 291dde8a05bSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 292019b4d63SUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_OPEN; 293dde8a05bSUgen J.S. Antsilevich 294019b4d63SUgen J.S. Antsilevich return (snp_detach(snp)); 295dde8a05bSUgen J.S. Antsilevich } 296dde8a05bSUgen J.S. Antsilevich 297964587caSUgen J.S. Antsilevich int 298964587caSUgen J.S. Antsilevich snpdown(snp) 299964587caSUgen J.S. Antsilevich struct snoop *snp; 300964587caSUgen J.S. Antsilevich { 301964587caSUgen J.S. Antsilevich snp->snp_blen = SNOOP_MINLEN; 302964587caSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 303964587caSUgen J.S. Antsilevich snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 304964587caSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_DOWN; 305dde8a05bSUgen J.S. Antsilevich 306964587caSUgen J.S. Antsilevich return (snp_detach(snp)); 307964587caSUgen J.S. Antsilevich } 308dde8a05bSUgen J.S. Antsilevich 309dde8a05bSUgen J.S. Antsilevich 310dde8a05bSUgen J.S. Antsilevich int 311dde8a05bSUgen J.S. Antsilevich snpioctl(dev, cmd, data, flag) 312dde8a05bSUgen J.S. Antsilevich dev_t dev; 313dde8a05bSUgen J.S. Antsilevich int cmd; 314dde8a05bSUgen J.S. Antsilevich caddr_t data; 315dde8a05bSUgen J.S. Antsilevich int flag; 316dde8a05bSUgen J.S. Antsilevich { 317dde8a05bSUgen J.S. Antsilevich int unit = minor(dev), s; 31877f77631SPaul Traina dev_t tdev; 319dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 320dde8a05bSUgen J.S. Antsilevich struct tty *tp, *tpo; 321dde8a05bSUgen J.S. Antsilevich 322dde8a05bSUgen J.S. Antsilevich switch (cmd) { 323dde8a05bSUgen J.S. Antsilevich case SNPSTTY: 32477f77631SPaul Traina tdev = *((dev_t *) data); 32577f77631SPaul Traina if (tdev == -1) 326964587caSUgen J.S. Antsilevich return (snpdown(snp)); 327964587caSUgen J.S. Antsilevich 32877f77631SPaul Traina tp = devtotty(tdev); 32977f77631SPaul Traina if (!tp) 330dde8a05bSUgen J.S. Antsilevich return (EINVAL); 331dde8a05bSUgen J.S. Antsilevich 33277f77631SPaul Traina if ((tp->t_sc != (caddr_t) snp) && (tp->t_state & TS_SNOOP)) 333dde8a05bSUgen J.S. Antsilevich return (EBUSY); 334dde8a05bSUgen J.S. Antsilevich 33577f77631SPaul Traina if ((tp->t_line != OTTYDISC) && (tp->t_line != NTTYDISC)) 336dde8a05bSUgen J.S. Antsilevich return (EBUSY); 337dde8a05bSUgen J.S. Antsilevich 338dde8a05bSUgen J.S. Antsilevich s = spltty(); 33977f77631SPaul Traina 34077f77631SPaul Traina if (snp->snp_target == -1) { 34177f77631SPaul Traina tpo = devtotty(snp->snp_target); 34277f77631SPaul Traina if (tpo) 343dde8a05bSUgen J.S. Antsilevich tpo->t_state &= ~TS_SNOOP; 344dde8a05bSUgen J.S. Antsilevich } 34577f77631SPaul Traina 346dde8a05bSUgen J.S. Antsilevich tp->t_sc = (caddr_t) snp; 347dde8a05bSUgen J.S. Antsilevich tp->t_state |= TS_SNOOP; 34877f77631SPaul Traina snp->snp_target = tdev; 34977f77631SPaul Traina 350964587caSUgen J.S. Antsilevich /* 351964587caSUgen J.S. Antsilevich * Clean overflow and down flags - 352964587caSUgen J.S. Antsilevich * we'll have a chance to get them in the future :))) 353964587caSUgen J.S. Antsilevich */ 354964587caSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_OFLOW; 355019b4d63SUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_DOWN; 356dde8a05bSUgen J.S. Antsilevich splx(s); 357dde8a05bSUgen J.S. Antsilevich break; 35877f77631SPaul Traina 359dde8a05bSUgen J.S. Antsilevich case SNPGTTY: 36077f77631SPaul Traina *((dev_t *) data) = snp->snp_target; 361dde8a05bSUgen J.S. Antsilevich break; 362dde8a05bSUgen J.S. Antsilevich 363dde8a05bSUgen J.S. Antsilevich case FIONBIO: 364dde8a05bSUgen J.S. Antsilevich if (*(int *) data) 365dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_NBIO; 366dde8a05bSUgen J.S. Antsilevich else 367dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_NBIO; 368dde8a05bSUgen J.S. Antsilevich break; 36977f77631SPaul Traina 370dde8a05bSUgen J.S. Antsilevich case FIOASYNC: 371dde8a05bSUgen J.S. Antsilevich if (*(int *) data) 372dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_ASYNC; 373dde8a05bSUgen J.S. Antsilevich else 374dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_ASYNC; 375dde8a05bSUgen J.S. Antsilevich break; 37677f77631SPaul Traina 377dde8a05bSUgen J.S. Antsilevich case FIONREAD: 378dde8a05bSUgen J.S. Antsilevich s = spltty(); 37977f77631SPaul Traina if (snp->snp_target != -1) 380dde8a05bSUgen J.S. Antsilevich *(int *) data = snp->snp_len; 381dde8a05bSUgen J.S. Antsilevich else 382964587caSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_DOWN) { 383964587caSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_OFLOW) 384964587caSUgen J.S. Antsilevich *(int *) data = SNP_OFLOW; 385964587caSUgen J.S. Antsilevich else 386964587caSUgen J.S. Antsilevich *(int *) data = SNP_TTYCLOSE; 387964587caSUgen J.S. Antsilevich } else { 388964587caSUgen J.S. Antsilevich *(int *) data = SNP_DETACH; 389964587caSUgen J.S. Antsilevich } 390dde8a05bSUgen J.S. Antsilevich splx(s); 391dde8a05bSUgen J.S. Antsilevich break; 39277f77631SPaul Traina 393dde8a05bSUgen J.S. Antsilevich default: 394dde8a05bSUgen J.S. Antsilevich return (ENOTTY); 395dde8a05bSUgen J.S. Antsilevich } 396dde8a05bSUgen J.S. Antsilevich return (0); 397dde8a05bSUgen J.S. Antsilevich } 398dde8a05bSUgen J.S. Antsilevich 399dde8a05bSUgen J.S. Antsilevich 400dde8a05bSUgen J.S. Antsilevich int 401dde8a05bSUgen J.S. Antsilevich snpselect(dev, rw, p) 402dde8a05bSUgen J.S. Antsilevich dev_t dev; 403dde8a05bSUgen J.S. Antsilevich int rw; 404dde8a05bSUgen J.S. Antsilevich struct proc *p; 405dde8a05bSUgen J.S. Antsilevich { 406dde8a05bSUgen J.S. Antsilevich int unit = minor(dev), s; 407dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 408dde8a05bSUgen J.S. Antsilevich 40977f77631SPaul Traina if (rw != FREAD) 410dde8a05bSUgen J.S. Antsilevich return 0; 41177f77631SPaul Traina 41277f77631SPaul Traina if (snp->snp_len > 0) 413dde8a05bSUgen J.S. Antsilevich return 1; 41477f77631SPaul Traina 415019b4d63SUgen J.S. Antsilevich /* 416019b4d63SUgen J.S. Antsilevich * If snoop is down,we don't want to select() forever so we return 1. 417019b4d63SUgen J.S. Antsilevich * Caller should see if we down via FIONREAD ioctl().The last should 418019b4d63SUgen J.S. Antsilevich * return -1 to indicate down state. 419019b4d63SUgen J.S. Antsilevich */ 42077f77631SPaul Traina if (snp->snp_flags & SNOOP_DOWN) 421019b4d63SUgen J.S. Antsilevich return 1; 42277f77631SPaul Traina 423dde8a05bSUgen J.S. Antsilevich selrecord(p, &snp->snp_sel); 424dde8a05bSUgen J.S. Antsilevich return 0; 425dde8a05bSUgen J.S. Antsilevich } 426dde8a05bSUgen J.S. Antsilevich 427dde8a05bSUgen J.S. Antsilevich #endif 428