|
|
1.1 ! root 1: #include "il.h" ! 2: ! 3: #if NIL > 0 ! 4: ! 5: #include "../h/param.h" ! 6: #include "../h/systm.h" ! 7: #include "../h/dir.h" ! 8: #include "../h/user.h" ! 9: #include "../h/map.h" ! 10: #include "../h/pte.h" ! 11: #include "../h/buf.h" ! 12: #include "../h/ubareg.h" ! 13: #include "../h/ubavar.h" ! 14: #include "../h/proc.h" ! 15: #include "../h/tty.h" ! 16: /*#include "../h/queue.h"*/ ! 17: #include "../h/ilreg.h" ! 18: #include "../h/conf.h" ! 19: ! 20: #define PRINET 26 /* sleep priority: interruptible */ ! 21: ! 22: struct ilcb ilcb[NIL]; ! 23: extern int ilprobe(), ilattach(), ilrint(), ilcint(); ! 24: struct uba_device *ildinfo[NIL]; ! 25: u_short ilstd[] = {0164040}; ! 26: struct uba_driver ildriver = ! 27: { ilprobe, 0, ilattach, 0, ilstd, "il", ildinfo }; ! 28: ! 29: ! 30: /*++* ! 31: * Macro: NM10command ! 32: * Abstract: pass the NM10 board an inline command ! 33: * Parameters: ! 34: * command: command to process ! 35: * size: size of data buffer ! 36: * buf: data buffer ! 37: * addr: NM10 device addr ! 38: * Returns: nothing ! 39: * Affects: nothing ! 40: * Errors: none ! 41: * Design: trivial ! 42: * ! 43: *--*/ ! 44: #define NM10command(command, size, buf) \ ! 45: { \ ! 46: register unsigned int map = ((unsigned int) buf); \ ! 47: reg->bcr = size; \ ! 48: reg->bar = map & 0xffff; \ ! 49: reg->csr = ((map & 0x30000) >> 2) | command; \ ! 50: while ((reg->csr & IL_CMD_DONE) == 0); \ ! 51: } ! 52: ! 53: ! 54: /*++* ! 55: * Routine: ilinit ! 56: * Abstract: Initialize the Interlan ethernet driver. ! 57: * Parameters: ! 58: * dev: number device to initialize; ! 59: * Returns: nothing ! 60: * Affects: nothing ! 61: * Errors: ! 62: * Design: trivial ! 63: * ! 64: *--*/ ! 65: ilinit (dev) ! 66: { ! 67: register struct ilcb *ib = &ilcb[dev]; ! 68: register struct uba_device *ui = ildinfo[dev]; ! 69: register struct ilreg *reg = (struct ilreg *)ui->ui_addr; ! 70: ! 71: if (ib->avail) ! 72: { ! 73: u.u_error = EBUSY; ! 74: return; ! 75: } ! 76: ! 77: ib->in_map = uballoc(ui->ui_ubanum, (caddr_t) 0x80000000, ! 78: ILUBASIZE, UBA_NEEDBDP|UBA_CANTWAIT); ! 79: ib->cmd_map = uballoc(ui->ui_ubanum, (caddr_t) 0x80000000, ! 80: ILUBASIZE, UBA_NEEDBDP|UBA_CANTWAIT); ! 81: ! 82: if ((ib->in_map == 0) || (ib->cmd_map == 0)) ! 83: { ! 84: if (ib->in_map) ! 85: ubarelse (ui->ui_ubanum, &ib->in_map); ! 86: if (ib->cmd_map) ! 87: ubarelse (ui->ui_ubanum, &ib->cmd_map); ! 88: u.u_error = ENOMEM; ! 89: return; ! 90: } ! 91: ! 92: /*++* ! 93: * initialize cummulative statistics ! 94: * ! 95: *--*/ ! 96: { ! 97: struct ilstats stats; ! 98: register unsigned short *st = (unsigned short *) &stats.rframes; ! 99: register unsigned int *in = (unsigned int *) &ib->info.rframes; ! 100: ! 101: NM10command (IL_RPT_STATS, 66, ! 102: ubaremap(ui->ui_ubanum, ib->in_map, stats)); ! 103: ! 104: /* we do this remap to cause a ubapurge */ ! 105: ubaremap(ui->ui_ubanum, ib->in_map, stats); ! 106: ! 107: while (st > (unsigned short *) &stats.modid) ! 108: *in++ = *st++; ! 109: ! 110: ib->info.iladdr = stats.iladdr; ! 111: ib->info.modid = stats.modid; ! 112: ib->info.firmid = stats.firmid; ! 113: } ! 114: ! 115: ib->in_ptr = 0; ! 116: ib->in_packet = NULL; ! 117: ib->cmd_packet = NULL; ! 118: ib->in_next = NULL; ! 119: ! 120: initqueue((struct Queue *)&ib->cmd_q); ! 121: ! 122: ilrstart (ui); ! 123: NM10command (IL_ON_LINE, 0, 0); ! 124: } ! 125: ! 126: ilopen (dev, flag) ! 127: { ! 128: register struct ilcb *ib = &ilcb[dev]; ! 129: ! 130: if (ib > &ilcb[NIL] || !ib->attached) ! 131: { ! 132: u.u_error = ENXIO; ! 133: return; ! 134: } ! 135: ! 136: } ! 137: ! 138: ilclose (dev) ! 139: { ! 140: return; ! 141: } ! 142: ! 143: ! 144: /*++* ! 145: * Procedure: ilcommand ! 146: * Abstract: ! 147: * send command to net. ! 148: * Parameters: ! 149: * dev = device number ! 150: * p = pointer to packet that is to be given to Interland device. ! 151: * Design: ! 152: * ! 153: *--*/ ! 154: ilcommand(dev, p) ! 155: register struct ilpacket *p; ! 156: { ! 157: register struct uba_device *ui = ildinfo [dev]; ! 158: register struct ilcb *ib = &ilcb [dev]; ! 159: int ipl; ! 160: extern ilcmdstart(); ! 161: ! 162: ipl = spl6(); ! 163: ! 164: if (ib->cmd_packet == NULL) ! 165: { ! 166: ib->cmd_packet = p; ! 167: ilcmdstart (ui); ! 168: } ! 169: else enqueue (&ib->cmd_q, p); ! 170: ! 171: splx(ipl); ! 172: } ! 173: ! 174: ! 175: ! 176: ilioctl (dev, cmd, arg) int *arg; ! 177: { ! 178: switch (cmd) ! 179: { ! 180: case IL_INIT: ! 181: { ! 182: if (suser()) ! 183: ilinit (dev); ! 184: else ! 185: { ! 186: u.u_error = EPERM; ! 187: return; ! 188: } ! 189: } ! 190: break; ! 191: ! 192: case IL_DISABLE: ! 193: { ! 194: /* ildisable (dev); */ ! 195: } ! 196: break; ! 197: ! 198: case IL_STATS: ! 199: { ! 200: register struct ilcb *ib = &ilcb[dev]; ! 201: unsigned short buf[ILPHEAD + 66]; ! 202: register struct ilpacket *p = (struct ilpacket *)buf; ! 203: extern ilstats (); ! 204: ! 205: p->command = IL_RPT_STATS; ! 206: p->function = ilstats; ! 207: p->count = 66; ! 208: ilcommand (dev, p); ! 209: ! 210: while (p->command == IL_RPT_STATS) ! 211: sleep((caddr_t) p, PRINET); ! 212: copyout(&ib->info, arg, sizeof ib->info); ! 213: } ! 214: break; ! 215: ! 216: default: ! 217: { ! 218: u.u_error = EINVAL; ! 219: } ! 220: break; ! 221: } ! 222: } ! 223: ! 224: ! 225: /*++* ! 226: * Routine: ilfind ! 227: * Abstract: find a type filter that matched a specified type. ! 228: * Parameters: ! 229: * ib = pointer to the ethernet device ilcb. ! 230: * type = type that filter will match. ! 231: * Returns: ! 232: * SUCCESS: a descriptor with the matched type. ! 233: * FAILURE: NULL ! 234: * Affects: nothing ! 235: * Errors: none ! 236: * Design: trivial ! 237: * ! 238: *--*/ ! 239: struct iltype *ilfind(ib, type) register unsigned short type; ! 240: register struct ilcb *ib; ! 241: { ! 242: register struct iltype *d; ! 243: for ( d = (struct iltype *)ib->type_q.F; ! 244: d != (struct iltype *)&ib->type_q; ! 245: d = (struct iltype *) d->head.F ) ! 246: if (d->type == type) ! 247: return (d); ! 248: return (NULL); ! 249: } ! 250: ! 251: ! 252: /*++* ! 253: * Routine: ilconnect ! 254: * Abstract: create and ethernet type filter entry ! 255: * Parameters: ! 256: * unit = ethernet device unit number. ! 257: * type = ethernet type ! 258: * funct = function to call if we find a match ! 259: * Returns: ! 260: * SUCCESS: 1 ! 261: * FAILURE: 0 ! 262: * Affects: ! 263: * ilcb[unit].type_q: entry placed in queue ! 264: * ilcb[unit].free_q: entry removed from queue ! 265: * Errors: none ! 266: * Design: ... ! 267: * ! 268: *--*/ ! 269: ilconnect (unit, type, function) register funct *function; ! 270: { ! 271: register struct iltype *d; ! 272: register struct ilcb *ib = &ilcb[unit]; ! 273: register int ipl; ! 274: ! 275: ipl = spl6(); ! 276: if (ilfind (ib, type) == NULL) ! 277: if (d = (struct iltype *) dequeue (&ib->free_q)) ! 278: { ! 279: ib->num_free--; ! 280: d->type = type; ! 281: d->funct = function; ! 282: enqueue (&ib->type_q, d); ! 283: ib->num_types++; ! 284: splx (ipl); ! 285: return (1); ! 286: } ! 287: splx (ipl); ! 288: return (0); ! 289: } ! 290: ! 291: ! 292: ! 293: /*++* ! 294: * Routine: ildisconnect ! 295: * Abstract: remove an ethernet type filter match entry ! 296: * Parameters: ! 297: * unit = ethernet device unit number ! 298: * type = ethernet type ! 299: * Returns: ! 300: * SUCCESS: 1 ! 301: * FAILURE: 0 ! 302: * Affects: ! 303: * ilcb[unit].type_q: entry removed ! 304: * ilcb[unit].free_q: entry entered ! 305: * Errors: none ! 306: * Design: ... ! 307: * ! 308: *--*/ ! 309: ildisconnect (unit, type) register int type; ! 310: { ! 311: struct iltype *d; ! 312: register struct ilcb *ib = &ilcb[unit]; ! 313: register int ipl; ! 314: ! 315: if (d = ilfind (ib, type)) ! 316: { ! 317: ipl = spl6 (); ! 318: enqueue (&ib->free_q, dequeue (&d)); ! 319: ib->num_types--; ! 320: ib->num_free++; ! 321: splx(ipl); ! 322: } ! 323: } ! 324: ! 325: ! 326: ! 327: /*++* ! 328: * Routine: iladdress ! 329: * Abstract: return (by reference) the device net address ! 330: * Parameters: ! 331: * addr = the network address. ! 332: * Returns: nothing ! 333: * Affects: nothing ! 334: * Errors: none ! 335: * Design: trivial ! 336: * ! 337: *--*/ ! 338: iladdress (dev, addr) register struct iladdr *addr; ! 339: { ! 340: register struct ilcb *ib = &ilcb[dev]; ! 341: *addr = ib->info.iladdr; ! 342: } ! 343: ! 344: ! 345: /*++* ! 346: * Procedure: ilrstart ! 347: * Abstract: Start read operation on net. ! 348: * Parameters: ! 349: * 'ui' type "uba_device *": pointer to ethernet device to be started. ! 350: * ! 351: *--*/ ! 352: ! 353: ilrstart(ui) ! 354: register struct uba_device *ui; ! 355: { ! 356: register struct ilreg *reg = (struct ilreg *)ui->ui_addr; ! 357: register struct ilcb *ib = &ilcb[ui->ui_unit]; ! 358: register struct ilpacket *p; ! 359: int ipl; ! 360: ! 361: if (ib->in_packet == NULL) ! 362: { ! 363: ipl = spl6(); ! 364: ib->in_packet = &ib->in_pool[ib->in_ptr]; ! 365: ib->in_ptr ^= 1; ! 366: ib->in_next = ubaremap (ui->ui_ubanum, ib->in_map, ! 367: ib->in_packet->data); ! 368: if (ib->cmd_packet == NULL) ! 369: { ! 370: NM10command (IL_RCVR_BUFFER | IL_RCV_INTR, ! 371: ILPACKETSIZE, ! 372: ib->in_next); ! 373: ib->in_next = NULL; ! 374: } ! 375: splx (ipl); ! 376: } ! 377: } ! 378: ! 379: ! 380: ! 381: /*++* ! 382: * Procedure: ilcmdstart ! 383: * Abstract: Start packet transmission on net. ! 384: * Parameters: ! 385: * ui pointer to ethernet device structure. ! 386: * Design: ! 387: * We give the Interland device the correct command ! 388: * ! 389: * The UNIBUS address is derived by calculating the offset of the ! 390: * packet from the packet pool buffer base address and adding it to the ! 391: * allocated unibus buffer base address. ! 392: * ! 393: * We must do a purge to make sure the uba device has no data words ! 394: * lying around that might get sent on the next DMA. ! 395: * ! 396: *--*/ ! 397: ilcmdstart(ui) ! 398: register struct uba_device *ui; ! 399: { ! 400: ! 401: register struct ilcb *ib = &ilcb[ui->ui_unit]; ! 402: register struct ilreg *ilreg = (struct ilreg *)ui->ui_addr; ! 403: register struct ilpacket *p; ! 404: register unsigned int buffer; ! 405: ! 406: if (ib->cmd_packet == NULL) ! 407: if ((ib->cmd_packet = (struct ilpacket *)dequeue(&ib->cmd_q)) == NULL) ! 408: return; ! 409: ! 410: /* we dont use NM10command here since we are not interested ! 411: in waiting for the command to complete synchronously */ ! 412: ! 413: p = ib->cmd_packet; ! 414: buffer = (unsigned int) ubaremap (ui->ui_ubanum, ib->cmd_map, ! 415: p->data); ! 416: ilreg->bcr = p->count; ! 417: ilreg->bar = buffer & 0xffff; ! 418: ilreg->csr = ((buffer & 0x30000) >> 2) ! 419: | p->command | IL_CMD_INTR | IL_RCV_INTR; ! 420: ! 421: } ! 422: ! 423: ! 424: /*++* ! 425: * Procedure: ilrint ! 426: * Abstract: Net read interrupt handler. ! 427: * Parameters: ! 428: * dev = number of ethernet device. ! 429: * ! 430: *--*/ ! 431: ilrint(dev) ! 432: { ! 433: ! 434: register struct ilcb *ib = &ilcb[dev]; ! 435: register struct uba_device *ui = ildinfo[dev]; ! 436: register struct il_rheader *l; ! 437: register struct iltype *d; ! 438: ! 439: l = (struct il_rheader *)ib->in_packet; ! 440: ilrstart(ui); ! 441: if (l->status & IL_RCV_STATUS) ! 442: printf ("il%d: received bad packet; status %x\n", dev, l); ! 443: else if (d = ilfind(ib, l->type)) ! 444: (*d->funct)(dev, l); ! 445: } ! 446: ! 447: ! 448: /*++* ! 449: * Procedure: ilcint ! 450: * Abstract: Net transmit interrupt handler. ! 451: * Parameters: ! 452: * 'en' number of device we interrupted on. ! 453: * ! 454: *--*/ ! 455: ! 456: ilcint(dev) ! 457: { ! 458: register struct ilcb *ib = &ilcb[dev]; ! 459: register struct uba_device *ui = ildinfo[dev]; ! 460: register unsigned short status; ! 461: register struct ilpacket *p = ib->cmd_packet; ! 462: register struct ilreg *reg = (struct ilreg *) ui->ui_addr; ! 463: ! 464: if (p == NULL) ! 465: { ! 466: printf ("il%d: spurious transmit interrupt\n", dev); ! 467: return; ! 468: } ! 469: ! 470: status = reg->csr & IL_CMD_STATUS; ! 471: if (p->command == IL_XMIT_SEND) ! 472: { ! 473: if ((status) > 1) ! 474: printf ("il%d: dropped xmit packet\n", dev); ! 475: } ! 476: else if (status) ! 477: printf ("il%d: command %x bad status packet: %x\n", ! 478: dev, p->command, p); ! 479: ! 480: if (p->function != NULL) ! 481: (*(p->function)) (p, dev); ! 482: ! 483: if (ib->in_next) ! 484: { ! 485: NM10command (IL_RCVR_BUFFER | IL_RCV_INTR, ! 486: ILPACKETSIZE, ! 487: ib->in_next); ! 488: } ! 489: ! 490: ib->in_next = NULL; ! 491: ib->cmd_packet = NULL; ! 492: ilcmdstart (ui); ! 493: } ! 494: ! 495: ! 496: /*++* ! 497: * Procedure: ilstats ! 498: * Abstract: ! 499: * Merge currently collected data into the device statistics ! 500: * table. This routine assumes HIGH PRIORITY. ! 501: * ! 502: *--*/ ! 503: ilstats (p, dev) struct ilpacket *p; ! 504: { ! 505: register struct ilcb *ib = &ilcb[dev]; ! 506: register struct ilstats *stats = (struct ilstats *)p->data; ! 507: register unsigned int *in = (unsigned int *) &ib->info.rframes; ! 508: register unsigned short *st = (unsigned short *) &stats->rframes; ! 509: ! 510: while (st < (unsigned short *) stats) ! 511: *in++ += *st++; ! 512: ib->info.rfifo = stats->rfifo; ! 513: p->command = IL_NULL_CMD; ! 514: wakeup((caddr_t) p); ! 515: } ! 516: ! 517: ! 518: ! 519: /*++* ! 520: * Procedure: ilattach ! 521: * Abstract: ! 522: * This routine is called at system startup and initializes ! 523: * the device information structures. ! 524: * Parameters: ! 525: * 'ui' type "uba_device *": pointer to the device information ! 526: * structure. ! 527: *--*/ ! 528: ilattach(ui) ! 529: register struct uba_device *ui; ! 530: { ! 531: register struct ilreg *reg = (struct ilreg *) ui->ui_addr; ! 532: register struct ilcb *ib = &ilcb[ui->ui_unit]; ! 533: register unsigned short status; ! 534: register int i; ! 535: ! 536: if (&ilcb[ui->ui_unit] > &ilcb[NIL]) ! 537: { ! 538: printf ("il%d: unit number to large. Max = %d\n", ! 539: ui->ui_unit, NIL); ! 540: return; ! 541: } ! 542: ! 543: if (status = (reg->csr & IL_CMD_STATUS)) ! 544: { ! 545: printf ("il%d: bad reset status %x\n"); ! 546: return; ! 547: } ! 548: ! 549: ib->attached = 1; ! 550: ! 551: initqueue((struct Queue *)&ib->type_q); ! 552: initqueue((struct Queue *)&ib->free_q); ! 553: ib->num_types = 0; ! 554: ib->num_free = ILMAXTYPES; ! 555: ! 556: for (i = 0; i < ILMAXTYPES; i++) ! 557: enqueue (&ib->free_q, ib->type[i]); ! 558: ! 559: #ifdef TCP_IP ! 560: #if NBBNNET > 0 ! 561: il_attach(); ! 562: #endif NBBNNET ! 563: #endif TCP_IP ! 564: } ! 565: ! 566: ! 567: ! 568: /*++* ! 569: * Procedure: ilprobe ! 570: * Abstract: ! 571: * This routine is called by the system auto configurer ! 572: * at boot time. It locates the interrupt vectors of the device ! 573: * by doing FM (f___ing Magic). Cvec is used as a global register ! 574: * in which the interrupt routine places the interrupt vector ! 575: * that it found when the device interrupted. ! 576: * We can use this routine to do some boot time testing if ! 577: * we want. ! 578: * Parameters: ! 579: * 'reg' the base address of the ethernet device. ! 580: * ! 581: *--*/ ! 582: ilprobe(reg) ! 583: struct ilreg *reg; ! 584: { ! 585: register int br,cvec; ! 586: ! 587: #ifdef lint ! 588: br = 0; cvec = br; br = cvec; ! 589: #endif ! 590: ! 591: reg->bcr = 0; ! 592: reg->bar = 0; ! 593: reg->csr = IL_OFF_LINE | IL_CMD_INTR; ! 594: DELAY(10000); ! 595: ! 596: br = reg->csr; /* clear off status from il board */ ! 597: cvec &= ~0xf; /* make sure we have the first intr vector */ ! 598: return(1); ! 599: } ! 600: ! 601: ! 602: ! 603: ! 604: /*++* ! 605: * Procedure: ilreset ! 606: * Abstract: ! 607: * reset the interlan ethernet device ! 608: * Called on UBA reset to restart pending I/O. ! 609: * Just prints the device name and restarts the receiver and ! 610: * transmitter. No other state that we care about is lost by ! 611: * the reset. ! 612: * Parameters: ! 613: * 'uban' number of the uba that was reset. ! 614: * ! 615: *--*/ ! 616: ilreset(uban) ! 617: { ! 618: ! 619: register int dev; ! 620: register struct uba_device *ui; ! 621: register struct ilreg *reg = (struct ilreg *) ui->ui_addr; ! 622: register struct ilcb *ib; ! 623: ! 624: for (dev = 0; dev < NIL; dev++) ! 625: { ! 626: if ((ui = ildinfo[dev]) || ! 627: ui->ui_alive == 0 || ! 628: ui->ui_ubanum != uban) ! 629: continue; ! 630: ! 631: ! 632: ib = &ilcb[dev]; ! 633: /*++* ! 634: * do a reset command so we are sure of the state ! 635: * ! 636: *--*/ ! 637: NM10command (IL_RESET, 0, 0); ! 638: printf("[reset] "); ! 639: ! 640: /*++* ! 641: * put us back on line if we are active ! 642: * and start the command and receive processes. ! 643: * ! 644: *--*/ ! 645: if (ib->avail) ! 646: { ! 647: NM10command (IL_ON_LINE, 0, 0); ! 648: printf ("[on line]"); ! 649: } ! 650: else printf ("[off line]"); ! 651: } ! 652: ! 653: if (ib->cmd_packet) ! 654: (*ib->cmd_packet->function) (ib->cmd_packet, dev); ! 655: ! 656: ib->in_ptr = 0; ! 657: ib->in_packet = NULL; ! 658: ib->in_next = NULL; ! 659: ib->cmd_packet = NULL; ! 660: ilcmdstart(ui); ! 661: ilrstart (ui); ! 662: } ! 663:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.