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