Subject: Broadcom BCM4401 driver (Re: CVS commit: src/sys/dev/pci)
To: None <mrg@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: tech-kern
Date: 09/27/2003 23:44:41
In article <20030927131328.49D322DA1D@cvs.netbsd.org> on source-changes
mrg@netbsd.org wrote:
> Module Name: src
> Committed By: mrg
> Date: Sat Sep 27 13:13:28 UTC 2003
>
> Modified Files:
> src/sys/dev/pci: files.pci
> Added Files:
> src/sys/dev/pci: if_bce.c if_bcereg.h
>
> Log Message:
> add new driver for broadcom BCM4401 chipset (as seen on recent dell
> laptops) written by Cliff Wright <cliff@snipe444.org> and tested by
> yours truly.
Hmm, it looks this driver still needs some cleanup:
- if_bcereg.h should only have register definitions, so declarations
of softc structure etc. should be in if_bce.c.
- The types of DMA descriptors should be u_int32_t, not unsigned long.
- netinet headers are not required here.
- Values passed via bce_tx_ring should also be byte-swapped.
- byte-swapping is not needed for bus_space access.
Patch is attached. (tested compile only)
The following items are not included in this patch:
- KNF (and remove __P() ?)
- Replace some magic numbers with proper macro
- RX pre-packet headers need to be byte-swapped or not?
- PAGE_SIZE bytes are allocated for both TX and RX DMA ring descriptors,
but they should be 1024 (== sizeof(struct bce_dma_slot) * N[TR]XDESC).
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp
Index: if_bce.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bce.c,v
retrieving revision 1.1
diff -u -r1.1 if_bce.c
--- if_bce.c 27 Sep 2003 13:13:28 -0000 1.1
+++ if_bce.c 27 Sep 2003 14:18:10 -0000
@@ -52,13 +52,6 @@
#include <net/if_media.h>
#include <net/if_ether.h>
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#endif
-
#if NBPFILTER > 0
#include <net/bpf.h>
#endif
@@ -76,9 +69,97 @@
#include <uvm/uvm_extern.h>
-static int bce_probe(struct device *, struct cfdata *, void *);
-static void bce_attach(struct device *, struct device *, void *);
-static int bce_ioctl(struct ifnet *, u_long, caddr_t);
+/* transmit buffer max frags allowed */
+#define BCE_NTXFRAGS 16
+
+/* ring descriptor */
+struct bce_dma_slot {
+ u_int32_t ctrl;
+ u_int32_t addr;
+};
+#define CTRL_BC_MASK 0x1fff /* buffer byte count */
+#define CTRL_EOT 0x10000000 /* end of descriptor table */
+#define CTRL_IOC 0x20000000 /* interrupt on completion */
+#define CTRL_EOF 0x40000000 /* end of frame */
+#define CTRL_SOF 0x80000000 /* start of frame */
+
+/* Packet status is returned in a pre-packet header */
+struct rx_pph {
+ u_int16_t len;
+ u_int16_t flags;
+ u_int16_t pad[12];
+};
+
+/* packet status flags bits */
+#define RXF_NO 0x8 /* odd number of nibbles */
+#define RXF_RXER 0x4 /* receive symbol error */
+#define RXF_CRC 0x2 /* crc error */
+#define RXF_OV 0x1 /* fifo overflow */
+
+/* number of descriptors used in a ring */
+#define BCE_NRXDESC 128
+#define BCE_NTXDESC 128
+
+/*
+ * Mbuf pointers. We need these to keep track of the virtual addresses
+ * of our mbuf chains since we can only convert from physical to virtual,
+ * not the other way around.
+ */
+struct bce_chain_data {
+ struct mbuf *bce_tx_chain[BCE_NTXDESC];
+ struct mbuf *bce_rx_chain[BCE_NRXDESC];
+ bus_dmamap_t bce_tx_map[BCE_NTXDESC];
+ bus_dmamap_t bce_rx_map[BCE_NRXDESC];
+};
+
+#define BCE_TIMEOUT 100 /* # 10us for mii read/write */
+
+struct bce_softc {
+ struct device bce_dev;
+ bus_space_tag_t bce_btag;
+ bus_space_handle_t bce_bhandle;
+ bus_dma_tag_t bce_dmatag;
+ struct ethercom ethercom; /* interface info */
+ void *bce_intrhand;
+ struct pci_attach_args bce_pa;
+ struct mii_data bce_mii;
+ u_int32_t bce_phy; /* eeprom indicated phy */
+ struct ifmedia bce_ifmedia; /* media info *//* Check */
+ u_int8_t enaddr[ETHER_ADDR_LEN];
+ struct bce_dma_slot *bce_rx_ring; /* receive ring */
+ struct bce_dma_slot *bce_tx_ring; /* transmit ring */
+ struct bce_chain_data bce_cdata; /* mbufs */
+ bus_dmamap_t bce_ring_map;
+ u_int32_t bce_rxin; /* last rx descriptor seen */
+ u_int32_t bce_txin; /* last tx descriptor seen */
+ int bce_txsfree; /* no. tx slots available */
+ int bce_txsnext; /* next available tx slot */
+ struct callout bce_timeout;
+};
+
+/* for ring descriptors */
+#define BCE_RXBUF_LEN (MCLBYTES - 4)
+#define BCE_INIT_RXDESC(sc, x) \
+do { \
+ struct bce_dma_slot *__bced = &sc->bce_rx_ring[x]; \
+ \
+ *mtod(sc->bce_cdata.bce_rx_chain[x], u_int32_t *) = 0; \
+ __bced->addr = \
+ htole32(sc->bce_cdata.bce_rx_map[x]->dm_segs[0].ds_addr \
+ + 0x40000000); \
+ if (x != (BCE_NRXDESC - 1)) \
+ __bced->ctrl = htole32(BCE_RXBUF_LEN); \
+ else \
+ __bced->ctrl = htole32(BCE_RXBUF_LEN | CTRL_EOT); \
+ bus_dmamap_sync(sc->bce_dmatag, sc->bce_ring_map, \
+ sizeof(struct bce_dma_slot) * x, \
+ sizeof(struct bce_dma_slot), \
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
+} while (/* CONSTCOND */ 0)
+
+static int bce_probe __P((struct device *, struct cfdata *, void *));
+static void bce_attach __P((struct device *, struct device *, void *));
+static int bce_ioctl __P((struct ifnet *, u_long, caddr_t));
static void bce_start __P((struct ifnet *));
static void bce_watchdog __P((struct ifnet *));
static int bce_intr(void *);
@@ -86,7 +167,7 @@
static void bce_txintr __P((struct bce_softc *));
static int bce_init __P((struct ifnet *));
static void bce_add_mac
- __P((struct bce_softc *, unsigned char *, unsigned long));
+ __P((struct bce_softc *, u_int8_t *, unsigned long));
static int bce_add_rxbuf __P((struct bce_softc *, int));
static void bce_rxdrain __P((struct bce_softc *));
static void bce_stop __P((struct ifnet *, int));
@@ -109,26 +190,6 @@
#define DPRINTFN(n,x)
#endif
-/* for ring descriptors */
-#define BCE_RXBUF_LEN (MCLBYTES - 4)
-#define BCE_INIT_RXDESC(sc, x) \
-do { \
- struct bce_dma_slot *__bced = &sc->bce_rx_ring[x]; \
- \
- *mtod(sc->bce_cdata.bce_rx_chain[x], long *) = 0; \
- __bced->addr = \
- htole32(sc->bce_cdata.bce_rx_map[x]->dm_segs[0].ds_addr \
- + 0x40000000); \
- if (x != (BCE_NRXDESC - 1)) \
- __bced->ctrl = htole32(BCE_RXBUF_LEN); \
- else \
- __bced->ctrl = htole32(BCE_RXBUF_LEN | CTRL_EOT); \
- bus_dmamap_sync(sc->bce_dmatag, sc->bce_ring_map, \
- sizeof(struct bce_dma_slot) * x, \
- sizeof(struct bce_dma_slot), \
- BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
-} while(0)
-
#ifdef OLDNETBSD
struct cfattach bce_ca = {
sizeof(struct bce_softc), bce_probe, bce_attach
@@ -557,7 +618,7 @@
/* Initialize the transmit descriptor(s). */
txstart = sc->bce_txsnext;
for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
- unsigned long ctrl;
+ u_int32_t ctrl;
ctrl = dmamap->dm_segs[seg].ds_len & CTRL_BC_MASK;
if (seg == 0)
@@ -567,9 +628,9 @@
if (sc->bce_txsnext == BCE_NTXDESC - 1)
ctrl |= CTRL_EOT;
ctrl |= CTRL_IOC;
- sc->bce_tx_ring[sc->bce_txsnext].ctrl = ctrl;
+ sc->bce_tx_ring[sc->bce_txsnext].ctrl = htole32(ctrl);
sc->bce_tx_ring[sc->bce_txsnext].addr =
- dmamap->dm_segs[seg].ds_addr + 0x40000000;
+ htole32(dmamap->dm_segs[seg].ds_addr + 0x40000000);
if (sc->bce_txsnext + 1 > BCE_NTXDESC - 1)
sc->bce_txsnext = 0;
else
@@ -626,8 +687,8 @@
{
struct bce_softc *sc;
struct ifnet *ifp;
- unsigned long intstatus;
- unsigned long intmask;
+ u_int32_t intstatus;
+ u_int32_t intmask;
int wantinit;
int handled = 0;
@@ -848,7 +909,7 @@
struct ifnet *ifp;
{
struct bce_softc *sc = ifp->if_softc;
- unsigned long reg_win;
+ u_int32_t reg_win;
int error;
int i;
@@ -910,7 +971,7 @@
/* enable transmit */
bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXCTL, XC_XE);
bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXADDR,
- htole32(sc->bce_ring_map->dm_segs[0].ds_addr + PAGE_SIZE + 0x40000000));
+ sc->bce_ring_map->dm_segs[0].ds_addr + PAGE_SIZE + 0x40000000);
/*
* Give the receive ring to the chip, and
@@ -924,7 +985,7 @@
bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXCTL,
30 << 1 | 1);
bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXADDR,
- htole32(sc->bce_ring_map->dm_segs[0].ds_addr + 0x40000000));
+ sc->bce_ring_map->dm_segs[0].ds_addr + 0x40000000);
/* Initalize receive descriptors */
for (i = 0; i < BCE_NRXDESC; i++) {
@@ -968,11 +1029,11 @@
void
bce_add_mac(sc, mac, idx)
struct bce_softc *sc;
- unsigned char *mac;
+ u_int8_t *mac;
unsigned long idx;
{
int i;
- unsigned long rval;
+ u_int32_t rval;
bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_LOW,
mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]);
@@ -1053,7 +1114,7 @@
{
struct bce_softc *sc = ifp->if_softc;
int i;
- unsigned long val;
+ u_int32_t val;
/* Stop the 1 second timer */
callout_stop(&sc->bce_timeout);
@@ -1095,7 +1156,6 @@
/* Mark the interface down and cancel the watchdog timer. */
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
ifp->if_timer = 0;
-
}
/* reset the chip */
@@ -1103,8 +1163,8 @@
bce_reset(sc)
struct bce_softc *sc;
{
- unsigned long val;
- unsigned long sbval;
+ u_int32_t val;
+ u_int32_t sbval;
int i;
/* if SB core is up */
@@ -1154,7 +1214,7 @@
printf("%s: timed out restting ethernet mac\n",
sc->bce_dev.dv_xname);
} else {
- unsigned long reg_win;
+ u_int32_t reg_win;
/* remap the pci registers to the Sonics config registers */
@@ -1314,7 +1374,7 @@
{
struct bce_softc *sc = (struct bce_softc *) self;
int i;
- unsigned long val;
+ u_int32_t val;
/* clear mii_int */
bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_STS, BCE_MIINTR);
@@ -1332,7 +1392,7 @@
}
val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_COMM);
if (i == BCE_TIMEOUT) {
- printf("%s: PHY read timed out reading phy %d, reg %d, val = 0x%08lx\n"
+ printf("%s: PHY read timed out reading phy %d, reg %d, val = 0x%08x\n"
,sc->bce_dev.dv_xname, phy, reg, val);
return (0);
}
@@ -1347,7 +1407,7 @@
{
struct bce_softc *sc = (struct bce_softc *) self;
int i;
- unsigned long rval;
+ u_int32_t rval;
/* clear mii_int */
bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_STS, BCE_MIINTR);
@@ -1378,7 +1438,7 @@
struct device *self;
{
struct bce_softc *sc = (struct bce_softc *) self;
- unsigned long reg;
+ u_int32_t reg;
/* if needed, change register to match duplex mode */
reg = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_CTL);
Index: if_bcereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bcereg.h,v
retrieving revision 1.1
diff -u -r1.1 if_bcereg.h
--- if_bcereg.h 27 Sep 2003 13:13:28 -0000 1.1
+++ if_bcereg.h 27 Sep 2003 14:18:11 -0000
@@ -138,71 +138,3 @@
#define BCE_MIREG(x) ((x & 0x1F) << 18)
#define BCE_MIPHY(x) ((x & 0x1F) << 23)
-
-/* transmit buffer max frags allowed */
-#define BCE_NTXFRAGS 16
-
-/* ring descriptor */
-struct bce_dma_slot {
- unsigned long ctrl;
- unsigned long addr;
-};
-#define CTRL_BC_MASK 0x1fff /* buffer byte count */
-#define CTRL_EOT 0x10000000 /* end of descriptor table */
-#define CTRL_IOC 0x20000000 /* interrupt on completion */
-#define CTRL_EOF 0x40000000 /* end of frame */
-#define CTRL_SOF 0x80000000 /* start of frame */
-
-/* Packet status is returned in a pre-packet header */
-struct rx_pph {
- unsigned short len;
- unsigned short flags;
- unsigned short pad[12];
-};
-
-/* packet status flags bits */
-#define RXF_NO 0x8 /* odd number of nibbles */
-#define RXF_RXER 0x4 /* receive symbol error */
-#define RXF_CRC 0x2 /* crc error */
-#define RXF_OV 0x1 /* fifo overflow */
-
-/* number of descriptors used in a ring */
-#define BCE_NRXDESC 128
-#define BCE_NTXDESC 128
-
-/*
- * Mbuf pointers. We need these to keep track of the virtual addresses
- * of our mbuf chains since we can only convert from physical to virtual,
- * not the other way around.
- */
-struct bce_chain_data {
- struct mbuf *bce_tx_chain[BCE_NTXDESC];
- struct mbuf *bce_rx_chain[BCE_NRXDESC];
- bus_dmamap_t bce_tx_map[BCE_NTXDESC];
- bus_dmamap_t bce_rx_map[BCE_NRXDESC];
-};
-
-#define BCE_TIMEOUT 100 /* # 10us for mii read/write */
-
-struct bce_softc {
- struct device bce_dev;
- struct ethercom ethercom; /* interface info */
- bus_space_handle_t bce_bhandle;
- bus_space_tag_t bce_btag;
- void *bce_intrhand;
- struct pci_attach_args bce_pa;
- struct mii_data bce_mii;
- u_int32_t bce_phy;/* eeprom indicated phy */
- struct ifmedia bce_ifmedia; /* media info *//* Check */
- bus_dma_tag_t bce_dmatag;
- u_int8_t enaddr[ETHER_ADDR_LEN];
- struct bce_dma_slot *bce_rx_ring; /* receive ring */
- struct bce_dma_slot *bce_tx_ring; /* transmit ring */
- struct bce_chain_data bce_cdata; /* mbufs */
- bus_dmamap_t bce_ring_map;
- u_int32_t bce_rxin; /* last rx descriptor seen */
- u_int32_t bce_txin; /* last tx descriptor seen */
- int bce_txsfree; /* no. tx slots available */
- int bce_txsnext; /* next available tx slot */
- struct callout bce_timeout;
-};