1: #include "../h/param.h"
2: #include "../h/systm.h"
3: #include "../h/dir.h"
4: #include "../h/user.h"
5: #include "../h/reg.h"
6: #include "../h/proc.h"
7: #include "../h/tty.h"
8: #include "../h/inode.h"
9: #define KERNEL 1
10: #include "../h/mx.h"
11: #include "../h/file.h"
12: #include "../h/conf.h"
13:
14: /*
15: * Multiplexor: clist version
16: *
17: * installation:
18: * requires a line in cdevsw -
19: * mxopen, mxclose, mxread, mxwrite, mxioctl, 0,
20: *
21: * also requires a line in linesw -
22: * mxopen, mxclose, mcread, mcwrite, mxioctl, nulldev, nulldev,
23: *
24: * The linesw entry for mpx should be the last one in the table.
25: * 'nldisp' (number of line disciplines) should not include the
26: * mpx line. This is to prevent mpx from being enabled by an ioctl.
27:
28: * mxtty.c must be loaded instead of tty.c so that certain
29: * sleeps will not be done if a typewriter is connected to
30: * a channel and so that sdata will be called from ttyinput.
31: *
32: */
33: struct chan chans[NCHANS];
34: struct schan schans[NPORTS];
35: struct group *groups[NGROUPS];
36: int mpxline;
37: struct chan *xcp();
38: dev_t mpxdev = -1;
39:
40:
41: char mcdebugs[NDEBUGS];
42:
43:
44: /*
45: * Allocate a channel, set c_index to index.
46: */
47: struct chan *
48: challoc(index, isport)
49: {
50: register s;
51:
52: s = spl6();
53: if (isport) {
54: register struct schan *cp, *lastcp;
55: cp = schans;
56: lastcp = &schans[NPORTS];
57: for (; cp < lastcp; cp++)
58: if (cp->c_group==NULL) {
59: cp->c_index = index;
60: cp->c_pgrp = 0;
61: cp->c_flags = 0;
62: splx(s);
63: return((struct chan *)cp);
64: }
65: goto out;
66: } else {
67: register struct chan *cp, *lastcp;
68: cp = chans;
69: lastcp = &chans[NCHANS];
70: for(; cp < lastcp; cp++)
71: if(cp->c_group==NULL) {
72: cp->c_index = index;
73: cp->c_pgrp = 0;
74: cp->c_flags = 0;
75: splx(s);
76: return(cp);
77: }
78: }
79: out:
80: splx(s);
81: return(NULL);
82: }
83:
84:
85:
86: /*
87: * Allocate a group table cell.
88: */
89: gpalloc()
90: {
91: register i,s;
92:
93: s = spl6();
94: for(i = NGROUPS-1; i>=0; i--)
95: if (groups[i]==NULL) {
96: groups[i]++;
97: break;
98: }
99: splx(s);
100: return(i);
101: }
102:
103:
104: /*
105: * Add a channel to the group in
106: * inode ip.
107: */
108: struct chan *
109: addch(ip, isport)
110: struct inode *ip;
111: {
112: register struct chan *cp;
113: register struct group *gp;
114: register i;
115:
116: plock(ip);
117: gp = &ip->i_un.i_group;
118: for(i=0;i<NINDEX;i++) {
119: cp = (struct chan *)gp->g_chans[i];
120: if (cp == NULL) {
121: if ((cp=challoc(i, isport)) != NULL) {
122: gp->g_chans[i] = cp;
123: cp->c_group = gp;
124: }
125: break;
126: }
127: cp = NULL;
128: }
129: prele(ip);
130: return(cp);
131: }
132:
133:
134:
135:
136: /*
137: * mpxchan system call
138: */
139: mpxchan()
140: {
141: struct inode *ip, *gip;
142: register int i;
143: extern mxopen(), mcread();
144: extern sdata(), scontrol();
145: dev_t dev;
146: struct tty *tp;
147: struct file *fp, *chfp, *gfp;
148: struct chan *cp;
149: struct group *gp, *ngp;
150: struct a {
151: int cmd;
152: int *argvec;
153: } *uap;
154: struct mx_args vec;
155:
156:
157: /*
158: * common setup code.
159: */
160: uap = (struct a *)u.u_ap;
161: copyin((caddr_t)uap->argvec, (caddr_t)&vec, sizeof vec);
162: gp = NULL;
163: switch(uap->cmd) {
164: case NPGRP:
165: if (vec.m_arg[1] < 0)
166: goto sw;
167: case CHAN:
168: case JOIN:
169: case EXTR:
170: case ATTACH:
171: case DETACH:
172: case CSIG:
173: gfp = getf(vec.m_arg[1]);
174: if (gfp==NULL)
175: goto bad;
176: gip = gfp->f_inode;
177: gp = &gip->i_un.i_group;
178: if (gp->g_inode != gip)
179: goto bad;
180: }
181:
182: sw:
183: switch(uap->cmd) {
184: /*
185: * creat an mpx file.
186: */
187: case MPX:
188: case MPXN:
189: if (mpxdev < 0) {
190: for(i=0; linesw[i].l_open; i++)
191: if (linesw[i].l_read == mcread) {
192: mpxline = i;
193: goto found1;
194: }
195: goto bad;
196:
197: found1:
198: for(i=0; cdevsw[i].d_open; i++) {
199: if (cdevsw[i].d_open == mxopen)
200: goto found2;
201: }
202: bad:
203: u.u_error = ENXIO;
204: return;
205: found2:
206: mpxdev = (dev_t)(i<<8);
207: }
208: if (uap->cmd==MPXN) {
209: if ((ip=ialloc(rootdev))==NULL)
210: goto bad;
211: ip->i_mode = 0666+IFCHR;
212: goto merge;
213: }
214: u.u_dirp = vec.m_name;
215: ip = namei(uchar,1);
216: if (ip != NULL) {
217: u.u_error = EEXIST;
218: iput(ip);
219: return;
220: }
221: if (u.u_error)
222: return;
223: ip = maknode((vec.m_arg[0]&0777)+IFCHR);
224: if (ip == NULL)
225: return;
226: merge:
227: if ((i = gpalloc()) < 0) {
228: iput(ip);
229: goto bad;
230: }
231: ip->i_un.i_rdev = (daddr_t)(mpxdev+i);
232: gp = &ip->i_un.i_group;
233: groups[i] = gp;
234: gp->g_inode = ip;
235: gp->g_state = COPEN;
236: gp->g_group = NULL;
237: gp->g_index = 0;
238: gp->g_rotmask = 1;
239: gp->g_rot = 0;
240: gp->g_datq = 0;
241: open1(ip,FREAD+FWRITE,2);
242: if (u.u_error) {
243: groups[i] = NULL;
244: iput(ip);
245: goto bad;
246: }
247: ip->i_mode = (ip->i_mode & ~IFMT) | IFMPC;
248: ip->i_count++;
249: ip->i_flag |= IACC|IUPD|ICHG;
250: fp = u.u_ofile[u.u_r.r_val1];
251: fp->f_flag |= FMP;
252: fp->f_un.f_chan = NULL;
253: gp->g_file = fp;
254: for(i=0;i<NINDEX;)
255: gp->g_chans[i++] = NULL;
256: return;
257: /*
258: * join file descriptor (arg 0) to group (arg 1)
259: * return channel number
260: */
261: case JOIN:
262: if ((fp=getf(vec.m_arg[0]))==NULL)
263: goto bad;
264: ip = fp->f_inode;
265: i = ip->i_mode & IFMT;
266: if (i == IFMPC) {
267: if ((fp->f_flag&FMP) != FMP) {
268: goto bad;
269: }
270: ngp = &ip->i_un.i_group;
271: mlink (ngp, gp);
272: fp->f_count++;
273: return;
274: }
275: if (i != IFCHR)
276: goto bad;
277: dev = (dev_t)ip->i_un.i_rdev;
278: tp = cdevsw[major(dev)].d_ttys;
279: if (tp==NULL)
280: goto bad;
281: tp = &tp[minor(dev)];
282: if (tp->t_chan)
283: goto bad;
284: if ((cp=addch(gip, 1))==NULL)
285: goto bad;
286: tp->t_chan = cp;
287: cp->c_fy = fp;
288: fp->f_count++;
289: cp->c_ttyp = tp;
290: cp->c_line = tp->t_line;
291: cp->c_flags = XGRP+PORT;
292: u.u_r.r_val1 = cpx(cp);
293: return;
294: /*
295: * attach channel (arg 0) to group (arg 1)
296: */
297: case ATTACH:
298: cp = xcp(gp, vec.m_arg[0]);
299: if (cp==NULL)
300: goto bad;
301: u.u_r.r_val1 = cpx(cp);
302: wakeup((caddr_t)cp);
303: return;
304: case DETACH:
305: cp = xcp(gp, vec.m_arg[0]);
306: if (cp==NULL)
307: goto bad;
308: detach(cp);
309: return;
310: /*
311: * extract channel (arg 0) from group (arg 1).
312: */
313: case EXTR:
314: cp = xcp(gp, vec.m_arg[0]);
315: if (cp==NULL) {
316: goto bad;
317: }
318: if (cp->c_flags & ISGRP) {
319: mxfalloc(((struct group *)cp)->g_file);
320: return;
321: }
322: if ((fp = cp->c_fy) != NULL) {
323: mxfalloc(fp);
324: return;
325: }
326: if ((fp = falloc()) == NULL) {
327: return;
328: }
329: fp->f_inode = gip;
330: gip->i_count++;
331: fp->f_un.f_chan = cp;
332: fp->f_flag = (vec.m_arg[2]) ?
333: (FREAD|FWRITE|FMPY) : (FREAD|FWRITE|FMPX);
334: cp->c_fy = fp;
335: return;
336: /*
337: * make new chan on group (arg 1)
338: */
339: case CHAN:
340: if ((cp=addch(gip, 0))==NULL)
341: goto bad;
342: cp->c_flags = XGRP;
343: cp->c_fy = NULL;
344: cp->c_ttyp = cp->c_ottyp = (struct tty *)cp;
345: cp->c_line = cp->c_oline = mpxline;
346: u.u_r.r_val1 = cpx(cp);
347: return;
348: /*
349: * connect fd (arg 0) to channel fd (arg 1)
350: * (arg 2 < 0) => fd to chan only
351: * (arg 2 > 0) => chan to fd only
352: * (arg 2 == 0) => both directions
353: */
354: case CONNECT:
355: if ((fp=getf(vec.m_arg[0]))==NULL)
356: goto bad;
357: if ((chfp=getf(vec.m_arg[1]))==NULL)
358: goto bad;
359: ip = fp->f_inode;
360: i = ip->i_mode&IFMT;
361: if (i!=IFCHR)
362: goto bad;
363: dev = (dev_t)ip->i_un.i_rdev;
364: tp = cdevsw[major(dev)].d_ttys;
365: if (tp==NULL)
366: goto bad;
367: tp = &tp[minor(dev)];
368: if (!(chfp->f_flag&FMPY)) {
369: goto bad;
370: }
371: cp = chfp->f_un.f_chan;
372: if (cp==NULL || cp->c_flags&PORT) {
373: goto bad;
374: }
375: i = vec.m_arg[2];
376: if (i>=0) {
377: cp->c_ottyp = tp;
378: cp->c_oline = tp->t_line;
379: }
380: if (i<=0) {
381: tp->t_chan = cp;
382: cp->c_ttyp = tp;
383: cp->c_line = tp->t_line;
384: }
385: return;
386: case NPGRP: {
387: register struct proc *pp;
388:
389: if (gp != NULL) {
390: cp = xcp(gp, vec.m_arg[0]);
391: if (cp==NULL)
392: goto bad;
393: }
394: pp = u.u_procp;
395: pp->p_pgrp = pp->p_pid;
396: if (vec.m_arg[2])
397: pp->p_pgrp = vec.m_arg[2];
398: if (gp != NULL)
399: cp->c_pgrp = pp->p_pgrp;
400: return;
401: }
402: case CSIG:
403: cp = xcp(gp, vec.m_arg[0]);
404: if (cp==NULL)
405: goto bad;
406: signal(cp->c_pgrp, vec.m_arg[2]);
407: return;
408: case DEBUG:
409: i = vec.m_arg[0];
410: if (i<0 || i>NDEBUGS)
411: return;
412: mcdebugs[i] = vec.m_arg[1];
413: if (i==ALL)
414: for(i=0;i<NDEBUGS;i++)
415: mcdebugs[i] = vec.m_arg[1];
416: return;
417: default:
418: goto bad;
419: }
420: }
421:
422: detach(cp)
423: register struct chan *cp;
424: {
425: register struct group *gp;
426: register int i;
427:
428: if (cp->c_flags&ISGRP) {
429: gp = (struct group *)cp;
430: closef(gp->g_file);
431: i = ((struct group *)cp)->g_index;
432: gp->g_chans[i] = NULL;
433: return;
434: } else if (cp->c_flags&PORT && cp->c_ttyp != NULL) {
435: closef(cp->c_fy);
436: chdrain(cp);
437: chfree(cp);
438: return;
439: }
440: if (cp->c_fy && (cp->c_flags&WCLOSE)==0) {
441: cp->c_flags |= WCLOSE;
442: chwake(cp);
443: } else {
444: chdrain(cp);
445: chfree(cp);
446: }
447: }
448:
449:
450: mxfalloc(fp)
451: register struct file *fp;
452: {
453: register i;
454:
455: if (fp==NULL) {
456: u.u_error = ENXIO;
457: return;
458: }
459:
460: i = ufalloc();
461: if (i < 0)
462: return;
463: u.u_ofile[i] = fp;
464: fp->f_count++;
465: u.u_r.r_val1 = i;
466: return;
467: }
468:
469:
470:
471:
472: mlink(sub,master)
473: struct group *sub, *master;
474: {
475: register i;
476:
477:
478: for(i=0;i<NINDEX;i++) {
479: if (master->g_chans[i] != NULL)
480: continue;
481: master->g_chans[i] = (struct chan *)sub;
482: sub->g_group = master;
483: sub->g_index = i;
484: u.u_r.r_val1 = i;
485: return;
486: }
487: u.u_error = ENXIO;
488: return;
489: }
Defined functions
Defined variables
chans
defined in line
33; used 2 times
Defined struct's
a
defined in line
150; used 2 times
Defined macros
KERNEL
defined in line
9;
never used