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 */
53void	atge_l1e_device_reset(atge_t *);
54void	atge_l1e_stop_rx_mac(atge_t *);
55void	atge_l1e_stop_tx_mac(atge_t *);
56
57static 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
72static 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
87static 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
102void	atge_l1e_rx_next_pkt(atge_t *, uint32_t);
103
104void
105atge_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
132int
133atge_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
238void
239atge_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
283void
284atge_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
316void
317atge_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
333void
334atge_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
416mblk_t *
417atge_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
585void
586atge_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
655void
656atge_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
664void
665atge_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
692void
693atge_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
822void
823atge_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*/
841uint_t
842atge_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
929done:
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