if_ixgb.c revision 211913
1139749Simp/*******************************************************************************
2129794Stackerman
3129794StackermanCopyright (c) 2001-2004, Intel Corporation
4129794StackermanAll rights reserved.
5129794Stackerman
6129794StackermanRedistribution and use in source and binary forms, with or without
7129794Stackermanmodification, are permitted provided that the following conditions are met:
8129794Stackerman
9129794Stackerman 1. Redistributions of source code must retain the above copyright notice,
10129794Stackerman    this list of conditions and the following disclaimer.
11129794Stackerman
12129794Stackerman 2. Redistributions in binary form must reproduce the above copyright
13129794Stackerman    notice, this list of conditions and the following disclaimer in the
14129794Stackerman    documentation and/or other materials provided with the distribution.
15129794Stackerman
16129794Stackerman 3. Neither the name of the Intel Corporation nor the names of its
17129794Stackerman    contributors may be used to endorse or promote products derived from
18129794Stackerman    this software without specific prior written permission.
19129794Stackerman
20129794StackermanTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21129794StackermanAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22129794StackermanIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23129794StackermanARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24129794StackermanLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25129794StackermanCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26129794StackermanSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27129794StackermanINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28129794StackermanCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29129794StackermanARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30129794StackermanPOSSIBILITY OF SUCH DAMAGE.
31129794Stackerman
32129794Stackerman***************************************************************************/
33129794Stackerman
34129794Stackerman/*$FreeBSD: head/sys/dev/ixgb/if_ixgb.c 211913 2010-08-28 00:34:22Z yongari $*/
35129794Stackerman
36150968Sglebius#ifdef HAVE_KERNEL_OPTION_HEADERS
37150968Sglebius#include "opt_device_polling.h"
38150968Sglebius#endif
39150968Sglebius
40129794Stackerman#include <dev/ixgb/if_ixgb.h>
41129794Stackerman
42129794Stackerman/*********************************************************************
43129794Stackerman *  Set this to one to display debug statistics
44129794Stackerman *********************************************************************/
45129794Stackermanint             ixgb_display_debug_stats = 0;
46129794Stackerman
47129794Stackerman/*********************************************************************
48129794Stackerman *  Linked list of board private structures for all NICs found
49129794Stackerman *********************************************************************/
50129794Stackerman
51129794Stackermanstruct adapter *ixgb_adapter_list = NULL;
52129794Stackerman
53129794Stackerman
54129794Stackerman
55129794Stackerman/*********************************************************************
56129794Stackerman *  Driver version
57129794Stackerman *********************************************************************/
58129794Stackerman
59129794Stackermanchar            ixgb_driver_version[] = "1.0.6";
60129794Stackermanchar            ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation.";
61129794Stackerman
62129794Stackerman/*********************************************************************
63129794Stackerman *  PCI Device ID Table
64129794Stackerman *
65129794Stackerman *  Used by probe to select devices to load on
66129794Stackerman *  Last field stores an index into ixgb_strings
67129794Stackerman *  Last entry must be all 0s
68129794Stackerman *
69129794Stackerman *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
70129794Stackerman *********************************************************************/
71129794Stackerman
72129794Stackermanstatic ixgb_vendor_info_t ixgb_vendor_info_array[] =
73129794Stackerman{
74129794Stackerman	/* Intel(R) PRO/10000 Network Connection */
75129794Stackerman	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX, PCI_ANY_ID, PCI_ANY_ID, 0},
76129794Stackerman	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR, PCI_ANY_ID, PCI_ANY_ID, 0},
77129794Stackerman	/* required last entry */
78129794Stackerman	{0, 0, 0, 0, 0}
79129794Stackerman};
80129794Stackerman
81129794Stackerman/*********************************************************************
82129794Stackerman *  Table of branding strings for all supported NICs.
83129794Stackerman *********************************************************************/
84129794Stackerman
85129794Stackermanstatic char    *ixgb_strings[] = {
86129794Stackerman	"Intel(R) PRO/10GbE Network Driver"
87129794Stackerman};
88129794Stackerman
89129794Stackerman/*********************************************************************
90129794Stackerman *  Function prototypes
91129794Stackerman *********************************************************************/
92129794Stackermanstatic int      ixgb_probe(device_t);
93129794Stackermanstatic int      ixgb_attach(device_t);
94129794Stackermanstatic int      ixgb_detach(device_t);
95129794Stackermanstatic int      ixgb_shutdown(device_t);
96129794Stackermanstatic void     ixgb_intr(void *);
97129794Stackermanstatic void     ixgb_start(struct ifnet *);
98144651Salcstatic void     ixgb_start_locked(struct ifnet *);
99129794Stackermanstatic int      ixgb_ioctl(struct ifnet *, IOCTL_CMD_TYPE, caddr_t);
100199539Sjhbstatic void     ixgb_watchdog(struct adapter *);
101129794Stackermanstatic void     ixgb_init(void *);
102144651Salcstatic void     ixgb_init_locked(struct adapter *);
103129794Stackermanstatic void     ixgb_stop(void *);
104129794Stackermanstatic void     ixgb_media_status(struct ifnet *, struct ifmediareq *);
105129794Stackermanstatic int      ixgb_media_change(struct ifnet *);
106129794Stackermanstatic void     ixgb_identify_hardware(struct adapter *);
107129794Stackermanstatic int      ixgb_allocate_pci_resources(struct adapter *);
108129794Stackermanstatic void     ixgb_free_pci_resources(struct adapter *);
109129794Stackermanstatic void     ixgb_local_timer(void *);
110129794Stackermanstatic int      ixgb_hardware_init(struct adapter *);
111211907Syongaristatic int      ixgb_setup_interface(device_t, struct adapter *);
112129794Stackermanstatic int      ixgb_setup_transmit_structures(struct adapter *);
113129794Stackermanstatic void     ixgb_initialize_transmit_unit(struct adapter *);
114129794Stackermanstatic int      ixgb_setup_receive_structures(struct adapter *);
115129794Stackermanstatic void     ixgb_initialize_receive_unit(struct adapter *);
116129794Stackermanstatic void     ixgb_enable_intr(struct adapter *);
117129794Stackermanstatic void     ixgb_disable_intr(struct adapter *);
118129794Stackermanstatic void     ixgb_free_transmit_structures(struct adapter *);
119129794Stackermanstatic void     ixgb_free_receive_structures(struct adapter *);
120129794Stackermanstatic void     ixgb_update_stats_counters(struct adapter *);
121129794Stackermanstatic void     ixgb_clean_transmit_interrupts(struct adapter *);
122129794Stackermanstatic int      ixgb_allocate_receive_structures(struct adapter *);
123129794Stackermanstatic int      ixgb_allocate_transmit_structures(struct adapter *);
124193096Sattiliostatic int      ixgb_process_receive_interrupts(struct adapter *, int);
125129794Stackermanstatic void
126129794Stackermanixgb_receive_checksum(struct adapter *,
127129794Stackerman		      struct ixgb_rx_desc * rx_desc,
128129794Stackerman		      struct mbuf *);
129129794Stackermanstatic void
130129794Stackermanixgb_transmit_checksum_setup(struct adapter *,
131129794Stackerman			     struct mbuf *,
132129794Stackerman			     u_int8_t *);
133129794Stackermanstatic void     ixgb_set_promisc(struct adapter *);
134129794Stackermanstatic void     ixgb_disable_promisc(struct adapter *);
135129794Stackermanstatic void     ixgb_set_multi(struct adapter *);
136129794Stackermanstatic void     ixgb_print_hw_stats(struct adapter *);
137129794Stackermanstatic void     ixgb_print_link_status(struct adapter *);
138129794Stackermanstatic int
139129794Stackermanixgb_get_buf(int i, struct adapter *,
140129794Stackerman	     struct mbuf *);
141129794Stackermanstatic void     ixgb_enable_vlans(struct adapter * adapter);
142129794Stackermanstatic int      ixgb_encap(struct adapter * adapter, struct mbuf * m_head);
143129794Stackermanstatic int      ixgb_sysctl_stats(SYSCTL_HANDLER_ARGS);
144129794Stackermanstatic int
145129794Stackermanixgb_dma_malloc(struct adapter *, bus_size_t,
146129794Stackerman		struct ixgb_dma_alloc *, int);
147129794Stackermanstatic void     ixgb_dma_free(struct adapter *, struct ixgb_dma_alloc *);
148150789Sglebius#ifdef DEVICE_POLLING
149150789Sglebiusstatic poll_handler_t ixgb_poll;
150150789Sglebius#endif
151129794Stackerman
152129794Stackerman/*********************************************************************
153129794Stackerman *  FreeBSD Device Interface Entry Points
154129794Stackerman *********************************************************************/
155129794Stackerman
156129794Stackermanstatic device_method_t ixgb_methods[] = {
157129794Stackerman	/* Device interface */
158129794Stackerman	DEVMETHOD(device_probe, ixgb_probe),
159129794Stackerman	DEVMETHOD(device_attach, ixgb_attach),
160129794Stackerman	DEVMETHOD(device_detach, ixgb_detach),
161129794Stackerman	DEVMETHOD(device_shutdown, ixgb_shutdown),
162129794Stackerman	{0, 0}
163129794Stackerman};
164129794Stackerman
165129794Stackermanstatic driver_t ixgb_driver = {
166129794Stackerman	"ixgb", ixgb_methods, sizeof(struct adapter),
167129794Stackerman};
168129794Stackerman
169129794Stackermanstatic devclass_t ixgb_devclass;
170192147SimpDRIVER_MODULE(ixgb, pci, ixgb_driver, ixgb_devclass, 0, 0);
171129794Stackerman
172192147SimpMODULE_DEPEND(ixgb, pci, 1, 1, 1);
173192147SimpMODULE_DEPEND(ixgb, ether, 1, 1, 1);
174144183Smux
175129794Stackerman/* some defines for controlling descriptor fetches in h/w */
176129794Stackerman#define RXDCTL_PTHRESH_DEFAULT 128	/* chip considers prefech below this */
177129794Stackerman#define RXDCTL_HTHRESH_DEFAULT 16	/* chip will only prefetch if tail is
178129794Stackerman					 * pushed this many descriptors from
179129794Stackerman					 * head */
180129794Stackerman#define RXDCTL_WTHRESH_DEFAULT 0	/* chip writes back at this many or RXT0 */
181129794Stackerman
182129794Stackerman
183129794Stackerman/*********************************************************************
184129794Stackerman *  Device identification routine
185129794Stackerman *
186129794Stackerman *  ixgb_probe determines if the driver should be loaded on
187129794Stackerman *  adapter based on PCI vendor/device id of the adapter.
188129794Stackerman *
189129794Stackerman *  return 0 on success, positive on failure
190129794Stackerman *********************************************************************/
191129794Stackerman
192129794Stackermanstatic int
193129794Stackermanixgb_probe(device_t dev)
194129794Stackerman{
195129794Stackerman	ixgb_vendor_info_t *ent;
196129794Stackerman
197129794Stackerman	u_int16_t       pci_vendor_id = 0;
198129794Stackerman	u_int16_t       pci_device_id = 0;
199129794Stackerman	u_int16_t       pci_subvendor_id = 0;
200129794Stackerman	u_int16_t       pci_subdevice_id = 0;
201129794Stackerman	char            adapter_name[60];
202129794Stackerman
203129794Stackerman	INIT_DEBUGOUT("ixgb_probe: begin");
204129794Stackerman
205129794Stackerman	pci_vendor_id = pci_get_vendor(dev);
206129794Stackerman	if (pci_vendor_id != IXGB_VENDOR_ID)
207129794Stackerman		return (ENXIO);
208129794Stackerman
209129794Stackerman	pci_device_id = pci_get_device(dev);
210129794Stackerman	pci_subvendor_id = pci_get_subvendor(dev);
211129794Stackerman	pci_subdevice_id = pci_get_subdevice(dev);
212129794Stackerman
213129794Stackerman	ent = ixgb_vendor_info_array;
214129794Stackerman	while (ent->vendor_id != 0) {
215129794Stackerman		if ((pci_vendor_id == ent->vendor_id) &&
216129794Stackerman		    (pci_device_id == ent->device_id) &&
217129794Stackerman
218129794Stackerman		    ((pci_subvendor_id == ent->subvendor_id) ||
219129794Stackerman		     (ent->subvendor_id == PCI_ANY_ID)) &&
220129794Stackerman
221129794Stackerman		    ((pci_subdevice_id == ent->subdevice_id) ||
222129794Stackerman		     (ent->subdevice_id == PCI_ANY_ID))) {
223129794Stackerman			sprintf(adapter_name, "%s, Version - %s",
224129794Stackerman				ixgb_strings[ent->index],
225129794Stackerman				ixgb_driver_version);
226129794Stackerman			device_set_desc_copy(dev, adapter_name);
227143160Simp			return (BUS_PROBE_DEFAULT);
228129794Stackerman		}
229129794Stackerman		ent++;
230129794Stackerman	}
231129794Stackerman
232129794Stackerman	return (ENXIO);
233129794Stackerman}
234129794Stackerman
235129794Stackerman/*********************************************************************
236129794Stackerman *  Device initialization routine
237129794Stackerman *
238129794Stackerman *  The attach entry point is called when the driver is being loaded.
239129794Stackerman *  This routine identifies the type of hardware, allocates all resources
240129794Stackerman *  and initializes the hardware.
241129794Stackerman *
242129794Stackerman *  return 0 on success, positive on failure
243129794Stackerman *********************************************************************/
244129794Stackerman
245129794Stackermanstatic int
246129794Stackermanixgb_attach(device_t dev)
247129794Stackerman{
248129794Stackerman	struct adapter *adapter;
249129794Stackerman	int             tsize, rsize;
250129794Stackerman	int             error = 0;
251129794Stackerman
252198987Sjhb	device_printf(dev, "%s\n", ixgb_copyright);
253129794Stackerman	INIT_DEBUGOUT("ixgb_attach: begin");
254129794Stackerman
255129794Stackerman	/* Allocate, clear, and link in our adapter structure */
256129794Stackerman	if (!(adapter = device_get_softc(dev))) {
257198987Sjhb		device_printf(dev, "adapter structure allocation failed\n");
258129794Stackerman		return (ENOMEM);
259129794Stackerman	}
260129794Stackerman	bzero(adapter, sizeof(struct adapter));
261129794Stackerman	adapter->dev = dev;
262129794Stackerman	adapter->osdep.dev = dev;
263144651Salc	IXGB_LOCK_INIT(adapter, device_get_nameunit(dev));
264129794Stackerman
265129794Stackerman	if (ixgb_adapter_list != NULL)
266129794Stackerman		ixgb_adapter_list->prev = adapter;
267129794Stackerman	adapter->next = ixgb_adapter_list;
268129794Stackerman	ixgb_adapter_list = adapter;
269129794Stackerman
270129794Stackerman	/* SYSCTL APIs */
271144183Smux	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
272144183Smux			SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
273129794Stackerman			OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW,
274129794Stackerman			(void *)adapter, 0,
275129794Stackerman			ixgb_sysctl_stats, "I", "Statistics");
276129794Stackerman
277199539Sjhb	callout_init_mtx(&adapter->timer, &adapter->mtx, 0);
278129794Stackerman
279129794Stackerman	/* Determine hardware revision */
280129794Stackerman	ixgb_identify_hardware(adapter);
281129794Stackerman
282129794Stackerman	/* Parameters (to be read from user) */
283129794Stackerman	adapter->num_tx_desc = IXGB_MAX_TXD;
284129794Stackerman	adapter->num_rx_desc = IXGB_MAX_RXD;
285129794Stackerman	adapter->tx_int_delay = TIDV;
286129794Stackerman	adapter->rx_int_delay = RDTR;
287129794Stackerman	adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
288129794Stackerman
289129794Stackerman	adapter->hw.fc.high_water = FCRTH;
290129794Stackerman	adapter->hw.fc.low_water = FCRTL;
291129794Stackerman	adapter->hw.fc.pause_time = FCPAUSE;
292129794Stackerman	adapter->hw.fc.send_xon = TRUE;
293129794Stackerman	adapter->hw.fc.type = FLOW_CONTROL;
294129794Stackerman
295129794Stackerman
296129794Stackerman	/* Set the max frame size assuming standard ethernet sized frames */
297129794Stackerman	adapter->hw.max_frame_size =
298129794Stackerman		ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
299129794Stackerman
300129794Stackerman	if (ixgb_allocate_pci_resources(adapter)) {
301198987Sjhb		device_printf(dev, "Allocation of PCI resources failed\n");
302129794Stackerman		error = ENXIO;
303129794Stackerman		goto err_pci;
304129794Stackerman	}
305129794Stackerman	tsize = IXGB_ROUNDUP(adapter->num_tx_desc *
306129794Stackerman			     sizeof(struct ixgb_tx_desc), 4096);
307129794Stackerman
308129794Stackerman	/* Allocate Transmit Descriptor ring */
309129794Stackerman	if (ixgb_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) {
310198987Sjhb		device_printf(dev, "Unable to allocate TxDescriptor memory\n");
311129794Stackerman		error = ENOMEM;
312129794Stackerman		goto err_tx_desc;
313129794Stackerman	}
314129794Stackerman	adapter->tx_desc_base = (struct ixgb_tx_desc *) adapter->txdma.dma_vaddr;
315129794Stackerman
316129794Stackerman	rsize = IXGB_ROUNDUP(adapter->num_rx_desc *
317129794Stackerman			     sizeof(struct ixgb_rx_desc), 4096);
318129794Stackerman
319129794Stackerman	/* Allocate Receive Descriptor ring */
320129794Stackerman	if (ixgb_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) {
321198987Sjhb		device_printf(dev, "Unable to allocate rx_desc memory\n");
322129794Stackerman		error = ENOMEM;
323129794Stackerman		goto err_rx_desc;
324129794Stackerman	}
325129794Stackerman	adapter->rx_desc_base = (struct ixgb_rx_desc *) adapter->rxdma.dma_vaddr;
326129794Stackerman
327211913Syongari	/* Allocate multicast array memory. */
328211913Syongari	adapter->mta = malloc(sizeof(u_int8_t) * IXGB_ETH_LENGTH_OF_ADDRESS *
329211913Syongari	    MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
330211913Syongari	if (adapter->mta == NULL) {
331211913Syongari		device_printf(dev, "Can not allocate multicast setup array\n");
332211913Syongari		error = ENOMEM;
333211913Syongari		goto err_hw_init;
334211913Syongari	}
335211913Syongari
336129794Stackerman	/* Initialize the hardware */
337129794Stackerman	if (ixgb_hardware_init(adapter)) {
338198987Sjhb		device_printf(dev, "Unable to initialize the hardware\n");
339129794Stackerman		error = EIO;
340129794Stackerman		goto err_hw_init;
341129794Stackerman	}
342129794Stackerman	/* Setup OS specific network interface */
343211907Syongari	if (ixgb_setup_interface(dev, adapter) != 0)
344211907Syongari		goto err_hw_init;
345129794Stackerman
346129794Stackerman	/* Initialize statistics */
347129794Stackerman	ixgb_clear_hw_cntrs(&adapter->hw);
348129794Stackerman	ixgb_update_stats_counters(adapter);
349129794Stackerman
350129794Stackerman	INIT_DEBUGOUT("ixgb_attach: end");
351129794Stackerman	return (0);
352129794Stackerman
353129794Stackermanerr_hw_init:
354129794Stackerman	ixgb_dma_free(adapter, &adapter->rxdma);
355129794Stackermanerr_rx_desc:
356129794Stackerman	ixgb_dma_free(adapter, &adapter->txdma);
357129794Stackermanerr_tx_desc:
358129794Stackermanerr_pci:
359211907Syongari	if (adapter->ifp != NULL)
360211907Syongari		if_free(adapter->ifp);
361129794Stackerman	ixgb_free_pci_resources(adapter);
362129794Stackerman	sysctl_ctx_free(&adapter->sysctl_ctx);
363211913Syongari	free(adapter->mta, M_DEVBUF);
364129794Stackerman	return (error);
365129794Stackerman
366129794Stackerman}
367129794Stackerman
368129794Stackerman/*********************************************************************
369129794Stackerman *  Device removal routine
370129794Stackerman *
371129794Stackerman *  The detach entry point is called when the driver is being removed.
372129794Stackerman *  This routine stops the adapter and deallocates all the resources
373129794Stackerman *  that were allocated for driver operation.
374129794Stackerman *
375129794Stackerman *  return 0 on success, positive on failure
376129794Stackerman *********************************************************************/
377129794Stackerman
378129794Stackermanstatic int
379129794Stackermanixgb_detach(device_t dev)
380129794Stackerman{
381129794Stackerman	struct adapter *adapter = device_get_softc(dev);
382147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
383129794Stackerman
384129794Stackerman	INIT_DEBUGOUT("ixgb_detach: begin");
385129794Stackerman
386150789Sglebius#ifdef DEVICE_POLLING
387150789Sglebius	if (ifp->if_capenable & IFCAP_POLLING)
388150789Sglebius		ether_poll_deregister(ifp);
389150789Sglebius#endif
390150789Sglebius
391144651Salc	IXGB_LOCK(adapter);
392129794Stackerman	adapter->in_detach = 1;
393129794Stackerman
394129794Stackerman	ixgb_stop(adapter);
395144651Salc	IXGB_UNLOCK(adapter);
396129794Stackerman
397129794Stackerman#if __FreeBSD_version < 500000
398199539Sjhb	ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
399129794Stackerman#else
400199539Sjhb	ether_ifdetach(ifp);
401150306Simp#endif
402199539Sjhb	callout_drain(&adapter->timer);
403150306Simp	ixgb_free_pci_resources(adapter);
404150306Simp#if __FreeBSD_version >= 500000
405199539Sjhb	if_free(ifp);
406129794Stackerman#endif
407129794Stackerman
408129794Stackerman	/* Free Transmit Descriptor ring */
409129794Stackerman	if (adapter->tx_desc_base) {
410129794Stackerman		ixgb_dma_free(adapter, &adapter->txdma);
411129794Stackerman		adapter->tx_desc_base = NULL;
412129794Stackerman	}
413129794Stackerman	/* Free Receive Descriptor ring */
414129794Stackerman	if (adapter->rx_desc_base) {
415129794Stackerman		ixgb_dma_free(adapter, &adapter->rxdma);
416129794Stackerman		adapter->rx_desc_base = NULL;
417129794Stackerman	}
418129794Stackerman	/* Remove from the adapter list */
419129794Stackerman	if (ixgb_adapter_list == adapter)
420129794Stackerman		ixgb_adapter_list = adapter->next;
421129794Stackerman	if (adapter->next != NULL)
422129794Stackerman		adapter->next->prev = adapter->prev;
423129794Stackerman	if (adapter->prev != NULL)
424129794Stackerman		adapter->prev->next = adapter->next;
425211913Syongari	free(adapter->mta, M_DEVBUF);
426129794Stackerman
427144651Salc	IXGB_LOCK_DESTROY(adapter);
428129794Stackerman	return (0);
429129794Stackerman}
430129794Stackerman
431129794Stackerman/*********************************************************************
432129794Stackerman *
433129794Stackerman *  Shutdown entry point
434129794Stackerman *
435129794Stackerman **********************************************************************/
436129794Stackerman
437129794Stackermanstatic int
438129794Stackermanixgb_shutdown(device_t dev)
439129794Stackerman{
440129794Stackerman	struct adapter *adapter = device_get_softc(dev);
441144651Salc	IXGB_LOCK(adapter);
442129794Stackerman	ixgb_stop(adapter);
443144651Salc	IXGB_UNLOCK(adapter);
444129794Stackerman	return (0);
445129794Stackerman}
446129794Stackerman
447129794Stackerman
448129794Stackerman/*********************************************************************
449129794Stackerman *  Transmit entry point
450129794Stackerman *
451129794Stackerman *  ixgb_start is called by the stack to initiate a transmit.
452129794Stackerman *  The driver will remain in this routine as long as there are
453129794Stackerman *  packets to transmit and transmit resources are available.
454129794Stackerman *  In case resources are not available stack is notified and
455129794Stackerman *  the packet is requeued.
456129794Stackerman **********************************************************************/
457129794Stackerman
458129794Stackermanstatic void
459144651Salcixgb_start_locked(struct ifnet * ifp)
460129794Stackerman{
461129794Stackerman	struct mbuf    *m_head;
462129794Stackerman	struct adapter *adapter = ifp->if_softc;
463129794Stackerman
464144651Salc	IXGB_LOCK_ASSERT(adapter);
465129794Stackerman
466129794Stackerman	if (!adapter->link_active)
467129794Stackerman		return;
468129794Stackerman
469129794Stackerman	while (ifp->if_snd.ifq_head != NULL) {
470129794Stackerman		IF_DEQUEUE(&ifp->if_snd, m_head);
471129794Stackerman
472129794Stackerman		if (m_head == NULL)
473129794Stackerman			break;
474129794Stackerman
475129794Stackerman		if (ixgb_encap(adapter, m_head)) {
476148887Srwatson			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
477129794Stackerman			IF_PREPEND(&ifp->if_snd, m_head);
478129794Stackerman			break;
479129794Stackerman		}
480129794Stackerman		/* Send a copy of the frame to the BPF listener */
481129794Stackerman#if __FreeBSD_version < 500000
482129794Stackerman		if (ifp->if_bpf)
483129794Stackerman			bpf_mtap(ifp, m_head);
484129794Stackerman#else
485167190Scsjp		ETHER_BPF_MTAP(ifp, m_head);
486129794Stackerman#endif
487129794Stackerman		/* Set timeout in case hardware has problems transmitting */
488199539Sjhb		adapter->tx_timer = IXGB_TX_TIMEOUT;
489129794Stackerman
490129794Stackerman	}
491129794Stackerman	return;
492129794Stackerman}
493129794Stackerman
494144651Salcstatic void
495144651Salcixgb_start(struct ifnet *ifp)
496144651Salc{
497144651Salc	struct adapter *adapter = ifp->if_softc;
498144651Salc
499144651Salc	IXGB_LOCK(adapter);
500144651Salc	ixgb_start_locked(ifp);
501144651Salc	IXGB_UNLOCK(adapter);
502144651Salc	return;
503144651Salc}
504144651Salc
505129794Stackerman/*********************************************************************
506129794Stackerman *  Ioctl entry point
507129794Stackerman *
508129794Stackerman *  ixgb_ioctl is called when the user wants to configure the
509129794Stackerman *  interface.
510129794Stackerman *
511129794Stackerman *  return 0 on success, positive on failure
512129794Stackerman **********************************************************************/
513129794Stackerman
514129794Stackermanstatic int
515129794Stackermanixgb_ioctl(struct ifnet * ifp, IOCTL_CMD_TYPE command, caddr_t data)
516129794Stackerman{
517144651Salc	int             mask, error = 0;
518129794Stackerman	struct ifreq   *ifr = (struct ifreq *) data;
519129794Stackerman	struct adapter *adapter = ifp->if_softc;
520129794Stackerman
521129794Stackerman	if (adapter->in_detach)
522129794Stackerman		goto out;
523129794Stackerman
524129794Stackerman	switch (command) {
525129794Stackerman	case SIOCSIFADDR:
526129794Stackerman	case SIOCGIFADDR:
527129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFADDR (Get/Set Interface Addr)");
528129794Stackerman		ether_ioctl(ifp, command, data);
529129794Stackerman		break;
530129794Stackerman	case SIOCSIFMTU:
531129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
532129794Stackerman		if (ifr->ifr_mtu > IXGB_MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN) {
533129794Stackerman			error = EINVAL;
534129794Stackerman		} else {
535144651Salc			IXGB_LOCK(adapter);
536129794Stackerman			ifp->if_mtu = ifr->ifr_mtu;
537129794Stackerman			adapter->hw.max_frame_size =
538129794Stackerman				ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
539129794Stackerman
540144651Salc			ixgb_init_locked(adapter);
541144651Salc			IXGB_UNLOCK(adapter);
542129794Stackerman		}
543129794Stackerman		break;
544129794Stackerman	case SIOCSIFFLAGS:
545129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)");
546144651Salc		IXGB_LOCK(adapter);
547129794Stackerman		if (ifp->if_flags & IFF_UP) {
548148887Srwatson			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
549144651Salc				ixgb_init_locked(adapter);
550129794Stackerman			}
551129794Stackerman			ixgb_disable_promisc(adapter);
552129794Stackerman			ixgb_set_promisc(adapter);
553129794Stackerman		} else {
554148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
555129794Stackerman				ixgb_stop(adapter);
556129794Stackerman			}
557129794Stackerman		}
558144651Salc		IXGB_UNLOCK(adapter);
559129794Stackerman		break;
560129794Stackerman	case SIOCADDMULTI:
561129794Stackerman	case SIOCDELMULTI:
562129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI");
563148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
564144651Salc			IXGB_LOCK(adapter);
565129794Stackerman			ixgb_disable_intr(adapter);
566129794Stackerman			ixgb_set_multi(adapter);
567129794Stackerman			ixgb_enable_intr(adapter);
568144651Salc			IXGB_UNLOCK(adapter);
569129794Stackerman		}
570129794Stackerman		break;
571129794Stackerman	case SIOCSIFMEDIA:
572129794Stackerman	case SIOCGIFMEDIA:
573129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA (Get/Set Interface Media)");
574129794Stackerman		error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
575129794Stackerman		break;
576129794Stackerman	case SIOCSIFCAP:
577129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
578129794Stackerman		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
579150789Sglebius#ifdef DEVICE_POLLING
580150789Sglebius		if (mask & IFCAP_POLLING) {
581150789Sglebius			if (ifr->ifr_reqcap & IFCAP_POLLING) {
582150789Sglebius				error = ether_poll_register(ixgb_poll, ifp);
583150789Sglebius				if (error)
584150789Sglebius					return(error);
585150789Sglebius				IXGB_LOCK(adapter);
586150789Sglebius				ixgb_disable_intr(adapter);
587150789Sglebius				ifp->if_capenable |= IFCAP_POLLING;
588150789Sglebius				IXGB_UNLOCK(adapter);
589150789Sglebius			} else {
590150789Sglebius				error = ether_poll_deregister(ifp);
591150789Sglebius				/* Enable interrupt even in error case */
592150789Sglebius				IXGB_LOCK(adapter);
593150789Sglebius				ixgb_enable_intr(adapter);
594150789Sglebius				ifp->if_capenable &= ~IFCAP_POLLING;
595150789Sglebius				IXGB_UNLOCK(adapter);
596150789Sglebius			}
597150789Sglebius		}
598150789Sglebius#endif /* DEVICE_POLLING */
599129794Stackerman		if (mask & IFCAP_HWCSUM) {
600129794Stackerman			if (IFCAP_HWCSUM & ifp->if_capenable)
601129794Stackerman				ifp->if_capenable &= ~IFCAP_HWCSUM;
602129794Stackerman			else
603129794Stackerman				ifp->if_capenable |= IFCAP_HWCSUM;
604148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
605129794Stackerman				ixgb_init(adapter);
606129794Stackerman		}
607129794Stackerman		break;
608129794Stackerman	default:
609129794Stackerman		IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%X)\n", (int)command);
610129794Stackerman		error = EINVAL;
611129794Stackerman	}
612129794Stackerman
613129794Stackermanout:
614129794Stackerman	return (error);
615129794Stackerman}
616129794Stackerman
617129794Stackerman/*********************************************************************
618129794Stackerman *  Watchdog entry point
619129794Stackerman *
620129794Stackerman *  This routine is called whenever hardware quits transmitting.
621129794Stackerman *
622129794Stackerman **********************************************************************/
623129794Stackerman
624129794Stackermanstatic void
625199539Sjhbixgb_watchdog(struct adapter *adapter)
626129794Stackerman{
627199539Sjhb	struct ifnet *ifp;
628129794Stackerman
629199539Sjhb	ifp = adapter->ifp;
630199539Sjhb
631129794Stackerman	/*
632129794Stackerman	 * If we are in this routine because of pause frames, then don't
633129794Stackerman	 * reset the hardware.
634129794Stackerman	 */
635129794Stackerman	if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF) {
636199539Sjhb		adapter->tx_timer = IXGB_TX_TIMEOUT;
637129794Stackerman		return;
638129794Stackerman	}
639198987Sjhb	if_printf(ifp, "watchdog timeout -- resetting\n");
640129794Stackerman
641129794Stackerman	ixgb_stop(adapter);
642199539Sjhb	ixgb_init_locked(adapter);
643129794Stackerman
644129794Stackerman
645129794Stackerman	ifp->if_oerrors++;
646129794Stackerman
647129794Stackerman	return;
648129794Stackerman}
649129794Stackerman
650129794Stackerman/*********************************************************************
651129794Stackerman *  Init entry point
652129794Stackerman *
653129794Stackerman *  This routine is used in two ways. It is used by the stack as
654129794Stackerman *  init entry point in network interface structure. It is also used
655129794Stackerman *  by the driver as a hw/sw initialization routine to get to a
656129794Stackerman *  consistent state.
657129794Stackerman *
658129794Stackerman *  return 0 on success, positive on failure
659129794Stackerman **********************************************************************/
660129794Stackerman
661129794Stackermanstatic void
662144651Salcixgb_init_locked(struct adapter *adapter)
663129794Stackerman{
664129794Stackerman	struct ifnet   *ifp;
665129794Stackerman
666129794Stackerman	INIT_DEBUGOUT("ixgb_init: begin");
667129794Stackerman
668144651Salc	IXGB_LOCK_ASSERT(adapter);
669129794Stackerman
670129794Stackerman	ixgb_stop(adapter);
671198987Sjhb	ifp = adapter->ifp;
672129794Stackerman
673129794Stackerman	/* Get the latest mac address, User can use a LAA */
674198987Sjhb	bcopy(IF_LLADDR(ifp), adapter->hw.curr_mac_addr,
675198987Sjhb	    IXGB_ETH_LENGTH_OF_ADDRESS);
676129794Stackerman
677129794Stackerman	/* Initialize the hardware */
678129794Stackerman	if (ixgb_hardware_init(adapter)) {
679198987Sjhb		if_printf(ifp, "Unable to initialize the hardware\n");
680129794Stackerman		return;
681129794Stackerman	}
682129794Stackerman	ixgb_enable_vlans(adapter);
683129794Stackerman
684129794Stackerman	/* Prepare transmit descriptors and buffers */
685129794Stackerman	if (ixgb_setup_transmit_structures(adapter)) {
686198987Sjhb		if_printf(ifp, "Could not setup transmit structures\n");
687129794Stackerman		ixgb_stop(adapter);
688129794Stackerman		return;
689129794Stackerman	}
690129794Stackerman	ixgb_initialize_transmit_unit(adapter);
691129794Stackerman
692129794Stackerman	/* Setup Multicast table */
693129794Stackerman	ixgb_set_multi(adapter);
694129794Stackerman
695129794Stackerman	/* Prepare receive descriptors and buffers */
696129794Stackerman	if (ixgb_setup_receive_structures(adapter)) {
697198987Sjhb		if_printf(ifp, "Could not setup receive structures\n");
698129794Stackerman		ixgb_stop(adapter);
699129794Stackerman		return;
700129794Stackerman	}
701129794Stackerman	ixgb_initialize_receive_unit(adapter);
702129794Stackerman
703160964Syar	/* Don't lose promiscuous settings */
704129794Stackerman	ixgb_set_promisc(adapter);
705129794Stackerman
706147256Sbrooks	ifp = adapter->ifp;
707148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
708148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
709129794Stackerman
710129794Stackerman
711129794Stackerman	if (ifp->if_capenable & IFCAP_TXCSUM)
712129794Stackerman		ifp->if_hwassist = IXGB_CHECKSUM_FEATURES;
713129794Stackerman	else
714129794Stackerman		ifp->if_hwassist = 0;
715129794Stackerman
716129794Stackerman
717129794Stackerman	/* Enable jumbo frames */
718129794Stackerman	if (ifp->if_mtu > ETHERMTU) {
719129794Stackerman		uint32_t        temp_reg;
720129794Stackerman		IXGB_WRITE_REG(&adapter->hw, MFS,
721129794Stackerman			       adapter->hw.max_frame_size << IXGB_MFS_SHIFT);
722129794Stackerman		temp_reg = IXGB_READ_REG(&adapter->hw, CTRL0);
723129794Stackerman		temp_reg |= IXGB_CTRL0_JFE;
724129794Stackerman		IXGB_WRITE_REG(&adapter->hw, CTRL0, temp_reg);
725129794Stackerman	}
726199539Sjhb	callout_reset(&adapter->timer, hz, ixgb_local_timer, adapter);
727129794Stackerman	ixgb_clear_hw_cntrs(&adapter->hw);
728129794Stackerman#ifdef DEVICE_POLLING
729129794Stackerman	/*
730129794Stackerman	 * Only disable interrupts if we are polling, make sure they are on
731129794Stackerman	 * otherwise.
732129794Stackerman	 */
733150789Sglebius	if (ifp->if_capenable & IFCAP_POLLING)
734129794Stackerman		ixgb_disable_intr(adapter);
735129794Stackerman	else
736150789Sglebius#endif
737129794Stackerman		ixgb_enable_intr(adapter);
738129794Stackerman
739129794Stackerman	return;
740129794Stackerman}
741129794Stackerman
742144651Salcstatic void
743144651Salcixgb_init(void *arg)
744144651Salc{
745144651Salc	struct adapter *adapter = arg;
746129794Stackerman
747144651Salc	IXGB_LOCK(adapter);
748144651Salc	ixgb_init_locked(adapter);
749144651Salc	IXGB_UNLOCK(adapter);
750144651Salc	return;
751144651Salc}
752144651Salc
753129794Stackerman#ifdef DEVICE_POLLING
754193096Sattiliostatic int
755144651Salcixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count)
756129794Stackerman{
757129794Stackerman	struct adapter *adapter = ifp->if_softc;
758129794Stackerman	u_int32_t       reg_icr;
759193096Sattilio	int		rx_npkts;
760129794Stackerman
761144651Salc	IXGB_LOCK_ASSERT(adapter);
762144651Salc
763129794Stackerman	if (cmd == POLL_AND_CHECK_STATUS) {
764129794Stackerman		reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
765129794Stackerman		if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
766129794Stackerman			ixgb_check_for_link(&adapter->hw);
767129794Stackerman			ixgb_print_link_status(adapter);
768129794Stackerman		}
769129794Stackerman	}
770193096Sattilio	rx_npkts = ixgb_process_receive_interrupts(adapter, count);
771150789Sglebius	ixgb_clean_transmit_interrupts(adapter);
772150789Sglebius
773150789Sglebius	if (ifp->if_snd.ifq_head != NULL)
774144651Salc		ixgb_start_locked(ifp);
775193096Sattilio	return (rx_npkts);
776129794Stackerman}
777144651Salc
778193096Sattiliostatic int
779144651Salcixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count)
780144651Salc{
781144651Salc	struct adapter *adapter = ifp->if_softc;
782193096Sattilio	int rx_npkts = 0;
783144651Salc
784144651Salc	IXGB_LOCK(adapter);
785150789Sglebius	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
786193096Sattilio		rx_npkts = ixgb_poll_locked(ifp, cmd, count);
787144651Salc	IXGB_UNLOCK(adapter);
788193096Sattilio	return (rx_npkts);
789144651Salc}
790150789Sglebius#endif /* DEVICE_POLLING */
791129794Stackerman
792129794Stackerman/*********************************************************************
793129794Stackerman *
794129794Stackerman *  Interrupt Service routine
795129794Stackerman *
796129794Stackerman **********************************************************************/
797129794Stackerman
798129794Stackermanstatic void
799129794Stackermanixgb_intr(void *arg)
800129794Stackerman{
801129794Stackerman	u_int32_t       loop_cnt = IXGB_MAX_INTR;
802129794Stackerman	u_int32_t       reg_icr;
803129794Stackerman	struct ifnet   *ifp;
804129794Stackerman	struct adapter *adapter = arg;
805129794Stackerman	boolean_t       rxdmt0 = FALSE;
806129794Stackerman
807144651Salc	IXGB_LOCK(adapter);
808144651Salc
809147256Sbrooks	ifp = adapter->ifp;
810129794Stackerman
811129794Stackerman#ifdef DEVICE_POLLING
812150789Sglebius	if (ifp->if_capenable & IFCAP_POLLING) {
813144651Salc		IXGB_UNLOCK(adapter);
814129794Stackerman		return;
815144651Salc	}
816150789Sglebius#endif
817129794Stackerman
818144651Salc	reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
819144651Salc	if (reg_icr == 0) {
820144651Salc		IXGB_UNLOCK(adapter);
821129794Stackerman		return;
822144651Salc	}
823129794Stackerman
824129794Stackerman	if (reg_icr & IXGB_INT_RXDMT0)
825129794Stackerman		rxdmt0 = TRUE;
826129794Stackerman
827129794Stackerman#ifdef _SV_
828129794Stackerman	if (reg_icr & IXGB_INT_RXDMT0)
829129794Stackerman		adapter->sv_stats.icr_rxdmt0++;
830129794Stackerman	if (reg_icr & IXGB_INT_RXO)
831129794Stackerman		adapter->sv_stats.icr_rxo++;
832129794Stackerman	if (reg_icr & IXGB_INT_RXT0)
833129794Stackerman		adapter->sv_stats.icr_rxt0++;
834129794Stackerman	if (reg_icr & IXGB_INT_TXDW)
835129794Stackerman		adapter->sv_stats.icr_TXDW++;
836129794Stackerman#endif				/* _SV_ */
837129794Stackerman
838129794Stackerman	/* Link status change */
839129794Stackerman	if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
840129794Stackerman		ixgb_check_for_link(&adapter->hw);
841129794Stackerman		ixgb_print_link_status(adapter);
842129794Stackerman	}
843129794Stackerman	while (loop_cnt > 0) {
844148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
845129794Stackerman			ixgb_process_receive_interrupts(adapter, -1);
846129794Stackerman			ixgb_clean_transmit_interrupts(adapter);
847129794Stackerman		}
848129794Stackerman		loop_cnt--;
849129794Stackerman	}
850129794Stackerman
851129794Stackerman	if (rxdmt0 && adapter->raidc) {
852129794Stackerman		IXGB_WRITE_REG(&adapter->hw, IMC, IXGB_INT_RXDMT0);
853129794Stackerman		IXGB_WRITE_REG(&adapter->hw, IMS, IXGB_INT_RXDMT0);
854129794Stackerman	}
855148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING && ifp->if_snd.ifq_head != NULL)
856144651Salc		ixgb_start_locked(ifp);
857129794Stackerman
858144651Salc	IXGB_UNLOCK(adapter);
859129794Stackerman	return;
860129794Stackerman}
861129794Stackerman
862129794Stackerman
863129794Stackerman/*********************************************************************
864129794Stackerman *
865129794Stackerman *  Media Ioctl callback
866129794Stackerman *
867129794Stackerman *  This routine is called whenever the user queries the status of
868129794Stackerman *  the interface using ifconfig.
869129794Stackerman *
870129794Stackerman **********************************************************************/
871129794Stackermanstatic void
872129794Stackermanixgb_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
873129794Stackerman{
874129794Stackerman	struct adapter *adapter = ifp->if_softc;
875129794Stackerman
876129794Stackerman	INIT_DEBUGOUT("ixgb_media_status: begin");
877129794Stackerman
878129794Stackerman	ixgb_check_for_link(&adapter->hw);
879129794Stackerman	ixgb_print_link_status(adapter);
880129794Stackerman
881129794Stackerman	ifmr->ifm_status = IFM_AVALID;
882129794Stackerman	ifmr->ifm_active = IFM_ETHER;
883129794Stackerman
884129794Stackerman	if (!adapter->hw.link_up)
885129794Stackerman		return;
886129794Stackerman
887129794Stackerman	ifmr->ifm_status |= IFM_ACTIVE;
888129794Stackerman	ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
889129794Stackerman
890129794Stackerman	return;
891129794Stackerman}
892129794Stackerman
893129794Stackerman/*********************************************************************
894129794Stackerman *
895129794Stackerman *  Media Ioctl callback
896129794Stackerman *
897129794Stackerman *  This routine is called when the user changes speed/duplex using
898129794Stackerman *  media/mediopt option with ifconfig.
899129794Stackerman *
900129794Stackerman **********************************************************************/
901129794Stackermanstatic int
902129794Stackermanixgb_media_change(struct ifnet * ifp)
903129794Stackerman{
904129794Stackerman	struct adapter *adapter = ifp->if_softc;
905129794Stackerman	struct ifmedia *ifm = &adapter->media;
906129794Stackerman
907129794Stackerman	INIT_DEBUGOUT("ixgb_media_change: begin");
908129794Stackerman
909129794Stackerman	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
910129794Stackerman		return (EINVAL);
911129794Stackerman
912129794Stackerman	return (0);
913129794Stackerman}
914129794Stackerman
915129794Stackerman/*********************************************************************
916129794Stackerman *
917129794Stackerman *  This routine maps the mbufs to tx descriptors.
918129794Stackerman *
919129794Stackerman *  return 0 on success, positive on failure
920129794Stackerman **********************************************************************/
921129794Stackerman
922129794Stackermanstatic int
923129794Stackermanixgb_encap(struct adapter * adapter, struct mbuf * m_head)
924129794Stackerman{
925129794Stackerman	u_int8_t        txd_popts;
926146339Salc	int             i, j, error, nsegs;
927129794Stackerman
928129794Stackerman#if __FreeBSD_version < 500000
929129794Stackerman	struct ifvlan  *ifv = NULL;
930129794Stackerman#endif
931146339Salc	bus_dma_segment_t segs[IXGB_MAX_SCATTER];
932146339Salc	bus_dmamap_t	map;
933129794Stackerman	struct ixgb_buffer *tx_buffer = NULL;
934129794Stackerman	struct ixgb_tx_desc *current_tx_desc = NULL;
935147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
936129794Stackerman
937129794Stackerman	/*
938129794Stackerman	 * Force a cleanup if number of TX descriptors available hits the
939129794Stackerman	 * threshold
940129794Stackerman	 */
941129794Stackerman	if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) {
942129794Stackerman		ixgb_clean_transmit_interrupts(adapter);
943129794Stackerman	}
944129794Stackerman	if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) {
945129794Stackerman		adapter->no_tx_desc_avail1++;
946129794Stackerman		return (ENOBUFS);
947129794Stackerman	}
948129794Stackerman	/*
949129794Stackerman	 * Map the packet for DMA.
950129794Stackerman	 */
951146339Salc	if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &map)) {
952129794Stackerman		adapter->no_tx_map_avail++;
953129794Stackerman		return (ENOMEM);
954129794Stackerman	}
955146339Salc	error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs,
956146339Salc					&nsegs, BUS_DMA_NOWAIT);
957129794Stackerman	if (error != 0) {
958129794Stackerman		adapter->no_tx_dma_setup++;
959198987Sjhb		if_printf(ifp, "ixgb_encap: bus_dmamap_load_mbuf failed; "
960198987Sjhb		       "error %u\n", error);
961146339Salc		bus_dmamap_destroy(adapter->txtag, map);
962129794Stackerman		return (error);
963129794Stackerman	}
964146339Salc	KASSERT(nsegs != 0, ("ixgb_encap: empty packet"));
965129794Stackerman
966146339Salc	if (nsegs > adapter->num_tx_desc_avail) {
967129794Stackerman		adapter->no_tx_desc_avail2++;
968146339Salc		bus_dmamap_destroy(adapter->txtag, map);
969129794Stackerman		return (ENOBUFS);
970129794Stackerman	}
971129794Stackerman	if (ifp->if_hwassist > 0) {
972129794Stackerman		ixgb_transmit_checksum_setup(adapter, m_head,
973129794Stackerman					     &txd_popts);
974129794Stackerman	} else
975129794Stackerman		txd_popts = 0;
976129794Stackerman
977129794Stackerman	/* Find out if we are in vlan mode */
978129794Stackerman#if __FreeBSD_version < 500000
979129794Stackerman	if ((m_head->m_flags & (M_PROTO1 | M_PKTHDR)) == (M_PROTO1 | M_PKTHDR) &&
980129794Stackerman	    m_head->m_pkthdr.rcvif != NULL &&
981129794Stackerman	    m_head->m_pkthdr.rcvif->if_type == IFT_L2VLAN)
982129794Stackerman		ifv = m_head->m_pkthdr.rcvif->if_softc;
983162375Sandre#elseif __FreeBSD_version < 700000
984129794Stackerman	mtag = VLAN_OUTPUT_TAG(ifp, m_head);
985129794Stackerman#endif
986129794Stackerman	i = adapter->next_avail_tx_desc;
987146339Salc	for (j = 0; j < nsegs; j++) {
988129794Stackerman		tx_buffer = &adapter->tx_buffer_area[i];
989129794Stackerman		current_tx_desc = &adapter->tx_desc_base[i];
990129794Stackerman
991146339Salc		current_tx_desc->buff_addr = htole64(segs[j].ds_addr);
992146339Salc		current_tx_desc->cmd_type_len = (adapter->txd_cmd | segs[j].ds_len);
993129794Stackerman		current_tx_desc->popts = txd_popts;
994129794Stackerman		if (++i == adapter->num_tx_desc)
995129794Stackerman			i = 0;
996129794Stackerman
997129794Stackerman		tx_buffer->m_head = NULL;
998129794Stackerman	}
999129794Stackerman
1000146339Salc	adapter->num_tx_desc_avail -= nsegs;
1001129794Stackerman	adapter->next_avail_tx_desc = i;
1002129794Stackerman
1003129794Stackerman#if __FreeBSD_version < 500000
1004129794Stackerman	if (ifv != NULL) {
1005129794Stackerman		/* Set the vlan id */
1006129794Stackerman		current_tx_desc->vlan = ifv->ifv_tag;
1007162375Sandre#elseif __FreeBSD_version < 700000
1008129794Stackerman	if (mtag != NULL) {
1009129794Stackerman		/* Set the vlan id */
1010129794Stackerman		current_tx_desc->vlan = VLAN_TAG_VALUE(mtag);
1011162375Sandre#else
1012162375Sandre	if (m_head->m_flags & M_VLANTAG) {
1013162375Sandre		current_tx_desc->vlan = m_head->m_pkthdr.ether_vtag;
1014129794Stackerman#endif
1015129794Stackerman
1016129794Stackerman		/* Tell hardware to add tag */
1017129794Stackerman		current_tx_desc->cmd_type_len |= IXGB_TX_DESC_CMD_VLE;
1018129794Stackerman	}
1019129794Stackerman	tx_buffer->m_head = m_head;
1020146339Salc	tx_buffer->map = map;
1021146339Salc	bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE);
1022129794Stackerman
1023129794Stackerman	/*
1024129794Stackerman	 * Last Descriptor of Packet needs End Of Packet (EOP)
1025129794Stackerman	 */
1026129794Stackerman	current_tx_desc->cmd_type_len |= (IXGB_TX_DESC_CMD_EOP);
1027129794Stackerman
1028129794Stackerman	/*
1029129794Stackerman	 * Advance the Transmit Descriptor Tail (Tdt), this tells the E1000
1030129794Stackerman	 * that this frame is available to transmit.
1031129794Stackerman	 */
1032129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDT, i);
1033129794Stackerman
1034129794Stackerman	return (0);
1035129794Stackerman}
1036129794Stackerman
1037129794Stackermanstatic void
1038129794Stackermanixgb_set_promisc(struct adapter * adapter)
1039129794Stackerman{
1040129794Stackerman
1041129794Stackerman	u_int32_t       reg_rctl;
1042147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
1043129794Stackerman
1044129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1045129794Stackerman
1046129794Stackerman	if (ifp->if_flags & IFF_PROMISC) {
1047129794Stackerman		reg_rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
1048129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1049129794Stackerman	} else if (ifp->if_flags & IFF_ALLMULTI) {
1050129794Stackerman		reg_rctl |= IXGB_RCTL_MPE;
1051129794Stackerman		reg_rctl &= ~IXGB_RCTL_UPE;
1052129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1053129794Stackerman	}
1054129794Stackerman	return;
1055129794Stackerman}
1056129794Stackerman
1057129794Stackermanstatic void
1058129794Stackermanixgb_disable_promisc(struct adapter * adapter)
1059129794Stackerman{
1060129794Stackerman	u_int32_t       reg_rctl;
1061129794Stackerman
1062129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1063129794Stackerman
1064129794Stackerman	reg_rctl &= (~IXGB_RCTL_UPE);
1065129794Stackerman	reg_rctl &= (~IXGB_RCTL_MPE);
1066129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1067129794Stackerman
1068129794Stackerman	return;
1069129794Stackerman}
1070129794Stackerman
1071129794Stackerman
1072129794Stackerman/*********************************************************************
1073129794Stackerman *  Multicast Update
1074129794Stackerman *
1075129794Stackerman *  This routine is called whenever multicast address list is updated.
1076129794Stackerman *
1077129794Stackerman **********************************************************************/
1078129794Stackerman
1079129794Stackermanstatic void
1080129794Stackermanixgb_set_multi(struct adapter * adapter)
1081129794Stackerman{
1082129794Stackerman	u_int32_t       reg_rctl = 0;
1083211913Syongari	u_int8_t        *mta;
1084129794Stackerman	struct ifmultiaddr *ifma;
1085129794Stackerman	int             mcnt = 0;
1086147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
1087129794Stackerman
1088129794Stackerman	IOCTL_DEBUGOUT("ixgb_set_multi: begin");
1089129794Stackerman
1090211913Syongari	mta = adapter->mta;
1091211913Syongari	bzero(mta, sizeof(u_int8_t) * IXGB_ETH_LENGTH_OF_ADDRESS *
1092211913Syongari	    MAX_NUM_MULTICAST_ADDRESSES);
1093211913Syongari
1094195049Srwatson	if_maddr_rlock(ifp);
1095129794Stackerman#if __FreeBSD_version < 500000
1096129794Stackerman	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1097129794Stackerman#else
1098129794Stackerman	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1099129794Stackerman#endif
1100129794Stackerman		if (ifma->ifma_addr->sa_family != AF_LINK)
1101129794Stackerman			continue;
1102129794Stackerman
1103129794Stackerman		bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
1104129794Stackerman		      &mta[mcnt * IXGB_ETH_LENGTH_OF_ADDRESS], IXGB_ETH_LENGTH_OF_ADDRESS);
1105129794Stackerman		mcnt++;
1106129794Stackerman	}
1107195049Srwatson	if_maddr_runlock(ifp);
1108129794Stackerman
1109129794Stackerman	if (mcnt > MAX_NUM_MULTICAST_ADDRESSES) {
1110129794Stackerman		reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1111129794Stackerman		reg_rctl |= IXGB_RCTL_MPE;
1112129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1113129794Stackerman	} else
1114129794Stackerman		ixgb_mc_addr_list_update(&adapter->hw, mta, mcnt, 0);
1115129794Stackerman
1116129794Stackerman	return;
1117129794Stackerman}
1118129794Stackerman
1119129794Stackerman
1120129794Stackerman/*********************************************************************
1121129794Stackerman *  Timer routine
1122129794Stackerman *
1123129794Stackerman *  This routine checks for link status and updates statistics.
1124129794Stackerman *
1125129794Stackerman **********************************************************************/
1126129794Stackerman
1127129794Stackermanstatic void
1128129794Stackermanixgb_local_timer(void *arg)
1129129794Stackerman{
1130129794Stackerman	struct ifnet   *ifp;
1131129794Stackerman	struct adapter *adapter = arg;
1132147256Sbrooks	ifp = adapter->ifp;
1133129794Stackerman
1134199539Sjhb	IXGB_LOCK_ASSERT(adapter);
1135129794Stackerman
1136129794Stackerman	ixgb_check_for_link(&adapter->hw);
1137129794Stackerman	ixgb_print_link_status(adapter);
1138129794Stackerman	ixgb_update_stats_counters(adapter);
1139148887Srwatson	if (ixgb_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) {
1140129794Stackerman		ixgb_print_hw_stats(adapter);
1141129794Stackerman	}
1142199539Sjhb	if (adapter->tx_timer != 0 && --adapter->tx_timer == 0)
1143199539Sjhb		ixgb_watchdog(adapter);
1144199539Sjhb	callout_reset(&adapter->timer, hz, ixgb_local_timer, adapter);
1145129794Stackerman}
1146129794Stackerman
1147129794Stackermanstatic void
1148129794Stackermanixgb_print_link_status(struct adapter * adapter)
1149129794Stackerman{
1150129794Stackerman	if (adapter->hw.link_up) {
1151129794Stackerman		if (!adapter->link_active) {
1152198987Sjhb			if_printf(adapter->ifp, "Link is up %d Mbps %s \n",
1153129794Stackerman			       10000,
1154129794Stackerman			       "Full Duplex");
1155129794Stackerman			adapter->link_active = 1;
1156129794Stackerman		}
1157129794Stackerman	} else {
1158129794Stackerman		if (adapter->link_active) {
1159198987Sjhb			if_printf(adapter->ifp, "Link is Down \n");
1160129794Stackerman			adapter->link_active = 0;
1161129794Stackerman		}
1162129794Stackerman	}
1163129794Stackerman
1164129794Stackerman	return;
1165129794Stackerman}
1166129794Stackerman
1167129794Stackerman
1168129794Stackerman
1169129794Stackerman/*********************************************************************
1170129794Stackerman *
1171129794Stackerman *  This routine disables all traffic on the adapter by issuing a
1172129794Stackerman *  global reset on the MAC and deallocates TX/RX buffers.
1173129794Stackerman *
1174129794Stackerman **********************************************************************/
1175129794Stackerman
1176129794Stackermanstatic void
1177129794Stackermanixgb_stop(void *arg)
1178129794Stackerman{
1179129794Stackerman	struct ifnet   *ifp;
1180129794Stackerman	struct adapter *adapter = arg;
1181147256Sbrooks	ifp = adapter->ifp;
1182129794Stackerman
1183144651Salc	IXGB_LOCK_ASSERT(adapter);
1184144651Salc
1185129794Stackerman	INIT_DEBUGOUT("ixgb_stop: begin\n");
1186129794Stackerman	ixgb_disable_intr(adapter);
1187129794Stackerman	adapter->hw.adapter_stopped = FALSE;
1188129794Stackerman	ixgb_adapter_stop(&adapter->hw);
1189144651Salc	callout_stop(&adapter->timer);
1190129794Stackerman	ixgb_free_transmit_structures(adapter);
1191129794Stackerman	ixgb_free_receive_structures(adapter);
1192129794Stackerman
1193129794Stackerman	/* Tell the stack that the interface is no longer active */
1194148887Srwatson	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1195199539Sjhb	adapter->tx_timer = 0;
1196129794Stackerman
1197129794Stackerman	return;
1198129794Stackerman}
1199129794Stackerman
1200129794Stackerman
1201129794Stackerman/*********************************************************************
1202129794Stackerman *
1203129794Stackerman *  Determine hardware revision.
1204129794Stackerman *
1205129794Stackerman **********************************************************************/
1206129794Stackermanstatic void
1207129794Stackermanixgb_identify_hardware(struct adapter * adapter)
1208129794Stackerman{
1209129794Stackerman	device_t        dev = adapter->dev;
1210129794Stackerman
1211129794Stackerman	/* Make sure our PCI config space has the necessary stuff set */
1212129794Stackerman	adapter->hw.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);
1213129794Stackerman	if (!((adapter->hw.pci_cmd_word & PCIM_CMD_BUSMASTEREN) &&
1214129794Stackerman	      (adapter->hw.pci_cmd_word & PCIM_CMD_MEMEN))) {
1215198987Sjhb		device_printf(dev,
1216198987Sjhb		    "Memory Access and/or Bus Master bits were not set!\n");
1217129794Stackerman		adapter->hw.pci_cmd_word |=
1218129794Stackerman			(PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
1219129794Stackerman		pci_write_config(dev, PCIR_COMMAND, adapter->hw.pci_cmd_word, 2);
1220129794Stackerman	}
1221129794Stackerman	/* Save off the information about this board */
1222129794Stackerman	adapter->hw.vendor_id = pci_get_vendor(dev);
1223129794Stackerman	adapter->hw.device_id = pci_get_device(dev);
1224129794Stackerman	adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1);
1225129794Stackerman	adapter->hw.subsystem_vendor_id = pci_read_config(dev, PCIR_SUBVEND_0, 2);
1226129794Stackerman	adapter->hw.subsystem_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
1227129794Stackerman
1228129794Stackerman	/* Set MacType, etc. based on this PCI info */
1229129794Stackerman	switch (adapter->hw.device_id) {
1230129794Stackerman	case IXGB_DEVICE_ID_82597EX:
1231129794Stackerman	case IXGB_DEVICE_ID_82597EX_SR:
1232129794Stackerman		adapter->hw.mac_type = ixgb_82597;
1233129794Stackerman		break;
1234129794Stackerman	default:
1235129794Stackerman		INIT_DEBUGOUT1("Unknown device if 0x%x", adapter->hw.device_id);
1236198987Sjhb		device_printf(dev, "unsupported device id 0x%x\n",
1237198987Sjhb		    adapter->hw.device_id);
1238129794Stackerman	}
1239129794Stackerman
1240129794Stackerman	return;
1241129794Stackerman}
1242129794Stackerman
1243129794Stackermanstatic int
1244129794Stackermanixgb_allocate_pci_resources(struct adapter * adapter)
1245129794Stackerman{
1246129794Stackerman	int             rid;
1247129794Stackerman	device_t        dev = adapter->dev;
1248129794Stackerman
1249129794Stackerman	rid = IXGB_MMBA;
1250129794Stackerman	adapter->res_memory = bus_alloc_resource(dev, SYS_RES_MEMORY,
1251129794Stackerman						 &rid, 0, ~0, 1,
1252129794Stackerman						 RF_ACTIVE);
1253129794Stackerman	if (!(adapter->res_memory)) {
1254198987Sjhb		device_printf(dev, "Unable to allocate bus resource: memory\n");
1255129794Stackerman		return (ENXIO);
1256129794Stackerman	}
1257129794Stackerman	adapter->osdep.mem_bus_space_tag =
1258129794Stackerman		rman_get_bustag(adapter->res_memory);
1259129794Stackerman	adapter->osdep.mem_bus_space_handle =
1260129794Stackerman		rman_get_bushandle(adapter->res_memory);
1261129794Stackerman	adapter->hw.hw_addr = (uint8_t *) & adapter->osdep.mem_bus_space_handle;
1262129794Stackerman
1263129794Stackerman	rid = 0x0;
1264129794Stackerman	adapter->res_interrupt = bus_alloc_resource(dev, SYS_RES_IRQ,
1265129794Stackerman						    &rid, 0, ~0, 1,
1266129794Stackerman						  RF_SHAREABLE | RF_ACTIVE);
1267129794Stackerman	if (!(adapter->res_interrupt)) {
1268198987Sjhb		device_printf(dev,
1269198987Sjhb		    "Unable to allocate bus resource: interrupt\n");
1270129794Stackerman		return (ENXIO);
1271129794Stackerman	}
1272144651Salc	if (bus_setup_intr(dev, adapter->res_interrupt,
1273144651Salc			   INTR_TYPE_NET | INTR_MPSAFE,
1274166901Spiso			   NULL, (void (*) (void *))ixgb_intr, adapter,
1275129794Stackerman			   &adapter->int_handler_tag)) {
1276198987Sjhb		device_printf(dev, "Error registering interrupt handler!\n");
1277129794Stackerman		return (ENXIO);
1278129794Stackerman	}
1279129794Stackerman	adapter->hw.back = &adapter->osdep;
1280129794Stackerman
1281129794Stackerman	return (0);
1282129794Stackerman}
1283129794Stackerman
1284129794Stackermanstatic void
1285129794Stackermanixgb_free_pci_resources(struct adapter * adapter)
1286129794Stackerman{
1287129794Stackerman	device_t        dev = adapter->dev;
1288129794Stackerman
1289129794Stackerman	if (adapter->res_interrupt != NULL) {
1290129794Stackerman		bus_teardown_intr(dev, adapter->res_interrupt,
1291129794Stackerman				  adapter->int_handler_tag);
1292129794Stackerman		bus_release_resource(dev, SYS_RES_IRQ, 0,
1293129794Stackerman				     adapter->res_interrupt);
1294129794Stackerman	}
1295129794Stackerman	if (adapter->res_memory != NULL) {
1296129794Stackerman		bus_release_resource(dev, SYS_RES_MEMORY, IXGB_MMBA,
1297129794Stackerman				     adapter->res_memory);
1298129794Stackerman	}
1299129794Stackerman	if (adapter->res_ioport != NULL) {
1300129794Stackerman		bus_release_resource(dev, SYS_RES_IOPORT, adapter->io_rid,
1301129794Stackerman				     adapter->res_ioport);
1302129794Stackerman	}
1303129794Stackerman	return;
1304129794Stackerman}
1305129794Stackerman
1306129794Stackerman/*********************************************************************
1307129794Stackerman *
1308129794Stackerman *  Initialize the hardware to a configuration as specified by the
1309129794Stackerman *  adapter structure. The controller is reset, the EEPROM is
1310129794Stackerman *  verified, the MAC address is set, then the shared initialization
1311129794Stackerman *  routines are called.
1312129794Stackerman *
1313129794Stackerman **********************************************************************/
1314129794Stackermanstatic int
1315129794Stackermanixgb_hardware_init(struct adapter * adapter)
1316129794Stackerman{
1317129794Stackerman	/* Issue a global reset */
1318129794Stackerman	adapter->hw.adapter_stopped = FALSE;
1319129794Stackerman	ixgb_adapter_stop(&adapter->hw);
1320129794Stackerman
1321129794Stackerman	/* Make sure we have a good EEPROM before we read from it */
1322129794Stackerman	if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
1323198987Sjhb		device_printf(adapter->dev,
1324198987Sjhb		    "The EEPROM Checksum Is Not Valid\n");
1325129794Stackerman		return (EIO);
1326129794Stackerman	}
1327129794Stackerman	if (!ixgb_init_hw(&adapter->hw)) {
1328198987Sjhb		device_printf(adapter->dev, "Hardware Initialization Failed");
1329129794Stackerman		return (EIO);
1330129794Stackerman	}
1331129794Stackerman
1332129794Stackerman	return (0);
1333129794Stackerman}
1334129794Stackerman
1335129794Stackerman/*********************************************************************
1336129794Stackerman *
1337129794Stackerman *  Setup networking device structure and register an interface.
1338129794Stackerman *
1339129794Stackerman **********************************************************************/
1340211907Syongaristatic int
1341129794Stackermanixgb_setup_interface(device_t dev, struct adapter * adapter)
1342129794Stackerman{
1343129794Stackerman	struct ifnet   *ifp;
1344129794Stackerman	INIT_DEBUGOUT("ixgb_setup_interface: begin");
1345129794Stackerman
1346147256Sbrooks	ifp = adapter->ifp = if_alloc(IFT_ETHER);
1347211907Syongari	if (ifp == NULL) {
1348211907Syongari		device_printf(dev, "can not allocate ifnet structure\n");
1349211907Syongari		return (-1);
1350211907Syongari	}
1351129794Stackerman#if __FreeBSD_version >= 502000
1352129794Stackerman	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1353129794Stackerman#else
1354198987Sjhb	ifp->if_unit = device_get_unit(dev);
1355129794Stackerman	ifp->if_name = "ixgb";
1356129794Stackerman#endif
1357129794Stackerman	ifp->if_mtu = ETHERMTU;
1358129794Stackerman	ifp->if_baudrate = 1000000000;
1359129794Stackerman	ifp->if_init = ixgb_init;
1360129794Stackerman	ifp->if_softc = adapter;
1361144651Salc	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1362129794Stackerman	ifp->if_ioctl = ixgb_ioctl;
1363129794Stackerman	ifp->if_start = ixgb_start;
1364129794Stackerman	ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 1;
1365129794Stackerman
1366129794Stackerman#if __FreeBSD_version < 500000
1367129794Stackerman	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
1368129794Stackerman#else
1369147256Sbrooks	ether_ifattach(ifp, adapter->hw.curr_mac_addr);
1370129794Stackerman#endif
1371129794Stackerman
1372129794Stackerman	ifp->if_capabilities = IFCAP_HWCSUM;
1373129794Stackerman
1374129794Stackerman	/*
1375129794Stackerman	 * Tell the upper layer(s) we support long frames.
1376129794Stackerman	 */
1377129794Stackerman	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
1378129794Stackerman
1379129794Stackerman#if __FreeBSD_version >= 500000
1380129794Stackerman	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
1381129794Stackerman#endif
1382148637Sbrueffer
1383148637Sbrueffer	ifp->if_capenable = ifp->if_capabilities;
1384148637Sbrueffer
1385150789Sglebius#ifdef DEVICE_POLLING
1386150789Sglebius	ifp->if_capabilities |= IFCAP_POLLING;
1387150789Sglebius#endif
1388150789Sglebius
1389129794Stackerman	/*
1390129794Stackerman	 * Specify the media types supported by this adapter and register
1391129794Stackerman	 * callbacks to update media and link information
1392129794Stackerman	 */
1393129794Stackerman	ifmedia_init(&adapter->media, IFM_IMASK, ixgb_media_change,
1394129794Stackerman		     ixgb_media_status);
1395129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX | IFM_FDX,
1396129794Stackerman		    0, NULL);
1397129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX,
1398129794Stackerman		    0, NULL);
1399129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
1400129794Stackerman	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
1401129794Stackerman
1402211907Syongari	return (0);
1403129794Stackerman}
1404129794Stackerman
1405129794Stackerman/********************************************************************
1406129794Stackerman * Manage DMA'able memory.
1407129794Stackerman *******************************************************************/
1408129794Stackermanstatic void
1409129794Stackermanixgb_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg, int error)
1410129794Stackerman{
1411129794Stackerman	if (error)
1412129794Stackerman		return;
1413129794Stackerman	*(bus_addr_t *) arg = segs->ds_addr;
1414129794Stackerman	return;
1415129794Stackerman}
1416129794Stackerman
1417129794Stackermanstatic int
1418129794Stackermanixgb_dma_malloc(struct adapter * adapter, bus_size_t size,
1419129794Stackerman		struct ixgb_dma_alloc * dma, int mapflags)
1420129794Stackerman{
1421198987Sjhb	device_t dev;
1422129794Stackerman	int             r;
1423129794Stackerman
1424198987Sjhb	dev = adapter->dev;
1425129794Stackerman	r = bus_dma_tag_create(NULL,	/* parent */
1426129794Stackerman			       PAGE_SIZE, 0,	/* alignment, bounds */
1427129794Stackerman			       BUS_SPACE_MAXADDR,	/* lowaddr */
1428129794Stackerman			       BUS_SPACE_MAXADDR,	/* highaddr */
1429129794Stackerman			       NULL, NULL,	/* filter, filterarg */
1430129794Stackerman			       size,	/* maxsize */
1431129794Stackerman			       1,	/* nsegments */
1432129794Stackerman			       size,	/* maxsegsize */
1433129794Stackerman			       BUS_DMA_ALLOCNOW,	/* flags */
1434129794Stackerman#if __FreeBSD_version >= 502000
1435129794Stackerman			       NULL,	/* lockfunc */
1436129794Stackerman			       NULL,	/* lockfuncarg */
1437129794Stackerman#endif
1438129794Stackerman			       &dma->dma_tag);
1439129794Stackerman	if (r != 0) {
1440198987Sjhb		device_printf(dev, "ixgb_dma_malloc: bus_dma_tag_create failed; "
1441198987Sjhb		       "error %u\n", r);
1442129794Stackerman		goto fail_0;
1443129794Stackerman	}
1444129794Stackerman	r = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr,
1445129794Stackerman			     BUS_DMA_NOWAIT, &dma->dma_map);
1446129794Stackerman	if (r != 0) {
1447198987Sjhb		device_printf(dev, "ixgb_dma_malloc: bus_dmamem_alloc failed; "
1448198987Sjhb		       "error %u\n", r);
1449144183Smux		goto fail_1;
1450129794Stackerman	}
1451129794Stackerman	r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
1452129794Stackerman			    size,
1453129794Stackerman			    ixgb_dmamap_cb,
1454129794Stackerman			    &dma->dma_paddr,
1455129794Stackerman			    mapflags | BUS_DMA_NOWAIT);
1456129794Stackerman	if (r != 0) {
1457198987Sjhb		device_printf(dev, "ixgb_dma_malloc: bus_dmamap_load failed; "
1458198987Sjhb		       "error %u\n", r);
1459144183Smux		goto fail_2;
1460129794Stackerman	}
1461129794Stackerman	dma->dma_size = size;
1462129794Stackerman	return (0);
1463129794Stackermanfail_2:
1464129794Stackerman	bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
1465129794Stackermanfail_1:
1466129794Stackerman	bus_dma_tag_destroy(dma->dma_tag);
1467129794Stackermanfail_0:
1468129794Stackerman	dma->dma_map = NULL;
1469129794Stackerman	dma->dma_tag = NULL;
1470129794Stackerman	return (r);
1471129794Stackerman}
1472129794Stackerman
1473129794Stackerman
1474129794Stackerman
1475129794Stackermanstatic void
1476129794Stackermanixgb_dma_free(struct adapter * adapter, struct ixgb_dma_alloc * dma)
1477129794Stackerman{
1478129794Stackerman	bus_dmamap_unload(dma->dma_tag, dma->dma_map);
1479129794Stackerman	bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
1480129794Stackerman	bus_dma_tag_destroy(dma->dma_tag);
1481129794Stackerman}
1482129794Stackerman
1483129794Stackerman/*********************************************************************
1484129794Stackerman *
1485129794Stackerman *  Allocate memory for tx_buffer structures. The tx_buffer stores all
1486129794Stackerman *  the information needed to transmit a packet on the wire.
1487129794Stackerman *
1488129794Stackerman **********************************************************************/
1489129794Stackermanstatic int
1490129794Stackermanixgb_allocate_transmit_structures(struct adapter * adapter)
1491129794Stackerman{
1492129794Stackerman	if (!(adapter->tx_buffer_area =
1493129794Stackerman	      (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) *
1494129794Stackerman					    adapter->num_tx_desc, M_DEVBUF,
1495129794Stackerman					    M_NOWAIT | M_ZERO))) {
1496198987Sjhb		device_printf(adapter->dev,
1497198987Sjhb		    "Unable to allocate tx_buffer memory\n");
1498129794Stackerman		return ENOMEM;
1499129794Stackerman	}
1500129794Stackerman	bzero(adapter->tx_buffer_area,
1501129794Stackerman	      sizeof(struct ixgb_buffer) * adapter->num_tx_desc);
1502129794Stackerman
1503129794Stackerman	return 0;
1504129794Stackerman}
1505129794Stackerman
1506129794Stackerman/*********************************************************************
1507129794Stackerman *
1508129794Stackerman *  Allocate and initialize transmit structures.
1509129794Stackerman *
1510129794Stackerman **********************************************************************/
1511129794Stackermanstatic int
1512129794Stackermanixgb_setup_transmit_structures(struct adapter * adapter)
1513129794Stackerman{
1514129794Stackerman	/*
1515129794Stackerman	 * Setup DMA descriptor areas.
1516129794Stackerman	 */
1517129794Stackerman	if (bus_dma_tag_create(NULL,	/* parent */
1518129794Stackerman			       PAGE_SIZE, 0,	/* alignment, bounds */
1519129794Stackerman			       BUS_SPACE_MAXADDR,	/* lowaddr */
1520129794Stackerman			       BUS_SPACE_MAXADDR,	/* highaddr */
1521129794Stackerman			       NULL, NULL,	/* filter, filterarg */
1522129794Stackerman			       MCLBYTES * IXGB_MAX_SCATTER,	/* maxsize */
1523129794Stackerman			       IXGB_MAX_SCATTER,	/* nsegments */
1524129794Stackerman			       MCLBYTES,	/* maxsegsize */
1525129794Stackerman			       BUS_DMA_ALLOCNOW,	/* flags */
1526129794Stackerman#if __FreeBSD_version >= 502000
1527129794Stackerman			       NULL,	/* lockfunc */
1528129794Stackerman			       NULL,	/* lockfuncarg */
1529129794Stackerman#endif
1530129794Stackerman			       &adapter->txtag)) {
1531198987Sjhb		device_printf(adapter->dev, "Unable to allocate TX DMA tag\n");
1532129794Stackerman		return (ENOMEM);
1533129794Stackerman	}
1534129794Stackerman	if (ixgb_allocate_transmit_structures(adapter))
1535129794Stackerman		return ENOMEM;
1536129794Stackerman
1537129794Stackerman	bzero((void *)adapter->tx_desc_base,
1538129794Stackerman	      (sizeof(struct ixgb_tx_desc)) * adapter->num_tx_desc);
1539129794Stackerman
1540129794Stackerman	adapter->next_avail_tx_desc = 0;
1541129794Stackerman	adapter->oldest_used_tx_desc = 0;
1542129794Stackerman
1543129794Stackerman	/* Set number of descriptors available */
1544129794Stackerman	adapter->num_tx_desc_avail = adapter->num_tx_desc;
1545129794Stackerman
1546129794Stackerman	/* Set checksum context */
1547129794Stackerman	adapter->active_checksum_context = OFFLOAD_NONE;
1548129794Stackerman
1549129794Stackerman	return 0;
1550129794Stackerman}
1551129794Stackerman
1552129794Stackerman/*********************************************************************
1553129794Stackerman *
1554129794Stackerman *  Enable transmit unit.
1555129794Stackerman *
1556129794Stackerman **********************************************************************/
1557129794Stackermanstatic void
1558129794Stackermanixgb_initialize_transmit_unit(struct adapter * adapter)
1559129794Stackerman{
1560129794Stackerman	u_int32_t       reg_tctl;
1561144183Smux	u_int64_t       tdba = adapter->txdma.dma_paddr;
1562129794Stackerman
1563129794Stackerman	/* Setup the Base and Length of the Tx Descriptor Ring */
1564129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDBAL,
1565129794Stackerman		       (tdba & 0x00000000ffffffffULL));
1566129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
1567129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDLEN,
1568129794Stackerman		       adapter->num_tx_desc *
1569129794Stackerman		       sizeof(struct ixgb_tx_desc));
1570129794Stackerman
1571129794Stackerman	/* Setup the HW Tx Head and Tail descriptor pointers */
1572129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDH, 0);
1573129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDT, 0);
1574129794Stackerman
1575129794Stackerman
1576129794Stackerman	HW_DEBUGOUT2("Base = %x, Length = %x\n",
1577129794Stackerman		     IXGB_READ_REG(&adapter->hw, TDBAL),
1578129794Stackerman		     IXGB_READ_REG(&adapter->hw, TDLEN));
1579129794Stackerman
1580129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay);
1581129794Stackerman
1582129794Stackerman
1583129794Stackerman	/* Program the Transmit Control Register */
1584129794Stackerman	reg_tctl = IXGB_READ_REG(&adapter->hw, TCTL);
1585129794Stackerman	reg_tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE;
1586129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TCTL, reg_tctl);
1587129794Stackerman
1588129794Stackerman	/* Setup Transmit Descriptor Settings for this adapter */
1589129794Stackerman	adapter->txd_cmd = IXGB_TX_DESC_TYPE | IXGB_TX_DESC_CMD_RS;
1590129794Stackerman
1591129794Stackerman	if (adapter->tx_int_delay > 0)
1592129794Stackerman		adapter->txd_cmd |= IXGB_TX_DESC_CMD_IDE;
1593129794Stackerman	return;
1594129794Stackerman}
1595129794Stackerman
1596129794Stackerman/*********************************************************************
1597129794Stackerman *
1598129794Stackerman *  Free all transmit related data structures.
1599129794Stackerman *
1600129794Stackerman **********************************************************************/
1601129794Stackermanstatic void
1602129794Stackermanixgb_free_transmit_structures(struct adapter * adapter)
1603129794Stackerman{
1604129794Stackerman	struct ixgb_buffer *tx_buffer;
1605129794Stackerman	int             i;
1606129794Stackerman
1607129794Stackerman	INIT_DEBUGOUT("free_transmit_structures: begin");
1608129794Stackerman
1609129794Stackerman	if (adapter->tx_buffer_area != NULL) {
1610129794Stackerman		tx_buffer = adapter->tx_buffer_area;
1611129794Stackerman		for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
1612129794Stackerman			if (tx_buffer->m_head != NULL) {
1613129794Stackerman				bus_dmamap_unload(adapter->txtag, tx_buffer->map);
1614129794Stackerman				bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
1615129794Stackerman				m_freem(tx_buffer->m_head);
1616129794Stackerman			}
1617129794Stackerman			tx_buffer->m_head = NULL;
1618129794Stackerman		}
1619129794Stackerman	}
1620129794Stackerman	if (adapter->tx_buffer_area != NULL) {
1621129794Stackerman		free(adapter->tx_buffer_area, M_DEVBUF);
1622129794Stackerman		adapter->tx_buffer_area = NULL;
1623129794Stackerman	}
1624129794Stackerman	if (adapter->txtag != NULL) {
1625129794Stackerman		bus_dma_tag_destroy(adapter->txtag);
1626129794Stackerman		adapter->txtag = NULL;
1627129794Stackerman	}
1628129794Stackerman	return;
1629129794Stackerman}
1630129794Stackerman
1631129794Stackerman/*********************************************************************
1632129794Stackerman *
1633129794Stackerman *  The offload context needs to be set when we transfer the first
1634129794Stackerman *  packet of a particular protocol (TCP/UDP). We change the
1635129794Stackerman *  context only if the protocol type changes.
1636129794Stackerman *
1637129794Stackerman **********************************************************************/
1638129794Stackermanstatic void
1639129794Stackermanixgb_transmit_checksum_setup(struct adapter * adapter,
1640129794Stackerman			     struct mbuf * mp,
1641129794Stackerman			     u_int8_t * txd_popts)
1642129794Stackerman{
1643129794Stackerman	struct ixgb_context_desc *TXD;
1644129794Stackerman	struct ixgb_buffer *tx_buffer;
1645129794Stackerman	int             curr_txd;
1646129794Stackerman
1647129794Stackerman	if (mp->m_pkthdr.csum_flags) {
1648129794Stackerman
1649129794Stackerman		if (mp->m_pkthdr.csum_flags & CSUM_TCP) {
1650129794Stackerman			*txd_popts = IXGB_TX_DESC_POPTS_TXSM;
1651129794Stackerman			if (adapter->active_checksum_context == OFFLOAD_TCP_IP)
1652129794Stackerman				return;
1653129794Stackerman			else
1654129794Stackerman				adapter->active_checksum_context = OFFLOAD_TCP_IP;
1655129794Stackerman		} else if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
1656129794Stackerman			*txd_popts = IXGB_TX_DESC_POPTS_TXSM;
1657129794Stackerman			if (adapter->active_checksum_context == OFFLOAD_UDP_IP)
1658129794Stackerman				return;
1659129794Stackerman			else
1660129794Stackerman				adapter->active_checksum_context = OFFLOAD_UDP_IP;
1661129794Stackerman		} else {
1662129794Stackerman			*txd_popts = 0;
1663129794Stackerman			return;
1664129794Stackerman		}
1665129794Stackerman	} else {
1666129794Stackerman		*txd_popts = 0;
1667129794Stackerman		return;
1668129794Stackerman	}
1669129794Stackerman
1670129794Stackerman	/*
1671129794Stackerman	 * If we reach this point, the checksum offload context needs to be
1672129794Stackerman	 * reset.
1673129794Stackerman	 */
1674129794Stackerman	curr_txd = adapter->next_avail_tx_desc;
1675129794Stackerman	tx_buffer = &adapter->tx_buffer_area[curr_txd];
1676129794Stackerman	TXD = (struct ixgb_context_desc *) & adapter->tx_desc_base[curr_txd];
1677129794Stackerman
1678129794Stackerman
1679129794Stackerman	TXD->tucss = ENET_HEADER_SIZE + sizeof(struct ip);
1680129794Stackerman	TXD->tucse = 0;
1681129794Stackerman
1682129794Stackerman	TXD->mss = 0;
1683129794Stackerman
1684129794Stackerman	if (adapter->active_checksum_context == OFFLOAD_TCP_IP) {
1685129794Stackerman		TXD->tucso =
1686129794Stackerman			ENET_HEADER_SIZE + sizeof(struct ip) +
1687129794Stackerman			offsetof(struct tcphdr, th_sum);
1688129794Stackerman	} else if (adapter->active_checksum_context == OFFLOAD_UDP_IP) {
1689129794Stackerman		TXD->tucso =
1690129794Stackerman			ENET_HEADER_SIZE + sizeof(struct ip) +
1691129794Stackerman			offsetof(struct udphdr, uh_sum);
1692129794Stackerman	}
1693129794Stackerman	TXD->cmd_type_len = IXGB_CONTEXT_DESC_CMD_TCP | IXGB_TX_DESC_CMD_RS | IXGB_CONTEXT_DESC_CMD_IDE;
1694129794Stackerman
1695129794Stackerman	tx_buffer->m_head = NULL;
1696129794Stackerman
1697129794Stackerman	if (++curr_txd == adapter->num_tx_desc)
1698129794Stackerman		curr_txd = 0;
1699129794Stackerman
1700129794Stackerman	adapter->num_tx_desc_avail--;
1701129794Stackerman	adapter->next_avail_tx_desc = curr_txd;
1702129794Stackerman	return;
1703129794Stackerman}
1704129794Stackerman
1705129794Stackerman/**********************************************************************
1706129794Stackerman *
1707129794Stackerman *  Examine each tx_buffer in the used queue. If the hardware is done
1708129794Stackerman *  processing the packet then free associated resources. The
1709129794Stackerman *  tx_buffer is put back on the free queue.
1710129794Stackerman *
1711129794Stackerman **********************************************************************/
1712129794Stackermanstatic void
1713129794Stackermanixgb_clean_transmit_interrupts(struct adapter * adapter)
1714129794Stackerman{
1715129794Stackerman	int             i, num_avail;
1716129794Stackerman	struct ixgb_buffer *tx_buffer;
1717129794Stackerman	struct ixgb_tx_desc *tx_desc;
1718129794Stackerman
1719144651Salc	IXGB_LOCK_ASSERT(adapter);
1720129794Stackerman
1721129794Stackerman	if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
1722129794Stackerman		return;
1723129794Stackerman
1724129794Stackerman#ifdef _SV_
1725129794Stackerman	adapter->clean_tx_interrupts++;
1726129794Stackerman#endif
1727129794Stackerman	num_avail = adapter->num_tx_desc_avail;
1728129794Stackerman	i = adapter->oldest_used_tx_desc;
1729129794Stackerman
1730129794Stackerman	tx_buffer = &adapter->tx_buffer_area[i];
1731129794Stackerman	tx_desc = &adapter->tx_desc_base[i];
1732129794Stackerman
1733129794Stackerman	while (tx_desc->status & IXGB_TX_DESC_STATUS_DD) {
1734129794Stackerman
1735129794Stackerman		tx_desc->status = 0;
1736129794Stackerman		num_avail++;
1737129794Stackerman
1738129794Stackerman		if (tx_buffer->m_head) {
1739129794Stackerman			bus_dmamap_sync(adapter->txtag, tx_buffer->map,
1740129794Stackerman					BUS_DMASYNC_POSTWRITE);
1741129794Stackerman			bus_dmamap_unload(adapter->txtag, tx_buffer->map);
1742129794Stackerman			bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
1743129794Stackerman			m_freem(tx_buffer->m_head);
1744129794Stackerman			tx_buffer->m_head = NULL;
1745129794Stackerman		}
1746129794Stackerman		if (++i == adapter->num_tx_desc)
1747129794Stackerman			i = 0;
1748129794Stackerman
1749129794Stackerman		tx_buffer = &adapter->tx_buffer_area[i];
1750129794Stackerman		tx_desc = &adapter->tx_desc_base[i];
1751129794Stackerman	}
1752129794Stackerman
1753129794Stackerman	adapter->oldest_used_tx_desc = i;
1754129794Stackerman
1755129794Stackerman	/*
1756148887Srwatson	 * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that
1757129794Stackerman	 * it is OK to send packets. If there are no pending descriptors,
1758129794Stackerman	 * clear the timeout. Otherwise, if some descriptors have been freed,
1759129794Stackerman	 * restart the timeout.
1760129794Stackerman	 */
1761129794Stackerman	if (num_avail > IXGB_TX_CLEANUP_THRESHOLD) {
1762147256Sbrooks		struct ifnet   *ifp = adapter->ifp;
1763129794Stackerman
1764148887Srwatson		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1765129794Stackerman		if (num_avail == adapter->num_tx_desc)
1766199539Sjhb			adapter->tx_timer = 0;
1767129794Stackerman		else if (num_avail == adapter->num_tx_desc_avail)
1768199539Sjhb			adapter->tx_timer = IXGB_TX_TIMEOUT;
1769129794Stackerman	}
1770129794Stackerman	adapter->num_tx_desc_avail = num_avail;
1771129794Stackerman	return;
1772129794Stackerman}
1773129794Stackerman
1774129794Stackerman
1775129794Stackerman/*********************************************************************
1776129794Stackerman *
1777129794Stackerman *  Get a buffer from system mbuf buffer pool.
1778129794Stackerman *
1779129794Stackerman **********************************************************************/
1780129794Stackermanstatic int
1781129794Stackermanixgb_get_buf(int i, struct adapter * adapter,
1782129794Stackerman	     struct mbuf * nmp)
1783129794Stackerman{
1784129794Stackerman	register struct mbuf *mp = nmp;
1785129794Stackerman	struct ixgb_buffer *rx_buffer;
1786129794Stackerman	struct ifnet   *ifp;
1787129794Stackerman	bus_addr_t      paddr;
1788129794Stackerman	int             error;
1789129794Stackerman
1790147256Sbrooks	ifp = adapter->ifp;
1791129794Stackerman
1792129794Stackerman	if (mp == NULL) {
1793129794Stackerman
1794129794Stackerman		mp = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1795129794Stackerman
1796129794Stackerman		if (mp == NULL) {
1797129794Stackerman			adapter->mbuf_alloc_failed++;
1798129794Stackerman			return (ENOBUFS);
1799129794Stackerman		}
1800129794Stackerman		mp->m_len = mp->m_pkthdr.len = MCLBYTES;
1801129794Stackerman	} else {
1802129794Stackerman		mp->m_len = mp->m_pkthdr.len = MCLBYTES;
1803129794Stackerman		mp->m_data = mp->m_ext.ext_buf;
1804129794Stackerman		mp->m_next = NULL;
1805129794Stackerman	}
1806129794Stackerman
1807129794Stackerman	if (ifp->if_mtu <= ETHERMTU) {
1808129794Stackerman		m_adj(mp, ETHER_ALIGN);
1809129794Stackerman	}
1810129794Stackerman	rx_buffer = &adapter->rx_buffer_area[i];
1811129794Stackerman
1812129794Stackerman	/*
1813129794Stackerman	 * Using memory from the mbuf cluster pool, invoke the bus_dma
1814129794Stackerman	 * machinery to arrange the memory mapping.
1815129794Stackerman	 */
1816129794Stackerman	error = bus_dmamap_load(adapter->rxtag, rx_buffer->map,
1817129794Stackerman				mtod(mp, void *), mp->m_len,
1818129794Stackerman				ixgb_dmamap_cb, &paddr, 0);
1819129794Stackerman	if (error) {
1820129794Stackerman		m_free(mp);
1821129794Stackerman		return (error);
1822129794Stackerman	}
1823129794Stackerman	rx_buffer->m_head = mp;
1824129794Stackerman	adapter->rx_desc_base[i].buff_addr = htole64(paddr);
1825129794Stackerman	bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD);
1826129794Stackerman
1827129794Stackerman	return (0);
1828129794Stackerman}
1829129794Stackerman
1830129794Stackerman/*********************************************************************
1831129794Stackerman *
1832129794Stackerman *  Allocate memory for rx_buffer structures. Since we use one
1833129794Stackerman *  rx_buffer per received packet, the maximum number of rx_buffer's
1834129794Stackerman *  that we'll need is equal to the number of receive descriptors
1835129794Stackerman *  that we've allocated.
1836129794Stackerman *
1837129794Stackerman **********************************************************************/
1838129794Stackermanstatic int
1839129794Stackermanixgb_allocate_receive_structures(struct adapter * adapter)
1840129794Stackerman{
1841129794Stackerman	int             i, error;
1842129794Stackerman	struct ixgb_buffer *rx_buffer;
1843129794Stackerman
1844129794Stackerman	if (!(adapter->rx_buffer_area =
1845129794Stackerman	      (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) *
1846129794Stackerman					    adapter->num_rx_desc, M_DEVBUF,
1847129794Stackerman					    M_NOWAIT | M_ZERO))) {
1848198987Sjhb		device_printf(adapter->dev,
1849198987Sjhb		    "Unable to allocate rx_buffer memory\n");
1850129794Stackerman		return (ENOMEM);
1851129794Stackerman	}
1852129794Stackerman	bzero(adapter->rx_buffer_area,
1853129794Stackerman	      sizeof(struct ixgb_buffer) * adapter->num_rx_desc);
1854129794Stackerman
1855129794Stackerman	error = bus_dma_tag_create(NULL,	/* parent */
1856129794Stackerman				   PAGE_SIZE, 0,	/* alignment, bounds */
1857129794Stackerman				   BUS_SPACE_MAXADDR,	/* lowaddr */
1858129794Stackerman				   BUS_SPACE_MAXADDR,	/* highaddr */
1859129794Stackerman				   NULL, NULL,	/* filter, filterarg */
1860129794Stackerman				   MCLBYTES,	/* maxsize */
1861129794Stackerman				   1,	/* nsegments */
1862129794Stackerman				   MCLBYTES,	/* maxsegsize */
1863129794Stackerman				   BUS_DMA_ALLOCNOW,	/* flags */
1864129794Stackerman#if __FreeBSD_version >= 502000
1865129794Stackerman				   NULL,	/* lockfunc */
1866129794Stackerman				   NULL,	/* lockfuncarg */
1867129794Stackerman#endif
1868129794Stackerman				   &adapter->rxtag);
1869129794Stackerman	if (error != 0) {
1870198987Sjhb		device_printf(adapter->dev, "ixgb_allocate_receive_structures: "
1871129794Stackerman		       "bus_dma_tag_create failed; error %u\n",
1872198987Sjhb		       error);
1873129794Stackerman		goto fail_0;
1874129794Stackerman	}
1875129794Stackerman	rx_buffer = adapter->rx_buffer_area;
1876129794Stackerman	for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
1877129794Stackerman		error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT,
1878129794Stackerman					  &rx_buffer->map);
1879129794Stackerman		if (error != 0) {
1880198987Sjhb			device_printf(adapter->dev,
1881198987Sjhb			       "ixgb_allocate_receive_structures: "
1882129794Stackerman			       "bus_dmamap_create failed; error %u\n",
1883198987Sjhb			       error);
1884129794Stackerman			goto fail_1;
1885129794Stackerman		}
1886129794Stackerman	}
1887129794Stackerman
1888129794Stackerman	for (i = 0; i < adapter->num_rx_desc; i++) {
1889129794Stackerman		if (ixgb_get_buf(i, adapter, NULL) == ENOBUFS) {
1890129794Stackerman			adapter->rx_buffer_area[i].m_head = NULL;
1891129794Stackerman			adapter->rx_desc_base[i].buff_addr = 0;
1892129794Stackerman			return (ENOBUFS);
1893129794Stackerman		}
1894129794Stackerman	}
1895129794Stackerman
1896129794Stackerman	return (0);
1897129794Stackermanfail_1:
1898129794Stackerman	bus_dma_tag_destroy(adapter->rxtag);
1899129794Stackermanfail_0:
1900129794Stackerman	adapter->rxtag = NULL;
1901129794Stackerman	free(adapter->rx_buffer_area, M_DEVBUF);
1902129794Stackerman	adapter->rx_buffer_area = NULL;
1903129794Stackerman	return (error);
1904129794Stackerman}
1905129794Stackerman
1906129794Stackerman/*********************************************************************
1907129794Stackerman *
1908129794Stackerman *  Allocate and initialize receive structures.
1909129794Stackerman *
1910129794Stackerman **********************************************************************/
1911129794Stackermanstatic int
1912129794Stackermanixgb_setup_receive_structures(struct adapter * adapter)
1913129794Stackerman{
1914129794Stackerman	bzero((void *)adapter->rx_desc_base,
1915129794Stackerman	      (sizeof(struct ixgb_rx_desc)) * adapter->num_rx_desc);
1916129794Stackerman
1917129794Stackerman	if (ixgb_allocate_receive_structures(adapter))
1918129794Stackerman		return ENOMEM;
1919129794Stackerman
1920129794Stackerman	/* Setup our descriptor pointers */
1921129794Stackerman	adapter->next_rx_desc_to_check = 0;
1922129794Stackerman	adapter->next_rx_desc_to_use = 0;
1923129794Stackerman	return (0);
1924129794Stackerman}
1925129794Stackerman
1926129794Stackerman/*********************************************************************
1927129794Stackerman *
1928129794Stackerman *  Enable receive unit.
1929129794Stackerman *
1930129794Stackerman **********************************************************************/
1931129794Stackermanstatic void
1932129794Stackermanixgb_initialize_receive_unit(struct adapter * adapter)
1933129794Stackerman{
1934129794Stackerman	u_int32_t       reg_rctl;
1935129794Stackerman	u_int32_t       reg_rxcsum;
1936129794Stackerman	u_int32_t       reg_rxdctl;
1937129794Stackerman	struct ifnet   *ifp;
1938144183Smux	u_int64_t       rdba = adapter->rxdma.dma_paddr;
1939129794Stackerman
1940147256Sbrooks	ifp = adapter->ifp;
1941129794Stackerman
1942129794Stackerman	/*
1943129794Stackerman	 * Make sure receives are disabled while setting up the descriptor
1944129794Stackerman	 * ring
1945129794Stackerman	 */
1946129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1947129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl & ~IXGB_RCTL_RXEN);
1948129794Stackerman
1949129794Stackerman	/* Set the Receive Delay Timer Register */
1950129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDTR,
1951129794Stackerman		       adapter->rx_int_delay);
1952129794Stackerman
1953129794Stackerman
1954129794Stackerman	/* Setup the Base and Length of the Rx Descriptor Ring */
1955129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDBAL,
1956129794Stackerman		       (rdba & 0x00000000ffffffffULL));
1957129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
1958129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDLEN, adapter->num_rx_desc *
1959129794Stackerman		       sizeof(struct ixgb_rx_desc));
1960129794Stackerman
1961129794Stackerman	/* Setup the HW Rx Head and Tail Descriptor Pointers */
1962129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDH, 0);
1963129794Stackerman
1964129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDT, adapter->num_rx_desc - 1);
1965129794Stackerman
1966129794Stackerman
1967129794Stackerman
1968129794Stackerman	reg_rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
1969129794Stackerman		| RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
1970129794Stackerman		| RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
1971129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RXDCTL, reg_rxdctl);
1972129794Stackerman
1973129794Stackerman
1974129794Stackerman	adapter->raidc = 1;
1975129794Stackerman	if (adapter->raidc) {
1976129794Stackerman		uint32_t        raidc;
1977129794Stackerman		uint8_t         poll_threshold;
1978129794Stackerman#define IXGB_RAIDC_POLL_DEFAULT 120
1979129794Stackerman
1980129794Stackerman		poll_threshold = ((adapter->num_rx_desc - 1) >> 3);
1981129794Stackerman		poll_threshold >>= 1;
1982129794Stackerman		poll_threshold &= 0x3F;
1983129794Stackerman		raidc = IXGB_RAIDC_EN | IXGB_RAIDC_RXT_GATE |
1984129794Stackerman			(IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) |
1985129794Stackerman			(adapter->rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) |
1986129794Stackerman			poll_threshold;
1987129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RAIDC, raidc);
1988129794Stackerman	}
1989129794Stackerman	/* Enable Receive Checksum Offload for TCP and UDP ? */
1990129794Stackerman	if (ifp->if_capenable & IFCAP_RXCSUM) {
1991129794Stackerman		reg_rxcsum = IXGB_READ_REG(&adapter->hw, RXCSUM);
1992129794Stackerman		reg_rxcsum |= IXGB_RXCSUM_TUOFL;
1993129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RXCSUM, reg_rxcsum);
1994129794Stackerman	}
1995129794Stackerman	/* Setup the Receive Control Register */
1996129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1997129794Stackerman	reg_rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
1998129794Stackerman	reg_rctl |= IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 | IXGB_RCTL_SECRC |
1999129794Stackerman		IXGB_RCTL_CFF |
2000129794Stackerman		(adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
2001129794Stackerman
2002129794Stackerman	switch (adapter->rx_buffer_len) {
2003129794Stackerman	default:
2004129794Stackerman	case IXGB_RXBUFFER_2048:
2005129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_2048;
2006129794Stackerman		break;
2007129794Stackerman	case IXGB_RXBUFFER_4096:
2008129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_4096;
2009129794Stackerman		break;
2010129794Stackerman	case IXGB_RXBUFFER_8192:
2011129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_8192;
2012129794Stackerman		break;
2013129794Stackerman	case IXGB_RXBUFFER_16384:
2014129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_16384;
2015129794Stackerman		break;
2016129794Stackerman	}
2017129794Stackerman
2018129794Stackerman	reg_rctl |= IXGB_RCTL_RXEN;
2019129794Stackerman
2020129794Stackerman
2021129794Stackerman	/* Enable Receives */
2022129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
2023129794Stackerman
2024129794Stackerman	return;
2025129794Stackerman}
2026129794Stackerman
2027129794Stackerman/*********************************************************************
2028129794Stackerman *
2029129794Stackerman *  Free receive related data structures.
2030129794Stackerman *
2031129794Stackerman **********************************************************************/
2032129794Stackermanstatic void
2033129794Stackermanixgb_free_receive_structures(struct adapter * adapter)
2034129794Stackerman{
2035129794Stackerman	struct ixgb_buffer *rx_buffer;
2036129794Stackerman	int             i;
2037129794Stackerman
2038129794Stackerman	INIT_DEBUGOUT("free_receive_structures: begin");
2039129794Stackerman
2040129794Stackerman	if (adapter->rx_buffer_area != NULL) {
2041129794Stackerman		rx_buffer = adapter->rx_buffer_area;
2042129794Stackerman		for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
2043129794Stackerman			if (rx_buffer->map != NULL) {
2044129794Stackerman				bus_dmamap_unload(adapter->rxtag, rx_buffer->map);
2045129794Stackerman				bus_dmamap_destroy(adapter->rxtag, rx_buffer->map);
2046129794Stackerman			}
2047129794Stackerman			if (rx_buffer->m_head != NULL)
2048129794Stackerman				m_freem(rx_buffer->m_head);
2049129794Stackerman			rx_buffer->m_head = NULL;
2050129794Stackerman		}
2051129794Stackerman	}
2052129794Stackerman	if (adapter->rx_buffer_area != NULL) {
2053129794Stackerman		free(adapter->rx_buffer_area, M_DEVBUF);
2054129794Stackerman		adapter->rx_buffer_area = NULL;
2055129794Stackerman	}
2056129794Stackerman	if (adapter->rxtag != NULL) {
2057129794Stackerman		bus_dma_tag_destroy(adapter->rxtag);
2058129794Stackerman		adapter->rxtag = NULL;
2059129794Stackerman	}
2060129794Stackerman	return;
2061129794Stackerman}
2062129794Stackerman
2063129794Stackerman/*********************************************************************
2064129794Stackerman *
2065129794Stackerman *  This routine executes in interrupt context. It replenishes
2066129794Stackerman *  the mbufs in the descriptor and sends data which has been
2067129794Stackerman *  dma'ed into host memory to upper layer.
2068129794Stackerman *
2069129794Stackerman *  We loop at most count times if count is > 0, or until done if
2070129794Stackerman *  count < 0.
2071129794Stackerman *
2072129794Stackerman *********************************************************************/
2073193096Sattiliostatic int
2074129794Stackermanixgb_process_receive_interrupts(struct adapter * adapter, int count)
2075129794Stackerman{
2076129794Stackerman	struct ifnet   *ifp;
2077129794Stackerman	struct mbuf    *mp;
2078129794Stackerman#if __FreeBSD_version < 500000
2079129794Stackerman	struct ether_header *eh;
2080129794Stackerman#endif
2081129794Stackerman	int             eop = 0;
2082129794Stackerman	int             len;
2083129794Stackerman	u_int8_t        accept_frame = 0;
2084129794Stackerman	int             i;
2085129794Stackerman	int             next_to_use = 0;
2086129794Stackerman	int             eop_desc;
2087193096Sattilio	int		rx_npkts = 0;
2088129794Stackerman	/* Pointer to the receive descriptor being examined. */
2089129794Stackerman	struct ixgb_rx_desc *current_desc;
2090129794Stackerman
2091144651Salc	IXGB_LOCK_ASSERT(adapter);
2092144651Salc
2093147256Sbrooks	ifp = adapter->ifp;
2094129794Stackerman	i = adapter->next_rx_desc_to_check;
2095129794Stackerman	next_to_use = adapter->next_rx_desc_to_use;
2096129794Stackerman	eop_desc = adapter->next_rx_desc_to_check;
2097129794Stackerman	current_desc = &adapter->rx_desc_base[i];
2098129794Stackerman
2099129794Stackerman	if (!((current_desc->status) & IXGB_RX_DESC_STATUS_DD)) {
2100129794Stackerman#ifdef _SV_
2101129794Stackerman		adapter->no_pkts_avail++;
2102129794Stackerman#endif
2103193096Sattilio		return (rx_npkts);
2104129794Stackerman	}
2105129794Stackerman	while ((current_desc->status & IXGB_RX_DESC_STATUS_DD) && (count != 0)) {
2106129794Stackerman
2107129794Stackerman		mp = adapter->rx_buffer_area[i].m_head;
2108129794Stackerman		bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map,
2109129794Stackerman				BUS_DMASYNC_POSTREAD);
2110129794Stackerman		accept_frame = 1;
2111129794Stackerman		if (current_desc->status & IXGB_RX_DESC_STATUS_EOP) {
2112129794Stackerman			count--;
2113129794Stackerman			eop = 1;
2114129794Stackerman		} else {
2115129794Stackerman			eop = 0;
2116129794Stackerman		}
2117129794Stackerman		len = current_desc->length;
2118129794Stackerman
2119129794Stackerman		if (current_desc->errors & (IXGB_RX_DESC_ERRORS_CE |
2120129794Stackerman			    IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P |
2121129794Stackerman					    IXGB_RX_DESC_ERRORS_RXE)) {
2122129794Stackerman			accept_frame = 0;
2123129794Stackerman		}
2124129794Stackerman		if (accept_frame) {
2125129794Stackerman
2126129794Stackerman			/* Assign correct length to the current fragment */
2127129794Stackerman			mp->m_len = len;
2128129794Stackerman
2129129794Stackerman			if (adapter->fmp == NULL) {
2130129794Stackerman				mp->m_pkthdr.len = len;
2131129794Stackerman				adapter->fmp = mp;	/* Store the first mbuf */
2132129794Stackerman				adapter->lmp = mp;
2133129794Stackerman			} else {
2134129794Stackerman				/* Chain mbuf's together */
2135129794Stackerman				mp->m_flags &= ~M_PKTHDR;
2136129794Stackerman				adapter->lmp->m_next = mp;
2137129794Stackerman				adapter->lmp = adapter->lmp->m_next;
2138129794Stackerman				adapter->fmp->m_pkthdr.len += len;
2139129794Stackerman			}
2140129794Stackerman
2141129794Stackerman			if (eop) {
2142129794Stackerman				eop_desc = i;
2143129794Stackerman				adapter->fmp->m_pkthdr.rcvif = ifp;
2144129794Stackerman
2145129794Stackerman#if __FreeBSD_version < 500000
2146129794Stackerman				eh = mtod(adapter->fmp, struct ether_header *);
2147129794Stackerman
2148129794Stackerman				/* Remove ethernet header from mbuf */
2149129794Stackerman				m_adj(adapter->fmp, sizeof(struct ether_header));
2150129794Stackerman				ixgb_receive_checksum(adapter, current_desc,
2151129794Stackerman						      adapter->fmp);
2152129794Stackerman
2153129794Stackerman				if (current_desc->status & IXGB_RX_DESC_STATUS_VP)
2154129794Stackerman					VLAN_INPUT_TAG(eh, adapter->fmp,
2155129794Stackerman						     current_desc->special);
2156129794Stackerman				else
2157129794Stackerman					ether_input(ifp, eh, adapter->fmp);
2158129794Stackerman#else
2159129794Stackerman				ixgb_receive_checksum(adapter, current_desc,
2160129794Stackerman						      adapter->fmp);
2161162375Sandre#if __FreeBSD_version < 700000
2162129794Stackerman				if (current_desc->status & IXGB_RX_DESC_STATUS_VP)
2163129794Stackerman					VLAN_INPUT_TAG(ifp, adapter->fmp,
2164153512Sglebius						       current_desc->special);
2165162375Sandre#else
2166162375Sandre				if (current_desc->status & IXGB_RX_DESC_STATUS_VP) {
2167162375Sandre					adapter->fmp->m_pkthdr.ether_vtag =
2168162375Sandre					    current_desc->special;
2169162375Sandre					adapter->fmp->m_flags |= M_VLANTAG;
2170162375Sandre				}
2171162375Sandre#endif
2172129794Stackerman
2173144651Salc				if (adapter->fmp != NULL) {
2174144651Salc					IXGB_UNLOCK(adapter);
2175129794Stackerman					(*ifp->if_input) (ifp, adapter->fmp);
2176144651Salc					IXGB_LOCK(adapter);
2177193096Sattilio					rx_npkts++;
2178144651Salc				}
2179129794Stackerman#endif
2180129794Stackerman				adapter->fmp = NULL;
2181129794Stackerman				adapter->lmp = NULL;
2182129794Stackerman			}
2183129794Stackerman			adapter->rx_buffer_area[i].m_head = NULL;
2184129794Stackerman		} else {
2185129794Stackerman			adapter->dropped_pkts++;
2186129794Stackerman			if (adapter->fmp != NULL)
2187129794Stackerman				m_freem(adapter->fmp);
2188129794Stackerman			adapter->fmp = NULL;
2189129794Stackerman			adapter->lmp = NULL;
2190129794Stackerman		}
2191129794Stackerman
2192129794Stackerman		/* Zero out the receive descriptors status  */
2193129794Stackerman		current_desc->status = 0;
2194129794Stackerman
2195129794Stackerman		/* Advance our pointers to the next descriptor */
2196129794Stackerman		if (++i == adapter->num_rx_desc) {
2197129794Stackerman			i = 0;
2198129794Stackerman			current_desc = adapter->rx_desc_base;
2199129794Stackerman		} else
2200129794Stackerman			current_desc++;
2201129794Stackerman	}
2202129794Stackerman	adapter->next_rx_desc_to_check = i;
2203129794Stackerman
2204129794Stackerman	if (--i < 0)
2205129794Stackerman		i = (adapter->num_rx_desc - 1);
2206129794Stackerman
2207129794Stackerman	/*
2208129794Stackerman	 * 82597EX: Workaround for redundent write back in receive descriptor ring (causes
2209129794Stackerman 	 * memory corruption). Avoid using and re-submitting the most recently received RX
2210129794Stackerman	 * descriptor back to hardware.
2211129794Stackerman	 *
2212129794Stackerman	 * if(Last written back descriptor == EOP bit set descriptor)
2213129794Stackerman	 * 	then avoid re-submitting the most recently received RX descriptor
2214129794Stackerman	 *	back to hardware.
2215129794Stackerman	 * if(Last written back descriptor != EOP bit set descriptor)
2216129794Stackerman	 *	then avoid re-submitting the most recently received RX descriptors
2217129794Stackerman	 * 	till last EOP bit set descriptor.
2218129794Stackerman	 */
2219129794Stackerman	if (eop_desc != i) {
2220129794Stackerman		if (++eop_desc == adapter->num_rx_desc)
2221129794Stackerman			eop_desc = 0;
2222129794Stackerman		i = eop_desc;
2223129794Stackerman	}
2224129794Stackerman	/* Replenish the descriptors with new mbufs till last EOP bit set descriptor */
2225129794Stackerman	while (next_to_use != i) {
2226129794Stackerman		current_desc = &adapter->rx_desc_base[next_to_use];
2227129794Stackerman		if ((current_desc->errors & (IXGB_RX_DESC_ERRORS_CE |
2228129794Stackerman			    IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P |
2229129794Stackerman					     IXGB_RX_DESC_ERRORS_RXE))) {
2230129794Stackerman			mp = adapter->rx_buffer_area[next_to_use].m_head;
2231129794Stackerman			ixgb_get_buf(next_to_use, adapter, mp);
2232129794Stackerman		} else {
2233129794Stackerman			if (ixgb_get_buf(next_to_use, adapter, NULL) == ENOBUFS)
2234129794Stackerman				break;
2235129794Stackerman		}
2236129794Stackerman		/* Advance our pointers to the next descriptor */
2237129794Stackerman		if (++next_to_use == adapter->num_rx_desc) {
2238129794Stackerman			next_to_use = 0;
2239129794Stackerman			current_desc = adapter->rx_desc_base;
2240129794Stackerman		} else
2241129794Stackerman			current_desc++;
2242129794Stackerman	}
2243129794Stackerman	adapter->next_rx_desc_to_use = next_to_use;
2244129794Stackerman	if (--next_to_use < 0)
2245129794Stackerman		next_to_use = (adapter->num_rx_desc - 1);
2246129794Stackerman	/* Advance the IXGB's Receive Queue #0  "Tail Pointer" */
2247129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDT, next_to_use);
2248129794Stackerman
2249193096Sattilio	return (rx_npkts);
2250129794Stackerman}
2251129794Stackerman
2252129794Stackerman/*********************************************************************
2253129794Stackerman *
2254129794Stackerman *  Verify that the hardware indicated that the checksum is valid.
2255129794Stackerman *  Inform the stack about the status of checksum so that stack
2256129794Stackerman *  doesn't spend time verifying the checksum.
2257129794Stackerman *
2258129794Stackerman *********************************************************************/
2259129794Stackermanstatic void
2260129794Stackermanixgb_receive_checksum(struct adapter * adapter,
2261129794Stackerman		      struct ixgb_rx_desc * rx_desc,
2262129794Stackerman		      struct mbuf * mp)
2263129794Stackerman{
2264129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) {
2265129794Stackerman		mp->m_pkthdr.csum_flags = 0;
2266129794Stackerman		return;
2267129794Stackerman	}
2268129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_IPCS) {
2269129794Stackerman		/* Did it pass? */
2270129794Stackerman		if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_IPE)) {
2271129794Stackerman			/* IP Checksum Good */
2272129794Stackerman			mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
2273129794Stackerman			mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
2274129794Stackerman
2275129794Stackerman		} else {
2276129794Stackerman			mp->m_pkthdr.csum_flags = 0;
2277129794Stackerman		}
2278129794Stackerman	}
2279129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS) {
2280129794Stackerman		/* Did it pass? */
2281129794Stackerman		if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE)) {
2282129794Stackerman			mp->m_pkthdr.csum_flags |=
2283129794Stackerman				(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
2284129794Stackerman			mp->m_pkthdr.csum_data = htons(0xffff);
2285129794Stackerman		}
2286129794Stackerman	}
2287129794Stackerman	return;
2288129794Stackerman}
2289129794Stackerman
2290129794Stackerman
2291129794Stackermanstatic void
2292129794Stackermanixgb_enable_vlans(struct adapter * adapter)
2293129794Stackerman{
2294129794Stackerman	uint32_t        ctrl;
2295129794Stackerman
2296129794Stackerman	ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
2297129794Stackerman	ctrl |= IXGB_CTRL0_VME;
2298129794Stackerman	IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
2299129794Stackerman
2300129794Stackerman	return;
2301129794Stackerman}
2302129794Stackerman
2303129794Stackerman
2304129794Stackermanstatic void
2305129794Stackermanixgb_enable_intr(struct adapter * adapter)
2306129794Stackerman{
2307129794Stackerman	IXGB_WRITE_REG(&adapter->hw, IMS, (IXGB_INT_RXT0 | IXGB_INT_TXDW |
2308129794Stackerman			    IXGB_INT_RXDMT0 | IXGB_INT_LSC | IXGB_INT_RXO));
2309129794Stackerman	return;
2310129794Stackerman}
2311129794Stackerman
2312129794Stackermanstatic void
2313129794Stackermanixgb_disable_intr(struct adapter * adapter)
2314129794Stackerman{
2315129794Stackerman	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
2316129794Stackerman	return;
2317129794Stackerman}
2318129794Stackerman
2319129794Stackermanvoid
2320129794Stackermanixgb_write_pci_cfg(struct ixgb_hw * hw,
2321129794Stackerman		   uint32_t reg,
2322129794Stackerman		   uint16_t * value)
2323129794Stackerman{
2324129794Stackerman	pci_write_config(((struct ixgb_osdep *) hw->back)->dev, reg,
2325129794Stackerman			 *value, 2);
2326129794Stackerman}
2327129794Stackerman
2328129794Stackerman/**********************************************************************
2329129794Stackerman *
2330129794Stackerman *  Update the board statistics counters.
2331129794Stackerman *
2332129794Stackerman **********************************************************************/
2333129794Stackermanstatic void
2334129794Stackermanixgb_update_stats_counters(struct adapter * adapter)
2335129794Stackerman{
2336129794Stackerman	struct ifnet   *ifp;
2337129794Stackerman
2338129794Stackerman	adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS);
2339129794Stackerman	adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);
2340129794Stackerman	adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);
2341129794Stackerman	adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL);
2342129794Stackerman	adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH);
2343129794Stackerman	adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
2344129794Stackerman	adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
2345129794Stackerman	adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
2346129794Stackerman	adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
2347129794Stackerman	adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC);
2348129794Stackerman
2349129794Stackerman	adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC);
2350129794Stackerman	adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC);
2351129794Stackerman	adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC);
2352129794Stackerman	adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC);
2353129794Stackerman	adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC);
2354129794Stackerman	adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC);
2355129794Stackerman	adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC);
2356129794Stackerman	adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL);
2357129794Stackerman	adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH);
2358129794Stackerman	adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL);
2359129794Stackerman	adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH);
2360129794Stackerman	adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC);
2361129794Stackerman	adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC);
2362129794Stackerman	adapter->stats.rjc += IXGB_READ_REG(&adapter->hw, RJC);
2363129794Stackerman	adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL);
2364129794Stackerman	adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH);
2365129794Stackerman	adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL);
2366129794Stackerman	adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH);
2367129794Stackerman	adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
2368129794Stackerman	adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
2369129794Stackerman	adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL);
2370129794Stackerman	adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH);
2371129794Stackerman	adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C);
2372129794Stackerman	adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL);
2373129794Stackerman	adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH);
2374129794Stackerman	adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL);
2375129794Stackerman	adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH);
2376129794Stackerman
2377129794Stackerman	adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);
2378129794Stackerman	adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);
2379129794Stackerman	adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);
2380129794Stackerman	adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH);
2381129794Stackerman	adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL);
2382129794Stackerman	adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH);
2383129794Stackerman	adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC);
2384129794Stackerman	adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC);
2385129794Stackerman	adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC);
2386129794Stackerman	adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL);
2387129794Stackerman	adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH);
2388129794Stackerman	adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL);
2389129794Stackerman	adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH);
2390129794Stackerman	adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL);
2391129794Stackerman	adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH);
2392129794Stackerman	adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC);
2393129794Stackerman	adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC);
2394129794Stackerman	adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC);
2395129794Stackerman	adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC);
2396129794Stackerman	adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC);
2397129794Stackerman	adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC);
2398129794Stackerman	adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC);
2399129794Stackerman
2400147256Sbrooks	ifp = adapter->ifp;
2401129794Stackerman
2402129794Stackerman	/* Fill out the OS statistics structure */
2403129794Stackerman	ifp->if_ipackets = adapter->stats.gprcl;
2404129794Stackerman	ifp->if_opackets = adapter->stats.gptcl;
2405129794Stackerman	ifp->if_ibytes = adapter->stats.gorcl;
2406129794Stackerman	ifp->if_obytes = adapter->stats.gotcl;
2407129794Stackerman	ifp->if_imcasts = adapter->stats.mprcl;
2408129794Stackerman	ifp->if_collisions = 0;
2409129794Stackerman
2410129794Stackerman	/* Rx Errors */
2411129794Stackerman	ifp->if_ierrors =
2412129794Stackerman		adapter->dropped_pkts +
2413129794Stackerman		adapter->stats.crcerrs +
2414129794Stackerman		adapter->stats.rnbc +
2415129794Stackerman		adapter->stats.mpc +
2416129794Stackerman		adapter->stats.rlec;
2417129794Stackerman
2418129794Stackerman
2419129794Stackerman}
2420129794Stackerman
2421129794Stackerman
2422129794Stackerman/**********************************************************************
2423129794Stackerman *
2424129794Stackerman *  This routine is called only when ixgb_display_debug_stats is enabled.
2425129794Stackerman *  This routine provides a way to take a look at important statistics
2426129794Stackerman *  maintained by the driver and hardware.
2427129794Stackerman *
2428129794Stackerman **********************************************************************/
2429129794Stackermanstatic void
2430129794Stackermanixgb_print_hw_stats(struct adapter * adapter)
2431129794Stackerman{
2432129794Stackerman	char            buf_speed[100], buf_type[100];
2433129794Stackerman	ixgb_bus_speed  bus_speed;
2434129794Stackerman	ixgb_bus_type   bus_type;
2435198987Sjhb	device_t dev;
2436129794Stackerman
2437198987Sjhb	dev = adapter->dev;
2438129794Stackerman#ifdef _SV_
2439198987Sjhb	device_printf(dev, "Packets not Avail = %ld\n",
2440129794Stackerman	       adapter->no_pkts_avail);
2441198987Sjhb	device_printf(dev, "CleanTxInterrupts = %ld\n",
2442129794Stackerman	       adapter->clean_tx_interrupts);
2443198987Sjhb	device_printf(dev, "ICR RXDMT0 = %lld\n",
2444129794Stackerman	       (long long)adapter->sv_stats.icr_rxdmt0);
2445198987Sjhb	device_printf(dev, "ICR RXO = %lld\n",
2446129794Stackerman	       (long long)adapter->sv_stats.icr_rxo);
2447198987Sjhb	device_printf(dev, "ICR RXT0 = %lld\n",
2448129794Stackerman	       (long long)adapter->sv_stats.icr_rxt0);
2449198987Sjhb	device_printf(dev, "ICR TXDW = %lld\n",
2450129794Stackerman	       (long long)adapter->sv_stats.icr_TXDW);
2451129794Stackerman#endif				/* _SV_ */
2452129794Stackerman
2453129794Stackerman	bus_speed = adapter->hw.bus.speed;
2454129794Stackerman	bus_type = adapter->hw.bus.type;
2455129794Stackerman	sprintf(buf_speed,
2456129794Stackerman		bus_speed == ixgb_bus_speed_33 ? "33MHz" :
2457129794Stackerman		bus_speed == ixgb_bus_speed_66 ? "66MHz" :
2458129794Stackerman		bus_speed == ixgb_bus_speed_100 ? "100MHz" :
2459129794Stackerman		bus_speed == ixgb_bus_speed_133 ? "133MHz" :
2460129794Stackerman		"UNKNOWN");
2461198987Sjhb	device_printf(dev, "PCI_Bus_Speed = %s\n",
2462129794Stackerman	       buf_speed);
2463129794Stackerman
2464129794Stackerman	sprintf(buf_type,
2465129794Stackerman		bus_type == ixgb_bus_type_pci ? "PCI" :
2466129794Stackerman		bus_type == ixgb_bus_type_pcix ? "PCI-X" :
2467129794Stackerman		"UNKNOWN");
2468198987Sjhb	device_printf(dev, "PCI_Bus_Type = %s\n",
2469129794Stackerman	       buf_type);
2470129794Stackerman
2471198987Sjhb	device_printf(dev, "Tx Descriptors not Avail1 = %ld\n",
2472129794Stackerman	       adapter->no_tx_desc_avail1);
2473198987Sjhb	device_printf(dev, "Tx Descriptors not Avail2 = %ld\n",
2474129794Stackerman	       adapter->no_tx_desc_avail2);
2475198987Sjhb	device_printf(dev, "Std Mbuf Failed = %ld\n",
2476129794Stackerman	       adapter->mbuf_alloc_failed);
2477198987Sjhb	device_printf(dev, "Std Cluster Failed = %ld\n",
2478129794Stackerman	       adapter->mbuf_cluster_failed);
2479129794Stackerman
2480198987Sjhb	device_printf(dev, "Defer count = %lld\n",
2481129794Stackerman	       (long long)adapter->stats.dc);
2482198987Sjhb	device_printf(dev, "Missed Packets = %lld\n",
2483129794Stackerman	       (long long)adapter->stats.mpc);
2484198987Sjhb	device_printf(dev, "Receive No Buffers = %lld\n",
2485129794Stackerman	       (long long)adapter->stats.rnbc);
2486198987Sjhb	device_printf(dev, "Receive length errors = %lld\n",
2487129794Stackerman	       (long long)adapter->stats.rlec);
2488198987Sjhb	device_printf(dev, "Crc errors = %lld\n",
2489129794Stackerman	       (long long)adapter->stats.crcerrs);
2490198987Sjhb	device_printf(dev, "Driver dropped packets = %ld\n",
2491129794Stackerman	       adapter->dropped_pkts);
2492129794Stackerman
2493198987Sjhb	device_printf(dev, "XON Rcvd = %lld\n",
2494129794Stackerman	       (long long)adapter->stats.xonrxc);
2495198987Sjhb	device_printf(dev, "XON Xmtd = %lld\n",
2496129794Stackerman	       (long long)adapter->stats.xontxc);
2497198987Sjhb	device_printf(dev, "XOFF Rcvd = %lld\n",
2498129794Stackerman	       (long long)adapter->stats.xoffrxc);
2499198987Sjhb	device_printf(dev, "XOFF Xmtd = %lld\n",
2500129794Stackerman	       (long long)adapter->stats.xofftxc);
2501129794Stackerman
2502198987Sjhb	device_printf(dev, "Good Packets Rcvd = %lld\n",
2503129794Stackerman	       (long long)adapter->stats.gprcl);
2504198987Sjhb	device_printf(dev, "Good Packets Xmtd = %lld\n",
2505129794Stackerman	       (long long)adapter->stats.gptcl);
2506129794Stackerman
2507198987Sjhb	device_printf(dev, "Jumbo frames recvd = %lld\n",
2508129794Stackerman	       (long long)adapter->stats.jprcl);
2509198987Sjhb	device_printf(dev, "Jumbo frames Xmtd = %lld\n",
2510129794Stackerman	       (long long)adapter->stats.jptcl);
2511129794Stackerman
2512129794Stackerman	return;
2513129794Stackerman
2514129794Stackerman}
2515129794Stackerman
2516129794Stackermanstatic int
2517129794Stackermanixgb_sysctl_stats(SYSCTL_HANDLER_ARGS)
2518129794Stackerman{
2519129794Stackerman	int             error;
2520129794Stackerman	int             result;
2521129794Stackerman	struct adapter *adapter;
2522129794Stackerman
2523129794Stackerman	result = -1;
2524129794Stackerman	error = sysctl_handle_int(oidp, &result, 0, req);
2525129794Stackerman
2526129794Stackerman	if (error || !req->newptr)
2527129794Stackerman		return (error);
2528129794Stackerman
2529129794Stackerman	if (result == 1) {
2530129794Stackerman		adapter = (struct adapter *) arg1;
2531129794Stackerman		ixgb_print_hw_stats(adapter);
2532129794Stackerman	}
2533129794Stackerman	return error;
2534129794Stackerman}
2535