2 * Copyright (c) 2005 by David E. O'Brien <obrien@FreeBSD.org>.
3 * Copyright (c) 2003,2004 by Quinton Dolan <q@onthenet.com.au>.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $Id: if_nv.c,v 1.20 2005/03/12 01:11:00 q Exp $
28 * $FreeBSD: src/sys/dev/nve/if_nve.c,v 1.20 2005/12/12 06:23:43 bz Exp $
29 * $DragonFly: src/sys/dev/netif/nv/Attic/if_nv.c,v 1.27 2006/01/29 22:10:11 corecode Exp $
33 * NVIDIA nForce MCP Networking Adapter driver
35 * This is a port of the NVIDIA MCP Linux ethernet driver distributed by NVIDIA
36 * through their web site.
38 * All mainstream nForce and nForce2 motherboards are supported. This module
39 * is as stable, sometimes more stable, than the linux version. (Recent
40 * Linux stability issues seem to be related to some issues with newer
41 * distributions using GCC 3.x, however this don't appear to effect FreeBSD
44 * In accordance with the NVIDIA distribution license it is necessary to
45 * link this module against the nvlibnet.o binary object included in the
46 * Linux driver source distribution. The binary component is not modified in
47 * any way and is simply linked against a FreeBSD equivalent of the nvnet.c
48 * linux kernel module "wrapper".
50 * The Linux driver uses a common code API that is shared between Win32 and
51 * i386 Linux. This abstracts the low level driver functions and uses
52 * callbacks and hooks to access the underlying hardware device. By using
53 * this same API in a FreeBSD kernel module it is possible to support the
54 * hardware without breaching the Linux source distributions licensing
55 * requirements, or obtaining the hardware programming specifications.
57 * Although not conventional, it works, and given the relatively small
58 * amount of hardware centric code, it's hopefully no more buggy than its
61 * NVIDIA now support the nForce3 AMD64 platform, however I have been
62 * unable to access such a system to verify support. However, the code is
63 * reported to work with little modification when compiled with the AMD64
64 * version of the NVIDIA Linux library. All that should be necessary to make
65 * the driver work is to link it directly into the kernel, instead of as a
66 * module, and apply the docs/amd64.diff patch in this source distribution to
67 * the NVIDIA Linux driver source.
69 * This driver should work on all versions of FreeBSD since 4.9/5.1 as well
70 * as recent versions of DragonFly.
72 * Written by Quinton Dolan <q@onthenet.com.au>
73 * Portions based on existing FreeBSD network drivers.
74 * NVIDIA API usage derived from distributed NVIDIA NVNET driver source files.
76 * $Id: if_nv.c,v 1.9 2003/12/13 15:27:40 q Exp $
79 #include "opt_polling.h"
81 #include <sys/param.h>
82 #include <sys/systm.h>
83 #include <sys/sockio.h>
85 #include <sys/malloc.h>
86 #include <sys/kernel.h>
87 #include <sys/socket.h>
88 #include <sys/sysctl.h>
89 #include <sys/queue.h>
90 #include <sys/module.h>
91 #include <sys/thread2.h>
94 #include <net/ifq_var.h>
95 #include <net/if_arp.h>
96 #include <net/ethernet.h>
97 #include <net/if_dl.h>
98 #include <net/if_media.h>
102 #include <net/vlan/if_vlan_var.h>
104 #include <machine/bus_memio.h>
105 #include <machine/bus.h>
106 #include <machine/resource.h>
108 #include <vm/vm.h> /* for vtophys */
109 #include <vm/pmap.h> /* for vtophys */
110 #include <machine/clock.h> /* for DELAY */
112 #include <sys/rman.h>
113 #include <sys/serialize.h>
115 #include <bus/pci/pcireg.h>
116 #include <bus/pci/pcivar.h>
118 #include <dev/netif/mii_layer/mii.h>
119 #include <dev/netif/mii_layer/miivar.h>
121 MODULE_DEPEND(nv
, pci
, 1, 1, 1);
122 MODULE_DEPEND(nv
, miibus
, 1, 1, 1);
124 #include "if_nvreg.h"
125 #include "miibus_if.h"
127 static int nv_probe(device_t
);
128 static int nv_attach(device_t
);
129 static int nv_detach(device_t
);
130 static void nv_init(void *);
131 static void nv_stop(struct nv_softc
*);
132 static void nv_shutdown(device_t
);
133 static int nv_init_rings(struct nv_softc
*);
134 static void nv_free_rings(struct nv_softc
*);
136 static void nv_ifstart(struct ifnet
*);
137 static int nv_ioctl(struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
138 static void nv_intr(void *);
139 static void nv_tick(void *);
140 static void nv_setmulti(struct nv_softc
*);
141 static void nv_watchdog(struct ifnet
*);
142 static void nv_update_stats(struct nv_softc
*);
143 #ifdef DEVICE_POLLING
144 static void nv_poll(struct ifnet
*, enum poll_cmd
, int);
147 static int nv_ifmedia_upd(struct ifnet
*);
148 static void nv_ifmedia_sts(struct ifnet
*, struct ifmediareq
*);
149 static int nv_miibus_readreg(device_t
, int, int);
150 static void nv_miibus_writereg(device_t
, int, int, int);
152 static void nv_dmamap_cb(void *, bus_dma_segment_t
*, int, int);
153 static void nv_dmamap_tx_cb(void *, bus_dma_segment_t
*, int, bus_size_t
, int);
155 static NV_SINT32
nv_osalloc(PNV_VOID
, PMEMORY_BLOCK
);
156 static NV_SINT32
nv_osfree(PNV_VOID
, PMEMORY_BLOCK
);
157 static NV_SINT32
nv_osallocex(PNV_VOID
, PMEMORY_BLOCKEX
);
158 static NV_SINT32
nv_osfreeex(PNV_VOID
, PMEMORY_BLOCKEX
);
159 static NV_SINT32
nv_osclear(PNV_VOID
, PNV_VOID
, NV_SINT32
);
160 static NV_SINT32
nv_osdelay(PNV_VOID
, NV_UINT32
);
161 static NV_SINT32
nv_osallocrxbuf(PNV_VOID
, PMEMORY_BLOCK
, PNV_VOID
*);
162 static NV_SINT32
nv_osfreerxbuf(PNV_VOID
, PMEMORY_BLOCK
, PNV_VOID
);
163 static NV_SINT32
nv_ospackettx(PNV_VOID
, PNV_VOID
, NV_UINT32
);
164 static NV_SINT32
nv_ospacketrx(PNV_VOID
, PNV_VOID
, NV_UINT32
, NV_UINT8
*, NV_UINT8
);
165 static NV_SINT32
nv_oslinkchg(PNV_VOID
, NV_SINT32
);
166 static NV_SINT32
nv_osalloctimer(PNV_VOID
, PNV_VOID
*);
167 static NV_SINT32
nv_osfreetimer(PNV_VOID
, PNV_VOID
);
168 static NV_SINT32
nv_osinittimer(PNV_VOID
, PNV_VOID
, PTIMER_FUNC
, PNV_VOID
);
169 static NV_SINT32
nv_ossettimer(PNV_VOID
, PNV_VOID
, NV_UINT32
);
170 static NV_SINT32
nv_oscanceltimer(PNV_VOID
, PNV_VOID
);
172 static NV_SINT32
nv_ospreprocpkt(PNV_VOID
, PNV_VOID
, PNV_VOID
*, NV_UINT8
*, NV_UINT8
);
173 static PNV_VOID
nv_ospreprocpktnopq(PNV_VOID
, PNV_VOID
);
174 static NV_SINT32
nv_osindicatepkt(PNV_VOID
, PNV_VOID
*, NV_UINT32
);
175 static NV_SINT32
nv_oslockalloc(PNV_VOID
, NV_SINT32
, PNV_VOID
*);
176 static NV_SINT32
nv_oslockacquire(PNV_VOID
, NV_SINT32
, PNV_VOID
);
177 static NV_SINT32
nv_oslockrelease(PNV_VOID
, NV_SINT32
, PNV_VOID
);
178 static PNV_VOID
nv_osreturnbufvirt(PNV_VOID
, PNV_VOID
);
180 static device_method_t nv_methods
[] = {
181 /* Device interface */
182 DEVMETHOD(device_probe
, nv_probe
),
183 DEVMETHOD(device_attach
, nv_attach
),
184 DEVMETHOD(device_detach
, nv_detach
),
185 DEVMETHOD(device_shutdown
, nv_shutdown
),
188 DEVMETHOD(bus_print_child
, bus_generic_print_child
),
189 DEVMETHOD(bus_driver_added
, bus_generic_driver_added
),
192 DEVMETHOD(miibus_readreg
, nv_miibus_readreg
),
193 DEVMETHOD(miibus_writereg
, nv_miibus_writereg
),
198 static driver_t nv_driver
= {
201 sizeof(struct nv_softc
)
204 static devclass_t nv_devclass
;
206 static int nv_pollinterval
= 0;
207 SYSCTL_INT(_hw
, OID_AUTO
, nv_pollinterval
, CTLFLAG_RW
,
208 &nv_pollinterval
, 0, "delay between interface polls");
210 DRIVER_MODULE(nv
, pci
, nv_driver
, nv_devclass
, 0, 0);
211 DRIVER_MODULE(miibus
, nv
, miibus_driver
, miibus_devclass
, 0, 0);
213 static struct nv_type nv_devs
[] = {
214 {NVIDIA_VENDORID
, NFORCE_MCPNET1_DEVICEID
,
215 "NVIDIA nForce MCP Networking Adapter"},
216 {NVIDIA_VENDORID
, NFORCE_MCPNET2_DEVICEID
,
217 "NVIDIA nForce MCP2 Networking Adapter"},
218 {NVIDIA_VENDORID
, NFORCE_MCPNET3_DEVICEID
,
219 "NVIDIA nForce MCP3 Networking Adapter"},
220 {NVIDIA_VENDORID
, NFORCE_MCPNET4_DEVICEID
,
221 "NVIDIA nForce MCP4 Networking Adapter"},
222 {NVIDIA_VENDORID
, NFORCE_MCPNET5_DEVICEID
,
223 "NVIDIA nForce MCP5 Networking Adapter"},
224 {NVIDIA_VENDORID
, NFORCE_MCPNET6_DEVICEID
,
225 "NVIDIA nForce MCP6 Networking Adapter"},
226 {NVIDIA_VENDORID
, NFORCE_MCPNET7_DEVICEID
,
227 "NVIDIA nForce MCP7 Networking Adapter"},
228 {NVIDIA_VENDORID
, NFORCE_MCPNET8_DEVICEID
,
229 "NVIDIA nForce MCP8 Networking Adapter"},
230 {NVIDIA_VENDORID
, NFORCE_MCPNET9_DEVICEID
,
231 "NVIDIA nForce MCP9 Networking Adapter"},
232 {NVIDIA_VENDORID
, NFORCE_MCPNET10_DEVICEID
,
233 "NVIDIA nForce MCP10 Networking Adapter"},
234 {NVIDIA_VENDORID
, NFORCE_MCPNET11_DEVICEID
,
235 "NVIDIA nForce MCP11 Networking Adapter"},
236 {NVIDIA_VENDORID
, NFORCE_MCPNET12_DEVICEID
,
237 "NVIDIA nForce MCP12 Networking Adapter"},
238 {NVIDIA_VENDORID
, NFORCE_MCPNET13_DEVICEID
,
239 "NVIDIA nForce MCP13 Networking Adapter"},
243 /* DMA MEM map callback function to get data segment physical address */
245 nv_dmamap_cb(void *arg
, bus_dma_segment_t
* segs
, int nsegs
, int error
)
251 ("Too many DMA segments returned when mapping DMA memory"));
252 *(bus_addr_t
*)arg
= segs
->ds_addr
;
255 /* DMA RX map callback function to get data segment physical address */
257 nv_dmamap_rx_cb(void *arg
, bus_dma_segment_t
* segs
, int nsegs
, bus_size_t mapsize
, int error
)
261 *(bus_addr_t
*)arg
= segs
->ds_addr
;
265 * DMA TX buffer callback function to allocate fragment data segment
269 nv_dmamap_tx_cb(void *arg
, bus_dma_segment_t
* segs
, int nsegs
, bus_size_t mapsize
, int error
)
271 struct nv_tx_desc
*info
= arg
;
275 KASSERT(nsegs
< NV_MAX_FRAGS
,
276 ("Too many DMA segments returned when mapping mbuf"));
277 info
->numfrags
= nsegs
;
278 bcopy(segs
, info
->frags
, nsegs
* sizeof(bus_dma_segment_t
));
281 /* Probe for supported hardware ID's */
283 nv_probe(device_t dev
)
285 struct nv_type
*t
= nv_devs
;
287 /* Check for matching PCI DEVICE ID's */
288 while (t
->name
!= NULL
) {
289 if ((pci_get_vendor(dev
) == t
->vid_id
) &&
290 (pci_get_device(dev
) == t
->dev_id
)) {
291 device_set_desc(dev
, t
->name
);
300 /* Attach driver and initialise hardware for use */
302 nv_attach(device_t dev
)
304 u_char eaddr
[ETHER_ADDR_LEN
];
308 ADAPTER_OPEN_PARAMS OpenParams
;
309 int error
= 0, i
, rid
;
313 device_printf(dev
, "nvenetlib.o version %s\n", DRIVER_VERSION
);
315 DEBUGOUT(NV_DEBUG_INIT
, "nv: nv_attach - entry\n");
317 sc
= device_get_softc(dev
);
318 unit
= device_get_unit(dev
);
322 callout_init(&sc
->nv_stat_timer
);
324 /* Preinitialize data structures */
325 bzero(&OpenParams
, sizeof(ADAPTER_OPEN_PARAMS
));
327 /* Enable bus mastering */
328 pci_enable_busmaster(dev
);
330 /* Allocate memory mapped address space */
332 sc
->res
= bus_alloc_resource_any(dev
, SYS_RES_MEMORY
, &rid
, RF_ACTIVE
);
334 if (sc
->res
== NULL
) {
335 device_printf(dev
, "couldn't map memory\n");
339 sc
->sc_st
= rman_get_bustag(sc
->res
);
340 sc
->sc_sh
= rman_get_bushandle(sc
->res
);
342 /* Allocate interrupt */
344 sc
->irq
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
, &rid
,
345 RF_SHAREABLE
| RF_ACTIVE
);
347 if (sc
->irq
== NULL
) {
348 device_printf(dev
, "couldn't map interrupt\n");
352 /* Allocate DMA tags */
353 error
= bus_dma_tag_create(NULL
, 4, 0, BUS_SPACE_MAXADDR_32BIT
,
354 BUS_SPACE_MAXADDR
, NULL
, NULL
, MCLBYTES
* NV_MAX_FRAGS
,
355 NV_MAX_FRAGS
, MCLBYTES
, 0,
358 device_printf(dev
, "couldn't allocate dma tag\n");
361 error
= bus_dma_tag_create(NULL
, 4, 0, BUS_SPACE_MAXADDR_32BIT
,
362 BUS_SPACE_MAXADDR
, NULL
, NULL
,
363 sizeof(struct nv_rx_desc
) * RX_RING_SIZE
, 1,
364 sizeof(struct nv_rx_desc
) * RX_RING_SIZE
, 0,
367 device_printf(dev
, "couldn't allocate dma tag\n");
370 error
= bus_dma_tag_create(NULL
, 4, 0, BUS_SPACE_MAXADDR_32BIT
,
371 BUS_SPACE_MAXADDR
, NULL
, NULL
,
372 sizeof(struct nv_tx_desc
) * TX_RING_SIZE
, 1,
373 sizeof(struct nv_tx_desc
) * TX_RING_SIZE
, 0,
376 device_printf(dev
, "couldn't allocate dma tag\n");
380 error
= bus_dmamap_create(sc
->ttag
, 0, &sc
->tmap
);
382 device_printf(dev
, "couldn't create dma map\n");
386 /* Allocate DMA safe memory and get the DMA addresses. */
387 error
= bus_dmamem_alloc(sc
->ttag
, (void **)&sc
->tx_desc
,
388 BUS_DMA_WAITOK
| BUS_DMA_ZERO
, &sc
->tmap
);
390 device_printf(dev
, "couldn't allocate dma memory\n");
393 error
= bus_dmamap_load(sc
->ttag
, sc
->tmap
, sc
->tx_desc
,
394 sizeof(struct nv_tx_desc
) * TX_RING_SIZE
, nv_dmamap_cb
,
397 device_printf(dev
, "couldn't map dma memory\n");
401 error
= bus_dmamap_create(sc
->rtag
, 0, &sc
->rmap
);
403 device_printf(dev
, "couldn't create dma map\n");
407 error
= bus_dmamem_alloc(sc
->rtag
, (void **)&sc
->rx_desc
,
408 BUS_DMA_WAITOK
| BUS_DMA_ZERO
, &sc
->rmap
);
410 device_printf(dev
, "couldn't allocate dma memory\n");
413 error
= bus_dmamap_load(sc
->rtag
, sc
->rmap
, sc
->rx_desc
,
414 sizeof(struct nv_rx_desc
) * RX_RING_SIZE
, nv_dmamap_cb
,
417 device_printf(dev
, "couldn't map dma memory\n");
420 /* Initialize rings. */
421 if (nv_init_rings(sc
)) {
422 device_printf(dev
, "failed to init rings\n");
426 /* Setup NVIDIA API callback routines */
429 osapi
->pfnAllocMemory
= nv_osalloc
;
430 osapi
->pfnFreeMemory
= nv_osfree
;
431 osapi
->pfnAllocMemoryEx
= nv_osallocex
;
432 osapi
->pfnFreeMemoryEx
= nv_osfreeex
;
433 osapi
->pfnClearMemory
= nv_osclear
;
434 osapi
->pfnStallExecution
= nv_osdelay
;
435 osapi
->pfnAllocReceiveBuffer
= nv_osallocrxbuf
;
436 osapi
->pfnFreeReceiveBuffer
= nv_osfreerxbuf
;
437 osapi
->pfnPacketWasSent
= nv_ospackettx
;
438 osapi
->pfnPacketWasReceived
= nv_ospacketrx
;
439 osapi
->pfnLinkStateHasChanged
= nv_oslinkchg
;
440 osapi
->pfnAllocTimer
= nv_osalloctimer
;
441 osapi
->pfnFreeTimer
= nv_osfreetimer
;
442 osapi
->pfnInitializeTimer
= nv_osinittimer
;
443 osapi
->pfnSetTimer
= nv_ossettimer
;
444 osapi
->pfnCancelTimer
= nv_oscanceltimer
;
445 osapi
->pfnPreprocessPacket
= nv_ospreprocpkt
;
446 osapi
->pfnPreprocessPacketNopq
= nv_ospreprocpktnopq
;
447 osapi
->pfnIndicatePackets
= nv_osindicatepkt
;
448 osapi
->pfnLockAlloc
= nv_oslockalloc
;
449 osapi
->pfnLockAcquire
= nv_oslockacquire
;
450 osapi
->pfnLockRelease
= nv_oslockrelease
;
451 osapi
->pfnReturnBufferVirtual
= nv_osreturnbufvirt
;
454 sc
->max_frame_size
= ETHERMTU
+ ETHER_HDR_LEN
+ FCS_LEN
;
456 /* TODO - We don't support hardware offload yet */
460 /* Set NVIDIA API startup parameters */
461 OpenParams
.MaxDpcLoop
= 2;
462 OpenParams
.MaxRxPkt
= RX_RING_SIZE
;
463 OpenParams
.MaxTxPkt
= TX_RING_SIZE
;
464 OpenParams
.SentPacketStatusSuccess
= 1;
465 OpenParams
.SentPacketStatusFailure
= 0;
466 OpenParams
.MaxRxPktToAccumulate
= 6;
467 OpenParams
.ulPollInterval
= nv_pollinterval
;
468 OpenParams
.SetForcedModeEveryNthRxPacket
= 0;
469 OpenParams
.SetForcedModeEveryNthTxPacket
= 0;
470 OpenParams
.RxForcedInterrupt
= 0;
471 OpenParams
.TxForcedInterrupt
= 0;
472 OpenParams
.pOSApi
= osapi
;
473 OpenParams
.pvHardwareBaseAddress
= rman_get_virtual(sc
->res
);
474 OpenParams
.bASFEnabled
= 0;
475 OpenParams
.ulDescriptorVersion
= sc
->hwmode
;
476 OpenParams
.ulMaxPacketSize
= sc
->max_frame_size
;
477 OpenParams
.DeviceId
= pci_get_device(dev
);
479 /* Open NVIDIA Hardware API */
480 error
= ADAPTER_Open(&OpenParams
, (void **)&(sc
->hwapi
), &sc
->phyaddr
);
482 device_printf(dev
, "failed to open NVIDIA Hardware API: 0x%x\n", error
);
486 /* TODO - Add support for MODE2 hardware offload */
488 bzero(&sc
->adapterdata
, sizeof(sc
->adapterdata
));
490 sc
->adapterdata
.ulMediaIF
= sc
->media
;
491 sc
->adapterdata
.ulModeRegTxReadCompleteEnable
= 1;
492 sc
->hwapi
->pfnSetCommonData(sc
->hwapi
->pADCX
, &sc
->adapterdata
);
494 sc
->hwapi
->pfnInit(sc
->hwapi
->pADCX
,
496 0, /* force full duplex */
498 0, /* force async mode */
501 /* MAC is loaded backwards into h/w reg */
502 sc
->hwapi
->pfnGetNodeAddress(sc
->hwapi
->pADCX
, sc
->original_mac_addr
);
503 for (i
= 0; i
< 6; i
++) {
504 eaddr
[i
] = sc
->original_mac_addr
[5 - i
];
506 sc
->hwapi
->pfnSetNodeAddress(sc
->hwapi
->pADCX
, eaddr
);
507 bcopy(eaddr
, (char *)&sc
->sc_macaddr
, ETHER_ADDR_LEN
);
509 DEBUGOUT(NV_DEBUG_INIT
, "nv: do mii_phy_probe\n");
511 /* Probe device for MII interface to PHY */
512 if (mii_phy_probe(dev
, &sc
->miibus
, nv_ifmedia_upd
, nv_ifmedia_sts
)) {
513 device_printf(dev
, "MII without any phy!\n");
517 /* Setup interface parameters */
520 if_initname(ifp
, device_get_name(dev
), device_get_unit(dev
));
521 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
;
522 ifp
->if_ioctl
= nv_ioctl
;
523 ifp
->if_start
= nv_ifstart
;
524 #ifdef DEVICE_POLLING
525 ifp
->if_poll
= nv_poll
;
527 ifp
->if_watchdog
= nv_watchdog
;
529 ifp
->if_init
= nv_init
;
530 ifp
->if_mtu
= ETHERMTU
;
531 ifp
->if_baudrate
= IF_Mbps(100);
532 ifp
->if_capabilities
|= IFCAP_VLAN_MTU
;
533 ifq_set_maxlen(&ifp
->if_snd
, TX_RING_SIZE
- 1);
534 ifq_set_ready(&ifp
->if_snd
);
536 /* Attach to OS's managers. */
537 ether_ifattach(ifp
, sc
->sc_macaddr
, NULL
);
539 /* Activate our interrupt handler. - attach last to avoid lock */
540 error
= bus_setup_intr(sc
->dev
, sc
->irq
, INTR_NETSAFE
,
541 nv_intr
, sc
, &sc
->sc_ih
, ifp
->if_serializer
);
544 device_printf(sc
->dev
, "couldn't set up interrupt handler\n");
547 DEBUGOUT(NV_DEBUG_INIT
, "nv: nv_attach - exit\n");
556 /* Detach interface for module unload */
558 nv_detach(device_t dev
)
560 struct nv_softc
*sc
= device_get_softc(dev
);
564 ifp
= &sc
->arpcom
.ac_if
;
566 DEBUGOUT(NV_DEBUG_DEINIT
, "nv: nv_detach - entry\n");
568 lwkt_serialize_enter(ifp
->if_serializer
);
570 is_attached
= device_is_attached(dev
);
575 device_delete_child(dev
, sc
->miibus
);
576 bus_generic_detach(dev
);
578 /* Reload unreversed address back into MAC in original state */
579 if (sc
->original_mac_addr
)
580 sc
->hwapi
->pfnSetNodeAddress(sc
->hwapi
->pADCX
, sc
->original_mac_addr
);
582 DEBUGOUT(NV_DEBUG_DEINIT
, "nv: do pfnClose\n");
583 /* Detach from NVIDIA hardware API */
584 if (sc
->hwapi
->pfnClose
)
585 sc
->hwapi
->pfnClose(sc
->hwapi
->pADCX
, FALSE
);
586 /* Release resources */
588 bus_teardown_intr(sc
->dev
, sc
->irq
, sc
->sc_ih
);
590 lwkt_serialize_exit(ifp
->if_serializer
);
596 bus_release_resource(sc
->dev
, SYS_RES_IRQ
, 0, sc
->irq
);
598 bus_release_resource(sc
->dev
, SYS_RES_MEMORY
, NV_RID
, sc
->res
);
603 bus_dmamap_unload(sc
->rtag
, sc
->rmap
);
604 bus_dmamem_free(sc
->rtag
, sc
->rx_desc
, sc
->rmap
);
605 bus_dmamap_destroy(sc
->rtag
, sc
->rmap
);
608 bus_dma_tag_destroy(sc
->mtag
);
610 bus_dma_tag_destroy(sc
->ttag
);
612 bus_dma_tag_destroy(sc
->rtag
);
614 DEBUGOUT(NV_DEBUG_DEINIT
, "nv: nv_detach - exit\n");
618 /* Initialise interface and start it "RUNNING" */
622 struct nv_softc
*sc
= xsc
;
626 DEBUGOUT(NV_DEBUG_INIT
, "nv: nv_init - entry (%d)\n", sc
->linkup
);
630 /* Do nothing if already running */
631 if (ifp
->if_flags
& IFF_RUNNING
)
636 DEBUGOUT(NV_DEBUG_INIT
, "nv: do pfnInit\n");
640 /* Setup Hardware interface and allocate memory structures */
641 error
= sc
->hwapi
->pfnInit(sc
->hwapi
->pADCX
,
643 0, /* force full duplex */
645 0, /* force async mode */
649 device_printf(sc
->dev
, "failed to start NVIDIA Hardware interface\n");
652 /* Set the MAC address */
653 sc
->hwapi
->pfnSetNodeAddress(sc
->hwapi
->pADCX
, sc
->sc_macaddr
);
655 /* Setup multicast filter */
658 sc
->hwapi
->pfnStart(sc
->hwapi
->pADCX
);
660 /* Update interface parameters */
661 ifp
->if_flags
|= IFF_RUNNING
;
662 ifp
->if_flags
&= ~IFF_OACTIVE
;
665 * Enable the interrupt. Currently the nvidia API does not support
666 * polling, if we do not call pfnEnableInterrupts() we cannot
667 * issue the nvidia callback to process interrupts. Call the
668 * interrupt service routine in case the interrupt got stuck during
669 * a reset, renegotiation, or timeout.
672 lwkt_serialize_handler_enable(ifp
->if_serializer
);
673 sc
->hwapi
->pfnEnableInterrupts(sc
->hwapi
->pADCX
);
675 if ((ifp
->if_flags
& IFF_POLLING
) == 0) {
676 lwkt_serialize_handler_enable(ifp
->if_serializer
);
677 sc
->hwapi
->pfnEnableInterrupts(sc
->hwapi
->pADCX
);
683 * Reset watchdog and ring queue indexes. XXX if the interface
684 * is reset with pending tx packets queued to the actual device,
685 * the mbufs are currently lost.
690 callout_reset(&sc
->nv_stat_timer
, hz
, nv_tick
, sc
);
692 DEBUGOUT(NV_DEBUG_INIT
, "nv: nv_init - exit\n");
695 #ifdef DEVICE_POLLING
698 nv_poll(struct ifnet
*ifp
, enum poll_cmd cmd
, int count
)
700 struct nv_softc
*sc
= ifp
->if_softc
;
705 * We must disable the hardware interrupt on the device
706 * as well as ensure that any interrupt queued prior to
707 * this point does not execute the handler function.
709 * NOTE! The nvidia API does not support polling with
710 * interrupts disabled, so we have to leave them turned on
714 sc
->hwapi
->pfnDisableInterrupts(sc
->hwapi
->pADCX
);
715 lwkt_serialize_handler_disable(ifp
->if_serializer
);
718 case POLL_DEREGISTER
:
720 lwkt_serialize_handler_enable(ifp
->if_serializer
);
721 sc
->hwapi
->pfnEnableInterrupts(sc
->hwapi
->pADCX
);
724 case POLL_AND_CHECK_STATUS
:
727 if (ifp
->if_flags
& IFF_RUNNING
) {
730 if (ifp
->if_flags
& IFF_RUNNING
) {
731 if (!ifq_is_empty(&ifp
->if_snd
))
740 /* Stop interface activity ie. not "RUNNING" */
742 nv_stop(struct nv_softc
*sc
)
746 DEBUGOUT(NV_DEBUG_RUNNING
, "nv: nv_stop - entry\n");
751 /* Cancel tick timer */
752 callout_stop(&sc
->nv_stat_timer
);
755 * Stop hardware activity. The serializer handler disablement call
756 * prevents any interrupt scheduled prior to this call from calling
759 sc
->hwapi
->pfnDisableInterrupts(sc
->hwapi
->pADCX
);
760 lwkt_serialize_handler_disable(ifp
->if_serializer
);
762 sc
->hwapi
->pfnStop(sc
->hwapi
->pADCX
,
763 AFFECT_RECEIVER
| AFFECT_TRANSMITTER
);
764 sc
->hwapi
->pfnClearTxDesc(sc
->hwapi
->pADCX
);
766 DEBUGOUT(NV_DEBUG_DEINIT
, "nv: do pfnDeinit\n");
767 /* Shutdown interface and deallocate memory buffers */
768 if (sc
->hwapi
->pfnDeinit
)
769 sc
->hwapi
->pfnDeinit(sc
->hwapi
->pADCX
, 0);
776 ifp
->if_flags
&= ~(IFF_RUNNING
| IFF_OACTIVE
);
778 DEBUGOUT(NV_DEBUG_RUNNING
, "nv: nv_stop - exit\n");
781 /* Shutdown interface for unload/reboot */
783 nv_shutdown(device_t dev
)
787 DEBUGOUT(NV_DEBUG_DEINIT
, "nv: nv_shutdown\n");
789 sc
= device_get_softc(dev
);
791 /* Stop hardware activity */
792 lwkt_serialize_enter(sc
->sc_if
.if_serializer
);
794 lwkt_serialize_exit(sc
->sc_if
.if_serializer
);
797 /* Allocate TX ring buffers */
799 nv_init_rings(struct nv_softc
*sc
)
803 DEBUGOUT(NV_DEBUG_INIT
, "nv: nv_init_rings - entry\n");
805 sc
->cur_rx
= sc
->cur_tx
= sc
->pending_rxs
= sc
->pending_txs
= 0;
806 /* Initialise RX ring */
807 for (i
= 0; i
< RX_RING_SIZE
; i
++) {
808 struct nv_rx_desc
*desc
= sc
->rx_desc
+ i
;
809 struct nv_map_buffer
*buf
= &desc
->buf
;
811 buf
->mbuf
= m_getcl(MB_DONTWAIT
, MT_DATA
, M_PKTHDR
);
812 if (buf
->mbuf
== NULL
) {
813 device_printf(sc
->dev
, "couldn't allocate mbuf\n");
818 buf
->mbuf
->m_len
= buf
->mbuf
->m_pkthdr
.len
= MCLBYTES
;
819 m_adj(buf
->mbuf
, ETHER_ALIGN
);
821 error
= bus_dmamap_create(sc
->mtag
, 0, &buf
->map
);
823 device_printf(sc
->dev
, "couldn't create dma map\n");
827 error
= bus_dmamap_load_mbuf(sc
->mtag
, buf
->map
, buf
->mbuf
,
828 nv_dmamap_rx_cb
, &desc
->paddr
, 0);
830 device_printf(sc
->dev
, "couldn't dma map mbuf\n");
834 bus_dmamap_sync(sc
->mtag
, buf
->map
, BUS_DMASYNC_PREREAD
);
836 desc
->buflength
= buf
->mbuf
->m_len
;
837 desc
->vaddr
= mtod(buf
->mbuf
, caddr_t
);
839 bus_dmamap_sync(sc
->rtag
, sc
->rmap
,
840 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
842 /* Initialize TX ring */
843 for (i
= 0; i
< TX_RING_SIZE
; i
++) {
844 struct nv_tx_desc
*desc
= sc
->tx_desc
+ i
;
845 struct nv_map_buffer
*buf
= &desc
->buf
;
849 error
= bus_dmamap_create(sc
->mtag
, 0, &buf
->map
);
851 device_printf(sc
->dev
, "couldn't create dma map\n");
856 bus_dmamap_sync(sc
->ttag
, sc
->tmap
,
857 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
859 DEBUGOUT(NV_DEBUG_INIT
, "nv: nv_init_rings - exit\n");
865 /* Free the TX ring buffers */
867 nv_free_rings(struct nv_softc
*sc
)
871 DEBUGOUT(NV_DEBUG_DEINIT
, "nv: nv_free_rings - entry\n");
873 for (i
= 0; i
< RX_RING_SIZE
; i
++) {
874 struct nv_rx_desc
*desc
= sc
->rx_desc
+ i
;
875 struct nv_map_buffer
*buf
= &desc
->buf
;
878 bus_dmamap_unload(sc
->mtag
, buf
->map
);
879 bus_dmamap_destroy(sc
->mtag
, buf
->map
);
885 for (i
= 0; i
< TX_RING_SIZE
; i
++) {
886 struct nv_tx_desc
*desc
= sc
->tx_desc
+ i
;
887 struct nv_map_buffer
*buf
= &desc
->buf
;
890 bus_dmamap_unload(sc
->mtag
, buf
->map
);
891 bus_dmamap_destroy(sc
->mtag
, buf
->map
);
897 DEBUGOUT(NV_DEBUG_DEINIT
, "nv: nv_free_rings - exit\n");
900 /* Main loop for sending packets from OS to interface */
903 nv_ifstart(struct ifnet
*ifp
)
905 struct nv_softc
*sc
= ifp
->if_softc
;
906 struct nv_map_buffer
*buf
;
908 struct nv_tx_desc
*desc
;
909 ADAPTER_WRITE_DATA txdata
;
912 DEBUGOUT(NV_DEBUG_RUNNING
, "nv: nv_ifstart - entry\n");
914 /* If link is down/busy or queue is empty do nothing */
915 if ((ifp
->if_flags
& IFF_OACTIVE
) || ifq_is_empty(&ifp
->if_snd
))
918 /* Transmit queued packets until sent or TX ring is full */
919 while (sc
->pending_txs
< TX_RING_SIZE
) {
920 desc
= sc
->tx_desc
+ sc
->cur_tx
;
923 /* Get next packet to send. */
924 m0
= ifq_dequeue(&ifp
->if_snd
, NULL
);
926 /* If nothing to send, return. */
930 /* Map MBUF for DMA access */
931 error
= bus_dmamap_load_mbuf(sc
->mtag
, buf
->map
, m0
,
932 nv_dmamap_tx_cb
, desc
, BUS_DMA_NOWAIT
);
934 if (error
&& error
!= EFBIG
) {
940 * Packet has too many fragments - defrag into new mbuf
944 m
= m_defrag(m0
, MB_DONTWAIT
);
952 error
= bus_dmamap_load_mbuf(sc
->mtag
, buf
->map
, m
,
953 nv_dmamap_tx_cb
, desc
, BUS_DMA_NOWAIT
);
960 /* Do sync on DMA bounce buffer */
961 bus_dmamap_sync(sc
->mtag
, buf
->map
, BUS_DMASYNC_PREWRITE
);
964 txdata
.ulNumberOfElements
= desc
->numfrags
;
965 txdata
.pvID
= (PVOID
)desc
;
967 /* Put fragments into API element list */
968 txdata
.ulTotalLength
= buf
->mbuf
->m_len
;
969 for (i
= 0; i
< desc
->numfrags
; i
++) {
970 txdata
.sElement
[i
].ulLength
= (ulong
)desc
->frags
[i
].ds_len
;
971 txdata
.sElement
[i
].pPhysical
= (PVOID
)desc
->frags
[i
].ds_addr
;
974 /* Send packet to Nvidia API for transmission */
975 error
= sc
->hwapi
->pfnWrite(sc
->hwapi
->pADCX
, &txdata
);
978 case ADAPTERERR_NONE
:
979 /* Packet was queued in API TX queue successfully */
981 sc
->cur_tx
= (sc
->cur_tx
+ 1) % TX_RING_SIZE
;
984 case ADAPTERERR_TRANSMIT_QUEUE_FULL
:
985 /* The API TX queue is full - requeue the packet */
986 device_printf(sc
->dev
, "nv_ifstart: transmit queue is full\n");
987 ifp
->if_flags
|= IFF_OACTIVE
;
988 bus_dmamap_unload(sc
->mtag
, buf
->map
);
990 m_freem(m0
); /* XXX requeue */
994 /* The API failed to queue/send the packet so dump it */
995 device_printf(sc
->dev
, "nv_ifstart: transmit error\n");
996 bus_dmamap_unload(sc
->mtag
, buf
->map
);
1002 /* Set watchdog timer. */
1005 /* Copy packet to BPF tap */
1008 ifp
->if_flags
|= IFF_OACTIVE
;
1010 DEBUGOUT(NV_DEBUG_RUNNING
, "nv: nv_ifstart - exit\n");
1013 /* Handle IOCTL events */
1015 nv_ioctl(struct ifnet
*ifp
, u_long command
, caddr_t data
, struct ucred
*cr
)
1017 struct nv_softc
*sc
= ifp
->if_softc
;
1018 struct ifreq
*ifr
= (struct ifreq
*) data
;
1019 struct mii_data
*mii
;
1022 DEBUGOUT(NV_DEBUG_IOCTL
, "nv: nv_ioctl - entry\n");
1027 if (ifp
->if_mtu
== ifr
->ifr_mtu
)
1029 if (ifr
->ifr_mtu
+ ifp
->if_hdrlen
<= MAX_PACKET_SIZE_1518
) {
1030 ifp
->if_mtu
= ifr
->ifr_mtu
;
1038 /* Setup interface flags */
1039 if (ifp
->if_flags
& IFF_UP
) {
1040 if ((ifp
->if_flags
& IFF_RUNNING
) == 0) {
1045 if (ifp
->if_flags
& IFF_RUNNING
) {
1051 /* Handle IFF_PROMISC and IFF_ALLMULTI flags. */
1057 /* Setup multicast filter */
1058 if (ifp
->if_flags
& IFF_RUNNING
) {
1064 /* Get/Set interface media parameters */
1065 mii
= device_get_softc(sc
->miibus
);
1066 error
= ifmedia_ioctl(ifp
, ifr
, &mii
->mii_media
, command
);
1070 /* Everything else we forward to generic ether ioctl */
1071 error
= ether_ioctl(ifp
, command
, data
);
1075 DEBUGOUT(NV_DEBUG_IOCTL
, "nv: nv_ioctl - exit\n");
1081 * Interrupt service routine. The serializer has already been entered
1082 * since we installed it in our bus_setup_intr() call.
1087 struct nv_softc
*sc
= arg
;
1088 struct ifnet
*ifp
= &sc
->sc_if
;
1090 DEBUGOUT(NV_DEBUG_INTERRUPT
, "nv: nv_intr - entry\n");
1093 * Handle an interrupt event. Unfortunately the nvidia API
1094 * does not support interrupt disablement when polling, so we
1095 * have to re-enable after the query masks them off.
1097 if (sc
->hwapi
->pfnQueryInterrupt(sc
->hwapi
->pADCX
)) {
1098 sc
->hwapi
->pfnHandleInterrupt(sc
->hwapi
->pADCX
);
1100 lwkt_serialize_handler_enable(ifp
->if_serializer
);
1101 sc
->hwapi
->pfnEnableInterrupts(sc
->hwapi
->pADCX
);
1103 if ((ifp
->if_flags
& IFF_POLLING
) == 0) {
1104 lwkt_serialize_handler_enable(ifp
->if_serializer
);
1105 sc
->hwapi
->pfnEnableInterrupts(sc
->hwapi
->pADCX
);
1109 if (!ifq_is_empty(&ifp
->if_snd
))
1112 /* If no pending packets we don't need a timeout */
1113 if (sc
->pending_txs
== 0)
1114 sc
->sc_if
.if_timer
= 0;
1116 DEBUGOUT(NV_DEBUG_INTERRUPT
, "nv: nv_intr - exit\n");
1120 * Setup multicast filters
1122 * Serialized on call
1125 nv_setmulti(struct nv_softc
*sc
)
1128 struct ifmultiaddr
*ifma
;
1129 PACKET_FILTER hwfilter
;
1132 u_int8_t andaddr
[6];
1134 DEBUGOUT(NV_DEBUG_RUNNING
, "nv: nv_setmulti - entry\n");
1138 /* Initialize filter */
1139 hwfilter
.ulFilterFlags
= 0;
1140 for (i
= 0; i
< 6; i
++) {
1141 hwfilter
.acMulticastAddress
[i
] = 0;
1142 hwfilter
.acMulticastMask
[i
] = 0;
1145 if (ifp
->if_flags
& (IFF_PROMISC
| IFF_ALLMULTI
)) {
1146 /* Accept all packets */
1147 hwfilter
.ulFilterFlags
|= ACCEPT_ALL_PACKETS
;
1148 sc
->hwapi
->pfnSetPacketFilter(sc
->hwapi
->pADCX
, &hwfilter
);
1151 /* Setup multicast filter */
1152 LIST_FOREACH(ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
1155 if (ifma
->ifma_addr
->sa_family
!= AF_LINK
)
1158 addrp
= LLADDR((struct sockaddr_dl
*) ifma
->ifma_addr
);
1159 for (i
= 0; i
< 6; i
++) {
1160 u_int8_t mcaddr
= addrp
[i
];
1161 andaddr
[i
] &= mcaddr
;
1162 oraddr
[i
] |= mcaddr
;
1165 for (i
= 0; i
< 6; i
++) {
1166 hwfilter
.acMulticastAddress
[i
] = andaddr
[i
] & oraddr
[i
];
1167 hwfilter
.acMulticastMask
[i
] = andaddr
[i
] | (~oraddr
[i
]);
1170 /* Send filter to NVIDIA API */
1171 sc
->hwapi
->pfnSetPacketFilter(sc
->hwapi
->pADCX
, &hwfilter
);
1173 DEBUGOUT(NV_DEBUG_RUNNING
, "nv: nv_setmulti - exit\n");
1177 * Change the current media/mediaopts
1179 * Serialized on call
1182 nv_ifmedia_upd(struct ifnet
*ifp
)
1184 struct nv_softc
*sc
= ifp
->if_softc
;
1185 struct mii_data
*mii
;
1187 DEBUGOUT(NV_DEBUG_MII
, "nv: nv_ifmedia_upd\n");
1189 mii
= device_get_softc(sc
->miibus
);
1191 if (mii
->mii_instance
) {
1192 struct mii_softc
*miisc
;
1193 for (miisc
= LIST_FIRST(&mii
->mii_phys
); miisc
!= NULL
;
1194 miisc
= LIST_NEXT(miisc
, mii_list
)) {
1195 mii_phy_reset(miisc
);
1204 * Update current miibus PHY status of media
1206 * Serialized on call
1209 nv_ifmedia_sts(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)
1211 struct nv_softc
*sc
;
1212 struct mii_data
*mii
;
1214 DEBUGOUT(NV_DEBUG_MII
, "nv: nv_ifmedia_sts\n");
1217 mii
= device_get_softc(sc
->miibus
);
1220 ifmr
->ifm_active
= mii
->mii_media_active
;
1221 ifmr
->ifm_status
= mii
->mii_media_status
;
1224 /* miibus tick timer - maintain link status */
1228 struct nv_softc
*sc
= xsc
;
1229 struct mii_data
*mii
;
1233 lwkt_serialize_enter(ifp
->if_serializer
);
1234 nv_update_stats(sc
);
1236 mii
= device_get_softc(sc
->miibus
);
1239 if ((mii
->mii_media_status
& IFM_ACTIVE
) &&
1240 IFM_SUBTYPE(mii
->mii_media_active
) != IFM_NONE
) {
1241 if (!ifq_is_empty(&ifp
->if_snd
))
1244 callout_reset(&sc
->nv_stat_timer
, hz
, nv_tick
, sc
);
1245 lwkt_serialize_exit(ifp
->if_serializer
);
1248 /* Update ifnet data structure with collected interface stats from API */
1250 nv_update_stats(struct nv_softc
*sc
)
1252 struct ifnet
*ifp
= &sc
->sc_if
;
1253 ADAPTER_STATS stats
;
1256 sc
->hwapi
->pfnGetStatistics(sc
->hwapi
->pADCX
, &stats
);
1258 ifp
->if_ipackets
= stats
.ulSuccessfulReceptions
;
1259 ifp
->if_ierrors
= stats
.ulMissedFrames
+
1260 stats
.ulFailedReceptions
+
1262 stats
.ulFramingErrors
+
1263 stats
.ulOverFlowErrors
;
1265 ifp
->if_opackets
= stats
.ulSuccessfulTransmissions
;
1266 ifp
->if_oerrors
= sc
->tx_errors
+
1267 stats
.ulFailedTransmissions
+
1268 stats
.ulRetryErrors
+
1269 stats
.ulUnderflowErrors
+
1270 stats
.ulLossOfCarrierErrors
+
1271 stats
.ulLateCollisionErrors
;
1273 ifp
->if_collisions
= stats
.ulLateCollisionErrors
;
1277 /* miibus Read PHY register wrapper - calls Nvidia API entry point */
1279 nv_miibus_readreg(device_t dev
, int phy
, int reg
)
1281 struct nv_softc
*sc
= device_get_softc(dev
);
1284 DEBUGOUT(NV_DEBUG_MII
, "nv: nv_miibus_readreg - entry\n");
1286 ADAPTER_ReadPhy(sc
->hwapi
->pADCX
, phy
, reg
, &data
);
1288 DEBUGOUT(NV_DEBUG_MII
, "nv: nv_miibus_readreg - exit\n");
1293 /* miibus Write PHY register wrapper - calls Nvidia API entry point */
1295 nv_miibus_writereg(device_t dev
, int phy
, int reg
, int data
)
1297 struct nv_softc
*sc
= device_get_softc(dev
);
1299 DEBUGOUT(NV_DEBUG_MII
, "nv: nv_miibus_writereg - entry\n");
1301 ADAPTER_WritePhy(sc
->hwapi
->pADCX
, phy
, reg
, (ulong
)data
);
1303 DEBUGOUT(NV_DEBUG_MII
, "nv: nv_miibus_writereg - exit\n");
1306 /* Watchdog timer to prevent PHY lockups */
1308 nv_watchdog(struct ifnet
*ifp
)
1310 struct nv_softc
*sc
= ifp
->if_softc
;
1312 device_printf(sc
->dev
, "device timeout (%d) flags %d\n",
1313 sc
->pending_txs
, ifp
->if_flags
& IFF_OACTIVE
);
1318 ifp
->if_flags
&= ~IFF_RUNNING
;
1321 if (!ifq_is_empty(&ifp
->if_snd
))
1325 /* --- Start of NVOSAPI interface --- */
1327 /* Allocate DMA enabled general use memory for API */
1329 nv_osalloc(PNV_VOID ctx
, PMEMORY_BLOCK mem
)
1331 struct nv_softc
*sc
;
1332 bus_addr_t mem_physical
;
1334 DEBUGOUT(NV_DEBUG_API
, "nv: nv_osalloc - %d\n", mem
->uiLength
);
1336 sc
= (struct nv_softc
*)ctx
;
1338 mem
->pLogical
= (PVOID
)contigmalloc(mem
->uiLength
, M_DEVBUF
,
1339 M_NOWAIT
| M_ZERO
, 0, 0xffffffff, PAGE_SIZE
, 0);
1341 if (!mem
->pLogical
) {
1342 device_printf(sc
->dev
, "memory allocation failed\n");
1345 memset(mem
->pLogical
, 0, (ulong
)mem
->uiLength
);
1346 mem_physical
= vtophys(mem
->pLogical
);
1347 mem
->pPhysical
= (PVOID
)mem_physical
;
1349 DEBUGOUT(NV_DEBUG_API
, "nv: nv_osalloc %p/%p - %d\n",
1350 mem
->pLogical
, mem
->pPhysical
, mem
->uiLength
);
1355 /* Free allocated memory */
1357 nv_osfree(PNV_VOID ctx
, PMEMORY_BLOCK mem
)
1359 DEBUGOUT(NV_DEBUG_API
, "nv: nv_osfree - %p - %d\n",
1360 mem
->pLogical
, mem
->uiLength
);
1362 contigfree(mem
->pLogical
, PAGE_SIZE
, M_DEVBUF
);
1366 /* Copied directly from nvnet.c */
1368 nv_osallocex(PNV_VOID ctx
, PMEMORY_BLOCKEX mem_block_ex
)
1370 MEMORY_BLOCK mem_block
;
1372 DEBUGOUT(NV_DEBUG_API
, "nv: nv_osallocex\n");
1374 mem_block_ex
->pLogical
= NULL
;
1375 mem_block_ex
->uiLengthOrig
= mem_block_ex
->uiLength
;
1377 if ((mem_block_ex
->AllocFlags
& ALLOC_MEMORY_ALIGNED
) &&
1378 (mem_block_ex
->AlignmentSize
> 1)) {
1379 DEBUGOUT(NV_DEBUG_API
, " aligning on %d\n",
1380 mem_block_ex
->AlignmentSize
);
1381 mem_block_ex
->uiLengthOrig
+= mem_block_ex
->AlignmentSize
;
1383 mem_block
.uiLength
= mem_block_ex
->uiLengthOrig
;
1385 if (nv_osalloc(ctx
, &mem_block
) == 0) {
1388 mem_block_ex
->pLogicalOrig
= mem_block
.pLogical
;
1389 mem_block_ex
->pPhysicalOrigLow
= (uintptr_t)mem_block
.pPhysical
;
1390 mem_block_ex
->pPhysicalOrigHigh
= 0;
1392 mem_block_ex
->pPhysical
= mem_block
.pPhysical
;
1393 mem_block_ex
->pLogical
= mem_block
.pLogical
;
1395 if (mem_block_ex
->uiLength
!= mem_block_ex
->uiLengthOrig
) {
1396 unsigned int offset
;
1397 offset
= mem_block_ex
->pPhysicalOrigLow
& (mem_block_ex
->AlignmentSize
- 1);
1400 mem_block_ex
->pPhysical
= (PVOID
)((uintptr_t)mem_block_ex
->pPhysical
+
1401 mem_block_ex
->AlignmentSize
- offset
);
1402 mem_block_ex
->pLogical
= (PVOID
)((uintptr_t)mem_block_ex
->pLogical
+
1403 mem_block_ex
->AlignmentSize
- offset
);
1405 } /* if (mem_block_ex->uiLength !=
1406 * mem_block_ex->uiLengthOrig) */
1410 /* Copied directly from nvnet.c */
1412 nv_osfreeex(PNV_VOID ctx
, PMEMORY_BLOCKEX mem_block_ex
)
1414 MEMORY_BLOCK mem_block
;
1416 DEBUGOUT(NV_DEBUG_API
, "nv: nv_osfreeex\n");
1418 mem_block
.pLogical
= mem_block_ex
->pLogicalOrig
;
1419 mem_block
.pPhysical
= (PVOID
)((uintptr_t)mem_block_ex
->pPhysicalOrigLow
);
1420 mem_block
.uiLength
= mem_block_ex
->uiLengthOrig
;
1422 return (nv_osfree(ctx
, &mem_block
));
1425 /* Clear memory region */
1427 nv_osclear(PNV_VOID ctx
, PNV_VOID mem
, NV_SINT32 length
)
1429 DEBUGOUT(NV_DEBUG_API
, "nv: nv_osclear\n");
1430 memset(mem
, 0, length
);
1434 /* Sleep for a tick */
1436 nv_osdelay(PNV_VOID ctx
, NV_UINT32 usec
)
1438 if (usec
>= 1000000 / hz
) {
1439 tsleep(nv_osdelay
, 0, "nvdelay", (usec
* hz
/ 1000000) + 1);
1446 /* Allocate memory for rx buffer */
1448 nv_osallocrxbuf(PNV_VOID ctx
, PMEMORY_BLOCK mem
, PNV_VOID
*id
)
1450 struct nv_softc
*sc
= ctx
;
1451 struct nv_rx_desc
*desc
;
1452 struct nv_map_buffer
*buf
;
1455 DEBUGOUT(NV_DEBUG_API
, "nv: nv_osallocrxbuf\n");
1457 if (sc
->pending_rxs
== RX_RING_SIZE
) {
1458 device_printf(sc
->dev
, "rx ring buffer is full\n");
1461 desc
= sc
->rx_desc
+ sc
->cur_rx
;
1464 if (buf
->mbuf
== NULL
) {
1465 buf
->mbuf
= m_getcl(MB_DONTWAIT
, MT_DATA
, M_PKTHDR
);
1466 if (buf
->mbuf
== NULL
) {
1467 device_printf(sc
->dev
, "failed to allocate memory\n");
1470 buf
->mbuf
->m_len
= buf
->mbuf
->m_pkthdr
.len
= MCLBYTES
;
1471 m_adj(buf
->mbuf
, ETHER_ALIGN
);
1473 error
= bus_dmamap_load_mbuf(sc
->mtag
, buf
->map
, buf
->mbuf
,
1474 nv_dmamap_rx_cb
, &desc
->paddr
, 0);
1476 device_printf(sc
->dev
, "failed to dmamap mbuf\n");
1481 bus_dmamap_sync(sc
->mtag
, buf
->map
, BUS_DMASYNC_PREREAD
);
1482 desc
->buflength
= buf
->mbuf
->m_len
;
1483 desc
->vaddr
= mtod(buf
->mbuf
, PVOID
);
1486 sc
->cur_rx
= (sc
->cur_rx
+ 1) % RX_RING_SIZE
;
1488 mem
->pLogical
= (void *)desc
->vaddr
;
1489 mem
->pPhysical
= (void *)desc
->paddr
;
1490 mem
->uiLength
= desc
->buflength
;
1499 /* Free the rx buffer */
1501 nv_osfreerxbuf(PNV_VOID ctx
, PMEMORY_BLOCK mem
, PNV_VOID id
)
1503 struct nv_softc
*sc
= ctx
;
1504 struct nv_rx_desc
*desc
;
1505 struct nv_map_buffer
*buf
;
1507 DEBUGOUT(NV_DEBUG_API
, "nv: nv_osfreerxbuf\n");
1509 desc
= (struct nv_rx_desc
*) id
;
1513 bus_dmamap_unload(sc
->mtag
, buf
->map
);
1514 bus_dmamap_destroy(sc
->mtag
, buf
->map
);
1523 /* This gets called by the Nvidia API after our TX packet has been sent */
1525 nv_ospackettx(PNV_VOID ctx
, PNV_VOID id
, NV_UINT32 success
)
1527 struct nv_softc
*sc
= ctx
;
1528 struct nv_map_buffer
*buf
;
1529 struct nv_tx_desc
*desc
= (struct nv_tx_desc
*) id
;
1532 DEBUGOUT(NV_DEBUG_API
, "nv: nv_ospackettx\n");
1538 /* Unload and free mbuf cluster */
1539 if (buf
->mbuf
== NULL
)
1542 bus_dmamap_sync(sc
->mtag
, buf
->map
, BUS_DMASYNC_POSTWRITE
);
1543 bus_dmamap_unload(sc
->mtag
, buf
->map
);
1548 * Make sure we are clear to go if we previously stalled due
1551 if (sc
->pending_txs
< TX_RING_SIZE
) {
1552 ifp
->if_flags
&= ~IFF_OACTIVE
;
1553 if (!ifq_is_empty(&ifp
->if_snd
))
1560 /* This gets called by the Nvidia API when a new packet has been received */
1561 /* XXX What is newbuf used for? XXX */
1563 nv_ospacketrx(PNV_VOID ctx
, PNV_VOID data
, NV_UINT32 success
,
1564 NV_UINT8
*newbuf
, NV_UINT8 priority
)
1566 struct nv_softc
*sc
= ctx
;
1568 struct nv_rx_desc
*desc
;
1569 struct nv_map_buffer
*buf
;
1570 ADAPTER_READ_DATA
*readdata
;
1572 DEBUGOUT(NV_DEBUG_API
, "nv: nv_ospacketrx\n");
1576 readdata
= (ADAPTER_READ_DATA
*) data
;
1577 desc
= readdata
->pvID
;
1579 bus_dmamap_sync(sc
->mtag
, buf
->map
, BUS_DMASYNC_POSTREAD
);
1582 /* Sync DMA bounce buffer. */
1583 bus_dmamap_sync(sc
->mtag
, buf
->map
, BUS_DMASYNC_POSTREAD
);
1585 /* First mbuf in packet holds the ethernet and packet headers */
1586 buf
->mbuf
->m_pkthdr
.rcvif
= ifp
;
1587 buf
->mbuf
->m_pkthdr
.len
= buf
->mbuf
->m_len
= readdata
->ulTotalLength
;
1589 bus_dmamap_unload(sc
->mtag
, buf
->map
);
1591 /* Give mbuf to OS. */
1592 ifp
->if_input(ifp
, buf
->mbuf
);
1593 if (readdata
->ulFilterMatch
& ADREADFL_MULTICAST_MATCH
)
1596 /* Blat the mbuf pointer, kernel will free the mbuf cluster */
1599 bus_dmamap_sync(sc
->mtag
, buf
->map
, BUS_DMASYNC_POSTREAD
);
1600 bus_dmamap_unload(sc
->mtag
, buf
->map
);
1605 sc
->cur_rx
= desc
- sc
->rx_desc
;
1611 /* This gets called by NVIDIA API when the PHY link state changes */
1613 nv_oslinkchg(PNV_VOID ctx
, NV_SINT32 enabled
)
1615 DEBUGOUT(NV_DEBUG_API
, "nv: nv_oslinkchg\n");
1621 /* Setup a watchdog timer */
1623 nv_osalloctimer(PNV_VOID ctx
, PNV_VOID
*timer
)
1625 struct nv_softc
*sc
= (struct nv_softc
*)ctx
;
1627 DEBUGOUT(NV_DEBUG_BROKEN
, "nv: nv_osalloctimer\n");
1629 callout_init(&sc
->ostimer
);
1630 *timer
= &sc
->ostimer
;
1635 /* Free the timer */
1637 nv_osfreetimer(PNV_VOID ctx
, PNV_VOID timer
)
1639 DEBUGOUT(NV_DEBUG_BROKEN
, "nv: nv_osfreetimer\n");
1644 /* Setup timer parameters */
1646 nv_osinittimer(PNV_VOID ctx
, PNV_VOID timer
, PTIMER_FUNC func
, PNV_VOID parameters
)
1648 struct nv_softc
*sc
= (struct nv_softc
*)ctx
;
1650 DEBUGOUT(NV_DEBUG_BROKEN
, "nv: nv_osinittimer\n");
1652 sc
->ostimer_func
= func
;
1653 sc
->ostimer_params
= parameters
;
1659 nv_ostimer_callback(void *data
)
1661 struct nv_softc
*sc
= data
;
1662 struct ifnet
*ifp
= &sc
->sc_if
;
1664 lwkt_serialize_enter(ifp
->if_serializer
);
1665 sc
->ostimer_func(sc
->ostimer_params
);
1666 lwkt_serialize_exit(ifp
->if_serializer
);
1670 * Set the timer to go off
1672 * XXX what the hell are the units for 'delay' ? They sure aren't ticks!
1675 nv_ossettimer(PNV_VOID ctx
, PNV_VOID timer
, NV_UINT32 delay
)
1677 struct nv_softc
*sc
= ctx
;
1679 DEBUGOUT(NV_DEBUG_BROKEN
, "nv: nv_ossettimer\n");
1680 printf("nv_ossettimer %d\n", (int)delay
);
1682 callout_reset(&sc
->ostimer
, delay
, nv_ostimer_callback
, sc
);
1687 /* Cancel the timer */
1689 nv_oscanceltimer(PNV_VOID ctx
, PNV_VOID timer
)
1691 struct nv_softc
*sc
= ctx
;
1693 DEBUGOUT(NV_DEBUG_BROKEN
, "nv: nv_oscanceltimer\n");
1695 callout_stop(&sc
->ostimer
);
1701 nv_ospreprocpkt(PNV_VOID ctx
, PNV_VOID readdata
, PNV_VOID
*id
, NV_UINT8
*newbuffer
,
1704 /* Not implemented */
1705 DEBUGOUT(NV_DEBUG_BROKEN
, "nv: nv_ospreprocpkt\n");
1711 nv_ospreprocpktnopq(PNV_VOID ctx
, PNV_VOID readdata
)
1713 /* Not implemented */
1714 DEBUGOUT(NV_DEBUG_BROKEN
, "nv: nv_ospreprocpkt\n");
1720 nv_osindicatepkt(PNV_VOID ctx
, PNV_VOID
*id
, NV_UINT32 pktno
)
1722 /* Not implemented */
1723 DEBUGOUT(NV_DEBUG_BROKEN
, "nv: nv_osindicatepkt\n");
1728 /* Allocate mutex context (already done in nv_attach) */
1730 nv_oslockalloc(PNV_VOID ctx
, NV_SINT32 type
, PNV_VOID
*pLock
)
1732 struct nv_softc
*sc
= (struct nv_softc
*)ctx
;
1734 DEBUGOUT(NV_DEBUG_LOCK
, "nv: nv_oslockalloc\n");
1736 *pLock
= (void **)sc
;
1741 /* Obtain a spin lock */
1743 nv_oslockacquire(PNV_VOID ctx
, NV_SINT32 type
, PNV_VOID lock
)
1745 DEBUGOUT(NV_DEBUG_LOCK
, "nv: nv_oslockacquire\n");
1752 nv_oslockrelease(PNV_VOID ctx
, NV_SINT32 type
, PNV_VOID lock
)
1754 DEBUGOUT(NV_DEBUG_LOCK
, "nv: nv_oslockrelease\n");
1759 /* I have no idea what this is for */
1761 nv_osreturnbufvirt(PNV_VOID ctx
, PNV_VOID readdata
)
1763 /* Not implemented */
1764 DEBUGOUT(NV_DEBUG_LOCK
, "nv: nv_osreturnbufvirt\n");
1765 panic("nv: nv_osreturnbufvirtual not implemented\n");
1771 /* --- End on NVOSAPI interface --- */