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