xref: /original-bsd/sys/vax/datakit/dksub.c (revision 28e93ce0)
1 /*
2  * Datakit driver
3  * Common subroutines for all drivers
4  *	SCCSID[] = "@(#)dksub.c	1.2 Garage 84/03/27"
5  *		   "@(#)dksub.c	1.7 (Berkeley) 12/16/90"
6  */
7 
8 #include "datakit.h"
9 #if NDATAKIT>0
10 
11 #include "../include/pte.h"
12 #include "sys/param.h"
13 #include "sys/signal.h"
14 #include "sys/errno.h"
15 #include "sys/seg.h"
16 #include "sys/user.h"
17 #include "sys/ioctl.h"
18 #include "sys/tty.h"
19 #include "sys/syslog.h"
20 #include "sys/conf.h"
21 #include "sys/file.h"
22 #include "sys/systm.h"
23 #include "sys/proc.h"
24 #include "sys/mbuf.h"
25 #include "sys/buf.h"
26 #include "sys/uio.h"
27 #include "sys/vnode.h"
28 #include "sys/specdev.h"
29 #include "dkit.h"
30 #include "dk.h"
31 #include "dkdev.h"
32 
33 #define DKBUFUSE	5	/* max buffers /channel */
34 
35 
36 extern struct dkdev dkdev[] ;
37 
38 int	dksubdebug = 512;
39 
40 
41 dkuread(chan, uio)
42 register struct uio *uio;
43 {
44 	register int len, blen ;
45 	register struct dkdev *tp ;
46 	short chanstat ;
47 	struct mbuf *mm ;
48 	int err = 0, s;
49 	extern wakeup() ;
50 	extern dkrdone() ;
51 
52 	tp = &dkdev[chan];
53 	MGET(mm, M_WAIT, DKMT_DATA);
54 	if (mm == NULL)
55 		return ENOBUFS;
56 	if (uio->uio_resid >= MLEN) {
57 		MCLGET(mm, M_WAIT);
58 		if ((mm->m_flags & M_EXT) == 0)
59 			goto nopages;
60 		blen = MCLBYTES;
61 	} else {
62 nopages:
63 		blen = MIN(MLEN, uio->uio_resid);
64 	}
65 
66 	while (uio->uio_resid && !err) {
67 		len = MIN(uio->uio_resid, blen) ;
68 		chanstat = dk_recv(chan, mtod(mm, caddr_t), len, tp->d_rmode, dkrdone, (caddr_t) tp) ;
69 		if (chanstat == 0) {
70 			if ((dk_status(chan) & DK_RESET) == 0)
71 				err = EIO ;
72 			break;
73 		}
74 		if ((tp->dc_state & DK_NDELAY) && (dk_status(chan) & DK_RCV)) {
75 			err = EWOULDBLOCK;
76 			break;
77 		}
78 
79 		s = spl5() ;
80 		while (dk_status(chan) & DK_RCV)
81 			if (err = tsleep((caddr_t)(tp), TTIPRI, ttyin, 0)) {
82 				if (dk_status(chan) & DK_RCV)
83 					(void) dk_rabort(chan, dkrdone,
84 					    (caddr_t) tp);
85 				splx(s);
86 				goto done;
87 			}
88 		splx(s) ;
89 
90 		len -= tp->d_rresid ;
91 		if (len)
92 			err = uiomove(mtod(mm, caddr_t), len, UIO_READ, uio);
93 		if (tp->d_rdone != DKR_FULL)
94 			break ;
95 	}
96 done:
97 	m_freem(mm) ;
98 	return err;
99 }
100 
101 
102 /*ARGSUSED*/
103 dkrdone(tp, chan, resid, rdone, rctl)
104 register struct dkdev *tp ;
105 {
106 	tp->d_rresid = resid ;
107 	tp->d_rdone = rdone ;
108 	tp->d_rctl = rctl ;
109 	wakeup((caddr_t) tp) ;
110 }
111 
112 
113 
114 
115 dkuwrite(chan, uio) register struct uio *uio;
116 {
117 extern wakeup() ;
118 extern dkwdone() ;
119 register struct dkdev *tp ;
120 register len ;
121 register struct mbuf *m;
122 register struct iovec *iov;
123 int s, error, eob;
124 short xc;
125 
126 	tp = &dkdev[chan] ;
127 	do {
128 		s = spl5() ;
129 		while (tp->d_bufct > DKBUFUSE) {
130 			if (tp->dc_state & DK_NDELAY) {
131 				splx(s);
132 				return EWOULDBLOCK;
133 			}
134 			tp->d_state |= DKWAIT ;
135 			if (error = tsleep((caddr_t)(&tp->d_state), TTOPRI,
136 			    ttyout, 0)) {
137 				splx(s);
138 				return (error);
139 			}
140 		}
141 		splx(s) ;
142 
143 		iov = uio->uio_iov;
144 		if (iov->iov_len) {
145 			MGET(m, M_WAIT, DKMT_DATA);
146 			if (m == NULL)
147 				return ENOBUFS;
148 			if (iov->iov_len >= MLEN) {
149 				MCLGET(m, M_WAIT);
150 				if ((m->m_flags & M_EXT) == 0)
151 					goto nopages;
152 				len = MIN(MCLBYTES, iov->iov_len);
153 			} else {
154 nopages:
155 				len = MIN(MLEN, iov->iov_len);
156 			}
157 			error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
158 			if (error) {
159 				(void) m_free(m);
160 				return error;
161 			}
162 			m->m_len = len;
163 		}
164 		else m = NULL;
165 
166 		s = spl5();
167 		tp->d_bufct++;
168 		eob = (uio->uio_resid == 0);
169 		if (eob) {
170 			xc = tp->d_xctl;
171 			tp->d_xctl = 0;
172 		}
173 		else xc = 0;
174 		if (dk_xmit(chan, m, eob, xc, dkwdone, (caddr_t) 0) == 0) {
175 			tp->d_bufct-- ;
176 			return EIO ;
177 		}
178 		splx(s);
179 	} while (uio->uio_resid);
180 	return 0;
181 }
182 
183 /*ARGSUSED*/
184 dkwdone(x, chan)
185 {
186 	register struct dkdev *tp ;
187 
188 	tp = &dkdev[chan] ;
189 	if (chan > dksubdebug)
190 		log(LOG_ERR, "dkwdone %d: state=0%o bufct=%d\n", chan, tp->d_state,
191 		    tp->d_bufct);
192 	if (tp->d_bufct)
193 		tp->d_bufct-- ;
194 	if (tp->d_state & DKWAIT) {
195 		tp->d_state &= ~DKWAIT ;
196 		wakeup((caddr_t) &tp->d_state) ;
197 	}
198 }
199 
200 /* wakeup and reinitialize channel upon receipt of reconnection message */
201 dkrsplice(chan)
202 {
203 	register struct dkdev *tp ;
204 
205 	tp = &dkdev[chan] ;
206 	tp->d_state |= DKSPLICED ;
207 	wakeup((caddr_t) tp) ;
208 	dk_cmd(chan, DKC_XINIT) ;
209 }
210 
211 /* wait for reconnection message indicating that splice completed */
212 dksplwait(chan)
213 {
214 	register struct dkdev *tp ;
215 	int error;
216 
217 	tp = &dkdev[chan] ;
218 	while ((tp->d_state & DKSPLICED) == 0)
219 		if (error = tsleep((caddr_t) tp, TTOPRI, ttopen, 0))
220 			return (error);
221 	return (0);
222 }
223 
224 /* convert file desciptor to Datakit channel */
225 dkgetdev(fildes, devnop)
226 	int fildes, *devnop;
227 {
228 	struct file *fp;
229 	register struct vnode *vp ;
230 	int error;
231 
232 	if (error = getvnode(u.u_ofile, fildes, &fp))
233 		return error;
234 	vp = (struct vnode *)fp->f_data;
235 	if (vp->v_type != VCHR)
236 		return ENOTTY;
237 	if (dkdevtype(vp->v_rdev)) {
238 		*devnop = minor(vp->v_rdev);
239 		return 0;
240 	}
241 	return EINVAL;
242 }
243 
244 /* validate device number as belonging to Datakit */
245 dkdevtype(dev) dev_t dev;
246 {
247 	extern dkopen();
248 #if NDKTTY > 0
249 	extern dktopen();
250 #endif
251 #if NDKXQT > 0
252 	extern dkxopen();
253 #endif
254 #if NDKI > 0
255 	extern dkiopen();
256 #endif
257 	register md = major(dev) ;
258 
259 	if ((cdevsw[md].d_open == dkopen)
260 #if NDKTTY > 0
261 		|| (cdevsw[md].d_open == dktopen)
262 #endif
263 #if NDKI > 0
264 		|| (cdevsw[md].d_open == dkiopen && md > 0)
265 #endif
266 #if NDKXQT > 0
267 		|| (cdevsw[md].d_open == dkxopen)
268 #endif
269 	    )
270 			return(1);
271 	else
272 		return(0);
273 }
274 
275 #endif
276