/* * Copyright (c) 1998, Larry Lile * All rights reserved. * * For latest sources and information on this driver, please * go to http://anarchy.stdio.com. * * Questions, comments or suggestions should be directed to * Larry Lile . * * 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 unmodified, 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR OR CONTRIBUTORS 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$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if (__FreeBSD_version < 400000) #include #endif #if (NBPFILTER > 0) || (__FreeBSD_version > 400000) #include #endif #include /* for vtophys */ #include /* for vtophys */ #include #include #include #include #include #include #include #include #include "contrib/dev/oltr/trlld.h" /*#define DEBUG_MASK DEBUG_POLL*/ #ifndef DEBUG_MASK #define DEBUG_MASK 0x0000 #endif #define DEBUG_POLL 0x0001 #define DEBUG_INT 0x0002 #define DEBUG_INIT 0x0004 #define DEBUG_FN_ENT 0x8000 #define PCI_VENDOR_OLICOM 0x108D #define MIN(A,B) (((A) < (B)) ? (A) : (B)) #define MIN3(A,B,C) (MIN(A, (MIN(B, C)))) char *AdapterName[] = { /* 0 */ "Olicom XT Adapter [unsupported]", /* 1 */ "Olicom OC-3115", /* 2 */ "Olicom ISA 16/4 Adapter (OC-3117)", /* 3 */ "Olicom ISA 16/4 Adapter (OC-3118)", /* 4 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]", /* 5 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]", /* 6 */ "Olicom MCA 16/4 Adapter (OC-3129) [unsupported]", /* 7 */ "Olicom EISA 16/4 Adapter (OC-3133)", /* 8 */ "Olicom EISA 16/4 Adapter (OC-3133)", /* 9 */ "Olicom EISA 16/4 Server Adapter (OC-3135)", /* 10 */ "Olicom PCI 16/4 Adapter (OC-3136)", /* 11 */ "Olicom PCI 16/4 Adapter (OC-3136)", /* 12 */ "Olicom PCI/II 16/4 Adapter (OC-3137)", /* 13 */ "Olicom PCI 16/4 Adapter (OC-3139)", /* 14 */ "Olicom RapidFire 3140 16/4 PCI Adapter (OC-3140)", /* 15 */ "Olicom RapidFire 3141 Fiber Adapter (OC-3141)", /* 16 */ "Olicom PCMCIA 16/4 Adapter (OC-3220) [unsupported]", /* 17 */ "Olicom PCMCIA 16/4 Adapter (OC-3121, OC-3230, OC-3232) [unsupported]", /* 18 */ "Olicom PCMCIA 16/4 Adapter (OC-3250)", /* 19 */ "Olicom RapidFire 3540 100/16/4 Adapter (OC-3540)" }; /* * Glue function prototypes for PMW kit IO */ #ifndef TRlldInlineIO static void DriverOutByte __P((unsigned short, unsigned char)); static void DriverOutWord __P((unsigned short, unsigned short)); static void DriverOutDword __P((unsigned short, unsigned long)); static void DriverRepOutByte __P((unsigned short, unsigned char *, int)); static void DriverRepOutWord __P((unsigned short, unsigned short *, int)); static void DriverRepOutDword __P((unsigned short, unsigned long *, int)); static unsigned char DriverInByte __P((unsigned short)); static unsigned short DriverInWord __P((unsigned short)); static unsigned long DriverInDword __P((unsigned short)); static void DriverRepInByte __P((unsigned short, unsigned char *, int)); static void DriverRepInWord __P((unsigned short, unsigned short *, int)); static void DriverRepInDword __P((unsigned short, unsigned long *, int)); #endif /*TRlldInlineIO*/ static void DriverSuspend __P((unsigned short)); static void DriverStatus __P((void *, TRlldStatus_t *)); static void DriverCloseCompleted __P((void *)); static void DriverStatistics __P((void *, TRlldStatistics_t *)); static void DriverTransmitFrameCompleted __P((void *, void *, int)); static void DriverReceiveFrameCompleted __P((void *, int, int, void *, int)); static TRlldDriver_t LldDriver = { TRLLD_VERSION, #ifndef TRlldInlineIO DriverOutByte, DriverOutWord, DriverOutDword, DriverRepOutByte, DriverRepOutWord, DriverRepOutDword, DriverInByte, DriverInWord, DriverInDword, DriverRepInByte, DriverRepInWord, DriverRepInDword, #endif /*TRlldInlineIO*/ DriverSuspend, DriverStatus, DriverCloseCompleted, DriverStatistics, DriverTransmitFrameCompleted, DriverReceiveFrameCompleted, }; struct oltr_rx_buf { int index; char *data; u_long address; }; struct oltr_tx_buf { int index; char *data; u_long address; }; #define RING_BUFFER_LEN 16 #define RING_BUFFER(x) ((RING_BUFFER_LEN - 1) & x) #define RX_BUFFER_LEN 2048 #define TX_BUFFER_LEN 2048 struct oltr_softc { struct arpcom arpcom; struct ifmedia ifmedia; bus_space_handle_t oltr_bhandle; bus_space_tag_t oltr_btag; void *oltr_intrhand; struct resource *oltr_irq; struct resource *oltr_res; int unit; int state; #define OL_UNKNOWN 0 #define OL_INIT 1 #define OL_READY 2 #define OL_CLOSING 3 #define OL_CLOSED 4 #define OL_OPENING 5 #define OL_OPEN 6 #define OL_PROMISC 7 #define OL_DEAD 8 struct oltr_rx_buf rx_ring[RING_BUFFER_LEN]; int tx_head, tx_avail, tx_frame; struct oltr_tx_buf tx_ring[RING_BUFFER_LEN]; TRlldTransmit_t frame_ring[RING_BUFFER_LEN]; struct mbuf *restart; TRlldAdapter_t TRlldAdapter; TRlldStatistics_t statistics; TRlldStatistics_t current; TRlldAdapterConfig_t config; u_short AdapterMode; u_long GroupAddress; u_long FunctionalAddress; struct callout_handle oltr_poll_ch; /*struct callout_handle oltr_stat_ch;*/ void *work_memory; }; #define SELF_TEST_POLLS 32 void oltr_poll __P((void *)); /*void oltr_stat __P((void *));*/ static void oltr_start __P((struct ifnet *)); static void oltr_stop __P((struct oltr_softc *)); static void oltr_close __P((struct oltr_softc *)); static void oltr_init __P((void *)); static int oltr_ioctl __P((struct ifnet *, u_long, caddr_t)); static void oltr_intr __P((void *)); static int oltr_ifmedia_upd __P((struct ifnet *)); static void oltr_ifmedia_sts __P((struct ifnet *, struct ifmediareq *)); #if __FreeBSD_version > 400000 static int oltr_pci_probe __P((device_t)); static int oltr_pci_attach __P((device_t)); static int oltr_pci_detach __P((device_t)); static void oltr_pci_shutdown __P((device_t)); static device_method_t oltr_methods[] = { DEVMETHOD(device_probe, oltr_pci_probe), DEVMETHOD(device_attach, oltr_pci_attach), DEVMETHOD(device_detach, oltr_pci_detach), DEVMETHOD(device_shutdown, oltr_pci_shutdown), { 0, 0 } }; static driver_t oltr_driver = { "oltr", oltr_methods, sizeof(struct oltr_softc) }; static devclass_t oltr_devclass; DRIVER_MODULE(oltr, pci, oltr_driver, oltr_devclass, 0, 0); static int oltr_pci_probe(device_t dev) { int i, rc; char PCIConfigHeader[64]; TRlldAdapterConfig_t config; if ((pci_get_vendor(dev) == PCI_VENDOR_OLICOM) && ((pci_get_device(dev) == 0x0001) || (pci_get_device(dev) == 0x0004) || (pci_get_device(dev) == 0x0005) || (pci_get_device(dev) == 0x0007) || (pci_get_device(dev) == 0x0008))) { for (i = 0; i < sizeof(PCIConfigHeader); i++) PCIConfigHeader[i] = pci_read_config(dev, i, 1); rc = TRlldPCIConfig(&LldDriver, &config, PCIConfigHeader); if (rc == TRLLD_PCICONFIG_FAIL) { device_printf(dev, "TRlldPciConfig failed!\n"); return(ENXIO); } if (rc == TRLLD_PCICONFIG_VERSION) { device_printf(dev, "wrong LLD version\n"); return(ENXIO); } device_set_desc(dev, AdapterName[config.type]); return(0); } return(ENXIO); } static int oltr_pci_attach(device_t dev) { int i, s, rc = 0, rid, scratch_size; int media = IFM_TOKEN|IFM_TOK_UTP16; u_long command; char PCIConfigHeader[64]; struct oltr_softc *sc = device_get_softc(dev); struct ifnet *ifp = &sc->arpcom.ac_if; s = splimp(); bzero(sc, sizeof(struct oltr_softc)); sc->unit = device_get_unit(dev); sc->state = OL_UNKNOWN; for (i = 0; i < sizeof(PCIConfigHeader); i++) PCIConfigHeader[i] = pci_read_config(dev, i, 1); switch(TRlldPCIConfig(&LldDriver, &sc->config, PCIConfigHeader)) { case TRLLD_PCICONFIG_OK: break; case TRLLD_PCICONFIG_SET_COMMAND: device_printf(dev, "enabling bus master mode\n"); command = pci_read_config(dev, PCIR_COMMAND, 4); pci_write_config(dev, PCIR_COMMAND, (command | PCIM_CMD_BUSMASTEREN), 4); command = pci_read_config(dev, PCIR_COMMAND, 4); if (!(command & PCIM_CMD_BUSMASTEREN)) { device_printf(dev, "failed to enable bus master mode\n"); goto config_failed; } break; case TRLLD_PCICONFIG_FAIL: device_printf(dev, "TRlldPciConfig failed!\n"); goto config_failed; break; case TRLLD_PCICONFIG_VERSION: device_printf(dev, "wrong LLD version\n"); goto config_failed; break; } device_printf(dev, "MAC address %6D\n", sc->config.macaddress, ":"); scratch_size = TRlldAdapterSize(); if (bootverbose) device_printf(dev, "adapter memory block size %d bytes\n", scratch_size); sc->TRlldAdapter = (TRlldAdapter_t)malloc(scratch_size, M_DEVBUF, M_NOWAIT); if (sc->TRlldAdapter == NULL) { device_printf(dev, "couldn't allocate scratch buffer (%d bytes)\n", scratch_size); goto config_failed; } /* * Allocate RX/TX Pools */ for (i = 0; i < RING_BUFFER_LEN; i++) { sc->rx_ring[i].index = i; sc->rx_ring[i].data = (char *)malloc(RX_BUFFER_LEN, M_DEVBUF, M_NOWAIT); sc->rx_ring[i].address = vtophys(sc->rx_ring[i].data); sc->tx_ring[i].index = i; sc->tx_ring[i].data = (char *)malloc(TX_BUFFER_LEN, M_DEVBUF, M_NOWAIT); sc->tx_ring[i].address = vtophys(sc->tx_ring[i].data); if ((!sc->rx_ring[i].data) || (!sc->tx_ring[i].data)) { device_printf(dev, "unable to allocate ring buffers\n"); while (i > 0) { if (sc->rx_ring[i].data) free(sc->rx_ring[i].data, M_DEVBUF); if (sc->tx_ring[i].data) free(sc->tx_ring[i].data, M_DEVBUF); i--; } goto config_failed; } } /* * Allocate interrupt and DMA channel */ rid = 0; sc->oltr_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, (sc->config.mode & TRLLD_MODE_SHARE_INTERRUPT ? RF_ACTIVE | RF_SHAREABLE : RF_ACTIVE)); if (sc->oltr_irq == NULL) { device_printf(dev, "couldn't map interrupt\n"); goto config_failed; } if (bus_setup_intr(dev, sc->oltr_irq, INTR_TYPE_NET, oltr_intr, sc, &sc->oltr_intrhand)) { device_printf(dev, "couldn't setup interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->oltr_irq); goto config_failed; } /* * Do the ifnet initialization */ ifp->if_softc = sc; ifp->if_unit = device_get_unit(dev); ifp->if_name = "oltr"; ifp->if_output = iso88025_output; ifp->if_init = oltr_init; ifp->if_start = oltr_start; ifp->if_ioctl = oltr_ioctl; ifp->if_flags = IFF_BROADCAST; bcopy(sc->config.macaddress, sc->arpcom.ac_enaddr, sizeof(sc->config.macaddress)); /* * Do ifmedia setup. */ ifmedia_init(&sc->ifmedia, 0, oltr_ifmedia_upd, oltr_ifmedia_sts); rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS); switch(sc->config.type) { case TRLLD_ADAPTER_PCI7: /* OC-3540 */ ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP100, 0, NULL); /* FALL THROUGH */ case TRLLD_ADAPTER_PCI4: /* OC-3139 */ case TRLLD_ADAPTER_PCI5: /* OC-3140 */ case TRLLD_ADAPTER_PCI6: /* OC-3141 */ ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_AUTO, 0, NULL); media = IFM_TOKEN|IFM_AUTO; rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* FALL THROUGH */ default: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP4, 0, NULL); ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16, 0, NULL); break; } sc->ifmedia.ifm_media = media; ifmedia_set(&sc->ifmedia, media); /* * Attach the interface */ if_attach(ifp); ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; iso88025_ifattach(ifp); #if (NBPFILTER > 0) || (__FreeBSD_version > 400000) bpfattach(ifp, DLT_IEEE802, sizeof(struct iso88025_header)); #endif splx(s); return(0); config_failed: splx(s); return(ENXIO); } static int oltr_pci_detach(device_t dev) { struct oltr_softc *sc = device_get_softc(dev); struct ifnet *ifp = &sc->arpcom.ac_if; int s; device_printf(dev, "driver unloading\n"); s = splimp(); if_detach(ifp); oltr_stop(sc); untimeout(oltr_poll, (void *)sc, sc->oltr_poll_ch); /*untimeout(oltr_stat, (void *)sc, sc->oltr_stat_ch);*/ bus_teardown_intr(dev, sc->oltr_irq, sc->oltr_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->oltr_irq); (void)splx(s); return(0); } static void oltr_pci_shutdown(device_t dev) { struct oltr_softc *sc = device_get_softc(dev); device_printf(dev, "oltr_pci_shutdown called\n"); oltr_stop(sc); return; } #else static const char *oltr_pci_probe __P((pcici_t, pcidi_t)); static void oltr_pci_attach __P((pcici_t, int)); static unsigned long oltr_count = 0; static struct pci_device oltr_device = { "oltr", oltr_pci_probe, oltr_pci_attach, &oltr_count, NULL }; DATA_SET(pcidevice_set, oltr_device); static const char * oltr_pci_probe(pcici_t config_id, pcidi_t device_id) { int i, rc; char PCIConfigHeader[64]; TRlldAdapterConfig_t config; if (((device_id & 0xffff) == PCI_VENDOR_OLICOM) && ( (((device_id >> 16) & 0xffff) == 0x0001) || (((device_id >> 16) & 0xffff) == 0x0004) || (((device_id >> 16) & 0xffff) == 0x0005) || (((device_id >> 16) & 0xffff) == 0x0007) || (((device_id >> 16) & 0xffff) == 0x0008))) { for (i = 0; i < 64; i++) PCIConfigHeader[i] = pci_cfgread(config_id, i, /* bytes */ 1); rc = TRlldPCIConfig(&LldDriver, &config, PCIConfigHeader); if (rc == TRLLD_PCICONFIG_FAIL) { printf("oltr: TRlldPciConfig failed!\n"); return(NULL); } if (rc == TRLLD_PCICONFIG_VERSION) { printf("oltr: wrong LLD version.\n"); return(NULL); } return(AdapterName[config.type]); } return(NULL); } static void oltr_pci_attach(pcici_t config_id, int unit) { int i, s, rc = 0, scratch_size; int media = IFM_TOKEN|IFM_TOK_UTP16; u_long command; char PCIConfigHeader[64]; struct oltr_softc *sc; struct ifnet *ifp; /* = &sc->arpcom.ac_if; */ s = splimp(); sc = malloc(sizeof(struct oltr_softc), M_DEVBUF, M_NOWAIT | M_ZERO); if (sc == NULL) { printf("oltr%d: no memory for softc struct!\n", unit); goto config_failed; } sc->unit = unit; sc->state = OL_UNKNOWN; ifp = &sc->arpcom.ac_if; for (i = 0; i < sizeof(PCIConfigHeader); i++) PCIConfigHeader[i] = pci_cfgread(config_id, i, 1); switch(TRlldPCIConfig(&LldDriver, &sc->config, PCIConfigHeader)) { case TRLLD_PCICONFIG_OK: break; case TRLLD_PCICONFIG_SET_COMMAND: printf("oltr%d: enabling bus master mode\n", unit); command = pci_conf_read(config_id, PCIR_COMMAND); pci_conf_write(config_id, PCIR_COMMAND, (command | PCIM_CMD_BUSMASTEREN)); command = pci_conf_read(config_id, PCIR_COMMAND); if (!(command & PCIM_CMD_BUSMASTEREN)) { printf("oltr%d: failed to enable bus master mode\n", unit); goto config_failed; } break; case TRLLD_PCICONFIG_FAIL: printf("oltr%d: TRlldPciConfig failed!\n", unit); goto config_failed; break; case TRLLD_PCICONFIG_VERSION: printf("oltr%d: wrong LLD version\n", unit); goto config_failed; break; } printf("oltr%d: MAC address %6D\n", unit, sc->config.macaddress, ":"); scratch_size = TRlldAdapterSize(); if (bootverbose) printf("oltr%d: adapter memory block size %d bytes\n", unit, scratch_size); sc->TRlldAdapter = (TRlldAdapter_t)malloc(scratch_size, M_DEVBUF, M_NOWAIT); if (sc->TRlldAdapter == NULL) { printf("oltr%d: couldn't allocate scratch buffer (%d bytes)\n",unit, scratch_size); goto config_failed; } /* * Allocate RX/TX Pools */ for (i = 0; i < RING_BUFFER_LEN; i++) { sc->rx_ring[i].index = i; sc->rx_ring[i].data = (char *)malloc(RX_BUFFER_LEN, M_DEVBUF, M_NOWAIT); sc->rx_ring[i].address = vtophys(sc->rx_ring[i].data); sc->tx_ring[i].index = i; sc->tx_ring[i].data = (char *)malloc(TX_BUFFER_LEN, M_DEVBUF, M_NOWAIT); sc->tx_ring[i].address = vtophys(sc->tx_ring[i].data); if ((!sc->rx_ring[i].data) || (!sc->tx_ring[i].data)) { printf("oltr%d: unable to allocate ring buffers\n", unit); while (i > 0) { if (sc->rx_ring[i].data) free(sc->rx_ring[i].data, M_DEVBUF); if (sc->tx_ring[i].data) free(sc->tx_ring[i].data, M_DEVBUF); i--; } goto config_failed; } } /* * Allocate interrupt and DMA channel */ if (!pci_map_int(config_id, oltr_intr, sc, &net_imask)) { printf("oltr%d: couldn't setup interrupt\n", unit); goto config_failed; } /* * Do the ifnet initialization */ ifp->if_softc = sc; ifp->if_unit = unit; ifp->if_name = "oltr"; ifp->if_output = iso88025_output; ifp->if_init = oltr_init; ifp->if_start = oltr_start; ifp->if_ioctl = oltr_ioctl; ifp->if_flags = IFF_BROADCAST; bcopy(sc->config.macaddress, sc->arpcom.ac_enaddr, sizeof(sc->config.macaddress)); /* * Do ifmedia setup. */ ifmedia_init(&sc->ifmedia, 0, oltr_ifmedia_upd, oltr_ifmedia_sts); rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS); switch(sc->config.type) { case TRLLD_ADAPTER_PCI7: /* OC-3540 */ ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP100, 0, NULL); /* FALL THROUGH */ case TRLLD_ADAPTER_PCI4: /* OC-3139 */ case TRLLD_ADAPTER_PCI5: /* OC-3140 */ case TRLLD_ADAPTER_PCI6: /* OC-3141 */ ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_AUTO, 0, NULL); media = IFM_TOKEN|IFM_AUTO; rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* FALL THROUGH */ default: ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP4, 0, NULL); ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16, 0, NULL); break; } sc->ifmedia.ifm_media = media; ifmedia_set(&sc->ifmedia, media); /* * Attach the interface */ if_attach(ifp); ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; iso88025_ifattach(ifp); #if (NBPFILTER > 0) || (__FreeBSD_version > 400000) bpfattach(ifp, DLT_IEEE802, sizeof(struct iso88025_header)); #endif splx(s); return; config_failed: (void)splx(s); return; } #endif static void oltr_intr(void *xsc) { struct oltr_softc *sc = (struct oltr_softc *)xsc; if (DEBUG_MASK & DEBUG_INT) printf("I"); TRlldInterruptService(sc->TRlldAdapter); return; } static void oltr_start(struct ifnet *ifp) { struct oltr_softc *sc = ifp->if_softc; struct mbuf *m0, *m; int copy_len, buffer, frame, fragment, rc, s; /* * Check to see if output is already active */ if (ifp->if_flags & IFF_OACTIVE) return; outloop: /* * Make sure we have buffers to transmit with */ if (sc->tx_avail <= 0) { printf("oltr%d: tx queue full\n", sc->unit); ifp->if_flags |= IFF_OACTIVE; return; } if (sc->restart == NULL) { IF_DEQUEUE(&ifp->if_snd, m); if (m == NULL) return; } else { m = sc->restart; sc->restart = NULL; } m0 = m; frame = RING_BUFFER(sc->tx_frame); buffer = RING_BUFFER(sc->tx_head); fragment = 0; copy_len = 0; sc->frame_ring[frame].FragmentCount = 0; while (copy_len < m0->m_pkthdr.len) { sc->frame_ring[frame].FragmentCount++; if (sc->frame_ring[frame].FragmentCount > sc->tx_avail) goto nobuffers; sc->frame_ring[frame].TransmitFragment[fragment].VirtualAddress = sc->tx_ring[buffer].data; sc->frame_ring[frame].TransmitFragment[fragment].PhysicalAddress = sc->tx_ring[buffer].address; sc->frame_ring[frame].TransmitFragment[fragment].count = MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN); m_copydata(m0, copy_len, MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN), sc->tx_ring[buffer].data); copy_len += MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN); fragment++; buffer = RING_BUFFER((buffer + 1)); } s = splimp(); rc = TRlldTransmitFrame(sc->TRlldAdapter, &sc->frame_ring[frame], (void *)&sc->frame_ring[frame]); (void)splx(s); if (rc != TRLLD_TRANSMIT_OK) { printf("oltr%d: TRlldTransmitFrame returned %d\n", sc->unit, rc); ifp->if_oerrors++; goto bad; } sc->tx_avail -= sc->frame_ring[frame].FragmentCount; sc->tx_head = RING_BUFFER((sc->tx_head + sc->frame_ring[frame].FragmentCount)); sc->tx_frame++; #if (NBPFILTER > 0) || (__FreeBSD_version > 400000) if (ifp->if_bpf) bpf_mtap(ifp, m0); #endif /*ifp->if_opackets++;*/ bad: m_freem(m0); goto outloop; nobuffers: printf("oltr%d: queue full\n", sc->unit); ifp->if_flags |= IFF_OACTIVE; ifp->if_oerrors++; /*m_freem(m0);*/ sc->restart = m0; return; } static void oltr_close(struct oltr_softc *sc) { /*printf("oltr%d: oltr_close\n", sc->unit);*/ oltr_stop(sc); tsleep(sc, PWAIT, "oltrclose", 30*hz); } static void oltr_stop(struct oltr_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; /*printf("oltr%d: oltr_stop\n", sc->unit);*/ ifp->if_flags &= ~(IFF_UP | IFF_RUNNING | IFF_OACTIVE); TRlldClose(sc->TRlldAdapter, 0); sc->state = OL_CLOSING; } static void oltr_init(void * xsc) { struct oltr_softc *sc = (struct oltr_softc *)xsc; struct ifnet *ifp = &sc->arpcom.ac_if; struct ifmedia *ifm = &sc->ifmedia; int poll = 0, i, rc = 0, s; int work_size; /* * Check adapter state, don't allow multiple inits */ if (sc->state > OL_CLOSED) { printf("oltr%d: adapter not ready\n", sc->unit); return; } s = splimp(); /* * Initialize Adapter */ if ((rc = TRlldAdapterInit(&LldDriver, sc->TRlldAdapter, vtophys(sc->TRlldAdapter), (void *)sc, &sc->config)) != TRLLD_INIT_OK) { switch(rc) { case TRLLD_INIT_NOT_FOUND: printf("oltr%d: adapter not found\n", sc->unit); break; case TRLLD_INIT_UNSUPPORTED: printf("oltr%d: adapter not supported by low level driver\n", sc->unit); break; case TRLLD_INIT_PHYS16: printf("oltr%d: adapter memory block above 16M cannot DMA\n", sc->unit); break; case TRLLD_INIT_VERSION: printf("oltr%d: low level driver version mismatch\n", sc->unit); break; default: printf("oltr%d: unknown init error %d\n", sc->unit, rc); break; } goto init_failed; } sc->state = OL_INIT; switch(sc->config.type) { case TRLLD_ADAPTER_PCI4: /* OC-3139 */ work_size = 32 * 1024; break; case TRLLD_ADAPTER_PCI7: /* OC-3540 */ work_size = 256; break; default: work_size = 0; } if (work_size) { if ((sc->work_memory = malloc(work_size, M_DEVBUF, M_NOWAIT)) == NULL) { printf("oltr%d: failed to allocate work memory (%d octets).\n", sc->unit, work_size); } else { TRlldAddMemory(sc->TRlldAdapter, sc->work_memory, vtophys(sc->work_memory), work_size); } } switch(IFM_SUBTYPE(ifm->ifm_media)) { case IFM_AUTO: rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */ break; case IFM_TOK_UTP4: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS); break; case IFM_TOK_UTP16: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS); break; case IFM_TOK_UTP100: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS); break; } /* * Download adapter micro-code */ if (bootverbose) printf("oltr%d: Downloading adapter microcode: ", sc->unit); switch(sc->config.mactype) { case TRLLD_MAC_TMS: rc = TRlldDownload(sc->TRlldAdapter, TRlldMacCode); if (bootverbose) printf("TMS-380"); break; case TRLLD_MAC_HAWKEYE: rc = TRlldDownload(sc->TRlldAdapter, TRlldHawkeyeMac); if (bootverbose) printf("Hawkeye"); break; case TRLLD_MAC_BULLSEYE: rc = TRlldDownload(sc->TRlldAdapter, TRlldBullseyeMac); if (bootverbose) printf("Bullseye"); break; default: if (bootverbose) printf("unknown - failed!\n"); goto init_failed; break; } /* * Check download status */ switch(rc) { case TRLLD_DOWNLOAD_OK: if (bootverbose) printf(" - ok\n"); break; case TRLLD_DOWNLOAD_ERROR: if (bootverbose) printf(" - failed\n"); else printf("oltr%d: adapter microcode download failed\n", sc->unit); goto init_failed; break; case TRLLD_STATE: if (bootverbose) printf(" - not ready\n"); goto init_failed; break; } /* * Wait for self-test to complete */ i = 0; while ((poll++ < SELF_TEST_POLLS) && (sc->state < OL_READY)) { if (DEBUG_MASK & DEBUG_INIT) printf("p"); DELAY(TRlldPoll(sc->TRlldAdapter) * 1000); if (TRlldInterruptService(sc->TRlldAdapter) != 0) if (DEBUG_MASK & DEBUG_INIT) printf("i"); } if (sc->state != OL_CLOSED) { printf("oltr%d: self-test failed\n", sc->unit); goto init_failed; } /* * Set up adapter poll */ callout_handle_init(&sc->oltr_poll_ch); sc->oltr_poll_ch = timeout(oltr_poll, (void *)sc, 1); sc->state = OL_OPENING; /* * Open the adapter */ rc = TRlldOpen(sc->TRlldAdapter, sc->arpcom.ac_enaddr, sc->GroupAddress, sc->FunctionalAddress, 1552, sc->AdapterMode); switch(rc) { case TRLLD_OPEN_OK: break; case TRLLD_OPEN_STATE: printf("oltr%d: adapter not ready for open\n", sc->unit); (void)splx(s); return; case TRLLD_OPEN_ADDRESS_ERROR: printf("oltr%d: illegal MAC address\n", sc->unit); (void)splx(s); return; case TRLLD_OPEN_MODE_ERROR: printf("oltr%d: illegal open mode\n", sc->unit); (void)splx(s); return; default: printf("oltr%d: unknown open error (%d)\n", sc->unit, rc); (void)splx(s); return; } /* * Set promiscious mode for now... */ TRlldSetPromiscuousMode(sc->TRlldAdapter, TRLLD_PROM_LLC); ifp->if_flags |= IFF_PROMISC; /* * Block on the ring insert and set a timeout */ tsleep(sc, PWAIT, "oltropen", 30*hz); /* * Set up receive buffer ring */ for (i = 0; i < RING_BUFFER_LEN; i++) { rc = TRlldReceiveFragment(sc->TRlldAdapter, (void *)sc->rx_ring[i].data, sc->rx_ring[i].address, RX_BUFFER_LEN, (void *)sc->rx_ring[i].index); if (rc != TRLLD_RECEIVE_OK) { printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc); break; } } sc->tx_avail = RING_BUFFER_LEN; sc->tx_head = 0; sc->tx_frame = 0; sc->restart = NULL; ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; /* * Set up adapter statistics poll */ /*callout_handle_init(&sc->oltr_stat_ch);*/ /*sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz);*/ (void)splx(s); return; init_failed: sc->state = OL_DEAD; (void)splx(s); return; } static int oltr_ioctl(struct ifnet *ifp, u_long command, caddr_t data) { struct oltr_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; int error = 0, s; s = splimp(); switch(command) { case SIOCSIFADDR: case SIOCGIFADDR: case SIOCSIFMTU: error = iso88025_ioctl(ifp, command, data); break; case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { oltr_init(sc); } else { if (ifp->if_flags & IFF_RUNNING) { oltr_close(sc); } } break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); break; default: error = EINVAL; break; } (void)splx(s); return(error); } void oltr_poll(void *arg) { struct oltr_softc *sc = (struct oltr_softc *)arg; int s; s = splimp(); if (DEBUG_MASK & DEBUG_POLL) printf("P"); /* Set up next adapter poll */ sc->oltr_poll_ch = timeout(oltr_poll, (void *)sc, (TRlldPoll(sc->TRlldAdapter) * hz / 1000)); (void)splx(s); } #ifdef NOTYET void oltr_stat(void *arg) { struct oltr_softc *sc = (struct oltr_softc *)arg; int s; s = splimp(); /* Set up next adapter poll */ sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz); if (TRlldGetStatistics(sc->TRlldAdapter, &sc->current, 0) != 0) { /*printf("oltr%d: statistics available immediately...\n", sc->unit);*/ DriverStatistics((void *)sc, &sc->current); } (void)splx(s); } #endif static int oltr_ifmedia_upd(struct ifnet *ifp) { struct oltr_softc *sc = ifp->if_softc; struct ifmedia *ifm = &sc->ifmedia; int rc; if (IFM_TYPE(ifm->ifm_media) != IFM_TOKEN) return(EINVAL); switch(IFM_SUBTYPE(ifm->ifm_media)) { case IFM_AUTO: rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */ break; case IFM_TOK_UTP4: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS); break; case IFM_TOK_UTP16: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS); break; case IFM_TOK_UTP100: rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS); break; default: return(EINVAL); break; } return(0); } static void oltr_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) { struct oltr_softc *sc = ifp->if_softc; struct ifmedia *ifm = &sc->ifmedia; /*printf("oltr%d: oltr_ifmedia_sts\n", sc->unit);*/ ifmr->ifm_active = IFM_TYPE(ifm->ifm_media)|IFM_SUBTYPE(ifm->ifm_media); } /* * ---------------------- PMW Callback Functions ----------------------- */ void DriverStatistics(void *DriverHandle, TRlldStatistics_t *statistics) { #ifdef NOTYET struct oltr_softc *sc = (struct oltr_softc *)DriverHandle; if (sc->statistics.LineErrors != statistics->LineErrors) printf("oltr%d: Line Errors %lu\n", sc->unit, statistics->LineErrors); if (sc->statistics.InternalErrors != statistics->InternalErrors) printf("oltr%d: Internal Errors %lu\n", sc->unit, statistics->InternalErrors); if (sc->statistics.BurstErrors != statistics->BurstErrors) printf("oltr%d: Burst Errors %lu\n", sc->unit, statistics->BurstErrors); if (sc->statistics.AbortDelimiters != statistics->AbortDelimiters) printf("oltr%d: Abort Delimiters %lu\n", sc->unit, statistics->AbortDelimiters); if (sc->statistics.ARIFCIErrors != statistics->ARIFCIErrors) printf("oltr%d: ARIFCI Errors %lu\n", sc->unit, statistics->ARIFCIErrors); if (sc->statistics.LostFrames != statistics->LostFrames) printf("oltr%d: Lost Frames %lu\n", sc->unit, statistics->LostFrames); if (sc->statistics.CongestionErrors != statistics->CongestionErrors) printf("oltr%d: Congestion Errors %lu\n", sc->unit, statistics->CongestionErrors); if (sc->statistics.FrequencyErrors != statistics->FrequencyErrors) printf("oltr%d: Frequency Errors %lu\n", sc->unit, statistics->FrequencyErrors); if (sc->statistics.TokenErrors != statistics->TokenErrors) printf("oltr%d: Token Errors %lu\n", sc->unit, statistics->TokenErrors); if (sc->statistics.DMABusErrors != statistics->DMABusErrors) printf("oltr%d: DMA Bus Errors %lu\n", sc->unit, statistics->DMABusErrors); if (sc->statistics.DMAParityErrors != statistics->DMAParityErrors) printf("oltr%d: DMA Parity Errors %lu\n", sc->unit, statistics->DMAParityErrors); if (sc->statistics.ReceiveLongFrame != statistics->ReceiveLongFrame) printf("oltr%d: Long frames received %lu\n", sc->unit, statistics->ReceiveLongFrame); if (sc->statistics.ReceiveCRCErrors != statistics->ReceiveCRCErrors) printf("oltr%d: Receive CRC Errors %lu\n", sc->unit, statistics->ReceiveCRCErrors); if (sc->statistics.ReceiveOverflow != statistics->ReceiveOverflow) printf("oltr%d: Recieve overflows %lu\n", sc->unit, statistics->ReceiveOverflow); if (sc->statistics.TransmitUnderrun != statistics->TransmitUnderrun) printf("oltr%d: Frequency Errors %lu\n", sc->unit, statistics->TransmitUnderrun); bcopy(statistics, &sc->statistics, sizeof(TRlldStatistics_t)); #endif } static void DriverSuspend(unsigned short MicroSeconds) { DELAY(MicroSeconds); } static void DriverStatus(void *DriverHandle, TRlldStatus_t *Status) { struct oltr_softc *sc = (struct oltr_softc *)DriverHandle; struct ifnet *ifp = &sc->arpcom.ac_if; char *Protocol[] = { /* 0 */ "Unknown", /* 1 */ "TKP", /* 2 */ "TXI" }; char *Timeout[] = { /* 0 */ "command", /* 1 */ "transmit", /* 2 */ "interrupt" }; switch (Status->Type) { case TRLLD_STS_ON_WIRE: printf("oltr%d: ring insert (%d Mbps - %s)\n", sc->unit, Status->Specification.OnWireInformation.Speed, Protocol[Status->Specification.OnWireInformation.AccessProtocol]); sc->state = OL_OPEN; wakeup(sc); break; case TRLLD_STS_SELFTEST_STATUS: if (Status->Specification.SelftestStatus == TRLLD_ST_OK) { sc->state = OL_CLOSED; if (bootverbose) printf("oltr%d: self test complete\n", sc->unit); } if (Status->Specification.SelftestStatus & TRLLD_ST_ERROR) { printf("oltr%d: Adapter self test error %d", sc->unit, Status->Specification.SelftestStatus & ~TRLLD_ST_ERROR); sc->state = OL_DEAD; } if (Status->Specification.SelftestStatus & TRLLD_ST_TIMEOUT) { printf("oltr%d: Adapter self test timed out.\n", sc->unit); sc->state = OL_DEAD; } break; case TRLLD_STS_INIT_STATUS: if (Status->Specification.InitStatus == 0x800) { oltr_stop(sc); ifmedia_set(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16); TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS); oltr_init(sc); break; } printf("oltr%d: adapter init failure 0x%03x\n", sc->unit, Status->Specification.InitStatus); oltr_stop(sc); break; case TRLLD_STS_RING_STATUS: if (Status->Specification.RingStatus) { printf("oltr%d: Ring status change: ", sc->unit); if (Status->Specification.RingStatus & TRLLD_RS_SIGNAL_LOSS) printf(" [Signal Loss]"); if (Status->Specification.RingStatus & TRLLD_RS_HARD_ERROR) printf(" [Hard Error]"); if (Status->Specification.RingStatus & TRLLD_RS_SOFT_ERROR) printf(" [Soft Error]"); if (Status->Specification.RingStatus & TRLLD_RS_TRANSMIT_BEACON) printf(" [Beacon]"); if (Status->Specification.RingStatus & TRLLD_RS_LOBE_WIRE_FAULT) printf(" [Wire Fault]"); if (Status->Specification.RingStatus & TRLLD_RS_AUTO_REMOVAL_ERROR) printf(" [Auto Removal]"); if (Status->Specification.RingStatus & TRLLD_RS_REMOVE_RECEIVED) printf(" [Remove Received]"); if (Status->Specification.RingStatus & TRLLD_RS_COUNTER_OVERFLOW) printf(" [Counter Overflow]"); if (Status->Specification.RingStatus & TRLLD_RS_SINGLE_STATION) printf(" [Single Station]"); if (Status->Specification.RingStatus & TRLLD_RS_RING_RECOVERY) printf(" [Ring Recovery]"); printf("\n"); } break; case TRLLD_STS_ADAPTER_CHECK: printf("oltr%d: adapter check (%04x %04x %04x %04x)\n", sc->unit, Status->Specification.AdapterCheck[0], Status->Specification.AdapterCheck[1], Status->Specification.AdapterCheck[2], Status->Specification.AdapterCheck[3]); sc->state = OL_DEAD; oltr_stop(sc); break; case TRLLD_STS_PROMISCUOUS_STOPPED: printf("oltr%d: promiscuous mode ", sc->unit); if (Status->Specification.PromRemovedCause == 1) printf("remove received."); if (Status->Specification.PromRemovedCause == 2) printf("poll failure."); if (Status->Specification.PromRemovedCause == 2) printf("buffer size failure."); printf("\n"); ifp->if_flags &= ~IFF_PROMISC; break; case TRLLD_STS_LLD_ERROR: printf("oltr%d: low level driver internal error ", sc->unit); printf("(%04x %04x %04x %04x).\n", Status->Specification.InternalError[0], Status->Specification.InternalError[1], Status->Specification.InternalError[2], Status->Specification.InternalError[3]); sc->state = OL_DEAD; oltr_stop(sc); break; case TRLLD_STS_ADAPTER_TIMEOUT: printf("oltr%d: adapter %s timeout.\n", sc->unit, Timeout[Status->Specification.AdapterTimeout]); break; default: printf("oltr%d: driver status Type = %d\n", sc->unit, Status->Type); break; } if (Status->Closed) { sc->state = OL_CLOSING; oltr_stop(sc); } } static void DriverCloseCompleted(void *DriverHandle) { struct oltr_softc *sc = (struct oltr_softc *)DriverHandle; printf("oltr%d: adapter closed\n", sc->unit); wakeup(sc); sc->state = OL_CLOSED; } static void DriverTransmitFrameCompleted(void *DriverHandle, void *FrameHandle, int TransmitStatus) { struct oltr_softc *sc = (struct oltr_softc *)DriverHandle; struct ifnet *ifp = &sc->arpcom.ac_if; TRlldTransmit_t *frame = (TRlldTransmit_t *)FrameHandle; /*printf("oltr%d: DriverTransmitFrameCompleted\n", sc->unit);*/ if (TransmitStatus != TRLLD_TRANSMIT_OK) { ifp->if_oerrors++; printf("oltr%d: transmit error %d\n", sc->unit, TransmitStatus); } else { ifp->if_opackets++; } sc->tx_avail += frame->FragmentCount; if (ifp->if_flags & IFF_OACTIVE) { printf("oltr%d: queue restart\n", sc->unit); ifp->if_flags &= ~IFF_OACTIVE; oltr_start(ifp); } } static void DriverReceiveFrameCompleted(void *DriverHandle, int ByteCount, int FragmentCount, void *FragmentHandle, int ReceiveStatus) { struct oltr_softc *sc = (struct oltr_softc *)DriverHandle; struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if; struct mbuf *m0, *m1, *m; struct iso88025_header *th; int frame_len = ByteCount, hdr_len, i = (int)FragmentHandle, rc, s; int mbuf_offset, mbuf_size, frag_offset, copy_length; char *fragment = sc->rx_ring[RING_BUFFER(i)].data; if (sc->state > OL_CLOSED) { if (ReceiveStatus == TRLLD_RCV_OK) { MGETHDR(m0, M_DONTWAIT, MT_DATA); mbuf_size = MHLEN - 2; if (!m0) { ifp->if_ierrors++; goto dropped; } if (ByteCount + 2 > MHLEN) { MCLGET(m0, M_DONTWAIT); mbuf_size = MCLBYTES - 2; if (!(m0->m_flags & M_EXT)) { m_freem(m0); ifp->if_ierrors++; goto dropped; } } m0->m_pkthdr.rcvif = ifp; m0->m_pkthdr.len = ByteCount; m0->m_len = 0; m0->m_data += 2; th = mtod(m0, struct iso88025_header *); m0->m_pkthdr.header = (void *)th; m = m0; mbuf_offset = 0; frag_offset = 0; while (frame_len) { copy_length = MIN3(frame_len, (RX_BUFFER_LEN - frag_offset), (mbuf_size - mbuf_offset)); bcopy(fragment + frag_offset, mtod(m, char *) + mbuf_offset, copy_length); m->m_len += copy_length; mbuf_offset += copy_length; frag_offset += copy_length; frame_len -= copy_length; if (frag_offset == RX_BUFFER_LEN) { fragment = sc->rx_ring[RING_BUFFER(++i)].data; frag_offset = 0; } if ((mbuf_offset == mbuf_size) && (frame_len > 0)) { MGET(m1, M_DONTWAIT, MT_DATA); mbuf_size = MHLEN; if (!m1) { ifp->if_ierrors++; m_freem(m0); goto dropped; } if (frame_len > MHLEN) { MCLGET(m1, M_DONTWAIT); mbuf_size = MCLBYTES; if (!(m1->m_flags & M_EXT)) { m_freem(m0); m_freem(m1); ifp->if_ierrors++; goto dropped; } } m->m_next = m1; m = m1; mbuf_offset = 0; m->m_len = 0; } } #if (NBPFILTER > 0) || (__FreeBSD_version > 400000) if (ifp->if_bpf) bpf_mtap(ifp, m0); #endif /*if (ifp->if_flags & IFF_PROMISC) {*/ if (bcmp(th->iso88025_dhost, etherbroadcastaddr , sizeof(th->iso88025_dhost))) { if ((bcmp(th->iso88025_dhost + 1, sc->arpcom.ac_enaddr + 1, ISO88025_ADDR_LEN - 1)) || ((th->iso88025_dhost[0] & 0x7f) != sc->arpcom.ac_enaddr[0])) { m_freem(m0); goto dropped; } } /*}*/ ifp->if_ipackets++; hdr_len = ISO88025_HDR_LEN; if (th->iso88025_shost[0] & 0x80) hdr_len += (ntohs(th->rcf) & 0x1f00) >> 8; m0->m_pkthdr.len -= hdr_len; m0->m_len -= hdr_len; m0->m_data += hdr_len; iso88025_input(ifp, th, m0); } else { /* Receiver error */ if (ReceiveStatus != TRLLD_RCV_NO_DATA) { printf("oltr%d: receive error %d\n", sc->unit, ReceiveStatus); ifp->if_ierrors++; } } dropped: s = splimp(); i = (int)FragmentHandle; while (FragmentCount--) { rc = TRlldReceiveFragment(sc->TRlldAdapter, (void *)sc->rx_ring[RING_BUFFER(i)].data, sc->rx_ring[RING_BUFFER(i)].address, RX_BUFFER_LEN, (void *)sc->rx_ring[RING_BUFFER(i)].index); if (rc != TRLLD_RECEIVE_OK) { printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc); break; } i++; } (void)splx(s); } } /* * ---------------------------- PMW Glue ------------------------------- */ #ifndef TRlldInlineIO static void DriverOutByte(unsigned short IOAddress, unsigned char value) { outb(IOAddress, value); } static void DriverOutWord(unsigned short IOAddress, unsigned short value) { outw(IOAddress, value); } static void DriverOutDword(unsigned short IOAddress, unsigned long value) { outl(IOAddress, value); } static void DriverRepOutByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount) { outsb(IOAddress, (void *)DataPointer, ByteCount); } static void DriverRepOutWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount) { outsw(IOAddress, (void *)DataPointer, WordCount); } static void DriverRepOutDword(unsigned short IOAddress, unsigned long *DataPointer, int DWordCount) { outsl(IOAddress, (void *)DataPointer, DWordCount); } static unsigned char DriverInByte(unsigned short IOAddress) { return(inb(IOAddress)); } static unsigned short DriverInWord(unsigned short IOAddress) { return(inw(IOAddress)); } static unsigned long DriverInDword(unsigned short IOAddress) { return(inl(IOAddress)); } static void DriverRepInByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount) { insb(IOAddress, (void *)DataPointer, ByteCount); } static void DriverRepInWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount) { insw(IOAddress, (void *)DataPointer, WordCount); } static void DriverRepInDword( unsigned short IOAddress, unsigned long *DataPointer, int DWordCount) { insl(IOAddress, (void *)DataPointer, DWordCount); } #endif /* TRlldInlineIO */