if_ixgb.c revision 150789
1139749Simp/*******************************************************************************
2129794Stackerman
3129794StackermanCopyright (c) 2001-2004, Intel Corporation
4129794StackermanAll rights reserved.
5129794Stackerman
6129794StackermanRedistribution and use in source and binary forms, with or without
7129794Stackermanmodification, are permitted provided that the following conditions are met:
8129794Stackerman
9129794Stackerman 1. Redistributions of source code must retain the above copyright notice,
10129794Stackerman    this list of conditions and the following disclaimer.
11129794Stackerman
12129794Stackerman 2. Redistributions in binary form must reproduce the above copyright
13129794Stackerman    notice, this list of conditions and the following disclaimer in the
14129794Stackerman    documentation and/or other materials provided with the distribution.
15129794Stackerman
16129794Stackerman 3. Neither the name of the Intel Corporation nor the names of its
17129794Stackerman    contributors may be used to endorse or promote products derived from
18129794Stackerman    this software without specific prior written permission.
19129794Stackerman
20129794StackermanTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21129794StackermanAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22129794StackermanIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23129794StackermanARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24129794StackermanLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25129794StackermanCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26129794StackermanSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27129794StackermanINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28129794StackermanCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29129794StackermanARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30129794StackermanPOSSIBILITY OF SUCH DAMAGE.
31129794Stackerman
32129794Stackerman***************************************************************************/
33129794Stackerman
34129794Stackerman/*$FreeBSD: head/sys/dev/ixgb/if_ixgb.c 150789 2005-10-01 18:56:19Z glebius $*/
35129794Stackerman
36129794Stackerman#include <dev/ixgb/if_ixgb.h>
37129794Stackerman
38129794Stackerman/*********************************************************************
39129794Stackerman *  Set this to one to display debug statistics
40129794Stackerman *********************************************************************/
41129794Stackermanint             ixgb_display_debug_stats = 0;
42129794Stackerman
43129794Stackerman/*********************************************************************
44129794Stackerman *  Linked list of board private structures for all NICs found
45129794Stackerman *********************************************************************/
46129794Stackerman
47129794Stackermanstruct adapter *ixgb_adapter_list = NULL;
48129794Stackerman
49129794Stackerman
50129794Stackerman
51129794Stackerman/*********************************************************************
52129794Stackerman *  Driver version
53129794Stackerman *********************************************************************/
54129794Stackerman
55129794Stackermanchar            ixgb_driver_version[] = "1.0.6";
56129794Stackermanchar            ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation.";
57129794Stackerman
58129794Stackerman/*********************************************************************
59129794Stackerman *  PCI Device ID Table
60129794Stackerman *
61129794Stackerman *  Used by probe to select devices to load on
62129794Stackerman *  Last field stores an index into ixgb_strings
63129794Stackerman *  Last entry must be all 0s
64129794Stackerman *
65129794Stackerman *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
66129794Stackerman *********************************************************************/
67129794Stackerman
68129794Stackermanstatic ixgb_vendor_info_t ixgb_vendor_info_array[] =
69129794Stackerman{
70129794Stackerman	/* Intel(R) PRO/10000 Network Connection */
71129794Stackerman	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX, PCI_ANY_ID, PCI_ANY_ID, 0},
72129794Stackerman	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR, PCI_ANY_ID, PCI_ANY_ID, 0},
73129794Stackerman	/* required last entry */
74129794Stackerman	{0, 0, 0, 0, 0}
75129794Stackerman};
76129794Stackerman
77129794Stackerman/*********************************************************************
78129794Stackerman *  Table of branding strings for all supported NICs.
79129794Stackerman *********************************************************************/
80129794Stackerman
81129794Stackermanstatic char    *ixgb_strings[] = {
82129794Stackerman	"Intel(R) PRO/10GbE Network Driver"
83129794Stackerman};
84129794Stackerman
85129794Stackerman/*********************************************************************
86129794Stackerman *  Function prototypes
87129794Stackerman *********************************************************************/
88129794Stackermanstatic int      ixgb_probe(device_t);
89129794Stackermanstatic int      ixgb_attach(device_t);
90129794Stackermanstatic int      ixgb_detach(device_t);
91129794Stackermanstatic int      ixgb_shutdown(device_t);
92129794Stackermanstatic void     ixgb_intr(void *);
93129794Stackermanstatic void     ixgb_start(struct ifnet *);
94144651Salcstatic void     ixgb_start_locked(struct ifnet *);
95129794Stackermanstatic int      ixgb_ioctl(struct ifnet *, IOCTL_CMD_TYPE, caddr_t);
96129794Stackermanstatic void     ixgb_watchdog(struct ifnet *);
97129794Stackermanstatic void     ixgb_init(void *);
98144651Salcstatic void     ixgb_init_locked(struct adapter *);
99129794Stackermanstatic void     ixgb_stop(void *);
100129794Stackermanstatic void     ixgb_media_status(struct ifnet *, struct ifmediareq *);
101129794Stackermanstatic int      ixgb_media_change(struct ifnet *);
102129794Stackermanstatic void     ixgb_identify_hardware(struct adapter *);
103129794Stackermanstatic int      ixgb_allocate_pci_resources(struct adapter *);
104129794Stackermanstatic void     ixgb_free_pci_resources(struct adapter *);
105129794Stackermanstatic void     ixgb_local_timer(void *);
106129794Stackermanstatic int      ixgb_hardware_init(struct adapter *);
107129794Stackermanstatic void     ixgb_setup_interface(device_t, struct adapter *);
108129794Stackermanstatic int      ixgb_setup_transmit_structures(struct adapter *);
109129794Stackermanstatic void     ixgb_initialize_transmit_unit(struct adapter *);
110129794Stackermanstatic int      ixgb_setup_receive_structures(struct adapter *);
111129794Stackermanstatic void     ixgb_initialize_receive_unit(struct adapter *);
112129794Stackermanstatic void     ixgb_enable_intr(struct adapter *);
113129794Stackermanstatic void     ixgb_disable_intr(struct adapter *);
114129794Stackermanstatic void     ixgb_free_transmit_structures(struct adapter *);
115129794Stackermanstatic void     ixgb_free_receive_structures(struct adapter *);
116129794Stackermanstatic void     ixgb_update_stats_counters(struct adapter *);
117129794Stackermanstatic void     ixgb_clean_transmit_interrupts(struct adapter *);
118129794Stackermanstatic int      ixgb_allocate_receive_structures(struct adapter *);
119129794Stackermanstatic int      ixgb_allocate_transmit_structures(struct adapter *);
120129794Stackermanstatic void     ixgb_process_receive_interrupts(struct adapter *, int);
121129794Stackermanstatic void
122129794Stackermanixgb_receive_checksum(struct adapter *,
123129794Stackerman		      struct ixgb_rx_desc * rx_desc,
124129794Stackerman		      struct mbuf *);
125129794Stackermanstatic void
126129794Stackermanixgb_transmit_checksum_setup(struct adapter *,
127129794Stackerman			     struct mbuf *,
128129794Stackerman			     u_int8_t *);
129129794Stackermanstatic void     ixgb_set_promisc(struct adapter *);
130129794Stackermanstatic void     ixgb_disable_promisc(struct adapter *);
131129794Stackermanstatic void     ixgb_set_multi(struct adapter *);
132129794Stackermanstatic void     ixgb_print_hw_stats(struct adapter *);
133129794Stackermanstatic void     ixgb_print_link_status(struct adapter *);
134129794Stackermanstatic int
135129794Stackermanixgb_get_buf(int i, struct adapter *,
136129794Stackerman	     struct mbuf *);
137129794Stackermanstatic void     ixgb_enable_vlans(struct adapter * adapter);
138129794Stackermanstatic int      ixgb_encap(struct adapter * adapter, struct mbuf * m_head);
139129794Stackermanstatic int      ixgb_sysctl_stats(SYSCTL_HANDLER_ARGS);
140129794Stackermanstatic int
141129794Stackermanixgb_dma_malloc(struct adapter *, bus_size_t,
142129794Stackerman		struct ixgb_dma_alloc *, int);
143129794Stackermanstatic void     ixgb_dma_free(struct adapter *, struct ixgb_dma_alloc *);
144150789Sglebius#ifdef DEVICE_POLLING
145150789Sglebiusstatic poll_handler_t ixgb_poll;
146150789Sglebius#endif
147129794Stackerman
148129794Stackerman/*********************************************************************
149129794Stackerman *  FreeBSD Device Interface Entry Points
150129794Stackerman *********************************************************************/
151129794Stackerman
152129794Stackermanstatic device_method_t ixgb_methods[] = {
153129794Stackerman	/* Device interface */
154129794Stackerman	DEVMETHOD(device_probe, ixgb_probe),
155129794Stackerman	DEVMETHOD(device_attach, ixgb_attach),
156129794Stackerman	DEVMETHOD(device_detach, ixgb_detach),
157129794Stackerman	DEVMETHOD(device_shutdown, ixgb_shutdown),
158129794Stackerman	{0, 0}
159129794Stackerman};
160129794Stackerman
161129794Stackermanstatic driver_t ixgb_driver = {
162129794Stackerman	"ixgb", ixgb_methods, sizeof(struct adapter),
163129794Stackerman};
164129794Stackerman
165129794Stackermanstatic devclass_t ixgb_devclass;
166129794StackermanDRIVER_MODULE(if_ixgb, pci, ixgb_driver, ixgb_devclass, 0, 0);
167129794Stackerman
168144190SmuxMODULE_DEPEND(if_ixgb, pci, 1, 1, 1);
169144190SmuxMODULE_DEPEND(if_ixgb, ether, 1, 1, 1);
170144183Smux
171129794Stackerman/* some defines for controlling descriptor fetches in h/w */
172129794Stackerman#define RXDCTL_PTHRESH_DEFAULT 128	/* chip considers prefech below this */
173129794Stackerman#define RXDCTL_HTHRESH_DEFAULT 16	/* chip will only prefetch if tail is
174129794Stackerman					 * pushed this many descriptors from
175129794Stackerman					 * head */
176129794Stackerman#define RXDCTL_WTHRESH_DEFAULT 0	/* chip writes back at this many or RXT0 */
177129794Stackerman
178129794Stackerman
179129794Stackerman/*********************************************************************
180129794Stackerman *  Device identification routine
181129794Stackerman *
182129794Stackerman *  ixgb_probe determines if the driver should be loaded on
183129794Stackerman *  adapter based on PCI vendor/device id of the adapter.
184129794Stackerman *
185129794Stackerman *  return 0 on success, positive on failure
186129794Stackerman *********************************************************************/
187129794Stackerman
188129794Stackermanstatic int
189129794Stackermanixgb_probe(device_t dev)
190129794Stackerman{
191129794Stackerman	ixgb_vendor_info_t *ent;
192129794Stackerman
193129794Stackerman	u_int16_t       pci_vendor_id = 0;
194129794Stackerman	u_int16_t       pci_device_id = 0;
195129794Stackerman	u_int16_t       pci_subvendor_id = 0;
196129794Stackerman	u_int16_t       pci_subdevice_id = 0;
197129794Stackerman	char            adapter_name[60];
198129794Stackerman
199129794Stackerman	INIT_DEBUGOUT("ixgb_probe: begin");
200129794Stackerman
201129794Stackerman	pci_vendor_id = pci_get_vendor(dev);
202129794Stackerman	if (pci_vendor_id != IXGB_VENDOR_ID)
203129794Stackerman		return (ENXIO);
204129794Stackerman
205129794Stackerman	pci_device_id = pci_get_device(dev);
206129794Stackerman	pci_subvendor_id = pci_get_subvendor(dev);
207129794Stackerman	pci_subdevice_id = pci_get_subdevice(dev);
208129794Stackerman
209129794Stackerman	ent = ixgb_vendor_info_array;
210129794Stackerman	while (ent->vendor_id != 0) {
211129794Stackerman		if ((pci_vendor_id == ent->vendor_id) &&
212129794Stackerman		    (pci_device_id == ent->device_id) &&
213129794Stackerman
214129794Stackerman		    ((pci_subvendor_id == ent->subvendor_id) ||
215129794Stackerman		     (ent->subvendor_id == PCI_ANY_ID)) &&
216129794Stackerman
217129794Stackerman		    ((pci_subdevice_id == ent->subdevice_id) ||
218129794Stackerman		     (ent->subdevice_id == PCI_ANY_ID))) {
219129794Stackerman			sprintf(adapter_name, "%s, Version - %s",
220129794Stackerman				ixgb_strings[ent->index],
221129794Stackerman				ixgb_driver_version);
222129794Stackerman			device_set_desc_copy(dev, adapter_name);
223143160Simp			return (BUS_PROBE_DEFAULT);
224129794Stackerman		}
225129794Stackerman		ent++;
226129794Stackerman	}
227129794Stackerman
228129794Stackerman	return (ENXIO);
229129794Stackerman}
230129794Stackerman
231129794Stackerman/*********************************************************************
232129794Stackerman *  Device initialization routine
233129794Stackerman *
234129794Stackerman *  The attach entry point is called when the driver is being loaded.
235129794Stackerman *  This routine identifies the type of hardware, allocates all resources
236129794Stackerman *  and initializes the hardware.
237129794Stackerman *
238129794Stackerman *  return 0 on success, positive on failure
239129794Stackerman *********************************************************************/
240129794Stackerman
241129794Stackermanstatic int
242129794Stackermanixgb_attach(device_t dev)
243129794Stackerman{
244129794Stackerman	struct adapter *adapter;
245129794Stackerman	int             tsize, rsize;
246129794Stackerman	int             error = 0;
247129794Stackerman
248129794Stackerman	printf("ixgb%d: %s\n", device_get_unit(dev), ixgb_copyright);
249129794Stackerman	INIT_DEBUGOUT("ixgb_attach: begin");
250129794Stackerman
251129794Stackerman	/* Allocate, clear, and link in our adapter structure */
252129794Stackerman	if (!(adapter = device_get_softc(dev))) {
253129794Stackerman		printf("ixgb: adapter structure allocation failed\n");
254129794Stackerman		return (ENOMEM);
255129794Stackerman	}
256129794Stackerman	bzero(adapter, sizeof(struct adapter));
257129794Stackerman	adapter->dev = dev;
258129794Stackerman	adapter->osdep.dev = dev;
259129794Stackerman	adapter->unit = device_get_unit(dev);
260144651Salc	IXGB_LOCK_INIT(adapter, device_get_nameunit(dev));
261129794Stackerman
262129794Stackerman	if (ixgb_adapter_list != NULL)
263129794Stackerman		ixgb_adapter_list->prev = adapter;
264129794Stackerman	adapter->next = ixgb_adapter_list;
265129794Stackerman	ixgb_adapter_list = adapter;
266129794Stackerman
267129794Stackerman	/* SYSCTL APIs */
268144183Smux	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
269144183Smux			SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
270129794Stackerman			OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW,
271129794Stackerman			(void *)adapter, 0,
272129794Stackerman			ixgb_sysctl_stats, "I", "Statistics");
273129794Stackerman
274144651Salc	callout_init(&adapter->timer, CALLOUT_MPSAFE);
275129794Stackerman
276129794Stackerman	/* Determine hardware revision */
277129794Stackerman	ixgb_identify_hardware(adapter);
278129794Stackerman
279129794Stackerman	/* Parameters (to be read from user) */
280129794Stackerman	adapter->num_tx_desc = IXGB_MAX_TXD;
281129794Stackerman	adapter->num_rx_desc = IXGB_MAX_RXD;
282129794Stackerman	adapter->tx_int_delay = TIDV;
283129794Stackerman	adapter->rx_int_delay = RDTR;
284129794Stackerman	adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
285129794Stackerman
286129794Stackerman	adapter->hw.fc.high_water = FCRTH;
287129794Stackerman	adapter->hw.fc.low_water = FCRTL;
288129794Stackerman	adapter->hw.fc.pause_time = FCPAUSE;
289129794Stackerman	adapter->hw.fc.send_xon = TRUE;
290129794Stackerman	adapter->hw.fc.type = FLOW_CONTROL;
291129794Stackerman
292129794Stackerman
293129794Stackerman	/* Set the max frame size assuming standard ethernet sized frames */
294129794Stackerman	adapter->hw.max_frame_size =
295129794Stackerman		ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
296129794Stackerman
297129794Stackerman	if (ixgb_allocate_pci_resources(adapter)) {
298129794Stackerman		printf("ixgb%d: Allocation of PCI resources failed\n",
299129794Stackerman		       adapter->unit);
300129794Stackerman		error = ENXIO;
301129794Stackerman		goto err_pci;
302129794Stackerman	}
303129794Stackerman	tsize = IXGB_ROUNDUP(adapter->num_tx_desc *
304129794Stackerman			     sizeof(struct ixgb_tx_desc), 4096);
305129794Stackerman
306129794Stackerman	/* Allocate Transmit Descriptor ring */
307129794Stackerman	if (ixgb_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) {
308129794Stackerman		printf("ixgb%d: Unable to allocate TxDescriptor memory\n",
309129794Stackerman		       adapter->unit);
310129794Stackerman		error = ENOMEM;
311129794Stackerman		goto err_tx_desc;
312129794Stackerman	}
313129794Stackerman	adapter->tx_desc_base = (struct ixgb_tx_desc *) adapter->txdma.dma_vaddr;
314129794Stackerman
315129794Stackerman	rsize = IXGB_ROUNDUP(adapter->num_rx_desc *
316129794Stackerman			     sizeof(struct ixgb_rx_desc), 4096);
317129794Stackerman
318129794Stackerman	/* Allocate Receive Descriptor ring */
319129794Stackerman	if (ixgb_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) {
320129794Stackerman		printf("ixgb%d: Unable to allocate rx_desc memory\n",
321129794Stackerman		       adapter->unit);
322129794Stackerman		error = ENOMEM;
323129794Stackerman		goto err_rx_desc;
324129794Stackerman	}
325129794Stackerman	adapter->rx_desc_base = (struct ixgb_rx_desc *) adapter->rxdma.dma_vaddr;
326129794Stackerman
327129794Stackerman	/* Initialize the hardware */
328129794Stackerman	if (ixgb_hardware_init(adapter)) {
329129794Stackerman		printf("ixgb%d: Unable to initialize the hardware\n",
330129794Stackerman		       adapter->unit);
331129794Stackerman		error = EIO;
332129794Stackerman		goto err_hw_init;
333129794Stackerman	}
334129794Stackerman	/* Setup OS specific network interface */
335129794Stackerman	ixgb_setup_interface(dev, adapter);
336129794Stackerman
337129794Stackerman	/* Initialize statistics */
338129794Stackerman	ixgb_clear_hw_cntrs(&adapter->hw);
339129794Stackerman	ixgb_update_stats_counters(adapter);
340129794Stackerman
341129794Stackerman	INIT_DEBUGOUT("ixgb_attach: end");
342129794Stackerman	return (0);
343129794Stackerman
344129794Stackermanerr_hw_init:
345129794Stackerman	ixgb_dma_free(adapter, &adapter->rxdma);
346129794Stackermanerr_rx_desc:
347129794Stackerman	ixgb_dma_free(adapter, &adapter->txdma);
348129794Stackermanerr_tx_desc:
349129794Stackermanerr_pci:
350129794Stackerman	ixgb_free_pci_resources(adapter);
351129794Stackerman	sysctl_ctx_free(&adapter->sysctl_ctx);
352129794Stackerman	return (error);
353129794Stackerman
354129794Stackerman}
355129794Stackerman
356129794Stackerman/*********************************************************************
357129794Stackerman *  Device removal routine
358129794Stackerman *
359129794Stackerman *  The detach entry point is called when the driver is being removed.
360129794Stackerman *  This routine stops the adapter and deallocates all the resources
361129794Stackerman *  that were allocated for driver operation.
362129794Stackerman *
363129794Stackerman *  return 0 on success, positive on failure
364129794Stackerman *********************************************************************/
365129794Stackerman
366129794Stackermanstatic int
367129794Stackermanixgb_detach(device_t dev)
368129794Stackerman{
369129794Stackerman	struct adapter *adapter = device_get_softc(dev);
370147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
371129794Stackerman
372129794Stackerman	INIT_DEBUGOUT("ixgb_detach: begin");
373129794Stackerman
374150789Sglebius#ifdef DEVICE_POLLING
375150789Sglebius	if (ifp->if_capenable & IFCAP_POLLING)
376150789Sglebius		ether_poll_deregister(ifp);
377150789Sglebius#endif
378150789Sglebius
379144651Salc	IXGB_LOCK(adapter);
380129794Stackerman	adapter->in_detach = 1;
381129794Stackerman
382129794Stackerman	ixgb_stop(adapter);
383144651Salc	IXGB_UNLOCK(adapter);
384129794Stackerman
385129794Stackerman#if __FreeBSD_version < 500000
386147256Sbrooks	ether_ifdetach(adapter->ifp, ETHER_BPF_SUPPORTED);
387129794Stackerman#else
388147256Sbrooks	ether_ifdetach(adapter->ifp);
389150306Simp#endif
390150306Simp	ixgb_free_pci_resources(adapter);
391150306Simp#if __FreeBSD_version >= 500000
392147256Sbrooks	if_free(adapter->ifp);
393129794Stackerman#endif
394129794Stackerman
395129794Stackerman	/* Free Transmit Descriptor ring */
396129794Stackerman	if (adapter->tx_desc_base) {
397129794Stackerman		ixgb_dma_free(adapter, &adapter->txdma);
398129794Stackerman		adapter->tx_desc_base = NULL;
399129794Stackerman	}
400129794Stackerman	/* Free Receive Descriptor ring */
401129794Stackerman	if (adapter->rx_desc_base) {
402129794Stackerman		ixgb_dma_free(adapter, &adapter->rxdma);
403129794Stackerman		adapter->rx_desc_base = NULL;
404129794Stackerman	}
405129794Stackerman	/* Remove from the adapter list */
406129794Stackerman	if (ixgb_adapter_list == adapter)
407129794Stackerman		ixgb_adapter_list = adapter->next;
408129794Stackerman	if (adapter->next != NULL)
409129794Stackerman		adapter->next->prev = adapter->prev;
410129794Stackerman	if (adapter->prev != NULL)
411129794Stackerman		adapter->prev->next = adapter->next;
412129794Stackerman
413148887Srwatson	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
414129794Stackerman	ifp->if_timer = 0;
415129794Stackerman
416144651Salc	IXGB_LOCK_DESTROY(adapter);
417129794Stackerman	return (0);
418129794Stackerman}
419129794Stackerman
420129794Stackerman/*********************************************************************
421129794Stackerman *
422129794Stackerman *  Shutdown entry point
423129794Stackerman *
424129794Stackerman **********************************************************************/
425129794Stackerman
426129794Stackermanstatic int
427129794Stackermanixgb_shutdown(device_t dev)
428129794Stackerman{
429129794Stackerman	struct adapter *adapter = device_get_softc(dev);
430144651Salc	IXGB_LOCK(adapter);
431129794Stackerman	ixgb_stop(adapter);
432144651Salc	IXGB_UNLOCK(adapter);
433129794Stackerman	return (0);
434129794Stackerman}
435129794Stackerman
436129794Stackerman
437129794Stackerman/*********************************************************************
438129794Stackerman *  Transmit entry point
439129794Stackerman *
440129794Stackerman *  ixgb_start is called by the stack to initiate a transmit.
441129794Stackerman *  The driver will remain in this routine as long as there are
442129794Stackerman *  packets to transmit and transmit resources are available.
443129794Stackerman *  In case resources are not available stack is notified and
444129794Stackerman *  the packet is requeued.
445129794Stackerman **********************************************************************/
446129794Stackerman
447129794Stackermanstatic void
448144651Salcixgb_start_locked(struct ifnet * ifp)
449129794Stackerman{
450129794Stackerman	struct mbuf    *m_head;
451129794Stackerman	struct adapter *adapter = ifp->if_softc;
452129794Stackerman
453144651Salc	IXGB_LOCK_ASSERT(adapter);
454129794Stackerman
455129794Stackerman	if (!adapter->link_active)
456129794Stackerman		return;
457129794Stackerman
458129794Stackerman	while (ifp->if_snd.ifq_head != NULL) {
459129794Stackerman		IF_DEQUEUE(&ifp->if_snd, m_head);
460129794Stackerman
461129794Stackerman		if (m_head == NULL)
462129794Stackerman			break;
463129794Stackerman
464129794Stackerman		if (ixgb_encap(adapter, m_head)) {
465148887Srwatson			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
466129794Stackerman			IF_PREPEND(&ifp->if_snd, m_head);
467129794Stackerman			break;
468129794Stackerman		}
469129794Stackerman		/* Send a copy of the frame to the BPF listener */
470129794Stackerman#if __FreeBSD_version < 500000
471129794Stackerman		if (ifp->if_bpf)
472129794Stackerman			bpf_mtap(ifp, m_head);
473129794Stackerman#else
474129794Stackerman		BPF_MTAP(ifp, m_head);
475129794Stackerman#endif
476129794Stackerman		/* Set timeout in case hardware has problems transmitting */
477129794Stackerman		ifp->if_timer = IXGB_TX_TIMEOUT;
478129794Stackerman
479129794Stackerman	}
480129794Stackerman	return;
481129794Stackerman}
482129794Stackerman
483144651Salcstatic void
484144651Salcixgb_start(struct ifnet *ifp)
485144651Salc{
486144651Salc	struct adapter *adapter = ifp->if_softc;
487144651Salc
488144651Salc	IXGB_LOCK(adapter);
489144651Salc	ixgb_start_locked(ifp);
490144651Salc	IXGB_UNLOCK(adapter);
491144651Salc	return;
492144651Salc}
493144651Salc
494129794Stackerman/*********************************************************************
495129794Stackerman *  Ioctl entry point
496129794Stackerman *
497129794Stackerman *  ixgb_ioctl is called when the user wants to configure the
498129794Stackerman *  interface.
499129794Stackerman *
500129794Stackerman *  return 0 on success, positive on failure
501129794Stackerman **********************************************************************/
502129794Stackerman
503129794Stackermanstatic int
504129794Stackermanixgb_ioctl(struct ifnet * ifp, IOCTL_CMD_TYPE command, caddr_t data)
505129794Stackerman{
506144651Salc	int             mask, error = 0;
507129794Stackerman	struct ifreq   *ifr = (struct ifreq *) data;
508129794Stackerman	struct adapter *adapter = ifp->if_softc;
509129794Stackerman
510129794Stackerman	if (adapter->in_detach)
511129794Stackerman		goto out;
512129794Stackerman
513129794Stackerman	switch (command) {
514129794Stackerman	case SIOCSIFADDR:
515129794Stackerman	case SIOCGIFADDR:
516129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFADDR (Get/Set Interface Addr)");
517129794Stackerman		ether_ioctl(ifp, command, data);
518129794Stackerman		break;
519129794Stackerman	case SIOCSIFMTU:
520129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
521129794Stackerman		if (ifr->ifr_mtu > IXGB_MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN) {
522129794Stackerman			error = EINVAL;
523129794Stackerman		} else {
524144651Salc			IXGB_LOCK(adapter);
525129794Stackerman			ifp->if_mtu = ifr->ifr_mtu;
526129794Stackerman			adapter->hw.max_frame_size =
527129794Stackerman				ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
528129794Stackerman
529144651Salc			ixgb_init_locked(adapter);
530144651Salc			IXGB_UNLOCK(adapter);
531129794Stackerman		}
532129794Stackerman		break;
533129794Stackerman	case SIOCSIFFLAGS:
534129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)");
535144651Salc		IXGB_LOCK(adapter);
536129794Stackerman		if (ifp->if_flags & IFF_UP) {
537148887Srwatson			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
538144651Salc				ixgb_init_locked(adapter);
539129794Stackerman			}
540129794Stackerman			ixgb_disable_promisc(adapter);
541129794Stackerman			ixgb_set_promisc(adapter);
542129794Stackerman		} else {
543148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
544129794Stackerman				ixgb_stop(adapter);
545129794Stackerman			}
546129794Stackerman		}
547144651Salc		IXGB_UNLOCK(adapter);
548129794Stackerman		break;
549129794Stackerman	case SIOCADDMULTI:
550129794Stackerman	case SIOCDELMULTI:
551129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI");
552148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
553144651Salc			IXGB_LOCK(adapter);
554129794Stackerman			ixgb_disable_intr(adapter);
555129794Stackerman			ixgb_set_multi(adapter);
556129794Stackerman			ixgb_enable_intr(adapter);
557144651Salc			IXGB_UNLOCK(adapter);
558129794Stackerman		}
559129794Stackerman		break;
560129794Stackerman	case SIOCSIFMEDIA:
561129794Stackerman	case SIOCGIFMEDIA:
562129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA (Get/Set Interface Media)");
563129794Stackerman		error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
564129794Stackerman		break;
565129794Stackerman	case SIOCSIFCAP:
566129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
567129794Stackerman		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
568150789Sglebius#ifdef DEVICE_POLLING
569150789Sglebius		if (mask & IFCAP_POLLING) {
570150789Sglebius			if (ifr->ifr_reqcap & IFCAP_POLLING) {
571150789Sglebius				error = ether_poll_register(ixgb_poll, ifp);
572150789Sglebius				if (error)
573150789Sglebius					return(error);
574150789Sglebius				IXGB_LOCK(adapter);
575150789Sglebius				ixgb_disable_intr(adapter);
576150789Sglebius				ifp->if_capenable |= IFCAP_POLLING;
577150789Sglebius				IXGB_UNLOCK(adapter);
578150789Sglebius			} else {
579150789Sglebius				error = ether_poll_deregister(ifp);
580150789Sglebius				/* Enable interrupt even in error case */
581150789Sglebius				IXGB_LOCK(adapter);
582150789Sglebius				ixgb_enable_intr(adapter);
583150789Sglebius				ifp->if_capenable &= ~IFCAP_POLLING;
584150789Sglebius				IXGB_UNLOCK(adapter);
585150789Sglebius			}
586150789Sglebius		}
587150789Sglebius#endif /* DEVICE_POLLING */
588129794Stackerman		if (mask & IFCAP_HWCSUM) {
589129794Stackerman			if (IFCAP_HWCSUM & ifp->if_capenable)
590129794Stackerman				ifp->if_capenable &= ~IFCAP_HWCSUM;
591129794Stackerman			else
592129794Stackerman				ifp->if_capenable |= IFCAP_HWCSUM;
593148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
594129794Stackerman				ixgb_init(adapter);
595129794Stackerman		}
596129794Stackerman		break;
597129794Stackerman	default:
598129794Stackerman		IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%X)\n", (int)command);
599129794Stackerman		error = EINVAL;
600129794Stackerman	}
601129794Stackerman
602129794Stackermanout:
603129794Stackerman	return (error);
604129794Stackerman}
605129794Stackerman
606129794Stackerman/*********************************************************************
607129794Stackerman *  Watchdog entry point
608129794Stackerman *
609129794Stackerman *  This routine is called whenever hardware quits transmitting.
610129794Stackerman *
611129794Stackerman **********************************************************************/
612129794Stackerman
613129794Stackermanstatic void
614129794Stackermanixgb_watchdog(struct ifnet * ifp)
615129794Stackerman{
616129794Stackerman	struct adapter *adapter;
617129794Stackerman	adapter = ifp->if_softc;
618129794Stackerman
619129794Stackerman	/*
620129794Stackerman	 * If we are in this routine because of pause frames, then don't
621129794Stackerman	 * reset the hardware.
622129794Stackerman	 */
623129794Stackerman	if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF) {
624129794Stackerman		ifp->if_timer = IXGB_TX_TIMEOUT;
625129794Stackerman		return;
626129794Stackerman	}
627129794Stackerman	printf("ixgb%d: watchdog timeout -- resetting\n", adapter->unit);
628129794Stackerman
629148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
630129794Stackerman
631129794Stackerman
632129794Stackerman	ixgb_stop(adapter);
633129794Stackerman	ixgb_init(adapter);
634129794Stackerman
635129794Stackerman
636129794Stackerman	ifp->if_oerrors++;
637129794Stackerman
638129794Stackerman	return;
639129794Stackerman}
640129794Stackerman
641129794Stackerman/*********************************************************************
642129794Stackerman *  Init entry point
643129794Stackerman *
644129794Stackerman *  This routine is used in two ways. It is used by the stack as
645129794Stackerman *  init entry point in network interface structure. It is also used
646129794Stackerman *  by the driver as a hw/sw initialization routine to get to a
647129794Stackerman *  consistent state.
648129794Stackerman *
649129794Stackerman *  return 0 on success, positive on failure
650129794Stackerman **********************************************************************/
651129794Stackerman
652129794Stackermanstatic void
653144651Salcixgb_init_locked(struct adapter *adapter)
654129794Stackerman{
655129794Stackerman	struct ifnet   *ifp;
656129794Stackerman
657129794Stackerman	INIT_DEBUGOUT("ixgb_init: begin");
658129794Stackerman
659144651Salc	IXGB_LOCK_ASSERT(adapter);
660129794Stackerman
661129794Stackerman	ixgb_stop(adapter);
662129794Stackerman
663129794Stackerman	/* Get the latest mac address, User can use a LAA */
664147256Sbrooks	bcopy(IFP2ENADDR(adapter->ifp), adapter->hw.curr_mac_addr,
665129794Stackerman	      IXGB_ETH_LENGTH_OF_ADDRESS);
666129794Stackerman
667129794Stackerman	/* Initialize the hardware */
668129794Stackerman	if (ixgb_hardware_init(adapter)) {
669129794Stackerman		printf("ixgb%d: Unable to initialize the hardware\n",
670129794Stackerman		       adapter->unit);
671129794Stackerman		return;
672129794Stackerman	}
673129794Stackerman	ixgb_enable_vlans(adapter);
674129794Stackerman
675129794Stackerman	/* Prepare transmit descriptors and buffers */
676129794Stackerman	if (ixgb_setup_transmit_structures(adapter)) {
677129794Stackerman		printf("ixgb%d: Could not setup transmit structures\n",
678129794Stackerman		       adapter->unit);
679129794Stackerman		ixgb_stop(adapter);
680129794Stackerman		return;
681129794Stackerman	}
682129794Stackerman	ixgb_initialize_transmit_unit(adapter);
683129794Stackerman
684129794Stackerman	/* Setup Multicast table */
685129794Stackerman	ixgb_set_multi(adapter);
686129794Stackerman
687129794Stackerman	/* Prepare receive descriptors and buffers */
688129794Stackerman	if (ixgb_setup_receive_structures(adapter)) {
689129794Stackerman		printf("ixgb%d: Could not setup receive structures\n",
690129794Stackerman		       adapter->unit);
691129794Stackerman		ixgb_stop(adapter);
692129794Stackerman		return;
693129794Stackerman	}
694129794Stackerman	ixgb_initialize_receive_unit(adapter);
695129794Stackerman
696129794Stackerman	/* Don't loose promiscuous settings */
697129794Stackerman	ixgb_set_promisc(adapter);
698129794Stackerman
699147256Sbrooks	ifp = adapter->ifp;
700148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
701148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
702129794Stackerman
703129794Stackerman
704129794Stackerman	if (ifp->if_capenable & IFCAP_TXCSUM)
705129794Stackerman		ifp->if_hwassist = IXGB_CHECKSUM_FEATURES;
706129794Stackerman	else
707129794Stackerman		ifp->if_hwassist = 0;
708129794Stackerman
709129794Stackerman
710129794Stackerman	/* Enable jumbo frames */
711129794Stackerman	if (ifp->if_mtu > ETHERMTU) {
712129794Stackerman		uint32_t        temp_reg;
713129794Stackerman		IXGB_WRITE_REG(&adapter->hw, MFS,
714129794Stackerman			       adapter->hw.max_frame_size << IXGB_MFS_SHIFT);
715129794Stackerman		temp_reg = IXGB_READ_REG(&adapter->hw, CTRL0);
716129794Stackerman		temp_reg |= IXGB_CTRL0_JFE;
717129794Stackerman		IXGB_WRITE_REG(&adapter->hw, CTRL0, temp_reg);
718129794Stackerman	}
719144651Salc	callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, adapter);
720129794Stackerman	ixgb_clear_hw_cntrs(&adapter->hw);
721129794Stackerman#ifdef DEVICE_POLLING
722129794Stackerman	/*
723129794Stackerman	 * Only disable interrupts if we are polling, make sure they are on
724129794Stackerman	 * otherwise.
725129794Stackerman	 */
726150789Sglebius	if (ifp->if_capenable & IFCAP_POLLING)
727129794Stackerman		ixgb_disable_intr(adapter);
728129794Stackerman	else
729150789Sglebius#endif
730129794Stackerman		ixgb_enable_intr(adapter);
731129794Stackerman
732129794Stackerman	return;
733129794Stackerman}
734129794Stackerman
735144651Salcstatic void
736144651Salcixgb_init(void *arg)
737144651Salc{
738144651Salc	struct adapter *adapter = arg;
739129794Stackerman
740144651Salc	IXGB_LOCK(adapter);
741144651Salc	ixgb_init_locked(adapter);
742144651Salc	IXGB_UNLOCK(adapter);
743144651Salc	return;
744144651Salc}
745144651Salc
746129794Stackerman#ifdef DEVICE_POLLING
747129794Stackermanstatic void
748144651Salcixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count)
749129794Stackerman{
750129794Stackerman	struct adapter *adapter = ifp->if_softc;
751129794Stackerman	u_int32_t       reg_icr;
752129794Stackerman
753144651Salc	IXGB_LOCK_ASSERT(adapter);
754144651Salc
755129794Stackerman	if (cmd == POLL_AND_CHECK_STATUS) {
756129794Stackerman		reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
757129794Stackerman		if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
758144651Salc			callout_stop(&adapter->timer);
759129794Stackerman			ixgb_check_for_link(&adapter->hw);
760129794Stackerman			ixgb_print_link_status(adapter);
761144651Salc			callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer,
762144651Salc			    adapter);
763129794Stackerman		}
764129794Stackerman	}
765150789Sglebius	ixgb_process_receive_interrupts(adapter, count);
766150789Sglebius	ixgb_clean_transmit_interrupts(adapter);
767150789Sglebius
768150789Sglebius	if (ifp->if_snd.ifq_head != NULL)
769144651Salc		ixgb_start_locked(ifp);
770129794Stackerman}
771144651Salc
772144651Salcstatic void
773144651Salcixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count)
774144651Salc{
775144651Salc	struct adapter *adapter = ifp->if_softc;
776144651Salc
777144651Salc	IXGB_LOCK(adapter);
778150789Sglebius	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
779150789Sglebius		ixgb_poll_locked(ifp, cmd, count);
780144651Salc	IXGB_UNLOCK(adapter);
781144651Salc}
782150789Sglebius#endif /* DEVICE_POLLING */
783129794Stackerman
784129794Stackerman/*********************************************************************
785129794Stackerman *
786129794Stackerman *  Interrupt Service routine
787129794Stackerman *
788129794Stackerman **********************************************************************/
789129794Stackerman
790129794Stackermanstatic void
791129794Stackermanixgb_intr(void *arg)
792129794Stackerman{
793129794Stackerman	u_int32_t       loop_cnt = IXGB_MAX_INTR;
794129794Stackerman	u_int32_t       reg_icr;
795129794Stackerman	struct ifnet   *ifp;
796129794Stackerman	struct adapter *adapter = arg;
797129794Stackerman	boolean_t       rxdmt0 = FALSE;
798129794Stackerman
799144651Salc	IXGB_LOCK(adapter);
800144651Salc
801147256Sbrooks	ifp = adapter->ifp;
802129794Stackerman
803129794Stackerman#ifdef DEVICE_POLLING
804150789Sglebius	if (ifp->if_capenable & IFCAP_POLLING) {
805144651Salc		IXGB_UNLOCK(adapter);
806129794Stackerman		return;
807144651Salc	}
808150789Sglebius#endif
809129794Stackerman
810144651Salc	reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
811144651Salc	if (reg_icr == 0) {
812144651Salc		IXGB_UNLOCK(adapter);
813129794Stackerman		return;
814144651Salc	}
815129794Stackerman
816129794Stackerman	if (reg_icr & IXGB_INT_RXDMT0)
817129794Stackerman		rxdmt0 = TRUE;
818129794Stackerman
819129794Stackerman#ifdef _SV_
820129794Stackerman	if (reg_icr & IXGB_INT_RXDMT0)
821129794Stackerman		adapter->sv_stats.icr_rxdmt0++;
822129794Stackerman	if (reg_icr & IXGB_INT_RXO)
823129794Stackerman		adapter->sv_stats.icr_rxo++;
824129794Stackerman	if (reg_icr & IXGB_INT_RXT0)
825129794Stackerman		adapter->sv_stats.icr_rxt0++;
826129794Stackerman	if (reg_icr & IXGB_INT_TXDW)
827129794Stackerman		adapter->sv_stats.icr_TXDW++;
828129794Stackerman#endif				/* _SV_ */
829129794Stackerman
830129794Stackerman	/* Link status change */
831129794Stackerman	if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
832144651Salc		callout_stop(&adapter->timer);
833129794Stackerman		ixgb_check_for_link(&adapter->hw);
834129794Stackerman		ixgb_print_link_status(adapter);
835144651Salc		callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer,
836144651Salc		    adapter);
837129794Stackerman	}
838129794Stackerman	while (loop_cnt > 0) {
839148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
840129794Stackerman			ixgb_process_receive_interrupts(adapter, -1);
841129794Stackerman			ixgb_clean_transmit_interrupts(adapter);
842129794Stackerman		}
843129794Stackerman		loop_cnt--;
844129794Stackerman	}
845129794Stackerman
846129794Stackerman	if (rxdmt0 && adapter->raidc) {
847129794Stackerman		IXGB_WRITE_REG(&adapter->hw, IMC, IXGB_INT_RXDMT0);
848129794Stackerman		IXGB_WRITE_REG(&adapter->hw, IMS, IXGB_INT_RXDMT0);
849129794Stackerman	}
850148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING && ifp->if_snd.ifq_head != NULL)
851144651Salc		ixgb_start_locked(ifp);
852129794Stackerman
853144651Salc	IXGB_UNLOCK(adapter);
854129794Stackerman	return;
855129794Stackerman}
856129794Stackerman
857129794Stackerman
858129794Stackerman/*********************************************************************
859129794Stackerman *
860129794Stackerman *  Media Ioctl callback
861129794Stackerman *
862129794Stackerman *  This routine is called whenever the user queries the status of
863129794Stackerman *  the interface using ifconfig.
864129794Stackerman *
865129794Stackerman **********************************************************************/
866129794Stackermanstatic void
867129794Stackermanixgb_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
868129794Stackerman{
869129794Stackerman	struct adapter *adapter = ifp->if_softc;
870129794Stackerman
871129794Stackerman	INIT_DEBUGOUT("ixgb_media_status: begin");
872129794Stackerman
873129794Stackerman	ixgb_check_for_link(&adapter->hw);
874129794Stackerman	ixgb_print_link_status(adapter);
875129794Stackerman
876129794Stackerman	ifmr->ifm_status = IFM_AVALID;
877129794Stackerman	ifmr->ifm_active = IFM_ETHER;
878129794Stackerman
879129794Stackerman	if (!adapter->hw.link_up)
880129794Stackerman		return;
881129794Stackerman
882129794Stackerman	ifmr->ifm_status |= IFM_ACTIVE;
883129794Stackerman	ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
884129794Stackerman
885129794Stackerman	return;
886129794Stackerman}
887129794Stackerman
888129794Stackerman/*********************************************************************
889129794Stackerman *
890129794Stackerman *  Media Ioctl callback
891129794Stackerman *
892129794Stackerman *  This routine is called when the user changes speed/duplex using
893129794Stackerman *  media/mediopt option with ifconfig.
894129794Stackerman *
895129794Stackerman **********************************************************************/
896129794Stackermanstatic int
897129794Stackermanixgb_media_change(struct ifnet * ifp)
898129794Stackerman{
899129794Stackerman	struct adapter *adapter = ifp->if_softc;
900129794Stackerman	struct ifmedia *ifm = &adapter->media;
901129794Stackerman
902129794Stackerman	INIT_DEBUGOUT("ixgb_media_change: begin");
903129794Stackerman
904129794Stackerman	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
905129794Stackerman		return (EINVAL);
906129794Stackerman
907129794Stackerman	return (0);
908129794Stackerman}
909129794Stackerman
910129794Stackerman/*********************************************************************
911129794Stackerman *
912129794Stackerman *  This routine maps the mbufs to tx descriptors.
913129794Stackerman *
914129794Stackerman *  return 0 on success, positive on failure
915129794Stackerman **********************************************************************/
916129794Stackerman
917129794Stackermanstatic int
918129794Stackermanixgb_encap(struct adapter * adapter, struct mbuf * m_head)
919129794Stackerman{
920129794Stackerman	u_int8_t        txd_popts;
921146339Salc	int             i, j, error, nsegs;
922129794Stackerman
923129794Stackerman#if __FreeBSD_version < 500000
924129794Stackerman	struct ifvlan  *ifv = NULL;
925129794Stackerman#else
926129794Stackerman	struct m_tag   *mtag;
927129794Stackerman#endif
928146339Salc	bus_dma_segment_t segs[IXGB_MAX_SCATTER];
929146339Salc	bus_dmamap_t	map;
930129794Stackerman	struct ixgb_buffer *tx_buffer = NULL;
931129794Stackerman	struct ixgb_tx_desc *current_tx_desc = NULL;
932147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
933129794Stackerman
934129794Stackerman	/*
935129794Stackerman	 * Force a cleanup if number of TX descriptors available hits the
936129794Stackerman	 * threshold
937129794Stackerman	 */
938129794Stackerman	if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) {
939129794Stackerman		ixgb_clean_transmit_interrupts(adapter);
940129794Stackerman	}
941129794Stackerman	if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) {
942129794Stackerman		adapter->no_tx_desc_avail1++;
943129794Stackerman		return (ENOBUFS);
944129794Stackerman	}
945129794Stackerman	/*
946129794Stackerman	 * Map the packet for DMA.
947129794Stackerman	 */
948146339Salc	if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &map)) {
949129794Stackerman		adapter->no_tx_map_avail++;
950129794Stackerman		return (ENOMEM);
951129794Stackerman	}
952146339Salc	error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs,
953146339Salc					&nsegs, BUS_DMA_NOWAIT);
954129794Stackerman	if (error != 0) {
955129794Stackerman		adapter->no_tx_dma_setup++;
956129794Stackerman		printf("ixgb%d: ixgb_encap: bus_dmamap_load_mbuf failed; "
957129794Stackerman		       "error %u\n", adapter->unit, error);
958146339Salc		bus_dmamap_destroy(adapter->txtag, map);
959129794Stackerman		return (error);
960129794Stackerman	}
961146339Salc	KASSERT(nsegs != 0, ("ixgb_encap: empty packet"));
962129794Stackerman
963146339Salc	if (nsegs > adapter->num_tx_desc_avail) {
964129794Stackerman		adapter->no_tx_desc_avail2++;
965146339Salc		bus_dmamap_destroy(adapter->txtag, map);
966129794Stackerman		return (ENOBUFS);
967129794Stackerman	}
968129794Stackerman	if (ifp->if_hwassist > 0) {
969129794Stackerman		ixgb_transmit_checksum_setup(adapter, m_head,
970129794Stackerman					     &txd_popts);
971129794Stackerman	} else
972129794Stackerman		txd_popts = 0;
973129794Stackerman
974129794Stackerman	/* Find out if we are in vlan mode */
975129794Stackerman#if __FreeBSD_version < 500000
976129794Stackerman	if ((m_head->m_flags & (M_PROTO1 | M_PKTHDR)) == (M_PROTO1 | M_PKTHDR) &&
977129794Stackerman	    m_head->m_pkthdr.rcvif != NULL &&
978129794Stackerman	    m_head->m_pkthdr.rcvif->if_type == IFT_L2VLAN)
979129794Stackerman		ifv = m_head->m_pkthdr.rcvif->if_softc;
980129794Stackerman#else
981129794Stackerman	mtag = VLAN_OUTPUT_TAG(ifp, m_head);
982129794Stackerman#endif
983129794Stackerman	i = adapter->next_avail_tx_desc;
984146339Salc	for (j = 0; j < nsegs; j++) {
985129794Stackerman		tx_buffer = &adapter->tx_buffer_area[i];
986129794Stackerman		current_tx_desc = &adapter->tx_desc_base[i];
987129794Stackerman
988146339Salc		current_tx_desc->buff_addr = htole64(segs[j].ds_addr);
989146339Salc		current_tx_desc->cmd_type_len = (adapter->txd_cmd | segs[j].ds_len);
990129794Stackerman		current_tx_desc->popts = txd_popts;
991129794Stackerman		if (++i == adapter->num_tx_desc)
992129794Stackerman			i = 0;
993129794Stackerman
994129794Stackerman		tx_buffer->m_head = NULL;
995129794Stackerman	}
996129794Stackerman
997146339Salc	adapter->num_tx_desc_avail -= nsegs;
998129794Stackerman	adapter->next_avail_tx_desc = i;
999129794Stackerman
1000129794Stackerman#if __FreeBSD_version < 500000
1001129794Stackerman	if (ifv != NULL) {
1002129794Stackerman		/* Set the vlan id */
1003129794Stackerman		current_tx_desc->vlan = ifv->ifv_tag;
1004129794Stackerman#else
1005129794Stackerman	if (mtag != NULL) {
1006129794Stackerman		/* Set the vlan id */
1007129794Stackerman		current_tx_desc->vlan = VLAN_TAG_VALUE(mtag);
1008129794Stackerman#endif
1009129794Stackerman
1010129794Stackerman		/* Tell hardware to add tag */
1011129794Stackerman		current_tx_desc->cmd_type_len |= IXGB_TX_DESC_CMD_VLE;
1012129794Stackerman	}
1013129794Stackerman	tx_buffer->m_head = m_head;
1014146339Salc	tx_buffer->map = map;
1015146339Salc	bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE);
1016129794Stackerman
1017129794Stackerman	/*
1018129794Stackerman	 * Last Descriptor of Packet needs End Of Packet (EOP)
1019129794Stackerman	 */
1020129794Stackerman	current_tx_desc->cmd_type_len |= (IXGB_TX_DESC_CMD_EOP);
1021129794Stackerman
1022129794Stackerman	/*
1023129794Stackerman	 * Advance the Transmit Descriptor Tail (Tdt), this tells the E1000
1024129794Stackerman	 * that this frame is available to transmit.
1025129794Stackerman	 */
1026129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDT, i);
1027129794Stackerman
1028129794Stackerman	return (0);
1029129794Stackerman}
1030129794Stackerman
1031129794Stackermanstatic void
1032129794Stackermanixgb_set_promisc(struct adapter * adapter)
1033129794Stackerman{
1034129794Stackerman
1035129794Stackerman	u_int32_t       reg_rctl;
1036147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
1037129794Stackerman
1038129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1039129794Stackerman
1040129794Stackerman	if (ifp->if_flags & IFF_PROMISC) {
1041129794Stackerman		reg_rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
1042129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1043129794Stackerman	} else if (ifp->if_flags & IFF_ALLMULTI) {
1044129794Stackerman		reg_rctl |= IXGB_RCTL_MPE;
1045129794Stackerman		reg_rctl &= ~IXGB_RCTL_UPE;
1046129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1047129794Stackerman	}
1048129794Stackerman	return;
1049129794Stackerman}
1050129794Stackerman
1051129794Stackermanstatic void
1052129794Stackermanixgb_disable_promisc(struct adapter * adapter)
1053129794Stackerman{
1054129794Stackerman	u_int32_t       reg_rctl;
1055129794Stackerman
1056129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1057129794Stackerman
1058129794Stackerman	reg_rctl &= (~IXGB_RCTL_UPE);
1059129794Stackerman	reg_rctl &= (~IXGB_RCTL_MPE);
1060129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1061129794Stackerman
1062129794Stackerman	return;
1063129794Stackerman}
1064129794Stackerman
1065129794Stackerman
1066129794Stackerman/*********************************************************************
1067129794Stackerman *  Multicast Update
1068129794Stackerman *
1069129794Stackerman *  This routine is called whenever multicast address list is updated.
1070129794Stackerman *
1071129794Stackerman **********************************************************************/
1072129794Stackerman
1073129794Stackermanstatic void
1074129794Stackermanixgb_set_multi(struct adapter * adapter)
1075129794Stackerman{
1076129794Stackerman	u_int32_t       reg_rctl = 0;
1077129794Stackerman	u_int8_t        mta[MAX_NUM_MULTICAST_ADDRESSES * IXGB_ETH_LENGTH_OF_ADDRESS];
1078129794Stackerman	struct ifmultiaddr *ifma;
1079129794Stackerman	int             mcnt = 0;
1080147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
1081129794Stackerman
1082129794Stackerman	IOCTL_DEBUGOUT("ixgb_set_multi: begin");
1083129794Stackerman
1084148654Srwatson	IF_ADDR_LOCK(ifp);
1085129794Stackerman#if __FreeBSD_version < 500000
1086129794Stackerman	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1087129794Stackerman#else
1088129794Stackerman	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1089129794Stackerman#endif
1090129794Stackerman		if (ifma->ifma_addr->sa_family != AF_LINK)
1091129794Stackerman			continue;
1092129794Stackerman
1093129794Stackerman		bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
1094129794Stackerman		      &mta[mcnt * IXGB_ETH_LENGTH_OF_ADDRESS], IXGB_ETH_LENGTH_OF_ADDRESS);
1095129794Stackerman		mcnt++;
1096129794Stackerman	}
1097148654Srwatson	IF_ADDR_UNLOCK(ifp);
1098129794Stackerman
1099129794Stackerman	if (mcnt > MAX_NUM_MULTICAST_ADDRESSES) {
1100129794Stackerman		reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1101129794Stackerman		reg_rctl |= IXGB_RCTL_MPE;
1102129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1103129794Stackerman	} else
1104129794Stackerman		ixgb_mc_addr_list_update(&adapter->hw, mta, mcnt, 0);
1105129794Stackerman
1106129794Stackerman	return;
1107129794Stackerman}
1108129794Stackerman
1109129794Stackerman
1110129794Stackerman/*********************************************************************
1111129794Stackerman *  Timer routine
1112129794Stackerman *
1113129794Stackerman *  This routine checks for link status and updates statistics.
1114129794Stackerman *
1115129794Stackerman **********************************************************************/
1116129794Stackerman
1117129794Stackermanstatic void
1118129794Stackermanixgb_local_timer(void *arg)
1119129794Stackerman{
1120129794Stackerman	struct ifnet   *ifp;
1121129794Stackerman	struct adapter *adapter = arg;
1122147256Sbrooks	ifp = adapter->ifp;
1123129794Stackerman
1124144651Salc	IXGB_LOCK(adapter);
1125129794Stackerman
1126129794Stackerman	ixgb_check_for_link(&adapter->hw);
1127129794Stackerman	ixgb_print_link_status(adapter);
1128129794Stackerman	ixgb_update_stats_counters(adapter);
1129148887Srwatson	if (ixgb_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) {
1130129794Stackerman		ixgb_print_hw_stats(adapter);
1131129794Stackerman	}
1132144651Salc	callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, adapter);
1133129794Stackerman
1134144651Salc	IXGB_UNLOCK(adapter);
1135129794Stackerman	return;
1136129794Stackerman}
1137129794Stackerman
1138129794Stackermanstatic void
1139129794Stackermanixgb_print_link_status(struct adapter * adapter)
1140129794Stackerman{
1141129794Stackerman	if (adapter->hw.link_up) {
1142129794Stackerman		if (!adapter->link_active) {
1143129794Stackerman			printf("ixgb%d: Link is up %d Mbps %s \n",
1144129794Stackerman			       adapter->unit,
1145129794Stackerman			       10000,
1146129794Stackerman			       "Full Duplex");
1147129794Stackerman			adapter->link_active = 1;
1148129794Stackerman		}
1149129794Stackerman	} else {
1150129794Stackerman		if (adapter->link_active) {
1151129794Stackerman			printf("ixgb%d: Link is Down \n", adapter->unit);
1152129794Stackerman			adapter->link_active = 0;
1153129794Stackerman		}
1154129794Stackerman	}
1155129794Stackerman
1156129794Stackerman	return;
1157129794Stackerman}
1158129794Stackerman
1159129794Stackerman
1160129794Stackerman
1161129794Stackerman/*********************************************************************
1162129794Stackerman *
1163129794Stackerman *  This routine disables all traffic on the adapter by issuing a
1164129794Stackerman *  global reset on the MAC and deallocates TX/RX buffers.
1165129794Stackerman *
1166129794Stackerman **********************************************************************/
1167129794Stackerman
1168129794Stackermanstatic void
1169129794Stackermanixgb_stop(void *arg)
1170129794Stackerman{
1171129794Stackerman	struct ifnet   *ifp;
1172129794Stackerman	struct adapter *adapter = arg;
1173147256Sbrooks	ifp = adapter->ifp;
1174129794Stackerman
1175144651Salc	IXGB_LOCK_ASSERT(adapter);
1176144651Salc
1177129794Stackerman	INIT_DEBUGOUT("ixgb_stop: begin\n");
1178129794Stackerman	ixgb_disable_intr(adapter);
1179129794Stackerman	adapter->hw.adapter_stopped = FALSE;
1180129794Stackerman	ixgb_adapter_stop(&adapter->hw);
1181144651Salc	callout_stop(&adapter->timer);
1182129794Stackerman	ixgb_free_transmit_structures(adapter);
1183129794Stackerman	ixgb_free_receive_structures(adapter);
1184129794Stackerman
1185129794Stackerman
1186129794Stackerman	/* Tell the stack that the interface is no longer active */
1187148887Srwatson	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1188129794Stackerman
1189129794Stackerman	return;
1190129794Stackerman}
1191129794Stackerman
1192129794Stackerman
1193129794Stackerman/*********************************************************************
1194129794Stackerman *
1195129794Stackerman *  Determine hardware revision.
1196129794Stackerman *
1197129794Stackerman **********************************************************************/
1198129794Stackermanstatic void
1199129794Stackermanixgb_identify_hardware(struct adapter * adapter)
1200129794Stackerman{
1201129794Stackerman	device_t        dev = adapter->dev;
1202129794Stackerman
1203129794Stackerman	/* Make sure our PCI config space has the necessary stuff set */
1204129794Stackerman	adapter->hw.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);
1205129794Stackerman	if (!((adapter->hw.pci_cmd_word & PCIM_CMD_BUSMASTEREN) &&
1206129794Stackerman	      (adapter->hw.pci_cmd_word & PCIM_CMD_MEMEN))) {
1207129794Stackerman		printf("ixgb%d: Memory Access and/or Bus Master bits were not set!\n",
1208129794Stackerman		       adapter->unit);
1209129794Stackerman		adapter->hw.pci_cmd_word |=
1210129794Stackerman			(PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
1211129794Stackerman		pci_write_config(dev, PCIR_COMMAND, adapter->hw.pci_cmd_word, 2);
1212129794Stackerman	}
1213129794Stackerman	/* Save off the information about this board */
1214129794Stackerman	adapter->hw.vendor_id = pci_get_vendor(dev);
1215129794Stackerman	adapter->hw.device_id = pci_get_device(dev);
1216129794Stackerman	adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1);
1217129794Stackerman	adapter->hw.subsystem_vendor_id = pci_read_config(dev, PCIR_SUBVEND_0, 2);
1218129794Stackerman	adapter->hw.subsystem_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
1219129794Stackerman
1220129794Stackerman	/* Set MacType, etc. based on this PCI info */
1221129794Stackerman	switch (adapter->hw.device_id) {
1222129794Stackerman	case IXGB_DEVICE_ID_82597EX:
1223129794Stackerman	case IXGB_DEVICE_ID_82597EX_SR:
1224129794Stackerman		adapter->hw.mac_type = ixgb_82597;
1225129794Stackerman		break;
1226129794Stackerman	default:
1227129794Stackerman		INIT_DEBUGOUT1("Unknown device if 0x%x", adapter->hw.device_id);
1228129794Stackerman		printf("ixgb%d: unsupported device id 0x%x\n", adapter->unit, adapter->hw.device_id);
1229129794Stackerman	}
1230129794Stackerman
1231129794Stackerman	return;
1232129794Stackerman}
1233129794Stackerman
1234129794Stackermanstatic int
1235129794Stackermanixgb_allocate_pci_resources(struct adapter * adapter)
1236129794Stackerman{
1237129794Stackerman	int             rid;
1238129794Stackerman	device_t        dev = adapter->dev;
1239129794Stackerman
1240129794Stackerman	rid = IXGB_MMBA;
1241129794Stackerman	adapter->res_memory = bus_alloc_resource(dev, SYS_RES_MEMORY,
1242129794Stackerman						 &rid, 0, ~0, 1,
1243129794Stackerman						 RF_ACTIVE);
1244129794Stackerman	if (!(adapter->res_memory)) {
1245129794Stackerman		printf("ixgb%d: Unable to allocate bus resource: memory\n",
1246129794Stackerman		       adapter->unit);
1247129794Stackerman		return (ENXIO);
1248129794Stackerman	}
1249129794Stackerman	adapter->osdep.mem_bus_space_tag =
1250129794Stackerman		rman_get_bustag(adapter->res_memory);
1251129794Stackerman	adapter->osdep.mem_bus_space_handle =
1252129794Stackerman		rman_get_bushandle(adapter->res_memory);
1253129794Stackerman	adapter->hw.hw_addr = (uint8_t *) & adapter->osdep.mem_bus_space_handle;
1254129794Stackerman
1255129794Stackerman	rid = 0x0;
1256129794Stackerman	adapter->res_interrupt = bus_alloc_resource(dev, SYS_RES_IRQ,
1257129794Stackerman						    &rid, 0, ~0, 1,
1258129794Stackerman						  RF_SHAREABLE | RF_ACTIVE);
1259129794Stackerman	if (!(adapter->res_interrupt)) {
1260129794Stackerman		printf("ixgb%d: Unable to allocate bus resource: interrupt\n",
1261129794Stackerman		       adapter->unit);
1262129794Stackerman		return (ENXIO);
1263129794Stackerman	}
1264144651Salc	if (bus_setup_intr(dev, adapter->res_interrupt,
1265144651Salc			   INTR_TYPE_NET | INTR_MPSAFE,
1266129794Stackerman			   (void (*) (void *))ixgb_intr, adapter,
1267129794Stackerman			   &adapter->int_handler_tag)) {
1268129794Stackerman		printf("ixgb%d: Error registering interrupt handler!\n",
1269129794Stackerman		       adapter->unit);
1270129794Stackerman		return (ENXIO);
1271129794Stackerman	}
1272129794Stackerman	adapter->hw.back = &adapter->osdep;
1273129794Stackerman
1274129794Stackerman	return (0);
1275129794Stackerman}
1276129794Stackerman
1277129794Stackermanstatic void
1278129794Stackermanixgb_free_pci_resources(struct adapter * adapter)
1279129794Stackerman{
1280129794Stackerman	device_t        dev = adapter->dev;
1281129794Stackerman
1282129794Stackerman	if (adapter->res_interrupt != NULL) {
1283129794Stackerman		bus_teardown_intr(dev, adapter->res_interrupt,
1284129794Stackerman				  adapter->int_handler_tag);
1285129794Stackerman		bus_release_resource(dev, SYS_RES_IRQ, 0,
1286129794Stackerman				     adapter->res_interrupt);
1287129794Stackerman	}
1288129794Stackerman	if (adapter->res_memory != NULL) {
1289129794Stackerman		bus_release_resource(dev, SYS_RES_MEMORY, IXGB_MMBA,
1290129794Stackerman				     adapter->res_memory);
1291129794Stackerman	}
1292129794Stackerman	if (adapter->res_ioport != NULL) {
1293129794Stackerman		bus_release_resource(dev, SYS_RES_IOPORT, adapter->io_rid,
1294129794Stackerman				     adapter->res_ioport);
1295129794Stackerman	}
1296129794Stackerman	return;
1297129794Stackerman}
1298129794Stackerman
1299129794Stackerman/*********************************************************************
1300129794Stackerman *
1301129794Stackerman *  Initialize the hardware to a configuration as specified by the
1302129794Stackerman *  adapter structure. The controller is reset, the EEPROM is
1303129794Stackerman *  verified, the MAC address is set, then the shared initialization
1304129794Stackerman *  routines are called.
1305129794Stackerman *
1306129794Stackerman **********************************************************************/
1307129794Stackermanstatic int
1308129794Stackermanixgb_hardware_init(struct adapter * adapter)
1309129794Stackerman{
1310129794Stackerman	/* Issue a global reset */
1311129794Stackerman	adapter->hw.adapter_stopped = FALSE;
1312129794Stackerman	ixgb_adapter_stop(&adapter->hw);
1313129794Stackerman
1314129794Stackerman	/* Make sure we have a good EEPROM before we read from it */
1315129794Stackerman	if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
1316129794Stackerman		printf("ixgb%d: The EEPROM Checksum Is Not Valid\n",
1317129794Stackerman		       adapter->unit);
1318129794Stackerman		return (EIO);
1319129794Stackerman	}
1320129794Stackerman	if (!ixgb_init_hw(&adapter->hw)) {
1321129794Stackerman		printf("ixgb%d: Hardware Initialization Failed",
1322129794Stackerman		       adapter->unit);
1323129794Stackerman		return (EIO);
1324129794Stackerman	}
1325129794Stackerman
1326129794Stackerman	return (0);
1327129794Stackerman}
1328129794Stackerman
1329129794Stackerman/*********************************************************************
1330129794Stackerman *
1331129794Stackerman *  Setup networking device structure and register an interface.
1332129794Stackerman *
1333129794Stackerman **********************************************************************/
1334129794Stackermanstatic void
1335129794Stackermanixgb_setup_interface(device_t dev, struct adapter * adapter)
1336129794Stackerman{
1337129794Stackerman	struct ifnet   *ifp;
1338129794Stackerman	INIT_DEBUGOUT("ixgb_setup_interface: begin");
1339129794Stackerman
1340147256Sbrooks	ifp = adapter->ifp = if_alloc(IFT_ETHER);
1341147256Sbrooks	if (ifp == NULL)
1342147256Sbrooks		panic("%s: can not if_alloc()\n", device_get_nameunit(dev));
1343129794Stackerman#if __FreeBSD_version >= 502000
1344129794Stackerman	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1345129794Stackerman#else
1346129794Stackerman	ifp->if_unit = adapter->unit;
1347129794Stackerman	ifp->if_name = "ixgb";
1348129794Stackerman#endif
1349129794Stackerman	ifp->if_mtu = ETHERMTU;
1350129794Stackerman	ifp->if_baudrate = 1000000000;
1351129794Stackerman	ifp->if_init = ixgb_init;
1352129794Stackerman	ifp->if_softc = adapter;
1353144651Salc	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1354129794Stackerman	ifp->if_ioctl = ixgb_ioctl;
1355129794Stackerman	ifp->if_start = ixgb_start;
1356129794Stackerman	ifp->if_watchdog = ixgb_watchdog;
1357129794Stackerman	ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 1;
1358129794Stackerman
1359129794Stackerman#if __FreeBSD_version < 500000
1360129794Stackerman	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
1361129794Stackerman#else
1362147256Sbrooks	ether_ifattach(ifp, adapter->hw.curr_mac_addr);
1363129794Stackerman#endif
1364129794Stackerman
1365129794Stackerman	ifp->if_capabilities = IFCAP_HWCSUM;
1366129794Stackerman
1367129794Stackerman	/*
1368129794Stackerman	 * Tell the upper layer(s) we support long frames.
1369129794Stackerman	 */
1370129794Stackerman	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
1371129794Stackerman
1372129794Stackerman#if __FreeBSD_version >= 500000
1373129794Stackerman	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
1374129794Stackerman#endif
1375148637Sbrueffer
1376148637Sbrueffer	ifp->if_capenable = ifp->if_capabilities;
1377148637Sbrueffer
1378150789Sglebius#ifdef DEVICE_POLLING
1379150789Sglebius	ifp->if_capabilities |= IFCAP_POLLING;
1380150789Sglebius#endif
1381150789Sglebius
1382129794Stackerman	/*
1383129794Stackerman	 * Specify the media types supported by this adapter and register
1384129794Stackerman	 * callbacks to update media and link information
1385129794Stackerman	 */
1386129794Stackerman	ifmedia_init(&adapter->media, IFM_IMASK, ixgb_media_change,
1387129794Stackerman		     ixgb_media_status);
1388129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX | IFM_FDX,
1389129794Stackerman		    0, NULL);
1390129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX,
1391129794Stackerman		    0, NULL);
1392129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
1393129794Stackerman	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
1394129794Stackerman
1395129794Stackerman	return;
1396129794Stackerman}
1397129794Stackerman
1398129794Stackerman/********************************************************************
1399129794Stackerman * Manage DMA'able memory.
1400129794Stackerman *******************************************************************/
1401129794Stackermanstatic void
1402129794Stackermanixgb_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg, int error)
1403129794Stackerman{
1404129794Stackerman	if (error)
1405129794Stackerman		return;
1406129794Stackerman	*(bus_addr_t *) arg = segs->ds_addr;
1407129794Stackerman	return;
1408129794Stackerman}
1409129794Stackerman
1410129794Stackermanstatic int
1411129794Stackermanixgb_dma_malloc(struct adapter * adapter, bus_size_t size,
1412129794Stackerman		struct ixgb_dma_alloc * dma, int mapflags)
1413129794Stackerman{
1414129794Stackerman	int             r;
1415129794Stackerman
1416129794Stackerman	r = bus_dma_tag_create(NULL,	/* parent */
1417129794Stackerman			       PAGE_SIZE, 0,	/* alignment, bounds */
1418129794Stackerman			       BUS_SPACE_MAXADDR,	/* lowaddr */
1419129794Stackerman			       BUS_SPACE_MAXADDR,	/* highaddr */
1420129794Stackerman			       NULL, NULL,	/* filter, filterarg */
1421129794Stackerman			       size,	/* maxsize */
1422129794Stackerman			       1,	/* nsegments */
1423129794Stackerman			       size,	/* maxsegsize */
1424129794Stackerman			       BUS_DMA_ALLOCNOW,	/* flags */
1425129794Stackerman#if __FreeBSD_version >= 502000
1426129794Stackerman			       NULL,	/* lockfunc */
1427129794Stackerman			       NULL,	/* lockfuncarg */
1428129794Stackerman#endif
1429129794Stackerman			       &dma->dma_tag);
1430129794Stackerman	if (r != 0) {
1431129794Stackerman		printf("ixgb%d: ixgb_dma_malloc: bus_dma_tag_create failed; "
1432129794Stackerman		       "error %u\n", adapter->unit, r);
1433129794Stackerman		goto fail_0;
1434129794Stackerman	}
1435129794Stackerman	r = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr,
1436129794Stackerman			     BUS_DMA_NOWAIT, &dma->dma_map);
1437129794Stackerman	if (r != 0) {
1438129794Stackerman		printf("ixgb%d: ixgb_dma_malloc: bus_dmamem_alloc failed; "
1439129794Stackerman		       "error %u\n", adapter->unit, r);
1440144183Smux		goto fail_1;
1441129794Stackerman	}
1442129794Stackerman	r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
1443129794Stackerman			    size,
1444129794Stackerman			    ixgb_dmamap_cb,
1445129794Stackerman			    &dma->dma_paddr,
1446129794Stackerman			    mapflags | BUS_DMA_NOWAIT);
1447129794Stackerman	if (r != 0) {
1448129794Stackerman		printf("ixgb%d: ixgb_dma_malloc: bus_dmamap_load failed; "
1449129794Stackerman		       "error %u\n", adapter->unit, r);
1450144183Smux		goto fail_2;
1451129794Stackerman	}
1452129794Stackerman	dma->dma_size = size;
1453129794Stackerman	return (0);
1454129794Stackermanfail_2:
1455129794Stackerman	bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
1456129794Stackermanfail_1:
1457129794Stackerman	bus_dma_tag_destroy(dma->dma_tag);
1458129794Stackermanfail_0:
1459129794Stackerman	dma->dma_map = NULL;
1460129794Stackerman	dma->dma_tag = NULL;
1461129794Stackerman	return (r);
1462129794Stackerman}
1463129794Stackerman
1464129794Stackerman
1465129794Stackerman
1466129794Stackermanstatic void
1467129794Stackermanixgb_dma_free(struct adapter * adapter, struct ixgb_dma_alloc * dma)
1468129794Stackerman{
1469129794Stackerman	bus_dmamap_unload(dma->dma_tag, dma->dma_map);
1470129794Stackerman	bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
1471129794Stackerman	bus_dma_tag_destroy(dma->dma_tag);
1472129794Stackerman}
1473129794Stackerman
1474129794Stackerman/*********************************************************************
1475129794Stackerman *
1476129794Stackerman *  Allocate memory for tx_buffer structures. The tx_buffer stores all
1477129794Stackerman *  the information needed to transmit a packet on the wire.
1478129794Stackerman *
1479129794Stackerman **********************************************************************/
1480129794Stackermanstatic int
1481129794Stackermanixgb_allocate_transmit_structures(struct adapter * adapter)
1482129794Stackerman{
1483129794Stackerman	if (!(adapter->tx_buffer_area =
1484129794Stackerman	      (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) *
1485129794Stackerman					    adapter->num_tx_desc, M_DEVBUF,
1486129794Stackerman					    M_NOWAIT | M_ZERO))) {
1487129794Stackerman		printf("ixgb%d: Unable to allocate tx_buffer memory\n",
1488129794Stackerman		       adapter->unit);
1489129794Stackerman		return ENOMEM;
1490129794Stackerman	}
1491129794Stackerman	bzero(adapter->tx_buffer_area,
1492129794Stackerman	      sizeof(struct ixgb_buffer) * adapter->num_tx_desc);
1493129794Stackerman
1494129794Stackerman	return 0;
1495129794Stackerman}
1496129794Stackerman
1497129794Stackerman/*********************************************************************
1498129794Stackerman *
1499129794Stackerman *  Allocate and initialize transmit structures.
1500129794Stackerman *
1501129794Stackerman **********************************************************************/
1502129794Stackermanstatic int
1503129794Stackermanixgb_setup_transmit_structures(struct adapter * adapter)
1504129794Stackerman{
1505129794Stackerman	/*
1506129794Stackerman	 * Setup DMA descriptor areas.
1507129794Stackerman	 */
1508129794Stackerman	if (bus_dma_tag_create(NULL,	/* parent */
1509129794Stackerman			       PAGE_SIZE, 0,	/* alignment, bounds */
1510129794Stackerman			       BUS_SPACE_MAXADDR,	/* lowaddr */
1511129794Stackerman			       BUS_SPACE_MAXADDR,	/* highaddr */
1512129794Stackerman			       NULL, NULL,	/* filter, filterarg */
1513129794Stackerman			       MCLBYTES * IXGB_MAX_SCATTER,	/* maxsize */
1514129794Stackerman			       IXGB_MAX_SCATTER,	/* nsegments */
1515129794Stackerman			       MCLBYTES,	/* maxsegsize */
1516129794Stackerman			       BUS_DMA_ALLOCNOW,	/* flags */
1517129794Stackerman#if __FreeBSD_version >= 502000
1518129794Stackerman			       NULL,	/* lockfunc */
1519129794Stackerman			       NULL,	/* lockfuncarg */
1520129794Stackerman#endif
1521129794Stackerman			       &adapter->txtag)) {
1522129794Stackerman		printf("ixgb%d: Unable to allocate TX DMA tag\n", adapter->unit);
1523129794Stackerman		return (ENOMEM);
1524129794Stackerman	}
1525129794Stackerman	if (ixgb_allocate_transmit_structures(adapter))
1526129794Stackerman		return ENOMEM;
1527129794Stackerman
1528129794Stackerman	bzero((void *)adapter->tx_desc_base,
1529129794Stackerman	      (sizeof(struct ixgb_tx_desc)) * adapter->num_tx_desc);
1530129794Stackerman
1531129794Stackerman	adapter->next_avail_tx_desc = 0;
1532129794Stackerman	adapter->oldest_used_tx_desc = 0;
1533129794Stackerman
1534129794Stackerman	/* Set number of descriptors available */
1535129794Stackerman	adapter->num_tx_desc_avail = adapter->num_tx_desc;
1536129794Stackerman
1537129794Stackerman	/* Set checksum context */
1538129794Stackerman	adapter->active_checksum_context = OFFLOAD_NONE;
1539129794Stackerman
1540129794Stackerman	return 0;
1541129794Stackerman}
1542129794Stackerman
1543129794Stackerman/*********************************************************************
1544129794Stackerman *
1545129794Stackerman *  Enable transmit unit.
1546129794Stackerman *
1547129794Stackerman **********************************************************************/
1548129794Stackermanstatic void
1549129794Stackermanixgb_initialize_transmit_unit(struct adapter * adapter)
1550129794Stackerman{
1551129794Stackerman	u_int32_t       reg_tctl;
1552144183Smux	u_int64_t       tdba = adapter->txdma.dma_paddr;
1553129794Stackerman
1554129794Stackerman	/* Setup the Base and Length of the Tx Descriptor Ring */
1555129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDBAL,
1556129794Stackerman		       (tdba & 0x00000000ffffffffULL));
1557129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
1558129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDLEN,
1559129794Stackerman		       adapter->num_tx_desc *
1560129794Stackerman		       sizeof(struct ixgb_tx_desc));
1561129794Stackerman
1562129794Stackerman	/* Setup the HW Tx Head and Tail descriptor pointers */
1563129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDH, 0);
1564129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDT, 0);
1565129794Stackerman
1566129794Stackerman
1567129794Stackerman	HW_DEBUGOUT2("Base = %x, Length = %x\n",
1568129794Stackerman		     IXGB_READ_REG(&adapter->hw, TDBAL),
1569129794Stackerman		     IXGB_READ_REG(&adapter->hw, TDLEN));
1570129794Stackerman
1571129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay);
1572129794Stackerman
1573129794Stackerman
1574129794Stackerman	/* Program the Transmit Control Register */
1575129794Stackerman	reg_tctl = IXGB_READ_REG(&adapter->hw, TCTL);
1576129794Stackerman	reg_tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE;
1577129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TCTL, reg_tctl);
1578129794Stackerman
1579129794Stackerman	/* Setup Transmit Descriptor Settings for this adapter */
1580129794Stackerman	adapter->txd_cmd = IXGB_TX_DESC_TYPE | IXGB_TX_DESC_CMD_RS;
1581129794Stackerman
1582129794Stackerman	if (adapter->tx_int_delay > 0)
1583129794Stackerman		adapter->txd_cmd |= IXGB_TX_DESC_CMD_IDE;
1584129794Stackerman	return;
1585129794Stackerman}
1586129794Stackerman
1587129794Stackerman/*********************************************************************
1588129794Stackerman *
1589129794Stackerman *  Free all transmit related data structures.
1590129794Stackerman *
1591129794Stackerman **********************************************************************/
1592129794Stackermanstatic void
1593129794Stackermanixgb_free_transmit_structures(struct adapter * adapter)
1594129794Stackerman{
1595129794Stackerman	struct ixgb_buffer *tx_buffer;
1596129794Stackerman	int             i;
1597129794Stackerman
1598129794Stackerman	INIT_DEBUGOUT("free_transmit_structures: begin");
1599129794Stackerman
1600129794Stackerman	if (adapter->tx_buffer_area != NULL) {
1601129794Stackerman		tx_buffer = adapter->tx_buffer_area;
1602129794Stackerman		for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
1603129794Stackerman			if (tx_buffer->m_head != NULL) {
1604129794Stackerman				bus_dmamap_unload(adapter->txtag, tx_buffer->map);
1605129794Stackerman				bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
1606129794Stackerman				m_freem(tx_buffer->m_head);
1607129794Stackerman			}
1608129794Stackerman			tx_buffer->m_head = NULL;
1609129794Stackerman		}
1610129794Stackerman	}
1611129794Stackerman	if (adapter->tx_buffer_area != NULL) {
1612129794Stackerman		free(adapter->tx_buffer_area, M_DEVBUF);
1613129794Stackerman		adapter->tx_buffer_area = NULL;
1614129794Stackerman	}
1615129794Stackerman	if (adapter->txtag != NULL) {
1616129794Stackerman		bus_dma_tag_destroy(adapter->txtag);
1617129794Stackerman		adapter->txtag = NULL;
1618129794Stackerman	}
1619129794Stackerman	return;
1620129794Stackerman}
1621129794Stackerman
1622129794Stackerman/*********************************************************************
1623129794Stackerman *
1624129794Stackerman *  The offload context needs to be set when we transfer the first
1625129794Stackerman *  packet of a particular protocol (TCP/UDP). We change the
1626129794Stackerman *  context only if the protocol type changes.
1627129794Stackerman *
1628129794Stackerman **********************************************************************/
1629129794Stackermanstatic void
1630129794Stackermanixgb_transmit_checksum_setup(struct adapter * adapter,
1631129794Stackerman			     struct mbuf * mp,
1632129794Stackerman			     u_int8_t * txd_popts)
1633129794Stackerman{
1634129794Stackerman	struct ixgb_context_desc *TXD;
1635129794Stackerman	struct ixgb_buffer *tx_buffer;
1636129794Stackerman	int             curr_txd;
1637129794Stackerman
1638129794Stackerman	if (mp->m_pkthdr.csum_flags) {
1639129794Stackerman
1640129794Stackerman		if (mp->m_pkthdr.csum_flags & CSUM_TCP) {
1641129794Stackerman			*txd_popts = IXGB_TX_DESC_POPTS_TXSM;
1642129794Stackerman			if (adapter->active_checksum_context == OFFLOAD_TCP_IP)
1643129794Stackerman				return;
1644129794Stackerman			else
1645129794Stackerman				adapter->active_checksum_context = OFFLOAD_TCP_IP;
1646129794Stackerman		} else if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
1647129794Stackerman			*txd_popts = IXGB_TX_DESC_POPTS_TXSM;
1648129794Stackerman			if (adapter->active_checksum_context == OFFLOAD_UDP_IP)
1649129794Stackerman				return;
1650129794Stackerman			else
1651129794Stackerman				adapter->active_checksum_context = OFFLOAD_UDP_IP;
1652129794Stackerman		} else {
1653129794Stackerman			*txd_popts = 0;
1654129794Stackerman			return;
1655129794Stackerman		}
1656129794Stackerman	} else {
1657129794Stackerman		*txd_popts = 0;
1658129794Stackerman		return;
1659129794Stackerman	}
1660129794Stackerman
1661129794Stackerman	/*
1662129794Stackerman	 * If we reach this point, the checksum offload context needs to be
1663129794Stackerman	 * reset.
1664129794Stackerman	 */
1665129794Stackerman	curr_txd = adapter->next_avail_tx_desc;
1666129794Stackerman	tx_buffer = &adapter->tx_buffer_area[curr_txd];
1667129794Stackerman	TXD = (struct ixgb_context_desc *) & adapter->tx_desc_base[curr_txd];
1668129794Stackerman
1669129794Stackerman
1670129794Stackerman	TXD->tucss = ENET_HEADER_SIZE + sizeof(struct ip);
1671129794Stackerman	TXD->tucse = 0;
1672129794Stackerman
1673129794Stackerman	TXD->mss = 0;
1674129794Stackerman
1675129794Stackerman	if (adapter->active_checksum_context == OFFLOAD_TCP_IP) {
1676129794Stackerman		TXD->tucso =
1677129794Stackerman			ENET_HEADER_SIZE + sizeof(struct ip) +
1678129794Stackerman			offsetof(struct tcphdr, th_sum);
1679129794Stackerman	} else if (adapter->active_checksum_context == OFFLOAD_UDP_IP) {
1680129794Stackerman		TXD->tucso =
1681129794Stackerman			ENET_HEADER_SIZE + sizeof(struct ip) +
1682129794Stackerman			offsetof(struct udphdr, uh_sum);
1683129794Stackerman	}
1684129794Stackerman	TXD->cmd_type_len = IXGB_CONTEXT_DESC_CMD_TCP | IXGB_TX_DESC_CMD_RS | IXGB_CONTEXT_DESC_CMD_IDE;
1685129794Stackerman
1686129794Stackerman	tx_buffer->m_head = NULL;
1687129794Stackerman
1688129794Stackerman	if (++curr_txd == adapter->num_tx_desc)
1689129794Stackerman		curr_txd = 0;
1690129794Stackerman
1691129794Stackerman	adapter->num_tx_desc_avail--;
1692129794Stackerman	adapter->next_avail_tx_desc = curr_txd;
1693129794Stackerman	return;
1694129794Stackerman}
1695129794Stackerman
1696129794Stackerman/**********************************************************************
1697129794Stackerman *
1698129794Stackerman *  Examine each tx_buffer in the used queue. If the hardware is done
1699129794Stackerman *  processing the packet then free associated resources. The
1700129794Stackerman *  tx_buffer is put back on the free queue.
1701129794Stackerman *
1702129794Stackerman **********************************************************************/
1703129794Stackermanstatic void
1704129794Stackermanixgb_clean_transmit_interrupts(struct adapter * adapter)
1705129794Stackerman{
1706129794Stackerman	int             i, num_avail;
1707129794Stackerman	struct ixgb_buffer *tx_buffer;
1708129794Stackerman	struct ixgb_tx_desc *tx_desc;
1709129794Stackerman
1710144651Salc	IXGB_LOCK_ASSERT(adapter);
1711129794Stackerman
1712129794Stackerman	if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
1713129794Stackerman		return;
1714129794Stackerman
1715129794Stackerman#ifdef _SV_
1716129794Stackerman	adapter->clean_tx_interrupts++;
1717129794Stackerman#endif
1718129794Stackerman	num_avail = adapter->num_tx_desc_avail;
1719129794Stackerman	i = adapter->oldest_used_tx_desc;
1720129794Stackerman
1721129794Stackerman	tx_buffer = &adapter->tx_buffer_area[i];
1722129794Stackerman	tx_desc = &adapter->tx_desc_base[i];
1723129794Stackerman
1724129794Stackerman	while (tx_desc->status & IXGB_TX_DESC_STATUS_DD) {
1725129794Stackerman
1726129794Stackerman		tx_desc->status = 0;
1727129794Stackerman		num_avail++;
1728129794Stackerman
1729129794Stackerman		if (tx_buffer->m_head) {
1730129794Stackerman			bus_dmamap_sync(adapter->txtag, tx_buffer->map,
1731129794Stackerman					BUS_DMASYNC_POSTWRITE);
1732129794Stackerman			bus_dmamap_unload(adapter->txtag, tx_buffer->map);
1733129794Stackerman			bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
1734129794Stackerman			m_freem(tx_buffer->m_head);
1735129794Stackerman			tx_buffer->m_head = NULL;
1736129794Stackerman		}
1737129794Stackerman		if (++i == adapter->num_tx_desc)
1738129794Stackerman			i = 0;
1739129794Stackerman
1740129794Stackerman		tx_buffer = &adapter->tx_buffer_area[i];
1741129794Stackerman		tx_desc = &adapter->tx_desc_base[i];
1742129794Stackerman	}
1743129794Stackerman
1744129794Stackerman	adapter->oldest_used_tx_desc = i;
1745129794Stackerman
1746129794Stackerman	/*
1747148887Srwatson	 * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that
1748129794Stackerman	 * it is OK to send packets. If there are no pending descriptors,
1749129794Stackerman	 * clear the timeout. Otherwise, if some descriptors have been freed,
1750129794Stackerman	 * restart the timeout.
1751129794Stackerman	 */
1752129794Stackerman	if (num_avail > IXGB_TX_CLEANUP_THRESHOLD) {
1753147256Sbrooks		struct ifnet   *ifp = adapter->ifp;
1754129794Stackerman
1755148887Srwatson		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1756129794Stackerman		if (num_avail == adapter->num_tx_desc)
1757129794Stackerman			ifp->if_timer = 0;
1758129794Stackerman		else if (num_avail == adapter->num_tx_desc_avail)
1759129794Stackerman			ifp->if_timer = IXGB_TX_TIMEOUT;
1760129794Stackerman	}
1761129794Stackerman	adapter->num_tx_desc_avail = num_avail;
1762129794Stackerman	return;
1763129794Stackerman}
1764129794Stackerman
1765129794Stackerman
1766129794Stackerman/*********************************************************************
1767129794Stackerman *
1768129794Stackerman *  Get a buffer from system mbuf buffer pool.
1769129794Stackerman *
1770129794Stackerman **********************************************************************/
1771129794Stackermanstatic int
1772129794Stackermanixgb_get_buf(int i, struct adapter * adapter,
1773129794Stackerman	     struct mbuf * nmp)
1774129794Stackerman{
1775129794Stackerman	register struct mbuf *mp = nmp;
1776129794Stackerman	struct ixgb_buffer *rx_buffer;
1777129794Stackerman	struct ifnet   *ifp;
1778129794Stackerman	bus_addr_t      paddr;
1779129794Stackerman	int             error;
1780129794Stackerman
1781147256Sbrooks	ifp = adapter->ifp;
1782129794Stackerman
1783129794Stackerman	if (mp == NULL) {
1784129794Stackerman
1785129794Stackerman		mp = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1786129794Stackerman
1787129794Stackerman		if (mp == NULL) {
1788129794Stackerman			adapter->mbuf_alloc_failed++;
1789129794Stackerman			return (ENOBUFS);
1790129794Stackerman		}
1791129794Stackerman		mp->m_len = mp->m_pkthdr.len = MCLBYTES;
1792129794Stackerman	} else {
1793129794Stackerman		mp->m_len = mp->m_pkthdr.len = MCLBYTES;
1794129794Stackerman		mp->m_data = mp->m_ext.ext_buf;
1795129794Stackerman		mp->m_next = NULL;
1796129794Stackerman	}
1797129794Stackerman
1798129794Stackerman	if (ifp->if_mtu <= ETHERMTU) {
1799129794Stackerman		m_adj(mp, ETHER_ALIGN);
1800129794Stackerman	}
1801129794Stackerman	rx_buffer = &adapter->rx_buffer_area[i];
1802129794Stackerman
1803129794Stackerman	/*
1804129794Stackerman	 * Using memory from the mbuf cluster pool, invoke the bus_dma
1805129794Stackerman	 * machinery to arrange the memory mapping.
1806129794Stackerman	 */
1807129794Stackerman	error = bus_dmamap_load(adapter->rxtag, rx_buffer->map,
1808129794Stackerman				mtod(mp, void *), mp->m_len,
1809129794Stackerman				ixgb_dmamap_cb, &paddr, 0);
1810129794Stackerman	if (error) {
1811129794Stackerman		m_free(mp);
1812129794Stackerman		return (error);
1813129794Stackerman	}
1814129794Stackerman	rx_buffer->m_head = mp;
1815129794Stackerman	adapter->rx_desc_base[i].buff_addr = htole64(paddr);
1816129794Stackerman	bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD);
1817129794Stackerman
1818129794Stackerman	return (0);
1819129794Stackerman}
1820129794Stackerman
1821129794Stackerman/*********************************************************************
1822129794Stackerman *
1823129794Stackerman *  Allocate memory for rx_buffer structures. Since we use one
1824129794Stackerman *  rx_buffer per received packet, the maximum number of rx_buffer's
1825129794Stackerman *  that we'll need is equal to the number of receive descriptors
1826129794Stackerman *  that we've allocated.
1827129794Stackerman *
1828129794Stackerman **********************************************************************/
1829129794Stackermanstatic int
1830129794Stackermanixgb_allocate_receive_structures(struct adapter * adapter)
1831129794Stackerman{
1832129794Stackerman	int             i, error;
1833129794Stackerman	struct ixgb_buffer *rx_buffer;
1834129794Stackerman
1835129794Stackerman	if (!(adapter->rx_buffer_area =
1836129794Stackerman	      (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) *
1837129794Stackerman					    adapter->num_rx_desc, M_DEVBUF,
1838129794Stackerman					    M_NOWAIT | M_ZERO))) {
1839129794Stackerman		printf("ixgb%d: Unable to allocate rx_buffer memory\n",
1840129794Stackerman		       adapter->unit);
1841129794Stackerman		return (ENOMEM);
1842129794Stackerman	}
1843129794Stackerman	bzero(adapter->rx_buffer_area,
1844129794Stackerman	      sizeof(struct ixgb_buffer) * adapter->num_rx_desc);
1845129794Stackerman
1846129794Stackerman	error = bus_dma_tag_create(NULL,	/* parent */
1847129794Stackerman				   PAGE_SIZE, 0,	/* alignment, bounds */
1848129794Stackerman				   BUS_SPACE_MAXADDR,	/* lowaddr */
1849129794Stackerman				   BUS_SPACE_MAXADDR,	/* highaddr */
1850129794Stackerman				   NULL, NULL,	/* filter, filterarg */
1851129794Stackerman				   MCLBYTES,	/* maxsize */
1852129794Stackerman				   1,	/* nsegments */
1853129794Stackerman				   MCLBYTES,	/* maxsegsize */
1854129794Stackerman				   BUS_DMA_ALLOCNOW,	/* flags */
1855129794Stackerman#if __FreeBSD_version >= 502000
1856129794Stackerman				   NULL,	/* lockfunc */
1857129794Stackerman				   NULL,	/* lockfuncarg */
1858129794Stackerman#endif
1859129794Stackerman				   &adapter->rxtag);
1860129794Stackerman	if (error != 0) {
1861129794Stackerman		printf("ixgb%d: ixgb_allocate_receive_structures: "
1862129794Stackerman		       "bus_dma_tag_create failed; error %u\n",
1863129794Stackerman		       adapter->unit, error);
1864129794Stackerman		goto fail_0;
1865129794Stackerman	}
1866129794Stackerman	rx_buffer = adapter->rx_buffer_area;
1867129794Stackerman	for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
1868129794Stackerman		error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT,
1869129794Stackerman					  &rx_buffer->map);
1870129794Stackerman		if (error != 0) {
1871129794Stackerman			printf("ixgb%d: ixgb_allocate_receive_structures: "
1872129794Stackerman			       "bus_dmamap_create failed; error %u\n",
1873129794Stackerman			       adapter->unit, error);
1874129794Stackerman			goto fail_1;
1875129794Stackerman		}
1876129794Stackerman	}
1877129794Stackerman
1878129794Stackerman	for (i = 0; i < adapter->num_rx_desc; i++) {
1879129794Stackerman		if (ixgb_get_buf(i, adapter, NULL) == ENOBUFS) {
1880129794Stackerman			adapter->rx_buffer_area[i].m_head = NULL;
1881129794Stackerman			adapter->rx_desc_base[i].buff_addr = 0;
1882129794Stackerman			return (ENOBUFS);
1883129794Stackerman		}
1884129794Stackerman	}
1885129794Stackerman
1886129794Stackerman	return (0);
1887129794Stackermanfail_1:
1888129794Stackerman	bus_dma_tag_destroy(adapter->rxtag);
1889129794Stackermanfail_0:
1890129794Stackerman	adapter->rxtag = NULL;
1891129794Stackerman	free(adapter->rx_buffer_area, M_DEVBUF);
1892129794Stackerman	adapter->rx_buffer_area = NULL;
1893129794Stackerman	return (error);
1894129794Stackerman}
1895129794Stackerman
1896129794Stackerman/*********************************************************************
1897129794Stackerman *
1898129794Stackerman *  Allocate and initialize receive structures.
1899129794Stackerman *
1900129794Stackerman **********************************************************************/
1901129794Stackermanstatic int
1902129794Stackermanixgb_setup_receive_structures(struct adapter * adapter)
1903129794Stackerman{
1904129794Stackerman	bzero((void *)adapter->rx_desc_base,
1905129794Stackerman	      (sizeof(struct ixgb_rx_desc)) * adapter->num_rx_desc);
1906129794Stackerman
1907129794Stackerman	if (ixgb_allocate_receive_structures(adapter))
1908129794Stackerman		return ENOMEM;
1909129794Stackerman
1910129794Stackerman	/* Setup our descriptor pointers */
1911129794Stackerman	adapter->next_rx_desc_to_check = 0;
1912129794Stackerman	adapter->next_rx_desc_to_use = 0;
1913129794Stackerman	return (0);
1914129794Stackerman}
1915129794Stackerman
1916129794Stackerman/*********************************************************************
1917129794Stackerman *
1918129794Stackerman *  Enable receive unit.
1919129794Stackerman *
1920129794Stackerman **********************************************************************/
1921129794Stackermanstatic void
1922129794Stackermanixgb_initialize_receive_unit(struct adapter * adapter)
1923129794Stackerman{
1924129794Stackerman	u_int32_t       reg_rctl;
1925129794Stackerman	u_int32_t       reg_rxcsum;
1926129794Stackerman	u_int32_t       reg_rxdctl;
1927129794Stackerman	struct ifnet   *ifp;
1928144183Smux	u_int64_t       rdba = adapter->rxdma.dma_paddr;
1929129794Stackerman
1930147256Sbrooks	ifp = adapter->ifp;
1931129794Stackerman
1932129794Stackerman	/*
1933129794Stackerman	 * Make sure receives are disabled while setting up the descriptor
1934129794Stackerman	 * ring
1935129794Stackerman	 */
1936129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1937129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl & ~IXGB_RCTL_RXEN);
1938129794Stackerman
1939129794Stackerman	/* Set the Receive Delay Timer Register */
1940129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDTR,
1941129794Stackerman		       adapter->rx_int_delay);
1942129794Stackerman
1943129794Stackerman
1944129794Stackerman	/* Setup the Base and Length of the Rx Descriptor Ring */
1945129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDBAL,
1946129794Stackerman		       (rdba & 0x00000000ffffffffULL));
1947129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
1948129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDLEN, adapter->num_rx_desc *
1949129794Stackerman		       sizeof(struct ixgb_rx_desc));
1950129794Stackerman
1951129794Stackerman	/* Setup the HW Rx Head and Tail Descriptor Pointers */
1952129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDH, 0);
1953129794Stackerman
1954129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDT, adapter->num_rx_desc - 1);
1955129794Stackerman
1956129794Stackerman
1957129794Stackerman
1958129794Stackerman	reg_rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
1959129794Stackerman		| RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
1960129794Stackerman		| RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
1961129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RXDCTL, reg_rxdctl);
1962129794Stackerman
1963129794Stackerman
1964129794Stackerman	adapter->raidc = 1;
1965129794Stackerman	if (adapter->raidc) {
1966129794Stackerman		uint32_t        raidc;
1967129794Stackerman		uint8_t         poll_threshold;
1968129794Stackerman#define IXGB_RAIDC_POLL_DEFAULT 120
1969129794Stackerman
1970129794Stackerman		poll_threshold = ((adapter->num_rx_desc - 1) >> 3);
1971129794Stackerman		poll_threshold >>= 1;
1972129794Stackerman		poll_threshold &= 0x3F;
1973129794Stackerman		raidc = IXGB_RAIDC_EN | IXGB_RAIDC_RXT_GATE |
1974129794Stackerman			(IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) |
1975129794Stackerman			(adapter->rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) |
1976129794Stackerman			poll_threshold;
1977129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RAIDC, raidc);
1978129794Stackerman	}
1979129794Stackerman	/* Enable Receive Checksum Offload for TCP and UDP ? */
1980129794Stackerman	if (ifp->if_capenable & IFCAP_RXCSUM) {
1981129794Stackerman		reg_rxcsum = IXGB_READ_REG(&adapter->hw, RXCSUM);
1982129794Stackerman		reg_rxcsum |= IXGB_RXCSUM_TUOFL;
1983129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RXCSUM, reg_rxcsum);
1984129794Stackerman	}
1985129794Stackerman	/* Setup the Receive Control Register */
1986129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1987129794Stackerman	reg_rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
1988129794Stackerman	reg_rctl |= IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 | IXGB_RCTL_SECRC |
1989129794Stackerman		IXGB_RCTL_CFF |
1990129794Stackerman		(adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
1991129794Stackerman
1992129794Stackerman	switch (adapter->rx_buffer_len) {
1993129794Stackerman	default:
1994129794Stackerman	case IXGB_RXBUFFER_2048:
1995129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_2048;
1996129794Stackerman		break;
1997129794Stackerman	case IXGB_RXBUFFER_4096:
1998129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_4096;
1999129794Stackerman		break;
2000129794Stackerman	case IXGB_RXBUFFER_8192:
2001129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_8192;
2002129794Stackerman		break;
2003129794Stackerman	case IXGB_RXBUFFER_16384:
2004129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_16384;
2005129794Stackerman		break;
2006129794Stackerman	}
2007129794Stackerman
2008129794Stackerman	reg_rctl |= IXGB_RCTL_RXEN;
2009129794Stackerman
2010129794Stackerman
2011129794Stackerman	/* Enable Receives */
2012129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
2013129794Stackerman
2014129794Stackerman	return;
2015129794Stackerman}
2016129794Stackerman
2017129794Stackerman/*********************************************************************
2018129794Stackerman *
2019129794Stackerman *  Free receive related data structures.
2020129794Stackerman *
2021129794Stackerman **********************************************************************/
2022129794Stackermanstatic void
2023129794Stackermanixgb_free_receive_structures(struct adapter * adapter)
2024129794Stackerman{
2025129794Stackerman	struct ixgb_buffer *rx_buffer;
2026129794Stackerman	int             i;
2027129794Stackerman
2028129794Stackerman	INIT_DEBUGOUT("free_receive_structures: begin");
2029129794Stackerman
2030129794Stackerman	if (adapter->rx_buffer_area != NULL) {
2031129794Stackerman		rx_buffer = adapter->rx_buffer_area;
2032129794Stackerman		for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
2033129794Stackerman			if (rx_buffer->map != NULL) {
2034129794Stackerman				bus_dmamap_unload(adapter->rxtag, rx_buffer->map);
2035129794Stackerman				bus_dmamap_destroy(adapter->rxtag, rx_buffer->map);
2036129794Stackerman			}
2037129794Stackerman			if (rx_buffer->m_head != NULL)
2038129794Stackerman				m_freem(rx_buffer->m_head);
2039129794Stackerman			rx_buffer->m_head = NULL;
2040129794Stackerman		}
2041129794Stackerman	}
2042129794Stackerman	if (adapter->rx_buffer_area != NULL) {
2043129794Stackerman		free(adapter->rx_buffer_area, M_DEVBUF);
2044129794Stackerman		adapter->rx_buffer_area = NULL;
2045129794Stackerman	}
2046129794Stackerman	if (adapter->rxtag != NULL) {
2047129794Stackerman		bus_dma_tag_destroy(adapter->rxtag);
2048129794Stackerman		adapter->rxtag = NULL;
2049129794Stackerman	}
2050129794Stackerman	return;
2051129794Stackerman}
2052129794Stackerman
2053129794Stackerman/*********************************************************************
2054129794Stackerman *
2055129794Stackerman *  This routine executes in interrupt context. It replenishes
2056129794Stackerman *  the mbufs in the descriptor and sends data which has been
2057129794Stackerman *  dma'ed into host memory to upper layer.
2058129794Stackerman *
2059129794Stackerman *  We loop at most count times if count is > 0, or until done if
2060129794Stackerman *  count < 0.
2061129794Stackerman *
2062129794Stackerman *********************************************************************/
2063129794Stackermanstatic void
2064129794Stackermanixgb_process_receive_interrupts(struct adapter * adapter, int count)
2065129794Stackerman{
2066129794Stackerman	struct ifnet   *ifp;
2067129794Stackerman	struct mbuf    *mp;
2068129794Stackerman#if __FreeBSD_version < 500000
2069129794Stackerman	struct ether_header *eh;
2070129794Stackerman#endif
2071129794Stackerman	int             eop = 0;
2072129794Stackerman	int             len;
2073129794Stackerman	u_int8_t        accept_frame = 0;
2074129794Stackerman	int             i;
2075129794Stackerman	int             next_to_use = 0;
2076129794Stackerman	int             eop_desc;
2077129794Stackerman	/* Pointer to the receive descriptor being examined. */
2078129794Stackerman	struct ixgb_rx_desc *current_desc;
2079129794Stackerman
2080144651Salc	IXGB_LOCK_ASSERT(adapter);
2081144651Salc
2082147256Sbrooks	ifp = adapter->ifp;
2083129794Stackerman	i = adapter->next_rx_desc_to_check;
2084129794Stackerman	next_to_use = adapter->next_rx_desc_to_use;
2085129794Stackerman	eop_desc = adapter->next_rx_desc_to_check;
2086129794Stackerman	current_desc = &adapter->rx_desc_base[i];
2087129794Stackerman
2088129794Stackerman	if (!((current_desc->status) & IXGB_RX_DESC_STATUS_DD)) {
2089129794Stackerman#ifdef _SV_
2090129794Stackerman		adapter->no_pkts_avail++;
2091129794Stackerman#endif
2092129794Stackerman		return;
2093129794Stackerman	}
2094129794Stackerman	while ((current_desc->status & IXGB_RX_DESC_STATUS_DD) && (count != 0)) {
2095129794Stackerman
2096129794Stackerman		mp = adapter->rx_buffer_area[i].m_head;
2097129794Stackerman		bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map,
2098129794Stackerman				BUS_DMASYNC_POSTREAD);
2099129794Stackerman		accept_frame = 1;
2100129794Stackerman		if (current_desc->status & IXGB_RX_DESC_STATUS_EOP) {
2101129794Stackerman			count--;
2102129794Stackerman			eop = 1;
2103129794Stackerman		} else {
2104129794Stackerman			eop = 0;
2105129794Stackerman		}
2106129794Stackerman		len = current_desc->length;
2107129794Stackerman
2108129794Stackerman		if (current_desc->errors & (IXGB_RX_DESC_ERRORS_CE |
2109129794Stackerman			    IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P |
2110129794Stackerman					    IXGB_RX_DESC_ERRORS_RXE)) {
2111129794Stackerman			accept_frame = 0;
2112129794Stackerman		}
2113129794Stackerman		if (accept_frame) {
2114129794Stackerman
2115129794Stackerman			/* Assign correct length to the current fragment */
2116129794Stackerman			mp->m_len = len;
2117129794Stackerman
2118129794Stackerman			if (adapter->fmp == NULL) {
2119129794Stackerman				mp->m_pkthdr.len = len;
2120129794Stackerman				adapter->fmp = mp;	/* Store the first mbuf */
2121129794Stackerman				adapter->lmp = mp;
2122129794Stackerman			} else {
2123129794Stackerman				/* Chain mbuf's together */
2124129794Stackerman				mp->m_flags &= ~M_PKTHDR;
2125129794Stackerman				adapter->lmp->m_next = mp;
2126129794Stackerman				adapter->lmp = adapter->lmp->m_next;
2127129794Stackerman				adapter->fmp->m_pkthdr.len += len;
2128129794Stackerman			}
2129129794Stackerman
2130129794Stackerman			if (eop) {
2131129794Stackerman				eop_desc = i;
2132129794Stackerman				adapter->fmp->m_pkthdr.rcvif = ifp;
2133129794Stackerman
2134129794Stackerman#if __FreeBSD_version < 500000
2135129794Stackerman				eh = mtod(adapter->fmp, struct ether_header *);
2136129794Stackerman
2137129794Stackerman				/* Remove ethernet header from mbuf */
2138129794Stackerman				m_adj(adapter->fmp, sizeof(struct ether_header));
2139129794Stackerman				ixgb_receive_checksum(adapter, current_desc,
2140129794Stackerman						      adapter->fmp);
2141129794Stackerman
2142129794Stackerman				if (current_desc->status & IXGB_RX_DESC_STATUS_VP)
2143129794Stackerman					VLAN_INPUT_TAG(eh, adapter->fmp,
2144129794Stackerman						     current_desc->special);
2145129794Stackerman				else
2146129794Stackerman					ether_input(ifp, eh, adapter->fmp);
2147129794Stackerman#else
2148129794Stackerman				ixgb_receive_checksum(adapter, current_desc,
2149129794Stackerman						      adapter->fmp);
2150129794Stackerman				if (current_desc->status & IXGB_RX_DESC_STATUS_VP)
2151129794Stackerman					VLAN_INPUT_TAG(ifp, adapter->fmp,
2152129794Stackerman						       current_desc->special,
2153129794Stackerman						       adapter->fmp = NULL);
2154129794Stackerman
2155144651Salc				if (adapter->fmp != NULL) {
2156144651Salc					IXGB_UNLOCK(adapter);
2157129794Stackerman					(*ifp->if_input) (ifp, adapter->fmp);
2158144651Salc					IXGB_LOCK(adapter);
2159144651Salc				}
2160129794Stackerman#endif
2161129794Stackerman				adapter->fmp = NULL;
2162129794Stackerman				adapter->lmp = NULL;
2163129794Stackerman			}
2164129794Stackerman			adapter->rx_buffer_area[i].m_head = NULL;
2165129794Stackerman		} else {
2166129794Stackerman			adapter->dropped_pkts++;
2167129794Stackerman			if (adapter->fmp != NULL)
2168129794Stackerman				m_freem(adapter->fmp);
2169129794Stackerman			adapter->fmp = NULL;
2170129794Stackerman			adapter->lmp = NULL;
2171129794Stackerman		}
2172129794Stackerman
2173129794Stackerman		/* Zero out the receive descriptors status  */
2174129794Stackerman		current_desc->status = 0;
2175129794Stackerman
2176129794Stackerman		/* Advance our pointers to the next descriptor */
2177129794Stackerman		if (++i == adapter->num_rx_desc) {
2178129794Stackerman			i = 0;
2179129794Stackerman			current_desc = adapter->rx_desc_base;
2180129794Stackerman		} else
2181129794Stackerman			current_desc++;
2182129794Stackerman	}
2183129794Stackerman	adapter->next_rx_desc_to_check = i;
2184129794Stackerman
2185129794Stackerman	if (--i < 0)
2186129794Stackerman		i = (adapter->num_rx_desc - 1);
2187129794Stackerman
2188129794Stackerman	/*
2189129794Stackerman	 * 82597EX: Workaround for redundent write back in receive descriptor ring (causes
2190129794Stackerman 	 * memory corruption). Avoid using and re-submitting the most recently received RX
2191129794Stackerman	 * descriptor back to hardware.
2192129794Stackerman	 *
2193129794Stackerman	 * if(Last written back descriptor == EOP bit set descriptor)
2194129794Stackerman	 * 	then avoid re-submitting the most recently received RX descriptor
2195129794Stackerman	 *	back to hardware.
2196129794Stackerman	 * if(Last written back descriptor != EOP bit set descriptor)
2197129794Stackerman	 *	then avoid re-submitting the most recently received RX descriptors
2198129794Stackerman	 * 	till last EOP bit set descriptor.
2199129794Stackerman	 */
2200129794Stackerman	if (eop_desc != i) {
2201129794Stackerman		if (++eop_desc == adapter->num_rx_desc)
2202129794Stackerman			eop_desc = 0;
2203129794Stackerman		i = eop_desc;
2204129794Stackerman	}
2205129794Stackerman	/* Replenish the descriptors with new mbufs till last EOP bit set descriptor */
2206129794Stackerman	while (next_to_use != i) {
2207129794Stackerman		current_desc = &adapter->rx_desc_base[next_to_use];
2208129794Stackerman		if ((current_desc->errors & (IXGB_RX_DESC_ERRORS_CE |
2209129794Stackerman			    IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P |
2210129794Stackerman					     IXGB_RX_DESC_ERRORS_RXE))) {
2211129794Stackerman			mp = adapter->rx_buffer_area[next_to_use].m_head;
2212129794Stackerman			ixgb_get_buf(next_to_use, adapter, mp);
2213129794Stackerman		} else {
2214129794Stackerman			if (ixgb_get_buf(next_to_use, adapter, NULL) == ENOBUFS)
2215129794Stackerman				break;
2216129794Stackerman		}
2217129794Stackerman		/* Advance our pointers to the next descriptor */
2218129794Stackerman		if (++next_to_use == adapter->num_rx_desc) {
2219129794Stackerman			next_to_use = 0;
2220129794Stackerman			current_desc = adapter->rx_desc_base;
2221129794Stackerman		} else
2222129794Stackerman			current_desc++;
2223129794Stackerman	}
2224129794Stackerman	adapter->next_rx_desc_to_use = next_to_use;
2225129794Stackerman	if (--next_to_use < 0)
2226129794Stackerman		next_to_use = (adapter->num_rx_desc - 1);
2227129794Stackerman	/* Advance the IXGB's Receive Queue #0  "Tail Pointer" */
2228129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDT, next_to_use);
2229129794Stackerman
2230129794Stackerman	return;
2231129794Stackerman}
2232129794Stackerman
2233129794Stackerman/*********************************************************************
2234129794Stackerman *
2235129794Stackerman *  Verify that the hardware indicated that the checksum is valid.
2236129794Stackerman *  Inform the stack about the status of checksum so that stack
2237129794Stackerman *  doesn't spend time verifying the checksum.
2238129794Stackerman *
2239129794Stackerman *********************************************************************/
2240129794Stackermanstatic void
2241129794Stackermanixgb_receive_checksum(struct adapter * adapter,
2242129794Stackerman		      struct ixgb_rx_desc * rx_desc,
2243129794Stackerman		      struct mbuf * mp)
2244129794Stackerman{
2245129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) {
2246129794Stackerman		mp->m_pkthdr.csum_flags = 0;
2247129794Stackerman		return;
2248129794Stackerman	}
2249129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_IPCS) {
2250129794Stackerman		/* Did it pass? */
2251129794Stackerman		if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_IPE)) {
2252129794Stackerman			/* IP Checksum Good */
2253129794Stackerman			mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
2254129794Stackerman			mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
2255129794Stackerman
2256129794Stackerman		} else {
2257129794Stackerman			mp->m_pkthdr.csum_flags = 0;
2258129794Stackerman		}
2259129794Stackerman	}
2260129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS) {
2261129794Stackerman		/* Did it pass? */
2262129794Stackerman		if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE)) {
2263129794Stackerman			mp->m_pkthdr.csum_flags |=
2264129794Stackerman				(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
2265129794Stackerman			mp->m_pkthdr.csum_data = htons(0xffff);
2266129794Stackerman		}
2267129794Stackerman	}
2268129794Stackerman	return;
2269129794Stackerman}
2270129794Stackerman
2271129794Stackerman
2272129794Stackermanstatic void
2273129794Stackermanixgb_enable_vlans(struct adapter * adapter)
2274129794Stackerman{
2275129794Stackerman	uint32_t        ctrl;
2276129794Stackerman
2277129794Stackerman	ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
2278129794Stackerman	ctrl |= IXGB_CTRL0_VME;
2279129794Stackerman	IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
2280129794Stackerman
2281129794Stackerman	return;
2282129794Stackerman}
2283129794Stackerman
2284129794Stackerman
2285129794Stackermanstatic void
2286129794Stackermanixgb_enable_intr(struct adapter * adapter)
2287129794Stackerman{
2288129794Stackerman	IXGB_WRITE_REG(&adapter->hw, IMS, (IXGB_INT_RXT0 | IXGB_INT_TXDW |
2289129794Stackerman			    IXGB_INT_RXDMT0 | IXGB_INT_LSC | IXGB_INT_RXO));
2290129794Stackerman	return;
2291129794Stackerman}
2292129794Stackerman
2293129794Stackermanstatic void
2294129794Stackermanixgb_disable_intr(struct adapter * adapter)
2295129794Stackerman{
2296129794Stackerman	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
2297129794Stackerman	return;
2298129794Stackerman}
2299129794Stackerman
2300129794Stackermanvoid
2301129794Stackermanixgb_write_pci_cfg(struct ixgb_hw * hw,
2302129794Stackerman		   uint32_t reg,
2303129794Stackerman		   uint16_t * value)
2304129794Stackerman{
2305129794Stackerman	pci_write_config(((struct ixgb_osdep *) hw->back)->dev, reg,
2306129794Stackerman			 *value, 2);
2307129794Stackerman}
2308129794Stackerman
2309129794Stackerman/**********************************************************************
2310129794Stackerman *
2311129794Stackerman *  Update the board statistics counters.
2312129794Stackerman *
2313129794Stackerman **********************************************************************/
2314129794Stackermanstatic void
2315129794Stackermanixgb_update_stats_counters(struct adapter * adapter)
2316129794Stackerman{
2317129794Stackerman	struct ifnet   *ifp;
2318129794Stackerman
2319129794Stackerman	adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS);
2320129794Stackerman	adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);
2321129794Stackerman	adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);
2322129794Stackerman	adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL);
2323129794Stackerman	adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH);
2324129794Stackerman	adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
2325129794Stackerman	adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
2326129794Stackerman	adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
2327129794Stackerman	adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
2328129794Stackerman	adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC);
2329129794Stackerman
2330129794Stackerman	adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC);
2331129794Stackerman	adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC);
2332129794Stackerman	adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC);
2333129794Stackerman	adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC);
2334129794Stackerman	adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC);
2335129794Stackerman	adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC);
2336129794Stackerman	adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC);
2337129794Stackerman	adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL);
2338129794Stackerman	adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH);
2339129794Stackerman	adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL);
2340129794Stackerman	adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH);
2341129794Stackerman	adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC);
2342129794Stackerman	adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC);
2343129794Stackerman	adapter->stats.rjc += IXGB_READ_REG(&adapter->hw, RJC);
2344129794Stackerman	adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL);
2345129794Stackerman	adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH);
2346129794Stackerman	adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL);
2347129794Stackerman	adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH);
2348129794Stackerman	adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
2349129794Stackerman	adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
2350129794Stackerman	adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL);
2351129794Stackerman	adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH);
2352129794Stackerman	adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C);
2353129794Stackerman	adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL);
2354129794Stackerman	adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH);
2355129794Stackerman	adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL);
2356129794Stackerman	adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH);
2357129794Stackerman
2358129794Stackerman	adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);
2359129794Stackerman	adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);
2360129794Stackerman	adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);
2361129794Stackerman	adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH);
2362129794Stackerman	adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL);
2363129794Stackerman	adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH);
2364129794Stackerman	adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC);
2365129794Stackerman	adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC);
2366129794Stackerman	adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC);
2367129794Stackerman	adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL);
2368129794Stackerman	adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH);
2369129794Stackerman	adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL);
2370129794Stackerman	adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH);
2371129794Stackerman	adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL);
2372129794Stackerman	adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH);
2373129794Stackerman	adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC);
2374129794Stackerman	adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC);
2375129794Stackerman	adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC);
2376129794Stackerman	adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC);
2377129794Stackerman	adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC);
2378129794Stackerman	adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC);
2379129794Stackerman	adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC);
2380129794Stackerman
2381147256Sbrooks	ifp = adapter->ifp;
2382129794Stackerman
2383129794Stackerman	/* Fill out the OS statistics structure */
2384129794Stackerman	ifp->if_ipackets = adapter->stats.gprcl;
2385129794Stackerman	ifp->if_opackets = adapter->stats.gptcl;
2386129794Stackerman	ifp->if_ibytes = adapter->stats.gorcl;
2387129794Stackerman	ifp->if_obytes = adapter->stats.gotcl;
2388129794Stackerman	ifp->if_imcasts = adapter->stats.mprcl;
2389129794Stackerman	ifp->if_collisions = 0;
2390129794Stackerman
2391129794Stackerman	/* Rx Errors */
2392129794Stackerman	ifp->if_ierrors =
2393129794Stackerman		adapter->dropped_pkts +
2394129794Stackerman		adapter->stats.crcerrs +
2395129794Stackerman		adapter->stats.rnbc +
2396129794Stackerman		adapter->stats.mpc +
2397129794Stackerman		adapter->stats.rlec;
2398129794Stackerman
2399129794Stackerman
2400129794Stackerman}
2401129794Stackerman
2402129794Stackerman
2403129794Stackerman/**********************************************************************
2404129794Stackerman *
2405129794Stackerman *  This routine is called only when ixgb_display_debug_stats is enabled.
2406129794Stackerman *  This routine provides a way to take a look at important statistics
2407129794Stackerman *  maintained by the driver and hardware.
2408129794Stackerman *
2409129794Stackerman **********************************************************************/
2410129794Stackermanstatic void
2411129794Stackermanixgb_print_hw_stats(struct adapter * adapter)
2412129794Stackerman{
2413129794Stackerman	char            buf_speed[100], buf_type[100];
2414129794Stackerman	ixgb_bus_speed  bus_speed;
2415129794Stackerman	ixgb_bus_type   bus_type;
2416129794Stackerman	int             unit = adapter->unit;
2417129794Stackerman
2418129794Stackerman#ifdef _SV_
2419129794Stackerman	printf("ixgb%d: Packets not Avail = %ld\n", unit,
2420129794Stackerman	       adapter->no_pkts_avail);
2421129794Stackerman	printf("ixgb%d: CleanTxInterrupts = %ld\n", unit,
2422129794Stackerman	       adapter->clean_tx_interrupts);
2423129794Stackerman	printf("ixgb%d: ICR RXDMT0 = %lld\n", unit,
2424129794Stackerman	       (long long)adapter->sv_stats.icr_rxdmt0);
2425129794Stackerman	printf("ixgb%d: ICR RXO = %lld\n", unit,
2426129794Stackerman	       (long long)adapter->sv_stats.icr_rxo);
2427129794Stackerman	printf("ixgb%d: ICR RXT0 = %lld\n", unit,
2428129794Stackerman	       (long long)adapter->sv_stats.icr_rxt0);
2429129794Stackerman	printf("ixgb%d: ICR TXDW = %lld\n", unit,
2430129794Stackerman	       (long long)adapter->sv_stats.icr_TXDW);
2431129794Stackerman#endif				/* _SV_ */
2432129794Stackerman
2433129794Stackerman	bus_speed = adapter->hw.bus.speed;
2434129794Stackerman	bus_type = adapter->hw.bus.type;
2435129794Stackerman	sprintf(buf_speed,
2436129794Stackerman		bus_speed == ixgb_bus_speed_33 ? "33MHz" :
2437129794Stackerman		bus_speed == ixgb_bus_speed_66 ? "66MHz" :
2438129794Stackerman		bus_speed == ixgb_bus_speed_100 ? "100MHz" :
2439129794Stackerman		bus_speed == ixgb_bus_speed_133 ? "133MHz" :
2440129794Stackerman		"UNKNOWN");
2441129794Stackerman	printf("ixgb%d: PCI_Bus_Speed = %s\n", unit,
2442129794Stackerman	       buf_speed);
2443129794Stackerman
2444129794Stackerman	sprintf(buf_type,
2445129794Stackerman		bus_type == ixgb_bus_type_pci ? "PCI" :
2446129794Stackerman		bus_type == ixgb_bus_type_pcix ? "PCI-X" :
2447129794Stackerman		"UNKNOWN");
2448129794Stackerman	printf("ixgb%d: PCI_Bus_Type = %s\n", unit,
2449129794Stackerman	       buf_type);
2450129794Stackerman
2451129794Stackerman	printf("ixgb%d: Tx Descriptors not Avail1 = %ld\n", unit,
2452129794Stackerman	       adapter->no_tx_desc_avail1);
2453129794Stackerman	printf("ixgb%d: Tx Descriptors not Avail2 = %ld\n", unit,
2454129794Stackerman	       adapter->no_tx_desc_avail2);
2455129794Stackerman	printf("ixgb%d: Std Mbuf Failed = %ld\n", unit,
2456129794Stackerman	       adapter->mbuf_alloc_failed);
2457129794Stackerman	printf("ixgb%d: Std Cluster Failed = %ld\n", unit,
2458129794Stackerman	       adapter->mbuf_cluster_failed);
2459129794Stackerman
2460129794Stackerman	printf("ixgb%d: Defer count = %lld\n", unit,
2461129794Stackerman	       (long long)adapter->stats.dc);
2462129794Stackerman	printf("ixgb%d: Missed Packets = %lld\n", unit,
2463129794Stackerman	       (long long)adapter->stats.mpc);
2464129794Stackerman	printf("ixgb%d: Receive No Buffers = %lld\n", unit,
2465129794Stackerman	       (long long)adapter->stats.rnbc);
2466129794Stackerman	printf("ixgb%d: Receive length errors = %lld\n", unit,
2467129794Stackerman	       (long long)adapter->stats.rlec);
2468129794Stackerman	printf("ixgb%d: Crc errors = %lld\n", unit,
2469129794Stackerman	       (long long)adapter->stats.crcerrs);
2470129794Stackerman	printf("ixgb%d: Driver dropped packets = %ld\n", unit,
2471129794Stackerman	       adapter->dropped_pkts);
2472129794Stackerman
2473129794Stackerman	printf("ixgb%d: XON Rcvd = %lld\n", unit,
2474129794Stackerman	       (long long)adapter->stats.xonrxc);
2475129794Stackerman	printf("ixgb%d: XON Xmtd = %lld\n", unit,
2476129794Stackerman	       (long long)adapter->stats.xontxc);
2477129794Stackerman	printf("ixgb%d: XOFF Rcvd = %lld\n", unit,
2478129794Stackerman	       (long long)adapter->stats.xoffrxc);
2479129794Stackerman	printf("ixgb%d: XOFF Xmtd = %lld\n", unit,
2480129794Stackerman	       (long long)adapter->stats.xofftxc);
2481129794Stackerman
2482129794Stackerman	printf("ixgb%d: Good Packets Rcvd = %lld\n", unit,
2483129794Stackerman	       (long long)adapter->stats.gprcl);
2484129794Stackerman	printf("ixgb%d: Good Packets Xmtd = %lld\n", unit,
2485129794Stackerman	       (long long)adapter->stats.gptcl);
2486129794Stackerman
2487129794Stackerman	printf("ixgb%d: Jumbo frames recvd = %lld\n", unit,
2488129794Stackerman	       (long long)adapter->stats.jprcl);
2489129794Stackerman	printf("ixgb%d: Jumbo frames Xmtd = %lld\n", unit,
2490129794Stackerman	       (long long)adapter->stats.jptcl);
2491129794Stackerman
2492129794Stackerman	return;
2493129794Stackerman
2494129794Stackerman}
2495129794Stackerman
2496129794Stackermanstatic int
2497129794Stackermanixgb_sysctl_stats(SYSCTL_HANDLER_ARGS)
2498129794Stackerman{
2499129794Stackerman	int             error;
2500129794Stackerman	int             result;
2501129794Stackerman	struct adapter *adapter;
2502129794Stackerman
2503129794Stackerman	result = -1;
2504129794Stackerman	error = sysctl_handle_int(oidp, &result, 0, req);
2505129794Stackerman
2506129794Stackerman	if (error || !req->newptr)
2507129794Stackerman		return (error);
2508129794Stackerman
2509129794Stackerman	if (result == 1) {
2510129794Stackerman		adapter = (struct adapter *) arg1;
2511129794Stackerman		ixgb_print_hw_stats(adapter);
2512129794Stackerman	}
2513129794Stackerman	return error;
2514129794Stackerman}
2515