138620Skarels /* 238620Skarels * Datakit driver 338620Skarels * SCCSID[] = "@(#)dk.c 2.1 DKHOST 84/07/03" 438620Skarels */ 538620Skarels 638620Skarels #include "datakit.h" 738620Skarels #if NDATAKIT>0 838620Skarels 938620Skarels #include "param.h" 1038620Skarels #include "../machine/pte.h" 1138620Skarels #include "signal.h" 1238620Skarels #include "errno.h" 1338620Skarels #include "conf.h" 1438620Skarels #include "user.h" 1538620Skarels #include "ioctl.h" 1638620Skarels #include "tty.h" 17*43390Smckusick #include "vnode.h" 1838620Skarels #include "file.h" 1938620Skarels #include "systm.h" 2038620Skarels #include "proc.h" 2138620Skarels #include "mbuf.h" 2238620Skarels #include "buf.h" 2338620Skarels #include "uio.h" 2438620Skarels #include "kernel.h" 2538620Skarels #include "dkit.h" 2638620Skarels #include "dkcmc.h" 2738620Skarels #include "dk.h" 2838620Skarels #include "dkdev.h" 2938620Skarels #include "syslog.h" 3038620Skarels 3138620Skarels extern int dkdebug ; 3238620Skarels 3338620Skarels #define DKBUFUSE 5 /* max buffers /channel */ 3438620Skarels 3538620Skarels 3638620Skarels int dk_nchan = NDATAKIT; 3738620Skarels struct dkdev dkdev[NDATAKIT]; 3838620Skarels struct dksetupreq *dkreq[NDATAKIT]; 3938620Skarels 4038620Skarels 4138620Skarels 4238620Skarels 4338620Skarels #ifdef MONITOR 4438620Skarels int dummy ; 4538620Skarels int *DKP2 = &dummy ; 4638620Skarels #define M_ON(a) *DKP2 |= (a) 4738620Skarels #define M_OFF(a) *DKP2 &= ~(a) 4838620Skarels 4938620Skarels #define Mread 0400 5038620Skarels #define Mrslp 01000 5138620Skarels #define Mrcpy 02000 5238620Skarels #define Mwrite 04000 5338620Skarels #define Mwcpy 010000 5438620Skarels 5538620Skarels #else 5638620Skarels #define M_ON(a) 5738620Skarels #define M_OFF(a) 5838620Skarels #endif 5938620Skarels 6038620Skarels 6138620Skarels 6238620Skarels /*ARGSUSED*/ 6338620Skarels dkioctl(dev, cmd, data, flag) 6438620Skarels register caddr_t data; 6538620Skarels { 6638620Skarels register struct dkdev *tp; 6738620Skarels register chanstat ; 6838620Skarels int chan, sp_chan; 69*43390Smckusick int s, error = 0; 7038620Skarels register short *pp ; 7138620Skarels struct dkdev *tsp; 7238620Skarels extern dkidone() ; 7338620Skarels struct diocdial dialreq; 7438620Skarels extern int commchan; 7538620Skarels 7638620Skarels chan = dev = minor(dev); 7738620Skarels tp = &dkdev[chan]; 7838620Skarels pp = (short *) data; 7938620Skarels switch(cmd) { 8038620Skarels case DIOCEXCL: 8138620Skarels tp->d_state |= DKXCLUDE ; 8238620Skarels break ; 8338620Skarels case DIOCNXCL: 8438620Skarels tp->d_state &= ~DKXCLUDE ; 8538620Skarels break ; 8638620Skarels case DIOCSETK: 8738620Skarels dkdebug = pp[0] ; 8838620Skarels break; 8938620Skarels case DIOCQQABO: 9038620Skarels pp[0] = tp->d_rresid; 9138620Skarels pp[1] = tp->d_rdone; 9238620Skarels pp[2] = tp->d_rctl; 9338620Skarels break ; 9438620Skarels case DIOCRMODE: 9538620Skarels if (pp[0] & DKR_TIME) 9638620Skarels tp->d_rmode = (DKR_TIME | DKR_BLOCK); 9738620Skarels else tp->d_rmode = pp[0] ; 9838620Skarels break ; 9938620Skarels case DIOCXCTL: 10038620Skarels tp->d_xctl = pp[0] ; 10138620Skarels break ; 10238620Skarels case DIOCFLUSH: 10338620Skarels dk_cmd(chan, DKC_XINIT|DKC_FLUSH); 10438620Skarels break; 10538620Skarels case KIOCINIT: 10638620Skarels dk_cmd(chan, DKC_XINIT); 10738620Skarels break; 10838620Skarels case DIOCXWIN: 10938620Skarels return dk_winsize(chan, (struct diocxwin *)data); 11038620Skarels case DIOCRESET: 11138620Skarels if (chan != 1 && chan != pp[0]) return EACCES; 11238620Skarels if (pp[0] > 1 && pp[0] < commchan) return EINVAL; 11338620Skarels if (pp[0] < 0 || pp[0] >= dk_nchan) return EINVAL; 11438620Skarels if (pp[0] == 0) return -dk_close(0); 11538620Skarels else dk_reset(pp[0]); 11638620Skarels break; 11738620Skarels case DIOCCTYPE: 11838620Skarels if (tp->d_ctype == NULL) { 11938620Skarels struct mbuf *m; 12038620Skarels 12138620Skarels MGET(m, M_WAIT, DKMT_CTYPE); 12238620Skarels if (m == NULL) 12338620Skarels return ENOBUFS; 12438620Skarels tp->d_ctype = mtod(m, struct diocctype *); 12538620Skarels } 12638620Skarels return bcopy(data, (caddr_t) tp->d_ctype, sizeof (struct diocctype)); 12738620Skarels case DIOCINFO: 12838620Skarels ((struct diocinfo *)data)->dioc_nchan = dk_nchan; 12938620Skarels ((struct diocinfo *)data)->dioc_channum = chan; 13038620Skarels ((struct diocinfo *)data)->dioc_commchan = commchan; 13138620Skarels break; 13238620Skarels case DIOCSTAT: 13338620Skarels if (*((int *)data) < 0 || *((int *)data) >= dk_nchan) 13438620Skarels return EINVAL; 13538620Skarels *((int *)data) = dk_status(*((int *)data)); 13638620Skarels break; 13738620Skarels case FIONBIO: 13838620Skarels if (*(int *)data) 13938620Skarels tp->dc_state |= DK_NDELAY; 14038620Skarels else 14138620Skarels tp->dc_state &= ~DK_NDELAY; 14238620Skarels break; 14338620Skarels case FIOASYNC: 14438620Skarels if (*(int *)data) 14538620Skarels tp->dc_state |= DK_ASYNC; 14638620Skarels else 14738620Skarels tp->dc_state &= ~DK_ASYNC; 14838620Skarels break; 14938620Skarels case TIOCGPGRP: 15038620Skarels *(int *)data = tp->d_pgrp; 15138620Skarels break; 15238620Skarels case TIOCSPGRP: 15338620Skarels tp->d_pgrp = *(int *)data; 15438620Skarels break; 15538620Skarels 15638620Skarels /* splice chan to file descriptor */ 15738620Skarels case DKIOCSPL: 158*43390Smckusick error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param, 15938620Skarels 3*sizeof (short)); 160*43390Smckusick if (error) return error; 161*43390Smckusick if ((error = dkgetdev(tp->d_param[0], &sp_chan)) <= 0) 162*43390Smckusick return error ; 16338620Skarels if (sp_chan == chan) 16438620Skarels return EINVAL ; 16538620Skarels tsp = &dkdev[sp_chan] ; 16638620Skarels tp->dc_state |= DKSETUP ; 16738620Skarels tsp->dc_state |= DKSETUP ; 16838620Skarels if (dk_splice(chan, sp_chan, dkidone, (caddr_t) tp, 16938620Skarels (caddr_t) tsp)) { 17038620Skarels tp->dc_state &= ~DKSETUP ; 17138620Skarels tsp->dc_state &= ~DKSETUP ; 17238620Skarels return EIO ; 17338620Skarels } 17438620Skarels s = spl5() ; 17538620Skarels while (tp->dc_state & DKSETUP) 17638620Skarels sleep((caddr_t) tp, TTOPRI); 17738620Skarels while (tsp->dc_state & DKSETUP) 17838620Skarels sleep((caddr_t) tsp, TTOPRI); 17938620Skarels splx(s) ; 18038620Skarels if ((dk_status(chan) & DK_RESET) || (dk_status(sp_chan) & DK_RESET)) 18138620Skarels return EIO ; 18238620Skarels if (tp->d_error || tsp->d_error) 18338620Skarels return EIO ; 184*43390Smckusick error = copyout((caddr_t) tp->d_param, *(caddr_t *)data, 18538620Skarels 3*sizeof (short)); 186*43390Smckusick if (error) return error; 18738620Skarels break ; 18838620Skarels 18938620Skarels case DIOCSWAIT: 19038620Skarels (void) dksplwait(chan) ; 19138620Skarels break ; 19238620Skarels 19338620Skarels default: 19438620Skarels if ((cmd & DKIOCMASK) != DKIOCVAL) { 19538620Skarels return ENOTTY ; 19638620Skarels } 19738620Skarels if (cmd == DKIODIAL) { 198*43390Smckusick error = copyin(*(caddr_t *)data, (caddr_t) &dialreq, 19938620Skarels sizeof (struct diocdial)); 200*43390Smckusick if (error) return error; 201*43390Smckusick if (error = dkiodial(chan, dialreq.dialstring)) 202*43390Smckusick return error; 20338620Skarels tp->dc_state |= DKSETUP ; 20438620Skarels chanstat = dk_setup(minor(dev), (int) DKIOCREQ, 0, 20538620Skarels 0, 0, (int) u.u_uid, dkidone, (caddr_t)tp) ; 20638620Skarels } 20738620Skarels else { 208*43390Smckusick error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param, 20938620Skarels 3*sizeof (short)); 210*43390Smckusick if (error) return error; 21138620Skarels tp->dc_state |= DKSETUP ; 21238625Skarels chanstat = dk_setup(minor(dev), cmd, 0, 0, 0, 21338620Skarels (int) u.u_uid, dkidone, (caddr_t)tp) ; 21438620Skarels } 21538620Skarels if (chanstat) { 21638620Skarels tp->dc_state &= ~DKSETUP ; 21738620Skarels return (chanstat < 0 ? ECONNREFUSED : chanstat); 21838620Skarels } 21938620Skarels s = spl5() ; 22038620Skarels while (tp->dc_state & DKSETUP) 22138620Skarels sleep((caddr_t)(tp), TTOPRI) ; 22238620Skarels splx(s) ; 223*43390Smckusick error = copyout((caddr_t) tp->d_param, *(caddr_t *)data, 22438620Skarels 3*sizeof (short)); 225*43390Smckusick if (error) return error; 22638620Skarels if (dk_status(minor(dev)) & DK_RESET) 22738620Skarels return ENETRESET ; 22838620Skarels if (tp->d_error) 22938620Skarels return EIO ; 23038620Skarels break ; 23138620Skarels } 232*43390Smckusick return error; 23338620Skarels } 23438620Skarels 23538620Skarels #define DS_SIZE 64 23638620Skarels static 23738620Skarels dkiodial(chan, user_ds) 23838620Skarels register char *user_ds; 23938620Skarels { 24038620Skarels register caddr_t ds; 24138620Skarels register n; 24238620Skarels register struct mbuf *mb; 24338620Skarels int u_count; 24438620Skarels 24538620Skarels mb = m_get(M_WAIT, DKMT_DATA); 24638620Skarels if (mb == NULL) return ENOBUFS; 24738620Skarels ds = mtod(mb, caddr_t); 24838620Skarels for (u_count = 0; u_count < MLEN - 6; u_count++) { 24938620Skarels *ds = *user_ds; 25038620Skarels if (*ds == '\n' || *ds == '\0') break; 25138620Skarels ds++; 25238620Skarels user_ds++; 25338620Skarels } 25438620Skarels *ds = '\n'; 25538620Skarels u_count++; 25638620Skarels 25738620Skarels /* add uid in char decimal */ 25838620Skarels 25938620Skarels ds++; 26038620Skarels u_count++; 26138620Skarels for (n = u.u_uid; n /= 10; ds++) u_count++; 26238620Skarels for (n = u.u_uid;; ds--) { 26338620Skarels *ds = n % 10 + '0'; 26438620Skarels if ((n /= 10) == 0) break; 26538620Skarels } 26638620Skarels 26738620Skarels mb->m_len = u_count; 26838620Skarels if (dk_xmit(chan, mb, 1, 0, (int (*)()) 0, (caddr_t) 0) == 0) { 26938620Skarels return(EIO); 27038620Skarels } 27138620Skarels else return(0); 27238620Skarels } 27338620Skarels /* 27438620Skarels * End action for ioctl completion 27538620Skarels */ 27638620Skarels /*ARGSUSED*/ 27738620Skarels dkidone(tp, chan, err, p0, p1, p2) 27838620Skarels register struct dkdev *tp ; 27938620Skarels short chan, p0, p1, p2 ; 28038620Skarels { 28138620Skarels tp->d_error = err ; 28238620Skarels tp->d_param[0] = p0 ; 28338620Skarels tp->d_param[1] = p1 ; 28438620Skarels tp->d_param[2] = p2 ; 28538620Skarels tp->dc_state &= ~DKSETUP ; 28638620Skarels wakeup((caddr_t)tp) ; 28738620Skarels } 28838620Skarels 28938620Skarels 29038620Skarels 29138620Skarels 29238620Skarels /*ARGSUSED*/ 29338620Skarels dkopen(dev, flag) 29438620Skarels { 29538620Skarels register struct dkdev *tp; 29638620Skarels register chan; 29738620Skarels register struct nameidata *ndp = &u.u_nd; 29838620Skarels struct file *fp; 29938620Skarels int m; 30038620Skarels 30138620Skarels #ifdef lint 30238620Skarels (void) dk_xint(0, 0); 30338620Skarels #endif 30438620Skarels dev = minor(dev); 30538620Skarels if (dev == 1) { 30638620Skarels return 0; /* Maintenance channel */ 30738620Skarels } 30838620Skarels 30938620Skarels chan = dev; 31038620Skarels if (chan >= dk_nchan) { 31138620Skarels /* debug */ log(LOG_ERR, "dkopen bad: chan>=NDKCHANS : %d\n",chan); 31238620Skarels return ENXIO; 31338620Skarels } 31438620Skarels 31538620Skarels tp = &dkdev[chan]; 31638620Skarels if ((tp->d_state & DKOPEN) == 0) 31738620Skarels tp->dc_state = 0 ; 31841516Smckusick if (tp->d_state&DKXCLUDE && u.u_procp->p_ruid!=0) { 31938620Skarels return EBUSY; 32038620Skarels } 32138620Skarels 32238620Skarels if ((m = dk_open(chan, (int (*)()) NULL)) < 0) 32338620Skarels return -m; 32438620Skarels 32538620Skarels 32638620Skarels /* 32738620Skarels * Channel 0 is reserved for maintenance. 32838620Skarels * An open on channel 0 is interpreted as a request 32938620Skarels * for an unused channel. 33038620Skarels */ 33138620Skarels if (chan==0) { 33238620Skarels char dname[30]; 33338620Skarels 33438620Skarels chan = m ; 33538620Skarels tp = &dkdev[chan] ; 33638620Skarels tp->dc_state = 0 ; 33738620Skarels /* 338*43390Smckusick * throw away vnode for dk0. (/dev/dk/dial) 33938620Skarels * Build standard name of new one, and ask namei for it. 34038620Skarels */ 34138620Skarels fp = u.u_ofile[u.u_r.r_val1]; 34238620Skarels 34338620Skarels dksnamer(dname, chan); 34438620Skarels /* log(LOG_ERR, "dname=%s chan=%d\n", dname, chan); */ 345*43390Smckusick ndp->ni_nameiop = FOLLOW | LOOKUP | LOCKLEAF; 34638620Skarels ndp->ni_segflg = UIO_SYSSPACE; 34738620Skarels ndp->ni_dirp = dname; 348*43390Smckusick if (error = namei(ndp)) { 34938620Skarels (void) dk_close(chan) ; 350*43390Smckusick return (error); 35138620Skarels } 35238620Skarels 35338620Skarels /* Give back old one */ 354*43390Smckusick vp = (struct vnode *) fp->f_data; 355*43390Smckusick VOP_LOCK(vp); 356*43390Smckusick vput(vp); 35738620Skarels 358*43390Smckusick vp = ndp->ni_vp; 359*43390Smckusick fp->f_data = (caddr_t) vp; 360*43390Smckusick VOP_UNLOCK(vp); 36138620Skarels } 36238620Skarels if ((tp->d_state & DKOPEN) == 0) { 36338620Skarels tp->d_state |= DKOPEN ; 36438620Skarels tp->dc_state = 0; 36538620Skarels tp->d_rmode = 0 ; 36638620Skarels tp->d_xctl = 0 ; 36738620Skarels tp->d_pgrp = 0; 36838620Skarels } 36938620Skarels tp->d_prot |= DpURP; 37038620Skarels return 0; 37138620Skarels } 37238620Skarels 37338620Skarels /* Policy decision here -- standard name of dk file known to this routine */ 37438620Skarels dksnamer(s, n) register char *s; 37538620Skarels { 37638620Skarels register char *p = "/dev/dk/dk"; 37738620Skarels 37838620Skarels while (*s++ = *p++) 37938620Skarels ; 38038620Skarels s--; 38138620Skarels *s++ = '0' + (n/100); n %= 100; 38238620Skarels *s++ = '0' + (n/10); n %= 10; 38338620Skarels *s++ = '0' + n; 38438620Skarels *s = '\0'; 38538620Skarels } 38638620Skarels 38738620Skarels /* 38838620Skarels * Close a channel: 38938620Skarels */ 39038620Skarels 39138620Skarels /*ARGSUSED*/ 39238620Skarels dkclose(dev, flag) 39338620Skarels dev_t dev; 39438620Skarels int flag; 39538620Skarels { 39638620Skarels register struct dkdev *tp; 39738620Skarels extern wakeup() ; 39838620Skarels extern brelse() ; 39938620Skarels short s, chan ; 40038620Skarels int i, cl = 0; 40138620Skarels 40238620Skarels chan = minor(dev); 40338620Skarels tp = &dkdev[chan]; 40438620Skarels if (chan == 1) { 40538620Skarels return 0; /* Maintenance channel */ 40638620Skarels } 40738620Skarels s = spl5() ; 40838620Skarels if (u.u_signal[SIGKILL] != SIG_IGN) { /* detect close from exit() */ 40938620Skarels while (tp->d_bufct) { 41038620Skarels tp->d_state |= DKWAIT ; 41138620Skarels sleep((caddr_t)(&tp->d_state), TTOPRI) ; 41238620Skarels } 41338620Skarels } 41438620Skarels else if (tp->d_bufct) 41538620Skarels /* Hmm -- buffers queued. Let's wait 15 seconds max */ 41638620Skarels for (i = 0; tp->d_bufct && i < 15; i++) { 41738620Skarels tp->d_state |= DKWAIT ; 41838620Skarels timeout(wakeup, (caddr_t) &tp->d_state, hz); 41938620Skarels sleep((caddr_t)(&tp->d_state), TTOPRI) ; 42038620Skarels } 42138620Skarels splx(s) ; 42238620Skarels tp->dc_state = 0; 42338620Skarels tp->d_rmode = 0; 42438620Skarels tp->d_prot &= ~DpURP; 42538620Skarels if(!tp->d_prot){ 42638620Skarels cl = dk_close(chan); 42738620Skarels (void) dk_takedown(chan); 42838620Skarels tp->d_state = 0; 42938620Skarels } 43038620Skarels return -cl; 43138620Skarels } 43238620Skarels 43338620Skarels dkread(dev, uio) 43438620Skarels dev_t dev ; 43538620Skarels struct uio *uio; 43638620Skarels { 43738620Skarels register struct dkdev *tp ; 43838620Skarels int err; 43938620Skarels 44038620Skarels M_ON(Mread) ; 44138620Skarels tp = &dkdev[minor(dev)] ; 44238620Skarels err = dkuread(minor(dev), uio) ; 44338620Skarels tp->d_rresid = uio->uio_resid ; 44438620Skarels M_OFF(Mread) ; 44538620Skarels return err; 44638620Skarels } 44738620Skarels 44838620Skarels 44938620Skarels dkwrite(dev, uio) 45038620Skarels struct uio *uio; 45138620Skarels dev_t dev ; 45238620Skarels { 45338620Skarels int err; 45438620Skarels 45538620Skarels M_ON(Mwrite) ; 45638620Skarels err = dkuwrite(minor(dev), uio) ; 45738620Skarels M_OFF(Mwrite) ; 45838620Skarels return err; 45938620Skarels } 46038620Skarels 46138620Skarels #endif 462