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
945800Sbostic #include "../include/pte.h"
1045800Sbostic #include "sys/param.h"
1145800Sbostic #include "sys/signal.h"
1245800Sbostic #include "sys/errno.h"
1345800Sbostic #include "sys/conf.h"
1445800Sbostic #include "sys/user.h"
1545800Sbostic #include "sys/ioctl.h"
1645800Sbostic #include "sys/tty.h"
1745800Sbostic #include "sys/vnode.h"
1845800Sbostic #include "sys/file.h"
1945800Sbostic #include "sys/systm.h"
2045800Sbostic #include "sys/proc.h"
2145800Sbostic #include "sys/mbuf.h"
2245800Sbostic #include "sys/buf.h"
2345800Sbostic #include "sys/uio.h"
2445800Sbostic #include "sys/kernel.h"
2545800Sbostic #include "sys/dkit.h"
2645800Sbostic #include "sys/dkcmc.h"
2745800Sbostic #include "sys/dk.h"
2845800Sbostic #include "sys/dkdev.h"
2945800Sbostic #include "sys/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*/
dkioctl(dev,cmd,data,flag)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;
6943390Smckusick 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:
15843390Smckusick error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param,
15938620Skarels 3*sizeof (short));
16043390Smckusick if (error) return error;
16143390Smckusick if ((error = dkgetdev(tp->d_param[0], &sp_chan)) <= 0)
16243390Smckusick 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() ;
17545184Skarels error = 0;
17645184Skarels while (error == 0 && tp->dc_state & DKSETUP)
17745184Skarels error = tsleep((caddr_t)tp, TTOPRI, ttopen, 0);
17845184Skarels while (error == 0 && tsp->dc_state & DKSETUP)
17945184Skarels error = tsleep((caddr_t)tsp, TTOPRI, ttopen, 0);
18038620Skarels splx(s) ;
18145184Skarels if (error)
18245184Skarels return (error);
18338620Skarels if ((dk_status(chan) & DK_RESET) || (dk_status(sp_chan) & DK_RESET))
18438620Skarels return EIO ;
18538620Skarels if (tp->d_error || tsp->d_error)
18638620Skarels return EIO ;
18743390Smckusick error = copyout((caddr_t) tp->d_param, *(caddr_t *)data,
18838620Skarels 3*sizeof (short));
18943390Smckusick if (error) return error;
19038620Skarels break ;
19138620Skarels
19238620Skarels case DIOCSWAIT:
19345184Skarels error = dksplwait(chan);
19438620Skarels break ;
19538620Skarels
19638620Skarels default:
19738620Skarels if ((cmd & DKIOCMASK) != DKIOCVAL) {
19838620Skarels return ENOTTY ;
19938620Skarels }
20038620Skarels if (cmd == DKIODIAL) {
20143390Smckusick error = copyin(*(caddr_t *)data, (caddr_t) &dialreq,
20238620Skarels sizeof (struct diocdial));
20343390Smckusick if (error) return error;
20443390Smckusick if (error = dkiodial(chan, dialreq.dialstring))
20543390Smckusick return error;
20638620Skarels tp->dc_state |= DKSETUP ;
20738620Skarels chanstat = dk_setup(minor(dev), (int) DKIOCREQ, 0,
20838620Skarels 0, 0, (int) u.u_uid, dkidone, (caddr_t)tp) ;
20938620Skarels }
21038620Skarels else {
21143390Smckusick error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param,
21238620Skarels 3*sizeof (short));
21343390Smckusick if (error) return error;
21438620Skarels tp->dc_state |= DKSETUP ;
21538625Skarels chanstat = dk_setup(minor(dev), cmd, 0, 0, 0,
21638620Skarels (int) u.u_uid, dkidone, (caddr_t)tp) ;
21738620Skarels }
21838620Skarels if (chanstat) {
21938620Skarels tp->dc_state &= ~DKSETUP ;
22038620Skarels return (chanstat < 0 ? ECONNREFUSED : chanstat);
22138620Skarels }
22238620Skarels s = spl5() ;
22345184Skarels error = 0;
22445184Skarels while (error == 0 && tp->dc_state & DKSETUP)
22545184Skarels error = tsleep((caddr_t)(tp), TTOPRI, ttyout, 0) ;
22638620Skarels splx(s) ;
22745184Skarels if (error)
22845184Skarels return error;
22943390Smckusick error = copyout((caddr_t) tp->d_param, *(caddr_t *)data,
23038620Skarels 3*sizeof (short));
23143390Smckusick if (error) return error;
23238620Skarels if (dk_status(minor(dev)) & DK_RESET)
23338620Skarels return ENETRESET ;
23438620Skarels if (tp->d_error)
23538620Skarels return EIO ;
23638620Skarels break ;
23738620Skarels }
23843390Smckusick return error;
23938620Skarels }
24038620Skarels
24138620Skarels #define DS_SIZE 64
24238620Skarels static
dkiodial(chan,user_ds)24338620Skarels dkiodial(chan, user_ds)
24438620Skarels register char *user_ds;
24538620Skarels {
24638620Skarels register caddr_t ds;
24738620Skarels register n;
24838620Skarels register struct mbuf *mb;
24938620Skarels int u_count;
25038620Skarels
25138620Skarels mb = m_get(M_WAIT, DKMT_DATA);
25238620Skarels if (mb == NULL) return ENOBUFS;
25338620Skarels ds = mtod(mb, caddr_t);
25438620Skarels for (u_count = 0; u_count < MLEN - 6; u_count++) {
25538620Skarels *ds = *user_ds;
25638620Skarels if (*ds == '\n' || *ds == '\0') break;
25738620Skarels ds++;
25838620Skarels user_ds++;
25938620Skarels }
26038620Skarels *ds = '\n';
26138620Skarels u_count++;
26238620Skarels
26338620Skarels /* add uid in char decimal */
26438620Skarels
26538620Skarels ds++;
26638620Skarels u_count++;
26738620Skarels for (n = u.u_uid; n /= 10; ds++) u_count++;
26838620Skarels for (n = u.u_uid;; ds--) {
26938620Skarels *ds = n % 10 + '0';
27038620Skarels if ((n /= 10) == 0) break;
27138620Skarels }
27238620Skarels
27338620Skarels mb->m_len = u_count;
27438620Skarels if (dk_xmit(chan, mb, 1, 0, (int (*)()) 0, (caddr_t) 0) == 0) {
27538620Skarels return(EIO);
27638620Skarels }
27738620Skarels else return(0);
27838620Skarels }
27938620Skarels /*
28038620Skarels * End action for ioctl completion
28138620Skarels */
28238620Skarels /*ARGSUSED*/
dkidone(tp,chan,err,p0,p1,p2)28338620Skarels dkidone(tp, chan, err, p0, p1, p2)
28438620Skarels register struct dkdev *tp ;
28538620Skarels short chan, p0, p1, p2 ;
28638620Skarels {
28738620Skarels tp->d_error = err ;
28838620Skarels tp->d_param[0] = p0 ;
28938620Skarels tp->d_param[1] = p1 ;
29038620Skarels tp->d_param[2] = p2 ;
29138620Skarels tp->dc_state &= ~DKSETUP ;
29238620Skarels wakeup((caddr_t)tp) ;
29338620Skarels }
29438620Skarels
29538620Skarels
29638620Skarels
29738620Skarels
29838620Skarels /*ARGSUSED*/
dkopen(dev,flag)29938620Skarels dkopen(dev, flag)
30038620Skarels {
301*53535Sheideman USES_VOP_LOCK;
302*53535Sheideman USES_VOP_UNLOCK;
30338620Skarels register struct dkdev *tp;
30438620Skarels register chan;
30545203Smckusick register struct nameidata *ndp = &u.u_nd; /* XXX */
30645203Smckusick struct proc *p = u.u_procp; /* XXX */
30745203Smckusick struct vnode *vp;
30838620Skarels struct file *fp;
30945203Smckusick int m, error;
31038620Skarels
31138620Skarels #ifdef lint
31238620Skarels (void) dk_xint(0, 0);
31338620Skarels #endif
31438620Skarels dev = minor(dev);
31538620Skarels if (dev == 1) {
31638620Skarels return 0; /* Maintenance channel */
31738620Skarels }
31838620Skarels
31938620Skarels chan = dev;
32038620Skarels if (chan >= dk_nchan) {
32138620Skarels /* debug */ log(LOG_ERR, "dkopen bad: chan>=NDKCHANS : %d\n",chan);
32238620Skarels return ENXIO;
32338620Skarels }
32438620Skarels
32538620Skarels tp = &dkdev[chan];
32638620Skarels if ((tp->d_state & DKOPEN) == 0)
32738620Skarels tp->dc_state = 0 ;
32841516Smckusick if (tp->d_state&DKXCLUDE && u.u_procp->p_ruid!=0) {
32938620Skarels return EBUSY;
33038620Skarels }
33138620Skarels
33238620Skarels if ((m = dk_open(chan, (int (*)()) NULL)) < 0)
33338620Skarels return -m;
33438620Skarels
33538620Skarels
33638620Skarels /*
33738620Skarels * Channel 0 is reserved for maintenance.
33838620Skarels * An open on channel 0 is interpreted as a request
33938620Skarels * for an unused channel.
34038620Skarels */
34138620Skarels if (chan==0) {
34238620Skarels char dname[30];
34338620Skarels
34438620Skarels chan = m ;
34538620Skarels tp = &dkdev[chan] ;
34638620Skarels tp->dc_state = 0 ;
34738620Skarels /*
34843390Smckusick * throw away vnode for dk0. (/dev/dk/dial)
34938620Skarels * Build standard name of new one, and ask namei for it.
35038620Skarels */
35145203Smckusick fp = u.u_ofile[-1 - p->p_dupfd];
35238620Skarels
35338620Skarels dksnamer(dname, chan);
35438620Skarels /* log(LOG_ERR, "dname=%s chan=%d\n", dname, chan); */
35543390Smckusick ndp->ni_nameiop = FOLLOW | LOOKUP | LOCKLEAF;
35638620Skarels ndp->ni_segflg = UIO_SYSSPACE;
35738620Skarels ndp->ni_dirp = dname;
35843390Smckusick if (error = namei(ndp)) {
35938620Skarels (void) dk_close(chan) ;
36043390Smckusick return (error);
36138620Skarels }
36238620Skarels
36338620Skarels /* Give back old one */
36443390Smckusick vp = (struct vnode *) fp->f_data;
36543390Smckusick VOP_LOCK(vp);
36643390Smckusick vput(vp);
36738620Skarels
36843390Smckusick vp = ndp->ni_vp;
36943390Smckusick fp->f_data = (caddr_t) vp;
37043390Smckusick VOP_UNLOCK(vp);
37138620Skarels }
37238620Skarels if ((tp->d_state & DKOPEN) == 0) {
37338620Skarels tp->d_state |= DKOPEN ;
37438620Skarels tp->dc_state = 0;
37538620Skarels tp->d_rmode = 0 ;
37638620Skarels tp->d_xctl = 0 ;
37738620Skarels tp->d_pgrp = 0;
37838620Skarels }
37938620Skarels tp->d_prot |= DpURP;
38038620Skarels return 0;
38138620Skarels }
38238620Skarels
38338620Skarels /* Policy decision here -- standard name of dk file known to this routine */
dksnamer(s,n)38438620Skarels dksnamer(s, n) register char *s;
38538620Skarels {
38638620Skarels register char *p = "/dev/dk/dk";
38738620Skarels
38838620Skarels while (*s++ = *p++)
38938620Skarels ;
39038620Skarels s--;
39138620Skarels *s++ = '0' + (n/100); n %= 100;
39238620Skarels *s++ = '0' + (n/10); n %= 10;
39338620Skarels *s++ = '0' + n;
39438620Skarels *s = '\0';
39538620Skarels }
39638620Skarels
39738620Skarels /*
39838620Skarels * Close a channel:
39938620Skarels */
40038620Skarels
40138620Skarels /*ARGSUSED*/
dkclose(dev,flag)40238620Skarels dkclose(dev, flag)
40338620Skarels dev_t dev;
40438620Skarels int flag;
40538620Skarels {
40638620Skarels register struct dkdev *tp;
40738620Skarels extern wakeup() ;
40838620Skarels extern brelse() ;
40938620Skarels short s, chan ;
41038620Skarels int i, cl = 0;
41138620Skarels
41238620Skarels chan = minor(dev);
41338620Skarels tp = &dkdev[chan];
41438620Skarels if (chan == 1) {
41538620Skarels return 0; /* Maintenance channel */
41638620Skarels }
41738620Skarels s = spl5() ;
41838620Skarels if (u.u_signal[SIGKILL] != SIG_IGN) { /* detect close from exit() */
41938620Skarels while (tp->d_bufct) {
42038620Skarels tp->d_state |= DKWAIT ;
42145184Skarels if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, 0))
42245184Skarels break;
42338620Skarels }
42438620Skarels }
42538620Skarels else if (tp->d_bufct)
42638620Skarels /* Hmm -- buffers queued. Let's wait 15 seconds max */
42738620Skarels for (i = 0; tp->d_bufct && i < 15; i++) {
42838620Skarels tp->d_state |= DKWAIT ;
42945184Skarels if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, hz))
43045184Skarels break;
43138620Skarels }
43238620Skarels splx(s) ;
43338620Skarels tp->dc_state = 0;
43438620Skarels tp->d_rmode = 0;
43538620Skarels tp->d_prot &= ~DpURP;
43638620Skarels if(!tp->d_prot){
43738620Skarels cl = dk_close(chan);
43838620Skarels (void) dk_takedown(chan);
43938620Skarels tp->d_state = 0;
44038620Skarels }
44138620Skarels return -cl;
44238620Skarels }
44338620Skarels
dkread(dev,uio)44438620Skarels dkread(dev, uio)
44538620Skarels dev_t dev ;
44638620Skarels struct uio *uio;
44738620Skarels {
44838620Skarels register struct dkdev *tp ;
44938620Skarels int err;
45038620Skarels
45138620Skarels M_ON(Mread) ;
45238620Skarels tp = &dkdev[minor(dev)] ;
45338620Skarels err = dkuread(minor(dev), uio) ;
45438620Skarels tp->d_rresid = uio->uio_resid ;
45538620Skarels M_OFF(Mread) ;
45638620Skarels return err;
45738620Skarels }
45838620Skarels
45938620Skarels
46038620Skarels dkwrite(dev, uio)
46138620Skarels struct uio *uio;
46238620Skarels dev_t dev ;
46338620Skarels {
46438620Skarels int err;
46538620Skarels
46638620Skarels M_ON(Mwrite) ;
46738620Skarels err = dkuwrite(minor(dev), uio) ;
46838620Skarels M_OFF(Mwrite) ;
46938620Skarels return err;
47038620Skarels }
47138620Skarels
47238620Skarels #endif
473