1*38620Skarels /* 2*38620Skarels * Datakit driver 3*38620Skarels * SCCSID[] = "@(#)dk.c 2.1 DKHOST 84/07/03" 4*38620Skarels */ 5*38620Skarels 6*38620Skarels #include "datakit.h" 7*38620Skarels #if NDATAKIT>0 8*38620Skarels 9*38620Skarels #include "param.h" 10*38620Skarels #include "../machine/pte.h" 11*38620Skarels #include "signal.h" 12*38620Skarels #include "errno.h" 13*38620Skarels #include "conf.h" 14*38620Skarels #include "dir.h" 15*38620Skarels #include "user.h" 16*38620Skarels #include "ioctl.h" 17*38620Skarels #include "tty.h" 18*38620Skarels #include "inode.h" 19*38620Skarels #include "file.h" 20*38620Skarels #include "systm.h" 21*38620Skarels #include "proc.h" 22*38620Skarels #include "mbuf.h" 23*38620Skarels #include "buf.h" 24*38620Skarels #include "uio.h" 25*38620Skarels #include "kernel.h" 26*38620Skarels #include "dkit.h" 27*38620Skarels #include "dkcmc.h" 28*38620Skarels #include "dk.h" 29*38620Skarels #include "dkdev.h" 30*38620Skarels #include "syslog.h" 31*38620Skarels 32*38620Skarels extern int dkdebug ; 33*38620Skarels 34*38620Skarels #define DKBUFUSE 5 /* max buffers /channel */ 35*38620Skarels 36*38620Skarels 37*38620Skarels int dk_nchan = NDATAKIT; 38*38620Skarels struct dkdev dkdev[NDATAKIT]; 39*38620Skarels struct dksetupreq *dkreq[NDATAKIT]; 40*38620Skarels 41*38620Skarels 42*38620Skarels 43*38620Skarels 44*38620Skarels #ifdef MONITOR 45*38620Skarels int dummy ; 46*38620Skarels int *DKP2 = &dummy ; 47*38620Skarels #define M_ON(a) *DKP2 |= (a) 48*38620Skarels #define M_OFF(a) *DKP2 &= ~(a) 49*38620Skarels 50*38620Skarels #define Mread 0400 51*38620Skarels #define Mrslp 01000 52*38620Skarels #define Mrcpy 02000 53*38620Skarels #define Mwrite 04000 54*38620Skarels #define Mwcpy 010000 55*38620Skarels 56*38620Skarels #else 57*38620Skarels #define M_ON(a) 58*38620Skarels #define M_OFF(a) 59*38620Skarels #endif 60*38620Skarels 61*38620Skarels 62*38620Skarels 63*38620Skarels /*ARGSUSED*/ 64*38620Skarels dkioctl(dev, cmd, data, flag) 65*38620Skarels register caddr_t data; 66*38620Skarels { 67*38620Skarels register struct dkdev *tp; 68*38620Skarels register chanstat ; 69*38620Skarels int chan, sp_chan; 70*38620Skarels int s; 71*38620Skarels register short *pp ; 72*38620Skarels struct dkdev *tsp; 73*38620Skarels extern dkidone() ; 74*38620Skarels struct diocdial dialreq; 75*38620Skarels extern int commchan; 76*38620Skarels 77*38620Skarels chan = dev = minor(dev); 78*38620Skarels tp = &dkdev[chan]; 79*38620Skarels pp = (short *) data; 80*38620Skarels switch(cmd) { 81*38620Skarels case DIOCEXCL: 82*38620Skarels tp->d_state |= DKXCLUDE ; 83*38620Skarels break ; 84*38620Skarels case DIOCNXCL: 85*38620Skarels tp->d_state &= ~DKXCLUDE ; 86*38620Skarels break ; 87*38620Skarels case DIOCSETK: 88*38620Skarels dkdebug = pp[0] ; 89*38620Skarels break; 90*38620Skarels case DIOCQQABO: 91*38620Skarels pp[0] = tp->d_rresid; 92*38620Skarels pp[1] = tp->d_rdone; 93*38620Skarels pp[2] = tp->d_rctl; 94*38620Skarels break ; 95*38620Skarels case DIOCRMODE: 96*38620Skarels if (pp[0] & DKR_TIME) 97*38620Skarels tp->d_rmode = (DKR_TIME | DKR_BLOCK); 98*38620Skarels else tp->d_rmode = pp[0] ; 99*38620Skarels break ; 100*38620Skarels case DIOCXCTL: 101*38620Skarels tp->d_xctl = pp[0] ; 102*38620Skarels break ; 103*38620Skarels case DIOCFLUSH: 104*38620Skarels dk_cmd(chan, DKC_XINIT|DKC_FLUSH); 105*38620Skarels break; 106*38620Skarels case KIOCINIT: 107*38620Skarels dk_cmd(chan, DKC_XINIT); 108*38620Skarels break; 109*38620Skarels case DIOCXWIN: 110*38620Skarels return dk_winsize(chan, (struct diocxwin *)data); 111*38620Skarels case DIOCRESET: 112*38620Skarels if (chan != 1 && chan != pp[0]) return EACCES; 113*38620Skarels if (pp[0] > 1 && pp[0] < commchan) return EINVAL; 114*38620Skarels if (pp[0] < 0 || pp[0] >= dk_nchan) return EINVAL; 115*38620Skarels if (pp[0] == 0) return -dk_close(0); 116*38620Skarels else dk_reset(pp[0]); 117*38620Skarels break; 118*38620Skarels case DIOCCTYPE: 119*38620Skarels if (tp->d_ctype == NULL) { 120*38620Skarels struct mbuf *m; 121*38620Skarels 122*38620Skarels MGET(m, M_WAIT, DKMT_CTYPE); 123*38620Skarels if (m == NULL) 124*38620Skarels return ENOBUFS; 125*38620Skarels tp->d_ctype = mtod(m, struct diocctype *); 126*38620Skarels } 127*38620Skarels return bcopy(data, (caddr_t) tp->d_ctype, sizeof (struct diocctype)); 128*38620Skarels case DIOCINFO: 129*38620Skarels ((struct diocinfo *)data)->dioc_nchan = dk_nchan; 130*38620Skarels ((struct diocinfo *)data)->dioc_channum = chan; 131*38620Skarels ((struct diocinfo *)data)->dioc_commchan = commchan; 132*38620Skarels break; 133*38620Skarels case DIOCSTAT: 134*38620Skarels if (*((int *)data) < 0 || *((int *)data) >= dk_nchan) 135*38620Skarels return EINVAL; 136*38620Skarels *((int *)data) = dk_status(*((int *)data)); 137*38620Skarels break; 138*38620Skarels case FIONBIO: 139*38620Skarels if (*(int *)data) 140*38620Skarels tp->dc_state |= DK_NDELAY; 141*38620Skarels else 142*38620Skarels tp->dc_state &= ~DK_NDELAY; 143*38620Skarels break; 144*38620Skarels case FIOASYNC: 145*38620Skarels if (*(int *)data) 146*38620Skarels tp->dc_state |= DK_ASYNC; 147*38620Skarels else 148*38620Skarels tp->dc_state &= ~DK_ASYNC; 149*38620Skarels break; 150*38620Skarels case TIOCGPGRP: 151*38620Skarels *(int *)data = tp->d_pgrp; 152*38620Skarels break; 153*38620Skarels case TIOCSPGRP: 154*38620Skarels tp->d_pgrp = *(int *)data; 155*38620Skarels break; 156*38620Skarels 157*38620Skarels /* splice chan to file descriptor */ 158*38620Skarels case DKIOCSPL: 159*38620Skarels u.u_error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param, 160*38620Skarels 3*sizeof (short)); 161*38620Skarels if (u.u_error) return u.u_error; 162*38620Skarels if ((sp_chan = dkgetdev(tp->d_param[0])) <= 0) 163*38620Skarels return u.u_error ; 164*38620Skarels if (sp_chan == chan) 165*38620Skarels return EINVAL ; 166*38620Skarels tsp = &dkdev[sp_chan] ; 167*38620Skarels tp->dc_state |= DKSETUP ; 168*38620Skarels tsp->dc_state |= DKSETUP ; 169*38620Skarels if (dk_splice(chan, sp_chan, dkidone, (caddr_t) tp, 170*38620Skarels (caddr_t) tsp)) { 171*38620Skarels tp->dc_state &= ~DKSETUP ; 172*38620Skarels tsp->dc_state &= ~DKSETUP ; 173*38620Skarels return EIO ; 174*38620Skarels } 175*38620Skarels s = spl5() ; 176*38620Skarels while (tp->dc_state & DKSETUP) 177*38620Skarels sleep((caddr_t) tp, TTOPRI); 178*38620Skarels while (tsp->dc_state & DKSETUP) 179*38620Skarels sleep((caddr_t) tsp, TTOPRI); 180*38620Skarels splx(s) ; 181*38620Skarels if ((dk_status(chan) & DK_RESET) || (dk_status(sp_chan) & DK_RESET)) 182*38620Skarels return EIO ; 183*38620Skarels if (tp->d_error || tsp->d_error) 184*38620Skarels return EIO ; 185*38620Skarels u.u_error = copyout((caddr_t) tp->d_param, *(caddr_t *)data, 186*38620Skarels 3*sizeof (short)); 187*38620Skarels if (u.u_error) return u.u_error; 188*38620Skarels break ; 189*38620Skarels 190*38620Skarels case DIOCSWAIT: 191*38620Skarels (void) dksplwait(chan) ; 192*38620Skarels break ; 193*38620Skarels 194*38620Skarels default: 195*38620Skarels if ((cmd & DKIOCMASK) != DKIOCVAL) { 196*38620Skarels return ENOTTY ; 197*38620Skarels } 198*38620Skarels if (cmd == DKIODIAL) { 199*38620Skarels u.u_error = copyin(*(caddr_t *)data, (caddr_t) &dialreq, 200*38620Skarels sizeof (struct diocdial)); 201*38620Skarels if (u.u_error) return u.u_error; 202*38620Skarels if (u.u_error = dkiodial(chan, dialreq.dialstring)) 203*38620Skarels return u.u_error; 204*38620Skarels tp->dc_state |= DKSETUP ; 205*38620Skarels chanstat = dk_setup(minor(dev), (int) DKIOCREQ, 0, 206*38620Skarels 0, 0, (int) u.u_uid, dkidone, (caddr_t)tp) ; 207*38620Skarels } 208*38620Skarels else { 209*38620Skarels u.u_error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param, 210*38620Skarels 3*sizeof (short)); 211*38620Skarels if (u.u_error) return u.u_error; 212*38620Skarels tp->dc_state |= DKSETUP ; 213*38620Skarels chanstat = dk_setup(minor(dev), cmd, tp->d_param[0], 214*38620Skarels tp->d_param[1], tp->d_param[2], 215*38620Skarels (int) u.u_uid, dkidone, (caddr_t)tp) ; 216*38620Skarels } 217*38620Skarels if (chanstat) { 218*38620Skarels tp->dc_state &= ~DKSETUP ; 219*38620Skarels return (chanstat < 0 ? ECONNREFUSED : chanstat); 220*38620Skarels } 221*38620Skarels s = spl5() ; 222*38620Skarels while (tp->dc_state & DKSETUP) 223*38620Skarels sleep((caddr_t)(tp), TTOPRI) ; 224*38620Skarels splx(s) ; 225*38620Skarels u.u_error = copyout((caddr_t) tp->d_param, *(caddr_t *)data, 226*38620Skarels 3*sizeof (short)); 227*38620Skarels if (u.u_error) return u.u_error; 228*38620Skarels if (dk_status(minor(dev)) & DK_RESET) 229*38620Skarels return ENETRESET ; 230*38620Skarels if (tp->d_error) 231*38620Skarels return EIO ; 232*38620Skarels break ; 233*38620Skarels } 234*38620Skarels return 0; 235*38620Skarels } 236*38620Skarels 237*38620Skarels #define DS_SIZE 64 238*38620Skarels static 239*38620Skarels dkiodial(chan, user_ds) 240*38620Skarels register char *user_ds; 241*38620Skarels { 242*38620Skarels register caddr_t ds; 243*38620Skarels register n; 244*38620Skarels register struct mbuf *mb; 245*38620Skarels int u_count; 246*38620Skarels 247*38620Skarels mb = m_get(M_WAIT, DKMT_DATA); 248*38620Skarels if (mb == NULL) return ENOBUFS; 249*38620Skarels ds = mtod(mb, caddr_t); 250*38620Skarels for (u_count = 0; u_count < MLEN - 6; u_count++) { 251*38620Skarels *ds = *user_ds; 252*38620Skarels if (*ds == '\n' || *ds == '\0') break; 253*38620Skarels ds++; 254*38620Skarels user_ds++; 255*38620Skarels } 256*38620Skarels *ds = '\n'; 257*38620Skarels u_count++; 258*38620Skarels 259*38620Skarels /* add uid in char decimal */ 260*38620Skarels 261*38620Skarels ds++; 262*38620Skarels u_count++; 263*38620Skarels for (n = u.u_uid; n /= 10; ds++) u_count++; 264*38620Skarels for (n = u.u_uid;; ds--) { 265*38620Skarels *ds = n % 10 + '0'; 266*38620Skarels if ((n /= 10) == 0) break; 267*38620Skarels } 268*38620Skarels 269*38620Skarels mb->m_len = u_count; 270*38620Skarels if (dk_xmit(chan, mb, 1, 0, (int (*)()) 0, (caddr_t) 0) == 0) { 271*38620Skarels return(EIO); 272*38620Skarels } 273*38620Skarels else return(0); 274*38620Skarels } 275*38620Skarels /* 276*38620Skarels * End action for ioctl completion 277*38620Skarels */ 278*38620Skarels /*ARGSUSED*/ 279*38620Skarels dkidone(tp, chan, err, p0, p1, p2) 280*38620Skarels register struct dkdev *tp ; 281*38620Skarels short chan, p0, p1, p2 ; 282*38620Skarels { 283*38620Skarels tp->d_error = err ; 284*38620Skarels tp->d_param[0] = p0 ; 285*38620Skarels tp->d_param[1] = p1 ; 286*38620Skarels tp->d_param[2] = p2 ; 287*38620Skarels tp->dc_state &= ~DKSETUP ; 288*38620Skarels wakeup((caddr_t)tp) ; 289*38620Skarels } 290*38620Skarels 291*38620Skarels 292*38620Skarels 293*38620Skarels 294*38620Skarels /*ARGSUSED*/ 295*38620Skarels dkopen(dev, flag) 296*38620Skarels { 297*38620Skarels register struct dkdev *tp; 298*38620Skarels register chan; 299*38620Skarels register struct nameidata *ndp = &u.u_nd; 300*38620Skarels struct inode *ip; 301*38620Skarels struct file *fp; 302*38620Skarels int m; 303*38620Skarels 304*38620Skarels #ifdef lint 305*38620Skarels (void) dk_xint(0, 0); 306*38620Skarels #endif 307*38620Skarels dev = minor(dev); 308*38620Skarels if (dev == 1) { 309*38620Skarels return 0; /* Maintenance channel */ 310*38620Skarels } 311*38620Skarels 312*38620Skarels chan = dev; 313*38620Skarels if (chan >= dk_nchan) { 314*38620Skarels /* debug */ log(LOG_ERR, "dkopen bad: chan>=NDKCHANS : %d\n",chan); 315*38620Skarels return ENXIO; 316*38620Skarels } 317*38620Skarels 318*38620Skarels tp = &dkdev[chan]; 319*38620Skarels if ((tp->d_state & DKOPEN) == 0) 320*38620Skarels tp->dc_state = 0 ; 321*38620Skarels if (tp->d_state&DKXCLUDE && u.u_ruid!=0) { 322*38620Skarels return EBUSY; 323*38620Skarels } 324*38620Skarels 325*38620Skarels if ((m = dk_open(chan, (int (*)()) NULL)) < 0) 326*38620Skarels return -m; 327*38620Skarels 328*38620Skarels 329*38620Skarels /* 330*38620Skarels * Channel 0 is reserved for maintenance. 331*38620Skarels * An open on channel 0 is interpreted as a request 332*38620Skarels * for an unused channel. 333*38620Skarels */ 334*38620Skarels if (chan==0) { 335*38620Skarels char dname[30]; 336*38620Skarels 337*38620Skarels chan = m ; 338*38620Skarels tp = &dkdev[chan] ; 339*38620Skarels tp->dc_state = 0 ; 340*38620Skarels /* 341*38620Skarels * throw away inode for dk0. (/dev/dk/dial) 342*38620Skarels * Build standard name of new one, and ask namei for it. 343*38620Skarels */ 344*38620Skarels fp = u.u_ofile[u.u_r.r_val1]; 345*38620Skarels 346*38620Skarels dksnamer(dname, chan); 347*38620Skarels /* log(LOG_ERR, "dname=%s chan=%d\n", dname, chan); */ 348*38620Skarels u.u_error = 0; 349*38620Skarels ndp->ni_nameiop = FOLLOW | LOOKUP; 350*38620Skarels ndp->ni_segflg = UIO_SYSSPACE; 351*38620Skarels ndp->ni_dirp = dname; 352*38620Skarels ip = namei(ndp); 353*38620Skarels 354*38620Skarels if (ip == NULL) { 355*38620Skarels (void) dk_close(chan) ; 356*38620Skarels return ENOENT ; 357*38620Skarels } 358*38620Skarels 359*38620Skarels /* Give back old one */ 360*38620Skarels ilock((struct inode *) fp->f_data); 361*38620Skarels iput((struct inode *) fp->f_data); 362*38620Skarels 363*38620Skarels fp->f_data = (caddr_t) ip; 364*38620Skarels iunlock(ip); 365*38620Skarels } 366*38620Skarels if ((tp->d_state & DKOPEN) == 0) { 367*38620Skarels tp->d_state |= DKOPEN ; 368*38620Skarels tp->dc_state = 0; 369*38620Skarels tp->d_rmode = 0 ; 370*38620Skarels tp->d_xctl = 0 ; 371*38620Skarels tp->d_pgrp = 0; 372*38620Skarels } 373*38620Skarels tp->d_prot |= DpURP; 374*38620Skarels return 0; 375*38620Skarels } 376*38620Skarels 377*38620Skarels /* Policy decision here -- standard name of dk file known to this routine */ 378*38620Skarels dksnamer(s, n) register char *s; 379*38620Skarels { 380*38620Skarels register char *p = "/dev/dk/dk"; 381*38620Skarels 382*38620Skarels while (*s++ = *p++) 383*38620Skarels ; 384*38620Skarels s--; 385*38620Skarels *s++ = '0' + (n/100); n %= 100; 386*38620Skarels *s++ = '0' + (n/10); n %= 10; 387*38620Skarels *s++ = '0' + n; 388*38620Skarels *s = '\0'; 389*38620Skarels } 390*38620Skarels 391*38620Skarels /* 392*38620Skarels * Close a channel: 393*38620Skarels */ 394*38620Skarels 395*38620Skarels /*ARGSUSED*/ 396*38620Skarels dkclose(dev, flag) 397*38620Skarels dev_t dev; 398*38620Skarels int flag; 399*38620Skarels { 400*38620Skarels register struct dkdev *tp; 401*38620Skarels extern wakeup() ; 402*38620Skarels extern brelse() ; 403*38620Skarels short s, chan ; 404*38620Skarels int i, cl = 0; 405*38620Skarels 406*38620Skarels chan = minor(dev); 407*38620Skarels tp = &dkdev[chan]; 408*38620Skarels if (chan == 1) { 409*38620Skarels return 0; /* Maintenance channel */ 410*38620Skarels } 411*38620Skarels s = spl5() ; 412*38620Skarels if (u.u_signal[SIGKILL] != SIG_IGN) { /* detect close from exit() */ 413*38620Skarels while (tp->d_bufct) { 414*38620Skarels tp->d_state |= DKWAIT ; 415*38620Skarels sleep((caddr_t)(&tp->d_state), TTOPRI) ; 416*38620Skarels } 417*38620Skarels } 418*38620Skarels else if (tp->d_bufct) 419*38620Skarels /* Hmm -- buffers queued. Let's wait 15 seconds max */ 420*38620Skarels for (i = 0; tp->d_bufct && i < 15; i++) { 421*38620Skarels tp->d_state |= DKWAIT ; 422*38620Skarels timeout(wakeup, (caddr_t) &tp->d_state, hz); 423*38620Skarels sleep((caddr_t)(&tp->d_state), TTOPRI) ; 424*38620Skarels } 425*38620Skarels splx(s) ; 426*38620Skarels tp->dc_state = 0; 427*38620Skarels tp->d_rmode = 0; 428*38620Skarels tp->d_prot &= ~DpURP; 429*38620Skarels if(!tp->d_prot){ 430*38620Skarels cl = dk_close(chan); 431*38620Skarels (void) dk_takedown(chan); 432*38620Skarels tp->d_state = 0; 433*38620Skarels } 434*38620Skarels return -cl; 435*38620Skarels } 436*38620Skarels 437*38620Skarels dkread(dev, uio) 438*38620Skarels dev_t dev ; 439*38620Skarels struct uio *uio; 440*38620Skarels { 441*38620Skarels register struct dkdev *tp ; 442*38620Skarels int err; 443*38620Skarels 444*38620Skarels M_ON(Mread) ; 445*38620Skarels tp = &dkdev[minor(dev)] ; 446*38620Skarels err = dkuread(minor(dev), uio) ; 447*38620Skarels tp->d_rresid = uio->uio_resid ; 448*38620Skarels M_OFF(Mread) ; 449*38620Skarels return err; 450*38620Skarels } 451*38620Skarels 452*38620Skarels 453*38620Skarels dkwrite(dev, uio) 454*38620Skarels struct uio *uio; 455*38620Skarels dev_t dev ; 456*38620Skarels { 457*38620Skarels int err; 458*38620Skarels 459*38620Skarels M_ON(Mwrite) ; 460*38620Skarels err = dkuwrite(minor(dev), uio) ; 461*38620Skarels M_OFF(Mwrite) ; 462*38620Skarels return err; 463*38620Skarels } 464*38620Skarels 465*38620Skarels #endif 466