diff options
-rw-r--r-- | sys/dev/ed/if_ed.c | 284 | ||||
-rw-r--r-- | sys/dev/ed/if_edreg.h | 9 | ||||
-rw-r--r-- | sys/i386/isa/if_ed.c | 284 | ||||
-rw-r--r-- | sys/i386/isa/if_edreg.h | 9 |
4 files changed, 276 insertions, 310 deletions
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c index d42e923..85524fa 100644 --- a/sys/dev/ed/if_ed.c +++ b/sys/dev/ed/if_ed.c @@ -17,76 +17,39 @@ * Modification history * * $Log: if_ed.c,v $ - * Revision 1.19 93/08/02 02:57:53 davidg - * Fixed problem where some rev 8013EBT boards want the DCR_LS flag - * set in order to work in 16bit mode. + * Revision 1.25 93/09/08 23:04:25 davidg + * fixed problem where 3c503 boards lock up if the cable is + * disconnected at boot time. Added printing of irq number if + * the kernel config and board don't match * - * Revision 1.18 93/07/27 03:41:36 davidg - * removed unnecessary variable assignment in ed_reset() + * Revision 1.24 93/09/07 12:08:36 davidg + * ED_FLAGS_NO_DOUBLE_BUFFERING was being checked against wrong variable * - * Revision 1.17 93/07/26 18:40:57 davidg - * Added include of systm.h to pick up inlined min/max/bcmp if you have - * them in cpufunc.h. Modified wait loop in reset to look a little better. - * Added read for talley counters to prevent an infinite loop on old - * 8003E's if they (the counters) overflow. + * Revision 1.23 93/09/07 10:32:53 davidg + * split wd and 3Com probe code into seperate routines * - * Revision 1.16 93/07/25 14:27:12 davidg - * added parans to the previous fix so that it can cope with outb - * being a macro. + * Revision 1.22 93/09/06 20:28:22 davidg + * change references to LAAR to use shadow/prototype rather than the + * real thing because 8013EBT asic regs are write-only. * - * Revision 1.15 93/07/25 14:07:56 davidg - * fixed logic problem where a 3c503 register was being written - * even if the board wasn't a 3Com. Wolfgang Solfrank pointed this - * out. + * Revision 1.21 93/08/25 20:38:02 davidg + * added recognition for WD8013WC (10BaseT) card type * - * Revision 1.14 93/07/20 15:24:25 davidg - * ommision for force 16bit case fixed from last patch + * Revision 1.20 93/08/14 20:07:35 davidg + * one more stab at getting the 8013EBT working * - * Revision 1.13 93/07/20 15:13:55 davidg - * Added config file override for memsize by using 'iosiz'. Also added - * config flags overrides to force 8/16bit mode and disable the use of - * double xmit buffers. + * Revision 1.19 93/08/02 02:57:53 davidg + * Fixed problem where some rev 8013EBT boards want the DCR_LS flag + * set in order to work in 16bit mode. Also improves performance on + * all types of boards. + * + *...(part of log nuked for brevity) * * Revision 1.12 93/07/07 06:27:44 davidg * moved call to bpfattach to after this drivers attach printf - * improves readability of startup messages. * - * Revision 1.11 93/06/27 03:07:01 davidg - * fixed bugs in the 3Com part of the probe routine that were uncovered by - * the previous fix. - * - * Revision 1.10 93/06/25 19:23:19 davidg - * fixed bug that caused erroneous 'Invalid irq configuration' message when - * no board is present (during autoconfiguration). - * - * Revision 1.9 93/06/23 03:48:14 davidg - * fixed minor typo introduced when cleaning up probe routine - * - * Revision 1.8 93/06/23 03:37:19 davidg - * cleaned up/added some comments. Also improved readability of a part of - * the probe routine. - * - * Revision 1.7 93/06/22 04:45:01 davidg - * (no additional changes) Second beta release - * - * Revision 1.6 93/06/22 04:40:35 davidg - * minor definition fix to ed_reset() - * - * Revision 1.5 93/06/22 04:37:39 davidg - * fixed some comments - * - * Revision 1.4 93/06/22 04:34:34 davidg - * added support to use the LLC0 'link-level control' flag - * to disable the tranceiver for AUI operation on 3Com boards. - * The default for this flag can be set in the kernel config - * file - 'flags 0x01' sets the flag (disables the tranceiver). - * - * Revision 1.3 93/06/17 03:57:28 davidg - * fixed some printf's - * - * Revision 1.2 93/06/17 03:26:49 davidg - * fixed 3c503 code to determine 8/16bit board - * changed attach printf to work with Interim-0.1.5 and NetBSD + *...(part of log nuked for brevity) * * Revision 1.1 93/06/14 22:21:24 davidg * Beta release of device driver for SMC/WD80x3 and 3C503 ethernet boards. @@ -136,6 +99,10 @@ #include "i386/include/pio.h" +/* For backwards compatibility */ +#ifndef IFF_ALTPHYS +#define IFF_ALTPHYS IFF_LLC0 +#endif /* * ed_softc: per line info and status @@ -169,6 +136,11 @@ struct ed_softc { u_char rec_page_start; /* first page of RX ring-buffer */ u_char rec_page_stop; /* last page of RX ring-buffer */ u_char next_packet; /* pointer to next unread RX packet */ +/* + * The following 'proto' variable is part of a work-around for 8013EBT asics + * being write-only. It's sort of a prototype/shadow of the real thing. + */ + u_char wd_laar_proto; } ed_softc[NED]; int ed_attach(), ed_init(), edintr(), ed_ioctl(), ed_probe(), @@ -221,9 +193,8 @@ ed_probe(isa_dev) struct isa_device *isa_dev; { struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; - int i, x; - u_int memsize; - u_char iptr, memwidth, sum, tmp; + int i; + u_char sum; /* * Setup initial i/o address for ASIC and NIC @@ -245,19 +216,27 @@ ed_probe(isa_dev) } if (sum == ED_WD_ROM_CHECKSUM_TOTAL) { - goto type_WD80x3; + return (ed_probe_WD80x3(isa_dev)); } else { /* - * Do additional checking to make sure its a 3Com and - * not a broken WD clone + * XXX - Should do additional checking to make sure its a 3Com + * and not a broken WD clone */ - goto type_3Com; + return (ed_probe_3Com(isa_dev)); } +} -type_WD80x3: - /* - * Looks like a WD/SMC board - */ +/* + * Probe and vendor-specific initialization routine for SMC/WD80x3 boards + */ +int +ed_probe_WD80x3(isa_dev) + struct isa_device *isa_dev; +{ + struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; + int i; + u_int memsize; + u_char iptr, memwidth, sum, tmp; sc->vendor = ED_VENDOR_WD_SMC; sc->type = inb(sc->asic_addr + ED_WD_CARD_ID); @@ -290,18 +269,23 @@ type_WD80x3: memsize = 16384; memwidth = 16; break; - case ED_TYPE_WD8013EB: /* also WD8003EP */ + case ED_TYPE_WD8013EP: /* also WD8003EP */ if (inb(sc->asic_addr + ED_WD_ICR) & ED_WD_ICR_16BIT) { memwidth = 16; memsize = 16384; - sc->type_str = "WD8013EB"; + sc->type_str = "WD8013EP"; } else { sc->type_str = "WD8003EP"; memsize = 8192; memwidth = 8; } break; + case ED_TYPE_WD8013WC: + sc->type_str = "WD8013WC"; + memsize = 16384; + memwidth = 16; + break; case ED_TYPE_WD8013EBP: sc->type_str = "WD8013EBP"; memsize = 16384; @@ -322,14 +306,16 @@ type_WD80x3: * Make some adjustments to initial values depending on what is * found in the ICR. */ - if ((memwidth==16) + if ((memwidth == 16) && (sc->type != ED_TYPE_WD8013EBT) && ((inb(sc->asic_addr + ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) { memwidth = 8; memsize = 8192; } +#if 0 /* This has caused more problems than it's worth */ if (inb(sc->asic_addr + ED_WD_ICR) & ED_WD_ICR_MSZ) { memsize = 32768; } +#endif #if ED_DEBUG printf("type=%s memwidth=%d memsize=%d id_msize=%d\n", @@ -367,8 +353,8 @@ type_WD80x3: * Translate it using translation table, and check for correctness. */ if (ed_intr_mask[iptr] != isa_dev->id_irq) { - printf("ed%d: kernel configured irq doesn't match board configured irq\n", - isa_dev->id_unit); + printf("ed%d: kernel configured irq %d doesn't match board configured irq %d\n", + isa_dev->id_unit, ffs(isa_dev->id_irq) - 1, ffs(ed_intr_mask[iptr]) - 1); return(0); } /* @@ -382,7 +368,7 @@ type_WD80x3: /* * allocate one xmit buffer if < 16k, two buffers otherwise */ - if ((memsize < 16384) || (isa_dev->id_msize & ED_FLAGS_NO_DOUBLE_BUFFERING)) { + if ((memsize < 16384) || (isa_dev->id_flags & ED_FLAGS_NO_DOUBLE_BUFFERING)) { sc->smem_ring = sc->smem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE); sc->txb_cnt = 1; sc->rec_page_start = ED_TXBUF_SIZE; @@ -411,14 +397,14 @@ type_WD80x3: /* * Set upper address bits and 8/16 bit access to shared memory */ - if (sc->type & ED_WD_SOFTCONFIG) { + if ((sc->type & ED_WD_SOFTCONFIG) || (sc->type == ED_TYPE_WD8013EBT)) { if (memwidth == 8) { - outb(sc->asic_addr + ED_WD_LAAR, - ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI)); + outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto = + ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI))); } else { - outb(sc->asic_addr + ED_WD_LAAR, + outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto = ED_WD_LAAR_L16EN | ED_WD_LAAR_M16EN | - ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI)); + ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI))); } } @@ -436,9 +422,8 @@ type_WD80x3: * Disable 16 bit access to shared memory */ if (memwidth == 16) - outb(sc->asic_addr + ED_WD_LAAR, - inb(sc->asic_addr + ED_WD_LAAR) - & ~ED_WD_LAAR_M16EN); + outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto &= + ~ED_WD_LAAR_M16EN)); return(0); } @@ -452,16 +437,23 @@ type_WD80x3: * memory can be used in this 128k region, too. */ if (memwidth == 16) - outb(sc->asic_addr + ED_WD_LAAR, inb(sc->asic_addr + ED_WD_LAAR) - & ~ED_WD_LAAR_M16EN); + outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto &= + ~ED_WD_LAAR_M16EN)); isa_dev->id_msize = memsize; return (ED_WD_IO_PORTS); +} -type_3Com: - /* - * Looks like a 3Com board - */ +/* + * Probe and vendor-specific initialization routine for 3Com 3c503 boards + */ +ed_probe_3Com(isa_dev) + struct isa_device *isa_dev; +{ + struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; + int i; + u_int memsize; + u_char memwidth, sum; sc->vendor = ED_VENDOR_3COM; sc->asic_addr = isa_dev->id_iobase + ED_3COM_ASIC_OFFSET; @@ -538,27 +530,46 @@ type_3Com: } /* - * Reset NIC and ASIC + * Reset NIC and ASIC. Enable on-board transceiver through reset sequence + * because it'll lock up if the cable isn't connected if we don't. */ - outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_RST); + outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL); + /* * Wait for a while, then un-reset it */ - DELAY(5000); - outb(sc->asic_addr + ED_3COM_CR, 0); + DELAY(50); + /* + * The 3Com ASIC defaults to rather strange settings for the CR after + * a reset - it's important to set it again after the following + * outb (this is done when we map the PROM below). + */ + outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL); /* * Wait a bit for the NIC to recover from the reset */ - DELAY(5000); + DELAY(50); /* - * The 3Com ASIC defaults to rather strange settings for the CR after - * a reset - it's important to set it so that the NIC I/O - * registers are mapped. The above setting of it to '0' only - * resets the reset condition - the CR is *not* set to zeros. + * Get station address from on-board ROM + */ + /* + * First, map ethernet address PROM over the top of where the NIC + * registers normally appear. + */ + outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL); + + for (i = 0; i < ETHER_ADDR_LEN; ++i) + sc->arpcom.ac_enaddr[i] = inb(sc->nic_addr + i); + + /* + * Unmap PROM - select NIC registers. The proper setting of the + * tranceiver is set in ed_init so that the attach code + * is given a chance to set the default based on a compile-time + * config option */ - outb(sc->asic_addr + ED_3COM_CR, 0); + outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL); /* * Determine if this is an 8bit or 16bit board @@ -629,7 +640,8 @@ type_3Com: outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5); break; default: - printf("ed%d: Invalid irq configuration\n", isa_dev->id_unit); + printf("ed%d: Invalid irq configuration (%d) must be 2-5 for 3c503\n", + isa_dev->id_unit, ffs(isa_dev->id_irq) - 1); return(0); } @@ -650,44 +662,6 @@ type_3Com: outb(sc->asic_addr + ED_3COM_VPTR0, 0x00); /* - * Get station address from on-board ROM - */ - /* - * First, map ethernet address PROM over the top of where the NIC - * registers normally appear. - */ - outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_EALO); - - for (i = 0; i < ETHER_ADDR_LEN; ++i) - sc->arpcom.ac_enaddr[i] = inb(sc->nic_addr + i); - - /* - * Unmap PROM - select NIC registers. Tranceiver remains disabled at - * this point. It's enabled in ed_init so that the attach code - * is given a chance to set the default based on a compile-time - * config option - */ - outb(sc->asic_addr + ED_3COM_CR, 0); - -#if 0 -printf("Starting write\n"); -for (i = 0; i < 8192; ++i) - bzero(sc->smem_start, 8192); -printf("Done.\n"); -#endif -#if 0 -{ char test_buf[1024]; -printf("starting write\n"); - for (i = 0; i < 8*8192; ++i) - bcopy(test_buf, sc->smem_start, 1024); -printf("starting read\n"); - for (i = 0; i < 8*8192; ++i) - bcopy(sc->smem_start, test_buf, 1024); -printf("done.\n"); -} -#endif - - /* * Zero memory and verify that it is clear */ bzero(sc->smem_start, memsize); @@ -734,12 +708,12 @@ ed_attach(isa_dev) ifp->if_watchdog = ed_watchdog; /* - * Set default state for LLC0 flag (used to disable the tranceiver + * Set default state for ALTPHYS flag (used to disable the tranceiver * for AUI operation), based on compile-time config option. */ if (isa_dev->id_flags & ED_FLAGS_DISABLE_TRANCEIVER) ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS - | IFF_LLC0); + | IFF_ALTPHYS); else ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS); @@ -777,7 +751,7 @@ ed_attach(isa_dev) printf("ed%d: address %s, type %s (%dbit) %s\n", isa_dev->id_unit, ether_sprintf(sc->arpcom.ac_enaddr), sc->type_str, sc->memwidth, ((sc->vendor == ED_VENDOR_3COM) && - (ifp->if_flags & IFF_LLC0)) ? "tranceiver disabled" : ""); + (ifp->if_flags & IFF_ALTPHYS)) ? "tranceiver disabled" : ""); /* * If BPF is in the kernel, call the attach for it @@ -979,7 +953,7 @@ ed_init(unit) * (there is no settable hardware default). */ if (sc->vendor == ED_VENDOR_3COM) { - if (ifp->if_flags & IFF_LLC0) { + if (ifp->if_flags & IFF_ALTPHYS) { outb(sc->asic_addr + ED_3COM_CR, 0); } else { outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL); @@ -1065,7 +1039,6 @@ ed_start(ifp) struct mbuf *m0, *m; caddr_t buffer; int len; - u_char laar_tmp; outloop: /* @@ -1112,11 +1085,14 @@ outloop: */ /* * Enable 16bit access to shared memory on WD/SMC boards + * Don't update wd_laar_proto because we want to restore the + * previous state (because an arp reply in the input code + * may cause a call-back to ed_start) */ if (sc->memwidth == 16) if (sc->vendor == ED_VENDOR_WD_SMC) { - laar_tmp = inb(sc->asic_addr + ED_WD_LAAR); - outb(sc->asic_addr + ED_WD_LAAR, laar_tmp | ED_WD_LAAR_M16EN); + outb(sc->asic_addr + ED_WD_LAAR, + (sc->wd_laar_proto | ED_WD_LAAR_M16EN)); } buffer = sc->smem_start + (sc->txb_next * ED_TXBUF_SIZE * ED_PAGE_SIZE); @@ -1124,7 +1100,7 @@ outloop: for (m0 = m; m != 0; m = m->m_next) { bcopy(mtod(m, caddr_t), buffer, m->m_len); buffer += m->m_len; - len += m->m_len; + len += m->m_len; } /* @@ -1132,7 +1108,7 @@ outloop: */ if (sc->memwidth == 16) if (sc->vendor == ED_VENDOR_WD_SMC) { - outb(sc->asic_addr + ED_WD_LAAR, laar_tmp); + outb(sc->asic_addr + ED_WD_LAAR, sc->wd_laar_proto); } sc->txb_next_len = MAX(len, ETHER_MIN_LEN); @@ -1457,8 +1433,8 @@ edintr(unit) if (sc->memwidth == 16) if (sc->vendor == ED_VENDOR_WD_SMC) { outb(sc->asic_addr + ED_WD_LAAR, - inb(sc->asic_addr + ED_WD_LAAR) - | ED_WD_LAAR_M16EN); + (sc->wd_laar_proto |= + ED_WD_LAAR_M16EN)); } ed_rint (unit); @@ -1469,8 +1445,8 @@ edintr(unit) if (sc->memwidth == 16) if (sc->vendor == ED_VENDOR_WD_SMC) { outb(sc->asic_addr + ED_WD_LAAR, - inb(sc->asic_addr + ED_WD_LAAR) - & ~ED_WD_LAAR_M16EN); + (sc->wd_laar_proto &= + ~ED_WD_LAAR_M16EN)); } } @@ -1614,11 +1590,11 @@ ed_ioctl(ifp, command, data) #endif /* * An unfortunate hack to provide the (required) software control - * of the tranceiver for 3Com boards. The LLC0 flag disables + * of the tranceiver for 3Com boards. The ALTPHYS flag disables * the tranceiver if set. */ if (sc->vendor == ED_VENDOR_3COM) { - if (ifp->if_flags & IFF_LLC0) { + if (ifp->if_flags & IFF_ALTPHYS) { outb(sc->asic_addr + ED_3COM_CR, 0); } else { outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL); diff --git a/sys/dev/ed/if_edreg.h b/sys/dev/ed/if_edreg.h index b9a76fa..79f84c2 100644 --- a/sys/dev/ed/if_edreg.h +++ b/sys/dev/ed/if_edreg.h @@ -2,6 +2,12 @@ * National Semiconductor DS8390 NIC register definitions * * $Log: if_edreg.h,v $ + * Revision 1.5 93/08/25 20:38:34 davidg + * added define for card type WD8013WC (10BaseT) + * + * Revision 1.4 93/08/14 20:07:55 davidg + * fix board type definition for 8013EP + * * Revision 1.3 93/07/20 15:25:25 davidg * added config flags for forcing 8/16bit mode and disabling double * xmit buffers. @@ -662,7 +668,8 @@ struct ed_ring { #define ED_TYPE_WD8003S 0x02 #define ED_TYPE_WD8003E 0x03 #define ED_TYPE_WD8013EBT 0x05 -#define ED_TYPE_WD8013EB 0x27 +#define ED_TYPE_WD8013EP 0x27 +#define ED_TYPE_WD8013WC 0x28 #define ED_TYPE_WD8013EBP 0x2c #define ED_TYPE_WD8013EPC 0x29 diff --git a/sys/i386/isa/if_ed.c b/sys/i386/isa/if_ed.c index d42e923..85524fa 100644 --- a/sys/i386/isa/if_ed.c +++ b/sys/i386/isa/if_ed.c @@ -17,76 +17,39 @@ * Modification history * * $Log: if_ed.c,v $ - * Revision 1.19 93/08/02 02:57:53 davidg - * Fixed problem where some rev 8013EBT boards want the DCR_LS flag - * set in order to work in 16bit mode. + * Revision 1.25 93/09/08 23:04:25 davidg + * fixed problem where 3c503 boards lock up if the cable is + * disconnected at boot time. Added printing of irq number if + * the kernel config and board don't match * - * Revision 1.18 93/07/27 03:41:36 davidg - * removed unnecessary variable assignment in ed_reset() + * Revision 1.24 93/09/07 12:08:36 davidg + * ED_FLAGS_NO_DOUBLE_BUFFERING was being checked against wrong variable * - * Revision 1.17 93/07/26 18:40:57 davidg - * Added include of systm.h to pick up inlined min/max/bcmp if you have - * them in cpufunc.h. Modified wait loop in reset to look a little better. - * Added read for talley counters to prevent an infinite loop on old - * 8003E's if they (the counters) overflow. + * Revision 1.23 93/09/07 10:32:53 davidg + * split wd and 3Com probe code into seperate routines * - * Revision 1.16 93/07/25 14:27:12 davidg - * added parans to the previous fix so that it can cope with outb - * being a macro. + * Revision 1.22 93/09/06 20:28:22 davidg + * change references to LAAR to use shadow/prototype rather than the + * real thing because 8013EBT asic regs are write-only. * - * Revision 1.15 93/07/25 14:07:56 davidg - * fixed logic problem where a 3c503 register was being written - * even if the board wasn't a 3Com. Wolfgang Solfrank pointed this - * out. + * Revision 1.21 93/08/25 20:38:02 davidg + * added recognition for WD8013WC (10BaseT) card type * - * Revision 1.14 93/07/20 15:24:25 davidg - * ommision for force 16bit case fixed from last patch + * Revision 1.20 93/08/14 20:07:35 davidg + * one more stab at getting the 8013EBT working * - * Revision 1.13 93/07/20 15:13:55 davidg - * Added config file override for memsize by using 'iosiz'. Also added - * config flags overrides to force 8/16bit mode and disable the use of - * double xmit buffers. + * Revision 1.19 93/08/02 02:57:53 davidg + * Fixed problem where some rev 8013EBT boards want the DCR_LS flag + * set in order to work in 16bit mode. Also improves performance on + * all types of boards. + * + *...(part of log nuked for brevity) * * Revision 1.12 93/07/07 06:27:44 davidg * moved call to bpfattach to after this drivers attach printf - * improves readability of startup messages. * - * Revision 1.11 93/06/27 03:07:01 davidg - * fixed bugs in the 3Com part of the probe routine that were uncovered by - * the previous fix. - * - * Revision 1.10 93/06/25 19:23:19 davidg - * fixed bug that caused erroneous 'Invalid irq configuration' message when - * no board is present (during autoconfiguration). - * - * Revision 1.9 93/06/23 03:48:14 davidg - * fixed minor typo introduced when cleaning up probe routine - * - * Revision 1.8 93/06/23 03:37:19 davidg - * cleaned up/added some comments. Also improved readability of a part of - * the probe routine. - * - * Revision 1.7 93/06/22 04:45:01 davidg - * (no additional changes) Second beta release - * - * Revision 1.6 93/06/22 04:40:35 davidg - * minor definition fix to ed_reset() - * - * Revision 1.5 93/06/22 04:37:39 davidg - * fixed some comments - * - * Revision 1.4 93/06/22 04:34:34 davidg - * added support to use the LLC0 'link-level control' flag - * to disable the tranceiver for AUI operation on 3Com boards. - * The default for this flag can be set in the kernel config - * file - 'flags 0x01' sets the flag (disables the tranceiver). - * - * Revision 1.3 93/06/17 03:57:28 davidg - * fixed some printf's - * - * Revision 1.2 93/06/17 03:26:49 davidg - * fixed 3c503 code to determine 8/16bit board - * changed attach printf to work with Interim-0.1.5 and NetBSD + *...(part of log nuked for brevity) * * Revision 1.1 93/06/14 22:21:24 davidg * Beta release of device driver for SMC/WD80x3 and 3C503 ethernet boards. @@ -136,6 +99,10 @@ #include "i386/include/pio.h" +/* For backwards compatibility */ +#ifndef IFF_ALTPHYS +#define IFF_ALTPHYS IFF_LLC0 +#endif /* * ed_softc: per line info and status @@ -169,6 +136,11 @@ struct ed_softc { u_char rec_page_start; /* first page of RX ring-buffer */ u_char rec_page_stop; /* last page of RX ring-buffer */ u_char next_packet; /* pointer to next unread RX packet */ +/* + * The following 'proto' variable is part of a work-around for 8013EBT asics + * being write-only. It's sort of a prototype/shadow of the real thing. + */ + u_char wd_laar_proto; } ed_softc[NED]; int ed_attach(), ed_init(), edintr(), ed_ioctl(), ed_probe(), @@ -221,9 +193,8 @@ ed_probe(isa_dev) struct isa_device *isa_dev; { struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; - int i, x; - u_int memsize; - u_char iptr, memwidth, sum, tmp; + int i; + u_char sum; /* * Setup initial i/o address for ASIC and NIC @@ -245,19 +216,27 @@ ed_probe(isa_dev) } if (sum == ED_WD_ROM_CHECKSUM_TOTAL) { - goto type_WD80x3; + return (ed_probe_WD80x3(isa_dev)); } else { /* - * Do additional checking to make sure its a 3Com and - * not a broken WD clone + * XXX - Should do additional checking to make sure its a 3Com + * and not a broken WD clone */ - goto type_3Com; + return (ed_probe_3Com(isa_dev)); } +} -type_WD80x3: - /* - * Looks like a WD/SMC board - */ +/* + * Probe and vendor-specific initialization routine for SMC/WD80x3 boards + */ +int +ed_probe_WD80x3(isa_dev) + struct isa_device *isa_dev; +{ + struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; + int i; + u_int memsize; + u_char iptr, memwidth, sum, tmp; sc->vendor = ED_VENDOR_WD_SMC; sc->type = inb(sc->asic_addr + ED_WD_CARD_ID); @@ -290,18 +269,23 @@ type_WD80x3: memsize = 16384; memwidth = 16; break; - case ED_TYPE_WD8013EB: /* also WD8003EP */ + case ED_TYPE_WD8013EP: /* also WD8003EP */ if (inb(sc->asic_addr + ED_WD_ICR) & ED_WD_ICR_16BIT) { memwidth = 16; memsize = 16384; - sc->type_str = "WD8013EB"; + sc->type_str = "WD8013EP"; } else { sc->type_str = "WD8003EP"; memsize = 8192; memwidth = 8; } break; + case ED_TYPE_WD8013WC: + sc->type_str = "WD8013WC"; + memsize = 16384; + memwidth = 16; + break; case ED_TYPE_WD8013EBP: sc->type_str = "WD8013EBP"; memsize = 16384; @@ -322,14 +306,16 @@ type_WD80x3: * Make some adjustments to initial values depending on what is * found in the ICR. */ - if ((memwidth==16) + if ((memwidth == 16) && (sc->type != ED_TYPE_WD8013EBT) && ((inb(sc->asic_addr + ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) { memwidth = 8; memsize = 8192; } +#if 0 /* This has caused more problems than it's worth */ if (inb(sc->asic_addr + ED_WD_ICR) & ED_WD_ICR_MSZ) { memsize = 32768; } +#endif #if ED_DEBUG printf("type=%s memwidth=%d memsize=%d id_msize=%d\n", @@ -367,8 +353,8 @@ type_WD80x3: * Translate it using translation table, and check for correctness. */ if (ed_intr_mask[iptr] != isa_dev->id_irq) { - printf("ed%d: kernel configured irq doesn't match board configured irq\n", - isa_dev->id_unit); + printf("ed%d: kernel configured irq %d doesn't match board configured irq %d\n", + isa_dev->id_unit, ffs(isa_dev->id_irq) - 1, ffs(ed_intr_mask[iptr]) - 1); return(0); } /* @@ -382,7 +368,7 @@ type_WD80x3: /* * allocate one xmit buffer if < 16k, two buffers otherwise */ - if ((memsize < 16384) || (isa_dev->id_msize & ED_FLAGS_NO_DOUBLE_BUFFERING)) { + if ((memsize < 16384) || (isa_dev->id_flags & ED_FLAGS_NO_DOUBLE_BUFFERING)) { sc->smem_ring = sc->smem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE); sc->txb_cnt = 1; sc->rec_page_start = ED_TXBUF_SIZE; @@ -411,14 +397,14 @@ type_WD80x3: /* * Set upper address bits and 8/16 bit access to shared memory */ - if (sc->type & ED_WD_SOFTCONFIG) { + if ((sc->type & ED_WD_SOFTCONFIG) || (sc->type == ED_TYPE_WD8013EBT)) { if (memwidth == 8) { - outb(sc->asic_addr + ED_WD_LAAR, - ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI)); + outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto = + ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI))); } else { - outb(sc->asic_addr + ED_WD_LAAR, + outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto = ED_WD_LAAR_L16EN | ED_WD_LAAR_M16EN | - ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI)); + ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI))); } } @@ -436,9 +422,8 @@ type_WD80x3: * Disable 16 bit access to shared memory */ if (memwidth == 16) - outb(sc->asic_addr + ED_WD_LAAR, - inb(sc->asic_addr + ED_WD_LAAR) - & ~ED_WD_LAAR_M16EN); + outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto &= + ~ED_WD_LAAR_M16EN)); return(0); } @@ -452,16 +437,23 @@ type_WD80x3: * memory can be used in this 128k region, too. */ if (memwidth == 16) - outb(sc->asic_addr + ED_WD_LAAR, inb(sc->asic_addr + ED_WD_LAAR) - & ~ED_WD_LAAR_M16EN); + outb(sc->asic_addr + ED_WD_LAAR, (sc->wd_laar_proto &= + ~ED_WD_LAAR_M16EN)); isa_dev->id_msize = memsize; return (ED_WD_IO_PORTS); +} -type_3Com: - /* - * Looks like a 3Com board - */ +/* + * Probe and vendor-specific initialization routine for 3Com 3c503 boards + */ +ed_probe_3Com(isa_dev) + struct isa_device *isa_dev; +{ + struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; + int i; + u_int memsize; + u_char memwidth, sum; sc->vendor = ED_VENDOR_3COM; sc->asic_addr = isa_dev->id_iobase + ED_3COM_ASIC_OFFSET; @@ -538,27 +530,46 @@ type_3Com: } /* - * Reset NIC and ASIC + * Reset NIC and ASIC. Enable on-board transceiver through reset sequence + * because it'll lock up if the cable isn't connected if we don't. */ - outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_RST); + outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL); + /* * Wait for a while, then un-reset it */ - DELAY(5000); - outb(sc->asic_addr + ED_3COM_CR, 0); + DELAY(50); + /* + * The 3Com ASIC defaults to rather strange settings for the CR after + * a reset - it's important to set it again after the following + * outb (this is done when we map the PROM below). + */ + outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL); /* * Wait a bit for the NIC to recover from the reset */ - DELAY(5000); + DELAY(50); /* - * The 3Com ASIC defaults to rather strange settings for the CR after - * a reset - it's important to set it so that the NIC I/O - * registers are mapped. The above setting of it to '0' only - * resets the reset condition - the CR is *not* set to zeros. + * Get station address from on-board ROM + */ + /* + * First, map ethernet address PROM over the top of where the NIC + * registers normally appear. + */ + outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL); + + for (i = 0; i < ETHER_ADDR_LEN; ++i) + sc->arpcom.ac_enaddr[i] = inb(sc->nic_addr + i); + + /* + * Unmap PROM - select NIC registers. The proper setting of the + * tranceiver is set in ed_init so that the attach code + * is given a chance to set the default based on a compile-time + * config option */ - outb(sc->asic_addr + ED_3COM_CR, 0); + outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL); /* * Determine if this is an 8bit or 16bit board @@ -629,7 +640,8 @@ type_3Com: outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5); break; default: - printf("ed%d: Invalid irq configuration\n", isa_dev->id_unit); + printf("ed%d: Invalid irq configuration (%d) must be 2-5 for 3c503\n", + isa_dev->id_unit, ffs(isa_dev->id_irq) - 1); return(0); } @@ -650,44 +662,6 @@ type_3Com: outb(sc->asic_addr + ED_3COM_VPTR0, 0x00); /* - * Get station address from on-board ROM - */ - /* - * First, map ethernet address PROM over the top of where the NIC - * registers normally appear. - */ - outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_EALO); - - for (i = 0; i < ETHER_ADDR_LEN; ++i) - sc->arpcom.ac_enaddr[i] = inb(sc->nic_addr + i); - - /* - * Unmap PROM - select NIC registers. Tranceiver remains disabled at - * this point. It's enabled in ed_init so that the attach code - * is given a chance to set the default based on a compile-time - * config option - */ - outb(sc->asic_addr + ED_3COM_CR, 0); - -#if 0 -printf("Starting write\n"); -for (i = 0; i < 8192; ++i) - bzero(sc->smem_start, 8192); -printf("Done.\n"); -#endif -#if 0 -{ char test_buf[1024]; -printf("starting write\n"); - for (i = 0; i < 8*8192; ++i) - bcopy(test_buf, sc->smem_start, 1024); -printf("starting read\n"); - for (i = 0; i < 8*8192; ++i) - bcopy(sc->smem_start, test_buf, 1024); -printf("done.\n"); -} -#endif - - /* * Zero memory and verify that it is clear */ bzero(sc->smem_start, memsize); @@ -734,12 +708,12 @@ ed_attach(isa_dev) ifp->if_watchdog = ed_watchdog; /* - * Set default state for LLC0 flag (used to disable the tranceiver + * Set default state for ALTPHYS flag (used to disable the tranceiver * for AUI operation), based on compile-time config option. */ if (isa_dev->id_flags & ED_FLAGS_DISABLE_TRANCEIVER) ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS - | IFF_LLC0); + | IFF_ALTPHYS); else ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS); @@ -777,7 +751,7 @@ ed_attach(isa_dev) printf("ed%d: address %s, type %s (%dbit) %s\n", isa_dev->id_unit, ether_sprintf(sc->arpcom.ac_enaddr), sc->type_str, sc->memwidth, ((sc->vendor == ED_VENDOR_3COM) && - (ifp->if_flags & IFF_LLC0)) ? "tranceiver disabled" : ""); + (ifp->if_flags & IFF_ALTPHYS)) ? "tranceiver disabled" : ""); /* * If BPF is in the kernel, call the attach for it @@ -979,7 +953,7 @@ ed_init(unit) * (there is no settable hardware default). */ if (sc->vendor == ED_VENDOR_3COM) { - if (ifp->if_flags & IFF_LLC0) { + if (ifp->if_flags & IFF_ALTPHYS) { outb(sc->asic_addr + ED_3COM_CR, 0); } else { outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL); @@ -1065,7 +1039,6 @@ ed_start(ifp) struct mbuf *m0, *m; caddr_t buffer; int len; - u_char laar_tmp; outloop: /* @@ -1112,11 +1085,14 @@ outloop: */ /* * Enable 16bit access to shared memory on WD/SMC boards + * Don't update wd_laar_proto because we want to restore the + * previous state (because an arp reply in the input code + * may cause a call-back to ed_start) */ if (sc->memwidth == 16) if (sc->vendor == ED_VENDOR_WD_SMC) { - laar_tmp = inb(sc->asic_addr + ED_WD_LAAR); - outb(sc->asic_addr + ED_WD_LAAR, laar_tmp | ED_WD_LAAR_M16EN); + outb(sc->asic_addr + ED_WD_LAAR, + (sc->wd_laar_proto | ED_WD_LAAR_M16EN)); } buffer = sc->smem_start + (sc->txb_next * ED_TXBUF_SIZE * ED_PAGE_SIZE); @@ -1124,7 +1100,7 @@ outloop: for (m0 = m; m != 0; m = m->m_next) { bcopy(mtod(m, caddr_t), buffer, m->m_len); buffer += m->m_len; - len += m->m_len; + len += m->m_len; } /* @@ -1132,7 +1108,7 @@ outloop: */ if (sc->memwidth == 16) if (sc->vendor == ED_VENDOR_WD_SMC) { - outb(sc->asic_addr + ED_WD_LAAR, laar_tmp); + outb(sc->asic_addr + ED_WD_LAAR, sc->wd_laar_proto); } sc->txb_next_len = MAX(len, ETHER_MIN_LEN); @@ -1457,8 +1433,8 @@ edintr(unit) if (sc->memwidth == 16) if (sc->vendor == ED_VENDOR_WD_SMC) { outb(sc->asic_addr + ED_WD_LAAR, - inb(sc->asic_addr + ED_WD_LAAR) - | ED_WD_LAAR_M16EN); + (sc->wd_laar_proto |= + ED_WD_LAAR_M16EN)); } ed_rint (unit); @@ -1469,8 +1445,8 @@ edintr(unit) if (sc->memwidth == 16) if (sc->vendor == ED_VENDOR_WD_SMC) { outb(sc->asic_addr + ED_WD_LAAR, - inb(sc->asic_addr + ED_WD_LAAR) - & ~ED_WD_LAAR_M16EN); + (sc->wd_laar_proto &= + ~ED_WD_LAAR_M16EN)); } } @@ -1614,11 +1590,11 @@ ed_ioctl(ifp, command, data) #endif /* * An unfortunate hack to provide the (required) software control - * of the tranceiver for 3Com boards. The LLC0 flag disables + * of the tranceiver for 3Com boards. The ALTPHYS flag disables * the tranceiver if set. */ if (sc->vendor == ED_VENDOR_3COM) { - if (ifp->if_flags & IFF_LLC0) { + if (ifp->if_flags & IFF_ALTPHYS) { outb(sc->asic_addr + ED_3COM_CR, 0); } else { outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL); diff --git a/sys/i386/isa/if_edreg.h b/sys/i386/isa/if_edreg.h index b9a76fa..79f84c2 100644 --- a/sys/i386/isa/if_edreg.h +++ b/sys/i386/isa/if_edreg.h @@ -2,6 +2,12 @@ * National Semiconductor DS8390 NIC register definitions * * $Log: if_edreg.h,v $ + * Revision 1.5 93/08/25 20:38:34 davidg + * added define for card type WD8013WC (10BaseT) + * + * Revision 1.4 93/08/14 20:07:55 davidg + * fix board type definition for 8013EP + * * Revision 1.3 93/07/20 15:25:25 davidg * added config flags for forcing 8/16bit mode and disabling double * xmit buffers. @@ -662,7 +668,8 @@ struct ed_ring { #define ED_TYPE_WD8003S 0x02 #define ED_TYPE_WD8003E 0x03 #define ED_TYPE_WD8013EBT 0x05 -#define ED_TYPE_WD8013EB 0x27 +#define ED_TYPE_WD8013EP 0x27 +#define ED_TYPE_WD8013WC 0x28 #define ED_TYPE_WD8013EBP 0x2c #define ED_TYPE_WD8013EPC 0x29 |