|
|
1.1 ! root 1: /* ! 2: * C H A O S L D ! 3: * ! 4: * Chaosnet line discipline, to be pushed on an ethernet controller. ! 5: * Handles xmit and rcv windows, packet numbering, and connection states. ! 6: * ! 7: * ! 8: * (c) Copyright 1985 Nirvonics, Inc. ! 9: * ! 10: * Written by Kurt Gollhardt ! 11: * Last update Tue Mar 12 04:18:58 1985 ! 12: * ! 13: * This software is the property of Nirvonics, Inc. ! 14: * All rights reserved. ! 15: * ! 16: */ ! 17: ! 18: #include "ch.h" ! 19: #if NCH ! 20: #include "../h/param.h" ! 21: #include "../h/systm.h" ! 22: #include "../h/stream.h" ! 23: #include "../h/ioctl.h" ! 24: #include "../h/ttyld.h" ! 25: #include "../h/map.h" ! 26: #include "../h/buf.h" ! 27: #include "../h/conf.h" ! 28: #include "../chaosld/types.h" ! 29: #define CHDEFINE ! 30: #include "../chaosld/globals.h" ! 31: ! 32: ! 33: extern int chrcv(), chb_put(); ! 34: int chopen(), chclose(), chosrv(), chisrv(); ! 35: static struct qinit chrinit = { chb_put, chisrv, chopen, chclose, 512, 64 }; ! 36: static struct qinit chwinit = { putq, chosrv, chopen, chclose, 512, 64 }; ! 37: struct streamtab chinfo = { &chrinit, &chwinit }; ! 38: ! 39: chopen(q, dev) ! 40: register struct queue *q; ! 41: { ! 42: if (q->ptr) ! 43: return(1); ! 44: if (ChaosQ != (struct queue *)0) /* Already open */ ! 45: return(0); ! 46: ChaosQ = q; /* that's the RD q */ ! 47: q->flag |= QDELIM|QNOENB; /* chiput calls qenable() */ ! 48: WR(q)->flag |= QDELIM; ! 49: return(1); ! 50: } ! 51: ! 52: chclose(q) ! 53: struct queue *q; ! 54: { ! 55: struct connection **connp; ! 56: int ps = spl6(); ! 57: ! 58: for (connp = Chconn; connp < &Chconn[NCH]; ++connp) ! 59: if (*connp != NOCONN) ! 60: chld_close(*connp, NOPKT); ! 61: ! 62: freelist(Chlsnlist); ! 63: freelist(Chrfclist); ! 64: Chlsnlist = Chrfclist = Chrfctail = NOPKT; ! 65: Chmyaddr.ch_addr = 0; ! 66: ! 67: ChaosQ = (struct queue *)0; ! 68: splx(ps); ! 69: } ! 70: ! 71: ! 72: chisrv(q) ! 73: struct queue *q; ! 74: { ! 75: register struct block *bp; ! 76: ! 77: chrcv(q); /* Receive the packet */ ! 78: ! 79: /* See if there's another packet on the queue */ ! 80: for (bp = q->first; bp != NOBLOCK; bp = bp->next) ! 81: if (bp->type == M_DELIM) { ! 82: qenable(q); /* re-enable queue for the next packet */ ! 83: break; ! 84: } ! 85: } ! 86: ! 87: ! 88: chosrv(q) ! 89: register struct queue *q; ! 90: { ! 91: register union stmsg *sp; ! 92: register struct block *bp; ! 93: ! 94: while(bp = getq(q)){ ! 95: if(bp->type == M_IOCTL){ ! 96: sp = (union stmsg *)bp->rptr; ! 97: switch(sp->ioc0.com){ ! 98: case CHIOCNAME: ! 99: copyin(*(caddr_t *)sp->iocx.xxx, Chmyname, CHSTATNAME); ! 100: bp->rptr = bp->wptr; ! 101: bp->type = M_IOCACK; ! 102: qreply(q, bp); ! 103: break; ! 104: case CHIOCADDR: ! 105: Chmyaddr.ch_addr = *(int *)sp->iocx.xxx; ! 106: /* fall through */ ! 107: default: ! 108: (*q->next->qinfo->putp)(q->next, bp); ! 109: break; ! 110: } ! 111: } else ! 112: (*q->next->qinfo->putp)(q->next, bp); ! 113: } ! 114: } ! 115: ! 116: chld_write(conn, pkt) ! 117: register struct connection *conn; ! 118: register struct packet *pkt; ! 119: { ! 120: setconn(conn, pkt); ! 121: ! 122: switch (pkt->pk_op) { ! 123: case ANSOP: ! 124: case FWDOP: ! 125: if (conn->cn_state != CSRFCRCVD || ! 126: (conn->cn_flags & CHANSWER) == 0) ! 127: goto err; ! 128: chld_close(conn, pkt); ! 129: return 0; ! 130: case RFCOP: ! 131: case BRDOP: ! 132: if (conn->cn_state != CSRFCSENT) ! 133: goto err; ! 134: break; ! 135: case UNCOP: ! 136: pkt->pk_pkn = 0; ! 137: pkt->next = NOPKT; ! 138: senddata(pkt); ! 139: return 0; ! 140: default: ! 141: if (!ISDATA(pkt)) ! 142: goto err; ! 143: case OPNOP: ! 144: case EOFOP: ! 145: if (conn->cn_state != CSOPEN) ! 146: goto err; ! 147: setack(conn, pkt); ! 148: break; ! 149: } ! 150: ! 151: pkt->pk_pkn = ++conn->cn_tlast; ! 152: senddata(pkt); ! 153: return 0; ! 154: ! 155: err: ! 156: free_packet(pkt); ! 157: return -1; ! 158: } ! 159: ! 160: ! 161: chld_eof(conn) ! 162: struct connection *conn; ! 163: { ! 164: register struct packet *pkt; ! 165: ! 166: if ((pkt = new_packet()) != NOPKT) { ! 167: setconn(conn, pkt); ! 168: pkt->pk_op = EOFOP; ! 169: return chld_write(conn, pkt); ! 170: } ! 171: return 0; ! 172: } ! 173: ! 174: ! 175: chld_accept(conn) ! 176: struct connection *conn; ! 177: { ! 178: conn->cn_state = CSOPEN; ! 179: sendopn(conn); ! 180: } ! 181: ! 182: ! 183: chld_open(conn, daddr, rwsize, pkt) ! 184: register struct connection *conn; ! 185: register struct packet *pkt; ! 186: { ! 187: conn->cn_faddr.ch_addr = daddr; ! 188: conn->cn_state = CSRFCSENT; ! 189: conn->cn_rwsize = rwsize; ! 190: conn->cn_rsts = rwsize / 2; ! 191: conn->cn_time = Chclock; ! 192: pkt->pk_op = RFCOP; ! 193: pkt->pk_fc = pkt->pk_ackn = 0; ! 194: debug(DCONN,printf("Conn #%x: RFCS state\n", conn->cn_lidx.ci_idx)); ! 195: /* ! 196: * By writing the RFC packet like a data packet, it will be kept ! 197: * around for automatic retransmission until freed by the normal ! 198: * receipting mechanism; xmitdone() and chrcv() facilitate this. ! 199: * Since new_conn() clears the connection (including cn_tlast), ! 200: * the packet number of the RFC will be 1 (pkn = ++cn_tlast). ! 201: */ ! 202: chld_write(conn, pkt); ! 203: } ! 204: ! 205: ! 206: chld_listen(conn, rwsize, pkt) ! 207: register struct connection *conn; ! 208: register struct packet *pkt; ! 209: { ! 210: register struct packet *opkt, *pktl; ! 211: int ps; ! 212: ! 213: conn->cn_state = CSLISTEN; ! 214: conn->cn_flags |= CHSERVER; ! 215: conn->cn_rwsize = rwsize; ! 216: pkt->pk_op = LSNOP; ! 217: setconn(conn, pkt); ! 218: ! 219: if (flatten(pkt)) { ! 220: free_packet(pkt); ! 221: return; ! 222: } ! 223: ! 224: ps = spl6(); ! 225: opkt = NOPKT; ! 226: for (pktl = Chrfclist; pktl != NOPKT; pktl = (opkt = pktl)->next) ! 227: if (concmp(pktl, pkt->data->rptr, (int)pkt->pk_len)) { ! 228: if (opkt == NOPKT) ! 229: Chrfclist = pktl->next; ! 230: else ! 231: opkt->next = pktl->next; ! 232: if (pktl == Chrfctail) ! 233: Chrfctail = opkt; ! 234: free_packet(pkt); ! 235: lsnmatch(pktl, conn); ! 236: chd_newstate(conn); ! 237: splx(ps); ! 238: return; ! 239: } ! 240: ! 241: pkt->next = Chlsnlist; ! 242: Chlsnlist = pkt; ! 243: splx(ps); ! 244: ! 245: debug(DCONN,printf("Conn #%x: LISTEN state\n", conn->cn_lidx.ci_idx)); ! 246: } ! 247: ! 248: ! 249: chld_close(conn, pkt) ! 250: register struct connection *conn; ! 251: register struct packet *pkt; ! 252: { ! 253: int ps = spl6(); ! 254: ! 255: ch_busy++; ! 256: switch (conn->cn_state) { ! 257: case CSOPEN: ! 258: case CSRFCRCVD: ! 259: if (pkt != NOPKT) { ! 260: setconn(conn, pkt); ! 261: pkt->pk_ackn = pkt->pk_pkn = 0; ! 262: sendctl(pkt); ! 263: pkt = NOPKT; ! 264: } ! 265: /* Fall into ... */ ! 266: case CSRFCSENT: ! 267: close_conn(conn, CSCLOSED, NOPKT); ! 268: break; ! 269: case CSLISTEN: ! 270: rmlisten(conn); ! 271: break; ! 272: } ! 273: --ch_busy; ! 274: splx(ps); ! 275: ! 276: if (pkt != NOPKT) ! 277: free_packet(pkt); ! 278: } ! 279: ! 280: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.