|
|
1.1 ! root 1: #include "../chunix/chsys.h" ! 2: #include "../chunix/chconf.h" ! 3: #include "../chaos/chaos.h" ! 4: /* ! 5: * DR11-C Chaos driver. ! 6: * This driver does framing and a block check for each packet. ! 7: * The framing is similar to standard synchronous links, except that ! 8: * the "byte" is 16 bits. Basically a frame starts after 2 or more ! 9: * DRSYNC words, then the next word being a count and the next word being the ! 10: * complement of the count (both count and its complement must not be DRSYNC). ! 11: * Then the number of words specified by the count are the actual data, ! 12: * followed by an LRC-16. Data words equal to DRSYNC or DRESC are preceded by ! 13: * DRESC. The count does not include the inserted DRESC words, but the CRC ! 14: * word does. The LRC word does not include the initial DRSYNC's or the count. ! 15: * This framing scheme was thought up quickly and may well be overkill. ! 16: * The LRC is a simple XOR of all data words. ! 17: * Chaos N.C.P.'s that use this file must include <chaos/dr11c.h> in their ! 18: * chconf.h files. ! 19: * Keep in mind that the interrupt priority level of this driver maybe less ! 20: * than either the clock or the LOCK macro supplied by the user. ! 21: * Also remember that the block check is not to great. ! 22: */ ! 23: ! 24: #define xc_draddr xc_info.xc_dr11c.dr_addr ! 25: #define xc_drtptr xc_info.xc_dr11c.dr_tptr ! 26: #define xc_drrptr xc_info.xc_dr11c.dr_rptr ! 27: #define xc_drtcnt xc_info.xc_dr11c.dr_tcnt ! 28: #define xc_drrcnt xc_info.xc_dr11c.dr_rcnt ! 29: #define xc_drrstate xc_info.xc_dr11c.dr_rstate ! 30: #define xc_drtstate xc_info.xc_dr11c.dr_tstate ! 31: #define xc_drrcheck xc_info.xc_dr11c.dr_rcheck ! 32: #define xc_drtcheck xc_info.xc_dr11c.dr_tcheck ! 33: #define xc_drintrup xc_info.xc_dr11c.dr_intrup ! 34: ! 35: struct chxcvr dr11cxcvr[NCHDR]; ! 36: ! 37: ! 38: /* ! 39: * dr11-c initialization. Also does initialization to the static chxcvr ! 40: * structure since initialized unions don't work anyway. ! 41: */ ! 42: ! 43: int chdrstart(), chdrreset(); ! 44: /* ! 45: * Initialize all dr11c interfaces - called from low priority ! 46: */ ! 47: chdrinit() ! 48: { ! 49: register struct chxcvr *xp; ! 50: register short *hp; ! 51: #ifdef VMUNIX ! 52: register int i = 0; ! 53: #else ! 54: register char *dp = (char *)DR11CBASE;/* must be char * to use DR11CINC */ ! 55: #endif ! 56: ! 57: hp = &dr11chosts[0]; ! 58: for (xp = &dr11cxcvr[0]; xp < &dr11cxcvr[NDR11C]; xp++) { ! 59: xp->xc_draddr = ! 60: #ifdef VMUNIX ! 61: (struct dr11c *) chdrdinfo[i++]->ui_addr; ! 62: #else ! 63: (struct dr11c *) dp; ! 64: dp += DR11CINC; ! 65: #endif ! 66: /*DEBUG*/ if (xp->xc_draddr == 0) panic("draddr"); ! 67: xp->xc_start = chdrstart; ! 68: xp->xc_reset = chdrreset; ! 69: xp->xc_host = *hp++; ! 70: LOCK; ! 71: chdrreset(xp); ! 72: UNLOCK; ! 73: } ! 74: } ! 75: /* ! 76: * Check for hung interfaces - if so flush the packet. ! 77: * Assumed called at clock level. ! 78: */ ! 79: chdrxtime() ! 80: { ! 81: register struct chxcvr *xp; ! 82: ! 83: for (xp = &dr11cxcvr[0]; xp < &dr11cxcvr[NDR11C]; xp++) { ! 84: if (xp->xc_drintrup) ! 85: continue; ! 86: if (xp->xc_rpkt != NOPKT && ! 87: Chclock - xp->xc_rtime > DR11CHUNG) { ! 88: ch_free((char *)xp->xc_rpkt); ! 89: xp->xc_rpkt = NOPKT; ! 90: xp->xc_drrstate = DRIDLE; ! 91: debug(DABNOR, printf("Rec pkt timeout\n")); ! 92: } ! 93: if (xp->xc_tpkt != NOPKT && ! 94: Chclock - xp->xc_ttime > DR11CHUNG) { ! 95: debug(DABNOR, printf("Trans pkt timeout\n")); ! 96: xp->xc_drtstate = DRTDONE; ! 97: chdrxint(xp - dr11cxcvr); ! 98: } ! 99: } ! 100: } ! 101: ! 102: /* ! 103: * Reset things from an unknown state (high priority) ! 104: * Basically enable interrupts and tell him we're ready for input. ! 105: * If he already has a word, take it right away. ! 106: */ ! 107: chdrreset(xp) ! 108: register struct chxcvr *xp; ! 109: { ! 110: register struct dr11c *dp = xp->xc_draddr; ! 111: ! 112: xp->xc_drrstate = xp->xc_drtstate = DRIDLE; ! 113: dp->dr_csr = 0; ! 114: dp->dr_csr = DRIN|DROUT|DRIE|DROE; ! 115: } ! 116: /* ! 117: * Start output on an idle line - called when nothing happening ! 118: */ ! 119: chdrstart(xp) ! 120: register struct chxcvr *xp; ! 121: { ! 122: ! 123: if (xp->xc_tpkt != NOPKT) ! 124: panic("chdrstart: already busy"); ! 125: chdrxint(xp - dr11cxcvr); ! 126: } ! 127: /* ! 128: * Receiver interrupt ! 129: */ ! 130: chdrrint(dev) ! 131: { ! 132: register unsigned short data; /* register short is dubious - be careful! */ ! 133: register struct chxcvr *xp = &dr11cxcvr[dev]; ! 134: register struct dr11c *dp = xp->xc_draddr; ! 135: ! 136: if ((dp->dr_csr & DRIRDY) == 0) { ! 137: debug(DABNOR, printf("extra dr11c rint\n")); ! 138: return; ! 139: } ! 140: dp->dr_csr &= ~DRIN; ! 141: data = dp->dr_ibuf; ! 142: dp->dr_csr |= DRIN; /* set his DRORDY, and cause his chdrxint */ ! 143: ! 144: xp->xc_drintrup = 1; ! 145: switch(xp->xc_drrstate) { ! 146: case DRIDLE: ! 147: if (data == DRSYNC) ! 148: xp->xc_drrstate = DRSYN1; ! 149: break; ! 150: case DRSYN1: ! 151: xp->xc_drrstate = data == DRSYNC ? DRSYN2 : DRIDLE; ! 152: break; ! 153: case DRSYN2: ! 154: if (data != DRSYNC) { ! 155: xp->xc_drrcnt = data; ! 156: xp->xc_drrstate = DRCNT1; ! 157: } ! 158: break; ! 159: case DRCNT1: ! 160: xp->xc_drrstate = DRIDLE; ! 161: data = ~data; ! 162: debug(DTRANS,printf("Rec size=%d\n", data)); ! 163: if (data != xp->xc_drrcnt) ! 164: debug(DABNOR, printf("Rec bad count\n")); ! 165: else if ((data <<= 1) < sizeof(struct pkt_header) || ! 166: data > CHMAXDATA + sizeof(struct pkt_header)) ! 167: debug(DABNOR, printf("Rec bad size: %d", data)); ! 168: else { ! 169: LOCK; /* in case of clock interrupt */ ! 170: if ((xp->xc_rpkt = (struct packet *)ch_alloc( ! 171: (int)data + sizeof(struct ncp_header) , 1)) ! 172: != NOPKT) { ! 173: xp->xc_drrstate = DRDATA; ! 174: xp->xc_drrptr = (short *)&xp->xc_rpkt->pk_phead; ! 175: xp->xc_drrcheck = 0; ! 176: xp->xc_rtime = Chclock; ! 177: } else ! 178: debug(DABNOR, printf("Rec alloc fail: %d\n", data)); ! 179: } ! 180: break; ! 181: case DRDATA: ! 182: if (data == DRESC) { ! 183: xp->xc_drrstate = DRESC1; ! 184: xp->xc_drrcheck ^= data; ! 185: break; ! 186: } ! 187: /* Falls into... */ ! 188: case DRESC1: ! 189: xp->xc_drrcheck ^= data; ! 190: *xp->xc_drrptr++ = data; ! 191: if (--xp->xc_drrcnt == 0) ! 192: xp->xc_drrstate = DRCHECK; ! 193: else ! 194: xp->xc_drrstate = DRDATA; ! 195: break; ! 196: case DRCHECK: ! 197: xp->xc_drrstate = DRIDLE; ! 198: LOCK; /* raise to possibly higher priority */ ! 199: if (data == xp->xc_drrcheck) ! 200: rcvpkt(xp->xc_rpkt); ! 201: else ! 202: ch_free((char *)xp->xc_rpkt); ! 203: xp->xc_rpkt = NOPKT; ! 204: } ! 205: xp->xc_drintrup = 0; ! 206: } ! 207: /* ! 208: * Transmit interrupt ! 209: */ ! 210: chdrxint(dev) ! 211: { ! 212: register struct chxcvr *xp = &dr11cxcvr[dev]; ! 213: register struct dr11c *dp = xp->xc_draddr; ! 214: register struct packet *pkt; ! 215: unsigned short data; ! 216: ! 217: if (xp->xc_tpkt != NOPKT && (dp->dr_csr & DRORDY) == 0) { ! 218: debug(DABNOR, printf("Extra dr11c xint\n")); ! 219: /*return;*/ ! 220: } ! 221: dp->dr_csr &= ~DROUT; ! 222: xp->xc_drintrup = 1; ! 223: switch (xp->xc_drtstate) { ! 224: case DRIDLE: ! 225: xp->xc_tpkt = NOPKT; ! 226: case DRTDONE: ! 227: LOCK; ! 228: if ((pkt = xcvrdone(xp)) == NOPKT) ! 229: goto out; ! 230: xp->xc_ttime = Chclock; ! 231: data = sizeof(struct pkt_header) + pkt->pk_len; ! 232: data = (data + (sizeof(short) - 1)) >> 1; ! 233: xp->xc_drtcnt = data; ! 234: xp->xc_drtptr = (short *)&pkt->pk_phead; ! 235: debug(DTRANS,printf("Trans size=%d, %x\n",data, pkt)); ! 236: data = DRSYNC; ! 237: xp->xc_drtstate = DRSYN1; ! 238: break; ! 239: case DRSYN1: ! 240: data = DRSYNC; ! 241: xp->xc_drtstate = DRSYN2; ! 242: break; ! 243: case DRSYN2: ! 244: data = xp->xc_drtcnt; ! 245: xp->xc_drtstate = DRCNT1; ! 246: break; ! 247: case DRCNT1: ! 248: data = ~xp->xc_drtcnt; ! 249: xp->xc_drtstate = DRDATA; ! 250: xp->xc_drtcheck = 0; ! 251: break; ! 252: case DRDATA: ! 253: if ((data = *xp->xc_drtptr) == DRESC || data == DRSYNC) { ! 254: data = DRESC; ! 255: xp->xc_drtcheck ^= data; ! 256: xp->xc_drtstate = DRESC1; ! 257: break; ! 258: } ! 259: /* Falls into... */ ! 260: case DRESC1: ! 261: data = *xp->xc_drtptr++; ! 262: xp->xc_drtcheck ^= data; ! 263: if (--xp->xc_drtcnt == 0) ! 264: xp->xc_drtstate = DRCHECK; ! 265: else ! 266: xp->xc_drtstate = DRDATA; ! 267: break; ! 268: case DRCHECK: ! 269: data = xp->xc_drtcheck; ! 270: xp->xc_drtstate = DRTDONE; ! 271: } ! 272: dp->dr_obuf = data; ! 273: dp->dr_csr |= DROUT; /* set his DRIRDY, cause his chdrrint */ ! 274: out: ! 275: xp->xc_drintrup = 0; ! 276: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.