|
|
1.1 ! root 1: #include "../chunix/chsys.h" ! 2: #include "../chunix/chconf.h" ! 3: #include "../chaos/chaos.h" ! 4: #include "../chaos/address-res.h" ! 5: ! 6: #ifdef VMUNIX ! 7: #include "../h/buf.h" ! 8: #include "../h/ubavar.h" ! 9: #include "../h/pte.h" ! 10: #include "../h/ubareg.h" ! 11: #endif VMUNIX ! 12: ! 13: /* ! 14: * Chaos device driver for the interlan ethernet interface. ! 15: * ! 16: * This driver depends heavily on the fact that the device will ! 17: * interrupt exactly once per receive buffer and once per command ! 18: * regardless of how many times the CSR is read (and thus the ! 19: * DONE bits cleared). ! 20: * Until a lot of this chaos code is rewritten, it is too painful to DMA ! 21: * directly into a packet buffer since the buffers must be > 512 bytes, even ! 22: * for the smallest packet. Thus we just have fixed buffers, and copy the data out. ! 23: * For transmission, we do indeed DMA directly from packets. ! 24: * Note that for the VAX we permanently allocate a buffered data path for transmit, ! 25: * unless NOHOG is defined, in which case we allocate as needed. ! 26: * For receive, we use a direct data path and a permanently-mapped buffer. ! 27: * ! 28: * NOTE!!! The size of this structure must not be an even multiple of 8 !!! ! 29: * If it is then "buffer chaining" will occur! ! 30: */ ! 31: union chilpkt { ! 32: struct il_stat ilp_stat; ! 33: struct { ! 34: struct il_rheader ilp_Rhdr; ! 35: union { ! 36: struct ar_packet ilp_Arpkt; ! 37: struct { ! 38: struct pkt_header ilp_Chhead; ! 39: char ilp_Chdata[CHMAXDATA]; ! 40: } ilp_Chpkt; ! 41: } ilp_data; ! 42: char ilp_crc[4]; ! 43: } ilp_edata; ! 44: }; ! 45: #define ilp_arpkt ilp_edata.ilp_data.ilp_Arpkt ! 46: #define ilp_chhead ilp_edata.ilp_data.ilp_Chpkt.ilp_Chhead ! 47: #define ilp_chdata ilp_edata.ilp_data.ilp_Chpkt.ilp_Chdata ! 48: #define ilp_chpkt ilp_edata.ilp_data.ilp_Chpkt ! 49: #define ilp_rhdr ilp_edata.ilp_Rhdr ! 50: int chilstart(), chilreset(); ! 51: ! 52: /* ! 53: #define DEBUG ! 54: */ ! 55: ! 56: #ifdef DEBUG ! 57: #define IF_DEBUG(x) (x) ! 58: #else ! 59: #define IF_DEBUG(x) ! 60: #endif ! 61: ! 62: #define NOHOG /* Don't hog buffered data path (for xmit) */ ! 63: ! 64: #define splIL() spl5() ! 65: ! 66: /* ! 67: * Address resolution data: ! 68: * This should move to an "address resolution" file when more than one ! 69: * Ethernet device is supported. ! 70: */ ! 71: #define ETHER_BROADCAST {-1, -1, -1, -1, -1, -1} ! 72: u_char ether_broadcast[6] = ETHER_BROADCAST; ! 73: #define NPAIRS 20 /* how many addresses should we remember */ ! 74: struct ar_pair { ! 75: chaddr arp_chaos; ! 76: u_char arp_ether[6]; ! 77: long arp_time; ! 78: }; ! 79: long arptime; /* LRU clock for ar_pair slots */ ! 80: ! 81: /* ! 82: * Canned request packet we send out when we don't have the ethernet address ! 83: * of an outgoing packet. ! 84: */ ! 85: struct chilapkt { ! 86: struct il_xheader ar_xhdr; ! 87: struct ar_packet ar_pkt; ! 88: }; ! 89: /* ! 90: * Software state per interface. ! 91: */ ! 92: struct chilsoft { ! 93: char il_unit; ! 94: #ifdef VMUNIX ! 95: char il_ubanum; ! 96: char il_rbdp; ! 97: char il_xbdp; ! 98: int il_ruba; ! 99: int il_xuba; ! 100: #endif ! 101: short il_oactive; /* is output active? */ ! 102: short il_startrcv; /* hang receive next chance */ ! 103: short il_scsr; ! 104: u_char il_enaddr[6]; /* board's ethernet address */ ! 105: short il_doreply; /* Reply buffer full */ ! 106: short il_replying; /* Reply buffer being transmitted */ ! 107: struct ildevice *il_devaddr; ! 108: struct chxcvr il_xcvr; ! 109: struct ar_pair il_pairs[NPAIRS]; ! 110: struct ar_pair *il_epairs; ! 111: struct il_xheader il_savex; /* Yick. */ ! 112: union chilpkt il_rpkt; /* DMA input buffer */ ! 113: struct chilapkt il_arrequest; /* Address request buffer */ ! 114: struct chilapkt il_arreply; /* Address reply buffer */ ! 115: } chilsoft[NCHIL]; ! 116: ! 117: /* ! 118: * Error codes ! 119: */ ! 120: char *ilerrs[] = { ! 121: "success", /* 0 */ ! 122: "success with retries", /* 01 */ ! 123: "illegal command", /* 02 */ ! 124: "inappropriate command", /* 03 */ ! 125: "failure", /* 04 */ ! 126: "buffer size exceeded", /* 05 */ ! 127: "frame too small", /* 06 */ ! 128: 0, /* 07 */ ! 129: "excessive collisions", /* 010 */ ! 130: 0, /* 011 */ ! 131: "buffer alignment error", /* 012 */ ! 132: 0, /* 013 */ ! 133: 0, /* 014 */ ! 134: 0, /* 015 */ ! 135: 0, /* 016 */ ! 136: "non-existent memory" /* 017 */ ! 137: }; ! 138: ! 139: char *ildiag[] = { ! 140: "success", /* 0 */ ! 141: "checksum error", /* 1 */ ! 142: "NM10 dma error", /* 2 */ ! 143: "transmitter error", /* 3 */ ! 144: "receiver error", /* 4 */ ! 145: "loopback failure", /* 5 */ ! 146: }; ! 147: long chillost; ! 148: long chilarrp; ! 149: long chilarls; ! 150: long chilxstat; ! 151: long chilrst; ! 152: long chilrin; ! 153: long chilcin; ! 154: long chilar; ! 155: long chilxrq; ! 156: long chilxrp; ! 157: ! 158: #ifdef VMUNIX ! 159: ! 160: /* ! 161: * This stuff should be elsewhere, but isn't right now. ! 162: */ ! 163: ! 164: #ifdef VAX780 ! 165: #define UBAPURGEBITS UBADPR_BNE ! 166: #else ! 167: #define UBAPURGEBITS (UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE) ! 168: #endif VAX780 ! 169: ! 170: #define PURGEBDP(ubanum, bdpnum) \ ! 171: uba_hd[ubanum].uh_uba->uba_dpr[bdpnum] |= UBAPURGEBITS ! 172: ! 173: /* ! 174: * Autoconfiguration support for VMUNIX ! 175: */ ! 176: int chilprobe(), chilattach(), chilrint(), chilcint(); ! 177: struct uba_device *chilinfo[NCHIL]; ! 178: unsigned short chilstd[] = { 0 }; ! 179: struct uba_driver childriver = { chilprobe, 0, chilattach, 0, chilstd, "chil", chilinfo }; ! 180: ! 181: /* ! 182: * Do an OFFLINE command to cause an interrupt for the ! 183: * autoconfigure stuff. ! 184: */ ! 185: chilprobe(reg) ! 186: caddr_t reg; ! 187: { ! 188: register int br, cvec; /* r11, r10 */ ! 189: register struct ildevice *addr = (struct ildevice *)reg; ! 190: register int i; ! 191: ! 192: #ifdef lint ! 193: { ! 194: int j = 0; ! 195: ! 196: br = 0; cvec = br; br = cvec; ! 197: i = j; j = i; ! 198: chilrint(0); chilcint(0); ! 199: } ! 200: #endif ! 201: addr->il_csr = ILC_OFFLINE|IL_CIE; ! 202: DELAY(100000); ! 203: i = addr->il_csr; /* clear CDONE */ ! 204: if (cvec > 0 && cvec != 0x200) ! 205: cvec -= 4; ! 206: ! 207: return (1); ! 208: } ! 209: ! 210: /* ! 211: * Attach interface ! 212: */ ! 213: chilattach(ui) ! 214: register struct uba_device *ui; ! 215: { ! 216: chilsoft[ui->ui_unit].il_ubanum = ui->ui_ubanum; ! 217: chilsetup(ui->ui_unit, (struct ildevice *)ui->ui_addr); ! 218: } ! 219: #else VMUNIX ! 220: int chilndev = NCHIL; ! 221: int chiladdr[NCHIL] = { CHIL_ADDR }; ! 222: #endif VMUNIX ! 223: ! 224: /* ! 225: * Do the run-time initialization of the given transceiver. ! 226: * Reception is not enabled. ! 227: */ ! 228: chilsetup(unit, addr) ! 229: int unit; ! 230: register struct ildevice *addr; ! 231: { ! 232: register struct chilsoft *sp = &chilsoft[unit]; ! 233: int s; ! 234: ! 235: sp->il_xcvr.xc_devaddr = (unsigned *)addr; /* This indicates attachment! */ ! 236: sp->il_xcvr.xc_addr = 0; /* We don't know chaos addr yet */ ! 237: sp->il_xcvr.xc_start = chilstart; ! 238: sp->il_xcvr.xc_reset = chilreset; ! 239: sp->il_xcvr.xc_ilinfo.il_soft = sp; ! 240: sp->il_epairs = &sp->il_pairs[NPAIRS]; ! 241: sp->il_devaddr = addr; ! 242: sp->il_unit = unit; ! 243: ! 244: #ifdef VMUNIX ! 245: ! 246: #ifndef NOHOG ! 247: sp->il_xuba = uballoc(sp->il_ubanum, (caddr_t)&sp->il_rpkt, ! 248: sizeof(union chilpkt), UBA_CANTWAIT|UBA_NEEDBDP); ! 249: sp->il_xbdp = (sp->il_xuba >> 28) & 0x0f; ! 250: #endif not NOHOG ! 251: ! 252: sp->il_ruba = uballoc(sp->il_ubanum, (caddr_t)&sp->il_rpkt, ! 253: sizeof(union chilpkt), UBA_CANTWAIT); ! 254: sp->il_rbdp = (sp->il_ruba >> 28) & 0x0f; ! 255: #endif VMUNIX ! 256: ! 257: s = splIL(); ! 258: ilbusywait(sp, ILC_RESET, 0); /* Initialize interface */ ! 259: addr->il_bar = sp->il_ruba & 0xffff; ! 260: addr->il_bcr = sizeof(struct il_stat); ! 261: ilbusywait(sp, ILC_STAT, (sp->il_ruba >> 2) & IL_EUA); ! 262: if (sp->il_rbdp) ! 263: PURGEBDP(sp->il_ubanum, sp->il_rbdp); ! 264: splx(s); ! 265: bcopy(sp->il_rpkt.ilp_stat.ils_addr, sp->il_enaddr, 6); ! 266: bcopy(ether_broadcast, sp->il_arrequest.ar_xhdr.ilx_dhost, 6); ! 267: sp->il_arrequest.ar_xhdr.ilx_type = ILADDR_TYPE; ! 268: sp->il_arrequest.ar_pkt.ar_hardware = AR_ETHERNET; ! 269: sp->il_arrequest.ar_pkt.ar_protocol = ILCHAOS_TYPE; ! 270: sp->il_arrequest.ar_pkt.ar_hlength = 6; ! 271: sp->il_arrequest.ar_pkt.ar_plength = 2; ! 272: sp->il_arrequest.ar_pkt.ar_opcode = AR_REQUEST; ! 273: bcopy(sp->il_enaddr, sp->il_arrequest.ar_pkt.ar_esender, 6); ! 274: bcopy((u_char *)&sp->il_arrequest, (u_char *)&sp->il_arreply, ! 275: sizeof(struct chilapkt)); ! 276: sp->il_arreply.ar_pkt.ar_opcode = AR_REPLY; ! 277: ! 278: printf("chil%d: ether addr %x %x %x %x %x %x module %s firmware %s\n", ! 279: unit, ! 280: sp->il_enaddr[0]&0xff, sp->il_enaddr[1]&0xff, ! 281: sp->il_enaddr[2]&0xff, sp->il_enaddr[3]&0xff, ! 282: sp->il_enaddr[4]&0xff, sp->il_enaddr[5]&0xff, ! 283: sp->il_rpkt.ilp_stat.ils_module, ! 284: sp->il_rpkt.ilp_stat.ils_firmware); ! 285: } ! 286: ! 287: /* ! 288: * chaos interlan initialization. Also does initialization to the static xcvr ! 289: * structure since initialized unions don't work anyway. ! 290: */ ! 291: chilinit() ! 292: { ! 293: int unit; ! 294: ! 295: for (unit = 0; unit < NCHIL; unit++) { ! 296: ! 297: #ifndef VMUNIX ! 298: chilsetup(unit, (struct ildevice *)chiladdr[unit]); ! 299: #endif not VMUNIX ! 300: ! 301: chilreset(&chilsoft[unit].il_xcvr); ! 302: } ! 303: } ! 304: /* ! 305: * Receive our chaosnet address ! 306: */ ! 307: chilseta(dev, addr) ! 308: unsigned dev; ! 309: unsigned short addr; ! 310: { ! 311: register struct chilsoft *sp; ! 312: register struct chroute *r; ! 313: ! 314: if (dev >= NCHIL) ! 315: return 1; ! 316: else { ! 317: sp = &chilsoft[dev]; ! 318: if (sp->il_xcvr.xc_devaddr == 0) ! 319: return 1; ! 320: if (sp->il_xcvr.xc_addr != 0) { /* If we were already connected */ ! 321: r = &Chroutetab[sp->il_xcvr.xc_subnet]; ! 322: r->rt_type = 0; ! 323: r->rt_cost = CHHCOST; ! 324: } ! 325: sp->il_xcvr.xc_addr = addr; ! 326: if (sp->il_xcvr.xc_subnet >= CHNSUBNET) ! 327: return 1; ! 328: sp->il_arrequest.ar_pkt.ar_csender.ch_addr = addr; ! 329: sp->il_arreply.ar_pkt.ar_csender.ch_addr = addr; ! 330: r = &Chroutetab[sp->il_xcvr.xc_subnet]; ! 331: r->rt_type = CHDIRECT; ! 332: r->rt_cost = CHHCOST/2; ! 333: r->rt_xcvr = &sp->il_xcvr; ! 334: return 0; ! 335: } ! 336: } ! 337: /* ! 338: * Reset interface after UNIBUS reset. ! 339: */ ! 340: chilreset(xp) ! 341: struct chxcvr *xp; ! 342: { ! 343: register struct chilsoft *sp = xp->xc_ilinfo.il_soft; ! 344: register int s; ! 345: ! 346: if (sp == 0) ! 347: return; ! 348: s = splIL(); ! 349: ilbusywait(sp, ILC_RESET, 0); ! 350: ilbusywait(sp, ILC_CLPBAK, 0); ! 351: ilbusywait(sp, ILC_CLPRMSC, 0); ! 352: ilbusywait(sp, ILC_CRCVERR, 0); ! 353: ilbusywait(sp, ILC_FLUSH, 0); ! 354: ilbusywait(sp, ILC_ONLINE, 0); ! 355: chilrstart(sp); ! 356: splx(s); ! 357: } ! 358: ! 359: /* ! 360: * Start output on an idle line ! 361: */ ! 362: chilstart(xp) ! 363: struct chxcvr *xp; ! 364: { ! 365: register struct chilsoft *sp = xp->xc_ilinfo.il_soft; ! 366: ! 367: /* IF_DEBUG(printf("chilstart (unit %d)\n", sp->il_unit)); */ ! 368: if (sp->il_xcvr.xc_tpkt != NOPKT) ! 369: panic("chilstart: already busy"); ! 370: if (sp->il_oactive == 0) ! 371: chilcint(sp->il_unit); ! 372: } ! 373: /* ! 374: * Command (usually transmit) done interrupt. ! 375: */ ! 376: chilcint(dev) ! 377: { ! 378: register struct ildevice *addr; ! 379: register struct il_xheader *epkt; ! 380: register struct chilsoft *sp = &chilsoft[dev]; ! 381: register struct packet *pkt; ! 382: int elength; ! 383: ! 384: chilcin++; ! 385: LOCK; ! 386: addr = (struct ildevice *)sp->il_xcvr.xc_devaddr; ! 387: IF_DEBUG(printf("chilcint: unit %d oactive %d xbdp %d\n", ! 388: minor(dev), sp->il_oactive, (sp->il_xuba >> 28) & 0x0f)); ! 389: ! 390: #ifdef VMUNIX ! 391: #ifdef NOHOG ! 392: if (sp->il_oactive) ! 393: ubarelse(sp->il_ubanum, &sp->il_xuba); ! 394: #else ! 395: if (sp->il_xbdp) ! 396: PURGEBDP(sp->il_ubanum, sp->il_xbdp); ! 397: #endif NOHOG ! 398: #endif VMUNIX ! 399: ! 400: sp->il_oactive = 0; ! 401: sp->il_scsr = addr->il_csr; ! 402: if (sp->il_replying) { ! 403: sp->il_replying = 0; ! 404: sp->il_doreply = 0; ! 405: } else if ((pkt = sp->il_xcvr.xc_tpkt) != NOPKT) { ! 406: if ((sp->il_scsr & IL_STATUS) > 1) { ! 407: chilxstat = sp->il_scsr; ! 408: sp->il_xcvr.xc_abrt++; ! 409: } else { ! 410: if (sp->il_scsr & IL_STATUS) ! 411: sp->il_xcvr.xc_abrt++; ! 412: sp->il_xcvr.xc_xmtd++; ! 413: } ! 414: bcopy(&sp->il_savex, ! 415: (char *)&pkt->pk_phead - sizeof(struct il_xheader), ! 416: sizeof(struct il_xheader)); ! 417: IF_DEBUG(printf("chil: pkt %d (op %o didx %x) done\n", ! 418: pkt->pk_pkn, pkt->pk_op, pkt->pk_didx & 0xffff)); ! 419: xmitdone(pkt); ! 420: } ! 421: /* ! 422: * If the last receive interrupt happened while a command was ! 423: * in progress, it couldn't prime the receive buffer then, so it ! 424: * set the flag telling us to do it here. ! 425: */ ! 426: if (sp->il_startrcv) ! 427: chilrstart(sp); ! 428: /* ! 429: * If last receive interrupt created an address resolution reply ! 430: * to send, send it rather than another data packet. ! 431: */ ! 432: if (sp->il_doreply) { ! 433: sp->il_replying = 1; ! 434: epkt = (struct il_xheader *)&sp->il_arreply; ! 435: elength = sizeof(struct chilapkt); ! 436: chilxrp++; ! 437: } else if ((pkt = xmitnext(&sp->il_xcvr)) == NOPKT) ! 438: return; ! 439: else { ! 440: IF_DEBUG(printf("chil: pkt %d (op %o didx %x) started\n", ! 441: pkt->pk_pkn, pkt->pk_op, pkt->pk_didx & 0xffff)); ! 442: epkt = (struct il_xheader *) ! 443: ((char *)&pkt->pk_phead - sizeof(struct il_xheader)); ! 444: elength = sizeof(struct il_xheader) + ! 445: sizeof(struct pkt_header) + ! 446: pkt->pk_len; ! 447: bcopy((char *)epkt, (char *)&sp->il_savex, ! 448: sizeof(struct il_xheader)); ! 449: if (pkt->pk_xdest == 0) { ! 450: epkt->ilx_type = ILCHAOS_TYPE; ! 451: bcopy(ether_broadcast, epkt->ilx_dhost, 6); ! 452: } else { ! 453: register struct ar_pair *app; ! 454: ! 455: for (app = sp->il_pairs; ! 456: app < sp->il_epairs && app->arp_chaos.ch_addr; ! 457: app++) ! 458: if (pkt->pk_xdest == app->arp_chaos.ch_addr) { ! 459: app->arp_time = ++arptime; ! 460: epkt->ilx_type = ILCHAOS_TYPE; ! 461: bcopy(app->arp_ether, epkt->ilx_dhost, ! 462: 6); ! 463: app = 0; ! 464: break; ! 465: } ! 466: if (app) { ! 467: chilxrq++; ! 468: /* ! 469: * We have no cached address translation - ! 470: * we must ask for one. ! 471: */ ! 472: epkt = (struct il_xheader *)&sp->il_arrequest; ! 473: sp->il_arrequest.ar_pkt.ar_ctarget.ch_addr = ! 474: pkt->pk_xdest; ! 475: elength = sizeof(struct chilapkt); ! 476: } ! 477: } ! 478: } ! 479: ! 480: #ifdef NOHOG ! 481: sp->il_xuba = uballoc(sp->il_ubanum, (caddr_t)epkt, elength, UBA_WANTBDP); ! 482: #else ! 483: sp->il_xuba = ubaremap(sp->il_ubanum, sp->il_xuba, (caddr_t)epkt); ! 484: #endif NOHOG ! 485: ! 486: IF_DEBUG(printf(" new uba map: xbdp %d addr %x\n", ! 487: (sp->il_xuba >> 28) & 0x0f, sp->il_xuba & 0xfff)); ! 488: ! 489: addr->il_bar = sp->il_xuba & 0xffff; ! 490: addr->il_bcr = (elength + 1) & ~1; ! 491: addr->il_csr = ((sp->il_xuba >> 2) & IL_EUA) | ! 492: ILC_XMIT|IL_CIE|IL_RIE; ! 493: sp->il_oactive++; ! 494: } ! 495: /* ! 496: * Receiver interrupt ! 497: */ ! 498: chilrint(dev) ! 499: { ! 500: register struct chilsoft *sp = &chilsoft[dev]; ! 501: register struct packet *pkt; /* shouldn't be reg on pdp11 */ ! 502: int elength; ! 503: ! 504: chilrin++; ! 505: if (sp->il_rbdp) ! 506: PURGEBDP(sp->il_ubanum, sp->il_rbdp); ! 507: if (sp->il_rpkt.ilp_rhdr.ilr_status == 0377) { ! 508: printf("chil%d: Receive interrupt with no packet!\n"); ! 509: return; ! 510: } ! 511: if (sp->il_rpkt.ilp_rhdr.ilr_status & 4) { ! 512: sp->il_xcvr.xc_rej++; ! 513: chillost++; ! 514: } ! 515: /* ! 516: * Data length is chaos packet size plus header (minus ! 517: * frame status and length == 4 plus 4 for the crc == 0!) ! 518: */ ! 519: elength = sp->il_rpkt.ilp_rhdr.ilr_length - sizeof(struct il_rheader); ! 520: if (sp->il_rpkt.ilp_rhdr.ilr_status & 3) ! 521: printf("chil%d: Received erroneous frame. Status: %d\n", ! 522: dev, sp->il_rpkt.ilp_rhdr.ilr_status); ! 523: else if (sp->il_rpkt.ilp_rhdr.ilr_type == ILADDR_TYPE) ! 524: chilrar(sp, &sp->il_rpkt.ilp_arpkt, elength); ! 525: else if (sp->il_rpkt.ilp_rhdr.ilr_type == ILCHAOS_TYPE) ! 526: if (elength < sizeof(struct pkt_header) || ! 527: elength < sizeof(struct pkt_header) + sp->il_rpkt.ilp_chhead.ph_len) ! 528: sp->il_xcvr.xc_leng++; ! 529: else { ! 530: register struct chroute *r; ! 531: ! 532: r = &Chroutetab[sp->il_xcvr.xc_subnet]; ! 533: r->rt_type = CHDIRECT; ! 534: r->rt_cost = CHCCOST; ! 535: r->rt_xcvr = &sp->il_xcvr; ! 536: if ((pkt = pkalloc((int)sp->il_rpkt.ilp_chhead.ph_len, ! 537: 1)) == NOPKT) ! 538: sp->il_xcvr.xc_rej++; ! 539: else { ! 540: bcopy((u_char *)&sp->il_rpkt.ilp_chpkt, ! 541: (u_char *)&pkt->pk_phead, ! 542: sizeof(struct pkt_header) + ! 543: sp->il_rpkt.ilp_chhead.ph_len); ! 544: sp->il_xcvr.xc_rcvd++; ! 545: LOCK; ! 546: if (pkt->pk_daddr == sp->il_xcvr.xc_addr && ! 547: Chmyaddr != -1) ! 548: pkt->pk_daddr = Chmyaddr; ! 549: rcvpkt(pkt); ! 550: } ! 551: } ! 552: if (sp->il_oactive) ! 553: sp->il_startrcv = 1; ! 554: else ! 555: chilrstart(sp); ! 556: } ! 557: chilrstart(sp) ! 558: register struct chilsoft *sp; ! 559: { ! 560: register struct ildevice *addr = sp->il_devaddr; ! 561: ! 562: chilrst++; ! 563: sp->il_rpkt.ilp_rhdr.ilr_status = 0177777; ! 564: addr->il_bar = sp->il_ruba & 0xffff; ! 565: addr->il_bcr = sizeof(union chilpkt); ! 566: addr->il_csr = (sp->il_ruba >> 2) & IL_EUA | ! 567: ILC_RCV|IL_RIE; ! 568: while (!((sp->il_scsr = addr->il_csr) & IL_CDONE)) ! 569: /* Busy wait */; ! 570: if (sp->il_scsr & IL_STATUS) ! 571: printf("il%d: receive buffer error: %d\n", ! 572: sp->il_unit, sp->il_scsr & IL_STATUS); ! 573: sp->il_startrcv = 0; ! 574: } ! 575: /* ! 576: * Receive an address resolution packet. ! 577: */ ! 578: chilrar(sp, arp, length) ! 579: register struct chilsoft *sp; ! 580: register struct ar_packet *arp; ! 581: { ! 582: register struct ar_pair *app; ! 583: register struct ar_pair *nap; ! 584: ! 585: u_char *eaddr; ! 586: ! 587: chilar++; ! 588: if (length < sizeof(struct ar_packet) || ! 589: arp->ar_hardware != AR_ETHERNET || ! 590: arp->ar_protocol != ILCHAOS_TYPE || ! 591: arp->ar_plength != sizeof(chaddr) || ! 592: arp->ar_csender.ch_addr == 0) ! 593: return; ! 594: eaddr = 0; ! 595: nap = sp->il_pairs; ! 596: for (app = nap; app < sp->il_epairs && app->arp_chaos.ch_addr; app++) ! 597: if (arp->ar_csender.ch_addr == app->arp_chaos.ch_addr) { ! 598: eaddr = app->arp_ether; ! 599: break; ! 600: } else if (app->arp_time < nap->arp_time) ! 601: nap = app; ! 602: /* ! 603: * If we are already cacheing the senders addresses, ! 604: * update our cache with possibly new information. ! 605: */ ! 606: if (eaddr) ! 607: bcopy(arp->ar_esender, app->arp_ether, 6); ! 608: if (arp->ar_ctarget.ch_addr != sp->il_xcvr.xc_addr) ! 609: return; ! 610: /* ! 611: * If we have never heard of this host before, find ! 612: * a slot and remember him. ! 613: * Note that we leave the time alone since we haven't used the entry. ! 614: * This is to prevent other hosts from flushing our cache ! 615: */ ! 616: if (eaddr == 0) { ! 617: bcopy(arp->ar_esender, nap->arp_ether, 6); ! 618: nap->arp_chaos.ch_addr = arp->ar_csender.ch_addr; ! 619: } ! 620: if (arp->ar_opcode == AR_REQUEST) ! 621: if (sp->il_doreply) ! 622: chilarls++; ! 623: else { ! 624: chilarrp++; ! 625: IF_DEBUG(printf("chilrar: sending arp (unit %d)\n", ! 626: sp->il_unit)); ! 627: sp->il_arreply.ar_pkt.ar_ctarget.ch_addr = arp->ar_csender.ch_addr; ! 628: bcopy(arp->ar_esender, sp->il_arreply.ar_pkt.ar_etarget, 6); ! 629: bcopy(arp->ar_esender, sp->il_arreply.ar_xhdr.ilx_dhost, 6); ! 630: sp->il_doreply = 1; ! 631: if (sp->il_oactive == 0) ! 632: chilcint(sp->il_unit); ! 633: } ! 634: } ! 635: #define MAXWAIT 1000000 /* on the order of 10 seconds */ ! 636: /* ! 637: * Perform a command and busy-wait for the interrupt. ! 638: * Used when it's not safe to sleep. ! 639: * This should never be called to receive a packet. ! 640: */ ! 641: ilbusywait(sp, command, bits) ! 642: register struct chilsoft *sp; ! 643: int command, bits; ! 644: { ! 645: register struct ildevice *addr = sp->il_devaddr; ! 646: register int csr, i; ! 647: ! 648: csr = addr->il_csr; ! 649: IF_DEBUG(printf("il%d: busy wait %x csr %x bcr %x bar %x bits %x", ! 650: sp->il_unit, command, csr&0xffff, addr->il_bcr&0xffff, addr->il_bar&0xffff, bits)); ! 651: addr->il_csr = bits|command; ! 652: for (i = 0; !((csr = addr->il_csr) & IL_CDONE); i++) ! 653: if (i >= MAXWAIT) { ! 654: printf("il%d: lost CDONE\n", sp->il_unit); ! 655: return; ! 656: } ! 657: IF_DEBUG((csr & IL_STATUS) ? printf("%s\n", ! 658: (command == ILC_DIAG || command == ILC_RESET ? ! 659: ildiag : ilerrs)[csr & IL_STATUS]) ! 660: : printf("done\n")); ! 661: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.