|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* NOTE: ! 27: * There are three outstanding bug/features in this implementation. ! 28: * They may even be hardware misfeatures. The conditions are registered ! 29: * by counters maintained by the software. ! 30: * 1: over_write is a condition that means that the board wants to store ! 31: * packets, but there is no room. So new packets are lost. What seems to ! 32: * be happening is that we get an over_write condition, but there are no ! 33: * or just a few packets in the board's ram. Also it seems that we get ! 34: * several over_writes in a row. ! 35: * 2: Since there is only one transmit buffer, we need a lock to indicate ! 36: * whether it is in use. We clear this lock when we get a transmit interrupt. ! 37: * Sometimes we go to transmit and although there is no transmit in progress, ! 38: * the lock is set. (In this case, we just ignore the lock.) It would look ! 39: * like we can miss transmit interrupts? ! 40: * 3: We tried to clean up the unnecessary switches to bank 0. ! 41: * Unfortunately, when you do an ifconfig "down", the system tend to lock up ! 42: * a few seconds later (this was when DSF_RUNNING) was not being set before. ! 43: * But even with DSF_RUNNING, on an EISA bus machine we ALWAYS lock up after ! 44: * a few seconds. ! 45: */ ! 46: ! 47: /* ! 48: * Western Digital 8003E Mach Ethernet driver (for intel 80386) ! 49: * Copyright (c) 1990 by Open Software Foundation (OSF). ! 50: */ ! 51: ! 52: /* ! 53: Copyright 1990 by Open Software Foundation, ! 54: Cambridge, MA. ! 55: ! 56: All Rights Reserved ! 57: ! 58: Permission to use, copy, modify, and distribute this software and ! 59: its documentation for any purpose and without fee is hereby granted, ! 60: provided that the above copyright notice appears in all copies and ! 61: that both the copyright notice and this permission notice appear in ! 62: supporting documentation, and that the name of OSF or Open Software ! 63: Foundation not be used in advertising or publicity pertaining to ! 64: distribution of the software without specific, written prior ! 65: permission. ! 66: ! 67: OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ! 68: <INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, ! 69: IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR ! 70: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ! 71: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, ! 72: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION ! 73: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ! 74: */ ! 75: ! 76: #define IF_CNTRS MACH ! 77: ! 78: #include <ns8390.h> ! 79: #if NNS8390 > 0 ! 80: ! 81: #include <mach_ttd.h> ! 82: #include <kern/time_out.h> ! 83: #include <device/device_types.h> ! 84: #include <device/errno.h> ! 85: #include <device/io_req.h> ! 86: #include <device/if_hdr.h> ! 87: #include <device/if_ether.h> ! 88: #include <device/net_status.h> ! 89: #include <device/net_io.h> ! 90: #include "vm_param.h" ! 91: #include <i386/ipl.h> ! 92: #include <chips/busses.h> ! 93: #include <i386at/ds8390.h> ! 94: #include <i386at/if_wd8003.h> ! 95: #include <i386at/if_3c503.h> ! 96: ! 97: #if MACH_TTD ! 98: #include <ttd/ttd_stub.h> ! 99: #endif /* MACH_TTD */ ! 100: ! 101: ! 102: #define SPLNET spl6 ! 103: ! 104: int wd_debug = 0; ! 105: ! 106: int ns8390probe(); ! 107: void ns8390attach(); ! 108: int ns8390intr(); ! 109: int ns8390init(); ! 110: int ns8390output(); ! 111: int ns8390ioctl(); ! 112: int ns8390reset(); ! 113: int ns8390rcv(); ! 114: int ns8390watch(); ! 115: int ns8390get_CURR(); ! 116: int ns8390over_write(); ! 117: ! 118: struct bus_device *ns8390info[NNS8390]; /* ???? */ ! 119: ! 120: static vm_offset_t ns8390_std[NNS8390] = { 0 }; ! 121: static struct bus_device *ns8390_info[NNS8390]; ! 122: struct bus_driver ns8390driver = ! 123: {ns8390probe, 0, ns8390attach, 0, ns8390_std, "ns8390", ns8390_info, 0, 0, 0}; ! 124: ! 125: int watchdog_id; ! 126: ! 127: char *wd8003_card = "wd"; ! 128: char *elii_card = "el"; ! 129: /* 2e0, 2a0, 280, 250, 350, 330, 310, 300*/ ! 130: int elii_irq[8] = {5, 2, 2, 5, 5, 0x711, 0x711, 5}; ! 131: int elii_bnc[8] = {1, 0, 1, 1, 0, 0x711, 0x711, 0}; ! 132: /*int elii_bnc[8] = {0, 1, 1, 1, 1, 1, 0, 1}; */ ! 133: ! 134: typedef struct { ! 135: #ifdef MACH_KERNEL ! 136: struct ifnet ds_if; /* generic interface header */ ! 137: u_char ds_addr[6]; /* Ethernet hardware address */ ! 138: #else MACH_KERNEL ! 139: struct arpcom ns8390_ac; ! 140: #define ds_if ns8390_ac.ac_if ! 141: #define ds_addr ns8390_ac.ac_enaddr ! 142: #endif MACH_KERNEL ! 143: int flags; ! 144: int timer; ! 145: int interrupt; ! 146: char *nic; ! 147: u_char address[ETHER_ADDR_SIZE]; ! 148: short mode; ! 149: int tbusy; ! 150: char *sram; /* beginning of the shared memory RAM buffer */ ! 151: int read_nxtpkt_ptr;/* pointer to next packet available */ ! 152: int pstart; /* page start hold */ ! 153: int pstop; /* page stop hold */ ! 154: int tpsr; /* transmit page start hold */ ! 155: int fifo_depth; /* NIC fifo threshold */ ! 156: char *card; ! 157: int board_id; ! 158: } ! 159: ns8390_softc_t; ! 160: ! 161: ns8390_softc_t ns8390_softc[NNS8390]; ! 162: ! 163: struct ns8390_cntrs { ! 164: u_int ovw, ! 165: jabber, ! 166: crc, ! 167: frame, ! 168: miss, ! 169: fifo, ! 170: rcv; ! 171: u_int xmt, ! 172: xmti, ! 173: busy, ! 174: heart; ! 175: } ns8390_cntrs[NNS8390]; ! 176: ! 177: #if MACH_TTD ! 178: boolean_t ttd_poll_loop; ! 179: ! 180: int ns8390poll_receive(); ! 181: int ns8390transmit_ttd(); ! 182: #endif /* MACH_TTD */ ! 183: ! 184: #ifdef IF_CNTRS ! 185: int ns_narp = 1, ns_arp = 0; ! 186: int ns_ein[32], ns_eout[32]; ! 187: int ns_lin[128/8], ns_lout[128/8]; ! 188: static ! 189: log_2(no) ! 190: unsigned long no; ! 191: { ! 192: return ({ unsigned long _temp__; ! 193: asm("bsr %1, %0; jne 0f; xorl %0, %0; 0:" : ! 194: "=r" (_temp__) : "a" (no)); ! 195: _temp__;}); ! 196: } ! 197: #endif IF_CNTRS ! 198: ! 199: /* Interrupts mask bits */ ! 200: int imr_hold = DSIM_PRXE|DSIM_PTXE|DSIM_RXEE|DSIM_TXEE|DSIM_OVWE|DSIM_CNTE; ! 201: ! 202: /* ! 203: * ns8390probe: ! 204: * ! 205: * This function "probes" or checks for the wd8003 board on the bus to see ! 206: * if it is there. As far as I can tell, the best break between this ! 207: * routine and the attach code is to simply determine whether the board ! 208: * is configured in properly. Currently my approach to this is to test the ! 209: * base I/O special offset for the Western Digital unique byte sequence ! 210: * identifier. If the bytes match we assume board is there. ! 211: * The config code expects to see a successful return from the probe ! 212: * routine before attach will be called. ! 213: * ! 214: * input : address device is mapped to, and unit # being checked ! 215: * output : a '1' is returned if the board exists, and a 0 otherwise ! 216: * ! 217: */ ! 218: ! 219: ns8390probe(port, dev) ! 220: struct bus_device *dev; ! 221: { ! 222: caddr_t hdwbase = (caddr_t)dev->address; ! 223: int unit = dev->unit; ! 224: ns8390_softc_t *sp = &ns8390_softc[unit]; ! 225: int tmp; ! 226: int vendor_id; ! 227: ! 228: if ((unit < 0) || (unit > NNS8390)) { ! 229: printf("ns8390 ethernet unit %d out of range\n", unit); ! 230: return(0); ! 231: } ! 232: if (((u_char) inb(hdwbase+IFWD_LAR_0) == (u_char) WD_NODE_ADDR_0) && ! 233: ((u_char) inb(hdwbase+IFWD_LAR_1) == (u_char) WD_NODE_ADDR_1) && ! 234: ((u_char) inb(hdwbase+IFWD_LAR_2) == (u_char) WD_NODE_ADDR_2)) { ! 235: ns8390info[unit] = dev; ! 236: sp->card = wd8003_card; ! 237: dev->name = wd8003_card; ! 238: sp->nic = hdwbase + OFF_8390; ! 239: /* enable mem access to board */ ! 240: sp->board_id = wd80xxget_board_id(dev); ! 241: ! 242: *(sp->address) = inb(hdwbase+IFWD_LAR_0); ! 243: *(sp->address + 1) = inb(hdwbase+IFWD_LAR_1); ! 244: *(sp->address + 2) = inb(hdwbase+IFWD_LAR_2); ! 245: *(sp->address + 3) = inb(hdwbase+IFWD_LAR_3); ! 246: *(sp->address + 4) = inb(hdwbase+IFWD_LAR_4); ! 247: *(sp->address + 5) = inb(hdwbase+IFWD_LAR_5); ! 248: return (1); ! 249: } /* checks the address of the board to verify that it is a WD */ ! 250: ! 251: /* try to avoid any NE2000 pretending to be an el II */ ! 252: if (inb(hdwbase + 0x408) == 0xff) ! 253: return 0; ! 254: ! 255: /* check vendor id */ ! 256: tmp = inb(hdwbase + CTLR); ! 257: ! 258: outb(hdwbase + CTLR, CTLR_RST|CTLR_THIN); /* Reset it... */ ! 259: outb(hdwbase + CTLR, CTLR_THIN); ! 260: /* ! 261: * Map the station addr PROM into the lower I/O ports. We now ! 262: * check for both the old and new 3Com prefix ! 263: */ ! 264: outb(hdwbase + CTLR, CTLR_STA_ADDR|CTLR_THIN); ! 265: vendor_id = inb(hdwbase)*0x10000 + inb(hdwbase + 1)*0x100 + ! 266: inb(hdwbase + 2); ! 267: /* Restore the register we frobbed. */ ! 268: outb(hdwbase + CTLR, tmp); ! 269: if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) ! 270: return 0; ! 271: ! 272: if ((tmp = inb(hdwbase+BCFR))) { ! 273: switch(tmp) { ! 274: case (1<<7): sp->board_id = 7; break; /*irq5 xvcr*/ ! 275: #ifdef not_currently_possible ! 276: case (1<<6): sp->board_id = 6; break; ! 277: case (1<<5): sp->board_id = 5; break; ! 278: #endif not_currently_possible ! 279: case (1<<4): sp->board_id = 4; break; ! 280: case (1<<3): sp->board_id = 3; break; ! 281: case (1<<2): sp->board_id = 2; break; /*irq2 bnc*/ ! 282: case (1<<1): sp->board_id = 1; break; /*irq2 xvcr*/ ! 283: case (1<<0): sp->board_id = 0; break; /*irq5 bnc*/ ! 284: default: return 0; ! 285: } ! 286: switch (inb(hdwbase+PCFR)) { ! 287: case (1<<7): dev->phys_address = 0xDC000; break; ! 288: case (1<<6): dev->phys_address = 0xD8000; break; ! 289: #ifdef not_currently_possible ! 290: case (1<<5): dev->phys_address = 0xCC000; break; ! 291: case (1<<4): dev->phys_address = 0xC8000; break; ! 292: #endif not_currently_possible ! 293: default: ! 294: printf("EtherLink II with NO memory configured\n"); ! 295: return 0; ! 296: } ! 297: ns8390info[unit] = dev; ! 298: dev->sysdep1 = elii_irq[sp->board_id]; ! 299: if (dev->sysdep1 == 2) ! 300: dev->sysdep1 = 9; ! 301: sp->card = elii_card; ! 302: dev->name = elii_card; ! 303: sp->nic = hdwbase; ! 304: return 1; ! 305: } ! 306: ! 307: return(0); ! 308: } ! 309: ! 310: /* ! 311: * ns8390attach: ! 312: * ! 313: * This function attaches a ns8390 board to the "system". The rest of ! 314: * runtime structures are initialized here (this routine is called after ! 315: * a successful probe of the board). Once the ethernet address is read ! 316: * and stored, the board's ifnet structure is attached and readied. ! 317: * ! 318: * input : bus_device structure setup in autoconfig ! 319: * output : board structs and ifnet is setup ! 320: * ! 321: */ ! 322: ! 323: void ns8390attach(dev) ! 324: struct bus_device *dev; ! 325: { ! 326: ns8390_softc_t *sp; ! 327: struct ifnet *ifp; ! 328: u_char unit; ! 329: int temp; ! 330: ! 331: take_dev_irq(dev); ! 332: unit = (u_char)dev->unit; ! 333: sp = &ns8390_softc[unit]; ! 334: printf(", port = %x, spl = %d, pic = %d. ", ! 335: dev->address, dev->sysdep, dev->sysdep1); ! 336: ! 337: if (sp->card == elii_card) { ! 338: if (elii_bnc[sp->board_id]) ! 339: printf("cheapernet "); ! 340: else ! 341: printf("ethernet "); ! 342: } else ! 343: printf("ethernet "); ! 344: ! 345: (volatile char *)sp->sram = ! 346: (volatile char *) phystokv(dev->phys_address); ! 347: dev->address = (vm_offset_t) phystokv(dev->address); ! 348: sp->timer = -1; ! 349: sp->flags = 0; ! 350: sp->mode = 0; ! 351: ! 352: if (!ns8390hwrst(unit)) { ! 353: printf("%s%d: attach(): reset failed.\n", ! 354: sp->card, unit); ! 355: return; ! 356: } ! 357: /* N.B. sp->address is not determined till ! 358: * hwrst time. */ ! 359: *(sp->ds_addr) = *(sp->address); ! 360: *(sp->ds_addr + 1) = *(sp->address + 1); ! 361: *(sp->ds_addr + 2) = *(sp->address + 2); ! 362: *(sp->ds_addr + 3) = *(sp->address + 3); ! 363: *(sp->ds_addr + 4) = *(sp->address + 4); ! 364: *(sp->ds_addr + 5) = *(sp->address + 5); ! 365: ! 366: printf("id [%x:%x:%x:%x:%x:%x]", ! 367: sp->address[0],sp->address[1],sp->address[2], ! 368: sp->address[3],sp->address[4],sp->address[5]); ! 369: ifp = &(sp->ds_if); ! 370: ifp->if_unit = unit; ! 371: ifp->if_mtu = ETHERMTU; ! 372: ifp->if_flags = IFF_BROADCAST; ! 373: #ifdef MACH_KERNEL ! 374: ifp->if_header_size = sizeof(struct ether_header); ! 375: ifp->if_header_format = HDR_ETHERNET; ! 376: ifp->if_address_size = 6; ! 377: ifp->if_address = (char *)&sp->address[0]; ! 378: if_init_queues(ifp); ! 379: #else MACH_KERNEL ! 380: ifp->if_name = sp->card; ! 381: ifp->if_init = ns8390init; ! 382: ifp->if_output = ns8390output; ! 383: ifp->if_ioctl = ns8390ioctl; ! 384: ifp->if_reset = ns8390reset; ! 385: ifp->if_next = NULL; ! 386: if_attach(ifp); ! 387: #ifdef notdef ! 388: watchdog_id = timeout(ns8390watch, &(ifp->if_unit), 20*HZ); ! 389: #endif ! 390: #endif MACH_KERNEL ! 391: ! 392: #ifdef MACH_KERNEL ! 393: #if MACH_TTD ! 394: if (!ttd_get_packet) { ! 395: ttd_device_unit = unit; ! 396: ttd_get_packet = ns8390poll_receive; ! 397: ttd_send_packet = ns8390transmit_ttd; ! 398: ttd_host_ether_id.array[0] = *(sp->address); ! 399: ttd_host_ether_id.array[1] = *(sp->address + 1); ! 400: ttd_host_ether_id.array[2] = *(sp->address + 2); ! 401: ttd_host_ether_id.array[3] = *(sp->address + 3); ! 402: ttd_host_ether_id.array[4] = *(sp->address + 4); ! 403: ttd_host_ether_id.array[5] = *(sp->address + 5); ! 404: } ! 405: #endif /* MACH_TTD */ ! 406: #endif /* MACH_KERNEL */ ! 407: } ! 408: ! 409: /* ! 410: * ns8390watch(): ! 411: * ! 412: */ ! 413: ! 414: int ! 415: ns8390watch(b_ptr) ! 416: caddr_t b_ptr; ! 417: { ! 418: int x, ! 419: y, ! 420: opri, ! 421: unit; ! 422: int temp_cr; ! 423: caddr_t nic; ! 424: ! 425: unit = *b_ptr; ! 426: #ifdef MACH_KERNEL ! 427: timeout(ns8390watch,b_ptr,20*HZ); ! 428: #else MACH_KERNEL ! 429: watchdog_id = timeout(ns8390watch,b_ptr,20*HZ); ! 430: #endif MACH_KERNEL ! 431: nic = ns8390_softc[unit].nic; ! 432: temp_cr = inb(nic+ds_cmd); ! 433: outb(nic + ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); ! 434: printf("<<< ISR=%x CURR=%x rdnxt=%x BNDY=%x>>> ", ! 435: inb(nic + ds0_isr), ! 436: ns8390get_CURR(unit), ns8390_softc[unit].read_nxtpkt_ptr, ! 437: inb(nic+ds0_bndy)); ! 438: outb(nic+ds_cmd,temp_cr); ! 439: } ! 440: ! 441: #ifdef MACH_KERNEL ! 442: int ns8390start(); /* forward */ ! 443: ! 444: /*ARGSUSED*/ ! 445: wd8003open(dev, flag) ! 446: dev_t dev; ! 447: int flag; ! 448: { ! 449: register int unit = minor(dev); ! 450: ! 451: if (ns8390_softc[unit].card != wd8003_card) ! 452: return (ENXIO); ! 453: if (unit < 0 || unit >= NNS8390 || ! 454: ns8390_softc[unit].nic == 0) ! 455: return (ENXIO); ! 456: ! 457: ns8390_softc[unit].ds_if.if_flags |= IFF_UP; ! 458: ns8390init(unit); ! 459: return(0); ! 460: } ! 461: ! 462: eliiopen(dev, flag) ! 463: dev_t dev; ! 464: int flag; ! 465: { ! 466: register int unit = minor(dev); ! 467: ! 468: if (ns8390_softc[unit].card != elii_card) ! 469: return (ENXIO); ! 470: if (unit < 0 || unit >= NNS8390 || ! 471: ns8390_softc[unit].nic == 0) ! 472: return (ENXIO); ! 473: ! 474: ns8390_softc[unit].ds_if.if_flags |= IFF_UP; ! 475: ns8390init(unit); ! 476: return(0); ! 477: } ! 478: ! 479: ns8390output(dev, ior) ! 480: dev_t dev; ! 481: io_req_t ior; ! 482: { ! 483: register int unit = minor(dev); ! 484: ! 485: if (unit < 0 || unit >= NNS8390 || ! 486: ns8390_softc[unit].nic == 0) ! 487: return (ENXIO); ! 488: return (net_write(&ns8390_softc[unit].ds_if, ns8390start, ior)); ! 489: } ! 490: ! 491: ns8390setinput(dev, receive_port, priority, filter, filter_count) ! 492: dev_t dev; ! 493: mach_port_t receive_port; ! 494: int priority; ! 495: filter_t filter[]; ! 496: unsigned int filter_count; ! 497: { ! 498: register int unit = minor(dev); ! 499: ! 500: if (unit < 0 || unit >= NNS8390 || ! 501: ns8390_softc[unit].nic == 0) ! 502: return (ENXIO); ! 503: ! 504: return (net_set_filter(&ns8390_softc[unit].ds_if, ! 505: receive_port, priority, ! 506: filter, filter_count)); ! 507: } ! 508: ! 509: #else MACH_KERNEL ! 510: /* ! 511: * ns8390output: ! 512: * ! 513: * This routine is called by the "if" layer to output a packet to ! 514: * the network. This code resolves the local ethernet address, and ! 515: * puts it into the mbuf if there is room. If not, then a new mbuf ! 516: * is allocated with the header information and precedes the data ! 517: * to be transmitted. The routine ns8390xmt() which actually ! 518: * transmits the data expects the ethernet header to precede the ! 519: * data in the mbuf. ! 520: * ! 521: * input: ifnet structure pointer, an mbuf with data, and address ! 522: * to be resolved ! 523: * output: mbuf is updated to hold enet address, or a new mbuf ! 524: * with the address is added ! 525: * ! 526: */ ! 527: ! 528: ns8390output(ifp, m0, dst) ! 529: struct ifnet *ifp; ! 530: struct mbuf *m0; ! 531: struct sockaddr *dst; ! 532: { ! 533: register ns8390_softc_t *is = &ns8390_softc[ifp->if_unit]; ! 534: u_char edst[6]; ! 535: struct in_addr idst; ! 536: register struct mbuf *m = m0; ! 537: register struct ether_header *eh; ! 538: register int off; ! 539: int usetrailers; ! 540: int type, error; ! 541: spl_t opri; ! 542: ! 543: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { ! 544: printf("%s%d output(): Turning off board %d\n", ! 545: is->card, ifp->if_unit); ! 546: ns8390intoff(ifp->if_unit); ! 547: error = ENETDOWN; ! 548: goto bad; ! 549: } ! 550: switch (dst->sa_family) { ! 551: #ifdef INET ! 552: case AF_INET: ! 553: idst = ((struct sockaddr_in *)dst)->sin_addr; ! 554: if (!arpresolve(&is->ns8390_ac, m, &idst, edst, &usetrailers)){ ! 555: return (0); /* if not yet resolved */ ! 556: } ! 557: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; ! 558: if (usetrailers && off > 0 && (off & 0x1ff) == 0 && ! 559: m->m_off >= MMINOFF + 2 * sizeof (u_short)) { ! 560: type = ETHERTYPE_TRAIL + (off>>9); ! 561: m->m_off -= 2 * sizeof (u_short); ! 562: m->m_len += 2 * sizeof (u_short); ! 563: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); ! 564: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); ! 565: goto gottrailertype; ! 566: } ! 567: type = ETHERTYPE_IP; ! 568: off = 0; ! 569: goto gottype; ! 570: #endif ! 571: #ifdef NS ! 572: case AF_NS: ! 573: type = ETHERTYPE_NS; ! 574: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), ! 575: (caddr_t)edst, ! 576: sizeof (edst)); ! 577: off = 0; ! 578: goto gottype; ! 579: #endif ! 580: case AF_UNSPEC: ! 581: eh = (struct ether_header *)dst->sa_data; ! 582: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); ! 583: type = eh->ether_type; ! 584: goto gottype; ! 585: default: ! 586: printf("%s%d output(): can't handle af%d\n", ! 587: is->card, ifp->if_unit, ! 588: dst->sa_family); ! 589: error = EAFNOSUPPORT; ! 590: goto bad; ! 591: } ! 592: gottrailertype: ! 593: /* ! 594: * Packet to be sent as trailer: move first packet ! 595: * (control information) to end of chain. ! 596: */ ! 597: while (m->m_next) ! 598: m = m->m_next; ! 599: m->m_next = m0; ! 600: m = m0->m_next; ! 601: m0->m_next = 0; ! 602: m0 = m; ! 603: gottype: ! 604: /* ! 605: * Add local net header. If no space in first mbuf, ! 606: * allocate another. ! 607: */ ! 608: if (m->m_off > MMAXOFF || ! 609: MMINOFF + sizeof (struct ether_header) > m->m_off) { ! 610: m = m_get(M_DONTWAIT, MT_HEADER); ! 611: if (m == 0) { ! 612: error = ENOBUFS; ! 613: goto bad; ! 614: } ! 615: m->m_next = m0; ! 616: m->m_off = MMINOFF; ! 617: m->m_len = sizeof (struct ether_header); ! 618: } else { ! 619: m->m_off -= sizeof (struct ether_header); ! 620: m->m_len += sizeof (struct ether_header); ! 621: } ! 622: eh = mtod(m, struct ether_header *); ! 623: eh->ether_type = htons((u_short)type); ! 624: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); ! 625: bcopy((caddr_t)is->address, ! 626: (caddr_t)eh->ether_shost, ! 627: sizeof(edst)); ! 628: /* ! 629: * Queue message on interface, and start output if interface ! 630: * not yet active. ! 631: */ ! 632: opri = SPLNET(); ! 633: if (IF_QFULL(&ifp->if_snd)) { ! 634: IF_DROP(&ifp->if_snd); ! 635: splx(opri); ! 636: m_freem(m); ! 637: return (ENOBUFS); ! 638: } ! 639: IF_ENQUEUE(&ifp->if_snd, m); ! 640: /* ! 641: * Some action needs to be added here for checking whether the ! 642: * board is already transmitting. If it is, we don't want to ! 643: * start it up (ie call ns8390start()). We will attempt to send ! 644: * packets that are queued up after an interrupt occurs. Some ! 645: * flag checking action has to happen here and/or in the start ! 646: * routine. This note is here to remind me that some thought ! 647: * is needed and there is a potential problem here. ! 648: * ! 649: */ ! 650: ns8390start(ifp->if_unit); ! 651: splx(opri); ! 652: return (0); ! 653: bad: ! 654: m_freem(m0); ! 655: return (error); ! 656: } ! 657: #endif MACH_KERNEL ! 658: ! 659: /* ! 660: * ns8390reset: ! 661: * ! 662: * This routine is in part an entry point for the "if" code. Since most ! 663: * of the actual initialization has already (we hope already) been done ! 664: * by calling ns8390attach(). ! 665: * ! 666: * input : unit number or board number to reset ! 667: * output : board is reset ! 668: * ! 669: */ ! 670: ! 671: int ! 672: ns8390reset(unit) ! 673: int unit; ! 674: { ! 675: ! 676: ns8390_softc[unit].ds_if.if_flags &= ~IFF_RUNNING; ! 677: return(ns8390init(unit)); ! 678: } ! 679: ! 680: /* ! 681: * ns8390init: ! 682: * ! 683: * Another routine that interfaces the "if" layer to this driver. ! 684: * Simply resets the structures that are used by "upper layers". ! 685: * As well as calling ns8390hwrst that does reset the ns8390 board. ! 686: * ! 687: * input : board number ! 688: * output : structures (if structs) and board are reset ! 689: * ! 690: */ ! 691: ! 692: int ! 693: ns8390init(unit) ! 694: int unit; ! 695: { ! 696: struct ifnet *ifp; ! 697: int stat; ! 698: spl_t oldpri; ! 699: ! 700: ifp = &(ns8390_softc[unit].ds_if); ! 701: #ifdef MACH_KERNEL ! 702: #else MACH_KERNEL ! 703: if (ifp->if_addrlist == (struct ifaddr *)0) { ! 704: return; ! 705: } ! 706: #endif MACH_KERNEL ! 707: oldpri = SPLNET(); ! 708: if ((stat = ns8390hwrst(unit)) == TRUE) { ! 709: ns8390_softc[unit].ds_if.if_flags |= IFF_RUNNING; ! 710: ns8390_softc[unit].flags |= DSF_RUNNING; ! 711: ns8390_softc[unit].tbusy = 0; ! 712: ns8390start(unit); ! 713: } else ! 714: printf("%s%d init(): trouble resetting board %d\n", ! 715: ns8390_softc[unit].card, unit); ! 716: ns8390_softc[unit].timer = 5; ! 717: splx(oldpri); ! 718: return(stat); ! 719: } ! 720: ! 721: /* ! 722: * ns8390start: ! 723: * ! 724: * This is yet another interface routine that simply tries to output a ! 725: * in an mbuf after a reset. ! 726: * ! 727: * input : board number ! 728: * output : stuff sent to board if any there ! 729: * ! 730: */ ! 731: ! 732: ns8390start(unit) ! 733: int unit; ! 734: { ! 735: register ns8390_softc_t *is = &ns8390_softc[unit]; ! 736: struct ifnet *ifp; ! 737: #ifdef MACH_KERNEL ! 738: io_req_t m; ! 739: #else MACH_KERNEL ! 740: struct mbuf *m; ! 741: #endif MACH_KERNEL ! 742: ! 743: if (is->tbusy) { ! 744: caddr_t nic = ns8390_softc[unit].nic; ! 745: if (!(inb(nic+ds_cmd) & DSCM_TRANS)) { ! 746: is->tbusy = 0; ! 747: ns8390_cntrs[unit].busy++; ! 748: } else ! 749: return; ! 750: } ! 751: ! 752: ifp = &(ns8390_softc[unit].ds_if); ! 753: ! 754: IF_DEQUEUE(&ifp->if_snd, m); ! 755: #ifdef MACH_KERNEL ! 756: if (m != 0) ! 757: #else MACH_KERNEL ! 758: if (m != (struct mbuf *)0) ! 759: #endif MACH_KERNEL ! 760: { ! 761: is->tbusy++; ! 762: ns8390_cntrs[unit].xmt++; ! 763: ns8390xmt(unit, m); ! 764: } ! 765: } ! 766: ! 767: #ifdef MACH_KERNEL ! 768: /*ARGSUSED*/ ! 769: ns8390getstat(dev, flavor, status, count) ! 770: dev_t dev; ! 771: int flavor; ! 772: dev_status_t status; /* pointer to OUT array */ ! 773: unsigned int *count; /* out */ ! 774: { ! 775: register int unit = minor(dev); ! 776: ! 777: if (unit < 0 || unit >= NNS8390 || ! 778: ns8390_softc[unit].nic == 0) ! 779: return (ENXIO); ! 780: ! 781: return (net_getstat(&ns8390_softc[unit].ds_if, ! 782: flavor, ! 783: status, ! 784: count)); ! 785: } ! 786: ns8390setstat(dev, flavor, status, count) ! 787: dev_t dev; ! 788: int flavor; ! 789: dev_status_t status; ! 790: unsigned int count; ! 791: { ! 792: register int unit = minor(dev); ! 793: register ns8390_softc_t *sp; ! 794: ! 795: if (unit < 0 || unit >= NNS8390 || ! 796: ns8390_softc[unit].nic == 0) ! 797: return (ENXIO); ! 798: ! 799: sp = &ns8390_softc[unit]; ! 800: ! 801: switch (flavor) { ! 802: case NET_STATUS: ! 803: { ! 804: /* ! 805: * All we can change are flags, and not many of those. ! 806: */ ! 807: register struct net_status *ns = (struct net_status *)status; ! 808: int mode = 0; ! 809: ! 810: if (count < NET_STATUS_COUNT) ! 811: return (D_INVALID_SIZE); ! 812: ! 813: if (ns->flags & IFF_ALLMULTI) ! 814: mode |= MOD_ENAL; ! 815: if (ns->flags & IFF_PROMISC) ! 816: mode |= MOD_PROM; ! 817: ! 818: /* ! 819: * Force a complete reset if the receive mode changes ! 820: * so that these take effect immediately. ! 821: */ ! 822: if (sp->mode != mode) { ! 823: sp->mode = mode; ! 824: if (sp->flags & DSF_RUNNING) { ! 825: sp->flags &= ~(DSF_LOCK | DSF_RUNNING); ! 826: ns8390init(unit); ! 827: } ! 828: } ! 829: break; ! 830: } ! 831: ! 832: default: ! 833: return (D_INVALID_OPERATION); ! 834: } ! 835: return (D_SUCCESS); ! 836: } ! 837: #else MACH_KERNEL ! 838: /* ! 839: * ns8390ioctl: ! 840: * ! 841: * This routine processes an ioctl request from the "if" layer ! 842: * above. ! 843: * ! 844: * input : pointer the appropriate "if" struct, command, and data ! 845: * output : based on command appropriate action is taken on the ! 846: * ns8390 board(s) or related structures ! 847: * return : error is returned containing exit conditions ! 848: * ! 849: */ ! 850: ! 851: int ! 852: ns8390ioctl(ifp, cmd, data) ! 853: struct ifnet *ifp; ! 854: int cmd; ! 855: caddr_t data; ! 856: { ! 857: register struct ifaddr *ifa = (struct ifaddr *)data; ! 858: register ns8390_softc_t *is; ! 859: int error; ! 860: spl_t opri; ! 861: short mode = 0; ! 862: ! 863: is = &ns8390_softc[ifp->if_unit]; ! 864: opri = SPLNET(); ! 865: error = 0; ! 866: switch (cmd) { ! 867: case SIOCSIFADDR: ! 868: ifp->if_flags |= IFF_UP; ! 869: ns8390init(ifp->if_unit); ! 870: switch (ifa->ifa_addr.sa_family) { ! 871: #ifdef INET ! 872: case AF_INET: ! 873: ((struct arpcom *)ifp)->ac_ipaddr = ! 874: IA_SIN(ifa)->sin_addr; ! 875: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 876: break; ! 877: #endif ! 878: #ifdef NS ! 879: case AF_NS: ! 880: { ! 881: register struct ns_addr *ina = ! 882: &(IA_SNS(ifa)->sns_addr); ! 883: if (ns_nullhost(*ina)) ! 884: ina->x_host = ! 885: *(union ns_host *)(ds->ds_addr); ! 886: else ! 887: ???? ! 888: ns8390seteh(ina->x_host.c_host, ! 889: ns8390_softc[ifp->if_unit].base); ! 890: break; ! 891: } ! 892: #endif ! 893: } ! 894: break; ! 895: case SIOCSIFFLAGS: ! 896: if (ifp->if_flags & IFF_ALLMULTI) ! 897: mode |= MOD_ENAL; ! 898: if (ifp->if_flags & IFF_PROMISC) ! 899: mode |= MOD_PROM; ! 900: /* ! 901: * force a complete reset if the receive multicast/ ! 902: * promiscuous mode changes so that these take ! 903: * effect immediately. ! 904: * ! 905: */ ! 906: if (is->mode != mode) { ! 907: is->mode = mode; ! 908: if (is->flags & DSF_RUNNING) { ! 909: is->flags &= ! 910: ~(DSF_LOCK|DSF_RUNNING); ! 911: ns8390init(ifp->if_unit); ! 912: } ! 913: } ! 914: if ((ifp->if_flags & IFF_UP) == 0 && ! 915: is->flags & DSF_RUNNING) { ! 916: printf("%s%d ioctl(): turning off board %d\n", ! 917: is->card, ifp->if_unit); ! 918: is->flags &= ~(DSF_LOCK | DSF_RUNNING); ! 919: is->timer = -1; ! 920: ns8390intoff(ifp->if_unit); ! 921: ns8390over_write(ifp->if_unit); ! 922: } else ! 923: if (ifp->if_flags & IFF_UP && ! 924: (is->flags & DSF_RUNNING) == 0) ! 925: ns8390init(ifp->if_unit); ! 926: break; ! 927: #ifdef IF_CNTRS ! 928: case SIOCCIFCNTRS: ! 929: if (!suser()) { ! 930: error = EPERM; ! 931: break; ! 932: } ! 933: bzero((caddr_t)ns_ein, sizeof (ns_ein)); ! 934: bzero((caddr_t)ns_eout, sizeof (ns_eout)); ! 935: bzero((caddr_t)ns_lin, sizeof (ns_lin)); ! 936: bzero((caddr_t)ns_lout, sizeof (ns_lout)); ! 937: bzero((caddr_t)&ns_arp, sizeof (int)); ! 938: bzero((caddr_t)&ns8390_cntrs, sizeof (ns8390_cntrs)); ! 939: break; ! 940: #endif IF_CNTRS ! 941: default: ! 942: error = EINVAL; ! 943: } ! 944: splx(opri); ! 945: return (error); ! 946: } ! 947: #endif MACH_KERNEL ! 948: ! 949: /* ! 950: * ns8390hwrst: ! 951: * ! 952: * This routine resets the ns8390 board that corresponds to the ! 953: * board number passed in. ! 954: * ! 955: * input : board number to do a hardware reset ! 956: * output : board is reset ! 957: * ! 958: */ ! 959: ! 960: int ! 961: ns8390hwrst(unit) ! 962: int unit; ! 963: { ! 964: caddr_t nic = ns8390_softc[unit].nic; ! 965: int count; ! 966: u_char stat; ! 967: spl_t spl = SPLNET(); ! 968: ! 969: if (ns8390_softc[unit].card == wd8003_card && ! 970: config_wd8003(unit) == FALSE) { ! 971: printf("%s%d hwrst(): config_wd8003 failed.\n", ! 972: ns8390_softc[unit].card, unit); ! 973: splx(spl); ! 974: return(FALSE); ! 975: } ! 976: if (ns8390_softc[unit].card == elii_card && ! 977: config_3c503(unit) == FALSE) { ! 978: printf("%s%d hwrst(): config_3c503 failed.\n", ! 979: ns8390_softc[unit].card, unit); ! 980: splx(spl); ! 981: return(FALSE); ! 982: } ! 983: if (config_nic(unit) == FALSE) { ! 984: printf("%s%d hwrst(): config_nic failed.\n", ! 985: ns8390_softc[unit].card, unit); ! 986: splx(spl); ! 987: return(FALSE); ! 988: } ! 989: splx(spl); ! 990: return(TRUE); ! 991: } ! 992: ! 993: /* ! 994: * ns8390intr: ! 995: * ! 996: * This function is the interrupt handler for the ns8390 ethernet ! 997: * board. This routine will be called whenever either a packet ! 998: * is received, or a packet has successfully been transfered and ! 999: * the unit is ready to transmit another packet. ! 1000: * ! 1001: * input : board number that interrupted ! 1002: * output : either a packet is received, or a packet is transfered ! 1003: * ! 1004: */ ! 1005: int ! 1006: ns8390intr(unit) ! 1007: { ! 1008: int opri, i; ! 1009: int isr_status; ! 1010: int temp_cr; ! 1011: caddr_t nic = ns8390_softc[unit].nic; ! 1012: ! 1013: temp_cr = inb(nic+ds_cmd); ! 1014: outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); ! 1015: outb(nic+ds0_imr, 0); /* stop board interrupts */ ! 1016: outb(nic+ds_cmd, temp_cr); ! 1017: while (isr_status = inb(nic+ds0_isr)) { ! 1018: outb(nic+ds0_isr, isr_status); /* clear interrupt status */ ! 1019: ! 1020: if ((isr_status & (DSIS_ROVRN|DSIS_RXE)) == DSIS_RXE) { ! 1021: int rsr = inb(nic+ds0_rsr); ! 1022: if (rsr & DSRS_DFR) ns8390_cntrs[unit].jabber++; ! 1023: if (rsr & ~(DSRS_DFR|DSRS_PHY|DSRS_FAE|DSRS_CRC|DSIS_RX)) ! 1024: printf("%s%d intr(): isr = %x, RSR = %x\n", ! 1025: ns8390_softc[unit].card, unit, ! 1026: isr_status, rsr); ! 1027: } else if (isr_status & DSIS_ROVRN) { ! 1028: ns8390_cntrs[unit].ovw++; ! 1029: ns8390over_write(unit); ! 1030: } ! 1031: if (isr_status & DSIS_RX) { /* DFR & PRX is possible */ ! 1032: ns8390rcv(unit); ! 1033: ! 1034: #if MACH_TTD ! 1035: if (kttd_active) ! 1036: ttd_poll_loop = FALSE; ! 1037: #endif /* MACH_TTD */ ! 1038: } ! 1039: ! 1040: if (isr_status & DSIS_TXE) { ! 1041: int tsr = inb(nic+ds0_tsr); ! 1042: tsr &= ~0x2; /* unadvertised special */ ! 1043: #if MACH_TTD ! 1044: if (!kttd_active) ! 1045: #endif /* MACH_TTD */ ! 1046: { ! 1047: if (tsr == (DSTS_CDH|DSTS_ABT)) ! 1048: ns8390_cntrs[unit].heart++; ! 1049: else ! 1050: printf("%s%d intr(): isr = %x, TSR = %x\n", ! 1051: ns8390_softc[unit].card, unit, ! 1052: isr_status, tsr); ! 1053: ns8390_softc[unit].tbusy = 0; ! 1054: ns8390start(unit); ! 1055: } ! 1056: } else if (isr_status & DSIS_TX) { ! 1057: #if MACH_TTD ! 1058: if (!kttd_active) ! 1059: #endif /* MACH_TTD */ ! 1060: { ! 1061: ns8390_cntrs[unit].xmti++; ! 1062: ns8390_softc[unit].tbusy = 0; ! 1063: ns8390start(unit); ! 1064: } ! 1065: } ! 1066: ! 1067: if (isr_status & DSIS_CTRS) { ! 1068: int c0 = inb(nic+ds0_cntr0); ! 1069: int c1 = inb(nic+ds0_cntr1); ! 1070: int c2 = inb(nic+ds0_cntr2); ! 1071: ns8390_cntrs[unit].frame += c0; ! 1072: ns8390_cntrs[unit].crc += c1; ! 1073: ns8390_cntrs[unit].miss += c2; ! 1074: #ifdef COUNTERS ! 1075: printf("%s%d intr(): isr = %x, FRAME %x, CRC %x, MISS %x\n", ! 1076: ns8390_softc[unit].card, unit, ! 1077: isr_status, c0, c1, c2); ! 1078: printf("%s%d intr(): TOTAL , FRAME %x, CRC %x, MISS %x\n", ! 1079: ns8390_softc[unit].card, unit, ! 1080: ns8390_cntrs[unit].frame, ! 1081: ns8390_cntrs[unit].crc, ! 1082: ns8390_cntrs[unit].miss); ! 1083: #endif COUNTERS ! 1084: outb(nic+ds0_isr, isr_status); /* clear interrupt status again */ ! 1085: } ! 1086: } ! 1087: temp_cr=inb(nic+ds_cmd); ! 1088: outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); ! 1089: outb(nic+ds0_imr, imr_hold); ! 1090: outb(nic+ds_cmd, temp_cr); ! 1091: return(0); ! 1092: } ! 1093: ! 1094: /* ! 1095: * Called if on board buffer has been completely filled by ns8390intr. It stops ! 1096: * the board, reads in all the buffers that are currently in the buffer, and ! 1097: * then restart board. ! 1098: */ ! 1099: ns8390over_write(unit) ! 1100: int unit; ! 1101: { ! 1102: caddr_t nic = ns8390_softc[unit].nic; ! 1103: int no; ! 1104: int count = 0; ! 1105: ! 1106: outb(nic+ds_cmd, DSCM_NODMA|DSCM_STOP|DSCM_PG0); /* clear the receive buffer */ ! 1107: outb(nic+ds0_rbcr0, 0); ! 1108: outb(nic+ds0_rbcr1, 0); ! 1109: while ((!(inb (nic + ds0_isr) & DSIS_RESET)) && (count < 10000)) ! 1110: count++; ! 1111: if (count == 10000) { ! 1112: printf("%s%d: over_write(): would not reset.\n", ! 1113: ns8390_softc[unit].card, unit); ! 1114: } ! 1115: no = ns8390rcv(unit); ! 1116: #ifdef OVWBUG ! 1117: printf("%s%d over_write(): ns8390 OVW ... %d.\n", ! 1118: ns8390_softc[unit].card, unit, no); ! 1119: #endif OVWBUG ! 1120: outb(nic+ds0_tcr, DSTC_LB0); /* External loopback mode */ ! 1121: outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0); ! 1122: outb(nic+ds0_tcr, 0); ! 1123: return; ! 1124: } ! 1125: ! 1126: /* ! 1127: * ns8390rcv: ! 1128: * ! 1129: * This routine is called by the interrupt handler to initiate a ! 1130: * packet transfer from the board to the "if" layer above this ! 1131: * driver. This routine checks if a buffer has been successfully ! 1132: * received by the ns8390. If so, it does the actual transfer of the ! 1133: * board data (including the ethernet header) into a packet (consisting ! 1134: * of an mbuf chain) and enqueues it to a higher level. ! 1135: * Then check again whether there are any packets in the receive ring, ! 1136: * if so, read the next packet, until there are no more. ! 1137: * ! 1138: * input : number of the board to check ! 1139: * output : if a packet is available, it is "sent up" ! 1140: */ ! 1141: ns8390rcv(unit) ! 1142: int unit; ! 1143: { ! 1144: register ns8390_softc_t *is = &ns8390_softc[unit]; ! 1145: register struct ifnet *ifp = &is->ds_if; ! 1146: caddr_t nic = is->nic; ! 1147: int packets = 0; ! 1148: struct ether_header eh; ! 1149: u_short mlen, len, bytes_in_mbuf, bytes; ! 1150: u_short remaining; ! 1151: int temp_cr; ! 1152: u_char *mb_p; ! 1153: int board_id = is->board_id; ! 1154: vm_offset_t hdwbase = ns8390info[unit]->address; ! 1155: spl_t s; ! 1156: ! 1157: /* calculation of pkt size */ ! 1158: int nic_overcount; /* NIC says 1 or 2 more than we need */ ! 1159: int pkt_size; /* calculated size of received data */ ! 1160: int wrap_size; /* size of data before wrapping it */ ! 1161: int header_nxtpkt_ptr; /* NIC's next pkt ptr in rcv header */ ! 1162: int low_byte_count; /* low byte count of read from rcv header */ ! 1163: int high_byte_count; /* calculated high byte count */ ! 1164: ! 1165: ! 1166: volatile char *sram_nxtpkt_ptr; /* mem location of next packet */ ! 1167: volatile char *sram_getdata_ptr; /* next location to be read */ ! 1168: #ifdef MACH_KERNEL ! 1169: ipc_kmsg_t new_kmsg; ! 1170: struct ether_header *ehp; ! 1171: struct packet_header *pkt; ! 1172: #else MACH_KERNEL ! 1173: struct mbuf *m, *tm; /* initial allocation of mem; temp */ ! 1174: #endif MACH_KERNEL ! 1175: ! 1176: ! 1177: #if MACH_TTD ! 1178: if (((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) && ! 1179: !kttd_active) { ! 1180: #else ! 1181: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { ! 1182: #endif /* MACH_TTD */ ! 1183: temp_cr = inb(nic+ds_cmd); /* get current CR value */ ! 1184: outb(nic+ds_cmd,((temp_cr & 0x3F)|DSCM_PG0|DSCM_STOP)); ! 1185: outb(nic+ds0_imr, 0); /* Interrupt Mask Register */ ! 1186: outb(nic+ds_cmd, temp_cr); ! 1187: return -1; ! 1188: } ! 1189: ! 1190: while(is->read_nxtpkt_ptr != ns8390get_CURR(unit)) { ! 1191: ! 1192: /* while there is a packet to read from the buffer */ ! 1193: ! 1194: if ((is->read_nxtpkt_ptr < is->pstart) || ! 1195: (is->read_nxtpkt_ptr >= is->pstop)) { ! 1196: ns8390hwrst(unit); ! 1197: return -1; ! 1198: } /* if next packet pointer is out of receive ring bounds */ ! 1199: ! 1200: #if MACH_TTD ! 1201: if (!kttd_active) ! 1202: #endif /* MACH_TTD */ ! 1203: { ! 1204: packets++; ! 1205: ns8390_cntrs[unit].rcv++; ! 1206: } ! 1207: ! 1208: sram_nxtpkt_ptr = (char *) (is->sram + (is->read_nxtpkt_ptr << 8)); ! 1209: ! 1210: /* get packet size and location of next packet */ ! 1211: header_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1); ! 1212: header_nxtpkt_ptr &= 0xFF; ! 1213: low_byte_count = *(sram_nxtpkt_ptr + 2); ! 1214: low_byte_count &= 0xFF; ! 1215: ! 1216: if ((low_byte_count + NIC_HEADER_SIZE) > NIC_PAGE_SIZE) ! 1217: nic_overcount = 2; ! 1218: else ! 1219: nic_overcount = 1; ! 1220: if (header_nxtpkt_ptr > is->read_nxtpkt_ptr) { ! 1221: wrap_size = 0; ! 1222: high_byte_count = header_nxtpkt_ptr - is->read_nxtpkt_ptr - ! 1223: nic_overcount; ! 1224: } else { ! 1225: wrap_size = (int) (is->pstop - is->read_nxtpkt_ptr - nic_overcount); ! 1226: high_byte_count = is->pstop - is->read_nxtpkt_ptr + ! 1227: header_nxtpkt_ptr - is->pstart - nic_overcount; ! 1228: } ! 1229: pkt_size = (high_byte_count << 8) | (low_byte_count & 0xFF); ! 1230: /* does not seem to include NIC_HEADER_SIZE */ ! 1231: if (!pkt_size) { ! 1232: printf("%s%d rcv(): zero length.\n", ! 1233: ns8390_softc[unit].card, unit); ! 1234: goto next_pkt; ! 1235: } ! 1236: len = pkt_size; ! 1237: ! 1238: sram_getdata_ptr = sram_nxtpkt_ptr + NIC_HEADER_SIZE; ! 1239: if (board_id & IFWD_SLOT_16BIT) { ! 1240: #if MACH_TTD ! 1241: if (!kttd_active) ! 1242: #endif /* MACH_TTD */ ! 1243: { s = splhi(); } ! 1244: ! 1245: en_16bit_access(hdwbase, board_id); ! 1246: bcopy16 (sram_getdata_ptr, ! 1247: &eh, ! 1248: sizeof(struct ether_header)); ! 1249: dis_16bit_access (hdwbase, board_id); ! 1250: #if MACH_TTD ! 1251: if (!kttd_active) ! 1252: #endif /* MACH_TTD */ ! 1253: { splx(s); } ! 1254: ! 1255: } else { ! 1256: bcopy16 (sram_getdata_ptr, ! 1257: &eh, ! 1258: sizeof(struct ether_header)); ! 1259: } ! 1260: sram_getdata_ptr += sizeof(struct ether_header); ! 1261: len -= (sizeof(struct ether_header) + 4); /* crc size */ ! 1262: #ifdef MACH_KERNEL ! 1263: #if MACH_TTD ! 1264: if (kttd_active) { ! 1265: new_kmsg = (ipc_kmsg_t)ttd_request_msg; ! 1266: }else ! 1267: #endif /* MACH_TTD */ ! 1268: { ! 1269: new_kmsg = net_kmsg_get(); ! 1270: if (new_kmsg == IKM_NULL) { ! 1271: /* ! 1272: * Drop the packet. ! 1273: */ ! 1274: is->ds_if.if_rcvdrops++; ! 1275: /* ! 1276: * not only do we want to return, we need to drop ! 1277: * the packet on the floor to clear the interrupt. ! 1278: */ ! 1279: ns8390lost_frame(unit); ! 1280: return;/* packets;*/ ! 1281: } ! 1282: } ! 1283: ! 1284: #if DEBUG_TTD ! 1285: dump_ether_header("ns8390wire",&eh); ! 1286: #endif /* DEBUG_TTD */ ! 1287: ! 1288: ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]); ! 1289: pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]); ! 1290: ! 1291: #if DEBUG_TTD ! 1292: printf("!ehp = 0x%x, pkt = 0x%x!",ehp, pkt); ! 1293: #endif /* DEBUG_TTD */ ! 1294: ! 1295: *ehp = eh; ! 1296: if (len > ! 1297: (wrap_size = (is->sram + (is->pstop << 8) - sram_getdata_ptr))) { ! 1298: /* if needs to wrap */ ! 1299: if (board_id & IFWD_SLOT_16BIT) { ! 1300: #if MACH_TTD ! 1301: if (!kttd_active) ! 1302: #endif /* MACH_TTD */ ! 1303: { s = splhi(); } ! 1304: ! 1305: en_16bit_access(hdwbase, board_id); ! 1306: bcopy16 (sram_getdata_ptr, (char *) (pkt + 1), ! 1307: wrap_size); ! 1308: dis_16bit_access (hdwbase, board_id); ! 1309: #if MACH_TTD ! 1310: if (!kttd_active) ! 1311: #endif /* MACH_TTD */ ! 1312: { splx(s); } ! 1313: } else { ! 1314: bcopy (sram_getdata_ptr, (char *) (pkt + 1), ! 1315: wrap_size); ! 1316: } ! 1317: sram_getdata_ptr = (volatile char *) ! 1318: (is->sram + (is->pstart << 8)); ! 1319: } else { /* normal getting data from buffer */ ! 1320: wrap_size = 0; ! 1321: } ! 1322: if (board_id & IFWD_SLOT_16BIT) { ! 1323: #if MACH_TTD ! 1324: if (!kttd_active) ! 1325: #endif /* MACH_TTD */ ! 1326: { s = splhi(); } ! 1327: en_16bit_access(hdwbase, board_id); ! 1328: bcopy16 (sram_getdata_ptr, ! 1329: (char *) (pkt + 1) + wrap_size, ! 1330: len - wrap_size); ! 1331: dis_16bit_access (hdwbase, board_id); ! 1332: #if MACH_TTD ! 1333: if (!kttd_active) ! 1334: #endif /* MACH_TTD */ ! 1335: { splx(s); } ! 1336: } else { ! 1337: bcopy (sram_getdata_ptr, ! 1338: (char *) (pkt + 1) + wrap_size, ! 1339: len - wrap_size); ! 1340: } ! 1341: ! 1342: pkt->type = ehp->ether_type; ! 1343: pkt->length = len + sizeof(struct packet_header); ! 1344: ! 1345: #if MACH_TTD ! 1346: /* ! 1347: * Don't want to call net_packet if we are polling ! 1348: * for a packet. ! 1349: */ ! 1350: if (!kttd_active) ! 1351: #endif /* MACH_TTD */ ! 1352: { ! 1353: /* ! 1354: * Hand the packet to the network module. ! 1355: */ ! 1356: net_packet(ifp, new_kmsg, pkt->length, ! 1357: ethernet_priority(new_kmsg)); ! 1358: } ! 1359: ! 1360: #else MACH_KERNEL ! 1361: #define NEW ! 1362: #ifdef NEW ! 1363: m = (struct mbuf *) 0; ! 1364: eh.ether_type = ntohs(eh.ether_type); ! 1365: MGET(m, M_DONTWAIT, MT_DATA); ! 1366: if (m == (struct mbuf *) 0) { ! 1367: printf("%s%d rcv(): Lost frame\n", ! 1368: ns8390_softc[unit].card, unit); ! 1369: ns8390lost_frame(unit); /* update NIC pointers and registers */ ! 1370: return packets; ! 1371: } ! 1372: m->m_next = (struct mbuf *) 0; ! 1373: tm = m; ! 1374: m->m_len = MLEN; ! 1375: if (len > 2 * MLEN - sizeof (struct ifnet **)) { ! 1376: MCLGET(m); ! 1377: } ! 1378: *(mtod(tm, struct ifnet **)) = ifp; ! 1379: mlen = sizeof (struct ifnet **); ! 1380: bytes_in_mbuf = m->m_len - sizeof(struct ifnet **); ! 1381: mb_p = mtod(tm, u_char *) + sizeof (struct ifnet **); ! 1382: bytes = min(bytes_in_mbuf, len); ! 1383: remaining = (int) (is->sram + (is->pstop << 8) - ! 1384: sram_getdata_ptr); ! 1385: bytes = min(bytes, remaining); ! 1386: do { ! 1387: if (board_id & IFWD_SLOT_16BIT) { ! 1388: s = splhi(); ! 1389: en_16bit_access(hdwbase, board_id); ! 1390: bcopy16 (sram_getdata_ptr, mb_p, bytes); ! 1391: dis_16bit_access (hdwbase, board_id); ! 1392: splx(s); ! 1393: } else { ! 1394: bcopy16 (sram_getdata_ptr, mb_p, bytes); ! 1395: } ! 1396: ! 1397: mlen += bytes; ! 1398: ! 1399: if (!(bytes_in_mbuf -= bytes)) { ! 1400: MGET(tm->m_next, M_DONTWAIT, MT_DATA); ! 1401: tm = tm->m_next; ! 1402: if (tm == (struct mbuf *)0) { ! 1403: printf("%s%d rcv(): No mbufs, lost frame\n", ! 1404: ns8390_softc[unit].card, unit); ! 1405: m_freem(m); /* free the mbuf chain */ ! 1406: ns8390lost_frame(unit); /* update NIC pointers and registers */ ! 1407: return; ! 1408: } ! 1409: mlen = 0; ! 1410: tm->m_len = MLEN; ! 1411: bytes_in_mbuf = MLEN; ! 1412: mb_p = mtod(tm, u_char *); ! 1413: } else ! 1414: mb_p += bytes; ! 1415: ! 1416: if (!(len -= bytes)) { ! 1417: tm->m_len = mlen; ! 1418: break; ! 1419: } else if (bytes == remaining) { ! 1420: sram_getdata_ptr = (volatile char *) (is->sram + ! 1421: (is->pstart << 8)); ! 1422: bytes = len; ! 1423: remaining = ETHERMTU; ! 1424: } else { ! 1425: sram_getdata_ptr += bytes; ! 1426: remaining -= bytes; ! 1427: } ! 1428: ! 1429: bytes = min(bytes_in_mbuf, len); ! 1430: bytes = min(bytes, remaining); ! 1431: } while(1); ! 1432: #else NEW ! 1433: m = (struct mbuf *) 0; ! 1434: eh.ether_type = ntohs(eh.ether_type); ! 1435: ! 1436: while ( len ) { ! 1437: if (m == (struct mbuf *) 0) { ! 1438: m = m_get(M_DONTWAIT, MT_DATA); ! 1439: if (m == (struct mbuf *) 0) { ! 1440: printf("%s%d rcv(): Lost frame\n", ! 1441: ns8390_softc[unit].card, unit); ! 1442: ns8390lost_frame(unit); /* update NIC pointers and registers */ ! 1443: return packets; ! 1444: } ! 1445: tm = m; ! 1446: tm->m_off = MMINOFF; ! 1447: ! 1448: ! 1449: /* ! 1450: * first mbuf in the packet must contain a pointer to the ! 1451: * ifnet structure. other mbufs that follow and make up ! 1452: * the packet do not need this pointer in the mbuf. ! 1453: * ! 1454: */ ! 1455: ! 1456: *(mtod(tm, struct ifnet **)) = ifp; ! 1457: tm->m_len = sizeof(struct ifnet **); ! 1458: ! 1459: /* end of first buffer of packet */ ! 1460: } else { ! 1461: tm->m_next = m_get(M_DONTWAIT, MT_DATA); ! 1462: tm = tm->m_next; ! 1463: if (tm == (struct mbuf *) 0) { ! 1464: printf("%s%d rcv(): No mbufs, lost frame\n", ! 1465: ns8390_softc[unit].card, unit); ! 1466: m_freem(m); /* free the mbuf chain */ ! 1467: ns8390lost_frame(unit); /* update NIC pointers and registers */ ! 1468: return packets; ! 1469: } ! 1470: tm->m_off = MMINOFF; ! 1471: tm->m_len = 0; ! 1472: } ! 1473: ! 1474: tlen = MIN( MLEN - tm->m_len, len); ! 1475: /* size of mbuf so you know how much you can copy from board */ ! 1476: tm->m_next = (struct mbuf *) 0; ! 1477: if (sram_getdata_ptr + tlen >= ! 1478: (volatile char *) (is->sram + (is->pstop << 8))) { ! 1479: /* if needs to wrap */ ! 1480: wrap_size = (int) (is->sram + (is->pstop << 8) - ! 1481: sram_getdata_ptr); ! 1482: if (board_id & IFWD_SLOT_16BIT) { ! 1483: s = splhi(); ! 1484: en_16bit_access(hdwbase, board_id); ! 1485: bcopy16 (sram_getdata_ptr, ! 1486: mtod(tm, char*) + tm->m_len, ! 1487: wrap_size); ! 1488: dis_16bit_access (hdwbase, board_id); ! 1489: splx(s); ! 1490: } else { ! 1491: bcopy16 (sram_getdata_ptr, ! 1492: mtod(tm, char*) + tm->m_len, ! 1493: wrap_size); ! 1494: } ! 1495: tm->m_len += wrap_size; ! 1496: len -= wrap_size; ! 1497: ! 1498: sram_getdata_ptr = (volatile char *) (is->sram + ! 1499: (is->pstart << 8)); ! 1500: } else { /* normal getting data from buffer */ ! 1501: if (board_id & IFWD_SLOT_16BIT) { ! 1502: s = splhi(); ! 1503: en_16bit_access(hdwbase, board_id); ! 1504: bcopy16 (sram_getdata_ptr, ! 1505: mtod(tm, char*) + tm->m_len, ! 1506: tlen); ! 1507: dis_16bit_access (hdwbase, board_id); ! 1508: splx(s); ! 1509: } else { ! 1510: bcopy16 (sram_getdata_ptr, ! 1511: mtod(tm, char*) + tm->m_len, ! 1512: tlen); ! 1513: } ! 1514: sram_getdata_ptr += tlen; ! 1515: tm->m_len += tlen; ! 1516: len -= tlen; ! 1517: ! 1518: } ! 1519: } ! 1520: ! 1521: #endif NEW ! 1522: if (!ns8390send_packet_up(m, &eh, is)) ! 1523: m_freem(m); ! 1524: #ifdef IF_CNTRS ! 1525: ns_ein[log_2(pkt_size)]++; ! 1526: if (pkt_size < 128) ns_lin[(pkt_size)>>3]++; ! 1527: ! 1528: if (eh.ether_type == ETHERTYPE_ARP) { ! 1529: ns_arp++; ! 1530: if (ns_narp) { ! 1531: ns_ein[log_2(pkt_size)]--; ! 1532: if (pkt_size < 128) ns_lin[(pkt_size)>>3]--; ! 1533: } ! 1534: } ! 1535: #endif IF_CNTRS ! 1536: #endif MACH_KERNEL ! 1537: ! 1538: next_pkt: ! 1539: is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1); ! 1540: is->read_nxtpkt_ptr &= 0xFF; ! 1541: ! 1542: #if MACH_TTD ! 1543: if (!kttd_active) ! 1544: #endif /* MACH_TTD */ ! 1545: { ! 1546: temp_cr = inb(nic+ds_cmd); ! 1547: outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); ! 1548: } ! 1549: ! 1550: if (is->read_nxtpkt_ptr == ns8390get_CURR(unit)) ! 1551: if (is->read_nxtpkt_ptr == is->pstart) ! 1552: outb(nic+ds0_bndy, is->pstop - 1); ! 1553: else ! 1554: outb(nic+ds0_bndy, is->read_nxtpkt_ptr - 1); ! 1555: else ! 1556: outb(nic+ds0_bndy, is->read_nxtpkt_ptr); ! 1557: ! 1558: #if MACH_TTD ! 1559: if (!kttd_active) ! 1560: #endif /* MACH_TTD */ ! 1561: { outb(nic+ds_cmd, temp_cr); } ! 1562: ! 1563: #if MACH_TTD ! 1564: /* ! 1565: * Hand the packet back to the TTD server, if active. ! 1566: */ ! 1567: if (kttd_active && pkt_size) ! 1568: return 1; ! 1569: #endif /* MACH_TTD */ ! 1570: ! 1571: ! 1572: } ! 1573: return packets; ! 1574: ! 1575: } ! 1576: ! 1577: #ifdef MACH_KERNEL ! 1578: #if MACH_TTD ! 1579: /* ! 1580: * Polling routines for the TTD debugger. ! 1581: */ ! 1582: int ns8390poll_receive(unit) ! 1583: int unit; ! 1584: { ! 1585: int s; ! 1586: int orig_cr; ! 1587: int orig_imr; ! 1588: int isr_status; ! 1589: int pkts; ! 1590: ! 1591: ttd_poll_loop = TRUE; ! 1592: ! 1593: ! 1594: /* ! 1595: * Should already in at splhigh. Is this necessary? XXX ! 1596: */ ! 1597: s = splhigh(); ! 1598: ! 1599: #if 0 ! 1600: if (kttd_debug) ! 1601: printf("ns8390poll_receive: beginning polling loop\n"); ! 1602: #endif /* DEBUG_TTD */ ! 1603: ! 1604: /* ! 1605: * Loop until packet arrives. ! 1606: */ ! 1607: while(ttd_poll_loop) { ! 1608: ! 1609: /* ! 1610: * Call intr routine ! 1611: */ ! 1612: ! 1613: ns8390intr(unit); ! 1614: } ! 1615: ! 1616: #if 0 ! 1617: if (kttd_debug) ! 1618: printf("ns8390poll_receive: got packet exiting loop\n"); ! 1619: #endif /* DEBUG_TTD */ ! 1620: ! 1621: splx(s); ! 1622: } ! 1623: ! 1624: int ns8390transmit_ttd(unit, packet, len) ! 1625: int unit; ! 1626: char * packet; ! 1627: int len; ! 1628: { ! 1629: ns8390_softc_t *is = &ns8390_softc[unit]; ! 1630: caddr_t nic = is->nic; ! 1631: u_short count = 0; /* amount of data already copied */ ! 1632: volatile char *sram_write_pkt; ! 1633: int board_id = is->board_id; ! 1634: caddr_t hdwbase = ns8390info[unit]->address; ! 1635: int s; ! 1636: int orig_cr; ! 1637: int orig_imr; ! 1638: int isr_status; ! 1639: boolean_t loop = TRUE; ! 1640: ! 1641: #if 0 ! 1642: dump_ipudpbootp("Beg of xmit",packet); ! 1643: #endif ! 1644: ! 1645: s = splhigh(); ! 1646: ! 1647: /* begining of physical address of transmition buffer */ ! 1648: ! 1649: sram_write_pkt = is->sram + is->tpsr * 0x100; ! 1650: ! 1651: count = len; ! 1652: if (board_id & IFWD_SLOT_16BIT) { ! 1653: en_16bit_access(hdwbase, board_id); ! 1654: bcopy16 (packet, sram_write_pkt, count); ! 1655: dis_16bit_access (hdwbase, board_id); ! 1656: } else { ! 1657: bcopy (packet, sram_write_pkt, count); ! 1658: } ! 1659: ! 1660: while (count < ETHERMIN+sizeof(struct ether_header)) { ! 1661: *(sram_write_pkt + count) = 0; ! 1662: count++; ! 1663: } ! 1664: outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0); /* select page 0 */ ! 1665: outb(nic+ds0_tpsr, is->tpsr); /* xmt page start at 0 of RAM */ ! 1666: outb(nic+ds0_tbcr1, count >> 8); /* upper byte of count */ ! 1667: outb(nic+ds0_tbcr0, count & 0xFF); /* lower byte of count */ ! 1668: outb(nic+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START); /* start transmission */ ! 1669: ! 1670: ns8390intr(unit); ! 1671: ! 1672: splx(s); ! 1673: } ! 1674: #endif /* MACH_TTD */ ! 1675: #endif /* MACH_KERNEL */ ! 1676: ! 1677: #ifdef MACH_KERNEL ! 1678: #else MACH_KERNEL ! 1679: /* ! 1680: * Send a packet composed of an mbuf chain to the higher levels ! 1681: * ! 1682: */ ! 1683: ns8390send_packet_up(m, eh, is) ! 1684: struct mbuf *m; ! 1685: struct ether_header *eh; ! 1686: ns8390_softc_t *is; ! 1687: { ! 1688: register struct ifqueue *inq; ! 1689: spl_t opri; ! 1690: ! 1691: switch (eh->ether_type) { ! 1692: #ifdef INET ! 1693: case ETHERTYPE_IP: ! 1694: schednetisr(NETISR_IP); ! 1695: inq = &ipintrq; ! 1696: break; ! 1697: case ETHERTYPE_ARP: ! 1698: arpinput(&is->ns8390_ac, m); ! 1699: return(TRUE); ! 1700: #endif ! 1701: #ifdef NS ! 1702: case ETHERTYPE_NS: ! 1703: schednetisr(NETISR_NS); ! 1704: inq = &nsintrq; ! 1705: break; ! 1706: #endif ! 1707: default: ! 1708: return(FALSE); ! 1709: } ! 1710: opri = SPLNET(); ! 1711: if (IF_QFULL(inq)) { ! 1712: IF_DROP(inq); ! 1713: splx(opri); ! 1714: return(FALSE); ! 1715: } ! 1716: IF_ENQUEUE(inq, m); ! 1717: splx(opri); ! 1718: return(TRUE); ! 1719: } ! 1720: #endif MACH_KERNEL ! 1721: ! 1722: /* ! 1723: * ns8390lost_frame: ! 1724: * this routine called by ns8390read after memory for mbufs could not be ! 1725: * allocated. It sets the boundary pointers and registers to the next ! 1726: * packet location. ! 1727: */ ! 1728: ! 1729: ns8390lost_frame(unit) ! 1730: int unit; ! 1731: { ! 1732: ns8390_softc_t *is = &ns8390_softc[unit]; ! 1733: caddr_t nic = is->nic; ! 1734: volatile char *sram_nxtpkt_ptr; ! 1735: int temp_cr; ! 1736: ! 1737: ! 1738: ! 1739: sram_nxtpkt_ptr = (volatile char *) (is->sram + ! 1740: (is->read_nxtpkt_ptr << 8)); ! 1741: ! 1742: is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1); ! 1743: is->read_nxtpkt_ptr &= 0xFF; ! 1744: ! 1745: temp_cr = inb(nic+ds_cmd); ! 1746: outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0); ! 1747: ! 1748: /* update boundary register */ ! 1749: if (is->read_nxtpkt_ptr == ns8390get_CURR(unit)) ! 1750: if (is->read_nxtpkt_ptr == is->pstart) ! 1751: outb(nic+ds0_bndy, is->pstop - 1); ! 1752: else ! 1753: outb(nic+ds0_bndy, is->read_nxtpkt_ptr - 1); ! 1754: else ! 1755: outb(nic+ds0_bndy, is->read_nxtpkt_ptr); ! 1756: ! 1757: outb(nic+ds_cmd, temp_cr); ! 1758: ! 1759: return; ! 1760: } ! 1761: ! 1762: /* ! 1763: * ns8390get_CURR(): ! 1764: * ! 1765: * Returns the value of the register CURR, which points to the next ! 1766: * available space for NIC to receive from network unto receive ring. ! 1767: * ! 1768: */ ! 1769: ! 1770: int ! 1771: ns8390get_CURR(unit) ! 1772: int unit; ! 1773: { ! 1774: caddr_t nic = ns8390_softc[unit].nic; ! 1775: int temp_cr; ! 1776: int ret_val; ! 1777: spl_t s; ! 1778: ! 1779: s = SPLNET(); ! 1780: ! 1781: temp_cr = inb(nic+ds_cmd); /* get current CR value */ ! 1782: outb(nic+ds_cmd, ((temp_cr & 0x3F) | DSCM_PG1)); /* select page 1 registers */ ! 1783: ret_val = inb(nic+ds1_curr); /* read CURR value */ ! 1784: outb(nic+ds_cmd, temp_cr); ! 1785: splx(s); ! 1786: return (ret_val & 0xFF); ! 1787: } ! 1788: ! 1789: /* ! 1790: * ns8390xmt: ! 1791: * ! 1792: * This routine fills in the appropriate registers and memory ! 1793: * locations on the ns8390 board and starts the board off on ! 1794: * the transmit. ! 1795: * ! 1796: * input : board number of interest, and a pointer to the mbuf ! 1797: * output : board memory and registers are set for xfer and attention ! 1798: * ! 1799: */ ! 1800: ! 1801: ns8390xmt(unit, m) ! 1802: int unit; ! 1803: #ifdef MACH_KERNEL ! 1804: io_req_t m; ! 1805: #else MACH_KERNEL ! 1806: struct mbuf *m; ! 1807: #endif MACH_KERNEL ! 1808: { ! 1809: ns8390_softc_t *is = &ns8390_softc[unit]; ! 1810: caddr_t nic = is->nic; ! 1811: struct ether_header *eh; ! 1812: int i; ! 1813: int opri; ! 1814: u_short count = 0; /* amount of data already copied */ ! 1815: volatile char *sram_write_pkt; ! 1816: int board_id = is->board_id; ! 1817: vm_offset_t hdwbase = ns8390info[unit]->address; ! 1818: spl_t s; ! 1819: ! 1820: #ifdef MACH_KERNEL ! 1821: #else MACH_KERNEL ! 1822: register struct mbuf *tm_p; ! 1823: #endif MACH_KERNEL ! 1824: /* begining of physical address of transmition buffer */ ! 1825: ! 1826: sram_write_pkt = is->sram + is->tpsr * 0x100; ! 1827: ! 1828: #ifdef MACH_KERNEL ! 1829: count = m->io_count; ! 1830: if (board_id & IFWD_SLOT_16BIT) { ! 1831: s = splhi(); ! 1832: en_16bit_access(hdwbase, board_id); ! 1833: bcopy16 (m->io_data, sram_write_pkt, count); ! 1834: dis_16bit_access (hdwbase, board_id); ! 1835: splx(s); ! 1836: } else { ! 1837: bcopy (m->io_data, sram_write_pkt, count); ! 1838: } ! 1839: #else MACH_KERNEL ! 1840: for(tm_p = m; tm_p != (struct mbuf *)0; tm_p = tm_p->m_next) { ! 1841: if (count + tm_p->m_len > ETHERMTU + sizeof (struct ether_header)) ! 1842: break; ! 1843: if (tm_p->m_len == 0) ! 1844: continue; ! 1845: if (board_id & IFWD_SLOT_16BIT) { ! 1846: s = splhi(); ! 1847: en_16bit_access(hdwbase, board_id); ! 1848: bcopy16 (mtod(tm_p, caddr_t), ! 1849: sram_write_pkt + count, ! 1850: tm_p->m_len); ! 1851: dis_16bit_access (hdwbase, board_id); ! 1852: splx(s); ! 1853: } else { ! 1854: bcopy16 (mtod(tm_p, caddr_t), ! 1855: sram_write_pkt + count, ! 1856: tm_p->m_len); ! 1857: } ! 1858: count += tm_p->m_len; ! 1859: } ! 1860: #ifdef IF_CNTRS ! 1861: ns_eout[log_2(count+4/*crc*/)]++; ! 1862: if (count < 128) ns_lout[(count+4/*crc*/)>>3]++; ! 1863: #endif IF_CNTRS ! 1864: #endif MACH_KERNEL ! 1865: while (count < ETHERMIN+sizeof(struct ether_header)) { ! 1866: *(sram_write_pkt + count) = 0; ! 1867: count++; ! 1868: } ! 1869: ! 1870: /* select page 0 */ ! 1871: outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0); ! 1872: outb(nic+ds0_tpsr, is->tpsr); /* xmt page start at 0 of RAM */ ! 1873: outb(nic+ds0_tbcr1, count >> 8); /* upper byte of count */ ! 1874: outb(nic+ds0_tbcr0, count & 0xFF); /* lower byte of count */ ! 1875: /* start transmission */ ! 1876: outb(nic+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START); ! 1877: ! 1878: #ifdef MACH_KERNEL ! 1879: iodone(m); ! 1880: m=0; ! 1881: #else MACH_KERNEL ! 1882: /* If this is a broadcast packet, loop it back to rcv. */ ! 1883: eh = mtod( m, struct ether_header *); ! 1884: for (i=0; ((i < 6) && (eh->ether_dhost[i] == 0xff)); i++) ; ! 1885: if (i == 6) { ! 1886: if (!ns8390send_packet_up(m, eh, is)) ! 1887: m_freem(m); ! 1888: } else ! 1889: m_freem(m); ! 1890: #endif MACH_KERNEL ! 1891: return; ! 1892: } ! 1893: ! 1894: config_nic(unit) ! 1895: int unit; ! 1896: { ! 1897: ns8390_softc_t *is = &ns8390_softc[unit]; ! 1898: caddr_t nic = is->nic; ! 1899: int i; ! 1900: int temp; ! 1901: int count = 0; ! 1902: spl_t s; ! 1903: ! 1904: /* soft reset and page 0 */ ! 1905: outb (nic+ds_cmd, DSCM_PG0|DSCM_NODMA|DSCM_STOP); ! 1906: ! 1907: while ((!(inb (nic + ds0_isr) & DSIS_RESET)) && (count < 10000)) ! 1908: count++; ! 1909: if (count == 10000) { ! 1910: printf("%s%d: config_nic(): would not reset.\n", ! 1911: ns8390_softc[unit].card, unit); ! 1912: } ! 1913: ! 1914: /* fifo depth | not loopback */ ! 1915: temp = ((is->fifo_depth & 0x0c) << 3) | DSDC_BMS; ! 1916: ! 1917: /* word xfer select (16 bit cards ) */ ! 1918: if (is->board_id & IFWD_SLOT_16BIT) ! 1919: temp |= DSDC_WTS; ! 1920: ! 1921: outb (nic+ds0_dcr, temp); ! 1922: outb (nic+ds0_tcr, 0); ! 1923: outb (nic+ds0_rcr, DSRC_MON); /* receive configuration register */ ! 1924: /* recieve ring starts 2k into RAM */ ! 1925: outb (nic+ds0_pstart, is->pstart); ! 1926: /* stop at last RAM buffer rcv location */ ! 1927: outb (nic+ds0_pstop, is->pstop); ! 1928: ! 1929: /* boundary pointer for page 0 */ ! 1930: outb (nic+ds0_bndy, is->pstart); ! 1931: s = SPLNET(); ! 1932: ! 1933: /* maintain rst | sel page 1 */ ! 1934: outb (nic+ds_cmd, DSCM_PG1|DSCM_NODMA|DSCM_STOP); ! 1935: ! 1936: /* internal next packet pointer */ ! 1937: is->read_nxtpkt_ptr = is->pstart + 1; ! 1938: ! 1939: outb (nic+ds1_curr, is->read_nxtpkt_ptr); /* Current page register */ ! 1940: for(i=0; i<ETHER_ADDR_SIZE; i++) ! 1941: outb (nic+ds1_par0+i, is->address[i]); ! 1942: for(i=0; i<8; i++) ! 1943: outb (nic+ds1_mar0+i, 0); ! 1944: ! 1945: outb (nic+ds_cmd, DSCM_PG0|DSCM_STOP|DSCM_NODMA); ! 1946: splx(s); ! 1947: outb (nic+ds0_isr, 0xff); /* clear all interrupt status bits */ ! 1948: outb (nic+ds0_imr, imr_hold); /* Enable interrupts */ ! 1949: outb (nic+ds0_rbcr0, 0); /* clear remote byte count */ ! 1950: outb (nic+ds0_rbcr1, 0); ! 1951: ! 1952: /* start NIC | select page 0 */ ! 1953: outb (nic+ds_cmd, DSCM_PG0|DSCM_START|DSCM_NODMA); ! 1954: ! 1955: outb (nic+ds0_rcr, DSRC_AB); /* receive configuration register */ ! 1956: ! 1957: return TRUE; ! 1958: } ! 1959: ! 1960: /* ! 1961: * config_ns8390: ! 1962: * ! 1963: * This routine does a standard config of a wd8003 family board, with ! 1964: * the proper modifications to different boards within this family. ! 1965: * ! 1966: */ ! 1967: config_wd8003(unit) ! 1968: int unit; ! 1969: { ! 1970: ns8390_softc_t *is = &ns8390_softc[unit]; ! 1971: vm_offset_t hdwbase = ns8390info[unit]->address; ! 1972: int i; ! 1973: int RAMsize; ! 1974: volatile char *RAMbase; ! 1975: int addr_temp; ! 1976: ! 1977: is->tpsr = 0; /* transmit page start hold */ ! 1978: is->pstart = 0x06; /* receive page start hold */ ! 1979: is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */ ! 1980: is->fifo_depth = 0x08; /* NIC fifo threshold */ ! 1981: switch (is->board_id & IFWD_RAM_SIZE_MASK) { ! 1982: case IFWD_RAM_SIZE_8K: ! 1983: RAMsize = 0x2000; break; ! 1984: case IFWD_RAM_SIZE_16K: ! 1985: RAMsize = 0x4000; break; ! 1986: case IFWD_RAM_SIZE_32K: ! 1987: RAMsize = 0x8000; break; ! 1988: case IFWD_RAM_SIZE_64K: ! 1989: RAMsize = 0x10000; break; ! 1990: default: ! 1991: RAMsize = 0x2000; break; ! 1992: } ! 1993: is->pstop = (((int)RAMsize >> 8) & 0x0ff); /* rcv page stop hold */ ! 1994: RAMbase = (volatile char *)ns8390info[unit]->phys_address; ! 1995: addr_temp = ((int)(RAMbase) >> 13) & 0x3f; /* convert to be written to MSR */ ! 1996: outb(hdwbase+IFWD_MSR, addr_temp | IFWD_MENB); /* initialize MSR */ ! 1997: /* enable 16 bit access from lan controller */ ! 1998: if (is->board_id & IFWD_SLOT_16BIT) { ! 1999: if (is->board_id & IFWD_INTERFACE_CHIP) { ! 2000: outb(hdwbase+IFWD_REG_5, ! 2001: (inb(hdwbase + IFWD_REG_5) & IFWD_REG5_MEM_MASK) | ! 2002: IFWD_LAN16ENB); ! 2003: } else { ! 2004: outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19)); ! 2005: } ! 2006: } ! 2007: /* ! 2008: outb(hdwbase+LAAR, LAN16ENB | LA19| MEM16ENB | SOFTINT); ! 2009: */ ! 2010: ! 2011: return TRUE; ! 2012: } ! 2013: ! 2014: /* ! 2015: * config_ns8390: ! 2016: * ! 2017: * This routine does a standard config of a 3 com etherlink II board. ! 2018: * ! 2019: */ ! 2020: int ! 2021: config_3c503(unit) ! 2022: int unit; ! 2023: { ! 2024: ns8390_softc_t *is = &ns8390_softc[unit]; ! 2025: struct bus_device *dev = ns8390info[unit]; ! 2026: vm_offset_t hdwbase = dev->address; ! 2027: int RAMsize = dev->am; ! 2028: int i; ! 2029: ! 2030: is->tpsr = 0x20; /* transmit page start hold */ ! 2031: is->sram = (char *)phystokv(dev->phys_address) - is->tpsr * 0x100; ! 2032: /* When NIC says page 20, this means go to ! 2033: the beginning of the sram range */ ! 2034: is->pstart = 0x26; /* receive page start hold */ ! 2035: is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */ ! 2036: is->fifo_depth = 0x08; /* NIC fifo threshold */ ! 2037: is->pstop = is->tpsr + ((RAMsize >> 8) & 0x0ff); /* rcv page stop hold */ ! 2038: ! 2039: outb(hdwbase+CTLR, CTLR_RST|CTLR_THIN); ! 2040: outb(hdwbase+CTLR, CTLR_THIN); ! 2041: outb(hdwbase+CTLR, CTLR_STA_ADDR|CTLR_THIN); ! 2042: for (i = 0; i < 6; i++) ! 2043: is->address[i] = inb(hdwbase+i); ! 2044: outb(hdwbase+CTLR, elii_bnc[is->board_id]?CTLR_THIN:CTLR_THICK); ! 2045: outb(hdwbase+PSTR, is->pstart); ! 2046: outb(hdwbase+PSPR, is->pstop); ! 2047: outb(hdwbase+IDCFR, IDCFR_IRQ2 << (elii_irq[is->board_id] - 2)); ! 2048: outb(hdwbase+GACFR, GACFR_TCM|GACFR_8K); ! 2049: /* BCFR & PCRFR ro */ ! 2050: /* STREG ro & dma */ ! 2051: outb(hdwbase+DQTR, 0); ! 2052: outb(hdwbase+DAMSB, 0); ! 2053: outb(hdwbase+DALSB, 0); ! 2054: outb(hdwbase+VPTR2, 0); ! 2055: outb(hdwbase+VPTR1, 0); ! 2056: outb(hdwbase+VPTR0, 0); ! 2057: outb(hdwbase+RFMSB, 0); ! 2058: outb(hdwbase+RFLSB, 0); ! 2059: return TRUE; ! 2060: } ! 2061: ! 2062: /* ! 2063: * ns8390intoff: ! 2064: * ! 2065: * This function turns interrupts off for the ns8390 board indicated. ! 2066: * ! 2067: */ ! 2068: void ! 2069: ns8390intoff(unit) ! 2070: int unit; ! 2071: { ! 2072: caddr_t nic = ns8390_softc[unit].nic; ! 2073: int temp_cr = inb(nic+ds_cmd); /* get current CR value */ ! 2074: ! 2075: outb(nic+ds_cmd,((temp_cr & 0x3F)|DSCM_PG0|DSCM_STOP)); ! 2076: outb(nic+ds0_imr, 0); /* Interrupt Mask Register */ ! 2077: outb(nic+ds_cmd, temp_cr|DSCM_STOP); ! 2078: ! 2079: } ! 2080: ! 2081: ! 2082: /* ! 2083: * wd80xxget_board_id: ! 2084: * ! 2085: * determine which board is being used. ! 2086: * Currently supports: ! 2087: * wd8003E (tested) ! 2088: * wd8003EBT ! 2089: * wd8003EP (tested) ! 2090: * wd8013EP (tested) ! 2091: * ! 2092: */ ! 2093: wd80xxget_board_id(dev) ! 2094: struct bus_device *dev; ! 2095: { ! 2096: vm_offset_t hdwbase = dev->address; ! 2097: long unit = dev->unit; ! 2098: long board_id = 0; ! 2099: int reg_temp; ! 2100: int rev_num; /* revision number */ ! 2101: int ram_flag; ! 2102: int intr_temp; ! 2103: int i; ! 2104: boolean_t register_aliasing; ! 2105: ! 2106: rev_num = (inb(hdwbase + IFWD_BOARD_ID) & IFWD_BOARD_REV_MASK) >> 1; ! 2107: printf("%s%d: ", ns8390_softc[unit].card, unit); ! 2108: ! 2109: if (rev_num == 0) { ! 2110: printf("rev 0x00\n"); ! 2111: /* It must be 8000 board */ ! 2112: return 0; ! 2113: } ! 2114: ! 2115: /* Check if register aliasing is true, that is reading from register ! 2116: offsets 0-7 will return the contents of register offsets 8-f */ ! 2117: ! 2118: register_aliasing = TRUE; ! 2119: for (i = 1; i < 5; i++) { ! 2120: if (inb(hdwbase + IFWD_REG_0 + i) != ! 2121: inb(hdwbase + IFWD_LAR_0 + i)) ! 2122: register_aliasing = FALSE; ! 2123: } ! 2124: if (inb(hdwbase + IFWD_REG_7) != inb(hdwbase + IFWD_CHKSUM)) ! 2125: register_aliasing = FALSE; ! 2126: ! 2127: ! 2128: if (register_aliasing == FALSE) { ! 2129: /* Check if board has interface chip */ ! 2130: ! 2131: reg_temp = inb(hdwbase + IFWD_REG_7); /* save old */ ! 2132: outb(hdwbase + IFWD_REG_7, 0x35); /* write value */ ! 2133: inb(hdwbase + IFWD_REG_0); /* dummy read */ ! 2134: if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x35) { ! 2135: outb(hdwbase + IFWD_REG_7, 0x3a);/* Try another value*/ ! 2136: inb(hdwbase + IFWD_REG_0); /* dummy read */ ! 2137: if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x3a) { ! 2138: board_id |= IFWD_INTERFACE_CHIP; ! 2139: outb(hdwbase + IFWD_REG_7, reg_temp); ! 2140: /* restore old value */ ! 2141: } ! 2142: } ! 2143: ! 2144: /* Check if board is 16 bit by testing if bit zero in ! 2145: register 1 is unchangeable by software. If so then ! 2146: card has 16 bit capability */ ! 2147: reg_temp = inb(hdwbase + IFWD_REG_1); ! 2148: outb(hdwbase + IFWD_REG_1, reg_temp ^ IFWD_16BIT); ! 2149: inb(hdwbase + IFWD_REG_0); /* dummy read */ ! 2150: if ((inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) == ! 2151: (reg_temp & IFWD_16BIT)) { /* Is bit unchanged */ ! 2152: board_id |= IFWD_BOARD_16BIT; /* Yes == 16 bit */ ! 2153: reg_temp &= 0xfe; /* For 16 bit board ! 2154: always reset bit 0 */ ! 2155: } ! 2156: outb(hdwbase + IFWD_REG_1, reg_temp); /* write value back */ ! 2157: ! 2158: /* Test if 16 bit card is in 16 bit slot by reading bit zero in ! 2159: register 1. */ ! 2160: if (board_id & IFWD_BOARD_16BIT) { ! 2161: if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) { ! 2162: board_id |= IFWD_SLOT_16BIT; ! 2163: } ! 2164: } ! 2165: } ! 2166: ! 2167: /* Get media type */ ! 2168: ! 2169: if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEDIA_TYPE) { ! 2170: board_id |= IFWD_ETHERNET_MEDIA; ! 2171: } else if (rev_num == 1) { ! 2172: board_id |= IFWD_STARLAN_MEDIA; ! 2173: } else { ! 2174: board_id |= IFWD_TWISTED_PAIR_MEDIA; ! 2175: } ! 2176: ! 2177: if (rev_num == 2) { ! 2178: if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_SOFT_CONFIG) { ! 2179: if ((board_id & IFWD_STATIC_ID_MASK) == WD8003EB || ! 2180: (board_id & IFWD_STATIC_ID_MASK) == WD8003W) { ! 2181: board_id |= IFWD_ALTERNATE_IRQ_BIT; ! 2182: } ! 2183: } ! 2184: /* Check for memory size */ ! 2185: ! 2186: ram_flag = inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEMSIZE; ! 2187: ! 2188: switch (board_id & IFWD_STATIC_ID_MASK) { ! 2189: case WD8003E: /* same as WD8003EBT */ ! 2190: case WD8003S: /* same as WD8003SH */ ! 2191: case WD8003WT: ! 2192: case WD8003W: ! 2193: case WD8003EB: /* same as WD8003EP */ ! 2194: if (ram_flag) ! 2195: board_id |= IFWD_RAM_SIZE_32K; ! 2196: else ! 2197: board_id |= IFWD_RAM_SIZE_8K; ! 2198: break; ! 2199: case WD8003ETA: ! 2200: case WD8003STA: ! 2201: case WD8003EA: ! 2202: case WD8003SHA: ! 2203: case WD8003WA: ! 2204: board_id |= IFWD_RAM_SIZE_16K; ! 2205: break; ! 2206: case WD8013EBT: ! 2207: if (board_id & IFWD_SLOT_16BIT) { ! 2208: if (ram_flag) ! 2209: board_id |= IFWD_RAM_SIZE_64K; ! 2210: else ! 2211: board_id |= IFWD_RAM_SIZE_16K; ! 2212: } else { ! 2213: if (ram_flag) ! 2214: board_id |= IFWD_RAM_SIZE_32K; ! 2215: else ! 2216: board_id |= IFWD_RAM_SIZE_8K; ! 2217: } ! 2218: break; ! 2219: default: ! 2220: board_id |= IFWD_RAM_SIZE_UNKNOWN; ! 2221: break; ! 2222: } ! 2223: } else if (rev_num >= 3) { ! 2224: board_id &= (long) ~IFWD_MEDIA_MASK; /* remove media info */ ! 2225: board_id |= IFWD_INTERFACE_584_CHIP; ! 2226: board_id |= wd80xxget_eeprom_info(hdwbase, board_id); ! 2227: } else { ! 2228: /* Check for memory size */ ! 2229: if (board_id & IFWD_BOARD_16BIT) { ! 2230: if (board_id & IFWD_SLOT_16BIT) ! 2231: board_id |= IFWD_RAM_SIZE_16K; ! 2232: else ! 2233: board_id |= IFWD_RAM_SIZE_8K; ! 2234: } else if (board_id & IFWD_MICROCHANNEL) ! 2235: board_id |= IFWD_RAM_SIZE_16K; ! 2236: else if (board_id & IFWD_INTERFACE_CHIP) { ! 2237: if (inb(hdwbase + IFWD_REG_1) & IFWD_MEMSIZE) ! 2238: board_id |= IFWD_RAM_SIZE_32K; ! 2239: else ! 2240: board_id |= IFWD_RAM_SIZE_8K; ! 2241: } else ! 2242: board_id |= IFWD_RAM_SIZE_UNKNOWN; ! 2243: ! 2244: /* No support for 690 chip yet. It should be checked here */ ! 2245: } ! 2246: ! 2247: switch (board_id & IFWD_STATIC_ID_MASK) { ! 2248: case WD8003E: printf("WD8003E or WD8003EBT"); break; ! 2249: case WD8003S: printf("WD8003S or WD8003SH"); break; ! 2250: case WD8003WT: printf("WD8003WT"); break; ! 2251: case WD8003W: printf("WD8003W"); break; ! 2252: case WD8003EB: ! 2253: if (board_id & IFWD_INTERFACE_584_CHIP) ! 2254: printf("WD8003EP"); ! 2255: else ! 2256: printf("WD8003EB"); ! 2257: break; ! 2258: case WD8003EW: printf("WD8003EW"); break; ! 2259: case WD8003ETA: printf("WD8003ETA"); break; ! 2260: case WD8003STA: printf("WD8003STA"); break; ! 2261: case WD8003EA: printf("WD8003EA"); break; ! 2262: case WD8003SHA: printf("WD8003SHA"); break; ! 2263: case WD8003WA: printf("WD8003WA"); break; ! 2264: case WD8013EBT: printf("WD8013EBT"); break; ! 2265: case WD8013EB: ! 2266: if (board_id & IFWD_INTERFACE_584_CHIP) ! 2267: printf("WD8013EP"); ! 2268: else ! 2269: printf("WD8013EB"); ! 2270: break; ! 2271: case WD8013W: printf("WD8013W"); break; ! 2272: case WD8013EW: printf("WD8013EW"); break; ! 2273: default: printf("unknown"); break; ! 2274: } ! 2275: printf(" rev 0x%02x", rev_num); ! 2276: switch(board_id & IFWD_RAM_SIZE_RES_7) { ! 2277: case IFWD_RAM_SIZE_UNKNOWN: ! 2278: break; ! 2279: case IFWD_RAM_SIZE_8K: ! 2280: printf(" 8 kB ram"); ! 2281: break; ! 2282: case IFWD_RAM_SIZE_16K: ! 2283: printf(" 16 kB ram"); ! 2284: break; ! 2285: case IFWD_RAM_SIZE_32K: ! 2286: printf(" 32 kB ram"); ! 2287: break; ! 2288: case IFWD_RAM_SIZE_64K: ! 2289: printf(" 64 kB ram"); ! 2290: break; ! 2291: default: ! 2292: printf("wd: Internal error ram size value invalid %d\n", ! 2293: (board_id & IFWD_RAM_SIZE_RES_7)>>16); ! 2294: } ! 2295: ! 2296: if (board_id & IFWD_BOARD_16BIT) { ! 2297: if (board_id & IFWD_SLOT_16BIT) { ! 2298: printf(", in 16 bit slot"); ! 2299: } else { ! 2300: printf(", 16 bit board in 8 bit slot"); ! 2301: } ! 2302: } ! 2303: if (board_id & IFWD_INTERFACE_CHIP) { ! 2304: if (board_id & IFWD_INTERFACE_584_CHIP) { ! 2305: printf(", 584 chip"); ! 2306: } else { ! 2307: printf(", 583 chip"); ! 2308: } ! 2309: } ! 2310: if ((board_id & IFWD_INTERFACE_CHIP) == IFWD_INTERFACE_CHIP) { ! 2311: /* program the WD83C583 EEPROM registers */ ! 2312: int irr_temp, icr_temp; ! 2313: ! 2314: icr_temp = inb(hdwbase + IFWD_ICR); ! 2315: irr_temp = inb(hdwbase + IFWD_IRR); ! 2316: ! 2317: irr_temp &= ~(IFWD_IR0 | IFWD_IR1); ! 2318: irr_temp |= IFWD_IEN; ! 2319: ! 2320: icr_temp &= IFWD_WTS; ! 2321: ! 2322: if (!(board_id & IFWD_INTERFACE_584_CHIP)) { ! 2323: icr_temp |= IFWD_DMAE | IFWD_IOPE; ! 2324: if (ram_flag) ! 2325: icr_temp |= IFWD_MSZ; ! 2326: } ! 2327: ! 2328: if (board_id & IFWD_INTERFACE_584_CHIP) { ! 2329: switch(ns8390info[unit]->sysdep1) { ! 2330: case 10: ! 2331: icr_temp |= IFWD_DMAE; ! 2332: break; ! 2333: case 2: ! 2334: case 9: /* Same as 2 */ ! 2335: break; ! 2336: case 11: ! 2337: icr_temp |= IFWD_DMAE; ! 2338: /*FALLTHROUGH*/ ! 2339: case 3: ! 2340: irr_temp |= IFWD_IR0; ! 2341: break; ! 2342: case 15: ! 2343: icr_temp |= IFWD_DMAE; ! 2344: /*FALLTHROUGH*/ ! 2345: case 5: ! 2346: irr_temp |= IFWD_IR1; ! 2347: break; ! 2348: case 4: ! 2349: icr_temp |= IFWD_DMAE; ! 2350: /*FALLTHROUGH*/ ! 2351: case 7: ! 2352: irr_temp |= IFWD_IR0 | IFWD_IR1; ! 2353: break; ! 2354: default: ! 2355: printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n", ! 2356: ns8390_softc[unit].card, unit, ! 2357: ns8390info[unit]->sysdep1); ! 2358: break; ! 2359: } ! 2360: } else { ! 2361: switch(ns8390info[unit]->sysdep1) { ! 2362: /* attempt to set interrupt according to assigned pic */ ! 2363: case 2: ! 2364: case 9: /* Same as 2 */ ! 2365: break; ! 2366: case 3: ! 2367: irr_temp |= IFWD_IR0; ! 2368: break; ! 2369: case 4: ! 2370: irr_temp |= IFWD_IR1; ! 2371: break; ! 2372: case 5: ! 2373: irr_temp |= IFWD_IR1 | IFWD_AINT; ! 2374: break; ! 2375: case 7: ! 2376: irr_temp |= IFWD_IR0 | IFWD_IR1; ! 2377: break; ! 2378: default: ! 2379: printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n", ! 2380: ns8390_softc[unit].card, unit, ! 2381: ns8390info[unit]->sysdep1); ! 2382: } ! 2383: } ! 2384: outb(hdwbase + IFWD_IRR, irr_temp); ! 2385: outb(hdwbase + IFWD_ICR, icr_temp); ! 2386: } ! 2387: printf("\n"); ! 2388: return (board_id); ! 2389: } ! 2390: ! 2391: wd80xxget_eeprom_info(hdwbase, board_id) ! 2392: caddr_t hdwbase; ! 2393: long board_id; ! 2394: { ! 2395: unsigned long new_bits = 0; ! 2396: int reg_temp; ! 2397: ! 2398: outb(hdwbase + IFWD_REG_1, ! 2399: ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT)); ! 2400: outb(hdwbase + IFWD_REG_3, ! 2401: ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_ENGR_PAGE)); ! 2402: outb(hdwbase + IFWD_REG_1, ! 2403: ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | ! 2404: (IFWD_RLA | IFWD_OTHER_BIT))); ! 2405: while (inb(hdwbase + IFWD_REG_1) & IFWD_RECALL_DONE_MASK) ! 2406: ; ! 2407: ! 2408: reg_temp = inb(hdwbase + IFWD_EEPROM_1); ! 2409: switch (reg_temp & IFWD_EEPROM_BUS_TYPE_MASK) { ! 2410: case IFWD_EEPROM_BUS_TYPE_AT: ! 2411: if (wd_debug & 1) printf("wd: AT bus, "); ! 2412: break; ! 2413: case IFWD_EEPROM_BUS_TYPE_MCA: ! 2414: if (wd_debug & 1) printf("wd: MICROCHANNEL, "); ! 2415: new_bits |= IFWD_MICROCHANNEL; ! 2416: break; ! 2417: default: ! 2418: break; ! 2419: } ! 2420: switch (reg_temp & IFWD_EEPROM_BUS_SIZE_MASK) { ! 2421: case IFWD_EEPROM_BUS_SIZE_8BIT: ! 2422: if (wd_debug & 1) printf("8 bit bus size, "); ! 2423: break; ! 2424: case IFWD_EEPROM_BUS_SIZE_16BIT: ! 2425: if (wd_debug & 1) printf("16 bit bus size "); ! 2426: new_bits |= IFWD_BOARD_16BIT; ! 2427: if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) { ! 2428: new_bits |= IFWD_SLOT_16BIT; ! 2429: if (wd_debug & 1) ! 2430: printf("in 16 bit slot, "); ! 2431: } else { ! 2432: if (wd_debug & 1) ! 2433: printf("in 8 bit slot (why?), "); ! 2434: } ! 2435: break; ! 2436: default: ! 2437: if (wd_debug & 1) printf("bus size other than 8 or 16 bit, "); ! 2438: break; ! 2439: } ! 2440: reg_temp = inb(hdwbase + IFWD_EEPROM_0); ! 2441: switch (reg_temp & IFWD_EEPROM_MEDIA_MASK) { ! 2442: case IFWD_STARLAN_TYPE: ! 2443: if (wd_debug & 1) printf("Starlan media, "); ! 2444: new_bits |= IFWD_STARLAN_MEDIA; ! 2445: break; ! 2446: case IFWD_TP_TYPE: ! 2447: if (wd_debug & 1) printf("Twisted pair media, "); ! 2448: new_bits |= IFWD_TWISTED_PAIR_MEDIA; ! 2449: break; ! 2450: case IFWD_EW_TYPE: ! 2451: if (wd_debug & 1) printf("Ethernet and twisted pair media, "); ! 2452: new_bits |= IFWD_EW_MEDIA; ! 2453: break; ! 2454: case IFWD_ETHERNET_TYPE: /*FALLTHROUGH*/ ! 2455: default: ! 2456: if (wd_debug & 1) printf("ethernet media, "); ! 2457: new_bits |= IFWD_ETHERNET_MEDIA; ! 2458: break; ! 2459: } ! 2460: switch (reg_temp & IFWD_EEPROM_IRQ_MASK) { ! 2461: case IFWD_ALTERNATE_IRQ_1: ! 2462: if (wd_debug & 1) printf("Alternate irq 1\n"); ! 2463: new_bits |= IFWD_ALTERNATE_IRQ_BIT; ! 2464: break; ! 2465: default: ! 2466: if (wd_debug & 1) printf("\n"); ! 2467: break; ! 2468: } ! 2469: switch (reg_temp & IFWD_EEPROM_RAM_SIZE_MASK) { ! 2470: case IFWD_EEPROM_RAM_SIZE_8K: ! 2471: new_bits |= IFWD_RAM_SIZE_8K; ! 2472: break; ! 2473: case IFWD_EEPROM_RAM_SIZE_16K: ! 2474: if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT)) ! 2475: new_bits |= IFWD_RAM_SIZE_16K; ! 2476: else ! 2477: new_bits |= IFWD_RAM_SIZE_8K; ! 2478: break; ! 2479: case IFWD_EEPROM_RAM_SIZE_32K: ! 2480: new_bits |= IFWD_RAM_SIZE_32K; ! 2481: break; ! 2482: case IFWD_EEPROM_RAM_SIZE_64K: ! 2483: if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT)) ! 2484: new_bits |= IFWD_RAM_SIZE_64K; ! 2485: else ! 2486: new_bits |= IFWD_RAM_SIZE_32K; ! 2487: break; ! 2488: default: ! 2489: new_bits |= IFWD_RAM_SIZE_UNKNOWN; ! 2490: break; ! 2491: } ! 2492: outb(hdwbase + IFWD_REG_1, ! 2493: ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT)); ! 2494: outb(hdwbase + IFWD_REG_3, ! 2495: ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_EA6)); ! 2496: outb(hdwbase + IFWD_REG_1, ! 2497: ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_RLA)); ! 2498: return (new_bits); ! 2499: } ! 2500: ! 2501: wdpr(unit) ! 2502: { ! 2503: caddr_t nic = ns8390_softc[unit].nic; ! 2504: spl_t s; ! 2505: int temp_cr; ! 2506: ! 2507: s = SPLNET(); ! 2508: temp_cr = inb(nic+ds_cmd); /* get current CR value */ ! 2509: ! 2510: printf("CR %x, BNDRY %x, TSR %x, NCR %x, FIFO %x, ISR %x, RSR %x\n", ! 2511: inb(nic+0x0), inb(nic+0x3), inb(nic+0x4), inb(nic+0x5), ! 2512: inb(nic+0x6), inb(nic+0x7), inb(nic+0xc)); ! 2513: printf("CLD %x:%x, CRD %x:%x, FR %x, CRC %x, Miss %x\n", ! 2514: inb(nic+0x1), inb(nic+0x2), ! 2515: inb(nic+0x8), inb(nic+0x9), ! 2516: inb(nic+0xd), inb(nic+0xe), inb(nic+0xf)); ! 2517: ! 2518: ! 2519: outb(nic, (temp_cr&0x3f)|DSCM_PG1); /* page 1 CR value */ ! 2520: printf("PHYS %x:%x:%x:%x:%x CUR %x\n", ! 2521: inb(nic+0x1), inb(nic+0x2), inb(nic+0x3), ! 2522: inb(nic+0x4), inb(nic+0x5), inb(nic+0x6), ! 2523: inb(nic+0x7)); ! 2524: printf("MAR %x:%x:%x:%x:%x:%x:%x:%x\n", ! 2525: inb(nic+0x8), inb(nic+0x9), inb(nic+0xa), inb(nic+0xb), ! 2526: inb(nic+0xc), inb(nic+0xd), inb(nic+0xe), inb(nic+0xf)); ! 2527: outb(nic, temp_cr); /* restore current CR value */ ! 2528: splx(s); ! 2529: } ! 2530: ! 2531: ! 2532: /* ! 2533: This sets bit 7 (0 justified) of register offset 0x05. It will enable ! 2534: the host to access shared RAM 16 bits at a time. It will also maintain ! 2535: the LAN16BIT bit high in addition, this routine maintains address bit 19 ! 2536: (previous cards assumed this bit high...we must do it manually) ! 2537: ! 2538: note 1: this is a write only register ! 2539: note 2: this routine should be called only after interrupts are disabled ! 2540: and they should remain disabled until after the routine 'dis_16bit_access' ! 2541: is called ! 2542: */ ! 2543: ! 2544: en_16bit_access (hdwbase, board_id) ! 2545: caddr_t hdwbase; ! 2546: long board_id; ! 2547: { ! 2548: if (board_id & IFWD_INTERFACE_CHIP) ! 2549: outb(hdwbase+IFWD_REG_5, ! 2550: (inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK) ! 2551: | IFWD_MEM16ENB | IFWD_LAN16ENB); ! 2552: else ! 2553: outb(hdwbase+IFWD_REG_5, (IFWD_MEM16ENB | IFWD_LAN16ENB | ! 2554: IFWD_LA19)); ! 2555: } ! 2556: ! 2557: /* ! 2558: This resets bit 7 (0 justified) of register offset 0x05. It will disable ! 2559: the host from accessing shared RAM 16 bits at a time. It will maintain the ! 2560: LAN16BIT bit high in addition, this routine maintains address bit 19 ! 2561: (previous cards assumed this bit high...we must do it manually) ! 2562: ! 2563: note: this is a write only register ! 2564: */ ! 2565: ! 2566: dis_16bit_access (hdwbase, board_id) ! 2567: caddr_t hdwbase; ! 2568: long board_id; ! 2569: { ! 2570: if (board_id & IFWD_INTERFACE_CHIP) ! 2571: outb(hdwbase+IFWD_REG_5, ! 2572: ((inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK) | ! 2573: IFWD_LAN16ENB)); ! 2574: else ! 2575: outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19)); ! 2576: } ! 2577: ! 2578: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.