Remove the INTR_TYPE_* flags. The interrupt type is no longer used to
[dragonfly.git] / sys / dev / netif / nv / if_nv.c
1 /*
2  * Copyright (c) 2003, 2004 by Quinton Dolan <q@onthenet.com.au>. 
3  * All rights reserved.
4  * 
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions 
7  * are met: 
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer. 
10  * 2. Redistributions in binary form must reproduce the above copyright 
11  *    notice, this list of conditions and the following disclaimer in the 
12  *    documentation and/or other materials provided with the distribution.
13  * 
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  * 
26  * $Id: if_nv.c,v 1.20 2005/03/12 01:11:00 q Exp $
27  * $DragonFly: src/sys/dev/netif/nv/Attic/if_nv.c,v 1.19 2005/10/12 17:35:52 dillon Exp $
28  */
29
30 /*
31  * NVIDIA nForce MCP Networking Adapter driver
32  * 
33  * This is a port of the NVIDIA MCP Linux ethernet driver distributed by NVIDIA
34  * through their web site.
35  * 
36  * All mainstream nForce and nForce2 motherboards are supported. This module
37  * is as stable, sometimes more stable, than the linux version. (Recent
38  * Linux stability issues seem to be related to some issues with newer
39  * distributions using GCC 3.x, however this don't appear to effect FreeBSD
40  * 5.x).
41  * 
42  * In accordance with the NVIDIA distribution license it is necessary to
43  * link this module against the nvlibnet.o binary object included in the
44  * Linux driver source distribution. The binary component is not modified in
45  * any way and is simply linked against a FreeBSD equivalent of the nvnet.c
46  * linux kernel module "wrapper".
47  * 
48  * The Linux driver uses a common code API that is shared between Win32 and
49  * i386 Linux. This abstracts the low level driver functions and uses
50  * callbacks and hooks to access the underlying hardware device. By using
51  * this same API in a FreeBSD kernel module it is possible to support the
52  * hardware without breaching the Linux source distributions licensing
53  * requirements, or obtaining the hardware programming specifications.
54  * 
55  * Although not conventional, it works, and given the relatively small
56  * amount of hardware centric code, it's hopefully no more buggy than its
57  * linux counterpart.
58  *
59  * NVIDIA now suppport the nForce3 AMD64 platform, however I have been
60  * unable to access such a system to verify support. However, the code is
61  * reported to work with little modification when compiled with the AMD64
62  * version of the NVIDIA Linux library. All that should be necessary to make
63  * the driver work is to link it directly into the kernel, instead of as a
64  * module, and apply the docs/amd64.diff patch in this source distribution to
65  * the NVIDIA Linux driver source.
66  *
67  * This driver should work on all versions of FreeBSD since 4.9/5.1 as well
68  * as recent versions of DragonFly.
69  *
70  * Written by Quinton Dolan <q@onthenet.com.au> 
71  * Portions based on existing FreeBSD network drivers. 
72  * NVIDIA API usage derived from distributed NVIDIA NVNET driver source files.
73  * 
74  * $Id: if_nv.c,v 1.9 2003/12/13 15:27:40 q Exp $
75  */
76
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/sockio.h>
80 #include <sys/mbuf.h>
81 #include <sys/malloc.h>
82 #include <sys/kernel.h>
83 #include <sys/socket.h>
84 #include <sys/sysctl.h>
85 #include <sys/queue.h>
86 #include <sys/module.h>
87 #include <sys/thread2.h>
88
89 #include <net/if.h>
90 #include <net/ifq_var.h>
91 #include <net/if_arp.h>
92 #include <net/ethernet.h>
93 #include <net/if_dl.h>
94 #include <net/if_media.h>
95
96 #include <net/bpf.h>
97
98 #include <net/vlan/if_vlan_var.h>
99
100 #include <machine/bus_memio.h>
101 #include <machine/bus.h>
102 #include <machine/resource.h>
103
104 #include <vm/vm.h>              /* for vtophys */
105 #include <vm/pmap.h>            /* for vtophys */
106 #include <machine/clock.h>      /* for DELAY */
107 #include <sys/bus.h>
108 #include <sys/rman.h>
109 #include <sys/serialize.h>
110
111 #include <bus/pci/pcireg.h>
112 #include <bus/pci/pcivar.h>
113
114 #include <dev/netif/mii_layer/mii.h>
115 #include <dev/netif/mii_layer/miivar.h>
116
117 MODULE_DEPEND(nv, pci, 1, 1, 1);
118 MODULE_DEPEND(nv, miibus, 1, 1, 1);
119
120 #include "if_nvreg.h"
121 #include "miibus_if.h"
122
123 static int      nv_probe(device_t);
124 static int      nv_attach(device_t);
125 static int      nv_detach(device_t);
126 static void     nv_init(void *);
127 static void     nv_init_serialized(struct nv_softc *);
128 static void     nv_stop(struct nv_softc *);
129 static void     nv_stop_serialized(struct nv_softc *);
130 static void     nv_shutdown(device_t);
131 static int      nv_init_rings(struct nv_softc *);
132 static void     nv_free_rings(struct nv_softc *);
133
134 static void     nv_ifstart(struct ifnet *);
135 static void     nv_ifstart_serialized(struct ifnet *);
136 static int      nv_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
137 static void     nv_intr(void *);
138 static void     nv_tick(void *);
139 static void     nv_setmulti(struct nv_softc *);
140 static void     nv_watchdog(struct ifnet *);
141 static void     nv_update_stats(struct nv_softc *);
142 #ifdef DEVICE_POLLING
143 static void     nv_poll(struct ifnet *, enum poll_cmd, int);
144 #endif
145
146 static int      nv_ifmedia_upd(struct ifnet *);
147 static void     nv_ifmedia_sts(struct ifnet *, struct ifmediareq *);
148 static int      nv_miibus_readreg(device_t, int, int);
149 static void     nv_miibus_writereg(device_t, int, int, int);
150
151 static void     nv_dmamap_cb(void *, bus_dma_segment_t *, int, int);
152 static void     nv_dmamap_tx_cb(void *, bus_dma_segment_t *, int, bus_size_t, int);
153
154 static NV_SINT32 nv_osalloc(PNV_VOID, PMEMORY_BLOCK);
155 static NV_SINT32 nv_osfree(PNV_VOID, PMEMORY_BLOCK);
156 static NV_SINT32 nv_osallocex(PNV_VOID, PMEMORY_BLOCKEX);
157 static NV_SINT32 nv_osfreeex(PNV_VOID, PMEMORY_BLOCKEX);
158 static NV_SINT32 nv_osclear(PNV_VOID, PNV_VOID, NV_SINT32);
159 static NV_SINT32 nv_osdelay(PNV_VOID, NV_UINT32);
160 static NV_SINT32 nv_osallocrxbuf(PNV_VOID, PMEMORY_BLOCK, PNV_VOID *);
161 static NV_SINT32 nv_osfreerxbuf(PNV_VOID, PMEMORY_BLOCK, PNV_VOID);
162 static NV_SINT32 nv_ospackettx(PNV_VOID, PNV_VOID, NV_UINT32);
163 static NV_SINT32 nv_ospacketrx(PNV_VOID, PNV_VOID, NV_UINT32, NV_UINT8 *, NV_UINT8);
164 static NV_SINT32 nv_oslinkchg(PNV_VOID, NV_SINT32);
165 static NV_SINT32 nv_osalloctimer(PNV_VOID, PNV_VOID *);
166 static NV_SINT32 nv_osfreetimer(PNV_VOID, PNV_VOID);
167 static NV_SINT32 nv_osinittimer(PNV_VOID, PNV_VOID, PTIMER_FUNC, PNV_VOID);
168 static NV_SINT32 nv_ossettimer(PNV_VOID, PNV_VOID, NV_UINT32);
169 static NV_SINT32 nv_oscanceltimer(PNV_VOID, PNV_VOID);
170
171 static NV_SINT32 nv_ospreprocpkt(PNV_VOID, PNV_VOID, PNV_VOID *, NV_UINT8 *, NV_UINT8);
172 static PNV_VOID  nv_ospreprocpktnopq(PNV_VOID, PNV_VOID);
173 static NV_SINT32 nv_osindicatepkt(PNV_VOID, PNV_VOID *, NV_UINT32);
174 static NV_SINT32 nv_oslockalloc(PNV_VOID, NV_SINT32, PNV_VOID *);
175 static NV_SINT32 nv_oslockacquire(PNV_VOID, NV_SINT32, PNV_VOID);
176 static NV_SINT32 nv_oslockrelease(PNV_VOID, NV_SINT32, PNV_VOID);
177 static PNV_VOID  nv_osreturnbufvirt(PNV_VOID, PNV_VOID);
178
179 static device_method_t nv_methods[] = {
180         /* Device interface */
181         DEVMETHOD(device_probe, nv_probe),
182         DEVMETHOD(device_attach, nv_attach),
183         DEVMETHOD(device_detach, nv_detach),
184         DEVMETHOD(device_shutdown, nv_shutdown),
185
186         /* Bus interface */
187         DEVMETHOD(bus_print_child, bus_generic_print_child),
188         DEVMETHOD(bus_driver_added, bus_generic_driver_added),
189
190         /* MII interface */
191         DEVMETHOD(miibus_readreg, nv_miibus_readreg),
192         DEVMETHOD(miibus_writereg, nv_miibus_writereg),
193
194         {0, 0}
195 };
196
197 static driver_t nv_driver = {
198         "nv",
199         nv_methods,
200         sizeof(struct nv_softc)
201 };
202
203 static devclass_t nv_devclass;
204
205 static int      nv_pollinterval = 0;
206 SYSCTL_INT(_hw, OID_AUTO, nv_pollinterval, CTLFLAG_RW,
207            &nv_pollinterval, 0, "delay between interface polls");
208
209 DRIVER_MODULE(nv, pci, nv_driver, nv_devclass, 0, 0);
210 DRIVER_MODULE(miibus, nv, miibus_driver, miibus_devclass, 0, 0);
211
212 static struct nv_type nv_devs[] = {
213         {NVIDIA_VENDORID, NFORCE_MCPNET1_DEVICEID,
214                 "NVIDIA nForce MCP Networking Adapter"},
215         {NVIDIA_VENDORID, NFORCE_MCPNET2_DEVICEID,
216                 "NVIDIA nForce MCP2 Networking Adapter"},
217         {NVIDIA_VENDORID, NFORCE_MCPNET3_DEVICEID,
218                 "NVIDIA nForce MCP3 Networking Adapter"},
219         {NVIDIA_VENDORID, NFORCE_MCPNET4_DEVICEID,
220                 "NVIDIA nForce MCP4 Networking Adapter"},
221         {NVIDIA_VENDORID, NFORCE_MCPNET5_DEVICEID,
222                 "NVIDIA nForce MCP5 Networking Adapter"},
223         {NVIDIA_VENDORID, NFORCE_MCPNET6_DEVICEID,
224                 "NVIDIA nForce MCP6 Networking Adapter"},
225         {NVIDIA_VENDORID, NFORCE_MCPNET7_DEVICEID,
226                 "NVIDIA nForce MCP7 Networking Adapter"},
227         {NVIDIA_VENDORID, NFORCE_MCPNET8_DEVICEID,
228                 "NVIDIA nForce MCP8 Networking Adapter"},
229         {NVIDIA_VENDORID, NFORCE_MCPNET9_DEVICEID,
230                 "NVIDIA nForce MCP9 Networking Adapter"},
231         {NVIDIA_VENDORID, NFORCE_MCPNET10_DEVICEID,
232                 "NVIDIA nForce MCP10 Networking Adapter"},
233         {NVIDIA_VENDORID, NFORCE_MCPNET11_DEVICEID,
234                 "NVIDIA nForce MCP11 Networking Adapter"},
235         {0, 0, NULL}
236 };
237
238 /* DMA MEM map callback function to get data segment physical address */
239 static void
240 nv_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nsegs, int error)
241 {
242         if (error)
243                 return;
244
245         KASSERT(nsegs == 1,
246                 ("Too many DMA segments returned when mapping DMA memory"));
247         *(bus_addr_t *)arg = segs->ds_addr;
248 }
249
250 /* DMA RX map callback function to get data segment physical address */
251 static void
252 nv_dmamap_rx_cb(void *arg, bus_dma_segment_t * segs, int nsegs, bus_size_t mapsize, int error)
253 {
254         if (error)
255                 return;
256         *(bus_addr_t *)arg = segs->ds_addr;
257 }
258
259 /*
260  * DMA TX buffer callback function to allocate fragment data segment
261  * addresses
262  */
263 static void
264 nv_dmamap_tx_cb(void *arg, bus_dma_segment_t * segs, int nsegs, bus_size_t mapsize, int error)
265 {
266         struct nv_tx_desc *info = arg;
267
268         if (error)
269                 return;
270         KASSERT(nsegs < NV_MAX_FRAGS,
271                 ("Too many DMA segments returned when mapping mbuf"));
272         info->numfrags = nsegs;
273         bcopy(segs, info->frags, nsegs * sizeof(bus_dma_segment_t));
274 }
275
276 /* Probe for supported hardware ID's */
277 static int
278 nv_probe(device_t dev)
279 {
280         struct nv_type *t = nv_devs;
281
282         /* Check for matching PCI DEVICE ID's */
283         while (t->name != NULL) {
284                 if ((pci_get_vendor(dev) == t->vid_id) &&
285                     (pci_get_device(dev) == t->dev_id)) {
286                         device_set_desc(dev, t->name);
287                         return (0);
288                 }
289                 t++;
290         }
291
292         return (ENXIO);
293 }
294
295 /* Attach driver and initialise hardware for use */
296 static int
297 nv_attach(device_t dev)
298 {
299         u_char          eaddr[ETHER_ADDR_LEN];
300         struct nv_softc *sc;
301         struct ifnet   *ifp;
302         OS_API         *osapi;
303         ADAPTER_OPEN_PARAMS OpenParams;
304         int             error = 0, i, rid;
305         u_int32_t       unit;
306
307         DEBUGOUT(NV_DEBUG_INIT, "nv: nv_attach - entry\n");
308
309         sc = device_get_softc(dev);
310         unit = device_get_unit(dev);
311
312         sc->dev = dev;
313         sc->unit = unit;
314         lwkt_serialize_init(&sc->serializer);
315         callout_init(&sc->nv_stat_timer);
316
317         /* Preinitialize data structures */
318         bzero(&OpenParams, sizeof(ADAPTER_OPEN_PARAMS));
319
320         /* Enable bus mastering */
321         pci_enable_busmaster(dev);
322
323         /* Allocate memory mapped address space */
324         rid = NV_RID;
325         sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
326
327         if (sc->res == NULL) {
328                 device_printf(dev, "couldn't map memory\n");
329                 error = ENXIO;
330                 goto fail;
331         }
332         sc->sc_st = rman_get_bustag(sc->res);
333         sc->sc_sh = rman_get_bushandle(sc->res);
334
335         /* Allocate interrupt */
336         rid = 0;
337         sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
338             RF_SHAREABLE | RF_ACTIVE);
339
340         if (sc->irq == NULL) {
341                 device_printf(dev, "couldn't map interrupt\n");
342                 error = ENXIO;
343                 goto fail;
344         }
345         /* Allocate DMA tags */
346         error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT,
347                      BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES * NV_MAX_FRAGS,
348                                    NV_MAX_FRAGS, MCLBYTES, 0,
349                                    &sc->mtag);
350         if (error) {
351                 device_printf(dev, "couldn't allocate dma tag\n");
352                 goto fail;
353         }
354         error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT,
355                                    BUS_SPACE_MAXADDR, NULL, NULL,
356                                 sizeof(struct nv_rx_desc) * RX_RING_SIZE, 1,
357                                 sizeof(struct nv_rx_desc) * RX_RING_SIZE, 0,
358                                    &sc->rtag);
359         if (error) {
360                 device_printf(dev, "couldn't allocate dma tag\n");
361                 goto fail;
362         }
363         error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT,
364                                    BUS_SPACE_MAXADDR, NULL, NULL,
365                                 sizeof(struct nv_tx_desc) * TX_RING_SIZE, 1,
366                                 sizeof(struct nv_tx_desc) * TX_RING_SIZE, 0,
367                                    &sc->ttag);
368         if (error) {
369                 device_printf(dev, "couldn't allocate dma tag\n");
370                 goto fail;
371         }
372
373         error = bus_dmamap_create(sc->ttag, 0, &sc->tmap);
374         if (error) {
375                 device_printf(dev, "couldn't create dma map\n");
376                 goto fail;
377         }
378
379         /* Allocate DMA safe memory and get the DMA addresses. */
380         error = bus_dmamem_alloc(sc->ttag, (void **)&sc->tx_desc,
381                                  BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->tmap);
382         if (error) {
383                 device_printf(dev, "couldn't allocate dma memory\n");
384                 goto fail;
385         }
386         error = bus_dmamap_load(sc->ttag, sc->tmap, sc->tx_desc,
387                      sizeof(struct nv_tx_desc) * TX_RING_SIZE, nv_dmamap_cb,
388                                 &sc->tx_addr, 0);
389         if (error) {
390                 device_printf(dev, "couldn't map dma memory\n");
391                 goto fail;
392         }
393
394         error = bus_dmamap_create(sc->rtag, 0, &sc->rmap);
395         if (error) {
396                 device_printf(dev, "couldn't create dma map\n");
397                 goto fail;
398         }
399
400         error = bus_dmamem_alloc(sc->rtag, (void **)&sc->rx_desc,
401                                  BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->rmap);
402         if (error) {
403                 device_printf(dev, "couldn't allocate dma memory\n");
404                 goto fail;
405         }
406         error = bus_dmamap_load(sc->rtag, sc->rmap, sc->rx_desc,
407                      sizeof(struct nv_rx_desc) * RX_RING_SIZE, nv_dmamap_cb,
408                                 &sc->rx_addr, 0);
409         if (error) {
410                 device_printf(dev, "couldn't map dma memory\n");
411                 goto fail;
412         }
413         /* Initialize rings. */
414         if (nv_init_rings(sc)) {
415                 device_printf(dev, "failed to init rings\n");
416                 error = ENXIO;
417                 goto fail;
418         }
419         /* Setup NVIDIA API callback routines */
420         osapi = &sc->osapi;
421         osapi->pOSCX = sc;
422         osapi->pfnAllocMemory = nv_osalloc;
423         osapi->pfnFreeMemory = nv_osfree;
424         osapi->pfnAllocMemoryEx = nv_osallocex;
425         osapi->pfnFreeMemoryEx = nv_osfreeex;
426         osapi->pfnClearMemory = nv_osclear;
427         osapi->pfnStallExecution = nv_osdelay;
428         osapi->pfnAllocReceiveBuffer = nv_osallocrxbuf;
429         osapi->pfnFreeReceiveBuffer = nv_osfreerxbuf;
430         osapi->pfnPacketWasSent = nv_ospackettx;
431         osapi->pfnPacketWasReceived = nv_ospacketrx;
432         osapi->pfnLinkStateHasChanged = nv_oslinkchg;
433         osapi->pfnAllocTimer = nv_osalloctimer;
434         osapi->pfnFreeTimer = nv_osfreetimer;
435         osapi->pfnInitializeTimer = nv_osinittimer;
436         osapi->pfnSetTimer = nv_ossettimer;
437         osapi->pfnCancelTimer = nv_oscanceltimer;
438         osapi->pfnPreprocessPacket = nv_ospreprocpkt;
439         osapi->pfnPreprocessPacketNopq = nv_ospreprocpktnopq;
440         osapi->pfnIndicatePackets = nv_osindicatepkt;
441         osapi->pfnLockAlloc = nv_oslockalloc;
442         osapi->pfnLockAcquire = nv_oslockacquire;
443         osapi->pfnLockRelease = nv_oslockrelease;
444         osapi->pfnReturnBufferVirtual = nv_osreturnbufvirt;
445
446         sc->linkup = FALSE;
447         sc->max_frame_size = ETHERMTU + ETHER_HDR_LEN + FCS_LEN;
448
449         /* TODO - We don't support hardware offload yet */
450         sc->hwmode = 1;
451         sc->media = 0;
452
453         /* Set NVIDIA API startup parameters */
454         OpenParams.MaxDpcLoop = 2;
455         OpenParams.MaxRxPkt = RX_RING_SIZE;
456         OpenParams.MaxTxPkt = TX_RING_SIZE;
457         OpenParams.SentPacketStatusSuccess = 1;
458         OpenParams.SentPacketStatusFailure = 0;
459         OpenParams.MaxRxPktToAccumulate = 6;
460         OpenParams.ulPollInterval = nv_pollinterval;
461         OpenParams.SetForcedModeEveryNthRxPacket = 0;
462         OpenParams.SetForcedModeEveryNthTxPacket = 0;
463         OpenParams.RxForcedInterrupt = 0;
464         OpenParams.TxForcedInterrupt = 0;
465         OpenParams.pOSApi = osapi;
466         OpenParams.pvHardwareBaseAddress = rman_get_virtual(sc->res);
467         OpenParams.bASFEnabled = 0;
468         OpenParams.ulDescriptorVersion = sc->hwmode;
469         OpenParams.ulMaxPacketSize = sc->max_frame_size;
470         OpenParams.DeviceId = pci_get_device(dev);
471
472         /* Open NVIDIA Hardware API */
473         error = ADAPTER_Open(&OpenParams, (void **)&(sc->hwapi), &sc->phyaddr);
474         if (error) {
475                 device_printf(dev, "failed to open NVIDIA Hardware API: 0x%x\n", error);
476                 goto fail;
477         }
478         
479         /* TODO - Add support for MODE2 hardware offload */ 
480
481         bzero(&sc->adapterdata, sizeof(sc->adapterdata));
482
483         sc->adapterdata.ulMediaIF = sc->media;
484         sc->adapterdata.ulModeRegTxReadCompleteEnable = 1;
485         sc->hwapi->pfnSetCommonData(sc->hwapi->pADCX, &sc->adapterdata);
486
487         sc->hwapi->pfnInit(sc->hwapi->pADCX, 
488                                    0, /* force speed */ 
489                                    0, /* force full duplex */
490                                    0, /* force mode */
491                                    0, /* force async mode */
492                                    &sc->linkup);
493
494         /* MAC is loaded backwards into h/w reg */
495         sc->hwapi->pfnGetNodeAddress(sc->hwapi->pADCX, sc->original_mac_addr);
496         for (i = 0; i < 6; i++) {
497                 eaddr[i] = sc->original_mac_addr[5 - i];
498         }
499         sc->hwapi->pfnSetNodeAddress(sc->hwapi->pADCX, eaddr);
500         bcopy(eaddr, (char *)&sc->sc_macaddr, ETHER_ADDR_LEN);
501
502         DEBUGOUT(NV_DEBUG_INIT, "nv: do mii_phy_probe\n");
503
504         /* Probe device for MII interface to PHY */
505         if (mii_phy_probe(dev, &sc->miibus, nv_ifmedia_upd, nv_ifmedia_sts)) {
506                 device_printf(dev, "MII without any phy!\n");
507                 error = ENXIO;
508                 goto fail;
509         }
510         /* Setup interface parameters */
511         ifp = &sc->sc_if;
512         ifp->if_softc = sc;
513         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
514         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
515         ifp->if_ioctl = nv_ioctl;
516         ifp->if_start = nv_ifstart;
517 #ifdef DEVICE_POLLING
518         ifp->if_poll = nv_poll;
519 #endif
520         ifp->if_watchdog = nv_watchdog;
521         ifp->if_timer = 0;
522         ifp->if_init = nv_init;
523         ifp->if_mtu = ETHERMTU;
524         ifp->if_baudrate = IF_Mbps(100);
525         ifp->if_capabilities |= IFCAP_VLAN_MTU;
526         ifq_set_maxlen(&ifp->if_snd, TX_RING_SIZE - 1);
527         ifq_set_ready(&ifp->if_snd);
528
529         /* Attach to OS's managers. */
530         ether_ifattach(ifp, sc->sc_macaddr);
531
532         /* Activate our interrupt handler. - attach last to avoid lock */
533         error = bus_setup_intr(sc->dev, sc->irq, 0,
534                                nv_intr, sc, &sc->sc_ih, &sc->serializer);
535         if (error) {
536                 ether_ifdetach(ifp);
537                 device_printf(sc->dev, "couldn't set up interrupt handler\n");
538                 goto fail;
539         }
540         DEBUGOUT(NV_DEBUG_INIT, "nv: nv_attach - exit\n");
541
542 fail:
543         if (error)
544                 nv_detach(dev);
545
546         return (error);
547 }
548
549 /* Detach interface for module unload */
550 static int
551 nv_detach(device_t dev)
552 {
553         struct nv_softc *sc = device_get_softc(dev);
554         struct ifnet   *ifp;
555
556         lwkt_serialize_enter(&sc->serializer);
557
558         DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_detach - entry\n");
559
560         ifp = &sc->arpcom.ac_if;
561
562         if (device_is_attached(dev)) {
563                 nv_stop_serialized(sc);
564                 lwkt_serialize_exit(&sc->serializer);
565                 ether_ifdetach(ifp);
566                 lwkt_serialize_enter(&sc->serializer);
567         }
568
569         if (sc->miibus)
570                 device_delete_child(dev, sc->miibus);
571         bus_generic_detach(dev);
572
573         /* Reload unreversed address back into MAC in original state */
574         if (sc->original_mac_addr)
575                 sc->hwapi->pfnSetNodeAddress(sc->hwapi->pADCX, sc->original_mac_addr);
576
577         DEBUGOUT(NV_DEBUG_DEINIT, "nv: do pfnClose\n");
578         /* Detach from NVIDIA hardware API */
579         if (sc->hwapi->pfnClose)
580                 sc->hwapi->pfnClose(sc->hwapi->pADCX, FALSE);
581         /* Release resources */
582         if (sc->sc_ih)
583                 bus_teardown_intr(sc->dev, sc->irq, sc->sc_ih);
584         if (sc->irq)
585                 bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->irq);
586         if (sc->res)
587                 bus_release_resource(sc->dev, SYS_RES_MEMORY, NV_RID, sc->res);
588
589         nv_free_rings(sc);
590
591         if (sc->tx_desc) {
592                 bus_dmamap_unload(sc->rtag, sc->rmap);
593                 bus_dmamem_free(sc->rtag, sc->rx_desc, sc->rmap);
594                 bus_dmamap_destroy(sc->rtag, sc->rmap);
595         }
596         if (sc->mtag)
597                 bus_dma_tag_destroy(sc->mtag);
598         if (sc->ttag)
599                 bus_dma_tag_destroy(sc->ttag);
600         if (sc->rtag)
601                 bus_dma_tag_destroy(sc->rtag);
602
603         lwkt_serialize_exit(&sc->serializer);
604
605         DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_detach - exit\n");
606
607         return (0);
608 }
609
610 static void
611 nv_init(void *xsc)
612 {
613         struct nv_softc *sc = xsc;
614
615         lwkt_serialize_enter(&sc->serializer);
616         nv_init_serialized(sc);
617         lwkt_serialize_exit(&sc->serializer);
618 }
619
620 /* Initialise interface and start it "RUNNING" */
621 static void
622 nv_init_serialized(struct nv_softc *sc)
623 {
624         struct ifnet   *ifp;
625         int             error;
626
627         DEBUGOUT(NV_DEBUG_INIT, "nv: nv_init - entry (%d)\n", sc->linkup);
628
629         ifp = &sc->sc_if;
630
631         /* Do nothing if already running */
632         if (ifp->if_flags & IFF_RUNNING)
633                 return;
634
635         nv_stop_serialized(sc);
636
637         DEBUGOUT(NV_DEBUG_INIT, "nv: do pfnInit\n");
638         /* Setup Hardware interface and allocate memory structures */
639         error = sc->hwapi->pfnInit(sc->hwapi->pADCX, 
640                                    0, /* force speed */ 
641                                    0, /* force full duplex */
642                                    0, /* force mode */
643                                    0, /* force async mode */
644                                    &sc->linkup);
645
646         if (error) {
647                 device_printf(sc->dev, "failed to start NVIDIA Hardware interface\n");
648                 return;
649         }
650         /* Set the MAC address */
651         sc->hwapi->pfnSetNodeAddress(sc->hwapi->pADCX, sc->sc_macaddr);
652
653         sc->hwapi->pfnStart(sc->hwapi->pADCX);
654
655         /* Setup multicast filter */
656         nv_setmulti(sc);
657         nv_ifmedia_upd(ifp);
658
659         /* Update interface parameters */
660         ifp->if_flags |= IFF_RUNNING;
661         ifp->if_flags &= ~IFF_OACTIVE;
662
663         /*
664          * Enable the interrupt.  Currently the nvidia API does not support
665          * polling, if we do not call pfnEnableInterrupts() we cannot
666          * issue the nvidia callback to process interrupts.  Call the
667          * interrupt service routine in case the interrupt got stuck during
668          * a reset, renegotiation, or timeout.
669          */
670 #if 1
671         lwkt_serialize_handler_enable(&sc->serializer);
672         sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX);
673 #else
674         if ((ifp->if_flags & IFF_POLLING) == 0) {
675                 lwkt_serialize_handler_enable(&sc->serializer);
676                 sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX);
677         }
678 #endif
679         nv_intr(sc);
680
681         /* 
682          * Reset watchdog and ring queue indexes.  XXX if the interface
683          * is reset with pending tx packets queued to the actual device,
684          * the mbufs are currently lost.
685          */
686         ifp->if_timer = 0;
687         sc->pending_txs = 0;
688
689         callout_reset(&sc->nv_stat_timer, hz, nv_tick, sc);
690
691         DEBUGOUT(NV_DEBUG_INIT, "nv: nv_init - exit\n");
692 }
693
694 #ifdef DEVICE_POLLING
695
696 static void
697 nv_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
698 {
699         struct nv_softc *sc = ifp->if_softc;
700
701         lwkt_serialize_enter(&sc->serializer);
702
703         switch(cmd) {
704         case POLL_REGISTER:
705                 /*
706                  * We must disable the hardware interrupt on the device
707                  * as well as ensure that any interrupt queued prior to
708                  * this point does not execute the handler function.
709                  *
710                  * NOTE!  The nvidia API does not support polling with
711                  * interrupts disabled, so we have to leave them turned on
712                  * unfortunately.
713                  */
714 #if 0
715                 sc->hwapi->pfnDisableInterrupts(sc->hwapi->pADCX);
716                 lwkt_serialize_handler_disable(&sc->serializer);
717 #endif
718                 break;
719         case POLL_DEREGISTER:
720 #if 0
721                 lwkt_serialize_handler_enable(&sc->serializer);
722                 sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX);
723 #endif
724                 break;
725         case POLL_AND_CHECK_STATUS:
726                 /* fall through */
727         case POLL_ONLY:
728                 if (ifp->if_flags & IFF_RUNNING) {
729                         nv_intr(sc);
730                 }
731                 if (ifp->if_flags & IFF_RUNNING) {
732                         if (!ifq_is_empty(&ifp->if_snd))
733                                 nv_ifstart_serialized(ifp);
734                 }
735                 break;
736         }
737         lwkt_serialize_exit(&sc->serializer);
738 }
739
740 #endif
741
742 static void
743 nv_stop(struct nv_softc *sc)
744 {
745         lwkt_serialize_enter(&sc->serializer);
746         nv_stop_serialized(sc);
747         lwkt_serialize_exit(&sc->serializer);
748 }
749
750 /* Stop interface activity ie. not "RUNNING" */
751 static void
752 nv_stop_serialized(struct nv_softc *sc)
753 {
754         struct ifnet   *ifp;
755
756         DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_stop - entry\n");
757
758         ifp = &sc->sc_if;
759         ifp->if_timer = 0;
760
761         /* Cancel tick timer */
762         callout_stop(&sc->nv_stat_timer);
763
764         /*
765          * Stop hardware activity.  The serializer handler disablement call
766          * prevents any interrupt scheduled prior to this call from calling
767          * the handler.
768          */
769         sc->hwapi->pfnDisableInterrupts(sc->hwapi->pADCX);
770         lwkt_serialize_handler_disable(&sc->serializer);
771
772         sc->hwapi->pfnStop(sc->hwapi->pADCX, 0);
773         sc->hwapi->pfnClearTxDesc(sc->hwapi->pADCX);
774
775         DEBUGOUT(NV_DEBUG_DEINIT, "nv: do pfnDeinit\n");
776         /* Shutdown interface and deallocate memory buffers */
777         if (sc->hwapi->pfnDeinit)
778                 sc->hwapi->pfnDeinit(sc->hwapi->pADCX, 0);
779
780         sc->linkup = 0;
781         sc->cur_rx = 0;
782         sc->pending_rxs = 0;
783
784         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
785
786         DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_stop - exit\n");
787 }
788
789 /* Shutdown interface for unload/reboot */
790 static void
791 nv_shutdown(device_t dev)
792 {
793         struct nv_softc *sc;
794
795         DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_shutdown\n");
796
797         sc = device_get_softc(dev);
798
799         /* Stop hardware activity */
800         nv_stop(sc);
801 }
802
803 /* Allocate TX ring buffers */
804 static int
805 nv_init_rings(struct nv_softc *sc)
806 {
807         int             error, i;
808
809         DEBUGOUT(NV_DEBUG_INIT, "nv: nv_init_rings - entry\n");
810
811         sc->cur_rx = sc->cur_tx = sc->pending_rxs = sc->pending_txs = 0;
812         /* Initialise RX ring */
813         for (i = 0; i < RX_RING_SIZE; i++) {
814                 struct nv_rx_desc *desc = sc->rx_desc + i;
815                 struct nv_map_buffer *buf = &desc->buf;
816
817                 buf->mbuf = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
818                 if (buf->mbuf == NULL) {
819                         device_printf(sc->dev, "couldn't allocate mbuf\n");
820                         nv_free_rings(sc);
821                         error = ENOBUFS;
822                         goto fail;
823                 }
824                 buf->mbuf->m_len = buf->mbuf->m_pkthdr.len = MCLBYTES;
825                 m_adj(buf->mbuf, ETHER_ALIGN);
826
827                 error = bus_dmamap_create(sc->mtag, 0, &buf->map);
828                 if (error) {
829                         device_printf(sc->dev, "couldn't create dma map\n");
830                         nv_free_rings(sc);
831                         goto fail;
832                 }
833                 error = bus_dmamap_load_mbuf(sc->mtag, buf->map, buf->mbuf,
834                                           nv_dmamap_rx_cb, &desc->paddr, 0);
835                 if (error) {
836                         device_printf(sc->dev, "couldn't dma map mbuf\n");
837                         nv_free_rings(sc);
838                         goto fail;
839                 }
840                 bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_PREREAD);
841
842                 desc->buflength = buf->mbuf->m_len;
843                 desc->vaddr = mtod(buf->mbuf, caddr_t);
844         }
845         bus_dmamap_sync(sc->rtag, sc->rmap,
846                         BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
847
848         /* Initialize TX ring */
849         for (i = 0; i < TX_RING_SIZE; i++) {
850                 struct nv_tx_desc *desc = sc->tx_desc + i;
851                 struct nv_map_buffer *buf = &desc->buf;
852
853                 buf->mbuf = NULL;
854
855                 error = bus_dmamap_create(sc->mtag, 0, &buf->map);
856                 if (error) {
857                         device_printf(sc->dev, "couldn't create dma map\n");
858                         nv_free_rings(sc);
859                         goto fail;
860                 }
861         }
862         bus_dmamap_sync(sc->ttag, sc->tmap,
863                         BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
864
865         DEBUGOUT(NV_DEBUG_INIT, "nv: nv_init_rings - exit\n");
866
867 fail:
868         return (error);
869 }
870
871 /* Free the TX ring buffers */
872 static void
873 nv_free_rings(struct nv_softc *sc)
874 {
875         int             i;
876
877         DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_free_rings - entry\n");
878
879         for (i = 0; i < RX_RING_SIZE; i++) {
880                 struct nv_rx_desc *desc = sc->rx_desc + i;
881                 struct nv_map_buffer *buf = &desc->buf;
882
883                 if (buf->mbuf) {
884                         bus_dmamap_unload(sc->mtag, buf->map);
885                         bus_dmamap_destroy(sc->mtag, buf->map);
886                         m_freem(buf->mbuf);
887                 }
888                 buf->mbuf = NULL;
889         }
890
891         for (i = 0; i < TX_RING_SIZE; i++) {
892                 struct nv_tx_desc *desc = sc->tx_desc + i;
893                 struct nv_map_buffer *buf = &desc->buf;
894
895                 if (buf->mbuf) {
896                         bus_dmamap_unload(sc->mtag, buf->map);
897                         bus_dmamap_destroy(sc->mtag, buf->map);
898                         m_freem(buf->mbuf);
899                 }
900                 buf->mbuf = NULL;
901         }
902
903         DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_free_rings - exit\n");
904 }
905
906 /* Main loop for sending packets from OS to interface */
907
908 static void
909 nv_ifstart(struct ifnet *ifp)
910 {
911         struct nv_softc *sc = ifp->if_softc;
912
913         lwkt_serialize_enter(&sc->serializer);
914         nv_ifstart_serialized(ifp);
915         lwkt_serialize_exit(&sc->serializer);
916 }
917
918 static void
919 nv_ifstart_serialized(struct ifnet *ifp)
920 {
921         struct nv_softc *sc = ifp->if_softc;
922         struct nv_map_buffer *buf;
923         struct mbuf    *m0, *m;
924         struct nv_tx_desc *desc;
925         ADAPTER_WRITE_DATA txdata;
926         int             error, i;
927
928         DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_ifstart - entry\n");
929
930         /* If link is down/busy or queue is empty do nothing */
931         if ((ifp->if_flags & IFF_OACTIVE) || ifq_is_empty(&ifp->if_snd))
932                 return;
933
934         /* Transmit queued packets until sent or TX ring is full */
935         while (sc->pending_txs < TX_RING_SIZE) {
936                 desc = sc->tx_desc + sc->cur_tx;
937                 buf = &desc->buf;
938
939                 /* Get next packet to send. */
940                 m0 = ifq_dequeue(&ifp->if_snd);
941
942                 /* If nothing to send, return. */
943                 if (m0 == NULL)
944                         return;
945
946                 /* Map MBUF for DMA access */
947                 error = bus_dmamap_load_mbuf(sc->mtag, buf->map, m0,
948                                      nv_dmamap_tx_cb, desc, BUS_DMA_NOWAIT);
949
950                 if (error && error != EFBIG) {
951                         m_freem(m0);
952                         sc->tx_errors++;
953                         continue;
954                 }
955                 /*
956                  * Packet has too many fragments - defrag into new mbuf
957                  * cluster
958                  */
959                 if (error) {
960                         m = m_defrag(m0, MB_DONTWAIT);
961                         if (m == NULL) {
962                                 m_freem(m0);
963                                 sc->tx_errors++;
964                                 continue;
965                         }
966                         m0 = m;
967
968                         error = bus_dmamap_load_mbuf(sc->mtag, buf->map, m,
969                                      nv_dmamap_tx_cb, desc, BUS_DMA_NOWAIT);
970                         if (error) {
971                                 m_freem(m);
972                                 sc->tx_errors++;
973                                 continue;
974                         }
975                 }
976                 /* Do sync on DMA bounce buffer */
977                 bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_PREWRITE);
978
979                 buf->mbuf = m0;
980                 txdata.ulNumberOfElements = desc->numfrags;
981                 txdata.pvID = (PVOID)desc;
982
983                 /* Put fragments into API element list */
984                 txdata.ulTotalLength = buf->mbuf->m_len;
985                 for (i = 0; i < desc->numfrags; i++) {
986                         txdata.sElement[i].ulLength = (ulong)desc->frags[i].ds_len;
987                         txdata.sElement[i].pPhysical = (PVOID)desc->frags[i].ds_addr;
988                 }
989
990                 /* Send packet to Nvidia API for transmission */
991                 error = sc->hwapi->pfnWrite(sc->hwapi->pADCX, &txdata);
992
993                 switch (error) {
994                 case ADAPTERERR_NONE:
995                         /* Packet was queued in API TX queue successfully */
996                         sc->pending_txs++;
997                         sc->cur_tx = (sc->cur_tx + 1) % TX_RING_SIZE;
998                         break;
999
1000                 case ADAPTERERR_TRANSMIT_QUEUE_FULL:
1001                         /* The API TX queue is full - requeue the packet */
1002                         device_printf(sc->dev, "nv_ifstart: transmit queue is full\n");
1003                         ifp->if_flags |= IFF_OACTIVE;
1004                         bus_dmamap_unload(sc->mtag, buf->map);
1005                         buf->mbuf = NULL;
1006                         m_freem(m0);    /* XXX requeue */
1007                         return;
1008
1009                 default:
1010                         /* The API failed to queue/send the packet so dump it */
1011                         device_printf(sc->dev, "nv_ifstart: transmit error\n");
1012                         bus_dmamap_unload(sc->mtag, buf->map);
1013                         m_freem(buf->mbuf);
1014                         buf->mbuf = NULL;
1015                         sc->tx_errors++;
1016                         return;
1017                 }
1018                 /* Set watchdog timer. */
1019                 ifp->if_timer = 8;
1020
1021                 /* Copy packet to BPF tap */
1022                 BPF_MTAP(ifp, m0);
1023         }
1024         ifp->if_flags |= IFF_OACTIVE;
1025
1026         DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_ifstart - exit\n");
1027 }
1028
1029 /* Handle IOCTL events */
1030 static int
1031 nv_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
1032 {
1033         struct nv_softc *sc = ifp->if_softc;
1034         struct ifreq   *ifr = (struct ifreq *) data;
1035         struct mii_data *mii;
1036         int             error = 0;
1037
1038         lwkt_serialize_enter(&sc->serializer);
1039
1040         DEBUGOUT(NV_DEBUG_IOCTL, "nv: nv_ioctl - entry\n");
1041
1042         switch (command) {
1043         case SIOCSIFMTU:
1044                 /* Set MTU size */
1045                 if (ifp->if_mtu == ifr->ifr_mtu)
1046                         break;
1047                 if (ifr->ifr_mtu + ifp->if_hdrlen <= MAX_PACKET_SIZE_1518) {
1048                         ifp->if_mtu = ifr->ifr_mtu;
1049                         nv_stop_serialized(sc);
1050                         nv_init_serialized(sc);
1051                 } else
1052                         error = EINVAL;
1053                 break;
1054
1055         case SIOCSIFFLAGS:
1056                 /* Setup interface flags */
1057                 if (ifp->if_flags & IFF_UP) {
1058                         if ((ifp->if_flags & IFF_RUNNING) == 0) {
1059                                 nv_init_serialized(sc);
1060                                 break;
1061                         }
1062                 } else {
1063                         if (ifp->if_flags & IFF_RUNNING) {
1064                                 nv_stop_serialized(sc);
1065                                 break;
1066                         }
1067                 }
1068
1069                 /* Handle IFF_PROMISC and IFF_ALLMULTI flags. */
1070                 nv_setmulti(sc);
1071                 break;
1072
1073         case SIOCADDMULTI:
1074         case SIOCDELMULTI:
1075                 /* Setup multicast filter */
1076                 if (ifp->if_flags & IFF_RUNNING) {
1077                         nv_setmulti(sc);
1078                 }
1079                 break;
1080         case SIOCGIFMEDIA:
1081         case SIOCSIFMEDIA:
1082                 /* Get/Set interface media parameters */
1083                 mii = device_get_softc(sc->miibus);
1084                 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
1085                 break;
1086
1087         default:
1088                 /* Everything else we forward to generic ether ioctl */
1089                 lwkt_serialize_exit(&sc->serializer);
1090                 error = ether_ioctl(ifp, command, data);
1091                 lwkt_serialize_enter(&sc->serializer);
1092                 break;
1093         }
1094
1095         DEBUGOUT(NV_DEBUG_IOCTL, "nv: nv_ioctl - exit\n");
1096
1097         lwkt_serialize_exit(&sc->serializer);
1098
1099         return (error);
1100 }
1101
1102 /*
1103  * Interrupt service routine.  The serializer has already been entered
1104  * since we installed it in our bus_setup_intr() call.
1105  */
1106 static void
1107 nv_intr(void *arg)
1108 {
1109         struct nv_softc *sc = arg;
1110         struct ifnet   *ifp = &sc->sc_if;
1111
1112         DEBUGOUT(NV_DEBUG_INTERRUPT, "nv: nv_intr - entry\n");
1113
1114         /*
1115          * Handle an interrupt event.  Unfortunately the nvidia API
1116          * does not support interrupt disablement when polling, so we
1117          * have to re-enable after the query masks them off.
1118          */
1119         if (sc->hwapi->pfnQueryInterrupt(sc->hwapi->pADCX)) {
1120                 sc->hwapi->pfnHandleInterrupt(sc->hwapi->pADCX);
1121 #if 1
1122                 lwkt_serialize_handler_enable(&sc->serializer);
1123                 sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX);
1124 #else
1125                 if ((ifp->if_flags & IFF_POLLING) == 0) {
1126                         lwkt_serialize_handler_enable(&sc->serializer);
1127                         sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX);
1128                 }
1129 #endif
1130         }
1131         if (!ifq_is_empty(&ifp->if_snd))
1132                 nv_ifstart_serialized(ifp);
1133
1134         /* If no pending packets we don't need a timeout */
1135         if (sc->pending_txs == 0)
1136                 sc->sc_if.if_timer = 0;
1137
1138         DEBUGOUT(NV_DEBUG_INTERRUPT, "nv: nv_intr - exit\n");
1139 }
1140
1141 /*
1142  * Setup multicast filters 
1143  *
1144  * Serialized on call
1145  */
1146 static void
1147 nv_setmulti(struct nv_softc *sc)
1148 {
1149         struct ifnet   *ifp;
1150         struct ifmultiaddr *ifma;
1151         PACKET_FILTER   hwfilter;
1152         int             i;
1153         u_int8_t        oraddr[6];
1154         u_int8_t        andaddr[6];
1155
1156         DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_setmulti - entry\n");
1157
1158         ifp = &sc->sc_if;
1159
1160         /* Initialize filter */
1161         hwfilter.ulFilterFlags = 0;
1162         for (i = 0; i < 6; i++) {
1163                 hwfilter.acMulticastAddress[i] = 0;
1164                 hwfilter.acMulticastMask[i] = 0;
1165         }
1166
1167         if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) {
1168                 /* Accept all packets */
1169                 hwfilter.ulFilterFlags |= ACCEPT_ALL_PACKETS;
1170                 sc->hwapi->pfnSetPacketFilter(sc->hwapi->pADCX, &hwfilter);
1171                 return;
1172         }
1173         /* Setup multicast filter */
1174         LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1175                 u_char         *addrp;
1176
1177                 if (ifma->ifma_addr->sa_family != AF_LINK)
1178                         continue;
1179
1180                 addrp = LLADDR((struct sockaddr_dl *) ifma->ifma_addr);
1181                 for (i = 0; i < 6; i++) {
1182                         u_int8_t        mcaddr = addrp[i];
1183                         andaddr[i] &= mcaddr;
1184                         oraddr[i] |= mcaddr;
1185                 }
1186         }
1187         for (i = 0; i < 6; i++) {
1188                 hwfilter.acMulticastAddress[i] = andaddr[i] & oraddr[i];
1189                 hwfilter.acMulticastMask[i] = andaddr[i] | (~oraddr[i]);
1190         }
1191
1192         /* Send filter to NVIDIA API */
1193         sc->hwapi->pfnSetPacketFilter(sc->hwapi->pADCX, &hwfilter);
1194
1195         DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_setmulti - exit\n");
1196 }
1197
1198 /*
1199  * Change the current media/mediaopts
1200  *
1201  * Serialized on call
1202  */
1203 static int
1204 nv_ifmedia_upd(struct ifnet *ifp)
1205 {
1206         struct nv_softc *sc = ifp->if_softc;
1207         struct mii_data *mii;
1208
1209         DEBUGOUT(NV_DEBUG_MII, "nv: nv_ifmedia_upd\n");
1210
1211         mii = device_get_softc(sc->miibus);
1212
1213         if (mii->mii_instance) {
1214                 struct mii_softc *miisc;
1215                 for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
1216                      miisc = LIST_NEXT(miisc, mii_list)) {
1217                         mii_phy_reset(miisc);
1218                 }
1219         }
1220         mii_mediachg(mii);
1221
1222         return (0);
1223 }
1224
1225 /*
1226  * Update current miibus PHY status of media 
1227  *
1228  * Serialized on call
1229  */
1230 static void
1231 nv_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
1232 {
1233         struct nv_softc *sc;
1234         struct mii_data *mii;
1235
1236         DEBUGOUT(NV_DEBUG_MII, "nv: nv_ifmedia_sts\n");
1237
1238         sc = ifp->if_softc;
1239         mii = device_get_softc(sc->miibus);
1240         mii_pollstat(mii);
1241
1242         ifmr->ifm_active = mii->mii_media_active;
1243         ifmr->ifm_status = mii->mii_media_status;
1244 }
1245
1246 /* miibus tick timer - maintain link status */
1247 static void
1248 nv_tick(void *xsc)
1249 {
1250         struct nv_softc *sc = xsc;
1251         struct mii_data *mii;
1252         struct ifnet   *ifp;
1253
1254         lwkt_serialize_enter(&sc->serializer);
1255
1256         ifp = &sc->sc_if;
1257         nv_update_stats(sc);
1258
1259         mii = device_get_softc(sc->miibus);
1260         mii_tick(mii);
1261
1262         if ((mii->mii_media_status & IFM_ACTIVE) &&
1263             IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
1264                 if (!ifq_is_empty(&ifp->if_snd))
1265                         nv_ifstart_serialized(ifp);
1266         }
1267         callout_reset(&sc->nv_stat_timer, hz, nv_tick, sc);
1268         lwkt_serialize_exit(&sc->serializer);
1269 }
1270
1271 /* Update ifnet data structure with collected interface stats from API */
1272 static void
1273 nv_update_stats(struct nv_softc *sc)
1274 {
1275         struct ifnet   *ifp = &sc->sc_if;
1276         ADAPTER_STATS   stats;
1277
1278         if (sc->hwapi) {
1279                 sc->hwapi->pfnGetStatistics(sc->hwapi->pADCX, &stats);
1280
1281                 ifp->if_ipackets = stats.ulSuccessfulReceptions;
1282                 ifp->if_ierrors = stats.ulMissedFrames +
1283                         stats.ulFailedReceptions +
1284                         stats.ulCRCErrors +
1285                         stats.ulFramingErrors +
1286                         stats.ulOverFlowErrors;
1287
1288                 ifp->if_opackets = stats.ulSuccessfulTransmissions;
1289                 ifp->if_oerrors = sc->tx_errors +
1290                         stats.ulFailedTransmissions +
1291                         stats.ulRetryErrors +
1292                         stats.ulUnderflowErrors +
1293                         stats.ulLossOfCarrierErrors +
1294                         stats.ulLateCollisionErrors;
1295
1296                 ifp->if_collisions = stats.ulLateCollisionErrors;
1297         }
1298 }
1299
1300 /* miibus Read PHY register wrapper - calls Nvidia API entry point */
1301 static int
1302 nv_miibus_readreg(device_t dev, int phy, int reg)
1303 {
1304         struct nv_softc *sc = device_get_softc(dev);
1305         ULONG           data;
1306
1307         DEBUGOUT(NV_DEBUG_MII, "nv: nv_miibus_readreg - entry\n");
1308
1309         ADAPTER_ReadPhy(sc->hwapi->pADCX, phy, reg, &data);
1310
1311         DEBUGOUT(NV_DEBUG_MII, "nv: nv_miibus_readreg - exit\n");
1312
1313         return (data);
1314 }
1315
1316 /* miibus Write PHY register wrapper - calls Nvidia API entry point */
1317 static void
1318 nv_miibus_writereg(device_t dev, int phy, int reg, int data)
1319 {
1320         struct nv_softc *sc = device_get_softc(dev);
1321
1322         DEBUGOUT(NV_DEBUG_MII, "nv: nv_miibus_writereg - entry\n");
1323
1324         ADAPTER_WritePhy(sc->hwapi->pADCX, phy, reg, (ulong)data);
1325
1326         DEBUGOUT(NV_DEBUG_MII, "nv: nv_miibus_writereg - exit\n");
1327 }
1328
1329 /* Watchdog timer to prevent PHY lockups */
1330 static void
1331 nv_watchdog(struct ifnet *ifp)
1332 {
1333         struct nv_softc *sc = ifp->if_softc;
1334
1335         lwkt_serialize_enter(&sc->serializer);
1336
1337         device_printf(sc->dev, "device timeout (%d) flags %d\n",
1338                         sc->pending_txs, ifp->if_flags & IFF_OACTIVE);
1339
1340         sc->tx_errors++;
1341
1342         nv_stop_serialized(sc);
1343         ifp->if_flags &= ~IFF_RUNNING;
1344         nv_init_serialized(sc);
1345
1346         if (!ifq_is_empty(&ifp->if_snd))
1347                 nv_ifstart_serialized(ifp);
1348
1349         lwkt_serialize_exit(&sc->serializer);
1350 }
1351
1352 /* --- Start of NVOSAPI interface --- */
1353
1354 /* Allocate DMA enabled general use memory for API */
1355 static NV_SINT32
1356 nv_osalloc(PNV_VOID ctx, PMEMORY_BLOCK mem)
1357 {
1358         struct nv_softc *sc;
1359         bus_addr_t      mem_physical;
1360
1361         DEBUGOUT(NV_DEBUG_API, "nv: nv_osalloc - %d\n", mem->uiLength);
1362
1363         sc = (struct nv_softc *)ctx;
1364
1365         mem->pLogical = (PVOID)contigmalloc(mem->uiLength, M_DEVBUF,
1366                                     M_NOWAIT | M_ZERO, 0, ~0, PAGE_SIZE, 0);
1367
1368         if (!mem->pLogical) {
1369                 device_printf(sc->dev, "memory allocation failed\n");
1370                 return (0);
1371         }
1372         memset(mem->pLogical, 0, (ulong)mem->uiLength);
1373         mem_physical = vtophys(mem->pLogical);
1374         mem->pPhysical = (PVOID)mem_physical;
1375
1376         DEBUGOUT(NV_DEBUG_API, "nv: nv_osalloc %p/%p - %d\n",
1377                  mem->pLogical, mem->pPhysical, mem->uiLength);
1378
1379         return (1);
1380 }
1381
1382 /* Free allocated memory */
1383 static NV_SINT32
1384 nv_osfree(PNV_VOID ctx, PMEMORY_BLOCK mem)
1385 {
1386         DEBUGOUT(NV_DEBUG_API, "nv: nv_osfree - %p - %d\n",
1387                  mem->pLogical, mem->uiLength);
1388
1389         contigfree(mem->pLogical, PAGE_SIZE, M_DEVBUF);
1390         return (1);
1391 }
1392
1393 /* Copied directly from nvnet.c */
1394 static NV_SINT32
1395 nv_osallocex(PNV_VOID ctx, PMEMORY_BLOCKEX mem_block_ex)
1396 {
1397         MEMORY_BLOCK    mem_block;
1398
1399         DEBUGOUT(NV_DEBUG_API, "nv: nv_osallocex\n");
1400
1401         mem_block_ex->pLogical = NULL;
1402         mem_block_ex->uiLengthOrig = mem_block_ex->uiLength;
1403
1404         if ((mem_block_ex->AllocFlags & ALLOC_MEMORY_ALIGNED) &&
1405             (mem_block_ex->AlignmentSize > 1)) {
1406                 DEBUGOUT(NV_DEBUG_API, "     aligning on %d\n",
1407                          mem_block_ex->AlignmentSize);
1408                 mem_block_ex->uiLengthOrig += mem_block_ex->AlignmentSize;
1409         }
1410         mem_block.uiLength = mem_block_ex->uiLengthOrig;
1411
1412         if (nv_osalloc(ctx, &mem_block) == 0) {
1413                 return (0);
1414         }
1415         mem_block_ex->pLogicalOrig = mem_block.pLogical;
1416         mem_block_ex->pPhysicalOrigLow = (uintptr_t)mem_block.pPhysical;
1417         mem_block_ex->pPhysicalOrigHigh = 0;
1418
1419         mem_block_ex->pPhysical = mem_block.pPhysical;
1420         mem_block_ex->pLogical = mem_block.pLogical;
1421
1422         if (mem_block_ex->uiLength != mem_block_ex->uiLengthOrig) {
1423                 unsigned int    offset;
1424                 offset = mem_block_ex->pPhysicalOrigLow & (mem_block_ex->AlignmentSize - 1);
1425
1426                 if (offset) {
1427                         mem_block_ex->pPhysical = (PVOID)((uintptr_t)mem_block_ex->pPhysical +
1428                                       mem_block_ex->AlignmentSize - offset);
1429                         mem_block_ex->pLogical = (PVOID)((uintptr_t)mem_block_ex->pLogical +
1430                                       mem_block_ex->AlignmentSize - offset);
1431                 }               /* if (offset) */
1432         }                       /* if (mem_block_ex->uiLength !=
1433                                  * mem_block_ex->uiLengthOrig) */
1434         return (1);
1435 }
1436
1437 /* Copied directly from nvnet.c */
1438 static NV_SINT32
1439 nv_osfreeex(PNV_VOID ctx, PMEMORY_BLOCKEX mem_block_ex)
1440 {
1441         MEMORY_BLOCK    mem_block;
1442
1443         DEBUGOUT(NV_DEBUG_API, "nv: nv_osfreeex\n");
1444
1445         mem_block.pLogical = mem_block_ex->pLogicalOrig;
1446         mem_block.pPhysical = (PVOID)((uintptr_t)mem_block_ex->pPhysicalOrigLow);
1447         mem_block.uiLength = mem_block_ex->uiLengthOrig;
1448
1449         return (nv_osfree(ctx, &mem_block));
1450 }
1451
1452 /* Clear memory region */
1453 static NV_SINT32
1454 nv_osclear(PNV_VOID ctx, PNV_VOID mem, NV_SINT32 length)
1455 {
1456         DEBUGOUT(NV_DEBUG_API, "nv: nv_osclear\n");
1457         memset(mem, 0, length);
1458         return (1);
1459 }
1460
1461 /* Sleep for a tick */
1462 static NV_SINT32
1463 nv_osdelay(PNV_VOID ctx, NV_UINT32 usec)
1464 {
1465         if (usec >= 1000000 / hz) {
1466             tsleep(nv_osdelay, 0, "nvdelay", (usec * hz / 1000000) + 1);
1467         } else {
1468             DELAY(usec);
1469         }
1470         return (1);
1471 }
1472
1473 /* Allocate memory for rx buffer */
1474 static NV_SINT32
1475 nv_osallocrxbuf(PNV_VOID ctx, PMEMORY_BLOCK mem, PNV_VOID *id)
1476 {
1477         struct nv_softc *sc = ctx;
1478         struct nv_rx_desc *desc;
1479         struct nv_map_buffer *buf;
1480         int             error;
1481
1482         DEBUGOUT(NV_DEBUG_API, "nv: nv_osallocrxbuf\n");
1483
1484         if (sc->pending_rxs == RX_RING_SIZE) {
1485                 device_printf(sc->dev, "rx ring buffer is full\n");
1486                 goto fail;
1487         }
1488         desc = sc->rx_desc + sc->cur_rx;
1489         buf = &desc->buf;
1490
1491         if (buf->mbuf == NULL) {
1492                 buf->mbuf = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
1493                 if (buf->mbuf == NULL) {
1494                         device_printf(sc->dev, "failed to allocate memory\n");
1495                         goto fail;
1496                 }
1497                 buf->mbuf->m_len = buf->mbuf->m_pkthdr.len = MCLBYTES;
1498                 m_adj(buf->mbuf, ETHER_ALIGN);
1499
1500                 error = bus_dmamap_load_mbuf(sc->mtag, buf->map, buf->mbuf,
1501                                           nv_dmamap_rx_cb, &desc->paddr, 0);
1502                 if (error) {
1503                         device_printf(sc->dev, "failed to dmamap mbuf\n");
1504                         m_freem(buf->mbuf);
1505                         buf->mbuf = NULL;
1506                         goto fail;
1507                 }
1508                 bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_PREREAD);
1509                 desc->buflength = buf->mbuf->m_len;
1510                 desc->vaddr = mtod(buf->mbuf, PVOID);
1511         }
1512         sc->pending_rxs++;
1513         sc->cur_rx = (sc->cur_rx + 1) % RX_RING_SIZE;
1514
1515         mem->pLogical = (void *)desc->vaddr;
1516         mem->pPhysical = (void *)desc->paddr;
1517         mem->uiLength = desc->buflength;
1518         *id = (void *)desc;
1519
1520         return (1);
1521 fail:
1522         return (0);
1523 }
1524
1525
1526 /* Free the rx buffer */
1527 static NV_SINT32
1528 nv_osfreerxbuf(PNV_VOID ctx, PMEMORY_BLOCK mem, PNV_VOID id)
1529 {
1530         struct nv_softc *sc = ctx;
1531         struct nv_rx_desc *desc;
1532         struct nv_map_buffer *buf;
1533
1534         DEBUGOUT(NV_DEBUG_API, "nv: nv_osfreerxbuf\n");
1535
1536         desc = (struct nv_rx_desc *) id;
1537         buf = &desc->buf;
1538
1539         if (buf->mbuf) {
1540                 bus_dmamap_unload(sc->mtag, buf->map);
1541                 bus_dmamap_destroy(sc->mtag, buf->map);
1542                 m_freem(buf->mbuf);
1543         }
1544         sc->pending_rxs--;
1545         buf->mbuf = NULL;
1546
1547         return (1);
1548 }
1549
1550 /* This gets called by the Nvidia API after our TX packet has been sent */
1551 static NV_SINT32
1552 nv_ospackettx(PNV_VOID ctx, PNV_VOID id, NV_UINT32 success)
1553 {
1554         struct nv_softc *sc = ctx;
1555         struct nv_map_buffer *buf;
1556         struct nv_tx_desc *desc = (struct nv_tx_desc *) id;
1557         struct ifnet   *ifp;
1558
1559         DEBUGOUT(NV_DEBUG_API, "nv: nv_ospackettx\n");
1560
1561         ifp = &sc->sc_if;
1562         buf = &desc->buf;
1563         sc->pending_txs--;
1564
1565         /* Unload and free mbuf cluster */
1566         if (buf->mbuf == NULL)
1567                 goto fail;
1568
1569         bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTWRITE);
1570         bus_dmamap_unload(sc->mtag, buf->map);
1571         m_freem(buf->mbuf);
1572         buf->mbuf = NULL;
1573
1574         /*
1575          * Make sure we are clear to go if we previously stalled due
1576          * to a full ring.
1577          */
1578         if (sc->pending_txs < TX_RING_SIZE) {
1579                 ifp->if_flags &= ~IFF_OACTIVE;
1580                 if (!ifq_is_empty(&ifp->if_snd))
1581                         nv_ifstart(ifp);
1582         }
1583 fail:
1584         return (1);
1585 }
1586
1587 /* This gets called by the Nvidia API when a new packet has been received */
1588 /* XXX What is newbuf used for? XXX */
1589 static NV_SINT32
1590 nv_ospacketrx(PNV_VOID ctx, PNV_VOID data, NV_UINT32 success,
1591               NV_UINT8 *newbuf, NV_UINT8 priority)
1592 {
1593         struct nv_softc *sc = ctx;
1594         struct ifnet   *ifp;
1595         struct nv_rx_desc *desc;
1596         struct nv_map_buffer *buf;
1597         ADAPTER_READ_DATA *readdata;
1598
1599         DEBUGOUT(NV_DEBUG_API, "nv: nv_ospacketrx\n");
1600
1601         ifp = &sc->sc_if;
1602
1603         readdata = (ADAPTER_READ_DATA *) data;
1604         desc = readdata->pvID;
1605         buf = &desc->buf;
1606         bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTREAD);
1607
1608         if (success) {
1609                 /* Sync DMA bounce buffer. */
1610                 bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTREAD);
1611
1612                 /* First mbuf in packet holds the ethernet and packet headers */
1613                 buf->mbuf->m_pkthdr.rcvif = ifp;
1614                 buf->mbuf->m_pkthdr.len = buf->mbuf->m_len = readdata->ulTotalLength;
1615
1616                 bus_dmamap_unload(sc->mtag, buf->map);
1617
1618                 /* Give mbuf to OS. */
1619                 (*ifp->if_input) (ifp, buf->mbuf);
1620                 if (readdata->ulFilterMatch & ADREADFL_MULTICAST_MATCH)
1621                         ifp->if_imcasts++;
1622
1623                 /* Blat the mbuf pointer, kernel will free the mbuf cluster */
1624                 buf->mbuf = NULL;
1625         } else {
1626                 bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTREAD);
1627                 bus_dmamap_unload(sc->mtag, buf->map);
1628                 m_freem(buf->mbuf);
1629                 buf->mbuf = NULL;
1630         }
1631
1632         sc->cur_rx = desc - sc->rx_desc;
1633         sc->pending_rxs--;
1634
1635         return (1);
1636 }
1637
1638 /* This gets called by NVIDIA API when the PHY link state changes */
1639 static NV_SINT32
1640 nv_oslinkchg(PNV_VOID ctx, NV_SINT32 enabled)
1641 {
1642         struct nv_softc *sc = (struct nv_softc *)ctx;
1643         struct ifnet   *ifp;
1644
1645         DEBUGOUT(NV_DEBUG_API, "nv: nv_oslinkchg\n");
1646
1647         ifp = &sc->sc_if;
1648
1649         if (enabled)
1650                 ifp->if_flags |= IFF_UP;
1651         else
1652                 ifp->if_flags &= ~IFF_UP;
1653
1654
1655         return (1);
1656 }
1657
1658
1659 /* Setup a watchdog timer */
1660 static NV_SINT32
1661 nv_osalloctimer(PNV_VOID ctx, PNV_VOID *timer)
1662 {
1663         struct nv_softc *sc = (struct nv_softc *)ctx;
1664
1665         DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_osalloctimer\n");
1666
1667         callout_init(&sc->ostimer);
1668         *timer = &sc->ostimer;
1669
1670         return (1);
1671 }
1672
1673 /* Free the timer */
1674 static NV_SINT32
1675 nv_osfreetimer(PNV_VOID ctx, PNV_VOID timer)
1676 {
1677         DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_osfreetimer\n");
1678
1679         return (1);
1680 }
1681
1682 /* Setup timer parameters */
1683 static NV_SINT32
1684 nv_osinittimer(PNV_VOID ctx, PNV_VOID timer, PTIMER_FUNC func, PNV_VOID parameters)
1685 {
1686         struct nv_softc *sc = (struct nv_softc *)ctx;
1687
1688         DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_osinittimer\n");
1689
1690         sc->ostimer_func = func;
1691         sc->ostimer_params = parameters;
1692
1693         return (1);
1694 }
1695
1696 /* 
1697  * Set the timer to go off 
1698  *
1699  * XXX what the hell are the units for 'delay' ?  They sure aren't ticks!
1700  */
1701 static NV_SINT32
1702 nv_ossettimer(PNV_VOID ctx, PNV_VOID timer, NV_UINT32 delay)
1703 {
1704         struct nv_softc *sc = ctx;
1705
1706         DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_ossettimer\n");
1707         printf("nv_ossettimer %d\n", (int)delay);
1708
1709         callout_reset(&sc->ostimer, delay, sc->ostimer_func,
1710                       sc->ostimer_params);
1711
1712         return (1);
1713 }
1714
1715 /* Cancel the timer */
1716 static NV_SINT32
1717 nv_oscanceltimer(PNV_VOID ctx, PNV_VOID timer)
1718 {
1719         struct nv_softc *sc = ctx;
1720
1721         DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_oscanceltimer\n");
1722
1723         callout_stop(&sc->ostimer);
1724
1725         return (1);
1726 }
1727
1728 static NV_SINT32
1729 nv_ospreprocpkt(PNV_VOID ctx, PNV_VOID readdata, PNV_VOID *id, NV_UINT8 *newbuffer,
1730                 NV_UINT8 priority)
1731 {
1732         /* Not implemented */
1733         DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_ospreprocpkt\n");
1734
1735         return (1);
1736 }
1737
1738 static PNV_VOID
1739 nv_ospreprocpktnopq(PNV_VOID ctx, PNV_VOID readdata)
1740 {
1741         /* Not implemented */
1742         DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_ospreprocpkt\n");
1743
1744         return (NULL);
1745 }
1746
1747 static NV_SINT32
1748 nv_osindicatepkt(PNV_VOID ctx, PNV_VOID *id, NV_UINT32 pktno)
1749 {
1750         /* Not implemented */
1751         DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_osindicatepkt\n");
1752
1753         return (1);
1754 }
1755
1756 /* Allocate mutex context (already done in nv_attach) */
1757 static NV_SINT32
1758 nv_oslockalloc(PNV_VOID ctx, NV_SINT32 type, PNV_VOID *pLock)
1759 {
1760         struct nv_softc *sc = (struct nv_softc *)ctx;
1761
1762         DEBUGOUT(NV_DEBUG_LOCK, "nv: nv_oslockalloc\n");
1763
1764         *pLock = (void **)sc;
1765
1766         return (1);
1767 }
1768
1769 /* Obtain a spin lock */
1770 static NV_SINT32
1771 nv_oslockacquire(PNV_VOID ctx, NV_SINT32 type, PNV_VOID lock)
1772 {
1773         DEBUGOUT(NV_DEBUG_LOCK, "nv: nv_oslockacquire\n");
1774
1775         NV_OSLOCK((struct nv_softc *)lock);
1776
1777         return (1);
1778 }
1779
1780 /* Release lock */
1781 static NV_SINT32
1782 nv_oslockrelease(PNV_VOID ctx, NV_SINT32 type, PNV_VOID lock)
1783 {
1784         DEBUGOUT(NV_DEBUG_LOCK, "nv: nv_oslockrelease\n");
1785
1786         NV_OSUNLOCK((struct nv_softc *)lock);
1787
1788         return (1);
1789 }
1790
1791 /* I have no idea what this is for */
1792 static PNV_VOID
1793 nv_osreturnbufvirt(PNV_VOID ctx, PNV_VOID readdata)
1794 {
1795         /* Not implemented */
1796         DEBUGOUT(NV_DEBUG_LOCK, "nv: nv_osreturnbufvirt\n");
1797         panic("nv: nv_osreturnbufvirtual not implemented\n");
1798
1799         return (NULL);
1800 }
1801
1802
1803 /* --- End on NVOSAPI interface --- */