aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2005-08-28 23:56:25 +0000
committerWarner Losh <imp@FreeBSD.org>2005-08-28 23:56:25 +0000
commitf1c4694df3c641a1bb24b31e0119234278174033 (patch)
tree7b1691cb23490adfbf5bb0159078c6ff7ab8d83a
parenta6c109d6581192d8520dda52be0f7b9aac41da3c (diff)
downloadsrc-f1c4694df3c641a1bb24b31e0119234278174033.tar.gz
src-f1c4694df3c641a1bb24b31e0119234278174033.zip
Finish conversion to bus space and make ed MP safe.
o Lock ed o Fix extra newline in probe messages o Eliminate gone. o Make detach less-racy. o Eliminate spl* o Switch from timeout/untimeout to callout interface. o Read/write card memory using bus_space calls. o generalize readmem so that we don't need ifs in the code. o Fix memory stuff to be consistant. o Remove OLDCARD compat stuff. o Mark interrupt as MPSAFE. # sic, hpp not tested at all # ISA and PCI attachments lightly tested
Notes
Notes: svn path=/head/; revision=149558
-rw-r--r--sys/dev/ed/if_ed.c324
-rw-r--r--sys/dev/ed/if_ed_3c503.c2
-rw-r--r--sys/dev/ed/if_ed_cbus.c14
-rw-r--r--sys/dev/ed/if_ed_hpp.c11
-rw-r--r--sys/dev/ed/if_ed_isa.c10
-rw-r--r--sys/dev/ed/if_ed_novell.c15
-rw-r--r--sys/dev/ed/if_ed_pccard.c103
-rw-r--r--sys/dev/ed/if_ed_pci.c3
-rw-r--r--sys/dev/ed/if_ed_sic.c7
-rw-r--r--sys/dev/ed/if_ed_wd80x3.c2
-rw-r--r--sys/dev/ed/if_edvar.h30
11 files changed, 285 insertions, 236 deletions
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index 18b625e2de20..9f05458ce8f8 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -29,6 +29,11 @@
__FBSDID("$FreeBSD$");
/*
+ * TODO:
+ * o lock MII
+ */
+
+/*
* Device driver for National Semiconductor DS8390/WD83C690 based ethernet
* adapters. By David Greenman, 29-April-1993
*
@@ -71,12 +76,15 @@ __FBSDID("$FreeBSD$");
#include <dev/ed/if_edreg.h>
#include <dev/ed/if_edvar.h>
+#include <sys/kdb.h>
devclass_t ed_devclass;
static void ed_init(void *);
+static void ed_init_locked(struct ed_softc *);
static int ed_ioctl(struct ifnet *, u_long, caddr_t);
static void ed_start(struct ifnet *);
+static void ed_start_locked(struct ifnet *);
static void ed_reset(struct ifnet *);
static void ed_watchdog(struct ifnet *);
#ifndef ED_NO_MIIBUS
@@ -85,12 +93,15 @@ static void ed_tick(void *);
static void ed_ds_getmcaf(struct ed_softc *, uint32_t *);
-static void ed_get_packet(struct ed_softc *, char *, u_short);
+static void ed_get_packet(struct ed_softc *, bus_size_t, u_short);
+static void ed_stop_hw(struct ed_softc *sc);
-static __inline void ed_rint(struct ed_softc *);
-static __inline void ed_xmit(struct ed_softc *);
-static __inline char *ed_ring_copy(struct ed_softc *, char *, char *, u_short);
-static u_short ed_pio_write_mbufs(struct ed_softc *, struct mbuf *, long);
+static __inline void ed_rint(struct ed_softc *);
+static __inline void ed_xmit(struct ed_softc *);
+static __inline void ed_ring_copy(struct ed_softc *, bus_size_t, char *,
+ u_short);
+static u_short ed_pio_write_mbufs(struct ed_softc *, struct mbuf *,
+ bus_size_t);
static void ed_setrcr(struct ed_softc *);
@@ -257,17 +268,31 @@ ed_attach(device_t dev)
struct ed_softc *sc = device_get_softc(dev);
struct ifnet *ifp;
+ sc->dev = dev;
+ ED_LOCK_INIT(sc);
ifp = sc->ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
+ ED_LOCK_DESTROY(sc);
return (ENOSPC);
}
- callout_handle_init(&sc->tick_ch);
+ if (sc->readmem == NULL) {
+ if (sc->mem_shared) {
+ if (sc->isa16bit)
+ sc->readmem = ed_shmem_readmem16;
+ else
+ sc->readmem = ed_shmem_readmem8;
+ } else {
+ sc->readmem = ed_pio_readmem;
+ }
+ }
+
+ callout_init_mtx(&sc->tick_ch, ED_MUTEX(sc), 0);
/*
* Set interface to stopped condition (reset)
*/
- ed_stop(sc);
+ ed_stop_hw(sc);
/*
* Initialize ifnet structure
@@ -298,15 +323,11 @@ ed_attach(device_t dev)
/*
* Set default state for ALTPHYS flag (used to disable the
- * tranceiver for AUI operation), based on compile-time
- * config option.
+ * tranceiver for AUI operation), based on config option.
*/
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
if (device_get_flags(dev) & ED_FLAGS_DISABLE_TRANCEIVER)
- ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX |
- IFF_MULTICAST | IFF_ALTPHYS | IFF_NEEDSGIANT);
- else
- ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX |
- IFF_MULTICAST | IFF_NEEDSGIANT);
+ ifp->if_flags |= IFF_ALTPHYS;
/*
* Attach the interface
@@ -331,7 +352,7 @@ ed_attach(device_t dev)
printf("%s ", sc->isa16bit ? "(16 bit)" : "(8 bit)");
#if defined(ED_HPP) || defined(ED_3C503)
- printf("%s\n", (((sc->vendor == ED_VENDOR_3COM) ||
+ printf("%s", (((sc->vendor == ED_VENDOR_3COM) ||
(sc->vendor == ED_VENDOR_HP)) &&
(ifp->if_flags & IFF_ALTPHYS)) ?
" tranceiver disabled" : "");
@@ -350,15 +371,18 @@ ed_detach(device_t dev)
struct ed_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->ifp;
- if (sc->gone)
- return (0);
- ed_stop(sc);
+ ED_ASSERT_UNLOCKED(sc);
+ ED_LOCK(sc);
+ if (bus_child_present(dev))
+ ed_stop(sc);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ ED_UNLOCK(sc);
+ callout_drain(&sc->tick_ch);
ether_ifdetach(ifp);
if_free(ifp);
- sc->gone = 1;
bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
ed_release_resources(dev);
+ ED_LOCK_DESTROY(sc);
return (0);
}
@@ -369,35 +393,20 @@ static void
ed_reset(struct ifnet *ifp)
{
struct ed_softc *sc = ifp->if_softc;
- int s;
-
- if (sc->gone)
- return;
- s = splimp();
+ ED_ASSERT_LOCKED(sc);
/*
* Stop interface and re-initialize.
*/
ed_stop(sc);
- ed_init(sc);
-
- (void) splx(s);
+ ed_init_locked(sc);
}
-/*
- * Take interface offline.
- */
-void
-ed_stop(struct ed_softc *sc)
+static void
+ed_stop_hw(struct ed_softc *sc)
{
int n = 5000;
-#ifndef ED_NO_MIIBUS
- untimeout(ed_tick, sc, sc->tick_ch);
- callout_handle_init(&sc->tick_ch);
-#endif
- if (sc->gone)
- return;
/*
* Stop everything on the interface, and select page 0 registers.
*/
@@ -414,6 +423,19 @@ ed_stop(struct ed_softc *sc)
}
/*
+ * Take interface offline.
+ */
+void
+ed_stop(struct ed_softc *sc)
+{
+ ED_ASSERT_LOCKED(sc);
+#ifndef ED_NO_MIIBUS
+ callout_stop(&sc->tick_ch);
+#endif
+ ed_stop_hw(sc);
+}
+
+/*
* Device timeout/watchdog routine. Entered if the device neglects to
* generate an interrupt after a transmit has been started on it.
*/
@@ -422,12 +444,12 @@ ed_watchdog(struct ifnet *ifp)
{
struct ed_softc *sc = ifp->if_softc;
- if (sc->gone)
- return;
log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
ifp->if_oerrors++;
+ ED_LOCK(sc);
ed_reset(ifp);
+ ED_UNLOCK(sc);
}
#ifndef ED_NO_MIIBUS
@@ -436,19 +458,13 @@ ed_tick(void *arg)
{
struct ed_softc *sc = arg;
struct mii_data *mii;
- int s;
- if (sc->gone) {
- callout_handle_init(&sc->tick_ch);
- return;
- }
- s = splimp();
+ ED_ASSERT_LOCKED(sc);
if (sc->miibus != NULL) {
mii = device_get_softc(sc->miibus);
mii_tick(mii);
}
- sc->tick_ch = timeout(ed_tick, sc, hz);
- splx(s);
+ callout_reset(&sc->tick_ch, hz, ed_tick, sc);
}
#endif
@@ -459,18 +475,26 @@ static void
ed_init(void *xsc)
{
struct ed_softc *sc = xsc;
+
+ ED_ASSERT_UNLOCKED(sc);
+ ED_LOCK(sc);
+ ed_init_locked(sc);
+ ED_UNLOCK(sc);
+}
+
+static void
+ed_init_locked(struct ed_softc *sc)
+{
struct ifnet *ifp = sc->ifp;
- int i, s;
+ int i;
- if (sc->gone)
- return;
+ ED_ASSERT_LOCKED(sc);
/*
* Initialize the NIC in the exact order outlined in the NS manual.
* This init procedure is "mandatory"...don't change what or when
* things happen.
*/
- s = splimp();
/* reset transmitter flags */
sc->xmit_busy = 0;
@@ -601,13 +625,11 @@ ed_init(void *xsc)
/*
* ...and attempt to start output
*/
- ed_start(ifp);
+ ed_start_locked(ifp);
#ifndef ED_NO_MIIBUS
- untimeout(ed_tick, sc, sc->tick_ch);
- sc->tick_ch = timeout(ed_tick, sc, hz);
+ callout_reset(&sc->tick_ch, hz, ed_tick, sc);
#endif
- (void) splx(s);
}
/*
@@ -619,8 +641,6 @@ ed_xmit(struct ed_softc *sc)
struct ifnet *ifp = sc->ifp;
unsigned short len;
- if (sc->gone)
- return;
len = sc->txb_len[sc->txb_next_tx];
/*
@@ -672,14 +692,22 @@ static void
ed_start(struct ifnet *ifp)
{
struct ed_softc *sc = ifp->if_softc;
+
+ ED_ASSERT_UNLOCKED(sc);
+ ED_LOCK(sc);
+ ed_start_locked(ifp);
+ ED_UNLOCK(sc);
+}
+
+static void
+ed_start_locked(struct ifnet *ifp)
+{
+ struct ed_softc *sc = ifp->if_softc;
struct mbuf *m0, *m;
- caddr_t buffer;
+ bus_size_t buffer;
int len;
- if (sc->gone) {
- printf("ed_start(%p) GONE\n",ifp);
- return;
- }
+ ED_ASSERT_LOCKED(sc);
outloop:
/*
@@ -719,7 +747,6 @@ outloop:
/*
* Copy the mbuf chain into the transmit buffer
*/
-
m0 = m;
/* txb_new points to next open buffer slot */
@@ -758,11 +785,14 @@ outloop:
}
}
for (len = 0; m != 0; m = m->m_next) {
- /* XXX
- * I'm not sure that this bcopy does only 16bit
- * access
- */
- bcopy(mtod(m, caddr_t), buffer, m->m_len);
+ if (sc->isa16bit)
+ bus_space_write_region_2(sc->mem_bst,
+ sc->mem_bsh, buffer,
+ mtod(m, uint16_t *), (m->m_len + 1)/ 2);
+ else
+ bus_space_write_region_1(sc->mem_bst,
+ sc->mem_bsh, buffer,
+ mtod(m, uint8_t *), m->m_len);
buffer += m->m_len;
len += m->m_len;
}
@@ -788,7 +818,7 @@ outloop:
}
}
} else {
- len = ed_pio_write_mbufs(sc, m, (uintptr_t)buffer);
+ len = ed_pio_write_mbufs(sc, m, buffer);
if (len == 0) {
m_freem(m0);
goto outloop;
@@ -832,10 +862,9 @@ ed_rint(struct ed_softc *sc)
u_char boundry;
u_short len;
struct ed_ring packet_hdr;
- char *packet_ptr;
+ bus_size_t packet_ptr;
- if (sc->gone)
- return;
+ ED_ASSERT_LOCKED(sc);
/*
* Set NIC to page 1 registers to get 'current' pointer
@@ -860,11 +889,8 @@ ed_rint(struct ed_softc *sc)
* The byte count includes a 4 byte header that was added by
* the NIC.
*/
- if (sc->mem_shared)
- packet_hdr = *(struct ed_ring *) packet_ptr;
- else
- ed_pio_readmem(sc, (uintptr_t)packet_ptr,
- (char *) &packet_hdr, sizeof(packet_hdr));
+ sc->readmem(sc, packet_ptr, (char *) &packet_hdr,
+ sizeof(packet_hdr));
len = packet_hdr.count;
if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN + sizeof(struct ed_ring)) ||
len < (ETHER_MIN_LEN - ETHER_CRC_LEN + sizeof(struct ed_ring))) {
@@ -968,8 +994,13 @@ edintr(void *arg)
u_char isr;
int count;
- if (sc->gone)
+ ED_LOCK(sc);
+#if 0
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ ED_UNLOCK(sc);
return;
+ }
+#endif
/*
* Set NIC to page 0 registers
*/
@@ -1181,7 +1212,7 @@ edintr(void *arg)
* after handling the receiver to give the receiver priority.
*/
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
- ed_start(ifp);
+ ed_start_locked(ifp);
/*
* return NIC CR to standard state: page 0, remote DMA
@@ -1202,6 +1233,7 @@ edintr(void *arg)
(void) ed_nic_inb(sc, ED_P0_CNTR2);
}
}
+ ED_UNLOCK(sc);
}
/*
@@ -1215,24 +1247,26 @@ ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct ifreq *ifr = (struct ifreq *)data;
struct mii_data *mii;
#endif
- int s, error = 0;
+ int error = 0;
- if (sc == NULL || sc->gone) {
+ /*
+ * XXX really needed?
+ */
+ if (sc == NULL) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- return ENXIO;
+ return (ENXIO);
}
- s = splimp();
switch (command) {
case SIOCSIFFLAGS:
-
/*
* If the interface is marked up and stopped, then start it.
* If it is marked down and running, then stop it.
*/
+ ED_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- ed_init(sc);
+ ed_init_locked(sc);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
ed_stop(sc);
@@ -1264,6 +1298,7 @@ ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (sc->vendor == ED_VENDOR_HP)
ed_hpp_set_physical_link(sc);
#endif
+ ED_UNLOCK(sc);
break;
case SIOCADDMULTI:
@@ -1272,7 +1307,9 @@ ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
* Multicast list has changed; set the hardware filter
* accordingly.
*/
+ ED_LOCK(sc);
ed_setrcr(sc);
+ ED_UNLOCK(sc);
error = 0;
break;
@@ -1290,8 +1327,8 @@ ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
default:
error = ether_ioctl(ifp, command, data);
+ break;
}
- (void) splx(s);
return (error);
}
@@ -1300,34 +1337,21 @@ ed_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
* the ring buffer into a linear destination buffer. Takes into account
* ring-wrap.
*/
-static __inline char *
-ed_ring_copy(struct ed_softc *sc, char *src, char *dst, u_short amount)
+static __inline void
+ed_ring_copy(struct ed_softc *sc, bus_size_t src, char *dst, u_short amount)
{
u_short tmp_amount;
/* does copy wrap to lower addr in ring buffer? */
if (src + amount > sc->mem_end) {
tmp_amount = sc->mem_end - src;
-
- /* XXX
- * I'm not sure that this bcopy does only 16bit access
- */
/* copy amount up to end of NIC memory */
- if (sc->mem_shared)
- bcopy(src, dst, tmp_amount);
- else
- ed_pio_readmem(sc, (uintptr_t)src, dst, tmp_amount);
-
+ sc->readmem(sc, src, dst, tmp_amount);
amount -= tmp_amount;
src = sc->mem_ring;
dst += tmp_amount;
}
- if (sc->mem_shared)
- bcopy(src, dst, amount);
- else
- ed_pio_readmem(sc, (uintptr_t)src, dst, amount);
-
- return (src + amount);
+ sc->readmem(sc, src, dst, amount);
}
/*
@@ -1335,7 +1359,7 @@ ed_ring_copy(struct ed_softc *sc, char *src, char *dst, u_short amount)
* ether_input().
*/
static void
-ed_get_packet(struct ed_softc *sc, char *buf, u_short len)
+ed_get_packet(struct ed_softc *sc, bus_size_t buf, u_short len)
{
struct ifnet *ifp = sc->ifp;
struct ether_header *eh;
@@ -1379,7 +1403,9 @@ ed_get_packet(struct ed_softc *sc, char *buf, u_short len)
m->m_pkthdr.len = m->m_len = len;
+ ED_UNLOCK(sc);
(*ifp->if_input)(ifp, m);
+ ED_LOCK(sc);
}
/*
@@ -1388,22 +1414,42 @@ ed_get_packet(struct ed_softc *sc, char *buf, u_short len)
/*
* Given a NIC memory source address and a host memory destination
+ * address, copy 'amount' from NIC to host using shared memory.
+ * The 'amount' is rounded up to a word - okay as long as mbufs
+ * are word sized. That's what the +1 is below.
+ * This routine accesses things as 16 bit quantities.
+ */
+void
+ed_shmem_readmem16(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
+ uint16_t amount)
+{
+ bus_space_read_region_2(sc->mem_bst, sc->mem_bsh, src, (uint16_t *)dst,
+ amount + 1 / 2);
+}
+
+/*
+ * Given a NIC memory source address and a host memory destination
+ * address, copy 'amount' from NIC to host using shared memory.
+ * This routine accesses things as 8 bit quantities.
+ */
+void
+ed_shmem_readmem8(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
+ uint16_t amount)
+{
+ bus_space_read_region_1(sc->mem_bst, sc->mem_bsh, src, dst, amount);
+}
+
+/*
+ * Given a NIC memory source address and a host memory destination
* address, copy 'amount' from NIC to host using Programmed I/O.
* The 'amount' is rounded up to a word - okay as long as mbufs
* are word sized.
* This routine is currently Novell-specific.
*/
void
-ed_pio_readmem(struct ed_softc *sc, long src, uint8_t *dst, uint16_t amount)
+ed_pio_readmem(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
+ uint16_t amount)
{
-#ifdef ED_HPP
- /* HP PC Lan+ cards need special handling */
- if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS) {
- ed_hpp_readmem(sc, src, dst, amount);
- return;
- }
-#endif
-
/* Regular Novell cards */
/* select page 0 registers */
ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STA);
@@ -1477,13 +1523,15 @@ ed_pio_writemem(struct ed_softc *sc, uint8_t *src, uint16_t dst, uint16_t len)
* programmed I/O.
*/
static u_short
-ed_pio_write_mbufs(struct ed_softc *sc, struct mbuf *m, long dst)
+ed_pio_write_mbufs(struct ed_softc *sc, struct mbuf *m, bus_size_t dst)
{
struct ifnet *ifp = sc->ifp;
unsigned short total_len, dma_len;
struct mbuf *mp;
int maxwait = 200; /* about 240us */
+ ED_ASSERT_LOCKED(sc);
+
#ifdef ED_HPP
/* HP PC Lan+ cards need special handling */
if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS)
@@ -1599,15 +1647,12 @@ int
ed_miibus_readreg(device_t dev, int phy, int reg)
{
struct ed_softc *sc;
- int failed, s, val;
+ int failed, val;
- s = splimp();
sc = device_get_softc(dev);
- if (sc->gone) {
- splx(s);
- return (0);
- }
+ /* XXX is this right? */
+ ED_LOCK(sc);
(*sc->mii_writebits)(sc, 0xffffffff, 32);
(*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS);
(*sc->mii_writebits)(sc, ED_MII_READOP, ED_MII_OP_BITS);
@@ -1617,8 +1662,8 @@ ed_miibus_readreg(device_t dev, int phy, int reg)
failed = (*sc->mii_readbits)(sc, ED_MII_ACK_BITS);
val = (*sc->mii_readbits)(sc, ED_MII_DATA_BITS);
(*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS);
-
- splx(s);
+ /* XXX is this right? */
+ ED_UNLOCK(sc);
return (failed ? 0 : val);
}
@@ -1626,15 +1671,11 @@ void
ed_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct ed_softc *sc;
- int s;
- s = splimp();
sc = device_get_softc(dev);
- if (sc->gone) {
- splx(s);
- return;
- }
+ /* XXX is this right? */
+ ED_LOCK(sc);
(*sc->mii_writebits)(sc, 0xffffffff, 32);
(*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS);
(*sc->mii_writebits)(sc, ED_MII_WRITEOP, ED_MII_OP_BITS);
@@ -1643,8 +1684,8 @@ ed_miibus_writereg(device_t dev, int phy, int reg, int data)
(*sc->mii_writebits)(sc, ED_MII_TURNAROUND, ED_MII_TURNAROUND_BITS);
(*sc->mii_writebits)(sc, data, ED_MII_DATA_BITS);
(*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS);
-
- splx(s);
+ /* XXX is this right? */
+ ED_UNLOCK(sc);
}
int
@@ -1654,7 +1695,7 @@ ed_ifmedia_upd(struct ifnet *ifp)
struct mii_data *mii;
sc = ifp->if_softc;
- if (sc->gone || sc->miibus == NULL)
+ if (sc->miibus == NULL)
return (ENXIO);
mii = device_get_softc(sc->miibus);
@@ -1668,7 +1709,7 @@ ed_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
struct mii_data *mii;
sc = ifp->if_softc;
- if (sc->gone || sc->miibus == NULL)
+ if (sc->miibus == NULL)
return;
mii = device_get_softc(sc->miibus);
@@ -1695,6 +1736,8 @@ ed_setrcr(struct ed_softc *sc)
int i;
u_char reg1;
+ ED_ASSERT_LOCKED(sc);
+
/* Bit 6 in AX88190 RCR register must be set. */
if (sc->chip_type == ED_CHIP_TYPE_AX88190)
reg1 = ED_RCR_INTT;
@@ -1804,17 +1847,14 @@ int
ed_clear_memory(device_t dev)
{
struct ed_softc *sc = device_get_softc(dev);
- int i;
+ bus_size_t i;
- /*
- * Now zero memory and verify that it is clear
- * XXX restricted to 16-bit writes? Do we need to
- * XXX enable 16-bit access?
- */
- bzero(sc->mem_start, sc->mem_size);
+ bus_space_set_region_1(sc->mem_bst, sc->mem_bsh, sc->mem_start,
+ 0, sc->mem_size);
- for (i = 0; i < sc->mem_size; ++i) {
- if (sc->mem_start[i]) {
+ for (i = 0; i < sc->mem_size; i++) {
+ if (bus_space_read_1(sc->mem_bst, sc->mem_bsh,
+ sc->mem_start + i)) {
device_printf(dev, "failed to clear shared memory at "
"0x%jx - check configuration\n",
(uintmax_t)rman_get_start(sc->mem_res) + i);
diff --git a/sys/dev/ed/if_ed_3c503.c b/sys/dev/ed/if_ed_3c503.c
index 160c112cd434..c0fcd67f44b5 100644
--- a/sys/dev/ed/if_ed_3c503.c
+++ b/sys/dev/ed/if_ed_3c503.c
@@ -249,7 +249,7 @@ ed_probe_3Com(device_t dev, int port_rid, int flags)
if (error)
return (error);
- sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
+ sc->mem_start = 0;
sc->mem_size = memsize;
sc->mem_end = sc->mem_start + memsize;
diff --git a/sys/dev/ed/if_ed_cbus.c b/sys/dev/ed/if_ed_cbus.c
index 00b616fabb43..b892111a54f7 100644
--- a/sys/dev/ed/if_ed_cbus.c
+++ b/sys/dev/ed/if_ed_cbus.c
@@ -242,7 +242,7 @@ ed_cbus_attach(dev)
ed_alloc_irq(dev, sc->irq_rid, 0);
- error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
+ error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
edintr, sc, &sc->irq_handle);
if (error) {
ed_release_resources(dev);
@@ -616,7 +616,7 @@ ed98_alloc_memory(dev, rid)
if (error)
return (error);
- sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
+ sc->mem_start = 0;
sc->mem_size = conf_msize;
return (0);
@@ -839,9 +839,10 @@ ed_probe_SIC98(device_t dev, int port_rid, int flags)
* type code and ethernet address check out, then we know we have
* an SIC card.
*/
- sum = sc->mem_start[6 * 2];
+ sum = bus_space_read_1(sc->mem_bst, sc->mem_bsh, 6 * 2);
for (i = 0; i < ETHER_ADDR_LEN; i++)
- sum ^= (sc->enaddr[i] = sc->mem_start[i * 2]);
+ sum ^= (sc->enaddr[i] =
+ bus_space_read_1(sc->mem_bst, sc->mem_bsh, i * 2));
#ifdef ED_DEBUG
device_printf(dev, "ed_probe_sic98: got address %6D\n",
sc->enaddr, ":");
@@ -1064,7 +1065,8 @@ ed_probe_CNET98(device_t dev, int port_rid, int flags)
/*
* Get station address from on-board ROM
*/
- bcopy(sc->mem_start, sc->enaddr, ETHER_ADDR_LEN);
+ bus_space_read_region_1(sc->mem_bst, sc->mem_bsh, sc->mem_start,
+ sc->enaddr, ETHER_ADDR_LEN);
sc->vendor = ED_VENDOR_MISC;
sc->type_str = "CNET98";
@@ -1577,7 +1579,7 @@ ed_pio_testmem(struct ed_softc *sc, int page_offset, int isa16bit, int flags)
}
#endif
sc->mem_size = memsize;
- sc->mem_start = (char *) page_offset;
+ sc->mem_start = page_offset;
sc->mem_end = sc->mem_start + memsize;
sc->tx_page_start = page_offset / ED_PAGE_SIZE;
diff --git a/sys/dev/ed/if_ed_hpp.c b/sys/dev/ed/if_ed_hpp.c
index b7a8a862d026..28e07485f611 100644
--- a/sys/dev/ed/if_ed_hpp.c
+++ b/sys/dev/ed/if_ed_hpp.c
@@ -410,7 +410,8 @@ ed_hpp_set_physical_link(struct ed_softc *sc)
*/
void
-ed_hpp_readmem(struct ed_softc *sc, long src, uint8_t *dst, uint16_t amount)
+ed_hpp_readmem(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
+ uint16_t amount)
{
int use_32bit_access = !(sc->hpp_id & ED_HPP_ID_16_BIT_ACCESS);
@@ -434,10 +435,10 @@ ed_hpp_readmem(struct ed_softc *sc, long src, uint8_t *dst, uint16_t amount)
(uint32_t *) sc->hpp_mem_start;
uint32_t *const fence = dl + (amount >> 2);
- /* Copy out NIC data. We could probably write this
- as a `movsl'. The currently generated code is lousy.
- */
-
+ /*
+ * Copy out NIC data. We could probably write this
+ * as a `movsl'. The currently generated code is lousy.
+ */
while (dl < fence)
*dl++ = *sl;
diff --git a/sys/dev/ed/if_ed_isa.c b/sys/dev/ed/if_ed_isa.c
index f5da28a1e452..fcf9b2097621 100644
--- a/sys/dev/ed/if_ed_isa.c
+++ b/sys/dev/ed/if_ed_isa.c
@@ -43,11 +43,13 @@ __FBSDID("$FreeBSD$");
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
+#include <net/if_media.h>
#include <net/if_mib.h>
#include <isa/isavar.h>
#include <dev/ed/if_edvar.h>
+#include <dev/ed/if_edreg.h>
static int ed_isa_probe(device_t);
static int ed_isa_attach(device_t);
@@ -157,13 +159,17 @@ ed_isa_attach(device_t dev)
ed_alloc_irq(dev, sc->irq_rid, 0);
- error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
- edintr, sc, &sc->irq_handle);
+ error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
+ edintr, sc, &sc->irq_handle);
if (error) {
ed_release_resources(dev);
return (error);
}
+#ifdef ED_HPP
+ if (sc->vendor == ED_VENDOR_HP && sc->type == ED_TYPE_HP_PCLANPLUS)
+ sc->readmem = ed_hpp_readmem;
+#endif
return ed_attach(dev);
}
diff --git a/sys/dev/ed/if_ed_novell.c b/sys/dev/ed/if_ed_novell.c
index 09ac0cd18a91..2d763a2b4281 100644
--- a/sys/dev/ed/if_ed_novell.c
+++ b/sys/dev/ed/if_ed_novell.c
@@ -169,7 +169,7 @@ ed_probe_Novell_generic(device_t dev, int flags)
/* NIC memory doesn't start at zero on an NE board */
/* The start address is tied to the bus width */
- sc->mem_start = (char *) 8192 + sc->isa16bit * 8192;
+ sc->mem_start = 8192 + sc->isa16bit * 8192;
sc->mem_end = sc->mem_start + memsize;
sc->tx_page_start = memsize / ED_PAGE_SIZE;
@@ -218,7 +218,7 @@ static int
ed_probe_gwether(device_t dev)
{
int x, i, msize = 0;
- long mstart = 0;
+ bus_size_t mstart = 0;
char pbuf0[ED_PAGE_SIZE], pbuf[ED_PAGE_SIZE], tbuf[ED_PAGE_SIZE];
struct ed_softc *sc = device_get_softc(dev);
@@ -269,14 +269,17 @@ ed_probe_gwether(device_t dev)
if (msize == 0) {
device_printf(dev,
- "Cannot find any RAM, start : %ld, x = %d.\n", mstart, x);
+ "Cannot find any RAM, start : %d, x = %d.\n",
+ (int)mstart, x);
return (ENXIO);
}
- device_printf(dev, "RAM start at %ld, size : %d.\n", mstart, msize);
+ if (bootverbose)
+ device_printf(dev,
+ "RAM start at %d, size : %d.\n", (int)mstart, msize);
sc->mem_size = msize;
- sc->mem_start = (caddr_t)(uintptr_t) mstart;
- sc->mem_end = (caddr_t)(uintptr_t) (msize + mstart);
+ sc->mem_start = mstart;
+ sc->mem_end = msize + mstart;
sc->tx_page_start = mstart / ED_PAGE_SIZE;
return 0;
}
diff --git a/sys/dev/ed/if_ed_pccard.c b/sys/dev/ed/if_ed_pccard.c
index fa95e790d5b6..5e940d7b5b9c 100644
--- a/sys/dev/ed/if_ed_pccard.c
+++ b/sys/dev/ed/if_ed_pccard.c
@@ -80,9 +80,8 @@ MODULE_DEPEND(ed, ether, 1, 1, 1);
#define ED_DEFAULT_MAC_OFFSET 0xff0
/*
- * PC-Card (PCMCIA) specific code.
+ * PC Card (PCMCIA) specific code.
*/
-static int ed_pccard_match(device_t);
static int ed_pccard_probe(device_t);
static int ed_pccard_attach(device_t);
@@ -198,7 +197,7 @@ static const struct ed_product {
};
static int
-ed_pccard_match(device_t dev)
+ed_pccard_probe(device_t dev)
{
const struct ed_product *pp;
int error;
@@ -226,45 +225,6 @@ ed_pccard_match(device_t dev)
return (ENXIO);
}
-/*
- * Probe framework for pccards. Replicates the standard framework,
- * minus the pccard driver registration and ignores the ether address
- * supplied (from the CIS), relying on the probe to find it instead.
- */
-static int
-ed_pccard_probe(device_t dev)
-{
- const struct ed_product *pp;
- int error;
- struct ed_softc *sc = device_get_softc(dev);
-
- if ((pp = (const struct ed_product *) pccard_product_lookup(dev,
- (const struct pccard_product *) ed_pccard_products,
- sizeof(ed_pccard_products[0]), NULL)) == NULL)
- return (ENXIO);
- sc->port_rid = pp->edrid;
- if (pp->flags & NE2000DVF_DL100XX) {
- error = ed_probe_Novell(dev, sc->port_rid, 0);
- if (error == 0)
- error = ed_pccard_Linksys(dev);
- ed_release_resources(dev);
- if (error == 0)
- goto end2;
- }
- if (pp->flags & NE2000DVF_AX88X90) {
- error = ed_pccard_ax88x90(dev);
- if (error == 0)
- goto end2;
- }
- error = ed_probe_Novell(dev, sc->port_rid, 0);
-end2:
- if (error == 0)
- error = ed_alloc_irq(dev, 0, 0);
-
- ed_release_resources(dev);
- return (error);
-}
-
static int
ed_pccard_rom_mac(device_t dev, uint8_t *enaddr)
{
@@ -300,25 +260,44 @@ ed_pccard_add_modem(device_t dev, int rid)
static int
ed_pccard_attach(device_t dev)
{
- int error, i;
- struct ed_softc *sc = device_get_softc(dev);
u_char sum;
u_char enaddr[ETHER_ADDR_LEN];
const struct ed_product *pp;
-
+ int error, i;
+ struct ed_softc *sc = device_get_softc(dev);
+
if ((pp = (const struct ed_product *) pccard_product_lookup(dev,
(const struct pccard_product *) ed_pccard_products,
sizeof(ed_pccard_products[0]), NULL)) == NULL)
return (ENXIO);
sc->port_rid = pp->edrid;
- if (sc->port_used > 0)
- ed_alloc_port(dev, sc->port_rid, sc->port_used);
- if (sc->mem_used)
- ed_alloc_memory(dev, sc->mem_rid, sc->mem_used);
- ed_alloc_irq(dev, sc->irq_rid, 0);
-
- error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, edintr, sc,
- &sc->irq_handle);
+ if (pp->flags & NE2000DVF_DL100XX) {
+ error = ed_probe_Novell(dev, sc->port_rid, 0);
+ if (error == 0)
+ error = ed_pccard_Linksys(dev);
+ ed_release_resources(dev);
+ if (error == 0)
+ goto end2;
+ }
+ if (pp->flags & NE2000DVF_AX88X90) {
+ error = ed_pccard_ax88x90(dev);
+ if (error == 0)
+ goto end2;
+ }
+ error = ed_probe_Novell(dev, sc->port_rid, 0);
+end2:
+ if (error) {
+ ed_release_resources(dev);
+ return (error);
+ }
+ error = ed_alloc_irq(dev, 0, 0);
+ if (error) {
+ ed_release_resources(dev);
+ return (error);
+ }
+
+ error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
+ edintr, sc, &sc->irq_handle);
if (error) {
device_printf(dev, "setup intr failed %d \n", error);
ed_release_resources(dev);
@@ -376,9 +355,13 @@ ed_pccard_attach(device_t dev)
}
error = ed_attach(dev);
+ if (error) {
+ ed_release_resources(dev);
+ return (error);
+ }
#ifndef ED_NO_MIIBUS
- if (error == 0 && (sc->chip_type == ED_CHIP_TYPE_DL10019 ||
- sc->chip_type == ED_CHIP_TYPE_DL10022)) {
+ if (sc->chip_type == ED_CHIP_TYPE_DL10019 ||
+ sc->chip_type == ED_CHIP_TYPE_DL10022) {
/* Probe for an MII bus, but ignore errors. */
ed_pccard_dlink_mii_reset(sc);
sc->mii_readbits = ed_pccard_dlink_mii_readbits;
@@ -389,7 +372,7 @@ ed_pccard_attach(device_t dev)
#endif
if (pp->flags & NE2000DVF_MODEM)
ed_pccard_add_modem(dev, pp->siorid);
- return (error);
+ return (0);
}
static void
@@ -650,8 +633,8 @@ ed_pccard_dlink_mii_readbits(sc, nbits)
static device_method_t ed_pccard_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, pccard_compat_probe),
- DEVMETHOD(device_attach, pccard_compat_attach),
+ DEVMETHOD(device_probe, ed_pccard_probe),
+ DEVMETHOD(device_attach, ed_pccard_attach),
DEVMETHOD(device_detach, ed_detach),
#ifndef ED_NO_MIIBUS
@@ -663,10 +646,6 @@ static device_method_t ed_pccard_methods[] = {
DEVMETHOD(miibus_writereg, ed_miibus_writereg),
#endif
- /* Card interface */
- DEVMETHOD(card_compat_match, ed_pccard_match),
- DEVMETHOD(card_compat_probe, ed_pccard_probe),
- DEVMETHOD(card_compat_attach, ed_pccard_attach),
{ 0, 0 }
};
diff --git a/sys/dev/ed/if_ed_pci.c b/sys/dev/ed/if_ed_pci.c
index 398d340527fa..c9722c08e57f 100644
--- a/sys/dev/ed/if_ed_pci.c
+++ b/sys/dev/ed/if_ed_pci.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_arp.h>
+#include <net/if_media.h>
#include <net/if_mib.h>
#include <dev/pci/pcireg.h>
@@ -94,7 +95,7 @@ ed_pci_attach(device_t dev)
ed_release_resources(dev);
return (error);
}
- error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
+ error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
edintr, sc, &sc->irq_handle);
if (error) {
ed_release_resources(dev);
diff --git a/sys/dev/ed/if_ed_sic.c b/sys/dev/ed/if_ed_sic.c
index 471065f060e1..627202b88e98 100644
--- a/sys/dev/ed/if_ed_sic.c
+++ b/sys/dev/ed/if_ed_sic.c
@@ -85,7 +85,7 @@ ed_probe_SIC(device_t dev, int port_rid, int flags)
if (error)
return (error);
- sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
+ sc->mem_start = 0;
sc->mem_size = memsize;
pmem = rman_get_start(sc->mem_res);
@@ -105,9 +105,10 @@ ed_probe_SIC(device_t dev, int port_rid, int flags)
ed_asic_outb(sc, 0, 0x81);
DELAY(100);
- sum = sc->mem_start[6];
+ sum = bus_space_read_1(sc->mem_bst, sc->mem_bsh, 6);
for (i = 0; i < ETHER_ADDR_LEN; i++)
- sum ^= (sc->enaddr[i] = sc->mem_start[i]);
+ sum ^= (sc->enaddr[i] =
+ bus_space_read_1(sc->mem_bst, sc->mem_bsh, i));
#ifdef ED_DEBUG
device_printf(dev, "ed_probe_sic: got address %6D\n",
sc->enaddr, ":");
diff --git a/sys/dev/ed/if_ed_wd80x3.c b/sys/dev/ed/if_ed_wd80x3.c
index dabd7588909a..348fe8ebdfc9 100644
--- a/sys/dev/ed/if_ed_wd80x3.c
+++ b/sys/dev/ed/if_ed_wd80x3.c
@@ -258,7 +258,7 @@ ed_probe_WD80x3_generic(device_t dev, int flags, uint16_t *intr_vals[])
error = ed_alloc_memory(dev, 0, memsize);
if (error)
return (error);
- sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
+ sc->mem_start = 0;
#ifdef ED_DEBUG
printf("type = %x type_str=%s isa16bit=%d memsize=%d id_msize=%lu\n",
diff --git a/sys/dev/ed/if_edvar.h b/sys/dev/ed/if_edvar.h
index 43bbb593b23c..09e832501810 100644
--- a/sys/dev/ed/if_edvar.h
+++ b/sys/dev/ed/if_edvar.h
@@ -34,12 +34,14 @@
*/
struct ed_softc {
struct ifnet *ifp;
+ struct ifmedia ifmedia; /* Media info */
+ device_t dev;
+ struct mtx sc_mtx;
char *type_str; /* pointer to type string */
u_char vendor; /* interface vendor */
u_char type; /* interface type code */
u_char chip_type; /* the type of chip (one of ED_CHIP_TYPE_*) */
- u_char gone; /* HW missing, presumed having a good time */
u_char isa16bit; /* width of access to card 0=8 or 1=16 */
u_char mem_shared; /* NIC memory is shared with host */
u_char xmit_busy; /* transmitter is busy */
@@ -61,7 +63,9 @@ struct ed_softc {
device_t miibus; /* MII bus for cards with MII. */
void (*mii_writebits)(struct ed_softc *, u_int, int);
u_int (*mii_readbits)(struct ed_softc *, int);
- struct callout_handle tick_ch; /* Callout handle for ed_tick */
+ struct callout tick_ch;
+ void (*readmem)(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
+ uint16_t amount);
int nic_offset; /* NIC (DS8390) I/O bus address offset */
int asic_offset; /* ASIC I/O bus address offset */
@@ -81,10 +85,10 @@ struct ed_softc {
u_short hpp_id; /* software revision and other fields */
caddr_t hpp_mem_start; /* Memory-mapped IO register address */
- caddr_t mem_start; /* NIC memory start address */
- caddr_t mem_end; /* NIC memory end address */
+ bus_size_t mem_start; /* NIC memory start address */
+ bus_size_t mem_end; /* NIC memory end address */
uint32_t mem_size; /* total NIC memory size */
- caddr_t mem_ring; /* start of RX ring-buffer (in NIC mem) */
+ bus_size_t mem_ring; /* start of RX ring-buffer (in NIC mem) */
u_char txb_cnt; /* number of transmit buffers */
u_char txb_inuse; /* number of TX buffers currently in-use */
@@ -202,7 +206,9 @@ int ed_detach(device_t);
int ed_clear_memory(device_t);
int ed_isa_mem_ok(device_t, u_long, u_int); /* XXX isa specific */
void ed_stop(struct ed_softc *);
-void ed_pio_readmem(struct ed_softc *, long, uint8_t *, uint16_t);
+void ed_shmem_readmem16(struct ed_softc *, bus_size_t, uint8_t *, uint16_t);
+void ed_shmem_readmem8(struct ed_softc *, bus_size_t, uint8_t *, uint16_t);
+void ed_pio_readmem(struct ed_softc *, bus_size_t, uint8_t *, uint16_t);
void ed_pio_writemem(struct ed_softc *, uint8_t *, uint16_t, uint16_t);
#ifndef ED_NO_MIIBUS
int ed_miibus_readreg(device_t, int, int);
@@ -215,7 +221,7 @@ void ed_child_detached(device_t, device_t);
/* The following is unsatisfying XXX */
#ifdef ED_HPP
void ed_hpp_set_physical_link(struct ed_softc *);
-void ed_hpp_readmem(struct ed_softc *, long, uint8_t *, uint16_t);
+void ed_hpp_readmem(struct ed_softc *, bus_size_t, uint8_t *, uint16_t);
u_short ed_hpp_write_mbufs(struct ed_softc *, struct mbuf *, int);
#endif
@@ -272,4 +278,14 @@ extern devclass_t ed_devclass;
#define ED_FLAGS_GETTYPE(flg) ((flg) & 0xff0000)
+#define ED_MUTEX(_sc) (&(_sc)->sc_mtx)
+#define ED_LOCK(_sc) mtx_lock(ED_MUTEX(_sc))
+#define ED_UNLOCK(_sc) mtx_unlock(ED_MUTEX(_sc))
+#define ED_LOCK_INIT(_sc) \
+ mtx_init(ED_MUTEX(_sc), device_get_nameunit(_sc->dev), \
+ MTX_NETWORK_LOCK, MTX_DEF)
+#define ED_LOCK_DESTROY(_sc) mtx_destroy(ED_MUTEX(_sc));
+#define ED_ASSERT_LOCKED(_sc) mtx_assert(ED_MUTEX(_sc), MA_OWNED);
+#define ED_ASSERT_UNLOCKED(_sc) mtx_assert(ED_MUTEX(_sc), MA_NOTOWNED);
+
#endif /* SYS_DEV_ED_IF_EDVAR_H */