summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ed/if_ed.c284
-rw-r--r--sys/dev/ed/if_edreg.h9
-rw-r--r--sys/i386/isa/if_ed.c284
-rw-r--r--sys/i386/isa/if_edreg.h9
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
OpenPOWER on IntegriCloud