1153203Sobrien/*- 2144073Sobrien * Copyright (c) 2005 by David E. O'Brien <obrien@FreeBSD.org>. 3143442Sobrien * Copyright (c) 2003,2004 by Quinton Dolan <q@onthenet.com.au>. 4143442Sobrien * All rights reserved. 5143442Sobrien * 6143442Sobrien * Redistribution and use in source and binary forms, with or without 7143442Sobrien * modification, are permitted provided that the following conditions 8143442Sobrien * are met: 9143442Sobrien * 1. Redistributions of source code must retain the above copyright 10143442Sobrien * notice, this list of conditions and the following disclaimer. 11143442Sobrien * 2. Redistributions in binary form must reproduce the above copyright 12143442Sobrien * notice, this list of conditions and the following disclaimer in the 13143442Sobrien * documentation and/or other materials provided with the distribution. 14143442Sobrien * 15143442Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 16143442Sobrien * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17143442Sobrien * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18143442Sobrien * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19143442Sobrien * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20143442Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21143442Sobrien * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22143442Sobrien * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23143442Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24143442Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25143442Sobrien * SUCH DAMAGE. 26143442Sobrien * 27143442Sobrien * $Id: if_nv.c,v 1.19 2004/08/12 14:00:05 q Exp $ 28143442Sobrien */ 29143442Sobrien/* 30143442Sobrien * NVIDIA nForce MCP Networking Adapter driver 31143442Sobrien * 32143442Sobrien * This is a port of the NVIDIA MCP Linux ethernet driver distributed by NVIDIA 33143442Sobrien * through their web site. 34143442Sobrien * 35143442Sobrien * All mainstream nForce and nForce2 motherboards are supported. This module 36143442Sobrien * is as stable, sometimes more stable, than the linux version. (Recent 37143442Sobrien * Linux stability issues seem to be related to some issues with newer 38143442Sobrien * distributions using GCC 3.x, however this don't appear to effect FreeBSD 39143442Sobrien * 5.x). 40143442Sobrien * 41143442Sobrien * In accordance with the NVIDIA distribution license it is necessary to 42143442Sobrien * link this module against the nvlibnet.o binary object included in the 43143442Sobrien * Linux driver source distribution. The binary component is not modified in 44143442Sobrien * any way and is simply linked against a FreeBSD equivalent of the nvnet.c 45143442Sobrien * linux kernel module "wrapper". 46143442Sobrien * 47143442Sobrien * The Linux driver uses a common code API that is shared between Win32 and 48143442Sobrien * i386 Linux. This abstracts the low level driver functions and uses 49143442Sobrien * callbacks and hooks to access the underlying hardware device. By using 50143442Sobrien * this same API in a FreeBSD kernel module it is possible to support the 51143442Sobrien * hardware without breaching the Linux source distributions licensing 52143442Sobrien * requirements, or obtaining the hardware programming specifications. 53143442Sobrien * 54143442Sobrien * Although not conventional, it works, and given the relatively small 55143442Sobrien * amount of hardware centric code, it's hopefully no more buggy than its 56143442Sobrien * linux counterpart. 57143442Sobrien * 58145998Sbrueffer * NVIDIA now support the nForce3 AMD64 platform, however I have been 59143442Sobrien * unable to access such a system to verify support. However, the code is 60143442Sobrien * reported to work with little modification when compiled with the AMD64 61143442Sobrien * version of the NVIDIA Linux library. All that should be necessary to make 62143442Sobrien * the driver work is to link it directly into the kernel, instead of as a 63143442Sobrien * module, and apply the docs/amd64.diff patch in this source distribution to 64143442Sobrien * the NVIDIA Linux driver source. 65143442Sobrien * 66143442Sobrien * This driver should work on all versions of FreeBSD since 4.9/5.1 as well 67143442Sobrien * as recent versions of DragonFly. 68143442Sobrien * 69143442Sobrien * Written by Quinton Dolan <q@onthenet.com.au> 70143442Sobrien * Portions based on existing FreeBSD network drivers. 71143442Sobrien * NVIDIA API usage derived from distributed NVIDIA NVNET driver source files. 72143442Sobrien */ 73143442Sobrien 74143442Sobrien#include <sys/cdefs.h> 75143442Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/dev/nve/if_nve.c 243857 2012-12-04 09:32:43Z glebius $"); 76143442Sobrien 77143442Sobrien#include <sys/param.h> 78143442Sobrien#include <sys/systm.h> 79143442Sobrien#include <sys/sockio.h> 80143442Sobrien#include <sys/mbuf.h> 81143442Sobrien#include <sys/malloc.h> 82143442Sobrien#include <sys/kernel.h> 83143442Sobrien#include <sys/socket.h> 84143442Sobrien#include <sys/sysctl.h> 85143442Sobrien#include <sys/queue.h> 86143442Sobrien#include <sys/module.h> 87143442Sobrien 88143442Sobrien#include <net/if.h> 89143442Sobrien#include <net/if_arp.h> 90143442Sobrien#include <net/ethernet.h> 91143442Sobrien#include <net/if_dl.h> 92143442Sobrien#include <net/if_media.h> 93147256Sbrooks#include <net/if_types.h> 94143442Sobrien#include <net/bpf.h> 95143442Sobrien#include <net/if_vlan_var.h> 96143442Sobrien 97143442Sobrien#include <machine/bus.h> 98143442Sobrien#include <machine/resource.h> 99143442Sobrien 100143442Sobrien#include <vm/vm.h> /* for vtophys */ 101143442Sobrien#include <vm/pmap.h> /* for vtophys */ 102143442Sobrien#include <sys/bus.h> 103143442Sobrien#include <sys/rman.h> 104143442Sobrien 105143442Sobrien#include <dev/pci/pcireg.h> 106143442Sobrien#include <dev/pci/pcivar.h> 107143442Sobrien#include <dev/mii/mii.h> 108143442Sobrien#include <dev/mii/miivar.h> 109143442Sobrien#include "miibus_if.h" 110143442Sobrien 111143442Sobrien/* Include NVIDIA Linux driver header files */ 112153203Sobrien#include <contrib/dev/nve/nvenet_version.h> 113143442Sobrien#define linux 114143442Sobrien#include <contrib/dev/nve/basetype.h> 115143442Sobrien#include <contrib/dev/nve/phy.h> 116143442Sobrien#include "os+%DIKED-nve.h" 117143442Sobrien#include <contrib/dev/nve/drvinfo.h> 118143442Sobrien#include <contrib/dev/nve/adapter.h> 119143442Sobrien#undef linux 120143442Sobrien 121143442Sobrien#include <dev/nve/if_nvereg.h> 122143442Sobrien 123143442SobrienMODULE_DEPEND(nve, pci, 1, 1, 1); 124143442SobrienMODULE_DEPEND(nve, ether, 1, 1, 1); 125143442SobrienMODULE_DEPEND(nve, miibus, 1, 1, 1); 126143442Sobrien 127143442Sobrienstatic int nve_probe(device_t); 128143442Sobrienstatic int nve_attach(device_t); 129143442Sobrienstatic int nve_detach(device_t); 130143442Sobrienstatic void nve_init(void *); 131152669Sjhbstatic void nve_init_locked(struct nve_softc *); 132143442Sobrienstatic void nve_stop(struct nve_softc *); 133173839Syongaristatic int nve_shutdown(device_t); 134143442Sobrienstatic int nve_init_rings(struct nve_softc *); 135143442Sobrienstatic void nve_free_rings(struct nve_softc *); 136143442Sobrien 137143442Sobrienstatic void nve_ifstart(struct ifnet *); 138152669Sjhbstatic void nve_ifstart_locked(struct ifnet *); 139143442Sobrienstatic int nve_ioctl(struct ifnet *, u_long, caddr_t); 140143442Sobrienstatic void nve_intr(void *); 141143442Sobrienstatic void nve_tick(void *); 142143442Sobrienstatic void nve_setmulti(struct nve_softc *); 143199560Sjhbstatic void nve_watchdog(struct nve_softc *); 144143442Sobrienstatic void nve_update_stats(struct nve_softc *); 145143442Sobrien 146143442Sobrienstatic int nve_ifmedia_upd(struct ifnet *); 147152669Sjhbstatic void nve_ifmedia_upd_locked(struct ifnet *); 148143442Sobrienstatic void nve_ifmedia_sts(struct ifnet *, struct ifmediareq *); 149143442Sobrienstatic int nve_miibus_readreg(device_t, int, int); 150188175Simpstatic int nve_miibus_writereg(device_t, int, int, int); 151143442Sobrien 152143442Sobrienstatic void nve_dmamap_cb(void *, bus_dma_segment_t *, int, int); 153143442Sobrienstatic void nve_dmamap_tx_cb(void *, bus_dma_segment_t *, int, bus_size_t, int); 154143442Sobrien 155242873Sdimstatic NV_API_CALL NV_SINT32 nve_osalloc(PNV_VOID, PMEMORY_BLOCK); 156242873Sdimstatic NV_API_CALL NV_SINT32 nve_osfree(PNV_VOID, PMEMORY_BLOCK); 157242873Sdimstatic NV_API_CALL NV_SINT32 nve_osallocex(PNV_VOID, PMEMORY_BLOCKEX); 158242873Sdimstatic NV_API_CALL NV_SINT32 nve_osfreeex(PNV_VOID, PMEMORY_BLOCKEX); 159242873Sdimstatic NV_API_CALL NV_SINT32 nve_osclear(PNV_VOID, PNV_VOID, NV_SINT32); 160242873Sdimstatic NV_API_CALL NV_SINT32 nve_osdelay(PNV_VOID, NV_UINT32); 161242873Sdimstatic NV_API_CALL NV_SINT32 nve_osallocrxbuf(PNV_VOID, PMEMORY_BLOCK, PNV_VOID *); 162242873Sdimstatic NV_API_CALL NV_SINT32 nve_osfreerxbuf(PNV_VOID, PMEMORY_BLOCK, PNV_VOID); 163242873Sdimstatic NV_API_CALL NV_SINT32 nve_ospackettx(PNV_VOID, PNV_VOID, NV_UINT32); 164242873Sdimstatic NV_API_CALL NV_SINT32 nve_ospacketrx(PNV_VOID, PNV_VOID, NV_UINT32, NV_UINT8 *, NV_UINT8); 165242873Sdimstatic NV_API_CALL NV_SINT32 nve_oslinkchg(PNV_VOID, NV_SINT32); 166242873Sdimstatic NV_API_CALL NV_SINT32 nve_osalloctimer(PNV_VOID, PNV_VOID *); 167242873Sdimstatic NV_API_CALL NV_SINT32 nve_osfreetimer(PNV_VOID, PNV_VOID); 168242873Sdimstatic NV_API_CALL NV_SINT32 nve_osinittimer(PNV_VOID, PNV_VOID, PTIMER_FUNC, PNV_VOID); 169242873Sdimstatic NV_API_CALL NV_SINT32 nve_ossettimer(PNV_VOID, PNV_VOID, NV_UINT32); 170242873Sdimstatic NV_API_CALL NV_SINT32 nve_oscanceltimer(PNV_VOID, PNV_VOID); 171143442Sobrien 172242873Sdimstatic NV_API_CALL NV_SINT32 nve_ospreprocpkt(PNV_VOID, PNV_VOID, PNV_VOID *, NV_UINT8 *, NV_UINT8); 173242873Sdimstatic NV_API_CALL PNV_VOID nve_ospreprocpktnopq(PNV_VOID, PNV_VOID); 174242873Sdimstatic NV_API_CALL NV_SINT32 nve_osindicatepkt(PNV_VOID, PNV_VOID *, NV_UINT32); 175242873Sdimstatic NV_API_CALL NV_SINT32 nve_oslockalloc(PNV_VOID, NV_SINT32, PNV_VOID *); 176242873Sdimstatic NV_API_CALL NV_SINT32 nve_oslockacquire(PNV_VOID, NV_SINT32, PNV_VOID); 177242873Sdimstatic NV_API_CALL NV_SINT32 nve_oslockrelease(PNV_VOID, NV_SINT32, PNV_VOID); 178242873Sdimstatic NV_API_CALL PNV_VOID nve_osreturnbufvirt(PNV_VOID, PNV_VOID); 179143442Sobrien 180143442Sobrienstatic device_method_t nve_methods[] = { 181143442Sobrien /* Device interface */ 182143442Sobrien DEVMETHOD(device_probe, nve_probe), 183143442Sobrien DEVMETHOD(device_attach, nve_attach), 184143442Sobrien DEVMETHOD(device_detach, nve_detach), 185143442Sobrien DEVMETHOD(device_shutdown, nve_shutdown), 186143442Sobrien 187143442Sobrien /* MII interface */ 188143442Sobrien DEVMETHOD(miibus_readreg, nve_miibus_readreg), 189143442Sobrien DEVMETHOD(miibus_writereg, nve_miibus_writereg), 190143442Sobrien 191227843Smarius DEVMETHOD_END 192143442Sobrien}; 193143442Sobrien 194143442Sobrienstatic driver_t nve_driver = { 195145556Sobrien "nve", 196143442Sobrien nve_methods, 197143442Sobrien sizeof(struct nve_softc) 198143442Sobrien}; 199143442Sobrien 200143442Sobrienstatic devclass_t nve_devclass; 201143442Sobrien 202143442Sobrienstatic int nve_pollinterval = 0; 203143442SobrienSYSCTL_INT(_hw, OID_AUTO, nve_pollinterval, CTLFLAG_RW, 204143442Sobrien &nve_pollinterval, 0, "delay between interface polls"); 205143442Sobrien 206143442SobrienDRIVER_MODULE(nve, pci, nve_driver, nve_devclass, 0, 0); 207143442SobrienDRIVER_MODULE(miibus, nve, miibus_driver, miibus_devclass, 0, 0); 208143442Sobrien 209143442Sobrienstatic struct nve_type nve_devs[] = { 210179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_LAN, 211179458Sremko "NVIDIA nForce MCP Networking Adapter"}, 212179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_LAN, 213179458Sremko "NVIDIA nForce2 MCP2 Networking Adapter"}, 214179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1, 215179458Sremko "NVIDIA nForce2 400 MCP4 Networking Adapter"}, 216179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2, 217179458Sremko "NVIDIA nForce2 400 MCP5 Networking Adapter"}, 218179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN1, 219179458Sremko "NVIDIA nForce3 MCP3 Networking Adapter"}, 220179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_250_LAN, 221179458Sremko "NVIDIA nForce3 250 MCP6 Networking Adapter"}, 222179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN4, 223179458Sremko "NVIDIA nForce3 MCP7 Networking Adapter"}, 224179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN1, 225179458Sremko "NVIDIA nForce4 CK804 MCP8 Networking Adapter"}, 226179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN2, 227179458Sremko "NVIDIA nForce4 CK804 MCP9 Networking Adapter"}, 228179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN1, 229179458Sremko "NVIDIA nForce MCP04 Networking Adapter"}, // MCP10 230179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN2, 231179458Sremko "NVIDIA nForce MCP04 Networking Adapter"}, // MCP11 232179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN1, 233179458Sremko "NVIDIA nForce 430 MCP12 Networking Adapter"}, 234179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN2, 235179458Sremko "NVIDIA nForce 430 MCP13 Networking Adapter"}, 236179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN1, 237179458Sremko "NVIDIA nForce MCP55 Networking Adapter"}, 238179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN2, 239179458Sremko "NVIDIA nForce MCP55 Networking Adapter"}, 240179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN1, 241179458Sremko "NVIDIA nForce MCP61 Networking Adapter"}, 242179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2, 243179458Sremko "NVIDIA nForce MCP61 Networking Adapter"}, 244179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN3, 245179458Sremko "NVIDIA nForce MCP61 Networking Adapter"}, 246179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN4, 247179458Sremko "NVIDIA nForce MCP61 Networking Adapter"}, 248179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1, 249179458Sremko "NVIDIA nForce MCP65 Networking Adapter"}, 250179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2, 251179458Sremko "NVIDIA nForce MCP65 Networking Adapter"}, 252179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN3, 253179458Sremko "NVIDIA nForce MCP65 Networking Adapter"}, 254179458Sremko {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN4, 255179458Sremko "NVIDIA nForce MCP65 Networking Adapter"}, 256143442Sobrien {0, 0, NULL} 257143442Sobrien}; 258143442Sobrien 259143442Sobrien/* DMA MEM map callback function to get data segment physical address */ 260143442Sobrienstatic void 261143442Sobriennve_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nsegs, int error) 262143442Sobrien{ 263143442Sobrien if (error) 264143442Sobrien return; 265143442Sobrien 266143442Sobrien KASSERT(nsegs == 1, 267143442Sobrien ("Too many DMA segments returned when mapping DMA memory")); 268143442Sobrien *(bus_addr_t *)arg = segs->ds_addr; 269143442Sobrien} 270143442Sobrien 271143442Sobrien/* DMA RX map callback function to get data segment physical address */ 272143442Sobrienstatic void 273143442Sobriennve_dmamap_rx_cb(void *arg, bus_dma_segment_t * segs, int nsegs, 274143442Sobrien bus_size_t mapsize, int error) 275143442Sobrien{ 276143442Sobrien if (error) 277143442Sobrien return; 278143442Sobrien *(bus_addr_t *)arg = segs->ds_addr; 279143442Sobrien} 280143442Sobrien 281143442Sobrien/* 282143442Sobrien * DMA TX buffer callback function to allocate fragment data segment 283143442Sobrien * addresses 284143442Sobrien */ 285143442Sobrienstatic void 286143442Sobriennve_dmamap_tx_cb(void *arg, bus_dma_segment_t * segs, int nsegs, bus_size_t mapsize, int error) 287143442Sobrien{ 288143442Sobrien struct nve_tx_desc *info; 289143442Sobrien 290143442Sobrien info = arg; 291143442Sobrien if (error) 292143442Sobrien return; 293143442Sobrien KASSERT(nsegs < NV_MAX_FRAGS, 294143442Sobrien ("Too many DMA segments returned when mapping mbuf")); 295143442Sobrien info->numfrags = nsegs; 296143442Sobrien bcopy(segs, info->frags, nsegs * sizeof(bus_dma_segment_t)); 297143442Sobrien} 298143442Sobrien 299143442Sobrien/* Probe for supported hardware ID's */ 300143442Sobrienstatic int 301143442Sobriennve_probe(device_t dev) 302143442Sobrien{ 303143442Sobrien struct nve_type *t; 304143442Sobrien 305143442Sobrien t = nve_devs; 306143442Sobrien /* Check for matching PCI DEVICE ID's */ 307143442Sobrien while (t->name != NULL) { 308143442Sobrien if ((pci_get_vendor(dev) == t->vid_id) && 309143442Sobrien (pci_get_device(dev) == t->dev_id)) { 310143442Sobrien device_set_desc(dev, t->name); 311170593Syongari return (BUS_PROBE_LOW_PRIORITY); 312143442Sobrien } 313143442Sobrien t++; 314143442Sobrien } 315143442Sobrien 316143442Sobrien return (ENXIO); 317143442Sobrien} 318143442Sobrien 319143442Sobrien/* Attach driver and initialise hardware for use */ 320143442Sobrienstatic int 321143442Sobriennve_attach(device_t dev) 322143442Sobrien{ 323143442Sobrien u_char eaddr[ETHER_ADDR_LEN]; 324143442Sobrien struct nve_softc *sc; 325143442Sobrien struct ifnet *ifp; 326143442Sobrien OS_API *osapi; 327143442Sobrien ADAPTER_OPEN_PARAMS OpenParams; 328152669Sjhb int error = 0, i, rid; 329143442Sobrien 330153203Sobrien if (bootverbose) 331153203Sobrien device_printf(dev, "nvenetlib.o version %s\n", DRIVER_VERSION); 332153203Sobrien 333143442Sobrien DEBUGOUT(NVE_DEBUG_INIT, "nve: nve_attach - entry\n"); 334143442Sobrien 335143442Sobrien sc = device_get_softc(dev); 336143442Sobrien 337143442Sobrien /* Allocate mutex */ 338143442Sobrien mtx_init(&sc->mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 339153134Sjhb MTX_DEF); 340152669Sjhb callout_init_mtx(&sc->stat_callout, &sc->mtx, 0); 341143442Sobrien 342143442Sobrien sc->dev = dev; 343143442Sobrien 344143442Sobrien /* Preinitialize data structures */ 345143442Sobrien bzero(&OpenParams, sizeof(ADAPTER_OPEN_PARAMS)); 346143442Sobrien 347143442Sobrien /* Enable bus mastering */ 348143442Sobrien pci_enable_busmaster(dev); 349143442Sobrien 350143442Sobrien /* Allocate memory mapped address space */ 351143442Sobrien rid = NV_RID; 352143442Sobrien sc->res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 353143442Sobrien RF_ACTIVE); 354143442Sobrien 355143442Sobrien if (sc->res == NULL) { 356143442Sobrien device_printf(dev, "couldn't map memory\n"); 357143442Sobrien error = ENXIO; 358143442Sobrien goto fail; 359143442Sobrien } 360143442Sobrien sc->sc_st = rman_get_bustag(sc->res); 361143442Sobrien sc->sc_sh = rman_get_bushandle(sc->res); 362143442Sobrien 363143442Sobrien /* Allocate interrupt */ 364143442Sobrien rid = 0; 365143442Sobrien sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 366143442Sobrien RF_SHAREABLE | RF_ACTIVE); 367143442Sobrien 368143442Sobrien if (sc->irq == NULL) { 369143442Sobrien device_printf(dev, "couldn't map interrupt\n"); 370143442Sobrien error = ENXIO; 371143442Sobrien goto fail; 372143442Sobrien } 373143442Sobrien /* Allocate DMA tags */ 374232874Sscottl error = bus_dma_tag_create(bus_get_dma_tag(dev), 375232874Sscottl 4, 0, BUS_SPACE_MAXADDR_32BIT, 376143442Sobrien BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES * NV_MAX_FRAGS, 377143442Sobrien NV_MAX_FRAGS, MCLBYTES, 0, 378143442Sobrien busdma_lock_mutex, &Giant, 379143442Sobrien &sc->mtag); 380143442Sobrien if (error) { 381143442Sobrien device_printf(dev, "couldn't allocate dma tag\n"); 382143442Sobrien goto fail; 383143442Sobrien } 384232874Sscottl error = bus_dma_tag_create(bus_get_dma_tag(dev), 385232874Sscottl 4, 0, BUS_SPACE_MAXADDR_32BIT, 386143442Sobrien BUS_SPACE_MAXADDR, NULL, NULL, 387143442Sobrien sizeof(struct nve_rx_desc) * RX_RING_SIZE, 1, 388143442Sobrien sizeof(struct nve_rx_desc) * RX_RING_SIZE, 0, 389143442Sobrien busdma_lock_mutex, &Giant, 390143442Sobrien &sc->rtag); 391143442Sobrien if (error) { 392143442Sobrien device_printf(dev, "couldn't allocate dma tag\n"); 393143442Sobrien goto fail; 394143442Sobrien } 395232874Sscottl error = bus_dma_tag_create(bus_get_dma_tag(dev), 396232874Sscottl 4, 0, BUS_SPACE_MAXADDR_32BIT, 397143442Sobrien BUS_SPACE_MAXADDR, NULL, NULL, 398143442Sobrien sizeof(struct nve_tx_desc) * TX_RING_SIZE, 1, 399143442Sobrien sizeof(struct nve_tx_desc) * TX_RING_SIZE, 0, 400143442Sobrien busdma_lock_mutex, &Giant, 401143442Sobrien &sc->ttag); 402143442Sobrien if (error) { 403143442Sobrien device_printf(dev, "couldn't allocate dma tag\n"); 404143442Sobrien goto fail; 405143442Sobrien } 406143442Sobrien /* Allocate DMA safe memory and get the DMA addresses. */ 407143442Sobrien error = bus_dmamem_alloc(sc->ttag, (void **)&sc->tx_desc, 408143442Sobrien BUS_DMA_WAITOK, &sc->tmap); 409143442Sobrien if (error) { 410143442Sobrien device_printf(dev, "couldn't allocate dma memory\n"); 411143442Sobrien goto fail; 412143442Sobrien } 413143442Sobrien bzero(sc->tx_desc, sizeof(struct nve_tx_desc) * TX_RING_SIZE); 414143442Sobrien error = bus_dmamap_load(sc->ttag, sc->tmap, sc->tx_desc, 415143442Sobrien sizeof(struct nve_tx_desc) * TX_RING_SIZE, nve_dmamap_cb, 416143442Sobrien &sc->tx_addr, 0); 417143442Sobrien if (error) { 418143442Sobrien device_printf(dev, "couldn't map dma memory\n"); 419143442Sobrien goto fail; 420143442Sobrien } 421143442Sobrien error = bus_dmamem_alloc(sc->rtag, (void **)&sc->rx_desc, 422143442Sobrien BUS_DMA_WAITOK, &sc->rmap); 423143442Sobrien if (error) { 424143442Sobrien device_printf(dev, "couldn't allocate dma memory\n"); 425143442Sobrien goto fail; 426143442Sobrien } 427143442Sobrien bzero(sc->rx_desc, sizeof(struct nve_rx_desc) * RX_RING_SIZE); 428143442Sobrien error = bus_dmamap_load(sc->rtag, sc->rmap, sc->rx_desc, 429143442Sobrien sizeof(struct nve_rx_desc) * RX_RING_SIZE, nve_dmamap_cb, 430143442Sobrien &sc->rx_addr, 0); 431143442Sobrien if (error) { 432143442Sobrien device_printf(dev, "couldn't map dma memory\n"); 433143442Sobrien goto fail; 434143442Sobrien } 435143442Sobrien /* Initialize rings. */ 436143442Sobrien if (nve_init_rings(sc)) { 437143442Sobrien device_printf(dev, "failed to init rings\n"); 438143442Sobrien error = ENXIO; 439143442Sobrien goto fail; 440143442Sobrien } 441143442Sobrien /* Setup NVIDIA API callback routines */ 442143442Sobrien osapi = &sc->osapi; 443143442Sobrien osapi->pOSCX = sc; 444143442Sobrien osapi->pfnAllocMemory = nve_osalloc; 445143442Sobrien osapi->pfnFreeMemory = nve_osfree; 446143442Sobrien osapi->pfnAllocMemoryEx = nve_osallocex; 447143442Sobrien osapi->pfnFreeMemoryEx = nve_osfreeex; 448143442Sobrien osapi->pfnClearMemory = nve_osclear; 449143442Sobrien osapi->pfnStallExecution = nve_osdelay; 450143442Sobrien osapi->pfnAllocReceiveBuffer = nve_osallocrxbuf; 451143442Sobrien osapi->pfnFreeReceiveBuffer = nve_osfreerxbuf; 452143442Sobrien osapi->pfnPacketWasSent = nve_ospackettx; 453143442Sobrien osapi->pfnPacketWasReceived = nve_ospacketrx; 454143442Sobrien osapi->pfnLinkStateHasChanged = nve_oslinkchg; 455143442Sobrien osapi->pfnAllocTimer = nve_osalloctimer; 456143442Sobrien osapi->pfnFreeTimer = nve_osfreetimer; 457143442Sobrien osapi->pfnInitializeTimer = nve_osinittimer; 458143442Sobrien osapi->pfnSetTimer = nve_ossettimer; 459143442Sobrien osapi->pfnCancelTimer = nve_oscanceltimer; 460143442Sobrien osapi->pfnPreprocessPacket = nve_ospreprocpkt; 461143442Sobrien osapi->pfnPreprocessPacketNopq = nve_ospreprocpktnopq; 462143442Sobrien osapi->pfnIndicatePackets = nve_osindicatepkt; 463143442Sobrien osapi->pfnLockAlloc = nve_oslockalloc; 464143442Sobrien osapi->pfnLockAcquire = nve_oslockacquire; 465143442Sobrien osapi->pfnLockRelease = nve_oslockrelease; 466143442Sobrien osapi->pfnReturnBufferVirtual = nve_osreturnbufvirt; 467143442Sobrien 468143442Sobrien sc->linkup = FALSE; 469143442Sobrien sc->max_frame_size = ETHERMTU + ETHER_HDR_LEN + FCS_LEN; 470143442Sobrien 471143442Sobrien /* TODO - We don't support hardware offload yet */ 472143442Sobrien sc->hwmode = 1; 473143442Sobrien sc->media = 0; 474143442Sobrien 475143442Sobrien /* Set NVIDIA API startup parameters */ 476143442Sobrien OpenParams.MaxDpcLoop = 2; 477143442Sobrien OpenParams.MaxRxPkt = RX_RING_SIZE; 478143442Sobrien OpenParams.MaxTxPkt = TX_RING_SIZE; 479143442Sobrien OpenParams.SentPacketStatusSuccess = 1; 480143442Sobrien OpenParams.SentPacketStatusFailure = 0; 481143442Sobrien OpenParams.MaxRxPktToAccumulate = 6; 482143442Sobrien OpenParams.ulPollInterval = nve_pollinterval; 483143442Sobrien OpenParams.SetForcedModeEveryNthRxPacket = 0; 484143442Sobrien OpenParams.SetForcedModeEveryNthTxPacket = 0; 485143442Sobrien OpenParams.RxForcedInterrupt = 0; 486143442Sobrien OpenParams.TxForcedInterrupt = 0; 487143442Sobrien OpenParams.pOSApi = osapi; 488143442Sobrien OpenParams.pvHardwareBaseAddress = rman_get_virtual(sc->res); 489143442Sobrien OpenParams.bASFEnabled = 0; 490143442Sobrien OpenParams.ulDescriptorVersion = sc->hwmode; 491143442Sobrien OpenParams.ulMaxPacketSize = sc->max_frame_size; 492143442Sobrien OpenParams.DeviceId = pci_get_device(dev); 493143442Sobrien 494143442Sobrien /* Open NVIDIA Hardware API */ 495143442Sobrien error = ADAPTER_Open(&OpenParams, (void **)&(sc->hwapi), &sc->phyaddr); 496143442Sobrien if (error) { 497143442Sobrien device_printf(dev, 498143442Sobrien "failed to open NVIDIA Hardware API: 0x%x\n", error); 499143442Sobrien goto fail; 500143442Sobrien } 501143442Sobrien 502143442Sobrien /* TODO - Add support for MODE2 hardware offload */ 503143442Sobrien 504143442Sobrien bzero(&sc->adapterdata, sizeof(sc->adapterdata)); 505143442Sobrien 506143442Sobrien sc->adapterdata.ulMediaIF = sc->media; 507143442Sobrien sc->adapterdata.ulModeRegTxReadCompleteEnable = 1; 508143442Sobrien sc->hwapi->pfnSetCommonData(sc->hwapi->pADCX, &sc->adapterdata); 509143442Sobrien 510143442Sobrien /* MAC is loaded backwards into h/w reg */ 511143442Sobrien sc->hwapi->pfnGetNodeAddress(sc->hwapi->pADCX, sc->original_mac_addr); 512143442Sobrien for (i = 0; i < 6; i++) { 513143442Sobrien eaddr[i] = sc->original_mac_addr[5 - i]; 514143442Sobrien } 515143442Sobrien sc->hwapi->pfnSetNodeAddress(sc->hwapi->pADCX, eaddr); 516143442Sobrien 517143442Sobrien /* Display ethernet address ,... */ 518147256Sbrooks device_printf(dev, "Ethernet address %6D\n", eaddr, ":"); 519143442Sobrien 520147291Sbrooks /* Allocate interface structures */ 521147291Sbrooks ifp = sc->ifp = if_alloc(IFT_ETHER); 522147291Sbrooks if (ifp == NULL) { 523147291Sbrooks device_printf(dev, "can not if_alloc()\n"); 524147291Sbrooks error = ENOSPC; 525147291Sbrooks goto fail; 526147291Sbrooks } 527143442Sobrien 528143442Sobrien /* Setup interface parameters */ 529143442Sobrien ifp->if_softc = sc; 530152669Sjhb if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 531143442Sobrien ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 532143442Sobrien ifp->if_ioctl = nve_ioctl; 533143442Sobrien ifp->if_start = nve_ifstart; 534143442Sobrien ifp->if_init = nve_init; 535143442Sobrien ifp->if_baudrate = IF_Mbps(100); 536158773Smlaier IFQ_SET_MAXLEN(&ifp->if_snd, TX_RING_SIZE - 1); 537158773Smlaier ifp->if_snd.ifq_drv_maxlen = TX_RING_SIZE - 1; 538158773Smlaier IFQ_SET_READY(&ifp->if_snd); 539143442Sobrien ifp->if_capabilities |= IFCAP_VLAN_MTU; 540169338Syar ifp->if_capenable |= IFCAP_VLAN_MTU; 541143442Sobrien 542213894Smarius /* Attach device for MII interface to PHY */ 543213894Smarius DEBUGOUT(NVE_DEBUG_INIT, "nve: do mii_attach\n"); 544213894Smarius error = mii_attach(dev, &sc->miibus, ifp, nve_ifmedia_upd, 545213894Smarius nve_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); 546213894Smarius if (error != 0) { 547213894Smarius device_printf(dev, "attaching PHYs failed\n"); 548203070Sjhb goto fail; 549203070Sjhb } 550203070Sjhb 551143442Sobrien /* Attach to OS's managers. */ 552147256Sbrooks ether_ifattach(ifp, eaddr); 553143442Sobrien 554143442Sobrien /* Activate our interrupt handler. - attach last to avoid lock */ 555213894Smarius error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, 556166901Spiso NULL, nve_intr, sc, &sc->sc_ih); 557143442Sobrien if (error) { 558213894Smarius device_printf(dev, "couldn't set up interrupt handler\n"); 559143442Sobrien goto fail; 560143442Sobrien } 561143442Sobrien DEBUGOUT(NVE_DEBUG_INIT, "nve: nve_attach - exit\n"); 562143442Sobrien 563143442Sobrienfail: 564143442Sobrien if (error) 565143442Sobrien nve_detach(dev); 566143442Sobrien 567143442Sobrien return (error); 568143442Sobrien} 569143442Sobrien 570143442Sobrien/* Detach interface for module unload */ 571143442Sobrienstatic int 572143442Sobriennve_detach(device_t dev) 573143442Sobrien{ 574143442Sobrien struct nve_softc *sc = device_get_softc(dev); 575143442Sobrien struct ifnet *ifp; 576143442Sobrien 577143442Sobrien KASSERT(mtx_initialized(&sc->mtx), ("mutex not initialized")); 578143442Sobrien 579143442Sobrien DEBUGOUT(NVE_DEBUG_DEINIT, "nve: nve_detach - entry\n"); 580143442Sobrien 581147256Sbrooks ifp = sc->ifp; 582143442Sobrien 583143442Sobrien if (device_is_attached(dev)) { 584191437Srwatson ether_ifdetach(ifp); 585152669Sjhb NVE_LOCK(sc); 586143442Sobrien nve_stop(sc); 587152669Sjhb NVE_UNLOCK(sc); 588152669Sjhb callout_drain(&sc->stat_callout); 589143442Sobrien } 590143442Sobrien 591143442Sobrien if (sc->miibus) 592143442Sobrien device_delete_child(dev, sc->miibus); 593143442Sobrien bus_generic_detach(dev); 594143442Sobrien 595143442Sobrien /* Reload unreversed address back into MAC in original state */ 596143442Sobrien if (sc->original_mac_addr) 597143442Sobrien sc->hwapi->pfnSetNodeAddress(sc->hwapi->pADCX, 598143442Sobrien sc->original_mac_addr); 599143442Sobrien 600143442Sobrien DEBUGOUT(NVE_DEBUG_DEINIT, "nve: do pfnClose\n"); 601143442Sobrien /* Detach from NVIDIA hardware API */ 602143442Sobrien if (sc->hwapi->pfnClose) 603143442Sobrien sc->hwapi->pfnClose(sc->hwapi->pADCX, FALSE); 604143442Sobrien /* Release resources */ 605143442Sobrien if (sc->sc_ih) 606143442Sobrien bus_teardown_intr(sc->dev, sc->irq, sc->sc_ih); 607143442Sobrien if (sc->irq) 608143442Sobrien bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->irq); 609143442Sobrien if (sc->res) 610143442Sobrien bus_release_resource(sc->dev, SYS_RES_MEMORY, NV_RID, sc->res); 611143442Sobrien 612143442Sobrien nve_free_rings(sc); 613143442Sobrien 614143442Sobrien if (sc->tx_desc) { 615143442Sobrien bus_dmamap_unload(sc->rtag, sc->rmap); 616143442Sobrien bus_dmamem_free(sc->rtag, sc->rx_desc, sc->rmap); 617143442Sobrien bus_dmamap_destroy(sc->rtag, sc->rmap); 618143442Sobrien } 619143442Sobrien if (sc->mtag) 620143442Sobrien bus_dma_tag_destroy(sc->mtag); 621143442Sobrien if (sc->ttag) 622143442Sobrien bus_dma_tag_destroy(sc->ttag); 623143442Sobrien if (sc->rtag) 624143442Sobrien bus_dma_tag_destroy(sc->rtag); 625143442Sobrien 626150306Simp if (ifp) 627150306Simp if_free(ifp); 628143442Sobrien mtx_destroy(&sc->mtx); 629143442Sobrien 630143442Sobrien DEBUGOUT(NVE_DEBUG_DEINIT, "nve: nve_detach - exit\n"); 631143442Sobrien 632143442Sobrien return (0); 633143442Sobrien} 634143442Sobrien 635143442Sobrien/* Initialise interface and start it "RUNNING" */ 636143442Sobrienstatic void 637143442Sobriennve_init(void *xsc) 638143442Sobrien{ 639143442Sobrien struct nve_softc *sc = xsc; 640152669Sjhb 641152669Sjhb NVE_LOCK(sc); 642152669Sjhb nve_init_locked(sc); 643152669Sjhb NVE_UNLOCK(sc); 644152669Sjhb} 645152669Sjhb 646152669Sjhbstatic void 647152669Sjhbnve_init_locked(struct nve_softc *sc) 648152669Sjhb{ 649143442Sobrien struct ifnet *ifp; 650143442Sobrien int error; 651143442Sobrien 652152669Sjhb NVE_LOCK_ASSERT(sc); 653143442Sobrien DEBUGOUT(NVE_DEBUG_INIT, "nve: nve_init - entry (%d)\n", sc->linkup); 654143442Sobrien 655147256Sbrooks ifp = sc->ifp; 656143442Sobrien 657143442Sobrien /* Do nothing if already running */ 658148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) 659152669Sjhb return; 660143442Sobrien 661143442Sobrien nve_stop(sc); 662143442Sobrien DEBUGOUT(NVE_DEBUG_INIT, "nve: do pfnInit\n"); 663143442Sobrien 664153333Sbz nve_ifmedia_upd_locked(ifp); 665153333Sbz 666143442Sobrien /* Setup Hardware interface and allocate memory structures */ 667143442Sobrien error = sc->hwapi->pfnInit(sc->hwapi->pADCX, 668143442Sobrien 0, /* force speed */ 669143442Sobrien 0, /* force full duplex */ 670143442Sobrien 0, /* force mode */ 671143442Sobrien 0, /* force async mode */ 672143442Sobrien &sc->linkup); 673143442Sobrien 674143442Sobrien if (error) { 675143442Sobrien device_printf(sc->dev, 676143442Sobrien "failed to start NVIDIA Hardware interface\n"); 677152669Sjhb return; 678143442Sobrien } 679143442Sobrien /* Set the MAC address */ 680152315Sru sc->hwapi->pfnSetNodeAddress(sc->hwapi->pADCX, IF_LLADDR(sc->ifp)); 681143442Sobrien sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX); 682143442Sobrien sc->hwapi->pfnStart(sc->hwapi->pADCX); 683143442Sobrien 684143442Sobrien /* Setup multicast filter */ 685143442Sobrien nve_setmulti(sc); 686143442Sobrien 687143442Sobrien /* Update interface parameters */ 688148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 689148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 690143442Sobrien 691152669Sjhb callout_reset(&sc->stat_callout, hz, nve_tick, sc); 692143442Sobrien 693143442Sobrien DEBUGOUT(NVE_DEBUG_INIT, "nve: nve_init - exit\n"); 694143442Sobrien 695143442Sobrien return; 696143442Sobrien} 697143442Sobrien 698143442Sobrien/* Stop interface activity ie. not "RUNNING" */ 699143442Sobrienstatic void 700143442Sobriennve_stop(struct nve_softc *sc) 701143442Sobrien{ 702143442Sobrien struct ifnet *ifp; 703143442Sobrien 704152669Sjhb NVE_LOCK_ASSERT(sc); 705143442Sobrien 706143442Sobrien DEBUGOUT(NVE_DEBUG_RUNNING, "nve: nve_stop - entry\n"); 707143442Sobrien 708147256Sbrooks ifp = sc->ifp; 709199560Sjhb sc->tx_timer = 0; 710143442Sobrien 711143442Sobrien /* Cancel tick timer */ 712152669Sjhb callout_stop(&sc->stat_callout); 713143442Sobrien 714143442Sobrien /* Stop hardware activity */ 715143442Sobrien sc->hwapi->pfnDisableInterrupts(sc->hwapi->pADCX); 716143442Sobrien sc->hwapi->pfnStop(sc->hwapi->pADCX, 0); 717143442Sobrien 718143442Sobrien DEBUGOUT(NVE_DEBUG_DEINIT, "nve: do pfnDeinit\n"); 719143442Sobrien /* Shutdown interface and deallocate memory buffers */ 720143442Sobrien if (sc->hwapi->pfnDeinit) 721143442Sobrien sc->hwapi->pfnDeinit(sc->hwapi->pADCX, 0); 722143442Sobrien 723143442Sobrien sc->linkup = 0; 724143442Sobrien sc->cur_rx = 0; 725143442Sobrien sc->pending_rxs = 0; 726151733Sobrien sc->pending_txs = 0; 727143442Sobrien 728148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 729143442Sobrien 730143442Sobrien DEBUGOUT(NVE_DEBUG_RUNNING, "nve: nve_stop - exit\n"); 731143442Sobrien 732143442Sobrien return; 733143442Sobrien} 734143442Sobrien 735143442Sobrien/* Shutdown interface for unload/reboot */ 736173839Syongaristatic int 737143442Sobriennve_shutdown(device_t dev) 738143442Sobrien{ 739143442Sobrien struct nve_softc *sc; 740143442Sobrien 741143442Sobrien DEBUGOUT(NVE_DEBUG_DEINIT, "nve: nve_shutdown\n"); 742143442Sobrien 743143442Sobrien sc = device_get_softc(dev); 744143442Sobrien 745143442Sobrien /* Stop hardware activity */ 746152669Sjhb NVE_LOCK(sc); 747143442Sobrien nve_stop(sc); 748152669Sjhb NVE_UNLOCK(sc); 749173839Syongari 750173839Syongari return (0); 751143442Sobrien} 752143442Sobrien 753143442Sobrien/* Allocate TX ring buffers */ 754143442Sobrienstatic int 755143442Sobriennve_init_rings(struct nve_softc *sc) 756143442Sobrien{ 757143442Sobrien int error, i; 758143442Sobrien 759143442Sobrien DEBUGOUT(NVE_DEBUG_INIT, "nve: nve_init_rings - entry\n"); 760143442Sobrien 761143442Sobrien sc->cur_rx = sc->cur_tx = sc->pending_rxs = sc->pending_txs = 0; 762143442Sobrien /* Initialise RX ring */ 763143442Sobrien for (i = 0; i < RX_RING_SIZE; i++) { 764143442Sobrien struct nve_rx_desc *desc = sc->rx_desc + i; 765143442Sobrien struct nve_map_buffer *buf = &desc->buf; 766143442Sobrien 767243857Sglebius buf->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 768143442Sobrien if (buf->mbuf == NULL) { 769143442Sobrien device_printf(sc->dev, "couldn't allocate mbuf\n"); 770143442Sobrien nve_free_rings(sc); 771152669Sjhb return (ENOBUFS); 772143442Sobrien } 773143442Sobrien buf->mbuf->m_len = buf->mbuf->m_pkthdr.len = MCLBYTES; 774143442Sobrien m_adj(buf->mbuf, ETHER_ALIGN); 775143442Sobrien 776143442Sobrien error = bus_dmamap_create(sc->mtag, 0, &buf->map); 777143442Sobrien if (error) { 778143442Sobrien device_printf(sc->dev, "couldn't create dma map\n"); 779143442Sobrien nve_free_rings(sc); 780152669Sjhb return (error); 781143442Sobrien } 782143442Sobrien error = bus_dmamap_load_mbuf(sc->mtag, buf->map, buf->mbuf, 783143442Sobrien nve_dmamap_rx_cb, &desc->paddr, 0); 784143442Sobrien if (error) { 785143442Sobrien device_printf(sc->dev, "couldn't dma map mbuf\n"); 786143442Sobrien nve_free_rings(sc); 787152669Sjhb return (error); 788143442Sobrien } 789143442Sobrien bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_PREREAD); 790143442Sobrien 791143442Sobrien desc->buflength = buf->mbuf->m_len; 792143442Sobrien desc->vaddr = mtod(buf->mbuf, caddr_t); 793143442Sobrien } 794143442Sobrien bus_dmamap_sync(sc->rtag, sc->rmap, 795143442Sobrien BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 796143442Sobrien 797143442Sobrien /* Initialize TX ring */ 798143442Sobrien for (i = 0; i < TX_RING_SIZE; i++) { 799143442Sobrien struct nve_tx_desc *desc = sc->tx_desc + i; 800143442Sobrien struct nve_map_buffer *buf = &desc->buf; 801143442Sobrien 802143442Sobrien buf->mbuf = NULL; 803143442Sobrien 804143442Sobrien error = bus_dmamap_create(sc->mtag, 0, &buf->map); 805143442Sobrien if (error) { 806143442Sobrien device_printf(sc->dev, "couldn't create dma map\n"); 807143442Sobrien nve_free_rings(sc); 808152669Sjhb return (error); 809143442Sobrien } 810143442Sobrien } 811143442Sobrien bus_dmamap_sync(sc->ttag, sc->tmap, 812143442Sobrien BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 813143442Sobrien 814143442Sobrien DEBUGOUT(NVE_DEBUG_INIT, "nve: nve_init_rings - exit\n"); 815143442Sobrien 816143442Sobrien return (error); 817143442Sobrien} 818143442Sobrien 819143442Sobrien/* Free the TX ring buffers */ 820143442Sobrienstatic void 821143442Sobriennve_free_rings(struct nve_softc *sc) 822143442Sobrien{ 823143442Sobrien int i; 824143442Sobrien 825143442Sobrien DEBUGOUT(NVE_DEBUG_DEINIT, "nve: nve_free_rings - entry\n"); 826143442Sobrien 827143442Sobrien for (i = 0; i < RX_RING_SIZE; i++) { 828143442Sobrien struct nve_rx_desc *desc = sc->rx_desc + i; 829143442Sobrien struct nve_map_buffer *buf = &desc->buf; 830143442Sobrien 831143442Sobrien if (buf->mbuf) { 832143442Sobrien bus_dmamap_unload(sc->mtag, buf->map); 833143442Sobrien bus_dmamap_destroy(sc->mtag, buf->map); 834143442Sobrien m_freem(buf->mbuf); 835143442Sobrien } 836143442Sobrien buf->mbuf = NULL; 837143442Sobrien } 838143442Sobrien 839143442Sobrien for (i = 0; i < TX_RING_SIZE; i++) { 840143442Sobrien struct nve_tx_desc *desc = sc->tx_desc + i; 841143442Sobrien struct nve_map_buffer *buf = &desc->buf; 842143442Sobrien 843143442Sobrien if (buf->mbuf) { 844143442Sobrien bus_dmamap_unload(sc->mtag, buf->map); 845143442Sobrien bus_dmamap_destroy(sc->mtag, buf->map); 846143442Sobrien m_freem(buf->mbuf); 847143442Sobrien } 848143442Sobrien buf->mbuf = NULL; 849143442Sobrien } 850143442Sobrien 851143442Sobrien DEBUGOUT(NVE_DEBUG_DEINIT, "nve: nve_free_rings - exit\n"); 852143442Sobrien} 853143442Sobrien 854143442Sobrien/* Main loop for sending packets from OS to interface */ 855143442Sobrienstatic void 856143442Sobriennve_ifstart(struct ifnet *ifp) 857143442Sobrien{ 858143442Sobrien struct nve_softc *sc = ifp->if_softc; 859152669Sjhb 860152669Sjhb NVE_LOCK(sc); 861152669Sjhb nve_ifstart_locked(ifp); 862152669Sjhb NVE_UNLOCK(sc); 863152669Sjhb} 864152669Sjhb 865152669Sjhbstatic void 866152669Sjhbnve_ifstart_locked(struct ifnet *ifp) 867152669Sjhb{ 868152669Sjhb struct nve_softc *sc = ifp->if_softc; 869143442Sobrien struct nve_map_buffer *buf; 870143442Sobrien struct mbuf *m0, *m; 871143442Sobrien struct nve_tx_desc *desc; 872143442Sobrien ADAPTER_WRITE_DATA txdata; 873143442Sobrien int error, i; 874143442Sobrien 875143442Sobrien DEBUGOUT(NVE_DEBUG_RUNNING, "nve: nve_ifstart - entry\n"); 876143442Sobrien 877152669Sjhb NVE_LOCK_ASSERT(sc); 878152669Sjhb 879143442Sobrien /* If link is down/busy or queue is empty do nothing */ 880152669Sjhb if (ifp->if_drv_flags & IFF_DRV_OACTIVE || 881152669Sjhb IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 882143442Sobrien return; 883143442Sobrien 884143442Sobrien /* Transmit queued packets until sent or TX ring is full */ 885143442Sobrien while (sc->pending_txs < TX_RING_SIZE) { 886143442Sobrien desc = sc->tx_desc + sc->cur_tx; 887143442Sobrien buf = &desc->buf; 888143442Sobrien 889143442Sobrien /* Get next packet to send. */ 890158773Smlaier IFQ_DRV_DEQUEUE(&ifp->if_snd, m0); 891143442Sobrien 892143442Sobrien /* If nothing to send, return. */ 893143442Sobrien if (m0 == NULL) 894143442Sobrien return; 895143442Sobrien 896158735Sjhb /* 897158735Sjhb * On nForce4, the chip doesn't interrupt on transmit, 898158735Sjhb * so try to flush transmitted packets from the queue 899158735Sjhb * if it's getting large (see note in nve_watchdog). 900158735Sjhb */ 901158735Sjhb if (sc->pending_txs > TX_RING_SIZE/2) { 902158735Sjhb sc->hwapi->pfnDisableInterrupts(sc->hwapi->pADCX); 903158735Sjhb sc->hwapi->pfnHandleInterrupt(sc->hwapi->pADCX); 904158735Sjhb sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX); 905158735Sjhb } 906158735Sjhb 907143442Sobrien /* Map MBUF for DMA access */ 908143442Sobrien error = bus_dmamap_load_mbuf(sc->mtag, buf->map, m0, 909143442Sobrien nve_dmamap_tx_cb, desc, BUS_DMA_NOWAIT); 910143442Sobrien 911143442Sobrien if (error && error != EFBIG) { 912143442Sobrien m_freem(m0); 913143442Sobrien sc->tx_errors++; 914143442Sobrien continue; 915143442Sobrien } 916143442Sobrien /* 917143442Sobrien * Packet has too many fragments - defrag into new mbuf 918143442Sobrien * cluster 919143442Sobrien */ 920143442Sobrien if (error) { 921243857Sglebius m = m_defrag(m0, M_NOWAIT); 922143442Sobrien if (m == NULL) { 923143442Sobrien m_freem(m0); 924143442Sobrien sc->tx_errors++; 925143442Sobrien continue; 926143442Sobrien } 927143442Sobrien m0 = m; 928143442Sobrien 929143442Sobrien error = bus_dmamap_load_mbuf(sc->mtag, buf->map, m, 930143442Sobrien nve_dmamap_tx_cb, desc, BUS_DMA_NOWAIT); 931143442Sobrien if (error) { 932143442Sobrien m_freem(m); 933143442Sobrien sc->tx_errors++; 934143442Sobrien continue; 935143442Sobrien } 936143442Sobrien } 937143442Sobrien /* Do sync on DMA bounce buffer */ 938143442Sobrien bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_PREWRITE); 939143442Sobrien 940143442Sobrien buf->mbuf = m0; 941143442Sobrien txdata.ulNumberOfElements = desc->numfrags; 942143442Sobrien txdata.pvID = (PVOID)desc; 943143442Sobrien 944143442Sobrien /* Put fragments into API element list */ 945143442Sobrien txdata.ulTotalLength = buf->mbuf->m_len; 946143442Sobrien for (i = 0; i < desc->numfrags; i++) { 947143442Sobrien txdata.sElement[i].ulLength = 948143442Sobrien (ulong)desc->frags[i].ds_len; 949143442Sobrien txdata.sElement[i].pPhysical = 950143442Sobrien (PVOID)desc->frags[i].ds_addr; 951143442Sobrien } 952143442Sobrien 953143442Sobrien /* Send packet to Nvidia API for transmission */ 954143442Sobrien error = sc->hwapi->pfnWrite(sc->hwapi->pADCX, &txdata); 955143442Sobrien 956143442Sobrien switch (error) { 957143442Sobrien case ADAPTERERR_NONE: 958143442Sobrien /* Packet was queued in API TX queue successfully */ 959143442Sobrien sc->pending_txs++; 960143442Sobrien sc->cur_tx = (sc->cur_tx + 1) % TX_RING_SIZE; 961143442Sobrien break; 962143442Sobrien 963143442Sobrien case ADAPTERERR_TRANSMIT_QUEUE_FULL: 964143442Sobrien /* The API TX queue is full - requeue the packet */ 965143442Sobrien device_printf(sc->dev, 966143442Sobrien "nve_ifstart: transmit queue is full\n"); 967148887Srwatson ifp->if_drv_flags |= IFF_DRV_OACTIVE; 968143442Sobrien bus_dmamap_unload(sc->mtag, buf->map); 969158773Smlaier IFQ_DRV_PREPEND(&ifp->if_snd, buf->mbuf); 970143442Sobrien buf->mbuf = NULL; 971143442Sobrien return; 972143442Sobrien 973143442Sobrien default: 974143442Sobrien /* The API failed to queue/send the packet so dump it */ 975143442Sobrien device_printf(sc->dev, "nve_ifstart: transmit error\n"); 976143442Sobrien bus_dmamap_unload(sc->mtag, buf->map); 977143442Sobrien m_freem(buf->mbuf); 978143442Sobrien buf->mbuf = NULL; 979143442Sobrien sc->tx_errors++; 980143442Sobrien return; 981143442Sobrien } 982143442Sobrien /* Set watchdog timer. */ 983199560Sjhb sc->tx_timer = 8; 984143442Sobrien 985143442Sobrien /* Copy packet to BPF tap */ 986143442Sobrien BPF_MTAP(ifp, m0); 987143442Sobrien } 988148887Srwatson ifp->if_drv_flags |= IFF_DRV_OACTIVE; 989143442Sobrien 990143442Sobrien DEBUGOUT(NVE_DEBUG_RUNNING, "nve: nve_ifstart - exit\n"); 991143442Sobrien} 992143442Sobrien 993143442Sobrien/* Handle IOCTL events */ 994143442Sobrienstatic int 995143442Sobriennve_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 996143442Sobrien{ 997143442Sobrien struct nve_softc *sc = ifp->if_softc; 998143442Sobrien struct ifreq *ifr = (struct ifreq *) data; 999143442Sobrien struct mii_data *mii; 1000143442Sobrien int error = 0; 1001143442Sobrien 1002143442Sobrien DEBUGOUT(NVE_DEBUG_IOCTL, "nve: nve_ioctl - entry\n"); 1003143442Sobrien 1004143442Sobrien switch (command) { 1005143442Sobrien case SIOCSIFMTU: 1006143442Sobrien /* Set MTU size */ 1007152669Sjhb NVE_LOCK(sc); 1008152669Sjhb if (ifp->if_mtu == ifr->ifr_mtu) { 1009152669Sjhb NVE_UNLOCK(sc); 1010143442Sobrien break; 1011152669Sjhb } 1012143442Sobrien if (ifr->ifr_mtu + ifp->if_hdrlen <= MAX_PACKET_SIZE_1518) { 1013143442Sobrien ifp->if_mtu = ifr->ifr_mtu; 1014143442Sobrien nve_stop(sc); 1015152669Sjhb nve_init_locked(sc); 1016143442Sobrien } else 1017143442Sobrien error = EINVAL; 1018152669Sjhb NVE_UNLOCK(sc); 1019143442Sobrien break; 1020143442Sobrien 1021143442Sobrien case SIOCSIFFLAGS: 1022143442Sobrien /* Setup interface flags */ 1023152669Sjhb NVE_LOCK(sc); 1024143442Sobrien if (ifp->if_flags & IFF_UP) { 1025148887Srwatson if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1026152669Sjhb nve_init_locked(sc); 1027152669Sjhb NVE_UNLOCK(sc); 1028143442Sobrien break; 1029143442Sobrien } 1030143442Sobrien } else { 1031148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1032143442Sobrien nve_stop(sc); 1033152669Sjhb NVE_UNLOCK(sc); 1034143442Sobrien break; 1035143442Sobrien } 1036143442Sobrien } 1037143442Sobrien /* Handle IFF_PROMISC and IFF_ALLMULTI flags. */ 1038143442Sobrien nve_setmulti(sc); 1039152669Sjhb NVE_UNLOCK(sc); 1040143442Sobrien break; 1041143442Sobrien 1042143442Sobrien case SIOCADDMULTI: 1043143442Sobrien case SIOCDELMULTI: 1044143442Sobrien /* Setup multicast filter */ 1045152669Sjhb NVE_LOCK(sc); 1046148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1047143442Sobrien nve_setmulti(sc); 1048143442Sobrien } 1049152669Sjhb NVE_UNLOCK(sc); 1050143442Sobrien break; 1051143442Sobrien 1052143442Sobrien case SIOCGIFMEDIA: 1053143442Sobrien case SIOCSIFMEDIA: 1054143442Sobrien /* Get/Set interface media parameters */ 1055143442Sobrien mii = device_get_softc(sc->miibus); 1056143442Sobrien error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 1057143442Sobrien break; 1058143442Sobrien 1059143442Sobrien default: 1060143442Sobrien /* Everything else we forward to generic ether ioctl */ 1061170442Sdwhite error = ether_ioctl(ifp, command, data); 1062143442Sobrien break; 1063143442Sobrien } 1064143442Sobrien 1065143442Sobrien DEBUGOUT(NVE_DEBUG_IOCTL, "nve: nve_ioctl - exit\n"); 1066143442Sobrien 1067143442Sobrien return (error); 1068143442Sobrien} 1069143442Sobrien 1070143442Sobrien/* Interrupt service routine */ 1071143442Sobrienstatic void 1072143442Sobriennve_intr(void *arg) 1073143442Sobrien{ 1074143442Sobrien struct nve_softc *sc = arg; 1075147256Sbrooks struct ifnet *ifp = sc->ifp; 1076143442Sobrien 1077143442Sobrien DEBUGOUT(NVE_DEBUG_INTERRUPT, "nve: nve_intr - entry\n"); 1078143442Sobrien 1079152669Sjhb NVE_LOCK(sc); 1080143442Sobrien if (!ifp->if_flags & IFF_UP) { 1081143442Sobrien nve_stop(sc); 1082152669Sjhb NVE_UNLOCK(sc); 1083143442Sobrien return; 1084143442Sobrien } 1085143442Sobrien /* Handle interrupt event */ 1086143442Sobrien if (sc->hwapi->pfnQueryInterrupt(sc->hwapi->pADCX)) { 1087143442Sobrien sc->hwapi->pfnHandleInterrupt(sc->hwapi->pADCX); 1088143442Sobrien sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX); 1089143442Sobrien } 1090152669Sjhb if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1091152669Sjhb nve_ifstart_locked(ifp); 1092143442Sobrien 1093143442Sobrien /* If no pending packets we don't need a timeout */ 1094143442Sobrien if (sc->pending_txs == 0) 1095199560Sjhb sc->tx_timer = 0; 1096152669Sjhb NVE_UNLOCK(sc); 1097143442Sobrien 1098143442Sobrien DEBUGOUT(NVE_DEBUG_INTERRUPT, "nve: nve_intr - exit\n"); 1099143442Sobrien 1100143442Sobrien return; 1101143442Sobrien} 1102143442Sobrien 1103143442Sobrien/* Setup multicast filters */ 1104143442Sobrienstatic void 1105143442Sobriennve_setmulti(struct nve_softc *sc) 1106143442Sobrien{ 1107143442Sobrien struct ifnet *ifp; 1108143442Sobrien struct ifmultiaddr *ifma; 1109143442Sobrien PACKET_FILTER hwfilter; 1110143442Sobrien int i; 1111143442Sobrien u_int8_t andaddr[6], oraddr[6]; 1112143442Sobrien 1113152669Sjhb NVE_LOCK_ASSERT(sc); 1114143442Sobrien 1115143442Sobrien DEBUGOUT(NVE_DEBUG_RUNNING, "nve: nve_setmulti - entry\n"); 1116143442Sobrien 1117147256Sbrooks ifp = sc->ifp; 1118143442Sobrien 1119143442Sobrien /* Initialize filter */ 1120143442Sobrien hwfilter.ulFilterFlags = 0; 1121143442Sobrien for (i = 0; i < 6; i++) { 1122143442Sobrien hwfilter.acMulticastAddress[i] = 0; 1123143442Sobrien hwfilter.acMulticastMask[i] = 0; 1124143442Sobrien } 1125143442Sobrien 1126143442Sobrien if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { 1127143442Sobrien /* Accept all packets */ 1128143442Sobrien hwfilter.ulFilterFlags |= ACCEPT_ALL_PACKETS; 1129143442Sobrien sc->hwapi->pfnSetPacketFilter(sc->hwapi->pADCX, &hwfilter); 1130143442Sobrien return; 1131143442Sobrien } 1132143442Sobrien /* Setup multicast filter */ 1133195049Srwatson if_maddr_rlock(ifp); 1134143442Sobrien TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1135143442Sobrien u_char *addrp; 1136143442Sobrien 1137143442Sobrien if (ifma->ifma_addr->sa_family != AF_LINK) 1138143442Sobrien continue; 1139143442Sobrien 1140143442Sobrien addrp = LLADDR((struct sockaddr_dl *) ifma->ifma_addr); 1141143442Sobrien for (i = 0; i < 6; i++) { 1142143442Sobrien u_int8_t mcaddr = addrp[i]; 1143143442Sobrien andaddr[i] &= mcaddr; 1144143442Sobrien oraddr[i] |= mcaddr; 1145143442Sobrien } 1146143442Sobrien } 1147195049Srwatson if_maddr_runlock(ifp); 1148143442Sobrien for (i = 0; i < 6; i++) { 1149143442Sobrien hwfilter.acMulticastAddress[i] = andaddr[i] & oraddr[i]; 1150143442Sobrien hwfilter.acMulticastMask[i] = andaddr[i] | (~oraddr[i]); 1151143442Sobrien } 1152143442Sobrien 1153143442Sobrien /* Send filter to NVIDIA API */ 1154143442Sobrien sc->hwapi->pfnSetPacketFilter(sc->hwapi->pADCX, &hwfilter); 1155143442Sobrien 1156143442Sobrien DEBUGOUT(NVE_DEBUG_RUNNING, "nve: nve_setmulti - exit\n"); 1157143442Sobrien 1158143442Sobrien return; 1159143442Sobrien} 1160143442Sobrien 1161143442Sobrien/* Change the current media/mediaopts */ 1162143442Sobrienstatic int 1163143442Sobriennve_ifmedia_upd(struct ifnet *ifp) 1164143442Sobrien{ 1165143442Sobrien struct nve_softc *sc = ifp->if_softc; 1166152669Sjhb 1167152669Sjhb NVE_LOCK(sc); 1168152669Sjhb nve_ifmedia_upd_locked(ifp); 1169152669Sjhb NVE_UNLOCK(sc); 1170152669Sjhb return (0); 1171152669Sjhb} 1172152669Sjhb 1173152669Sjhbstatic void 1174152669Sjhbnve_ifmedia_upd_locked(struct ifnet *ifp) 1175152669Sjhb{ 1176152669Sjhb struct nve_softc *sc = ifp->if_softc; 1177143442Sobrien struct mii_data *mii; 1178221407Smarius struct mii_softc *miisc; 1179143442Sobrien 1180143442Sobrien DEBUGOUT(NVE_DEBUG_MII, "nve: nve_ifmedia_upd\n"); 1181143442Sobrien 1182152669Sjhb NVE_LOCK_ASSERT(sc); 1183143442Sobrien mii = device_get_softc(sc->miibus); 1184143442Sobrien 1185221407Smarius LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 1186221407Smarius PHY_RESET(miisc); 1187143442Sobrien mii_mediachg(mii); 1188143442Sobrien} 1189143442Sobrien 1190143442Sobrien/* Update current miibus PHY status of media */ 1191143442Sobrienstatic void 1192143442Sobriennve_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 1193143442Sobrien{ 1194143442Sobrien struct nve_softc *sc; 1195143442Sobrien struct mii_data *mii; 1196143442Sobrien 1197143442Sobrien DEBUGOUT(NVE_DEBUG_MII, "nve: nve_ifmedia_sts\n"); 1198143442Sobrien 1199143442Sobrien sc = ifp->if_softc; 1200152669Sjhb NVE_LOCK(sc); 1201143442Sobrien mii = device_get_softc(sc->miibus); 1202143442Sobrien mii_pollstat(mii); 1203143442Sobrien 1204143442Sobrien ifmr->ifm_active = mii->mii_media_active; 1205143442Sobrien ifmr->ifm_status = mii->mii_media_status; 1206226478Syongari NVE_UNLOCK(sc); 1207143442Sobrien 1208143442Sobrien return; 1209143442Sobrien} 1210143442Sobrien 1211143442Sobrien/* miibus tick timer - maintain link status */ 1212143442Sobrienstatic void 1213143442Sobriennve_tick(void *xsc) 1214143442Sobrien{ 1215143442Sobrien struct nve_softc *sc = xsc; 1216143442Sobrien struct mii_data *mii; 1217143442Sobrien struct ifnet *ifp; 1218143442Sobrien 1219152669Sjhb NVE_LOCK_ASSERT(sc); 1220143442Sobrien 1221147256Sbrooks ifp = sc->ifp; 1222143442Sobrien nve_update_stats(sc); 1223143442Sobrien 1224143442Sobrien mii = device_get_softc(sc->miibus); 1225143442Sobrien mii_tick(mii); 1226143442Sobrien 1227143442Sobrien if (mii->mii_media_status & IFM_ACTIVE && 1228143442Sobrien IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 1229152669Sjhb if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1230152669Sjhb nve_ifstart_locked(ifp); 1231143442Sobrien } 1232199560Sjhb 1233199560Sjhb if (sc->tx_timer > 0 && --sc->tx_timer == 0) 1234199560Sjhb nve_watchdog(sc); 1235152669Sjhb callout_reset(&sc->stat_callout, hz, nve_tick, sc); 1236143442Sobrien 1237143442Sobrien return; 1238143442Sobrien} 1239143442Sobrien 1240143442Sobrien/* Update ifnet data structure with collected interface stats from API */ 1241143442Sobrienstatic void 1242143442Sobriennve_update_stats(struct nve_softc *sc) 1243143442Sobrien{ 1244147256Sbrooks struct ifnet *ifp = sc->ifp; 1245143442Sobrien ADAPTER_STATS stats; 1246143442Sobrien 1247152669Sjhb NVE_LOCK_ASSERT(sc); 1248143442Sobrien 1249143442Sobrien if (sc->hwapi) { 1250143442Sobrien sc->hwapi->pfnGetStatistics(sc->hwapi->pADCX, &stats); 1251143442Sobrien 1252143442Sobrien ifp->if_ipackets = stats.ulSuccessfulReceptions; 1253143442Sobrien ifp->if_ierrors = stats.ulMissedFrames + 1254143442Sobrien stats.ulFailedReceptions + 1255143442Sobrien stats.ulCRCErrors + 1256143442Sobrien stats.ulFramingErrors + 1257143442Sobrien stats.ulOverFlowErrors; 1258143442Sobrien 1259143442Sobrien ifp->if_opackets = stats.ulSuccessfulTransmissions; 1260143442Sobrien ifp->if_oerrors = sc->tx_errors + 1261143442Sobrien stats.ulFailedTransmissions + 1262143442Sobrien stats.ulRetryErrors + 1263143442Sobrien stats.ulUnderflowErrors + 1264143442Sobrien stats.ulLossOfCarrierErrors + 1265143442Sobrien stats.ulLateCollisionErrors; 1266143442Sobrien 1267143442Sobrien ifp->if_collisions = stats.ulLateCollisionErrors; 1268143442Sobrien } 1269143442Sobrien 1270143442Sobrien return; 1271143442Sobrien} 1272143442Sobrien 1273143442Sobrien/* miibus Read PHY register wrapper - calls Nvidia API entry point */ 1274143442Sobrienstatic int 1275143442Sobriennve_miibus_readreg(device_t dev, int phy, int reg) 1276143442Sobrien{ 1277143442Sobrien struct nve_softc *sc = device_get_softc(dev); 1278143442Sobrien ULONG data; 1279143442Sobrien 1280143442Sobrien DEBUGOUT(NVE_DEBUG_MII, "nve: nve_miibus_readreg - entry\n"); 1281143442Sobrien 1282143442Sobrien ADAPTER_ReadPhy(sc->hwapi->pADCX, phy, reg, &data); 1283143442Sobrien 1284143442Sobrien DEBUGOUT(NVE_DEBUG_MII, "nve: nve_miibus_readreg - exit\n"); 1285143442Sobrien 1286143442Sobrien return (data); 1287143442Sobrien} 1288143442Sobrien 1289143442Sobrien/* miibus Write PHY register wrapper - calls Nvidia API entry point */ 1290188175Simpstatic int 1291143442Sobriennve_miibus_writereg(device_t dev, int phy, int reg, int data) 1292143442Sobrien{ 1293143442Sobrien struct nve_softc *sc = device_get_softc(dev); 1294143442Sobrien 1295143442Sobrien DEBUGOUT(NVE_DEBUG_MII, "nve: nve_miibus_writereg - entry\n"); 1296143442Sobrien 1297143442Sobrien ADAPTER_WritePhy(sc->hwapi->pADCX, phy, reg, (ulong)data); 1298143442Sobrien 1299143442Sobrien DEBUGOUT(NVE_DEBUG_MII, "nve: nve_miibus_writereg - exit\n"); 1300143442Sobrien 1301188175Simp return 0; 1302143442Sobrien} 1303143442Sobrien 1304143442Sobrien/* Watchdog timer to prevent PHY lockups */ 1305143442Sobrienstatic void 1306199560Sjhbnve_watchdog(struct nve_softc *sc) 1307143442Sobrien{ 1308199560Sjhb struct ifnet *ifp; 1309158735Sjhb int pending_txs_start; 1310143442Sobrien 1311199560Sjhb NVE_LOCK_ASSERT(sc); 1312199560Sjhb ifp = sc->ifp; 1313158123Sjhb 1314158123Sjhb /* 1315158123Sjhb * The nvidia driver blob defers tx completion notifications. 1316158123Sjhb * Thus, sometimes the watchdog timer will go off when the 1317158123Sjhb * tx engine is fine, but the tx completions are just deferred. 1318158123Sjhb * Try kicking the driver blob to clear out any pending tx 1319158735Sjhb * completions. If that clears up any of the pending tx 1320158123Sjhb * operations, then just return without printing the warning 1321158735Sjhb * message or resetting the adapter, as we can then conclude 1322158735Sjhb * the chip hasn't actually crashed (it's still sending packets). 1323158123Sjhb */ 1324158735Sjhb pending_txs_start = sc->pending_txs; 1325158123Sjhb sc->hwapi->pfnDisableInterrupts(sc->hwapi->pADCX); 1326158123Sjhb sc->hwapi->pfnHandleInterrupt(sc->hwapi->pADCX); 1327158123Sjhb sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX); 1328199560Sjhb if (sc->pending_txs < pending_txs_start) 1329158123Sjhb return; 1330158123Sjhb 1331143442Sobrien device_printf(sc->dev, "device timeout (%d)\n", sc->pending_txs); 1332143442Sobrien 1333143442Sobrien sc->tx_errors++; 1334143442Sobrien 1335143442Sobrien nve_stop(sc); 1336152669Sjhb nve_init_locked(sc); 1337143442Sobrien 1338152669Sjhb if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1339152669Sjhb nve_ifstart_locked(ifp); 1340143442Sobrien} 1341143442Sobrien 1342143442Sobrien/* --- Start of NVOSAPI interface --- */ 1343143442Sobrien 1344143442Sobrien/* Allocate DMA enabled general use memory for API */ 1345242873Sdimstatic NV_API_CALL NV_SINT32 1346143442Sobriennve_osalloc(PNV_VOID ctx, PMEMORY_BLOCK mem) 1347143442Sobrien{ 1348143442Sobrien struct nve_softc *sc; 1349143442Sobrien bus_addr_t mem_physical; 1350143442Sobrien 1351143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_osalloc - %d\n", mem->uiLength); 1352143442Sobrien 1353143442Sobrien sc = (struct nve_softc *)ctx; 1354143442Sobrien 1355143442Sobrien mem->pLogical = (PVOID)contigmalloc(mem->uiLength, M_DEVBUF, 1356153333Sbz M_NOWAIT | M_ZERO, 0, 0xffffffff, PAGE_SIZE, 0); 1357143442Sobrien 1358143442Sobrien if (!mem->pLogical) { 1359143442Sobrien device_printf(sc->dev, "memory allocation failed\n"); 1360143442Sobrien return (0); 1361143442Sobrien } 1362143442Sobrien memset(mem->pLogical, 0, (ulong)mem->uiLength); 1363143442Sobrien mem_physical = vtophys(mem->pLogical); 1364143442Sobrien mem->pPhysical = (PVOID)mem_physical; 1365143442Sobrien 1366143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_osalloc 0x%x/0x%x - %d\n", 1367143442Sobrien (uint)mem->pLogical, (uint)mem->pPhysical, (uint)mem->uiLength); 1368143442Sobrien 1369143442Sobrien return (1); 1370143442Sobrien} 1371143442Sobrien 1372143442Sobrien/* Free allocated memory */ 1373242873Sdimstatic NV_API_CALL NV_SINT32 1374143442Sobriennve_osfree(PNV_VOID ctx, PMEMORY_BLOCK mem) 1375143442Sobrien{ 1376143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_osfree - 0x%x - %d\n", 1377143442Sobrien (uint)mem->pLogical, (uint) mem->uiLength); 1378143442Sobrien 1379143442Sobrien contigfree(mem->pLogical, PAGE_SIZE, M_DEVBUF); 1380143442Sobrien return (1); 1381143442Sobrien} 1382143442Sobrien 1383143442Sobrien/* Copied directly from nvnet.c */ 1384242873Sdimstatic NV_API_CALL NV_SINT32 1385143442Sobriennve_osallocex(PNV_VOID ctx, PMEMORY_BLOCKEX mem_block_ex) 1386143442Sobrien{ 1387143442Sobrien MEMORY_BLOCK mem_block; 1388143442Sobrien 1389143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_osallocex\n"); 1390143442Sobrien 1391143442Sobrien mem_block_ex->pLogical = NULL; 1392143442Sobrien mem_block_ex->uiLengthOrig = mem_block_ex->uiLength; 1393143442Sobrien 1394143442Sobrien if ((mem_block_ex->AllocFlags & ALLOC_MEMORY_ALIGNED) && 1395143442Sobrien (mem_block_ex->AlignmentSize > 1)) { 1396143442Sobrien DEBUGOUT(NVE_DEBUG_API, " aligning on %d\n", 1397143442Sobrien mem_block_ex->AlignmentSize); 1398143442Sobrien mem_block_ex->uiLengthOrig += mem_block_ex->AlignmentSize; 1399143442Sobrien } 1400143442Sobrien mem_block.uiLength = mem_block_ex->uiLengthOrig; 1401143442Sobrien 1402143442Sobrien if (nve_osalloc(ctx, &mem_block) == 0) { 1403143442Sobrien return (0); 1404143442Sobrien } 1405143442Sobrien mem_block_ex->pLogicalOrig = mem_block.pLogical; 1406143442Sobrien mem_block_ex->pPhysicalOrigLow = (unsigned long)mem_block.pPhysical; 1407143442Sobrien mem_block_ex->pPhysicalOrigHigh = 0; 1408143442Sobrien 1409143442Sobrien mem_block_ex->pPhysical = mem_block.pPhysical; 1410143442Sobrien mem_block_ex->pLogical = mem_block.pLogical; 1411143442Sobrien 1412143442Sobrien if (mem_block_ex->uiLength != mem_block_ex->uiLengthOrig) { 1413143442Sobrien unsigned int offset; 1414143442Sobrien offset = mem_block_ex->pPhysicalOrigLow & 1415143442Sobrien (mem_block_ex->AlignmentSize - 1); 1416143442Sobrien 1417143442Sobrien if (offset) { 1418143442Sobrien mem_block_ex->pPhysical = 1419143442Sobrien (PVOID)((ulong)mem_block_ex->pPhysical + 1420143442Sobrien mem_block_ex->AlignmentSize - offset); 1421143442Sobrien mem_block_ex->pLogical = 1422143442Sobrien (PVOID)((ulong)mem_block_ex->pLogical + 1423143442Sobrien mem_block_ex->AlignmentSize - offset); 1424143442Sobrien } /* if (offset) */ 1425143442Sobrien } /* if (mem_block_ex->uiLength != *mem_block_ex->uiLengthOrig) */ 1426143442Sobrien return (1); 1427143442Sobrien} 1428143442Sobrien 1429143442Sobrien/* Copied directly from nvnet.c */ 1430242873Sdimstatic NV_API_CALL NV_SINT32 1431143442Sobriennve_osfreeex(PNV_VOID ctx, PMEMORY_BLOCKEX mem_block_ex) 1432143442Sobrien{ 1433143442Sobrien MEMORY_BLOCK mem_block; 1434143442Sobrien 1435143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_osfreeex\n"); 1436143442Sobrien 1437143442Sobrien mem_block.pLogical = mem_block_ex->pLogicalOrig; 1438143442Sobrien mem_block.pPhysical = (PVOID)((ulong)mem_block_ex->pPhysicalOrigLow); 1439143442Sobrien mem_block.uiLength = mem_block_ex->uiLengthOrig; 1440143442Sobrien 1441143442Sobrien return (nve_osfree(ctx, &mem_block)); 1442143442Sobrien} 1443143442Sobrien 1444143442Sobrien/* Clear memory region */ 1445242873Sdimstatic NV_API_CALL NV_SINT32 1446143442Sobriennve_osclear(PNV_VOID ctx, PNV_VOID mem, NV_SINT32 length) 1447143442Sobrien{ 1448143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_osclear\n"); 1449143442Sobrien memset(mem, 0, length); 1450143442Sobrien return (1); 1451143442Sobrien} 1452143442Sobrien 1453143442Sobrien/* Sleep for a tick */ 1454242873Sdimstatic NV_API_CALL NV_SINT32 1455143442Sobriennve_osdelay(PNV_VOID ctx, NV_UINT32 usec) 1456143442Sobrien{ 1457143442Sobrien DELAY(usec); 1458143442Sobrien return (1); 1459143442Sobrien} 1460143442Sobrien 1461143442Sobrien/* Allocate memory for rx buffer */ 1462242873Sdimstatic NV_API_CALL NV_SINT32 1463143442Sobriennve_osallocrxbuf(PNV_VOID ctx, PMEMORY_BLOCK mem, PNV_VOID *id) 1464143442Sobrien{ 1465143442Sobrien struct nve_softc *sc = ctx; 1466143442Sobrien struct nve_rx_desc *desc; 1467143442Sobrien struct nve_map_buffer *buf; 1468143442Sobrien int error; 1469143442Sobrien 1470152669Sjhb if (device_is_attached(sc->dev)) 1471152669Sjhb NVE_LOCK_ASSERT(sc); 1472143442Sobrien 1473143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_osallocrxbuf\n"); 1474143442Sobrien 1475143442Sobrien if (sc->pending_rxs == RX_RING_SIZE) { 1476143442Sobrien device_printf(sc->dev, "rx ring buffer is full\n"); 1477143442Sobrien goto fail; 1478143442Sobrien } 1479143442Sobrien desc = sc->rx_desc + sc->cur_rx; 1480143442Sobrien buf = &desc->buf; 1481143442Sobrien 1482143442Sobrien if (buf->mbuf == NULL) { 1483243857Sglebius buf->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 1484143442Sobrien if (buf->mbuf == NULL) { 1485143442Sobrien device_printf(sc->dev, "failed to allocate memory\n"); 1486143442Sobrien goto fail; 1487143442Sobrien } 1488143442Sobrien buf->mbuf->m_len = buf->mbuf->m_pkthdr.len = MCLBYTES; 1489143442Sobrien m_adj(buf->mbuf, ETHER_ALIGN); 1490143442Sobrien 1491143442Sobrien error = bus_dmamap_load_mbuf(sc->mtag, buf->map, buf->mbuf, 1492143442Sobrien nve_dmamap_rx_cb, &desc->paddr, 0); 1493143442Sobrien if (error) { 1494143442Sobrien device_printf(sc->dev, "failed to dmamap mbuf\n"); 1495143442Sobrien m_freem(buf->mbuf); 1496143442Sobrien buf->mbuf = NULL; 1497143442Sobrien goto fail; 1498143442Sobrien } 1499143442Sobrien bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_PREREAD); 1500143442Sobrien desc->buflength = buf->mbuf->m_len; 1501143442Sobrien desc->vaddr = mtod(buf->mbuf, caddr_t); 1502143442Sobrien } 1503143442Sobrien sc->pending_rxs++; 1504143442Sobrien sc->cur_rx = (sc->cur_rx + 1) % RX_RING_SIZE; 1505143442Sobrien 1506143442Sobrien mem->pLogical = (void *)desc->vaddr; 1507143442Sobrien mem->pPhysical = (void *)desc->paddr; 1508143442Sobrien mem->uiLength = desc->buflength; 1509143442Sobrien *id = (void *)desc; 1510143442Sobrien 1511143442Sobrien return (1); 1512143442Sobrien 1513143442Sobrienfail: 1514143442Sobrien return (0); 1515143442Sobrien} 1516143442Sobrien 1517143442Sobrien/* Free the rx buffer */ 1518242873Sdimstatic NV_API_CALL NV_SINT32 1519143442Sobriennve_osfreerxbuf(PNV_VOID ctx, PMEMORY_BLOCK mem, PNV_VOID id) 1520143442Sobrien{ 1521143442Sobrien struct nve_softc *sc = ctx; 1522143442Sobrien struct nve_rx_desc *desc; 1523143442Sobrien struct nve_map_buffer *buf; 1524143442Sobrien 1525143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_osfreerxbuf\n"); 1526143442Sobrien 1527143442Sobrien desc = (struct nve_rx_desc *) id; 1528143442Sobrien buf = &desc->buf; 1529143442Sobrien 1530143442Sobrien if (buf->mbuf) { 1531143442Sobrien bus_dmamap_unload(sc->mtag, buf->map); 1532143442Sobrien bus_dmamap_destroy(sc->mtag, buf->map); 1533143442Sobrien m_freem(buf->mbuf); 1534143442Sobrien } 1535143442Sobrien sc->pending_rxs--; 1536143442Sobrien buf->mbuf = NULL; 1537143442Sobrien 1538143442Sobrien return (1); 1539143442Sobrien} 1540143442Sobrien 1541143442Sobrien/* This gets called by the Nvidia API after our TX packet has been sent */ 1542242873Sdimstatic NV_API_CALL NV_SINT32 1543143442Sobriennve_ospackettx(PNV_VOID ctx, PNV_VOID id, NV_UINT32 success) 1544143442Sobrien{ 1545143442Sobrien struct nve_softc *sc = ctx; 1546143442Sobrien struct nve_map_buffer *buf; 1547143442Sobrien struct nve_tx_desc *desc = (struct nve_tx_desc *) id; 1548143442Sobrien struct ifnet *ifp; 1549143442Sobrien 1550152669Sjhb NVE_LOCK_ASSERT(sc); 1551143442Sobrien 1552143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_ospackettx\n"); 1553143442Sobrien 1554147256Sbrooks ifp = sc->ifp; 1555143442Sobrien buf = &desc->buf; 1556143442Sobrien sc->pending_txs--; 1557143442Sobrien 1558143442Sobrien /* Unload and free mbuf cluster */ 1559143442Sobrien if (buf->mbuf == NULL) 1560143442Sobrien goto fail; 1561143442Sobrien 1562143442Sobrien bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTWRITE); 1563143442Sobrien bus_dmamap_unload(sc->mtag, buf->map); 1564143442Sobrien m_freem(buf->mbuf); 1565143442Sobrien buf->mbuf = NULL; 1566143442Sobrien 1567143442Sobrien /* Send more packets if we have them */ 1568143442Sobrien if (sc->pending_txs < TX_RING_SIZE) 1569148887Srwatson sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1570143442Sobrien 1571152669Sjhb if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->pending_txs < TX_RING_SIZE) 1572152669Sjhb nve_ifstart_locked(ifp); 1573143442Sobrien 1574143442Sobrienfail: 1575143442Sobrien 1576143442Sobrien return (1); 1577143442Sobrien} 1578143442Sobrien 1579143442Sobrien/* This gets called by the Nvidia API when a new packet has been received */ 1580143442Sobrien/* XXX What is newbuf used for? XXX */ 1581242873Sdimstatic NV_API_CALL NV_SINT32 1582143442Sobriennve_ospacketrx(PNV_VOID ctx, PNV_VOID data, NV_UINT32 success, NV_UINT8 *newbuf, 1583143442Sobrien NV_UINT8 priority) 1584143442Sobrien{ 1585143442Sobrien struct nve_softc *sc = ctx; 1586143442Sobrien struct ifnet *ifp; 1587143442Sobrien struct nve_rx_desc *desc; 1588143442Sobrien struct nve_map_buffer *buf; 1589143442Sobrien ADAPTER_READ_DATA *readdata; 1590152669Sjhb struct mbuf *m; 1591143442Sobrien 1592152669Sjhb NVE_LOCK_ASSERT(sc); 1593143442Sobrien 1594143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_ospacketrx\n"); 1595143442Sobrien 1596147256Sbrooks ifp = sc->ifp; 1597143442Sobrien 1598143442Sobrien readdata = (ADAPTER_READ_DATA *) data; 1599143442Sobrien desc = readdata->pvID; 1600143442Sobrien buf = &desc->buf; 1601143442Sobrien bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTREAD); 1602143442Sobrien 1603143442Sobrien if (success) { 1604143442Sobrien /* Sync DMA bounce buffer. */ 1605143442Sobrien bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTREAD); 1606143442Sobrien 1607143442Sobrien /* First mbuf in packet holds the ethernet and packet headers */ 1608143442Sobrien buf->mbuf->m_pkthdr.rcvif = ifp; 1609143442Sobrien buf->mbuf->m_pkthdr.len = buf->mbuf->m_len = 1610143442Sobrien readdata->ulTotalLength; 1611143442Sobrien 1612143442Sobrien bus_dmamap_unload(sc->mtag, buf->map); 1613143442Sobrien 1614152669Sjhb /* Blat the mbuf pointer, kernel will free the mbuf cluster */ 1615152669Sjhb m = buf->mbuf; 1616152669Sjhb buf->mbuf = NULL; 1617152669Sjhb 1618143442Sobrien /* Give mbuf to OS. */ 1619152669Sjhb NVE_UNLOCK(sc); 1620152669Sjhb (*ifp->if_input)(ifp, m); 1621152669Sjhb NVE_LOCK(sc); 1622143442Sobrien if (readdata->ulFilterMatch & ADREADFL_MULTICAST_MATCH) 1623143442Sobrien ifp->if_imcasts++; 1624143442Sobrien 1625143442Sobrien } else { 1626143442Sobrien bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTREAD); 1627143442Sobrien bus_dmamap_unload(sc->mtag, buf->map); 1628143442Sobrien m_freem(buf->mbuf); 1629143442Sobrien buf->mbuf = NULL; 1630143442Sobrien } 1631143442Sobrien 1632143442Sobrien sc->cur_rx = desc - sc->rx_desc; 1633143442Sobrien sc->pending_rxs--; 1634143442Sobrien 1635143442Sobrien return (1); 1636143442Sobrien} 1637143442Sobrien 1638143442Sobrien/* This gets called by NVIDIA API when the PHY link state changes */ 1639242873Sdimstatic NV_API_CALL NV_SINT32 1640143442Sobriennve_oslinkchg(PNV_VOID ctx, NV_SINT32 enabled) 1641143442Sobrien{ 1642143442Sobrien 1643143442Sobrien DEBUGOUT(NVE_DEBUG_API, "nve: nve_oslinkchg\n"); 1644143442Sobrien 1645143442Sobrien return (1); 1646143442Sobrien} 1647143442Sobrien 1648143442Sobrien/* Setup a watchdog timer */ 1649242873Sdimstatic NV_API_CALL NV_SINT32 1650143442Sobriennve_osalloctimer(PNV_VOID ctx, PNV_VOID *timer) 1651143442Sobrien{ 1652143442Sobrien struct nve_softc *sc = (struct nve_softc *)ctx; 1653143442Sobrien 1654143442Sobrien DEBUGOUT(NVE_DEBUG_BROKEN, "nve: nve_osalloctimer\n"); 1655143442Sobrien 1656152669Sjhb callout_init(&sc->ostimer, CALLOUT_MPSAFE); 1657143442Sobrien *timer = &sc->ostimer; 1658143442Sobrien 1659143442Sobrien return (1); 1660143442Sobrien} 1661143442Sobrien 1662143442Sobrien/* Free the timer */ 1663242873Sdimstatic NV_API_CALL NV_SINT32 1664143442Sobriennve_osfreetimer(PNV_VOID ctx, PNV_VOID timer) 1665143442Sobrien{ 1666143442Sobrien 1667143442Sobrien DEBUGOUT(NVE_DEBUG_BROKEN, "nve: nve_osfreetimer\n"); 1668143442Sobrien 1669152669Sjhb callout_drain((struct callout *)timer); 1670152669Sjhb 1671143442Sobrien return (1); 1672143442Sobrien} 1673143442Sobrien 1674143442Sobrien/* Setup timer parameters */ 1675242873Sdimstatic NV_API_CALL NV_SINT32 1676143442Sobriennve_osinittimer(PNV_VOID ctx, PNV_VOID timer, PTIMER_FUNC func, PNV_VOID parameters) 1677143442Sobrien{ 1678143442Sobrien struct nve_softc *sc = (struct nve_softc *)ctx; 1679143442Sobrien 1680143442Sobrien DEBUGOUT(NVE_DEBUG_BROKEN, "nve: nve_osinittimer\n"); 1681143442Sobrien 1682143442Sobrien sc->ostimer_func = func; 1683143442Sobrien sc->ostimer_params = parameters; 1684143442Sobrien 1685143442Sobrien return (1); 1686143442Sobrien} 1687143442Sobrien 1688143442Sobrien/* Set the timer to go off */ 1689242873Sdimstatic NV_API_CALL NV_SINT32 1690143442Sobriennve_ossettimer(PNV_VOID ctx, PNV_VOID timer, NV_UINT32 delay) 1691143442Sobrien{ 1692143442Sobrien struct nve_softc *sc = ctx; 1693143442Sobrien 1694143442Sobrien DEBUGOUT(NVE_DEBUG_BROKEN, "nve: nve_ossettimer\n"); 1695143442Sobrien 1696152669Sjhb callout_reset((struct callout *)timer, delay, sc->ostimer_func, 1697152669Sjhb sc->ostimer_params); 1698143442Sobrien 1699143442Sobrien return (1); 1700143442Sobrien} 1701143442Sobrien 1702143442Sobrien/* Cancel the timer */ 1703242873Sdimstatic NV_API_CALL NV_SINT32 1704143442Sobriennve_oscanceltimer(PNV_VOID ctx, PNV_VOID timer) 1705143442Sobrien{ 1706143442Sobrien 1707143442Sobrien DEBUGOUT(NVE_DEBUG_BROKEN, "nve: nve_oscanceltimer\n"); 1708143442Sobrien 1709152669Sjhb callout_stop((struct callout *)timer); 1710143442Sobrien 1711143442Sobrien return (1); 1712143442Sobrien} 1713143442Sobrien 1714242873Sdimstatic NV_API_CALL NV_SINT32 1715143442Sobriennve_ospreprocpkt(PNV_VOID ctx, PNV_VOID readdata, PNV_VOID *id, 1716143442Sobrien NV_UINT8 *newbuffer, NV_UINT8 priority) 1717143442Sobrien{ 1718143442Sobrien 1719143442Sobrien /* Not implemented */ 1720143442Sobrien DEBUGOUT(NVE_DEBUG_BROKEN, "nve: nve_ospreprocpkt\n"); 1721143442Sobrien 1722143442Sobrien return (1); 1723143442Sobrien} 1724143442Sobrien 1725242873Sdimstatic NV_API_CALL PNV_VOID 1726143442Sobriennve_ospreprocpktnopq(PNV_VOID ctx, PNV_VOID readdata) 1727143442Sobrien{ 1728143442Sobrien 1729143442Sobrien /* Not implemented */ 1730143442Sobrien DEBUGOUT(NVE_DEBUG_BROKEN, "nve: nve_ospreprocpkt\n"); 1731143442Sobrien 1732143442Sobrien return (NULL); 1733143442Sobrien} 1734143442Sobrien 1735242873Sdimstatic NV_API_CALL NV_SINT32 1736143442Sobriennve_osindicatepkt(PNV_VOID ctx, PNV_VOID *id, NV_UINT32 pktno) 1737143442Sobrien{ 1738143442Sobrien 1739143442Sobrien /* Not implemented */ 1740143442Sobrien DEBUGOUT(NVE_DEBUG_BROKEN, "nve: nve_osindicatepkt\n"); 1741143442Sobrien 1742143442Sobrien return (1); 1743143442Sobrien} 1744143442Sobrien 1745143442Sobrien/* Allocate mutex context (already done in nve_attach) */ 1746242873Sdimstatic NV_API_CALL NV_SINT32 1747143442Sobriennve_oslockalloc(PNV_VOID ctx, NV_SINT32 type, PNV_VOID *pLock) 1748143442Sobrien{ 1749143442Sobrien struct nve_softc *sc = (struct nve_softc *)ctx; 1750143442Sobrien 1751143442Sobrien DEBUGOUT(NVE_DEBUG_LOCK, "nve: nve_oslockalloc\n"); 1752143442Sobrien 1753143442Sobrien *pLock = (void **)sc; 1754143442Sobrien 1755143442Sobrien return (1); 1756143442Sobrien} 1757143442Sobrien 1758143442Sobrien/* Obtain a spin lock */ 1759242873Sdimstatic NV_API_CALL NV_SINT32 1760143442Sobriennve_oslockacquire(PNV_VOID ctx, NV_SINT32 type, PNV_VOID lock) 1761143442Sobrien{ 1762143442Sobrien 1763143442Sobrien DEBUGOUT(NVE_DEBUG_LOCK, "nve: nve_oslockacquire\n"); 1764143442Sobrien 1765143442Sobrien return (1); 1766143442Sobrien} 1767143442Sobrien 1768143442Sobrien/* Release lock */ 1769242873Sdimstatic NV_API_CALL NV_SINT32 1770143442Sobriennve_oslockrelease(PNV_VOID ctx, NV_SINT32 type, PNV_VOID lock) 1771143442Sobrien{ 1772143442Sobrien 1773143442Sobrien DEBUGOUT(NVE_DEBUG_LOCK, "nve: nve_oslockrelease\n"); 1774143442Sobrien 1775143442Sobrien return (1); 1776143442Sobrien} 1777143442Sobrien 1778143442Sobrien/* I have no idea what this is for */ 1779242873Sdimstatic NV_API_CALL PNV_VOID 1780143442Sobriennve_osreturnbufvirt(PNV_VOID ctx, PNV_VOID readdata) 1781143442Sobrien{ 1782143442Sobrien 1783143442Sobrien /* Not implemented */ 1784143442Sobrien DEBUGOUT(NVE_DEBUG_LOCK, "nve: nve_osreturnbufvirt\n"); 1785143442Sobrien panic("nve: nve_osreturnbufvirtual not implemented\n"); 1786143442Sobrien 1787143442Sobrien return (NULL); 1788143442Sobrien} 1789143442Sobrien 1790143442Sobrien/* --- End on NVOSAPI interface --- */ 1791