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