Commit | Line | Data |
---|---|---|
2487aa9d BJ |
1 | /* mx2.c 4.2 11/9/80 */ |
2 | ||
3 | #include "../h/param.h" | |
4 | #include "../h/systm.h" | |
5 | #include "../h/dir.h" | |
6 | #include "../h/user.h" | |
7 | #include "../h/proc.h" | |
8 | #include "../h/tty.h" | |
9 | #include "../h/inode.h" | |
10 | #include "../h/mx.h" | |
11 | #include "../h/file.h" | |
12 | #include "../h/conf.h" | |
13 | #include "../h/buf.h" | |
14 | /* | |
15 | * multiplexor driver | |
16 | */ | |
17 | struct chan chans[NCHANS]; | |
18 | struct group *groups[NGROUPS]; | |
19 | int mpxline; | |
20 | ||
21 | short cmask[16] ={ | |
22 | 01, 02, 04, | |
23 | 010, 020, 040, | |
24 | 0100, 0200, 0400, | |
25 | 01000, 02000, 04000, | |
26 | 010000, 020000, 040000, 0100000 | |
27 | }; | |
28 | ||
29 | #define IOMOVE iomove | |
30 | #define FPEND &file[NFILE] | |
31 | struct chan *xcp(),*addch(),*nextcp(); | |
32 | ||
33 | #define HIQ 100 | |
34 | #define LOQ 20 | |
35 | #define FP ((struct file *)cp) | |
36 | ||
37 | char mcdebugs[NDEBUGS]; | |
38 | ||
39 | struct group * | |
40 | getmpx(dev) | |
41 | dev_t dev; | |
42 | { | |
43 | register d; | |
44 | ||
45 | d = minor(dev); | |
46 | if (d >= NGROUPS) { | |
47 | u.u_error = ENXIO; | |
48 | return(NULL); | |
49 | } | |
50 | return(groups[d]); | |
51 | } | |
52 | ||
53 | ||
54 | /*ARGSUSED*/ | |
55 | mxopen(dev, flag) | |
56 | { | |
57 | register struct group *gp; | |
58 | register struct file *fp; | |
59 | register struct chan *cp; | |
60 | int msg; | |
61 | ||
62 | if ((gp=getmpx(dev)) == NULL) { | |
63 | return; | |
64 | } | |
65 | if (!(gp->g_state&INUSE)) { | |
66 | u.u_error = ENXIO; | |
67 | return; | |
68 | } | |
69 | fp = u.u_ofile[u.u_r.r_val1]; | |
70 | if (fp->f_inode != gp->g_inode) { | |
71 | u.u_error = ENXIO; | |
72 | return; | |
73 | } | |
74 | if ((cp=addch(gp->g_inode,0)) == NULL) { | |
75 | u.u_error = ENXIO; | |
76 | return; | |
77 | } | |
78 | ||
79 | cp->c_flags = XGRP; | |
80 | cp->c_ottyp = cp->c_ttyp = (struct tty *)cp; | |
81 | cp->c_line = cp->c_oline = mpxline; | |
82 | ||
83 | fp->f_flag |= FMPY; | |
84 | fp->f_flag |= FREAD+FWRITE; | |
85 | fp->f_un.f_chan = cp; | |
86 | ||
87 | if (gp->g_inode == mpxip) { | |
88 | plock(mpxip); | |
89 | mpxname(cp); | |
90 | msg = M_OPEN; | |
91 | } else | |
92 | msg = M_WATCH; | |
93 | ||
94 | scontrol(cp, msg+(cp->c_index<<8), u.u_uid); | |
95 | sleep((caddr_t)cp,TTIPRI); | |
96 | if (cp->c_flags&NMBUF) | |
97 | prele(mpxip); | |
98 | if (cp->c_flags & WCLOSE) { | |
99 | chdrain(cp); | |
100 | chfree(cp); | |
101 | u.u_error = ENXIO; | |
102 | return; | |
103 | } | |
104 | cp->c_fy = fp; | |
105 | cp->c_pgrp = u.u_procp->p_pgrp; | |
106 | } | |
107 | ||
108 | ||
109 | char mxnmbuf[NMSIZE]; | |
110 | int nmsize; | |
111 | ||
112 | mpxname(cp) | |
113 | register struct chan *cp; | |
114 | { | |
115 | register char *np; | |
116 | register c; | |
117 | ||
118 | np = mxnmbuf; | |
119 | u.u_dirp = (caddr_t)u.u_arg[0]; | |
120 | ||
121 | while (np < &mxnmbuf[NMSIZE]) { | |
122 | c = uchar(); | |
123 | if (c <= 0) | |
124 | break; | |
125 | *np++ = c; | |
126 | } | |
127 | *np++ = '\0'; | |
128 | nmsize = np - mxnmbuf; | |
129 | ||
130 | cp->c_flags |= NMBUF; | |
131 | } | |
132 | ||
133 | ||
134 | mxclose(dev, flag, cp) | |
135 | dev_t dev; | |
136 | register struct chan *cp; | |
137 | { | |
138 | register struct group *gp; | |
139 | register struct inode *ip; | |
140 | register struct file *fp; | |
141 | int i, fmp; | |
142 | ||
143 | fmp = flag&FMP; | |
144 | if ((gp=getmpx(dev)) == NULL) | |
145 | return; | |
146 | ||
147 | ip = gp->g_inode; | |
148 | if (ip==NULL || (ip->i_mode&IFMT)!=IFMPC) { | |
149 | return; | |
150 | } | |
151 | ||
152 | /* | |
153 | * close a channel | |
154 | */ | |
155 | if (cp!=NULL && fmp && fmp!=FMP) { | |
156 | for(fp=file; fp< FPEND; fp++) | |
157 | if(fp->f_count && fp->f_flag&FMP && fp->f_un.f_chan==cp){ | |
158 | return; | |
159 | } | |
160 | chdrain(cp); | |
161 | if ((cp->c_flags&WCLOSE)==0) { | |
162 | scontrol(cp, M_CLOSE, 0); | |
163 | cp->c_flags |= WCLOSE; | |
164 | } else { | |
165 | chfree(cp); | |
166 | } | |
167 | goto out; | |
168 | } | |
169 | ||
170 | ||
171 | for(fp=file; fp < FPEND; fp++) { | |
172 | if (fp->f_count && (fp->f_flag&FMP)==FMP && fp->f_inode==ip) | |
173 | return; | |
174 | } | |
175 | ||
176 | if (ip == mpxip) { | |
177 | mpxip = NULL; | |
178 | prele(ip); | |
179 | } | |
180 | ||
181 | for(i=0;i<NINDEX;i++) | |
182 | (void) detach(gp->g_chans[i]); | |
183 | ||
184 | out: | |
185 | if (ip->i_count == 1) { | |
186 | groups[minor(dev)] = NULL; | |
187 | plock(ip); | |
188 | zero((caddr_t)gp, sizeof (struct group)); | |
189 | ip->i_mode = IFREG + 0666; | |
190 | ip->i_un.i_rdev = 0; | |
191 | ip->i_flag |= IUPD|ICHG; | |
192 | iput(ip); | |
193 | } | |
194 | } | |
195 | ||
196 | zero(s, cc) | |
197 | register char *s; | |
198 | register cc; | |
199 | { | |
200 | while (cc--) | |
201 | *s++ = 0; | |
202 | } | |
203 | ||
204 | char m_eot[] ={ M_EOT, 0, 0, 0}; | |
205 | ||
206 | /* | |
207 | * Mxread + mxwrite are entered from cdevsw | |
208 | * for all read/write calls. Operations on | |
209 | * an mpx file are handled here. | |
210 | * Calls are made through linesw to handle actual | |
211 | * data movement. | |
212 | */ | |
213 | mxread(dev) | |
214 | { | |
215 | register struct group *gp; | |
216 | register struct chan *cp; | |
217 | register esc; | |
218 | struct rh h; | |
219 | caddr_t base; | |
220 | unsigned count; | |
221 | int s, xfr, more, fmp; | |
222 | ||
223 | if ((gp=getmpx(dev))==NULL || (FP=getf(u.u_arg[0]))==NULL) { | |
224 | u.u_error = ENXIO; | |
225 | return; | |
226 | } | |
227 | ||
228 | fmp = FP->f_flag & FMP; | |
229 | if (fmp != FMP) { | |
230 | if (u.u_count == 0) | |
231 | return; | |
232 | msread(fmp, FP->f_un.f_chan); | |
233 | return; | |
234 | } | |
235 | ||
236 | if ((int)u.u_base & 1) { | |
237 | u.u_error = ENXIO; | |
238 | return; | |
239 | } | |
240 | ||
241 | s = spl6(); | |
242 | if (u.u_count == 0) | |
243 | { | |
244 | if (gp->g_datq == 0) | |
245 | u.u_error = ENXIO; | |
246 | splx(s); | |
247 | return; | |
248 | } | |
249 | while (gp->g_datq == 0) { | |
250 | sleep((caddr_t)&gp->g_datq, TTIPRI); | |
251 | } | |
252 | splx(s); | |
253 | ||
254 | while (gp->g_datq && u.u_count >= CNTLSIZ + 2) { | |
255 | esc = 0; | |
256 | cp = nextcp(gp); | |
257 | if (cp==NULL) { | |
258 | continue; | |
259 | } | |
260 | h.index = cpx(cp); | |
261 | if (count = cp->c_ctlx.c_cc) { | |
262 | count += CNTLSIZ; | |
263 | if (cp->c_flags&NMBUF) | |
264 | count += nmsize; | |
265 | if (count > u.u_count) { | |
266 | (void) sdata(cp); | |
267 | return; | |
268 | } | |
269 | esc++; | |
270 | } | |
271 | base = u.u_base; | |
272 | count = u.u_count; | |
273 | u.u_base += sizeof h; | |
274 | u.u_count -= sizeof h; | |
275 | xfr = u.u_count; | |
276 | if (esc) { | |
277 | more = mcread(cp); | |
278 | } else { | |
279 | more = (*linesw[cp->c_line].l_read)(cp->c_ttyp); | |
280 | } | |
281 | if (more > 0) | |
282 | (void) sdata(cp); | |
283 | if (more < 0) | |
284 | scontrol(cp, M_CLOSE, 0); | |
285 | (void) spl0(); | |
286 | if (xfr == u.u_count) { | |
287 | esc++; | |
288 | IOMOVE((caddr_t)m_eot, sizeof m_eot, B_READ); | |
289 | } | |
290 | xfr -= u.u_count; | |
291 | if (esc) { | |
292 | h.count = 0; | |
293 | h.ccount = xfr; | |
294 | } else { | |
295 | h.count = xfr; | |
296 | h.ccount = 0; | |
297 | mxrstrt(cp, &cp->cx.datq, BLOCK|ALT); | |
298 | } | |
299 | if (u.u_count && (xfr&1)) { | |
300 | u.u_base++; | |
301 | u.u_count--; | |
302 | } | |
303 | (void) copyout((caddr_t)&h, base, sizeof h); | |
304 | ||
305 | } | |
306 | } | |
307 | ||
308 | ||
309 | mxwrite(dev) | |
310 | { | |
311 | register struct chan *cp; | |
312 | struct wh h; | |
313 | struct group *gp; | |
314 | int ucount, esc, fmp, burpcount; | |
315 | caddr_t ubase, hbase; | |
316 | ||
317 | if ((gp=getmpx(dev))==NULL || (FP=getf(u.u_arg[0]))==NULL) { | |
318 | return; | |
319 | } | |
320 | fmp = FP->f_flag & FMP; | |
321 | if (fmp != FMP) { | |
322 | mswrite(fmp, FP->f_un.f_chan); | |
323 | return; | |
324 | } | |
325 | ||
326 | burpcount = 0; | |
327 | while (u.u_count >= sizeof h) { | |
328 | hbase = u.u_base; | |
329 | IOMOVE((caddr_t)&h, sizeof h, B_WRITE); | |
330 | if (u.u_error) | |
331 | return; | |
332 | esc = 0; | |
333 | if (h.count==0) { | |
334 | esc++; | |
335 | h.count = h.ccount; | |
336 | } | |
337 | cp = xcp(gp, h.index); | |
338 | if (cp==NULL || cp->c_flags&ISGRP) { | |
339 | u.u_error = ENXIO; | |
340 | return; | |
341 | } | |
342 | ucount = u.u_count; | |
343 | ubase = u.u_base; | |
344 | u.u_count = h.count; | |
345 | u.u_base = h.data; | |
346 | ||
347 | if (esc==0) { | |
348 | struct tty *tp; | |
349 | caddr_t waddr; | |
350 | int line; | |
351 | ||
352 | if (cp->c_flags&PORT) { | |
353 | line = cp->c_line; | |
354 | tp = cp->c_ttyp; | |
355 | } else { | |
356 | line = cp->c_oline; | |
357 | tp = cp->c_ottyp; | |
358 | } | |
359 | loop: | |
360 | waddr = (caddr_t)(*linesw[line].l_write)(tp); | |
361 | if (u.u_count) { | |
362 | if (gp->g_state&ENAMSG) { | |
363 | burpcount++; | |
364 | cp->c_flags |= BLKMSG; | |
365 | /* | |
366 | scontrol(cp, M_BLK, u.u_count); | |
367 | */ | |
368 | h.ccount = -1; | |
369 | h.count = u.u_count; | |
370 | h.data = u.u_base; | |
371 | (void) copyout((caddr_t)&h, hbase, sizeof h); | |
372 | } else { | |
373 | if(waddr == 0) { | |
374 | u.u_error = ENXIO; | |
375 | return; | |
376 | } | |
377 | sleep(waddr, TTOPRI); | |
378 | goto loop; | |
379 | } | |
380 | } | |
381 | } else { | |
382 | mxwcontrol(cp); | |
383 | } | |
384 | u.u_count = ucount; | |
385 | u.u_base = ubase; | |
386 | } | |
387 | u.u_count = burpcount; | |
388 | } | |
389 | ||
390 | ||
391 | ||
392 | /* | |
393 | * Mcread and mcwrite move data on an mpx file. | |
394 | * Transfer addr and length is controlled by mxread/mxwrite. | |
395 | * Kernel-to-Kernel and other special transfers are not | |
396 | * yet in. | |
397 | */ | |
398 | mcread(cp) | |
399 | register struct chan *cp; | |
400 | { | |
401 | register struct clist *q; | |
402 | register char *np; | |
403 | ||
404 | ||
405 | q = (cp->c_ctlx.c_cc) ? &cp->c_ctlx : &cp->cx.datq; | |
406 | (void) mxmove(q, B_READ); | |
407 | ||
408 | if (cp->c_flags&NMBUF && q == &cp->c_ctlx) { | |
409 | np = mxnmbuf; | |
410 | while (nmsize--) | |
411 | (void) passc(*np++); | |
412 | cp->c_flags &= ~NMBUF; | |
413 | prele(mpxip); | |
414 | } | |
415 | if (cp->c_flags&PORT) | |
416 | return(cp->c_ctlx.c_cc + cp->c_ttyp->t_rawq.c_cc); else | |
417 | return(cp->c_ctlx.c_cc + cp->cx.datq.c_cc); | |
418 | ||
419 | } | |
420 | ||
421 | ||
422 | caddr_t | |
423 | mcwrite(cp) | |
424 | register struct chan *cp; | |
425 | { | |
426 | register struct clist *q; | |
427 | int s; | |
428 | ||
429 | q = &cp->cy.datq; | |
430 | while (u.u_count) { | |
431 | s = spl6(); | |
432 | if (q->c_cc > HIQ || (cp->c_flags&EOTMARK)) { | |
433 | cp->c_flags |= SIGBLK; | |
434 | splx(s); | |
435 | break; | |
436 | } | |
437 | splx(s); | |
438 | (void) mxmove(q, B_WRITE); | |
439 | } | |
440 | wakeup((caddr_t)q); | |
441 | return((caddr_t)q); | |
442 | } | |
443 | ||
444 | ||
445 | /* | |
446 | * Msread and mswrite move bytes | |
447 | * between user and non-multiplexed channel. | |
448 | */ | |
449 | msread(fmp, cp) | |
450 | register struct chan *cp; | |
451 | { | |
452 | register struct clist *q; | |
453 | int s; | |
454 | ||
455 | q = (fmp&FMPX) ? &cp->cx.datq : &cp->cy.datq; | |
456 | s = spl6(); | |
457 | while (q->c_cc == 0) { | |
458 | if (cp->c_flags&WCLOSE) { | |
459 | u.u_error = ENXIO; | |
460 | goto out; | |
461 | } | |
462 | if (cp->c_flags & EOTMARK) { | |
463 | cp->c_flags &= ~EOTMARK; | |
464 | if(msgenab(cp)) | |
465 | scontrol(cp, M_UBLK, 0); | |
466 | else { | |
467 | wakeup((caddr_t)cp); | |
468 | wakeup((caddr_t)q); | |
469 | } | |
470 | goto out; | |
471 | } | |
472 | sleep((caddr_t)q,TTIPRI); | |
473 | } | |
474 | if (cp->c_flags&WCLOSE) { | |
475 | u.u_error = ENXIO; | |
476 | goto out; | |
477 | } | |
478 | splx(s); | |
479 | while (mxmove(q, B_READ) > 0) | |
480 | ; | |
481 | mxrstrt(cp, q, SIGBLK); | |
482 | return; | |
483 | out: | |
484 | splx(s); | |
485 | } | |
486 | ||
487 | ||
488 | mswrite(fmp, cp) | |
489 | register struct chan *cp; | |
490 | { | |
491 | register struct clist *q; | |
492 | register int cc; | |
493 | ||
494 | q = (fmp&FMPX) ? &cp->cy.datq : &cp->cx.datq; | |
495 | while (u.u_count) { | |
496 | (void) spl6(); | |
497 | if (cp->c_flags&WCLOSE) { | |
498 | gsignal(cp->c_pgrp, SIGPIPE); | |
499 | (void) spl0(); | |
500 | return; | |
501 | } | |
502 | if (q->c_cc>= HIQ || cp->c_flags&FBLOCK) { | |
503 | if (cp->c_flags&WCLOSE) { | |
504 | gsignal(cp->c_pgrp, SIGPIPE); | |
505 | (void) spl0(); | |
506 | return; | |
507 | } | |
508 | (void) sdata(cp); | |
509 | cp->c_flags |= BLOCK; | |
510 | sleep((caddr_t)q+1,TTOPRI); | |
511 | (void) spl0(); | |
512 | continue; | |
513 | } | |
514 | (void) spl0(); | |
515 | cc = mxmove(q, B_WRITE); | |
516 | if (cc < 0) | |
517 | break; | |
518 | } | |
519 | if (fmp&FMPX) { | |
520 | if (cp->c_flags&YGRP) (void) sdata(cp); | |
521 | else wakeup((caddr_t)q); | |
522 | } else { | |
523 | if (cp->c_flags&XGRP) (void) sdata(cp); | |
524 | else wakeup((caddr_t)q); | |
525 | } | |
526 | } | |
527 | ||
528 | ||
529 | /* | |
530 | * move chars between clist and user space. | |
531 | */ | |
532 | ||
533 | mxmove(q, dir) | |
534 | register struct clist *q; | |
535 | register dir; | |
536 | { | |
537 | register cc; | |
538 | char cbuf[HIQ]; | |
539 | ||
540 | cc = MIN(u.u_count, sizeof cbuf); | |
541 | if (dir == B_READ) | |
542 | cc = q_to_b(q, cbuf, cc); | |
543 | if (cc <= 0) | |
544 | return(cc); | |
545 | IOMOVE((caddr_t)cbuf, (unsigned)cc, dir); | |
546 | if (dir == B_WRITE) | |
547 | cc = b_to_q(cbuf, cc, q); | |
548 | return(cc); | |
549 | } | |
550 | ||
551 | ||
552 | ||
553 | mxrstrt(cp, q, b) | |
554 | register struct chan *cp; | |
555 | register struct clist *q; | |
556 | register b; | |
557 | { | |
558 | int s; | |
559 | ||
560 | s = spl6(); | |
561 | if (cp->c_flags&b && q->c_cc<LOQ) { | |
562 | cp->c_flags &= ~b; | |
563 | if (b&ALT) | |
564 | wakeup((caddr_t)q+1); else | |
565 | mcstart(cp, (caddr_t)q); | |
566 | } | |
567 | if (cp->c_flags&WFLUSH) | |
568 | wakeup((caddr_t)q+2); | |
569 | splx(s); | |
570 | } | |
571 | ||
572 | ||
573 | ||
574 | /* | |
575 | * called from driver start or xint routines | |
576 | * to wakeup output sleeper. | |
577 | */ | |
578 | mcstart(cp, q) | |
579 | register struct chan *cp; | |
580 | register caddr_t q; | |
581 | { | |
582 | ||
583 | if (cp->c_flags&(BLKMSG)) { | |
584 | cp->c_flags &= ~BLKMSG; | |
585 | scontrol(cp, M_UBLK, 0); | |
586 | } else | |
587 | wakeup((caddr_t)q); | |
588 | } | |
589 | ||
590 | ||
591 | mxwcontrol(cp) | |
592 | register struct chan *cp; | |
593 | { | |
594 | short cmd; | |
595 | struct sgttyb vec; | |
596 | int s; | |
597 | ||
598 | IOMOVE((caddr_t)&cmd, sizeof cmd, B_WRITE); | |
599 | if (u.u_error) | |
600 | return; | |
601 | switch(cmd) { | |
602 | /* | |
603 | * not ready to queue this up yet. | |
604 | */ | |
605 | case M_EOT: | |
606 | s = spl6(); | |
607 | while (cp->c_flags & EOTMARK) | |
608 | if(msgenab(cp)){ | |
609 | scontrol(cp, M_BLK, 0); | |
610 | goto out; | |
611 | } else | |
612 | sleep((caddr_t)cp, TTOPRI); | |
613 | cp->c_flags |= EOTMARK; | |
614 | out: | |
615 | wakeup((caddr_t)&cp->cy.datq); | |
616 | splx(s); | |
617 | break; | |
618 | case M_IOCTL: | |
619 | break; | |
620 | case M_IOANS: | |
621 | if (cp->c_flags&SIOCTL) { | |
622 | IOMOVE((caddr_t)&vec, sizeof vec, B_WRITE); | |
623 | (void) b_to_q((caddr_t)&vec, sizeof vec, &cp->c_ctly); | |
624 | cp->c_flags &= ~SIOCTL; | |
625 | wakeup((caddr_t)cp); | |
626 | } | |
627 | break; | |
628 | case M_BLK: | |
629 | cp->c_flags |= FBLOCK; | |
630 | break; | |
631 | case M_UBLK: | |
632 | cp->c_flags &= ~FBLOCK; | |
633 | chwake(cp); | |
634 | break; | |
635 | default: | |
636 | u.u_error = ENXIO; | |
637 | } | |
638 | } | |
639 | ||
640 | ||
641 | ||
642 | /*ARGSUSED*/ | |
643 | mxioctl(dev, cmd, addr, flag) | |
644 | caddr_t addr; | |
645 | { | |
646 | struct group *gp; | |
647 | int fmp; | |
648 | struct file *fp; | |
649 | struct { | |
650 | short c_ctl; | |
651 | short c_cmd; | |
652 | struct sgttyb c_vec; | |
653 | } ctlbuf; | |
654 | ||
655 | if ((gp=getmpx(dev))==NULL || (fp=getf(u.u_arg[0]))==NULL) { | |
656 | return; | |
657 | } | |
658 | ||
659 | fmp = fp->f_flag & FMP; | |
660 | if (fmp == FMP) { | |
661 | switch(cmd) { | |
662 | ||
663 | case MXLSTN: | |
664 | if (mpxip == NULL) { | |
665 | mpxip = gp->g_inode; | |
666 | } else { | |
667 | u.u_error = ENXIO; | |
668 | return; | |
669 | } | |
670 | break; | |
671 | ||
672 | case MXNBLK: | |
673 | gp->g_state |= ENAMSG; | |
674 | break; | |
675 | ||
676 | default: | |
677 | u.u_error = ENXIO; | |
678 | return; | |
679 | } | |
680 | } else { | |
681 | ctlbuf.c_ctl = M_IOCTL; | |
682 | ctlbuf.c_cmd = cmd; | |
683 | (void) copyin(addr, (caddr_t)&ctlbuf.c_vec, sizeof (struct sgttyb)); | |
684 | sioctl(fp->f_un.f_chan, (char *)&ctlbuf, sizeof ctlbuf); | |
685 | (void) copyout((caddr_t)&ctlbuf, addr, sizeof (struct sgttyb)); | |
686 | } | |
687 | } | |
688 | ||
689 | ||
690 | chdrain(cp) | |
691 | register struct chan *cp; | |
692 | { | |
693 | register struct tty *tp; | |
694 | int wflag; | |
695 | ||
696 | chwake(cp); | |
697 | ||
698 | wflag = (cp->c_flags&WCLOSE)==0; | |
699 | tp = cp->c_ttyp; | |
700 | if (tp == NULL) /* prob not required */ | |
701 | return; | |
702 | if (cp->c_flags&PORT && tp->t_chan == cp) { | |
703 | cp->c_ttyp = NULL; | |
704 | tp->t_chan = NULL; | |
705 | return; | |
706 | } | |
707 | if (wflag) | |
708 | wflush(cp,&cp->cx.datq); else | |
709 | flush(&cp->cx.datq); | |
710 | if (!(cp->c_flags&YGRP)) { | |
711 | flush(&cp->cy.datq); | |
712 | } | |
713 | } | |
714 | ||
715 | chwake(cp) | |
716 | register struct chan *cp; | |
717 | { | |
718 | register char *p; | |
719 | ||
720 | wakeup((caddr_t)cp); | |
721 | flush(&cp->c_ctlx); | |
722 | p = (char *)&cp->cx.datq; | |
723 | wakeup((caddr_t)p); wakeup((caddr_t)++p); wakeup((caddr_t)++p); | |
724 | p = (char *)&cp->cy.datq; | |
725 | wakeup((caddr_t)p); wakeup((caddr_t)++p); wakeup((caddr_t)++p); | |
726 | } | |
727 | ||
728 | ||
729 | chfree(cp) | |
730 | register struct chan *cp; | |
731 | { | |
732 | register struct group *gp; | |
733 | register i; | |
734 | ||
735 | gp = cp->c_group; | |
736 | if (gp==NULL) | |
737 | return; | |
738 | i = cp->c_index; | |
739 | if (cp == gp->g_chans[i]) { | |
740 | gp->g_chans[i] = NULL; | |
741 | } | |
742 | cp->c_group = NULL; | |
743 | wakeup((caddr_t)gp); | |
744 | } | |
745 | ||
746 | ||
747 | flush(q) | |
748 | register struct clist *q; | |
749 | { | |
750 | ||
751 | while(q->c_cc) | |
752 | (void) getc(q); | |
753 | } | |
754 | ||
755 | ||
756 | wflush(cp,q) | |
757 | register struct chan *cp; | |
758 | register struct clist *q; | |
759 | { | |
760 | register s; | |
761 | ||
762 | s = spl6(); | |
763 | if(q->c_cc && (cp->c_flags&WCLOSE) == 0) { | |
764 | cp->c_flags |= WFLUSH; | |
765 | (void) sdata(cp); | |
766 | (void) tsleep((caddr_t)q+2, TTOPRI, 30); | |
767 | } | |
768 | flush(q); | |
769 | cp->c_flags &= ~WFLUSH; | |
770 | splx(s); | |
771 | } | |
772 | ||
773 | ||
774 | scontrol(cp,event,value) | |
775 | register struct chan *cp; | |
776 | short event,value; | |
777 | { | |
778 | register struct clist *q; | |
779 | int s; | |
780 | ||
781 | q = &cp->c_ctlx; | |
782 | s = spl6(); | |
783 | if (sdata(cp) == NULL) | |
784 | return; | |
785 | (void) putw(event,q); | |
786 | (void) putw(value,q); | |
787 | splx(s); | |
788 | } | |
789 | ||
790 | ||
791 | ||
792 | sioctl(cp, vec, cc) | |
793 | register struct chan *cp; | |
794 | char *vec; | |
795 | { | |
796 | register s; | |
797 | register struct clist *q; | |
798 | ||
799 | s = spl6(); | |
800 | q = &cp->cx.datq; | |
801 | while (q->c_cc) { | |
802 | cp->c_flags |= BLOCK; | |
803 | if (sdata(cp)==NULL) { | |
804 | u.u_error = ENXIO; | |
805 | return; | |
806 | } | |
807 | sleep((caddr_t)q+1, TTOPRI); | |
808 | } | |
809 | (void) b_to_q(vec, cc, &cp->c_ctlx); | |
810 | cp->c_flags |= SIOCTL; | |
811 | while (cp->c_flags&SIOCTL) { | |
812 | if (cp->c_ctlx.c_cc) | |
813 | if (sdata(cp)==NULL) { | |
814 | u.u_error = ENXIO; | |
815 | return; | |
816 | } | |
817 | sleep((caddr_t)cp, TTOPRI); | |
818 | } | |
819 | (void) q_to_b(&cp->c_ctly, vec, cp->c_ctly.c_cc); | |
820 | splx(s); | |
821 | } | |
822 | ||
823 | sdata(cp) | |
824 | struct chan *cp; | |
825 | { | |
826 | register struct group *gp = (struct group *)cp; | |
827 | register struct group *ngp; | |
828 | register int s; | |
829 | ||
830 | ngp = gp->g_group; | |
831 | if (ngp==NULL || (ngp->g_state&ISGRP)==0) | |
832 | return(NULL); | |
833 | ||
834 | s = spl6(); | |
835 | do { | |
836 | ngp->g_datq |= cmask[gp->g_index]; | |
837 | wakeup((caddr_t)&ngp->g_datq); | |
838 | gp = ngp; | |
839 | } while(ngp=ngp->g_group); | |
840 | splx(s); | |
841 | return((int)gp); | |
842 | } | |
843 | ||
844 | ||
845 | ||
846 | struct chan * | |
847 | xcp(gp, x) | |
848 | register struct group *gp; | |
849 | register short x; | |
850 | { | |
851 | register int i; | |
852 | ||
853 | while (gp->g_group) gp=gp->g_group; | |
854 | for (i=0;i<NLEVELS;i++) { | |
855 | if ((x&017) >= NINDEX) | |
856 | break; | |
857 | if (gp==NULL || (gp->g_state&ISGRP)==0) | |
858 | return((struct chan *)NULL); | |
859 | gp = (struct group *)gp->g_chans[x&017]; | |
860 | x >>= 4; | |
861 | } | |
862 | return((struct chan *)gp); | |
863 | } | |
864 | ||
865 | cpx(cp) | |
866 | register struct chan *cp; | |
867 | { | |
868 | register x; | |
869 | register struct group *gp; | |
870 | ||
871 | x = (-1<<4) + cp->c_index; | |
872 | gp = cp->c_group; | |
873 | while (gp->g_group) { | |
874 | x <<= 4; | |
875 | x |= gp->g_index; | |
876 | gp = gp->g_group; | |
877 | } | |
878 | return(x); | |
879 | } | |
880 | ||
881 | ||
882 | struct chan * | |
883 | nextcp(gp) | |
884 | register struct group *gp; | |
885 | { | |
886 | register struct group *lgp, *ngp; | |
887 | ||
888 | do { | |
889 | while ((gp->g_datq & cmask[gp->g_rot]) == 0) { | |
890 | gp->g_rot = (gp->g_rot+1)%NINDEX; | |
891 | } | |
892 | lgp = gp; | |
893 | gp = (struct group *)gp->g_chans[gp->g_rot]; | |
894 | } while (gp!=NULL && gp->g_state&ISGRP); | |
895 | ||
896 | lgp->g_datq &= ~cmask[lgp->g_rot]; | |
897 | lgp->g_rot = (lgp->g_rot+1)%NINDEX; | |
898 | ||
899 | while (ngp=lgp->g_group) { | |
900 | ngp->g_datq &= ~cmask[lgp->g_index]; | |
901 | if (ngp->g_datq) | |
902 | break; | |
903 | lgp = ngp; | |
904 | } | |
905 | return((struct chan *)gp); | |
906 | } | |
907 | ||
908 | ||
909 | ||
910 | msgenab(cp) | |
911 | register struct chan *cp; | |
912 | { | |
913 | register struct group *gp; | |
914 | ||
915 | for(gp=cp->c_group;gp;gp=gp->g_group) | |
916 | if(gp->g_state & ENAMSG)return(1); | |
917 | return(0); | |
918 | } |