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 37dde8a05bSUgen J.S. Antsilevich 38dde8a05bSUgen J.S. Antsilevich #ifdef ST_PTY 39dde8a05bSUgen J.S. Antsilevich /* 40dde8a05bSUgen J.S. Antsilevich * This should be same as in "kern/tty_pty.c" 41dde8a05bSUgen J.S. Antsilevich */ 42dde8a05bSUgen J.S. Antsilevich #include "pty.h" 43dde8a05bSUgen J.S. Antsilevich 44dde8a05bSUgen J.S. Antsilevich #if NPTY == 1 45dde8a05bSUgen J.S. Antsilevich #undef NPTY 46dde8a05bSUgen J.S. Antsilevich #define NPTY 32 47dde8a05bSUgen J.S. Antsilevich #endif 48dde8a05bSUgen J.S. Antsilevich 49dde8a05bSUgen J.S. Antsilevich extern struct tty pt_tty[]; 50dde8a05bSUgen J.S. Antsilevich #endif /* ST_PTY */ 51dde8a05bSUgen J.S. Antsilevich 52dde8a05bSUgen J.S. Antsilevich 53dde8a05bSUgen J.S. Antsilevich #ifdef ST_SIO 54dde8a05bSUgen J.S. Antsilevich /* 55dde8a05bSUgen J.S. Antsilevich * This should be same as "i386/isa/sio.c" 56dde8a05bSUgen J.S. Antsilevich */ 57dde8a05bSUgen J.S. Antsilevich #include "sio.h" 58dde8a05bSUgen J.S. Antsilevich 59dde8a05bSUgen J.S. Antsilevich extern struct tty sio_tty[]; 60dde8a05bSUgen J.S. Antsilevich #endif /* ST_SIO */ 61dde8a05bSUgen J.S. Antsilevich 62dde8a05bSUgen J.S. Antsilevich 63dde8a05bSUgen J.S. Antsilevich #ifdef ST_VTY 64dde8a05bSUgen J.S. Antsilevich /* 65dde8a05bSUgen J.S. Antsilevich * This should match "i386/isa/sc.c" 66dde8a05bSUgen J.S. Antsilevich */ 67dde8a05bSUgen J.S. Antsilevich 68dde8a05bSUgen J.S. Antsilevich #if !defined(MAXCONS) 69dde8a05bSUgen J.S. Antsilevich #define MAXCONS 16 70dde8a05bSUgen J.S. Antsilevich #endif 71dde8a05bSUgen J.S. Antsilevich 72dde8a05bSUgen J.S. Antsilevich extern struct tty sccons[]; 73dde8a05bSUgen J.S. Antsilevich #endif /* ST_VTY */ 74dde8a05bSUgen J.S. Antsilevich 75dde8a05bSUgen J.S. Antsilevich 76dde8a05bSUgen J.S. Antsilevich /* 77019b4d63SUgen J.S. Antsilevich * This is local structure to hold data for all tty arrays we serve. 78dde8a05bSUgen J.S. Antsilevich */ 79dde8a05bSUgen J.S. Antsilevich typedef struct tty tty_arr[]; 80dde8a05bSUgen J.S. Antsilevich struct tty_tab { 81dde8a05bSUgen J.S. Antsilevich int lt_max; 82dde8a05bSUgen J.S. Antsilevich tty_arr *lt_tab; 83dde8a05bSUgen J.S. Antsilevich }; 84dde8a05bSUgen J.S. Antsilevich 85dde8a05bSUgen J.S. Antsilevich static struct tty_tab tty_tabs[] = { 86dde8a05bSUgen J.S. Antsilevich #ifdef ST_PTY 87dde8a05bSUgen J.S. Antsilevich {NPTY, &pt_tty}, 88dde8a05bSUgen J.S. Antsilevich #else 89dde8a05bSUgen J.S. Antsilevich {-1, NULL}, 90dde8a05bSUgen J.S. Antsilevich #endif 91dde8a05bSUgen J.S. Antsilevich #ifdef ST_VTY 92dde8a05bSUgen J.S. Antsilevich {MAXCONS, &sccons}, 93dde8a05bSUgen J.S. Antsilevich #else 94dde8a05bSUgen J.S. Antsilevich {-1, NULL}, 95dde8a05bSUgen J.S. Antsilevich #endif 96dde8a05bSUgen J.S. Antsilevich #ifdef ST_SIO 97dde8a05bSUgen J.S. Antsilevich {NSIO, &sio_tty} 98dde8a05bSUgen J.S. Antsilevich #else 99dde8a05bSUgen J.S. Antsilevich {-1, NULL} 100dde8a05bSUgen J.S. Antsilevich #endif 101dde8a05bSUgen J.S. Antsilevich }; 102dde8a05bSUgen J.S. Antsilevich 103dde8a05bSUgen J.S. Antsilevich 104dde8a05bSUgen J.S. Antsilevich #ifndef MIN 105dde8a05bSUgen J.S. Antsilevich #define MIN(a,b) (((a)<(b))?(a):(b)) 106dde8a05bSUgen J.S. Antsilevich #endif 107dde8a05bSUgen J.S. Antsilevich 108dde8a05bSUgen J.S. Antsilevich 109dde8a05bSUgen J.S. Antsilevich static struct snoop snoopsw[NSNP]; 110dde8a05bSUgen J.S. Antsilevich 111dde8a05bSUgen J.S. Antsilevich int 112dde8a05bSUgen J.S. Antsilevich snpread(dev, uio, flag) 113dde8a05bSUgen J.S. Antsilevich dev_t dev; 114dde8a05bSUgen J.S. Antsilevich struct uio *uio; 115dde8a05bSUgen J.S. Antsilevich int flag; 116dde8a05bSUgen J.S. Antsilevich { 117dde8a05bSUgen J.S. Antsilevich int unit = minor(dev), s; 118dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 119dde8a05bSUgen J.S. Antsilevich int len, n, nblen, error = 0; 120dde8a05bSUgen J.S. Antsilevich caddr_t from; 121dde8a05bSUgen J.S. Antsilevich char *nbuf; 122dde8a05bSUgen J.S. Antsilevich 123dde8a05bSUgen J.S. Antsilevich #ifdef DIAGNOSTIC 124dde8a05bSUgen J.S. Antsilevich if ((snp->snp_len + snp->snp_base) > snp->snp_blen) 125dde8a05bSUgen J.S. Antsilevich panic("snoop buffer error"); 126dde8a05bSUgen J.S. Antsilevich #endif 127dde8a05bSUgen J.S. Antsilevich if (snp->snp_unit == -1) 128dde8a05bSUgen J.S. Antsilevich return (EIO); 129dde8a05bSUgen J.S. Antsilevich 130dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_RWAIT; 131dde8a05bSUgen J.S. Antsilevich 132dde8a05bSUgen J.S. Antsilevich do { 133dde8a05bSUgen J.S. Antsilevich if (snp->snp_len == 0) { 134dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_NBIO) { 135dde8a05bSUgen J.S. Antsilevich return EWOULDBLOCK; 136dde8a05bSUgen J.S. Antsilevich } 137dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_RWAIT; 138dde8a05bSUgen J.S. Antsilevich tsleep((caddr_t) snp, (PZERO + 1) | PCATCH, "snoopread", 0); 139dde8a05bSUgen J.S. Antsilevich } 140dde8a05bSUgen J.S. Antsilevich } while (snp->snp_len == 0); 141dde8a05bSUgen J.S. Antsilevich 142019b4d63SUgen J.S. Antsilevich n = snp->snp_len; 143dde8a05bSUgen J.S. Antsilevich 144dde8a05bSUgen J.S. Antsilevich while (snp->snp_len > 0 && uio->uio_resid > 0 && error == 0) { 145dde8a05bSUgen J.S. Antsilevich len = MIN(uio->uio_resid, snp->snp_len); 146dde8a05bSUgen J.S. Antsilevich from = (caddr_t) (snp->snp_buf + snp->snp_base); 147dde8a05bSUgen J.S. Antsilevich if (len == 0) 148dde8a05bSUgen J.S. Antsilevich break; 149dde8a05bSUgen J.S. Antsilevich 150dde8a05bSUgen J.S. Antsilevich error = uiomove(from, len, uio); 151dde8a05bSUgen J.S. Antsilevich snp->snp_base += len; 152dde8a05bSUgen J.S. Antsilevich snp->snp_len -= len; 153dde8a05bSUgen J.S. Antsilevich } 154019b4d63SUgen J.S. Antsilevich if ((snp->snp_flags & SNOOP_OFLOW) && (n < snp->snp_len)) { 155dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_OFLOW; 156019b4d63SUgen J.S. Antsilevich } 157dde8a05bSUgen J.S. Antsilevich s = spltty(); 158dde8a05bSUgen J.S. Antsilevich nblen = snp->snp_blen; 159dde8a05bSUgen J.S. Antsilevich if (((nblen / 2) >= SNOOP_MINLEN) && (nblen / 2) >= snp->snp_len) { 160dde8a05bSUgen J.S. Antsilevich while (((nblen / 2) >= snp->snp_len) && ((nblen / 2) >= SNOOP_MINLEN)) 161dde8a05bSUgen J.S. Antsilevich nblen = nblen / 2; 162dde8a05bSUgen J.S. Antsilevich if (nbuf = malloc(nblen, M_TTYS, M_NOWAIT)) { 163dde8a05bSUgen J.S. Antsilevich bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 164dde8a05bSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 165dde8a05bSUgen J.S. Antsilevich snp->snp_buf = nbuf; 166dde8a05bSUgen J.S. Antsilevich snp->snp_blen = nblen; 167dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 168dde8a05bSUgen J.S. Antsilevich } 169dde8a05bSUgen J.S. Antsilevich } 170dde8a05bSUgen J.S. Antsilevich splx(s); 171dde8a05bSUgen J.S. Antsilevich 172dde8a05bSUgen J.S. Antsilevich return error; 173dde8a05bSUgen J.S. Antsilevich } 174dde8a05bSUgen J.S. Antsilevich 175dde8a05bSUgen J.S. Antsilevich 176dde8a05bSUgen J.S. Antsilevich int 177dde8a05bSUgen J.S. Antsilevich snpin(snp, buf, n) 178dde8a05bSUgen J.S. Antsilevich struct snoop *snp; 179dde8a05bSUgen J.S. Antsilevich char *buf; 180dde8a05bSUgen J.S. Antsilevich int n; 181dde8a05bSUgen J.S. Antsilevich { 182dde8a05bSUgen J.S. Antsilevich int s_free, s_tail; 183dde8a05bSUgen J.S. Antsilevich int s, len, nblen; 184dde8a05bSUgen J.S. Antsilevich caddr_t from, to; 185dde8a05bSUgen J.S. Antsilevich char *nbuf; 186dde8a05bSUgen J.S. Antsilevich struct tty_tab *l_tty; 187dde8a05bSUgen J.S. Antsilevich struct tty *tp; 188dde8a05bSUgen J.S. Antsilevich 189dde8a05bSUgen J.S. Antsilevich 190dde8a05bSUgen J.S. Antsilevich if (n == 0) 191dde8a05bSUgen J.S. Antsilevich return 0; 192dde8a05bSUgen J.S. Antsilevich 193dde8a05bSUgen J.S. Antsilevich #ifdef DIAGNOSTIC 194dde8a05bSUgen J.S. Antsilevich if (n < 0) 195dde8a05bSUgen J.S. Antsilevich panic("bad snoop char count"); 196dde8a05bSUgen J.S. Antsilevich 197019b4d63SUgen J.S. Antsilevich if (!(snp->snp_flags & SNOOP_OPEN)) { 198019b4d63SUgen J.S. Antsilevich printf("Snoop: data coming to closed device.\n"); 199019b4d63SUgen J.S. Antsilevich return 0; 200dde8a05bSUgen J.S. Antsilevich } 201019b4d63SUgen J.S. Antsilevich #endif 202019b4d63SUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_DOWN) { 203019b4d63SUgen J.S. Antsilevich printf("Snoop: more data to down interface.\n"); 204019b4d63SUgen J.S. Antsilevich return 0; 205019b4d63SUgen J.S. Antsilevich } 206019b4d63SUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_OFLOW) { 207019b4d63SUgen J.S. Antsilevich printf("Snoop: buffer overflow.\n"); 208019b4d63SUgen J.S. Antsilevich /* 209019b4d63SUgen J.S. Antsilevich * On overflow we just repeat the standart close 210019b4d63SUgen J.S. Antsilevich * procedure...yes , this is waste of space but.. Then next 211019b4d63SUgen J.S. Antsilevich * read from device will fail if one would recall he is 212019b4d63SUgen J.S. Antsilevich * snooping and retry... 213019b4d63SUgen J.S. Antsilevich */ 214dde8a05bSUgen J.S. Antsilevich 215019b4d63SUgen J.S. Antsilevich snp->snp_blen = SNOOP_MINLEN; 216019b4d63SUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 217019b4d63SUgen J.S. Antsilevich snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 218019b4d63SUgen J.S. Antsilevich snp->snp_flags |= SNOOP_DOWN; 219019b4d63SUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_OFLOW; 220019b4d63SUgen J.S. Antsilevich 221019b4d63SUgen J.S. Antsilevich return (snp_detach(snp)); 222019b4d63SUgen J.S. Antsilevich } 223019b4d63SUgen J.S. Antsilevich s_tail = snp->snp_blen - (snp->snp_len + snp->snp_base); 224019b4d63SUgen J.S. Antsilevich s_free = snp->snp_blen - snp->snp_len; 225dde8a05bSUgen J.S. Antsilevich 226dde8a05bSUgen J.S. Antsilevich 227dde8a05bSUgen J.S. Antsilevich if (n > s_free) { 228dde8a05bSUgen J.S. Antsilevich s = spltty(); 229dde8a05bSUgen J.S. Antsilevich nblen = snp->snp_blen; 230dde8a05bSUgen J.S. Antsilevich while ((n > s_free) && ((nblen * 2) <= SNOOP_MAXLEN)) { 231dde8a05bSUgen J.S. Antsilevich nblen = snp->snp_blen * 2; 232dde8a05bSUgen J.S. Antsilevich s_free = nblen - (snp->snp_len + snp->snp_base); 233dde8a05bSUgen J.S. Antsilevich } 234dde8a05bSUgen J.S. Antsilevich if ((n <= s_free) && (nbuf = malloc(nblen, M_TTYS, M_NOWAIT))) { 235dde8a05bSUgen J.S. Antsilevich bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len); 236dde8a05bSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 237dde8a05bSUgen J.S. Antsilevich snp->snp_buf = nbuf; 238dde8a05bSUgen J.S. Antsilevich snp->snp_blen = nblen; 239dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 240dde8a05bSUgen J.S. Antsilevich } else { 241dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_OFLOW; 242dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_RWAIT) { 243dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_RWAIT; 244dde8a05bSUgen J.S. Antsilevich wakeup((caddr_t) snp); 245dde8a05bSUgen J.S. Antsilevich } 246dde8a05bSUgen J.S. Antsilevich splx(s); 247dde8a05bSUgen J.S. Antsilevich return 0; 248dde8a05bSUgen J.S. Antsilevich } 249dde8a05bSUgen J.S. Antsilevich splx(s); 250dde8a05bSUgen J.S. Antsilevich } 251dde8a05bSUgen J.S. Antsilevich if (n > s_tail) { 252dde8a05bSUgen J.S. Antsilevich from = (caddr_t) (snp->snp_buf + snp->snp_base); 253dde8a05bSUgen J.S. Antsilevich to = (caddr_t) (snp->snp_buf); 254dde8a05bSUgen J.S. Antsilevich len = snp->snp_len; 255dde8a05bSUgen J.S. Antsilevich bcopy(from, to, len); 256dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 257dde8a05bSUgen J.S. Antsilevich } 258dde8a05bSUgen J.S. Antsilevich to = (caddr_t) (snp->snp_buf + snp->snp_base + snp->snp_len); 259dde8a05bSUgen J.S. Antsilevich bcopy(buf, to, n); 260dde8a05bSUgen J.S. Antsilevich snp->snp_len += n; 261dde8a05bSUgen J.S. Antsilevich 262dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_RWAIT) { 263dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_RWAIT; 264dde8a05bSUgen J.S. Antsilevich wakeup((caddr_t) snp); 265dde8a05bSUgen J.S. Antsilevich } 266dde8a05bSUgen J.S. Antsilevich selwakeup(&snp->snp_sel); 267dde8a05bSUgen J.S. Antsilevich snp->snp_sel.si_pid = 0; 268dde8a05bSUgen J.S. Antsilevich 269dde8a05bSUgen J.S. Antsilevich return n; 270dde8a05bSUgen J.S. Antsilevich } 271dde8a05bSUgen J.S. Antsilevich 272dde8a05bSUgen J.S. Antsilevich int 273dde8a05bSUgen J.S. Antsilevich snpopen(dev, flag, mode, p) 274dde8a05bSUgen J.S. Antsilevich dev_t dev; 275dde8a05bSUgen J.S. Antsilevich int flag, mode; 276dde8a05bSUgen J.S. Antsilevich struct proc *p; 277dde8a05bSUgen J.S. Antsilevich { 278dde8a05bSUgen J.S. Antsilevich struct snoop *snp; 279dde8a05bSUgen J.S. Antsilevich register int unit, error; 280dde8a05bSUgen J.S. Antsilevich 281dde8a05bSUgen J.S. Antsilevich if (error = suser(p->p_ucred, &p->p_acflag)) 282dde8a05bSUgen J.S. Antsilevich return (error); 283dde8a05bSUgen J.S. Antsilevich 284dde8a05bSUgen J.S. Antsilevich if ((unit = minor(dev)) >= NSNP) 285dde8a05bSUgen J.S. Antsilevich return (ENXIO); 286dde8a05bSUgen J.S. Antsilevich snp = &snoopsw[unit]; 287dde8a05bSUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_OPEN) 288dde8a05bSUgen J.S. Antsilevich return (ENXIO); 289019b4d63SUgen J.S. Antsilevich /* 290019b4d63SUgen J.S. Antsilevich * We intentionally do not OR flags with SNOOP_OPEN,but set them so 291019b4d63SUgen J.S. Antsilevich * all previous settings (especially SNOOP_OFLOW) will be cleared. 292019b4d63SUgen J.S. Antsilevich */ 293019b4d63SUgen J.S. Antsilevich snp->snp_flags = SNOOP_OPEN; 294dde8a05bSUgen J.S. Antsilevich 295dde8a05bSUgen J.S. Antsilevich snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK); 296dde8a05bSUgen J.S. Antsilevich snp->snp_blen = SNOOP_MINLEN; 297dde8a05bSUgen J.S. Antsilevich snp->snp_base = 0; 298dde8a05bSUgen J.S. Antsilevich snp->snp_len = 0; 299dde8a05bSUgen J.S. Antsilevich 300dde8a05bSUgen J.S. Antsilevich /* 301019b4d63SUgen J.S. Antsilevich * unit == -1 is for inactive snoop devices. 302dde8a05bSUgen J.S. Antsilevich */ 303dde8a05bSUgen J.S. Antsilevich snp->snp_unit = -1; 304dde8a05bSUgen J.S. Antsilevich 305dde8a05bSUgen J.S. Antsilevich return (0); 306dde8a05bSUgen J.S. Antsilevich } 307dde8a05bSUgen J.S. Antsilevich 308019b4d63SUgen J.S. Antsilevich 309019b4d63SUgen J.S. Antsilevich int 310019b4d63SUgen J.S. Antsilevich snp_detach(snp) 311019b4d63SUgen J.S. Antsilevich struct snoop *snp; 312019b4d63SUgen J.S. Antsilevich { 313019b4d63SUgen J.S. Antsilevich struct tty *tp; 314019b4d63SUgen J.S. Antsilevich struct tty_tab *l_tty; 315019b4d63SUgen J.S. Antsilevich 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 325019b4d63SUgen J.S. Antsilevich if (snp->snp_unit == -1) 326019b4d63SUgen J.S. Antsilevich goto destroy_notty; 327019b4d63SUgen J.S. Antsilevich 328019b4d63SUgen J.S. Antsilevich 329019b4d63SUgen J.S. Antsilevich l_tty = &tty_tabs[snp->snp_type]; 330019b4d63SUgen J.S. Antsilevich tp = &((*l_tty->lt_tab)[snp->snp_unit]); 331019b4d63SUgen J.S. Antsilevich 332019b4d63SUgen J.S. Antsilevich if ((tp->t_sc == snp) && (tp->t_state & TS_SNOOP) && 333019b4d63SUgen J.S. Antsilevich (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) { 334019b4d63SUgen J.S. Antsilevich tp->t_sc = NULL; 335019b4d63SUgen J.S. Antsilevich tp->t_state &= ~TS_SNOOP; 336019b4d63SUgen J.S. Antsilevich } else 337019b4d63SUgen J.S. Antsilevich printf("Snoop: bad attached tty data.\n"); 338019b4d63SUgen J.S. Antsilevich 339019b4d63SUgen J.S. Antsilevich snp->snp_unit = -1; 340019b4d63SUgen J.S. Antsilevich 341019b4d63SUgen J.S. Antsilevich destroy_notty: 342019b4d63SUgen J.S. Antsilevich selwakeup(&snp->snp_sel); 343019b4d63SUgen J.S. Antsilevich snp->snp_sel.si_pid = 0; 344019b4d63SUgen J.S. Antsilevich 345019b4d63SUgen J.S. Antsilevich return (0); 346019b4d63SUgen J.S. Antsilevich } 347019b4d63SUgen J.S. Antsilevich 348dde8a05bSUgen J.S. Antsilevich int 349dde8a05bSUgen J.S. Antsilevich snpclose(dev, flag) 350dde8a05bSUgen J.S. Antsilevich dev_t dev; 351dde8a05bSUgen J.S. Antsilevich int flag; 352dde8a05bSUgen J.S. Antsilevich { 353dde8a05bSUgen J.S. Antsilevich register int unit = minor(dev); 354dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 355dde8a05bSUgen J.S. Antsilevich 356dde8a05bSUgen J.S. Antsilevich snp->snp_blen = 0; 357dde8a05bSUgen J.S. Antsilevich free(snp->snp_buf, M_TTYS); 358019b4d63SUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_OPEN; 359dde8a05bSUgen J.S. Antsilevich 360019b4d63SUgen J.S. Antsilevich return (snp_detach(snp)); 361dde8a05bSUgen J.S. Antsilevich } 362dde8a05bSUgen J.S. Antsilevich 363dde8a05bSUgen J.S. Antsilevich 364dde8a05bSUgen J.S. Antsilevich 365dde8a05bSUgen J.S. Antsilevich 366dde8a05bSUgen J.S. Antsilevich int 367dde8a05bSUgen J.S. Antsilevich snpioctl(dev, cmd, data, flag) 368dde8a05bSUgen J.S. Antsilevich dev_t dev; 369dde8a05bSUgen J.S. Antsilevich int cmd; 370dde8a05bSUgen J.S. Antsilevich caddr_t data; 371dde8a05bSUgen J.S. Antsilevich int flag; 372dde8a05bSUgen J.S. Antsilevich { 373dde8a05bSUgen J.S. Antsilevich int unit = minor(dev), s; 374dde8a05bSUgen J.S. Antsilevich int tunit, ttype; 375dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 376dde8a05bSUgen J.S. Antsilevich struct tty *tp, *tpo; 377dde8a05bSUgen J.S. Antsilevich struct tty_tab *l_tty, *l_otty; 378dde8a05bSUgen J.S. Antsilevich 379dde8a05bSUgen J.S. Antsilevich switch (cmd) { 380dde8a05bSUgen J.S. Antsilevich case SNPSTTY: 381dde8a05bSUgen J.S. Antsilevich tunit = ((struct snptty *) data)->st_unit; 382dde8a05bSUgen J.S. Antsilevich ttype = ((struct snptty *) data)->st_type; 383dde8a05bSUgen J.S. Antsilevich 384dde8a05bSUgen J.S. Antsilevich if (ttype < 0 || ttype > ST_MAXTYPE) 385dde8a05bSUgen J.S. Antsilevich return (EINVAL); 386dde8a05bSUgen J.S. Antsilevich 387dde8a05bSUgen J.S. Antsilevich l_tty = &tty_tabs[ttype]; 388dde8a05bSUgen J.S. Antsilevich if (l_tty->lt_tab == NULL) 389dde8a05bSUgen J.S. Antsilevich return (EINVAL); 390dde8a05bSUgen J.S. Antsilevich 391dde8a05bSUgen J.S. Antsilevich if (tunit < 0 || tunit >= l_tty->lt_max) 392dde8a05bSUgen J.S. Antsilevich return (EINVAL); 393dde8a05bSUgen J.S. Antsilevich 394dde8a05bSUgen J.S. Antsilevich tp = &((*l_tty->lt_tab)[tunit]); 395dde8a05bSUgen J.S. Antsilevich 396dde8a05bSUgen J.S. Antsilevich if (tp->t_sc != (caddr_t) snp && (tp->t_state & TS_SNOOP)) 397dde8a05bSUgen J.S. Antsilevich return (EBUSY); 398dde8a05bSUgen J.S. Antsilevich 399dde8a05bSUgen J.S. Antsilevich if (tp->t_line != OTTYDISC && tp->t_line != NTTYDISC) 400dde8a05bSUgen J.S. Antsilevich return (EBUSY); 401dde8a05bSUgen J.S. Antsilevich 402dde8a05bSUgen J.S. Antsilevich s = spltty(); 403dde8a05bSUgen J.S. Antsilevich if (snp->snp_unit != -1) { 404dde8a05bSUgen J.S. Antsilevich l_otty = &tty_tabs[snp->snp_type]; 405dde8a05bSUgen J.S. Antsilevich tpo = &((*l_otty->lt_tab)[snp->snp_unit]); 406dde8a05bSUgen J.S. Antsilevich tpo->t_state &= ~TS_SNOOP; 407dde8a05bSUgen J.S. Antsilevich } 408dde8a05bSUgen J.S. Antsilevich tp->t_sc = (caddr_t) snp; 409dde8a05bSUgen J.S. Antsilevich tp->t_state |= TS_SNOOP; 410dde8a05bSUgen J.S. Antsilevich snp->snp_unit = tunit; 411019b4d63SUgen J.S. Antsilevich snp->snp_type = ttype; 412019b4d63SUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_DOWN; 413dde8a05bSUgen J.S. Antsilevich splx(s); 414dde8a05bSUgen J.S. Antsilevich 415dde8a05bSUgen J.S. Antsilevich break; 416dde8a05bSUgen J.S. Antsilevich case SNPGTTY: 417dde8a05bSUgen J.S. Antsilevich ((struct snptty *) data)->st_unit = snp->snp_unit; 418dde8a05bSUgen J.S. Antsilevich ((struct snptty *) data)->st_type = snp->snp_type; 419dde8a05bSUgen J.S. Antsilevich break; 420dde8a05bSUgen J.S. Antsilevich 421dde8a05bSUgen J.S. Antsilevich case FIONBIO: 422dde8a05bSUgen J.S. Antsilevich if (*(int *) data) 423dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_NBIO; 424dde8a05bSUgen J.S. Antsilevich else 425dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_NBIO; 426dde8a05bSUgen J.S. Antsilevich break; 427dde8a05bSUgen J.S. Antsilevich case FIOASYNC: 428dde8a05bSUgen J.S. Antsilevich if (*(int *) data) 429dde8a05bSUgen J.S. Antsilevich snp->snp_flags |= SNOOP_ASYNC; 430dde8a05bSUgen J.S. Antsilevich else 431dde8a05bSUgen J.S. Antsilevich snp->snp_flags &= ~SNOOP_ASYNC; 432dde8a05bSUgen J.S. Antsilevich break; 433dde8a05bSUgen J.S. Antsilevich case FIONREAD: 434dde8a05bSUgen J.S. Antsilevich s = spltty(); 435dde8a05bSUgen J.S. Antsilevich if (snp->snp_unit != -1) 436dde8a05bSUgen J.S. Antsilevich *(int *) data = snp->snp_len; 437019b4d63SUgen J.S. Antsilevich else if (snp->snp_flags & SNOOP_DOWN) 438019b4d63SUgen J.S. Antsilevich *(int *) data = -1; 439dde8a05bSUgen J.S. Antsilevich else 440dde8a05bSUgen J.S. Antsilevich *(int *) data = 0; 441dde8a05bSUgen J.S. Antsilevich splx(s); 442dde8a05bSUgen J.S. Antsilevich break; 443dde8a05bSUgen J.S. Antsilevich default: 444dde8a05bSUgen J.S. Antsilevich return (ENOTTY); 445dde8a05bSUgen J.S. Antsilevich } 446dde8a05bSUgen J.S. Antsilevich return (0); 447dde8a05bSUgen J.S. Antsilevich } 448dde8a05bSUgen J.S. Antsilevich 449dde8a05bSUgen J.S. Antsilevich 450dde8a05bSUgen J.S. Antsilevich int 451dde8a05bSUgen J.S. Antsilevich snpselect(dev, rw, p) 452dde8a05bSUgen J.S. Antsilevich dev_t dev; 453dde8a05bSUgen J.S. Antsilevich int rw; 454dde8a05bSUgen J.S. Antsilevich struct proc *p; 455dde8a05bSUgen J.S. Antsilevich { 456dde8a05bSUgen J.S. Antsilevich int unit = minor(dev), s; 457dde8a05bSUgen J.S. Antsilevich struct snoop *snp = &snoopsw[unit]; 458dde8a05bSUgen J.S. Antsilevich 459dde8a05bSUgen J.S. Antsilevich if (rw != FREAD) { 460dde8a05bSUgen J.S. Antsilevich return 0; 461dde8a05bSUgen J.S. Antsilevich } 462dde8a05bSUgen J.S. Antsilevich if (snp->snp_len > 0) { 463dde8a05bSUgen J.S. Antsilevich return 1; 464dde8a05bSUgen J.S. Antsilevich } 465019b4d63SUgen J.S. Antsilevich /* 466019b4d63SUgen J.S. Antsilevich * If snoop is down,we don't want to select() forever so we return 1. 467019b4d63SUgen J.S. Antsilevich * Caller should see if we down via FIONREAD ioctl().The last should 468019b4d63SUgen J.S. Antsilevich * return -1 to indicate down state. 469019b4d63SUgen J.S. Antsilevich */ 470019b4d63SUgen J.S. Antsilevich if (snp->snp_flags & SNOOP_DOWN) { 471019b4d63SUgen J.S. Antsilevich return 1; 472019b4d63SUgen J.S. Antsilevich } 473dde8a05bSUgen J.S. Antsilevich selrecord(p, &snp->snp_sel); 474dde8a05bSUgen J.S. Antsilevich return 0; 475dde8a05bSUgen J.S. Antsilevich } 476dde8a05bSUgen J.S. Antsilevich 477dde8a05bSUgen J.S. Antsilevich #endif 478