diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-08-29 21:12:56 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-08-29 21:12:56 +0000 |
commit | 6bed2bd2bebb3bc2213623236ef2874fc2fb9141 (patch) | |
tree | 317a2723279afbc8469e3f5a171eb42572736f36 /sys/dev/pci | |
parent | bd1d57e1e7d32857956f0496b2bc2f60338a7a0a (diff) |
Split the ti(4) driver into mostly bus-agnostic code and PCI-specific
attachment. Add SBus support to the bus-agnostic code.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/files.pci | 7 | ||||
-rw-r--r-- | sys/dev/pci/if_ti.c | 2624 | ||||
-rw-r--r-- | sys/dev/pci/if_ti_pci.c | 181 | ||||
-rw-r--r-- | sys/dev/pci/if_tireg.h | 1175 | ||||
-rw-r--r-- | sys/dev/pci/if_tivar.h | 43 |
5 files changed, 184 insertions, 3846 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 0e25bdbee70..930e01243cd 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.262 2009/08/08 09:31:13 kevlo Exp $ +# $OpenBSD: files.pci,v 1.263 2009/08/29 21:12:55 kettenis Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -400,9 +400,8 @@ attach epic at pci with epic_pci file dev/pci/if_epic_pci.c epic_pci # Alteon Tigon I & II -device ti: ether, ifnet, ifmedia, firmload -attach ti at pci -file dev/pci/if_ti.c ti +attach ti at pci with ti_pci +file dev/pci/if_ti_pci.c ti_pci # NE2000-compatible PCI Ethernet cards attach ne at pci with ne_pci: rtl80x9 diff --git a/sys/dev/pci/if_ti.c b/sys/dev/pci/if_ti.c deleted file mode 100644 index 187dd8b25ef..00000000000 --- a/sys/dev/pci/if_ti.c +++ /dev/null @@ -1,2624 +0,0 @@ -/* $OpenBSD: if_ti.c,v 1.98 2009/08/13 14:24:47 jasper Exp $ */ - -/* - * Copyright (c) 1997, 1998, 1999 - * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/pci/if_ti.c,v 1.25 2000/01/18 00:26:29 wpaul Exp $ - */ - -/* - * Alteon Networks Tigon PCI gigabit ethernet driver for OpenBSD. - * - * Written by Bill Paul <wpaul@ctr.columbia.edu> - * Electrical Engineering Department - * Columbia University, New York City - */ - -/* - * The Alteon Networks Tigon chip contains an embedded R4000 CPU, - * gigabit MAC, dual DMA channels and a PCI interface unit. NICs - * using the Tigon may have anywhere from 512K to 2MB of SRAM. The - * Tigon supports hardware IP, TCP and UCP checksumming, multicast - * filtering and jumbo (9014 byte) frames. The hardware is largely - * controlled by firmware, which must be loaded into the NIC during - * initialization. - * - * The Tigon 2 contains 2 R4000 CPUs and requires a newer firmware - * revision, which supports new features such as extended commands, - * extended jumbo receive ring desciptors and a mini receive ring. - * - * Alteon Networks is to be commended for releasing such a vast amount - * of development material for the Tigon NIC without requiring an NDA - * (although they really should have done it a long time ago). With - * any luck, the other vendors will finally wise up and follow Alteon's - * stellar example. - * - * The following people deserve special thanks: - * - Terry Murphy of 3Com, for providing a 3c985 Tigon 1 board - * for testing - * - Raymond Lee of Netgear, for providing a pair of Netgear - * GA620 Tigon 2 boards for testing - * - Ulf Zimmermann, for bringing the GA260 to my attention and - * convincing me to write this driver. - * - Andrew Gallatin for providing FreeBSD/Alpha support. - */ - -#include "bpfilter.h" -#include "vlan.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/device.h> -#include <sys/queue.h> - -#include <net/if.h> -#include <net/if_dl.h> -#include <net/if_types.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#endif - -#include <net/if_media.h> - -#if NBPFILTER > 0 -#include <net/bpf.h> -#endif - -#if NVLAN > 0 -#include <net/if_types.h> -#include <net/if_vlan_var.h> -#endif - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> -#include <dev/pci/pcidevs.h> - -#include <dev/pci/if_tireg.h> -#include <dev/pci/if_tivar.h> - -int ti_probe(struct device *, void *, void *); -void ti_attach(struct device *, struct device *, void *); - -struct cfattach ti_ca = { - sizeof(struct ti_softc), ti_probe, ti_attach -}; - -struct cfdriver ti_cd = { - NULL, "ti", DV_IFNET -}; - -void ti_txeof_tigon1(struct ti_softc *); -void ti_txeof_tigon2(struct ti_softc *); -void ti_rxeof(struct ti_softc *); - -void ti_stats_update(struct ti_softc *); -int ti_encap_tigon1(struct ti_softc *, struct mbuf *, u_int32_t *); -int ti_encap_tigon2(struct ti_softc *, struct mbuf *, u_int32_t *); - -int ti_intr(void *); -void ti_start(struct ifnet *); -int ti_ioctl(struct ifnet *, u_long, caddr_t); -void ti_init(void *); -void ti_init2(struct ti_softc *); -void ti_stop(struct ti_softc *); -void ti_watchdog(struct ifnet *); -void ti_shutdown(void *); -int ti_ifmedia_upd(struct ifnet *); -void ti_ifmedia_sts(struct ifnet *, struct ifmediareq *); - -u_int32_t ti_eeprom_putbyte(struct ti_softc *, int); -u_int8_t ti_eeprom_getbyte(struct ti_softc *, int, u_int8_t *); -int ti_read_eeprom(struct ti_softc *, caddr_t, int, int); - -void ti_add_mcast(struct ti_softc *, struct ether_addr *); -void ti_del_mcast(struct ti_softc *, struct ether_addr *); -void ti_setmulti(struct ti_softc *); - -void ti_mem_read(struct ti_softc *, u_int32_t, u_int32_t, void *); -void ti_mem_write(struct ti_softc *, u_int32_t, u_int32_t, const void*); -void ti_mem_set(struct ti_softc *, u_int32_t, u_int32_t); -void ti_loadfw(struct ti_softc *); -void ti_cmd(struct ti_softc *, struct ti_cmd_desc *); -void ti_cmd_ext(struct ti_softc *, struct ti_cmd_desc *, - caddr_t, int); -void ti_handle_events(struct ti_softc *); -int ti_alloc_jumbo_mem(struct ti_softc *); -void *ti_jalloc(struct ti_softc *); -void ti_jfree(caddr_t, u_int, void *); -int ti_newbuf_std(struct ti_softc *, int, struct mbuf *, bus_dmamap_t); -int ti_newbuf_mini(struct ti_softc *, int, struct mbuf *, bus_dmamap_t); -int ti_newbuf_jumbo(struct ti_softc *, int, struct mbuf *); -int ti_init_rx_ring_std(struct ti_softc *); -void ti_free_rx_ring_std(struct ti_softc *); -int ti_init_rx_ring_jumbo(struct ti_softc *); -void ti_free_rx_ring_jumbo(struct ti_softc *); -int ti_init_rx_ring_mini(struct ti_softc *); -void ti_free_rx_ring_mini(struct ti_softc *); -void ti_free_tx_ring(struct ti_softc *); -int ti_init_tx_ring(struct ti_softc *); - -int ti_64bitslot_war(struct ti_softc *); -int ti_chipinit(struct ti_softc *); -int ti_gibinit(struct ti_softc *); - -const struct pci_matchid ti_devices[] = { - { PCI_VENDOR_NETGEAR, PCI_PRODUCT_NETGEAR_GA620 }, - { PCI_VENDOR_NETGEAR, PCI_PRODUCT_NETGEAR_GA620T }, - { PCI_VENDOR_ALTEON, PCI_PRODUCT_ALTEON_ACENIC }, - { PCI_VENDOR_ALTEON, PCI_PRODUCT_ALTEON_ACENICT }, - { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C985 }, - { PCI_VENDOR_SGI, PCI_PRODUCT_SGI_TIGON }, - { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_PN9000SX } -}; - -/* - * Send an instruction or address to the EEPROM, check for ACK. - */ -u_int32_t -ti_eeprom_putbyte(struct ti_softc *sc, int byte) -{ - int i, ack = 0; - - /* - * Make sure we're in TX mode. - */ - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN); - - /* - * Feed in each bit and strobe the clock. - */ - for (i = 0x80; i; i >>= 1) { - if (byte & i) - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT); - else - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT); - DELAY(1); - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); - DELAY(1); - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); - } - - /* - * Turn off TX mode. - */ - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN); - - /* - * Check for ack. - */ - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); - ack = CSR_READ_4(sc, TI_MISC_LOCAL_CTL) & TI_MLC_EE_DIN; - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); - - return (ack); -} - -/* - * Read a byte of data stored in the EEPROM at address 'addr.' - * We have to send two address bytes since the EEPROM can hold - * more than 256 bytes of data. - */ -u_int8_t -ti_eeprom_getbyte(struct ti_softc *sc, int addr, u_int8_t *dest) -{ - int i; - u_int8_t byte = 0; - - EEPROM_START; - - /* - * Send write control code to EEPROM. - */ - if (ti_eeprom_putbyte(sc, EEPROM_CTL_WRITE)) { - printf("%s: failed to send write command, status: %x\n", - sc->sc_dv.dv_xname, CSR_READ_4(sc, TI_MISC_LOCAL_CTL)); - return (1); - } - - /* - * Send first byte of address of byte we want to read. - */ - if (ti_eeprom_putbyte(sc, (addr >> 8) & 0xFF)) { - printf("%s: failed to send address, status: %x\n", - sc->sc_dv.dv_xname, CSR_READ_4(sc, TI_MISC_LOCAL_CTL)); - return (1); - } - /* - * Send second byte address of byte we want to read. - */ - if (ti_eeprom_putbyte(sc, addr & 0xFF)) { - printf("%s: failed to send address, status: %x\n", - sc->sc_dv.dv_xname, CSR_READ_4(sc, TI_MISC_LOCAL_CTL)); - return (1); - } - - EEPROM_STOP; - EEPROM_START; - /* - * Send read control code to EEPROM. - */ - if (ti_eeprom_putbyte(sc, EEPROM_CTL_READ)) { - printf("%s: failed to send read command, status: %x\n", - sc->sc_dv.dv_xname, CSR_READ_4(sc, TI_MISC_LOCAL_CTL)); - return (1); - } - - /* - * Start reading bits from EEPROM. - */ - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN); - for (i = 0x80; i; i >>= 1) { - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); - DELAY(1); - if (CSR_READ_4(sc, TI_MISC_LOCAL_CTL) & TI_MLC_EE_DIN) - byte |= i; - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); - DELAY(1); - } - - EEPROM_STOP; - - /* - * No ACK generated for read, so just return byte. - */ - - *dest = byte; - - return (0); -} - -/* - * Read a sequence of bytes from the EEPROM. - */ -int -ti_read_eeprom(struct ti_softc *sc, caddr_t dest, int off, int cnt) -{ - int err = 0, i; - u_int8_t byte = 0; - - for (i = 0; i < cnt; i++) { - err = ti_eeprom_getbyte(sc, off + i, &byte); - if (err) - break; - *(dest + i) = byte; - } - - return (err ? 1 : 0); -} - -/* - * NIC memory read function. - * Can be used to copy data from NIC local memory. - */ -void -ti_mem_read(struct ti_softc *sc, u_int32_t addr, u_int32_t len, void *buf) -{ - int segptr, segsize, cnt; - caddr_t ptr; - - segptr = addr; - cnt = len; - ptr = buf; - - while(cnt) { - if (cnt < TI_WINLEN) - segsize = cnt; - else - segsize = TI_WINLEN - (segptr % TI_WINLEN); - CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1))); - bus_space_read_region_4(sc->ti_btag, sc->ti_bhandle, - TI_WINDOW + (segptr & (TI_WINLEN - 1)), (u_int32_t *)ptr, - segsize / 4); - ptr += segsize; - segptr += segsize; - cnt -= segsize; - } -} - -/* - * NIC memory write function. - * Can be used to copy data into NIC local memory. - */ -void -ti_mem_write(struct ti_softc *sc, u_int32_t addr, u_int32_t len, - const void *buf) -{ - int segptr, segsize, cnt; - const char *ptr; - - segptr = addr; - cnt = len; - ptr = buf; - - while(cnt) { - if (cnt < TI_WINLEN) - segsize = cnt; - else - segsize = TI_WINLEN - (segptr % TI_WINLEN); - CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1))); - bus_space_write_region_4(sc->ti_btag, sc->ti_bhandle, - TI_WINDOW + (segptr & (TI_WINLEN - 1)), (u_int32_t *)ptr, - segsize / 4); - ptr += segsize; - segptr += segsize; - cnt -= segsize; - } -} - -/* - * NIC memory write function. - * Can be used to clear a section of NIC local memory. - */ -void -ti_mem_set(struct ti_softc *sc, u_int32_t addr, u_int32_t len) -{ - int segptr, segsize, cnt; - - segptr = addr; - cnt = len; - - while(cnt) { - if (cnt < TI_WINLEN) - segsize = cnt; - else - segsize = TI_WINLEN - (segptr % TI_WINLEN); - CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1))); - bus_space_set_region_4(sc->ti_btag, sc->ti_bhandle, - TI_WINDOW + (segptr & (TI_WINLEN - 1)), 0, segsize / 4); - segptr += segsize; - cnt -= segsize; - } -} - -/* - * Load firmware image into the NIC. Check that the firmware revision - * is acceptable and see if we want the firmware for the Tigon 1 or - * Tigon 2. - */ -void -ti_loadfw(struct ti_softc *sc) -{ - struct tigon_firmware *tf; - u_char *buf = NULL; - u_int32_t *b; - size_t buflen, i, cnt; - char *name; - int error; - - switch(sc->ti_hwrev) { - case TI_HWREV_TIGON: - name = "tigon1"; - break; - case TI_HWREV_TIGON_II: - name = "tigon2"; - break; - default: - printf("%s: can't load firmware: unknown hardware rev\n", - sc->sc_dv.dv_xname); - return; - } - - error = loadfirmware(name, &buf, &buflen); - if (error) - return; - /* convert firmware to host byte order */ - b = (u_int32_t *)buf; - cnt = buflen / sizeof(u_int32_t); - for (i = 0; i < cnt; i++) - b[i] = letoh32(b[i]); - - tf = (struct tigon_firmware *)buf; - if (tf->FwReleaseMajor != TI_FIRMWARE_MAJOR || - tf->FwReleaseMinor != TI_FIRMWARE_MINOR || - tf->FwReleaseFix != TI_FIRMWARE_FIX) { - printf("%s: firmware revision mismatch; want " - "%d.%d.%d, got %d.%d.%d\n", sc->sc_dv.dv_xname, - TI_FIRMWARE_MAJOR, TI_FIRMWARE_MINOR, - TI_FIRMWARE_FIX, tf->FwReleaseMajor, - tf->FwReleaseMinor, tf->FwReleaseFix); - free(buf, M_DEVBUF); - return; - } - ti_mem_write(sc, tf->FwTextAddr, tf->FwTextLen, - (caddr_t)&tf->data[tf->FwTextOffset]); - ti_mem_write(sc, tf->FwRodataAddr, tf->FwRodataLen, - (caddr_t)&tf->data[tf->FwRodataOffset]); - ti_mem_write(sc, tf->FwDataAddr, tf->FwDataLen, - (caddr_t)&tf->data[tf->FwDataOffset]); - ti_mem_set(sc, tf->FwBssAddr, tf->FwBssLen); - ti_mem_set(sc, tf->FwSbssAddr, tf->FwSbssLen); - CSR_WRITE_4(sc, TI_CPU_PROGRAM_COUNTER, tf->FwStartAddr); - free(buf, M_DEVBUF); -} - -/* - * Send the NIC a command via the command ring. - */ -void -ti_cmd(struct ti_softc *sc, struct ti_cmd_desc *cmd) -{ - u_int32_t index; - - index = sc->ti_cmd_saved_prodidx; - CSR_WRITE_4(sc, TI_GCR_CMDRING + (index * 4), *(u_int32_t *)(cmd)); - TI_INC(index, TI_CMD_RING_CNT); - CSR_WRITE_4(sc, TI_MB_CMDPROD_IDX, index); - sc->ti_cmd_saved_prodidx = index; -} - -/* - * Send the NIC an extended command. The 'len' parameter specifies the - * number of command slots to include after the initial command. - */ -void -ti_cmd_ext(struct ti_softc *sc, struct ti_cmd_desc *cmd, caddr_t arg, - int len) -{ - u_int32_t index; - int i; - - index = sc->ti_cmd_saved_prodidx; - CSR_WRITE_4(sc, TI_GCR_CMDRING + (index * 4), *(u_int32_t *)(cmd)); - TI_INC(index, TI_CMD_RING_CNT); - for (i = 0; i < len; i++) { - CSR_WRITE_4(sc, TI_GCR_CMDRING + (index * 4), - *(u_int32_t *)(&arg[i * 4])); - TI_INC(index, TI_CMD_RING_CNT); - } - CSR_WRITE_4(sc, TI_MB_CMDPROD_IDX, index); - sc->ti_cmd_saved_prodidx = index; -} - -/* - * Handle events that have triggered interrupts. - */ -void -ti_handle_events(struct ti_softc *sc) -{ - struct ti_event_desc *e; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->ti_rdata->ti_event_ring == NULL) - return; - - while (sc->ti_ev_saved_considx != sc->ti_ev_prodidx.ti_idx) { - e = &sc->ti_rdata->ti_event_ring[sc->ti_ev_saved_considx]; - switch (TI_EVENT_EVENT(e)) { - case TI_EV_LINKSTAT_CHANGED: - sc->ti_linkstat = TI_EVENT_CODE(e); - switch (sc->ti_linkstat) { - case TI_EV_CODE_LINK_UP: - case TI_EV_CODE_GIG_LINK_UP: - { - struct ifmediareq ifmr; - - bzero(&ifmr, sizeof(ifmr)); - ti_ifmedia_sts(ifp, &ifmr); - if (ifmr.ifm_active & IFM_FDX) { - ifp->if_link_state = - LINK_STATE_FULL_DUPLEX; - } else { - ifp->if_link_state = - LINK_STATE_HALF_DUPLEX; - } - if_link_state_change(ifp); - ifp->if_baudrate = - ifmedia_baudrate(ifmr.ifm_active); - break; - } - case TI_EV_CODE_LINK_DOWN: - ifp->if_link_state = LINK_STATE_DOWN; - if_link_state_change(ifp); - ifp->if_baudrate = 0; - break; - default: - printf("%s: unknown link state code %d\n", - sc->sc_dv.dv_xname, sc->ti_linkstat); - } - break; - case TI_EV_ERROR: - if (TI_EVENT_CODE(e) == TI_EV_CODE_ERR_INVAL_CMD) - printf("%s: invalid command\n", - sc->sc_dv.dv_xname); - else if (TI_EVENT_CODE(e) == TI_EV_CODE_ERR_UNIMP_CMD) - printf("%s: unknown command\n", - sc->sc_dv.dv_xname); - else if (TI_EVENT_CODE(e) == TI_EV_CODE_ERR_BADCFG) - printf("%s: bad config data\n", - sc->sc_dv.dv_xname); - break; - case TI_EV_FIRMWARE_UP: - ti_init2(sc); - break; - case TI_EV_STATS_UPDATED: - ti_stats_update(sc); - break; - case TI_EV_RESET_JUMBO_RING: - case TI_EV_MCAST_UPDATED: - /* Who cares. */ - break; - default: - printf("%s: unknown event: %d\n", sc->sc_dv.dv_xname, - TI_EVENT_EVENT(e)); - break; - } - /* Advance the consumer index. */ - TI_INC(sc->ti_ev_saved_considx, TI_EVENT_RING_CNT); - CSR_WRITE_4(sc, TI_GCR_EVENTCONS_IDX, sc->ti_ev_saved_considx); - } -} - -/* - * Memory management for the jumbo receive ring is a pain in the - * butt. We need to allocate at least 9018 bytes of space per frame, - * _and_ it has to be contiguous (unless you use the extended - * jumbo descriptor format). Using malloc() all the time won't - * work: malloc() allocates memory in powers of two, which means we - * would end up wasting a considerable amount of space by allocating - * 9K chunks. We don't have a jumbo mbuf cluster pool. Thus, we have - * to do our own memory management. - * - * The driver needs to allocate a contiguous chunk of memory at boot - * time. We then chop this up ourselves into 9K pieces and use them - * as external mbuf storage. - * - * One issue here is how much memory to allocate. The jumbo ring has - * 256 slots in it, but at 9K per slot than can consume over 2MB of - * RAM. This is a bit much, especially considering we also need - * RAM for the standard ring and mini ring (on the Tigon 2). To - * save space, we only actually allocate enough memory for 64 slots - * by default, which works out to between 500 and 600K. This can - * be tuned by changing a #define in if_tireg.h. - */ - -int -ti_alloc_jumbo_mem(struct ti_softc *sc) -{ - caddr_t ptr, kva; - bus_dma_segment_t seg; - int i, rseg, state, error; - struct ti_jpool_entry *entry; - - state = error = 0; - - /* Grab a big chunk o' storage. */ - if (bus_dmamem_alloc(sc->sc_dmatag, TI_JMEM, PAGE_SIZE, 0, - &seg, 1, &rseg, BUS_DMA_NOWAIT)) { - printf("%s: can't alloc rx buffers\n", sc->sc_dv.dv_xname); - return (ENOBUFS); - } - - state = 1; - if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, TI_JMEM, &kva, - BUS_DMA_NOWAIT)) { - printf("%s: can't map dma buffers (%d bytes)\n", - sc->sc_dv.dv_xname, TI_JMEM); - error = ENOBUFS; - goto out; - } - - state = 2; - if (bus_dmamap_create(sc->sc_dmatag, TI_JMEM, 1, TI_JMEM, 0, - BUS_DMA_NOWAIT, &sc->ti_cdata.ti_rx_jumbo_map)) { - printf("%s: can't create dma map\n", sc->sc_dv.dv_xname); - error = ENOBUFS; - goto out; - } - - state = 3; - if (bus_dmamap_load(sc->sc_dmatag, sc->ti_cdata.ti_rx_jumbo_map, kva, - TI_JMEM, NULL, BUS_DMA_NOWAIT)) { - printf("%s: can't load dma map\n", sc->sc_dv.dv_xname); - error = ENOBUFS; - goto out; - } - - state = 4; - sc->ti_cdata.ti_jumbo_buf = (caddr_t)kva; - - SLIST_INIT(&sc->ti_jfree_listhead); - SLIST_INIT(&sc->ti_jinuse_listhead); - - /* - * Now divide it up into 9K pieces and save the addresses - * in an array. - */ - ptr = sc->ti_cdata.ti_jumbo_buf; - for (i = 0; i < TI_JSLOTS; i++) { - sc->ti_cdata.ti_jslots[i].ti_buf = ptr; - sc->ti_cdata.ti_jslots[i].ti_inuse = 0; - ptr += TI_JLEN; - entry = malloc(sizeof(struct ti_jpool_entry), - M_DEVBUF, M_NOWAIT); - if (entry == NULL) { - sc->ti_cdata.ti_jumbo_buf = NULL; - printf("%s: no memory for jumbo buffer queue\n", - sc->sc_dv.dv_xname); - error = ENOBUFS; - goto out; - } - entry->slot = i; - SLIST_INSERT_HEAD(&sc->ti_jfree_listhead, entry, jpool_entries); - } -out: - if (error != 0) { - switch (state) { - case 4: - bus_dmamap_unload(sc->sc_dmatag, - sc->ti_cdata.ti_rx_jumbo_map); - case 3: - bus_dmamap_destroy(sc->sc_dmatag, - sc->ti_cdata.ti_rx_jumbo_map); - case 2: - bus_dmamem_unmap(sc->sc_dmatag, kva, TI_JMEM); - case 1: - bus_dmamem_free(sc->sc_dmatag, &seg, rseg); - break; - default: - break; - } - } - - return (error); -} - -/* - * Allocate a jumbo buffer. - */ -void * -ti_jalloc(struct ti_softc *sc) -{ - struct ti_jpool_entry *entry; - - entry = SLIST_FIRST(&sc->ti_jfree_listhead); - - if (entry == NULL) - return (NULL); - - SLIST_REMOVE_HEAD(&sc->ti_jfree_listhead, jpool_entries); - SLIST_INSERT_HEAD(&sc->ti_jinuse_listhead, entry, jpool_entries); - sc->ti_cdata.ti_jslots[entry->slot].ti_inuse = 1; - return (sc->ti_cdata.ti_jslots[entry->slot].ti_buf); -} - -/* - * Release a jumbo buffer. - */ -void -ti_jfree(caddr_t buf, u_int size, void *arg) -{ - struct ti_softc *sc; - int i; - struct ti_jpool_entry *entry; - - /* Extract the softc struct pointer. */ - sc = (struct ti_softc *)arg; - - if (sc == NULL) - panic("ti_jfree: can't find softc pointer!"); - - /* calculate the slot this buffer belongs to */ - i = ((vaddr_t)buf - (vaddr_t)sc->ti_cdata.ti_jumbo_buf) / TI_JLEN; - - if ((i < 0) || (i >= TI_JSLOTS)) - panic("ti_jfree: asked to free buffer that we don't manage!"); - else if (sc->ti_cdata.ti_jslots[i].ti_inuse == 0) - panic("ti_jfree: buffer already free!"); - - sc->ti_cdata.ti_jslots[i].ti_inuse--; - if(sc->ti_cdata.ti_jslots[i].ti_inuse == 0) { - entry = SLIST_FIRST(&sc->ti_jinuse_listhead); - if (entry == NULL) - panic("ti_jfree: buffer not in use!"); - entry->slot = i; - SLIST_REMOVE_HEAD(&sc->ti_jinuse_listhead, jpool_entries); - SLIST_INSERT_HEAD(&sc->ti_jfree_listhead, - entry, jpool_entries); - } -} - -/* - * Intialize a standard receive ring descriptor. - */ -int -ti_newbuf_std(struct ti_softc *sc, int i, struct mbuf *m, - bus_dmamap_t dmamap) -{ - struct mbuf *m_new = NULL; - struct ti_rx_desc *r; - - if (dmamap == NULL) { - /* if (m) panic() */ - - if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, 1, MCLBYTES, - 0, BUS_DMA_NOWAIT, &dmamap)) { - printf("%s: can't create recv map\n", - sc->sc_dv.dv_xname); - return (ENOMEM); - } - } else if (m == NULL) - bus_dmamap_unload(sc->sc_dmatag, dmamap); - - sc->ti_cdata.ti_rx_std_map[i] = dmamap; - - if (m == NULL) { - MGETHDR(m_new, M_DONTWAIT, MT_DATA); - if (m_new == NULL) - return (ENOBUFS); - - MCLGET(m_new, M_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - m_freem(m_new); - return (ENOBUFS); - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - - m_adj(m_new, ETHER_ALIGN); - - if (bus_dmamap_load_mbuf(sc->sc_dmatag, dmamap, m_new, - BUS_DMA_NOWAIT)) - return (ENOBUFS); - - } else { - /* - * We're re-using a previously allocated mbuf; - * be sure to re-init pointers and lengths to - * default values. - */ - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - m_new->m_data = m_new->m_ext.ext_buf; - m_adj(m_new, ETHER_ALIGN); - } - - sc->ti_cdata.ti_rx_std_chain[i] = m_new; - r = &sc->ti_rdata->ti_rx_std_ring[i]; - TI_HOSTADDR(r->ti_addr) = dmamap->dm_segs[0].ds_addr; - r->ti_type = TI_BDTYPE_RECV_BD; - r->ti_flags = TI_BDFLAG_IP_CKSUM; - r->ti_len = dmamap->dm_segs[0].ds_len; - r->ti_idx = i; - - if ((dmamap->dm_segs[0].ds_addr & ~(MCLBYTES - 1)) != - ((dmamap->dm_segs[0].ds_addr + dmamap->dm_segs[0].ds_len - 1) & - ~(MCLBYTES - 1))) - panic("%s: overwritten!!!", sc->sc_dv.dv_xname); - - return (0); -} - -/* - * Intialize a mini receive ring descriptor. This only applies to - * the Tigon 2. - */ -int -ti_newbuf_mini(struct ti_softc *sc, int i, struct mbuf *m, - bus_dmamap_t dmamap) -{ - struct mbuf *m_new = NULL; - struct ti_rx_desc *r; - - if (dmamap == NULL) { - /* if (m) panic() */ - - if (bus_dmamap_create(sc->sc_dmatag, MHLEN, 1, MHLEN, - 0, BUS_DMA_NOWAIT, &dmamap)) { - printf("%s: can't create recv map\n", - sc->sc_dv.dv_xname); - return (ENOMEM); - } - } else if (m == NULL) - bus_dmamap_unload(sc->sc_dmatag, dmamap); - - sc->ti_cdata.ti_rx_mini_map[i] = dmamap; - - if (m == NULL) { - MGETHDR(m_new, M_DONTWAIT, MT_DATA); - if (m_new == NULL) - return (ENOBUFS); - m_new->m_len = m_new->m_pkthdr.len = MHLEN; - m_adj(m_new, ETHER_ALIGN); - - if (bus_dmamap_load_mbuf(sc->sc_dmatag, dmamap, m_new, - BUS_DMA_NOWAIT)) - return (ENOBUFS); - - } else { - /* - * We're re-using a previously allocated mbuf; - * be sure to re-init pointers and lengths to - * default values. - */ - m_new = m; - m_new->m_data = m_new->m_pktdat; - m_new->m_len = m_new->m_pkthdr.len = MHLEN; - } - - r = &sc->ti_rdata->ti_rx_mini_ring[i]; - sc->ti_cdata.ti_rx_mini_chain[i] = m_new; - TI_HOSTADDR(r->ti_addr) = dmamap->dm_segs[0].ds_addr; - r->ti_type = TI_BDTYPE_RECV_BD; - r->ti_flags = TI_BDFLAG_MINI_RING | TI_BDFLAG_IP_CKSUM; - r->ti_len = dmamap->dm_segs[0].ds_len; - r->ti_idx = i; - - return (0); -} - -/* - * Initialize a jumbo receive ring descriptor. This allocates - * a jumbo buffer from the pool managed internally by the driver. - */ -int -ti_newbuf_jumbo(struct ti_softc *sc, int i, struct mbuf *m) -{ - struct mbuf *m_new = NULL; - struct ti_rx_desc *r; - - if (m == NULL) { - caddr_t buf = NULL; - - /* Allocate the mbuf. */ - MGETHDR(m_new, M_DONTWAIT, MT_DATA); - if (m_new == NULL) - return (ENOBUFS); - - /* Allocate the jumbo buffer */ - buf = ti_jalloc(sc); - if (buf == NULL) { - m_freem(m_new); - return (ENOBUFS); - } - - /* Attach the buffer to the mbuf. */ - m_new->m_len = m_new->m_pkthdr.len = TI_JUMBO_FRAMELEN; - MEXTADD(m_new, buf, TI_JUMBO_FRAMELEN, 0, ti_jfree, sc); - } else { - /* - * We're re-using a previously allocated mbuf; - * be sure to re-init pointers and lengths to - * default values. - */ - m_new = m; - m_new->m_data = m_new->m_ext.ext_buf; - m_new->m_ext.ext_size = TI_JUMBO_FRAMELEN; - } - - m_adj(m_new, ETHER_ALIGN); - /* Set up the descriptor. */ - r = &sc->ti_rdata->ti_rx_jumbo_ring[i]; - sc->ti_cdata.ti_rx_jumbo_chain[i] = m_new; - TI_HOSTADDR(r->ti_addr) = TI_JUMBO_DMA_ADDR(sc, m_new); - r->ti_type = TI_BDTYPE_RECV_JUMBO_BD; - r->ti_flags = TI_BDFLAG_JUMBO_RING | TI_BDFLAG_IP_CKSUM; - r->ti_len = m_new->m_len; - r->ti_idx = i; - - return (0); -} - -/* - * The standard receive ring has 512 entries in it. At 2K per mbuf cluster, - * that's 1MB of memory, which is a lot. For now, we fill only the first - * 256 ring entries and hope that our CPU is fast enough to keep up with - * the NIC. - */ -int -ti_init_rx_ring_std(struct ti_softc *sc) -{ - int i; - struct ti_cmd_desc cmd; - - for (i = 0; i < TI_SSLOTS; i++) { - if (ti_newbuf_std(sc, i, NULL, 0) == ENOBUFS) - return (ENOBUFS); - } - - TI_UPDATE_STDPROD(sc, i - 1); - sc->ti_std = i - 1; - - return (0); -} - -void -ti_free_rx_ring_std(struct ti_softc *sc) -{ - int i; - - for (i = 0; i < TI_STD_RX_RING_CNT; i++) { - if (sc->ti_cdata.ti_rx_std_chain[i] != NULL) { - m_freem(sc->ti_cdata.ti_rx_std_chain[i]); - sc->ti_cdata.ti_rx_std_chain[i] = NULL; - bus_dmamap_destroy(sc->sc_dmatag, - sc->ti_cdata.ti_rx_std_map[i]); - sc->ti_cdata.ti_rx_std_map[i] = 0; - } - bzero((char *)&sc->ti_rdata->ti_rx_std_ring[i], - sizeof(struct ti_rx_desc)); - } -} - -int -ti_init_rx_ring_jumbo(struct ti_softc *sc) -{ - int i; - struct ti_cmd_desc cmd; - - for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) { - if (ti_newbuf_jumbo(sc, i, NULL) == ENOBUFS) - return (ENOBUFS); - }; - - TI_UPDATE_JUMBOPROD(sc, i - 1); - sc->ti_jumbo = i - 1; - - return (0); -} - -void -ti_free_rx_ring_jumbo(struct ti_softc *sc) -{ - int i; - - for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) { - if (sc->ti_cdata.ti_rx_jumbo_chain[i] != NULL) { - m_freem(sc->ti_cdata.ti_rx_jumbo_chain[i]); - sc->ti_cdata.ti_rx_jumbo_chain[i] = NULL; - } - bzero((char *)&sc->ti_rdata->ti_rx_jumbo_ring[i], - sizeof(struct ti_rx_desc)); - } -} - -int -ti_init_rx_ring_mini(struct ti_softc *sc) -{ - int i; - - for (i = 0; i < TI_MSLOTS; i++) { - if (ti_newbuf_mini(sc, i, NULL, 0) == ENOBUFS) - return (ENOBUFS); - }; - - TI_UPDATE_MINIPROD(sc, i - 1); - sc->ti_mini = i - 1; - - return (0); -} - -void -ti_free_rx_ring_mini(struct ti_softc *sc) -{ - int i; - - for (i = 0; i < TI_MINI_RX_RING_CNT; i++) { - if (sc->ti_cdata.ti_rx_mini_chain[i] != NULL) { - m_freem(sc->ti_cdata.ti_rx_mini_chain[i]); - sc->ti_cdata.ti_rx_mini_chain[i] = NULL; - bus_dmamap_destroy(sc->sc_dmatag, - sc->ti_cdata.ti_rx_mini_map[i]); - sc->ti_cdata.ti_rx_mini_map[i] = 0; - } - bzero((char *)&sc->ti_rdata->ti_rx_mini_ring[i], - sizeof(struct ti_rx_desc)); - } -} - -void -ti_free_tx_ring(struct ti_softc *sc) -{ - int i; - struct ti_txmap_entry *entry; - - if (sc->ti_rdata->ti_tx_ring == NULL) - return; - - for (i = 0; i < TI_TX_RING_CNT; i++) { - if (sc->ti_cdata.ti_tx_chain[i] != NULL) { - m_freem(sc->ti_cdata.ti_tx_chain[i]); - sc->ti_cdata.ti_tx_chain[i] = NULL; - SLIST_INSERT_HEAD(&sc->ti_tx_map_listhead, - sc->ti_cdata.ti_tx_map[i], link); - sc->ti_cdata.ti_tx_map[i] = 0; - } - bzero((char *)&sc->ti_rdata->ti_tx_ring[i], - sizeof(struct ti_tx_desc)); - } - - while ((entry = SLIST_FIRST(&sc->ti_tx_map_listhead))) { - SLIST_REMOVE_HEAD(&sc->ti_tx_map_listhead, link); - bus_dmamap_destroy(sc->sc_dmatag, entry->dmamap); - free(entry, M_DEVBUF); - } -} - -int -ti_init_tx_ring(struct ti_softc *sc) -{ - int i; - bus_dmamap_t dmamap; - struct ti_txmap_entry *entry; - - sc->ti_txcnt = 0; - sc->ti_tx_saved_considx = 0; - sc->ti_tx_saved_prodidx = 0; - CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, 0); - - SLIST_INIT(&sc->ti_tx_map_listhead); - for (i = 0; i < TI_TX_RING_CNT; i++) { - if (bus_dmamap_create(sc->sc_dmatag, TI_JUMBO_FRAMELEN, - TI_NTXSEG, MCLBYTES, 0, BUS_DMA_NOWAIT, &dmamap)) - return (ENOBUFS); - - entry = malloc(sizeof(*entry), M_DEVBUF, M_NOWAIT); - if (!entry) { - bus_dmamap_destroy(sc->sc_dmatag, dmamap); - return (ENOBUFS); - } - entry->dmamap = dmamap; - SLIST_INSERT_HEAD(&sc->ti_tx_map_listhead, entry, link); - } - - return (0); -} - -/* - * The Tigon 2 firmware has a new way to add/delete multicast addresses, - * but we have to support the old way too so that Tigon 1 cards will - * work. - */ -void -ti_add_mcast(struct ti_softc *sc, struct ether_addr *addr) -{ - struct ti_cmd_desc cmd; - u_int16_t *m; - u_int32_t ext[2] = {0, 0}; - - m = (u_int16_t *)&addr->ether_addr_octet[0]; - - switch(sc->ti_hwrev) { - case TI_HWREV_TIGON: - CSR_WRITE_4(sc, TI_GCR_MAR0, htons(m[0])); - CSR_WRITE_4(sc, TI_GCR_MAR1, (htons(m[1]) << 16) | htons(m[2])); - TI_DO_CMD(TI_CMD_ADD_MCAST_ADDR, 0, 0); - break; - case TI_HWREV_TIGON_II: - ext[0] = htons(m[0]); - ext[1] = (htons(m[1]) << 16) | htons(m[2]); - TI_DO_CMD_EXT(TI_CMD_EXT_ADD_MCAST, 0, 0, (caddr_t)&ext, 2); - break; - default: - printf("%s: unknown hwrev\n", sc->sc_dv.dv_xname); - break; - } -} - -void -ti_del_mcast(struct ti_softc *sc, struct ether_addr *addr) -{ - struct ti_cmd_desc cmd; - u_int16_t *m; - u_int32_t ext[2] = {0, 0}; - - m = (u_int16_t *)&addr->ether_addr_octet[0]; - - switch(sc->ti_hwrev) { - case TI_HWREV_TIGON: - CSR_WRITE_4(sc, TI_GCR_MAR0, htons(m[0])); - CSR_WRITE_4(sc, TI_GCR_MAR1, (htons(m[1]) << 16) | htons(m[2])); - TI_DO_CMD(TI_CMD_DEL_MCAST_ADDR, 0, 0); - break; - case TI_HWREV_TIGON_II: - ext[0] = htons(m[0]); - ext[1] = (htons(m[1]) << 16) | htons(m[2]); - TI_DO_CMD_EXT(TI_CMD_EXT_DEL_MCAST, 0, 0, (caddr_t)&ext, 2); - break; - default: - printf("%s: unknown hwrev\n", sc->sc_dv.dv_xname); - break; - } -} - -/* - * Configure the Tigon's multicast address filter. - * - * The actual multicast table management is a bit of a pain, thanks to - * slight brain damage on the part of both Alteon and us. With our - * multicast code, we are only alerted when the multicast address table - * changes and at that point we only have the current list of addresses: - * we only know the current state, not the previous state, so we don't - * actually know what addresses were removed or added. The firmware has - * state, but we can't get our grubby mits on it, and there is no 'delete - * all multicast addresses' command. Hence, we have to maintain our own - * state so we know what addresses have been programmed into the NIC at - * any given time. - */ -void -ti_setmulti(struct ti_softc *sc) -{ - struct ifnet *ifp; - struct arpcom *ac = &sc->arpcom; - struct ether_multi *enm; - struct ether_multistep step; - struct ti_cmd_desc cmd; - struct ti_mc_entry *mc; - u_int32_t intrs; - - ifp = &sc->arpcom.ac_if; - -allmulti: - if (ifp->if_flags & IFF_ALLMULTI) { - TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_ENB, 0); - return; - } else { - TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_DIS, 0); - } - - /* Disable interrupts. */ - intrs = CSR_READ_4(sc, TI_MB_HOSTINTR); - CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1); - - /* First, zot all the existing filters. */ - while (SLIST_FIRST(&sc->ti_mc_listhead) != NULL) { - mc = SLIST_FIRST(&sc->ti_mc_listhead); - ti_del_mcast(sc, &mc->mc_addr); - SLIST_REMOVE_HEAD(&sc->ti_mc_listhead, mc_entries); - free(mc, M_DEVBUF); - } - - /* Now program new ones. */ - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { - /* Re-enable interrupts. */ - CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs); - - ifp->if_flags |= IFF_ALLMULTI; - goto allmulti; - } - mc = malloc(sizeof(struct ti_mc_entry), M_DEVBUF, M_NOWAIT); - if (mc == NULL) - panic("ti_setmulti"); - bcopy(enm->enm_addrlo, (char *)&mc->mc_addr, ETHER_ADDR_LEN); - SLIST_INSERT_HEAD(&sc->ti_mc_listhead, mc, mc_entries); - ti_add_mcast(sc, &mc->mc_addr); - ETHER_NEXT_MULTI(step, enm); - } - - /* Re-enable interrupts. */ - CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs); -} - -/* - * Check to see if the BIOS has configured us for a 64 bit slot when - * we aren't actually in one. If we detect this condition, we can work - * around it on the Tigon 2 by setting a bit in the PCI state register, - * but for the Tigon 1 we must give up and abort the interface attach. - */ -int -ti_64bitslot_war(struct ti_softc *sc) -{ - if (!(CSR_READ_4(sc, TI_PCI_STATE) & TI_PCISTATE_32BIT_BUS)) { - CSR_WRITE_4(sc, 0x600, 0); - CSR_WRITE_4(sc, 0x604, 0); - CSR_WRITE_4(sc, 0x600, 0x5555AAAA); - if (CSR_READ_4(sc, 0x604) == 0x5555AAAA) { - if (sc->ti_hwrev == TI_HWREV_TIGON) - return (EINVAL); - else { - TI_SETBIT(sc, TI_PCI_STATE, - TI_PCISTATE_32BIT_BUS); - return (0); - } - } - } - - return (0); -} - -/* - * Do endian, PCI and DMA initialization. Also check the on-board ROM - * self-test results. - */ -int -ti_chipinit(struct ti_softc *sc) -{ - u_int32_t cacheline; - u_int32_t pci_writemax = 0; - u_int32_t chip_rev; - - /* Initialize link to down state. */ - sc->ti_linkstat = TI_EV_CODE_LINK_DOWN; - - /* Set endianness before we access any non-PCI registers. */ - CSR_WRITE_4(sc, TI_MISC_HOST_CTL, - TI_MHC_LITTLEENDIAN_INIT | (TI_MHC_LITTLEENDIAN_INIT << 24)); - - /* Check the ROM failed bit to see if self-tests passed. */ - if (CSR_READ_4(sc, TI_CPU_STATE) & TI_CPUSTATE_ROMFAIL) { - printf("%s: board self-diagnostics failed!\n", - sc->sc_dv.dv_xname); - return (ENODEV); - } - - /* Halt the CPU. */ - TI_SETBIT(sc, TI_CPU_STATE, TI_CPUSTATE_HALT); - - /* Figure out the hardware revision. */ - chip_rev = CSR_READ_4(sc, TI_MISC_HOST_CTL) & TI_MHC_CHIP_REV_MASK; - switch(chip_rev) { - case TI_REV_TIGON_I: - sc->ti_hwrev = TI_HWREV_TIGON; - break; - case TI_REV_TIGON_II: - sc->ti_hwrev = TI_HWREV_TIGON_II; - break; - default: - printf("\n"); - printf("%s: unsupported chip revision: %x\n", - sc->sc_dv.dv_xname, chip_rev); - return (ENODEV); - } - - /* Do special setup for Tigon 2. */ - if (sc->ti_hwrev == TI_HWREV_TIGON_II) { - TI_SETBIT(sc, TI_CPU_CTL_B, TI_CPUSTATE_HALT); - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_SRAM_BANK_512K); - TI_SETBIT(sc, TI_MISC_CONF, TI_MCR_SRAM_SYNCHRONOUS); - } - - /* Set up the PCI state register. */ - CSR_WRITE_4(sc, TI_PCI_STATE, TI_PCI_READ_CMD|TI_PCI_WRITE_CMD); - if (sc->ti_hwrev == TI_HWREV_TIGON_II) - TI_SETBIT(sc, TI_PCI_STATE, TI_PCISTATE_USE_MEM_RD_MULT); - - /* Clear the read/write max DMA parameters. */ - TI_CLRBIT(sc, TI_PCI_STATE, (TI_PCISTATE_WRITE_MAXDMA| - TI_PCISTATE_READ_MAXDMA)); - - /* Get cache line size. */ - cacheline = CSR_READ_4(sc, TI_PCI_BIST) & 0xFF; - - /* - * If the system has set enabled the PCI memory write - * and invalidate command in the command register, set - * the write max parameter accordingly. This is necessary - * to use MWI with the Tigon 2. - */ - if (CSR_READ_4(sc, TI_PCI_CMDSTAT) & PCI_COMMAND_INVALIDATE_ENABLE) { - switch(cacheline) { - case 1: - case 4: - case 8: - case 16: - case 32: - case 64: - break; - default: - /* Disable PCI memory write and invalidate. */ - CSR_WRITE_4(sc, TI_PCI_CMDSTAT, CSR_READ_4(sc, - TI_PCI_CMDSTAT) & ~PCI_COMMAND_INVALIDATE_ENABLE); - break; - } - } - -#ifdef __brokenalpha__ - /* - * From the Alteon sample driver: - * Must insure that we do not cross an 8K (bytes) boundary - * for DMA reads. Our highest limit is 1K bytes. This is a - * restriction on some ALPHA platforms with early revision - * 21174 PCI chipsets, such as the AlphaPC 164lx - */ - TI_SETBIT(sc, TI_PCI_STATE, pci_writemax|TI_PCI_READMAX_1024); -#else - TI_SETBIT(sc, TI_PCI_STATE, pci_writemax); -#endif - - /* This sets the min dma param all the way up (0xff). */ - TI_SETBIT(sc, TI_PCI_STATE, TI_PCISTATE_MINDMA); - - /* Configure DMA variables. */ - CSR_WRITE_4(sc, TI_GCR_OPMODE, TI_DMA_SWAP_OPTIONS | - TI_OPMODE_WARN_ENB | TI_OPMODE_FATAL_ENB | - TI_OPMODE_DONT_FRAG_JUMBO); - - /* Recommended settings from Tigon manual. */ - CSR_WRITE_4(sc, TI_GCR_DMA_WRITECFG, TI_DMA_STATE_THRESH_8W); - CSR_WRITE_4(sc, TI_GCR_DMA_READCFG, TI_DMA_STATE_THRESH_8W); - - if (ti_64bitslot_war(sc)) { - printf("%s: bios thinks we're in a 64 bit slot, " - "but we aren't", sc->sc_dv.dv_xname); - return (EINVAL); - } - - return (0); -} - -/* - * Initialize the general information block and firmware, and - * start the CPU(s) running. - */ -int -ti_gibinit(struct ti_softc *sc) -{ - struct ti_rcb *rcb; - int i; - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - - /* Disable interrupts for now. */ - CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1); - - /* - * Tell the chip where to find the general information block. - * While this struct could go into >4GB memory, we allocate it in a - * single slab with the other descriptors, and those don't seem to - * support being located in a 64-bit region. - */ - CSR_WRITE_4(sc, TI_GCR_GENINFO_HI, 0); - CSR_WRITE_4(sc, TI_GCR_GENINFO_LO, - TI_RING_DMA_ADDR(sc, ti_info) & 0xffffffff); - - /* Load the firmware into SRAM. */ - ti_loadfw(sc); - - /* Set up the contents of the general info and ring control blocks. */ - - /* Set up the event ring and producer pointer. */ - rcb = &sc->ti_rdata->ti_info.ti_ev_rcb; - - TI_HOSTADDR(rcb->ti_hostaddr) = TI_RING_DMA_ADDR(sc, ti_event_ring); - rcb->ti_flags = 0; - TI_HOSTADDR(sc->ti_rdata->ti_info.ti_ev_prodidx_ptr) = - TI_RING_DMA_ADDR(sc, ti_ev_prodidx_r); - sc->ti_ev_prodidx.ti_idx = 0; - CSR_WRITE_4(sc, TI_GCR_EVENTCONS_IDX, 0); - sc->ti_ev_saved_considx = 0; - - /* Set up the command ring and producer mailbox. */ - rcb = &sc->ti_rdata->ti_info.ti_cmd_rcb; - - TI_HOSTADDR(rcb->ti_hostaddr) = TI_GCR_NIC_ADDR(TI_GCR_CMDRING); - rcb->ti_flags = 0; - rcb->ti_max_len = 0; - for (i = 0; i < TI_CMD_RING_CNT; i++) { - CSR_WRITE_4(sc, TI_GCR_CMDRING + (i * 4), 0); - } - CSR_WRITE_4(sc, TI_GCR_CMDCONS_IDX, 0); - CSR_WRITE_4(sc, TI_MB_CMDPROD_IDX, 0); - sc->ti_cmd_saved_prodidx = 0; - - /* - * Assign the address of the stats refresh buffer. - * We re-use the current stats buffer for this to - * conserve memory. - */ - TI_HOSTADDR(sc->ti_rdata->ti_info.ti_refresh_stats_ptr) = - TI_RING_DMA_ADDR(sc, ti_info.ti_stats); - - /* Set up the standard receive ring. */ - rcb = &sc->ti_rdata->ti_info.ti_std_rx_rcb; - TI_HOSTADDR(rcb->ti_hostaddr) = - TI_RING_DMA_ADDR(sc, ti_rx_std_ring); - rcb->ti_max_len = ETHER_MAX_LEN; - rcb->ti_flags = 0; - rcb->ti_flags |= TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM; -#if NVLAN > 0 - if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) - rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST; -#endif - - /* Set up the jumbo receive ring. */ - rcb = &sc->ti_rdata->ti_info.ti_jumbo_rx_rcb; - TI_HOSTADDR(rcb->ti_hostaddr) = TI_RING_DMA_ADDR(sc, ti_rx_jumbo_ring); - rcb->ti_max_len = TI_JUMBO_FRAMELEN; - rcb->ti_flags = 0; - rcb->ti_flags |= TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM; -#if NVLAN > 0 - if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) - rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST; -#endif - - /* - * Set up the mini ring. Only activated on the - * Tigon 2 but the slot in the config block is - * still there on the Tigon 1. - */ - rcb = &sc->ti_rdata->ti_info.ti_mini_rx_rcb; - TI_HOSTADDR(rcb->ti_hostaddr) = TI_RING_DMA_ADDR(sc, ti_rx_mini_ring); - rcb->ti_max_len = MHLEN - ETHER_ALIGN; - if (sc->ti_hwrev == TI_HWREV_TIGON) - rcb->ti_flags = TI_RCB_FLAG_RING_DISABLED; - else - rcb->ti_flags = 0; - rcb->ti_flags |= TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM; -#if NVLAN > 0 - if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) - rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST; -#endif - - /* - * Set up the receive return ring. - */ - rcb = &sc->ti_rdata->ti_info.ti_return_rcb; - TI_HOSTADDR(rcb->ti_hostaddr) = TI_RING_DMA_ADDR(sc,ti_rx_return_ring); - rcb->ti_flags = 0; - rcb->ti_max_len = TI_RETURN_RING_CNT; - TI_HOSTADDR(sc->ti_rdata->ti_info.ti_return_prodidx_ptr) = - TI_RING_DMA_ADDR(sc, ti_return_prodidx_r); - - /* - * Set up the tx ring. Note: for the Tigon 2, we have the option - * of putting the transmit ring in the host's address space and - * letting the chip DMA it instead of leaving the ring in the NIC's - * memory and accessing it through the shared memory region. We - * do this for the Tigon 2, but it doesn't work on the Tigon 1, - * so we have to revert to the shared memory scheme if we detect - * a Tigon 1 chip. - */ - CSR_WRITE_4(sc, TI_WINBASE, TI_TX_RING_BASE); - bzero((char *)sc->ti_rdata->ti_tx_ring, - TI_TX_RING_CNT * sizeof(struct ti_tx_desc)); - rcb = &sc->ti_rdata->ti_info.ti_tx_rcb; - if (sc->ti_hwrev == TI_HWREV_TIGON) - rcb->ti_flags = 0; - else - rcb->ti_flags = TI_RCB_FLAG_HOST_RING; - rcb->ti_flags |= TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM; -#if NVLAN > 0 - if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) - rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST; -#endif - rcb->ti_max_len = TI_TX_RING_CNT; - if (sc->ti_hwrev == TI_HWREV_TIGON) - TI_HOSTADDR(rcb->ti_hostaddr) = TI_TX_RING_BASE; - else - TI_HOSTADDR(rcb->ti_hostaddr) = - TI_RING_DMA_ADDR(sc, ti_tx_ring); - TI_HOSTADDR(sc->ti_rdata->ti_info.ti_tx_considx_ptr) = - TI_RING_DMA_ADDR(sc, ti_tx_considx_r); - - TI_RING_DMASYNC(sc, ti_info, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - - /* Set up tuneables */ - CSR_WRITE_4(sc, TI_GCR_RX_COAL_TICKS, (sc->ti_rx_coal_ticks / 10)); - CSR_WRITE_4(sc, TI_GCR_TX_COAL_TICKS, sc->ti_tx_coal_ticks); - CSR_WRITE_4(sc, TI_GCR_STAT_TICKS, sc->ti_stat_ticks); - CSR_WRITE_4(sc, TI_GCR_RX_MAX_COAL_BD, sc->ti_rx_max_coal_bds); - CSR_WRITE_4(sc, TI_GCR_TX_MAX_COAL_BD, sc->ti_tx_max_coal_bds); - CSR_WRITE_4(sc, TI_GCR_TX_BUFFER_RATIO, sc->ti_tx_buf_ratio); - - /* Turn interrupts on. */ - CSR_WRITE_4(sc, TI_GCR_MASK_INTRS, 0); - CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0); - - /* Start CPU. */ - TI_CLRBIT(sc, TI_CPU_STATE, (TI_CPUSTATE_HALT|TI_CPUSTATE_STEP)); - - return (0); -} - -/* - * Probe for a Tigon chip. Check the PCI vendor and device IDs - * against our list and return its name if we find a match. - */ -int -ti_probe(struct device *parent, void *match, void *aux) -{ - return (pci_matchbyid((struct pci_attach_args *)aux, ti_devices, - sizeof(ti_devices)/sizeof(ti_devices[0]))); -} - -void -ti_attach(struct device *parent, struct device *self, void *aux) -{ - struct ti_softc *sc = (struct ti_softc *)self; - struct pci_attach_args *pa = aux; - pci_chipset_tag_t pc = pa->pa_pc; - pci_intr_handle_t ih; - const char *intrstr = NULL; - bus_size_t size; - bus_dma_segment_t seg; - int rseg; - struct ifnet *ifp; - caddr_t kva; - - /* - * Map control/status registers. - */ - - if (pci_mapreg_map(pa, TI_PCI_LOMEM, - PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, - &sc->ti_btag, &sc->ti_bhandle, NULL, &size, 0)) { - printf(": can't map mem space\n"); - return; - } - - if (pci_intr_map(pa, &ih)) { - printf(": couldn't map interrupt\n"); - goto fail_1; - } - intrstr = pci_intr_string(pc, ih); - sc->ti_intrhand = pci_intr_establish(pc, ih, IPL_NET, ti_intr, sc, - self->dv_xname); - if (sc->ti_intrhand == NULL) { - printf(": couldn't establish interrupt"); - if (intrstr != NULL) - printf(" at %s", intrstr); - printf("\n"); - goto fail_1; - } - - if (ti_chipinit(sc)) { - printf("%s: chip initialization failed\n", sc->sc_dv.dv_xname); - goto fail_2; - } - - /* Zero out the NIC's on-board SRAM. */ - ti_mem_set(sc, 0x2000, 0x100000 - 0x2000); - - /* Init again -- zeroing memory may have clobbered some registers. */ - if (ti_chipinit(sc)) { - printf("%s: chip initialization failed\n", sc->sc_dv.dv_xname); - goto fail_2; - } - - /* - * Get station address from the EEPROM. Note: the manual states - * that the MAC address is at offset 0x8c, however the data is - * stored as two longwords (since that's how it's loaded into - * the NIC). This means the MAC address is actually preceded - * by two zero bytes. We need to skip over those. - */ - if (ti_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr, - TI_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) { - printf("%s: failed to read station address\n", - sc->sc_dv.dv_xname); - free(sc, M_DEVBUF); - goto fail_2; - } - - /* - * A Tigon chip was detected. Inform the world. - */ - printf(": %s, address %s\n", intrstr, - ether_sprintf(sc->arpcom.ac_enaddr)); - - /* Allocate the general information block and ring buffers. */ - sc->sc_dmatag = pa->pa_dmat; - if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct ti_ring_data), - PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { - printf("%s: can't alloc rx buffers\n", sc->sc_dv.dv_xname); - goto fail_2; - } - if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, - sizeof(struct ti_ring_data), &kva, BUS_DMA_NOWAIT)) { - printf("%s: can't map dma buffers (%d bytes)\n", - sc->sc_dv.dv_xname, sizeof(struct ti_ring_data)); - goto fail_3; - } - if (bus_dmamap_create(sc->sc_dmatag, sizeof(struct ti_ring_data), 1, - sizeof(struct ti_ring_data), 0, BUS_DMA_NOWAIT, - &sc->ti_ring_map)) { - printf("%s: can't create dma map\n", sc->sc_dv.dv_xname); - goto fail_4; - } - if (bus_dmamap_load(sc->sc_dmatag, sc->ti_ring_map, kva, - sizeof(struct ti_ring_data), NULL, BUS_DMA_NOWAIT)) { - goto fail_5; - } - sc->ti_rdata = (struct ti_ring_data *)kva; - bzero(sc->ti_rdata, sizeof(struct ti_ring_data)); - - /* Try to allocate memory for jumbo buffers. */ - if (ti_alloc_jumbo_mem(sc)) { - printf("%s: jumbo buffer allocation failed\n", - sc->sc_dv.dv_xname); - goto fail_5; - } - - /* - * We really need a better way to tell a 1000baseTX card - * from a 1000baseSX one, since in theory there could be - * OEMed 1000baseTX cards from lame vendors who aren't - * clever enough to change the PCI ID. For the moment - * though, the AceNIC is the only copper card available. - */ - if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALTEON && - PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALTEON_ACENICT) - sc->ti_copper = 1; - /* Ok, it's not the only copper card available */ - if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NETGEAR && - PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NETGEAR_GA620T) - sc->ti_copper = 1; - - /* Set default tuneable values. */ - sc->ti_stat_ticks = 2 * TI_TICKS_PER_SEC; - sc->ti_rx_coal_ticks = TI_TICKS_PER_SEC / 5000; - sc->ti_tx_coal_ticks = TI_TICKS_PER_SEC / 500; - sc->ti_rx_max_coal_bds = 64; - sc->ti_tx_max_coal_bds = 128; - sc->ti_tx_buf_ratio = 21; - - /* Set up ifnet structure */ - ifp = &sc->arpcom.ac_if; - ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = ti_ioctl; - ifp->if_start = ti_start; - ifp->if_watchdog = ti_watchdog; - ifp->if_hardmtu = TI_JUMBO_FRAMELEN - ETHER_HDR_LEN; - IFQ_SET_MAXLEN(&ifp->if_snd, TI_TX_RING_CNT - 1); - IFQ_SET_READY(&ifp->if_snd); - bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ); - - ifp->if_capabilities = IFCAP_VLAN_MTU; - -#if NVLAN > 0 - ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; -#endif - - /* Set up ifmedia support. */ - ifmedia_init(&sc->ifmedia, IFM_IMASK, ti_ifmedia_upd, ti_ifmedia_sts); - if (sc->ti_copper) { - /* - * Copper cards allow manual 10/100 mode selection, - * but not manual 1000baseTX mode selection. Why? - * Because currently there's no way to specify the - * master/slave setting through the firmware interface, - * so Alteon decided to just bag it and handle it - * via autonegotiation. - */ - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); - ifmedia_add(&sc->ifmedia, - IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); - ifmedia_add(&sc->ifmedia, - IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_1000_T, 0, NULL); - ifmedia_add(&sc->ifmedia, - IFM_ETHER|IFM_1000_T|IFM_FDX, 0, NULL); - } else { - /* Fiber cards don't support 10/100 modes. */ - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL); - ifmedia_add(&sc->ifmedia, - IFM_ETHER|IFM_1000_SX|IFM_FDX, 0, NULL); - } - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); - ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO); - - /* - * Call MI attach routines. - */ - if_attach(ifp); - ether_ifattach(ifp); - - shutdownhook_establish(ti_shutdown, sc); - return; - -fail_5: - bus_dmamap_destroy(sc->sc_dmatag, sc->ti_ring_map); - -fail_4: - bus_dmamem_unmap(sc->sc_dmatag, kva, - sizeof(struct ti_ring_data)); - -fail_3: - bus_dmamem_free(sc->sc_dmatag, &seg, rseg); - -fail_2: - pci_intr_disestablish(pc, sc->ti_intrhand); - -fail_1: - bus_space_unmap(sc->ti_btag, sc->ti_bhandle, size); -} - -/* - * Frame reception handling. This is called if there's a frame - * on the receive return list. - * - * Note: we have to be able to handle three possibilities here: - * 1) the frame is from the mini receive ring (can only happen) - * on Tigon 2 boards) - * 2) the frame is from the jumbo receive ring - * 3) the frame is from the standard receive ring - */ - -void -ti_rxeof(struct ti_softc *sc) -{ - struct ifnet *ifp; - struct ti_cmd_desc cmd; - - ifp = &sc->arpcom.ac_if; - - while(sc->ti_rx_saved_considx != sc->ti_return_prodidx.ti_idx) { - struct ti_rx_desc *cur_rx; - u_int32_t rxidx; - struct mbuf *m = NULL; - bus_dmamap_t dmamap; - - cur_rx = - &sc->ti_rdata->ti_rx_return_ring[sc->ti_rx_saved_considx]; - rxidx = cur_rx->ti_idx; - TI_INC(sc->ti_rx_saved_considx, TI_RETURN_RING_CNT); - - if (cur_rx->ti_flags & TI_BDFLAG_JUMBO_RING) { - TI_INC(sc->ti_jumbo, TI_JUMBO_RX_RING_CNT); - m = sc->ti_cdata.ti_rx_jumbo_chain[rxidx]; - sc->ti_cdata.ti_rx_jumbo_chain[rxidx] = NULL; - if (cur_rx->ti_flags & TI_BDFLAG_ERROR) { - ifp->if_ierrors++; - ti_newbuf_jumbo(sc, sc->ti_jumbo, m); - continue; - } - if (ti_newbuf_jumbo(sc, sc->ti_jumbo, NULL) - == ENOBUFS) { - struct mbuf *m0; - m0 = m_devget(mtod(m, char *), cur_rx->ti_len, - ETHER_ALIGN, ifp, NULL); - ti_newbuf_jumbo(sc, sc->ti_jumbo, m); - if (m0 == NULL) { - ifp->if_ierrors++; - continue; - } - m = m0; - } - } else if (cur_rx->ti_flags & TI_BDFLAG_MINI_RING) { - TI_INC(sc->ti_mini, TI_MINI_RX_RING_CNT); - m = sc->ti_cdata.ti_rx_mini_chain[rxidx]; - sc->ti_cdata.ti_rx_mini_chain[rxidx] = NULL; - dmamap = sc->ti_cdata.ti_rx_mini_map[rxidx]; - sc->ti_cdata.ti_rx_mini_map[rxidx] = 0; - if (cur_rx->ti_flags & TI_BDFLAG_ERROR) { - ifp->if_ierrors++; - ti_newbuf_mini(sc, sc->ti_mini, m, dmamap); - continue; - } - if (ti_newbuf_mini(sc, sc->ti_mini, NULL, dmamap) - == ENOBUFS) { - ifp->if_ierrors++; - ti_newbuf_mini(sc, sc->ti_mini, m, dmamap); - continue; - } - } else { - TI_INC(sc->ti_std, TI_STD_RX_RING_CNT); - m = sc->ti_cdata.ti_rx_std_chain[rxidx]; - sc->ti_cdata.ti_rx_std_chain[rxidx] = NULL; - dmamap = sc->ti_cdata.ti_rx_std_map[rxidx]; - sc->ti_cdata.ti_rx_std_map[rxidx] = 0; - if (cur_rx->ti_flags & TI_BDFLAG_ERROR) { - ifp->if_ierrors++; - ti_newbuf_std(sc, sc->ti_std, m, dmamap); - continue; - } - if (ti_newbuf_std(sc, sc->ti_std, NULL, dmamap) - == ENOBUFS) { - ifp->if_ierrors++; - ti_newbuf_std(sc, sc->ti_std, m, dmamap); - continue; - } - } - - if (m == NULL) - panic("%s: couldn't get mbuf", sc->sc_dv.dv_xname); - - m->m_pkthdr.len = m->m_len = cur_rx->ti_len; - ifp->if_ipackets++; - m->m_pkthdr.rcvif = ifp; - -#if NVLAN > 0 - if (cur_rx->ti_flags & TI_BDFLAG_VLAN_TAG) { - m->m_pkthdr.ether_vtag = cur_rx->ti_vlan_tag; - m->m_flags |= M_VLANTAG; - } -#endif - -#if NBPFILTER > 0 - /* - * Handle BPF listeners. Let the BPF user see the packet. - */ - if (ifp->if_bpf) - bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_IN); -#endif - - if ((cur_rx->ti_ip_cksum ^ 0xffff) == 0) - m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; - - ether_input_mbuf(ifp, m); - } - - /* Only necessary on the Tigon 1. */ - if (sc->ti_hwrev == TI_HWREV_TIGON) - CSR_WRITE_4(sc, TI_GCR_RXRETURNCONS_IDX, - sc->ti_rx_saved_considx); - - TI_UPDATE_STDPROD(sc, sc->ti_std); - TI_UPDATE_MINIPROD(sc, sc->ti_mini); - TI_UPDATE_JUMBOPROD(sc, sc->ti_jumbo); -} - -void -ti_txeof_tigon1(struct ti_softc *sc) -{ - struct ifnet *ifp; - struct ti_txmap_entry *entry; - int active = 1; - - ifp = &sc->arpcom.ac_if; - - /* - * Go through our tx ring and free mbufs for those - * frames that have been sent. - */ - while (sc->ti_tx_saved_considx != sc->ti_tx_considx.ti_idx) { - u_int32_t idx = 0; - struct ti_tx_desc txdesc; - - idx = sc->ti_tx_saved_considx; - ti_mem_read(sc, TI_TX_RING_BASE + idx * sizeof(txdesc), - sizeof(txdesc), (caddr_t)&txdesc); - - if (txdesc.ti_flags & TI_BDFLAG_END) - ifp->if_opackets++; - - if (sc->ti_cdata.ti_tx_chain[idx] != NULL) { - m_freem(sc->ti_cdata.ti_tx_chain[idx]); - sc->ti_cdata.ti_tx_chain[idx] = NULL; - - entry = sc->ti_cdata.ti_tx_map[idx]; - bus_dmamap_sync(sc->sc_dmatag, entry->dmamap, 0, - entry->dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); - - bus_dmamap_unload(sc->sc_dmatag, entry->dmamap); - SLIST_INSERT_HEAD(&sc->ti_tx_map_listhead, entry, - link); - sc->ti_cdata.ti_tx_map[idx] = NULL; - - } - sc->ti_txcnt--; - TI_INC(sc->ti_tx_saved_considx, TI_TX_RING_CNT); - ifp->if_timer = 0; - - active = 0; - } - - if (!active) - ifp->if_flags &= ~IFF_OACTIVE; -} - -void -ti_txeof_tigon2(struct ti_softc *sc) -{ - struct ti_tx_desc *cur_tx = NULL; - struct ifnet *ifp; - struct ti_txmap_entry *entry; - - ifp = &sc->arpcom.ac_if; - - /* - * Go through our tx ring and free mbufs for those - * frames that have been sent. - */ - while (sc->ti_tx_saved_considx != sc->ti_tx_considx.ti_idx) { - u_int32_t idx = 0; - - idx = sc->ti_tx_saved_considx; - cur_tx = &sc->ti_rdata->ti_tx_ring[idx]; - - if (cur_tx->ti_flags & TI_BDFLAG_END) - ifp->if_opackets++; - if (sc->ti_cdata.ti_tx_chain[idx] != NULL) { - m_freem(sc->ti_cdata.ti_tx_chain[idx]); - sc->ti_cdata.ti_tx_chain[idx] = NULL; - - entry = sc->ti_cdata.ti_tx_map[idx]; - bus_dmamap_sync(sc->sc_dmatag, entry->dmamap, 0, - entry->dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); - - bus_dmamap_unload(sc->sc_dmatag, entry->dmamap); - SLIST_INSERT_HEAD(&sc->ti_tx_map_listhead, entry, - link); - sc->ti_cdata.ti_tx_map[idx] = NULL; - - } - sc->ti_txcnt--; - TI_INC(sc->ti_tx_saved_considx, TI_TX_RING_CNT); - ifp->if_timer = 0; - } - - if (cur_tx != NULL) - ifp->if_flags &= ~IFF_OACTIVE; -} - -int -ti_intr(void *xsc) -{ - struct ti_softc *sc; - struct ifnet *ifp; - - sc = xsc; - ifp = &sc->arpcom.ac_if; - - /* XXX checking this register is expensive. */ - /* Make sure this is really our interrupt. */ - if (!(CSR_READ_4(sc, TI_MISC_HOST_CTL) & TI_MHC_INTSTATE)) - return (0); - - /* Ack interrupt and stop others from occurring. */ - CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1); - - if (ifp->if_flags & IFF_RUNNING) { - /* Check RX return ring producer/consumer */ - ti_rxeof(sc); - - /* Check TX ring producer/consumer */ - if (sc->ti_hwrev == TI_HWREV_TIGON) - ti_txeof_tigon1(sc); - else - ti_txeof_tigon2(sc); - } - - ti_handle_events(sc); - - /* Re-enable interrupts. */ - CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0); - - if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd)) - ti_start(ifp); - - return (1); -} - -void -ti_stats_update(struct ti_softc *sc) -{ - struct ifnet *ifp; - struct ti_stats *stats = &sc->ti_rdata->ti_info.ti_stats; - - ifp = &sc->arpcom.ac_if; - - TI_RING_DMASYNC(sc, ti_info.ti_stats, BUS_DMASYNC_POSTREAD); - - ifp->if_collisions += stats->dot3StatsSingleCollisionFrames + - stats->dot3StatsMultipleCollisionFrames + - stats->dot3StatsExcessiveCollisions + - stats->dot3StatsLateCollisions - - ifp->if_collisions; - - TI_RING_DMASYNC(sc, ti_info.ti_stats, BUS_DMASYNC_PREREAD); -} - -/* - * Encapsulate an mbuf chain in the tx ring by coupling the mbuf data - * pointers to descriptors. - */ -int -ti_encap_tigon1(struct ti_softc *sc, struct mbuf *m_head, u_int32_t *txidx) -{ - u_int32_t frag, cur; - struct ti_txmap_entry *entry; - bus_dmamap_t txmap; - struct ti_tx_desc txdesc; - int i = 0; - - entry = SLIST_FIRST(&sc->ti_tx_map_listhead); - if (entry == NULL) - return (ENOBUFS); - txmap = entry->dmamap; - - cur = frag = *txidx; - - /* - * Start packing the mbufs in this chain into - * the fragment pointers. Stop when we run out - * of fragments or hit the end of the mbuf chain. - */ - if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, - BUS_DMA_NOWAIT)) - return (ENOBUFS); - - /* - * Sanity check: avoid coming within 16 descriptors - * of the end of the ring. - */ - if (txmap->dm_nsegs > (TI_TX_RING_CNT - sc->ti_txcnt - 16)) - goto fail_unload; - - for (i = 0; i < txmap->dm_nsegs; i++) { - if (sc->ti_cdata.ti_tx_chain[frag] != NULL) - break; - - memset(&txdesc, 0, sizeof(txdesc)); - - TI_HOSTADDR(txdesc.ti_addr) = txmap->dm_segs[i].ds_addr; - txdesc.ti_len = txmap->dm_segs[i].ds_len & 0xffff; - txdesc.ti_flags = 0; - txdesc.ti_vlan_tag = 0; - -#if NVLAN > 0 - if (m_head->m_flags & M_VLANTAG) { - txdesc.ti_flags |= TI_BDFLAG_VLAN_TAG; - txdesc.ti_vlan_tag = m_head->m_pkthdr.ether_vtag; - } -#endif - - ti_mem_write(sc, TI_TX_RING_BASE + frag * sizeof(txdesc), - sizeof(txdesc), (caddr_t)&txdesc); - - cur = frag; - TI_INC(frag, TI_TX_RING_CNT); - } - - if (frag == sc->ti_tx_saved_considx) - goto fail_unload; - - txdesc.ti_flags |= TI_BDFLAG_END; - ti_mem_write(sc, TI_TX_RING_BASE + cur * sizeof(txdesc), - sizeof(txdesc), (caddr_t)&txdesc); - - bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize, - BUS_DMASYNC_PREWRITE); - - sc->ti_cdata.ti_tx_chain[cur] = m_head; - SLIST_REMOVE_HEAD(&sc->ti_tx_map_listhead, link); - sc->ti_cdata.ti_tx_map[cur] = entry; - sc->ti_txcnt += txmap->dm_nsegs; - - *txidx = frag; - - return (0); - -fail_unload: - bus_dmamap_unload(sc->sc_dmatag, txmap); - - return (ENOBUFS); -} - -/* - * Encapsulate an mbuf chain in the tx ring by coupling the mbuf data - * pointers to descriptors. - */ -int -ti_encap_tigon2(struct ti_softc *sc, struct mbuf *m_head, u_int32_t *txidx) -{ - struct ti_tx_desc *f = NULL; - u_int32_t frag, cur; - struct ti_txmap_entry *entry; - bus_dmamap_t txmap; - int i = 0; - - entry = SLIST_FIRST(&sc->ti_tx_map_listhead); - if (entry == NULL) - return (ENOBUFS); - txmap = entry->dmamap; - - cur = frag = *txidx; - - /* - * Start packing the mbufs in this chain into - * the fragment pointers. Stop when we run out - * of fragments or hit the end of the mbuf chain. - */ - if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, - BUS_DMA_NOWAIT)) - return (ENOBUFS); - - /* - * Sanity check: avoid coming within 16 descriptors - * of the end of the ring. - */ - if (txmap->dm_nsegs > (TI_TX_RING_CNT - sc->ti_txcnt - 16)) - goto fail_unload; - - for (i = 0; i < txmap->dm_nsegs; i++) { - f = &sc->ti_rdata->ti_tx_ring[frag]; - - if (sc->ti_cdata.ti_tx_chain[frag] != NULL) - break; - - TI_HOSTADDR(f->ti_addr) = txmap->dm_segs[i].ds_addr; - f->ti_len = txmap->dm_segs[i].ds_len & 0xffff; - f->ti_flags = 0; - f->ti_vlan_tag = 0; - -#if NVLAN > 0 - if (m_head->m_flags & M_VLANTAG) { - f->ti_flags |= TI_BDFLAG_VLAN_TAG; - f->ti_vlan_tag = m_head->m_pkthdr.ether_vtag; - } -#endif - - cur = frag; - TI_INC(frag, TI_TX_RING_CNT); - } - - if (frag == sc->ti_tx_saved_considx) - goto fail_unload; - - sc->ti_rdata->ti_tx_ring[cur].ti_flags |= TI_BDFLAG_END; - - bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize, - BUS_DMASYNC_PREWRITE); - - TI_RING_DMASYNC(sc, ti_tx_ring[cur], BUS_DMASYNC_POSTREAD); - - sc->ti_cdata.ti_tx_chain[cur] = m_head; - SLIST_REMOVE_HEAD(&sc->ti_tx_map_listhead, link); - sc->ti_cdata.ti_tx_map[cur] = entry; - sc->ti_txcnt += txmap->dm_nsegs; - - *txidx = frag; - - return (0); - -fail_unload: - bus_dmamap_unload(sc->sc_dmatag, txmap); - - return (ENOBUFS); -} - -/* - * Main transmit routine. To avoid having to do mbuf copies, we put pointers - * to the mbuf data regions directly in the transmit descriptors. - */ -void -ti_start(struct ifnet *ifp) -{ - struct ti_softc *sc; - struct mbuf *m_head = NULL; - u_int32_t prodidx; - int pkts = 0, error; - - sc = ifp->if_softc; - - prodidx = sc->ti_tx_saved_prodidx; - - while(sc->ti_cdata.ti_tx_chain[prodidx] == NULL) { - IFQ_POLL(&ifp->if_snd, m_head); - if (m_head == NULL) - break; - - /* - * Pack the data into the transmit ring. If we - * don't have room, set the OACTIVE flag and wait - * for the NIC to drain the ring. - */ - if (sc->ti_hwrev == TI_HWREV_TIGON) - error = ti_encap_tigon1(sc, m_head, &prodidx); - else - error = ti_encap_tigon2(sc, m_head, &prodidx); - - if (error) { - ifp->if_flags |= IFF_OACTIVE; - break; - } - - /* now we are committed to transmit the packet */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); - pkts++; - - /* - * If there's a BPF listener, bounce a copy of this frame - * to him. - */ -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap_ether(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); -#endif - } - if (pkts == 0) - return; - - /* Transmit */ - sc->ti_tx_saved_prodidx = prodidx; - CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, prodidx); - - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; -} - -void -ti_init(void *xsc) -{ - struct ti_softc *sc = xsc; - int s; - - s = splnet(); - - /* Cancel pending I/O and flush buffers. */ - ti_stop(sc); - - /* Init the gen info block, ring control blocks and firmware. */ - if (ti_gibinit(sc)) { - printf("%s: initialization failure\n", sc->sc_dv.dv_xname); - splx(s); - return; - } - - splx(s); -} - -void -ti_init2(struct ti_softc *sc) -{ - struct ti_cmd_desc cmd; - struct ifnet *ifp; - u_int16_t *m; - struct ifmedia *ifm; - int tmp; - - ifp = &sc->arpcom.ac_if; - - /* Specify MTU and interface index. */ - CSR_WRITE_4(sc, TI_GCR_IFINDEX, sc->sc_dv.dv_unit); - CSR_WRITE_4(sc, TI_GCR_IFMTU, - TI_JUMBO_FRAMELEN + ETHER_VLAN_ENCAP_LEN); - TI_DO_CMD(TI_CMD_UPDATE_GENCOM, 0, 0); - - /* Load our MAC address. */ - m = (u_int16_t *)&sc->arpcom.ac_enaddr[0]; - CSR_WRITE_4(sc, TI_GCR_PAR0, htons(m[0])); - CSR_WRITE_4(sc, TI_GCR_PAR1, (htons(m[1]) << 16) | htons(m[2])); - TI_DO_CMD(TI_CMD_SET_MAC_ADDR, 0, 0); - - /* Enable or disable promiscuous mode as needed. */ - if (ifp->if_flags & IFF_PROMISC) { - TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, TI_CMD_CODE_PROMISC_ENB, 0); - } else { - TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, TI_CMD_CODE_PROMISC_DIS, 0); - } - - /* Program multicast filter. */ - ti_setmulti(sc); - - /* - * If this is a Tigon 1, we should tell the - * firmware to use software packet filtering. - */ - if (sc->ti_hwrev == TI_HWREV_TIGON) { - TI_DO_CMD(TI_CMD_FDR_FILTERING, TI_CMD_CODE_FILT_ENB, 0); - } - - /* Init RX ring. */ - if (ti_init_rx_ring_std(sc) == ENOBUFS) - panic("not enough mbufs for rx ring"); - - /* Init jumbo RX ring. */ - ti_init_rx_ring_jumbo(sc); - - /* - * If this is a Tigon 2, we can also configure the - * mini ring. - */ - if (sc->ti_hwrev == TI_HWREV_TIGON_II) - ti_init_rx_ring_mini(sc); - - CSR_WRITE_4(sc, TI_GCR_RXRETURNCONS_IDX, 0); - sc->ti_rx_saved_considx = 0; - - /* Init TX ring. */ - ti_init_tx_ring(sc); - - /* Tell firmware we're alive. */ - TI_DO_CMD(TI_CMD_HOST_STATE, TI_CMD_CODE_STACK_UP, 0); - - /* Enable host interrupts. */ - CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0); - - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - - /* - * Make sure to set media properly. We have to do this - * here since we have to issue commands in order to set - * the link negotiation and we can't issue commands until - * the firmware is running. - */ - ifm = &sc->ifmedia; - tmp = ifm->ifm_media; - ifm->ifm_media = ifm->ifm_cur->ifm_media; - ti_ifmedia_upd(ifp); - ifm->ifm_media = tmp; -} - -/* - * Set media options. - */ -int -ti_ifmedia_upd(struct ifnet *ifp) -{ - struct ti_softc *sc; - struct ifmedia *ifm; - struct ti_cmd_desc cmd; - - sc = ifp->if_softc; - ifm = &sc->ifmedia; - - if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) - return(EINVAL); - - switch(IFM_SUBTYPE(ifm->ifm_media)) { - case IFM_AUTO: - CSR_WRITE_4(sc, TI_GCR_GLINK, TI_GLNK_PREF|TI_GLNK_1000MB| - TI_GLNK_FULL_DUPLEX|TI_GLNK_RX_FLOWCTL_Y| - TI_GLNK_AUTONEGENB|TI_GLNK_ENB); - CSR_WRITE_4(sc, TI_GCR_LINK, TI_LNK_100MB|TI_LNK_10MB| - TI_LNK_FULL_DUPLEX|TI_LNK_HALF_DUPLEX| - TI_LNK_AUTONEGENB|TI_LNK_ENB); - TI_DO_CMD(TI_CMD_LINK_NEGOTIATION, - TI_CMD_CODE_NEGOTIATE_BOTH, 0); - break; - case IFM_1000_SX: - case IFM_1000_T: - CSR_WRITE_4(sc, TI_GCR_GLINK, TI_GLNK_PREF|TI_GLNK_1000MB| - TI_GLNK_RX_FLOWCTL_Y|TI_GLNK_ENB); - CSR_WRITE_4(sc, TI_GCR_LINK, 0); - if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) { - TI_SETBIT(sc, TI_GCR_GLINK, TI_GLNK_FULL_DUPLEX); - } - TI_DO_CMD(TI_CMD_LINK_NEGOTIATION, - TI_CMD_CODE_NEGOTIATE_GIGABIT, 0); - break; - case IFM_100_FX: - case IFM_10_FL: - case IFM_100_TX: - case IFM_10_T: - CSR_WRITE_4(sc, TI_GCR_GLINK, 0); - CSR_WRITE_4(sc, TI_GCR_LINK, TI_LNK_ENB|TI_LNK_PREF); - if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_FX || - IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) { - TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_100MB); - } else { - TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_10MB); - } - if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) { - TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_FULL_DUPLEX); - } else { - TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_HALF_DUPLEX); - } - TI_DO_CMD(TI_CMD_LINK_NEGOTIATION, - TI_CMD_CODE_NEGOTIATE_10_100, 0); - break; - } - - return (0); -} - -/* - * Report current media status. - */ -void -ti_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct ti_softc *sc; - u_int32_t media = 0; - - sc = ifp->if_softc; - - ifmr->ifm_status = IFM_AVALID; - ifmr->ifm_active = IFM_ETHER; - - if (sc->ti_linkstat == TI_EV_CODE_LINK_DOWN) { - ifmr->ifm_active |= IFM_NONE; - return; - } - - ifmr->ifm_status |= IFM_ACTIVE; - - if (sc->ti_linkstat == TI_EV_CODE_GIG_LINK_UP) { - media = CSR_READ_4(sc, TI_GCR_GLINK_STAT); - if (sc->ti_copper) - ifmr->ifm_active |= IFM_1000_T; - else - ifmr->ifm_active |= IFM_1000_SX; - if (media & TI_GLNK_FULL_DUPLEX) - ifmr->ifm_active |= IFM_FDX; - else - ifmr->ifm_active |= IFM_HDX; - } else if (sc->ti_linkstat == TI_EV_CODE_LINK_UP) { - media = CSR_READ_4(sc, TI_GCR_LINK_STAT); - if (sc->ti_copper) { - if (media & TI_LNK_100MB) - ifmr->ifm_active |= IFM_100_TX; - if (media & TI_LNK_10MB) - ifmr->ifm_active |= IFM_10_T; - } else { - if (media & TI_LNK_100MB) - ifmr->ifm_active |= IFM_100_FX; - if (media & TI_LNK_10MB) - ifmr->ifm_active |= IFM_10_FL; - } - if (media & TI_LNK_FULL_DUPLEX) - ifmr->ifm_active |= IFM_FDX; - if (media & TI_LNK_HALF_DUPLEX) - ifmr->ifm_active |= IFM_HDX; - } -} - -int -ti_ioctl(struct ifnet *ifp, u_long command, caddr_t data) -{ - struct ti_softc *sc = ifp->if_softc; - struct ifaddr *ifa = (struct ifaddr *)data; - struct ifreq *ifr = (struct ifreq *)data; - int s, error = 0; - struct ti_cmd_desc cmd; - - s = splnet(); - - switch(command) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - if ((ifp->if_flags & IFF_RUNNING) == 0) - ti_init(sc); -#ifdef INET - if (ifa->ifa_addr->sa_family == AF_INET) - arp_ifinit(&sc->arpcom, ifa); -#endif /* INET */ - break; - - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - /* - * If only the state of the PROMISC flag changed, - * then just use the 'set promisc mode' command - * instead of reinitializing the entire NIC. Doing - * a full re-init means reloading the firmware and - * waiting for it to start up, which may take a - * second or two. - */ - if (ifp->if_flags & IFF_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->ti_if_flags & IFF_PROMISC)) { - TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, - TI_CMD_CODE_PROMISC_ENB, 0); - } else if (ifp->if_flags & IFF_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->ti_if_flags & IFF_PROMISC) { - TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, - TI_CMD_CODE_PROMISC_DIS, 0); - } else { - if ((ifp->if_flags & IFF_RUNNING) == 0) - ti_init(sc); - } - } else { - if (ifp->if_flags & IFF_RUNNING) - ti_stop(sc); - } - sc->ti_if_flags = ifp->if_flags; - break; - - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); - break; - - default: - error = ether_ioctl(ifp, &sc->arpcom, command, data); - } - - if (error == ENETRESET) { - if (ifp->if_flags & IFF_RUNNING) - ti_setmulti(sc); - error = 0; - } - - splx(s); - return (error); -} - -void -ti_watchdog(struct ifnet *ifp) -{ - struct ti_softc *sc; - - sc = ifp->if_softc; - - printf("%s: watchdog timeout -- resetting\n", sc->sc_dv.dv_xname); - ti_stop(sc); - ti_init(sc); - - ifp->if_oerrors++; -} - -/* - * Stop the adapter and free any mbufs allocated to the - * RX and TX lists. - */ -void -ti_stop(struct ti_softc *sc) -{ - struct ifnet *ifp; - struct ti_cmd_desc cmd; - - ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - - /* Disable host interrupts. */ - CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1); - /* - * Tell firmware we're shutting down. - */ - TI_DO_CMD(TI_CMD_HOST_STATE, TI_CMD_CODE_STACK_DOWN, 0); - - /* Halt and reinitialize. */ - ti_chipinit(sc); - ti_mem_set(sc, 0x2000, 0x100000 - 0x2000); - ti_chipinit(sc); - - /* Free the RX lists. */ - ti_free_rx_ring_std(sc); - - /* Free jumbo RX list. */ - ti_free_rx_ring_jumbo(sc); - - /* Free mini RX list. */ - ti_free_rx_ring_mini(sc); - - /* Free TX buffers. */ - ti_free_tx_ring(sc); - - sc->ti_ev_prodidx.ti_idx = 0; - sc->ti_return_prodidx.ti_idx = 0; - sc->ti_tx_considx.ti_idx = 0; - sc->ti_tx_saved_considx = TI_TXCONS_UNSET; -} - -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -void -ti_shutdown(void *xsc) -{ - struct ti_softc *sc; - - sc = xsc; - - ti_chipinit(sc); -} diff --git a/sys/dev/pci/if_ti_pci.c b/sys/dev/pci/if_ti_pci.c new file mode 100644 index 00000000000..12260f686a3 --- /dev/null +++ b/sys/dev/pci/if_ti_pci.c @@ -0,0 +1,181 @@ +/* $OpenBSD: if_ti_pci.c,v 1.1 2009/08/29 21:12:55 kettenis Exp $ */ + +/* + * Copyright (c) 1997, 1998, 1999 + * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/pci/if_ti.c,v 1.25 2000/01/18 00:26:29 wpaul Exp $ + */ + +/* + * Alteon Networks Tigon PCI gigabit ethernet driver for OpenBSD. + * + * Written by Bill Paul <wpaul@ctr.columbia.edu> + * Electrical Engineering Department + * Columbia University, New York City + */ + +/* + * The Alteon Networks Tigon chip contains an embedded R4000 CPU, + * gigabit MAC, dual DMA channels and a PCI interface unit. NICs + * using the Tigon may have anywhere from 512K to 2MB of SRAM. The + * Tigon supports hardware IP, TCP and UCP checksumming, multicast + * filtering and jumbo (9014 byte) frames. The hardware is largely + * controlled by firmware, which must be loaded into the NIC during + * initialization. + * + * The Tigon 2 contains 2 R4000 CPUs and requires a newer firmware + * revision, which supports new features such as extended commands, + * extended jumbo receive ring desciptors and a mini receive ring. + * + * Alteon Networks is to be commended for releasing such a vast amount + * of development material for the Tigon NIC without requiring an NDA + * (although they really should have done it a long time ago). With + * any luck, the other vendors will finally wise up and follow Alteon's + * stellar example. + * + * The following people deserve special thanks: + * - Terry Murphy of 3Com, for providing a 3c985 Tigon 1 board + * for testing + * - Raymond Lee of Netgear, for providing a pair of Netgear + * GA620 Tigon 2 boards for testing + * - Ulf Zimmermann, for bringing the GA260 to my attention and + * convincing me to write this driver. + * - Andrew Gallatin for providing FreeBSD/Alpha support. + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/socket.h> +#include <sys/systm.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_media.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/if_ether.h> +#endif + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <dev/ic/tireg.h> +#include <dev/ic/tivar.h> + +int ti_pci_match(struct device *, void *, void *); +void ti_pci_attach(struct device *, struct device *, void *); + +struct cfattach ti_pci_ca = { + sizeof(struct ti_softc), ti_pci_match, ti_pci_attach +}; + +const struct pci_matchid ti_devices[] = { + { PCI_VENDOR_NETGEAR, PCI_PRODUCT_NETGEAR_GA620 }, + { PCI_VENDOR_NETGEAR, PCI_PRODUCT_NETGEAR_GA620T }, + { PCI_VENDOR_ALTEON, PCI_PRODUCT_ALTEON_ACENIC }, + { PCI_VENDOR_ALTEON, PCI_PRODUCT_ALTEON_ACENICT }, + { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C985 }, + { PCI_VENDOR_SGI, PCI_PRODUCT_SGI_TIGON }, + { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_PN9000SX } +}; + +int +ti_pci_match(struct device *parent, void *match, void *aux) +{ + return (pci_matchbyid(aux, ti_devices, nitems(ti_devices))); +} + +void +ti_pci_attach(struct device *parent, struct device *self, void *aux) +{ + struct ti_softc *sc = (struct ti_softc *)self; + struct pci_attach_args *pa = aux; + pci_chipset_tag_t pc = pa->pa_pc; + pci_intr_handle_t ih; + const char *intrstr = NULL; + bus_size_t size; + + /* + * Map control/status registers. + */ + if (pci_mapreg_map(pa, TI_PCI_LOMEM, + PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, + &sc->ti_btag, &sc->ti_bhandle, NULL, &size, 0)) { + printf(": can't map registers\n"); + return; + } + + sc->sc_dmatag = pa->pa_dmat; + + if (pci_intr_map(pa, &ih)) { + printf(": can't map interrupt\n"); + goto unmap; + } + intrstr = pci_intr_string(pc, ih); + sc->ti_intrhand = pci_intr_establish(pc, ih, IPL_NET, ti_intr, sc, + self->dv_xname); + if (sc->ti_intrhand == NULL) { + printf(": can't establish interrupt"); + if (intrstr != NULL) + printf(" at %s", intrstr); + printf("\n"); + goto unmap; + } + printf(": %s", intrstr); + + /* + * We really need a better way to tell a 1000baseTX card + * from a 1000baseSX one, since in theory there could be + * OEMed 1000baseTX cards from lame vendors who aren't + * clever enough to change the PCI ID. For the moment + * though, the AceNIC is the only copper card available. + */ + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALTEON && + PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALTEON_ACENICT) + sc->ti_copper = 1; + /* Ok, it's not the only copper card available */ + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NETGEAR && + PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NETGEAR_GA620T) + sc->ti_copper = 1; + + if (ti_attach(sc) == 0) + return; + + pci_intr_disestablish(pc, sc->ti_intrhand); + +unmap: + bus_space_unmap(sc->ti_btag, sc->ti_bhandle, size); +} diff --git a/sys/dev/pci/if_tireg.h b/sys/dev/pci/if_tireg.h deleted file mode 100644 index c76b1a99fb0..00000000000 --- a/sys/dev/pci/if_tireg.h +++ /dev/null @@ -1,1175 +0,0 @@ -/* $OpenBSD: if_tireg.h,v 1.25 2006/08/16 02:37:00 brad Exp $ */ - -/* - * Copyright (c) 1997, 1998, 1999 - * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/pci/if_tireg.h,v 1.12 2000/01/18 00:26:29 wpaul Exp $ - */ - -/* - * Tigon register offsets. These are memory mapped registers - * which can be accessed with the CSR_READ_4()/CSR_WRITE_4() macros. - * Each register must be accessed using 32 bit operations. - * - * All reegisters are accessed through a 16K shared memory block. - * The first group of registers are actually copies of the PCI - * configuration space registers. - */ - -#define TI_PCI_ID PCI_ID_REG /* PCI device/vendor ID */ -#define TI_PCI_CMDSTAT PCI_COMMAND_STATUS_REG -#define TI_PCI_CLASSCODE PCI_CLASS_REG -#define TI_PCI_BIST PCI_BHLC_REG -#define TI_PCI_LOMEM PCI_MAPS /* Shared memory base address */ -#define TI_PCI_SUBSYS PCI_SUBVEND_0 -#define TI_PCI_ROMBASE 0x030 -#define TI_PCI_INT PCI_INTLINE - -/* - * Tigon configuration and control registers. - */ -#define TI_MISC_HOST_CTL 0x040 -#define TI_MISC_LOCAL_CTL 0x044 -#define TI_SEM_AB 0x048 /* Tigon 2 only */ -#define TI_MISC_CONF 0x050 /* Tigon 2 only */ -#define TI_TIMER_BITS 0x054 -#define TI_TIMERREF 0x058 -#define TI_PCI_STATE 0x05C -#define TI_MAIN_EVENT_A 0x060 -#define TI_MAILBOX_EVENT_A 0x064 -#define TI_WINBASE 0x068 -#define TI_WINDATA 0x06C -#define TI_MAIN_EVENT_B 0x070 /* Tigon 2 only */ -#define TI_MAILBOX_EVENT_B 0x074 /* Tigon 2 only */ -#define TI_TIMERREF_B 0x078 /* Tigon 2 only */ -#define TI_SERIAL 0x07C - -/* - * Misc host control bits. - */ -#define TI_MHC_INTSTATE 0x00000001 -#define TI_MHC_CLEARINT 0x00000002 -#define TI_MHC_RESET 0x00000008 -#define TI_MHC_BYTE_SWAP_ENB 0x00000010 -#define TI_MHC_WORD_SWAP_ENB 0x00000020 -#define TI_MHC_MASK_INTS 0x00000040 -#define TI_MHC_CHIP_REV_MASK 0xF0000000 - -#define TI_MHC_BIGENDIAN_INIT \ - (TI_MHC_BYTE_SWAP_ENB|TI_MHC_WORD_SWAP_ENB|TI_MHC_CLEARINT) - -#define TI_MHC_LITTLEENDIAN_INIT \ - (TI_MHC_WORD_SWAP_ENB|TI_MHC_CLEARINT) - -/* - * Tigon chip rev values. Rev 4 is the Tigon 1. Rev 6 is the Tigon 2. - * Rev 5 is also the Tigon 2, but is a broken version which was never - * used in any actual hardware, so we ignore it. - */ -#define TI_REV_TIGON_I 0x40000000 -#define TI_REV_TIGON_II 0x60000000 - -/* - * Firmware revision that we want. - */ -#define TI_FIRMWARE_MAJOR 0xc -#define TI_FIRMWARE_MINOR 0x4 -#define TI_FIRMWARE_FIX 0xd - -/* - * Miscelaneous Local Control register. - */ -#define TI_MLC_EE_WRITE_ENB 0x00000010 -#define TI_MLC_SRAM_BANK_SIZE 0x00000300 /* Tigon 2 only */ -#define TI_MLC_LOCALADDR_21 0x00004000 -#define TI_MLC_LOCALADDR_22 0x00008000 -#define TI_MLC_SBUS_WRITEERR 0x00080000 -#define TI_MLC_EE_CLK 0x00100000 -#define TI_MLC_EE_TXEN 0x00200000 -#define TI_MLC_EE_DOUT 0x00400000 -#define TI_MLC_EE_DIN 0x00800000 - -/* Possible memory sizes. */ -#define TI_MLC_SRAM_BANK_DISA 0x00000000 -#define TI_MLC_SRAM_BANK_1024K 0x00000100 -#define TI_MLC_SRAM_BANK_512K 0x00000200 -#define TI_MLC_SRAM_BANK_256K 0x00000300 - -/* - * Offset of MAC address inside EEPROM. - */ -#define TI_EE_MAC_OFFSET 0x8c - -#define TI_DMA_ASSIST 0x11C -#define TI_CPU_STATE 0x140 -#define TI_CPU_PROGRAM_COUNTER 0x144 -#define TI_SRAM_ADDR 0x154 -#define TI_SRAM_DATA 0x158 -#define TI_GEN_0 0x180 -#define TI_GEN_X 0x1FC -#define TI_MAC_TX_STATE 0x200 -#define TI_MAC_RX_STATE 0x220 -#define TI_CPU_CTL_B 0x240 /* Tigon 2 only */ -#define TI_CPU_PROGRAM_COUNTER_B 0x244 /* Tigon 2 only */ -#define TI_SRAM_ADDR_B 0x254 /* Tigon 2 only */ -#define TI_SRAM_DATA_B 0x258 /* Tigon 2 only */ -#define TI_GEN_B_0 0x280 /* Tigon 2 only */ -#define TI_GEN_B_X 0x2FC /* Tigon 2 only */ - -/* - * Misc config register. - */ -#define TI_MCR_SRAM_SYNCHRONOUS 0x00100000 /* Tigon 2 only */ - -/* - * PCI state register. - */ -#define TI_PCISTATE_FORCE_RESET 0x00000001 -#define TI_PCISTATE_PROVIDE_LEN 0x00000002 -#define TI_PCISTATE_READ_MAXDMA 0x0000001C -#define TI_PCISTATE_WRITE_MAXDMA 0x000000E0 -#define TI_PCISTATE_MINDMA 0x0000FF00 -#define TI_PCISTATE_FIFO_RETRY_ENB 0x00010000 -#define TI_PCISTATE_USE_MEM_RD_MULT 0x00020000 -#define TI_PCISTATE_NO_SWAP_READ_DMA 0x00040000 -#define TI_PCISTATE_NO_SWAP_WRITE_DMA 0x00080000 -#define TI_PCISTATE_66MHZ_BUS 0x00080000 /* Tigon 2 only */ -#define TI_PCISTATE_32BIT_BUS 0x00100000 /* Tigon 2 only */ -#define TI_PCISTATE_ENB_BYTE_ENABLES 0x00800000 /* Tigon 2 only */ -#define TI_PCISTATE_READ_CMD 0x0F000000 -#define TI_PCISTATE_WRITE_CMD 0xF0000000 - -#define TI_PCI_READMAX_4 0x04 -#define TI_PCI_READMAX_16 0x08 -#define TI_PCI_READMAX_32 0x0C -#define TI_PCI_READMAX_64 0x10 -#define TI_PCI_READMAX_128 0x14 -#define TI_PCI_READMAX_256 0x18 -#define TI_PCI_READMAX_1024 0x1C - -#define TI_PCI_WRITEMAX_4 0x20 -#define TI_PCI_WRITEMAX_16 0x40 -#define TI_PCI_WRITEMAX_32 0x60 -#define TI_PCI_WRITEMAX_64 0x80 -#define TI_PCI_WRITEMAX_128 0xA0 -#define TI_PCI_WRITEMAX_256 0xC0 -#define TI_PCI_WRITEMAX_1024 0xE0 - -#define TI_PCI_READ_CMD 0x06000000 -#define TI_PCI_WRITE_CMD 0x70000000 - -/* - * DMA state register. - */ -#define TI_DMASTATE_ENABLE 0x00000001 -#define TI_DMASTATE_PAUSE 0x00000002 - -/* - * CPU state register. - */ -#define TI_CPUSTATE_RESET 0x00000001 -#define TI_CPUSTATE_STEP 0x00000002 -#define TI_CPUSTATE_ROMFAIL 0x00000010 -#define TI_CPUSTATE_HALT 0x00010000 -/* - * MAC TX state register - */ -#define TI_TXSTATE_RESET 0x00000001 -#define TI_TXSTATE_ENB 0x00000002 -#define TI_TXSTATE_STOP 0x00000004 - -/* - * MAC RX state register - */ -#define TI_RXSTATE_RESET 0x00000001 -#define TI_RXSTATE_ENB 0x00000002 -#define TI_RXSTATE_STOP 0x00000004 - -/* - * Tigon 2 mailbox registers. The mailbox area consists of 256 bytes - * split into 64 bit registers. Only the lower 32 bits of each mailbox - * are used. - */ -#define TI_MB_HOSTINTR_HI 0x500 -#define TI_MB_HOSTINTR_LO 0x504 -#define TI_MB_HOSTINTR TI_MB_HOSTINTR_LO -#define TI_MB_CMDPROD_IDX_HI 0x508 -#define TI_MB_CMDPROD_IDX_LO 0x50C -#define TI_MB_CMDPROD_IDX TI_MB_CMDPROD_IDX_LO -#define TI_MB_SENDPROD_IDX_HI 0x510 -#define TI_MB_SENDPROD_IDX_LO 0x514 -#define TI_MB_SENDPROD_IDX TI_MB_SENDPROD_IDX_LO -#define TI_MB_STDRXPROD_IDX_HI 0x518 /* Tigon 2 only */ -#define TI_MB_STDRXPROD_IDX_LO 0x51C /* Tigon 2 only */ -#define TI_MB_STDRXPROD_IDX TI_MB_STDRXPROD_IDX_LO -#define TI_MB_JUMBORXPROD_IDX_HI 0x520 /* Tigon 2 only */ -#define TI_MB_JUMBORXPROD_IDX_LO 0x524 /* Tigon 2 only */ -#define TI_MB_JUMBORXPROD_IDX TI_MB_JUMBORXPROD_IDX_LO -#define TI_MB_MINIRXPROD_IDX_HI 0x528 /* Tigon 2 only */ -#define TI_MB_MINIRXPROD_IDX_LO 0x52C /* Tigon 2 only */ -#define TI_MB_MINIRXPROD_IDX TI_MB_MINIRXPROD_IDX_LO -#define TI_MB_RSVD 0x530 - -/* - * Tigon 2 general communication registers. These are 64 and 32 bit - * registers which are only valid after the firmware has been - * loaded and started. They actually exist in NIC memory but are - * mapped into the host memory via the shared memory region. - * - * The NIC internally maps these registers starting at address 0, - * so to determine the NIC address of any of these registers, we - * subtract 0x600 (the address of the first register). - */ - -#define TI_GCR_BASE 0x600 -#define TI_GCR_MACADDR 0x600 -#define TI_GCR_PAR0 0x600 -#define TI_GCR_PAR1 0x604 -#define TI_GCR_GENINFO_HI 0x608 -#define TI_GCR_GENINFO_LO 0x60C -#define TI_GCR_MCASTADDR 0x610 /* obsolete */ -#define TI_GCR_MAR0 0x610 /* obsolete */ -#define TI_GCR_MAR1 0x614 /* obsolete */ -#define TI_GCR_OPMODE 0x618 -#define TI_GCR_DMA_READCFG 0x61C -#define TI_GCR_DMA_WRITECFG 0x620 -#define TI_GCR_TX_BUFFER_RATIO 0x624 -#define TI_GCR_EVENTCONS_IDX 0x628 -#define TI_GCR_CMDCONS_IDX 0x62C -#define TI_GCR_TUNEPARMS 0x630 -#define TI_GCR_RX_COAL_TICKS 0x630 -#define TI_GCR_TX_COAL_TICKS 0x634 -#define TI_GCR_STAT_TICKS 0x638 -#define TI_GCR_TX_MAX_COAL_BD 0x63C -#define TI_GCR_RX_MAX_COAL_BD 0x640 -#define TI_GCR_NIC_TRACING 0x644 -#define TI_GCR_GLINK 0x648 -#define TI_GCR_LINK 0x64C -#define TI_GCR_NICTRACE_PTR 0x650 -#define TI_GCR_NICTRACE_START 0x654 -#define TI_GCR_NICTRACE_LEN 0x658 -#define TI_GCR_IFINDEX 0x65C -#define TI_GCR_IFMTU 0x660 -#define TI_GCR_MASK_INTRS 0x664 -#define TI_GCR_GLINK_STAT 0x668 -#define TI_GCR_LINK_STAT 0x66C -#define TI_GCR_RXRETURNCONS_IDX 0x680 -#define TI_GCR_CMDRING 0x700 - -#define TI_GCR_NIC_ADDR(x) (x - TI_GCR_BASE) - -/* - * Local memory window. The local memory window is a 2K shared - * memory region which can be used to access the NIC's internal - * SRAM. The window can be mapped to a given 2K region using - * the TI_WINDOW_BASE register. - */ -#define TI_WINDOW 0x800 -#define TI_WINLEN 0x800 - -#define TI_TICKS_PER_SEC 1000000 - -/* - * Operation mode register. - */ -#define TI_OPMODE_BYTESWAP_BD 0x00000002 -#define TI_OPMODE_WORDSWAP_BD 0x00000004 -#define TI_OPMODE_WARN_ENB 0x00000008 /* not yet implemented */ -#define TI_OPMODE_BYTESWAP_DATA 0x00000010 -#define TI_OPMODE_1_DMA_ACTIVE 0x00000040 -#define TI_OPMODE_SBUS 0x00000100 -#define TI_OPMODE_DONT_FRAG_JUMBO 0x00000200 -#define TI_OPMODE_INCLUDE_CRC 0x00000400 -#define TI_OPMODE_RX_BADFRAMES 0x00000800 -#define TI_OPMODE_NO_EVENT_INTRS 0x00001000 -#define TI_OPMODE_NO_TX_INTRS 0x00002000 -#define TI_OPMODE_NO_RX_INTRS 0x00004000 -#define TI_OPMODE_FATAL_ENB 0x40000000 /* not yet implemented */ - -#if BYTE_ORDER == BIG_ENDIAN -#define TI_DMA_SWAP_OPTIONS \ - TI_OPMODE_BYTESWAP_DATA| \ - TI_OPMODE_BYTESWAP_BD|TI_OPMODE_WORDSWAP_BD -#else -#define TI_DMA_SWAP_OPTIONS \ - TI_OPMODE_BYTESWAP_DATA -#endif - -/* - * DMA configuration thresholds. - */ -#define TI_DMA_STATE_THRESH_16W 0x00000100 -#define TI_DMA_STATE_THRESH_8W 0x00000080 -#define TI_DMA_STATE_THRESH_4W 0x00000040 -#define TI_DMA_STATE_THRESH_2W 0x00000020 -#define TI_DMA_STATE_THRESH_1W 0x00000010 - -#define TI_DMA_STATE_FORCE_32_BIT 0x00000008 - -/* - * Gigabit link status bits. - */ -#define TI_GLNK_SENSE_NO_BEG 0x00002000 -#define TI_GLNK_LOOPBACK 0x00004000 -#define TI_GLNK_PREF 0x00008000 -#define TI_GLNK_1000MB 0x00040000 -#define TI_GLNK_FULL_DUPLEX 0x00080000 -#define TI_GLNK_TX_FLOWCTL_Y 0x00200000 /* Tigon 2 only */ -#define TI_GLNK_RX_FLOWCTL_Y 0x00800000 -#define TI_GLNK_AUTONEGENB 0x20000000 -#define TI_GLNK_ENB 0x40000000 - -/* - * Link status bits. - */ -#define TI_LNK_LOOPBACK 0x00004000 -#define TI_LNK_PREF 0x00008000 -#define TI_LNK_10MB 0x00010000 -#define TI_LNK_100MB 0x00020000 -#define TI_LNK_1000MB 0x00040000 -#define TI_LNK_FULL_DUPLEX 0x00080000 -#define TI_LNK_HALF_DUPLEX 0x00100000 -#define TI_LNK_TX_FLOWCTL_Y 0x00200000 /* Tigon 2 only */ -#define TI_LNK_RX_FLOWCTL_Y 0x00800000 -#define TI_LNK_AUTONEGENB 0x20000000 -#define TI_LNK_ENB 0x40000000 - -/* - * Ring size constants. - */ -#define TI_EVENT_RING_CNT 256 -#define TI_CMD_RING_CNT 64 -#define TI_STD_RX_RING_CNT 512 -#define TI_JUMBO_RX_RING_CNT 256 -#define TI_MINI_RX_RING_CNT 1024 -#define TI_RETURN_RING_CNT 2048 - -/* - * Possible TX ring sizes. - */ -#define TI_TX_RING_CNT_128 128 -#define TI_TX_RING_BASE_128 0x3800 - -#define TI_TX_RING_CNT_256 256 -#define TI_TX_RING_BASE_256 0x3000 - -#define TI_TX_RING_CNT_512 512 -#define TI_TX_RING_BASE_512 0x2000 - -#define TI_TX_RING_CNT TI_TX_RING_CNT_512 -#define TI_TX_RING_BASE TI_TX_RING_BASE_512 - -/* - * The Tigon can have up to 8MB of external SRAM, however the Tigon 1 - * is limited to 2MB total, and in general I think most adapters have - * around 1MB. We use this value for zeroing the NIC's SRAM, so to - * be safe we use the largest possible value (zeroing memory that - * isn't there doesn't hurt anything). - */ -#define TI_MEM_MAX 0x7FFFFF - -/* - * Even on the alpha, pci addresses are 32-bit quantities - */ - -typedef struct { - u_int32_t ti_addr_hi; - u_int32_t ti_addr_lo; -} ti_hostaddr; -#define TI_HOSTADDR(x) x.ti_addr_lo - -/* - * Ring control block structure. The rules for the max_len field - * are as follows: - * - * For the send ring, max_len indicates the number of entries in the - * ring (128, 256 or 512). - * - * For the standard receive ring, max_len indicates the threshold - * used to decide when a frame should be put in the jumbo receive ring - * instead of the standard one. - * - * For the mini ring, max_len indicates the size of the buffers in the - * ring. This is the value used to decide when a frame is small enough - * to be placed in the mini ring. - * - * For the return receive ring, max_len indicates the number of entries - * in the ring. It can be one of 2048, 1024 or 0 (which is the same as - * 2048 for backwards compatibility). The value 1024 can only be used - * if the mini ring is disabled. - */ -struct ti_rcb { - ti_hostaddr ti_hostaddr; -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_max_len; - u_int16_t ti_flags; -#else - u_int16_t ti_flags; - u_int16_t ti_max_len; -#endif - u_int32_t ti_unused; -}; - -#define TI_RCB_FLAG_TCP_UDP_CKSUM 0x00000001 -#define TI_RCB_FLAG_IP_CKSUM 0x00000002 -#define TI_RCB_FLAG_NO_PHDR_CKSUM 0x00000008 -#define TI_RCB_FLAG_VLAN_ASSIST 0x00000010 -#define TI_RCB_FLAG_COAL_UPD_ONLY 0x00000020 -#define TI_RCB_FLAG_HOST_RING 0x00000040 -#define TI_RCB_FLAG_IEEE_SNAP_CKSUM 0x00000080 -#define TI_RCB_FLAG_USE_EXT_RX_BD 0x00000100 -#define TI_RCB_FLAG_RING_DISABLED 0x00000200 - -struct ti_producer { - u_int32_t ti_idx; - u_int32_t ti_unused; -}; - -/* - * Tigon statistics counters. - */ -struct ti_stats { - /* - * MAC stats, taken from RFC 1643, ethernet-like MIB - */ - volatile u_int32_t dot3StatsAlignmentErrors; /* 0 */ - volatile u_int32_t dot3StatsFCSErrors; /* 1 */ - volatile u_int32_t dot3StatsSingleCollisionFrames; /* 2 */ - volatile u_int32_t dot3StatsMultipleCollisionFrames; /* 3 */ - volatile u_int32_t dot3StatsSQETestErrors; /* 4 */ - volatile u_int32_t dot3StatsDeferredTransmissions; /* 5 */ - volatile u_int32_t dot3StatsLateCollisions; /* 6 */ - volatile u_int32_t dot3StatsExcessiveCollisions; /* 7 */ - volatile u_int32_t dot3StatsInternalMacTransmitErrors; /* 8 */ - volatile u_int32_t dot3StatsCarrierSenseErrors; /* 9 */ - volatile u_int32_t dot3StatsFrameTooLongs; /* 10 */ - volatile u_int32_t dot3StatsInternalMacReceiveErrors; /* 11 */ - /* - * interface stats, taken from RFC 1213, MIB-II, interfaces group - */ - volatile u_int32_t ifIndex; /* 12 */ - volatile u_int32_t ifType; /* 13 */ - volatile u_int32_t ifMtu; /* 14 */ - volatile u_int32_t ifSpeed; /* 15 */ - volatile u_int32_t ifAdminStatus; /* 16 */ -#define IF_ADMIN_STATUS_UP 1 -#define IF_ADMIN_STATUS_DOWN 2 -#define IF_ADMIN_STATUS_TESTING 3 - volatile u_int32_t ifOperStatus; /* 17 */ -#define IF_OPER_STATUS_UP 1 -#define IF_OPER_STATUS_DOWN 2 -#define IF_OPER_STATUS_TESTING 3 -#define IF_OPER_STATUS_UNKNOWN 4 -#define IF_OPER_STATUS_DORMANT 5 - volatile u_int32_t ifLastChange; /* 18 */ - volatile u_int32_t ifInDiscards; /* 19 */ - volatile u_int32_t ifInErrors; /* 20 */ - volatile u_int32_t ifInUnknownProtos; /* 21 */ - volatile u_int32_t ifOutDiscards; /* 22 */ - volatile u_int32_t ifOutErrors; /* 23 */ - volatile u_int32_t ifOutQLen; /* deprecated */ /* 24 */ - volatile u_int8_t ifPhysAddress[8]; /* 8 bytes */ /* 25 - 26 */ - volatile u_int8_t ifDescr[32]; /* 27 - 34 */ - u_int32_t alignIt; /* align to 64 bit for u_int64_ts following */ - /* - * more interface stats, taken from RFC 1573, MIB-IIupdate, - * interfaces group - */ - volatile u_int64_t ifHCInOctets; /* 36 - 37 */ - volatile u_int64_t ifHCInUcastPkts; /* 38 - 39 */ - volatile u_int64_t ifHCInMulticastPkts; /* 40 - 41 */ - volatile u_int64_t ifHCInBroadcastPkts; /* 42 - 43 */ - volatile u_int64_t ifHCOutOctets; /* 44 - 45 */ - volatile u_int64_t ifHCOutUcastPkts; /* 46 - 47 */ - volatile u_int64_t ifHCOutMulticastPkts; /* 48 - 49 */ - volatile u_int64_t ifHCOutBroadcastPkts; /* 50 - 51 */ - volatile u_int32_t ifLinkUpDownTrapEnable; /* 52 */ - volatile u_int32_t ifHighSpeed; /* 53 */ - volatile u_int32_t ifPromiscuousMode; /* 54 */ - volatile u_int32_t ifConnectorPresent; /* follow link state 55 */ - /* - * Host Commands - */ - volatile u_int32_t nicCmdsHostState; /* 56 */ - volatile u_int32_t nicCmdsFDRFiltering; /* 57 */ - volatile u_int32_t nicCmdsSetRecvProdIndex; /* 58 */ - volatile u_int32_t nicCmdsUpdateGencommStats; /* 59 */ - volatile u_int32_t nicCmdsResetJumboRing; /* 60 */ - volatile u_int32_t nicCmdsAddMCastAddr; /* 61 */ - volatile u_int32_t nicCmdsDelMCastAddr; /* 62 */ - volatile u_int32_t nicCmdsSetPromiscMode; /* 63 */ - volatile u_int32_t nicCmdsLinkNegotiate; /* 64 */ - volatile u_int32_t nicCmdsSetMACAddr; /* 65 */ - volatile u_int32_t nicCmdsClearProfile; /* 66 */ - volatile u_int32_t nicCmdsSetMulticastMode; /* 67 */ - volatile u_int32_t nicCmdsClearStats; /* 68 */ - volatile u_int32_t nicCmdsSetRecvJumboProdIndex; /* 69 */ - volatile u_int32_t nicCmdsSetRecvMiniProdIndex; /* 70 */ - volatile u_int32_t nicCmdsRefreshStats; /* 71 */ - volatile u_int32_t nicCmdsUnknown; /* 72 */ - /* - * NIC Events - */ - volatile u_int32_t nicEventsNICFirmwareOperational; /* 73 */ - volatile u_int32_t nicEventsStatsUpdated; /* 74 */ - volatile u_int32_t nicEventsLinkStateChanged; /* 75 */ - volatile u_int32_t nicEventsError; /* 76 */ - volatile u_int32_t nicEventsMCastListUpdated; /* 77 */ - volatile u_int32_t nicEventsResetJumboRing; /* 78 */ - /* - * Ring manipulation - */ - volatile u_int32_t nicRingSetSendProdIndex; /* 79 */ - volatile u_int32_t nicRingSetSendConsIndex; /* 80 */ - volatile u_int32_t nicRingSetRecvReturnProdIndex; /* 81 */ - /* - * Interrupts - */ - volatile u_int32_t nicInterrupts; /* 82 */ - volatile u_int32_t nicAvoidedInterrupts; /* 83 */ - /* - * BD Coalessing Thresholds - */ - volatile u_int32_t nicEventThresholdHit; /* 84 */ - volatile u_int32_t nicSendThresholdHit; /* 85 */ - volatile u_int32_t nicRecvThresholdHit; /* 86 */ - /* - * DMA Attentions - */ - volatile u_int32_t nicDmaRdOverrun; /* 87 */ - volatile u_int32_t nicDmaRdUnderrun; /* 88 */ - volatile u_int32_t nicDmaWrOverrun; /* 89 */ - volatile u_int32_t nicDmaWrUnderrun; /* 90 */ - volatile u_int32_t nicDmaWrMasterAborts; /* 91 */ - volatile u_int32_t nicDmaRdMasterAborts; /* 92 */ - /* - * NIC Resources - */ - volatile u_int32_t nicDmaWriteRingFull; /* 93 */ - volatile u_int32_t nicDmaReadRingFull; /* 94 */ - volatile u_int32_t nicEventRingFull; /* 95 */ - volatile u_int32_t nicEventProducerRingFull; /* 96 */ - volatile u_int32_t nicTxMacDescrRingFull; /* 97 */ - volatile u_int32_t nicOutOfTxBufSpaceFrameRetry; /* 98 */ - volatile u_int32_t nicNoMoreWrDMADescriptors; /* 99 */ - volatile u_int32_t nicNoMoreRxBDs; /* 100 */ - volatile u_int32_t nicNoSpaceInReturnRing; /* 101 */ - volatile u_int32_t nicSendBDs; /* current count 102 */ - volatile u_int32_t nicRecvBDs; /* current count 103 */ - volatile u_int32_t nicJumboRecvBDs; /* current count 104 */ - volatile u_int32_t nicMiniRecvBDs; /* current count 105 */ - volatile u_int32_t nicTotalRecvBDs; /* current count 106 */ - volatile u_int32_t nicTotalSendBDs; /* current count 107 */ - volatile u_int32_t nicJumboSpillOver; /* 108 */ - volatile u_int32_t nicSbusHangCleared; /* 109 */ - volatile u_int32_t nicEnqEventDelayed; /* 110 */ - /* - * Stats from MAC rx completion - */ - volatile u_int32_t nicMacRxLateColls; /* 111 */ - volatile u_int32_t nicMacRxLinkLostDuringPkt; /* 112 */ - volatile u_int32_t nicMacRxPhyDecodeErr; /* 113 */ - volatile u_int32_t nicMacRxMacAbort; /* 114 */ - volatile u_int32_t nicMacRxTruncNoResources; /* 115 */ - /* - * Stats from the mac_stats area - */ - volatile u_int32_t nicMacRxDropUla; /* 116 */ - volatile u_int32_t nicMacRxDropMcast; /* 117 */ - volatile u_int32_t nicMacRxFlowControl; /* 118 */ - volatile u_int32_t nicMacRxDropSpace; /* 119 */ - volatile u_int32_t nicMacRxColls; /* 120 */ - /* - * MAC RX Attentions - */ - volatile u_int32_t nicMacRxTotalAttns; /* 121 */ - volatile u_int32_t nicMacRxLinkAttns; /* 122 */ - volatile u_int32_t nicMacRxSyncAttns; /* 123 */ - volatile u_int32_t nicMacRxConfigAttns; /* 124 */ - volatile u_int32_t nicMacReset; /* 125 */ - volatile u_int32_t nicMacRxBufDescrAttns; /* 126 */ - volatile u_int32_t nicMacRxBufAttns; /* 127 */ - volatile u_int32_t nicMacRxZeroFrameCleanup; /* 128 */ - volatile u_int32_t nicMacRxOneFrameCleanup; /* 129 */ - volatile u_int32_t nicMacRxMultipleFrameCleanup; /* 130 */ - volatile u_int32_t nicMacRxTimerCleanup; /* 131 */ - volatile u_int32_t nicMacRxDmaCleanup; /* 132 */ - /* - * Stats from the mac_stats area - */ - volatile u_int32_t nicMacTxCollisionHistogram[15]; /* 133 */ - /* - * MAC TX Attentions - */ - volatile u_int32_t nicMacTxTotalAttns; /* 134 */ - /* - * NIC Profile - */ - volatile u_int32_t nicProfile[32]; /* 135 */ - /* - * Pat to 1024 bytes. - */ - u_int32_t pad[75]; -}; -/* - * Tigon general information block. This resides in host memory - * and contains the status counters, ring control blocks and - * producer pointers. - */ - -struct ti_gib { - struct ti_stats ti_stats; - struct ti_rcb ti_ev_rcb; - struct ti_rcb ti_cmd_rcb; - struct ti_rcb ti_tx_rcb; - struct ti_rcb ti_std_rx_rcb; - struct ti_rcb ti_jumbo_rx_rcb; - struct ti_rcb ti_mini_rx_rcb; - struct ti_rcb ti_return_rcb; - ti_hostaddr ti_ev_prodidx_ptr; - ti_hostaddr ti_return_prodidx_ptr; - ti_hostaddr ti_tx_considx_ptr; - ti_hostaddr ti_refresh_stats_ptr; -}; - -/* - * Buffer descriptor structures. There are basically three types - * of structures: normal receive descriptors, extended receive - * descriptors and transmit descriptors. The extended receive - * descriptors are optionally used only for the jumbo receive ring. - */ - -struct ti_rx_desc { - ti_hostaddr ti_addr; -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_idx; - u_int16_t ti_len; -#else - u_int16_t ti_len; - u_int16_t ti_idx; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_type; - u_int16_t ti_flags; -#else - u_int16_t ti_flags; - u_int16_t ti_type; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_ip_cksum; - u_int16_t ti_tcp_udp_cksum; -#else - u_int16_t ti_tcp_udp_cksum; - u_int16_t ti_ip_cksum; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_error_flags; - u_int16_t ti_vlan_tag; -#else - u_int16_t ti_vlan_tag; - u_int16_t ti_error_flags; -#endif - u_int32_t ti_rsvd; - u_int32_t ti_opaque; -}; - -struct ti_rx_desc_ext { - ti_hostaddr ti_addr1; - ti_hostaddr ti_addr2; - ti_hostaddr ti_addr3; -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_len1; - u_int16_t ti_len2; -#else - u_int16_t ti_len2; - u_int16_t ti_len1; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_len3; - u_int16_t ti_rsvd0; -#else - u_int16_t ti_rsvd0; - u_int16_t ti_len3; -#endif - ti_hostaddr ti_addr0; -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_idx; - u_int16_t ti_len0; -#else - u_int16_t ti_len0; - u_int16_t ti_idx; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_type; - u_int16_t ti_flags; -#else - u_int16_t ti_flags; - u_int16_t ti_type; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_ip_cksum; - u_int16_t ti_tcp_udp_cksum; -#else - u_int16_t ti_tcp_udp_cksum; - u_int16_t ti_ip_cksum; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_error_flags; - u_int16_t ti_vlan_tag; -#else - u_int16_t ti_vlan_tag; - u_int16_t ti_error_flags; -#endif - u_int32_t ti_rsvd1; - u_int32_t ti_opaque; -}; - -/* - * Transmit descriptors are, mercifully, very small. - */ -struct ti_tx_desc { - ti_hostaddr ti_addr; -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_len; - u_int16_t ti_flags; -#else - u_int16_t ti_flags; - u_int16_t ti_len; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int16_t ti_rsvd; - u_int16_t ti_vlan_tag; -#else - u_int16_t ti_vlan_tag; - u_int16_t ti_rsvd; -#endif -}; - -/* - * NOTE! On the Alpha, we have an alignment constraint. - * The first thing in the packet is a 14-byte Ethernet header. - * This means that the packet is misaligned. To compensate, - * we actually offset the data 2 bytes into the cluster. This - * alignes the packet after the Ethernet header at a 32-bit - * boundary. - */ - -#define TI_JUMBO_FRAMELEN 9018 -#define TI_JUMBO_MTU (TI_JUMBO_FRAMELEN - ETHER_HDR_LEN - ETHER_CRC_LEN) -#define TI_PAGE_SIZE PAGE_SIZE - -/* - * Buffer descriptor error flags. - */ -#define TI_BDERR_CRC 0x0001 -#define TI_BDERR_COLLDETECT 0x0002 -#define TI_BDERR_LINKLOST 0x0004 -#define TI_BDERR_DECODE 0x0008 -#define TI_BDERR_ODD_NIBBLES 0x0010 -#define TI_BDERR_MAC_ABRT 0x0020 -#define TI_BDERR_RUNT 0x0040 -#define TI_BDERR_TRUNC 0x0080 -#define TI_BDERR_GIANT 0x0100 - -/* - * Buffer descriptor flags. - */ -#define TI_BDFLAG_TCP_UDP_CKSUM 0x0001 -#define TI_BDFLAG_IP_CKSUM 0x0002 -#define TI_BDFLAG_END 0x0004 -#define TI_BDFLAG_MORE 0x0008 -#define TI_BDFLAG_JUMBO_RING 0x0010 -#define TI_BDFLAG_UCAST_PKT 0x0020 -#define TI_BDFLAG_MCAST_PKT 0x0040 -#define TI_BDFLAG_BCAST_PKT 0x0060 -#define TI_BDFLAG_IP_FRAG 0x0080 -#define TI_BDFLAG_IP_FRAG_END 0x0100 -#define TI_BDFLAG_VLAN_TAG 0x0200 -#define TI_BDFLAG_ERROR 0x0400 -#define TI_BDFLAG_COAL_NOW 0x0800 -#define TI_BDFLAG_MINI_RING 0x1000 - -/* - * Descriptor type flags. I think these only have meaning for - * the Tigon 1. I had to extract them from the sample driver source - * since they aren't in the manual. - */ -#define TI_BDTYPE_TYPE_NULL 0x0000 -#define TI_BDTYPE_SEND_BD 0x0001 -#define TI_BDTYPE_RECV_BD 0x0002 -#define TI_BDTYPE_RECV_JUMBO_BD 0x0003 -#define TI_BDTYPE_RECV_BD_LAST 0x0004 -#define TI_BDTYPE_SEND_DATA 0x0005 -#define TI_BDTYPE_SEND_DATA_LAST 0x0006 -#define TI_BDTYPE_RECV_DATA 0x0007 -#define TI_BDTYPE_RECV_DATA_LAST 0x000b -#define TI_BDTYPE_EVENT_RUPT 0x000c -#define TI_BDTYPE_EVENT_NO_RUPT 0x000d -#define TI_BDTYPE_ODD_START 0x000e -#define TI_BDTYPE_UPDATE_STATS 0x000f -#define TI_BDTYPE_SEND_DUMMY_DMA 0x0010 -#define TI_BDTYPE_EVENT_PROD 0x0011 -#define TI_BDTYPE_TX_CONS 0x0012 -#define TI_BDTYPE_RX_PROD 0x0013 -#define TI_BDTYPE_REFRESH_STATS 0x0014 -#define TI_BDTYPE_SEND_DATA_LAST_VLAN 0x0015 -#define TI_BDTYPE_SEND_DATA_COAL 0x0016 -#define TI_BDTYPE_SEND_DATA_LAST_COAL 0x0017 -#define TI_BDTYPE_SEND_DATA_LAST_VLAN_COAL 0x0018 -#define TI_BDTYPE_TX_CONS_NO_INTR 0x0019 - -/* - * Tigon command structure. - */ -struct ti_cmd_desc { - u_int32_t ti_cmdx; -}; - -#define TI_CMD_CMD(cmd) (((((cmd)->ti_cmdx)) >> 24) & 0xff) -#define TI_CMD_CODE(cmd) (((((cmd)->ti_cmdx)) >> 12) & 0xfff) -#define TI_CMD_IDX(cmd) ((((cmd)->ti_cmdx)) & 0xfff) - -#define TI_CMD_HOST_STATE 0x01 -#define TI_CMD_CODE_STACK_UP 0x01 -#define TI_CMD_CODE_STACK_DOWN 0x02 - -/* - * This command enables software address filtering. It's a workaround - * for a bug in the Tigon 1 and not implemented for the Tigon 2. - */ -#define TI_CMD_FDR_FILTERING 0x02 -#define TI_CMD_CODE_FILT_ENB 0x01 -#define TI_CMD_CODE_FILT_DIS 0x02 - -#define TI_CMD_SET_RX_PROD_IDX 0x03 /* obsolete */ -#define TI_CMD_UPDATE_GENCOM 0x04 -#define TI_CMD_RESET_JUMBO_RING 0x05 -#define TI_CMD_SET_PARTIAL_RX_CNT 0x06 -#define TI_CMD_ADD_MCAST_ADDR 0x08 /* obsolete */ -#define TI_CMD_DEL_MCAST_ADDR 0x09 /* obsolete */ - -#define TI_CMD_SET_PROMISC_MODE 0x0A -#define TI_CMD_CODE_PROMISC_ENB 0x01 -#define TI_CMD_CODE_PROMISC_DIS 0x02 - -#define TI_CMD_LINK_NEGOTIATION 0x0B -#define TI_CMD_CODE_NEGOTIATE_BOTH 0x00 -#define TI_CMD_CODE_NEGOTIATE_GIGABIT 0x01 -#define TI_CMD_CODE_NEGOTIATE_10_100 0x02 - -#define TI_CMD_SET_MAC_ADDR 0x0C -#define TI_CMD_CLR_PROFILE 0x0D - -#define TI_CMD_SET_ALLMULTI 0x0E -#define TI_CMD_CODE_ALLMULTI_ENB 0x01 -#define TI_CMD_CODE_ALLMULTI_DIS 0x02 - -#define TI_CMD_CLR_STATS 0x0F -#define TI_CMD_SET_RX_JUMBO_PROD_IDX 0x10 /* obsolete */ -#define TI_CMD_RFRSH_STATS 0x11 - -#define TI_CMD_EXT_ADD_MCAST 0x12 -#define TI_CMD_EXT_DEL_MCAST 0x13 - -/* - * Utility macros to make issuing commands a little simpler. Assumes - * that 'sc' and 'cmd' are in local scope. - */ -#define TI_DO_CMD(x, y, z) \ - cmd.ti_cmdx = (((x) << 24) | ((y) << 12) | ((z))); \ - ti_cmd(sc, &cmd); - -#define TI_DO_CMD_EXT(x, y, z, v, w) \ - cmd.ti_cmdx = (((x) << 24) | ((y) << 12) | ((z))); \ - ti_cmd_ext(sc, &cmd, v, w); - -/* - * Other utility macros. - */ -#define TI_INC(x, y) (x) = (x + 1) % y - -#define TI_UPDATE_JUMBOPROD(x, y) \ - if (x->ti_hwrev == TI_HWREV_TIGON) { \ - TI_DO_CMD(TI_CMD_SET_RX_JUMBO_PROD_IDX, 0, y); \ - } else { \ - CSR_WRITE_4(x, TI_MB_JUMBORXPROD_IDX, y); \ - } - -#define TI_UPDATE_MINIPROD(x, y) \ - CSR_WRITE_4(x, TI_MB_MINIRXPROD_IDX, y); - -#define TI_UPDATE_STDPROD(x, y) \ - if (x->ti_hwrev == TI_HWREV_TIGON) { \ - TI_DO_CMD(TI_CMD_SET_RX_PROD_IDX, 0, y); \ - } else { \ - CSR_WRITE_4(x, TI_MB_STDRXPROD_IDX, y); \ - } - - -/* - * Tigon event structure. - */ -struct ti_event_desc { - u_int32_t ti_eventx; - u_int32_t ti_rsvd; -}; - -#define TI_EVENT_EVENT(e) (((((e)->ti_eventx)) >> 24) & 0xff) -#define TI_EVENT_CODE(e) (((((e)->ti_eventx)) >> 12) & 0xfff) -#define TI_EVENT_IDX(e) (((((e)->ti_eventx))) & 0xfff) - -/* - * Tigon events. - */ -#define TI_EV_FIRMWARE_UP 0x01 -#define TI_EV_STATS_UPDATED 0x04 - -#define TI_EV_LINKSTAT_CHANGED 0x06 -#define TI_EV_CODE_GIG_LINK_UP 0x01 -#define TI_EV_CODE_LINK_DOWN 0x02 -#define TI_EV_CODE_LINK_UP 0x03 - -#define TI_EV_ERROR 0x07 -#define TI_EV_CODE_ERR_INVAL_CMD 0x01 -#define TI_EV_CODE_ERR_UNIMP_CMD 0x02 -#define TI_EV_CODE_ERR_BADCFG 0x03 - -#define TI_EV_MCAST_UPDATED 0x08 -#define TI_EV_CODE_MCAST_ADD 0x01 -#define TI_EV_CODE_MCAST_DEL 0x02 - -#define TI_EV_RESET_JUMBO_RING 0x09 -/* - * Register access macros. The Tigon always uses memory mapped register - * accesses and all registers must be accessed with 32 bit operations. - */ - -#define CSR_WRITE_4(sc, reg, val) \ - bus_space_write_4(sc->ti_btag, sc->ti_bhandle, (reg), (val)) - -#define CSR_READ_4(sc, reg) \ - bus_space_read_4(sc->ti_btag, sc->ti_bhandle, (reg)) - -#define TI_SETBIT(sc, reg, x) \ - CSR_WRITE_4(sc, (reg), (CSR_READ_4(sc, (reg)) | (x))) -#define TI_CLRBIT(sc, reg, x) \ - CSR_WRITE_4(sc, (reg), (CSR_READ_4(sc, (reg)) & ~(x))) - -/* - * Memory management stuff. Note: the SSLOTS, MSLOTS and JSLOTS - * values are tuneable. They control the actual amount of buffers - * allocated for the standard, mini and jumbo receive rings. - */ - -#define TI_SSLOTS 256 -#define TI_MSLOTS 256 -#define TI_JSLOTS 384 - -#define TI_JRAWLEN (TI_JUMBO_FRAMELEN + ETHER_ALIGN) -#define TI_JLEN (TI_JRAWLEN + (sizeof(u_int64_t) - \ - (TI_JRAWLEN % sizeof(u_int64_t)))) -#define TI_JPAGESZ PAGE_SIZE -#define TI_RESID (TI_JPAGESZ - (TI_JLEN * TI_JSLOTS) % TI_JPAGESZ) -#define TI_JMEM ((TI_JLEN * TI_JSLOTS) + TI_RESID) - -struct ti_jslot { - caddr_t ti_buf; - int ti_inuse; -}; - -/* - * Ring structures. Most of these reside in host memory and we tell - * the NIC where they are via the ring control blocks. The exceptions - * are the tx and command rings, which live in NIC memory and which - * we access via the shared memory window. - */ -struct ti_ring_data { - struct ti_rx_desc ti_rx_std_ring[TI_STD_RX_RING_CNT]; - struct ti_rx_desc ti_rx_jumbo_ring[TI_JUMBO_RX_RING_CNT]; - struct ti_rx_desc ti_rx_mini_ring[TI_MINI_RX_RING_CNT]; - struct ti_rx_desc ti_rx_return_ring[TI_RETURN_RING_CNT]; - struct ti_event_desc ti_event_ring[TI_EVENT_RING_CNT]; - struct ti_tx_desc ti_tx_ring[TI_TX_RING_CNT]; - - /* - * Make sure producer structures are aligned on 32-byte cache - * line boundaries. - */ - struct ti_producer ti_ev_prodidx_r; - u_int32_t ti_pad0[6]; - struct ti_producer ti_return_prodidx_r; - u_int32_t ti_pad1[6]; - struct ti_producer ti_tx_considx_r; - u_int32_t ti_pad2[6]; - struct ti_gib ti_info; -}; - -#define TI_RING_DMA_ADDR(sc, offset) \ - ((sc)->ti_ring_map->dm_segs[0].ds_addr + \ - offsetof(struct ti_ring_data, offset)) - -#define TI_RING_DMASYNC(sc, offset, op) \ - bus_dmamap_sync((sc)->sc_dmatag, (sc)->ti_ring_map, \ - offsetof(struct ti_ring_data, offset), \ - sizeof(((struct ti_ring_data *)0)->offset), (op)) - -/* - * Number of DMA segments in a TxCB. Note that this is carefully - * chosen to make the total struct size an even power of two. It's - * critical that no TxCB be split across a page boundry since - * no attempt is made to allocate physically contiguous memory. - * - */ -#ifdef __LP64__ -#define TI_NTXSEG 30 -#else -#define TI_NTXSEG 31 -#endif - -struct ti_txmap_entry { - bus_dmamap_t dmamap; - SLIST_ENTRY(ti_txmap_entry) link; -}; - -/* - * Mbuf pointers. We need these to keep track of the virtual addresses - * of our mbuf chains since we can only convert from physical to virtual, - * not the other way around. - */ -struct ti_chain_data { - struct mbuf *ti_tx_chain[TI_TX_RING_CNT]; - struct mbuf *ti_rx_std_chain[TI_STD_RX_RING_CNT]; - struct mbuf *ti_rx_jumbo_chain[TI_JUMBO_RX_RING_CNT]; - struct mbuf *ti_rx_mini_chain[TI_MINI_RX_RING_CNT]; - - struct ti_txmap_entry *ti_tx_map[TI_TX_RING_CNT]; - bus_dmamap_t ti_rx_std_map[TI_STD_RX_RING_CNT]; - bus_dmamap_t ti_rx_jumbo_map; - bus_dmamap_t ti_rx_mini_map[TI_MINI_RX_RING_CNT]; - - /* Stick the jumbo mem management stuff here too. */ - struct ti_jslot ti_jslots[TI_JSLOTS]; - void *ti_jumbo_buf; -}; - -#define TI_JUMBO_DMA_ADDR(sc, m) \ - ((sc)->ti_cdata.ti_rx_jumbo_map->dm_segs[0].ds_addr + \ - (mtod((m), char *) - (char *)(sc)->ti_cdata.ti_jumbo_buf)) - -struct ti_type { - u_int16_t ti_vid; - u_int16_t ti_did; - char *ti_name; -}; - -#define TI_HWREV_TIGON 0x01 -#define TI_HWREV_TIGON_II 0x02 -#define TI_TIMEOUT 1000 -#define TI_TXCONS_UNSET 0xFFFF /* impossible value */ - -struct ti_mc_entry { - struct ether_addr mc_addr; - SLIST_ENTRY(ti_mc_entry) mc_entries; -}; - -struct ti_jpool_entry { - int slot; - SLIST_ENTRY(ti_jpool_entry) jpool_entries; -}; - -struct ti_softc { - struct device sc_dv; - struct arpcom arpcom; /* interface info */ - bus_space_handle_t ti_bhandle; - bus_space_tag_t ti_btag; - void * ti_intrhand; - struct ifmedia ifmedia; /* media info */ - u_int8_t ti_hwrev; /* Tigon rev (1 or 2) */ - u_int8_t ti_copper; /* 1000baseTX card */ - u_int8_t ti_linkstat; /* Link state */ - bus_dma_tag_t sc_dmatag; - struct ti_ring_data *ti_rdata; /* rings */ - struct ti_chain_data ti_cdata; /* mbufs */ -#define ti_ev_prodidx ti_rdata->ti_ev_prodidx_r -#define ti_return_prodidx ti_rdata->ti_return_prodidx_r -#define ti_tx_considx ti_rdata->ti_tx_considx_r - struct ti_tx_desc *ti_tx_ring_nic;/* pointer to shared mem */ - bus_dmamap_t ti_ring_map; - u_int16_t ti_tx_saved_prodidx; - u_int16_t ti_tx_saved_considx; - u_int16_t ti_rx_saved_considx; - u_int16_t ti_ev_saved_considx; - u_int16_t ti_cmd_saved_prodidx; - u_int16_t ti_std; /* current std ring head */ - u_int16_t ti_mini; /* current mini ring head */ - u_int16_t ti_jumbo; /* current jumo ring head */ - SLIST_HEAD(__ti_mchead, ti_mc_entry) ti_mc_listhead; - SLIST_HEAD(__ti_jfreehead, ti_jpool_entry) ti_jfree_listhead; - SLIST_HEAD(__ti_jinusehead, ti_jpool_entry) ti_jinuse_listhead; - SLIST_HEAD(__ti_txmaphead, ti_txmap_entry) ti_tx_map_listhead; - u_int32_t ti_stat_ticks; - u_int32_t ti_rx_coal_ticks; - u_int32_t ti_tx_coal_ticks; - u_int32_t ti_rx_max_coal_bds; - u_int32_t ti_tx_max_coal_bds; - u_int32_t ti_tx_buf_ratio; - int ti_if_flags; - int ti_txcnt; -}; - -/* - * Microchip Technology 24Cxx EEPROM control bytes - */ -#define EEPROM_CTL_READ 0xA1 /* 0101 0001 */ -#define EEPROM_CTL_WRITE 0xA0 /* 0101 0000 */ - -/* - * Note that EEPROM_START leaves transmission enabled. - */ -#define EEPROM_START \ - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); /* Pull clock pin high */\ - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT); /* Set DATA bit to 1 */ \ - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN); /* Enable xmit to write bit */\ - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT); /* Pull DATA bit to 0 again */\ - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); /* Pull clock low again */ - -/* - * EEPROM_STOP ends access to the EEPROM and clears the ETXEN bit so - * that no further data can be written to the EEPROM I/O pin. - */ -#define EEPROM_STOP \ - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN); /* Disable xmit */ \ - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT); /* Pull DATA to 0 */ \ - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); /* Pull clock high */ \ - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN); /* Enable xmit */ \ - TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT); /* Toggle DATA to 1 */ \ - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN); /* Disable xmit. */ \ - TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK); /* Pull clock low again */ diff --git a/sys/dev/pci/if_tivar.h b/sys/dev/pci/if_tivar.h deleted file mode 100644 index 5c3c37e943e..00000000000 --- a/sys/dev/pci/if_tivar.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $OpenBSD: if_tivar.h,v 1.2 2004/11/22 21:23:57 deraadt Exp $ */ - -/* - * Copyright (c) 2004 Theo de Raadt <deraadt@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -struct tigon_firmware { - int FwReleaseMajor; - int FwReleaseMinor; - int FwReleaseFix; - u_int32_t FwStartAddr; - - u_int32_t FwTextAddr; - int FwTextLen; - u_int32_t FwRodataAddr; - int FwRodataLen; - - u_int32_t FwDataAddr; - int FwDataLen; - u_int32_t FwSbssAddr; - int FwSbssLen; - - u_int32_t FwBssAddr; - int FwBssLen; - - int FwTextOffset; - int FwRodataOffset; - int FwDataOffset; - - u_char data[1]; -}; |