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
dkuread(chan,uio)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*/
dkrdone(tp,chan,resid,rdone,rctl)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
dkuwrite(chan,uio)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*/
dkwdone(x,chan)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 */
dkrsplice(chan)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 */
dksplwait(chan)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 */
dkgetdev(fildes,devnop)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 */
dkdevtype(dev)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