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
This commit is contained in:
Warner Losh 2005-08-28 23:56:25 +00:00
parent a6c109d658
commit f1c4694df3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=149558
11 changed files with 286 additions and 237 deletions

View file

@ -28,6 +28,11 @@
#include <sys/cdefs.h>
__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.
*/
@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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 }
};

View file

@ -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);

View file

@ -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, ":");

View file

@ -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",

View file

@ -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 */