xref: /illumos-gate/usr/src/uts/common/io/atge/atge_l1c.c (revision 25c28e83beb90e7c80452a7c818c5e6f73a07dc8)
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  * Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org>
30  * All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  * 1. Redistributions of source code must retain the above copyright
36  *    notice unmodified, this list of conditions, and the following
37  *    disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
43  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
46  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  */
54 
55 #include <sys/types.h>
56 #include <sys/stream.h>
57 #include <sys/strsun.h>
58 #include <sys/stat.h>
59 #include <sys/modctl.h>
60 #include <sys/ethernet.h>
61 #include <sys/debug.h>
62 #include <sys/conf.h>
63 #include <sys/mii.h>
64 #include <sys/miiregs.h>
65 #include <sys/sysmacros.h>
66 #include <sys/dditypes.h>
67 #include <sys/ddi.h>
68 #include <sys/sunddi.h>
69 #include <sys/byteorder.h>
70 #include <sys/note.h>
71 #include <sys/vlan.h>
72 #include <sys/stream.h>
73 
74 #include "atge.h"
75 #include "atge_l1c_reg.h"
76 #include "atge_cmn_reg.h"
77 
78 static ddi_dma_attr_t atge_l1c_dma_attr_tx_desc = {
79 	DMA_ATTR_V0,		/* dma_attr_version */
80 	0,			/* dma_attr_addr_lo */
81 	0x0000ffffffffull,	/* dma_attr_addr_hi */
82 	0x0000ffffffffull,	/* dma_attr_count_max */
83 	L1C_TX_RING_ALIGN,	/* dma_attr_align */
84 	0x0000fffc,		/* dma_attr_burstsizes */
85 	1,			/* dma_attr_minxfer */
86 	0x0000ffffffffull,	/* dma_attr_maxxfer */
87 	0x0000ffffffffull,	/* dma_attr_seg */
88 	1,			/* dma_attr_sgllen */
89 	1,			/* dma_attr_granular */
90 	0			/* dma_attr_flags */
91 };
92 
93 static ddi_dma_attr_t atge_l1c_dma_attr_rx_desc = {
94 	DMA_ATTR_V0,		/* dma_attr_version */
95 	0,			/* dma_attr_addr_lo */
96 	0x0000ffffffffull,	/* dma_attr_addr_hi */
97 	0x0000ffffffffull,	/* dma_attr_count_max */
98 	L1C_RX_RING_ALIGN,	/* dma_attr_align */
99 	0x0000fffc,		/* dma_attr_burstsizes */
100 	1,			/* dma_attr_minxfer */
101 	0x0000ffffffffull,	/* dma_attr_maxxfer */
102 	0x0000ffffffffull,	/* dma_attr_seg */
103 	1,			/* dma_attr_sgllen */
104 	1,			/* dma_attr_granular */
105 	0			/* dma_attr_flags */
106 };
107 
108 static ddi_dma_attr_t atge_l1c_dma_attr_cmb = {
109 	DMA_ATTR_V0,		/* dma_attr_version */
110 	0,			/* dma_attr_addr_lo */
111 	0x0000ffffffffull,	/* dma_attr_addr_hi */
112 	0x0000ffffffffull,	/* dma_attr_count_max */
113 	L1C_CMB_ALIGN,		/* dma_attr_align */
114 	0x0000fffc,		/* dma_attr_burstsizes */
115 	1,			/* dma_attr_minxfer */
116 	0x0000ffffffffull,	/* dma_attr_maxxfer */
117 	0x0000ffffffffull,	/* dma_attr_seg */
118 	1,			/* dma_attr_sgllen */
119 	1,			/* dma_attr_granular */
120 	0			/* dma_attr_flags */
121 };
122 
123 static ddi_dma_attr_t atge_l1c_dma_attr_smb = {
124 	DMA_ATTR_V0,		/* dma_attr_version */
125 	0,			/* dma_attr_addr_lo */
126 	0x0000ffffffffull,	/* dma_attr_addr_hi */
127 	0x0000ffffffffull,	/* dma_attr_count_max */
128 	L1C_SMB_ALIGN,		/* dma_attr_align */
129 	0x0000fffc,		/* dma_attr_burstsizes */
130 	1,			/* dma_attr_minxfer */
131 	0x0000ffffffffull,	/* dma_attr_maxxfer */
132 	0x0000ffffffffull,	/* dma_attr_seg */
133 	1,			/* dma_attr_sgllen */
134 	1,			/* dma_attr_granular */
135 	0			/* dma_attr_flags */
136 };
137 
138 static ddi_dma_attr_t atge_l1c_dma_attr_rr = {
139 	DMA_ATTR_V0,		/* dma_attr_version */
140 	0,			/* dma_attr_addr_lo */
141 	0x0000ffffffffull,	/* dma_attr_addr_hi */
142 	0x0000ffffffffull,	/* dma_attr_count_max */
143 	L1C_RR_RING_ALIGN,	/* dma_attr_align */
144 	0x0000fffc,		/* dma_attr_burstsizes */
145 	1,			/* dma_attr_minxfer */
146 	0x0000ffffffffull,	/* dma_attr_maxxfer */
147 	0x0000ffffffffull,	/* dma_attr_seg */
148 	1,			/* dma_attr_sgllen */
149 	1,			/* dma_attr_granular */
150 	0			/* dma_attr_flags */
151 };
152 
153 int
154 atge_l1c_alloc_dma(atge_t *atgep)
155 {
156 	atge_l1c_data_t *l1c;
157 	atge_dma_t *dma;
158 	int err;
159 
160 	l1c = kmem_zalloc(sizeof (atge_l1c_data_t), KM_SLEEP);
161 	atgep->atge_private_data = l1c;
162 
163 	/*
164 	 * Allocate TX ring descriptor.
165 	 */
166 	atgep->atge_tx_buf_len = atgep->atge_mtu +
167 	    sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
168 	atgep->atge_tx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
169 	atgep->atge_tx_ring->r_atge = atgep;
170 	atgep->atge_tx_ring->r_desc_ring = NULL;
171 	dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_tx_desc,
172 	    ATGE_TX_RING_SZ, DDI_DMA_RDWR);
173 	if (dma == NULL) {
174 		atge_error(atgep->atge_dip, "DMA allocation failed for TX"
175 		    " desc ring");
176 		return (DDI_FAILURE);
177 	}
178 	atgep->atge_tx_ring->r_desc_ring = dma;
179 
180 	/*
181 	 * Allocate DMA buffers for TX ring.
182 	 */
183 	err = atge_alloc_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT,
184 	    atgep->atge_tx_buf_len, DDI_DMA_WRITE);
185 	if (err != DDI_SUCCESS) {
186 		atge_error(atgep->atge_dip, "DMA allocation failed for"
187 		    " TX Ring");
188 		return (err);
189 	}
190 
191 	/*
192 	 * Allocate RX ring.
193 	 */
194 	atgep->atge_rx_buf_len = atgep->atge_mtu +
195 	    sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
196 	l1c->atge_rx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
197 	l1c->atge_rx_ring->r_atge = atgep;
198 	l1c->atge_rx_ring->r_desc_ring = NULL;
199 	dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_rx_desc,
200 	    L1C_RX_RING_SZ, DDI_DMA_RDWR);
201 	if (dma == NULL) {
202 		atge_error(atgep->atge_dip, "DMA allocation failed"
203 		    " for RX Ring");
204 		return (DDI_FAILURE);
205 	}
206 	l1c->atge_rx_ring->r_desc_ring = dma;
207 
208 	/*
209 	 * Allocate DMA buffers for RX ring.
210 	 */
211 	err = atge_alloc_buffers(l1c->atge_rx_ring, L1C_RX_RING_CNT,
212 	    atgep->atge_rx_buf_len, DDI_DMA_READ);
213 	if (err != DDI_SUCCESS) {
214 		atge_error(atgep->atge_dip, "DMA allocation failed for"
215 		    " RX buffers");
216 		return (err);
217 	}
218 
219 	/*
220 	 * Allocate CMB used for fetching interrupt status data.
221 	 */
222 	ATGE_DB(("%s: %s() L1C_CMB_BLOCK_SZ : 0x%x", atgep->atge_name,
223 	    __func__, L1C_CMB_BLOCK_SZ));
224 
225 	dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_cmb,
226 	    L1C_CMB_BLOCK_SZ, DDI_DMA_RDWR);
227 	l1c->atge_l1c_cmb = dma;
228 	if (dma == NULL) {
229 		atge_error(atgep->atge_dip, "DMA allocation failed for CMB");
230 		return (DDI_FAILURE);
231 	}
232 
233 	/*
234 	 * RR ring (Return Ring for RX and TX).
235 	 */
236 	ATGE_DB(("%s: %s() L1C_RR_RING_SZ : 0x%x", atgep->atge_name,
237 	    __func__, L1C_RR_RING_SZ));
238 
239 	dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_rr,
240 	    L1C_RR_RING_SZ, DDI_DMA_RDWR);
241 	l1c->atge_l1c_rr = dma;
242 	if (dma == NULL) {
243 		atge_error(atgep->atge_dip, "DMA allocation failed"
244 		    " for RX RR ring");
245 		return (DDI_FAILURE);
246 	}
247 
248 	/*
249 	 * SMB for statistics.
250 	 */
251 	ATGE_DB(("%s: %s() L1C_SMB_BLOCK_SZ : 0x%x", atgep->atge_name,
252 	    __func__, L1C_SMB_BLOCK_SZ));
253 
254 	dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_smb,
255 	    L1C_SMB_BLOCK_SZ, DDI_DMA_RDWR);
256 	l1c->atge_l1c_smb = dma;
257 	if (dma == NULL) {
258 		atge_error(atgep->atge_dip, "DMA allocation failed for SMB");
259 		return (DDI_FAILURE);
260 	}
261 
262 	atgep->atge_hw_stats = kmem_zalloc(sizeof (atge_l1c_smb_t), KM_SLEEP);
263 
264 	return (DDI_SUCCESS);
265 }
266 
267 void
268 atge_l1c_free_dma(atge_t *atgep)
269 {
270 	atge_l1c_data_t *l1c;
271 
272 	l1c = atgep->atge_private_data;
273 
274 	/*
275 	 * Free TX ring.
276 	 */
277 	if (atgep->atge_tx_ring != NULL) {
278 		atge_free_buffers(atgep->atge_tx_ring,  ATGE_TX_RING_CNT);
279 
280 		if (atgep->atge_tx_ring->r_desc_ring != NULL) {
281 			atge_free_a_dma_blk(atgep->atge_tx_ring->r_desc_ring);
282 		}
283 
284 		kmem_free(atgep->atge_tx_ring, sizeof (atge_ring_t));
285 		atgep->atge_tx_ring = NULL;
286 	}
287 
288 	if (l1c && l1c->atge_l1c_cmb != NULL) {
289 		atge_free_a_dma_blk(l1c->atge_l1c_cmb);
290 		l1c->atge_l1c_cmb = NULL;
291 	}
292 
293 	if (l1c && l1c->atge_l1c_rr != NULL) {
294 		atge_free_a_dma_blk(l1c->atge_l1c_rr);
295 		l1c->atge_l1c_rr = NULL;
296 	}
297 
298 	if (l1c && l1c->atge_l1c_smb != NULL) {
299 		atge_free_a_dma_blk(l1c->atge_l1c_smb);
300 		l1c->atge_l1c_smb = NULL;
301 	}
302 
303 	/*
304 	 * Free RX ring.
305 	 */
306 	if (l1c && l1c->atge_rx_ring != NULL) {
307 		atge_free_buffers(l1c->atge_rx_ring,  L1C_RX_RING_CNT);
308 
309 		if (l1c->atge_rx_ring->r_desc_ring != NULL) {
310 			atge_free_a_dma_blk(l1c->atge_rx_ring->r_desc_ring);
311 		}
312 
313 		kmem_free(l1c->atge_rx_ring, sizeof (atge_ring_t));
314 		l1c->atge_rx_ring = NULL;
315 	}
316 
317 	/*
318 	 * Free the memory allocated for gathering hw stats.
319 	 */
320 	if (atgep->atge_hw_stats != NULL) {
321 		kmem_free(atgep->atge_hw_stats, sizeof (atge_l1c_smb_t));
322 		atgep->atge_hw_stats = NULL;
323 	}
324 
325 	/*
326 	 * Free the private area.
327 	 */
328 	if (l1c != NULL) {
329 		kmem_free(l1c, sizeof (atge_l1c_data_t));
330 		atgep->atge_private_data = NULL;
331 	}
332 }
333 
334 void
335 atge_l1c_init_rx_ring(atge_t *atgep)
336 {
337 	atge_l1c_data_t *l1c;
338 	atge_dma_t *dma;
339 	l1c_rx_desc_t *rx;
340 	int i;
341 
342 	l1c = atgep->atge_private_data;
343 	l1c->atge_rx_ring->r_consumer = L1C_RX_RING_CNT - 1;
344 	dma = l1c->atge_rx_ring->r_desc_ring;
345 	bzero(dma->addr, L1C_RX_RING_SZ);
346 
347 	for (i = 0; i < L1C_RX_RING_CNT; i++) {
348 		rx = (l1c_rx_desc_t *)(dma->addr +
349 		    (i * sizeof (l1c_rx_desc_t)));
350 
351 		ATGE_PUT64(dma, &rx->addr,
352 		    l1c->atge_rx_ring->r_buf_tbl[i]->cookie.dmac_laddress);
353 		/* No length field. */
354 	}
355 
356 	DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
357 	/* Let controller know availability of new Rx buffers. */
358 	OUTL(atgep, ATGE_MBOX_RD0_PROD_IDX, l1c->atge_rx_ring->r_consumer);
359 }
360 
361 void
362 atge_l1c_init_tx_ring(atge_t *atgep)
363 {
364 	atgep->atge_tx_ring->r_producer = 0;
365 	atgep->atge_tx_ring->r_consumer = 0;
366 	atgep->atge_tx_ring->r_avail_desc = ATGE_TX_RING_CNT;
367 
368 	bzero(atgep->atge_tx_ring->r_desc_ring->addr, ATGE_TX_RING_SZ);
369 	DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, 0, DDI_DMA_SYNC_FORDEV);
370 }
371 
372 void
373 atge_l1c_init_rr_ring(atge_t *atgep)
374 {
375 	atge_l1c_data_t *l1c;
376 	atge_dma_t *dma;
377 
378 	l1c = atgep->atge_private_data;
379 	l1c->atge_l1c_rr_consumers = 0;
380 
381 	dma = l1c->atge_l1c_rr;
382 	bzero(dma->addr, L1C_RR_RING_SZ);
383 	DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
384 }
385 
386 void
387 atge_l1c_init_smb(atge_t *atgep)
388 {
389 	atge_l1c_data_t *l1c;
390 	atge_dma_t *dma;
391 
392 	l1c = atgep->atge_private_data;
393 	dma = l1c->atge_l1c_smb;
394 	bzero(dma->addr, L1C_SMB_BLOCK_SZ);
395 	DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
396 }
397 
398 void
399 atge_l1c_init_cmb(atge_t *atgep)
400 {
401 	atge_l1c_data_t *l1c;
402 	atge_dma_t *dma;
403 
404 	l1c = atgep->atge_private_data;
405 	dma = l1c->atge_l1c_cmb;
406 	bzero(dma->addr, L1C_CMB_BLOCK_SZ);
407 	DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
408 }
409 
410 void
411 atge_l1c_program_dma(atge_t *atgep)
412 {
413 	atge_l1c_data_t *l1c;
414 	atge_ring_t *r;
415 	uint32_t reg;
416 
417 	l1c = atgep->atge_private_data;
418 
419 	/*
420 	 * Clear WOL status and disable all WOL feature as WOL
421 	 * would interfere Rx operation under normal environments.
422 	 */
423 	(void) INL(atgep, ATGE_WOL_CFG);
424 	OUTL(atgep, ATGE_WOL_CFG, 0);
425 
426 	/* TX */
427 	r = atgep->atge_tx_ring;
428 	OUTL(atgep, L1C_TX_BASE_ADDR_HI,
429 	    ATGE_ADDR_HI(r->r_desc_ring->cookie.dmac_laddress));
430 	OUTL(atgep, L1C_TDL_HEAD_ADDR_LO,
431 	    ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress));
432 	/* We don't use high priority ring. */
433 	OUTL(atgep, L1C_TDH_HEAD_ADDR_LO, 0);
434 
435 	/* RX */
436 	r = l1c->atge_rx_ring;
437 	OUTL(atgep, L1C_RX_BASE_ADDR_HI,
438 	    ATGE_ADDR_HI(r->r_desc_ring->cookie.dmac_laddress));
439 	OUTL(atgep, L1C_RD0_HEAD_ADDR_LO,
440 	    ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress));
441 	/* We use one Rx ring. */
442 	OUTL(atgep, L1C_RD1_HEAD_ADDR_LO, 0);
443 	OUTL(atgep, L1C_RD2_HEAD_ADDR_LO, 0);
444 	OUTL(atgep, L1C_RD3_HEAD_ADDR_LO, 0);
445 
446 	/* RR Ring */
447 	/*
448 	 * Let hardware split jumbo frames into alc_max_buf_sized chunks.
449 	 * if it do not fit the buffer size. Rx return descriptor holds
450 	 * a counter that indicates how many fragments were made by the
451 	 * hardware. The buffer size should be multiple of 8 bytes.
452 	 * Since hardware has limit on the size of buffer size, always
453 	 * use the maximum value.
454 	 * For strict-alignment architectures make sure to reduce buffer
455 	 * size by 8 bytes to make room for alignment fixup.
456 	 */
457 	OUTL(atgep, L1C_RX_BUF_SIZE, RX_BUF_SIZE_MAX); /* XXX */
458 
459 	/* Set Rx return descriptor base addresses. */
460 	OUTL(atgep, L1C_RRD0_HEAD_ADDR_LO,
461 	    ATGE_ADDR_LO(l1c->atge_l1c_rr->cookie.dmac_laddress));
462 	/* We use one Rx return ring. */
463 	OUTL(atgep, L1C_RRD1_HEAD_ADDR_LO, 0);
464 	OUTL(atgep, L1C_RRD2_HEAD_ADDR_LO, 0);
465 	OUTL(atgep, L1C_RRD3_HEAD_ADDR_LO, 0);
466 
467 	/* CMB */
468 	OUTL(atgep, L1C_CMB_BASE_ADDR_LO,
469 	    ATGE_ADDR_LO(l1c->atge_l1c_cmb->cookie.dmac_laddress));
470 
471 	/* SMB */
472 	OUTL(atgep, L1C_SMB_BASE_ADDR_HI,
473 	    ATGE_ADDR_HI(l1c->atge_l1c_smb->cookie.dmac_laddress));
474 	OUTL(atgep, L1C_SMB_BASE_ADDR_LO,
475 	    ATGE_ADDR_LO(l1c->atge_l1c_smb->cookie.dmac_laddress));
476 
477 	/*
478 	 * Set RX return ring (RR) counter.
479 	 */
480 	/* Set Rx descriptor counter. */
481 	OUTL(atgep, L1C_RD_RING_CNT,
482 	    (L1C_RX_RING_CNT << RD_RING_CNT_SHIFT) & RD_RING_CNT_MASK);
483 	/* Set Rx return descriptor counter. */
484 	OUTL(atgep, L1C_RRD_RING_CNT,
485 	    (L1C_RR_RING_CNT << RRD_RING_CNT_SHIFT) & RRD_RING_CNT_MASK);
486 
487 	/*
488 	 * Set TX descriptor counter.
489 	 */
490 	OUTL(atgep, L1C_TD_RING_CNT,
491 	    (ATGE_TX_RING_CNT << TD_RING_CNT_SHIFT) & TD_RING_CNT_MASK);
492 
493 	switch (ATGE_DID(atgep)) {
494 	case ATGE_CHIP_AR8152V1_DEV_ID:
495 		/* Reconfigure SRAM - Vendor magic. */
496 		OUTL(atgep, L1C_SRAM_RX_FIFO_LEN, 0x000002A0);
497 		OUTL(atgep, L1C_SRAM_TX_FIFO_LEN, 0x00000100);
498 		OUTL(atgep, L1C_SRAM_RX_FIFO_ADDR, 0x029F0000);
499 		OUTL(atgep, L1C_SRAM_RD_ADDR, 0x02BF02A0);
500 		OUTL(atgep, L1C_SRAM_TX_FIFO_ADDR, 0x03BF02C0);
501 		OUTL(atgep, L1C_SRAM_TRD_ADDR, 0x03DF03C0);
502 		OUTL(atgep, L1C_TXF_WATER_MARK, 0x00000000);
503 		OUTL(atgep, L1C_RD_DMA_CFG, 0x00000000);
504 		break;
505 	}
506 
507 	/*
508 	 * Inform hardware that we have loaded DMA registers.
509 	 */
510 	OUTL(atgep, ATGE_DMA_BLOCK, DMA_BLOCK_LOAD);
511 
512 	/* Configure interrupt moderation timer. */
513 	reg = ATGE_USECS(atgep->atge_int_rx_mod) << IM_TIMER_RX_SHIFT;
514 	reg |= ATGE_USECS(atgep->atge_int_tx_mod) << IM_TIMER_TX_SHIFT;
515 	OUTL(atgep, ATGE_IM_TIMER, reg);
516 	/*
517 	 * We don't want to automatic interrupt clear as task queue
518 	 * for the interrupt should know interrupt status.
519 	 */
520 	reg = 0;
521 	if (ATGE_USECS(atgep->atge_int_rx_mod) != 0)
522 		reg |= MASTER_IM_RX_TIMER_ENB;
523 	if (ATGE_USECS(atgep->atge_int_tx_mod) != 0)
524 		reg |= MASTER_IM_TX_TIMER_ENB;
525 	OUTL(atgep, ATGE_MASTER_CFG, reg);
526 }
527 
528 void
529 atge_l1c_clear_stats(atge_t *atgep)
530 {
531 	atge_l1c_smb_t smb;
532 	uint32_t *reg;
533 	int i;
534 
535 	/*
536 	 * Clear RX stats first.
537 	 */
538 	i = 0;
539 	reg = &smb.rx_frames;
540 	while (reg++ <= &smb.rx_pkts_filtered) {
541 		(void) INL(atgep, ATGE_RX_MIB_BASE + i);
542 		i += sizeof (uint32_t);
543 	}
544 
545 	/*
546 	 * Clear TX stats.
547 	 */
548 	i = 0;
549 	reg = &smb.tx_frames;
550 	while (reg++ <= &smb.tx_mcast_bytes) {
551 		(void) INL(atgep, ATGE_TX_MIB_BASE + i);
552 		i += sizeof (uint32_t);
553 	}
554 }
555 
556 void
557 atge_l1c_gather_stats(atge_t *atgep)
558 {
559 	atge_l1c_data_t *l1c;
560 	atge_dma_t *dma;
561 	atge_l1c_smb_t *stat;
562 	atge_l1c_smb_t *smb;
563 
564 	ASSERT(atgep != NULL);
565 
566 	l1c = atgep->atge_private_data;
567 	dma = l1c->atge_l1c_smb;
568 	DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORKERNEL);
569 	stat = (atge_l1c_smb_t *)atgep->atge_hw_stats;
570 	smb = (atge_l1c_smb_t *)dma->addr;
571 
572 	/* Rx stats. */
573 	stat->rx_frames += smb->rx_frames;
574 	stat->rx_bcast_frames += smb->rx_bcast_frames;
575 	stat->rx_mcast_frames += smb->rx_mcast_frames;
576 	stat->rx_pause_frames += smb->rx_pause_frames;
577 	stat->rx_control_frames += smb->rx_control_frames;
578 	stat->rx_crcerrs += smb->rx_crcerrs;
579 	stat->rx_lenerrs += smb->rx_lenerrs;
580 	stat->rx_bytes += smb->rx_bytes;
581 	stat->rx_runts += smb->rx_runts;
582 	stat->rx_fragments += smb->rx_fragments;
583 	stat->rx_pkts_64 += smb->rx_pkts_64;
584 	stat->rx_pkts_65_127 += smb->rx_pkts_65_127;
585 	stat->rx_pkts_128_255 += smb->rx_pkts_128_255;
586 	stat->rx_pkts_256_511 += smb->rx_pkts_256_511;
587 	stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023;
588 	stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518;
589 	stat->rx_pkts_1519_max += smb->rx_pkts_1519_max;
590 	stat->rx_pkts_truncated += smb->rx_pkts_truncated;
591 	stat->rx_fifo_oflows += smb->rx_fifo_oflows;
592 	stat->rx_alignerrs += smb->rx_alignerrs;
593 	stat->rx_bcast_bytes += smb->rx_bcast_bytes;
594 	stat->rx_mcast_bytes += smb->rx_mcast_bytes;
595 	stat->rx_pkts_filtered += smb->rx_pkts_filtered;
596 
597 	/* Tx stats. */
598 	stat->tx_frames += smb->tx_frames;
599 	stat->tx_bcast_frames += smb->tx_bcast_frames;
600 	stat->tx_mcast_frames += smb->tx_mcast_frames;
601 	stat->tx_pause_frames += smb->tx_pause_frames;
602 	stat->tx_excess_defer += smb->tx_excess_defer;
603 	stat->tx_control_frames += smb->tx_control_frames;
604 	stat->tx_deferred += smb->tx_deferred;
605 	stat->tx_bytes += smb->tx_bytes;
606 	stat->tx_pkts_64 += smb->tx_pkts_64;
607 	stat->tx_pkts_65_127 += smb->tx_pkts_65_127;
608 	stat->tx_pkts_128_255 += smb->tx_pkts_128_255;
609 	stat->tx_pkts_256_511 += smb->tx_pkts_256_511;
610 	stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023;
611 	stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518;
612 	stat->tx_pkts_1519_max += smb->tx_pkts_1519_max;
613 	stat->tx_single_colls += smb->tx_single_colls;
614 	stat->tx_multi_colls += smb->tx_multi_colls;
615 	stat->tx_late_colls += smb->tx_late_colls;
616 	stat->tx_excess_colls += smb->tx_excess_colls;
617 	stat->tx_underrun += smb->tx_underrun;
618 	stat->tx_desc_underrun += smb->tx_desc_underrun;
619 	stat->tx_lenerrs += smb->tx_lenerrs;
620 	stat->tx_pkts_truncated += smb->tx_pkts_truncated;
621 	stat->tx_bcast_bytes += smb->tx_bcast_bytes;
622 	stat->tx_mcast_bytes += smb->tx_mcast_bytes;
623 
624 	/*
625 	 * Update global counters in atge_t.
626 	 */
627 	atgep->atge_brdcstrcv += smb->rx_bcast_frames;
628 	atgep->atge_multircv += smb->rx_mcast_frames;
629 	atgep->atge_multixmt += smb->tx_mcast_frames;
630 	atgep->atge_brdcstxmt += smb->tx_bcast_frames;
631 
632 	atgep->atge_align_errors += smb->rx_alignerrs;
633 	atgep->atge_fcs_errors += smb->rx_crcerrs;
634 	atgep->atge_defer_xmts += smb->tx_deferred;
635 	atgep->atge_first_collisions += smb->tx_single_colls;
636 	atgep->atge_multi_collisions += smb->tx_multi_colls * 2;
637 	atgep->atge_tx_late_collisions += smb->tx_late_colls;
638 	atgep->atge_ex_collisions += smb->tx_excess_colls;
639 	atgep->atge_toolong_errors += smb->rx_lenerrs;
640 	atgep->atge_overflow += smb->rx_fifo_oflows;
641 	atgep->atge_underflow += (smb->tx_underrun + smb->tx_desc_underrun);
642 	atgep->atge_runt += smb->rx_runts;
643 
644 
645 	atgep->atge_collisions += smb->tx_single_colls +
646 	    smb->tx_multi_colls * 2 + smb->tx_late_colls;
647 
648 	/*
649 	 * tx_pkts_truncated counter looks suspicious. It constantly
650 	 * increments with no sign of Tx errors. Hence we don't factor it.
651 	 */
652 	atgep->atge_macxmt_errors += smb->tx_late_colls + smb->tx_underrun;
653 
654 	atgep->atge_macrcv_errors += smb->rx_crcerrs + smb->rx_lenerrs +
655 	    smb->rx_runts + smb->rx_pkts_truncated +
656 	    smb->rx_alignerrs;
657 
658 	smb->updated = 0;
659 	DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
660 }
661 
662 void
663 atge_l1c_stop_tx_mac(atge_t *atgep)
664 {
665 	uint32_t reg;
666 	int t;
667 
668 	ATGE_DB(("%s: %s() called", atgep->atge_name, __func__));
669 
670 	reg = INL(atgep, ATGE_MAC_CFG);
671 	if ((reg & ATGE_CFG_TX_ENB) != 0) {
672 		reg &= ~ATGE_CFG_TX_ENB;
673 		OUTL(atgep, ATGE_MAC_CFG, reg);
674 	}
675 
676 	/* Stop TX DMA engine. */
677 	reg = INL(atgep, ATGE_DMA_CFG);
678 	if ((reg & DMA_CFG_RD_ENB) != 0) {
679 		reg &= ~DMA_CFG_RD_ENB;
680 		OUTL(atgep, ATGE_DMA_CFG, reg);
681 	}
682 
683 	for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
684 		if ((INL(atgep, ATGE_IDLE_STATUS) &
685 		    (IDLE_STATUS_TXMAC | IDLE_STATUS_DMARD)) == 0)
686 			break;
687 
688 		drv_usecwait(10);
689 	}
690 
691 	if (t == 0) {
692 		/* This should be an FMA event. */
693 		atge_error(atgep->atge_dip, "stopping TX DMA Engine timeout");
694 	}
695 }
696 
697 void
698 atge_l1c_stop_rx_mac(atge_t *atgep)
699 {
700 	uint32_t reg;
701 	int t;
702 
703 	ATGE_DB(("%s: %s() called", atgep->atge_name, __func__));
704 
705 	reg = INL(atgep, ATGE_MAC_CFG);
706 	if ((reg & ATGE_CFG_RX_ENB) != 0) {
707 		reg &= ~ATGE_CFG_RX_ENB;
708 		OUTL(atgep, ATGE_MAC_CFG, reg);
709 	}
710 
711 	/* Stop RX DMA engine. */
712 	reg = INL(atgep, ATGE_DMA_CFG);
713 	if ((reg & DMA_CFG_WR_ENB) != 0) {
714 		reg &= ~DMA_CFG_WR_ENB;
715 		OUTL(atgep, ATGE_DMA_CFG, reg);
716 	}
717 
718 	for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
719 		if ((INL(atgep, ATGE_IDLE_STATUS) &
720 		    (IDLE_STATUS_RXMAC | IDLE_STATUS_DMAWR)) == 0)
721 			break;
722 		drv_usecwait(10);
723 	}
724 
725 	if (t == 0) {
726 		/* This should be an FMA event. */
727 		atge_error(atgep->atge_dip, " stopping RX DMA Engine timeout");
728 	}
729 }
730 
731 /*
732  * Receives (consumes) packets.
733  */
734 static mblk_t *
735 atge_l1c_rx(atge_t *atgep)
736 {
737 	atge_l1c_data_t *l1c;
738 	mblk_t *mp = NULL, *rx_head = NULL, *rx_tail = NULL;
739 	l1c_rx_rdesc_t *rx_rr;
740 	uint32_t rdinfo, status, totlen, pktlen, slotlen;
741 	int nsegs, rx_cons = 0, cnt;
742 	atge_dma_t *buf;
743 	uchar_t *bufp;
744 	int sync = 0;
745 
746 	l1c = atgep->atge_private_data;
747 	ASSERT(l1c != NULL);
748 
749 	DMA_SYNC(l1c->atge_l1c_rr, 0, 0, DDI_DMA_SYNC_FORKERNEL);
750 	for (;;) {
751 		rx_rr = (l1c_rx_rdesc_t *)(l1c->atge_l1c_rr->addr +
752 		    (l1c->atge_l1c_rr_consumers * sizeof (l1c_rx_rdesc_t)));
753 
754 		rdinfo = ATGE_GET32(l1c->atge_l1c_rr, &rx_rr->rdinfo);
755 		status = ATGE_GET32(l1c->atge_l1c_rr, &rx_rr->status);
756 
757 		rx_cons = L1C_RRD_RD_IDX(rdinfo);
758 		nsegs = L1C_RRD_RD_CNT(rdinfo);
759 		totlen = L1C_RRD_BYTES(status);
760 
761 		ATGE_DB(("%s: %s() PKT -- rdinfo : 0x%x,"
762 		    "status : 0x%x, totlen : %d,"
763 		    " rx_cons : %d, nsegs : %d", atgep->atge_name, __func__,
764 		    rdinfo, status, totlen, rx_cons, nsegs));
765 
766 		if ((status & L1C_RRD_VALID) == 0) {
767 			break;
768 		}
769 
770 		if ((status & (L1C_RRD_ERR_CRC | L1C_RRD_ERR_ALIGN |
771 		    L1C_RRD_ERR_TRUNC | L1C_RRD_ERR_RUNT |
772 		    L1C_RRD_ERR_ICMP | L1C_RRD_ERR_LENGTH)) != 0) {
773 			atge_error(atgep->atge_dip, "errored pkt");
774 
775 			l1c->atge_rx_ring->r_consumer += nsegs;
776 			l1c->atge_rx_ring->r_consumer %= L1C_RX_RING_CNT;
777 			break;
778 		}
779 
780 		ASSERT(rx_cons >= 0 && rx_cons <= L1C_RX_RING_CNT);
781 
782 		mp = allocb(totlen + L1C_HEADROOM, BPRI_MED);
783 		if (mp != NULL) {
784 			mp->b_rptr += L1C_HEADROOM;
785 			bufp = mp->b_rptr;
786 			mp->b_wptr = bufp + totlen;
787 			mp->b_next = NULL;
788 
789 			atgep->atge_ipackets++;
790 			atgep->atge_rbytes += totlen;
791 
792 			/*
793 			 * If there are more than one segments, then the first
794 			 * segment should be of size MTU. We couldn't verify
795 			 * this as our driver does not support changing MTU
796 			 * or Jumbo Frames.
797 			 */
798 			if (nsegs > 1) {
799 				slotlen = atgep->atge_mtu;
800 			} else {
801 				slotlen = totlen;
802 			}
803 		} else {
804 			ATGE_DB(("%s: %s() PKT mp == NULL totlen : %d",
805 			    atgep->atge_name, __func__, totlen));
806 
807 			if (slotlen > atgep->atge_rx_buf_len) {
808 				atgep->atge_toolong_errors++;
809 			} else if (mp == NULL) {
810 				atgep->atge_norcvbuf++;
811 			}
812 
813 			rx_rr->status = 0;
814 			break;
815 		}
816 
817 		for (cnt = 0, pktlen = 0; cnt < nsegs; cnt++) {
818 			buf = l1c->atge_rx_ring->r_buf_tbl[rx_cons];
819 
820 			slotlen = min(atgep->atge_max_frame_size, totlen);
821 
822 			bcopy(buf->addr, (bufp + pktlen), slotlen);
823 			pktlen += slotlen;
824 			totlen -= slotlen;
825 
826 			ATGE_DB(("%s: %s() len : %d, rxcons : %d, pktlen : %d",
827 			    atgep->atge_name, __func__, slotlen, rx_cons,
828 			    pktlen));
829 
830 			ATGE_INC_SLOT(rx_cons, L1C_RX_RING_CNT);
831 		}
832 
833 		if (rx_tail == NULL) {
834 			rx_head = rx_tail = mp;
835 		} else {
836 			rx_tail->b_next = mp;
837 			rx_tail = mp;
838 		}
839 
840 		if (cnt != nsegs) {
841 			l1c->atge_rx_ring->r_consumer += nsegs;
842 			l1c->atge_rx_ring->r_consumer %= L1C_RX_RING_CNT;
843 		} else {
844 			l1c->atge_rx_ring->r_consumer = rx_cons;
845 		}
846 
847 		/*
848 		 * Tell the chip that this RR can be reused.
849 		 */
850 		rx_rr->status = 0;
851 
852 		ATGE_INC_SLOT(l1c->atge_l1c_rr_consumers, L1C_RR_RING_CNT);
853 		sync++;
854 	}
855 
856 	if (sync) {
857 		DMA_SYNC(l1c->atge_rx_ring->r_desc_ring, 0, 0,
858 		    DDI_DMA_SYNC_FORDEV);
859 
860 		DMA_SYNC(l1c->atge_l1c_rr, 0, 0, DDI_DMA_SYNC_FORDEV);
861 		/*
862 		 * Let controller know availability of new Rx buffers.
863 		 */
864 		OUTL(atgep, ATGE_MBOX_RD0_PROD_IDX,
865 		    l1c->atge_rx_ring->r_consumer);
866 
867 		ATGE_DB(("%s: %s() PKT Recved -> r_consumer : %d, rx_cons : %d"
868 		    " atge_l1c_rr_consumers : %d",
869 		    atgep->atge_name, __func__, l1c->atge_rx_ring->r_consumer,
870 		    rx_cons, l1c->atge_l1c_rr_consumers));
871 	}
872 
873 
874 	return (rx_head);
875 }
876 
877 /*
878  * The interrupt handler for L1C chip.
879  */
880 /*ARGSUSED*/
881 uint_t
882 atge_l1c_interrupt(caddr_t arg1, caddr_t arg2)
883 {
884 	atge_t *atgep = (void *)arg1;
885 	mblk_t *rx_head = NULL;
886 	uint32_t status;
887 	int resched = 0;
888 
889 	ASSERT(atgep != NULL);
890 
891 	mutex_enter(&atgep->atge_intr_lock);
892 
893 	if (atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) {
894 		mutex_exit(&atgep->atge_intr_lock);
895 		return (DDI_INTR_UNCLAIMED);
896 	}
897 
898 	status = INL(atgep, ATGE_INTR_STATUS);
899 	if (status == 0 || (status & atgep->atge_intrs) == 0) {
900 		mutex_exit(&atgep->atge_intr_lock);
901 
902 		if (atgep->atge_flags & ATGE_FIXED_TYPE)
903 			return (DDI_INTR_UNCLAIMED);
904 
905 		return (DDI_INTR_CLAIMED);
906 	}
907 
908 	ATGE_DB(("%s: %s() entry status : %x",
909 	    atgep->atge_name, __func__, status));
910 
911 	/*
912 	 * Disable interrupts.
913 	 */
914 	if (status & L1C_INTR_GPHY) {
915 		/* clear PHY interrupt source before we ack interrupts */
916 		(void) atge_mii_read(atgep,
917 		    atgep->atge_phyaddr, ATGE_ISR_ACK_GPHY);
918 	}
919 
920 	OUTL(atgep, ATGE_INTR_STATUS, status | L1C_INTR_DIS_INT);
921 	FLUSH(atgep, ATGE_INTR_STATUS);
922 
923 	/*
924 	 * Check if chip is running, only then do the work.
925 	 */
926 	if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
927 		atge_l1c_data_t *l1c;
928 
929 		l1c = atgep->atge_private_data;
930 
931 		ATGE_DB(("%s: %s() atge_l1c_intr_status : %x, "
932 		    "atge_l1c_rx_prod_cons : %d, atge_l1c_tx_prod_cons : %d"
933 		    " atge_l1c_rr_consumers : %d",
934 		    atgep->atge_name, __func__, l1c->atge_l1c_intr_status,
935 		    l1c->atge_l1c_rx_prod_cons, l1c->atge_l1c_tx_prod_cons,
936 		    l1c->atge_l1c_rr_consumers));
937 
938 		if (status & L1C_INTR_SMB)
939 			atge_l1c_gather_stats(atgep);
940 
941 		/*
942 		 * Check for errors.
943 		 */
944 		if (status & (L1C_INTR_DMA_RD_TO_RST |
945 		    L1C_INTR_DMA_WR_TO_RST | L1C_INTR_TXQ_TO_RST)) {
946 			/* This should be an FMA event. */
947 			atge_error(atgep->atge_dip,
948 			    "L1C chip detected a fatal error, "
949 			    "interrupt status: %x", status);
950 
951 			if (status & L1C_INTR_DMA_RD_TO_RST) {
952 				atge_error(atgep->atge_dip,
953 				    "DMA read error");
954 			}
955 			if (status & L1C_INTR_DMA_WR_TO_RST) {
956 				atge_error(atgep->atge_dip,
957 				    "DMA write error");
958 			}
959 			if (status & L1C_INTR_TXQ_TO_RST) {
960 				atge_error(atgep->atge_dip,
961 				    "Transmit queue error");
962 			}
963 
964 			/* This should be an FMA event. */
965 			atge_device_stop(atgep);
966 			/*
967 			 * Device has failed fatally.
968 			 * It will not be restarted by the driver.
969 			 */
970 			goto done;
971 
972 		}
973 
974 		rx_head = atge_l1c_rx(atgep);
975 		if (status & L1C_INTR_TX_PKT) {
976 			int cons;
977 
978 			mutex_enter(&atgep->atge_tx_lock);
979 			cons = INL(atgep, ATGE_MBOX_TD_CONS_IDX) >> 16;
980 			atge_tx_reclaim(atgep, cons);
981 			if (atgep->atge_tx_resched) {
982 				atgep->atge_tx_resched = 0;
983 				resched = 1;
984 			}
985 
986 			mutex_exit(&atgep->atge_tx_lock);
987 		}
988 	}
989 
990 	/* Re-enable interrupts. */
991 	OUTL(atgep, ATGE_INTR_STATUS, 0);
992 
993 done:
994 	mutex_exit(&atgep->atge_intr_lock);
995 
996 	if (status & L1C_INTR_GPHY) {
997 		/* link down */
998 		ATGE_DB(("%s: %s() MII_CHECK Performed",
999 		    atgep->atge_name, __func__));
1000 		mii_check(atgep->atge_mii);
1001 	}
1002 
1003 	/*
1004 	 * Pass the list of packets received from chip to MAC layer.
1005 	 */
1006 	if (rx_head) {
1007 		mac_rx(atgep->atge_mh, 0, rx_head);
1008 	}
1009 
1010 	/*
1011 	 * Let MAC start sending pkts if the downstream was asked to pause.
1012 	 */
1013 	if (resched)
1014 		mac_tx_update(atgep->atge_mh);
1015 
1016 	return (DDI_INTR_CLAIMED);
1017 }
1018 
1019 void
1020 atge_l1c_send_packet(atge_ring_t *r)
1021 {
1022 	atge_t *atgep;
1023 
1024 	atgep = r->r_atge;
1025 
1026 	mutex_enter(&atgep->atge_mbox_lock);
1027 	/* Sync descriptors. */
1028 	DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, 0, DDI_DMA_SYNC_FORDEV);
1029 	/* Kick. Assume we're using normal Tx priority queue. */
1030 	OUTL(atgep, ATGE_MBOX_TD_PROD_IDX,
1031 	    (atgep->atge_tx_ring->r_producer << MBOX_TD_PROD_LO_IDX_SHIFT) &
1032 	    MBOX_TD_PROD_LO_IDX_MASK);
1033 	mutex_exit(&atgep->atge_mbox_lock);
1034 }
1035