|
|
1.1 root 1: /*
2: * UNIX device driver interface to the Chaos N.C.P.
3: */
4: #include "../chunix/chsys.h"
5: #include "../chunix/chconf.h"
6: #include "../chaos/chaos.h"
7: #include "../chaos/user.h"
8: #include "../chaos/dev.h"
9: #include "../h/inode.h"
10: #include "../h/file.h"
11: #include "../h/dir.h"
12: #include "../h/user.h"
13: #include "../h/conf.h"
14: #include "../h/ioctl.h"
15: #include "../h/buf.h"
16: #include "../h/systm.h"
17: #include "../h/tty.h"
18:
19: #ifdef VMUNIX
20: #include "cht.h"
21: #endif
22:
23: static int initted; /* NCP initialization flag */
24: int Rfcwaiting; /* Someone waiting on unmatched RFC */
25: static char *chnames[][3] = {
26: /* reading writing read/write */
27: { "uread", "ucreate", "ureadwrite", },
28: };
29:
30: #define CHFCONN(fp) ((fp)->f_conn)
31: #define CHIOPRIO (PZERO+1) /* Just interruptible */
32: #ifndef VMUNIX
33: #define setjmp save
34: #endif
35: static struct packet *fillpacket();
36: /*
37: * Open a chaos channel.
38: * Special case devices are indicated if CHHOST(dev) == CHHSPEC.
39: * See <chaos/dev.h> for the definitions.
40: * Non-special device opens imply a request to create a new connection
41: * via an RFC to a specified host, with a specified contact name string.
42: * The host number is specified one of three ways (CHHOST(dev)):
43: * CHHREAD Read an ascii host number from the remainder
44: * of the pathname (after the component that
45: * matched this device).
46: * CHHUSE Use the component that matched itself
47: * as an ascii number.
48: * else Use the CHHOST(dev) as an index into an
49: * internal host table where frequently used
50: * host numbers should reside.
51: * The contact name can also be specified in three ways (CHNAME(dev)):
52: * CHNREAD Read the contact string from the rest of the
53: * path name (possibly after host number).
54: * CHNUSE Read the contact string from the path
55: * component that matched (possibly after host
56: * number).
57: * else Use the CHNAME(dev) as an index into an
58: * internal array of contact names, also
59: * indexed by the type of open (read, write, rw).
60: */
61: chropen(dev, flag)
62: dev_t dev;
63: {
64: register struct connection *conn;
65: register struct packet *pkt;
66: int host, name, wstate;
67:
68: ch_bufalloc();
69: /* initialize the NCP somewhere else? */
70: if (!initted) {
71: chrreset(); /* Reset drivers */
72: chtimeout(); /* Start clock "process" */
73: initted++;
74: }
75: conn = NOCONN;
76: name = CHNAME(dev);
77: host = CHHOST(dev);
78: wstate = 0;
79: if (host == CHHSPEC)
80: switch (name) {
81: case CHUNMATCHED:
82: if(Chrfcrcv == 0) {
83: Chrfcrcv++;
84: return;
85: }
86: break;
87: /*
88: * Listens create a connection waiting for RFC's containing
89: * the given contact name. The returned file descriptor
90: * corresponds to a connection that may not be open yet.
91: * Use ioctls (CHIOCGSTAT, CHIOCSWAIT), to check or
92: * hang on the state of the connection.
93: */
94: case CHLISTEN:
95: if ((pkt = fillpacket("", 0)) != NOPKT)
96: conn = ch_listen(pkt);
97: break;
98: }
99: else {
100: register int len = DIRSIZ;
101: char *namp = u.u_dbuf;
102:
103: switch(host) {
104: case CHHREAD:
105: host = uatoi((char **)0);
106: break;
107: case CHHUSE:
108: host = uatoi(&namp); /* stuffs namp */
109: break;
110: default:
111: host = chhosts[host];
112: }
113: if (u.u_error)
114: host = 0;
115: switch(name) {
116: case CHNREAD:
117: namp = "";
118: len = 0;
119: break;
120: case CHNUSE:
121: len = DIRSIZ - (namp - u.u_dbuf);
122: break;
123: default:
124: len = CHMAXRFC;
125: if ((namp = chnames[name][flag-1]) == NONAME)
126: host = 0;
127: }
128: if (host != 0 && (pkt = fillpacket(namp, len)) != NOPKT &&
129: (conn = ch_open(host, CHDRWSIZE, pkt)) != NOCONN &&
130: CHHANGDEV(dev))
131: wstate = CSRFCSENT; /* Wait until OPEN/CLOSED */
132: }
133: if (conn == NOCONN) {
134: u.u_error = ENXIO;
135: ch_buffree();
136: } else {
137: register struct file *fp;
138:
139: fp = u.u_ofile[u.u_r.r_val1]; /* Yick. (see mx2.c) */
140: CHFCONN(fp) = (caddr_t)conn;
141: if (wstate) {
142: /*
143: * We should hang until the connection changes from
144: * its initial state.
145: * If interrupted, flush the connection.
146: */
147: #ifdef VMUNIX
148: if (setjmp(u.u_qsav) == 0) {
149: #else
150: if (save(u.u_qsav) == 0) {
151: #endif
152: spl6();
153: while (conn->cn_state == wstate)
154: sleep((caddr_t)conn, CHIOPRIO);
155: spl0();
156: #ifdef DEBUG
157: if (ch_badaddr((char *)conn))
158: panic("chopen");
159: #endif DEBUG
160: }
161: /*
162: * If the connection is not open, the open failed.
163: * Unless is got an ANS back.
164: */
165: if (conn->cn_state != CSOPEN &&
166: (conn->cn_state != CSCLOSED ||
167: (pkt = conn->cn_rhead) == NOPKT ||
168: pkt->pk_op != ANSOP)) {
169: rlsconn(conn);
170: u.u_error = ENXIO;
171: return;
172: }
173: }
174: conn->cn_sflags |= CHRAW;
175: conn->cn_mode = CHSTREAM;
176: }
177: }
178:
179: /* ARGSUSED */
180: chrclose(dev, flag, cp)
181: dev_t dev;
182: struct chan *cp;
183: {
184: register struct connection *conn = (struct connection *)cp;
185:
186: if (minor(dev) == CHURFCMIN) {
187: Chrfcrcv = 0;
188: freelist(Chrfclist);
189: Chrfclist = NOPKT;
190: return;
191: }
192: /*
193: * If this connection has been turned into a tty, then the
194: * tty owns it and we don't do anything.
195: */
196: if (conn->cn_mode != CHTTY)
197: chclose(conn, flag);
198: }
199: chclose(conn, flag)
200: register struct connection *conn;
201: {
202: register struct packet *pkt;
203:
204: switch (conn->cn_mode) {
205: case CHTTY:
206: panic("chclose on tty");
207: case CHSTREAM:
208: spl6();
209: if (setjmp(u.u_qsav)) {
210: pkt = pktstr(NOPKT, "User interrupted", 16);
211: if (pkt != NOPKT)
212: pkt->pk_op = CLSOP;
213: ch_close(conn, pkt, 0);
214: goto shut;
215: }
216: if (flag & FWRITE) {
217: /*
218: * If any input packets other than the RFC are around
219: * something is wrong and we just abort the connection
220: */
221: while ((pkt = conn->cn_rhead) != NOPKT) {
222: ch_read(conn);
223: if (pkt->pk_op != RFCOP)
224: goto recclose;
225: }
226: /*
227: * We set this flag telling the interrupt time
228: * receiver to abort the connection if any new packets
229: * arrive.
230: */
231: conn->cn_sflags |= CHCLOSING;
232: /*
233: * Closing a stream transmitter involves flushing
234: * the last packet, sending an EOF and waiting for
235: * it to be acknowledged. If the connection was
236: * bidirectional, the reader should have already
237: * read until EOF if everything is to be closed
238: * cleanly.
239: */
240: checkfull:
241: while (chtfull(conn)) {
242: conn->cn_sflags |= CHOWAIT;
243: sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
244: }
245: if (conn->cn_state == CSOPEN ||
246: conn->cn_state == CSRFCRCVD) {
247: if (conn->cn_toutput) {
248: ch_sflush(conn);
249: goto checkfull;
250: }
251: if (conn->cn_state == CSOPEN)
252: (void)ch_eof(conn);
253: }
254: while (!chtempty(conn)) {
255: conn->cn_sflags |= CHOWAIT;
256: sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
257: }
258: } else if (conn->cn_state == CSOPEN) {
259: /*
260: * If we are only reading then we should read the EOF
261: * before closing and wiat for the other end to close.
262: */
263: if (conn->cn_flags & CHEOFSEEN)
264: while (conn->cn_state == CSOPEN)
265: sleep((caddr_t)conn, CHIOPRIO);
266: }
267: recclose:
268: spl0();
269: /* Fall into... */
270: case CHRECORD: /* Record oriented close is just sending a CLOSE */
271: if (conn->cn_state == CSOPEN) {
272: pkt = pkalloc(0, 0);
273: if (pkt != NOPKT) {
274: pkt->pk_op = CLSOP;
275: pkt->pk_len = 0;
276: }
277: ch_close(conn, pkt, 0);
278: }
279: }
280: shut:
281: spl0();
282: ch_close(conn, NOPKT, 1);
283: ch_buffree();
284: }
285: /*
286: * Raw read routine.
287: */
288: chrread(dev)
289: dev_t dev;
290: {
291: register struct connection *conn;
292: register struct packet *pkt;
293: register int count, n;
294:
295: if(minor(dev) == CHURFCMIN) {
296: spl6();
297: while ((pkt = ch_rnext()) == NOPKT) {
298: Rfcwaiting++;
299: sleep((caddr_t)&Chrfclist, CHIOPRIO);
300: }
301: spl0();
302: if (u.u_count < pkt->pk_len)
303: u.u_error = EIO;
304: else
305: iomove((caddr_t)pkt->pk_cdata, pkt->pk_len, B_READ);
306: return;
307: }
308: conn = (struct connection *)CHFCONN(getf(u.u_arg[0]));
309:
310: switch (conn->cn_mode) {
311: case CHTTY:
312: panic("chread on tty");
313: break;
314: case CHSTREAM:
315: for (count = u.u_count; u.u_count != 0; )
316: switch (n = ch_sread(conn, (char*)0, u.u_count)) {
317: case 0: /* No data to read */
318: if (count != u.u_count)
319: return;
320: spl6();
321: while (chrempty(conn)) {
322: conn->cn_sflags |= CHIWAIT;
323: sleep((char *)&conn->cn_rhead,
324: CHIOPRIO);
325: }
326: spl0();
327: break;
328: case CHEOF:
329: return;
330: default:
331: if (n < 0) {
332: u.u_error = EIO;
333: return;
334: }
335: }
336: break;
337: /*
338: * Record oriented mode gives a one byte packet opcode
339: * followed by the data in the packet. The buffer must
340: * be large enough to fit the data and the opcode, otherwise an
341: * i/o error results.
342: */
343: case CHRECORD:
344: spl6();
345: while (chrempty(conn)) {
346: conn->cn_sflags |= CHIWAIT;
347: sleep((char *)&conn->cn_rhead,
348: CHIOPRIO);
349: }
350: spl0();
351: if ((pkt = conn->cn_rhead) == NOPKT ||
352: pkt->pk_len + 1 > u.u_count) /* + 1 for opcode */
353: u.u_error = EIO;
354: else {
355: iomove((caddr_t)&pkt->pk_op, 1, B_READ);
356: iomove((caddr_t)pkt->pk_cdata, pkt->pk_len, B_READ);
357: spl6();
358: ch_read(conn);
359: spl0();
360: }
361: }
362: }
363: /*
364: * Raw write routine
365: * Note that user programs can write to a connection
366: * that has been CHIOCANSWER"'d, implying transmission of an ANS packet
367: * rather than a normal packet. This is illegal for TTY mode connections,
368: * is handled in the system independent stream code for STREAM mode, and
369: * is handled here for RECORD mode.
370: */
371: chrwrite(dev)
372: dev_t dev;
373: {
374: register struct connection *conn;
375:
376: if(minor(dev) == CHURFCMIN) {
377: u.u_error = EIO;
378: return;
379: }
380: conn = (struct connection *)CHFCONN(getf(u.u_arg[0]));
381: chwrite(conn);
382: }
383: chwrite(conn)
384: register struct connection *conn;
385: {
386: register struct packet *pkt;
387: register int n;
388:
389: if (conn->cn_rhead != NOPKT && conn->cn_rhead->pk_op == RFCOP) {
390: spl6();
391: ch_read(conn);
392: spl0();
393: }
394: switch (conn->cn_mode) {
395: case CHTTY:
396: /* Fall into (on RAW mode only) */
397: case CHSTREAM:
398: while (u.u_count != 0)
399: switch (n = ch_swrite(conn, (char *)0, u.u_count)) {
400: case 0:
401: spl6();
402: while (chtfull(conn)) {
403: conn->cn_sflags |= CHOWAIT;
404: sleep((caddr_t)&conn->cn_thead,
405: CHIOPRIO);
406: }
407: spl0();
408: break;
409: case CHTEMP:
410: sleep((caddr_t)&lbolt, CHIOPRIO);
411: break;
412: default:
413: if (n < 0) {
414: u.u_error = EIO;
415: return;
416: }
417: }
418: break;
419: case CHRECORD: /* one write call -> one packet */
420: if (u.u_count < 1 || u.u_count - 1 > CHMAXDATA) {
421: u.u_error = EIO;
422: return;
423: }
424: loop:
425: spl6();
426: while (chtfull(conn)) {
427: conn->cn_sflags |= CHOWAIT;
428: sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
429: }
430: spl0();
431: if ((pkt = pkalloc((int)(u.u_count - 1), 0)) == NOPKT) {
432: sleep((caddr_t)&lbolt, CHIOPRIO);
433: goto loop;
434: }
435: iomove(&pkt->pk_op, 1, B_WRITE);
436: pkt->pk_len = u.u_count;
437: if (u.u_count)
438: iomove(pkt->pk_cdata, u.u_count, B_WRITE);
439: if (u.u_error == 0) {
440: spl6();
441: if (ch_write(conn, pkt))
442: u.u_error = EIO;
443: spl0();
444: }
445: }
446: }
447:
448: /*
449: * This routine allocates a packet and fills it with data from pointer in
450: * user space until null or CHMAXDATA characters
451: */
452: static struct packet *
453: fillpacket(str, len)
454: register char *str;
455: int len; /* assumed <= CHMAXDATA */
456: {
457: register char *ptr;
458: register struct packet *pkt;
459: int c;
460: extern uchar();
461:
462: if ((pkt = pkalloc(CHMAXDATA, 0)) != NOPKT) {
463: ptr = pkt->pk_cdata;
464: for (pkt->pk_len = 0; *str != '\0' && pkt->pk_len < len; pkt->pk_len++)
465: *ptr++ = *str++;
466: while ((c = uchar()) > 0 && pkt->pk_len < CHMAXDATA) {
467: *ptr++ = c;
468: pkt->pk_len++;
469: }
470: if (c > 0) {
471: debug(DABNOR,
472: printf("Fillpacket too long: %s\n",
473: pkt->pk_cdata));
474: ch_free((char *)pkt);
475: } else
476: return(pkt);
477: }
478: u.u_error = ENXIO;
479: return(NOPKT);
480: }
481: /*
482: * This is atoi from users space terminates on / or null.
483: * If cpp is not NULL then get the number from *cpp (u.u_dbuf).
484: * *cpp is stuffed where the scan stopped, enabling further usage of the
485: * contents of u.u_dbuf.
486: */
487: static
488: uatoi(cpp)
489: char **cpp;
490: {
491: register char *p = cpp ? *cpp - 1 : (char *)0;
492: register int i = 0, chr;
493: extern uchar();
494:
495: for (;;) {
496: if (p)
497: if (++p >= &u.u_dbuf[DIRSIZ])
498: break;
499: else
500: chr = *p;
501: else if ((chr = uchar()) == '/')
502: break;
503: if ((chr -= '0') < 0 || chr > 9)
504: break;
505: i *= 10;
506: i += chr;
507: }
508: if (cpp)
509: *cpp = p;
510: return(i);
511: }
512:
513: /*
514: * Raw ioctl routine - perform non-connection functions, otherwise call down
515: */
516: chrioctl(dev, cmd, addr, flag)
517: register int cmd;
518: caddr_t addr;
519: {
520: register char *cp;
521: register int c;
522:
523: switch (cmd) {
524: /*
525: * Skip the first unmatched RFC at the head of the queue
526: * and mark it so that ch_rnext will never pick it up again.
527: */
528: case CHIOCRSKIP:
529: if (minor(dev) != CHURFCMIN)
530: break;
531: spl6();
532: ch_rskip();
533: spl0();
534: return;
535: /*
536: * Specify the chaosnet address of an interlan ethernet interface.
537: */
538: case CHIOCILADDR:
539: if (minor(dev) != CHURFCMIN)
540: break;
541: #if NCHIL > 0
542: {
543: struct chiladdr ca;
544:
545: if (addr == 0 || copyin(addr, (caddr_t)&ca, sizeof(ca)))
546: break;
547: if (chilseta(ca.cil_device, ca.cil_address))
548: break;
549: return;
550: }
551: #else
552: break;
553: #endif
554: case CHIOCNAME:
555: if (minor(dev) != CHURFCMIN)
556: break;
557: for (cp = Chmyname; c = fubyte(addr); *cp++ = c, addr++)
558: if (c < 0) {
559: cp = Chmyname;
560: u.u_error = EFAULT;
561: break;
562: } else if(cp >= &Chmyname[CHSTATNAME])
563: break;
564: while (cp < &Chmyname[CHSTATNAME])
565: *cp++ = '\0';
566: if (c >= 0)
567: return;
568: break;
569: /*
570: * Specify my own network number.
571: */
572: case CHIOCADDR:
573: if (minor(dev) != CHURFCMIN)
574: break;
575: Chmyaddr = (int)addr;
576: return;
577: default:
578: if (minor(dev) == CHURFCMIN)
579: break;
580: chioctl(CHFCONN(getf(u.u_arg[0])), dev, cmd, addr, flag);
581: return;
582: }
583: u.u_error = ENXIO;
584: }
585: /* ARGSUSED */
586: chioctl(conn, dev, cmd, addr, flag)
587: register struct connection *conn;
588: dev_t dev;
589: caddr_t addr;
590: {
591: register struct packet *pkt;
592: struct chstatus chst;
593:
594: switch(cmd) {
595: /*
596: * Read the first packet in the read queue for a connection.
597: * This call is primarily intended for those who want to read
598: * non-data packets (which are normally ignored) like RFC
599: * (for arguments in the contact string), CLS (for error string) etc.
600: * The reader's buffer is assumed to be CHMAXDATA long. When ioctl's
601: * change on the VAX to have data length arguments, this will be done
602: * right. An error results if there is no packet to read.
603: * No hanging is currently provided for.
604: * The normal mode of operation for reading such packets is to
605: * first do a CHIOCGSTAT call to find out whether there is a packet
606: * to read (and what kind) and then make this call - except for
607: * RFC's when you know it must be there.
608: */
609: case CHIOCPREAD:
610: if ((pkt = conn->cn_rhead) == NULL)
611: break;
612: if (copyout((caddr_t)pkt->pk_cdata, addr, pkt->pk_len))
613: break;
614: spl6();
615: ch_read(conn);
616: spl0();
617: return;
618: /*
619: * Change the mode of the connection.
620: * The default mode is CHSTREAM.
621: */
622: case CHIOCSMODE:
623: switch ((int)addr) {
624: case CHTTY:
625: #if NCHT > 0
626: if (conn->cn_state == CSOPEN &&
627: conn->cn_mode != CHTTY) {
628: register struct tty *tp;
629: extern struct tty cht_tty[];
630: extern int cht_cnt;
631: /*
632: * To turn a connection into a tty,
633: * we need to find a tty that is waiting to
634: * be opened and connect ourselves to it.
635: */
636: for (tp = cht_tty; tp < &cht_tty[cht_cnt]; tp++)
637: if (tp->t_addr == 0 &&
638: tp->t_state & WOPEN) {
639: tp->t_addr = (caddr_t)conn;
640: tp->t_state |= CARR_ON;
641: conn->cn_ttyp = tp;
642: conn->cn_mode = CHTTY;
643: wakeup((caddr_t)&tp->t_rawq);
644: return;
645: }
646:
647: }
648: #endif
649: break;
650: case CHSTREAM:
651: case CHRECORD:
652: if (conn->cn_mode == CHTTY)
653: break;
654: conn->cn_mode = (int)addr;
655: return;
656: }
657: break;
658: /*
659: * Flush the current output packet if there is one.
660: * This is only valid in stream mode.
661: * If the argument is non-zero an error is returned if the
662: * transmit window is full, otherwise we hang.
663: */
664: case CHIOCFLUSH:
665: if (conn->cn_mode == CHSTREAM) {
666: spl6();
667: while ((flag = ch_sflush(conn)) == CHTEMP)
668: if (addr)
669: break;
670: else {
671: conn->cn_sflags |= CHOWAIT;
672: sleep((caddr_t)&conn->cn_thead,
673: CHIOPRIO);
674: }
675: if (flag)
676: u.u_error = EIO;
677: spl0();
678: return;
679: }
680: break;
681: /*
682: * Wait for all output to be acknowledged. If addr is non-zero
683: * an EOF packet is also sent before waiting.
684: * If in stream mode, output is flushed first.
685: */
686: case CHIOCOWAIT:
687: if (conn->cn_mode == CHSTREAM) {
688: spl6();
689: while ((flag = ch_sflush(conn)) == CHTEMP) {
690: conn->cn_sflags |= CHOWAIT;
691: sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
692: }
693: spl0();
694: if (flag) {
695: u.u_error = EIO;
696: return;
697: }
698: }
699: if (addr) {
700: spl6();
701: while (chtfull(conn)) {
702: conn->cn_sflags |= CHOWAIT;
703: sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
704: }
705: flag = ch_eof(conn);
706: spl0();
707: if (flag) {
708: u.u_error = EIO;
709: return;
710: }
711: }
712: spl6();
713: while (!chtempty(conn)) {
714: conn->cn_sflags |= CHOWAIT;
715: sleep((caddr_t)&conn->cn_thead, CHIOPRIO);
716: }
717: spl0();
718: if (conn->cn_state != CSOPEN)
719: u.u_error = EIO;
720: return;
721: /*
722: * Return the status of the connection in a structure supplied
723: * by the user program.
724: */
725: case CHIOCGSTAT:
726: chst.st_fhost = conn->cn_faddr;
727: chst.st_cnum = conn->cn_ltidx;
728: chst.st_rwsize = conn->cn_rwsize;
729: chst.st_twsize = conn->cn_twsize;
730: chst.st_state = conn->cn_state;
731: chst.st_cmode = conn->cn_mode;
732: chst.st_oroom = conn->cn_twsize - (conn->cn_tlast - conn->cn_tacked);
733: if ((pkt = conn->cn_rhead) != NOPKT) {
734: chst.st_ptype = pkt->pk_op;
735: chst.st_plength = pkt->pk_len;
736: } else {
737: chst.st_ptype = 0;
738: chst.st_plength = 0;
739: }
740: if (copyout((caddr_t)&chst, addr, sizeof(chst)))
741: break;
742: return;
743: /*
744: * Wait for the state of the connection to be different from
745: * the given state.
746: */
747: case CHIOCSWAIT:
748: spl6();
749: while (conn->cn_state == (int)addr)
750: sleep((caddr_t)conn, CHIOPRIO);
751: spl0();
752: return;
753: /*
754: * Answer an RFC. Basically this call does nothing except
755: * setting a bit that says this connection should be of the
756: * datagram variety so that the connection automatically gets
757: * closed after the first write, whose data is immediately sent
758: * in an ANS packet.
759: */
760: case CHIOCANSWER:
761: spl6();
762: if (conn->cn_state == CSRFCRCVD && conn->cn_mode != CHTTY)
763: conn->cn_flags |= CHANSWER;
764: else
765: u.u_error = EIO;
766: spl0();
767: return;
768: /*
769: * Reject a RFC, giving a string (null terminated), to put in the
770: * close packet. This call can also be used to shut down a connection
771: * prematurely giving an ascii close reason.
772: */
773: case CHIOCREJECT:
774: spl6();
775: if (conn->cn_state == CSRFCRCVD || conn->cn_state == CSOPEN) {
776: u.u_dirp = addr; /* a kludge for fillpacket */
777: pkt = fillpacket("", 0);
778: pkt->pk_op = CLSOP;
779: ch_close(conn, pkt, 0);
780: } else
781: u.u_error = EIO;
782: spl0();
783: return;
784: /*
785: * Accept an RFC causing the OPEN packet to be sent
786: */
787: case CHIOCACCEPT:
788: spl6();
789: if (conn->cn_state == CSRFCRCVD)
790: ch_accept(conn);
791: else
792: u.u_error = EIO;
793: spl0();
794: return;
795: /*
796: * Count how many bytes can be immediately read.
797: */
798: case FIONREAD:
799: if (conn->cn_mode != CHTTY) {
800: off_t nread = 0;
801:
802: for (pkt = conn->cn_rhead; pkt != NOPKT; pkt = pkt->pk_next)
803: if (ISDATOP(pkt))
804: nread += pkt->pk_len;
805: if (conn->cn_rhead != NOPKT)
806: nread -= conn->cn_roffset;
807: if (copyout((caddr_t)&nread, addr, sizeof(off_t)))
808: u.u_error = EFAULT;
809: return;
810: }
811: default:
812: break;
813: }
814: u.u_error = ENXIO;
815: }
816: /*
817: * Timeout routine that implements the chaosnet clock process.
818: */
819: chtimeout()
820: {
821: register int s = spl6();
822: ch_clock();
823: timeout(chtimeout, 0, 1);
824: splx(s);
825: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.