vnode interface conversion
[unix-history] / usr / src / sys / vax / datakit / dk.c
CommitLineData
398dc04d
MK
1/*
2 * Datakit driver
3 * SCCSID[] = "@(#)dk.c 2.1 DKHOST 84/07/03"
4 */
5
6#include "datakit.h"
7#if NDATAKIT>0
8
b28b3a13
KB
9#include "../include/pte.h"
10#include "sys/param.h"
11#include "sys/signal.h"
12#include "sys/errno.h"
13#include "sys/conf.h"
14#include "sys/user.h"
15#include "sys/ioctl.h"
16#include "sys/tty.h"
17#include "sys/vnode.h"
18#include "sys/file.h"
19#include "sys/systm.h"
20#include "sys/proc.h"
21#include "sys/mbuf.h"
22#include "sys/buf.h"
23#include "sys/uio.h"
24#include "sys/kernel.h"
25#include "sys/dkit.h"
26#include "sys/dkcmc.h"
27#include "sys/dk.h"
28#include "sys/dkdev.h"
29#include "sys/syslog.h"
398dc04d
MK
30
31extern int dkdebug ;
32
33#define DKBUFUSE 5 /* max buffers /channel */
34
35
36int dk_nchan = NDATAKIT;
37struct dkdev dkdev[NDATAKIT];
38struct dksetupreq *dkreq[NDATAKIT];
39
40
41
42
43#ifdef MONITOR
44int dummy ;
45int *DKP2 = &dummy ;
46#define M_ON(a) *DKP2 |= (a)
47#define M_OFF(a) *DKP2 &= ~(a)
48
49#define Mread 0400
50#define Mrslp 01000
51#define Mrcpy 02000
52#define Mwrite 04000
53#define Mwcpy 010000
54
55#else
56#define M_ON(a)
57#define M_OFF(a)
58#endif
59
60
61
62/*ARGSUSED*/
63dkioctl(dev, cmd, data, flag)
64register caddr_t data;
65{
66 register struct dkdev *tp;
67 register chanstat ;
68 int chan, sp_chan;
1059378b 69 int s, error = 0;
398dc04d
MK
70 register short *pp ;
71 struct dkdev *tsp;
72 extern dkidone() ;
73 struct diocdial dialreq;
74 extern int commchan;
75
76 chan = dev = minor(dev);
77 tp = &dkdev[chan];
78 pp = (short *) data;
79 switch(cmd) {
80 case DIOCEXCL:
81 tp->d_state |= DKXCLUDE ;
82 break ;
83 case DIOCNXCL:
84 tp->d_state &= ~DKXCLUDE ;
85 break ;
86 case DIOCSETK:
87 dkdebug = pp[0] ;
88 break;
89 case DIOCQQABO:
90 pp[0] = tp->d_rresid;
91 pp[1] = tp->d_rdone;
92 pp[2] = tp->d_rctl;
93 break ;
94 case DIOCRMODE:
95 if (pp[0] & DKR_TIME)
96 tp->d_rmode = (DKR_TIME | DKR_BLOCK);
97 else tp->d_rmode = pp[0] ;
98 break ;
99 case DIOCXCTL:
100 tp->d_xctl = pp[0] ;
101 break ;
102 case DIOCFLUSH:
103 dk_cmd(chan, DKC_XINIT|DKC_FLUSH);
104 break;
105 case KIOCINIT:
106 dk_cmd(chan, DKC_XINIT);
107 break;
108 case DIOCXWIN:
109 return dk_winsize(chan, (struct diocxwin *)data);
110 case DIOCRESET:
111 if (chan != 1 && chan != pp[0]) return EACCES;
112 if (pp[0] > 1 && pp[0] < commchan) return EINVAL;
113 if (pp[0] < 0 || pp[0] >= dk_nchan) return EINVAL;
114 if (pp[0] == 0) return -dk_close(0);
115 else dk_reset(pp[0]);
116 break;
117 case DIOCCTYPE:
118 if (tp->d_ctype == NULL) {
119 struct mbuf *m;
120
121 MGET(m, M_WAIT, DKMT_CTYPE);
122 if (m == NULL)
123 return ENOBUFS;
124 tp->d_ctype = mtod(m, struct diocctype *);
125 }
126 return bcopy(data, (caddr_t) tp->d_ctype, sizeof (struct diocctype));
127 case DIOCINFO:
128 ((struct diocinfo *)data)->dioc_nchan = dk_nchan;
129 ((struct diocinfo *)data)->dioc_channum = chan;
130 ((struct diocinfo *)data)->dioc_commchan = commchan;
131 break;
132 case DIOCSTAT:
133 if (*((int *)data) < 0 || *((int *)data) >= dk_nchan)
134 return EINVAL;
135 *((int *)data) = dk_status(*((int *)data));
136 break;
137 case FIONBIO:
138 if (*(int *)data)
139 tp->dc_state |= DK_NDELAY;
140 else
141 tp->dc_state &= ~DK_NDELAY;
142 break;
143 case FIOASYNC:
144 if (*(int *)data)
145 tp->dc_state |= DK_ASYNC;
146 else
147 tp->dc_state &= ~DK_ASYNC;
148 break;
149 case TIOCGPGRP:
150 *(int *)data = tp->d_pgrp;
151 break;
152 case TIOCSPGRP:
153 tp->d_pgrp = *(int *)data;
154 break;
155
156 /* splice chan to file descriptor */
157 case DKIOCSPL:
1059378b 158 error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param,
398dc04d 159 3*sizeof (short));
1059378b
KM
160 if (error) return error;
161 if ((error = dkgetdev(tp->d_param[0], &sp_chan)) <= 0)
162 return error ;
398dc04d
MK
163 if (sp_chan == chan)
164 return EINVAL ;
165 tsp = &dkdev[sp_chan] ;
166 tp->dc_state |= DKSETUP ;
167 tsp->dc_state |= DKSETUP ;
168 if (dk_splice(chan, sp_chan, dkidone, (caddr_t) tp,
169 (caddr_t) tsp)) {
170 tp->dc_state &= ~DKSETUP ;
171 tsp->dc_state &= ~DKSETUP ;
172 return EIO ;
173 }
174 s = spl5() ;
e9036de0
MK
175 error = 0;
176 while (error == 0 && tp->dc_state & DKSETUP)
177 error = tsleep((caddr_t)tp, TTOPRI, ttopen, 0);
178 while (error == 0 && tsp->dc_state & DKSETUP)
179 error = tsleep((caddr_t)tsp, TTOPRI, ttopen, 0);
398dc04d 180 splx(s) ;
e9036de0
MK
181 if (error)
182 return (error);
398dc04d
MK
183 if ((dk_status(chan) & DK_RESET) || (dk_status(sp_chan) & DK_RESET))
184 return EIO ;
185 if (tp->d_error || tsp->d_error)
186 return EIO ;
1059378b 187 error = copyout((caddr_t) tp->d_param, *(caddr_t *)data,
398dc04d 188 3*sizeof (short));
1059378b 189 if (error) return error;
398dc04d
MK
190 break ;
191
192 case DIOCSWAIT:
e9036de0 193 error = dksplwait(chan);
398dc04d
MK
194 break ;
195
196 default:
197 if ((cmd & DKIOCMASK) != DKIOCVAL) {
198 return ENOTTY ;
199 }
200 if (cmd == DKIODIAL) {
1059378b 201 error = copyin(*(caddr_t *)data, (caddr_t) &dialreq,
398dc04d 202 sizeof (struct diocdial));
1059378b
KM
203 if (error) return error;
204 if (error = dkiodial(chan, dialreq.dialstring))
205 return error;
398dc04d
MK
206 tp->dc_state |= DKSETUP ;
207 chanstat = dk_setup(minor(dev), (int) DKIOCREQ, 0,
208 0, 0, (int) u.u_uid, dkidone, (caddr_t)tp) ;
209 }
210 else {
1059378b 211 error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param,
398dc04d 212 3*sizeof (short));
1059378b 213 if (error) return error;
398dc04d 214 tp->dc_state |= DKSETUP ;
586a8972 215 chanstat = dk_setup(minor(dev), cmd, 0, 0, 0,
398dc04d
MK
216 (int) u.u_uid, dkidone, (caddr_t)tp) ;
217 }
218 if (chanstat) {
219 tp->dc_state &= ~DKSETUP ;
220 return (chanstat < 0 ? ECONNREFUSED : chanstat);
221 }
222 s = spl5() ;
e9036de0
MK
223 error = 0;
224 while (error == 0 && tp->dc_state & DKSETUP)
225 error = tsleep((caddr_t)(tp), TTOPRI, ttyout, 0) ;
398dc04d 226 splx(s) ;
e9036de0
MK
227 if (error)
228 return error;
1059378b 229 error = copyout((caddr_t) tp->d_param, *(caddr_t *)data,
398dc04d 230 3*sizeof (short));
1059378b 231 if (error) return error;
398dc04d
MK
232 if (dk_status(minor(dev)) & DK_RESET)
233 return ENETRESET ;
234 if (tp->d_error)
235 return EIO ;
236 break ;
237 }
1059378b 238 return error;
398dc04d
MK
239}
240
241#define DS_SIZE 64
242static
243dkiodial(chan, user_ds)
244register char *user_ds;
245{
246 register caddr_t ds;
247 register n;
248 register struct mbuf *mb;
249 int u_count;
250
251 mb = m_get(M_WAIT, DKMT_DATA);
252 if (mb == NULL) return ENOBUFS;
253 ds = mtod(mb, caddr_t);
254 for (u_count = 0; u_count < MLEN - 6; u_count++) {
255 *ds = *user_ds;
256 if (*ds == '\n' || *ds == '\0') break;
257 ds++;
258 user_ds++;
259 }
260 *ds = '\n';
261 u_count++;
262
263 /* add uid in char decimal */
264
265 ds++;
266 u_count++;
267 for (n = u.u_uid; n /= 10; ds++) u_count++;
268 for (n = u.u_uid;; ds--) {
269 *ds = n % 10 + '0';
270 if ((n /= 10) == 0) break;
271 }
272
273 mb->m_len = u_count;
274 if (dk_xmit(chan, mb, 1, 0, (int (*)()) 0, (caddr_t) 0) == 0) {
275 return(EIO);
276 }
277 else return(0);
278}
279/*
280 * End action for ioctl completion
281 */
282/*ARGSUSED*/
283dkidone(tp, chan, err, p0, p1, p2)
284register struct dkdev *tp ;
285short chan, p0, p1, p2 ;
286{
287 tp->d_error = err ;
288 tp->d_param[0] = p0 ;
289 tp->d_param[1] = p1 ;
290 tp->d_param[2] = p2 ;
291 tp->dc_state &= ~DKSETUP ;
292 wakeup((caddr_t)tp) ;
293}
294
295
296
297
298/*ARGSUSED*/
299dkopen(dev, flag)
300{
9342689a
JH
301 USES_VOP_LOCK;
302 USES_VOP_UNLOCK;
398dc04d
MK
303 register struct dkdev *tp;
304 register chan;
75a5515b
KM
305 register struct nameidata *ndp = &u.u_nd; /* XXX */
306 struct proc *p = u.u_procp; /* XXX */
307 struct vnode *vp;
398dc04d 308 struct file *fp;
75a5515b 309 int m, error;
398dc04d
MK
310
311#ifdef lint
312 (void) dk_xint(0, 0);
313#endif
314 dev = minor(dev);
315 if (dev == 1) {
316 return 0; /* Maintenance channel */
317 }
318
319 chan = dev;
320 if (chan >= dk_nchan) {
321/* debug */ log(LOG_ERR, "dkopen bad: chan>=NDKCHANS : %d\n",chan);
322 return ENXIO;
323 }
324
325 tp = &dkdev[chan];
326 if ((tp->d_state & DKOPEN) == 0)
327 tp->dc_state = 0 ;
76d640d7 328 if (tp->d_state&DKXCLUDE && u.u_procp->p_ruid!=0) {
398dc04d
MK
329 return EBUSY;
330 }
331
332 if ((m = dk_open(chan, (int (*)()) NULL)) < 0)
333 return -m;
334
335
336 /*
337 * Channel 0 is reserved for maintenance.
338 * An open on channel 0 is interpreted as a request
339 * for an unused channel.
340 */
341 if (chan==0) {
342 char dname[30];
343
344 chan = m ;
345 tp = &dkdev[chan] ;
346 tp->dc_state = 0 ;
347 /*
1059378b 348 * throw away vnode for dk0. (/dev/dk/dial)
398dc04d
MK
349 * Build standard name of new one, and ask namei for it.
350 */
75a5515b 351 fp = u.u_ofile[-1 - p->p_dupfd];
398dc04d
MK
352
353 dksnamer(dname, chan);
354 /* log(LOG_ERR, "dname=%s chan=%d\n", dname, chan); */
1059378b 355 ndp->ni_nameiop = FOLLOW | LOOKUP | LOCKLEAF;
398dc04d
MK
356 ndp->ni_segflg = UIO_SYSSPACE;
357 ndp->ni_dirp = dname;
1059378b 358 if (error = namei(ndp)) {
398dc04d 359 (void) dk_close(chan) ;
1059378b 360 return (error);
398dc04d
MK
361 }
362
363 /* Give back old one */
1059378b
KM
364 vp = (struct vnode *) fp->f_data;
365 VOP_LOCK(vp);
366 vput(vp);
398dc04d 367
1059378b
KM
368 vp = ndp->ni_vp;
369 fp->f_data = (caddr_t) vp;
370 VOP_UNLOCK(vp);
398dc04d
MK
371 }
372 if ((tp->d_state & DKOPEN) == 0) {
373 tp->d_state |= DKOPEN ;
374 tp->dc_state = 0;
375 tp->d_rmode = 0 ;
376 tp->d_xctl = 0 ;
377 tp->d_pgrp = 0;
378 }
379 tp->d_prot |= DpURP;
380 return 0;
381}
382
383/* Policy decision here -- standard name of dk file known to this routine */
384dksnamer(s, n) register char *s;
385{
386 register char *p = "/dev/dk/dk";
387
388 while (*s++ = *p++)
389 ;
390 s--;
391 *s++ = '0' + (n/100); n %= 100;
392 *s++ = '0' + (n/10); n %= 10;
393 *s++ = '0' + n;
394 *s = '\0';
395}
396
397/*
398 * Close a channel:
399 */
400
401/*ARGSUSED*/
402dkclose(dev, flag)
403dev_t dev;
404int flag;
405{
406 register struct dkdev *tp;
407 extern wakeup() ;
408 extern brelse() ;
409 short s, chan ;
410 int i, cl = 0;
411
412 chan = minor(dev);
413 tp = &dkdev[chan];
414 if (chan == 1) {
415 return 0; /* Maintenance channel */
416 }
417 s = spl5() ;
418 if (u.u_signal[SIGKILL] != SIG_IGN) { /* detect close from exit() */
419 while (tp->d_bufct) {
420 tp->d_state |= DKWAIT ;
e9036de0
MK
421 if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, 0))
422 break;
398dc04d
MK
423 }
424 }
425 else if (tp->d_bufct)
426 /* Hmm -- buffers queued. Let's wait 15 seconds max */
427 for (i = 0; tp->d_bufct && i < 15; i++) {
428 tp->d_state |= DKWAIT ;
e9036de0
MK
429 if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, hz))
430 break;
398dc04d
MK
431 }
432 splx(s) ;
433 tp->dc_state = 0;
434 tp->d_rmode = 0;
435 tp->d_prot &= ~DpURP;
436 if(!tp->d_prot){
437 cl = dk_close(chan);
438 (void) dk_takedown(chan);
439 tp->d_state = 0;
440 }
441 return -cl;
442}
443
444dkread(dev, uio)
445dev_t dev ;
446struct uio *uio;
447{
448register struct dkdev *tp ;
449int err;
450
451 M_ON(Mread) ;
452 tp = &dkdev[minor(dev)] ;
453 err = dkuread(minor(dev), uio) ;
454 tp->d_rresid = uio->uio_resid ;
455 M_OFF(Mread) ;
456 return err;
457}
458
459
460dkwrite(dev, uio)
461struct uio *uio;
462dev_t dev ;
463{
464 int err;
465
466 M_ON(Mwrite) ;
467 err = dkuwrite(minor(dev), uio) ;
468 M_OFF(Mwrite) ;
469 return err;
470}
471
472#endif