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