xref: /titanic_44/usr/src/uts/common/io/atge/atge_l1e.c (revision 888e055994b8b0dc77b98c53dd97026237caec5d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/stream.h>
29 #include <sys/strsun.h>
30 #include <sys/stat.h>
31 #include <sys/modctl.h>
32 #include <sys/ethernet.h>
33 #include <sys/debug.h>
34 #include <sys/conf.h>
35 #include <sys/mii.h>
36 #include <sys/miiregs.h>
37 #include <sys/sysmacros.h>
38 #include <sys/dditypes.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/byteorder.h>
42 #include <sys/note.h>
43 #include <sys/vlan.h>
44 #include <sys/stream.h>
45 
46 #include "atge.h"
47 #include "atge_l1e_reg.h"
48 #include "atge_cmn_reg.h"
49 
50 /*
51  * L1E specfic functions.
52  */
53 void	atge_l1e_device_reset(atge_t *);
54 void	atge_l1e_stop_rx_mac(atge_t *);
55 void	atge_l1e_stop_tx_mac(atge_t *);
56 void	atge_l1e_interrupt(atge_t *, uint32_t, caddr_t);
57 
58 static ddi_dma_attr_t atge_l1e_dma_attr_tx_desc = {
59 	DMA_ATTR_V0,		/* dma_attr_version */
60 	0,			/* dma_attr_addr_lo */
61 	0x0000ffffffffull,	/* dma_attr_addr_hi */
62 	0x0000ffffffffull,	/* dma_attr_count_max */
63 	L1E_TX_RING_ALIGN,	/* dma_attr_align */
64 	0x0000fffc,		/* dma_attr_burstsizes */
65 	1,			/* dma_attr_minxfer */
66 	0x0000ffffffffull,	/* dma_attr_maxxfer */
67 	0x0000ffffffffull,	/* dma_attr_seg */
68 	1,			/* dma_attr_sgllen */
69 	1,			/* dma_attr_granular */
70 	0			/* dma_attr_flags */
71 };
72 
73 static ddi_dma_attr_t atge_l1e_dma_attr_rx_desc = {
74 	DMA_ATTR_V0,		/* dma_attr_version */
75 	0,			/* dma_attr_addr_lo */
76 	0x0000ffffffffull,	/* dma_attr_addr_hi */
77 	0x0000ffffffffull,	/* dma_attr_count_max */
78 	L1E_RX_PAGE_ALIGN,	/* dma_attr_align */
79 	0x0000fffc,		/* dma_attr_burstsizes */
80 	1,			/* dma_attr_minxfer */
81 	0x0000ffffffffull,	/* dma_attr_maxxfer */
82 	0x0000ffffffffull,	/* dma_attr_seg */
83 	1,			/* dma_attr_sgllen */
84 	1,			/* dma_attr_granular */
85 	0			/* dma_attr_flags */
86 };
87 
88 static ddi_dma_attr_t atge_l1e_dma_attr_cmb = {
89 	DMA_ATTR_V0,		/* dma_attr_version */
90 	0,			/* dma_attr_addr_lo */
91 	0x0000ffffffffull,	/* dma_attr_addr_hi */
92 	0x0000ffffffffull,	/* dma_attr_count_max */
93 	L1E_CMB_ALIGN,		/* dma_attr_align */
94 	0x0000fffc,		/* dma_attr_burstsizes */
95 	1,			/* dma_attr_minxfer */
96 	0x0000ffffffffull,	/* dma_attr_maxxfer */
97 	0x0000ffffffffull,	/* dma_attr_seg */
98 	1,			/* dma_attr_sgllen */
99 	1,			/* dma_attr_granular */
100 	0			/* dma_attr_flags */
101 };
102 
103 void	atge_l1e_rx_next_pkt(atge_t *, uint32_t);
104 
105 void
106 atge_rx_desc_free(atge_t *atgep)
107 {
108 	atge_l1e_data_t *l1e;
109 	atge_dma_t *dma;
110 	int pages;
111 
112 	l1e = (atge_l1e_data_t *)atgep->atge_private_data;
113 	if (l1e == NULL)
114 		return;
115 
116 	if (l1e->atge_l1e_rx_page == NULL)
117 		return;
118 
119 	for (pages = 0; pages < L1E_RX_PAGES; pages++) {
120 		dma = l1e->atge_l1e_rx_page[pages];
121 		if (dma != NULL) {
122 			(void) ddi_dma_unbind_handle(dma->hdl);
123 			ddi_dma_mem_free(&dma->acchdl);
124 			ddi_dma_free_handle(&dma->hdl);
125 			kmem_free(dma, sizeof (atge_dma_t));
126 		}
127 	}
128 
129 	kmem_free(l1e->atge_l1e_rx_page, L1E_RX_PAGES * sizeof (atge_dma_t *));
130 	l1e->atge_l1e_rx_page = NULL;
131 }
132 
133 int
134 atge_l1e_alloc_dma(atge_t *atgep)
135 {
136 	atge_dma_t *dma;
137 	atge_l1e_data_t *l1e;
138 	int err;
139 	int pages;
140 	int guard_size;
141 
142 	l1e = kmem_zalloc(sizeof (atge_l1e_data_t), KM_SLEEP);
143 	atgep->atge_private_data = l1e;
144 
145 	/*
146 	 * Allocate TX ring descriptor.
147 	 */
148 	atgep->atge_tx_buf_len = atgep->atge_mtu +
149 	    sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
150 	atgep->atge_tx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
151 	atgep->atge_tx_ring->r_atge = atgep;
152 	atgep->atge_tx_ring->r_desc_ring = NULL;
153 	dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_tx_desc,
154 	    L1E_TX_RING_SZ, DDI_DMA_RDWR);
155 	if (dma == NULL) {
156 		ATGE_DB(("%s :%s failed",
157 		    atgep->atge_name, __func__));
158 		return (ATGE_FAILURE);
159 	}
160 	atgep->atge_tx_ring->r_desc_ring = dma;
161 
162 	/*
163 	 * Allocate DMA buffers for TX ring.
164 	 */
165 	err = atge_alloc_buffers(atgep->atge_tx_ring, L1E_TX_RING_CNT,
166 	    atgep->atge_tx_buf_len, DDI_DMA_WRITE);
167 	if (err != ATGE_SUCCESS) {
168 		ATGE_DB(("%s :%s() TX buffers failed",
169 		    atgep->atge_name, __func__));
170 		return (err);
171 	}
172 
173 	/*
174 	 * Allocate RX pages.
175 	 */
176 	atgep->atge_rx_buf_len = atgep->atge_mtu +
177 	    sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
178 
179 	if (atgep->atge_flags & ATGE_FLAG_JUMBO)
180 		guard_size = L1E_JUMBO_FRAMELEN;
181 	else
182 		guard_size = L1E_MAX_FRAMELEN;
183 
184 	l1e->atge_l1e_pagesize = ROUNDUP(guard_size + L1E_RX_PAGE_SZ,
185 	    L1E_RX_PAGE_ALIGN);
186 	l1e->atge_l1e_rx_page =
187 	    kmem_zalloc(L1E_RX_PAGES * sizeof (atge_dma_t *), KM_SLEEP);
188 
189 	ATGE_DB(("%s: %s() atge_l1e_pagesize : %d, L1E_RX_PAGE_SZ : %d",
190 	    atgep->atge_name, __func__, l1e->atge_l1e_pagesize,
191 	    L1E_RX_PAGE_SZ));
192 
193 	err = ATGE_SUCCESS;
194 	for (pages = 0; pages < L1E_RX_PAGES; pages++) {
195 		dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_rx_desc,
196 		    l1e->atge_l1e_pagesize, DDI_DMA_READ);
197 
198 		if (dma == NULL) {
199 			err = ATGE_FAILURE;
200 			break;
201 		}
202 
203 		l1e->atge_l1e_rx_page[pages] = dma;
204 	}
205 
206 	if (err == ATGE_FAILURE) {
207 		ATGE_DB(("%s :%s RX pages failed",
208 		    atgep->atge_name, __func__));
209 		return (ATGE_FAILURE);
210 	}
211 
212 	/*
213 	 * Allocate CMB used for fetching interrupt status data.
214 	 */
215 	ATGE_DB(("%s: %s() L1E_RX_CMB_SZ : %x", atgep->atge_name,
216 	    __func__, L1E_RX_CMB_SZ));
217 
218 	err = ATGE_SUCCESS;
219 	dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_cmb,
220 	    L1E_RX_CMB_SZ * L1E_RX_PAGES, DDI_DMA_RDWR);
221 	if (dma == NULL) {
222 		ATGE_DB(("%s :%s() RX CMB failed",
223 		    atgep->atge_name, __func__));
224 		return (ATGE_FAILURE);
225 	}
226 	l1e->atge_l1e_rx_cmb = dma;
227 
228 	if (err == ATGE_FAILURE) {
229 		ATGE_DB(("%s :%s() RX CMB failed",
230 		    atgep->atge_name, __func__));
231 		return (ATGE_FAILURE);
232 	}
233 
234 	atgep->atge_hw_stats = kmem_zalloc(sizeof (atge_l1e_smb_t), KM_SLEEP);
235 
236 	return (ATGE_SUCCESS);
237 }
238 
239 void
240 atge_l1e_free_dma(atge_t *atgep)
241 {
242 	atge_l1e_data_t *l1e;
243 
244 	/*
245 	 * Free TX ring.
246 	 */
247 	if (atgep->atge_tx_ring != NULL) {
248 		atge_free_buffers(atgep->atge_tx_ring,  L1E_TX_RING_CNT);
249 
250 		if (atgep->atge_tx_ring->r_desc_ring != NULL) {
251 			atge_free_a_dma_blk(atgep->atge_tx_ring->r_desc_ring);
252 		}
253 
254 		kmem_free(atgep->atge_tx_ring, sizeof (atge_ring_t));
255 		atgep->atge_tx_ring = NULL;
256 	}
257 
258 	l1e = atgep->atge_private_data;
259 	if (l1e == NULL)
260 		return;
261 
262 	/*
263 	 * Free RX CMB.
264 	 */
265 	if (l1e->atge_l1e_rx_cmb != NULL) {
266 		atge_free_a_dma_blk(l1e->atge_l1e_rx_cmb);
267 		l1e->atge_l1e_rx_cmb = NULL;
268 	}
269 
270 	/*
271 	 * Free RX buffers and RX ring.
272 	 */
273 	atge_rx_desc_free(atgep);
274 
275 	/*
276 	 * Free the memory allocated for gathering hw stats.
277 	 */
278 	if (atgep->atge_hw_stats != NULL) {
279 		kmem_free(atgep->atge_hw_stats, sizeof (atge_l1e_smb_t));
280 		atgep->atge_hw_stats = NULL;
281 	}
282 }
283 
284 void
285 atge_l1e_init_rx_pages(atge_t *atgep)
286 {
287 	atge_l1e_data_t *l1e;
288 	atge_dma_t *dma;
289 	int pages;
290 
291 	ASSERT(atgep != NULL);
292 	l1e = atgep->atge_private_data;
293 
294 	ASSERT(l1e != NULL);
295 
296 	l1e->atge_l1e_proc_max = L1E_RX_PAGE_SZ / ETHERMIN;
297 	l1e->atge_l1e_rx_curp = 0;
298 	l1e->atge_l1e_rx_seqno = 0;
299 
300 	for (pages = 0; pages < L1E_RX_PAGES; pages++) {
301 		l1e->atge_l1e_rx_page_cons = 0;
302 		l1e->atge_l1e_rx_page_prods[pages] = 0;
303 
304 
305 		dma = l1e->atge_l1e_rx_page[pages];
306 		ASSERT(dma != NULL);
307 		bzero(dma->addr, l1e->atge_l1e_pagesize);
308 		DMA_SYNC(dma, 0, l1e->atge_l1e_pagesize, DDI_DMA_SYNC_FORDEV);
309 	}
310 
311 	dma = l1e->atge_l1e_rx_cmb;
312 	ASSERT(dma != NULL);
313 	bzero(dma->addr, L1E_RX_CMB_SZ * L1E_RX_PAGES);
314 	DMA_SYNC(dma, 0, L1E_RX_CMB_SZ * L1E_RX_PAGES, DDI_DMA_SYNC_FORDEV);
315 }
316 
317 void
318 atge_l1e_init_tx_ring(atge_t *atgep)
319 {
320 	ASSERT(atgep != NULL);
321 	ASSERT(atgep->atge_tx_ring != NULL);
322 	ASSERT(atgep->atge_tx_ring->r_desc_ring != NULL);
323 
324 	atgep->atge_tx_ring->r_producer = 0;
325 	atgep->atge_tx_ring->r_consumer = 0;
326 	atgep->atge_tx_ring->r_avail_desc = L1E_TX_RING_CNT;
327 
328 	bzero(atgep->atge_tx_ring->r_desc_ring->addr, L1E_TX_RING_SZ);
329 
330 	DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, L1E_TX_RING_SZ,
331 	    DDI_DMA_SYNC_FORDEV);
332 }
333 
334 void
335 atge_l1e_program_dma(atge_t *atgep)
336 {
337 	atge_l1e_data_t *l1e;
338 	uint64_t paddr;
339 	uint32_t reg;
340 
341 	l1e = (atge_l1e_data_t *)atgep->atge_private_data;
342 
343 	/*
344 	 * Clear WOL status and disable all WOL feature as WOL
345 	 * would interfere Rx operation under normal environments.
346 	 */
347 	(void) INL(atgep, ATGE_WOL_CFG);
348 	OUTL(atgep, ATGE_WOL_CFG, 0);
349 
350 	/*
351 	 * Set Tx descriptor/RXF0/CMB base addresses. They share
352 	 * the same high address part of DMAable region.
353 	 */
354 	paddr = atgep->atge_tx_ring->r_desc_ring->cookie.dmac_laddress;
355 	OUTL(atgep, ATGE_DESC_ADDR_HI, ATGE_ADDR_HI(paddr));
356 	OUTL(atgep, ATGE_DESC_TPD_ADDR_LO, ATGE_ADDR_LO(paddr));
357 	OUTL(atgep, ATGE_DESC_TPD_CNT,
358 	    (L1E_TX_RING_CNT << DESC_TPD_CNT_SHIFT) & DESC_TPD_CNT_MASK);
359 
360 	/* Set Rx page base address, note we use single queue. */
361 	paddr = l1e->atge_l1e_rx_page[0]->cookie.dmac_laddress;
362 	OUTL(atgep, L1E_RXF0_PAGE0_ADDR_LO, ATGE_ADDR_LO(paddr));
363 	paddr = l1e->atge_l1e_rx_page[1]->cookie.dmac_laddress;
364 	OUTL(atgep, L1E_RXF0_PAGE1_ADDR_LO, ATGE_ADDR_LO(paddr));
365 
366 	/* Set Tx/Rx CMB addresses. */
367 	paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress;
368 	OUTL(atgep, L1E_RXF0_CMB0_ADDR_LO, ATGE_ADDR_LO(paddr));
369 	paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress + sizeof (uint32_t);
370 	OUTL(atgep, L1E_RXF0_CMB1_ADDR_LO, ATGE_ADDR_LO(paddr));
371 
372 	/* Mark RXF0 valid. */
373 	OUTB(atgep, L1E_RXF0_PAGE0, RXF_VALID);	/* 0 */
374 	OUTB(atgep, L1E_RXF0_PAGE1, RXF_VALID);	/* 1 */
375 	OUTB(atgep, L1E_RXF0_PAGE0 + 2, 0);
376 	OUTB(atgep, L1E_RXF0_PAGE0 + 3, 0);
377 	OUTB(atgep, L1E_RXF0_PAGE0 + 4, 0);
378 	OUTB(atgep, L1E_RXF0_PAGE0 + 5, 0);
379 	OUTB(atgep, L1E_RXF0_PAGE0 + 6, 0);
380 	OUTB(atgep, L1E_RXF0_PAGE0 + 6, 0);
381 
382 	/* Set Rx page size, excluding guard frame size. */
383 	OUTL(atgep, L1E_RXF_PAGE_SIZE, L1E_RX_PAGE_SZ);
384 
385 	/* Tell hardware that we're ready to load DMA blocks. */
386 	OUTL(atgep, ATGE_DMA_BLOCK, DMA_BLOCK_LOAD);
387 
388 	/* Set Rx/Tx interrupt trigger threshold. */
389 	OUTL(atgep, L1E_INT_TRIG_THRESH, (1 << INT_TRIG_RX_THRESH_SHIFT) |
390 	    (4 << INT_TRIG_TX_THRESH_SHIFT));
391 
392 	/*
393 	 * Set interrupt trigger timer, its purpose and relation
394 	 * with interrupt moderation mechanism is not clear yet.
395 	 */
396 	OUTL(atgep, L1E_INT_TRIG_TIMER,
397 	    ((ATGE_USECS(10) << INT_TRIG_RX_TIMER_SHIFT) |
398 	    (ATGE_USECS(1000) << INT_TRIG_TX_TIMER_SHIFT)));
399 
400 	reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
401 	reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) << IM_TIMER_TX_SHIFT;
402 	OUTL(atgep, ATGE_IM_TIMER, reg);
403 
404 	reg = INL(atgep, ATGE_MASTER_CFG);
405 	reg &= ~(MASTER_CHIP_REV_MASK | MASTER_CHIP_ID_MASK);
406 	reg &= ~(MASTER_IM_RX_TIMER_ENB | MASTER_IM_TX_TIMER_ENB);
407 	reg |= MASTER_IM_RX_TIMER_ENB;
408 	reg |= MASTER_IM_TX_TIMER_ENB;
409 	OUTL(atgep, ATGE_MASTER_CFG, reg);
410 
411 	OUTW(atgep, RX_COALSC_PKT_1e, 0);
412 	OUTW(atgep, RX_COALSC_TO_1e, 0);
413 	OUTW(atgep, TX_COALSC_PKT_1e, 1);
414 	OUTW(atgep, TX_COALSC_TO_1e, 4000/2);		/* 4mS */
415 }
416 
417 mblk_t *
418 atge_l1e_receive(atge_t *atgep)
419 {
420 	atge_l1e_data_t *l1e;
421 	atge_dma_t *dma_rx_page;
422 	atge_dma_t *dma_rx_cmb;
423 	uint32_t *ptr;
424 	uint32_t cons, current_page;
425 	uchar_t *pageaddr, *bufp;
426 	rx_rs_t	*rs;
427 	int prog;
428 	uint32_t seqno, len, flags;
429 	mblk_t *mp = NULL, *rx_head, *rx_tail;
430 	static uint32_t gen = 0;
431 
432 	l1e = atgep->atge_private_data;
433 
434 	ASSERT(MUTEX_HELD(&atgep->atge_intr_lock));
435 	ASSERT(l1e != NULL);
436 
437 	rx_tail = NULL;
438 	rx_head = NULL;
439 
440 	current_page = l1e->atge_l1e_rx_curp;
441 
442 	/* Sync CMB first */
443 	dma_rx_cmb = l1e->atge_l1e_rx_cmb;
444 	DMA_SYNC(dma_rx_cmb, 0, L1E_RX_CMB_SZ * L1E_RX_PAGES,
445 	    DDI_DMA_SYNC_FORKERNEL);
446 
447 	dma_rx_page = l1e->atge_l1e_rx_page[current_page];
448 
449 	/*
450 	 * Get the producer offset from CMB.
451 	 */
452 	ptr = (void *)dma_rx_cmb->addr;
453 
454 	l1e->atge_l1e_rx_page_prods[current_page] =
455 	    ATGE_GET32(dma_rx_cmb, ptr + current_page);
456 
457 	/* Sync current RX Page as well */
458 	DMA_SYNC(dma_rx_page, l1e->atge_l1e_rx_page_cons,
459 	    l1e->atge_l1e_rx_page_prods[current_page], DDI_DMA_SYNC_FORKERNEL);
460 
461 	ATGE_DB(("%s: %s() prod : %d, cons : %d, curr page : %d, gen : (%d)"
462 	    " cmb[0,1] : %d, %d",
463 	    atgep->atge_name, __func__,
464 	    l1e->atge_l1e_rx_page_prods[current_page],
465 	    l1e->atge_l1e_rx_page_cons, l1e->atge_l1e_rx_curp, gen,
466 	    ATGE_GET32(dma_rx_cmb, ptr), ATGE_GET32(dma_rx_cmb, ptr + 1)));
467 
468 	for (prog = 0; prog <= l1e->atge_l1e_proc_max; prog++) {
469 		cons = l1e->atge_l1e_rx_page_cons;
470 		if (cons >= l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp])
471 			break;
472 
473 		dma_rx_page = l1e->atge_l1e_rx_page[l1e->atge_l1e_rx_curp];
474 		pageaddr = (uchar_t *)dma_rx_page->addr;
475 		pageaddr = pageaddr + cons;
476 		rs = (rx_rs_t *)pageaddr;
477 
478 		seqno = ATGE_GET32(dma_rx_page, &(rs->seqno));
479 		seqno = L1E_RX_SEQNO(seqno);
480 
481 		len = ATGE_GET32(dma_rx_page, &(rs->length));
482 		len = L1E_RX_BYTES(len);
483 
484 		flags = ATGE_GET32(dma_rx_page, &(rs->flags));
485 
486 		if (seqno != l1e->atge_l1e_rx_seqno) {
487 			/*
488 			 * We have not seen this happening but we
489 			 * must restart the chip if that happens.
490 			 */
491 			ATGE_DB(("%s: %s() MISS-MATCH in seqno :%d,"
492 			    " atge_l1e_rx_seqno : %d, length : %d, flags : %x",
493 			    atgep->atge_name, __func__, seqno,
494 			    l1e->atge_l1e_rx_seqno, len, flags));
495 
496 			mutex_enter(&atgep->atge_tx_lock);
497 			atge_device_restart(atgep);
498 			mutex_exit(&atgep->atge_tx_lock);
499 
500 			/*
501 			 * Return all the pkts received before restarting
502 			 * the chip.
503 			 */
504 			return (rx_head);
505 		} else {
506 			l1e->atge_l1e_rx_seqno++;
507 		}
508 
509 		/*
510 		 * We will pass the pkt to upper layer provided it's clear
511 		 * from any error.
512 		 */
513 		if ((flags & L1E_RD_ERROR) != 0) {
514 			if ((flags & (L1E_RD_CRC | L1E_RD_CODE |
515 			    L1E_RD_DRIBBLE | L1E_RD_RUNT | L1E_RD_OFLOW |
516 			    L1E_RD_TRUNC)) != 0) {
517 				ATGE_DB(("%s: %s() ERRORED PKT : %x",
518 				    atgep->atge_name, __func__, flags));
519 				atge_l1e_rx_next_pkt(atgep, len);
520 				atgep->atge_errrcv++;
521 				continue;
522 			}
523 		}
524 
525 		/*
526 		 * So we have received a frame/pkt.
527 		 */
528 		if (len == 0 || len > atgep->atge_rx_buf_len) {
529 			ATGE_DB(("%s: %s() PKT len > error : %d",
530 			    atgep->atge_name, __func__, len));
531 			atge_l1e_rx_next_pkt(atgep, len);
532 			continue;
533 		}
534 
535 		mp = allocb(len + VLAN_TAGSZ, BPRI_MED);
536 		if (mp != NULL) {
537 			mp->b_rptr += VLAN_TAGSZ;
538 			bufp = mp->b_rptr;
539 			mp->b_wptr = bufp + len;
540 			mp->b_next = NULL;
541 
542 			bcopy(pageaddr + sizeof (rx_rs_t), bufp, len);
543 
544 			if (rx_tail == NULL)
545 				rx_head = rx_tail = mp;
546 			else {
547 				rx_tail->b_next = mp;
548 				rx_tail = mp;
549 			}
550 
551 			atgep->atge_ipackets++;
552 			atgep->atge_rbytes += len;
553 		} else {
554 			ATGE_DB(("%s: %s() PKT mp == NULL len : %d",
555 			    atgep->atge_name, __func__, len));
556 
557 			if (len > atgep->atge_rx_buf_len) {
558 				atgep->atge_toolong_errors++;
559 			} else if (mp == NULL) {
560 				atgep->atge_norcvbuf++;
561 			}
562 		}
563 
564 		atge_l1e_rx_next_pkt(atgep, len);
565 
566 		ATGE_DB(("%s: %s() seqno :%d, atge_l1e_rx_seqno :"
567 		    " %d, length : %d,"
568 		    " flags : %x, cons : %d, prod : %d",
569 		    atgep->atge_name, __func__, seqno,
570 		    l1e->atge_l1e_rx_seqno, len, flags,
571 		    l1e->atge_l1e_rx_page_cons,
572 		    l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp]));
573 	}
574 
575 	ATGE_DB(("%s: %s() receive completed (gen : %d) : cons : %d,"
576 	    " prod :%d, L1E_RX_PAGE_SZ : %d (prog:%d)",
577 	    atgep->atge_name, __func__, gen,
578 	    l1e->atge_l1e_rx_page_cons,
579 	    l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp],
580 	    L1E_RX_PAGE_SZ, prog));
581 
582 	gen++;
583 	return (rx_head);
584 }
585 
586 void
587 atge_l1e_rx_next_pkt(atge_t *atgep, uint32_t len)
588 {
589 	atge_l1e_data_t *l1e = atgep->atge_private_data;
590 	atge_dma_t *dma_rx_page;
591 	atge_dma_t *dma_rx_cmb;
592 	int curr = l1e->atge_l1e_rx_curp;
593 	uint32_t *p;
594 
595 	/*
596 	 * Update consumer position.
597 	 */
598 	l1e->atge_l1e_rx_page_cons +=
599 	    ROUNDUP(len + sizeof (rx_rs_t), L1E_RX_PAGE_ALIGN);
600 
601 	/*
602 	 * If we need to flip to the other page. Note that we use only two
603 	 * pages.
604 	 */
605 	if (l1e->atge_l1e_rx_page_cons >= L1E_RX_PAGE_SZ) {
606 		ATGE_DB(("%s: %s() cons : %d, prod :%d, L1E_RX_PAGE_SZ : %d",
607 		    atgep->atge_name, __func__, l1e->atge_l1e_rx_page_cons,
608 		    l1e->atge_l1e_rx_page_prods[curr], L1E_RX_PAGE_SZ));
609 
610 		/*
611 		 * Clear the producer.
612 		 */
613 		dma_rx_cmb = l1e->atge_l1e_rx_cmb;
614 		p = (void *)dma_rx_cmb->addr;
615 		p = p + curr;
616 		*p = 0;
617 		DMA_SYNC(dma_rx_cmb, curr * L1E_RX_CMB_SZ,
618 		    L1E_RX_CMB_SZ, DDI_DMA_SYNC_FORDEV);
619 
620 		/*
621 		 * Notify the NIC that the current RX page is available again.
622 		 */
623 		OUTB(atgep, L1E_RXF0_PAGE0 + curr, RXF_VALID);
624 
625 		/*
626 		 * End of Rx page reached, let hardware reuse this page.
627 		 */
628 		l1e->atge_l1e_rx_page_cons = 0;
629 		l1e->atge_l1e_rx_page_prods[curr] = 0;
630 
631 		/*
632 		 * Switch to alternate Rx page.
633 		 */
634 		curr ^= 1;
635 		l1e->atge_l1e_rx_curp = curr;
636 
637 		/*
638 		 * Page flipped, sync CMB and then Rx page.
639 		 */
640 		DMA_SYNC(dma_rx_cmb, 0, L1E_RX_PAGES * L1E_RX_CMB_SZ,
641 		    DDI_DMA_SYNC_FORKERNEL);
642 		p = (void *)dma_rx_cmb->addr;
643 		l1e->atge_l1e_rx_page_prods[curr] =
644 		    ATGE_GET32(dma_rx_cmb, p + curr);
645 
646 		dma_rx_page = l1e->atge_l1e_rx_page[curr];
647 		DMA_SYNC(dma_rx_page, 0, l1e->atge_l1e_rx_page_prods[curr],
648 		    DDI_DMA_SYNC_FORKERNEL);
649 
650 		ATGE_DB(("%s: %s() PAGE FLIPPED -> %d, producer[0,1]: %d, %d",
651 		    atgep->atge_name, __func__, curr,
652 		    ATGE_GET32(dma_rx_cmb, p), ATGE_GET32(dma_rx_cmb, p + 1)));
653 	}
654 }
655 
656 void
657 atge_l1e_send_packet(atge_ring_t *r, int start, uint32_t pktlen)
658 {
659 	atge_l1e_tx_desc_t	*txd;
660 	uchar_t *c;
661 	uint32_t cflags = 0;
662 
663 	c = (uchar_t *)r->r_desc_ring->addr;
664 	c += (sizeof (atge_l1e_tx_desc_t) * start);
665 	txd = (atge_l1e_tx_desc_t *)c;
666 
667 	ATGE_PUT64(r->r_desc_ring, &txd->addr,
668 	    r->r_buf_tbl[start]->cookie.dmac_laddress);
669 
670 	ATGE_PUT32(r->r_desc_ring, &txd->len, L1E_TX_BYTES(pktlen));
671 
672 	cflags |= L1E_TD_EOP;
673 	ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags);
674 
675 	/*
676 	 * Sync buffer first.
677 	 */
678 	DMA_SYNC(r->r_buf_tbl[start], 0, pktlen, DDI_DMA_SYNC_FORDEV);
679 
680 	/*
681 	 * Increment TX producer count by one.
682 	 */
683 	ATGE_DESC_INC(r->r_producer, L1E_TX_RING_CNT);
684 
685 	/*
686 	 * Sync descriptor table.
687 	 */
688 	DMA_SYNC(r->r_desc_ring, 0, L1E_TX_RING_SZ, DDI_DMA_SYNC_FORDEV);
689 
690 	/*
691 	 * Ask chip to send the packet now.
692 	 */
693 	OUTL(r->r_atge, ATGE_MBOX, r->r_producer);
694 
695 	r->r_atge->atge_opackets++;
696 	r->r_atge->atge_obytes += pktlen;
697 }
698 
699 void
700 atge_l1e_tx_reclaim(atge_t *atgep)
701 {
702 	int start, end;
703 
704 	ASSERT(MUTEX_HELD(&atgep->atge_tx_lock));
705 
706 	end = INW(atgep, L1E_TPD_CONS_IDX);
707 	start = atgep->atge_tx_ring->r_consumer;
708 
709 	ATGE_DB(("%s: %s() start : %d, end : %d, avail : %d",
710 	    atgep->atge_name, __func__, start, end,
711 	    atgep->atge_tx_ring->r_avail_desc));
712 
713 	while (start != end) {
714 		atgep->atge_tx_ring->r_avail_desc++;
715 		ATGE_DESC_INC(start, L1E_TX_RING_CNT);
716 	}
717 
718 	atgep->atge_tx_ring->r_consumer = start;
719 }
720 
721 void
722 atge_l1e_clear_stats(atge_t *atgep)
723 {
724 	atge_l1e_smb_t smb;
725 	uint32_t *reg;
726 	int i;
727 
728 	/*
729 	 * Clear RX stats first.
730 	 */
731 	i = 0;
732 	reg = &smb.rx_frames;
733 	while (reg++ <= &smb.rx_pkts_filtered) {
734 		(void) INL(atgep, L1E_RX_MIB_BASE + i);
735 		i += sizeof (uint32_t);
736 	}
737 
738 	/*
739 	 * Clear TX stats.
740 	 */
741 	i = 0;
742 	reg = &smb.tx_frames;
743 	while (reg++ <= &smb.tx_mcast_bytes) {
744 		(void) INL(atgep, L1E_TX_MIB_BASE + i);
745 		i += sizeof (uint32_t);
746 	}
747 }
748 
749 void
750 atge_l1e_gather_stats(atge_t *atgep)
751 {
752 	atge_l1e_smb_t *stat;
753 	atge_l1e_smb_t *smb;
754 	atge_l1e_smb_t local_smb;
755 	uint32_t *reg;
756 	int i;
757 
758 	ASSERT(atgep != NULL);
759 
760 	stat = (atge_l1e_smb_t *)atgep->atge_hw_stats;
761 
762 	bzero(&local_smb, sizeof (atge_l1e_smb_t));
763 	smb = &local_smb;
764 
765 	/* Read Rx statistics. */
766 	i = 0;
767 	reg = &smb->rx_frames;
768 	while (reg++ <= &smb->rx_pkts_filtered) {
769 		*reg = INL(atgep, L1E_RX_MIB_BASE + i);
770 		i += sizeof (uint32_t);
771 	}
772 
773 	/* Read Tx statistics. */
774 	i = 0;
775 	reg = &smb->tx_frames;
776 	while (reg++ <= &smb->tx_mcast_bytes) {
777 		*reg = INL(atgep, L1E_TX_MIB_BASE + i);
778 		i += sizeof (uint32_t);
779 	}
780 
781 	/*
782 	 * SMB is cleared everytime we read; hence we always do '+='.
783 	 */
784 
785 	/* Rx stats. */
786 	stat->rx_frames += smb->rx_frames;
787 	stat->rx_bcast_frames += smb->rx_bcast_frames;
788 	stat->rx_mcast_frames += smb->rx_mcast_frames;
789 	stat->rx_pause_frames += smb->rx_pause_frames;
790 	stat->rx_control_frames += smb->rx_control_frames;
791 	stat->rx_crcerrs += smb->rx_crcerrs;
792 	stat->rx_lenerrs += smb->rx_lenerrs;
793 	stat->rx_bytes += smb->rx_bytes;
794 	stat->rx_runts += smb->rx_runts;
795 	stat->rx_fragments += smb->rx_fragments;
796 	stat->rx_pkts_64 += smb->rx_pkts_64;
797 	stat->rx_pkts_65_127 += smb->rx_pkts_65_127;
798 	stat->rx_pkts_128_255 += smb->rx_pkts_128_255;
799 	stat->rx_pkts_256_511 += smb->rx_pkts_256_511;
800 	stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023;
801 	stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518;
802 	stat->rx_pkts_1519_max += smb->rx_pkts_1519_max;
803 	stat->rx_pkts_truncated += smb->rx_pkts_truncated;
804 	stat->rx_fifo_oflows += smb->rx_fifo_oflows;
805 	stat->rx_rrs_errs += smb->rx_rrs_errs;
806 	stat->rx_alignerrs += smb->rx_alignerrs;
807 	stat->rx_bcast_bytes += smb->rx_bcast_bytes;
808 	stat->rx_mcast_bytes += smb->rx_mcast_bytes;
809 	stat->rx_pkts_filtered += smb->rx_pkts_filtered;
810 
811 	/* Tx stats. */
812 	stat->tx_frames += smb->tx_frames;
813 	stat->tx_bcast_frames += smb->tx_bcast_frames;
814 	stat->tx_mcast_frames += smb->tx_mcast_frames;
815 	stat->tx_pause_frames += smb->tx_pause_frames;
816 	stat->tx_excess_defer += smb->tx_excess_defer;
817 	stat->tx_control_frames += smb->tx_control_frames;
818 	stat->tx_deferred += smb->tx_deferred;
819 	stat->tx_bytes += smb->tx_bytes;
820 	stat->tx_pkts_64 += smb->tx_pkts_64;
821 	stat->tx_pkts_65_127 += smb->tx_pkts_65_127;
822 	stat->tx_pkts_128_255 += smb->tx_pkts_128_255;
823 	stat->tx_pkts_256_511 += smb->tx_pkts_256_511;
824 	stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023;
825 	stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518;
826 	stat->tx_pkts_1519_max += smb->tx_pkts_1519_max;
827 	stat->tx_single_colls += smb->tx_single_colls;
828 	stat->tx_multi_colls += smb->tx_multi_colls;
829 	stat->tx_late_colls += smb->tx_late_colls;
830 	stat->tx_excess_colls += smb->tx_excess_colls;
831 	stat->tx_abort += smb->tx_abort;
832 	stat->tx_underrun += smb->tx_underrun;
833 	stat->tx_desc_underrun += smb->tx_desc_underrun;
834 	stat->tx_lenerrs += smb->tx_lenerrs;
835 	stat->tx_pkts_truncated += smb->tx_pkts_truncated;
836 	stat->tx_bcast_bytes += smb->tx_bcast_bytes;
837 	stat->tx_mcast_bytes += smb->tx_mcast_bytes;
838 
839 	/*
840 	 * Update global counters in atge_t.
841 	 */
842 	atgep->atge_brdcstrcv += smb->rx_bcast_frames;
843 	atgep->atge_multircv += smb->rx_mcast_frames;
844 	atgep->atge_multixmt += smb->tx_mcast_frames;
845 	atgep->atge_brdcstxmt += smb->tx_bcast_frames;
846 
847 	atgep->atge_align_errors += smb->rx_alignerrs;
848 	atgep->atge_fcs_errors += smb->rx_crcerrs;
849 	atgep->atge_sqe_errors += smb->rx_rrs_errs;
850 	atgep->atge_defer_xmts += smb->tx_deferred;
851 	atgep->atge_first_collisions += smb->tx_single_colls;
852 	atgep->atge_multi_collisions += smb->tx_multi_colls * 2;
853 	atgep->atge_tx_late_collisions += smb->tx_late_colls;
854 	atgep->atge_ex_collisions += smb->tx_excess_colls;
855 	atgep->atge_macxmt_errors += smb->tx_abort;
856 	atgep->atge_toolong_errors += smb->rx_lenerrs;
857 	atgep->atge_overflow += smb->rx_fifo_oflows;
858 	atgep->atge_underflow += (smb->tx_underrun + smb->tx_desc_underrun);
859 	atgep->atge_runt += smb->rx_runts;
860 
861 
862 	atgep->atge_collisions += smb->tx_single_colls +
863 	    smb->tx_multi_colls * 2 + smb->tx_late_colls +
864 	    smb->tx_abort * HDPX_CFG_RETRY_DEFAULT;
865 
866 	/*
867 	 * tx_pkts_truncated counter looks suspicious. It constantly
868 	 * increments with no sign of Tx errors. Hence we don't factor it.
869 	 */
870 	atgep->atge_macxmt_errors += smb->tx_abort + smb->tx_late_colls +
871 	    smb->tx_underrun;
872 
873 	atgep->atge_macrcv_errors += smb->rx_crcerrs + smb->rx_lenerrs +
874 	    smb->rx_runts + smb->rx_pkts_truncated +
875 	    smb->rx_fifo_oflows + smb->rx_rrs_errs +
876 	    smb->rx_alignerrs;
877 }
878 
879 void
880 atge_l1e_stop_mac(atge_t *atgep)
881 {
882 	uint32_t reg;
883 
884 	reg = INL(atgep, ATGE_MAC_CFG);
885 	ATGE_DB(("%s: %s() reg : %x", atgep->atge_name, __func__, reg));
886 
887 	if ((reg & (ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB)) != 0) {
888 		reg &= ~ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB;
889 		OUTL(atgep, ATGE_MAC_CFG, reg);
890 		ATGE_DB(("%s: %s() mac stopped", atgep->atge_name, __func__));
891 	}
892 }
893