xref: /csrg-svn/sys/vax/datakit/dk.c (revision 38625)
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