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: stable/11/sys/dev/ixgb/if_ixgb.c 333171 2018-05-02 15:21:51Z sbruno $*/
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 */
75253102Sjkim	{IXGB_VENDOR_ID, IXGB_DEVICE_ID_82597EX, PCI_ANY_ID, PCI_ANY_ID, 0},
76253102Sjkim	{IXGB_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);
100272241Sglebiusstatic uint64_t	ixgb_get_counter(struct ifnet *, ift_counter);
101199539Sjhbstatic void     ixgb_watchdog(struct adapter *);
102129794Stackermanstatic void     ixgb_init(void *);
103144651Salcstatic void     ixgb_init_locked(struct adapter *);
104129794Stackermanstatic void     ixgb_stop(void *);
105129794Stackermanstatic void     ixgb_media_status(struct ifnet *, struct ifmediareq *);
106129794Stackermanstatic int      ixgb_media_change(struct ifnet *);
107129794Stackermanstatic void     ixgb_identify_hardware(struct adapter *);
108129794Stackermanstatic int      ixgb_allocate_pci_resources(struct adapter *);
109129794Stackermanstatic void     ixgb_free_pci_resources(struct adapter *);
110129794Stackermanstatic void     ixgb_local_timer(void *);
111129794Stackermanstatic int      ixgb_hardware_init(struct adapter *);
112211907Syongaristatic int      ixgb_setup_interface(device_t, struct adapter *);
113129794Stackermanstatic int      ixgb_setup_transmit_structures(struct adapter *);
114129794Stackermanstatic void     ixgb_initialize_transmit_unit(struct adapter *);
115129794Stackermanstatic int      ixgb_setup_receive_structures(struct adapter *);
116129794Stackermanstatic void     ixgb_initialize_receive_unit(struct adapter *);
117129794Stackermanstatic void     ixgb_enable_intr(struct adapter *);
118129794Stackermanstatic void     ixgb_disable_intr(struct adapter *);
119129794Stackermanstatic void     ixgb_free_transmit_structures(struct adapter *);
120129794Stackermanstatic void     ixgb_free_receive_structures(struct adapter *);
121129794Stackermanstatic void     ixgb_update_stats_counters(struct adapter *);
122129794Stackermanstatic void     ixgb_clean_transmit_interrupts(struct adapter *);
123129794Stackermanstatic int      ixgb_allocate_receive_structures(struct adapter *);
124129794Stackermanstatic int      ixgb_allocate_transmit_structures(struct adapter *);
125193096Sattiliostatic int      ixgb_process_receive_interrupts(struct adapter *, int);
126129794Stackermanstatic void
127129794Stackermanixgb_receive_checksum(struct adapter *,
128129794Stackerman		      struct ixgb_rx_desc * rx_desc,
129129794Stackerman		      struct mbuf *);
130129794Stackermanstatic void
131129794Stackermanixgb_transmit_checksum_setup(struct adapter *,
132129794Stackerman			     struct mbuf *,
133129794Stackerman			     u_int8_t *);
134129794Stackermanstatic void     ixgb_set_promisc(struct adapter *);
135129794Stackermanstatic void     ixgb_disable_promisc(struct adapter *);
136129794Stackermanstatic void     ixgb_set_multi(struct adapter *);
137129794Stackermanstatic void     ixgb_print_hw_stats(struct adapter *);
138129794Stackermanstatic void     ixgb_print_link_status(struct adapter *);
139129794Stackermanstatic int
140129794Stackermanixgb_get_buf(int i, struct adapter *,
141129794Stackerman	     struct mbuf *);
142129794Stackermanstatic void     ixgb_enable_vlans(struct adapter * adapter);
143129794Stackermanstatic int      ixgb_encap(struct adapter * adapter, struct mbuf * m_head);
144129794Stackermanstatic int      ixgb_sysctl_stats(SYSCTL_HANDLER_ARGS);
145129794Stackermanstatic int
146129794Stackermanixgb_dma_malloc(struct adapter *, bus_size_t,
147129794Stackerman		struct ixgb_dma_alloc *, int);
148129794Stackermanstatic void     ixgb_dma_free(struct adapter *, struct ixgb_dma_alloc *);
149150789Sglebius#ifdef DEVICE_POLLING
150150789Sglebiusstatic poll_handler_t ixgb_poll;
151150789Sglebius#endif
152129794Stackerman
153129794Stackerman/*********************************************************************
154129794Stackerman *  FreeBSD Device Interface Entry Points
155129794Stackerman *********************************************************************/
156129794Stackerman
157129794Stackermanstatic device_method_t ixgb_methods[] = {
158129794Stackerman	/* Device interface */
159129794Stackerman	DEVMETHOD(device_probe, ixgb_probe),
160129794Stackerman	DEVMETHOD(device_attach, ixgb_attach),
161129794Stackerman	DEVMETHOD(device_detach, ixgb_detach),
162129794Stackerman	DEVMETHOD(device_shutdown, ixgb_shutdown),
163246128Ssbz
164246128Ssbz	DEVMETHOD_END
165129794Stackerman};
166129794Stackerman
167129794Stackermanstatic driver_t ixgb_driver = {
168129794Stackerman	"ixgb", ixgb_methods, sizeof(struct adapter),
169129794Stackerman};
170129794Stackerman
171129794Stackermanstatic devclass_t ixgb_devclass;
172192147SimpDRIVER_MODULE(ixgb, pci, ixgb_driver, ixgb_devclass, 0, 0);
173129794Stackerman
174192147SimpMODULE_DEPEND(ixgb, pci, 1, 1, 1);
175192147SimpMODULE_DEPEND(ixgb, ether, 1, 1, 1);
176144183Smux
177129794Stackerman/* some defines for controlling descriptor fetches in h/w */
178129794Stackerman#define RXDCTL_PTHRESH_DEFAULT 128	/* chip considers prefech below this */
179129794Stackerman#define RXDCTL_HTHRESH_DEFAULT 16	/* chip will only prefetch if tail is
180129794Stackerman					 * pushed this many descriptors from
181129794Stackerman					 * head */
182129794Stackerman#define RXDCTL_WTHRESH_DEFAULT 0	/* chip writes back at this many or RXT0 */
183129794Stackerman
184129794Stackerman
185129794Stackerman/*********************************************************************
186129794Stackerman *  Device identification routine
187129794Stackerman *
188129794Stackerman *  ixgb_probe determines if the driver should be loaded on
189129794Stackerman *  adapter based on PCI vendor/device id of the adapter.
190129794Stackerman *
191129794Stackerman *  return 0 on success, positive on failure
192129794Stackerman *********************************************************************/
193129794Stackerman
194129794Stackermanstatic int
195129794Stackermanixgb_probe(device_t dev)
196129794Stackerman{
197129794Stackerman	ixgb_vendor_info_t *ent;
198129794Stackerman
199129794Stackerman	u_int16_t       pci_vendor_id = 0;
200129794Stackerman	u_int16_t       pci_device_id = 0;
201129794Stackerman	u_int16_t       pci_subvendor_id = 0;
202129794Stackerman	u_int16_t       pci_subdevice_id = 0;
203129794Stackerman	char            adapter_name[60];
204129794Stackerman
205129794Stackerman	INIT_DEBUGOUT("ixgb_probe: begin");
206129794Stackerman
207129794Stackerman	pci_vendor_id = pci_get_vendor(dev);
208129794Stackerman	if (pci_vendor_id != IXGB_VENDOR_ID)
209129794Stackerman		return (ENXIO);
210129794Stackerman
211129794Stackerman	pci_device_id = pci_get_device(dev);
212129794Stackerman	pci_subvendor_id = pci_get_subvendor(dev);
213129794Stackerman	pci_subdevice_id = pci_get_subdevice(dev);
214129794Stackerman
215129794Stackerman	ent = ixgb_vendor_info_array;
216129794Stackerman	while (ent->vendor_id != 0) {
217129794Stackerman		if ((pci_vendor_id == ent->vendor_id) &&
218129794Stackerman		    (pci_device_id == ent->device_id) &&
219129794Stackerman
220129794Stackerman		    ((pci_subvendor_id == ent->subvendor_id) ||
221129794Stackerman		     (ent->subvendor_id == PCI_ANY_ID)) &&
222129794Stackerman
223129794Stackerman		    ((pci_subdevice_id == ent->subdevice_id) ||
224129794Stackerman		     (ent->subdevice_id == PCI_ANY_ID))) {
225129794Stackerman			sprintf(adapter_name, "%s, Version - %s",
226129794Stackerman				ixgb_strings[ent->index],
227129794Stackerman				ixgb_driver_version);
228129794Stackerman			device_set_desc_copy(dev, adapter_name);
229143160Simp			return (BUS_PROBE_DEFAULT);
230129794Stackerman		}
231129794Stackerman		ent++;
232129794Stackerman	}
233129794Stackerman
234129794Stackerman	return (ENXIO);
235129794Stackerman}
236129794Stackerman
237129794Stackerman/*********************************************************************
238129794Stackerman *  Device initialization routine
239129794Stackerman *
240129794Stackerman *  The attach entry point is called when the driver is being loaded.
241129794Stackerman *  This routine identifies the type of hardware, allocates all resources
242129794Stackerman *  and initializes the hardware.
243129794Stackerman *
244129794Stackerman *  return 0 on success, positive on failure
245129794Stackerman *********************************************************************/
246129794Stackerman
247129794Stackermanstatic int
248129794Stackermanixgb_attach(device_t dev)
249129794Stackerman{
250129794Stackerman	struct adapter *adapter;
251129794Stackerman	int             tsize, rsize;
252129794Stackerman	int             error = 0;
253129794Stackerman
254198987Sjhb	device_printf(dev, "%s\n", ixgb_copyright);
255129794Stackerman	INIT_DEBUGOUT("ixgb_attach: begin");
256129794Stackerman
257129794Stackerman	/* Allocate, clear, and link in our adapter structure */
258129794Stackerman	if (!(adapter = device_get_softc(dev))) {
259198987Sjhb		device_printf(dev, "adapter structure allocation failed\n");
260129794Stackerman		return (ENOMEM);
261129794Stackerman	}
262129794Stackerman	bzero(adapter, sizeof(struct adapter));
263129794Stackerman	adapter->dev = dev;
264129794Stackerman	adapter->osdep.dev = dev;
265144651Salc	IXGB_LOCK_INIT(adapter, device_get_nameunit(dev));
266129794Stackerman
267129794Stackerman	if (ixgb_adapter_list != NULL)
268129794Stackerman		ixgb_adapter_list->prev = adapter;
269129794Stackerman	adapter->next = ixgb_adapter_list;
270129794Stackerman	ixgb_adapter_list = adapter;
271129794Stackerman
272129794Stackerman	/* SYSCTL APIs */
273144183Smux	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
274144183Smux			SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
275129794Stackerman			OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW,
276129794Stackerman			(void *)adapter, 0,
277129794Stackerman			ixgb_sysctl_stats, "I", "Statistics");
278129794Stackerman
279199539Sjhb	callout_init_mtx(&adapter->timer, &adapter->mtx, 0);
280129794Stackerman
281129794Stackerman	/* Determine hardware revision */
282129794Stackerman	ixgb_identify_hardware(adapter);
283129794Stackerman
284129794Stackerman	/* Parameters (to be read from user) */
285129794Stackerman	adapter->num_tx_desc = IXGB_MAX_TXD;
286129794Stackerman	adapter->num_rx_desc = IXGB_MAX_RXD;
287129794Stackerman	adapter->tx_int_delay = TIDV;
288129794Stackerman	adapter->rx_int_delay = RDTR;
289129794Stackerman	adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
290129794Stackerman
291129794Stackerman	adapter->hw.fc.high_water = FCRTH;
292129794Stackerman	adapter->hw.fc.low_water = FCRTL;
293129794Stackerman	adapter->hw.fc.pause_time = FCPAUSE;
294129794Stackerman	adapter->hw.fc.send_xon = TRUE;
295129794Stackerman	adapter->hw.fc.type = FLOW_CONTROL;
296129794Stackerman
297129794Stackerman
298129794Stackerman	/* Set the max frame size assuming standard ethernet sized frames */
299129794Stackerman	adapter->hw.max_frame_size =
300129794Stackerman		ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
301129794Stackerman
302129794Stackerman	if (ixgb_allocate_pci_resources(adapter)) {
303198987Sjhb		device_printf(dev, "Allocation of PCI resources failed\n");
304129794Stackerman		error = ENXIO;
305129794Stackerman		goto err_pci;
306129794Stackerman	}
307129794Stackerman	tsize = IXGB_ROUNDUP(adapter->num_tx_desc *
308129794Stackerman			     sizeof(struct ixgb_tx_desc), 4096);
309129794Stackerman
310129794Stackerman	/* Allocate Transmit Descriptor ring */
311129794Stackerman	if (ixgb_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) {
312198987Sjhb		device_printf(dev, "Unable to allocate TxDescriptor memory\n");
313129794Stackerman		error = ENOMEM;
314129794Stackerman		goto err_tx_desc;
315129794Stackerman	}
316129794Stackerman	adapter->tx_desc_base = (struct ixgb_tx_desc *) adapter->txdma.dma_vaddr;
317129794Stackerman
318129794Stackerman	rsize = IXGB_ROUNDUP(adapter->num_rx_desc *
319129794Stackerman			     sizeof(struct ixgb_rx_desc), 4096);
320129794Stackerman
321129794Stackerman	/* Allocate Receive Descriptor ring */
322129794Stackerman	if (ixgb_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) {
323198987Sjhb		device_printf(dev, "Unable to allocate rx_desc memory\n");
324129794Stackerman		error = ENOMEM;
325129794Stackerman		goto err_rx_desc;
326129794Stackerman	}
327129794Stackerman	adapter->rx_desc_base = (struct ixgb_rx_desc *) adapter->rxdma.dma_vaddr;
328129794Stackerman
329211913Syongari	/* Allocate multicast array memory. */
330211913Syongari	adapter->mta = malloc(sizeof(u_int8_t) * IXGB_ETH_LENGTH_OF_ADDRESS *
331211913Syongari	    MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
332211913Syongari	if (adapter->mta == NULL) {
333211913Syongari		device_printf(dev, "Can not allocate multicast setup array\n");
334211913Syongari		error = ENOMEM;
335211913Syongari		goto err_hw_init;
336211913Syongari	}
337211913Syongari
338129794Stackerman	/* Initialize the hardware */
339129794Stackerman	if (ixgb_hardware_init(adapter)) {
340198987Sjhb		device_printf(dev, "Unable to initialize the hardware\n");
341129794Stackerman		error = EIO;
342129794Stackerman		goto err_hw_init;
343129794Stackerman	}
344129794Stackerman	/* Setup OS specific network interface */
345211907Syongari	if (ixgb_setup_interface(dev, adapter) != 0)
346211907Syongari		goto err_hw_init;
347129794Stackerman
348129794Stackerman	/* Initialize statistics */
349129794Stackerman	ixgb_clear_hw_cntrs(&adapter->hw);
350129794Stackerman	ixgb_update_stats_counters(adapter);
351129794Stackerman
352333171Ssbruno	gone_in_dev(dev, 12, "ixgb(4) driver");
353129794Stackerman	INIT_DEBUGOUT("ixgb_attach: end");
354129794Stackerman	return (0);
355129794Stackerman
356129794Stackermanerr_hw_init:
357129794Stackerman	ixgb_dma_free(adapter, &adapter->rxdma);
358129794Stackermanerr_rx_desc:
359129794Stackerman	ixgb_dma_free(adapter, &adapter->txdma);
360129794Stackermanerr_tx_desc:
361129794Stackermanerr_pci:
362211907Syongari	if (adapter->ifp != NULL)
363211907Syongari		if_free(adapter->ifp);
364129794Stackerman	ixgb_free_pci_resources(adapter);
365129794Stackerman	sysctl_ctx_free(&adapter->sysctl_ctx);
366211913Syongari	free(adapter->mta, M_DEVBUF);
367129794Stackerman	return (error);
368129794Stackerman
369129794Stackerman}
370129794Stackerman
371129794Stackerman/*********************************************************************
372129794Stackerman *  Device removal routine
373129794Stackerman *
374129794Stackerman *  The detach entry point is called when the driver is being removed.
375129794Stackerman *  This routine stops the adapter and deallocates all the resources
376129794Stackerman *  that were allocated for driver operation.
377129794Stackerman *
378129794Stackerman *  return 0 on success, positive on failure
379129794Stackerman *********************************************************************/
380129794Stackerman
381129794Stackermanstatic int
382129794Stackermanixgb_detach(device_t dev)
383129794Stackerman{
384129794Stackerman	struct adapter *adapter = device_get_softc(dev);
385147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
386129794Stackerman
387129794Stackerman	INIT_DEBUGOUT("ixgb_detach: begin");
388129794Stackerman
389150789Sglebius#ifdef DEVICE_POLLING
390150789Sglebius	if (ifp->if_capenable & IFCAP_POLLING)
391150789Sglebius		ether_poll_deregister(ifp);
392150789Sglebius#endif
393150789Sglebius
394144651Salc	IXGB_LOCK(adapter);
395129794Stackerman	adapter->in_detach = 1;
396129794Stackerman
397129794Stackerman	ixgb_stop(adapter);
398144651Salc	IXGB_UNLOCK(adapter);
399129794Stackerman
400129794Stackerman#if __FreeBSD_version < 500000
401199539Sjhb	ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
402129794Stackerman#else
403199539Sjhb	ether_ifdetach(ifp);
404150306Simp#endif
405199539Sjhb	callout_drain(&adapter->timer);
406150306Simp	ixgb_free_pci_resources(adapter);
407150306Simp#if __FreeBSD_version >= 500000
408199539Sjhb	if_free(ifp);
409129794Stackerman#endif
410129794Stackerman
411129794Stackerman	/* Free Transmit Descriptor ring */
412129794Stackerman	if (adapter->tx_desc_base) {
413129794Stackerman		ixgb_dma_free(adapter, &adapter->txdma);
414129794Stackerman		adapter->tx_desc_base = NULL;
415129794Stackerman	}
416129794Stackerman	/* Free Receive Descriptor ring */
417129794Stackerman	if (adapter->rx_desc_base) {
418129794Stackerman		ixgb_dma_free(adapter, &adapter->rxdma);
419129794Stackerman		adapter->rx_desc_base = NULL;
420129794Stackerman	}
421129794Stackerman	/* Remove from the adapter list */
422129794Stackerman	if (ixgb_adapter_list == adapter)
423129794Stackerman		ixgb_adapter_list = adapter->next;
424129794Stackerman	if (adapter->next != NULL)
425129794Stackerman		adapter->next->prev = adapter->prev;
426129794Stackerman	if (adapter->prev != NULL)
427129794Stackerman		adapter->prev->next = adapter->next;
428211913Syongari	free(adapter->mta, M_DEVBUF);
429129794Stackerman
430144651Salc	IXGB_LOCK_DESTROY(adapter);
431129794Stackerman	return (0);
432129794Stackerman}
433129794Stackerman
434129794Stackerman/*********************************************************************
435129794Stackerman *
436129794Stackerman *  Shutdown entry point
437129794Stackerman *
438129794Stackerman **********************************************************************/
439129794Stackerman
440129794Stackermanstatic int
441129794Stackermanixgb_shutdown(device_t dev)
442129794Stackerman{
443129794Stackerman	struct adapter *adapter = device_get_softc(dev);
444144651Salc	IXGB_LOCK(adapter);
445129794Stackerman	ixgb_stop(adapter);
446144651Salc	IXGB_UNLOCK(adapter);
447129794Stackerman	return (0);
448129794Stackerman}
449129794Stackerman
450129794Stackerman
451129794Stackerman/*********************************************************************
452129794Stackerman *  Transmit entry point
453129794Stackerman *
454129794Stackerman *  ixgb_start is called by the stack to initiate a transmit.
455129794Stackerman *  The driver will remain in this routine as long as there are
456129794Stackerman *  packets to transmit and transmit resources are available.
457129794Stackerman *  In case resources are not available stack is notified and
458129794Stackerman *  the packet is requeued.
459129794Stackerman **********************************************************************/
460129794Stackerman
461129794Stackermanstatic void
462144651Salcixgb_start_locked(struct ifnet * ifp)
463129794Stackerman{
464129794Stackerman	struct mbuf    *m_head;
465129794Stackerman	struct adapter *adapter = ifp->if_softc;
466129794Stackerman
467144651Salc	IXGB_LOCK_ASSERT(adapter);
468129794Stackerman
469129794Stackerman	if (!adapter->link_active)
470129794Stackerman		return;
471129794Stackerman
472129794Stackerman	while (ifp->if_snd.ifq_head != NULL) {
473129794Stackerman		IF_DEQUEUE(&ifp->if_snd, m_head);
474129794Stackerman
475129794Stackerman		if (m_head == NULL)
476129794Stackerman			break;
477129794Stackerman
478129794Stackerman		if (ixgb_encap(adapter, m_head)) {
479148887Srwatson			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
480129794Stackerman			IF_PREPEND(&ifp->if_snd, m_head);
481129794Stackerman			break;
482129794Stackerman		}
483129794Stackerman		/* Send a copy of the frame to the BPF listener */
484129794Stackerman#if __FreeBSD_version < 500000
485129794Stackerman		if (ifp->if_bpf)
486129794Stackerman			bpf_mtap(ifp, m_head);
487129794Stackerman#else
488167190Scsjp		ETHER_BPF_MTAP(ifp, m_head);
489129794Stackerman#endif
490129794Stackerman		/* Set timeout in case hardware has problems transmitting */
491199539Sjhb		adapter->tx_timer = IXGB_TX_TIMEOUT;
492129794Stackerman
493129794Stackerman	}
494129794Stackerman	return;
495129794Stackerman}
496129794Stackerman
497144651Salcstatic void
498144651Salcixgb_start(struct ifnet *ifp)
499144651Salc{
500144651Salc	struct adapter *adapter = ifp->if_softc;
501144651Salc
502144651Salc	IXGB_LOCK(adapter);
503144651Salc	ixgb_start_locked(ifp);
504144651Salc	IXGB_UNLOCK(adapter);
505144651Salc	return;
506144651Salc}
507144651Salc
508129794Stackerman/*********************************************************************
509129794Stackerman *  Ioctl entry point
510129794Stackerman *
511129794Stackerman *  ixgb_ioctl is called when the user wants to configure the
512129794Stackerman *  interface.
513129794Stackerman *
514129794Stackerman *  return 0 on success, positive on failure
515129794Stackerman **********************************************************************/
516129794Stackerman
517129794Stackermanstatic int
518129794Stackermanixgb_ioctl(struct ifnet * ifp, IOCTL_CMD_TYPE command, caddr_t data)
519129794Stackerman{
520144651Salc	int             mask, error = 0;
521129794Stackerman	struct ifreq   *ifr = (struct ifreq *) data;
522129794Stackerman	struct adapter *adapter = ifp->if_softc;
523129794Stackerman
524129794Stackerman	if (adapter->in_detach)
525129794Stackerman		goto out;
526129794Stackerman
527129794Stackerman	switch (command) {
528129794Stackerman	case SIOCSIFADDR:
529129794Stackerman	case SIOCGIFADDR:
530129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFADDR (Get/Set Interface Addr)");
531129794Stackerman		ether_ioctl(ifp, command, data);
532129794Stackerman		break;
533129794Stackerman	case SIOCSIFMTU:
534129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
535129794Stackerman		if (ifr->ifr_mtu > IXGB_MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN) {
536129794Stackerman			error = EINVAL;
537129794Stackerman		} else {
538144651Salc			IXGB_LOCK(adapter);
539129794Stackerman			ifp->if_mtu = ifr->ifr_mtu;
540129794Stackerman			adapter->hw.max_frame_size =
541129794Stackerman				ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
542129794Stackerman
543302384Ssbruno			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
544302384Ssbruno				ixgb_init_locked(adapter);
545144651Salc			IXGB_UNLOCK(adapter);
546129794Stackerman		}
547129794Stackerman		break;
548129794Stackerman	case SIOCSIFFLAGS:
549129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)");
550144651Salc		IXGB_LOCK(adapter);
551129794Stackerman		if (ifp->if_flags & IFF_UP) {
552148887Srwatson			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
553144651Salc				ixgb_init_locked(adapter);
554129794Stackerman			}
555129794Stackerman			ixgb_disable_promisc(adapter);
556129794Stackerman			ixgb_set_promisc(adapter);
557129794Stackerman		} else {
558148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
559129794Stackerman				ixgb_stop(adapter);
560129794Stackerman			}
561129794Stackerman		}
562144651Salc		IXGB_UNLOCK(adapter);
563129794Stackerman		break;
564129794Stackerman	case SIOCADDMULTI:
565129794Stackerman	case SIOCDELMULTI:
566129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI");
567148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
568144651Salc			IXGB_LOCK(adapter);
569129794Stackerman			ixgb_disable_intr(adapter);
570129794Stackerman			ixgb_set_multi(adapter);
571129794Stackerman			ixgb_enable_intr(adapter);
572144651Salc			IXGB_UNLOCK(adapter);
573129794Stackerman		}
574129794Stackerman		break;
575129794Stackerman	case SIOCSIFMEDIA:
576129794Stackerman	case SIOCGIFMEDIA:
577129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA (Get/Set Interface Media)");
578129794Stackerman		error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
579129794Stackerman		break;
580129794Stackerman	case SIOCSIFCAP:
581129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
582129794Stackerman		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
583150789Sglebius#ifdef DEVICE_POLLING
584150789Sglebius		if (mask & IFCAP_POLLING) {
585150789Sglebius			if (ifr->ifr_reqcap & IFCAP_POLLING) {
586150789Sglebius				error = ether_poll_register(ixgb_poll, ifp);
587150789Sglebius				if (error)
588150789Sglebius					return(error);
589150789Sglebius				IXGB_LOCK(adapter);
590150789Sglebius				ixgb_disable_intr(adapter);
591150789Sglebius				ifp->if_capenable |= IFCAP_POLLING;
592150789Sglebius				IXGB_UNLOCK(adapter);
593150789Sglebius			} else {
594150789Sglebius				error = ether_poll_deregister(ifp);
595150789Sglebius				/* Enable interrupt even in error case */
596150789Sglebius				IXGB_LOCK(adapter);
597150789Sglebius				ixgb_enable_intr(adapter);
598150789Sglebius				ifp->if_capenable &= ~IFCAP_POLLING;
599150789Sglebius				IXGB_UNLOCK(adapter);
600150789Sglebius			}
601150789Sglebius		}
602150789Sglebius#endif /* DEVICE_POLLING */
603129794Stackerman		if (mask & IFCAP_HWCSUM) {
604129794Stackerman			if (IFCAP_HWCSUM & ifp->if_capenable)
605129794Stackerman				ifp->if_capenable &= ~IFCAP_HWCSUM;
606129794Stackerman			else
607129794Stackerman				ifp->if_capenable |= IFCAP_HWCSUM;
608148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
609129794Stackerman				ixgb_init(adapter);
610129794Stackerman		}
611129794Stackerman		break;
612129794Stackerman	default:
613129794Stackerman		IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%X)\n", (int)command);
614129794Stackerman		error = EINVAL;
615129794Stackerman	}
616129794Stackerman
617129794Stackermanout:
618129794Stackerman	return (error);
619129794Stackerman}
620129794Stackerman
621129794Stackerman/*********************************************************************
622129794Stackerman *  Watchdog entry point
623129794Stackerman *
624129794Stackerman *  This routine is called whenever hardware quits transmitting.
625129794Stackerman *
626129794Stackerman **********************************************************************/
627129794Stackerman
628129794Stackermanstatic void
629199539Sjhbixgb_watchdog(struct adapter *adapter)
630129794Stackerman{
631199539Sjhb	struct ifnet *ifp;
632129794Stackerman
633199539Sjhb	ifp = adapter->ifp;
634199539Sjhb
635129794Stackerman	/*
636129794Stackerman	 * If we are in this routine because of pause frames, then don't
637129794Stackerman	 * reset the hardware.
638129794Stackerman	 */
639129794Stackerman	if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF) {
640199539Sjhb		adapter->tx_timer = IXGB_TX_TIMEOUT;
641129794Stackerman		return;
642129794Stackerman	}
643198987Sjhb	if_printf(ifp, "watchdog timeout -- resetting\n");
644129794Stackerman
645129794Stackerman	ixgb_stop(adapter);
646199539Sjhb	ixgb_init_locked(adapter);
647129794Stackerman
648129794Stackerman
649272241Sglebius	if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
650129794Stackerman
651129794Stackerman	return;
652129794Stackerman}
653129794Stackerman
654129794Stackerman/*********************************************************************
655129794Stackerman *  Init entry point
656129794Stackerman *
657129794Stackerman *  This routine is used in two ways. It is used by the stack as
658129794Stackerman *  init entry point in network interface structure. It is also used
659129794Stackerman *  by the driver as a hw/sw initialization routine to get to a
660129794Stackerman *  consistent state.
661129794Stackerman *
662129794Stackerman *  return 0 on success, positive on failure
663129794Stackerman **********************************************************************/
664129794Stackerman
665129794Stackermanstatic void
666144651Salcixgb_init_locked(struct adapter *adapter)
667129794Stackerman{
668129794Stackerman	struct ifnet   *ifp;
669129794Stackerman
670129794Stackerman	INIT_DEBUGOUT("ixgb_init: begin");
671129794Stackerman
672144651Salc	IXGB_LOCK_ASSERT(adapter);
673129794Stackerman
674129794Stackerman	ixgb_stop(adapter);
675198987Sjhb	ifp = adapter->ifp;
676129794Stackerman
677129794Stackerman	/* Get the latest mac address, User can use a LAA */
678198987Sjhb	bcopy(IF_LLADDR(ifp), adapter->hw.curr_mac_addr,
679198987Sjhb	    IXGB_ETH_LENGTH_OF_ADDRESS);
680129794Stackerman
681129794Stackerman	/* Initialize the hardware */
682129794Stackerman	if (ixgb_hardware_init(adapter)) {
683198987Sjhb		if_printf(ifp, "Unable to initialize the hardware\n");
684129794Stackerman		return;
685129794Stackerman	}
686129794Stackerman	ixgb_enable_vlans(adapter);
687129794Stackerman
688129794Stackerman	/* Prepare transmit descriptors and buffers */
689129794Stackerman	if (ixgb_setup_transmit_structures(adapter)) {
690198987Sjhb		if_printf(ifp, "Could not setup transmit structures\n");
691129794Stackerman		ixgb_stop(adapter);
692129794Stackerman		return;
693129794Stackerman	}
694129794Stackerman	ixgb_initialize_transmit_unit(adapter);
695129794Stackerman
696129794Stackerman	/* Setup Multicast table */
697129794Stackerman	ixgb_set_multi(adapter);
698129794Stackerman
699129794Stackerman	/* Prepare receive descriptors and buffers */
700129794Stackerman	if (ixgb_setup_receive_structures(adapter)) {
701198987Sjhb		if_printf(ifp, "Could not setup receive structures\n");
702129794Stackerman		ixgb_stop(adapter);
703129794Stackerman		return;
704129794Stackerman	}
705129794Stackerman	ixgb_initialize_receive_unit(adapter);
706129794Stackerman
707160964Syar	/* Don't lose promiscuous settings */
708129794Stackerman	ixgb_set_promisc(adapter);
709129794Stackerman
710147256Sbrooks	ifp = adapter->ifp;
711148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
712148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
713129794Stackerman
714129794Stackerman
715129794Stackerman	if (ifp->if_capenable & IFCAP_TXCSUM)
716129794Stackerman		ifp->if_hwassist = IXGB_CHECKSUM_FEATURES;
717129794Stackerman	else
718129794Stackerman		ifp->if_hwassist = 0;
719129794Stackerman
720129794Stackerman
721129794Stackerman	/* Enable jumbo frames */
722129794Stackerman	if (ifp->if_mtu > ETHERMTU) {
723129794Stackerman		uint32_t        temp_reg;
724129794Stackerman		IXGB_WRITE_REG(&adapter->hw, MFS,
725129794Stackerman			       adapter->hw.max_frame_size << IXGB_MFS_SHIFT);
726129794Stackerman		temp_reg = IXGB_READ_REG(&adapter->hw, CTRL0);
727129794Stackerman		temp_reg |= IXGB_CTRL0_JFE;
728129794Stackerman		IXGB_WRITE_REG(&adapter->hw, CTRL0, temp_reg);
729129794Stackerman	}
730199539Sjhb	callout_reset(&adapter->timer, hz, ixgb_local_timer, adapter);
731129794Stackerman	ixgb_clear_hw_cntrs(&adapter->hw);
732129794Stackerman#ifdef DEVICE_POLLING
733129794Stackerman	/*
734129794Stackerman	 * Only disable interrupts if we are polling, make sure they are on
735129794Stackerman	 * otherwise.
736129794Stackerman	 */
737150789Sglebius	if (ifp->if_capenable & IFCAP_POLLING)
738129794Stackerman		ixgb_disable_intr(adapter);
739129794Stackerman	else
740150789Sglebius#endif
741129794Stackerman		ixgb_enable_intr(adapter);
742129794Stackerman
743129794Stackerman	return;
744129794Stackerman}
745129794Stackerman
746144651Salcstatic void
747144651Salcixgb_init(void *arg)
748144651Salc{
749144651Salc	struct adapter *adapter = arg;
750129794Stackerman
751144651Salc	IXGB_LOCK(adapter);
752144651Salc	ixgb_init_locked(adapter);
753144651Salc	IXGB_UNLOCK(adapter);
754144651Salc	return;
755144651Salc}
756144651Salc
757129794Stackerman#ifdef DEVICE_POLLING
758193096Sattiliostatic int
759144651Salcixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count)
760129794Stackerman{
761129794Stackerman	struct adapter *adapter = ifp->if_softc;
762129794Stackerman	u_int32_t       reg_icr;
763193096Sattilio	int		rx_npkts;
764129794Stackerman
765144651Salc	IXGB_LOCK_ASSERT(adapter);
766144651Salc
767129794Stackerman	if (cmd == POLL_AND_CHECK_STATUS) {
768129794Stackerman		reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
769129794Stackerman		if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
770129794Stackerman			ixgb_check_for_link(&adapter->hw);
771129794Stackerman			ixgb_print_link_status(adapter);
772129794Stackerman		}
773129794Stackerman	}
774193096Sattilio	rx_npkts = ixgb_process_receive_interrupts(adapter, count);
775150789Sglebius	ixgb_clean_transmit_interrupts(adapter);
776150789Sglebius
777150789Sglebius	if (ifp->if_snd.ifq_head != NULL)
778144651Salc		ixgb_start_locked(ifp);
779193096Sattilio	return (rx_npkts);
780129794Stackerman}
781144651Salc
782193096Sattiliostatic int
783144651Salcixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count)
784144651Salc{
785144651Salc	struct adapter *adapter = ifp->if_softc;
786193096Sattilio	int rx_npkts = 0;
787144651Salc
788144651Salc	IXGB_LOCK(adapter);
789150789Sglebius	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
790193096Sattilio		rx_npkts = ixgb_poll_locked(ifp, cmd, count);
791144651Salc	IXGB_UNLOCK(adapter);
792193096Sattilio	return (rx_npkts);
793144651Salc}
794150789Sglebius#endif /* DEVICE_POLLING */
795129794Stackerman
796129794Stackerman/*********************************************************************
797129794Stackerman *
798129794Stackerman *  Interrupt Service routine
799129794Stackerman *
800129794Stackerman **********************************************************************/
801129794Stackerman
802129794Stackermanstatic void
803129794Stackermanixgb_intr(void *arg)
804129794Stackerman{
805129794Stackerman	u_int32_t       loop_cnt = IXGB_MAX_INTR;
806129794Stackerman	u_int32_t       reg_icr;
807129794Stackerman	struct ifnet   *ifp;
808129794Stackerman	struct adapter *adapter = arg;
809129794Stackerman	boolean_t       rxdmt0 = FALSE;
810129794Stackerman
811144651Salc	IXGB_LOCK(adapter);
812144651Salc
813147256Sbrooks	ifp = adapter->ifp;
814129794Stackerman
815129794Stackerman#ifdef DEVICE_POLLING
816150789Sglebius	if (ifp->if_capenable & IFCAP_POLLING) {
817144651Salc		IXGB_UNLOCK(adapter);
818129794Stackerman		return;
819144651Salc	}
820150789Sglebius#endif
821129794Stackerman
822144651Salc	reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
823144651Salc	if (reg_icr == 0) {
824144651Salc		IXGB_UNLOCK(adapter);
825129794Stackerman		return;
826144651Salc	}
827129794Stackerman
828129794Stackerman	if (reg_icr & IXGB_INT_RXDMT0)
829129794Stackerman		rxdmt0 = TRUE;
830129794Stackerman
831129794Stackerman#ifdef _SV_
832129794Stackerman	if (reg_icr & IXGB_INT_RXDMT0)
833129794Stackerman		adapter->sv_stats.icr_rxdmt0++;
834129794Stackerman	if (reg_icr & IXGB_INT_RXO)
835129794Stackerman		adapter->sv_stats.icr_rxo++;
836129794Stackerman	if (reg_icr & IXGB_INT_RXT0)
837129794Stackerman		adapter->sv_stats.icr_rxt0++;
838129794Stackerman	if (reg_icr & IXGB_INT_TXDW)
839129794Stackerman		adapter->sv_stats.icr_TXDW++;
840129794Stackerman#endif				/* _SV_ */
841129794Stackerman
842129794Stackerman	/* Link status change */
843129794Stackerman	if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
844129794Stackerman		ixgb_check_for_link(&adapter->hw);
845129794Stackerman		ixgb_print_link_status(adapter);
846129794Stackerman	}
847129794Stackerman	while (loop_cnt > 0) {
848148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
849129794Stackerman			ixgb_process_receive_interrupts(adapter, -1);
850129794Stackerman			ixgb_clean_transmit_interrupts(adapter);
851129794Stackerman		}
852129794Stackerman		loop_cnt--;
853129794Stackerman	}
854129794Stackerman
855129794Stackerman	if (rxdmt0 && adapter->raidc) {
856129794Stackerman		IXGB_WRITE_REG(&adapter->hw, IMC, IXGB_INT_RXDMT0);
857129794Stackerman		IXGB_WRITE_REG(&adapter->hw, IMS, IXGB_INT_RXDMT0);
858129794Stackerman	}
859148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING && ifp->if_snd.ifq_head != NULL)
860144651Salc		ixgb_start_locked(ifp);
861129794Stackerman
862144651Salc	IXGB_UNLOCK(adapter);
863129794Stackerman	return;
864129794Stackerman}
865129794Stackerman
866129794Stackerman
867129794Stackerman/*********************************************************************
868129794Stackerman *
869129794Stackerman *  Media Ioctl callback
870129794Stackerman *
871129794Stackerman *  This routine is called whenever the user queries the status of
872129794Stackerman *  the interface using ifconfig.
873129794Stackerman *
874129794Stackerman **********************************************************************/
875129794Stackermanstatic void
876129794Stackermanixgb_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
877129794Stackerman{
878129794Stackerman	struct adapter *adapter = ifp->if_softc;
879129794Stackerman
880129794Stackerman	INIT_DEBUGOUT("ixgb_media_status: begin");
881129794Stackerman
882129794Stackerman	ixgb_check_for_link(&adapter->hw);
883129794Stackerman	ixgb_print_link_status(adapter);
884129794Stackerman
885129794Stackerman	ifmr->ifm_status = IFM_AVALID;
886129794Stackerman	ifmr->ifm_active = IFM_ETHER;
887129794Stackerman
888129794Stackerman	if (!adapter->hw.link_up)
889129794Stackerman		return;
890129794Stackerman
891129794Stackerman	ifmr->ifm_status |= IFM_ACTIVE;
892129794Stackerman	ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
893129794Stackerman
894129794Stackerman	return;
895129794Stackerman}
896129794Stackerman
897129794Stackerman/*********************************************************************
898129794Stackerman *
899129794Stackerman *  Media Ioctl callback
900129794Stackerman *
901129794Stackerman *  This routine is called when the user changes speed/duplex using
902129794Stackerman *  media/mediopt option with ifconfig.
903129794Stackerman *
904129794Stackerman **********************************************************************/
905129794Stackermanstatic int
906129794Stackermanixgb_media_change(struct ifnet * ifp)
907129794Stackerman{
908129794Stackerman	struct adapter *adapter = ifp->if_softc;
909129794Stackerman	struct ifmedia *ifm = &adapter->media;
910129794Stackerman
911129794Stackerman	INIT_DEBUGOUT("ixgb_media_change: begin");
912129794Stackerman
913129794Stackerman	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
914129794Stackerman		return (EINVAL);
915129794Stackerman
916129794Stackerman	return (0);
917129794Stackerman}
918129794Stackerman
919129794Stackerman/*********************************************************************
920129794Stackerman *
921129794Stackerman *  This routine maps the mbufs to tx descriptors.
922129794Stackerman *
923129794Stackerman *  return 0 on success, positive on failure
924129794Stackerman **********************************************************************/
925129794Stackerman
926129794Stackermanstatic int
927129794Stackermanixgb_encap(struct adapter * adapter, struct mbuf * m_head)
928129794Stackerman{
929129794Stackerman	u_int8_t        txd_popts;
930146339Salc	int             i, j, error, nsegs;
931129794Stackerman
932129794Stackerman#if __FreeBSD_version < 500000
933129794Stackerman	struct ifvlan  *ifv = NULL;
934129794Stackerman#endif
935146339Salc	bus_dma_segment_t segs[IXGB_MAX_SCATTER];
936146339Salc	bus_dmamap_t	map;
937129794Stackerman	struct ixgb_buffer *tx_buffer = NULL;
938129794Stackerman	struct ixgb_tx_desc *current_tx_desc = NULL;
939147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
940129794Stackerman
941129794Stackerman	/*
942129794Stackerman	 * Force a cleanup if number of TX descriptors available hits the
943129794Stackerman	 * threshold
944129794Stackerman	 */
945129794Stackerman	if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) {
946129794Stackerman		ixgb_clean_transmit_interrupts(adapter);
947129794Stackerman	}
948129794Stackerman	if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) {
949129794Stackerman		adapter->no_tx_desc_avail1++;
950129794Stackerman		return (ENOBUFS);
951129794Stackerman	}
952129794Stackerman	/*
953129794Stackerman	 * Map the packet for DMA.
954129794Stackerman	 */
955146339Salc	if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &map)) {
956129794Stackerman		adapter->no_tx_map_avail++;
957129794Stackerman		return (ENOMEM);
958129794Stackerman	}
959146339Salc	error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs,
960146339Salc					&nsegs, BUS_DMA_NOWAIT);
961129794Stackerman	if (error != 0) {
962129794Stackerman		adapter->no_tx_dma_setup++;
963198987Sjhb		if_printf(ifp, "ixgb_encap: bus_dmamap_load_mbuf failed; "
964198987Sjhb		       "error %u\n", error);
965146339Salc		bus_dmamap_destroy(adapter->txtag, map);
966129794Stackerman		return (error);
967129794Stackerman	}
968146339Salc	KASSERT(nsegs != 0, ("ixgb_encap: empty packet"));
969129794Stackerman
970146339Salc	if (nsegs > adapter->num_tx_desc_avail) {
971129794Stackerman		adapter->no_tx_desc_avail2++;
972146339Salc		bus_dmamap_destroy(adapter->txtag, map);
973129794Stackerman		return (ENOBUFS);
974129794Stackerman	}
975129794Stackerman	if (ifp->if_hwassist > 0) {
976129794Stackerman		ixgb_transmit_checksum_setup(adapter, m_head,
977129794Stackerman					     &txd_popts);
978129794Stackerman	} else
979129794Stackerman		txd_popts = 0;
980129794Stackerman
981129794Stackerman	/* Find out if we are in vlan mode */
982129794Stackerman#if __FreeBSD_version < 500000
983129794Stackerman	if ((m_head->m_flags & (M_PROTO1 | M_PKTHDR)) == (M_PROTO1 | M_PKTHDR) &&
984129794Stackerman	    m_head->m_pkthdr.rcvif != NULL &&
985129794Stackerman	    m_head->m_pkthdr.rcvif->if_type == IFT_L2VLAN)
986129794Stackerman		ifv = m_head->m_pkthdr.rcvif->if_softc;
987162375Sandre#elseif __FreeBSD_version < 700000
988129794Stackerman	mtag = VLAN_OUTPUT_TAG(ifp, m_head);
989129794Stackerman#endif
990129794Stackerman	i = adapter->next_avail_tx_desc;
991146339Salc	for (j = 0; j < nsegs; j++) {
992129794Stackerman		tx_buffer = &adapter->tx_buffer_area[i];
993129794Stackerman		current_tx_desc = &adapter->tx_desc_base[i];
994129794Stackerman
995146339Salc		current_tx_desc->buff_addr = htole64(segs[j].ds_addr);
996146339Salc		current_tx_desc->cmd_type_len = (adapter->txd_cmd | segs[j].ds_len);
997129794Stackerman		current_tx_desc->popts = txd_popts;
998129794Stackerman		if (++i == adapter->num_tx_desc)
999129794Stackerman			i = 0;
1000129794Stackerman
1001129794Stackerman		tx_buffer->m_head = NULL;
1002129794Stackerman	}
1003129794Stackerman
1004146339Salc	adapter->num_tx_desc_avail -= nsegs;
1005129794Stackerman	adapter->next_avail_tx_desc = i;
1006129794Stackerman
1007129794Stackerman#if __FreeBSD_version < 500000
1008129794Stackerman	if (ifv != NULL) {
1009129794Stackerman		/* Set the vlan id */
1010129794Stackerman		current_tx_desc->vlan = ifv->ifv_tag;
1011162375Sandre#elseif __FreeBSD_version < 700000
1012129794Stackerman	if (mtag != NULL) {
1013129794Stackerman		/* Set the vlan id */
1014129794Stackerman		current_tx_desc->vlan = VLAN_TAG_VALUE(mtag);
1015162375Sandre#else
1016162375Sandre	if (m_head->m_flags & M_VLANTAG) {
1017162375Sandre		current_tx_desc->vlan = m_head->m_pkthdr.ether_vtag;
1018129794Stackerman#endif
1019129794Stackerman
1020129794Stackerman		/* Tell hardware to add tag */
1021129794Stackerman		current_tx_desc->cmd_type_len |= IXGB_TX_DESC_CMD_VLE;
1022129794Stackerman	}
1023129794Stackerman	tx_buffer->m_head = m_head;
1024146339Salc	tx_buffer->map = map;
1025146339Salc	bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE);
1026129794Stackerman
1027129794Stackerman	/*
1028129794Stackerman	 * Last Descriptor of Packet needs End Of Packet (EOP)
1029129794Stackerman	 */
1030129794Stackerman	current_tx_desc->cmd_type_len |= (IXGB_TX_DESC_CMD_EOP);
1031129794Stackerman
1032129794Stackerman	/*
1033129794Stackerman	 * Advance the Transmit Descriptor Tail (Tdt), this tells the E1000
1034129794Stackerman	 * that this frame is available to transmit.
1035129794Stackerman	 */
1036129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDT, i);
1037129794Stackerman
1038129794Stackerman	return (0);
1039129794Stackerman}
1040129794Stackerman
1041129794Stackermanstatic void
1042129794Stackermanixgb_set_promisc(struct adapter * adapter)
1043129794Stackerman{
1044129794Stackerman
1045129794Stackerman	u_int32_t       reg_rctl;
1046147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
1047129794Stackerman
1048129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1049129794Stackerman
1050129794Stackerman	if (ifp->if_flags & IFF_PROMISC) {
1051129794Stackerman		reg_rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
1052129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1053129794Stackerman	} else if (ifp->if_flags & IFF_ALLMULTI) {
1054129794Stackerman		reg_rctl |= IXGB_RCTL_MPE;
1055129794Stackerman		reg_rctl &= ~IXGB_RCTL_UPE;
1056129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1057129794Stackerman	}
1058129794Stackerman	return;
1059129794Stackerman}
1060129794Stackerman
1061129794Stackermanstatic void
1062129794Stackermanixgb_disable_promisc(struct adapter * adapter)
1063129794Stackerman{
1064129794Stackerman	u_int32_t       reg_rctl;
1065129794Stackerman
1066129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1067129794Stackerman
1068129794Stackerman	reg_rctl &= (~IXGB_RCTL_UPE);
1069129794Stackerman	reg_rctl &= (~IXGB_RCTL_MPE);
1070129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1071129794Stackerman
1072129794Stackerman	return;
1073129794Stackerman}
1074129794Stackerman
1075129794Stackerman
1076129794Stackerman/*********************************************************************
1077129794Stackerman *  Multicast Update
1078129794Stackerman *
1079129794Stackerman *  This routine is called whenever multicast address list is updated.
1080129794Stackerman *
1081129794Stackerman **********************************************************************/
1082129794Stackerman
1083129794Stackermanstatic void
1084129794Stackermanixgb_set_multi(struct adapter * adapter)
1085129794Stackerman{
1086129794Stackerman	u_int32_t       reg_rctl = 0;
1087211913Syongari	u_int8_t        *mta;
1088129794Stackerman	struct ifmultiaddr *ifma;
1089129794Stackerman	int             mcnt = 0;
1090147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
1091129794Stackerman
1092129794Stackerman	IOCTL_DEBUGOUT("ixgb_set_multi: begin");
1093129794Stackerman
1094211913Syongari	mta = adapter->mta;
1095211913Syongari	bzero(mta, sizeof(u_int8_t) * IXGB_ETH_LENGTH_OF_ADDRESS *
1096211913Syongari	    MAX_NUM_MULTICAST_ADDRESSES);
1097211913Syongari
1098195049Srwatson	if_maddr_rlock(ifp);
1099129794Stackerman#if __FreeBSD_version < 500000
1100129794Stackerman	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1101129794Stackerman#else
1102129794Stackerman	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1103129794Stackerman#endif
1104129794Stackerman		if (ifma->ifma_addr->sa_family != AF_LINK)
1105129794Stackerman			continue;
1106129794Stackerman
1107129794Stackerman		bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
1108129794Stackerman		      &mta[mcnt * IXGB_ETH_LENGTH_OF_ADDRESS], IXGB_ETH_LENGTH_OF_ADDRESS);
1109129794Stackerman		mcnt++;
1110129794Stackerman	}
1111195049Srwatson	if_maddr_runlock(ifp);
1112129794Stackerman
1113129794Stackerman	if (mcnt > MAX_NUM_MULTICAST_ADDRESSES) {
1114129794Stackerman		reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1115129794Stackerman		reg_rctl |= IXGB_RCTL_MPE;
1116129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1117129794Stackerman	} else
1118129794Stackerman		ixgb_mc_addr_list_update(&adapter->hw, mta, mcnt, 0);
1119129794Stackerman
1120129794Stackerman	return;
1121129794Stackerman}
1122129794Stackerman
1123129794Stackerman
1124129794Stackerman/*********************************************************************
1125129794Stackerman *  Timer routine
1126129794Stackerman *
1127129794Stackerman *  This routine checks for link status and updates statistics.
1128129794Stackerman *
1129129794Stackerman **********************************************************************/
1130129794Stackerman
1131129794Stackermanstatic void
1132129794Stackermanixgb_local_timer(void *arg)
1133129794Stackerman{
1134129794Stackerman	struct ifnet   *ifp;
1135129794Stackerman	struct adapter *adapter = arg;
1136147256Sbrooks	ifp = adapter->ifp;
1137129794Stackerman
1138199539Sjhb	IXGB_LOCK_ASSERT(adapter);
1139129794Stackerman
1140129794Stackerman	ixgb_check_for_link(&adapter->hw);
1141129794Stackerman	ixgb_print_link_status(adapter);
1142129794Stackerman	ixgb_update_stats_counters(adapter);
1143148887Srwatson	if (ixgb_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) {
1144129794Stackerman		ixgb_print_hw_stats(adapter);
1145129794Stackerman	}
1146199539Sjhb	if (adapter->tx_timer != 0 && --adapter->tx_timer == 0)
1147199539Sjhb		ixgb_watchdog(adapter);
1148199539Sjhb	callout_reset(&adapter->timer, hz, ixgb_local_timer, adapter);
1149129794Stackerman}
1150129794Stackerman
1151129794Stackermanstatic void
1152129794Stackermanixgb_print_link_status(struct adapter * adapter)
1153129794Stackerman{
1154129794Stackerman	if (adapter->hw.link_up) {
1155129794Stackerman		if (!adapter->link_active) {
1156198987Sjhb			if_printf(adapter->ifp, "Link is up %d Mbps %s \n",
1157129794Stackerman			       10000,
1158129794Stackerman			       "Full Duplex");
1159129794Stackerman			adapter->link_active = 1;
1160129794Stackerman		}
1161129794Stackerman	} else {
1162129794Stackerman		if (adapter->link_active) {
1163198987Sjhb			if_printf(adapter->ifp, "Link is Down \n");
1164129794Stackerman			adapter->link_active = 0;
1165129794Stackerman		}
1166129794Stackerman	}
1167129794Stackerman
1168129794Stackerman	return;
1169129794Stackerman}
1170129794Stackerman
1171129794Stackerman
1172129794Stackerman
1173129794Stackerman/*********************************************************************
1174129794Stackerman *
1175129794Stackerman *  This routine disables all traffic on the adapter by issuing a
1176129794Stackerman *  global reset on the MAC and deallocates TX/RX buffers.
1177129794Stackerman *
1178129794Stackerman **********************************************************************/
1179129794Stackerman
1180129794Stackermanstatic void
1181129794Stackermanixgb_stop(void *arg)
1182129794Stackerman{
1183129794Stackerman	struct ifnet   *ifp;
1184129794Stackerman	struct adapter *adapter = arg;
1185147256Sbrooks	ifp = adapter->ifp;
1186129794Stackerman
1187144651Salc	IXGB_LOCK_ASSERT(adapter);
1188144651Salc
1189129794Stackerman	INIT_DEBUGOUT("ixgb_stop: begin\n");
1190129794Stackerman	ixgb_disable_intr(adapter);
1191129794Stackerman	adapter->hw.adapter_stopped = FALSE;
1192129794Stackerman	ixgb_adapter_stop(&adapter->hw);
1193144651Salc	callout_stop(&adapter->timer);
1194129794Stackerman	ixgb_free_transmit_structures(adapter);
1195129794Stackerman	ixgb_free_receive_structures(adapter);
1196129794Stackerman
1197129794Stackerman	/* Tell the stack that the interface is no longer active */
1198148887Srwatson	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1199199539Sjhb	adapter->tx_timer = 0;
1200129794Stackerman
1201129794Stackerman	return;
1202129794Stackerman}
1203129794Stackerman
1204129794Stackerman
1205129794Stackerman/*********************************************************************
1206129794Stackerman *
1207129794Stackerman *  Determine hardware revision.
1208129794Stackerman *
1209129794Stackerman **********************************************************************/
1210129794Stackermanstatic void
1211129794Stackermanixgb_identify_hardware(struct adapter * adapter)
1212129794Stackerman{
1213129794Stackerman	device_t        dev = adapter->dev;
1214129794Stackerman
1215129794Stackerman	/* Make sure our PCI config space has the necessary stuff set */
1216254263Sscottl	pci_enable_busmaster(dev);
1217129794Stackerman	adapter->hw.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);
1218254263Sscottl
1219129794Stackerman	/* Save off the information about this board */
1220129794Stackerman	adapter->hw.vendor_id = pci_get_vendor(dev);
1221129794Stackerman	adapter->hw.device_id = pci_get_device(dev);
1222129794Stackerman	adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1);
1223129794Stackerman	adapter->hw.subsystem_vendor_id = pci_read_config(dev, PCIR_SUBVEND_0, 2);
1224129794Stackerman	adapter->hw.subsystem_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
1225129794Stackerman
1226129794Stackerman	/* Set MacType, etc. based on this PCI info */
1227129794Stackerman	switch (adapter->hw.device_id) {
1228129794Stackerman	case IXGB_DEVICE_ID_82597EX:
1229129794Stackerman	case IXGB_DEVICE_ID_82597EX_SR:
1230129794Stackerman		adapter->hw.mac_type = ixgb_82597;
1231129794Stackerman		break;
1232129794Stackerman	default:
1233129794Stackerman		INIT_DEBUGOUT1("Unknown device if 0x%x", adapter->hw.device_id);
1234198987Sjhb		device_printf(dev, "unsupported device id 0x%x\n",
1235198987Sjhb		    adapter->hw.device_id);
1236129794Stackerman	}
1237129794Stackerman
1238129794Stackerman	return;
1239129794Stackerman}
1240129794Stackerman
1241129794Stackermanstatic int
1242129794Stackermanixgb_allocate_pci_resources(struct adapter * adapter)
1243129794Stackerman{
1244129794Stackerman	int             rid;
1245129794Stackerman	device_t        dev = adapter->dev;
1246129794Stackerman
1247129794Stackerman	rid = IXGB_MMBA;
1248295790Sjhibbits	adapter->res_memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
1249295790Sjhibbits						 &rid,
1250129794Stackerman						 RF_ACTIVE);
1251129794Stackerman	if (!(adapter->res_memory)) {
1252198987Sjhb		device_printf(dev, "Unable to allocate bus resource: memory\n");
1253129794Stackerman		return (ENXIO);
1254129794Stackerman	}
1255129794Stackerman	adapter->osdep.mem_bus_space_tag =
1256129794Stackerman		rman_get_bustag(adapter->res_memory);
1257129794Stackerman	adapter->osdep.mem_bus_space_handle =
1258129794Stackerman		rman_get_bushandle(adapter->res_memory);
1259129794Stackerman	adapter->hw.hw_addr = (uint8_t *) & adapter->osdep.mem_bus_space_handle;
1260129794Stackerman
1261129794Stackerman	rid = 0x0;
1262295790Sjhibbits	adapter->res_interrupt = bus_alloc_resource_any(dev, SYS_RES_IRQ,
1263295790Sjhibbits							&rid,
1264295790Sjhibbits							RF_SHAREABLE | RF_ACTIVE);
1265129794Stackerman	if (!(adapter->res_interrupt)) {
1266198987Sjhb		device_printf(dev,
1267198987Sjhb		    "Unable to allocate bus resource: interrupt\n");
1268129794Stackerman		return (ENXIO);
1269129794Stackerman	}
1270144651Salc	if (bus_setup_intr(dev, adapter->res_interrupt,
1271144651Salc			   INTR_TYPE_NET | INTR_MPSAFE,
1272166901Spiso			   NULL, (void (*) (void *))ixgb_intr, adapter,
1273129794Stackerman			   &adapter->int_handler_tag)) {
1274198987Sjhb		device_printf(dev, "Error registering interrupt handler!\n");
1275129794Stackerman		return (ENXIO);
1276129794Stackerman	}
1277129794Stackerman	adapter->hw.back = &adapter->osdep;
1278129794Stackerman
1279129794Stackerman	return (0);
1280129794Stackerman}
1281129794Stackerman
1282129794Stackermanstatic void
1283129794Stackermanixgb_free_pci_resources(struct adapter * adapter)
1284129794Stackerman{
1285129794Stackerman	device_t        dev = adapter->dev;
1286129794Stackerman
1287129794Stackerman	if (adapter->res_interrupt != NULL) {
1288129794Stackerman		bus_teardown_intr(dev, adapter->res_interrupt,
1289129794Stackerman				  adapter->int_handler_tag);
1290129794Stackerman		bus_release_resource(dev, SYS_RES_IRQ, 0,
1291129794Stackerman				     adapter->res_interrupt);
1292129794Stackerman	}
1293129794Stackerman	if (adapter->res_memory != NULL) {
1294129794Stackerman		bus_release_resource(dev, SYS_RES_MEMORY, IXGB_MMBA,
1295129794Stackerman				     adapter->res_memory);
1296129794Stackerman	}
1297129794Stackerman	if (adapter->res_ioport != NULL) {
1298129794Stackerman		bus_release_resource(dev, SYS_RES_IOPORT, adapter->io_rid,
1299129794Stackerman				     adapter->res_ioport);
1300129794Stackerman	}
1301129794Stackerman	return;
1302129794Stackerman}
1303129794Stackerman
1304129794Stackerman/*********************************************************************
1305129794Stackerman *
1306129794Stackerman *  Initialize the hardware to a configuration as specified by the
1307129794Stackerman *  adapter structure. The controller is reset, the EEPROM is
1308129794Stackerman *  verified, the MAC address is set, then the shared initialization
1309129794Stackerman *  routines are called.
1310129794Stackerman *
1311129794Stackerman **********************************************************************/
1312129794Stackermanstatic int
1313129794Stackermanixgb_hardware_init(struct adapter * adapter)
1314129794Stackerman{
1315129794Stackerman	/* Issue a global reset */
1316129794Stackerman	adapter->hw.adapter_stopped = FALSE;
1317129794Stackerman	ixgb_adapter_stop(&adapter->hw);
1318129794Stackerman
1319129794Stackerman	/* Make sure we have a good EEPROM before we read from it */
1320129794Stackerman	if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
1321198987Sjhb		device_printf(adapter->dev,
1322198987Sjhb		    "The EEPROM Checksum Is Not Valid\n");
1323129794Stackerman		return (EIO);
1324129794Stackerman	}
1325129794Stackerman	if (!ixgb_init_hw(&adapter->hw)) {
1326198987Sjhb		device_printf(adapter->dev, "Hardware Initialization Failed");
1327129794Stackerman		return (EIO);
1328129794Stackerman	}
1329129794Stackerman
1330129794Stackerman	return (0);
1331129794Stackerman}
1332129794Stackerman
1333129794Stackerman/*********************************************************************
1334129794Stackerman *
1335129794Stackerman *  Setup networking device structure and register an interface.
1336129794Stackerman *
1337129794Stackerman **********************************************************************/
1338211907Syongaristatic int
1339129794Stackermanixgb_setup_interface(device_t dev, struct adapter * adapter)
1340129794Stackerman{
1341129794Stackerman	struct ifnet   *ifp;
1342129794Stackerman	INIT_DEBUGOUT("ixgb_setup_interface: begin");
1343129794Stackerman
1344147256Sbrooks	ifp = adapter->ifp = if_alloc(IFT_ETHER);
1345211907Syongari	if (ifp == NULL) {
1346211907Syongari		device_printf(dev, "can not allocate ifnet structure\n");
1347211907Syongari		return (-1);
1348211907Syongari	}
1349129794Stackerman#if __FreeBSD_version >= 502000
1350129794Stackerman	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1351129794Stackerman#else
1352198987Sjhb	ifp->if_unit = device_get_unit(dev);
1353129794Stackerman	ifp->if_name = "ixgb";
1354129794Stackerman#endif
1355129794Stackerman	ifp->if_baudrate = 1000000000;
1356129794Stackerman	ifp->if_init = ixgb_init;
1357129794Stackerman	ifp->if_softc = adapter;
1358144651Salc	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1359129794Stackerman	ifp->if_ioctl = ixgb_ioctl;
1360129794Stackerman	ifp->if_start = ixgb_start;
1361272241Sglebius	ifp->if_get_counter = ixgb_get_counter;
1362129794Stackerman	ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 1;
1363129794Stackerman
1364129794Stackerman#if __FreeBSD_version < 500000
1365129794Stackerman	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
1366129794Stackerman#else
1367147256Sbrooks	ether_ifattach(ifp, adapter->hw.curr_mac_addr);
1368129794Stackerman#endif
1369129794Stackerman
1370129794Stackerman	ifp->if_capabilities = IFCAP_HWCSUM;
1371129794Stackerman
1372129794Stackerman	/*
1373129794Stackerman	 * Tell the upper layer(s) we support long frames.
1374129794Stackerman	 */
1375270856Sglebius	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
1376129794Stackerman
1377129794Stackerman#if __FreeBSD_version >= 500000
1378129794Stackerman	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
1379129794Stackerman#endif
1380148637Sbrueffer
1381148637Sbrueffer	ifp->if_capenable = ifp->if_capabilities;
1382148637Sbrueffer
1383150789Sglebius#ifdef DEVICE_POLLING
1384150789Sglebius	ifp->if_capabilities |= IFCAP_POLLING;
1385150789Sglebius#endif
1386150789Sglebius
1387129794Stackerman	/*
1388129794Stackerman	 * Specify the media types supported by this adapter and register
1389129794Stackerman	 * callbacks to update media and link information
1390129794Stackerman	 */
1391129794Stackerman	ifmedia_init(&adapter->media, IFM_IMASK, ixgb_media_change,
1392129794Stackerman		     ixgb_media_status);
1393129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX | IFM_FDX,
1394129794Stackerman		    0, NULL);
1395129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX,
1396129794Stackerman		    0, NULL);
1397129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
1398129794Stackerman	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
1399129794Stackerman
1400211907Syongari	return (0);
1401129794Stackerman}
1402129794Stackerman
1403129794Stackerman/********************************************************************
1404129794Stackerman * Manage DMA'able memory.
1405129794Stackerman *******************************************************************/
1406129794Stackermanstatic void
1407129794Stackermanixgb_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg, int error)
1408129794Stackerman{
1409129794Stackerman	if (error)
1410129794Stackerman		return;
1411129794Stackerman	*(bus_addr_t *) arg = segs->ds_addr;
1412129794Stackerman	return;
1413129794Stackerman}
1414129794Stackerman
1415129794Stackermanstatic int
1416129794Stackermanixgb_dma_malloc(struct adapter * adapter, bus_size_t size,
1417129794Stackerman		struct ixgb_dma_alloc * dma, int mapflags)
1418129794Stackerman{
1419198987Sjhb	device_t dev;
1420129794Stackerman	int             r;
1421129794Stackerman
1422198987Sjhb	dev = adapter->dev;
1423232874Sscottl	r = bus_dma_tag_create(bus_get_dma_tag(dev),	/* parent */
1424129794Stackerman			       PAGE_SIZE, 0,	/* alignment, bounds */
1425129794Stackerman			       BUS_SPACE_MAXADDR,	/* lowaddr */
1426129794Stackerman			       BUS_SPACE_MAXADDR,	/* highaddr */
1427129794Stackerman			       NULL, NULL,	/* filter, filterarg */
1428129794Stackerman			       size,	/* maxsize */
1429129794Stackerman			       1,	/* nsegments */
1430129794Stackerman			       size,	/* maxsegsize */
1431129794Stackerman			       BUS_DMA_ALLOCNOW,	/* flags */
1432129794Stackerman#if __FreeBSD_version >= 502000
1433129794Stackerman			       NULL,	/* lockfunc */
1434129794Stackerman			       NULL,	/* lockfuncarg */
1435129794Stackerman#endif
1436129794Stackerman			       &dma->dma_tag);
1437129794Stackerman	if (r != 0) {
1438198987Sjhb		device_printf(dev, "ixgb_dma_malloc: bus_dma_tag_create failed; "
1439198987Sjhb		       "error %u\n", r);
1440129794Stackerman		goto fail_0;
1441129794Stackerman	}
1442129794Stackerman	r = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr,
1443129794Stackerman			     BUS_DMA_NOWAIT, &dma->dma_map);
1444129794Stackerman	if (r != 0) {
1445198987Sjhb		device_printf(dev, "ixgb_dma_malloc: bus_dmamem_alloc failed; "
1446198987Sjhb		       "error %u\n", r);
1447144183Smux		goto fail_1;
1448129794Stackerman	}
1449129794Stackerman	r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
1450129794Stackerman			    size,
1451129794Stackerman			    ixgb_dmamap_cb,
1452129794Stackerman			    &dma->dma_paddr,
1453129794Stackerman			    mapflags | BUS_DMA_NOWAIT);
1454129794Stackerman	if (r != 0) {
1455198987Sjhb		device_printf(dev, "ixgb_dma_malloc: bus_dmamap_load failed; "
1456198987Sjhb		       "error %u\n", r);
1457144183Smux		goto fail_2;
1458129794Stackerman	}
1459129794Stackerman	dma->dma_size = size;
1460129794Stackerman	return (0);
1461129794Stackermanfail_2:
1462129794Stackerman	bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
1463129794Stackermanfail_1:
1464129794Stackerman	bus_dma_tag_destroy(dma->dma_tag);
1465129794Stackermanfail_0:
1466129794Stackerman	dma->dma_tag = NULL;
1467129794Stackerman	return (r);
1468129794Stackerman}
1469129794Stackerman
1470129794Stackerman
1471129794Stackerman
1472129794Stackermanstatic void
1473129794Stackermanixgb_dma_free(struct adapter * adapter, struct ixgb_dma_alloc * dma)
1474129794Stackerman{
1475129794Stackerman	bus_dmamap_unload(dma->dma_tag, dma->dma_map);
1476129794Stackerman	bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
1477129794Stackerman	bus_dma_tag_destroy(dma->dma_tag);
1478129794Stackerman}
1479129794Stackerman
1480129794Stackerman/*********************************************************************
1481129794Stackerman *
1482129794Stackerman *  Allocate memory for tx_buffer structures. The tx_buffer stores all
1483129794Stackerman *  the information needed to transmit a packet on the wire.
1484129794Stackerman *
1485129794Stackerman **********************************************************************/
1486129794Stackermanstatic int
1487129794Stackermanixgb_allocate_transmit_structures(struct adapter * adapter)
1488129794Stackerman{
1489129794Stackerman	if (!(adapter->tx_buffer_area =
1490129794Stackerman	      (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) *
1491129794Stackerman					    adapter->num_tx_desc, M_DEVBUF,
1492129794Stackerman					    M_NOWAIT | M_ZERO))) {
1493198987Sjhb		device_printf(adapter->dev,
1494198987Sjhb		    "Unable to allocate tx_buffer memory\n");
1495129794Stackerman		return ENOMEM;
1496129794Stackerman	}
1497129794Stackerman	bzero(adapter->tx_buffer_area,
1498129794Stackerman	      sizeof(struct ixgb_buffer) * adapter->num_tx_desc);
1499129794Stackerman
1500129794Stackerman	return 0;
1501129794Stackerman}
1502129794Stackerman
1503129794Stackerman/*********************************************************************
1504129794Stackerman *
1505129794Stackerman *  Allocate and initialize transmit structures.
1506129794Stackerman *
1507129794Stackerman **********************************************************************/
1508129794Stackermanstatic int
1509129794Stackermanixgb_setup_transmit_structures(struct adapter * adapter)
1510129794Stackerman{
1511129794Stackerman	/*
1512129794Stackerman	 * Setup DMA descriptor areas.
1513129794Stackerman	 */
1514232874Sscottl	if (bus_dma_tag_create(bus_get_dma_tag(adapter->dev),	/* parent */
1515129794Stackerman			       PAGE_SIZE, 0,	/* alignment, bounds */
1516129794Stackerman			       BUS_SPACE_MAXADDR,	/* lowaddr */
1517129794Stackerman			       BUS_SPACE_MAXADDR,	/* highaddr */
1518129794Stackerman			       NULL, NULL,	/* filter, filterarg */
1519129794Stackerman			       MCLBYTES * IXGB_MAX_SCATTER,	/* maxsize */
1520129794Stackerman			       IXGB_MAX_SCATTER,	/* nsegments */
1521129794Stackerman			       MCLBYTES,	/* maxsegsize */
1522129794Stackerman			       BUS_DMA_ALLOCNOW,	/* flags */
1523129794Stackerman#if __FreeBSD_version >= 502000
1524129794Stackerman			       NULL,	/* lockfunc */
1525129794Stackerman			       NULL,	/* lockfuncarg */
1526129794Stackerman#endif
1527129794Stackerman			       &adapter->txtag)) {
1528198987Sjhb		device_printf(adapter->dev, "Unable to allocate TX DMA tag\n");
1529129794Stackerman		return (ENOMEM);
1530129794Stackerman	}
1531129794Stackerman	if (ixgb_allocate_transmit_structures(adapter))
1532129794Stackerman		return ENOMEM;
1533129794Stackerman
1534129794Stackerman	bzero((void *)adapter->tx_desc_base,
1535129794Stackerman	      (sizeof(struct ixgb_tx_desc)) * adapter->num_tx_desc);
1536129794Stackerman
1537129794Stackerman	adapter->next_avail_tx_desc = 0;
1538129794Stackerman	adapter->oldest_used_tx_desc = 0;
1539129794Stackerman
1540129794Stackerman	/* Set number of descriptors available */
1541129794Stackerman	adapter->num_tx_desc_avail = adapter->num_tx_desc;
1542129794Stackerman
1543129794Stackerman	/* Set checksum context */
1544129794Stackerman	adapter->active_checksum_context = OFFLOAD_NONE;
1545129794Stackerman
1546129794Stackerman	return 0;
1547129794Stackerman}
1548129794Stackerman
1549129794Stackerman/*********************************************************************
1550129794Stackerman *
1551129794Stackerman *  Enable transmit unit.
1552129794Stackerman *
1553129794Stackerman **********************************************************************/
1554129794Stackermanstatic void
1555129794Stackermanixgb_initialize_transmit_unit(struct adapter * adapter)
1556129794Stackerman{
1557129794Stackerman	u_int32_t       reg_tctl;
1558144183Smux	u_int64_t       tdba = adapter->txdma.dma_paddr;
1559129794Stackerman
1560129794Stackerman	/* Setup the Base and Length of the Tx Descriptor Ring */
1561129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDBAL,
1562129794Stackerman		       (tdba & 0x00000000ffffffffULL));
1563129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
1564129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDLEN,
1565129794Stackerman		       adapter->num_tx_desc *
1566129794Stackerman		       sizeof(struct ixgb_tx_desc));
1567129794Stackerman
1568129794Stackerman	/* Setup the HW Tx Head and Tail descriptor pointers */
1569129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDH, 0);
1570129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDT, 0);
1571129794Stackerman
1572129794Stackerman
1573129794Stackerman	HW_DEBUGOUT2("Base = %x, Length = %x\n",
1574129794Stackerman		     IXGB_READ_REG(&adapter->hw, TDBAL),
1575129794Stackerman		     IXGB_READ_REG(&adapter->hw, TDLEN));
1576129794Stackerman
1577129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay);
1578129794Stackerman
1579129794Stackerman
1580129794Stackerman	/* Program the Transmit Control Register */
1581129794Stackerman	reg_tctl = IXGB_READ_REG(&adapter->hw, TCTL);
1582129794Stackerman	reg_tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE;
1583129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TCTL, reg_tctl);
1584129794Stackerman
1585129794Stackerman	/* Setup Transmit Descriptor Settings for this adapter */
1586129794Stackerman	adapter->txd_cmd = IXGB_TX_DESC_TYPE | IXGB_TX_DESC_CMD_RS;
1587129794Stackerman
1588129794Stackerman	if (adapter->tx_int_delay > 0)
1589129794Stackerman		adapter->txd_cmd |= IXGB_TX_DESC_CMD_IDE;
1590129794Stackerman	return;
1591129794Stackerman}
1592129794Stackerman
1593129794Stackerman/*********************************************************************
1594129794Stackerman *
1595129794Stackerman *  Free all transmit related data structures.
1596129794Stackerman *
1597129794Stackerman **********************************************************************/
1598129794Stackermanstatic void
1599129794Stackermanixgb_free_transmit_structures(struct adapter * adapter)
1600129794Stackerman{
1601129794Stackerman	struct ixgb_buffer *tx_buffer;
1602129794Stackerman	int             i;
1603129794Stackerman
1604129794Stackerman	INIT_DEBUGOUT("free_transmit_structures: begin");
1605129794Stackerman
1606129794Stackerman	if (adapter->tx_buffer_area != NULL) {
1607129794Stackerman		tx_buffer = adapter->tx_buffer_area;
1608129794Stackerman		for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
1609129794Stackerman			if (tx_buffer->m_head != NULL) {
1610129794Stackerman				bus_dmamap_unload(adapter->txtag, tx_buffer->map);
1611129794Stackerman				bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
1612129794Stackerman				m_freem(tx_buffer->m_head);
1613129794Stackerman			}
1614129794Stackerman			tx_buffer->m_head = NULL;
1615129794Stackerman		}
1616129794Stackerman	}
1617129794Stackerman	if (adapter->tx_buffer_area != NULL) {
1618129794Stackerman		free(adapter->tx_buffer_area, M_DEVBUF);
1619129794Stackerman		adapter->tx_buffer_area = NULL;
1620129794Stackerman	}
1621129794Stackerman	if (adapter->txtag != NULL) {
1622129794Stackerman		bus_dma_tag_destroy(adapter->txtag);
1623129794Stackerman		adapter->txtag = NULL;
1624129794Stackerman	}
1625129794Stackerman	return;
1626129794Stackerman}
1627129794Stackerman
1628129794Stackerman/*********************************************************************
1629129794Stackerman *
1630129794Stackerman *  The offload context needs to be set when we transfer the first
1631129794Stackerman *  packet of a particular protocol (TCP/UDP). We change the
1632129794Stackerman *  context only if the protocol type changes.
1633129794Stackerman *
1634129794Stackerman **********************************************************************/
1635129794Stackermanstatic void
1636129794Stackermanixgb_transmit_checksum_setup(struct adapter * adapter,
1637129794Stackerman			     struct mbuf * mp,
1638129794Stackerman			     u_int8_t * txd_popts)
1639129794Stackerman{
1640129794Stackerman	struct ixgb_context_desc *TXD;
1641129794Stackerman	struct ixgb_buffer *tx_buffer;
1642129794Stackerman	int             curr_txd;
1643129794Stackerman
1644129794Stackerman	if (mp->m_pkthdr.csum_flags) {
1645129794Stackerman
1646129794Stackerman		if (mp->m_pkthdr.csum_flags & CSUM_TCP) {
1647129794Stackerman			*txd_popts = IXGB_TX_DESC_POPTS_TXSM;
1648129794Stackerman			if (adapter->active_checksum_context == OFFLOAD_TCP_IP)
1649129794Stackerman				return;
1650129794Stackerman			else
1651129794Stackerman				adapter->active_checksum_context = OFFLOAD_TCP_IP;
1652129794Stackerman		} else if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
1653129794Stackerman			*txd_popts = IXGB_TX_DESC_POPTS_TXSM;
1654129794Stackerman			if (adapter->active_checksum_context == OFFLOAD_UDP_IP)
1655129794Stackerman				return;
1656129794Stackerman			else
1657129794Stackerman				adapter->active_checksum_context = OFFLOAD_UDP_IP;
1658129794Stackerman		} else {
1659129794Stackerman			*txd_popts = 0;
1660129794Stackerman			return;
1661129794Stackerman		}
1662129794Stackerman	} else {
1663129794Stackerman		*txd_popts = 0;
1664129794Stackerman		return;
1665129794Stackerman	}
1666129794Stackerman
1667129794Stackerman	/*
1668129794Stackerman	 * If we reach this point, the checksum offload context needs to be
1669129794Stackerman	 * reset.
1670129794Stackerman	 */
1671129794Stackerman	curr_txd = adapter->next_avail_tx_desc;
1672129794Stackerman	tx_buffer = &adapter->tx_buffer_area[curr_txd];
1673129794Stackerman	TXD = (struct ixgb_context_desc *) & adapter->tx_desc_base[curr_txd];
1674129794Stackerman
1675129794Stackerman
1676129794Stackerman	TXD->tucss = ENET_HEADER_SIZE + sizeof(struct ip);
1677129794Stackerman	TXD->tucse = 0;
1678129794Stackerman
1679129794Stackerman	TXD->mss = 0;
1680129794Stackerman
1681129794Stackerman	if (adapter->active_checksum_context == OFFLOAD_TCP_IP) {
1682129794Stackerman		TXD->tucso =
1683129794Stackerman			ENET_HEADER_SIZE + sizeof(struct ip) +
1684129794Stackerman			offsetof(struct tcphdr, th_sum);
1685129794Stackerman	} else if (adapter->active_checksum_context == OFFLOAD_UDP_IP) {
1686129794Stackerman		TXD->tucso =
1687129794Stackerman			ENET_HEADER_SIZE + sizeof(struct ip) +
1688129794Stackerman			offsetof(struct udphdr, uh_sum);
1689129794Stackerman	}
1690129794Stackerman	TXD->cmd_type_len = IXGB_CONTEXT_DESC_CMD_TCP | IXGB_TX_DESC_CMD_RS | IXGB_CONTEXT_DESC_CMD_IDE;
1691129794Stackerman
1692129794Stackerman	tx_buffer->m_head = NULL;
1693129794Stackerman
1694129794Stackerman	if (++curr_txd == adapter->num_tx_desc)
1695129794Stackerman		curr_txd = 0;
1696129794Stackerman
1697129794Stackerman	adapter->num_tx_desc_avail--;
1698129794Stackerman	adapter->next_avail_tx_desc = curr_txd;
1699129794Stackerman	return;
1700129794Stackerman}
1701129794Stackerman
1702129794Stackerman/**********************************************************************
1703129794Stackerman *
1704129794Stackerman *  Examine each tx_buffer in the used queue. If the hardware is done
1705129794Stackerman *  processing the packet then free associated resources. The
1706129794Stackerman *  tx_buffer is put back on the free queue.
1707129794Stackerman *
1708129794Stackerman **********************************************************************/
1709129794Stackermanstatic void
1710129794Stackermanixgb_clean_transmit_interrupts(struct adapter * adapter)
1711129794Stackerman{
1712129794Stackerman	int             i, num_avail;
1713129794Stackerman	struct ixgb_buffer *tx_buffer;
1714129794Stackerman	struct ixgb_tx_desc *tx_desc;
1715129794Stackerman
1716144651Salc	IXGB_LOCK_ASSERT(adapter);
1717129794Stackerman
1718129794Stackerman	if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
1719129794Stackerman		return;
1720129794Stackerman
1721129794Stackerman#ifdef _SV_
1722129794Stackerman	adapter->clean_tx_interrupts++;
1723129794Stackerman#endif
1724129794Stackerman	num_avail = adapter->num_tx_desc_avail;
1725129794Stackerman	i = adapter->oldest_used_tx_desc;
1726129794Stackerman
1727129794Stackerman	tx_buffer = &adapter->tx_buffer_area[i];
1728129794Stackerman	tx_desc = &adapter->tx_desc_base[i];
1729129794Stackerman
1730129794Stackerman	while (tx_desc->status & IXGB_TX_DESC_STATUS_DD) {
1731129794Stackerman
1732129794Stackerman		tx_desc->status = 0;
1733129794Stackerman		num_avail++;
1734129794Stackerman
1735129794Stackerman		if (tx_buffer->m_head) {
1736129794Stackerman			bus_dmamap_sync(adapter->txtag, tx_buffer->map,
1737129794Stackerman					BUS_DMASYNC_POSTWRITE);
1738129794Stackerman			bus_dmamap_unload(adapter->txtag, tx_buffer->map);
1739129794Stackerman			bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
1740129794Stackerman			m_freem(tx_buffer->m_head);
1741129794Stackerman			tx_buffer->m_head = NULL;
1742129794Stackerman		}
1743129794Stackerman		if (++i == adapter->num_tx_desc)
1744129794Stackerman			i = 0;
1745129794Stackerman
1746129794Stackerman		tx_buffer = &adapter->tx_buffer_area[i];
1747129794Stackerman		tx_desc = &adapter->tx_desc_base[i];
1748129794Stackerman	}
1749129794Stackerman
1750129794Stackerman	adapter->oldest_used_tx_desc = i;
1751129794Stackerman
1752129794Stackerman	/*
1753148887Srwatson	 * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that
1754129794Stackerman	 * it is OK to send packets. If there are no pending descriptors,
1755129794Stackerman	 * clear the timeout. Otherwise, if some descriptors have been freed,
1756129794Stackerman	 * restart the timeout.
1757129794Stackerman	 */
1758129794Stackerman	if (num_avail > IXGB_TX_CLEANUP_THRESHOLD) {
1759147256Sbrooks		struct ifnet   *ifp = adapter->ifp;
1760129794Stackerman
1761148887Srwatson		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1762129794Stackerman		if (num_avail == adapter->num_tx_desc)
1763199539Sjhb			adapter->tx_timer = 0;
1764129794Stackerman		else if (num_avail == adapter->num_tx_desc_avail)
1765199539Sjhb			adapter->tx_timer = IXGB_TX_TIMEOUT;
1766129794Stackerman	}
1767129794Stackerman	adapter->num_tx_desc_avail = num_avail;
1768129794Stackerman	return;
1769129794Stackerman}
1770129794Stackerman
1771129794Stackerman
1772129794Stackerman/*********************************************************************
1773129794Stackerman *
1774129794Stackerman *  Get a buffer from system mbuf buffer pool.
1775129794Stackerman *
1776129794Stackerman **********************************************************************/
1777129794Stackermanstatic int
1778129794Stackermanixgb_get_buf(int i, struct adapter * adapter,
1779129794Stackerman	     struct mbuf * nmp)
1780129794Stackerman{
1781331643Sdim	struct mbuf    *mp = nmp;
1782129794Stackerman	struct ixgb_buffer *rx_buffer;
1783129794Stackerman	struct ifnet   *ifp;
1784129794Stackerman	bus_addr_t      paddr;
1785129794Stackerman	int             error;
1786129794Stackerman
1787147256Sbrooks	ifp = adapter->ifp;
1788129794Stackerman
1789129794Stackerman	if (mp == NULL) {
1790129794Stackerman
1791243857Sglebius		mp = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1792129794Stackerman
1793129794Stackerman		if (mp == NULL) {
1794129794Stackerman			adapter->mbuf_alloc_failed++;
1795129794Stackerman			return (ENOBUFS);
1796129794Stackerman		}
1797129794Stackerman		mp->m_len = mp->m_pkthdr.len = MCLBYTES;
1798129794Stackerman	} else {
1799129794Stackerman		mp->m_len = mp->m_pkthdr.len = MCLBYTES;
1800129794Stackerman		mp->m_data = mp->m_ext.ext_buf;
1801129794Stackerman		mp->m_next = NULL;
1802129794Stackerman	}
1803129794Stackerman
1804129794Stackerman	if (ifp->if_mtu <= ETHERMTU) {
1805129794Stackerman		m_adj(mp, ETHER_ALIGN);
1806129794Stackerman	}
1807129794Stackerman	rx_buffer = &adapter->rx_buffer_area[i];
1808129794Stackerman
1809129794Stackerman	/*
1810129794Stackerman	 * Using memory from the mbuf cluster pool, invoke the bus_dma
1811129794Stackerman	 * machinery to arrange the memory mapping.
1812129794Stackerman	 */
1813129794Stackerman	error = bus_dmamap_load(adapter->rxtag, rx_buffer->map,
1814129794Stackerman				mtod(mp, void *), mp->m_len,
1815129794Stackerman				ixgb_dmamap_cb, &paddr, 0);
1816129794Stackerman	if (error) {
1817129794Stackerman		m_free(mp);
1818129794Stackerman		return (error);
1819129794Stackerman	}
1820129794Stackerman	rx_buffer->m_head = mp;
1821129794Stackerman	adapter->rx_desc_base[i].buff_addr = htole64(paddr);
1822129794Stackerman	bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD);
1823129794Stackerman
1824129794Stackerman	return (0);
1825129794Stackerman}
1826129794Stackerman
1827129794Stackerman/*********************************************************************
1828129794Stackerman *
1829129794Stackerman *  Allocate memory for rx_buffer structures. Since we use one
1830129794Stackerman *  rx_buffer per received packet, the maximum number of rx_buffer's
1831129794Stackerman *  that we'll need is equal to the number of receive descriptors
1832129794Stackerman *  that we've allocated.
1833129794Stackerman *
1834129794Stackerman **********************************************************************/
1835129794Stackermanstatic int
1836129794Stackermanixgb_allocate_receive_structures(struct adapter * adapter)
1837129794Stackerman{
1838129794Stackerman	int             i, error;
1839129794Stackerman	struct ixgb_buffer *rx_buffer;
1840129794Stackerman
1841129794Stackerman	if (!(adapter->rx_buffer_area =
1842129794Stackerman	      (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) *
1843129794Stackerman					    adapter->num_rx_desc, M_DEVBUF,
1844129794Stackerman					    M_NOWAIT | M_ZERO))) {
1845198987Sjhb		device_printf(adapter->dev,
1846198987Sjhb		    "Unable to allocate rx_buffer memory\n");
1847129794Stackerman		return (ENOMEM);
1848129794Stackerman	}
1849129794Stackerman	bzero(adapter->rx_buffer_area,
1850129794Stackerman	      sizeof(struct ixgb_buffer) * adapter->num_rx_desc);
1851129794Stackerman
1852232874Sscottl	error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev),/* parent */
1853129794Stackerman				   PAGE_SIZE, 0,	/* alignment, bounds */
1854129794Stackerman				   BUS_SPACE_MAXADDR,	/* lowaddr */
1855129794Stackerman				   BUS_SPACE_MAXADDR,	/* highaddr */
1856129794Stackerman				   NULL, NULL,	/* filter, filterarg */
1857129794Stackerman				   MCLBYTES,	/* maxsize */
1858129794Stackerman				   1,	/* nsegments */
1859129794Stackerman				   MCLBYTES,	/* maxsegsize */
1860129794Stackerman				   BUS_DMA_ALLOCNOW,	/* flags */
1861129794Stackerman#if __FreeBSD_version >= 502000
1862129794Stackerman				   NULL,	/* lockfunc */
1863129794Stackerman				   NULL,	/* lockfuncarg */
1864129794Stackerman#endif
1865129794Stackerman				   &adapter->rxtag);
1866129794Stackerman	if (error != 0) {
1867198987Sjhb		device_printf(adapter->dev, "ixgb_allocate_receive_structures: "
1868129794Stackerman		       "bus_dma_tag_create failed; error %u\n",
1869198987Sjhb		       error);
1870129794Stackerman		goto fail_0;
1871129794Stackerman	}
1872129794Stackerman	rx_buffer = adapter->rx_buffer_area;
1873129794Stackerman	for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
1874129794Stackerman		error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT,
1875129794Stackerman					  &rx_buffer->map);
1876129794Stackerman		if (error != 0) {
1877198987Sjhb			device_printf(adapter->dev,
1878198987Sjhb			       "ixgb_allocate_receive_structures: "
1879129794Stackerman			       "bus_dmamap_create failed; error %u\n",
1880198987Sjhb			       error);
1881129794Stackerman			goto fail_1;
1882129794Stackerman		}
1883129794Stackerman	}
1884129794Stackerman
1885129794Stackerman	for (i = 0; i < adapter->num_rx_desc; i++) {
1886129794Stackerman		if (ixgb_get_buf(i, adapter, NULL) == ENOBUFS) {
1887129794Stackerman			adapter->rx_buffer_area[i].m_head = NULL;
1888129794Stackerman			adapter->rx_desc_base[i].buff_addr = 0;
1889129794Stackerman			return (ENOBUFS);
1890129794Stackerman		}
1891129794Stackerman	}
1892129794Stackerman
1893129794Stackerman	return (0);
1894129794Stackermanfail_1:
1895129794Stackerman	bus_dma_tag_destroy(adapter->rxtag);
1896129794Stackermanfail_0:
1897129794Stackerman	adapter->rxtag = NULL;
1898129794Stackerman	free(adapter->rx_buffer_area, M_DEVBUF);
1899129794Stackerman	adapter->rx_buffer_area = NULL;
1900129794Stackerman	return (error);
1901129794Stackerman}
1902129794Stackerman
1903129794Stackerman/*********************************************************************
1904129794Stackerman *
1905129794Stackerman *  Allocate and initialize receive structures.
1906129794Stackerman *
1907129794Stackerman **********************************************************************/
1908129794Stackermanstatic int
1909129794Stackermanixgb_setup_receive_structures(struct adapter * adapter)
1910129794Stackerman{
1911129794Stackerman	bzero((void *)adapter->rx_desc_base,
1912129794Stackerman	      (sizeof(struct ixgb_rx_desc)) * adapter->num_rx_desc);
1913129794Stackerman
1914129794Stackerman	if (ixgb_allocate_receive_structures(adapter))
1915129794Stackerman		return ENOMEM;
1916129794Stackerman
1917129794Stackerman	/* Setup our descriptor pointers */
1918129794Stackerman	adapter->next_rx_desc_to_check = 0;
1919129794Stackerman	adapter->next_rx_desc_to_use = 0;
1920129794Stackerman	return (0);
1921129794Stackerman}
1922129794Stackerman
1923129794Stackerman/*********************************************************************
1924129794Stackerman *
1925129794Stackerman *  Enable receive unit.
1926129794Stackerman *
1927129794Stackerman **********************************************************************/
1928129794Stackermanstatic void
1929129794Stackermanixgb_initialize_receive_unit(struct adapter * adapter)
1930129794Stackerman{
1931129794Stackerman	u_int32_t       reg_rctl;
1932129794Stackerman	u_int32_t       reg_rxcsum;
1933129794Stackerman	u_int32_t       reg_rxdctl;
1934129794Stackerman	struct ifnet   *ifp;
1935144183Smux	u_int64_t       rdba = adapter->rxdma.dma_paddr;
1936129794Stackerman
1937147256Sbrooks	ifp = adapter->ifp;
1938129794Stackerman
1939129794Stackerman	/*
1940129794Stackerman	 * Make sure receives are disabled while setting up the descriptor
1941129794Stackerman	 * ring
1942129794Stackerman	 */
1943129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1944129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl & ~IXGB_RCTL_RXEN);
1945129794Stackerman
1946129794Stackerman	/* Set the Receive Delay Timer Register */
1947129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDTR,
1948129794Stackerman		       adapter->rx_int_delay);
1949129794Stackerman
1950129794Stackerman
1951129794Stackerman	/* Setup the Base and Length of the Rx Descriptor Ring */
1952129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDBAL,
1953129794Stackerman		       (rdba & 0x00000000ffffffffULL));
1954129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
1955129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDLEN, adapter->num_rx_desc *
1956129794Stackerman		       sizeof(struct ixgb_rx_desc));
1957129794Stackerman
1958129794Stackerman	/* Setup the HW Rx Head and Tail Descriptor Pointers */
1959129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDH, 0);
1960129794Stackerman
1961129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDT, adapter->num_rx_desc - 1);
1962129794Stackerman
1963129794Stackerman
1964129794Stackerman
1965129794Stackerman	reg_rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
1966129794Stackerman		| RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
1967129794Stackerman		| RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
1968129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RXDCTL, reg_rxdctl);
1969129794Stackerman
1970129794Stackerman
1971129794Stackerman	adapter->raidc = 1;
1972129794Stackerman	if (adapter->raidc) {
1973129794Stackerman		uint32_t        raidc;
1974129794Stackerman		uint8_t         poll_threshold;
1975129794Stackerman#define IXGB_RAIDC_POLL_DEFAULT 120
1976129794Stackerman
1977129794Stackerman		poll_threshold = ((adapter->num_rx_desc - 1) >> 3);
1978129794Stackerman		poll_threshold >>= 1;
1979129794Stackerman		poll_threshold &= 0x3F;
1980129794Stackerman		raidc = IXGB_RAIDC_EN | IXGB_RAIDC_RXT_GATE |
1981129794Stackerman			(IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) |
1982129794Stackerman			(adapter->rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) |
1983129794Stackerman			poll_threshold;
1984129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RAIDC, raidc);
1985129794Stackerman	}
1986129794Stackerman	/* Enable Receive Checksum Offload for TCP and UDP ? */
1987129794Stackerman	if (ifp->if_capenable & IFCAP_RXCSUM) {
1988129794Stackerman		reg_rxcsum = IXGB_READ_REG(&adapter->hw, RXCSUM);
1989129794Stackerman		reg_rxcsum |= IXGB_RXCSUM_TUOFL;
1990129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RXCSUM, reg_rxcsum);
1991129794Stackerman	}
1992129794Stackerman	/* Setup the Receive Control Register */
1993129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1994129794Stackerman	reg_rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
1995129794Stackerman	reg_rctl |= IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 | IXGB_RCTL_SECRC |
1996129794Stackerman		IXGB_RCTL_CFF |
1997129794Stackerman		(adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
1998129794Stackerman
1999129794Stackerman	switch (adapter->rx_buffer_len) {
2000129794Stackerman	default:
2001129794Stackerman	case IXGB_RXBUFFER_2048:
2002129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_2048;
2003129794Stackerman		break;
2004129794Stackerman	case IXGB_RXBUFFER_4096:
2005129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_4096;
2006129794Stackerman		break;
2007129794Stackerman	case IXGB_RXBUFFER_8192:
2008129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_8192;
2009129794Stackerman		break;
2010129794Stackerman	case IXGB_RXBUFFER_16384:
2011129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_16384;
2012129794Stackerman		break;
2013129794Stackerman	}
2014129794Stackerman
2015129794Stackerman	reg_rctl |= IXGB_RCTL_RXEN;
2016129794Stackerman
2017129794Stackerman
2018129794Stackerman	/* Enable Receives */
2019129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
2020129794Stackerman
2021129794Stackerman	return;
2022129794Stackerman}
2023129794Stackerman
2024129794Stackerman/*********************************************************************
2025129794Stackerman *
2026129794Stackerman *  Free receive related data structures.
2027129794Stackerman *
2028129794Stackerman **********************************************************************/
2029129794Stackermanstatic void
2030129794Stackermanixgb_free_receive_structures(struct adapter * adapter)
2031129794Stackerman{
2032129794Stackerman	struct ixgb_buffer *rx_buffer;
2033129794Stackerman	int             i;
2034129794Stackerman
2035129794Stackerman	INIT_DEBUGOUT("free_receive_structures: begin");
2036129794Stackerman
2037129794Stackerman	if (adapter->rx_buffer_area != NULL) {
2038129794Stackerman		rx_buffer = adapter->rx_buffer_area;
2039129794Stackerman		for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
2040129794Stackerman			if (rx_buffer->map != NULL) {
2041129794Stackerman				bus_dmamap_unload(adapter->rxtag, rx_buffer->map);
2042129794Stackerman				bus_dmamap_destroy(adapter->rxtag, rx_buffer->map);
2043129794Stackerman			}
2044129794Stackerman			if (rx_buffer->m_head != NULL)
2045129794Stackerman				m_freem(rx_buffer->m_head);
2046129794Stackerman			rx_buffer->m_head = NULL;
2047129794Stackerman		}
2048129794Stackerman	}
2049129794Stackerman	if (adapter->rx_buffer_area != NULL) {
2050129794Stackerman		free(adapter->rx_buffer_area, M_DEVBUF);
2051129794Stackerman		adapter->rx_buffer_area = NULL;
2052129794Stackerman	}
2053129794Stackerman	if (adapter->rxtag != NULL) {
2054129794Stackerman		bus_dma_tag_destroy(adapter->rxtag);
2055129794Stackerman		adapter->rxtag = NULL;
2056129794Stackerman	}
2057129794Stackerman	return;
2058129794Stackerman}
2059129794Stackerman
2060129794Stackerman/*********************************************************************
2061129794Stackerman *
2062129794Stackerman *  This routine executes in interrupt context. It replenishes
2063129794Stackerman *  the mbufs in the descriptor and sends data which has been
2064129794Stackerman *  dma'ed into host memory to upper layer.
2065129794Stackerman *
2066129794Stackerman *  We loop at most count times if count is > 0, or until done if
2067129794Stackerman *  count < 0.
2068129794Stackerman *
2069129794Stackerman *********************************************************************/
2070193096Sattiliostatic int
2071129794Stackermanixgb_process_receive_interrupts(struct adapter * adapter, int count)
2072129794Stackerman{
2073129794Stackerman	struct ifnet   *ifp;
2074129794Stackerman	struct mbuf    *mp;
2075129794Stackerman#if __FreeBSD_version < 500000
2076129794Stackerman	struct ether_header *eh;
2077129794Stackerman#endif
2078129794Stackerman	int             eop = 0;
2079129794Stackerman	int             len;
2080129794Stackerman	u_int8_t        accept_frame = 0;
2081129794Stackerman	int             i;
2082129794Stackerman	int             next_to_use = 0;
2083129794Stackerman	int             eop_desc;
2084193096Sattilio	int		rx_npkts = 0;
2085129794Stackerman	/* Pointer to the receive descriptor being examined. */
2086129794Stackerman	struct ixgb_rx_desc *current_desc;
2087129794Stackerman
2088144651Salc	IXGB_LOCK_ASSERT(adapter);
2089144651Salc
2090147256Sbrooks	ifp = adapter->ifp;
2091129794Stackerman	i = adapter->next_rx_desc_to_check;
2092129794Stackerman	next_to_use = adapter->next_rx_desc_to_use;
2093129794Stackerman	eop_desc = adapter->next_rx_desc_to_check;
2094129794Stackerman	current_desc = &adapter->rx_desc_base[i];
2095129794Stackerman
2096129794Stackerman	if (!((current_desc->status) & IXGB_RX_DESC_STATUS_DD)) {
2097129794Stackerman#ifdef _SV_
2098129794Stackerman		adapter->no_pkts_avail++;
2099129794Stackerman#endif
2100193096Sattilio		return (rx_npkts);
2101129794Stackerman	}
2102129794Stackerman	while ((current_desc->status & IXGB_RX_DESC_STATUS_DD) && (count != 0)) {
2103129794Stackerman
2104129794Stackerman		mp = adapter->rx_buffer_area[i].m_head;
2105129794Stackerman		bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map,
2106129794Stackerman				BUS_DMASYNC_POSTREAD);
2107129794Stackerman		accept_frame = 1;
2108129794Stackerman		if (current_desc->status & IXGB_RX_DESC_STATUS_EOP) {
2109129794Stackerman			count--;
2110129794Stackerman			eop = 1;
2111129794Stackerman		} else {
2112129794Stackerman			eop = 0;
2113129794Stackerman		}
2114129794Stackerman		len = current_desc->length;
2115129794Stackerman
2116129794Stackerman		if (current_desc->errors & (IXGB_RX_DESC_ERRORS_CE |
2117129794Stackerman			    IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P |
2118129794Stackerman					    IXGB_RX_DESC_ERRORS_RXE)) {
2119129794Stackerman			accept_frame = 0;
2120129794Stackerman		}
2121129794Stackerman		if (accept_frame) {
2122129794Stackerman
2123129794Stackerman			/* Assign correct length to the current fragment */
2124129794Stackerman			mp->m_len = len;
2125129794Stackerman
2126129794Stackerman			if (adapter->fmp == NULL) {
2127129794Stackerman				mp->m_pkthdr.len = len;
2128129794Stackerman				adapter->fmp = mp;	/* Store the first mbuf */
2129129794Stackerman				adapter->lmp = mp;
2130129794Stackerman			} else {
2131129794Stackerman				/* Chain mbuf's together */
2132129794Stackerman				mp->m_flags &= ~M_PKTHDR;
2133129794Stackerman				adapter->lmp->m_next = mp;
2134129794Stackerman				adapter->lmp = adapter->lmp->m_next;
2135129794Stackerman				adapter->fmp->m_pkthdr.len += len;
2136129794Stackerman			}
2137129794Stackerman
2138129794Stackerman			if (eop) {
2139129794Stackerman				eop_desc = i;
2140129794Stackerman				adapter->fmp->m_pkthdr.rcvif = ifp;
2141129794Stackerman
2142129794Stackerman#if __FreeBSD_version < 500000
2143129794Stackerman				eh = mtod(adapter->fmp, struct ether_header *);
2144129794Stackerman
2145129794Stackerman				/* Remove ethernet header from mbuf */
2146129794Stackerman				m_adj(adapter->fmp, sizeof(struct ether_header));
2147129794Stackerman				ixgb_receive_checksum(adapter, current_desc,
2148129794Stackerman						      adapter->fmp);
2149129794Stackerman
2150129794Stackerman				if (current_desc->status & IXGB_RX_DESC_STATUS_VP)
2151129794Stackerman					VLAN_INPUT_TAG(eh, adapter->fmp,
2152129794Stackerman						     current_desc->special);
2153129794Stackerman				else
2154129794Stackerman					ether_input(ifp, eh, adapter->fmp);
2155129794Stackerman#else
2156129794Stackerman				ixgb_receive_checksum(adapter, current_desc,
2157129794Stackerman						      adapter->fmp);
2158162375Sandre#if __FreeBSD_version < 700000
2159129794Stackerman				if (current_desc->status & IXGB_RX_DESC_STATUS_VP)
2160129794Stackerman					VLAN_INPUT_TAG(ifp, adapter->fmp,
2161153512Sglebius						       current_desc->special);
2162162375Sandre#else
2163162375Sandre				if (current_desc->status & IXGB_RX_DESC_STATUS_VP) {
2164162375Sandre					adapter->fmp->m_pkthdr.ether_vtag =
2165162375Sandre					    current_desc->special;
2166162375Sandre					adapter->fmp->m_flags |= M_VLANTAG;
2167162375Sandre				}
2168162375Sandre#endif
2169129794Stackerman
2170144651Salc				if (adapter->fmp != NULL) {
2171144651Salc					IXGB_UNLOCK(adapter);
2172129794Stackerman					(*ifp->if_input) (ifp, adapter->fmp);
2173144651Salc					IXGB_LOCK(adapter);
2174193096Sattilio					rx_npkts++;
2175144651Salc				}
2176129794Stackerman#endif
2177129794Stackerman				adapter->fmp = NULL;
2178129794Stackerman				adapter->lmp = NULL;
2179129794Stackerman			}
2180129794Stackerman			adapter->rx_buffer_area[i].m_head = NULL;
2181129794Stackerman		} else {
2182129794Stackerman			adapter->dropped_pkts++;
2183129794Stackerman			if (adapter->fmp != NULL)
2184129794Stackerman				m_freem(adapter->fmp);
2185129794Stackerman			adapter->fmp = NULL;
2186129794Stackerman			adapter->lmp = NULL;
2187129794Stackerman		}
2188129794Stackerman
2189129794Stackerman		/* Zero out the receive descriptors status  */
2190129794Stackerman		current_desc->status = 0;
2191129794Stackerman
2192129794Stackerman		/* Advance our pointers to the next descriptor */
2193129794Stackerman		if (++i == adapter->num_rx_desc) {
2194129794Stackerman			i = 0;
2195129794Stackerman			current_desc = adapter->rx_desc_base;
2196129794Stackerman		} else
2197129794Stackerman			current_desc++;
2198129794Stackerman	}
2199129794Stackerman	adapter->next_rx_desc_to_check = i;
2200129794Stackerman
2201129794Stackerman	if (--i < 0)
2202129794Stackerman		i = (adapter->num_rx_desc - 1);
2203129794Stackerman
2204129794Stackerman	/*
2205129794Stackerman	 * 82597EX: Workaround for redundent write back in receive descriptor ring (causes
2206129794Stackerman 	 * memory corruption). Avoid using and re-submitting the most recently received RX
2207129794Stackerman	 * descriptor back to hardware.
2208129794Stackerman	 *
2209129794Stackerman	 * if(Last written back descriptor == EOP bit set descriptor)
2210129794Stackerman	 * 	then avoid re-submitting the most recently received RX descriptor
2211129794Stackerman	 *	back to hardware.
2212129794Stackerman	 * if(Last written back descriptor != EOP bit set descriptor)
2213129794Stackerman	 *	then avoid re-submitting the most recently received RX descriptors
2214129794Stackerman	 * 	till last EOP bit set descriptor.
2215129794Stackerman	 */
2216129794Stackerman	if (eop_desc != i) {
2217129794Stackerman		if (++eop_desc == adapter->num_rx_desc)
2218129794Stackerman			eop_desc = 0;
2219129794Stackerman		i = eop_desc;
2220129794Stackerman	}
2221129794Stackerman	/* Replenish the descriptors with new mbufs till last EOP bit set descriptor */
2222129794Stackerman	while (next_to_use != i) {
2223129794Stackerman		current_desc = &adapter->rx_desc_base[next_to_use];
2224129794Stackerman		if ((current_desc->errors & (IXGB_RX_DESC_ERRORS_CE |
2225129794Stackerman			    IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P |
2226129794Stackerman					     IXGB_RX_DESC_ERRORS_RXE))) {
2227129794Stackerman			mp = adapter->rx_buffer_area[next_to_use].m_head;
2228129794Stackerman			ixgb_get_buf(next_to_use, adapter, mp);
2229129794Stackerman		} else {
2230129794Stackerman			if (ixgb_get_buf(next_to_use, adapter, NULL) == ENOBUFS)
2231129794Stackerman				break;
2232129794Stackerman		}
2233129794Stackerman		/* Advance our pointers to the next descriptor */
2234129794Stackerman		if (++next_to_use == adapter->num_rx_desc) {
2235129794Stackerman			next_to_use = 0;
2236129794Stackerman			current_desc = adapter->rx_desc_base;
2237129794Stackerman		} else
2238129794Stackerman			current_desc++;
2239129794Stackerman	}
2240129794Stackerman	adapter->next_rx_desc_to_use = next_to_use;
2241129794Stackerman	if (--next_to_use < 0)
2242129794Stackerman		next_to_use = (adapter->num_rx_desc - 1);
2243129794Stackerman	/* Advance the IXGB's Receive Queue #0  "Tail Pointer" */
2244129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDT, next_to_use);
2245129794Stackerman
2246193096Sattilio	return (rx_npkts);
2247129794Stackerman}
2248129794Stackerman
2249129794Stackerman/*********************************************************************
2250129794Stackerman *
2251129794Stackerman *  Verify that the hardware indicated that the checksum is valid.
2252129794Stackerman *  Inform the stack about the status of checksum so that stack
2253129794Stackerman *  doesn't spend time verifying the checksum.
2254129794Stackerman *
2255129794Stackerman *********************************************************************/
2256129794Stackermanstatic void
2257129794Stackermanixgb_receive_checksum(struct adapter * adapter,
2258129794Stackerman		      struct ixgb_rx_desc * rx_desc,
2259129794Stackerman		      struct mbuf * mp)
2260129794Stackerman{
2261129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) {
2262129794Stackerman		mp->m_pkthdr.csum_flags = 0;
2263129794Stackerman		return;
2264129794Stackerman	}
2265129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_IPCS) {
2266129794Stackerman		/* Did it pass? */
2267129794Stackerman		if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_IPE)) {
2268129794Stackerman			/* IP Checksum Good */
2269129794Stackerman			mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
2270129794Stackerman			mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
2271129794Stackerman
2272129794Stackerman		} else {
2273129794Stackerman			mp->m_pkthdr.csum_flags = 0;
2274129794Stackerman		}
2275129794Stackerman	}
2276129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS) {
2277129794Stackerman		/* Did it pass? */
2278129794Stackerman		if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE)) {
2279129794Stackerman			mp->m_pkthdr.csum_flags |=
2280129794Stackerman				(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
2281129794Stackerman			mp->m_pkthdr.csum_data = htons(0xffff);
2282129794Stackerman		}
2283129794Stackerman	}
2284129794Stackerman	return;
2285129794Stackerman}
2286129794Stackerman
2287129794Stackerman
2288129794Stackermanstatic void
2289129794Stackermanixgb_enable_vlans(struct adapter * adapter)
2290129794Stackerman{
2291129794Stackerman	uint32_t        ctrl;
2292129794Stackerman
2293129794Stackerman	ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
2294129794Stackerman	ctrl |= IXGB_CTRL0_VME;
2295129794Stackerman	IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
2296129794Stackerman
2297129794Stackerman	return;
2298129794Stackerman}
2299129794Stackerman
2300129794Stackerman
2301129794Stackermanstatic void
2302129794Stackermanixgb_enable_intr(struct adapter * adapter)
2303129794Stackerman{
2304129794Stackerman	IXGB_WRITE_REG(&adapter->hw, IMS, (IXGB_INT_RXT0 | IXGB_INT_TXDW |
2305129794Stackerman			    IXGB_INT_RXDMT0 | IXGB_INT_LSC | IXGB_INT_RXO));
2306129794Stackerman	return;
2307129794Stackerman}
2308129794Stackerman
2309129794Stackermanstatic void
2310129794Stackermanixgb_disable_intr(struct adapter * adapter)
2311129794Stackerman{
2312129794Stackerman	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
2313129794Stackerman	return;
2314129794Stackerman}
2315129794Stackerman
2316129794Stackermanvoid
2317129794Stackermanixgb_write_pci_cfg(struct ixgb_hw * hw,
2318129794Stackerman		   uint32_t reg,
2319129794Stackerman		   uint16_t * value)
2320129794Stackerman{
2321129794Stackerman	pci_write_config(((struct ixgb_osdep *) hw->back)->dev, reg,
2322129794Stackerman			 *value, 2);
2323129794Stackerman}
2324129794Stackerman
2325129794Stackerman/**********************************************************************
2326129794Stackerman *
2327129794Stackerman *  Update the board statistics counters.
2328129794Stackerman *
2329129794Stackerman **********************************************************************/
2330129794Stackermanstatic void
2331129794Stackermanixgb_update_stats_counters(struct adapter * adapter)
2332129794Stackerman{
2333129794Stackerman
2334129794Stackerman	adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS);
2335129794Stackerman	adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);
2336129794Stackerman	adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);
2337129794Stackerman	adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL);
2338129794Stackerman	adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH);
2339129794Stackerman	adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
2340129794Stackerman	adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
2341129794Stackerman	adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
2342129794Stackerman	adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
2343129794Stackerman	adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC);
2344129794Stackerman
2345129794Stackerman	adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC);
2346129794Stackerman	adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC);
2347129794Stackerman	adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC);
2348129794Stackerman	adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC);
2349129794Stackerman	adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC);
2350129794Stackerman	adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC);
2351129794Stackerman	adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC);
2352129794Stackerman	adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL);
2353129794Stackerman	adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH);
2354129794Stackerman	adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL);
2355129794Stackerman	adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH);
2356129794Stackerman	adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC);
2357129794Stackerman	adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC);
2358129794Stackerman	adapter->stats.rjc += IXGB_READ_REG(&adapter->hw, RJC);
2359129794Stackerman	adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL);
2360129794Stackerman	adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH);
2361129794Stackerman	adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL);
2362129794Stackerman	adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH);
2363129794Stackerman	adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
2364129794Stackerman	adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
2365129794Stackerman	adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL);
2366129794Stackerman	adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH);
2367129794Stackerman	adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C);
2368129794Stackerman	adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL);
2369129794Stackerman	adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH);
2370129794Stackerman	adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL);
2371129794Stackerman	adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH);
2372129794Stackerman
2373129794Stackerman	adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);
2374129794Stackerman	adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);
2375129794Stackerman	adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);
2376129794Stackerman	adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH);
2377129794Stackerman	adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL);
2378129794Stackerman	adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH);
2379129794Stackerman	adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC);
2380129794Stackerman	adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC);
2381129794Stackerman	adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC);
2382129794Stackerman	adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL);
2383129794Stackerman	adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH);
2384129794Stackerman	adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL);
2385129794Stackerman	adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH);
2386129794Stackerman	adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL);
2387129794Stackerman	adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH);
2388129794Stackerman	adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC);
2389129794Stackerman	adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC);
2390129794Stackerman	adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC);
2391129794Stackerman	adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC);
2392129794Stackerman	adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC);
2393129794Stackerman	adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC);
2394129794Stackerman	adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC);
2395272241Sglebius}
2396129794Stackerman
2397272241Sglebiusstatic uint64_t
2398272241Sglebiusixgb_get_counter(struct ifnet *ifp, ift_counter cnt)
2399272241Sglebius{
2400272241Sglebius	struct adapter *adapter;
2401129794Stackerman
2402272241Sglebius	adapter = if_getsoftc(ifp);
2403129794Stackerman
2404272241Sglebius	switch (cnt) {
2405272241Sglebius	case IFCOUNTER_IPACKETS:
2406272241Sglebius		return (adapter->stats.gprcl);
2407272241Sglebius	case IFCOUNTER_OPACKETS:
2408272241Sglebius		return ( adapter->stats.gptcl);
2409272241Sglebius	case IFCOUNTER_IBYTES:
2410272241Sglebius		return (adapter->stats.gorcl);
2411272241Sglebius	case IFCOUNTER_OBYTES:
2412272241Sglebius		return (adapter->stats.gotcl);
2413272241Sglebius	case IFCOUNTER_IMCASTS:
2414272241Sglebius		return ( adapter->stats.mprcl);
2415272241Sglebius	case IFCOUNTER_COLLISIONS:
2416272241Sglebius		return (0);
2417272241Sglebius	case IFCOUNTER_IERRORS:
2418272241Sglebius		return (adapter->dropped_pkts + adapter->stats.crcerrs +
2419272241Sglebius		    adapter->stats.rnbc + adapter->stats.mpc +
2420272241Sglebius		    adapter->stats.rlec);
2421272241Sglebius	default:
2422272241Sglebius		return (if_get_counter_default(ifp, cnt));
2423272241Sglebius	}
2424129794Stackerman}
2425129794Stackerman
2426129794Stackerman/**********************************************************************
2427129794Stackerman *
2428129794Stackerman *  This routine is called only when ixgb_display_debug_stats is enabled.
2429129794Stackerman *  This routine provides a way to take a look at important statistics
2430129794Stackerman *  maintained by the driver and hardware.
2431129794Stackerman *
2432129794Stackerman **********************************************************************/
2433129794Stackermanstatic void
2434129794Stackermanixgb_print_hw_stats(struct adapter * adapter)
2435129794Stackerman{
2436129794Stackerman	char            buf_speed[100], buf_type[100];
2437129794Stackerman	ixgb_bus_speed  bus_speed;
2438129794Stackerman	ixgb_bus_type   bus_type;
2439198987Sjhb	device_t dev;
2440129794Stackerman
2441198987Sjhb	dev = adapter->dev;
2442129794Stackerman#ifdef _SV_
2443198987Sjhb	device_printf(dev, "Packets not Avail = %ld\n",
2444129794Stackerman	       adapter->no_pkts_avail);
2445198987Sjhb	device_printf(dev, "CleanTxInterrupts = %ld\n",
2446129794Stackerman	       adapter->clean_tx_interrupts);
2447198987Sjhb	device_printf(dev, "ICR RXDMT0 = %lld\n",
2448129794Stackerman	       (long long)adapter->sv_stats.icr_rxdmt0);
2449198987Sjhb	device_printf(dev, "ICR RXO = %lld\n",
2450129794Stackerman	       (long long)adapter->sv_stats.icr_rxo);
2451198987Sjhb	device_printf(dev, "ICR RXT0 = %lld\n",
2452129794Stackerman	       (long long)adapter->sv_stats.icr_rxt0);
2453198987Sjhb	device_printf(dev, "ICR TXDW = %lld\n",
2454129794Stackerman	       (long long)adapter->sv_stats.icr_TXDW);
2455129794Stackerman#endif				/* _SV_ */
2456129794Stackerman
2457129794Stackerman	bus_speed = adapter->hw.bus.speed;
2458129794Stackerman	bus_type = adapter->hw.bus.type;
2459129794Stackerman	sprintf(buf_speed,
2460129794Stackerman		bus_speed == ixgb_bus_speed_33 ? "33MHz" :
2461129794Stackerman		bus_speed == ixgb_bus_speed_66 ? "66MHz" :
2462129794Stackerman		bus_speed == ixgb_bus_speed_100 ? "100MHz" :
2463129794Stackerman		bus_speed == ixgb_bus_speed_133 ? "133MHz" :
2464129794Stackerman		"UNKNOWN");
2465198987Sjhb	device_printf(dev, "PCI_Bus_Speed = %s\n",
2466129794Stackerman	       buf_speed);
2467129794Stackerman
2468129794Stackerman	sprintf(buf_type,
2469129794Stackerman		bus_type == ixgb_bus_type_pci ? "PCI" :
2470129794Stackerman		bus_type == ixgb_bus_type_pcix ? "PCI-X" :
2471129794Stackerman		"UNKNOWN");
2472198987Sjhb	device_printf(dev, "PCI_Bus_Type = %s\n",
2473129794Stackerman	       buf_type);
2474129794Stackerman
2475198987Sjhb	device_printf(dev, "Tx Descriptors not Avail1 = %ld\n",
2476129794Stackerman	       adapter->no_tx_desc_avail1);
2477198987Sjhb	device_printf(dev, "Tx Descriptors not Avail2 = %ld\n",
2478129794Stackerman	       adapter->no_tx_desc_avail2);
2479198987Sjhb	device_printf(dev, "Std Mbuf Failed = %ld\n",
2480129794Stackerman	       adapter->mbuf_alloc_failed);
2481198987Sjhb	device_printf(dev, "Std Cluster Failed = %ld\n",
2482129794Stackerman	       adapter->mbuf_cluster_failed);
2483129794Stackerman
2484198987Sjhb	device_printf(dev, "Defer count = %lld\n",
2485129794Stackerman	       (long long)adapter->stats.dc);
2486198987Sjhb	device_printf(dev, "Missed Packets = %lld\n",
2487129794Stackerman	       (long long)adapter->stats.mpc);
2488198987Sjhb	device_printf(dev, "Receive No Buffers = %lld\n",
2489129794Stackerman	       (long long)adapter->stats.rnbc);
2490198987Sjhb	device_printf(dev, "Receive length errors = %lld\n",
2491129794Stackerman	       (long long)adapter->stats.rlec);
2492198987Sjhb	device_printf(dev, "Crc errors = %lld\n",
2493129794Stackerman	       (long long)adapter->stats.crcerrs);
2494198987Sjhb	device_printf(dev, "Driver dropped packets = %ld\n",
2495129794Stackerman	       adapter->dropped_pkts);
2496129794Stackerman
2497198987Sjhb	device_printf(dev, "XON Rcvd = %lld\n",
2498129794Stackerman	       (long long)adapter->stats.xonrxc);
2499198987Sjhb	device_printf(dev, "XON Xmtd = %lld\n",
2500129794Stackerman	       (long long)adapter->stats.xontxc);
2501198987Sjhb	device_printf(dev, "XOFF Rcvd = %lld\n",
2502129794Stackerman	       (long long)adapter->stats.xoffrxc);
2503198987Sjhb	device_printf(dev, "XOFF Xmtd = %lld\n",
2504129794Stackerman	       (long long)adapter->stats.xofftxc);
2505129794Stackerman
2506198987Sjhb	device_printf(dev, "Good Packets Rcvd = %lld\n",
2507129794Stackerman	       (long long)adapter->stats.gprcl);
2508198987Sjhb	device_printf(dev, "Good Packets Xmtd = %lld\n",
2509129794Stackerman	       (long long)adapter->stats.gptcl);
2510129794Stackerman
2511198987Sjhb	device_printf(dev, "Jumbo frames recvd = %lld\n",
2512129794Stackerman	       (long long)adapter->stats.jprcl);
2513198987Sjhb	device_printf(dev, "Jumbo frames Xmtd = %lld\n",
2514129794Stackerman	       (long long)adapter->stats.jptcl);
2515129794Stackerman
2516129794Stackerman	return;
2517129794Stackerman
2518129794Stackerman}
2519129794Stackerman
2520129794Stackermanstatic int
2521129794Stackermanixgb_sysctl_stats(SYSCTL_HANDLER_ARGS)
2522129794Stackerman{
2523129794Stackerman	int             error;
2524129794Stackerman	int             result;
2525129794Stackerman	struct adapter *adapter;
2526129794Stackerman
2527129794Stackerman	result = -1;
2528129794Stackerman	error = sysctl_handle_int(oidp, &result, 0, req);
2529129794Stackerman
2530129794Stackerman	if (error || !req->newptr)
2531129794Stackerman		return (error);
2532129794Stackerman
2533129794Stackerman	if (result == 1) {
2534129794Stackerman		adapter = (struct adapter *) arg1;
2535129794Stackerman		ixgb_print_hw_stats(adapter);
2536129794Stackerman	}
2537129794Stackerman	return error;
2538129794Stackerman}
2539