From owner-freebsd-bugs@FreeBSD.ORG Sun Apr 6 09:00:32 2003 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id F04C137B401 for ; Sun, 6 Apr 2003 09:00:31 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3D3B143FCB for ; Sun, 6 Apr 2003 09:00:29 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.9/8.12.9) with ESMTP id h36G0TUp025877 for ; Sun, 6 Apr 2003 09:00:29 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.9/8.12.9/Submit) id h36G0Tkl025876; Sun, 6 Apr 2003 09:00:29 -0700 (PDT) Resent-Date: Sun, 6 Apr 2003 09:00:29 -0700 (PDT) Resent-Message-Id: <200304061600.h36G0Tkl025876@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Scott Mitchell Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id A0A9D37B401 for ; Sun, 6 Apr 2003 08:51:19 -0700 (PDT) Received: from mta02-svc.ntlworld.com (mta02-svc.ntlworld.com [62.253.162.42]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0260343FBF for ; Sun, 6 Apr 2003 08:51:17 -0700 (PDT) (envelope-from scott@fishballoon.org) Received: from fishballoon.org ([81.104.195.199]) by mta02-svc.ntlworld.com (InterMail vM.4.01.03.37 201-229-121-137-20020806) with ESMTP id <20030406155111.PTFQ9882.mta02-svc.ntlworld.com@fishballoon.org> for ; Sun, 6 Apr 2003 16:51:11 +0100 Received: from tuatara.fishballoon.org (tuatara [192.168.1.6]) by fishballoon.org (8.12.6p2/8.12.6) with ESMTP id h36FoUGw045989 for ; Sun, 6 Apr 2003 16:50:30 +0100 (BST) (envelope-from scott@tuatara.fishballoon.org) Received: (from scott@localhost) by tuatara.fishballoon.org (8.12.7/8.12.6/Submit) id h36FoUI9072246; Sun, 6 Apr 2003 16:50:30 +0100 (BST) (envelope-from scott) Message-Id: <200304061550.h36FoUI9072246@tuatara.fishballoon.org> Date: Sun, 6 Apr 2003 16:50:30 +0100 (BST) From: Scott Mitchell To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: kern/50644: [PATCH] Update xe driver: multicast, hardware setup, etc. X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Scott Mitchell List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 06 Apr 2003 16:00:32 -0000 >Number: 50644 >Category: kern >Synopsis: [PATCH] Update xe driver: multicast, hardware setup, etc. >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sun Apr 06 09:00:28 PDT 2003 >Closed-Date: >Last-Modified: >Originator: Scott Mitchell >Release: FreeBSD 5.0-CURRENT i386 >Organization: >Environment: System: FreeBSD orac 5.0-CURRENT FreeBSD 5.0-CURRENT #0: Sun Apr 6 14:00:33 BST 2003 scott@tuatara:/local/0/obj/local/0/-CURRENT/src/sys/ORAC i386 >Description: The xe driver is in dire need of some maintenance :-) The attached patch is the first of several I have planned. This one: - Fixes the hardware initialisation to eliminate the watchdog timeout every time the card is powered up. - Add multicast support (apparently this had never worked). - Enable 'early transmit' mode on CE3-class hardware. This may improve performance, assuming the card can be fed fast enough. - Clean up handling of MAC interrupts and statistics in ISR. - Some general code cleanup. The next stage will be to improve the detection and handling of CE2-class cards, which have also never really worked. I'm releasing this work in progress in the hope that people will test it and confirm that I haven't broken anything -- any card that worked before should continue to work, hopefully with fewer complaints. >How-To-Repeat: >Fix: Index: src/sys/dev/xe/if_xe.c =================================================================== RCS file: /home/ncvs/src/sys/dev/xe/if_xe.c,v retrieving revision 1.36 retrieving revision 1.35.10000.3 diff -c -r1.36 -r1.35.10000.3 *** src/sys/dev/xe/if_xe.c 19 Feb 2003 05:47:17 -0000 1.36 --- src/sys/dev/xe/if_xe.c 6 Apr 2003 15:06:24 -0000 1.35.10000.3 *************** *** 1,5 **** /*- ! * Copyright (c) 1998, 1999 Scott Mitchell * All rights reserved. * * Redistribution and use in source and binary forms, with or without --- 1,5 ---- /*- ! * Copyright (c) 1998, 1999, 2003 Scott Mitchell * All rights reserved. * * Redistribution and use in source and binary forms, with or without *************** *** 24,39 **** * SUCH DAMAGE. * * $Id: if_xe.c,v 1.20 1999/06/13 19:17:40 scott Exp $ ! * $FreeBSD: src/sys/dev/xe/if_xe.c,v 1.36 2003/02/19 05:47:17 imp Exp $ ! */ ! ! /* ! * XXX TODO XXX ! * ! * I've pushed this fairly far, but there are some things that need to be ! * done here. I'm documenting them here in case I get destracted. -- imp ! * ! * xe_cem56fix -- need to figure out how to map the extra stuff. */ /* --- 24,30 ---- * SUCH DAMAGE. * * $Id: if_xe.c,v 1.20 1999/06/13 19:17:40 scott Exp $ ! * $FreeBSD: src/sys/dev/xe/if_xe.c,v 1.35.10000.3 2003/04/06 15:06:24 scott Exp $ */ /* *************** *** 97,110 **** * the CEM56/REM56 support code; and the FreeBSD UK Users' Group for hosting * the web pages. * - * Contact points: - * - * Driver web page: http://ukug.uk.freebsd.org/~scott/xe_drv/ - * - * Mailing list: http://www.lovett.com/lists/freebsd-xircom/ - * or send "subscribe freebsd-xircom" to - * * Author email: */ --- 88,95 ---- * the CEM56/REM56 support code; and the FreeBSD UK Users' Group for hosting * the web pages. * * Author email: + * Driver web page: http://ukug.uk.freebsd.org/~scott/xe_drv/ */ *************** *** 157,162 **** --- 142,151 ---- #define XE_AUTONEG_100TX 3 /* Trying to force 100baseTX link */ #define XE_AUTONEG_FAIL 4 /* Autonegotiation failed */ + /* + * Multicast hashing CRC constants + */ + #define XE_CRC_POLY 0x04c11db6 /* * Prototypes start here *************** *** 168,183 **** 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_hard_reset (struct xe_softc *scp); ! static void xe_soft_reset (struct xe_softc *scp); static void xe_stop (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_setmulti (struct xe_softc *scp); ! static void xe_setaddrs (struct xe_softc *scp); static int xe_pio_write_packet (struct xe_softc *scp, struct mbuf *mbp); - static u_int32_t xe_compute_crc (u_int8_t *data, int len) __unused; - static int xe_compute_hashbit (u_int32_t crc) __unused; /* * MII functions --- 157,170 ---- 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_stop (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_set_hash (struct xe_softc *scp, u_int8_t* addr); static int xe_pio_write_packet (struct xe_softc *scp, struct mbuf *mbp); /* * MII functions *************** *** 190,201 **** 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); /* ! * Debug functions -- uncomment for VERY verbose dignostic information. ! * Set to 1 for less verbose information */ ! /* #define XE_DEBUG 2 */ ! #ifdef XE_DEBUG #define XE_REG_DUMP(scp) xe_reg_dump((scp)) #define XE_MII_DUMP(scp) xe_mii_dump((scp)) static void xe_reg_dump (struct xe_softc *scp); --- 177,192 ---- 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); + /* ! * Debug logging level (comment out for normal operation): ! * 1 = Log more hardware details, xe_ioctl details ! * 2 = Log most function calls, some (eg. multicast, MII) in detail ! * 3 = Log everything, including all interrupts and packets sent */ ! #define XE_DEBUG 0 ! ! #if XE_DEBUG > 2 #define XE_REG_DUMP(scp) xe_reg_dump((scp)) #define XE_MII_DUMP(scp) xe_mii_dump((scp)) static void xe_reg_dump (struct xe_softc *scp); *************** *** 205,210 **** --- 196,202 ---- #define XE_MII_DUMP(scp) #endif + /* * Attach a device. */ *************** *** 213,232 **** { struct xe_softc *scp = device_get_softc(dev); ! #ifdef XE_DEBUG device_printf(dev, "attach\n"); #endif ! /* Fill in some private data */ scp->ifp = &scp->arpcom.ac_if; scp->ifm = &scp->ifmedia; ! scp->autoneg_status = 0; - /* Hopefully safe to read this here */ - XE_SELECT_PAGE(4); - scp->version = XE_INB(XE_BOV); - - scp->dev = dev; /* Initialise the ifnet structure */ if (!scp->ifp->if_name) { scp->ifp->if_softc = scp; --- 205,220 ---- { struct xe_softc *scp = device_get_softc(dev); ! #if XE_DEBUG > 1 device_printf(dev, "attach\n"); #endif ! /* Initialise stuff... */ ! scp->dev = dev; scp->ifp = &scp->arpcom.ac_if; scp->ifm = &scp->ifmedia; ! scp->autoneg_status = XE_AUTONEG_NONE; /* Initialise the ifnet structure */ if (!scp->ifp->if_name) { scp->ifp->if_softc = scp; *************** *** 241,246 **** --- 229,235 ---- scp->ifp->if_ioctl = xe_ioctl; scp->ifp->if_watchdog = xe_watchdog; scp->ifp->if_init = xe_init; + scp->ifp->if_baudrate = 100000000; scp->ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; } *************** *** 248,291 **** ifmedia_init(scp->ifm, 0, xe_media_change, xe_media_status); callout_handle_init(&scp->chand); ! /* ! * Fill in supported media types. Some cards _do_ support full duplex ! * operation, but this driver doesn't, yet. Therefore we leave those modes ! * out of the list. We support some form of autoselection in all cases. ! */ if (scp->mohawk) { ifmedia_add(scp->ifm, IFM_ETHER|IFM_100_TX, 0, NULL); ! ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_T, 0, NULL); } ! else { ! ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_T, 0, NULL); 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); /* Print some useful information */ ! device_printf(dev, "%s %s, bonding version %#x%s%s\n", scp->vendor, scp->card_type, scp->version, scp->mohawk ? ", 100Mbps capable" : "", scp->modem ? ", with modem" : ""); if (scp->mohawk) { XE_SELECT_PAGE(0x10); ! device_printf(dev, "DingoID = %#x, RevisionID = %#x, VendorID = %#x\n", XE_INW(XE_DINGOID), XE_INW(XE_RevID), XE_INW(XE_VendorID)); } if (scp->ce2) { XE_SELECT_PAGE(0x45); ! device_printf(dev, "CE2 version = %#x\n", XE_INB(XE_REV)); } ! ! /* Print MAC address */ device_printf(dev, "Ethernet address %6D\n", scp->arpcom.ac_enaddr, ":"); /* Attach the interface */ --- 237,288 ---- ifmedia_init(scp->ifm, 0, xe_media_change, xe_media_status); callout_handle_init(&scp->chand); ! /* 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_reset(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, "%s %s, version 0x%02x/0x%02x%s%s\n", scp->vendor, scp->card_type, scp->version, + scp->srev, scp->mohawk ? ", 100Mbps capable" : "", scp->modem ? ", with modem" : ""); + #if XE_DEBUG > 0 if (scp->mohawk) { XE_SELECT_PAGE(0x10); ! device_printf(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); ! device_printf(dev, "CE2 version = 0x%#02x\n", XE_INB(XE_REV)); } ! #endif device_printf(dev, "Ethernet address %6D\n", scp->arpcom.ac_enaddr, ":"); /* Attach the interface */ *************** *** 297,401 **** /* ! * Initialize device. Completes the reset procedure on the card and starts ! * output. If there's an autonegotiation in progress we DON'T do anything; ! * the media selection code will call us again when it's done. */ static void xe_init(void *xscp) { struct xe_softc *scp = xscp; int s; ! #ifdef XE_DEBUG device_printf(scp->dev, "init\n"); #endif ! if (TAILQ_EMPTY(&scp->ifp->if_addrhead)) return; /* Reset transmitter flags */ scp->tx_queued = 0; scp->tx_tpr = 0; ! scp->tx_collisions = 0; scp->ifp->if_timer = 0; ! s = splimp(); XE_SELECT_PAGE(0x42); ! XE_OUTB(XE_SWC0, 0x20); /* Disable source insertion (WTF is that?) */ ! /* ! * Set the 'local memory dividing line' -- splits the 32K card memory into ! * 8K for transmit buffers and 24K for receive. This is done automatically ! * on newer revision cards. ! */ if (scp->srev != 1) { XE_SELECT_PAGE(2); XE_OUTW(XE_RBS, 0x2000); } /* Set up multicast addresses */ ! xe_setmulti(scp); ! /* Fix the data offset register -- reset leaves it off-by-one */ XE_SELECT_PAGE(0); XE_OUTW(XE_DO, 0x2000); ! /* ! * Set MAC interrupt masks and clear status regs. The bit names are direct ! * from the Linux code; I have no idea what most of them do. ! */ ! XE_SELECT_PAGE(0x40); /* Bit 7..0 */ ! XE_OUTB(XE_RX0Msk, 0xff); /* ROK, RAB, rsv, RO, CRC, AE, PTL, MP */ ! XE_OUTB(XE_TX0Msk, 0xff); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */ ! XE_OUTB(XE_TX0Msk+1, 0xb0); /* rsv, rsv, PTD, EXT, rsv, rsv, rsv, rsv */ ! XE_OUTB(XE_RST0, 0x00); /* ROK, RAB, REN, RO, CRC, AE, PTL, MP */ ! XE_OUTB(XE_TXST0, 0x00); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */ ! XE_OUTB(XE_TXST1, 0x00); /* TEN, rsv, PTD, EXT, retry_counter:4 */ ! /* ! * Check for an in-progress autonegotiation. If one is active, just set ! * IFF_RUNNING and return. The media selection code will call us again when ! * it's done. ! */ ! if (scp->autoneg_status) { ! scp->ifp->if_flags |= IFF_RUNNING; ! } ! else { ! /* Enable receiver, 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); ! /* Attempt to start output */ ! scp->ifp->if_flags |= IFF_RUNNING; ! scp->ifp->if_flags &= ~IFF_OACTIVE; ! xe_start(scp->ifp); ! } (void)splx(s); } /* ! * Start output on interface. We make two assumptions here: ! * 1) that the current priority is set to splimp _before_ this code ! * is called *and* is returned to the appropriate priority after ! * return ! * 2) that the IFF_OACTIVE flag is checked before this code is called ! * (i.e. that the output part of the interface is idle) */ static void xe_start(struct ifnet *ifp) { struct xe_softc *scp = ifp->if_softc; struct mbuf *mbp; /* * Loop while there are packets to be sent, and space to send them. */ while (1) { ! IF_DEQUEUE(&ifp->if_snd, mbp); /* Suck a packet off the send queue */ if (mbp == NULL) { /* --- 294,445 ---- /* ! * Complete hardware intitialisation and enable output. Exits without doing ! * anything if there's no address assigned to the card, or if media selection ! * is in progress (the latter implies we've already run this function). */ static void xe_init(void *xscp) { struct xe_softc *scp = xscp; + unsigned i; int s; ! if (TAILQ_EMPTY(&scp->ifp->if_addrhead)) return; ! ! if (scp->autoneg_status != XE_AUTONEG_NONE) return; ! ! #if XE_DEBUG > 1 device_printf(scp->dev, "init\n"); #endif ! s = splimp(); /* Reset transmitter flags */ scp->tx_queued = 0; scp->tx_tpr = 0; ! scp->tx_timeouts = 0; ! scp->tx_thres = 64; scp->ifp->if_timer = 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, scp->arpcom.ac_enaddr[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_flags |= IFF_RUNNING; ! scp->ifp->if_flags &= ~IFF_OACTIVE; (void)splx(s); } /* ! * Start output on interface. Should be called at splimp() priority. Check ! * that the output is idle (ie, IFF_OACTIVE is not set) before calling this ! * function. If media selection is in progress we set IFF_OACTIVE ourselves ! * and return immediately. */ static void xe_start(struct ifnet *ifp) { struct xe_softc *scp = ifp->if_softc; struct mbuf *mbp; + if (scp->autoneg_status != XE_AUTONEG_NONE) { + ifp->if_flags |= IFF_OACTIVE; + return; + } + + #if XE_DEBUG > 2 + device_printf(scp->dev, "start"); + #endif + /* * 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) { /* *************** *** 410,416 **** } if (xe_pio_write_packet(scp, mbp) != 0) { ! IF_PREPEND(&ifp->if_snd, mbp); /* Push the packet back onto the queue */ ifp->if_flags |= IFF_OACTIVE; return; } --- 454,461 ---- } if (xe_pio_write_packet(scp, mbp) != 0) { ! /* Push the packet back onto the queue */ ! IF_PREPEND(&ifp->if_snd, mbp); ifp->if_flags |= IFF_OACTIVE; return; } *************** *** 418,424 **** /* Tap off here if there is a bpf listener */ BPF_MTAP(ifp, mbp); ! ifp->if_timer = 5; /* In case we don't hear from the card again */ scp->tx_queued++; m_freem(mbp); --- 463,470 ---- /* Tap off here if there is a bpf listener */ BPF_MTAP(ifp, mbp); ! /* In case we don't hear from the card again... */ ! ifp->if_timer = 5; scp->tx_queued++; m_freem(mbp); *************** *** 441,455 **** switch (command) { ! case SIOCSIFFLAGS: /* * If the interface is marked up and stopped, then start it. If it is * marked down and running, then stop it. */ if (ifp->if_flags & IFF_UP) { if (!(ifp->if_flags & IFF_RUNNING)) { ! xe_hard_reset(scp); ! xe_setmedia(scp); xe_init(scp); } } --- 487,503 ---- switch (command) { ! case SIOCSIFFLAGS: ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "ioctl: SIOCSIFFLAGS: 0x%04x\n", ifp->if_flags); ! #endif /* * If the interface is marked up and stopped, then start it. If it is * marked down and running, then stop it. */ if (ifp->if_flags & IFF_UP) { if (!(ifp->if_flags & IFF_RUNNING)) { ! xe_reset(scp); xe_init(scp); } } *************** *** 457,483 **** if (ifp->if_flags & IFF_RUNNING) xe_stop(scp); } ! case SIOCADDMULTI: ! case SIOCDELMULTI: /* ! * Multicast list has (maybe) changed; set the hardware filter ! * accordingly. This also serves to deal with promiscuous mode if we have ! * a BPF listener active. */ ! xe_setmulti(scp); error = 0; break; ! case SIOCSIFMEDIA: ! case SIOCGIFMEDIA: /* * Someone wants to get/set media options. */ error = ifmedia_ioctl(ifp, (struct ifreq *)data, &scp->ifmedia, command); break; ! default: error = ether_ioctl(ifp, command, data); } --- 505,540 ---- if (ifp->if_flags & IFF_RUNNING) xe_stop(scp); } + /* FALL THROUGH (handle changes to PROMISC/ALLMULTI flags) */ ! case SIOCADDMULTI: ! case SIOCDELMULTI: ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "ioctl: SIOC{ADD,DEL}MULTI\n"); ! #endif /* ! * Multicast list has (maybe) changed; set the hardware filters ! * accordingly. */ ! xe_set_multicast(scp); error = 0; break; ! case SIOCSIFMEDIA: ! case SIOCGIFMEDIA: ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "ioctl: bounce to ifmedia_ioctl\n"); ! #endif /* * Someone wants to get/set media options. */ error = ifmedia_ioctl(ifp, (struct ifreq *)data, &scp->ifmedia, command); break; ! default: ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "ioctl: bounce to ether_ioctl\n"); ! #endif error = ether_ioctl(ifp, command, data); } *************** *** 510,757 **** { struct xe_softc *scp = (struct xe_softc *) xscp; struct ifnet *ifp; ! int result; ! u_int16_t rx_bytes, rxs, txs; ! u_int8_t psr, isr, esr, rsr; ifp = &scp->arpcom.ac_if; - rx_bytes = 0; /* Bytes received on this interrupt */ - result = 0; /* Set true if the interrupt is for us */ ! if (scp->mohawk) { ! XE_OUTB(XE_CR, 0); /* Disable interrupts */ ! } ! psr = XE_INB(XE_PR); /* Stash the current register page */ ! /* ! * Read ISR to see what caused this interrupt. Note that this clears the ! * ISR on CE2 type cards. ! */ ! if ((isr = XE_INB(XE_ISR)) && isr != 0xff) { ! result = 1; /* This device did generate an int */ ! esr = XE_INB(XE_ESR); /* Read the other status registers */ XE_SELECT_PAGE(0x40); ! rxs = XE_INB(XE_RST0); ! XE_OUTB(XE_RST0, ~rxs & 0xff); ! txs = XE_INB(XE_TXST0); ! txs |= XE_INB(XE_TXST1) << 8; XE_OUTB(XE_TXST0, 0); XE_OUTB(XE_TXST1, 0); XE_SELECT_PAGE(0); #if XE_DEBUG > 2 ! printf("xe%d: ISR=%#2.2x ESR=%#2.2x RST=%#2.2x TXST=%#4.4x\n", unit, isr, esr, rxs, txs); #endif ! /* ! * Handle transmit interrupts ! */ if (isr & XE_ISR_TX_PACKET) { ! u_int8_t new_tpr, sent; ! ! if ((new_tpr = XE_INB(XE_TPR)) < scp->tx_tpr) /* Update packet count */ ! sent = (0xff - scp->tx_tpr) + new_tpr; /* TPR rolled over */ ! else ! sent = new_tpr - scp->tx_tpr; ! if (sent > 0) { /* Packets sent since last interrupt */ ! scp->tx_tpr = new_tpr; scp->tx_queued -= sent; ifp->if_opackets += sent; ! ifp->if_collisions += scp->tx_collisions; /* ! * Collision stats are a PITA. If multiples frames have been sent, we ! * distribute any outstanding collision count equally amongst them. ! * However, if we're missing interrupts we're quite likely to also ! * miss some collisions; thus the total count will be off anyway. ! * Likewise, if we miss a frame dropped due to excessive collisions ! * any outstanding collisions count will be held against the next ! * frame to be successfully sent. Hopefully it averages out in the ! * end! ! * XXX - This will screw up if tx_collisions/sent > 14. FIX IT! */ ! switch (scp->tx_collisions) { ! case 0: break; ! case 1: scp->mibdata.dot3StatsSingleCollisionFrames++; scp->mibdata.dot3StatsCollFrequencies[0]++; break; ! default: ! if (sent == 1) { ! scp->mibdata.dot3StatsMultipleCollisionFrames++; ! scp->mibdata.dot3StatsCollFrequencies[scp->tx_collisions-1]++; ! } ! else { /* Distribute across multiple frames */ ! scp->mibdata.dot3StatsMultipleCollisionFrames += sent; ! scp->mibdata. ! dot3StatsCollFrequencies[scp->tx_collisions/sent] += sent - scp->tx_collisions%sent; ! scp->mibdata. ! dot3StatsCollFrequencies[scp->tx_collisions/sent + 1] += scp->tx_collisions%sent; ! } } - scp->tx_collisions = 0; } ifp->if_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; } - if (txs & 0x0002) { /* Excessive collisions (packet dropped) */ - ifp->if_collisions += 16; - ifp->if_oerrors++; - scp->tx_collisions = 0; - scp->mibdata.dot3StatsExcessiveCollisions++; - scp->mibdata.dot3StatsMultipleCollisionFrames++; - scp->mibdata.dot3StatsCollFrequencies[15]++; - XE_OUTB(XE_CR, XE_CR_RESTART_TX); - } - if (txs & 0x0040) /* Transmit aborted -- probably collisions */ - scp->tx_collisions++; ! /* ! * Handle receive interrupts ! */ while ((esr = XE_INB(XE_ESR)) & XE_ESR_FULL_PACKET_RX) { ! if ((rsr = XE_INB(XE_RSR)) & XE_RSR_RX_OK) { struct ether_header *ehp; struct mbuf *mbp; u_int16_t len; ! len = XE_INW(XE_RBC); ! if (len == 0) continue; - #if 0 /* ! * Limit the amount of time we spend in this loop, dropping packets if ! * necessary. The Linux code does this with considerably more ! * finesse, adjusting the threshold dynamically. */ ! if ((rx_bytes += len) > 22000) { ifp->if_iqdrops++; - scp->mibData.dot3StatsMissedFrames++; - XE_OUTW(XE_DO, 0x8000); continue; } - #endif ! if (len & 0x01) ! len++; ! ! MGETHDR(mbp, M_DONTWAIT, MT_DATA); /* Allocate a header mbuf */ ! if (mbp != NULL) { ! mbp->m_pkthdr.rcvif = ifp; ! mbp->m_pkthdr.len = mbp->m_len = len; ! ! /* ! * If the mbuf header isn't big enough for the packet, attach an ! * mbuf cluster to hold it. The +2 is to allow for the nasty little ! * alignment hack below. ! */ ! if (len + 2 > MHLEN) { ! MCLGET(mbp, M_DONTWAIT); ! if ((mbp->m_flags & M_EXT) == 0) { ! m_freem(mbp); ! mbp = NULL; ! } } } ! if (mbp != NULL) { ! /* ! * The Ethernet header is 14 bytes long; thus the actual packet data ! * won't be 32-bit aligned when it's dumped into the mbuf. We ! * offset everything by 2 bytes to fix this. Apparently the ! * alignment is important for NFS, damn its eyes. ! */ ! mbp->m_data += 2; ! ehp = mtod(mbp, struct ether_header *); ! /* ! * Now get the packet, including the Ethernet header and trailer (?) ! * We use programmed I/O, because we don't know how to do shared ! * memory with these cards. So yes, it's real slow, and heavy on ! * the interrupts (CPU on my P150 maxed out at ~950KBps incoming). ! */ ! if (scp->srev == 0) { /* Workaround a bug in old cards */ ! 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; ! ! /* ! * XXX - This i-- seems very wrong, but it's what the Linux guys ! * XXX - do. Need someone with an old CE2 to test this for me. ! * XXX - 99/3/28: Changed the first i-- to an i++, maybe that'll ! * XXX - fix it? It seems as though the previous version would ! * XXX - have caused an infinite loop (what, another one?). ! */ ! for (i = 0; i < len; i++, rhs++) { ! ((char *)ehp)[i] = XE_INB(XE_EDP); ! if (rhs == 0x8000) { ! rhs = 0; ! i--; ! } } } - else - bus_space_read_multi_2(scp->bst, scp->bsh, XE_EDP, - (u_int16_t *) ehp, len >> 1); } else bus_space_read_multi_2(scp->bst, scp->bsh, XE_EDP, ! (u_int16_t *) ehp, len >> 1); ! ! /* Deliver packet to upper layers */ ! if (mbp != NULL) { ! mbp->m_flags |= M_HASFCS; /* FCS is included in our ! * packet */ ! mbp->m_pkthdr.len = mbp->m_len = len; ! (*ifp->if_input)(ifp, mbp); /* Send the packet on its way */ ! ifp->if_ipackets++; /* Success! */ ! } ! XE_OUTW(XE_DO, 0x8000); /* skip_rx_packet command */ } } ! else if (rsr & XE_RSR_LONG_PACKET) { /* Packet length >1518 bytes */ ! scp->mibdata.dot3StatsFrameTooLongs++; ! ifp->if_ierrors++; ! } ! else if (rsr & XE_RSR_CRC_ERROR) { /* Bad checksum on packet */ ! scp->mibdata.dot3StatsFCSErrors++; ! ifp->if_ierrors++; ! } ! else if (rsr & XE_RSR_ALIGN_ERROR) { /* Packet alignment error */ scp->mibdata.dot3StatsAlignmentErrors++; ifp->if_ierrors++; } } ! if (rxs & 0x10) { /* Receiver overrun */ ! scp->mibdata.dot3StatsInternalMacReceiveErrors++; ifp->if_ierrors++; XE_OUTB(XE_CR, XE_CR_CLEAR_OVERRUN); } } ! XE_SELECT_PAGE(psr); /* Restore saved page */ ! XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); /* Re-enable interrupts */ ! /* Could force an int here, instead of dropping packets? */ ! /* XE_OUTB(XE_CR, XE_CR_ENABLE_INTR|XE_CE_FORCE_INTR); */ return; } --- 567,823 ---- { struct xe_softc *scp = (struct xe_softc *) xscp; struct ifnet *ifp; ! u_int8_t psr, isr, esr, rsr, rst0, txst0, txst1, coll; ifp = &scp->arpcom.ac_if; ! /* Disable interrupts */ ! XE_OUTB(XE_CR, 0); ! /* Cache current register page */ ! psr = XE_INB(XE_PR); ! /* Read ISR to see what caused this interrupt */ ! if ((isr = XE_INB(XE_ISR)) != 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); ! coll = txst1 & XE_TXST1_RETRY_COUNT; XE_OUTB(XE_TXST0, 0); XE_OUTB(XE_TXST1, 0); XE_SELECT_PAGE(0); #if XE_DEBUG > 2 ! device_printf(scp->dev, "intr: ISR=0x%02x, RST=0x%02x, TXT=0x%02x%02x, COLL=0x%01x\n", isr, rst0, txst1, txst0, coll); #endif ! /* Handle transmitted packet(s) */ if (isr & XE_ISR_TX_PACKET) { ! u_int8_t tpr, sent; ! /* 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) { ! 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]++; } } ifp->if_timer = 0; ifp->if_flags &= ~IFF_OACTIVE; } + /* Handle most MAC interrupts */ + if (isr & XE_ISR_MAC_INTR) { ! #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++; ! } ! #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) { ! device_printf(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; ! printf(": increasing transmit threshold to %u", scp->tx_thres); ! XE_SELECT_PAGE(0x3); ! XE_OUTW(XE_TPT, scp->tx_thres); ! XE_SELECT_PAGE(0x0); ! } ! printf("\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++; ! } ! } ! ! /* Handle received packet(s) */ while ((esr = XE_INB(XE_ESR)) & XE_ESR_FULL_PACKET_RX) { + rsr = XE_INB(XE_RSR); ! #if XE_DEBUG > 2 ! device_printf(scp->dev, "intr: ESR=0x%02x, RSR=0x%02x\n", esr, rsr,); ! #endif ! ! /* 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; ! 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_space_read_multi_2(scp->bst, scp->bsh, XE_EDP, ! (u_int16_t *) ehp, (len + 1) >> 1); } + else + bus_space_read_multi_2(scp->bst, scp->bsh, 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; + (*ifp->if_input)(ifp, mbp); + 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) { ! device_printf(scp->dev, "receive overrun\n"); ifp->if_ierrors++; + scp->mibdata.dot3StatsInternalMacReceiveErrors++; XE_OUTB(XE_CR, XE_CR_CLEAR_OVERRUN); } } ! /* Restore saved page */ ! XE_SELECT_PAGE(psr); ! /* Re-enable interrupts */ ! XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); return; } *************** *** 767,778 **** xe_watchdog(struct ifnet *ifp) { struct xe_softc *scp = ifp->if_softc; ! device_printf(scp->dev, "watchdog timeout; resetting card\n"); scp->tx_timeouts++; ifp->if_oerrors += scp->tx_queued; xe_stop(scp); ! xe_hard_reset(scp); ! xe_setmedia(scp); xe_init(scp); } --- 833,843 ---- xe_watchdog(struct ifnet *ifp) { struct xe_softc *scp = ifp->if_softc; ! device_printf(scp->dev, "watchdog timeout: resetting card\n"); scp->tx_timeouts++; ifp->if_oerrors += scp->tx_queued; xe_stop(scp); ! xe_reset(scp); xe_init(scp); } *************** *** 784,790 **** xe_media_change(struct ifnet *ifp) { struct xe_softc *scp = ifp->if_softc; ! #ifdef XE_DEBUG if_printf(ifp, "media_change\n"); #endif --- 849,855 ---- xe_media_change(struct ifnet *ifp) { struct xe_softc *scp = ifp->if_softc; ! #if XE_DEBUG > 1 if_printf(ifp, "media_change\n"); #endif *************** *** 810,819 **** static void xe_media_status(struct ifnet *ifp, struct ifmediareq *mrp) { ! #ifdef XE_DEBUG if_printf(ifp, "media_status\n"); #endif mrp->ifm_active = ((struct xe_softc *)ifp->if_softc)->media; return; --- 875,886 ---- static void xe_media_status(struct ifnet *ifp, struct ifmediareq *mrp) { ! #if XE_DEBUG > 1 if_printf(ifp, "media_status\n"); #endif + /* XXX - This is clearly wrong. Will fix once I have CE2 working */ + mrp->ifm_status = IFM_AVALID | IFM_ACTIVE; mrp->ifm_active = ((struct xe_softc *)ifp->if_softc)->media; return; *************** *** 827,833 **** struct xe_softc *scp = xscp; u_int16_t bmcr, bmsr, anar, lpar; ! #ifdef XE_DEBUG device_printf(scp->dev, "setmedia\n"); #endif --- 894,900 ---- struct xe_softc *scp = xscp; u_int16_t bmcr, bmsr, anar, lpar; ! #if XE_DEBUG > 1 device_printf(scp->dev, "setmedia\n"); #endif *************** *** 873,889 **** */ switch (scp->autoneg_status) { ! case XE_AUTONEG_NONE: #if XE_DEBUG > 1 device_printf(scp->dev, "Waiting for idle transmitter\n"); #endif scp->arpcom.ac_if.if_flags |= IFF_OACTIVE; scp->autoneg_status = XE_AUTONEG_WAITING; ! scp->chand = timeout(xe_setmedia, scp, hz * 2); ! return; ! case XE_AUTONEG_WAITING: ! xe_soft_reset(scp); if (scp->phy_ok) { #if XE_DEBUG > 1 device_printf(scp->dev, "Starting autonegotiation\n"); --- 940,958 ---- */ switch (scp->autoneg_status) { ! case XE_AUTONEG_NONE: #if XE_DEBUG > 1 device_printf(scp->dev, "Waiting for idle transmitter\n"); #endif scp->arpcom.ac_if.if_flags |= IFF_OACTIVE; scp->autoneg_status = XE_AUTONEG_WAITING; ! /* FALL THROUGH */ ! case XE_AUTONEG_WAITING: ! if (scp->tx_queued != 0) { ! scp->chand = timeout(xe_setmedia, scp, hz/2); ! return; ! } if (scp->phy_ok) { #if XE_DEBUG > 1 device_printf(scp->dev, "Starting autonegotiation\n"); *************** *** 898,904 **** bmcr |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR; xe_phy_writereg(scp, PHY_BMCR, bmcr); scp->autoneg_status = XE_AUTONEG_STARTED; ! scp->chand = timeout(xe_setmedia, scp, hz * 7/2); return; } else { --- 967,973 ---- bmcr |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR; xe_phy_writereg(scp, PHY_BMCR, bmcr); scp->autoneg_status = XE_AUTONEG_STARTED; ! scp->chand = timeout(xe_setmedia, scp, hz * 7/2); return; } else { *************** *** 953,959 **** device_printf(scp->dev, "Autonegotiation failed; trying 100baseTX\n"); #endif XE_MII_DUMP(scp); - xe_soft_reset(scp); if (scp->phy_ok) { xe_phy_writereg(scp, PHY_BMCR, PHY_BMCR_SPEEDSEL); scp->autoneg_status = XE_AUTONEG_100TX; --- 1022,1027 ---- *************** *** 1028,1034 **** * no PHY, we fall back to 10baseT operation). */ case IFM_100_TX: /* Force 100baseTX */ - xe_soft_reset(scp); if (scp->phy_ok) { #if XE_DEBUG > 1 device_printf(scp->dev, "Selecting 100baseTX\n"); --- 1096,1101 ---- *************** *** 1044,1050 **** /* FALLTHROUGH */ case IFM_10_T: /* Force 10baseT */ - xe_soft_reset(scp); #if XE_DEBUG > 1 device_printf(scp->dev, "Selecting 10baseT\n"); #endif --- 1111,1116 ---- *************** *** 1059,1065 **** break; case IFM_10_2: - xe_soft_reset(scp); #if XE_DEBUG > 1 device_printf(scp->dev, "Selecting 10base2\n"); #endif --- 1125,1130 ---- *************** *** 1092,1099 **** } /* Restart output? */ scp->ifp->if_flags &= ~IFF_OACTIVE; ! xe_init(scp); } --- 1157,1165 ---- } /* Restart output? */ + xe_enable_intr(scp); scp->ifp->if_flags &= ~IFF_OACTIVE; ! xe_start(scp->ifp); } *************** *** 1101,1198 **** * Hard reset (power cycle) the card. */ static void ! xe_hard_reset(struct xe_softc *scp) { int s; ! #ifdef XE_DEBUG ! device_printf(scp->dev, "hard_reset\n"); #endif s = splimp(); ! /* ! * Power cycle the card. ! */ XE_SELECT_PAGE(4); ! XE_OUTB(XE_GPR1, 0); /* Power off */ DELAY(40000); if (scp->mohawk) ! XE_OUTB(XE_GPR1, 1); /* And back on again */ else ! XE_OUTB(XE_GPR1, 5); /* Also set AIC bit, whatever that is */ ! DELAY(40000); ! XE_SELECT_PAGE(0); ! ! (void)splx(s); ! } ! - /* - * Soft reset the card. Also makes sure that the ML6692 and 10Mbit controller - * are powered up, sets the silicon revision number in softc, disables - * interrupts and checks for the prescence of a 100Mbit PHY. This should - * leave us in a position where we can access the PHY and do media - * selection. The function imposes a 0.5s delay while the hardware powers up. - */ - static void - xe_soft_reset(struct xe_softc *scp) { - int s; - - #ifdef XE_DEBUG - device_printf(scp->dev, "soft_reset\n"); - #endif - - s = splimp(); - - /* - * Reset the card, (again). - */ - 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, 0x0e); - } - - /* - * Wait for everything to wake up. - */ - DELAY(500000); - - /* - * Get silicon revision number. - */ - XE_SELECT_PAGE(4); - if (scp->mohawk) - scp->srev = (XE_INB(XE_BOV) & 0x70) >> 4; - else - scp->srev = (XE_INB(XE_BOV) & 0x30) >> 4; - #ifdef XE_DEBUG - device_printf(scp->dev, "silicon revision = %d\n", scp->srev); - #endif - - /* - * Shut off interrupts. - */ - xe_disable_intr(scp); - - /* - * Check for PHY. - */ - if (scp->mohawk) { - scp->phy_ok = xe_mii_init(scp); - } - XE_SELECT_PAGE(0); (void)splx(s); --- 1167,1193 ---- * Hard reset (power cycle) the card. */ static void ! xe_reset(struct xe_softc *scp) { int s; ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "reset\n"); #endif s = splimp(); ! /* 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); DELAY(40000); XE_SELECT_PAGE(0); (void)splx(s); *************** *** 1208,1214 **** xe_stop(struct xe_softc *scp) { int s; ! #ifdef XE_DEBUG device_printf(scp->dev, "stop\n"); #endif --- 1203,1209 ---- xe_stop(struct xe_softc *scp) { int s; ! #if XE_DEBUG > 1 device_printf(scp->dev, "stop\n"); #endif *************** *** 1225,1230 **** --- 1220,1234 ---- 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_RUNNING == interface down. *************** *** 1238,1256 **** /* ! * Enable Ethernet interrupts from the card. */ static void xe_enable_intr(struct xe_softc *scp) { ! #ifdef XE_DEBUG device_printf(scp->dev, "enable_intr\n"); #endif - XE_SELECT_PAGE(1); - XE_OUTB(XE_IMR0, 0xff); /* Unmask everything */ - XE_OUTB(XE_IMR1, 0x01); /* Unmask TX underrun detection */ - DELAY(1); - XE_SELECT_PAGE(0); XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); /* Enable interrupts */ if (scp->modem && !scp->dingo) { /* This bit is just magic */ --- 1242,1256 ---- /* ! * Enable interrupts from the card. */ static void xe_enable_intr(struct xe_softc *scp) { ! ! #if XE_DEBUG > 1 device_printf(scp->dev, "enable_intr\n"); #endif XE_SELECT_PAGE(0); XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); /* Enable interrupts */ if (scp->modem && !scp->dingo) { /* This bit is just magic */ *************** *** 1262,1393 **** /* ! * Disable all Ethernet interrupts from the card. */ static void xe_disable_intr(struct xe_softc *scp) { ! #ifdef XE_DEBUG device_printf(scp->dev, "disable_intr\n"); #endif XE_SELECT_PAGE(0); XE_OUTB(XE_CR, 0); /* Disable interrupts */ ! if (scp->modem && !scp->dingo) { /* More magic (does this work?) */ XE_OUTB(0x10, 0x10); /* Mask the master int enable bit */ } - - XE_SELECT_PAGE(1); - XE_OUTB(XE_IMR0, 0); /* Forbid all interrupts */ - XE_OUTB(XE_IMR1, 0); - XE_SELECT_PAGE(0); } /* ! * Set up multicast filter and promiscuous mode */ static void ! xe_setmulti(struct xe_softc *scp) { struct ifnet *ifp; struct ifmultiaddr *maddr; ! int count; ifp = &scp->arpcom.ac_if; ! maddr = TAILQ_FIRST(&ifp->if_multiaddrs); ! /* Get length of multicast list */ ! for (count = 0; maddr != NULL; maddr = TAILQ_NEXT(maddr, ifma_link), count++); ! if ((ifp->if_flags & IFF_PROMISC) || (ifp->if_flags & IFF_ALLMULTI) || (count > 9)) { ! /* ! * Go into promiscuous mode if either of the PROMISC or ALLMULTI flags are ! * set, or if we have been asked to deal with more than 9 multicast ! * addresses. To do this: set MPE and PME in SWC1 ! */ ! XE_SELECT_PAGE(0x42); ! XE_OUTB(XE_SWC1, 0x06); } ! else if ((ifp->if_flags & IFF_MULTICAST) && (count > 0)) { ! /* ! * Program the filters for up to 9 addresses ! */ XE_SELECT_PAGE(0x42); ! XE_OUTB(XE_SWC1, 0x01); ! XE_SELECT_PAGE(0x40); ! XE_OUTB(XE_CMD0, XE_CMD0_OFFLINE); ! /*xe_reg_dump(scp);*/ ! xe_setaddrs(scp); ! /*xe_reg_dump(scp);*/ ! XE_SELECT_PAGE(0x40); ! XE_OUTB(XE_CMD0, XE_CMD0_RX_ENABLE|XE_CMD0_ONLINE); } ! else { ! /* ! * No multicast operation (default) ! */ XE_SELECT_PAGE(0x42); ! XE_OUTB(XE_SWC1, 0); } XE_SELECT_PAGE(0); } /* ! * Set up all on-chip addresses (for multicast). AFAICS, there are 10 ! * of these things; the first is our MAC address, the other 9 are mcast ! * addresses, padded with the MAC address if there aren't enough. ! * XXX - This doesn't work right, but I'm not sure why yet. We seem to be ! * XXX - doing much the same as the Linux code, which is weird enough that ! * XXX - it's probably right (despite my earlier comments to the contrary). */ static void ! xe_setaddrs(struct xe_softc *scp) { ! struct ifmultiaddr *maddr; ! u_int8_t *addr; ! u_int8_t page, slot, byte, i; ! ! maddr = TAILQ_FIRST(&scp->arpcom.ac_if.if_multiaddrs); ! XE_SELECT_PAGE(page = 0x50); ! for (slot = 0, byte = 8; slot < 10; slot++) { ! if (slot == 0) ! addr = (u_int8_t *)(&scp->arpcom.ac_enaddr); ! else { ! while (maddr != NULL && maddr->ifma_addr->sa_family != AF_LINK) ! maddr = TAILQ_NEXT(maddr, ifma_link); ! if (maddr != NULL) ! addr = LLADDR((struct sockaddr_dl *)maddr->ifma_addr); ! else ! addr = (u_int8_t *)(&scp->arpcom.ac_enaddr); } ! ! for (i = 0; i < 6; i++, byte++) { ! #if XE_DEBUG > 2 ! if (i) ! printf(":%x", addr[i]); ! else ! device_printf(scp->dev, "individual addresses %d: %x", slot, addr[0]); #endif - if (byte > 15) { - page++; - byte = 8; - XE_SELECT_PAGE(page); - } ! if (scp->mohawk) ! XE_OUTB(byte, addr[5 - i]); else ! XE_OUTB(byte, addr[i]); } ! #if XE_DEBUG > 2 ! printf("\n"); #endif } ! XE_SELECT_PAGE(0); } --- 1262,1497 ---- /* ! * Disable interrupts from the card. */ static void xe_disable_intr(struct xe_softc *scp) { ! ! #if XE_DEBUG > 1 device_printf(scp->dev, "disable_intr\n"); #endif 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 */ } } /* ! * 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; ! ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "set_multicast\n"); ! #endif ifp = &scp->arpcom.ac_if; ! 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 __FreeBSD_version < 500000 ! LIST_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { ! #else ! TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { ! #endif ! 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_set_hash(scp, LLADDR((struct sockaddr_dl *)maddr->ifma_addr)); ! else ! /* Nowhere else to put them on CE2 */ ! break; ! } ! ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "set_multicast: count = %u\n", count); ! #endif ! ! /* 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, (u_int8_t *)(&scp->arpcom.ac_enaddr), 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 ! * Individual Address idx. Assumes that addr is really a multicast address ! * 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); ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "set_addr: idx = %u, page = 0x%02x, reg = 0x%02x\n", ! idx+1, page, reg); ! #endif ! /* ! * 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 XE_DEBUG > 1 ! if (i > 0) ! printf(":%02x", addr[i]); ! else ! device_printf(scp->dev, "set_addr: %02x", addr[0]); ! #endif ! XE_OUTB(reg, addr[scp->mohawk ? 5 - i : i]); ! if (++reg == 0x10) { ! reg = 0x08; ! XE_SELECT_PAGE(++page); } ! } ! #if XE_DEBUG > 1 ! printf("\n"); #endif + } ! /* ! * Set the appropriate bit in the multicast hash table for the supplied ! * Ethernet multicast address addr. Assumes that addr is really a multicast ! * address. ! */ ! static void ! xe_set_hash(struct xe_softc* scp, u_int8_t* addr) { ! u_int32_t crc = 0xffffffff; ! u_int8_t bit, byte, crc31, idx; ! unsigned i, j; ! ! /* Compute CRC of the address -- standard Ethernet CRC function */ ! for (i = 0; i < 6; i++) { ! byte = addr[i]; ! for (j = 1; j <= 8; j++) { ! if (crc & 0x80000000) ! crc31 = 0x01; else ! crc31 = 0; ! bit = crc31 ^ (byte & 0x01); ! crc <<= 1; ! byte >>= 1; ! if (bit) ! crc = (crc ^ XE_CRC_POLY)|1; } ! } ! ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "set_hash: CRC = 0x%08x\n", crc); #endif + + /* Hash table index = 6 msbs of CRC, reversed */ + for (i = 0, idx = 0; i < 6; i++) { + idx >>= 1; + if (crc & 0x80000000) { + idx |= 0x20; + } + crc <<= 1; } ! /* Top 3 bits of idx give register - 8, bottom 3 give bit within register */ ! byte = idx >> 3 | 0x08; ! bit = 0x01 << (idx & 0x07); ! ! #if XE_DEBUG > 1 ! device_printf(scp->dev, "set_hash: idx = 0x%02x, byte = 0x%02x, bit = 0x%02x\n", idx, byte, bit); ! #endif ! ! XE_SELECT_PAGE(0x58); ! XE_OUTB(byte, XE_INB(byte) | bit); } *************** *** 1460,1466 **** * out the packet. I guess it is then sent automatically (?) */ if (scp->mohawk) ! XE_OUTB(XE_CR, XE_CR_TX_PACKET|XE_CR_ENABLE_INTR); else while (pad > 0) { XE_OUTW(XE_EDP, 0xdead); --- 1564,1570 ---- * out the packet. I guess it is then sent automatically (?) */ if (scp->mohawk) ! XE_OUTB(XE_CR, XE_CR_TX_PACKET | XE_CR_RESTART_TX | XE_CR_ENABLE_INTR); else while (pad > 0) { XE_OUTW(XE_EDP, 0xdead); *************** *** 1470,1528 **** return 0; } - /* - * Compute the 32-bit Ethernet CRC for the given buffer. - */ - static u_int32_t - xe_compute_crc(u_int8_t *data, int len) { - u_int32_t crc = 0xffffffff; - u_int32_t poly = 0x04c11db6; - u_int8_t current, crc31, bit; - int i, k; - - for (i = 0; i < len; i++) { - current = data[i]; - for (k = 1; k <= 8; k++) { - if (crc & 0x80000000) { - crc31 = 0x01; - } - else { - crc31 = 0; - } - bit = crc31 ^ (current & 0x01); - crc <<= 1; - current >>= 1; - if (bit) { - crc = (crc ^ poly)|1; - } - } - } - return crc; - } - - - /* - * Convert a CRC into an index into the multicast hash table. What we do is - * take the most-significant 6 bits of the CRC, reverse them, and use that as - * the bit number in the hash table. Bits 5:3 of the result give the byte - * within the table (0-7); bits 2:0 give the bit number within that byte (also - * 0-7), ie. the number of shifts needed to get it into the lsb position. - */ - static int - xe_compute_hashbit(u_int32_t crc) { - u_int8_t hashbit = 0; - int i; - - for (i = 0; i < 6; i++) { - hashbit >>= 1; - if (crc & 0x80000000) { - hashbit &= 0x80; - } - crc <<= 1; - } - return (hashbit >> 2); - } - /************************************************************** --- 1574,1579 ---- *************** *** 1790,1796 **** } ! #ifdef XE_DEBUG /* * A bit of debugging code. */ --- 1841,1847 ---- } ! #if XE_DEBUG > 2 /* * A bit of debugging code. */ *************** *** 1857,1862 **** --- 1908,1917 ---- struct xe_softc *sc = device_get_softc(dev); int start, err; + #if XE_DEBUG > 1 + device_printf(dev, "activate\n"); + #endif + if (!sc->dingo) { sc->port_rid = 0; /* 0 is managed by pccard */ sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, *************** *** 1921,1926 **** --- 1976,1985 ---- { struct xe_softc *sc = device_get_softc(dev); + #if XE_DEBUG > 1 + device_printf(dev, "deactivate\n"); + #endif + if (sc->intrhand) bus_teardown_intr(dev, sc->irq_res, sc->intrhand); sc->intrhand = 0; Index: src/sys/dev/xe/if_xereg.h =================================================================== RCS file: /home/ncvs/src/sys/dev/xe/if_xereg.h,v retrieving revision 1.5 retrieving revision 1.5.10000.1 diff -c -r1.5 -r1.5.10000.1 *** src/sys/dev/xe/if_xereg.h 10 Jan 2000 08:05:53 -0000 1.5 --- src/sys/dev/xe/if_xereg.h 25 Mar 2003 21:02:31 -0000 1.5.10000.1 *************** *** 24,30 **** * SUCH DAMAGE. * * $Id: if_xereg.h,v 1.5 1999/05/20 21:53:58 scott Exp $ ! * $FreeBSD: src/sys/dev/xe/if_xereg.h,v 1.5 2000/01/10 08:05:53 imp Exp $ */ #ifndef DEV_XE_IF_XEREG_H #define DEV_XE_IF_XEREG_H --- 24,30 ---- * SUCH DAMAGE. * * $Id: if_xereg.h,v 1.5 1999/05/20 21:53:58 scott Exp $ ! * $FreeBSD: src/sys/dev/xe/if_xereg.h,v 1.5.10000.1 2003/03/25 21:02:31 scott Exp $ */ #ifndef DEV_XE_IF_XEREG_H #define DEV_XE_IF_XEREG_H *************** *** 283,293 **** --- 283,297 ---- #define XE_IMR0_TX_OVERFLOW 0x01 /* Masks for bits in ISR */ #define XE_IMR0_TX_PACKET 0x02 #define XE_IMR0_MAC_INTR 0x04 + #define XE_IMR0_TX_RESGRANT 0x08 /* Tx reservation granted (CE2) */ #define XE_IMR0_RX_EARLY 0x10 #define XE_IMR0_RX_PACKET 0x20 #define XE_IMR0_RX_REJECT 0x40 #define XE_IMR0_FORCE_INTR 0x80 + /* XE_IMR1 bits */ + #define XE_IMR1_TX_UNDERRUN 0x01 + /* XE_ECR bits */ #define XE_ECR_EARLY_TX 0x01 /* Enable early transmit mode */ #define XE_ECR_EARLY_RX 0x02 /* Enable early receive mode */ *************** *** 366,379 **** /* XE_GPR0 bits */ #define XE_GPR0_GP1_OUT 0x01 /* Value written to GP1 line */ ! #define XE_GPR0_GP2_OUT 0x02 /* Value wirtten to GP2 line */ #define XE_GPR0_GP1_SELECT 0x04 /* 1 = GP1 is output, 0 = GP1 is input */ #define XE_GPR0_GP2_SELECT 0x08 /* 1 = GP2 is output, 0 = GP2 is input */ #define XE_GPR0_GP1_IN 0x10 /* Value read from GP1 line */ #define XE_GPR0_GP2_IN 0x20 /* Value read from GP2 line */ /* XE_GPR1 bits */ ! #define XE_GPR1_POWER_DOWN 0x01 /* Power down analog section (down to 20mA load) */ /* XE_BOV values */ #define XE_BOV_DINGO 0x55 /* Dingo in Dingo mode */ --- 370,384 ---- /* XE_GPR0 bits */ #define XE_GPR0_GP1_OUT 0x01 /* Value written to GP1 line */ ! #define XE_GPR0_GP2_OUT 0x02 /* Value written to GP2 line */ #define XE_GPR0_GP1_SELECT 0x04 /* 1 = GP1 is output, 0 = GP1 is input */ #define XE_GPR0_GP2_SELECT 0x08 /* 1 = GP2 is output, 0 = GP2 is input */ #define XE_GPR0_GP1_IN 0x10 /* Value read from GP1 line */ #define XE_GPR0_GP2_IN 0x20 /* Value read from GP2 line */ /* XE_GPR1 bits */ ! #define XE_GPR1_POWER_DOWN 0x01 /* 0 = Power down analog section */ ! #define XE_GPR1_AIC 0x04 /* AIC bit (CE2 only) */ /* XE_BOV values */ #define XE_BOV_DINGO 0x55 /* Dingo in Dingo mode */ *************** *** 471,476 **** --- 476,482 ---- #define XE_TXST1_LINK_STATUS 0x10 /* Valid link status */ /* RX0Msk bits */ + #define XE_RX0M_MP 0x01 /* Multicast packet? (CE2 only) */ #define XE_RX0M_LONG_PACKET 0x02 /* Masks for bits in RXST0 */ #define XE_RX0M_ALIGN_ERROR 0x04 /* Alignment error (CE2 only) */ #define XE_RX0M_CRC_ERROR 0x08 *************** *** 504,509 **** --- 510,516 ---- #define XE_SWC0_LOOPBACK_SOURCE 0x02 /* 1 = Transceiver, 0 = MAC */ #define XE_SWC0_ACCEPT_ERROR 0x04 /* Accept otherwise OK packets with CRC errors */ #define XE_SWC0_ACCEPT_SHORT 0x08 /* Accept otherwise OK packets that are too short */ + #define XE_SWC0_NO_SRC_INSERT 0x20 /* Disable source insertion (CE2) */ #define XE_SWC0_NO_CRC_INSERT 0x40 /* Don't add CRC to outgoing packets */ /* SWC1 bits */ Index: src/sys/dev/xe/if_xevar.h =================================================================== RCS file: /home/ncvs/src/sys/dev/xe/if_xevar.h,v retrieving revision 1.3 retrieving revision 1.3.10000.1 diff -c -r1.3 -r1.3.10000.1 *** src/sys/dev/xe/if_xevar.h 20 Feb 2002 14:23:58 -0000 1.3 --- src/sys/dev/xe/if_xevar.h 6 Apr 2003 12:12:52 -0000 1.3.10000.1 *************** *** 24,30 **** * SUCH DAMAGE. * * $Id: if_xe.c,v 1.20 1999/06/13 19:17:40 scott Exp $ ! * $FreeBSD: src/sys/dev/xe/if_xevar.h,v 1.3 2002/02/20 14:23:58 shiba Exp $ */ #ifndef DEV_XE_IF_XEDEV_H #define DEV_XE_IF_XEDEV_H --- 24,30 ---- * SUCH DAMAGE. * * $Id: if_xe.c,v 1.20 1999/06/13 19:17:40 scott Exp $ ! * $FreeBSD: src/sys/dev/xe/if_xevar.h,v 1.3.10000.1 2003/04/06 12:12:52 scott Exp $ */ #ifndef DEV_XE_IF_XEDEV_H #define DEV_XE_IF_XEDEV_H *************** *** 52,59 **** int srev; /* Silicon revision */ int tx_queued; /* Packets currently waiting to transmit */ int tx_tpr; /* Last value of TPR reg on card */ - int tx_collisions; /* Collisions since last successful send */ int tx_timeouts; /* Count of transmit timeouts */ int autoneg_status; /* Autonegotiation progress state */ int media; /* Private media word */ u_char version; /* Bonding Version register from card */ --- 52,59 ---- 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_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 */ >Release-Note: >Audit-Trail: >Unformatted: