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