From 4b688a59eb900063ae3e4bc89db0f9faee56e0e5 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 4 Jun 2008 20:26:57 +0000 Subject: Style(9) xe(4). The MD5 sums are different, but comparing the dissassemblies the only changes are from gcc moving some global variables around slightly. --- sys/dev/xe/if_xe.c | 3052 +++++++++++++++++++++++---------------------- sys/dev/xe/if_xe_pccard.c | 49 +- sys/dev/xe/if_xevar.h | 86 +- 3 files changed, 1621 insertions(+), 1566 deletions(-) (limited to 'sys/dev/xe') diff --git a/sys/dev/xe/if_xe.c b/sys/dev/xe/if_xe.c index 7d7ba7c..e73d56a 100644 --- a/sys/dev/xe/if_xe.c +++ b/sys/dev/xe/if_xe.c @@ -126,64 +126,68 @@ __FBSDID("$FreeBSD$"); * MII command structure */ struct xe_mii_frame { - u_int8_t mii_stdelim; - u_int8_t mii_opcode; - u_int8_t mii_phyaddr; - u_int8_t mii_regaddr; - u_int8_t mii_turnaround; - u_int16_t mii_data; + uint8_t mii_stdelim; + uint8_t mii_opcode; + uint8_t mii_phyaddr; + uint8_t mii_regaddr; + uint8_t mii_turnaround; + uint16_t mii_data; }; /* * Media autonegotiation progress constants */ -#define XE_AUTONEG_NONE 0 /* No autonegotiation in progress */ -#define XE_AUTONEG_WAITING 1 /* Waiting for transmitter to go idle */ -#define XE_AUTONEG_STARTED 2 /* Waiting for autonegotiation to complete */ -#define XE_AUTONEG_100TX 3 /* Trying to force 100baseTX link */ -#define XE_AUTONEG_FAIL 4 /* Autonegotiation failed */ +#define XE_AUTONEG_NONE 0 /* No autonegotiation in progress */ +#define XE_AUTONEG_WAITING 1 /* Waiting for transmitter to go idle */ +#define XE_AUTONEG_STARTED 2 /* Waiting for autonegotiation to complete */ +#define XE_AUTONEG_100TX 3 /* Trying to force 100baseTX link */ +#define XE_AUTONEG_FAIL 4 /* Autonegotiation failed */ /* * Prototypes start here */ -static void xe_init (void *xscp); -static void xe_init_locked (struct xe_softc *scp); -static void xe_start (struct ifnet *ifp); -static void xe_start_locked (struct ifnet *ifp); -static int xe_ioctl (struct ifnet *ifp, u_long command, caddr_t data); -static void xe_watchdog (void *arg); -static void xe_intr (void *xscp); -static void xe_txintr (struct xe_softc *scp, u_int8_t txst1); -static void xe_macintr (struct xe_softc *scp, u_int8_t rst0, uint8_t txst0, uint8_t txst1); -static void xe_rxintr (struct xe_softc *scp, u_int8_t rst0); -static int xe_media_change (struct ifnet *ifp); -static void xe_media_status (struct ifnet *ifp, struct ifmediareq *mrp); -static timeout_t xe_setmedia; -static void xe_reset (struct xe_softc *scp); -static void xe_enable_intr (struct xe_softc *scp); -static void xe_disable_intr (struct xe_softc *scp); -static void xe_set_multicast (struct xe_softc *scp); -static void xe_set_addr (struct xe_softc *scp, u_int8_t* addr, unsigned idx); -static void xe_mchash (struct xe_softc *scp, const uint8_t *addr); -static int xe_pio_write_packet (struct xe_softc *scp, struct mbuf *mbp); +static void xe_init(void *xscp); +static void xe_init_locked(struct xe_softc *scp); +static void xe_start(struct ifnet *ifp); +static void xe_start_locked(struct ifnet *ifp); +static int xe_ioctl(struct ifnet *ifp, u_long command, caddr_t data); +static void xe_watchdog(void *arg); +static void xe_intr(void *xscp); +static void xe_txintr(struct xe_softc *scp, uint8_t txst1); +static void xe_macintr(struct xe_softc *scp, uint8_t rst0, uint8_t txst0, + uint8_t txst1); +static void xe_rxintr(struct xe_softc *scp, uint8_t rst0); +static int xe_media_change(struct ifnet *ifp); +static void xe_media_status(struct ifnet *ifp, struct ifmediareq *mrp); +static void xe_setmedia(void *arg); +static void xe_reset(struct xe_softc *scp); +static void xe_enable_intr(struct xe_softc *scp); +static void xe_disable_intr(struct xe_softc *scp); +static void xe_set_multicast(struct xe_softc *scp); +static void xe_set_addr(struct xe_softc *scp, uint8_t* addr, unsigned idx); +static void xe_mchash(struct xe_softc *scp, const uint8_t *addr); +static int xe_pio_write_packet(struct xe_softc *scp, struct mbuf *mbp); /* * MII functions */ -static void xe_mii_sync (struct xe_softc *scp); -static int xe_mii_init (struct xe_softc *scp); -static void xe_mii_send (struct xe_softc *scp, u_int32_t bits, int cnt); -static int xe_mii_readreg (struct xe_softc *scp, struct xe_mii_frame *frame); -static int xe_mii_writereg (struct xe_softc *scp, struct xe_mii_frame *frame); -static u_int16_t xe_phy_readreg (struct xe_softc *scp, u_int16_t reg); -static void xe_phy_writereg (struct xe_softc *scp, u_int16_t reg, u_int16_t data); +static void xe_mii_sync(struct xe_softc *scp); +static int xe_mii_init(struct xe_softc *scp); +static void xe_mii_send(struct xe_softc *scp, uint32_t bits, int cnt); +static int xe_mii_readreg(struct xe_softc *scp, + struct xe_mii_frame *frame); +static int xe_mii_writereg(struct xe_softc *scp, + struct xe_mii_frame *frame); +static uint16_t xe_phy_readreg(struct xe_softc *scp, uint16_t reg); +static void xe_phy_writereg(struct xe_softc *scp, uint16_t reg, + uint16_t data); /* * Debugging functions */ -static void xe_mii_dump (struct xe_softc *scp); +static void xe_mii_dump(struct xe_softc *scp); #if 0 -static void xe_reg_dump (struct xe_softc *scp); +static void xe_reg_dump(struct xe_softc *scp); #endif /* @@ -193,127 +197,125 @@ static void xe_reg_dump (struct xe_softc *scp); * 2 = Most function calls, ioctls and media selection progress * 3 = Everything - interrupts, packets in/out and multicast address setup */ -#define XE_DEBUG +#define XE_DEBUG #ifdef XE_DEBUG /* sysctl vars */ SYSCTL_NODE(_hw, OID_AUTO, xe, CTLFLAG_RD, 0, "if_xe parameters"); int xe_debug = 0; -SYSCTL_INT(_hw_xe, OID_AUTO, debug, CTLFLAG_RW, - &xe_debug, 0, "if_xe debug level"); +SYSCTL_INT(_hw_xe, OID_AUTO, debug, CTLFLAG_RW, &xe_debug, 0, + "if_xe debug level"); -#define DEVPRINTF(level, arg) if (xe_debug >= (level)) device_printf arg -#define DPRINTF(level, arg) if (xe_debug >= (level)) printf arg -#define XE_MII_DUMP(scp) if (xe_debug >= 3) xe_mii_dump(scp) +#define DEVPRINTF(level, arg) if (xe_debug >= (level)) device_printf arg +#define DPRINTF(level, arg) if (xe_debug >= (level)) printf arg +#define XE_MII_DUMP(scp) if (xe_debug >= 3) xe_mii_dump(scp) #if 0 -#define XE_REG_DUMP(scp) if (xe_debug >= 3) xe_reg_dump(scp) +#define XE_REG_DUMP(scp) if (xe_debug >= 3) xe_reg_dump(scp) #endif #else -#define DEVPRINTF(level, arg) -#define DPRINTF(level, arg) -#define XE_MII_DUMP(scp) +#define DEVPRINTF(level, arg) +#define DPRINTF(level, arg) +#define XE_MII_DUMP(scp) #if 0 -#define XE_REG_DUMP(scp) +#define XE_REG_DUMP(scp) #endif #endif - /* * Attach a device. */ int -xe_attach (device_t dev) +xe_attach(device_t dev) { - struct xe_softc *scp = device_get_softc(dev); - int err; - - DEVPRINTF(2, (dev, "attach\n")); - - /* Initialise stuff... */ - scp->dev = dev; - scp->ifp = if_alloc(IFT_ETHER); - if (scp->ifp == NULL) - return ENOSPC; - scp->ifm = &scp->ifmedia; - scp->autoneg_status = XE_AUTONEG_NONE; - mtx_init(&scp->lock, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); - callout_init_mtx(&scp->wdog_timer, &scp->lock, 0); - - /* Initialise the ifnet structure */ - scp->ifp->if_softc = scp; - if_initname(scp->ifp, device_get_name(dev), device_get_unit(dev)); - scp->ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); - scp->ifp->if_linkmib = &scp->mibdata; - scp->ifp->if_linkmiblen = sizeof scp->mibdata; - scp->ifp->if_start = xe_start; - scp->ifp->if_ioctl = xe_ioctl; - scp->ifp->if_init = xe_init; - scp->ifp->if_baudrate = 100000000; - IFQ_SET_MAXLEN(&scp->ifp->if_snd, IFQ_MAXLEN); - - /* Initialise the ifmedia structure */ - ifmedia_init(scp->ifm, 0, xe_media_change, xe_media_status); - callout_init_mtx(&scp->media_timer, &scp->lock, 0); - - /* Add supported media types */ - if (scp->mohawk) { - ifmedia_add(scp->ifm, IFM_ETHER|IFM_100_TX, 0, NULL); - ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); - ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL); - } - ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_T, 0, NULL); - if (scp->ce2) - ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_2, 0, NULL); - ifmedia_add(scp->ifm, IFM_ETHER|IFM_AUTO, 0, NULL); - - /* Default is to autoselect best supported media type */ - ifmedia_set(scp->ifm, IFM_ETHER|IFM_AUTO); - - /* Get the hardware into a known state */ - XE_LOCK(scp); - xe_reset(scp); - XE_UNLOCK(scp); - - /* Get hardware version numbers */ - XE_SELECT_PAGE(4); - scp->version = XE_INB(XE_BOV); - if (scp->mohawk) - scp->srev = (XE_INB(XE_BOV) & 0x70) >> 4; - else - scp->srev = (XE_INB(XE_BOV) & 0x30) >> 4; - - /* Print some useful information */ - device_printf(dev, "version 0x%02x/0x%02x%s%s\n", scp->version, - scp->srev, scp->mohawk ? ", 100Mbps capable" : "", - scp->modem ? ", with modem" : ""); - if (scp->mohawk) { - XE_SELECT_PAGE(0x10); - DEVPRINTF(1, (dev, "DingoID=0x%04x, RevisionID=0x%04x, VendorID=0x%04x\n", - XE_INW(XE_DINGOID), - XE_INW(XE_RevID), - XE_INW(XE_VendorID))); - } - if (scp->ce2) { - XE_SELECT_PAGE(0x45); - DEVPRINTF(1, (dev, "CE2 version = 0x%02x\n", XE_INB(XE_REV))); - } - - /* Attach the interface */ - ether_ifattach(scp->ifp, scp->enaddr); - - err = bus_setup_intr(dev, scp->irq_res, INTR_TYPE_NET | INTR_MPSAFE, NULL, - xe_intr, scp, &scp->intrhand); - if (err) { - ether_ifdetach(scp->ifp); - mtx_destroy(&scp->lock); - return err; - } - - /* Done */ - return 0; -} + struct xe_softc *scp = device_get_softc(dev); + int err; + + DEVPRINTF(2, (dev, "attach\n")); + + /* Initialise stuff... */ + scp->dev = dev; + scp->ifp = if_alloc(IFT_ETHER); + if (scp->ifp == NULL) + return (ENOSPC); + scp->ifm = &scp->ifmedia; + scp->autoneg_status = XE_AUTONEG_NONE; + mtx_init(&scp->lock, device_get_nameunit(dev), MTX_NETWORK_LOCK, + MTX_DEF); + callout_init_mtx(&scp->wdog_timer, &scp->lock, 0); + + /* Initialise the ifnet structure */ + scp->ifp->if_softc = scp; + if_initname(scp->ifp, device_get_name(dev), device_get_unit(dev)); + scp->ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); + scp->ifp->if_linkmib = &scp->mibdata; + scp->ifp->if_linkmiblen = sizeof(scp->mibdata); + scp->ifp->if_start = xe_start; + scp->ifp->if_ioctl = xe_ioctl; + scp->ifp->if_init = xe_init; + scp->ifp->if_baudrate = 100000000; + IFQ_SET_MAXLEN(&scp->ifp->if_snd, IFQ_MAXLEN); + + /* Initialise the ifmedia structure */ + ifmedia_init(scp->ifm, 0, xe_media_change, xe_media_status); + callout_init_mtx(&scp->media_timer, &scp->lock, 0); + + /* Add supported media types */ + if (scp->mohawk) { + ifmedia_add(scp->ifm, IFM_ETHER|IFM_100_TX, 0, NULL); + ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); + ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL); + } + ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_T, 0, NULL); + if (scp->ce2) + ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_2, 0, NULL); + ifmedia_add(scp->ifm, IFM_ETHER|IFM_AUTO, 0, NULL); + + /* Default is to autoselect best supported media type */ + ifmedia_set(scp->ifm, IFM_ETHER|IFM_AUTO); + + /* Get the hardware into a known state */ + XE_LOCK(scp); + xe_reset(scp); + XE_UNLOCK(scp); + + /* Get hardware version numbers */ + XE_SELECT_PAGE(4); + scp->version = XE_INB(XE_BOV); + if (scp->mohawk) + scp->srev = (XE_INB(XE_BOV) & 0x70) >> 4; + else + scp->srev = (XE_INB(XE_BOV) & 0x30) >> 4; + + /* Print some useful information */ + device_printf(dev, "version 0x%02x/0x%02x%s%s\n", scp->version, + scp->srev, scp->mohawk ? ", 100Mbps capable" : "", + scp->modem ? ", with modem" : ""); + if (scp->mohawk) { + XE_SELECT_PAGE(0x10); + DEVPRINTF(1, (dev, + "DingoID=0x%04x, RevisionID=0x%04x, VendorID=0x%04x\n", + XE_INW(XE_DINGOID), XE_INW(XE_RevID), XE_INW(XE_VendorID))); + } + if (scp->ce2) { + XE_SELECT_PAGE(0x45); + DEVPRINTF(1, (dev, "CE2 version = 0x%02x\n", XE_INB(XE_REV))); + } + + /* Attach the interface */ + ether_ifattach(scp->ifp, scp->enaddr); + err = bus_setup_intr(dev, scp->irq_res, INTR_TYPE_NET | INTR_MPSAFE, + NULL, xe_intr, scp, &scp->intrhand); + if (err) { + ether_ifdetach(scp->ifp); + mtx_destroy(&scp->lock); + return (err); + } + + /* Done */ + return (0); +} /* * Complete hardware intitialisation and enable output. Exits without doing @@ -321,121 +323,125 @@ xe_attach (device_t dev) * is in progress (the latter implies we've already run this function). */ static void -xe_init(void *xscp) { - struct xe_softc *scp = xscp; +xe_init(void *xscp) +{ + struct xe_softc *scp = xscp; - XE_LOCK(scp); - xe_init_locked(scp); - XE_UNLOCK(scp); + XE_LOCK(scp); + xe_init_locked(scp); + XE_UNLOCK(scp); } static void -xe_init_locked(struct xe_softc *scp) { - unsigned i; - - if (scp->autoneg_status != XE_AUTONEG_NONE) return; - - DEVPRINTF(2, (scp->dev, "init\n")); - - /* Reset transmitter flags */ - scp->tx_queued = 0; - scp->tx_tpr = 0; - scp->tx_timeouts = 0; - scp->tx_thres = 64; - scp->tx_min = ETHER_MIN_LEN - ETHER_CRC_LEN; - scp->tx_timeout = 0; - - /* Soft reset the card */ - XE_SELECT_PAGE(0); - XE_OUTB(XE_CR, XE_CR_SOFT_RESET); - DELAY(40000); - XE_OUTB(XE_CR, 0); - DELAY(40000); - - if (scp->mohawk) { - /* - * set GP1 and GP2 as outputs (bits 2 & 3) - * set GP1 low to power on the ML6692 (bit 0) - * set GP2 high to power on the 10Mhz chip (bit 1) - */ - XE_SELECT_PAGE(4); - XE_OUTB(XE_GPR0, XE_GPR0_GP2_SELECT|XE_GPR0_GP1_SELECT|XE_GPR0_GP2_OUT); - } - - /* Shut off interrupts */ - xe_disable_intr(scp); - - /* Wait for everything to wake up */ - DELAY(500000); - - /* Check for PHY */ - if (scp->mohawk) - scp->phy_ok = xe_mii_init(scp); - - /* Disable 'source insertion' (not sure what that means) */ - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC0, XE_SWC0_NO_SRC_INSERT); - - /* Set 8K/24K Tx/Rx buffer split */ - if (scp->srev != 1) { - XE_SELECT_PAGE(2); - XE_OUTW(XE_RBS, 0x2000); - } - - /* Enable early transmit mode on Mohawk/Dingo */ - if (scp->mohawk) { - XE_SELECT_PAGE(0x03); - XE_OUTW(XE_TPT, scp->tx_thres); - XE_SELECT_PAGE(0x01); - XE_OUTB(XE_ECR, XE_INB(XE_ECR) | XE_ECR_EARLY_TX); - } - - /* Put MAC address in first 'individual address' register */ - XE_SELECT_PAGE(0x50); - for (i = 0; i < 6; i++) - XE_OUTB(0x08 + i, IF_LLADDR(scp->ifp)[scp->mohawk ? 5 - i : i]); - - /* Set up multicast addresses */ - xe_set_multicast(scp); - - /* Fix the receive data offset -- reset can leave it off-by-one */ - XE_SELECT_PAGE(0); - XE_OUTW(XE_DO, 0x2000); - - /* Set interrupt masks */ - XE_SELECT_PAGE(1); - XE_OUTB(XE_IMR0, XE_IMR0_TX_PACKET | XE_IMR0_MAC_INTR | XE_IMR0_RX_PACKET); - - /* Set MAC interrupt masks */ - XE_SELECT_PAGE(0x40); - XE_OUTB(XE_RX0Msk, - ~(XE_RX0M_RX_OVERRUN | XE_RX0M_CRC_ERROR - | XE_RX0M_ALIGN_ERROR | XE_RX0M_LONG_PACKET)); - XE_OUTB(XE_TX0Msk, - ~(XE_TX0M_SQE_FAIL | XE_TX0M_LATE_COLLISION | XE_TX0M_TX_UNDERRUN - | XE_TX0M_16_COLLISIONS | XE_TX0M_NO_CARRIER)); - - /* Clear MAC status registers */ - XE_SELECT_PAGE(0x40); - XE_OUTB(XE_RST0, 0x00); - XE_OUTB(XE_TXST0, 0x00); - - /* Enable receiver and put MAC online */ - XE_SELECT_PAGE(0x40); - XE_OUTB(XE_CMD0, XE_CMD0_RX_ENABLE|XE_CMD0_ONLINE); - - /* Set up IMR, enable interrupts */ - xe_enable_intr(scp); - - /* Start media selection */ - xe_setmedia(scp); - - /* Enable output */ - scp->ifp->if_drv_flags |= IFF_DRV_RUNNING; - scp->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - callout_reset(&scp->wdog_timer, hz, xe_watchdog, scp); -} +xe_init_locked(struct xe_softc *scp) +{ + unsigned i; + + if (scp->autoneg_status != XE_AUTONEG_NONE) + return; + + DEVPRINTF(2, (scp->dev, "init\n")); + + /* Reset transmitter flags */ + scp->tx_queued = 0; + scp->tx_tpr = 0; + scp->tx_timeouts = 0; + scp->tx_thres = 64; + scp->tx_min = ETHER_MIN_LEN - ETHER_CRC_LEN; + scp->tx_timeout = 0; + + /* Soft reset the card */ + XE_SELECT_PAGE(0); + XE_OUTB(XE_CR, XE_CR_SOFT_RESET); + DELAY(40000); + XE_OUTB(XE_CR, 0); + DELAY(40000); + + if (scp->mohawk) { + /* + * set GP1 and GP2 as outputs (bits 2 & 3) + * set GP1 low to power on the ML6692 (bit 0) + * set GP2 high to power on the 10Mhz chip (bit 1) + */ + XE_SELECT_PAGE(4); + XE_OUTB(XE_GPR0, XE_GPR0_GP2_SELECT | XE_GPR0_GP1_SELECT | + XE_GPR0_GP2_OUT); + } + + /* Shut off interrupts */ + xe_disable_intr(scp); + + /* Wait for everything to wake up */ + DELAY(500000); + + /* Check for PHY */ + if (scp->mohawk) + scp->phy_ok = xe_mii_init(scp); + + /* Disable 'source insertion' (not sure what that means) */ + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC0, XE_SWC0_NO_SRC_INSERT); + + /* Set 8K/24K Tx/Rx buffer split */ + if (scp->srev != 1) { + XE_SELECT_PAGE(2); + XE_OUTW(XE_RBS, 0x2000); + } + + /* Enable early transmit mode on Mohawk/Dingo */ + if (scp->mohawk) { + XE_SELECT_PAGE(0x03); + XE_OUTW(XE_TPT, scp->tx_thres); + XE_SELECT_PAGE(0x01); + XE_OUTB(XE_ECR, XE_INB(XE_ECR) | XE_ECR_EARLY_TX); + } + /* Put MAC address in first 'individual address' register */ + XE_SELECT_PAGE(0x50); + for (i = 0; i < ETHER_ADDR_LEN; i++) + XE_OUTB(0x08 + i, IF_LLADDR(scp->ifp)[scp->mohawk ? 5 - i : i]); + + /* Set up multicast addresses */ + xe_set_multicast(scp); + + /* Fix the receive data offset -- reset can leave it off-by-one */ + XE_SELECT_PAGE(0); + XE_OUTW(XE_DO, 0x2000); + + /* Set interrupt masks */ + XE_SELECT_PAGE(1); + XE_OUTB(XE_IMR0, XE_IMR0_TX_PACKET | XE_IMR0_MAC_INTR | + XE_IMR0_RX_PACKET); + + /* Set MAC interrupt masks */ + XE_SELECT_PAGE(0x40); + XE_OUTB(XE_RX0Msk, + ~(XE_RX0M_RX_OVERRUN | XE_RX0M_CRC_ERROR | XE_RX0M_ALIGN_ERROR | + XE_RX0M_LONG_PACKET)); + XE_OUTB(XE_TX0Msk, + ~(XE_TX0M_SQE_FAIL | XE_TX0M_LATE_COLLISION | XE_TX0M_TX_UNDERRUN | + XE_TX0M_16_COLLISIONS | XE_TX0M_NO_CARRIER)); + + /* Clear MAC status registers */ + XE_SELECT_PAGE(0x40); + XE_OUTB(XE_RST0, 0x00); + XE_OUTB(XE_TXST0, 0x00); + + /* Enable receiver and put MAC online */ + XE_SELECT_PAGE(0x40); + XE_OUTB(XE_CMD0, XE_CMD0_RX_ENABLE|XE_CMD0_ONLINE); + + /* Set up IMR, enable interrupts */ + xe_enable_intr(scp); + + /* Start media selection */ + xe_setmedia(scp); + + /* Enable output */ + scp->ifp->if_drv_flags |= IFF_DRV_RUNNING; + scp->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + callout_reset(&scp->wdog_timer, hz, xe_watchdog, scp); +} /* * Start output on interface. Should be called at splimp() priority. Check @@ -444,130 +450,133 @@ xe_init_locked(struct xe_softc *scp) { * and return immediately. */ static void -xe_start(struct ifnet *ifp) { - struct xe_softc *scp = ifp->if_softc; +xe_start(struct ifnet *ifp) +{ + struct xe_softc *scp = ifp->if_softc; - XE_LOCK(scp); - xe_start_locked(ifp); - XE_UNLOCK(scp); + XE_LOCK(scp); + xe_start_locked(ifp); + XE_UNLOCK(scp); } static void -xe_start_locked(struct ifnet *ifp) { - struct xe_softc *scp = ifp->if_softc; - struct mbuf *mbp; - - if (scp->autoneg_status != XE_AUTONEG_NONE) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - return; - } - - DEVPRINTF(3, (scp->dev, "start\n")); - - /* - * Loop while there are packets to be sent, and space to send them. - */ - while (1) { - /* Suck a packet off the send queue */ - IF_DEQUEUE(&ifp->if_snd, mbp); - - if (mbp == NULL) { - /* - * We are using the !OACTIVE flag to indicate to the outside world that - * we can accept an additional packet rather than that the transmitter - * is _actually_ active. Indeed, the transmitter may be active, but if - * we haven't filled all the buffers with data then we still want to - * accept more. - */ - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - return; - } - - if (xe_pio_write_packet(scp, mbp) != 0) { - /* Push the packet back onto the queue */ - IF_PREPEND(&ifp->if_snd, mbp); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - return; - } - - /* Tap off here if there is a bpf listener */ - BPF_MTAP(ifp, mbp); - - /* In case we don't hear from the card again... */ - scp->tx_timeout = 5; - scp->tx_queued++; - - m_freem(mbp); - } -} +xe_start_locked(struct ifnet *ifp) +{ + struct xe_softc *scp = ifp->if_softc; + struct mbuf *mbp; + + if (scp->autoneg_status != XE_AUTONEG_NONE) { + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + return; + } + + DEVPRINTF(3, (scp->dev, "start\n")); + /* + * Loop while there are packets to be sent, and space to send + * them. + */ + for (;;) { + /* Suck a packet off the send queue */ + IF_DEQUEUE(&ifp->if_snd, mbp); + + if (mbp == NULL) { + /* + * We are using the !OACTIVE flag to indicate + * to the outside world that we can accept an + * additional packet rather than that the + * transmitter is _actually_ active. Indeed, + * the transmitter may be active, but if we + * haven't filled all the buffers with data + * then we still want to accept more. + */ + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + return; + } + + if (xe_pio_write_packet(scp, mbp) != 0) { + /* Push the packet back onto the queue */ + IF_PREPEND(&ifp->if_snd, mbp); + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + return; + } + + /* Tap off here if there is a bpf listener */ + BPF_MTAP(ifp, mbp); + + /* In case we don't hear from the card again... */ + scp->tx_timeout = 5; + scp->tx_queued++; + + m_freem(mbp); + } +} /* * Process an ioctl request. Adapted from the ed driver. */ static int -xe_ioctl (register struct ifnet *ifp, u_long command, caddr_t data) { - struct xe_softc *scp; - int error; - - scp = ifp->if_softc; - error = 0; - - switch (command) { - - case SIOCSIFFLAGS: - DEVPRINTF(2, (scp->dev, "ioctl: SIOCSIFFLAGS: 0x%04x\n", ifp->if_flags)); - /* - * If the interface is marked up and stopped, then start it. If it is - * marked down and running, then stop it. - */ - XE_LOCK(scp); - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - xe_reset(scp); - xe_init_locked(scp); - } - } - else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - xe_stop(scp); - } - /* handle changes to PROMISC/ALLMULTI flags */ - xe_set_multicast(scp); - XE_UNLOCK(scp); - error = 0; - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - DEVPRINTF(2, (scp->dev, "ioctl: SIOC{ADD,DEL}MULTI\n")); - /* - * Multicast list has (maybe) changed; set the hardware filters - * accordingly. - */ - XE_LOCK(scp); - xe_set_multicast(scp); - XE_UNLOCK(scp); - error = 0; - break; - - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - DEVPRINTF(3, (scp->dev, "ioctl: bounce to ifmedia_ioctl\n")); - /* - * Someone wants to get/set media options. - */ - error = ifmedia_ioctl(ifp, (struct ifreq *)data, &scp->ifmedia, command); - break; - - default: - DEVPRINTF(3, (scp->dev, "ioctl: bounce to ether_ioctl\n")); - error = ether_ioctl(ifp, command, data); - } - - return error; -} +xe_ioctl(struct ifnet *ifp, u_long command, caddr_t data) +{ + struct xe_softc *scp; + int error; + scp = ifp->if_softc; + error = 0; + + switch (command) { + case SIOCSIFFLAGS: + DEVPRINTF(2, (scp->dev, "ioctl: SIOCSIFFLAGS: 0x%04x\n", + ifp->if_flags)); + /* + * If the interface is marked up and stopped, then + * start it. If it is marked down and running, then + * stop it. + */ + XE_LOCK(scp); + if (ifp->if_flags & IFF_UP) { + if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + xe_reset(scp); + xe_init_locked(scp); + } + } else { + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + xe_stop(scp); + } + + /* handle changes to PROMISC/ALLMULTI flags */ + xe_set_multicast(scp); + XE_UNLOCK(scp); + error = 0; + break; + case SIOCADDMULTI: + case SIOCDELMULTI: + DEVPRINTF(2, (scp->dev, "ioctl: SIOC{ADD,DEL}MULTI\n")); + /* + * Multicast list has (maybe) changed; set the + * hardware filters accordingly. + */ + XE_LOCK(scp); + xe_set_multicast(scp); + XE_UNLOCK(scp); + error = 0; + break; + case SIOCSIFMEDIA: + case SIOCGIFMEDIA: + DEVPRINTF(3, (scp->dev, "ioctl: bounce to ifmedia_ioctl\n")); + /* + * Someone wants to get/set media options. + */ + error = ifmedia_ioctl(ifp, (struct ifreq *)data, &scp->ifmedia, + command); + break; + default: + DEVPRINTF(3, (scp->dev, "ioctl: bounce to ether_ioctl\n")); + error = ether_ioctl(ifp, command, data); + } + + return (error); +} /* * Card interrupt handler. @@ -588,301 +597,315 @@ xe_ioctl (register struct ifnet *ifp, u_long command, caddr_t data) { * how to do memory-mapped I/O :) */ static void -xe_txintr(struct xe_softc *scp, u_int8_t txst1) +xe_txintr(struct xe_softc *scp, uint8_t txst1) { - struct ifnet *ifp; - u_int8_t tpr, sent, coll; + struct ifnet *ifp; + uint8_t tpr, sent, coll; - ifp = scp->ifp; + ifp = scp->ifp; - /* Update packet count, accounting for rollover */ - tpr = XE_INB(XE_TPR); - sent = -scp->tx_tpr + tpr; + /* Update packet count, accounting for rollover */ + tpr = XE_INB(XE_TPR); + sent = -scp->tx_tpr + tpr; - /* Update statistics if we actually sent anything */ - if (sent > 0) { - coll = txst1 & XE_TXST1_RETRY_COUNT; - scp->tx_tpr = tpr; - scp->tx_queued -= sent; - ifp->if_opackets += sent; - ifp->if_collisions += coll; + /* Update statistics if we actually sent anything */ + if (sent > 0) { + coll = txst1 & XE_TXST1_RETRY_COUNT; + scp->tx_tpr = tpr; + scp->tx_queued -= sent; + ifp->if_opackets += sent; + ifp->if_collisions += coll; - /* - * According to the Xircom manual, Dingo will sometimes manage to - * transmit a packet with triggering an interrupt. If this happens, - * we have sent > 1 and the collision count only reflects collisions - * on the last packet sent (the one that triggered the interrupt). - * Collision stats might therefore be a bit low, but there doesn't - * seem to be anything we can do about that. - */ - - switch (coll) { - case 0: - break; - case 1: - scp->mibdata.dot3StatsSingleCollisionFrames++; - scp->mibdata.dot3StatsCollFrequencies[0]++; - break; - default: - scp->mibdata.dot3StatsMultipleCollisionFrames++; - scp->mibdata.dot3StatsCollFrequencies[coll-1]++; + /* + * According to the Xircom manual, Dingo will + * sometimes manage to transmit a packet with + * triggering an interrupt. If this happens, we have + * sent > 1 and the collision count only reflects + * collisions on the last packet sent (the one that + * triggered the interrupt). Collision stats might + * therefore be a bit low, but there doesn't seem to + * be anything we can do about that. + */ + switch (coll) { + case 0: + break; + case 1: + scp->mibdata.dot3StatsSingleCollisionFrames++; + scp->mibdata.dot3StatsCollFrequencies[0]++; + break; + default: + scp->mibdata.dot3StatsMultipleCollisionFrames++; + scp->mibdata.dot3StatsCollFrequencies[coll-1]++; + } } - } - scp->tx_timeout = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + scp->tx_timeout = 0; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } /* Handle most MAC interrupts */ static void -xe_macintr(struct xe_softc *scp, u_int8_t rst0, uint8_t txst0, uint8_t txst1) +xe_macintr(struct xe_softc *scp, uint8_t rst0, uint8_t txst0, uint8_t txst1) { - struct ifnet *ifp; + struct ifnet *ifp; - ifp = scp->ifp; + ifp = scp->ifp; #if 0 - /* Carrier sense lost -- only in 10Mbit HDX mode */ - if (txst0 & XE_TXST0_NO_CARRIER || !(txst1 & XE_TXST1_LINK_STATUS)) { - /* XXX - Need to update media status here */ - device_printf(scp->dev, "no carrier\n"); - ifp->if_oerrors++; - scp->mibdata.dot3StatsCarrierSenseErrors++; - } + /* Carrier sense lost -- only in 10Mbit HDX mode */ + if (txst0 & XE_TXST0_NO_CARRIER || !(txst1 & XE_TXST1_LINK_STATUS)) { + /* XXX - Need to update media status here */ + device_printf(scp->dev, "no carrier\n"); + ifp->if_oerrors++; + scp->mibdata.dot3StatsCarrierSenseErrors++; + } #endif - /* Excessive collisions -- try sending again */ - if (txst0 & XE_TXST0_16_COLLISIONS) { - ifp->if_collisions += 16; - ifp->if_oerrors++; - scp->mibdata.dot3StatsExcessiveCollisions++; - scp->mibdata.dot3StatsMultipleCollisionFrames++; - scp->mibdata.dot3StatsCollFrequencies[15]++; - XE_OUTB(XE_CR, XE_CR_RESTART_TX); - } - /* Transmit underrun -- increase early transmit threshold */ - if (txst0 & XE_TXST0_TX_UNDERRUN && scp->mohawk) { - DEVPRINTF(1, (scp->dev, "transmit underrun")); - if (scp->tx_thres < ETHER_MAX_LEN) { - if ((scp->tx_thres += 64) > ETHER_MAX_LEN) - scp->tx_thres = ETHER_MAX_LEN; - DPRINTF(1, (": increasing transmit threshold to %u", scp->tx_thres)); - XE_SELECT_PAGE(0x3); - XE_OUTW(XE_TPT, scp->tx_thres); - XE_SELECT_PAGE(0x0); + /* Excessive collisions -- try sending again */ + if (txst0 & XE_TXST0_16_COLLISIONS) { + ifp->if_collisions += 16; + ifp->if_oerrors++; + scp->mibdata.dot3StatsExcessiveCollisions++; + scp->mibdata.dot3StatsMultipleCollisionFrames++; + scp->mibdata.dot3StatsCollFrequencies[15]++; + XE_OUTB(XE_CR, XE_CR_RESTART_TX); } - DPRINTF(1, ("\n")); - ifp->if_oerrors++; - scp->mibdata.dot3StatsInternalMacTransmitErrors++; - } - /* Late collision -- just complain about it */ - if (txst0 & XE_TXST0_LATE_COLLISION) { - device_printf(scp->dev, "late collision\n"); - ifp->if_oerrors++; - scp->mibdata.dot3StatsLateCollisions++; - } - /* SQE test failure -- just complain about it */ - if (txst0 & XE_TXST0_SQE_FAIL) { - device_printf(scp->dev, "SQE test failure\n"); - ifp->if_oerrors++; - scp->mibdata.dot3StatsSQETestErrors++; - } - /* Packet too long -- what happens to these */ - if (rst0 & XE_RST0_LONG_PACKET) { - device_printf(scp->dev, "received giant packet\n"); - ifp->if_ierrors++; - scp->mibdata.dot3StatsFrameTooLongs++; - } - /* CRC error -- packet dropped */ - if (rst0 & XE_RST0_CRC_ERROR) { - device_printf(scp->dev, "CRC error\n"); - ifp->if_ierrors++; - scp->mibdata.dot3StatsFCSErrors++; - } -} - -static void -xe_rxintr(struct xe_softc *scp, u_int8_t rst0) -{ - struct ifnet *ifp; - u_int8_t esr, rsr; - - ifp = scp->ifp; - - /* Handle received packet(s) */ - while ((esr = XE_INB(XE_ESR)) & XE_ESR_FULL_PACKET_RX) { - rsr = XE_INB(XE_RSR); - - DEVPRINTF(3, (scp->dev, "intr: ESR=0x%02x, RSR=0x%02x\n", esr, rsr)); - - /* Make sure packet is a good one */ - if (rsr & XE_RSR_RX_OK) { - struct ether_header *ehp; - struct mbuf *mbp; - u_int16_t len; - - len = XE_INW(XE_RBC) - ETHER_CRC_LEN; - - DEVPRINTF(3, (scp->dev, "intr: receive length = %d\n", len)); - if (len == 0) { - ifp->if_iqdrops++; - continue; + /* Transmit underrun -- increase early transmit threshold */ + if (txst0 & XE_TXST0_TX_UNDERRUN && scp->mohawk) { + DEVPRINTF(1, (scp->dev, "transmit underrun")); + if (scp->tx_thres < ETHER_MAX_LEN) { + if ((scp->tx_thres += 64) > ETHER_MAX_LEN) + scp->tx_thres = ETHER_MAX_LEN; + DPRINTF(1, (": increasing transmit threshold to %u", + scp->tx_thres)); + XE_SELECT_PAGE(0x3); + XE_OUTW(XE_TPT, scp->tx_thres); + XE_SELECT_PAGE(0x0); + } + DPRINTF(1, ("\n")); + ifp->if_oerrors++; + scp->mibdata.dot3StatsInternalMacTransmitErrors++; } - /* - * Allocate mbuf to hold received packet. If the mbuf header isn't - * big enough, we attach an mbuf cluster to hold the packet. Note the - * +=2 to align the packet data on a 32-bit boundary, and the +3 to - * allow for the possibility of reading one more byte than the actual - * packet length (we always read 16-bit words). - * XXX - Surely there's a better way to do this alignment? - */ - MGETHDR(mbp, M_DONTWAIT, MT_DATA); - if (mbp == NULL) { - ifp->if_iqdrops++; - continue; + /* Late collision -- just complain about it */ + if (txst0 & XE_TXST0_LATE_COLLISION) { + device_printf(scp->dev, "late collision\n"); + ifp->if_oerrors++; + scp->mibdata.dot3StatsLateCollisions++; } - if (len + 3 > MHLEN) { - MCLGET(mbp, M_DONTWAIT); - if ((mbp->m_flags & M_EXT) == 0) { - m_freem(mbp); - ifp->if_iqdrops++; - continue; - } + /* SQE test failure -- just complain about it */ + if (txst0 & XE_TXST0_SQE_FAIL) { + device_printf(scp->dev, "SQE test failure\n"); + ifp->if_oerrors++; + scp->mibdata.dot3StatsSQETestErrors++; } - mbp->m_data += 2; - ehp = mtod(mbp, struct ether_header *); + /* Packet too long -- what happens to these */ + if (rst0 & XE_RST0_LONG_PACKET) { + device_printf(scp->dev, "received giant packet\n"); + ifp->if_ierrors++; + scp->mibdata.dot3StatsFrameTooLongs++; + } - /* - * Now get the packet in PIO mode, including the Ethernet header but - * omitting the trailing CRC. - */ + /* CRC error -- packet dropped */ + if (rst0 & XE_RST0_CRC_ERROR) { + device_printf(scp->dev, "CRC error\n"); + ifp->if_ierrors++; + scp->mibdata.dot3StatsFCSErrors++; + } +} - /* - * Work around a bug in CE2 cards. There seems to be a problem with - * duplicated and extraneous bytes in the receive buffer, but without - * any real documentation for the CE2 it's hard to tell for sure. - * XXX - Needs testing on CE2 hardware - */ - if (scp->srev == 0) { - u_short rhs; - - XE_SELECT_PAGE(5); - rhs = XE_INW(XE_RHSA); - XE_SELECT_PAGE(0); - - rhs += 3; /* Skip control info */ - - if (rhs >= 0x8000) - rhs = 0; - - if (rhs + len > 0x8000) { - int i; - - for (i = 0; i < len; i++, rhs++) { - ((char *)ehp)[i] = XE_INB(XE_EDP); - if (rhs == 0x8000) { - rhs = 0; - i--; - } - } - } - else - bus_read_multi_2(scp->port_res, XE_EDP, - (u_int16_t *) ehp, (len + 1) >> 1); +static void +xe_rxintr(struct xe_softc *scp, uint8_t rst0) +{ + struct ifnet *ifp; + uint8_t esr, rsr; + + ifp = scp->ifp; + + /* Handle received packet(s) */ + while ((esr = XE_INB(XE_ESR)) & XE_ESR_FULL_PACKET_RX) { + rsr = XE_INB(XE_RSR); + + DEVPRINTF(3, (scp->dev, "intr: ESR=0x%02x, RSR=0x%02x\n", esr, + rsr)); + + /* Make sure packet is a good one */ + if (rsr & XE_RSR_RX_OK) { + struct ether_header *ehp; + struct mbuf *mbp; + uint16_t len; + + len = XE_INW(XE_RBC) - ETHER_CRC_LEN; + + DEVPRINTF(3, (scp->dev, "intr: receive length = %d\n", + len)); + + if (len == 0) { + ifp->if_iqdrops++; + continue; + } + + /* + * Allocate mbuf to hold received packet. If + * the mbuf header isn't big enough, we attach + * an mbuf cluster to hold the packet. Note + * the +=2 to align the packet data on a + * 32-bit boundary, and the +3 to allow for + * the possibility of reading one more byte + * than the actual packet length (we always + * read 16-bit words). XXX - Surely there's a + * better way to do this alignment? + */ + MGETHDR(mbp, M_DONTWAIT, MT_DATA); + if (mbp == NULL) { + ifp->if_iqdrops++; + continue; + } + + if (len + 3 > MHLEN) { + MCLGET(mbp, M_DONTWAIT); + if ((mbp->m_flags & M_EXT) == 0) { + m_freem(mbp); + ifp->if_iqdrops++; + continue; + } + } + + mbp->m_data += 2; + ehp = mtod(mbp, struct ether_header *); + + /* + * Now get the packet in PIO mode, including + * the Ethernet header but omitting the + * trailing CRC. + */ + + /* + * Work around a bug in CE2 cards. There + * seems to be a problem with duplicated and + * extraneous bytes in the receive buffer, but + * without any real documentation for the CE2 + * it's hard to tell for sure. XXX - Needs + * testing on CE2 hardware + */ + if (scp->srev == 0) { + u_short rhs; + + XE_SELECT_PAGE(5); + rhs = XE_INW(XE_RHSA); + XE_SELECT_PAGE(0); + + rhs += 3; /* Skip control info */ + + if (rhs >= 0x8000) + rhs = 0; + + if (rhs + len > 0x8000) { + int i; + + for (i = 0; i < len; i++, rhs++) { + ((char *)ehp)[i] = + XE_INB(XE_EDP); + if (rhs == 0x8000) { + rhs = 0; + i--; + } + } + } else + bus_read_multi_2(scp->port_res, XE_EDP, + (uint16_t *)ehp, (len + 1) >> 1); + } else + bus_read_multi_2(scp->port_res, XE_EDP, + (uint16_t *)ehp, (len + 1) >> 1); + + /* Deliver packet to upper layers */ + mbp->m_pkthdr.rcvif = ifp; + mbp->m_pkthdr.len = mbp->m_len = len; + XE_UNLOCK(scp); + (*ifp->if_input)(ifp, mbp); + XE_LOCK(scp); + ifp->if_ipackets++; + + } else if (rsr & XE_RSR_ALIGN_ERROR) { + /* Packet alignment error -- drop packet */ + device_printf(scp->dev, "alignment error\n"); + scp->mibdata.dot3StatsAlignmentErrors++; + ifp->if_ierrors++; + } + + /* Skip to next packet, if there is one */ + XE_OUTW(XE_DO, 0x8000); } - else - bus_read_multi_2(scp->port_res, XE_EDP, - (u_int16_t *) ehp, (len + 1) >> 1); - /* Deliver packet to upper layers */ - mbp->m_pkthdr.rcvif = ifp; - mbp->m_pkthdr.len = mbp->m_len = len; - XE_UNLOCK(scp); - (*ifp->if_input)(ifp, mbp); - XE_LOCK(scp); - ifp->if_ipackets++; - } - - /* Packet alignment error -- drop packet */ - else if (rsr & XE_RSR_ALIGN_ERROR) { - device_printf(scp->dev, "alignment error\n"); - scp->mibdata.dot3StatsAlignmentErrors++; - ifp->if_ierrors++; - } - - /* Skip to next packet, if there is one */ - XE_OUTW(XE_DO, 0x8000); - } - - /* Clear receiver overruns now we have some free buffer space */ - if (rst0 & XE_RST0_RX_OVERRUN) { - DEVPRINTF(1, (scp->dev, "receive overrun\n")); - ifp->if_ierrors++; - scp->mibdata.dot3StatsInternalMacReceiveErrors++; - XE_OUTB(XE_CR, XE_CR_CLEAR_OVERRUN); - } + /* Clear receiver overruns now we have some free buffer space */ + if (rst0 & XE_RST0_RX_OVERRUN) { + DEVPRINTF(1, (scp->dev, "receive overrun\n")); + ifp->if_ierrors++; + scp->mibdata.dot3StatsInternalMacReceiveErrors++; + XE_OUTB(XE_CR, XE_CR_CLEAR_OVERRUN); + } } static void -xe_intr(void *xscp) +xe_intr(void *xscp) { - struct xe_softc *scp = (struct xe_softc *) xscp; - struct ifnet *ifp; - u_int8_t psr, isr, rst0, txst0, txst1; + struct xe_softc *scp = (struct xe_softc *) xscp; + struct ifnet *ifp; + uint8_t psr, isr, rst0, txst0, txst1; - ifp = scp->ifp; - XE_LOCK(scp); + ifp = scp->ifp; + XE_LOCK(scp); - /* Disable interrupts */ - if (scp->mohawk) - XE_OUTB(XE_CR, 0); + /* Disable interrupts */ + if (scp->mohawk) + XE_OUTB(XE_CR, 0); - /* Cache current register page */ - psr = XE_INB(XE_PR); + /* Cache current register page */ + psr = XE_INB(XE_PR); - /* Read ISR to see what caused this interrupt */ - while ((isr = XE_INB(XE_ISR)) != 0) { + /* Read ISR to see what caused this interrupt */ + while ((isr = XE_INB(XE_ISR)) != 0) { - /* 0xff might mean the card is no longer around */ - if (isr == 0xff) { - DEVPRINTF(3, (scp->dev, "intr: interrupt received for missing card?\n")); - break; - } + /* 0xff might mean the card is no longer around */ + if (isr == 0xff) { + DEVPRINTF(3, (scp->dev, + "intr: interrupt received for missing card?\n")); + break; + } - /* Read other status registers */ - XE_SELECT_PAGE(0x40); - rst0 = XE_INB(XE_RST0); - XE_OUTB(XE_RST0, 0); - txst0 = XE_INB(XE_TXST0); - txst1 = XE_INB(XE_TXST1); - XE_OUTB(XE_TXST0, 0); - XE_OUTB(XE_TXST1, 0); - XE_SELECT_PAGE(0); + /* Read other status registers */ + XE_SELECT_PAGE(0x40); + rst0 = XE_INB(XE_RST0); + XE_OUTB(XE_RST0, 0); + txst0 = XE_INB(XE_TXST0); + txst1 = XE_INB(XE_TXST1); + XE_OUTB(XE_TXST0, 0); + XE_OUTB(XE_TXST1, 0); + XE_SELECT_PAGE(0); - DEVPRINTF(3, (scp->dev, "intr: ISR=0x%02x, RST=0x%02x, TXT=0x%02x%02x\n", isr, rst0, txst1, txst0)); + DEVPRINTF(3, (scp->dev, + "intr: ISR=0x%02x, RST=0x%02x, TXT=0x%02x%02x\n", isr, + rst0, txst1, txst0)); - if (isr & XE_ISR_TX_PACKET) - xe_txintr(scp, txst1); + if (isr & XE_ISR_TX_PACKET) + xe_txintr(scp, txst1); - if (isr & XE_ISR_MAC_INTR) - xe_macintr(scp, rst0, txst0, txst1); + if (isr & XE_ISR_MAC_INTR) + xe_macintr(scp, rst0, txst0, txst1); - xe_rxintr(scp, rst0); - } + xe_rxintr(scp, rst0); + } - /* Restore saved page */ - XE_SELECT_PAGE(psr); + /* Restore saved page */ + XE_SELECT_PAGE(psr); - /* Re-enable interrupts */ - XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); + /* Re-enable interrupts */ + XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); - XE_UNLOCK(scp); - return; + XE_UNLOCK(scp); } - /* * Device timeout/watchdog routine. Called automatically if we queue a packet * for transmission but don't get an interrupt within a specified timeout @@ -890,539 +913,569 @@ xe_intr(void *xscp) * card. */ static void -xe_watchdog(void *arg) { - struct xe_softc *scp = arg; - - XE_ASSERT_LOCKED(scp); - - if (scp->tx_timeout && --scp->tx_timeout == 0) { - device_printf(scp->dev, "watchdog timeout: resetting card\n"); - scp->tx_timeouts++; - scp->ifp->if_oerrors += scp->tx_queued; - xe_stop(scp); - xe_reset(scp); - xe_init_locked(scp); - } - callout_reset(&scp->wdog_timer, hz, xe_watchdog, scp); -} +xe_watchdog(void *arg) +{ + struct xe_softc *scp = arg; + XE_ASSERT_LOCKED(scp); + + if (scp->tx_timeout && --scp->tx_timeout == 0) { + device_printf(scp->dev, "watchdog timeout: resetting card\n"); + scp->tx_timeouts++; + scp->ifp->if_oerrors += scp->tx_queued; + xe_stop(scp); + xe_reset(scp); + xe_init_locked(scp); + } + callout_reset(&scp->wdog_timer, hz, xe_watchdog, scp); +} /* * Change media selection. */ static int -xe_media_change(struct ifnet *ifp) { - struct xe_softc *scp = ifp->if_softc; - - DEVPRINTF(2, (scp->dev, "media_change\n")); - - XE_LOCK(scp); - if (IFM_TYPE(scp->ifm->ifm_media) != IFM_ETHER) { - XE_UNLOCK(scp); - return(EINVAL); - } - - /* - * Some card/media combos aren't always possible -- filter those out here. - */ - if ((IFM_SUBTYPE(scp->ifm->ifm_media) == IFM_AUTO || - IFM_SUBTYPE(scp->ifm->ifm_media) == IFM_100_TX) && !scp->phy_ok) { - XE_UNLOCK(scp); - return (EINVAL); - } - - xe_setmedia(scp); - XE_UNLOCK(scp); - - return 0; -} +xe_media_change(struct ifnet *ifp) +{ + struct xe_softc *scp = ifp->if_softc; + DEVPRINTF(2, (scp->dev, "media_change\n")); + + XE_LOCK(scp); + if (IFM_TYPE(scp->ifm->ifm_media) != IFM_ETHER) { + XE_UNLOCK(scp); + return(EINVAL); + } + + /* + * Some card/media combos aren't always possible -- filter + * those out here. + */ + if ((IFM_SUBTYPE(scp->ifm->ifm_media) == IFM_AUTO || + IFM_SUBTYPE(scp->ifm->ifm_media) == IFM_100_TX) && !scp->phy_ok) { + XE_UNLOCK(scp); + return (EINVAL); + } + + xe_setmedia(scp); + XE_UNLOCK(scp); + + return (0); +} /* * Return current media selection. */ static void -xe_media_status(struct ifnet *ifp, struct ifmediareq *mrp) { - struct xe_softc *scp = ifp->if_softc; - - DEVPRINTF(3, (scp->dev, "media_status\n")); +xe_media_status(struct ifnet *ifp, struct ifmediareq *mrp) +{ + struct xe_softc *scp = ifp->if_softc; - /* XXX - This is clearly wrong. Will fix once I have CE2 working */ - XE_LOCK(scp); - mrp->ifm_status = IFM_AVALID | IFM_ACTIVE; - mrp->ifm_active = ((struct xe_softc *)ifp->if_softc)->media; - XE_UNLOCK(scp); + DEVPRINTF(3, (scp->dev, "media_status\n")); - return; + /* XXX - This is clearly wrong. Will fix once I have CE2 working */ + XE_LOCK(scp); + mrp->ifm_status = IFM_AVALID | IFM_ACTIVE; + mrp->ifm_active = ((struct xe_softc *)ifp->if_softc)->media; + XE_UNLOCK(scp); } - /* * Select active media. */ -static void xe_setmedia(void *xscp) { - struct xe_softc *scp = xscp; - u_int16_t bmcr, bmsr, anar, lpar; - - DEVPRINTF(2, (scp->dev, "setmedia\n")); - - XE_ASSERT_LOCKED(scp); - - /* Cancel any pending timeout */ - callout_stop(&scp->media_timer); - xe_disable_intr(scp); - - /* Select media */ - scp->media = IFM_ETHER; - switch (IFM_SUBTYPE(scp->ifm->ifm_media)) { - - case IFM_AUTO: /* Autoselect media */ - scp->media = IFM_ETHER|IFM_AUTO; - - /* - * Autoselection is really awful. It goes something like this: - * - * Wait until the transmitter goes idle (2sec timeout). - * Reset card - * IF a 100Mbit PHY exists - * Start NWAY autonegotiation (3.5sec timeout) - * IF that succeeds - * Select 100baseTX or 10baseT, whichever was detected - * ELSE - * Reset card - * IF a 100Mbit PHY exists - * Try to force a 100baseTX link (3sec timeout) - * IF that succeeds - * Select 100baseTX - * ELSE - * Disable the PHY - * ENDIF - * ENDIF - * ENDIF - * ENDIF - * IF nothing selected so far - * IF a 100Mbit PHY exists - * Select 10baseT - * ELSE - * Select 10baseT or 10base2, whichever is connected - * ENDIF - * ENDIF - */ - switch (scp->autoneg_status) { - - case XE_AUTONEG_NONE: - DEVPRINTF(2, (scp->dev, "Waiting for idle transmitter\n")); - scp->ifp->if_drv_flags |= IFF_DRV_OACTIVE; - scp->autoneg_status = XE_AUTONEG_WAITING; - /* FALL THROUGH */ - - case XE_AUTONEG_WAITING: - if (scp->tx_queued != 0) { - callout_reset(&scp->media_timer, hz/2, xe_setmedia, scp); - return; - } - if (scp->phy_ok) { - DEVPRINTF(2, (scp->dev, "Starting autonegotiation\n")); - bmcr = xe_phy_readreg(scp, PHY_BMCR); - bmcr &= ~(PHY_BMCR_AUTONEGENBL); - xe_phy_writereg(scp, PHY_BMCR, bmcr); - anar = xe_phy_readreg(scp, PHY_ANAR); - anar &= ~(PHY_ANAR_100BT4|PHY_ANAR_100BTXFULL|PHY_ANAR_10BTFULL); - anar |= PHY_ANAR_100BTXHALF|PHY_ANAR_10BTHALF; - xe_phy_writereg(scp, PHY_ANAR, anar); - bmcr |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR; - xe_phy_writereg(scp, PHY_BMCR, bmcr); - scp->autoneg_status = XE_AUTONEG_STARTED; - callout_reset(&scp->media_timer, hz * 7/2, xe_setmedia, scp); - return; - } - else { - scp->autoneg_status = XE_AUTONEG_FAIL; - } - break; - - case XE_AUTONEG_STARTED: - bmsr = xe_phy_readreg(scp, PHY_BMSR); - lpar = xe_phy_readreg(scp, PHY_LPAR); - if (bmsr & (PHY_BMSR_AUTONEGCOMP|PHY_BMSR_LINKSTAT)) { - DEVPRINTF(2, (scp->dev, "Autonegotiation complete!\n")); +static void +xe_setmedia(void *xscp) +{ + struct xe_softc *scp = xscp; + uint16_t bmcr, bmsr, anar, lpar; + + DEVPRINTF(2, (scp->dev, "setmedia\n")); + + XE_ASSERT_LOCKED(scp); + + /* Cancel any pending timeout */ + callout_stop(&scp->media_timer); + xe_disable_intr(scp); + + /* Select media */ + scp->media = IFM_ETHER; + switch (IFM_SUBTYPE(scp->ifm->ifm_media)) { + + case IFM_AUTO: /* Autoselect media */ + scp->media = IFM_ETHER|IFM_AUTO; + + /* + * Autoselection is really awful. It goes something like this: + * + * Wait until the transmitter goes idle (2sec timeout). + * Reset card + * IF a 100Mbit PHY exists + * Start NWAY autonegotiation (3.5sec timeout) + * IF that succeeds + * Select 100baseTX or 10baseT, whichever was detected + * ELSE + * Reset card + * IF a 100Mbit PHY exists + * Try to force a 100baseTX link (3sec timeout) + * IF that succeeds + * Select 100baseTX + * ELSE + * Disable the PHY + * ENDIF + * ENDIF + * ENDIF + * ENDIF + * IF nothing selected so far + * IF a 100Mbit PHY exists + * Select 10baseT + * ELSE + * Select 10baseT or 10base2, whichever is connected + * ENDIF + * ENDIF + */ + switch (scp->autoneg_status) { + case XE_AUTONEG_NONE: + DEVPRINTF(2, (scp->dev, + "Waiting for idle transmitter\n")); + scp->ifp->if_drv_flags |= IFF_DRV_OACTIVE; + scp->autoneg_status = XE_AUTONEG_WAITING; + /* FALL THROUGH */ + case XE_AUTONEG_WAITING: + if (scp->tx_queued != 0) { + callout_reset(&scp->media_timer, hz / 2, + xe_setmedia, scp); + return; + } + if (scp->phy_ok) { + DEVPRINTF(2, (scp->dev, + "Starting autonegotiation\n")); + bmcr = xe_phy_readreg(scp, PHY_BMCR); + bmcr &= ~(PHY_BMCR_AUTONEGENBL); + xe_phy_writereg(scp, PHY_BMCR, bmcr); + anar = xe_phy_readreg(scp, PHY_ANAR); + anar &= ~(PHY_ANAR_100BT4 | + PHY_ANAR_100BTXFULL | PHY_ANAR_10BTFULL); + anar |= PHY_ANAR_100BTXHALF | PHY_ANAR_10BTHALF; + xe_phy_writereg(scp, PHY_ANAR, anar); + bmcr |= PHY_BMCR_AUTONEGENBL | + PHY_BMCR_AUTONEGRSTR; + xe_phy_writereg(scp, PHY_BMCR, bmcr); + scp->autoneg_status = XE_AUTONEG_STARTED; + callout_reset(&scp->media_timer, hz * 7/2, + xe_setmedia, scp); + return; + } else { + scp->autoneg_status = XE_AUTONEG_FAIL; + } + break; + case XE_AUTONEG_STARTED: + bmsr = xe_phy_readreg(scp, PHY_BMSR); + lpar = xe_phy_readreg(scp, PHY_LPAR); + if (bmsr & (PHY_BMSR_AUTONEGCOMP | PHY_BMSR_LINKSTAT)) { + DEVPRINTF(2, (scp->dev, + "Autonegotiation complete!\n")); + + /* + * XXX - Shouldn't have to do this, + * but (on my hub at least) the + * transmitter won't work after a + * successful autoneg. So we see what + * the negotiation result was and + * force that mode. I'm sure there is + * an easy fix for this. + */ + if (lpar & PHY_LPAR_100BTXHALF) { + xe_phy_writereg(scp, PHY_BMCR, + PHY_BMCR_SPEEDSEL); + XE_MII_DUMP(scp); + XE_SELECT_PAGE(2); + XE_OUTB(XE_MSR, XE_INB(XE_MSR) | 0x08); + scp->media = IFM_ETHER | IFM_100_TX; + scp->autoneg_status = XE_AUTONEG_NONE; + } else { + /* + * XXX - Bit of a hack going + * on in here. This is + * derived from Ken Hughes + * patch to the Linux driver + * to make it work with 10Mbit + * _autonegotiated_ links on + * CE3B cards. What's a CE3B + * and how's it differ from a + * plain CE3? these are the + * things we need to find out. + */ + xe_phy_writereg(scp, PHY_BMCR, 0x0000); + XE_SELECT_PAGE(2); + /* BEGIN HACK */ + XE_OUTB(XE_MSR, XE_INB(XE_MSR) | 0x08); + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, 0x80); + scp->media = IFM_ETHER | IFM_10_T; + scp->autoneg_status = XE_AUTONEG_NONE; + /* END HACK */ +#if 0 + /* Display PHY? */ + XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~0x08); + scp->autoneg_status = XE_AUTONEG_FAIL; +#endif + } + } else { + DEVPRINTF(2, (scp->dev, + "Autonegotiation failed; trying 100baseTX\n")); + XE_MII_DUMP(scp); + if (scp->phy_ok) { + xe_phy_writereg(scp, PHY_BMCR, + PHY_BMCR_SPEEDSEL); + scp->autoneg_status = XE_AUTONEG_100TX; + callout_reset(&scp->media_timer, hz * 3, + xe_setmedia, scp); + return; + } else { + scp->autoneg_status = XE_AUTONEG_FAIL; + } + } + break; + case XE_AUTONEG_100TX: + (void)xe_phy_readreg(scp, PHY_BMSR); + bmsr = xe_phy_readreg(scp, PHY_BMSR); + if (bmsr & PHY_BMSR_LINKSTAT) { + DEVPRINTF(2, (scp->dev, + "Got 100baseTX link!\n")); + XE_MII_DUMP(scp); + XE_SELECT_PAGE(2); + XE_OUTB(XE_MSR, XE_INB(XE_MSR) | 0x08); + scp->media = IFM_ETHER | IFM_100_TX; + scp->autoneg_status = XE_AUTONEG_NONE; + } else { + DEVPRINTF(2, (scp->dev, + "Autonegotiation failed; disabling PHY\n")); + XE_MII_DUMP(scp); + xe_phy_writereg(scp, PHY_BMCR, 0x0000); + XE_SELECT_PAGE(2); + + /* Disable PHY? */ + XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~0x08); + scp->autoneg_status = XE_AUTONEG_FAIL; + } + break; + } + + /* + * If we got down here _and_ autoneg_status is + * XE_AUTONEG_FAIL, then either autonegotiation + * failed, or never got started to begin with. In + * either case, select a suitable 10Mbit media and + * hope it works. We don't need to reset the card + * again, since it will have been done already by the + * big switch above. + */ + if (scp->autoneg_status == XE_AUTONEG_FAIL) { + DEVPRINTF(2, (scp->dev, "Selecting 10baseX\n")); + if (scp->mohawk) { + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, 0x80); + scp->media = IFM_ETHER | IFM_10_T; + scp->autoneg_status = XE_AUTONEG_NONE; + } else { + XE_SELECT_PAGE(4); + XE_OUTB(XE_GPR0, 4); + DELAY(50000); + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, + (XE_INB(XE_ESR) & XE_ESR_MEDIA_SELECT) ? + 0x80 : 0xc0); + scp->media = IFM_ETHER | ((XE_INB(XE_ESR) & + XE_ESR_MEDIA_SELECT) ? IFM_10_T : IFM_10_2); + scp->autoneg_status = XE_AUTONEG_NONE; + } + } + break; + /* - * XXX - Shouldn't have to do this, but (on my hub at least) the - * XXX - transmitter won't work after a successful autoneg. So we see - * XXX - what the negotiation result was and force that mode. I'm - * XXX - sure there is an easy fix for this. + * If a specific media has been requested, we just reset the + * card and select it (one small exception -- if 100baseTX is + * requested but there is no PHY, we fall back to 10baseT + * operation). */ - if (lpar & PHY_LPAR_100BTXHALF) { - xe_phy_writereg(scp, PHY_BMCR, PHY_BMCR_SPEEDSEL); - XE_MII_DUMP(scp); - XE_SELECT_PAGE(2); - XE_OUTB(XE_MSR, XE_INB(XE_MSR) | 0x08); - scp->media = IFM_ETHER|IFM_100_TX; - scp->autoneg_status = XE_AUTONEG_NONE; - } - else { - /* - * XXX - Bit of a hack going on in here. - * XXX - This is derived from Ken Hughes patch to the Linux driver - * XXX - to make it work with 10Mbit _autonegotiated_ links on CE3B - * XXX - cards. What's a CE3B and how's it differ from a plain CE3? - * XXX - these are the things we need to find out. - */ - xe_phy_writereg(scp, PHY_BMCR, 0x0000); - XE_SELECT_PAGE(2); - /* BEGIN HACK */ - XE_OUTB(XE_MSR, XE_INB(XE_MSR) | 0x08); - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, 0x80); - scp->media = IFM_ETHER|IFM_10_T; - scp->autoneg_status = XE_AUTONEG_NONE; - /* END HACK */ - /*XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~0x08);*/ /* Disable PHY? */ - /*scp->autoneg_status = XE_AUTONEG_FAIL;*/ - } - } - else { - DEVPRINTF(2, (scp->dev, "Autonegotiation failed; trying 100baseTX\n")); - XE_MII_DUMP(scp); - if (scp->phy_ok) { - xe_phy_writereg(scp, PHY_BMCR, PHY_BMCR_SPEEDSEL); - scp->autoneg_status = XE_AUTONEG_100TX; - callout_reset(&scp->media_timer, hz * 3, xe_setmedia, scp); - return; - } - else { - scp->autoneg_status = XE_AUTONEG_FAIL; + case IFM_100_TX: /* Force 100baseTX */ + if (scp->phy_ok) { + DEVPRINTF(2, (scp->dev, "Selecting 100baseTX\n")); + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, 0); + xe_phy_writereg(scp, PHY_BMCR, PHY_BMCR_SPEEDSEL); + XE_SELECT_PAGE(2); + XE_OUTB(XE_MSR, XE_INB(XE_MSR) | 0x08); + scp->media |= IFM_100_TX; + break; + } + /* FALLTHROUGH */ + case IFM_10_T: /* Force 10baseT */ + DEVPRINTF(2, (scp->dev, "Selecting 10baseT\n")); + if (scp->phy_ok) { + xe_phy_writereg(scp, PHY_BMCR, 0x0000); + XE_SELECT_PAGE(2); + + /* Disable PHY */ + XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~0x08); + } + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, 0x80); + scp->media |= IFM_10_T; + break; + case IFM_10_2: + DEVPRINTF(2, (scp->dev, "Selecting 10base2\n")); + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, 0xc0); + scp->media |= IFM_10_2; + break; } - } - break; - - case XE_AUTONEG_100TX: - (void)xe_phy_readreg(scp, PHY_BMSR); - bmsr = xe_phy_readreg(scp, PHY_BMSR); - if (bmsr & PHY_BMSR_LINKSTAT) { - DEVPRINTF(2, (scp->dev, "Got 100baseTX link!\n")); - XE_MII_DUMP(scp); - XE_SELECT_PAGE(2); - XE_OUTB(XE_MSR, XE_INB(XE_MSR) | 0x08); - scp->media = IFM_ETHER|IFM_100_TX; - scp->autoneg_status = XE_AUTONEG_NONE; - } - else { - DEVPRINTF(2, (scp->dev, "Autonegotiation failed; disabling PHY\n")); - XE_MII_DUMP(scp); - xe_phy_writereg(scp, PHY_BMCR, 0x0000); + + /* + * Finally, the LEDs are set to match whatever media was + * chosen and the transmitter is unblocked. + */ + DEVPRINTF(2, (scp->dev, "Setting LEDs\n")); XE_SELECT_PAGE(2); - XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~0x08); /* Disable PHY? */ - scp->autoneg_status = XE_AUTONEG_FAIL; - } - break; - } - - /* - * If we got down here _and_ autoneg_status is XE_AUTONEG_FAIL, then - * either autonegotiation failed, or never got started to begin with. In - * either case, select a suitable 10Mbit media and hope it works. We - * don't need to reset the card again, since it will have been done - * already by the big switch above. - */ - if (scp->autoneg_status == XE_AUTONEG_FAIL) { - DEVPRINTF(2, (scp->dev, "Selecting 10baseX\n")); - if (scp->mohawk) { - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, 0x80); - scp->media = IFM_ETHER|IFM_10_T; - scp->autoneg_status = XE_AUTONEG_NONE; - } - else { - XE_SELECT_PAGE(4); - XE_OUTB(XE_GPR0, 4); - DELAY(50000); - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, (XE_INB(XE_ESR) & XE_ESR_MEDIA_SELECT) ? 0x80 : 0xc0); - scp->media = IFM_ETHER|((XE_INB(XE_ESR) & XE_ESR_MEDIA_SELECT) ? IFM_10_T : IFM_10_2); - scp->autoneg_status = XE_AUTONEG_NONE; - } - } - break; - - - /* - * If a specific media has been requested, we just reset the card and - * select it (one small exception -- if 100baseTX is requested by there is - * no PHY, we fall back to 10baseT operation). - */ - case IFM_100_TX: /* Force 100baseTX */ - if (scp->phy_ok) { - DEVPRINTF(2, (scp->dev, "Selecting 100baseTX\n")); - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, 0); - xe_phy_writereg(scp, PHY_BMCR, PHY_BMCR_SPEEDSEL); - XE_SELECT_PAGE(2); - XE_OUTB(XE_MSR, XE_INB(XE_MSR) | 0x08); - scp->media |= IFM_100_TX; - break; - } - /* FALLTHROUGH */ - - case IFM_10_T: /* Force 10baseT */ - DEVPRINTF(2, (scp->dev, "Selecting 10baseT\n")); - if (scp->phy_ok) { - xe_phy_writereg(scp, PHY_BMCR, 0x0000); - XE_SELECT_PAGE(2); - XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~0x08); /* Disable PHY */ - } - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, 0x80); - scp->media |= IFM_10_T; - break; - - case IFM_10_2: - DEVPRINTF(2, (scp->dev, "Selecting 10base2\n")); - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, 0xc0); - scp->media |= IFM_10_2; - break; - } - - - /* - * Finally, the LEDs are set to match whatever media was chosen and the - * transmitter is unblocked. - */ - DEVPRINTF(2, (scp->dev, "Setting LEDs\n")); - XE_SELECT_PAGE(2); - switch (IFM_SUBTYPE(scp->media)) { - case IFM_100_TX: - case IFM_10_T: - XE_OUTB(XE_LED, 0x3b); - if (scp->dingo) - XE_OUTB(0x0b, 0x04); /* 100Mbit LED */ - break; - - case IFM_10_2: - XE_OUTB(XE_LED, 0x3a); - break; - } - - /* Restart output? */ - xe_enable_intr(scp); - scp->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - xe_start_locked(scp->ifp); -} + switch (IFM_SUBTYPE(scp->media)) { + case IFM_100_TX: + case IFM_10_T: + XE_OUTB(XE_LED, 0x3b); + if (scp->dingo) + XE_OUTB(0x0b, 0x04); /* 100Mbit LED */ + break; + case IFM_10_2: + XE_OUTB(XE_LED, 0x3a); + break; + } + /* Restart output? */ + xe_enable_intr(scp); + scp->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + xe_start_locked(scp->ifp); +} /* * Hard reset (power cycle) the card. */ static void -xe_reset(struct xe_softc *scp) { +xe_reset(struct xe_softc *scp) +{ - DEVPRINTF(2, (scp->dev, "reset\n")); + DEVPRINTF(2, (scp->dev, "reset\n")); - XE_ASSERT_LOCKED(scp); + XE_ASSERT_LOCKED(scp); - /* Power down */ - XE_SELECT_PAGE(4); - XE_OUTB(XE_GPR1, 0); - DELAY(40000); + /* Power down */ + XE_SELECT_PAGE(4); + XE_OUTB(XE_GPR1, 0); + DELAY(40000); - /* Power up again */ - if (scp->mohawk) - XE_OUTB(XE_GPR1, XE_GPR1_POWER_DOWN); - else - XE_OUTB(XE_GPR1, XE_GPR1_POWER_DOWN|XE_GPR1_AIC); + /* Power up again */ + if (scp->mohawk) + XE_OUTB(XE_GPR1, XE_GPR1_POWER_DOWN); + else + XE_OUTB(XE_GPR1, XE_GPR1_POWER_DOWN | XE_GPR1_AIC); - DELAY(40000); - XE_SELECT_PAGE(0); + DELAY(40000); + XE_SELECT_PAGE(0); } - /* * Take interface offline. This is done by powering down the device, which I * assume means just shutting down the transceiver and Ethernet logic. This * requires a _hard_ reset to recover from, as we need to power up again. */ void -xe_stop(struct xe_softc *scp) { - - DEVPRINTF(2, (scp->dev, "stop\n")); - - XE_ASSERT_LOCKED(scp); - - /* - * Shut off interrupts. - */ - xe_disable_intr(scp); - - /* - * Power down. - */ - XE_SELECT_PAGE(4); - XE_OUTB(XE_GPR1, 0); - XE_SELECT_PAGE(0); - if (scp->mohawk) { - /* - * set GP1 and GP2 as outputs (bits 2 & 3) - * set GP1 high to power on the ML6692 (bit 0) - * set GP2 low to power on the 10Mhz chip (bit 1) - */ - XE_SELECT_PAGE(4); - XE_OUTB(XE_GPR0, XE_GPR0_GP2_SELECT|XE_GPR0_GP1_SELECT|XE_GPR0_GP1_OUT); - } - - /* - * ~IFF_DRV_RUNNING == interface down. - */ - scp->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - scp->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - scp->tx_timeout = 0; - callout_stop(&scp->wdog_timer); - callout_stop(&scp->media_timer); -} +xe_stop(struct xe_softc *scp) +{ + + DEVPRINTF(2, (scp->dev, "stop\n")); + XE_ASSERT_LOCKED(scp); + + /* + * Shut off interrupts. + */ + xe_disable_intr(scp); + + /* + * Power down. + */ + XE_SELECT_PAGE(4); + XE_OUTB(XE_GPR1, 0); + XE_SELECT_PAGE(0); + if (scp->mohawk) { + /* + * set GP1 and GP2 as outputs (bits 2 & 3) + * set GP1 high to power on the ML6692 (bit 0) + * set GP2 low to power on the 10Mhz chip (bit 1) + */ + XE_SELECT_PAGE(4); + XE_OUTB(XE_GPR0, XE_GPR0_GP2_SELECT | XE_GPR0_GP1_SELECT | + XE_GPR0_GP1_OUT); + } + + /* + * ~IFF_DRV_RUNNING == interface down. + */ + scp->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + scp->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + scp->tx_timeout = 0; + callout_stop(&scp->wdog_timer); + callout_stop(&scp->media_timer); +} /* * Enable interrupts from the card. */ static void -xe_enable_intr(struct xe_softc *scp) { +xe_enable_intr(struct xe_softc *scp) +{ - DEVPRINTF(2, (scp->dev, "enable_intr\n")); + DEVPRINTF(2, (scp->dev, "enable_intr\n")); - XE_SELECT_PAGE(0); - XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); /* Enable interrupts */ - if (scp->modem && !scp->dingo) { /* This bit is just magic */ - if (!(XE_INB(0x10) & 0x01)) { - XE_OUTB(0x10, 0x11); /* Unmask master int enable bit */ - } - } + XE_SELECT_PAGE(0); + XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); /* Enable interrupts */ + if (scp->modem && !scp->dingo) { /* This bit is just magic */ + if (!(XE_INB(0x10) & 0x01)) { + XE_OUTB(0x10, 0x11); /* Unmask master int enable */ + } + } } - /* * Disable interrupts from the card. */ static void -xe_disable_intr(struct xe_softc *scp) { +xe_disable_intr(struct xe_softc *scp) +{ - DEVPRINTF(2, (scp->dev, "disable_intr\n")); + DEVPRINTF(2, (scp->dev, "disable_intr\n")); - XE_SELECT_PAGE(0); - XE_OUTB(XE_CR, 0); /* Disable interrupts */ - if (scp->modem && !scp->dingo) { /* More magic */ - XE_OUTB(0x10, 0x10); /* Mask the master int enable bit */ - } + XE_SELECT_PAGE(0); + XE_OUTB(XE_CR, 0); /* Disable interrupts */ + if (scp->modem && !scp->dingo) { /* More magic */ + XE_OUTB(0x10, 0x10); /* Mask the master int enable */ + } } - /* * Set up multicast filter and promiscuous modes. */ static void -xe_set_multicast(struct xe_softc *scp) { - struct ifnet *ifp; - struct ifmultiaddr *maddr; - unsigned count, i; - - DEVPRINTF(2, (scp->dev, "set_multicast\n")); - - ifp = scp->ifp; - XE_SELECT_PAGE(0x42); - - /* Handle PROMISC flag */ - if (ifp->if_flags & IFF_PROMISC) { - XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) | XE_SWC1_PROMISCUOUS); - return; - } - else - XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) & ~XE_SWC1_PROMISCUOUS); - - /* Handle ALLMULTI flag */ - if (ifp->if_flags & IFF_ALLMULTI) { - XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) | XE_SWC1_ALLMULTI); - return; - } - else - XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) & ~XE_SWC1_ALLMULTI); - - /* Iterate over multicast address list */ - count = 0; - IF_ADDR_LOCK(ifp); - TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { - if (maddr->ifma_addr->sa_family != AF_LINK) - continue; - - count++; - - if (count < 10) - /* First 9 use Individual Addresses for exact matching */ - xe_set_addr(scp, LLADDR((struct sockaddr_dl *)maddr->ifma_addr), count); - else - if (scp->mohawk) - /* Use hash filter on Mohawk and Dingo */ - xe_mchash(scp, LLADDR((struct sockaddr_dl *)maddr->ifma_addr)); - else - /* Nowhere else to put them on CE2 */ - break; - } - IF_ADDR_UNLOCK(ifp); - - DEVPRINTF(2, (scp->dev, "set_multicast: count = %u\n", count)); - - /* Now do some cleanup and enable multicast handling as needed */ - if (count == 0) { - /* Disable all multicast handling */ - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) & ~(XE_SWC1_IA_ENABLE|XE_SWC1_ALLMULTI)); - if (scp->mohawk) { - XE_SELECT_PAGE(0x02); - XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~XE_MSR_HASH_TABLE); - } - } - else if (count < 10) { - /* Full in any unused Individual Addresses with our MAC address */ - for (i = count + 1; i < 10; i++) - xe_set_addr(scp, IF_LLADDR(scp->ifp), i); - /* Enable Individual Address matching only */ - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, (XE_INB(XE_SWC1) & ~XE_SWC1_ALLMULTI) | XE_SWC1_IA_ENABLE); - if (scp->mohawk) { - XE_SELECT_PAGE(0x02); - XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~XE_MSR_HASH_TABLE); - } - } - else { - if (scp->mohawk) { - /* Check whether hash table is full */ - XE_SELECT_PAGE(0x58); - for (i = 0x08; i < 0x10; i++) - if (XE_INB(i) != 0xff) - break; - if (i == 0x10) { - /* Hash table full - enable promiscuous multicast matching */ - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, (XE_INB(XE_SWC1) & ~XE_SWC1_IA_ENABLE) | XE_SWC1_ALLMULTI); - XE_SELECT_PAGE(0x02); - XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~XE_MSR_HASH_TABLE); - } - else { - /* Enable hash table and Individual Address matching */ +xe_set_multicast(struct xe_softc *scp) +{ + struct ifnet *ifp; + struct ifmultiaddr *maddr; + unsigned count, i; + + DEVPRINTF(2, (scp->dev, "set_multicast\n")); + + ifp = scp->ifp; XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, (XE_INB(XE_SWC1) & ~XE_SWC1_ALLMULTI) | XE_SWC1_IA_ENABLE); - XE_SELECT_PAGE(0x02); - XE_OUTB(XE_MSR, XE_INB(XE_MSR) | XE_MSR_HASH_TABLE); - } - } - else { - /* Enable promiscuous multicast matching */ - XE_SELECT_PAGE(0x42); - XE_OUTB(XE_SWC1, (XE_INB(XE_SWC1) & ~XE_SWC1_IA_ENABLE) | XE_SWC1_ALLMULTI); - } - } - - XE_SELECT_PAGE(0); -} + /* Handle PROMISC flag */ + if (ifp->if_flags & IFF_PROMISC) { + XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) | XE_SWC1_PROMISCUOUS); + return; + } else + XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) & ~XE_SWC1_PROMISCUOUS); + + /* Handle ALLMULTI flag */ + if (ifp->if_flags & IFF_ALLMULTI) { + XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) | XE_SWC1_ALLMULTI); + return; + } else + XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) & ~XE_SWC1_ALLMULTI); + + /* Iterate over multicast address list */ + count = 0; + IF_ADDR_LOCK(ifp); + TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { + if (maddr->ifma_addr->sa_family != AF_LINK) + continue; + + count++; + + if (count < 10) + /* + * First 9 use Individual Addresses for exact + * matching. + */ + xe_set_addr(scp, + LLADDR((struct sockaddr_dl *)maddr->ifma_addr), + count); + else if (scp->mohawk) + /* Use hash filter on Mohawk and Dingo */ + xe_mchash(scp, + LLADDR((struct sockaddr_dl *)maddr->ifma_addr)); + else + /* Nowhere else to put them on CE2 */ + break; + } + IF_ADDR_UNLOCK(ifp); + + DEVPRINTF(2, (scp->dev, "set_multicast: count = %u\n", count)); + + /* Now do some cleanup and enable multicast handling as needed */ + if (count == 0) { + /* Disable all multicast handling */ + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, XE_INB(XE_SWC1) & + ~(XE_SWC1_IA_ENABLE | XE_SWC1_ALLMULTI)); + if (scp->mohawk) { + XE_SELECT_PAGE(0x02); + XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~XE_MSR_HASH_TABLE); + } + } else if (count < 10) { + /* + * Full in any unused Individual Addresses with our + * MAC address. + */ + for (i = count + 1; i < 10; i++) + xe_set_addr(scp, IF_LLADDR(scp->ifp), i); + + /* Enable Individual Address matching only */ + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, (XE_INB(XE_SWC1) & ~XE_SWC1_ALLMULTI) | + XE_SWC1_IA_ENABLE); + if (scp->mohawk) { + XE_SELECT_PAGE(0x02); + XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~XE_MSR_HASH_TABLE); + } + } else if (scp->mohawk) { + /* Check whether hash table is full */ + XE_SELECT_PAGE(0x58); + for (i = 0x08; i < 0x10; i++) + if (XE_INB(i) != 0xff) + break; + if (i == 0x10) { + /* + * Hash table full - enable + * promiscuous multicast matching + */ + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, (XE_INB(XE_SWC1) & + ~XE_SWC1_IA_ENABLE) | XE_SWC1_ALLMULTI); + XE_SELECT_PAGE(0x02); + XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~XE_MSR_HASH_TABLE); + } else { + /* Enable hash table and Individual Address matching */ + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, (XE_INB(XE_SWC1) & ~XE_SWC1_ALLMULTI) | + XE_SWC1_IA_ENABLE); + XE_SELECT_PAGE(0x02); + XE_OUTB(XE_MSR, XE_INB(XE_MSR) | XE_MSR_HASH_TABLE); + } + } else { + /* Enable promiscuous multicast matching */ + XE_SELECT_PAGE(0x42); + XE_OUTB(XE_SWC1, (XE_INB(XE_SWC1) & ~XE_SWC1_IA_ENABLE) | + XE_SWC1_ALLMULTI); + } + + XE_SELECT_PAGE(0); +} /* * Copy the Ethernet multicast address in addr to the on-chip registers for @@ -1430,43 +1483,44 @@ xe_set_multicast(struct xe_softc *scp) { * and that idx > 0 (slot 0 is always used for the card MAC address). */ static void -xe_set_addr(struct xe_softc *scp, u_int8_t* addr, unsigned idx) { - u_int8_t page, reg; - unsigned i; - - /* - * Individual Addresses are stored in registers 8-F of pages 0x50-0x57. IA1 - * therefore starts at register 0xE on page 0x50. The expressions below - * compute the starting page and register for any IA index > 0. - */ - --idx; - page = 0x50 + idx%4 + idx/4*3; - reg = 0x0e - 2 * (idx%4); - - DEVPRINTF(3, (scp->dev, "set_addr: idx = %u, page = 0x%02x, reg = 0x%02x\n", - idx+1, page, reg)); - - /* - * Copy the IA bytes. Note that the byte order is reversed for Mohawk and - * Dingo wrt. CE2 hardware. - */ - XE_SELECT_PAGE(page); - for (i = 0; i < 6; i++) { - if (i > 0) { - DPRINTF(3, (":%02x", addr[i])); - } - else { - DEVPRINTF(3, (scp->dev, "set_addr: %02x", addr[0])); - } - XE_OUTB(reg, addr[scp->mohawk ? 5 - i : i]); - if (++reg == 0x10) { - reg = 0x08; - XE_SELECT_PAGE(++page); - } - } - DPRINTF(3, ("\n")); -} +xe_set_addr(struct xe_softc *scp, uint8_t* addr, unsigned idx) +{ + uint8_t page, reg; + unsigned i; + + /* + * Individual Addresses are stored in registers 8-F of pages + * 0x50-0x57. IA1 therefore starts at register 0xE on page + * 0x50. The expressions below compute the starting page and + * register for any IA index > 0. + */ + --idx; + page = 0x50 + idx % 4 + idx / 4 * 3; + reg = 0x0e - 2 * (idx % 4); + DEVPRINTF(3, (scp->dev, + "set_addr: idx = %u, page = 0x%02x, reg = 0x%02x\n", idx + 1, page, + reg)); + + /* + * Copy the IA bytes. Note that the byte order is reversed + * for Mohawk and Dingo wrt. CE2 hardware. + */ + XE_SELECT_PAGE(page); + for (i = 0; i < ETHER_ADDR_LEN; i++) { + if (i > 0) { + DPRINTF(3, (":%02x", addr[i])); + } else { + DEVPRINTF(3, (scp->dev, "set_addr: %02x", addr[0])); + } + XE_OUTB(reg, addr[scp->mohawk ? 5 - i : i]); + if (++reg == 0x10) { + reg = 0x08; + XE_SELECT_PAGE(++page); + } + } + DPRINTF(3, ("\n")); +} /* * Set the appropriate bit in the multicast hash table for the supplied @@ -1474,116 +1528,123 @@ xe_set_addr(struct xe_softc *scp, u_int8_t* addr, unsigned idx) { * address. */ static void -xe_mchash(struct xe_softc* scp, const uint8_t *addr) { - int bit; - uint8_t byte, hash; +xe_mchash(struct xe_softc* scp, const uint8_t *addr) +{ + int bit; + uint8_t byte, hash; - hash = ether_crc32_le(addr, ETHER_ADDR_LEN) & 0x3F; + hash = ether_crc32_le(addr, ETHER_ADDR_LEN) & 0x3F; - /* Top 3 bits of hash give register - 8, bottom 3 give bit within register */ - byte = hash >> 3 | 0x08; - bit = 0x01 << (hash & 0x07); + /* + * Top 3 bits of hash give register - 8, bottom 3 give bit + * within register. + */ + byte = hash >> 3 | 0x08; + bit = 0x01 << (hash & 0x07); - DEVPRINTF(3, (scp->dev, "set_hash: hash = 0x%02x, byte = 0x%02x, bit = 0x%02x\n", hash, byte, bit)); + DEVPRINTF(3, (scp->dev, + "set_hash: hash = 0x%02x, byte = 0x%02x, bit = 0x%02x\n", hash, + byte, bit)); - XE_SELECT_PAGE(0x58); - XE_OUTB(byte, XE_INB(byte) | bit); + XE_SELECT_PAGE(0x58); + XE_OUTB(byte, XE_INB(byte) | bit); } - /* * Write an outgoing packet to the card using programmed I/O. */ static int -xe_pio_write_packet(struct xe_softc *scp, struct mbuf *mbp) { - unsigned len, pad; - unsigned char wantbyte; - u_int8_t *data; - u_int8_t savebyte[2]; - - /* Get total packet length */ - if (mbp->m_flags & M_PKTHDR) - len = mbp->m_pkthdr.len; - else { - struct mbuf* mbp2 = mbp; - for (len = 0; mbp2 != NULL; len += mbp2->m_len, mbp2 = mbp2->m_next); - } - - DEVPRINTF(3, (scp->dev, "pio_write_packet: len = %u\n", len)); - - /* Packets < minimum length may need to be padded out */ - pad = 0; - if (len < scp->tx_min) { - pad = scp->tx_min - len; - len = scp->tx_min; - } - - /* Check transmit buffer space */ - XE_SELECT_PAGE(0); - XE_OUTW(XE_TRS, len+2); /* Only effective on rev. 1 CE2 cards */ - if ((XE_INW(XE_TSO) & 0x7fff) <= len + 2) - return 1; - - /* Send packet length to card */ - XE_OUTW(XE_EDP, len); - - /* - * Write packet to card using PIO (code stolen from the ed driver) - */ - wantbyte = 0; - while (mbp != NULL) { - len = mbp->m_len; - if (len > 0) { - data = mtod(mbp, caddr_t); - if (wantbyte) { /* Finish the last word */ - savebyte[1] = *data; - XE_OUTW(XE_EDP, *(u_short *)savebyte); - data++; - len--; +xe_pio_write_packet(struct xe_softc *scp, struct mbuf *mbp) +{ + unsigned len, pad; + unsigned char wantbyte; + uint8_t *data; + uint8_t savebyte[2]; + + /* Get total packet length */ + if (mbp->m_flags & M_PKTHDR) + len = mbp->m_pkthdr.len; + else { + struct mbuf* mbp2 = mbp; + for (len = 0; mbp2 != NULL; + len += mbp2->m_len, mbp2 = mbp2->m_next); + } + + DEVPRINTF(3, (scp->dev, "pio_write_packet: len = %u\n", len)); + + /* Packets < minimum length may need to be padded out */ + pad = 0; + if (len < scp->tx_min) { + pad = scp->tx_min - len; + len = scp->tx_min; + } + + /* Check transmit buffer space */ + XE_SELECT_PAGE(0); + XE_OUTW(XE_TRS, len + 2); /* Only effective on rev. 1 CE2 cards */ + if ((XE_INW(XE_TSO) & 0x7fff) <= len + 2) + return (1); + + /* Send packet length to card */ + XE_OUTW(XE_EDP, len); + + /* + * Write packet to card using PIO (code stolen from the ed driver) + */ wantbyte = 0; - } - if (len > 1) { /* Output contiguous words */ - bus_write_multi_2(scp->port_res, XE_EDP, (u_int16_t *) data, - len >> 1); - data += len & ~1; - len &= 1; - } - if (len == 1) { /* Save last byte, if necessary */ - savebyte[0] = *data; - wantbyte = 1; - } - } - mbp = mbp->m_next; - } - - /* - * Send last byte of odd-length packets - */ - if (wantbyte) - XE_OUTB(XE_EDP, savebyte[0]); - - /* - * Can just tell CE3 cards to send; short packets will be padded out with - * random cruft automatically. For CE2, manually pad the packet with - * garbage; it will be sent when the required number or bytes have been - * delivered to the card. - */ - if (scp->mohawk) - XE_OUTB(XE_CR, XE_CR_TX_PACKET | XE_CR_RESTART_TX | XE_CR_ENABLE_INTR); - else if (pad > 0) { - if (pad & 0x01) - XE_OUTB(XE_EDP, 0xaa); - pad >>= 1; - while (pad > 0) { - XE_OUTW(XE_EDP, 0xdead); - pad--; - } - } - - return 0; -} + while (mbp != NULL) { + len = mbp->m_len; + if (len > 0) { + data = mtod(mbp, caddr_t); + if (wantbyte) { /* Finish the last word */ + savebyte[1] = *data; + XE_OUTW(XE_EDP, *(u_short *)savebyte); + data++; + len--; + wantbyte = 0; + } + if (len > 1) { /* Output contiguous words */ + bus_write_multi_2(scp->port_res, XE_EDP, + (uint16_t *)data, len >> 1); + data += len & ~1; + len &= 1; + } + if (len == 1) { /* Save last byte, if needed */ + savebyte[0] = *data; + wantbyte = 1; + } + } + mbp = mbp->m_next; + } + /* + * Send last byte of odd-length packets + */ + if (wantbyte) + XE_OUTB(XE_EDP, savebyte[0]); + + /* + * Can just tell CE3 cards to send; short packets will be + * padded out with random cruft automatically. For CE2, + * manually pad the packet with garbage; it will be sent when + * the required number of bytes have been delivered to the + * card. + */ + if (scp->mohawk) + XE_OUTB(XE_CR, XE_CR_TX_PACKET | XE_CR_RESTART_TX | + XE_CR_ENABLE_INTR); + else if (pad > 0) { + if (pad & 0x01) + XE_OUTB(XE_EDP, 0xaa); + pad >>= 1; + while (pad > 0) { + XE_OUTW(XE_EDP, 0xdead); + pad--; + } + } + return (0); +} /************************************************************** * * @@ -1598,299 +1659,297 @@ xe_pio_write_packet(struct xe_softc *scp, struct mbuf *mbp) { * XXX - some kind of common MII-handling code, shared by all drivers. But * XXX - that's a whole other mission. */ -#define XE_MII_SET(x) XE_OUTB(XE_GPR2, (XE_INB(XE_GPR2) | 0x04) | (x)) -#define XE_MII_CLR(x) XE_OUTB(XE_GPR2, (XE_INB(XE_GPR2) | 0x04) & ~(x)) - +#define XE_MII_SET(x) XE_OUTB(XE_GPR2, (XE_INB(XE_GPR2) | 0x04) | (x)) +#define XE_MII_CLR(x) XE_OUTB(XE_GPR2, (XE_INB(XE_GPR2) | 0x04) & ~(x)) /* * Sync the PHYs by setting data bit and strobing the clock 32 times. */ static void -xe_mii_sync(struct xe_softc *scp) { - register int i; - - XE_SELECT_PAGE(2); - XE_MII_SET(XE_MII_DIR|XE_MII_WRD); - - for (i = 0; i < 32; i++) { - XE_MII_SET(XE_MII_CLK); - DELAY(1); - XE_MII_CLR(XE_MII_CLK); - DELAY(1); - } -} +xe_mii_sync(struct xe_softc *scp) +{ + int i; + + XE_SELECT_PAGE(2); + XE_MII_SET(XE_MII_DIR|XE_MII_WRD); + for (i = 0; i < 32; i++) { + XE_MII_SET(XE_MII_CLK); + DELAY(1); + XE_MII_CLR(XE_MII_CLK); + DELAY(1); + } +} /* * Look for a MII-compliant PHY. If we find one, reset it. */ static int -xe_mii_init(struct xe_softc *scp) { - u_int16_t status; - - status = xe_phy_readreg(scp, PHY_BMSR); - if ((status & 0xff00) != 0x7800) { - DEVPRINTF(2, (scp->dev, "no PHY found, %0x\n", status)); - return 0; - } - else { - DEVPRINTF(2, (scp->dev, "PHY OK!\n")); - - /* Reset the PHY */ - xe_phy_writereg(scp, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(xe_phy_readreg(scp, PHY_BMCR) & PHY_BMCR_RESET); - XE_MII_DUMP(scp); - return 1; - } +xe_mii_init(struct xe_softc *scp) +{ + uint16_t status; + + status = xe_phy_readreg(scp, PHY_BMSR); + if ((status & 0xff00) != 0x7800) { + DEVPRINTF(2, (scp->dev, "no PHY found, %0x\n", status)); + return (0); + } else { + DEVPRINTF(2, (scp->dev, "PHY OK!\n")); + + /* Reset the PHY */ + xe_phy_writereg(scp, PHY_BMCR, PHY_BMCR_RESET); + DELAY(500); + while(xe_phy_readreg(scp, PHY_BMCR) & PHY_BMCR_RESET) + ; /* nothing */ + XE_MII_DUMP(scp); + return (1); + } } - /* * Clock a series of bits through the MII. */ static void -xe_mii_send(struct xe_softc *scp, u_int32_t bits, int cnt) { - int i; +xe_mii_send(struct xe_softc *scp, uint32_t bits, int cnt) +{ + int i; - XE_SELECT_PAGE(2); - XE_MII_CLR(XE_MII_CLK); + XE_SELECT_PAGE(2); + XE_MII_CLR(XE_MII_CLK); - for (i = (0x1 << (cnt - 1)); i; i >>= 1) { - if (bits & i) { - XE_MII_SET(XE_MII_WRD); - } else { - XE_MII_CLR(XE_MII_WRD); - } - DELAY(1); - XE_MII_CLR(XE_MII_CLK); - DELAY(1); - XE_MII_SET(XE_MII_CLK); - } + for (i = (0x1 << (cnt - 1)); i; i >>= 1) { + if (bits & i) { + XE_MII_SET(XE_MII_WRD); + } else { + XE_MII_CLR(XE_MII_WRD); + } + DELAY(1); + XE_MII_CLR(XE_MII_CLK); + DELAY(1); + XE_MII_SET(XE_MII_CLK); + } } - /* * Read an PHY register through the MII. */ static int -xe_mii_readreg(struct xe_softc *scp, struct xe_mii_frame *frame) { - int i, ack; - - XE_ASSERT_LOCKED(scp); - - /* - * Set up frame for RX. - */ - frame->mii_stdelim = XE_MII_STARTDELIM; - frame->mii_opcode = XE_MII_READOP; - frame->mii_turnaround = 0; - frame->mii_data = 0; +xe_mii_readreg(struct xe_softc *scp, struct xe_mii_frame *frame) +{ + int i, ack; + + XE_ASSERT_LOCKED(scp); + + /* + * Set up frame for RX. + */ + frame->mii_stdelim = XE_MII_STARTDELIM; + frame->mii_opcode = XE_MII_READOP; + frame->mii_turnaround = 0; + frame->mii_data = 0; - XE_SELECT_PAGE(2); - XE_OUTB(XE_GPR2, 0); - - /* - * Turn on data xmit. - */ - XE_MII_SET(XE_MII_DIR); - - xe_mii_sync(scp); - - /* - * Send command/address info. - */ - xe_mii_send(scp, frame->mii_stdelim, 2); - xe_mii_send(scp, frame->mii_opcode, 2); - xe_mii_send(scp, frame->mii_phyaddr, 5); - xe_mii_send(scp, frame->mii_regaddr, 5); - - /* Idle bit */ - XE_MII_CLR((XE_MII_CLK|XE_MII_WRD)); - DELAY(1); - XE_MII_SET(XE_MII_CLK); - DELAY(1); - - /* Turn off xmit. */ - XE_MII_CLR(XE_MII_DIR); - - /* Check for ack */ - XE_MII_CLR(XE_MII_CLK); - DELAY(1); - ack = XE_INB(XE_GPR2) & XE_MII_RDD; - XE_MII_SET(XE_MII_CLK); - DELAY(1); - - /* - * Now try reading data bits. If the ack failed, we still - * need to clock through 16 cycles to keep the PHY(s) in sync. - */ - if (ack) { - for(i = 0; i < 16; i++) { - XE_MII_CLR(XE_MII_CLK); - DELAY(1); - XE_MII_SET(XE_MII_CLK); - DELAY(1); - } - goto fail; - } - - for (i = 0x8000; i; i >>= 1) { - XE_MII_CLR(XE_MII_CLK); - DELAY(1); - if (!ack) { - if (XE_INB(XE_GPR2) & XE_MII_RDD) - frame->mii_data |= i; - DELAY(1); - } - XE_MII_SET(XE_MII_CLK); - DELAY(1); - } + XE_SELECT_PAGE(2); + XE_OUTB(XE_GPR2, 0); -fail: + /* + * Turn on data xmit. + */ + XE_MII_SET(XE_MII_DIR); - XE_MII_CLR(XE_MII_CLK); - DELAY(1); - XE_MII_SET(XE_MII_CLK); - DELAY(1); + xe_mii_sync(scp); - if (ack) - return(1); - return(0); -} + /* + * Send command/address info. + */ + xe_mii_send(scp, frame->mii_stdelim, 2); + xe_mii_send(scp, frame->mii_opcode, 2); + xe_mii_send(scp, frame->mii_phyaddr, 5); + xe_mii_send(scp, frame->mii_regaddr, 5); + + /* Idle bit */ + XE_MII_CLR((XE_MII_CLK|XE_MII_WRD)); + DELAY(1); + XE_MII_SET(XE_MII_CLK); + DELAY(1); + + /* Turn off xmit. */ + XE_MII_CLR(XE_MII_DIR); + + /* Check for ack */ + XE_MII_CLR(XE_MII_CLK); + DELAY(1); + ack = XE_INB(XE_GPR2) & XE_MII_RDD; + XE_MII_SET(XE_MII_CLK); + DELAY(1); + /* + * Now try reading data bits. If the ack failed, we still + * need to clock through 16 cycles to keep the PHY(s) in sync. + */ + if (ack) { + for(i = 0; i < 16; i++) { + XE_MII_CLR(XE_MII_CLK); + DELAY(1); + XE_MII_SET(XE_MII_CLK); + DELAY(1); + } + goto fail; + } + + for (i = 0x8000; i; i >>= 1) { + XE_MII_CLR(XE_MII_CLK); + DELAY(1); + if (!ack) { + if (XE_INB(XE_GPR2) & XE_MII_RDD) + frame->mii_data |= i; + DELAY(1); + } + XE_MII_SET(XE_MII_CLK); + DELAY(1); + } + +fail: + XE_MII_CLR(XE_MII_CLK); + DELAY(1); + XE_MII_SET(XE_MII_CLK); + DELAY(1); + + if (ack) + return(1); + return(0); +} /* * Write to a PHY register through the MII. */ static int -xe_mii_writereg(struct xe_softc *scp, struct xe_mii_frame *frame) { +xe_mii_writereg(struct xe_softc *scp, struct xe_mii_frame *frame) +{ - XE_ASSERT_LOCKED(scp); + XE_ASSERT_LOCKED(scp); - /* - * Set up frame for TX. - */ - frame->mii_stdelim = XE_MII_STARTDELIM; - frame->mii_opcode = XE_MII_WRITEOP; - frame->mii_turnaround = XE_MII_TURNAROUND; + /* + * Set up frame for TX. + */ + frame->mii_stdelim = XE_MII_STARTDELIM; + frame->mii_opcode = XE_MII_WRITEOP; + frame->mii_turnaround = XE_MII_TURNAROUND; - XE_SELECT_PAGE(2); - - /* - * Turn on data output. - */ - XE_MII_SET(XE_MII_DIR); - - xe_mii_sync(scp); - - xe_mii_send(scp, frame->mii_stdelim, 2); - xe_mii_send(scp, frame->mii_opcode, 2); - xe_mii_send(scp, frame->mii_phyaddr, 5); - xe_mii_send(scp, frame->mii_regaddr, 5); - xe_mii_send(scp, frame->mii_turnaround, 2); - xe_mii_send(scp, frame->mii_data, 16); - - /* Idle bit. */ - XE_MII_SET(XE_MII_CLK); - DELAY(1); - XE_MII_CLR(XE_MII_CLK); - DELAY(1); - - /* - * Turn off xmit. - */ - XE_MII_CLR(XE_MII_DIR); - - return(0); -} + XE_SELECT_PAGE(2); + + /* + * Turn on data output. + */ + XE_MII_SET(XE_MII_DIR); + + xe_mii_sync(scp); + xe_mii_send(scp, frame->mii_stdelim, 2); + xe_mii_send(scp, frame->mii_opcode, 2); + xe_mii_send(scp, frame->mii_phyaddr, 5); + xe_mii_send(scp, frame->mii_regaddr, 5); + xe_mii_send(scp, frame->mii_turnaround, 2); + xe_mii_send(scp, frame->mii_data, 16); + + /* Idle bit. */ + XE_MII_SET(XE_MII_CLK); + DELAY(1); + XE_MII_CLR(XE_MII_CLK); + DELAY(1); + + /* + * Turn off xmit. + */ + XE_MII_CLR(XE_MII_DIR); + + return(0); +} /* * Read a register from the PHY. */ -static u_int16_t -xe_phy_readreg(struct xe_softc *scp, u_int16_t reg) { - struct xe_mii_frame frame; +static uint16_t +xe_phy_readreg(struct xe_softc *scp, uint16_t reg) +{ + struct xe_mii_frame frame; - bzero((char *)&frame, sizeof(frame)); + bzero((char *)&frame, sizeof(frame)); - frame.mii_phyaddr = 0; - frame.mii_regaddr = reg; - xe_mii_readreg(scp, &frame); + frame.mii_phyaddr = 0; + frame.mii_regaddr = reg; + xe_mii_readreg(scp, &frame); - return(frame.mii_data); + return (frame.mii_data); } - /* * Write to a PHY register. */ static void -xe_phy_writereg(struct xe_softc *scp, u_int16_t reg, u_int16_t data) { - struct xe_mii_frame frame; - - bzero((char *)&frame, sizeof(frame)); +xe_phy_writereg(struct xe_softc *scp, uint16_t reg, uint16_t data) +{ + struct xe_mii_frame frame; - frame.mii_phyaddr = 0; - frame.mii_regaddr = reg; - frame.mii_data = data; - xe_mii_writereg(scp, &frame); + bzero((char *)&frame, sizeof(frame)); - return; + frame.mii_phyaddr = 0; + frame.mii_regaddr = reg; + frame.mii_data = data; + xe_mii_writereg(scp, &frame); } - /* * A bit of debugging code. */ static void -xe_mii_dump(struct xe_softc *scp) { - int i; - - device_printf(scp->dev, "MII registers: "); - for (i = 0; i < 2; i++) { - printf(" %d:%04x", i, xe_phy_readreg(scp, i)); - } - for (i = 4; i < 7; i++) { - printf(" %d:%04x", i, xe_phy_readreg(scp, i)); - } - printf("\n"); +xe_mii_dump(struct xe_softc *scp) +{ + int i; + + device_printf(scp->dev, "MII registers: "); + for (i = 0; i < 2; i++) { + printf(" %d:%04x", i, xe_phy_readreg(scp, i)); + } + for (i = 4; i < 7; i++) { + printf(" %d:%04x", i, xe_phy_readreg(scp, i)); + } + printf("\n"); } #if 0 void -xe_reg_dump(struct xe_softc *scp) { - int page, i; - - device_printf(scp->dev, "Common registers: "); - for (i = 0; i < 8; i++) { - printf(" %2.2x", XE_INB(i)); - } - printf("\n"); - - for (page = 0; page <= 8; page++) { - device_printf(scp->dev, "Register page %2.2x: ", page); - XE_SELECT_PAGE(page); - for (i = 8; i < 16; i++) { - printf(" %2.2x", XE_INB(i)); - } - printf("\n"); - } - - for (page = 0x10; page < 0x5f; page++) { - if ((page >= 0x11 && page <= 0x3f) || - (page == 0x41) || - (page >= 0x43 && page <= 0x4f) || - (page >= 0x59)) - continue; - device_printf(scp->dev, "Register page %2.2x: ", page); - XE_SELECT_PAGE(page); - for (i = 8; i < 16; i++) { - printf(" %2.2x", XE_INB(i)); - } - printf("\n"); - } +xe_reg_dump(struct xe_softc *scp) +{ + int page, i; + + device_printf(scp->dev, "Common registers: "); + for (i = 0; i < 8; i++) { + printf(" %2.2x", XE_INB(i)); + } + printf("\n"); + + for (page = 0; page <= 8; page++) { + device_printf(scp->dev, "Register page %2.2x: ", page); + XE_SELECT_PAGE(page); + for (i = 8; i < 16; i++) { + printf(" %2.2x", XE_INB(i)); + } + printf("\n"); + } + + for (page = 0x10; page < 0x5f; page++) { + if ((page >= 0x11 && page <= 0x3f) || + (page == 0x41) || + (page >= 0x43 && page <= 0x4f) || + (page >= 0x59)) + continue; + device_printf(scp->dev, "Register page %2.2x: ", page); + XE_SELECT_PAGE(page); + for (i = 8; i < 16; i++) { + printf(" %2.2x", XE_INB(i)); + } + printf("\n"); + } } #endif @@ -1905,9 +1964,8 @@ xe_activate(device_t dev) if (!sc->modem) { sc->port_rid = 0; /* 0 is managed by pccard */ sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sc->port_rid, 0, ~0, 16, RF_ACTIVE); - } - else if (sc->dingo) { + &sc->port_rid, 0ul, ~0ul, 16, RF_ACTIVE); + } else if (sc->dingo) { /* * Find a 16 byte aligned ioport for the card. */ @@ -1915,13 +1973,12 @@ xe_activate(device_t dev) sc->port_rid = 1; /* 0 is managed by pccard */ start = 0x100; do { - sc->port_res = bus_alloc_resource(dev, - SYS_RES_IOPORT, &sc->port_rid, start, 0x3ff, 16, - RF_ACTIVE); - if (sc->port_res == 0) - break; /* we failed */ + sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->port_rid, start, 0x3ff, 16, RF_ACTIVE); + if (sc->port_res == NULL) + break; if ((rman_get_start(sc->port_res) & 0xf) == 0) - break; /* good */ + break; bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, sc->port_res); start = (rman_get_start(sc->port_res) + 15) & ~0xf; @@ -1929,43 +1986,43 @@ xe_activate(device_t dev) DEVPRINTF(1, (dev, "RealPort port 0x%0lx, size 0x%0lx\n", bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid), bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid))); - } - else if (sc->ce2) { - /* - * Find contiguous I/O port for the Ethernet function on CEM2 and - * CEM3 cards. We allocate window 0 wherever pccard has decided - * it should be, then find an available window adjacent to it for - * the second function. Not sure that both windows are actually - * needed. - */ - DEVPRINTF(1, (dev, "Finding I/O port for CEM2/CEM3\n")); - sc->ce2_port_rid = 0; /* 0 is managed by pccard */ - sc->ce2_port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sc->ce2_port_rid, 0, ~0, - 8, RF_ACTIVE); - if (!sc->ce2_port_res) { - DEVPRINTF(1, (dev, "Cannot allocate I/O port for modem\n")); - xe_deactivate(dev); - return ENOMEM; - } - - sc->port_rid = 1; - start = bus_get_resource_start(dev, SYS_RES_IOPORT, - sc->ce2_port_rid); - for (i = 0; i < 2; i++) { - start += (i == 0 ? 8 : -24); - sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, - &sc->port_rid, start, start + 15, 16, RF_ACTIVE); - if (sc->port_res == 0) - continue; /* Failed, try again if possible */ - if (bus_get_resource_start(dev, SYS_RES_IOPORT, - sc->port_rid) == start) - break; /* Success! */ - - bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, - sc->port_res); - sc->port_res = 0; - } + } else if (sc->ce2) { + /* + * Find contiguous I/O port for the Ethernet function + * on CEM2 and CEM3 cards. We allocate window 0 + * wherever pccard has decided it should be, then find + * an available window adjacent to it for the second + * function. Not sure that both windows are actually + * needed. + */ + DEVPRINTF(1, (dev, "Finding I/O port for CEM2/CEM3\n")); + sc->ce2_port_rid = 0; /* 0 is managed by pccard */ + sc->ce2_port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->ce2_port_rid, 0ul, ~0ul, 8, RF_ACTIVE); + if (sc->ce2_port_res == NULL) { + DEVPRINTF(1, (dev, + "Cannot allocate I/O port for modem\n")); + xe_deactivate(dev); + return (ENOMEM); + } + + sc->port_rid = 1; + start = bus_get_resource_start(dev, SYS_RES_IOPORT, + sc->ce2_port_rid); + for (i = 0; i < 2; i++) { + start += (i == 0 ? 8 : -24); + sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->port_rid, start, start + 15, 16, RF_ACTIVE); + if (sc->port_res == NULL) + continue; + if (bus_get_resource_start(dev, SYS_RES_IOPORT, + sc->port_rid) == start) + break; + + bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, + sc->port_res); + sc->port_res = NULL; + } DEVPRINTF(1, (dev, "CEM2/CEM3 port 0x%0lx, size 0x%0lx\n", bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid), bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid))); @@ -1974,16 +2031,16 @@ xe_activate(device_t dev) if (!sc->port_res) { DEVPRINTF(1, (dev, "Cannot allocate ioport\n")); xe_deactivate(dev); - return ENOMEM; + return (ENOMEM); } sc->irq_rid = 0; sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, RF_ACTIVE); - if (!sc->irq_res) { + if (sc->irq_res == NULL) { DEVPRINTF(1, (dev, "Cannot allocate irq\n")); xe_deactivate(dev); - return ENOMEM; + return (ENOMEM); } return (0); @@ -1997,21 +2054,20 @@ xe_deactivate(device_t dev) DEVPRINTF(2, (dev, "deactivate\n")); if (sc->intrhand) bus_teardown_intr(dev, sc->irq_res, sc->intrhand); - sc->intrhand = 0; + sc->intrhand = NULL; if (sc->port_res) bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, sc->port_res); - sc->port_res = 0; + sc->port_res = NULL; if (sc->ce2_port_res) bus_release_resource(dev, SYS_RES_IOPORT, sc->ce2_port_rid, - sc->ce2_port_res); - sc->ce2_port_res = 0; + sc->ce2_port_res); + sc->ce2_port_res = NULL; if (sc->irq_res) bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq_res); - sc->irq_res = 0; + sc->irq_res = NULL; if (sc->ifp) if_free(sc->ifp); - sc->ifp = 0; - return; + sc->ifp = NULL; } diff --git a/sys/dev/xe/if_xe_pccard.c b/sys/dev/xe/if_xe_pccard.c index 039dd90..f60ab1a 100644 --- a/sys/dev/xe/if_xe_pccard.c +++ b/sys/dev/xe/if_xe_pccard.c @@ -67,38 +67,37 @@ __FBSDID("$FreeBSD$"); extern int xe_debug; -#define DEVPRINTF(level, arg) if (xe_debug >= (level)) device_printf arg -#define DPRINTF(level, arg) if (xe_debug >= (level)) printf arg +#define DEVPRINTF(level, arg) if (xe_debug >= (level)) device_printf arg +#define DPRINTF(level, arg) if (xe_debug >= (level)) printf arg #else -#define DEVPRINTF(level, arg) -#define DPRINTF(level, arg) +#define DEVPRINTF(level, arg) +#define DPRINTF(level, arg) #endif -#define XE_CARD_TYPE_FLAGS_NO 0x0 -#define XE_CARD_TYPE_FLAGS_CE2 0x1 -#define XE_CARD_TYPE_FLAGS_MOHAWK 0x2 -#define XE_CARD_TYPE_FLAGS_DINGO 0x4 -#define XE_PROD_ETHER_MASK 0x0100 -#define XE_PROD_MODEM_MASK 0x1000 +#define XE_CARD_TYPE_FLAGS_NO 0x0 +#define XE_CARD_TYPE_FLAGS_CE2 0x1 +#define XE_CARD_TYPE_FLAGS_MOHAWK 0x2 +#define XE_CARD_TYPE_FLAGS_DINGO 0x4 +#define XE_PROD_ETHER_MASK 0x0100 +#define XE_PROD_MODEM_MASK 0x1000 -#define XE_BOGUS_MAC_OFFSET 0x90 +#define XE_BOGUS_MAC_OFFSET 0x90 /* MAC vendor prefix used by most Xircom cards is 00:80:c7 */ -#define XE_MAC_ADDR_0 0x00 -#define XE_MAC_ADDR_1 0x80 -#define XE_MAC_ADDR_2 0xc7 +#define XE_MAC_ADDR_0 0x00 +#define XE_MAC_ADDR_1 0x80 +#define XE_MAC_ADDR_2 0xc7 /* Some (all?) REM56 cards have vendor prefix 00:10:a4 */ -#define XE_REM56_MAC_ADDR_0 0x00 -#define XE_REM56_MAC_ADDR_1 0x10 -#define XE_REM56_MAC_ADDR_2 0xa4 - +#define XE_REM56_MAC_ADDR_0 0x00 +#define XE_REM56_MAC_ADDR_1 0x10 +#define XE_REM56_MAC_ADDR_2 0xa4 struct xe_pccard_product { struct pccard_product product; - uint16_t prodext; - uint16_t flags; + uint16_t prodext; + uint16_t flags; }; static const struct xe_pccard_product xe_pccard_products[] = { @@ -126,7 +125,6 @@ static const struct xe_pccard_product xe_pccard_products[] = { { { NULL }, 0, 0 } }; - /* * Fixing for CEM2, CEM3 and CEM56/REM56 cards. These need some magic to * enable the Ethernet function, which isn't mentioned anywhere in the CIS. @@ -135,7 +133,7 @@ static const struct xe_pccard_product xe_pccard_products[] = { static int xe_cemfix(device_t dev) { - struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev); + struct xe_softc *sc = device_get_softc(dev); int ioport; DEVPRINTF(2, (dev, "cemfix\n")); @@ -164,7 +162,8 @@ xe_cemfix(device_t dev) } static int -xe_pccard_product_match(device_t dev, const struct pccard_product* ent, int vpfmatch) +xe_pccard_product_match(device_t dev, const struct pccard_product* ent, + int vpfmatch) { const struct xe_pccard_product* xpp; uint16_t prodext; @@ -184,7 +183,7 @@ xe_pccard_product_match(device_t dev, const struct pccard_product* ent, int vpfm static const struct xe_pccard_product * xe_pccard_get_product(device_t dev) { - return ((const struct xe_pccard_product *) pccard_product_lookup(dev, + return ((const struct xe_pccard_product *)pccard_product_lookup(dev, (const struct pccard_product *)xe_pccard_products, sizeof(xe_pccard_products[0]), xe_pccard_product_match)); } @@ -237,7 +236,7 @@ xe_bad_mac(uint8_t *enaddr) static int xe_pccard_attach(device_t dev) { - struct xe_softc *scp = (struct xe_softc *) device_get_softc(dev); + struct xe_softc *scp = device_get_softc(dev); uint32_t vendor,product; uint16_t prodext; const char* vendor_str = NULL; diff --git a/sys/dev/xe/if_xevar.h b/sys/dev/xe/if_xevar.h index 12c37cb..616b52c 100644 --- a/sys/dev/xe/if_xevar.h +++ b/sys/dev/xe/if_xevar.h @@ -33,40 +33,40 @@ * One of these structures per allocated device */ struct xe_softc { - struct ifmedia ifmedia; - struct ifmib_iso_8802_3 mibdata; - struct callout media_timer; - struct callout wdog_timer; - int tx_timeout; - struct mtx lock; - struct ifnet *ifp; - struct ifmedia *ifm; - u_char enaddr[6]; - const char *card_type;/* Card model name */ - const char *vendor; /* Card manufacturer */ - device_t dev; /* Device */ - void *intrhand; - struct resource *irq_res; - int irq_rid; - struct resource *port_res; - int port_rid; - struct resource *ce2_port_res; - int ce2_port_rid; - int srev; /* Silicon revision */ - int tx_queued; /* Packets currently waiting to transmit */ - int tx_tpr; /* Last value of TPR reg on card */ - int tx_timeouts; /* Count of transmit timeouts */ - u_int16_t tx_min; /* Smallest packet we can send without padding */ - u_int16_t tx_thres; /* Threshold bytes for early transmit */ - int autoneg_status; /* Autonegotiation progress state */ - int media; /* Private media word */ - u_char version; /* Bonding Version register from card */ - u_char modem; /* 1 = Card has a modem */ - u_char ce2; /* 1 = Card has CE2 silicon */ - u_char mohawk; /* 1 = Card has Mohawk (CE3) silicon */ - u_char dingo; /* 1 = Card has Dingo (CEM56) silicon */ - u_char phy_ok; /* 1 = MII-compliant PHY found and initialised */ - u_char gone; /* 1 = Card bailed out */ + struct ifmedia ifmedia; + struct ifmib_iso_8802_3 mibdata; + struct callout media_timer; + struct callout wdog_timer; + int tx_timeout; + struct mtx lock; + struct ifnet *ifp; + struct ifmedia *ifm; + u_char enaddr[ETHER_ADDR_LEN]; + const char *card_type; /* Card model name */ + const char *vendor; /* Card manufacturer */ + device_t dev; /* Device */ + void *intrhand; + struct resource *irq_res; + int irq_rid; + struct resource *port_res; + int port_rid; + struct resource *ce2_port_res; + int ce2_port_rid; + int srev; /* Silicon revision */ + int tx_queued; /* Transmit packets currently waiting */ + int tx_tpr; /* Last value of TPR reg on card */ + int tx_timeouts; /* Count of transmit timeouts */ + uint16_t tx_min; /* Smallest packet for no padding */ + uint16_t tx_thres; /* Threshold bytes for early transmit */ + int autoneg_status; /* Autonegotiation progress state */ + int media; /* Private media word */ + u_char version; /* Bonding Version register from card */ + u_char modem; /* 1 = Card has a modem */ + u_char ce2; /* 1 = Card has CE2 silicon */ + u_char mohawk; /* 1 = Card has Mohawk (CE3) silicon */ + u_char dingo; /* 1 = Card has Dingo (CEM56) silicon */ + u_char phy_ok; /* 1 = MII-compliant PHY found */ + u_char gone; /* 1 = Card bailed out */ }; #define XE_LOCK(sc) mtx_lock(&(sc)->lock) @@ -76,15 +76,15 @@ struct xe_softc { /* * For accessing card registers */ -#define XE_INB(r) bus_read_1(scp->port_res, (r)) -#define XE_INW(r) bus_read_2(scp->port_res, (r)) -#define XE_OUTB(r, b) bus_write_1(scp->port_res, (r), (b)) -#define XE_OUTW(r, w) bus_write_2(scp->port_res, (r), (w)) -#define XE_SELECT_PAGE(p) XE_OUTB(XE_PR, (p)) +#define XE_INB(r) bus_read_1(scp->port_res, (r)) +#define XE_INW(r) bus_read_2(scp->port_res, (r)) +#define XE_OUTB(r, b) bus_write_1(scp->port_res, (r), (b)) +#define XE_OUTW(r, w) bus_write_2(scp->port_res, (r), (w)) +#define XE_SELECT_PAGE(p) XE_OUTB(XE_PR, (p)) -int xe_attach(device_t dev); -int xe_activate(device_t dev); -void xe_deactivate(device_t dev); -void xe_stop(struct xe_softc *scp); +int xe_attach(device_t dev); +int xe_activate(device_t dev); +void xe_deactivate(device_t dev); +void xe_stop(struct xe_softc *scp); #endif /* DEV_XE_IF_XEVAR_H */ -- cgit v1.1