summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1993-06-22 12:10:07 +0000
committerdg <dg@FreeBSD.org>1993-06-22 12:10:07 +0000
commit5387edd7b5f4038fa67bbb3693e857590df4b8ba (patch)
tree3454e7dbee9d23d8063012b50efd1b0db077945c /sys/dev
parent4636dacebf2f623f0a347dda4aeeede5cb07f197 (diff)
downloadFreeBSD-src-5387edd7b5f4038fa67bbb3693e857590df4b8ba.zip
FreeBSD-src-5387edd7b5f4038fa67bbb3693e857590df4b8ba.tar.gz
Second beta release of device driver for WD/SMC 80x3 and 3c503 ethernet boards
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ed/if_ed.c125
-rw-r--r--sys/dev/ed/if_edreg.h8
2 files changed, 104 insertions, 29 deletions
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index 1e585db..ec1d682 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -16,7 +16,32 @@
/*
* Modification history
*
- * $Log$
+ * $Log: if_ed.c,v $
+ * 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
+ *
+ * Revision 1.1 93/06/14 22:21:24 davidg
+ * Beta release of device driver for SMC/WD80x3 and 3C503 ethernet boards.
+ *
*
*/
@@ -433,45 +458,44 @@ type_3Com:
*/
outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_RST);
/*
- * Verify that reset bit was set
- */
- if ((inb(sc->asic_addr + ED_3COM_CR) & ED_3COM_CR_RST) == 0)
- return (0);
- /*
* Wait for a while, then un-reset it
*/
DELAY(5000);
outb(sc->asic_addr + ED_3COM_CR, 0);
/*
- * Verify that the bit cleared
+ * Wait a bit for the NIC to recover from the reset
*/
- if (inb(sc->asic_addr + ED_3COM_CR) & ED_3COM_CR_RST)
- return (0);
+ DELAY(5000);
/*
- * Wait a bit for the NIC to recover from the reset
+ * 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.
*/
- DELAY(5000);
+ outb(sc->asic_addr + ED_3COM_CR, 0);
/*
* Determine if this is an 8bit or 16bit board
*/
- /* XXX - either this code is broken...or the hardware is... */
- /* it always comes up 8bit */
+
/*
* select page 0 registers
*/
outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STP);
+
/*
* Attempt to clear WTS bit. If it doesn't clear, then this is a
* 16bit board.
*/
outb(sc->nic_addr + ED_P0_DCR, 0);
+
/*
* select page 2 registers
*/
outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_2|ED_CR_RD2|ED_CR_STP);
+
/*
* The 3c503 forces the WTS bit to a one if this is a 16bit board
*/
@@ -480,13 +504,10 @@ type_3Com:
else
memwidth = 8;
-#if 0
-printf(" (%dbit)",memwidth);
-#endif
/*
* select page 0 registers
*/
- outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STP);
+ outb(sc->nic_addr + ED_P2_CR, ED_CR_RD2|ED_CR_STP);
sc->txb_cnt = 1;
@@ -524,7 +545,7 @@ printf(" (%dbit)",memwidth);
outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
break;
default:
- printf("ed0: Invalid irq configuration\n");
+ printf("ed%d: Invalid irq configuration\n", isa_dev->id_unit);
return(0);
}
@@ -557,13 +578,19 @@ printf(" (%dbit)",memwidth);
sc->arpcom.ac_enaddr[i] = inb(sc->nic_addr + i);
/*
- * Unmap PROM - select NIC registers
+ * 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);
- /*
- * Zero memory and verify that it is clear
- */
+#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");
@@ -576,6 +603,9 @@ printf("done.\n");
}
#endif
+ /*
+ * Zero memory and verify that it is clear
+ */
bzero(sc->smem_start, memsize);
for (i = 0; i < memsize; ++i)
@@ -612,7 +642,6 @@ ed_attach(isa_dev)
ifp->if_unit = isa_dev->id_unit;
ifp->if_name = "ed" ;
ifp->if_mtu = ETHERMTU;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS ;
ifp->if_init = ed_init;
ifp->if_output = ether_output;
ifp->if_start = ed_start;
@@ -620,6 +649,16 @@ ed_attach(isa_dev)
ifp->if_reset = ed_reset;
ifp->if_watchdog = ed_watchdog;
+ /*
+ * Set default state for LLC0 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);
+ else
+ ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS);
+
if_attach(ifp);
#if NBPFILTER > 0
@@ -635,11 +674,11 @@ ed_attach(isa_dev)
ifa = ifa->ifa_next;
/*
- * If we find an AF_LINK type entry, we well fill in the hardware addr
+ * If we find an AF_LINK type entry we fill in the hardware address
*/
if ((ifa != 0) && (ifa->ifa_addr != 0)) {
/*
- * Fill in the link level address for this interface
+ * Fill in the link-level address for this interface
*/
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
sdl->sdl_type = IFT_ETHER;
@@ -651,15 +690,17 @@ ed_attach(isa_dev)
/*
* Print additional info when attached
*/
- printf(" enet %s type %s", ether_sprintf(sc->arpcom.ac_enaddr),
- sc->type_str);
+ 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" : "");
}
/*
* Reset interface.
*/
int
-ed_reset(unit, uban)
+ed_reset(unit)
int unit;
{
int s;
@@ -840,6 +881,16 @@ ed_init(unit)
outb(sc->nic_addr + ED_P0_TCR, 0);
/*
+ * If this is a 3Com board, the tranceiver must be software enabled
+ * (there is no settable hardware default).
+ */
+ if ((sc->vendor == ED_VENDOR_3COM) && (ifp->if_flags & IFF_LLC0)) {
+ outb(sc->asic_addr + ED_3COM_CR, 0);
+ } else {
+ outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL);
+ }
+
+ /*
* Set 'running' flag, and clear output active flag.
*/
ifp->if_flags |= IFF_RUNNING;
@@ -1221,6 +1272,10 @@ edintr(unit)
*/
if (isr & ED_ISR_RXE) {
++sc->arpcom.ac_if.if_ierrors;
+#ifdef ED_DEBUG
+ printf("ed%d: receive error %x\n", unit,
+ inb(sc->nic_addr + ED_P0_RSR));
+#endif
}
/*
@@ -1421,14 +1476,26 @@ ed_ioctl(ifp, command, data)
*/
outb(sc->nic_addr + ED_P0_RCR,
ED_RCR_PRO|ED_RCR_AM|ED_RCR_AB);
- } else
+ } else {
/*
* XXX - for multicasts to work, we would need to
* rewrite the multicast hashing array with the
* proper hash (would have been destroyed above).
*/
outb(sc->nic_addr + ED_P0_RCR, ED_RCR_AB);
+ }
#endif
+ /*
+ * An unfortunate hack to provide the (required) software control
+ * of the tranceiver for 3Com boards. The LLC0 flag disables
+ * the tranceiver if set.
+ */
+ if ((sc->vendor == ED_VENDOR_3COM) && (ifp->if_flags & IFF_LLC0)) {
+ outb(sc->asic_addr + ED_3COM_CR, 0);
+ } else {
+ outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL);
+ }
+
break;
default:
diff --git a/sys/dev/ed/if_edreg.h b/sys/dev/ed/if_edreg.h
index 00d36b3..a202848 100644
--- a/sys/dev/ed/if_edreg.h
+++ b/sys/dev/ed/if_edreg.h
@@ -547,6 +547,14 @@ struct ed_ring {
#define ED_VENDOR_3COM 0x01 /* 3Com */
/*
+ * Compile-time config flags
+ */
+/*
+ * this sets the default for enabling/disablng the tranceiver
+ */
+#define ED_FLAGS_DISABLE_TRANCEIVER 0x01
+
+/*
* Definitions for Western digital/SMC WD80x3 series ASIC
*/
/*
OpenPOWER on IntegriCloud