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 @@ -28,6 +28,11 @@ #include __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 #include +#include 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. */ @@ -413,6 +422,19 @@ ed_stop(struct ed_softc *sc) continue; } +/* + * 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; - struct ifnet *ifp = sc->ifp; - int i, s; - if (sc->gone) - return; + 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; + + 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]; /* @@ -670,16 +690,24 @@ ed_xmit(struct ed_softc *sc) */ 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 @@ ed_start(struct ifnet *ifp) /* * Copy the mbuf chain into the transmit buffer */ - m0 = m; /* txb_new points to next open buffer slot */ @@ -758,11 +785,14 @@ ed_start(struct ifnet *ifp) } } 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 @@ ed_start(struct ifnet *ifp) } } } 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,13 +1403,42 @@ 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); } /* * Supporting routines */ +/* + * 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. @@ -1394,16 +1447,9 @@ ed_get_packet(struct ed_softc *sc, char *buf, u_short len) * 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 #include #include +#include #include #include #include +#include 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 #include +#include #include #include @@ -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 */