if_ixgb.c revision 148887
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 148887 2005-08-09 10:20:02Z rwatson $*/
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 *);
144129794Stackerman
145129794Stackerman/*********************************************************************
146129794Stackerman *  FreeBSD Device Interface Entry Points
147129794Stackerman *********************************************************************/
148129794Stackerman
149129794Stackermanstatic device_method_t ixgb_methods[] = {
150129794Stackerman	/* Device interface */
151129794Stackerman	DEVMETHOD(device_probe, ixgb_probe),
152129794Stackerman	DEVMETHOD(device_attach, ixgb_attach),
153129794Stackerman	DEVMETHOD(device_detach, ixgb_detach),
154129794Stackerman	DEVMETHOD(device_shutdown, ixgb_shutdown),
155129794Stackerman	{0, 0}
156129794Stackerman};
157129794Stackerman
158129794Stackermanstatic driver_t ixgb_driver = {
159129794Stackerman	"ixgb", ixgb_methods, sizeof(struct adapter),
160129794Stackerman};
161129794Stackerman
162129794Stackermanstatic devclass_t ixgb_devclass;
163129794StackermanDRIVER_MODULE(if_ixgb, pci, ixgb_driver, ixgb_devclass, 0, 0);
164129794Stackerman
165144190SmuxMODULE_DEPEND(if_ixgb, pci, 1, 1, 1);
166144190SmuxMODULE_DEPEND(if_ixgb, ether, 1, 1, 1);
167144183Smux
168129794Stackerman/* some defines for controlling descriptor fetches in h/w */
169129794Stackerman#define RXDCTL_PTHRESH_DEFAULT 128	/* chip considers prefech below this */
170129794Stackerman#define RXDCTL_HTHRESH_DEFAULT 16	/* chip will only prefetch if tail is
171129794Stackerman					 * pushed this many descriptors from
172129794Stackerman					 * head */
173129794Stackerman#define RXDCTL_WTHRESH_DEFAULT 0	/* chip writes back at this many or RXT0 */
174129794Stackerman
175129794Stackerman
176129794Stackerman/*********************************************************************
177129794Stackerman *  Device identification routine
178129794Stackerman *
179129794Stackerman *  ixgb_probe determines if the driver should be loaded on
180129794Stackerman *  adapter based on PCI vendor/device id of the adapter.
181129794Stackerman *
182129794Stackerman *  return 0 on success, positive on failure
183129794Stackerman *********************************************************************/
184129794Stackerman
185129794Stackermanstatic int
186129794Stackermanixgb_probe(device_t dev)
187129794Stackerman{
188129794Stackerman	ixgb_vendor_info_t *ent;
189129794Stackerman
190129794Stackerman	u_int16_t       pci_vendor_id = 0;
191129794Stackerman	u_int16_t       pci_device_id = 0;
192129794Stackerman	u_int16_t       pci_subvendor_id = 0;
193129794Stackerman	u_int16_t       pci_subdevice_id = 0;
194129794Stackerman	char            adapter_name[60];
195129794Stackerman
196129794Stackerman	INIT_DEBUGOUT("ixgb_probe: begin");
197129794Stackerman
198129794Stackerman	pci_vendor_id = pci_get_vendor(dev);
199129794Stackerman	if (pci_vendor_id != IXGB_VENDOR_ID)
200129794Stackerman		return (ENXIO);
201129794Stackerman
202129794Stackerman	pci_device_id = pci_get_device(dev);
203129794Stackerman	pci_subvendor_id = pci_get_subvendor(dev);
204129794Stackerman	pci_subdevice_id = pci_get_subdevice(dev);
205129794Stackerman
206129794Stackerman	ent = ixgb_vendor_info_array;
207129794Stackerman	while (ent->vendor_id != 0) {
208129794Stackerman		if ((pci_vendor_id == ent->vendor_id) &&
209129794Stackerman		    (pci_device_id == ent->device_id) &&
210129794Stackerman
211129794Stackerman		    ((pci_subvendor_id == ent->subvendor_id) ||
212129794Stackerman		     (ent->subvendor_id == PCI_ANY_ID)) &&
213129794Stackerman
214129794Stackerman		    ((pci_subdevice_id == ent->subdevice_id) ||
215129794Stackerman		     (ent->subdevice_id == PCI_ANY_ID))) {
216129794Stackerman			sprintf(adapter_name, "%s, Version - %s",
217129794Stackerman				ixgb_strings[ent->index],
218129794Stackerman				ixgb_driver_version);
219129794Stackerman			device_set_desc_copy(dev, adapter_name);
220143160Simp			return (BUS_PROBE_DEFAULT);
221129794Stackerman		}
222129794Stackerman		ent++;
223129794Stackerman	}
224129794Stackerman
225129794Stackerman	return (ENXIO);
226129794Stackerman}
227129794Stackerman
228129794Stackerman/*********************************************************************
229129794Stackerman *  Device initialization routine
230129794Stackerman *
231129794Stackerman *  The attach entry point is called when the driver is being loaded.
232129794Stackerman *  This routine identifies the type of hardware, allocates all resources
233129794Stackerman *  and initializes the hardware.
234129794Stackerman *
235129794Stackerman *  return 0 on success, positive on failure
236129794Stackerman *********************************************************************/
237129794Stackerman
238129794Stackermanstatic int
239129794Stackermanixgb_attach(device_t dev)
240129794Stackerman{
241129794Stackerman	struct adapter *adapter;
242129794Stackerman	int             tsize, rsize;
243129794Stackerman	int             error = 0;
244129794Stackerman
245129794Stackerman	printf("ixgb%d: %s\n", device_get_unit(dev), ixgb_copyright);
246129794Stackerman	INIT_DEBUGOUT("ixgb_attach: begin");
247129794Stackerman
248129794Stackerman	/* Allocate, clear, and link in our adapter structure */
249129794Stackerman	if (!(adapter = device_get_softc(dev))) {
250129794Stackerman		printf("ixgb: adapter structure allocation failed\n");
251129794Stackerman		return (ENOMEM);
252129794Stackerman	}
253129794Stackerman	bzero(adapter, sizeof(struct adapter));
254129794Stackerman	adapter->dev = dev;
255129794Stackerman	adapter->osdep.dev = dev;
256129794Stackerman	adapter->unit = device_get_unit(dev);
257144651Salc	IXGB_LOCK_INIT(adapter, device_get_nameunit(dev));
258129794Stackerman
259129794Stackerman	if (ixgb_adapter_list != NULL)
260129794Stackerman		ixgb_adapter_list->prev = adapter;
261129794Stackerman	adapter->next = ixgb_adapter_list;
262129794Stackerman	ixgb_adapter_list = adapter;
263129794Stackerman
264129794Stackerman	/* SYSCTL APIs */
265144183Smux	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
266144183Smux			SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
267129794Stackerman			OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW,
268129794Stackerman			(void *)adapter, 0,
269129794Stackerman			ixgb_sysctl_stats, "I", "Statistics");
270129794Stackerman
271144651Salc	callout_init(&adapter->timer, CALLOUT_MPSAFE);
272129794Stackerman
273129794Stackerman	/* Determine hardware revision */
274129794Stackerman	ixgb_identify_hardware(adapter);
275129794Stackerman
276129794Stackerman	/* Parameters (to be read from user) */
277129794Stackerman	adapter->num_tx_desc = IXGB_MAX_TXD;
278129794Stackerman	adapter->num_rx_desc = IXGB_MAX_RXD;
279129794Stackerman	adapter->tx_int_delay = TIDV;
280129794Stackerman	adapter->rx_int_delay = RDTR;
281129794Stackerman	adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
282129794Stackerman
283129794Stackerman	adapter->hw.fc.high_water = FCRTH;
284129794Stackerman	adapter->hw.fc.low_water = FCRTL;
285129794Stackerman	adapter->hw.fc.pause_time = FCPAUSE;
286129794Stackerman	adapter->hw.fc.send_xon = TRUE;
287129794Stackerman	adapter->hw.fc.type = FLOW_CONTROL;
288129794Stackerman
289129794Stackerman
290129794Stackerman	/* Set the max frame size assuming standard ethernet sized frames */
291129794Stackerman	adapter->hw.max_frame_size =
292129794Stackerman		ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN;
293129794Stackerman
294129794Stackerman	if (ixgb_allocate_pci_resources(adapter)) {
295129794Stackerman		printf("ixgb%d: Allocation of PCI resources failed\n",
296129794Stackerman		       adapter->unit);
297129794Stackerman		error = ENXIO;
298129794Stackerman		goto err_pci;
299129794Stackerman	}
300129794Stackerman	tsize = IXGB_ROUNDUP(adapter->num_tx_desc *
301129794Stackerman			     sizeof(struct ixgb_tx_desc), 4096);
302129794Stackerman
303129794Stackerman	/* Allocate Transmit Descriptor ring */
304129794Stackerman	if (ixgb_dma_malloc(adapter, tsize, &adapter->txdma, BUS_DMA_NOWAIT)) {
305129794Stackerman		printf("ixgb%d: Unable to allocate TxDescriptor memory\n",
306129794Stackerman		       adapter->unit);
307129794Stackerman		error = ENOMEM;
308129794Stackerman		goto err_tx_desc;
309129794Stackerman	}
310129794Stackerman	adapter->tx_desc_base = (struct ixgb_tx_desc *) adapter->txdma.dma_vaddr;
311129794Stackerman
312129794Stackerman	rsize = IXGB_ROUNDUP(adapter->num_rx_desc *
313129794Stackerman			     sizeof(struct ixgb_rx_desc), 4096);
314129794Stackerman
315129794Stackerman	/* Allocate Receive Descriptor ring */
316129794Stackerman	if (ixgb_dma_malloc(adapter, rsize, &adapter->rxdma, BUS_DMA_NOWAIT)) {
317129794Stackerman		printf("ixgb%d: Unable to allocate rx_desc memory\n",
318129794Stackerman		       adapter->unit);
319129794Stackerman		error = ENOMEM;
320129794Stackerman		goto err_rx_desc;
321129794Stackerman	}
322129794Stackerman	adapter->rx_desc_base = (struct ixgb_rx_desc *) adapter->rxdma.dma_vaddr;
323129794Stackerman
324129794Stackerman	/* Initialize the hardware */
325129794Stackerman	if (ixgb_hardware_init(adapter)) {
326129794Stackerman		printf("ixgb%d: Unable to initialize the hardware\n",
327129794Stackerman		       adapter->unit);
328129794Stackerman		error = EIO;
329129794Stackerman		goto err_hw_init;
330129794Stackerman	}
331129794Stackerman	/* Setup OS specific network interface */
332129794Stackerman	ixgb_setup_interface(dev, adapter);
333129794Stackerman
334129794Stackerman	/* Initialize statistics */
335129794Stackerman	ixgb_clear_hw_cntrs(&adapter->hw);
336129794Stackerman	ixgb_update_stats_counters(adapter);
337129794Stackerman
338129794Stackerman	INIT_DEBUGOUT("ixgb_attach: end");
339129794Stackerman	return (0);
340129794Stackerman
341129794Stackermanerr_hw_init:
342129794Stackerman	ixgb_dma_free(adapter, &adapter->rxdma);
343129794Stackermanerr_rx_desc:
344129794Stackerman	ixgb_dma_free(adapter, &adapter->txdma);
345129794Stackermanerr_tx_desc:
346129794Stackermanerr_pci:
347129794Stackerman	ixgb_free_pci_resources(adapter);
348129794Stackerman	sysctl_ctx_free(&adapter->sysctl_ctx);
349129794Stackerman	return (error);
350129794Stackerman
351129794Stackerman}
352129794Stackerman
353129794Stackerman/*********************************************************************
354129794Stackerman *  Device removal routine
355129794Stackerman *
356129794Stackerman *  The detach entry point is called when the driver is being removed.
357129794Stackerman *  This routine stops the adapter and deallocates all the resources
358129794Stackerman *  that were allocated for driver operation.
359129794Stackerman *
360129794Stackerman *  return 0 on success, positive on failure
361129794Stackerman *********************************************************************/
362129794Stackerman
363129794Stackermanstatic int
364129794Stackermanixgb_detach(device_t dev)
365129794Stackerman{
366129794Stackerman	struct adapter *adapter = device_get_softc(dev);
367147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
368129794Stackerman
369129794Stackerman	INIT_DEBUGOUT("ixgb_detach: begin");
370129794Stackerman
371144651Salc	IXGB_LOCK(adapter);
372129794Stackerman	adapter->in_detach = 1;
373129794Stackerman
374129794Stackerman	ixgb_stop(adapter);
375144651Salc	IXGB_UNLOCK(adapter);
376129794Stackerman
377129794Stackerman#if __FreeBSD_version < 500000
378147256Sbrooks	ether_ifdetach(adapter->ifp, ETHER_BPF_SUPPORTED);
379129794Stackerman#else
380147256Sbrooks	ether_ifdetach(adapter->ifp);
381147256Sbrooks	if_free(adapter->ifp);
382129794Stackerman#endif
383129794Stackerman	ixgb_free_pci_resources(adapter);
384129794Stackerman
385129794Stackerman
386129794Stackerman	/* Free Transmit Descriptor ring */
387129794Stackerman	if (adapter->tx_desc_base) {
388129794Stackerman		ixgb_dma_free(adapter, &adapter->txdma);
389129794Stackerman		adapter->tx_desc_base = NULL;
390129794Stackerman	}
391129794Stackerman	/* Free Receive Descriptor ring */
392129794Stackerman	if (adapter->rx_desc_base) {
393129794Stackerman		ixgb_dma_free(adapter, &adapter->rxdma);
394129794Stackerman		adapter->rx_desc_base = NULL;
395129794Stackerman	}
396129794Stackerman	/* Remove from the adapter list */
397129794Stackerman	if (ixgb_adapter_list == adapter)
398129794Stackerman		ixgb_adapter_list = adapter->next;
399129794Stackerman	if (adapter->next != NULL)
400129794Stackerman		adapter->next->prev = adapter->prev;
401129794Stackerman	if (adapter->prev != NULL)
402129794Stackerman		adapter->prev->next = adapter->next;
403129794Stackerman
404148887Srwatson	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
405129794Stackerman	ifp->if_timer = 0;
406129794Stackerman
407144651Salc	IXGB_LOCK_DESTROY(adapter);
408129794Stackerman	return (0);
409129794Stackerman}
410129794Stackerman
411129794Stackerman/*********************************************************************
412129794Stackerman *
413129794Stackerman *  Shutdown entry point
414129794Stackerman *
415129794Stackerman **********************************************************************/
416129794Stackerman
417129794Stackermanstatic int
418129794Stackermanixgb_shutdown(device_t dev)
419129794Stackerman{
420129794Stackerman	struct adapter *adapter = device_get_softc(dev);
421144651Salc	IXGB_LOCK(adapter);
422129794Stackerman	ixgb_stop(adapter);
423144651Salc	IXGB_UNLOCK(adapter);
424129794Stackerman	return (0);
425129794Stackerman}
426129794Stackerman
427129794Stackerman
428129794Stackerman/*********************************************************************
429129794Stackerman *  Transmit entry point
430129794Stackerman *
431129794Stackerman *  ixgb_start is called by the stack to initiate a transmit.
432129794Stackerman *  The driver will remain in this routine as long as there are
433129794Stackerman *  packets to transmit and transmit resources are available.
434129794Stackerman *  In case resources are not available stack is notified and
435129794Stackerman *  the packet is requeued.
436129794Stackerman **********************************************************************/
437129794Stackerman
438129794Stackermanstatic void
439144651Salcixgb_start_locked(struct ifnet * ifp)
440129794Stackerman{
441129794Stackerman	struct mbuf    *m_head;
442129794Stackerman	struct adapter *adapter = ifp->if_softc;
443129794Stackerman
444144651Salc	IXGB_LOCK_ASSERT(adapter);
445129794Stackerman
446129794Stackerman	if (!adapter->link_active)
447129794Stackerman		return;
448129794Stackerman
449129794Stackerman	while (ifp->if_snd.ifq_head != NULL) {
450129794Stackerman		IF_DEQUEUE(&ifp->if_snd, m_head);
451129794Stackerman
452129794Stackerman		if (m_head == NULL)
453129794Stackerman			break;
454129794Stackerman
455129794Stackerman		if (ixgb_encap(adapter, m_head)) {
456148887Srwatson			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
457129794Stackerman			IF_PREPEND(&ifp->if_snd, m_head);
458129794Stackerman			break;
459129794Stackerman		}
460129794Stackerman		/* Send a copy of the frame to the BPF listener */
461129794Stackerman#if __FreeBSD_version < 500000
462129794Stackerman		if (ifp->if_bpf)
463129794Stackerman			bpf_mtap(ifp, m_head);
464129794Stackerman#else
465129794Stackerman		BPF_MTAP(ifp, m_head);
466129794Stackerman#endif
467129794Stackerman		/* Set timeout in case hardware has problems transmitting */
468129794Stackerman		ifp->if_timer = IXGB_TX_TIMEOUT;
469129794Stackerman
470129794Stackerman	}
471129794Stackerman	return;
472129794Stackerman}
473129794Stackerman
474144651Salcstatic void
475144651Salcixgb_start(struct ifnet *ifp)
476144651Salc{
477144651Salc	struct adapter *adapter = ifp->if_softc;
478144651Salc
479144651Salc	IXGB_LOCK(adapter);
480144651Salc	ixgb_start_locked(ifp);
481144651Salc	IXGB_UNLOCK(adapter);
482144651Salc	return;
483144651Salc}
484144651Salc
485129794Stackerman/*********************************************************************
486129794Stackerman *  Ioctl entry point
487129794Stackerman *
488129794Stackerman *  ixgb_ioctl is called when the user wants to configure the
489129794Stackerman *  interface.
490129794Stackerman *
491129794Stackerman *  return 0 on success, positive on failure
492129794Stackerman **********************************************************************/
493129794Stackerman
494129794Stackermanstatic int
495129794Stackermanixgb_ioctl(struct ifnet * ifp, IOCTL_CMD_TYPE command, caddr_t data)
496129794Stackerman{
497144651Salc	int             mask, error = 0;
498129794Stackerman	struct ifreq   *ifr = (struct ifreq *) data;
499129794Stackerman	struct adapter *adapter = ifp->if_softc;
500129794Stackerman
501129794Stackerman	if (adapter->in_detach)
502129794Stackerman		goto out;
503129794Stackerman
504129794Stackerman	switch (command) {
505129794Stackerman	case SIOCSIFADDR:
506129794Stackerman	case SIOCGIFADDR:
507129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFADDR (Get/Set Interface Addr)");
508129794Stackerman		ether_ioctl(ifp, command, data);
509129794Stackerman		break;
510129794Stackerman	case SIOCSIFMTU:
511129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFMTU (Set Interface MTU)");
512129794Stackerman		if (ifr->ifr_mtu > IXGB_MAX_JUMBO_FRAME_SIZE - ETHER_HDR_LEN) {
513129794Stackerman			error = EINVAL;
514129794Stackerman		} else {
515144651Salc			IXGB_LOCK(adapter);
516129794Stackerman			ifp->if_mtu = ifr->ifr_mtu;
517129794Stackerman			adapter->hw.max_frame_size =
518129794Stackerman				ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
519129794Stackerman
520144651Salc			ixgb_init_locked(adapter);
521144651Salc			IXGB_UNLOCK(adapter);
522129794Stackerman		}
523129794Stackerman		break;
524129794Stackerman	case SIOCSIFFLAGS:
525129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface Flags)");
526144651Salc		IXGB_LOCK(adapter);
527129794Stackerman		if (ifp->if_flags & IFF_UP) {
528148887Srwatson			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
529144651Salc				ixgb_init_locked(adapter);
530129794Stackerman			}
531129794Stackerman			ixgb_disable_promisc(adapter);
532129794Stackerman			ixgb_set_promisc(adapter);
533129794Stackerman		} else {
534148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
535129794Stackerman				ixgb_stop(adapter);
536129794Stackerman			}
537129794Stackerman		}
538144651Salc		IXGB_UNLOCK(adapter);
539129794Stackerman		break;
540129794Stackerman	case SIOCADDMULTI:
541129794Stackerman	case SIOCDELMULTI:
542129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOC(ADD|DEL)MULTI");
543148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
544144651Salc			IXGB_LOCK(adapter);
545129794Stackerman			ixgb_disable_intr(adapter);
546129794Stackerman			ixgb_set_multi(adapter);
547129794Stackerman			ixgb_enable_intr(adapter);
548144651Salc			IXGB_UNLOCK(adapter);
549129794Stackerman		}
550129794Stackerman		break;
551129794Stackerman	case SIOCSIFMEDIA:
552129794Stackerman	case SIOCGIFMEDIA:
553129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFMEDIA (Get/Set Interface Media)");
554129794Stackerman		error = ifmedia_ioctl(ifp, ifr, &adapter->media, command);
555129794Stackerman		break;
556129794Stackerman	case SIOCSIFCAP:
557129794Stackerman		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
558129794Stackerman		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
559129794Stackerman		if (mask & IFCAP_HWCSUM) {
560129794Stackerman			if (IFCAP_HWCSUM & ifp->if_capenable)
561129794Stackerman				ifp->if_capenable &= ~IFCAP_HWCSUM;
562129794Stackerman			else
563129794Stackerman				ifp->if_capenable |= IFCAP_HWCSUM;
564148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
565129794Stackerman				ixgb_init(adapter);
566129794Stackerman		}
567129794Stackerman		break;
568129794Stackerman	default:
569129794Stackerman		IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%X)\n", (int)command);
570129794Stackerman		error = EINVAL;
571129794Stackerman	}
572129794Stackerman
573129794Stackermanout:
574129794Stackerman	return (error);
575129794Stackerman}
576129794Stackerman
577129794Stackerman/*********************************************************************
578129794Stackerman *  Watchdog entry point
579129794Stackerman *
580129794Stackerman *  This routine is called whenever hardware quits transmitting.
581129794Stackerman *
582129794Stackerman **********************************************************************/
583129794Stackerman
584129794Stackermanstatic void
585129794Stackermanixgb_watchdog(struct ifnet * ifp)
586129794Stackerman{
587129794Stackerman	struct adapter *adapter;
588129794Stackerman	adapter = ifp->if_softc;
589129794Stackerman
590129794Stackerman	/*
591129794Stackerman	 * If we are in this routine because of pause frames, then don't
592129794Stackerman	 * reset the hardware.
593129794Stackerman	 */
594129794Stackerman	if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF) {
595129794Stackerman		ifp->if_timer = IXGB_TX_TIMEOUT;
596129794Stackerman		return;
597129794Stackerman	}
598129794Stackerman	printf("ixgb%d: watchdog timeout -- resetting\n", adapter->unit);
599129794Stackerman
600148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
601129794Stackerman
602129794Stackerman
603129794Stackerman	ixgb_stop(adapter);
604129794Stackerman	ixgb_init(adapter);
605129794Stackerman
606129794Stackerman
607129794Stackerman	ifp->if_oerrors++;
608129794Stackerman
609129794Stackerman	return;
610129794Stackerman}
611129794Stackerman
612129794Stackerman/*********************************************************************
613129794Stackerman *  Init entry point
614129794Stackerman *
615129794Stackerman *  This routine is used in two ways. It is used by the stack as
616129794Stackerman *  init entry point in network interface structure. It is also used
617129794Stackerman *  by the driver as a hw/sw initialization routine to get to a
618129794Stackerman *  consistent state.
619129794Stackerman *
620129794Stackerman *  return 0 on success, positive on failure
621129794Stackerman **********************************************************************/
622129794Stackerman
623129794Stackermanstatic void
624144651Salcixgb_init_locked(struct adapter *adapter)
625129794Stackerman{
626129794Stackerman	struct ifnet   *ifp;
627129794Stackerman
628129794Stackerman	INIT_DEBUGOUT("ixgb_init: begin");
629129794Stackerman
630144651Salc	IXGB_LOCK_ASSERT(adapter);
631129794Stackerman
632129794Stackerman	ixgb_stop(adapter);
633129794Stackerman
634129794Stackerman	/* Get the latest mac address, User can use a LAA */
635147256Sbrooks	bcopy(IFP2ENADDR(adapter->ifp), adapter->hw.curr_mac_addr,
636129794Stackerman	      IXGB_ETH_LENGTH_OF_ADDRESS);
637129794Stackerman
638129794Stackerman	/* Initialize the hardware */
639129794Stackerman	if (ixgb_hardware_init(adapter)) {
640129794Stackerman		printf("ixgb%d: Unable to initialize the hardware\n",
641129794Stackerman		       adapter->unit);
642129794Stackerman		return;
643129794Stackerman	}
644129794Stackerman	ixgb_enable_vlans(adapter);
645129794Stackerman
646129794Stackerman	/* Prepare transmit descriptors and buffers */
647129794Stackerman	if (ixgb_setup_transmit_structures(adapter)) {
648129794Stackerman		printf("ixgb%d: Could not setup transmit structures\n",
649129794Stackerman		       adapter->unit);
650129794Stackerman		ixgb_stop(adapter);
651129794Stackerman		return;
652129794Stackerman	}
653129794Stackerman	ixgb_initialize_transmit_unit(adapter);
654129794Stackerman
655129794Stackerman	/* Setup Multicast table */
656129794Stackerman	ixgb_set_multi(adapter);
657129794Stackerman
658129794Stackerman	/* Prepare receive descriptors and buffers */
659129794Stackerman	if (ixgb_setup_receive_structures(adapter)) {
660129794Stackerman		printf("ixgb%d: Could not setup receive structures\n",
661129794Stackerman		       adapter->unit);
662129794Stackerman		ixgb_stop(adapter);
663129794Stackerman		return;
664129794Stackerman	}
665129794Stackerman	ixgb_initialize_receive_unit(adapter);
666129794Stackerman
667129794Stackerman	/* Don't loose promiscuous settings */
668129794Stackerman	ixgb_set_promisc(adapter);
669129794Stackerman
670147256Sbrooks	ifp = adapter->ifp;
671148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
672148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
673129794Stackerman
674129794Stackerman
675129794Stackerman	if (ifp->if_capenable & IFCAP_TXCSUM)
676129794Stackerman		ifp->if_hwassist = IXGB_CHECKSUM_FEATURES;
677129794Stackerman	else
678129794Stackerman		ifp->if_hwassist = 0;
679129794Stackerman
680129794Stackerman
681129794Stackerman	/* Enable jumbo frames */
682129794Stackerman	if (ifp->if_mtu > ETHERMTU) {
683129794Stackerman		uint32_t        temp_reg;
684129794Stackerman		IXGB_WRITE_REG(&adapter->hw, MFS,
685129794Stackerman			       adapter->hw.max_frame_size << IXGB_MFS_SHIFT);
686129794Stackerman		temp_reg = IXGB_READ_REG(&adapter->hw, CTRL0);
687129794Stackerman		temp_reg |= IXGB_CTRL0_JFE;
688129794Stackerman		IXGB_WRITE_REG(&adapter->hw, CTRL0, temp_reg);
689129794Stackerman	}
690144651Salc	callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, adapter);
691129794Stackerman	ixgb_clear_hw_cntrs(&adapter->hw);
692129794Stackerman#ifdef DEVICE_POLLING
693129794Stackerman	/*
694129794Stackerman	 * Only disable interrupts if we are polling, make sure they are on
695129794Stackerman	 * otherwise.
696129794Stackerman	 */
697131426Stackerman	if (ifp->if_flags & IFF_POLLING)
698129794Stackerman		ixgb_disable_intr(adapter);
699129794Stackerman	else
700129794Stackerman#endif				/* DEVICE_POLLING */
701129794Stackerman		ixgb_enable_intr(adapter);
702129794Stackerman
703129794Stackerman	return;
704129794Stackerman}
705129794Stackerman
706144651Salcstatic void
707144651Salcixgb_init(void *arg)
708144651Salc{
709144651Salc	struct adapter *adapter = arg;
710129794Stackerman
711144651Salc	IXGB_LOCK(adapter);
712144651Salc	ixgb_init_locked(adapter);
713144651Salc	IXGB_UNLOCK(adapter);
714144651Salc	return;
715144651Salc}
716144651Salc
717129794Stackerman#ifdef DEVICE_POLLING
718129794Stackermanstatic poll_handler_t ixgb_poll;
719129794Stackerman
720129794Stackermanstatic void
721144651Salcixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count)
722129794Stackerman{
723129794Stackerman	struct adapter *adapter = ifp->if_softc;
724129794Stackerman	u_int32_t       reg_icr;
725129794Stackerman
726144651Salc	IXGB_LOCK_ASSERT(adapter);
727144651Salc
728148637Sbrueffer	if (!(ifp->if_capenable & IFCAP_POLLING)) {
729148637Sbrueffer		ether_poll_deregister(ifp);
730148637Sbrueffer		cmd = POLL_DEREGISTER;
731148637Sbrueffer	}
732148637Sbrueffer
733129794Stackerman	if (cmd == POLL_DEREGISTER) {	/* final call, enable interrupts */
734129794Stackerman		ixgb_enable_intr(adapter);
735129794Stackerman		return;
736129794Stackerman	}
737129794Stackerman	if (cmd == POLL_AND_CHECK_STATUS) {
738129794Stackerman		reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
739129794Stackerman		if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
740144651Salc			callout_stop(&adapter->timer);
741129794Stackerman			ixgb_check_for_link(&adapter->hw);
742129794Stackerman			ixgb_print_link_status(adapter);
743144651Salc			callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer,
744144651Salc			    adapter);
745129794Stackerman		}
746129794Stackerman	}
747148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
748129794Stackerman		ixgb_process_receive_interrupts(adapter, count);
749129794Stackerman		ixgb_clean_transmit_interrupts(adapter);
750129794Stackerman	}
751148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
752148887Srwatson	    ifp->if_snd.ifq_head != NULL)
753144651Salc		ixgb_start_locked(ifp);
754129794Stackerman}
755144651Salc
756144651Salcstatic void
757144651Salcixgb_poll(struct ifnet * ifp, enum poll_cmd cmd, int count)
758144651Salc{
759144651Salc	struct adapter *adapter = ifp->if_softc;
760144651Salc
761144651Salc	IXGB_LOCK(adapter);
762144651Salc	ixgb_poll_locked(ifp, cmd, count);
763144651Salc	IXGB_UNLOCK(adapter);
764144651Salc}
765129794Stackerman#endif				/* DEVICE_POLLING */
766129794Stackerman
767129794Stackerman/*********************************************************************
768129794Stackerman *
769129794Stackerman *  Interrupt Service routine
770129794Stackerman *
771129794Stackerman **********************************************************************/
772129794Stackerman
773129794Stackermanstatic void
774129794Stackermanixgb_intr(void *arg)
775129794Stackerman{
776129794Stackerman	u_int32_t       loop_cnt = IXGB_MAX_INTR;
777129794Stackerman	u_int32_t       reg_icr;
778129794Stackerman	struct ifnet   *ifp;
779129794Stackerman	struct adapter *adapter = arg;
780129794Stackerman	boolean_t       rxdmt0 = FALSE;
781129794Stackerman
782144651Salc	IXGB_LOCK(adapter);
783144651Salc
784147256Sbrooks	ifp = adapter->ifp;
785129794Stackerman
786129794Stackerman#ifdef DEVICE_POLLING
787144651Salc	if (ifp->if_flags & IFF_POLLING) {
788144651Salc		IXGB_UNLOCK(adapter);
789129794Stackerman		return;
790144651Salc	}
791129794Stackerman
792148637Sbrueffer	if ((ifp->if_capenable & IFCAP_POLLING) &&
793148637Sbrueffer	    ether_poll_register(ixgb_poll, ifp)) {
794129794Stackerman		ixgb_disable_intr(adapter);
795144651Salc		ixgb_poll_locked(ifp, 0, 1);
796144651Salc		IXGB_UNLOCK(adapter);
797129794Stackerman		return;
798129794Stackerman	}
799129794Stackerman#endif				/* DEVICE_POLLING */
800129794Stackerman
801144651Salc	reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
802144651Salc	if (reg_icr == 0) {
803144651Salc		IXGB_UNLOCK(adapter);
804129794Stackerman		return;
805144651Salc	}
806129794Stackerman
807129794Stackerman	if (reg_icr & IXGB_INT_RXDMT0)
808129794Stackerman		rxdmt0 = TRUE;
809129794Stackerman
810129794Stackerman#ifdef _SV_
811129794Stackerman	if (reg_icr & IXGB_INT_RXDMT0)
812129794Stackerman		adapter->sv_stats.icr_rxdmt0++;
813129794Stackerman	if (reg_icr & IXGB_INT_RXO)
814129794Stackerman		adapter->sv_stats.icr_rxo++;
815129794Stackerman	if (reg_icr & IXGB_INT_RXT0)
816129794Stackerman		adapter->sv_stats.icr_rxt0++;
817129794Stackerman	if (reg_icr & IXGB_INT_TXDW)
818129794Stackerman		adapter->sv_stats.icr_TXDW++;
819129794Stackerman#endif				/* _SV_ */
820129794Stackerman
821129794Stackerman	/* Link status change */
822129794Stackerman	if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
823144651Salc		callout_stop(&adapter->timer);
824129794Stackerman		ixgb_check_for_link(&adapter->hw);
825129794Stackerman		ixgb_print_link_status(adapter);
826144651Salc		callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer,
827144651Salc		    adapter);
828129794Stackerman	}
829129794Stackerman	while (loop_cnt > 0) {
830148887Srwatson		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
831129794Stackerman			ixgb_process_receive_interrupts(adapter, -1);
832129794Stackerman			ixgb_clean_transmit_interrupts(adapter);
833129794Stackerman		}
834129794Stackerman		loop_cnt--;
835129794Stackerman	}
836129794Stackerman
837129794Stackerman	if (rxdmt0 && adapter->raidc) {
838129794Stackerman		IXGB_WRITE_REG(&adapter->hw, IMC, IXGB_INT_RXDMT0);
839129794Stackerman		IXGB_WRITE_REG(&adapter->hw, IMS, IXGB_INT_RXDMT0);
840129794Stackerman	}
841148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING && ifp->if_snd.ifq_head != NULL)
842144651Salc		ixgb_start_locked(ifp);
843129794Stackerman
844144651Salc	IXGB_UNLOCK(adapter);
845129794Stackerman	return;
846129794Stackerman}
847129794Stackerman
848129794Stackerman
849129794Stackerman/*********************************************************************
850129794Stackerman *
851129794Stackerman *  Media Ioctl callback
852129794Stackerman *
853129794Stackerman *  This routine is called whenever the user queries the status of
854129794Stackerman *  the interface using ifconfig.
855129794Stackerman *
856129794Stackerman **********************************************************************/
857129794Stackermanstatic void
858129794Stackermanixgb_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
859129794Stackerman{
860129794Stackerman	struct adapter *adapter = ifp->if_softc;
861129794Stackerman
862129794Stackerman	INIT_DEBUGOUT("ixgb_media_status: begin");
863129794Stackerman
864129794Stackerman	ixgb_check_for_link(&adapter->hw);
865129794Stackerman	ixgb_print_link_status(adapter);
866129794Stackerman
867129794Stackerman	ifmr->ifm_status = IFM_AVALID;
868129794Stackerman	ifmr->ifm_active = IFM_ETHER;
869129794Stackerman
870129794Stackerman	if (!adapter->hw.link_up)
871129794Stackerman		return;
872129794Stackerman
873129794Stackerman	ifmr->ifm_status |= IFM_ACTIVE;
874129794Stackerman	ifmr->ifm_active |= IFM_1000_SX | IFM_FDX;
875129794Stackerman
876129794Stackerman	return;
877129794Stackerman}
878129794Stackerman
879129794Stackerman/*********************************************************************
880129794Stackerman *
881129794Stackerman *  Media Ioctl callback
882129794Stackerman *
883129794Stackerman *  This routine is called when the user changes speed/duplex using
884129794Stackerman *  media/mediopt option with ifconfig.
885129794Stackerman *
886129794Stackerman **********************************************************************/
887129794Stackermanstatic int
888129794Stackermanixgb_media_change(struct ifnet * ifp)
889129794Stackerman{
890129794Stackerman	struct adapter *adapter = ifp->if_softc;
891129794Stackerman	struct ifmedia *ifm = &adapter->media;
892129794Stackerman
893129794Stackerman	INIT_DEBUGOUT("ixgb_media_change: begin");
894129794Stackerman
895129794Stackerman	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
896129794Stackerman		return (EINVAL);
897129794Stackerman
898129794Stackerman	return (0);
899129794Stackerman}
900129794Stackerman
901129794Stackerman/*********************************************************************
902129794Stackerman *
903129794Stackerman *  This routine maps the mbufs to tx descriptors.
904129794Stackerman *
905129794Stackerman *  return 0 on success, positive on failure
906129794Stackerman **********************************************************************/
907129794Stackerman
908129794Stackermanstatic int
909129794Stackermanixgb_encap(struct adapter * adapter, struct mbuf * m_head)
910129794Stackerman{
911129794Stackerman	u_int8_t        txd_popts;
912146339Salc	int             i, j, error, nsegs;
913129794Stackerman
914129794Stackerman#if __FreeBSD_version < 500000
915129794Stackerman	struct ifvlan  *ifv = NULL;
916129794Stackerman#else
917129794Stackerman	struct m_tag   *mtag;
918129794Stackerman#endif
919146339Salc	bus_dma_segment_t segs[IXGB_MAX_SCATTER];
920146339Salc	bus_dmamap_t	map;
921129794Stackerman	struct ixgb_buffer *tx_buffer = NULL;
922129794Stackerman	struct ixgb_tx_desc *current_tx_desc = NULL;
923147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
924129794Stackerman
925129794Stackerman	/*
926129794Stackerman	 * Force a cleanup if number of TX descriptors available hits the
927129794Stackerman	 * threshold
928129794Stackerman	 */
929129794Stackerman	if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) {
930129794Stackerman		ixgb_clean_transmit_interrupts(adapter);
931129794Stackerman	}
932129794Stackerman	if (adapter->num_tx_desc_avail <= IXGB_TX_CLEANUP_THRESHOLD) {
933129794Stackerman		adapter->no_tx_desc_avail1++;
934129794Stackerman		return (ENOBUFS);
935129794Stackerman	}
936129794Stackerman	/*
937129794Stackerman	 * Map the packet for DMA.
938129794Stackerman	 */
939146339Salc	if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &map)) {
940129794Stackerman		adapter->no_tx_map_avail++;
941129794Stackerman		return (ENOMEM);
942129794Stackerman	}
943146339Salc	error = bus_dmamap_load_mbuf_sg(adapter->txtag, map, m_head, segs,
944146339Salc					&nsegs, BUS_DMA_NOWAIT);
945129794Stackerman	if (error != 0) {
946129794Stackerman		adapter->no_tx_dma_setup++;
947129794Stackerman		printf("ixgb%d: ixgb_encap: bus_dmamap_load_mbuf failed; "
948129794Stackerman		       "error %u\n", adapter->unit, error);
949146339Salc		bus_dmamap_destroy(adapter->txtag, map);
950129794Stackerman		return (error);
951129794Stackerman	}
952146339Salc	KASSERT(nsegs != 0, ("ixgb_encap: empty packet"));
953129794Stackerman
954146339Salc	if (nsegs > adapter->num_tx_desc_avail) {
955129794Stackerman		adapter->no_tx_desc_avail2++;
956146339Salc		bus_dmamap_destroy(adapter->txtag, map);
957129794Stackerman		return (ENOBUFS);
958129794Stackerman	}
959129794Stackerman	if (ifp->if_hwassist > 0) {
960129794Stackerman		ixgb_transmit_checksum_setup(adapter, m_head,
961129794Stackerman					     &txd_popts);
962129794Stackerman	} else
963129794Stackerman		txd_popts = 0;
964129794Stackerman
965129794Stackerman	/* Find out if we are in vlan mode */
966129794Stackerman#if __FreeBSD_version < 500000
967129794Stackerman	if ((m_head->m_flags & (M_PROTO1 | M_PKTHDR)) == (M_PROTO1 | M_PKTHDR) &&
968129794Stackerman	    m_head->m_pkthdr.rcvif != NULL &&
969129794Stackerman	    m_head->m_pkthdr.rcvif->if_type == IFT_L2VLAN)
970129794Stackerman		ifv = m_head->m_pkthdr.rcvif->if_softc;
971129794Stackerman#else
972129794Stackerman	mtag = VLAN_OUTPUT_TAG(ifp, m_head);
973129794Stackerman#endif
974129794Stackerman	i = adapter->next_avail_tx_desc;
975146339Salc	for (j = 0; j < nsegs; j++) {
976129794Stackerman		tx_buffer = &adapter->tx_buffer_area[i];
977129794Stackerman		current_tx_desc = &adapter->tx_desc_base[i];
978129794Stackerman
979146339Salc		current_tx_desc->buff_addr = htole64(segs[j].ds_addr);
980146339Salc		current_tx_desc->cmd_type_len = (adapter->txd_cmd | segs[j].ds_len);
981129794Stackerman		current_tx_desc->popts = txd_popts;
982129794Stackerman		if (++i == adapter->num_tx_desc)
983129794Stackerman			i = 0;
984129794Stackerman
985129794Stackerman		tx_buffer->m_head = NULL;
986129794Stackerman	}
987129794Stackerman
988146339Salc	adapter->num_tx_desc_avail -= nsegs;
989129794Stackerman	adapter->next_avail_tx_desc = i;
990129794Stackerman
991129794Stackerman#if __FreeBSD_version < 500000
992129794Stackerman	if (ifv != NULL) {
993129794Stackerman		/* Set the vlan id */
994129794Stackerman		current_tx_desc->vlan = ifv->ifv_tag;
995129794Stackerman#else
996129794Stackerman	if (mtag != NULL) {
997129794Stackerman		/* Set the vlan id */
998129794Stackerman		current_tx_desc->vlan = VLAN_TAG_VALUE(mtag);
999129794Stackerman#endif
1000129794Stackerman
1001129794Stackerman		/* Tell hardware to add tag */
1002129794Stackerman		current_tx_desc->cmd_type_len |= IXGB_TX_DESC_CMD_VLE;
1003129794Stackerman	}
1004129794Stackerman	tx_buffer->m_head = m_head;
1005146339Salc	tx_buffer->map = map;
1006146339Salc	bus_dmamap_sync(adapter->txtag, map, BUS_DMASYNC_PREWRITE);
1007129794Stackerman
1008129794Stackerman	/*
1009129794Stackerman	 * Last Descriptor of Packet needs End Of Packet (EOP)
1010129794Stackerman	 */
1011129794Stackerman	current_tx_desc->cmd_type_len |= (IXGB_TX_DESC_CMD_EOP);
1012129794Stackerman
1013129794Stackerman	/*
1014129794Stackerman	 * Advance the Transmit Descriptor Tail (Tdt), this tells the E1000
1015129794Stackerman	 * that this frame is available to transmit.
1016129794Stackerman	 */
1017129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDT, i);
1018129794Stackerman
1019129794Stackerman	return (0);
1020129794Stackerman}
1021129794Stackerman
1022129794Stackermanstatic void
1023129794Stackermanixgb_set_promisc(struct adapter * adapter)
1024129794Stackerman{
1025129794Stackerman
1026129794Stackerman	u_int32_t       reg_rctl;
1027147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
1028129794Stackerman
1029129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1030129794Stackerman
1031129794Stackerman	if (ifp->if_flags & IFF_PROMISC) {
1032129794Stackerman		reg_rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
1033129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1034129794Stackerman	} else if (ifp->if_flags & IFF_ALLMULTI) {
1035129794Stackerman		reg_rctl |= IXGB_RCTL_MPE;
1036129794Stackerman		reg_rctl &= ~IXGB_RCTL_UPE;
1037129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1038129794Stackerman	}
1039129794Stackerman	return;
1040129794Stackerman}
1041129794Stackerman
1042129794Stackermanstatic void
1043129794Stackermanixgb_disable_promisc(struct adapter * adapter)
1044129794Stackerman{
1045129794Stackerman	u_int32_t       reg_rctl;
1046129794Stackerman
1047129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1048129794Stackerman
1049129794Stackerman	reg_rctl &= (~IXGB_RCTL_UPE);
1050129794Stackerman	reg_rctl &= (~IXGB_RCTL_MPE);
1051129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1052129794Stackerman
1053129794Stackerman	return;
1054129794Stackerman}
1055129794Stackerman
1056129794Stackerman
1057129794Stackerman/*********************************************************************
1058129794Stackerman *  Multicast Update
1059129794Stackerman *
1060129794Stackerman *  This routine is called whenever multicast address list is updated.
1061129794Stackerman *
1062129794Stackerman **********************************************************************/
1063129794Stackerman
1064129794Stackermanstatic void
1065129794Stackermanixgb_set_multi(struct adapter * adapter)
1066129794Stackerman{
1067129794Stackerman	u_int32_t       reg_rctl = 0;
1068129794Stackerman	u_int8_t        mta[MAX_NUM_MULTICAST_ADDRESSES * IXGB_ETH_LENGTH_OF_ADDRESS];
1069129794Stackerman	struct ifmultiaddr *ifma;
1070129794Stackerman	int             mcnt = 0;
1071147256Sbrooks	struct ifnet   *ifp = adapter->ifp;
1072129794Stackerman
1073129794Stackerman	IOCTL_DEBUGOUT("ixgb_set_multi: begin");
1074129794Stackerman
1075148654Srwatson	IF_ADDR_LOCK(ifp);
1076129794Stackerman#if __FreeBSD_version < 500000
1077129794Stackerman	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1078129794Stackerman#else
1079129794Stackerman	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1080129794Stackerman#endif
1081129794Stackerman		if (ifma->ifma_addr->sa_family != AF_LINK)
1082129794Stackerman			continue;
1083129794Stackerman
1084129794Stackerman		bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
1085129794Stackerman		      &mta[mcnt * IXGB_ETH_LENGTH_OF_ADDRESS], IXGB_ETH_LENGTH_OF_ADDRESS);
1086129794Stackerman		mcnt++;
1087129794Stackerman	}
1088148654Srwatson	IF_ADDR_UNLOCK(ifp);
1089129794Stackerman
1090129794Stackerman	if (mcnt > MAX_NUM_MULTICAST_ADDRESSES) {
1091129794Stackerman		reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1092129794Stackerman		reg_rctl |= IXGB_RCTL_MPE;
1093129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
1094129794Stackerman	} else
1095129794Stackerman		ixgb_mc_addr_list_update(&adapter->hw, mta, mcnt, 0);
1096129794Stackerman
1097129794Stackerman	return;
1098129794Stackerman}
1099129794Stackerman
1100129794Stackerman
1101129794Stackerman/*********************************************************************
1102129794Stackerman *  Timer routine
1103129794Stackerman *
1104129794Stackerman *  This routine checks for link status and updates statistics.
1105129794Stackerman *
1106129794Stackerman **********************************************************************/
1107129794Stackerman
1108129794Stackermanstatic void
1109129794Stackermanixgb_local_timer(void *arg)
1110129794Stackerman{
1111129794Stackerman	struct ifnet   *ifp;
1112129794Stackerman	struct adapter *adapter = arg;
1113147256Sbrooks	ifp = adapter->ifp;
1114129794Stackerman
1115144651Salc	IXGB_LOCK(adapter);
1116129794Stackerman
1117129794Stackerman	ixgb_check_for_link(&adapter->hw);
1118129794Stackerman	ixgb_print_link_status(adapter);
1119129794Stackerman	ixgb_update_stats_counters(adapter);
1120148887Srwatson	if (ixgb_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) {
1121129794Stackerman		ixgb_print_hw_stats(adapter);
1122129794Stackerman	}
1123144651Salc	callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, adapter);
1124129794Stackerman
1125144651Salc	IXGB_UNLOCK(adapter);
1126129794Stackerman	return;
1127129794Stackerman}
1128129794Stackerman
1129129794Stackermanstatic void
1130129794Stackermanixgb_print_link_status(struct adapter * adapter)
1131129794Stackerman{
1132129794Stackerman	if (adapter->hw.link_up) {
1133129794Stackerman		if (!adapter->link_active) {
1134129794Stackerman			printf("ixgb%d: Link is up %d Mbps %s \n",
1135129794Stackerman			       adapter->unit,
1136129794Stackerman			       10000,
1137129794Stackerman			       "Full Duplex");
1138129794Stackerman			adapter->link_active = 1;
1139129794Stackerman		}
1140129794Stackerman	} else {
1141129794Stackerman		if (adapter->link_active) {
1142129794Stackerman			printf("ixgb%d: Link is Down \n", adapter->unit);
1143129794Stackerman			adapter->link_active = 0;
1144129794Stackerman		}
1145129794Stackerman	}
1146129794Stackerman
1147129794Stackerman	return;
1148129794Stackerman}
1149129794Stackerman
1150129794Stackerman
1151129794Stackerman
1152129794Stackerman/*********************************************************************
1153129794Stackerman *
1154129794Stackerman *  This routine disables all traffic on the adapter by issuing a
1155129794Stackerman *  global reset on the MAC and deallocates TX/RX buffers.
1156129794Stackerman *
1157129794Stackerman **********************************************************************/
1158129794Stackerman
1159129794Stackermanstatic void
1160129794Stackermanixgb_stop(void *arg)
1161129794Stackerman{
1162129794Stackerman	struct ifnet   *ifp;
1163129794Stackerman	struct adapter *adapter = arg;
1164147256Sbrooks	ifp = adapter->ifp;
1165129794Stackerman
1166144651Salc	IXGB_LOCK_ASSERT(adapter);
1167144651Salc
1168129794Stackerman	INIT_DEBUGOUT("ixgb_stop: begin\n");
1169129794Stackerman	ixgb_disable_intr(adapter);
1170129794Stackerman	adapter->hw.adapter_stopped = FALSE;
1171129794Stackerman	ixgb_adapter_stop(&adapter->hw);
1172144651Salc	callout_stop(&adapter->timer);
1173129794Stackerman	ixgb_free_transmit_structures(adapter);
1174129794Stackerman	ixgb_free_receive_structures(adapter);
1175129794Stackerman
1176129794Stackerman
1177129794Stackerman	/* Tell the stack that the interface is no longer active */
1178148887Srwatson	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1179129794Stackerman
1180129794Stackerman	return;
1181129794Stackerman}
1182129794Stackerman
1183129794Stackerman
1184129794Stackerman/*********************************************************************
1185129794Stackerman *
1186129794Stackerman *  Determine hardware revision.
1187129794Stackerman *
1188129794Stackerman **********************************************************************/
1189129794Stackermanstatic void
1190129794Stackermanixgb_identify_hardware(struct adapter * adapter)
1191129794Stackerman{
1192129794Stackerman	device_t        dev = adapter->dev;
1193129794Stackerman
1194129794Stackerman	/* Make sure our PCI config space has the necessary stuff set */
1195129794Stackerman	adapter->hw.pci_cmd_word = pci_read_config(dev, PCIR_COMMAND, 2);
1196129794Stackerman	if (!((adapter->hw.pci_cmd_word & PCIM_CMD_BUSMASTEREN) &&
1197129794Stackerman	      (adapter->hw.pci_cmd_word & PCIM_CMD_MEMEN))) {
1198129794Stackerman		printf("ixgb%d: Memory Access and/or Bus Master bits were not set!\n",
1199129794Stackerman		       adapter->unit);
1200129794Stackerman		adapter->hw.pci_cmd_word |=
1201129794Stackerman			(PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN);
1202129794Stackerman		pci_write_config(dev, PCIR_COMMAND, adapter->hw.pci_cmd_word, 2);
1203129794Stackerman	}
1204129794Stackerman	/* Save off the information about this board */
1205129794Stackerman	adapter->hw.vendor_id = pci_get_vendor(dev);
1206129794Stackerman	adapter->hw.device_id = pci_get_device(dev);
1207129794Stackerman	adapter->hw.revision_id = pci_read_config(dev, PCIR_REVID, 1);
1208129794Stackerman	adapter->hw.subsystem_vendor_id = pci_read_config(dev, PCIR_SUBVEND_0, 2);
1209129794Stackerman	adapter->hw.subsystem_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
1210129794Stackerman
1211129794Stackerman	/* Set MacType, etc. based on this PCI info */
1212129794Stackerman	switch (adapter->hw.device_id) {
1213129794Stackerman	case IXGB_DEVICE_ID_82597EX:
1214129794Stackerman	case IXGB_DEVICE_ID_82597EX_SR:
1215129794Stackerman		adapter->hw.mac_type = ixgb_82597;
1216129794Stackerman		break;
1217129794Stackerman	default:
1218129794Stackerman		INIT_DEBUGOUT1("Unknown device if 0x%x", adapter->hw.device_id);
1219129794Stackerman		printf("ixgb%d: unsupported device id 0x%x\n", adapter->unit, adapter->hw.device_id);
1220129794Stackerman	}
1221129794Stackerman
1222129794Stackerman	return;
1223129794Stackerman}
1224129794Stackerman
1225129794Stackermanstatic int
1226129794Stackermanixgb_allocate_pci_resources(struct adapter * adapter)
1227129794Stackerman{
1228129794Stackerman	int             rid;
1229129794Stackerman	device_t        dev = adapter->dev;
1230129794Stackerman
1231129794Stackerman	rid = IXGB_MMBA;
1232129794Stackerman	adapter->res_memory = bus_alloc_resource(dev, SYS_RES_MEMORY,
1233129794Stackerman						 &rid, 0, ~0, 1,
1234129794Stackerman						 RF_ACTIVE);
1235129794Stackerman	if (!(adapter->res_memory)) {
1236129794Stackerman		printf("ixgb%d: Unable to allocate bus resource: memory\n",
1237129794Stackerman		       adapter->unit);
1238129794Stackerman		return (ENXIO);
1239129794Stackerman	}
1240129794Stackerman	adapter->osdep.mem_bus_space_tag =
1241129794Stackerman		rman_get_bustag(adapter->res_memory);
1242129794Stackerman	adapter->osdep.mem_bus_space_handle =
1243129794Stackerman		rman_get_bushandle(adapter->res_memory);
1244129794Stackerman	adapter->hw.hw_addr = (uint8_t *) & adapter->osdep.mem_bus_space_handle;
1245129794Stackerman
1246129794Stackerman	rid = 0x0;
1247129794Stackerman	adapter->res_interrupt = bus_alloc_resource(dev, SYS_RES_IRQ,
1248129794Stackerman						    &rid, 0, ~0, 1,
1249129794Stackerman						  RF_SHAREABLE | RF_ACTIVE);
1250129794Stackerman	if (!(adapter->res_interrupt)) {
1251129794Stackerman		printf("ixgb%d: Unable to allocate bus resource: interrupt\n",
1252129794Stackerman		       adapter->unit);
1253129794Stackerman		return (ENXIO);
1254129794Stackerman	}
1255144651Salc	if (bus_setup_intr(dev, adapter->res_interrupt,
1256144651Salc			   INTR_TYPE_NET | INTR_MPSAFE,
1257129794Stackerman			   (void (*) (void *))ixgb_intr, adapter,
1258129794Stackerman			   &adapter->int_handler_tag)) {
1259129794Stackerman		printf("ixgb%d: Error registering interrupt handler!\n",
1260129794Stackerman		       adapter->unit);
1261129794Stackerman		return (ENXIO);
1262129794Stackerman	}
1263129794Stackerman	adapter->hw.back = &adapter->osdep;
1264129794Stackerman
1265129794Stackerman	return (0);
1266129794Stackerman}
1267129794Stackerman
1268129794Stackermanstatic void
1269129794Stackermanixgb_free_pci_resources(struct adapter * adapter)
1270129794Stackerman{
1271129794Stackerman	device_t        dev = adapter->dev;
1272129794Stackerman
1273129794Stackerman	if (adapter->res_interrupt != NULL) {
1274129794Stackerman		bus_teardown_intr(dev, adapter->res_interrupt,
1275129794Stackerman				  adapter->int_handler_tag);
1276129794Stackerman		bus_release_resource(dev, SYS_RES_IRQ, 0,
1277129794Stackerman				     adapter->res_interrupt);
1278129794Stackerman	}
1279129794Stackerman	if (adapter->res_memory != NULL) {
1280129794Stackerman		bus_release_resource(dev, SYS_RES_MEMORY, IXGB_MMBA,
1281129794Stackerman				     adapter->res_memory);
1282129794Stackerman	}
1283129794Stackerman	if (adapter->res_ioport != NULL) {
1284129794Stackerman		bus_release_resource(dev, SYS_RES_IOPORT, adapter->io_rid,
1285129794Stackerman				     adapter->res_ioport);
1286129794Stackerman	}
1287129794Stackerman	return;
1288129794Stackerman}
1289129794Stackerman
1290129794Stackerman/*********************************************************************
1291129794Stackerman *
1292129794Stackerman *  Initialize the hardware to a configuration as specified by the
1293129794Stackerman *  adapter structure. The controller is reset, the EEPROM is
1294129794Stackerman *  verified, the MAC address is set, then the shared initialization
1295129794Stackerman *  routines are called.
1296129794Stackerman *
1297129794Stackerman **********************************************************************/
1298129794Stackermanstatic int
1299129794Stackermanixgb_hardware_init(struct adapter * adapter)
1300129794Stackerman{
1301129794Stackerman	/* Issue a global reset */
1302129794Stackerman	adapter->hw.adapter_stopped = FALSE;
1303129794Stackerman	ixgb_adapter_stop(&adapter->hw);
1304129794Stackerman
1305129794Stackerman	/* Make sure we have a good EEPROM before we read from it */
1306129794Stackerman	if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
1307129794Stackerman		printf("ixgb%d: The EEPROM Checksum Is Not Valid\n",
1308129794Stackerman		       adapter->unit);
1309129794Stackerman		return (EIO);
1310129794Stackerman	}
1311129794Stackerman	if (!ixgb_init_hw(&adapter->hw)) {
1312129794Stackerman		printf("ixgb%d: Hardware Initialization Failed",
1313129794Stackerman		       adapter->unit);
1314129794Stackerman		return (EIO);
1315129794Stackerman	}
1316129794Stackerman
1317129794Stackerman	return (0);
1318129794Stackerman}
1319129794Stackerman
1320129794Stackerman/*********************************************************************
1321129794Stackerman *
1322129794Stackerman *  Setup networking device structure and register an interface.
1323129794Stackerman *
1324129794Stackerman **********************************************************************/
1325129794Stackermanstatic void
1326129794Stackermanixgb_setup_interface(device_t dev, struct adapter * adapter)
1327129794Stackerman{
1328129794Stackerman	struct ifnet   *ifp;
1329129794Stackerman	INIT_DEBUGOUT("ixgb_setup_interface: begin");
1330129794Stackerman
1331147256Sbrooks	ifp = adapter->ifp = if_alloc(IFT_ETHER);
1332147256Sbrooks	if (ifp == NULL)
1333147256Sbrooks		panic("%s: can not if_alloc()\n", device_get_nameunit(dev));
1334129794Stackerman#if __FreeBSD_version >= 502000
1335129794Stackerman	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1336129794Stackerman#else
1337129794Stackerman	ifp->if_unit = adapter->unit;
1338129794Stackerman	ifp->if_name = "ixgb";
1339129794Stackerman#endif
1340129794Stackerman	ifp->if_mtu = ETHERMTU;
1341129794Stackerman	ifp->if_baudrate = 1000000000;
1342129794Stackerman	ifp->if_init = ixgb_init;
1343129794Stackerman	ifp->if_softc = adapter;
1344144651Salc	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1345129794Stackerman	ifp->if_ioctl = ixgb_ioctl;
1346129794Stackerman	ifp->if_start = ixgb_start;
1347129794Stackerman	ifp->if_watchdog = ixgb_watchdog;
1348129794Stackerman	ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 1;
1349129794Stackerman
1350129794Stackerman#if __FreeBSD_version < 500000
1351129794Stackerman	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
1352129794Stackerman#else
1353147256Sbrooks	ether_ifattach(ifp, adapter->hw.curr_mac_addr);
1354129794Stackerman#endif
1355129794Stackerman
1356129794Stackerman	ifp->if_capabilities = IFCAP_HWCSUM;
1357148637Sbrueffer#ifdef DEVICE_POLLING
1358148637Sbrueffer	ifp->if_capabilities |= IFCAP_POLLING;
1359148637Sbrueffer#endif
1360129794Stackerman
1361129794Stackerman	/*
1362129794Stackerman	 * Tell the upper layer(s) we support long frames.
1363129794Stackerman	 */
1364129794Stackerman	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
1365129794Stackerman
1366129794Stackerman#if __FreeBSD_version >= 500000
1367129794Stackerman	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
1368129794Stackerman#endif
1369148637Sbrueffer
1370148637Sbrueffer	ifp->if_capenable = ifp->if_capabilities;
1371148637Sbrueffer
1372129794Stackerman	/*
1373129794Stackerman	 * Specify the media types supported by this adapter and register
1374129794Stackerman	 * callbacks to update media and link information
1375129794Stackerman	 */
1376129794Stackerman	ifmedia_init(&adapter->media, IFM_IMASK, ixgb_media_change,
1377129794Stackerman		     ixgb_media_status);
1378129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX | IFM_FDX,
1379129794Stackerman		    0, NULL);
1380129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX,
1381129794Stackerman		    0, NULL);
1382129794Stackerman	ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
1383129794Stackerman	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
1384129794Stackerman
1385129794Stackerman	return;
1386129794Stackerman}
1387129794Stackerman
1388129794Stackerman/********************************************************************
1389129794Stackerman * Manage DMA'able memory.
1390129794Stackerman *******************************************************************/
1391129794Stackermanstatic void
1392129794Stackermanixgb_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nseg, int error)
1393129794Stackerman{
1394129794Stackerman	if (error)
1395129794Stackerman		return;
1396129794Stackerman	*(bus_addr_t *) arg = segs->ds_addr;
1397129794Stackerman	return;
1398129794Stackerman}
1399129794Stackerman
1400129794Stackermanstatic int
1401129794Stackermanixgb_dma_malloc(struct adapter * adapter, bus_size_t size,
1402129794Stackerman		struct ixgb_dma_alloc * dma, int mapflags)
1403129794Stackerman{
1404129794Stackerman	int             r;
1405129794Stackerman
1406129794Stackerman	r = bus_dma_tag_create(NULL,	/* parent */
1407129794Stackerman			       PAGE_SIZE, 0,	/* alignment, bounds */
1408129794Stackerman			       BUS_SPACE_MAXADDR,	/* lowaddr */
1409129794Stackerman			       BUS_SPACE_MAXADDR,	/* highaddr */
1410129794Stackerman			       NULL, NULL,	/* filter, filterarg */
1411129794Stackerman			       size,	/* maxsize */
1412129794Stackerman			       1,	/* nsegments */
1413129794Stackerman			       size,	/* maxsegsize */
1414129794Stackerman			       BUS_DMA_ALLOCNOW,	/* flags */
1415129794Stackerman#if __FreeBSD_version >= 502000
1416129794Stackerman			       NULL,	/* lockfunc */
1417129794Stackerman			       NULL,	/* lockfuncarg */
1418129794Stackerman#endif
1419129794Stackerman			       &dma->dma_tag);
1420129794Stackerman	if (r != 0) {
1421129794Stackerman		printf("ixgb%d: ixgb_dma_malloc: bus_dma_tag_create failed; "
1422129794Stackerman		       "error %u\n", adapter->unit, r);
1423129794Stackerman		goto fail_0;
1424129794Stackerman	}
1425129794Stackerman	r = bus_dmamem_alloc(dma->dma_tag, (void **)&dma->dma_vaddr,
1426129794Stackerman			     BUS_DMA_NOWAIT, &dma->dma_map);
1427129794Stackerman	if (r != 0) {
1428129794Stackerman		printf("ixgb%d: ixgb_dma_malloc: bus_dmamem_alloc failed; "
1429129794Stackerman		       "error %u\n", adapter->unit, r);
1430144183Smux		goto fail_1;
1431129794Stackerman	}
1432129794Stackerman	r = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
1433129794Stackerman			    size,
1434129794Stackerman			    ixgb_dmamap_cb,
1435129794Stackerman			    &dma->dma_paddr,
1436129794Stackerman			    mapflags | BUS_DMA_NOWAIT);
1437129794Stackerman	if (r != 0) {
1438129794Stackerman		printf("ixgb%d: ixgb_dma_malloc: bus_dmamap_load failed; "
1439129794Stackerman		       "error %u\n", adapter->unit, r);
1440144183Smux		goto fail_2;
1441129794Stackerman	}
1442129794Stackerman	dma->dma_size = size;
1443129794Stackerman	return (0);
1444129794Stackermanfail_2:
1445129794Stackerman	bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
1446129794Stackermanfail_1:
1447129794Stackerman	bus_dma_tag_destroy(dma->dma_tag);
1448129794Stackermanfail_0:
1449129794Stackerman	dma->dma_map = NULL;
1450129794Stackerman	dma->dma_tag = NULL;
1451129794Stackerman	return (r);
1452129794Stackerman}
1453129794Stackerman
1454129794Stackerman
1455129794Stackerman
1456129794Stackermanstatic void
1457129794Stackermanixgb_dma_free(struct adapter * adapter, struct ixgb_dma_alloc * dma)
1458129794Stackerman{
1459129794Stackerman	bus_dmamap_unload(dma->dma_tag, dma->dma_map);
1460129794Stackerman	bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
1461129794Stackerman	bus_dma_tag_destroy(dma->dma_tag);
1462129794Stackerman}
1463129794Stackerman
1464129794Stackerman/*********************************************************************
1465129794Stackerman *
1466129794Stackerman *  Allocate memory for tx_buffer structures. The tx_buffer stores all
1467129794Stackerman *  the information needed to transmit a packet on the wire.
1468129794Stackerman *
1469129794Stackerman **********************************************************************/
1470129794Stackermanstatic int
1471129794Stackermanixgb_allocate_transmit_structures(struct adapter * adapter)
1472129794Stackerman{
1473129794Stackerman	if (!(adapter->tx_buffer_area =
1474129794Stackerman	      (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) *
1475129794Stackerman					    adapter->num_tx_desc, M_DEVBUF,
1476129794Stackerman					    M_NOWAIT | M_ZERO))) {
1477129794Stackerman		printf("ixgb%d: Unable to allocate tx_buffer memory\n",
1478129794Stackerman		       adapter->unit);
1479129794Stackerman		return ENOMEM;
1480129794Stackerman	}
1481129794Stackerman	bzero(adapter->tx_buffer_area,
1482129794Stackerman	      sizeof(struct ixgb_buffer) * adapter->num_tx_desc);
1483129794Stackerman
1484129794Stackerman	return 0;
1485129794Stackerman}
1486129794Stackerman
1487129794Stackerman/*********************************************************************
1488129794Stackerman *
1489129794Stackerman *  Allocate and initialize transmit structures.
1490129794Stackerman *
1491129794Stackerman **********************************************************************/
1492129794Stackermanstatic int
1493129794Stackermanixgb_setup_transmit_structures(struct adapter * adapter)
1494129794Stackerman{
1495129794Stackerman	/*
1496129794Stackerman	 * Setup DMA descriptor areas.
1497129794Stackerman	 */
1498129794Stackerman	if (bus_dma_tag_create(NULL,	/* parent */
1499129794Stackerman			       PAGE_SIZE, 0,	/* alignment, bounds */
1500129794Stackerman			       BUS_SPACE_MAXADDR,	/* lowaddr */
1501129794Stackerman			       BUS_SPACE_MAXADDR,	/* highaddr */
1502129794Stackerman			       NULL, NULL,	/* filter, filterarg */
1503129794Stackerman			       MCLBYTES * IXGB_MAX_SCATTER,	/* maxsize */
1504129794Stackerman			       IXGB_MAX_SCATTER,	/* nsegments */
1505129794Stackerman			       MCLBYTES,	/* maxsegsize */
1506129794Stackerman			       BUS_DMA_ALLOCNOW,	/* flags */
1507129794Stackerman#if __FreeBSD_version >= 502000
1508129794Stackerman			       NULL,	/* lockfunc */
1509129794Stackerman			       NULL,	/* lockfuncarg */
1510129794Stackerman#endif
1511129794Stackerman			       &adapter->txtag)) {
1512129794Stackerman		printf("ixgb%d: Unable to allocate TX DMA tag\n", adapter->unit);
1513129794Stackerman		return (ENOMEM);
1514129794Stackerman	}
1515129794Stackerman	if (ixgb_allocate_transmit_structures(adapter))
1516129794Stackerman		return ENOMEM;
1517129794Stackerman
1518129794Stackerman	bzero((void *)adapter->tx_desc_base,
1519129794Stackerman	      (sizeof(struct ixgb_tx_desc)) * adapter->num_tx_desc);
1520129794Stackerman
1521129794Stackerman	adapter->next_avail_tx_desc = 0;
1522129794Stackerman	adapter->oldest_used_tx_desc = 0;
1523129794Stackerman
1524129794Stackerman	/* Set number of descriptors available */
1525129794Stackerman	adapter->num_tx_desc_avail = adapter->num_tx_desc;
1526129794Stackerman
1527129794Stackerman	/* Set checksum context */
1528129794Stackerman	adapter->active_checksum_context = OFFLOAD_NONE;
1529129794Stackerman
1530129794Stackerman	return 0;
1531129794Stackerman}
1532129794Stackerman
1533129794Stackerman/*********************************************************************
1534129794Stackerman *
1535129794Stackerman *  Enable transmit unit.
1536129794Stackerman *
1537129794Stackerman **********************************************************************/
1538129794Stackermanstatic void
1539129794Stackermanixgb_initialize_transmit_unit(struct adapter * adapter)
1540129794Stackerman{
1541129794Stackerman	u_int32_t       reg_tctl;
1542144183Smux	u_int64_t       tdba = adapter->txdma.dma_paddr;
1543129794Stackerman
1544129794Stackerman	/* Setup the Base and Length of the Tx Descriptor Ring */
1545129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDBAL,
1546129794Stackerman		       (tdba & 0x00000000ffffffffULL));
1547129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
1548129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDLEN,
1549129794Stackerman		       adapter->num_tx_desc *
1550129794Stackerman		       sizeof(struct ixgb_tx_desc));
1551129794Stackerman
1552129794Stackerman	/* Setup the HW Tx Head and Tail descriptor pointers */
1553129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDH, 0);
1554129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TDT, 0);
1555129794Stackerman
1556129794Stackerman
1557129794Stackerman	HW_DEBUGOUT2("Base = %x, Length = %x\n",
1558129794Stackerman		     IXGB_READ_REG(&adapter->hw, TDBAL),
1559129794Stackerman		     IXGB_READ_REG(&adapter->hw, TDLEN));
1560129794Stackerman
1561129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TIDV, adapter->tx_int_delay);
1562129794Stackerman
1563129794Stackerman
1564129794Stackerman	/* Program the Transmit Control Register */
1565129794Stackerman	reg_tctl = IXGB_READ_REG(&adapter->hw, TCTL);
1566129794Stackerman	reg_tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE;
1567129794Stackerman	IXGB_WRITE_REG(&adapter->hw, TCTL, reg_tctl);
1568129794Stackerman
1569129794Stackerman	/* Setup Transmit Descriptor Settings for this adapter */
1570129794Stackerman	adapter->txd_cmd = IXGB_TX_DESC_TYPE | IXGB_TX_DESC_CMD_RS;
1571129794Stackerman
1572129794Stackerman	if (adapter->tx_int_delay > 0)
1573129794Stackerman		adapter->txd_cmd |= IXGB_TX_DESC_CMD_IDE;
1574129794Stackerman	return;
1575129794Stackerman}
1576129794Stackerman
1577129794Stackerman/*********************************************************************
1578129794Stackerman *
1579129794Stackerman *  Free all transmit related data structures.
1580129794Stackerman *
1581129794Stackerman **********************************************************************/
1582129794Stackermanstatic void
1583129794Stackermanixgb_free_transmit_structures(struct adapter * adapter)
1584129794Stackerman{
1585129794Stackerman	struct ixgb_buffer *tx_buffer;
1586129794Stackerman	int             i;
1587129794Stackerman
1588129794Stackerman	INIT_DEBUGOUT("free_transmit_structures: begin");
1589129794Stackerman
1590129794Stackerman	if (adapter->tx_buffer_area != NULL) {
1591129794Stackerman		tx_buffer = adapter->tx_buffer_area;
1592129794Stackerman		for (i = 0; i < adapter->num_tx_desc; i++, tx_buffer++) {
1593129794Stackerman			if (tx_buffer->m_head != NULL) {
1594129794Stackerman				bus_dmamap_unload(adapter->txtag, tx_buffer->map);
1595129794Stackerman				bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
1596129794Stackerman				m_freem(tx_buffer->m_head);
1597129794Stackerman			}
1598129794Stackerman			tx_buffer->m_head = NULL;
1599129794Stackerman		}
1600129794Stackerman	}
1601129794Stackerman	if (adapter->tx_buffer_area != NULL) {
1602129794Stackerman		free(adapter->tx_buffer_area, M_DEVBUF);
1603129794Stackerman		adapter->tx_buffer_area = NULL;
1604129794Stackerman	}
1605129794Stackerman	if (adapter->txtag != NULL) {
1606129794Stackerman		bus_dma_tag_destroy(adapter->txtag);
1607129794Stackerman		adapter->txtag = NULL;
1608129794Stackerman	}
1609129794Stackerman	return;
1610129794Stackerman}
1611129794Stackerman
1612129794Stackerman/*********************************************************************
1613129794Stackerman *
1614129794Stackerman *  The offload context needs to be set when we transfer the first
1615129794Stackerman *  packet of a particular protocol (TCP/UDP). We change the
1616129794Stackerman *  context only if the protocol type changes.
1617129794Stackerman *
1618129794Stackerman **********************************************************************/
1619129794Stackermanstatic void
1620129794Stackermanixgb_transmit_checksum_setup(struct adapter * adapter,
1621129794Stackerman			     struct mbuf * mp,
1622129794Stackerman			     u_int8_t * txd_popts)
1623129794Stackerman{
1624129794Stackerman	struct ixgb_context_desc *TXD;
1625129794Stackerman	struct ixgb_buffer *tx_buffer;
1626129794Stackerman	int             curr_txd;
1627129794Stackerman
1628129794Stackerman	if (mp->m_pkthdr.csum_flags) {
1629129794Stackerman
1630129794Stackerman		if (mp->m_pkthdr.csum_flags & CSUM_TCP) {
1631129794Stackerman			*txd_popts = IXGB_TX_DESC_POPTS_TXSM;
1632129794Stackerman			if (adapter->active_checksum_context == OFFLOAD_TCP_IP)
1633129794Stackerman				return;
1634129794Stackerman			else
1635129794Stackerman				adapter->active_checksum_context = OFFLOAD_TCP_IP;
1636129794Stackerman		} else if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
1637129794Stackerman			*txd_popts = IXGB_TX_DESC_POPTS_TXSM;
1638129794Stackerman			if (adapter->active_checksum_context == OFFLOAD_UDP_IP)
1639129794Stackerman				return;
1640129794Stackerman			else
1641129794Stackerman				adapter->active_checksum_context = OFFLOAD_UDP_IP;
1642129794Stackerman		} else {
1643129794Stackerman			*txd_popts = 0;
1644129794Stackerman			return;
1645129794Stackerman		}
1646129794Stackerman	} else {
1647129794Stackerman		*txd_popts = 0;
1648129794Stackerman		return;
1649129794Stackerman	}
1650129794Stackerman
1651129794Stackerman	/*
1652129794Stackerman	 * If we reach this point, the checksum offload context needs to be
1653129794Stackerman	 * reset.
1654129794Stackerman	 */
1655129794Stackerman	curr_txd = adapter->next_avail_tx_desc;
1656129794Stackerman	tx_buffer = &adapter->tx_buffer_area[curr_txd];
1657129794Stackerman	TXD = (struct ixgb_context_desc *) & adapter->tx_desc_base[curr_txd];
1658129794Stackerman
1659129794Stackerman
1660129794Stackerman	TXD->tucss = ENET_HEADER_SIZE + sizeof(struct ip);
1661129794Stackerman	TXD->tucse = 0;
1662129794Stackerman
1663129794Stackerman	TXD->mss = 0;
1664129794Stackerman
1665129794Stackerman	if (adapter->active_checksum_context == OFFLOAD_TCP_IP) {
1666129794Stackerman		TXD->tucso =
1667129794Stackerman			ENET_HEADER_SIZE + sizeof(struct ip) +
1668129794Stackerman			offsetof(struct tcphdr, th_sum);
1669129794Stackerman	} else if (adapter->active_checksum_context == OFFLOAD_UDP_IP) {
1670129794Stackerman		TXD->tucso =
1671129794Stackerman			ENET_HEADER_SIZE + sizeof(struct ip) +
1672129794Stackerman			offsetof(struct udphdr, uh_sum);
1673129794Stackerman	}
1674129794Stackerman	TXD->cmd_type_len = IXGB_CONTEXT_DESC_CMD_TCP | IXGB_TX_DESC_CMD_RS | IXGB_CONTEXT_DESC_CMD_IDE;
1675129794Stackerman
1676129794Stackerman	tx_buffer->m_head = NULL;
1677129794Stackerman
1678129794Stackerman	if (++curr_txd == adapter->num_tx_desc)
1679129794Stackerman		curr_txd = 0;
1680129794Stackerman
1681129794Stackerman	adapter->num_tx_desc_avail--;
1682129794Stackerman	adapter->next_avail_tx_desc = curr_txd;
1683129794Stackerman	return;
1684129794Stackerman}
1685129794Stackerman
1686129794Stackerman/**********************************************************************
1687129794Stackerman *
1688129794Stackerman *  Examine each tx_buffer in the used queue. If the hardware is done
1689129794Stackerman *  processing the packet then free associated resources. The
1690129794Stackerman *  tx_buffer is put back on the free queue.
1691129794Stackerman *
1692129794Stackerman **********************************************************************/
1693129794Stackermanstatic void
1694129794Stackermanixgb_clean_transmit_interrupts(struct adapter * adapter)
1695129794Stackerman{
1696129794Stackerman	int             i, num_avail;
1697129794Stackerman	struct ixgb_buffer *tx_buffer;
1698129794Stackerman	struct ixgb_tx_desc *tx_desc;
1699129794Stackerman
1700144651Salc	IXGB_LOCK_ASSERT(adapter);
1701129794Stackerman
1702129794Stackerman	if (adapter->num_tx_desc_avail == adapter->num_tx_desc)
1703129794Stackerman		return;
1704129794Stackerman
1705129794Stackerman#ifdef _SV_
1706129794Stackerman	adapter->clean_tx_interrupts++;
1707129794Stackerman#endif
1708129794Stackerman	num_avail = adapter->num_tx_desc_avail;
1709129794Stackerman	i = adapter->oldest_used_tx_desc;
1710129794Stackerman
1711129794Stackerman	tx_buffer = &adapter->tx_buffer_area[i];
1712129794Stackerman	tx_desc = &adapter->tx_desc_base[i];
1713129794Stackerman
1714129794Stackerman	while (tx_desc->status & IXGB_TX_DESC_STATUS_DD) {
1715129794Stackerman
1716129794Stackerman		tx_desc->status = 0;
1717129794Stackerman		num_avail++;
1718129794Stackerman
1719129794Stackerman		if (tx_buffer->m_head) {
1720129794Stackerman			bus_dmamap_sync(adapter->txtag, tx_buffer->map,
1721129794Stackerman					BUS_DMASYNC_POSTWRITE);
1722129794Stackerman			bus_dmamap_unload(adapter->txtag, tx_buffer->map);
1723129794Stackerman			bus_dmamap_destroy(adapter->txtag, tx_buffer->map);
1724129794Stackerman			m_freem(tx_buffer->m_head);
1725129794Stackerman			tx_buffer->m_head = NULL;
1726129794Stackerman		}
1727129794Stackerman		if (++i == adapter->num_tx_desc)
1728129794Stackerman			i = 0;
1729129794Stackerman
1730129794Stackerman		tx_buffer = &adapter->tx_buffer_area[i];
1731129794Stackerman		tx_desc = &adapter->tx_desc_base[i];
1732129794Stackerman	}
1733129794Stackerman
1734129794Stackerman	adapter->oldest_used_tx_desc = i;
1735129794Stackerman
1736129794Stackerman	/*
1737148887Srwatson	 * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that
1738129794Stackerman	 * it is OK to send packets. If there are no pending descriptors,
1739129794Stackerman	 * clear the timeout. Otherwise, if some descriptors have been freed,
1740129794Stackerman	 * restart the timeout.
1741129794Stackerman	 */
1742129794Stackerman	if (num_avail > IXGB_TX_CLEANUP_THRESHOLD) {
1743147256Sbrooks		struct ifnet   *ifp = adapter->ifp;
1744129794Stackerman
1745148887Srwatson		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1746129794Stackerman		if (num_avail == adapter->num_tx_desc)
1747129794Stackerman			ifp->if_timer = 0;
1748129794Stackerman		else if (num_avail == adapter->num_tx_desc_avail)
1749129794Stackerman			ifp->if_timer = IXGB_TX_TIMEOUT;
1750129794Stackerman	}
1751129794Stackerman	adapter->num_tx_desc_avail = num_avail;
1752129794Stackerman	return;
1753129794Stackerman}
1754129794Stackerman
1755129794Stackerman
1756129794Stackerman/*********************************************************************
1757129794Stackerman *
1758129794Stackerman *  Get a buffer from system mbuf buffer pool.
1759129794Stackerman *
1760129794Stackerman **********************************************************************/
1761129794Stackermanstatic int
1762129794Stackermanixgb_get_buf(int i, struct adapter * adapter,
1763129794Stackerman	     struct mbuf * nmp)
1764129794Stackerman{
1765129794Stackerman	register struct mbuf *mp = nmp;
1766129794Stackerman	struct ixgb_buffer *rx_buffer;
1767129794Stackerman	struct ifnet   *ifp;
1768129794Stackerman	bus_addr_t      paddr;
1769129794Stackerman	int             error;
1770129794Stackerman
1771147256Sbrooks	ifp = adapter->ifp;
1772129794Stackerman
1773129794Stackerman	if (mp == NULL) {
1774129794Stackerman
1775129794Stackerman		mp = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1776129794Stackerman
1777129794Stackerman		if (mp == NULL) {
1778129794Stackerman			adapter->mbuf_alloc_failed++;
1779129794Stackerman			return (ENOBUFS);
1780129794Stackerman		}
1781129794Stackerman		mp->m_len = mp->m_pkthdr.len = MCLBYTES;
1782129794Stackerman	} else {
1783129794Stackerman		mp->m_len = mp->m_pkthdr.len = MCLBYTES;
1784129794Stackerman		mp->m_data = mp->m_ext.ext_buf;
1785129794Stackerman		mp->m_next = NULL;
1786129794Stackerman	}
1787129794Stackerman
1788129794Stackerman	if (ifp->if_mtu <= ETHERMTU) {
1789129794Stackerman		m_adj(mp, ETHER_ALIGN);
1790129794Stackerman	}
1791129794Stackerman	rx_buffer = &adapter->rx_buffer_area[i];
1792129794Stackerman
1793129794Stackerman	/*
1794129794Stackerman	 * Using memory from the mbuf cluster pool, invoke the bus_dma
1795129794Stackerman	 * machinery to arrange the memory mapping.
1796129794Stackerman	 */
1797129794Stackerman	error = bus_dmamap_load(adapter->rxtag, rx_buffer->map,
1798129794Stackerman				mtod(mp, void *), mp->m_len,
1799129794Stackerman				ixgb_dmamap_cb, &paddr, 0);
1800129794Stackerman	if (error) {
1801129794Stackerman		m_free(mp);
1802129794Stackerman		return (error);
1803129794Stackerman	}
1804129794Stackerman	rx_buffer->m_head = mp;
1805129794Stackerman	adapter->rx_desc_base[i].buff_addr = htole64(paddr);
1806129794Stackerman	bus_dmamap_sync(adapter->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD);
1807129794Stackerman
1808129794Stackerman	return (0);
1809129794Stackerman}
1810129794Stackerman
1811129794Stackerman/*********************************************************************
1812129794Stackerman *
1813129794Stackerman *  Allocate memory for rx_buffer structures. Since we use one
1814129794Stackerman *  rx_buffer per received packet, the maximum number of rx_buffer's
1815129794Stackerman *  that we'll need is equal to the number of receive descriptors
1816129794Stackerman *  that we've allocated.
1817129794Stackerman *
1818129794Stackerman **********************************************************************/
1819129794Stackermanstatic int
1820129794Stackermanixgb_allocate_receive_structures(struct adapter * adapter)
1821129794Stackerman{
1822129794Stackerman	int             i, error;
1823129794Stackerman	struct ixgb_buffer *rx_buffer;
1824129794Stackerman
1825129794Stackerman	if (!(adapter->rx_buffer_area =
1826129794Stackerman	      (struct ixgb_buffer *) malloc(sizeof(struct ixgb_buffer) *
1827129794Stackerman					    adapter->num_rx_desc, M_DEVBUF,
1828129794Stackerman					    M_NOWAIT | M_ZERO))) {
1829129794Stackerman		printf("ixgb%d: Unable to allocate rx_buffer memory\n",
1830129794Stackerman		       adapter->unit);
1831129794Stackerman		return (ENOMEM);
1832129794Stackerman	}
1833129794Stackerman	bzero(adapter->rx_buffer_area,
1834129794Stackerman	      sizeof(struct ixgb_buffer) * adapter->num_rx_desc);
1835129794Stackerman
1836129794Stackerman	error = bus_dma_tag_create(NULL,	/* parent */
1837129794Stackerman				   PAGE_SIZE, 0,	/* alignment, bounds */
1838129794Stackerman				   BUS_SPACE_MAXADDR,	/* lowaddr */
1839129794Stackerman				   BUS_SPACE_MAXADDR,	/* highaddr */
1840129794Stackerman				   NULL, NULL,	/* filter, filterarg */
1841129794Stackerman				   MCLBYTES,	/* maxsize */
1842129794Stackerman				   1,	/* nsegments */
1843129794Stackerman				   MCLBYTES,	/* maxsegsize */
1844129794Stackerman				   BUS_DMA_ALLOCNOW,	/* flags */
1845129794Stackerman#if __FreeBSD_version >= 502000
1846129794Stackerman				   NULL,	/* lockfunc */
1847129794Stackerman				   NULL,	/* lockfuncarg */
1848129794Stackerman#endif
1849129794Stackerman				   &adapter->rxtag);
1850129794Stackerman	if (error != 0) {
1851129794Stackerman		printf("ixgb%d: ixgb_allocate_receive_structures: "
1852129794Stackerman		       "bus_dma_tag_create failed; error %u\n",
1853129794Stackerman		       adapter->unit, error);
1854129794Stackerman		goto fail_0;
1855129794Stackerman	}
1856129794Stackerman	rx_buffer = adapter->rx_buffer_area;
1857129794Stackerman	for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
1858129794Stackerman		error = bus_dmamap_create(adapter->rxtag, BUS_DMA_NOWAIT,
1859129794Stackerman					  &rx_buffer->map);
1860129794Stackerman		if (error != 0) {
1861129794Stackerman			printf("ixgb%d: ixgb_allocate_receive_structures: "
1862129794Stackerman			       "bus_dmamap_create failed; error %u\n",
1863129794Stackerman			       adapter->unit, error);
1864129794Stackerman			goto fail_1;
1865129794Stackerman		}
1866129794Stackerman	}
1867129794Stackerman
1868129794Stackerman	for (i = 0; i < adapter->num_rx_desc; i++) {
1869129794Stackerman		if (ixgb_get_buf(i, adapter, NULL) == ENOBUFS) {
1870129794Stackerman			adapter->rx_buffer_area[i].m_head = NULL;
1871129794Stackerman			adapter->rx_desc_base[i].buff_addr = 0;
1872129794Stackerman			return (ENOBUFS);
1873129794Stackerman		}
1874129794Stackerman	}
1875129794Stackerman
1876129794Stackerman	return (0);
1877129794Stackermanfail_1:
1878129794Stackerman	bus_dma_tag_destroy(adapter->rxtag);
1879129794Stackermanfail_0:
1880129794Stackerman	adapter->rxtag = NULL;
1881129794Stackerman	free(adapter->rx_buffer_area, M_DEVBUF);
1882129794Stackerman	adapter->rx_buffer_area = NULL;
1883129794Stackerman	return (error);
1884129794Stackerman}
1885129794Stackerman
1886129794Stackerman/*********************************************************************
1887129794Stackerman *
1888129794Stackerman *  Allocate and initialize receive structures.
1889129794Stackerman *
1890129794Stackerman **********************************************************************/
1891129794Stackermanstatic int
1892129794Stackermanixgb_setup_receive_structures(struct adapter * adapter)
1893129794Stackerman{
1894129794Stackerman	bzero((void *)adapter->rx_desc_base,
1895129794Stackerman	      (sizeof(struct ixgb_rx_desc)) * adapter->num_rx_desc);
1896129794Stackerman
1897129794Stackerman	if (ixgb_allocate_receive_structures(adapter))
1898129794Stackerman		return ENOMEM;
1899129794Stackerman
1900129794Stackerman	/* Setup our descriptor pointers */
1901129794Stackerman	adapter->next_rx_desc_to_check = 0;
1902129794Stackerman	adapter->next_rx_desc_to_use = 0;
1903129794Stackerman	return (0);
1904129794Stackerman}
1905129794Stackerman
1906129794Stackerman/*********************************************************************
1907129794Stackerman *
1908129794Stackerman *  Enable receive unit.
1909129794Stackerman *
1910129794Stackerman **********************************************************************/
1911129794Stackermanstatic void
1912129794Stackermanixgb_initialize_receive_unit(struct adapter * adapter)
1913129794Stackerman{
1914129794Stackerman	u_int32_t       reg_rctl;
1915129794Stackerman	u_int32_t       reg_rxcsum;
1916129794Stackerman	u_int32_t       reg_rxdctl;
1917129794Stackerman	struct ifnet   *ifp;
1918144183Smux	u_int64_t       rdba = adapter->rxdma.dma_paddr;
1919129794Stackerman
1920147256Sbrooks	ifp = adapter->ifp;
1921129794Stackerman
1922129794Stackerman	/*
1923129794Stackerman	 * Make sure receives are disabled while setting up the descriptor
1924129794Stackerman	 * ring
1925129794Stackerman	 */
1926129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1927129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl & ~IXGB_RCTL_RXEN);
1928129794Stackerman
1929129794Stackerman	/* Set the Receive Delay Timer Register */
1930129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDTR,
1931129794Stackerman		       adapter->rx_int_delay);
1932129794Stackerman
1933129794Stackerman
1934129794Stackerman	/* Setup the Base and Length of the Rx Descriptor Ring */
1935129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDBAL,
1936129794Stackerman		       (rdba & 0x00000000ffffffffULL));
1937129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
1938129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDLEN, adapter->num_rx_desc *
1939129794Stackerman		       sizeof(struct ixgb_rx_desc));
1940129794Stackerman
1941129794Stackerman	/* Setup the HW Rx Head and Tail Descriptor Pointers */
1942129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDH, 0);
1943129794Stackerman
1944129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDT, adapter->num_rx_desc - 1);
1945129794Stackerman
1946129794Stackerman
1947129794Stackerman
1948129794Stackerman	reg_rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
1949129794Stackerman		| RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
1950129794Stackerman		| RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
1951129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RXDCTL, reg_rxdctl);
1952129794Stackerman
1953129794Stackerman
1954129794Stackerman	adapter->raidc = 1;
1955129794Stackerman	if (adapter->raidc) {
1956129794Stackerman		uint32_t        raidc;
1957129794Stackerman		uint8_t         poll_threshold;
1958129794Stackerman#define IXGB_RAIDC_POLL_DEFAULT 120
1959129794Stackerman
1960129794Stackerman		poll_threshold = ((adapter->num_rx_desc - 1) >> 3);
1961129794Stackerman		poll_threshold >>= 1;
1962129794Stackerman		poll_threshold &= 0x3F;
1963129794Stackerman		raidc = IXGB_RAIDC_EN | IXGB_RAIDC_RXT_GATE |
1964129794Stackerman			(IXGB_RAIDC_POLL_DEFAULT << IXGB_RAIDC_POLL_SHIFT) |
1965129794Stackerman			(adapter->rx_int_delay << IXGB_RAIDC_DELAY_SHIFT) |
1966129794Stackerman			poll_threshold;
1967129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RAIDC, raidc);
1968129794Stackerman	}
1969129794Stackerman	/* Enable Receive Checksum Offload for TCP and UDP ? */
1970129794Stackerman	if (ifp->if_capenable & IFCAP_RXCSUM) {
1971129794Stackerman		reg_rxcsum = IXGB_READ_REG(&adapter->hw, RXCSUM);
1972129794Stackerman		reg_rxcsum |= IXGB_RXCSUM_TUOFL;
1973129794Stackerman		IXGB_WRITE_REG(&adapter->hw, RXCSUM, reg_rxcsum);
1974129794Stackerman	}
1975129794Stackerman	/* Setup the Receive Control Register */
1976129794Stackerman	reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
1977129794Stackerman	reg_rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
1978129794Stackerman	reg_rctl |= IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 | IXGB_RCTL_SECRC |
1979129794Stackerman		IXGB_RCTL_CFF |
1980129794Stackerman		(adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
1981129794Stackerman
1982129794Stackerman	switch (adapter->rx_buffer_len) {
1983129794Stackerman	default:
1984129794Stackerman	case IXGB_RXBUFFER_2048:
1985129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_2048;
1986129794Stackerman		break;
1987129794Stackerman	case IXGB_RXBUFFER_4096:
1988129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_4096;
1989129794Stackerman		break;
1990129794Stackerman	case IXGB_RXBUFFER_8192:
1991129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_8192;
1992129794Stackerman		break;
1993129794Stackerman	case IXGB_RXBUFFER_16384:
1994129794Stackerman		reg_rctl |= IXGB_RCTL_BSIZE_16384;
1995129794Stackerman		break;
1996129794Stackerman	}
1997129794Stackerman
1998129794Stackerman	reg_rctl |= IXGB_RCTL_RXEN;
1999129794Stackerman
2000129794Stackerman
2001129794Stackerman	/* Enable Receives */
2002129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
2003129794Stackerman
2004129794Stackerman	return;
2005129794Stackerman}
2006129794Stackerman
2007129794Stackerman/*********************************************************************
2008129794Stackerman *
2009129794Stackerman *  Free receive related data structures.
2010129794Stackerman *
2011129794Stackerman **********************************************************************/
2012129794Stackermanstatic void
2013129794Stackermanixgb_free_receive_structures(struct adapter * adapter)
2014129794Stackerman{
2015129794Stackerman	struct ixgb_buffer *rx_buffer;
2016129794Stackerman	int             i;
2017129794Stackerman
2018129794Stackerman	INIT_DEBUGOUT("free_receive_structures: begin");
2019129794Stackerman
2020129794Stackerman	if (adapter->rx_buffer_area != NULL) {
2021129794Stackerman		rx_buffer = adapter->rx_buffer_area;
2022129794Stackerman		for (i = 0; i < adapter->num_rx_desc; i++, rx_buffer++) {
2023129794Stackerman			if (rx_buffer->map != NULL) {
2024129794Stackerman				bus_dmamap_unload(adapter->rxtag, rx_buffer->map);
2025129794Stackerman				bus_dmamap_destroy(adapter->rxtag, rx_buffer->map);
2026129794Stackerman			}
2027129794Stackerman			if (rx_buffer->m_head != NULL)
2028129794Stackerman				m_freem(rx_buffer->m_head);
2029129794Stackerman			rx_buffer->m_head = NULL;
2030129794Stackerman		}
2031129794Stackerman	}
2032129794Stackerman	if (adapter->rx_buffer_area != NULL) {
2033129794Stackerman		free(adapter->rx_buffer_area, M_DEVBUF);
2034129794Stackerman		adapter->rx_buffer_area = NULL;
2035129794Stackerman	}
2036129794Stackerman	if (adapter->rxtag != NULL) {
2037129794Stackerman		bus_dma_tag_destroy(adapter->rxtag);
2038129794Stackerman		adapter->rxtag = NULL;
2039129794Stackerman	}
2040129794Stackerman	return;
2041129794Stackerman}
2042129794Stackerman
2043129794Stackerman/*********************************************************************
2044129794Stackerman *
2045129794Stackerman *  This routine executes in interrupt context. It replenishes
2046129794Stackerman *  the mbufs in the descriptor and sends data which has been
2047129794Stackerman *  dma'ed into host memory to upper layer.
2048129794Stackerman *
2049129794Stackerman *  We loop at most count times if count is > 0, or until done if
2050129794Stackerman *  count < 0.
2051129794Stackerman *
2052129794Stackerman *********************************************************************/
2053129794Stackermanstatic void
2054129794Stackermanixgb_process_receive_interrupts(struct adapter * adapter, int count)
2055129794Stackerman{
2056129794Stackerman	struct ifnet   *ifp;
2057129794Stackerman	struct mbuf    *mp;
2058129794Stackerman#if __FreeBSD_version < 500000
2059129794Stackerman	struct ether_header *eh;
2060129794Stackerman#endif
2061129794Stackerman	int             eop = 0;
2062129794Stackerman	int             len;
2063129794Stackerman	u_int8_t        accept_frame = 0;
2064129794Stackerman	int             i;
2065129794Stackerman	int             next_to_use = 0;
2066129794Stackerman	int             eop_desc;
2067129794Stackerman	/* Pointer to the receive descriptor being examined. */
2068129794Stackerman	struct ixgb_rx_desc *current_desc;
2069129794Stackerman
2070144651Salc	IXGB_LOCK_ASSERT(adapter);
2071144651Salc
2072147256Sbrooks	ifp = adapter->ifp;
2073129794Stackerman	i = adapter->next_rx_desc_to_check;
2074129794Stackerman	next_to_use = adapter->next_rx_desc_to_use;
2075129794Stackerman	eop_desc = adapter->next_rx_desc_to_check;
2076129794Stackerman	current_desc = &adapter->rx_desc_base[i];
2077129794Stackerman
2078129794Stackerman	if (!((current_desc->status) & IXGB_RX_DESC_STATUS_DD)) {
2079129794Stackerman#ifdef _SV_
2080129794Stackerman		adapter->no_pkts_avail++;
2081129794Stackerman#endif
2082129794Stackerman		return;
2083129794Stackerman	}
2084129794Stackerman	while ((current_desc->status & IXGB_RX_DESC_STATUS_DD) && (count != 0)) {
2085129794Stackerman
2086129794Stackerman		mp = adapter->rx_buffer_area[i].m_head;
2087129794Stackerman		bus_dmamap_sync(adapter->rxtag, adapter->rx_buffer_area[i].map,
2088129794Stackerman				BUS_DMASYNC_POSTREAD);
2089129794Stackerman		accept_frame = 1;
2090129794Stackerman		if (current_desc->status & IXGB_RX_DESC_STATUS_EOP) {
2091129794Stackerman			count--;
2092129794Stackerman			eop = 1;
2093129794Stackerman		} else {
2094129794Stackerman			eop = 0;
2095129794Stackerman		}
2096129794Stackerman		len = current_desc->length;
2097129794Stackerman
2098129794Stackerman		if (current_desc->errors & (IXGB_RX_DESC_ERRORS_CE |
2099129794Stackerman			    IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P |
2100129794Stackerman					    IXGB_RX_DESC_ERRORS_RXE)) {
2101129794Stackerman			accept_frame = 0;
2102129794Stackerman		}
2103129794Stackerman		if (accept_frame) {
2104129794Stackerman
2105129794Stackerman			/* Assign correct length to the current fragment */
2106129794Stackerman			mp->m_len = len;
2107129794Stackerman
2108129794Stackerman			if (adapter->fmp == NULL) {
2109129794Stackerman				mp->m_pkthdr.len = len;
2110129794Stackerman				adapter->fmp = mp;	/* Store the first mbuf */
2111129794Stackerman				adapter->lmp = mp;
2112129794Stackerman			} else {
2113129794Stackerman				/* Chain mbuf's together */
2114129794Stackerman				mp->m_flags &= ~M_PKTHDR;
2115129794Stackerman				adapter->lmp->m_next = mp;
2116129794Stackerman				adapter->lmp = adapter->lmp->m_next;
2117129794Stackerman				adapter->fmp->m_pkthdr.len += len;
2118129794Stackerman			}
2119129794Stackerman
2120129794Stackerman			if (eop) {
2121129794Stackerman				eop_desc = i;
2122129794Stackerman				adapter->fmp->m_pkthdr.rcvif = ifp;
2123129794Stackerman
2124129794Stackerman#if __FreeBSD_version < 500000
2125129794Stackerman				eh = mtod(adapter->fmp, struct ether_header *);
2126129794Stackerman
2127129794Stackerman				/* Remove ethernet header from mbuf */
2128129794Stackerman				m_adj(adapter->fmp, sizeof(struct ether_header));
2129129794Stackerman				ixgb_receive_checksum(adapter, current_desc,
2130129794Stackerman						      adapter->fmp);
2131129794Stackerman
2132129794Stackerman				if (current_desc->status & IXGB_RX_DESC_STATUS_VP)
2133129794Stackerman					VLAN_INPUT_TAG(eh, adapter->fmp,
2134129794Stackerman						     current_desc->special);
2135129794Stackerman				else
2136129794Stackerman					ether_input(ifp, eh, adapter->fmp);
2137129794Stackerman#else
2138129794Stackerman				ixgb_receive_checksum(adapter, current_desc,
2139129794Stackerman						      adapter->fmp);
2140129794Stackerman				if (current_desc->status & IXGB_RX_DESC_STATUS_VP)
2141129794Stackerman					VLAN_INPUT_TAG(ifp, adapter->fmp,
2142129794Stackerman						       current_desc->special,
2143129794Stackerman						       adapter->fmp = NULL);
2144129794Stackerman
2145144651Salc				if (adapter->fmp != NULL) {
2146144651Salc					IXGB_UNLOCK(adapter);
2147129794Stackerman					(*ifp->if_input) (ifp, adapter->fmp);
2148144651Salc					IXGB_LOCK(adapter);
2149144651Salc				}
2150129794Stackerman#endif
2151129794Stackerman				adapter->fmp = NULL;
2152129794Stackerman				adapter->lmp = NULL;
2153129794Stackerman			}
2154129794Stackerman			adapter->rx_buffer_area[i].m_head = NULL;
2155129794Stackerman		} else {
2156129794Stackerman			adapter->dropped_pkts++;
2157129794Stackerman			if (adapter->fmp != NULL)
2158129794Stackerman				m_freem(adapter->fmp);
2159129794Stackerman			adapter->fmp = NULL;
2160129794Stackerman			adapter->lmp = NULL;
2161129794Stackerman		}
2162129794Stackerman
2163129794Stackerman		/* Zero out the receive descriptors status  */
2164129794Stackerman		current_desc->status = 0;
2165129794Stackerman
2166129794Stackerman		/* Advance our pointers to the next descriptor */
2167129794Stackerman		if (++i == adapter->num_rx_desc) {
2168129794Stackerman			i = 0;
2169129794Stackerman			current_desc = adapter->rx_desc_base;
2170129794Stackerman		} else
2171129794Stackerman			current_desc++;
2172129794Stackerman	}
2173129794Stackerman	adapter->next_rx_desc_to_check = i;
2174129794Stackerman
2175129794Stackerman	if (--i < 0)
2176129794Stackerman		i = (adapter->num_rx_desc - 1);
2177129794Stackerman
2178129794Stackerman	/*
2179129794Stackerman	 * 82597EX: Workaround for redundent write back in receive descriptor ring (causes
2180129794Stackerman 	 * memory corruption). Avoid using and re-submitting the most recently received RX
2181129794Stackerman	 * descriptor back to hardware.
2182129794Stackerman	 *
2183129794Stackerman	 * if(Last written back descriptor == EOP bit set descriptor)
2184129794Stackerman	 * 	then avoid re-submitting the most recently received RX descriptor
2185129794Stackerman	 *	back to hardware.
2186129794Stackerman	 * if(Last written back descriptor != EOP bit set descriptor)
2187129794Stackerman	 *	then avoid re-submitting the most recently received RX descriptors
2188129794Stackerman	 * 	till last EOP bit set descriptor.
2189129794Stackerman	 */
2190129794Stackerman	if (eop_desc != i) {
2191129794Stackerman		if (++eop_desc == adapter->num_rx_desc)
2192129794Stackerman			eop_desc = 0;
2193129794Stackerman		i = eop_desc;
2194129794Stackerman	}
2195129794Stackerman	/* Replenish the descriptors with new mbufs till last EOP bit set descriptor */
2196129794Stackerman	while (next_to_use != i) {
2197129794Stackerman		current_desc = &adapter->rx_desc_base[next_to_use];
2198129794Stackerman		if ((current_desc->errors & (IXGB_RX_DESC_ERRORS_CE |
2199129794Stackerman			    IXGB_RX_DESC_ERRORS_SE | IXGB_RX_DESC_ERRORS_P |
2200129794Stackerman					     IXGB_RX_DESC_ERRORS_RXE))) {
2201129794Stackerman			mp = adapter->rx_buffer_area[next_to_use].m_head;
2202129794Stackerman			ixgb_get_buf(next_to_use, adapter, mp);
2203129794Stackerman		} else {
2204129794Stackerman			if (ixgb_get_buf(next_to_use, adapter, NULL) == ENOBUFS)
2205129794Stackerman				break;
2206129794Stackerman		}
2207129794Stackerman		/* Advance our pointers to the next descriptor */
2208129794Stackerman		if (++next_to_use == adapter->num_rx_desc) {
2209129794Stackerman			next_to_use = 0;
2210129794Stackerman			current_desc = adapter->rx_desc_base;
2211129794Stackerman		} else
2212129794Stackerman			current_desc++;
2213129794Stackerman	}
2214129794Stackerman	adapter->next_rx_desc_to_use = next_to_use;
2215129794Stackerman	if (--next_to_use < 0)
2216129794Stackerman		next_to_use = (adapter->num_rx_desc - 1);
2217129794Stackerman	/* Advance the IXGB's Receive Queue #0  "Tail Pointer" */
2218129794Stackerman	IXGB_WRITE_REG(&adapter->hw, RDT, next_to_use);
2219129794Stackerman
2220129794Stackerman	return;
2221129794Stackerman}
2222129794Stackerman
2223129794Stackerman/*********************************************************************
2224129794Stackerman *
2225129794Stackerman *  Verify that the hardware indicated that the checksum is valid.
2226129794Stackerman *  Inform the stack about the status of checksum so that stack
2227129794Stackerman *  doesn't spend time verifying the checksum.
2228129794Stackerman *
2229129794Stackerman *********************************************************************/
2230129794Stackermanstatic void
2231129794Stackermanixgb_receive_checksum(struct adapter * adapter,
2232129794Stackerman		      struct ixgb_rx_desc * rx_desc,
2233129794Stackerman		      struct mbuf * mp)
2234129794Stackerman{
2235129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) {
2236129794Stackerman		mp->m_pkthdr.csum_flags = 0;
2237129794Stackerman		return;
2238129794Stackerman	}
2239129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_IPCS) {
2240129794Stackerman		/* Did it pass? */
2241129794Stackerman		if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_IPE)) {
2242129794Stackerman			/* IP Checksum Good */
2243129794Stackerman			mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
2244129794Stackerman			mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
2245129794Stackerman
2246129794Stackerman		} else {
2247129794Stackerman			mp->m_pkthdr.csum_flags = 0;
2248129794Stackerman		}
2249129794Stackerman	}
2250129794Stackerman	if (rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS) {
2251129794Stackerman		/* Did it pass? */
2252129794Stackerman		if (!(rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE)) {
2253129794Stackerman			mp->m_pkthdr.csum_flags |=
2254129794Stackerman				(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
2255129794Stackerman			mp->m_pkthdr.csum_data = htons(0xffff);
2256129794Stackerman		}
2257129794Stackerman	}
2258129794Stackerman	return;
2259129794Stackerman}
2260129794Stackerman
2261129794Stackerman
2262129794Stackermanstatic void
2263129794Stackermanixgb_enable_vlans(struct adapter * adapter)
2264129794Stackerman{
2265129794Stackerman	uint32_t        ctrl;
2266129794Stackerman
2267129794Stackerman	ctrl = IXGB_READ_REG(&adapter->hw, CTRL0);
2268129794Stackerman	ctrl |= IXGB_CTRL0_VME;
2269129794Stackerman	IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl);
2270129794Stackerman
2271129794Stackerman	return;
2272129794Stackerman}
2273129794Stackerman
2274129794Stackerman
2275129794Stackermanstatic void
2276129794Stackermanixgb_enable_intr(struct adapter * adapter)
2277129794Stackerman{
2278129794Stackerman	IXGB_WRITE_REG(&adapter->hw, IMS, (IXGB_INT_RXT0 | IXGB_INT_TXDW |
2279129794Stackerman			    IXGB_INT_RXDMT0 | IXGB_INT_LSC | IXGB_INT_RXO));
2280129794Stackerman	return;
2281129794Stackerman}
2282129794Stackerman
2283129794Stackermanstatic void
2284129794Stackermanixgb_disable_intr(struct adapter * adapter)
2285129794Stackerman{
2286129794Stackerman	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
2287129794Stackerman	return;
2288129794Stackerman}
2289129794Stackerman
2290129794Stackermanvoid
2291129794Stackermanixgb_write_pci_cfg(struct ixgb_hw * hw,
2292129794Stackerman		   uint32_t reg,
2293129794Stackerman		   uint16_t * value)
2294129794Stackerman{
2295129794Stackerman	pci_write_config(((struct ixgb_osdep *) hw->back)->dev, reg,
2296129794Stackerman			 *value, 2);
2297129794Stackerman}
2298129794Stackerman
2299129794Stackerman/**********************************************************************
2300129794Stackerman *
2301129794Stackerman *  Update the board statistics counters.
2302129794Stackerman *
2303129794Stackerman **********************************************************************/
2304129794Stackermanstatic void
2305129794Stackermanixgb_update_stats_counters(struct adapter * adapter)
2306129794Stackerman{
2307129794Stackerman	struct ifnet   *ifp;
2308129794Stackerman
2309129794Stackerman	adapter->stats.crcerrs += IXGB_READ_REG(&adapter->hw, CRCERRS);
2310129794Stackerman	adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);
2311129794Stackerman	adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);
2312129794Stackerman	adapter->stats.gorcl += IXGB_READ_REG(&adapter->hw, GORCL);
2313129794Stackerman	adapter->stats.gorch += IXGB_READ_REG(&adapter->hw, GORCH);
2314129794Stackerman	adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
2315129794Stackerman	adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
2316129794Stackerman	adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
2317129794Stackerman	adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
2318129794Stackerman	adapter->stats.roc += IXGB_READ_REG(&adapter->hw, ROC);
2319129794Stackerman
2320129794Stackerman	adapter->stats.mpc += IXGB_READ_REG(&adapter->hw, MPC);
2321129794Stackerman	adapter->stats.dc += IXGB_READ_REG(&adapter->hw, DC);
2322129794Stackerman	adapter->stats.rlec += IXGB_READ_REG(&adapter->hw, RLEC);
2323129794Stackerman	adapter->stats.xonrxc += IXGB_READ_REG(&adapter->hw, XONRXC);
2324129794Stackerman	adapter->stats.xontxc += IXGB_READ_REG(&adapter->hw, XONTXC);
2325129794Stackerman	adapter->stats.xoffrxc += IXGB_READ_REG(&adapter->hw, XOFFRXC);
2326129794Stackerman	adapter->stats.xofftxc += IXGB_READ_REG(&adapter->hw, XOFFTXC);
2327129794Stackerman	adapter->stats.gptcl += IXGB_READ_REG(&adapter->hw, GPTCL);
2328129794Stackerman	adapter->stats.gptch += IXGB_READ_REG(&adapter->hw, GPTCH);
2329129794Stackerman	adapter->stats.gotcl += IXGB_READ_REG(&adapter->hw, GOTCL);
2330129794Stackerman	adapter->stats.gotch += IXGB_READ_REG(&adapter->hw, GOTCH);
2331129794Stackerman	adapter->stats.ruc += IXGB_READ_REG(&adapter->hw, RUC);
2332129794Stackerman	adapter->stats.rfc += IXGB_READ_REG(&adapter->hw, RFC);
2333129794Stackerman	adapter->stats.rjc += IXGB_READ_REG(&adapter->hw, RJC);
2334129794Stackerman	adapter->stats.torl += IXGB_READ_REG(&adapter->hw, TORL);
2335129794Stackerman	adapter->stats.torh += IXGB_READ_REG(&adapter->hw, TORH);
2336129794Stackerman	adapter->stats.totl += IXGB_READ_REG(&adapter->hw, TOTL);
2337129794Stackerman	adapter->stats.toth += IXGB_READ_REG(&adapter->hw, TOTH);
2338129794Stackerman	adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
2339129794Stackerman	adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
2340129794Stackerman	adapter->stats.tptl += IXGB_READ_REG(&adapter->hw, TPTL);
2341129794Stackerman	adapter->stats.tpth += IXGB_READ_REG(&adapter->hw, TPTH);
2342129794Stackerman	adapter->stats.plt64c += IXGB_READ_REG(&adapter->hw, PLT64C);
2343129794Stackerman	adapter->stats.mptcl += IXGB_READ_REG(&adapter->hw, MPTCL);
2344129794Stackerman	adapter->stats.mptch += IXGB_READ_REG(&adapter->hw, MPTCH);
2345129794Stackerman	adapter->stats.bptcl += IXGB_READ_REG(&adapter->hw, BPTCL);
2346129794Stackerman	adapter->stats.bptch += IXGB_READ_REG(&adapter->hw, BPTCH);
2347129794Stackerman
2348129794Stackerman	adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);
2349129794Stackerman	adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);
2350129794Stackerman	adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);
2351129794Stackerman	adapter->stats.vprch += IXGB_READ_REG(&adapter->hw, VPRCH);
2352129794Stackerman	adapter->stats.jprcl += IXGB_READ_REG(&adapter->hw, JPRCL);
2353129794Stackerman	adapter->stats.jprch += IXGB_READ_REG(&adapter->hw, JPRCH);
2354129794Stackerman	adapter->stats.rnbc += IXGB_READ_REG(&adapter->hw, RNBC);
2355129794Stackerman	adapter->stats.icbc += IXGB_READ_REG(&adapter->hw, ICBC);
2356129794Stackerman	adapter->stats.ecbc += IXGB_READ_REG(&adapter->hw, ECBC);
2357129794Stackerman	adapter->stats.uptcl += IXGB_READ_REG(&adapter->hw, UPTCL);
2358129794Stackerman	adapter->stats.uptch += IXGB_READ_REG(&adapter->hw, UPTCH);
2359129794Stackerman	adapter->stats.vptcl += IXGB_READ_REG(&adapter->hw, VPTCL);
2360129794Stackerman	adapter->stats.vptch += IXGB_READ_REG(&adapter->hw, VPTCH);
2361129794Stackerman	adapter->stats.jptcl += IXGB_READ_REG(&adapter->hw, JPTCL);
2362129794Stackerman	adapter->stats.jptch += IXGB_READ_REG(&adapter->hw, JPTCH);
2363129794Stackerman	adapter->stats.tsctc += IXGB_READ_REG(&adapter->hw, TSCTC);
2364129794Stackerman	adapter->stats.tsctfc += IXGB_READ_REG(&adapter->hw, TSCTFC);
2365129794Stackerman	adapter->stats.ibic += IXGB_READ_REG(&adapter->hw, IBIC);
2366129794Stackerman	adapter->stats.lfc += IXGB_READ_REG(&adapter->hw, LFC);
2367129794Stackerman	adapter->stats.pfrc += IXGB_READ_REG(&adapter->hw, PFRC);
2368129794Stackerman	adapter->stats.pftc += IXGB_READ_REG(&adapter->hw, PFTC);
2369129794Stackerman	adapter->stats.mcfrc += IXGB_READ_REG(&adapter->hw, MCFRC);
2370129794Stackerman
2371147256Sbrooks	ifp = adapter->ifp;
2372129794Stackerman
2373129794Stackerman	/* Fill out the OS statistics structure */
2374129794Stackerman	ifp->if_ipackets = adapter->stats.gprcl;
2375129794Stackerman	ifp->if_opackets = adapter->stats.gptcl;
2376129794Stackerman	ifp->if_ibytes = adapter->stats.gorcl;
2377129794Stackerman	ifp->if_obytes = adapter->stats.gotcl;
2378129794Stackerman	ifp->if_imcasts = adapter->stats.mprcl;
2379129794Stackerman	ifp->if_collisions = 0;
2380129794Stackerman
2381129794Stackerman	/* Rx Errors */
2382129794Stackerman	ifp->if_ierrors =
2383129794Stackerman		adapter->dropped_pkts +
2384129794Stackerman		adapter->stats.crcerrs +
2385129794Stackerman		adapter->stats.rnbc +
2386129794Stackerman		adapter->stats.mpc +
2387129794Stackerman		adapter->stats.rlec;
2388129794Stackerman
2389129794Stackerman
2390129794Stackerman}
2391129794Stackerman
2392129794Stackerman
2393129794Stackerman/**********************************************************************
2394129794Stackerman *
2395129794Stackerman *  This routine is called only when ixgb_display_debug_stats is enabled.
2396129794Stackerman *  This routine provides a way to take a look at important statistics
2397129794Stackerman *  maintained by the driver and hardware.
2398129794Stackerman *
2399129794Stackerman **********************************************************************/
2400129794Stackermanstatic void
2401129794Stackermanixgb_print_hw_stats(struct adapter * adapter)
2402129794Stackerman{
2403129794Stackerman	char            buf_speed[100], buf_type[100];
2404129794Stackerman	ixgb_bus_speed  bus_speed;
2405129794Stackerman	ixgb_bus_type   bus_type;
2406129794Stackerman	int             unit = adapter->unit;
2407129794Stackerman
2408129794Stackerman#ifdef _SV_
2409129794Stackerman	printf("ixgb%d: Packets not Avail = %ld\n", unit,
2410129794Stackerman	       adapter->no_pkts_avail);
2411129794Stackerman	printf("ixgb%d: CleanTxInterrupts = %ld\n", unit,
2412129794Stackerman	       adapter->clean_tx_interrupts);
2413129794Stackerman	printf("ixgb%d: ICR RXDMT0 = %lld\n", unit,
2414129794Stackerman	       (long long)adapter->sv_stats.icr_rxdmt0);
2415129794Stackerman	printf("ixgb%d: ICR RXO = %lld\n", unit,
2416129794Stackerman	       (long long)adapter->sv_stats.icr_rxo);
2417129794Stackerman	printf("ixgb%d: ICR RXT0 = %lld\n", unit,
2418129794Stackerman	       (long long)adapter->sv_stats.icr_rxt0);
2419129794Stackerman	printf("ixgb%d: ICR TXDW = %lld\n", unit,
2420129794Stackerman	       (long long)adapter->sv_stats.icr_TXDW);
2421129794Stackerman#endif				/* _SV_ */
2422129794Stackerman
2423129794Stackerman	bus_speed = adapter->hw.bus.speed;
2424129794Stackerman	bus_type = adapter->hw.bus.type;
2425129794Stackerman	sprintf(buf_speed,
2426129794Stackerman		bus_speed == ixgb_bus_speed_33 ? "33MHz" :
2427129794Stackerman		bus_speed == ixgb_bus_speed_66 ? "66MHz" :
2428129794Stackerman		bus_speed == ixgb_bus_speed_100 ? "100MHz" :
2429129794Stackerman		bus_speed == ixgb_bus_speed_133 ? "133MHz" :
2430129794Stackerman		"UNKNOWN");
2431129794Stackerman	printf("ixgb%d: PCI_Bus_Speed = %s\n", unit,
2432129794Stackerman	       buf_speed);
2433129794Stackerman
2434129794Stackerman	sprintf(buf_type,
2435129794Stackerman		bus_type == ixgb_bus_type_pci ? "PCI" :
2436129794Stackerman		bus_type == ixgb_bus_type_pcix ? "PCI-X" :
2437129794Stackerman		"UNKNOWN");
2438129794Stackerman	printf("ixgb%d: PCI_Bus_Type = %s\n", unit,
2439129794Stackerman	       buf_type);
2440129794Stackerman
2441129794Stackerman	printf("ixgb%d: Tx Descriptors not Avail1 = %ld\n", unit,
2442129794Stackerman	       adapter->no_tx_desc_avail1);
2443129794Stackerman	printf("ixgb%d: Tx Descriptors not Avail2 = %ld\n", unit,
2444129794Stackerman	       adapter->no_tx_desc_avail2);
2445129794Stackerman	printf("ixgb%d: Std Mbuf Failed = %ld\n", unit,
2446129794Stackerman	       adapter->mbuf_alloc_failed);
2447129794Stackerman	printf("ixgb%d: Std Cluster Failed = %ld\n", unit,
2448129794Stackerman	       adapter->mbuf_cluster_failed);
2449129794Stackerman
2450129794Stackerman	printf("ixgb%d: Defer count = %lld\n", unit,
2451129794Stackerman	       (long long)adapter->stats.dc);
2452129794Stackerman	printf("ixgb%d: Missed Packets = %lld\n", unit,
2453129794Stackerman	       (long long)adapter->stats.mpc);
2454129794Stackerman	printf("ixgb%d: Receive No Buffers = %lld\n", unit,
2455129794Stackerman	       (long long)adapter->stats.rnbc);
2456129794Stackerman	printf("ixgb%d: Receive length errors = %lld\n", unit,
2457129794Stackerman	       (long long)adapter->stats.rlec);
2458129794Stackerman	printf("ixgb%d: Crc errors = %lld\n", unit,
2459129794Stackerman	       (long long)adapter->stats.crcerrs);
2460129794Stackerman	printf("ixgb%d: Driver dropped packets = %ld\n", unit,
2461129794Stackerman	       adapter->dropped_pkts);
2462129794Stackerman
2463129794Stackerman	printf("ixgb%d: XON Rcvd = %lld\n", unit,
2464129794Stackerman	       (long long)adapter->stats.xonrxc);
2465129794Stackerman	printf("ixgb%d: XON Xmtd = %lld\n", unit,
2466129794Stackerman	       (long long)adapter->stats.xontxc);
2467129794Stackerman	printf("ixgb%d: XOFF Rcvd = %lld\n", unit,
2468129794Stackerman	       (long long)adapter->stats.xoffrxc);
2469129794Stackerman	printf("ixgb%d: XOFF Xmtd = %lld\n", unit,
2470129794Stackerman	       (long long)adapter->stats.xofftxc);
2471129794Stackerman
2472129794Stackerman	printf("ixgb%d: Good Packets Rcvd = %lld\n", unit,
2473129794Stackerman	       (long long)adapter->stats.gprcl);
2474129794Stackerman	printf("ixgb%d: Good Packets Xmtd = %lld\n", unit,
2475129794Stackerman	       (long long)adapter->stats.gptcl);
2476129794Stackerman
2477129794Stackerman	printf("ixgb%d: Jumbo frames recvd = %lld\n", unit,
2478129794Stackerman	       (long long)adapter->stats.jprcl);
2479129794Stackerman	printf("ixgb%d: Jumbo frames Xmtd = %lld\n", unit,
2480129794Stackerman	       (long long)adapter->stats.jptcl);
2481129794Stackerman
2482129794Stackerman	return;
2483129794Stackerman
2484129794Stackerman}
2485129794Stackerman
2486129794Stackermanstatic int
2487129794Stackermanixgb_sysctl_stats(SYSCTL_HANDLER_ARGS)
2488129794Stackerman{
2489129794Stackerman	int             error;
2490129794Stackerman	int             result;
2491129794Stackerman	struct adapter *adapter;
2492129794Stackerman
2493129794Stackerman	result = -1;
2494129794Stackerman	error = sysctl_handle_int(oidp, &result, 0, req);
2495129794Stackerman
2496129794Stackerman	if (error || !req->newptr)
2497129794Stackerman		return (error);
2498129794Stackerman
2499129794Stackerman	if (result == 1) {
2500129794Stackerman		adapter = (struct adapter *) arg1;
2501129794Stackerman		ixgb_print_hw_stats(adapter);
2502129794Stackerman	}
2503129794Stackerman	return error;
2504129794Stackerman}
2505