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