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