xref: /titanic_52/usr/src/uts/common/io/xge/drv/xgell.c (revision bd0f52d78d701efcad2c460df61b45677d041c35)
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 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  *  Copyright (c) 2002-2005 Neterion, Inc.
31  *  All right Reserved.
32  *
33  *  FileName :    xgell.c
34  *
35  *  Description:  Xge Link Layer data path implementation
36  *
37  */
38 
39 #include "xgell.h"
40 
41 #include <netinet/ip.h>
42 #include <netinet/tcp.h>
43 #include <netinet/udp.h>
44 
45 #define	XGELL_MAX_FRAME_SIZE(hldev)	((hldev)->config.mtu +	\
46     sizeof (struct ether_vlan_header))
47 
48 #define	HEADROOM		2	/* for DIX-only packets */
49 
50 void header_free_func(void *arg) { }
51 frtn_t header_frtn = {header_free_func, NULL};
52 
53 /* DMA attributes used for Tx side */
54 static struct ddi_dma_attr tx_dma_attr = {
55 	DMA_ATTR_V0,			/* dma_attr_version */
56 	0x0ULL,				/* dma_attr_addr_lo */
57 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_addr_hi */
58 	0xFFFFFFFFULL,			/* dma_attr_count_max */
59 	0x1ULL,				/* dma_attr_align */
60 	0xFFF,				/* dma_attr_burstsizes */
61 	1,				/* dma_attr_minxfer */
62 	0xFFFFFFFFULL,			/* dma_attr_maxxfer */
63 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_seg */
64 	18,				/* dma_attr_sgllen */
65 	1,				/* dma_attr_granular */
66 	0				/* dma_attr_flags */
67 };
68 
69 /* Aligned DMA attributes used for Tx side */
70 struct ddi_dma_attr tx_dma_attr_align = {
71 	DMA_ATTR_V0,			/* dma_attr_version */
72 	0x0ULL,				/* dma_attr_addr_lo */
73 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_addr_hi */
74 	0xFFFFFFFFULL,			/* dma_attr_count_max */
75 	4096,				/* dma_attr_align */
76 	0xFFF,				/* dma_attr_burstsizes */
77 	1,				/* dma_attr_minxfer */
78 	0xFFFFFFFFULL,			/* dma_attr_maxxfer */
79 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_seg */
80 	4,				/* dma_attr_sgllen */
81 	1,				/* dma_attr_granular */
82 	0				/* dma_attr_flags */
83 };
84 
85 /*
86  * DMA attributes used when using ddi_dma_mem_alloc to
87  * allocat HAL descriptors and Rx buffers during replenish
88  */
89 static struct ddi_dma_attr hal_dma_attr = {
90 	DMA_ATTR_V0,			/* dma_attr_version */
91 	0x0ULL,				/* dma_attr_addr_lo */
92 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_addr_hi */
93 	0xFFFFFFFFULL,			/* dma_attr_count_max */
94 	0x1ULL,				/* dma_attr_align */
95 	0xFFF,				/* dma_attr_burstsizes */
96 	1,				/* dma_attr_minxfer */
97 	0xFFFFFFFFULL,			/* dma_attr_maxxfer */
98 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_seg */
99 	1,				/* dma_attr_sgllen */
100 	1,				/* dma_attr_granular */
101 	0				/* dma_attr_flags */
102 };
103 
104 /*
105  * Aligned DMA attributes used when using ddi_dma_mem_alloc to
106  * allocat HAL descriptors and Rx buffers during replenish
107  */
108 struct ddi_dma_attr hal_dma_attr_aligned = {
109 	DMA_ATTR_V0,			/* dma_attr_version */
110 	0x0ULL,				/* dma_attr_addr_lo */
111 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_addr_hi */
112 	0xFFFFFFFFULL,			/* dma_attr_count_max */
113 	4096,				/* dma_attr_align */
114 	0xFFF,				/* dma_attr_burstsizes */
115 	1,				/* dma_attr_minxfer */
116 	0xFFFFFFFFULL,			/* dma_attr_maxxfer */
117 	0xFFFFFFFFFFFFFFFFULL,		/* dma_attr_seg */
118 	1,				/* dma_attr_sgllen */
119 	1,				/* dma_attr_granular */
120 	0				/* dma_attr_flags */
121 };
122 
123 struct ddi_dma_attr *p_hal_dma_attr = &hal_dma_attr;
124 struct ddi_dma_attr *p_hal_dma_attr_aligned = &hal_dma_attr_aligned;
125 
126 static int		xgell_m_stat(void *, uint_t, uint64_t *);
127 static int		xgell_m_start(void *);
128 static void		xgell_m_stop(void *);
129 static int		xgell_m_promisc(void *, boolean_t);
130 static int		xgell_m_multicst(void *, boolean_t, const uint8_t *);
131 static int		xgell_m_unicst(void *, const uint8_t *);
132 static void		xgell_m_ioctl(void *, queue_t *, mblk_t *);
133 static mblk_t 		*xgell_m_tx(void *, mblk_t *);
134 static boolean_t	xgell_m_getcapab(void *, mac_capab_t, void *);
135 
136 #define	XGELL_M_CALLBACK_FLAGS	(MC_IOCTL | MC_GETCAPAB)
137 
138 static mac_callbacks_t xgell_m_callbacks = {
139 	XGELL_M_CALLBACK_FLAGS,
140 	xgell_m_stat,
141 	xgell_m_start,
142 	xgell_m_stop,
143 	xgell_m_promisc,
144 	xgell_m_multicst,
145 	xgell_m_unicst,
146 	xgell_m_tx,
147 	NULL,
148 	xgell_m_ioctl,
149 	xgell_m_getcapab
150 };
151 
152 /*
153  * xge_device_poll
154  *
155  * Cyclic should call me every 1s. xge_callback_event_queued should call me
156  * when HAL hope event was rescheduled.
157  */
158 /*ARGSUSED*/
159 void
160 xge_device_poll(void *data)
161 {
162 	xgelldev_t *lldev = xge_hal_device_private(data);
163 
164 	mutex_enter(&lldev->genlock);
165 	if (lldev->is_initialized) {
166 		xge_hal_device_poll(data);
167 		lldev->timeout_id = timeout(xge_device_poll, data,
168 		    XGE_DEV_POLL_TICKS);
169 	} else if (lldev->in_reset == 1) {
170 		lldev->timeout_id = timeout(xge_device_poll, data,
171 		    XGE_DEV_POLL_TICKS);
172 	} else {
173 		lldev->timeout_id = 0;
174 	}
175 	mutex_exit(&lldev->genlock);
176 }
177 
178 /*
179  * xge_device_poll_now
180  *
181  * Will call xge_device_poll() immediately
182  */
183 void
184 xge_device_poll_now(void *data)
185 {
186 	xgelldev_t *lldev = xge_hal_device_private(data);
187 
188 	mutex_enter(&lldev->genlock);
189 	if (lldev->is_initialized) {
190 		xge_hal_device_poll(data);
191 	}
192 	mutex_exit(&lldev->genlock);
193 }
194 
195 /*
196  * xgell_callback_link_up
197  *
198  * This function called by HAL to notify HW link up state change.
199  */
200 void
201 xgell_callback_link_up(void *userdata)
202 {
203 	xgelldev_t *lldev = (xgelldev_t *)userdata;
204 
205 	mac_link_update(lldev->mh, LINK_STATE_UP);
206 }
207 
208 /*
209  * xgell_callback_link_down
210  *
211  * This function called by HAL to notify HW link down state change.
212  */
213 void
214 xgell_callback_link_down(void *userdata)
215 {
216 	xgelldev_t *lldev = (xgelldev_t *)userdata;
217 
218 	mac_link_update(lldev->mh, LINK_STATE_DOWN);
219 }
220 
221 /*
222  * xgell_rx_buffer_replenish_all
223  *
224  * To replenish all freed dtr(s) with buffers in free pool. It's called by
225  * xgell_rx_buffer_recycle() or xgell_rx_1b_compl().
226  * Must be called with pool_lock held.
227  */
228 static void
229 xgell_rx_buffer_replenish_all(xgelldev_t *lldev)
230 {
231 	xge_hal_dtr_h dtr;
232 	xgell_rx_buffer_t *rx_buffer;
233 	xgell_rxd_priv_t *rxd_priv;
234 
235 	xge_assert(mutex_owned(&lldev->bf_pool.pool_lock));
236 
237 	while ((lldev->bf_pool.free > 0) &&
238 	    (xge_hal_ring_dtr_reserve(lldev->ring_main.channelh, &dtr) ==
239 	    XGE_HAL_OK)) {
240 		rx_buffer = lldev->bf_pool.head;
241 		lldev->bf_pool.head = rx_buffer->next;
242 		lldev->bf_pool.free--;
243 
244 		xge_assert(rx_buffer);
245 		xge_assert(rx_buffer->dma_addr);
246 
247 		rxd_priv = (xgell_rxd_priv_t *)
248 		    xge_hal_ring_dtr_private(lldev->ring_main.channelh, dtr);
249 		xge_hal_ring_dtr_1b_set(dtr, rx_buffer->dma_addr,
250 		    lldev->bf_pool.size);
251 
252 		rxd_priv->rx_buffer = rx_buffer;
253 		xge_hal_ring_dtr_post(lldev->ring_main.channelh, dtr);
254 	}
255 }
256 
257 /*
258  * xgell_rx_buffer_release
259  *
260  * The only thing done here is to put the buffer back to the pool.
261  * Calling this function need be protected by mutex, bf_pool.pool_lock.
262  */
263 static void
264 xgell_rx_buffer_release(xgell_rx_buffer_t *rx_buffer)
265 {
266 	xgelldev_t *lldev = rx_buffer->lldev;
267 
268 	xge_assert(mutex_owned(&lldev->bf_pool.pool_lock));
269 
270 	/* Put the buffer back to pool */
271 	rx_buffer->next = lldev->bf_pool.head;
272 	lldev->bf_pool.head = rx_buffer;
273 
274 	lldev->bf_pool.free++;
275 }
276 
277 /*
278  * xgell_rx_buffer_recycle
279  *
280  * Called by desballoc() to "free" the resource.
281  * We will try to replenish all descripters.
282  */
283 static void
284 xgell_rx_buffer_recycle(char *arg)
285 {
286 	xgell_rx_buffer_t *rx_buffer = (xgell_rx_buffer_t *)arg;
287 	xgelldev_t *lldev = rx_buffer->lldev;
288 
289 	mutex_enter(&lldev->bf_pool.pool_lock);
290 
291 	xgell_rx_buffer_release(rx_buffer);
292 	lldev->bf_pool.post--;
293 
294 	/*
295 	 * Before finding a good way to set this hiwat, just always call to
296 	 * replenish_all. *TODO*
297 	 */
298 	if (lldev->is_initialized != 0) {
299 		xgell_rx_buffer_replenish_all(lldev);
300 	}
301 
302 	mutex_exit(&lldev->bf_pool.pool_lock);
303 }
304 
305 /*
306  * xgell_rx_buffer_alloc
307  *
308  * Allocate one rx buffer and return with the pointer to the buffer.
309  * Return NULL if failed.
310  */
311 static xgell_rx_buffer_t *
312 xgell_rx_buffer_alloc(xgelldev_t *lldev)
313 {
314 	xge_hal_device_t *hldev;
315 	void *vaddr;
316 	ddi_dma_handle_t dma_handle;
317 	ddi_acc_handle_t dma_acch;
318 	dma_addr_t dma_addr;
319 	uint_t ncookies;
320 	ddi_dma_cookie_t dma_cookie;
321 	size_t real_size;
322 	extern ddi_device_acc_attr_t *p_xge_dev_attr;
323 	xgell_rx_buffer_t *rx_buffer;
324 
325 	hldev = (xge_hal_device_t *)lldev->devh;
326 
327 	if (ddi_dma_alloc_handle(hldev->pdev, p_hal_dma_attr, DDI_DMA_SLEEP,
328 	    0, &dma_handle) != DDI_SUCCESS) {
329 		xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA handle",
330 		    XGELL_IFNAME, lldev->instance);
331 		goto handle_failed;
332 	}
333 
334 	/* reserve some space at the end of the buffer for recycling */
335 	if (ddi_dma_mem_alloc(dma_handle, HEADROOM + lldev->bf_pool.size +
336 	    sizeof (xgell_rx_buffer_t), p_xge_dev_attr, DDI_DMA_STREAMING,
337 	    DDI_DMA_SLEEP, 0, (caddr_t *)&vaddr, &real_size, &dma_acch) !=
338 	    DDI_SUCCESS) {
339 		xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA-able memory",
340 		    XGELL_IFNAME, lldev->instance);
341 		goto mem_failed;
342 	}
343 
344 	if (HEADROOM + lldev->bf_pool.size + sizeof (xgell_rx_buffer_t) >
345 	    real_size) {
346 		xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA-able memory",
347 		    XGELL_IFNAME, lldev->instance);
348 		goto bind_failed;
349 	}
350 
351 	if (ddi_dma_addr_bind_handle(dma_handle, NULL, (char *)vaddr + HEADROOM,
352 	    lldev->bf_pool.size, DDI_DMA_READ | DDI_DMA_STREAMING,
353 	    DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_SUCCESS) {
354 		xge_debug_ll(XGE_ERR, "%s%d: out of mapping for mblk",
355 		    XGELL_IFNAME, lldev->instance);
356 		goto bind_failed;
357 	}
358 
359 	if (ncookies != 1 || dma_cookie.dmac_size < lldev->bf_pool.size) {
360 		xge_debug_ll(XGE_ERR, "%s%d: can not handle partial DMA",
361 		    XGELL_IFNAME, lldev->instance);
362 		goto check_failed;
363 	}
364 
365 	dma_addr = dma_cookie.dmac_laddress;
366 
367 	rx_buffer = (xgell_rx_buffer_t *)((char *)vaddr + real_size -
368 	    sizeof (xgell_rx_buffer_t));
369 	rx_buffer->next = NULL;
370 	rx_buffer->vaddr = vaddr;
371 	rx_buffer->dma_addr = dma_addr;
372 	rx_buffer->dma_handle = dma_handle;
373 	rx_buffer->dma_acch = dma_acch;
374 	rx_buffer->lldev = lldev;
375 	rx_buffer->frtn.free_func = xgell_rx_buffer_recycle;
376 	rx_buffer->frtn.free_arg = (void *)rx_buffer;
377 
378 	return (rx_buffer);
379 
380 check_failed:
381 	(void) ddi_dma_unbind_handle(dma_handle);
382 bind_failed:
383 	XGE_OS_MEMORY_CHECK_FREE(vaddr, 0);
384 	ddi_dma_mem_free(&dma_acch);
385 mem_failed:
386 	ddi_dma_free_handle(&dma_handle);
387 handle_failed:
388 
389 	return (NULL);
390 }
391 
392 /*
393  * xgell_rx_destroy_buffer_pool
394  *
395  * Destroy buffer pool. If there is still any buffer hold by upper layer,
396  * recorded by bf_pool.post, return DDI_FAILURE to reject to be unloaded.
397  */
398 static int
399 xgell_rx_destroy_buffer_pool(xgelldev_t *lldev)
400 {
401 	xgell_rx_buffer_t *rx_buffer;
402 	ddi_dma_handle_t  dma_handle;
403 	ddi_acc_handle_t  dma_acch;
404 	int i;
405 
406 	/*
407 	 * If there is any posted buffer, the driver should reject to be
408 	 * detached. Need notice upper layer to release them.
409 	 */
410 	if (lldev->bf_pool.post != 0) {
411 		xge_debug_ll(XGE_ERR,
412 		    "%s%d has some buffers not be recycled, try later!",
413 		    XGELL_IFNAME, lldev->instance);
414 		return (DDI_FAILURE);
415 	}
416 
417 	/*
418 	 * Relase buffers one by one.
419 	 */
420 	for (i = lldev->bf_pool.total; i > 0; i--) {
421 		rx_buffer = lldev->bf_pool.head;
422 		xge_assert(rx_buffer != NULL);
423 
424 		lldev->bf_pool.head = rx_buffer->next;
425 
426 		dma_handle = rx_buffer->dma_handle;
427 		dma_acch = rx_buffer->dma_acch;
428 
429 		if (ddi_dma_unbind_handle(dma_handle) != DDI_SUCCESS) {
430 			xge_debug_ll(XGE_ERR, "failed to unbind DMA handle!");
431 			lldev->bf_pool.head = rx_buffer;
432 			return (DDI_FAILURE);
433 		}
434 		ddi_dma_mem_free(&dma_acch);
435 		ddi_dma_free_handle(&dma_handle);
436 
437 		lldev->bf_pool.total--;
438 		lldev->bf_pool.free--;
439 	}
440 
441 	mutex_destroy(&lldev->bf_pool.pool_lock);
442 	return (DDI_SUCCESS);
443 }
444 
445 /*
446  * xgell_rx_create_buffer_pool
447  *
448  * Initialize RX buffer pool for all RX rings. Refer to rx_buffer_pool_t.
449  */
450 static int
451 xgell_rx_create_buffer_pool(xgelldev_t *lldev)
452 {
453 	xge_hal_device_t *hldev;
454 	xgell_rx_buffer_t *rx_buffer;
455 	int i;
456 
457 	hldev = (xge_hal_device_t *)lldev->devh;
458 
459 	lldev->bf_pool.total = 0;
460 	lldev->bf_pool.size = XGELL_MAX_FRAME_SIZE(hldev);
461 	lldev->bf_pool.head = NULL;
462 	lldev->bf_pool.free = 0;
463 	lldev->bf_pool.post = 0;
464 	lldev->bf_pool.post_hiwat = lldev->config.rx_buffer_post_hiwat;
465 
466 	mutex_init(&lldev->bf_pool.pool_lock, NULL, MUTEX_DRIVER,
467 	    hldev->irqh);
468 
469 	/*
470 	 * Allocate buffers one by one. If failed, destroy whole pool by
471 	 * call to xgell_rx_destroy_buffer_pool().
472 	 */
473 	for (i = 0; i < lldev->config.rx_buffer_total; i++) {
474 		if ((rx_buffer = xgell_rx_buffer_alloc(lldev)) == NULL) {
475 			(void) xgell_rx_destroy_buffer_pool(lldev);
476 			return (DDI_FAILURE);
477 		}
478 
479 		rx_buffer->next = lldev->bf_pool.head;
480 		lldev->bf_pool.head = rx_buffer;
481 
482 		lldev->bf_pool.total++;
483 		lldev->bf_pool.free++;
484 	}
485 
486 	return (DDI_SUCCESS);
487 }
488 
489 /*
490  * xgell_rx_dtr_replenish
491  *
492  * Replenish descriptor with rx_buffer in RX buffer pool.
493  * The dtr should be post right away.
494  */
495 xge_hal_status_e
496 xgell_rx_dtr_replenish(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, int index,
497     void *userdata, xge_hal_channel_reopen_e reopen)
498 {
499 	xgell_ring_t *ring = userdata;
500 	xgelldev_t *lldev = ring->lldev;
501 	xgell_rx_buffer_t *rx_buffer;
502 	xgell_rxd_priv_t *rxd_priv;
503 
504 	if (lldev->bf_pool.head == NULL) {
505 		xge_debug_ll(XGE_ERR, "no more available rx DMA buffer!");
506 		return (XGE_HAL_FAIL);
507 	}
508 	rx_buffer = lldev->bf_pool.head;
509 	lldev->bf_pool.head = rx_buffer->next;
510 	lldev->bf_pool.free--;
511 
512 	xge_assert(rx_buffer);
513 	xge_assert(rx_buffer->dma_addr);
514 
515 	rxd_priv = (xgell_rxd_priv_t *)
516 	    xge_hal_ring_dtr_private(lldev->ring_main.channelh, dtr);
517 	xge_hal_ring_dtr_1b_set(dtr, rx_buffer->dma_addr, lldev->bf_pool.size);
518 
519 	rxd_priv->rx_buffer = rx_buffer;
520 
521 	return (XGE_HAL_OK);
522 }
523 
524 /*
525  * xgell_get_ip_offset
526  *
527  * Calculate the offset to IP header.
528  */
529 static inline int
530 xgell_get_ip_offset(xge_hal_dtr_info_t *ext_info)
531 {
532 	int ip_off;
533 
534 	/* get IP-header offset */
535 	switch (ext_info->frame) {
536 	case XGE_HAL_FRAME_TYPE_DIX:
537 		ip_off = XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE;
538 		break;
539 	case XGE_HAL_FRAME_TYPE_IPX:
540 		ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
541 		    XGE_HAL_HEADER_802_2_SIZE +
542 		    XGE_HAL_HEADER_SNAP_SIZE);
543 		break;
544 	case XGE_HAL_FRAME_TYPE_LLC:
545 		ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
546 		    XGE_HAL_HEADER_802_2_SIZE);
547 		break;
548 	case XGE_HAL_FRAME_TYPE_SNAP:
549 		ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
550 		    XGE_HAL_HEADER_SNAP_SIZE);
551 		break;
552 	default:
553 		ip_off = 0;
554 		break;
555 	}
556 
557 	if ((ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4 ||
558 	    ext_info->proto & XGE_HAL_FRAME_PROTO_IPV6) &&
559 	    (ext_info->proto & XGE_HAL_FRAME_PROTO_VLAN_TAGGED)) {
560 		ip_off += XGE_HAL_HEADER_VLAN_SIZE;
561 	}
562 
563 	return (ip_off);
564 }
565 
566 /*
567  * xgell_rx_hcksum_assoc
568  *
569  * Judge the packet type and then call to hcksum_assoc() to associate
570  * h/w checksum information.
571  */
572 static inline void
573 xgell_rx_hcksum_assoc(mblk_t *mp, char *vaddr, int pkt_length,
574     xge_hal_dtr_info_t *ext_info)
575 {
576 	int cksum_flags = 0;
577 
578 	if (!(ext_info->proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED)) {
579 		if (ext_info->proto & XGE_HAL_FRAME_PROTO_TCP_OR_UDP) {
580 			if (ext_info->l3_cksum == XGE_HAL_L3_CKSUM_OK) {
581 				cksum_flags |= HCK_IPV4_HDRCKSUM;
582 			}
583 			if (ext_info->l4_cksum == XGE_HAL_L4_CKSUM_OK) {
584 				cksum_flags |= HCK_FULLCKSUM_OK;
585 			}
586 			if (cksum_flags) {
587 				cksum_flags |= HCK_FULLCKSUM;
588 				(void) hcksum_assoc(mp, NULL, NULL, 0,
589 				    0, 0, 0, cksum_flags, 0);
590 			}
591 		}
592 	} else if (ext_info->proto &
593 	    (XGE_HAL_FRAME_PROTO_IPV4 | XGE_HAL_FRAME_PROTO_IPV6)) {
594 		/*
595 		 * Just pass the partial cksum up to IP.
596 		 */
597 		int ip_off = xgell_get_ip_offset(ext_info);
598 		int start, end = pkt_length - ip_off;
599 
600 		if (ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4) {
601 			struct ip *ip =
602 			    (struct ip *)(vaddr + ip_off);
603 			start = ip->ip_hl * 4 + ip_off;
604 		} else {
605 			start = ip_off + 40;
606 		}
607 		cksum_flags |= HCK_PARTIALCKSUM;
608 		(void) hcksum_assoc(mp, NULL, NULL, start, 0,
609 		    end, ntohs(ext_info->l4_cksum), cksum_flags,
610 		    0);
611 	}
612 }
613 
614 /*
615  * xgell_rx_1b_msg_alloc
616  *
617  * Allocate message header for data buffer, and decide if copy the packet to
618  * new data buffer to release big rx_buffer to save memory.
619  *
620  * If the pkt_length <= XGELL_RX_DMA_LOWAT, call allocb() to allocate
621  * new message and copy the payload in.
622  */
623 static mblk_t *
624 xgell_rx_1b_msg_alloc(xgelldev_t *lldev, xgell_rx_buffer_t *rx_buffer,
625     int pkt_length, xge_hal_dtr_info_t *ext_info, boolean_t *copyit)
626 {
627 	mblk_t *mp;
628 	char *vaddr;
629 
630 	vaddr = (char *)rx_buffer->vaddr + HEADROOM;
631 	/*
632 	 * Copy packet into new allocated message buffer, if pkt_length
633 	 * is less than XGELL_RX_DMA_LOWAT
634 	 */
635 	if (*copyit || pkt_length <= lldev->config.rx_dma_lowat) {
636 		if ((mp = allocb(pkt_length, 0)) == NULL) {
637 			return (NULL);
638 		}
639 		bcopy(vaddr, mp->b_rptr, pkt_length);
640 		mp->b_wptr = mp->b_rptr + pkt_length;
641 		*copyit = B_TRUE;
642 		return (mp);
643 	}
644 
645 	/*
646 	 * Just allocate mblk for current data buffer
647 	 */
648 	if ((mp = (mblk_t *)desballoc((unsigned char *)vaddr, pkt_length, 0,
649 	    &rx_buffer->frtn)) == NULL) {
650 		/* Drop it */
651 		return (NULL);
652 	}
653 	/*
654 	 * Adjust the b_rptr/b_wptr in the mblk_t structure.
655 	 */
656 	mp->b_wptr += pkt_length;
657 
658 	return (mp);
659 }
660 
661 /*
662  * xgell_rx_1b_compl
663  *
664  * If the interrupt is because of a received frame or if the receive ring
665  * contains fresh as yet un-processed frames, this function is called.
666  */
667 static xge_hal_status_e
668 xgell_rx_1b_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code,
669     void *userdata)
670 {
671 	xgelldev_t *lldev = ((xgell_ring_t *)userdata)->lldev;
672 	xgell_rx_buffer_t *rx_buffer;
673 	mblk_t *mp_head = NULL;
674 	mblk_t *mp_end  = NULL;
675 	int pkt_burst = 0;
676 
677 	mutex_enter(&lldev->bf_pool.pool_lock);
678 
679 	do {
680 		int pkt_length;
681 		dma_addr_t dma_data;
682 		mblk_t *mp;
683 		boolean_t copyit = B_FALSE;
684 
685 		xgell_rxd_priv_t *rxd_priv = ((xgell_rxd_priv_t *)
686 		    xge_hal_ring_dtr_private(channelh, dtr));
687 		xge_hal_dtr_info_t ext_info;
688 
689 		rx_buffer = rxd_priv->rx_buffer;
690 
691 		xge_hal_ring_dtr_1b_get(channelh, dtr, &dma_data, &pkt_length);
692 		xge_hal_ring_dtr_info_get(channelh, dtr, &ext_info);
693 
694 		xge_assert(dma_data == rx_buffer->dma_addr);
695 
696 		if (t_code != 0) {
697 			xge_debug_ll(XGE_ERR, "%s%d: rx: dtr 0x%"PRIx64
698 			    " completed due to error t_code %01x", XGELL_IFNAME,
699 			    lldev->instance, (uint64_t)(uintptr_t)dtr, t_code);
700 
701 			(void) xge_hal_device_handle_tcode(channelh, dtr,
702 			    t_code);
703 			xge_hal_ring_dtr_free(channelh, dtr); /* drop it */
704 			xgell_rx_buffer_release(rx_buffer);
705 			continue;
706 		}
707 
708 		/*
709 		 * Sync the DMA memory
710 		 */
711 		if (ddi_dma_sync(rx_buffer->dma_handle, 0, pkt_length,
712 		    DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS) {
713 			xge_debug_ll(XGE_ERR, "%s%d: rx: can not do DMA sync",
714 			    XGELL_IFNAME, lldev->instance);
715 			xge_hal_ring_dtr_free(channelh, dtr); /* drop it */
716 			xgell_rx_buffer_release(rx_buffer);
717 			continue;
718 		}
719 
720 		/*
721 		 * Allocate message for the packet.
722 		 */
723 		if (lldev->bf_pool.post > lldev->bf_pool.post_hiwat) {
724 			copyit = B_TRUE;
725 		} else {
726 			copyit = B_FALSE;
727 		}
728 
729 		mp = xgell_rx_1b_msg_alloc(lldev, rx_buffer, pkt_length,
730 		    &ext_info, &copyit);
731 
732 		xge_hal_ring_dtr_free(channelh, dtr);
733 
734 		/*
735 		 * Release the buffer and recycle it later
736 		 */
737 		if ((mp == NULL) || copyit) {
738 			xgell_rx_buffer_release(rx_buffer);
739 		} else {
740 			/*
741 			 * Count it since the buffer should be loaned up.
742 			 */
743 			lldev->bf_pool.post++;
744 		}
745 		if (mp == NULL) {
746 			xge_debug_ll(XGE_ERR,
747 			    "%s%d: rx: can not allocate mp mblk",
748 			    XGELL_IFNAME, lldev->instance);
749 			continue;
750 		}
751 
752 		/*
753 		 * Associate cksum_flags per packet type and h/w
754 		 * cksum flags.
755 		 */
756 		xgell_rx_hcksum_assoc(mp, (char *)rx_buffer->vaddr +
757 		    HEADROOM, pkt_length, &ext_info);
758 
759 		if (mp_head == NULL) {
760 			mp_head = mp;
761 			mp_end = mp;
762 		} else {
763 			mp_end->b_next = mp;
764 			mp_end = mp;
765 		}
766 
767 		if (++pkt_burst < lldev->config.rx_pkt_burst)
768 			continue;
769 
770 		if (lldev->bf_pool.post > lldev->bf_pool.post_hiwat) {
771 			/* Replenish rx buffers */
772 			xgell_rx_buffer_replenish_all(lldev);
773 		}
774 		mutex_exit(&lldev->bf_pool.pool_lock);
775 		if (mp_head != NULL) {
776 			mac_rx(lldev->mh, ((xgell_ring_t *)userdata)->handle,
777 			    mp_head);
778 		}
779 		mp_head = mp_end  = NULL;
780 		pkt_burst = 0;
781 		mutex_enter(&lldev->bf_pool.pool_lock);
782 
783 	} while (xge_hal_ring_dtr_next_completed(channelh, &dtr, &t_code) ==
784 	    XGE_HAL_OK);
785 
786 	/*
787 	 * Always call replenish_all to recycle rx_buffers.
788 	 */
789 	xgell_rx_buffer_replenish_all(lldev);
790 	mutex_exit(&lldev->bf_pool.pool_lock);
791 
792 	if (mp_head != NULL) {
793 		mac_rx(lldev->mh, ((xgell_ring_t *)userdata)->handle, mp_head);
794 	}
795 
796 	return (XGE_HAL_OK);
797 }
798 
799 /*
800  * xgell_xmit_compl
801  *
802  * If an interrupt was raised to indicate DMA complete of the Tx packet,
803  * this function is called. It identifies the last TxD whose buffer was
804  * freed and frees all skbs whose data have already DMA'ed into the NICs
805  * internal memory.
806  */
807 static xge_hal_status_e
808 xgell_xmit_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code,
809     void *userdata)
810 {
811 	xgelldev_t *lldev = userdata;
812 
813 	do {
814 		xgell_txd_priv_t *txd_priv = ((xgell_txd_priv_t *)
815 		    xge_hal_fifo_dtr_private(dtr));
816 		mblk_t *mp = txd_priv->mblk;
817 		int i;
818 
819 		if (t_code) {
820 			xge_debug_ll(XGE_TRACE, "%s%d: tx: dtr 0x%"PRIx64
821 			    " completed due to error t_code %01x", XGELL_IFNAME,
822 			    lldev->instance, (uint64_t)(uintptr_t)dtr, t_code);
823 
824 			(void) xge_hal_device_handle_tcode(channelh, dtr,
825 			    t_code);
826 		}
827 
828 		for (i = 0; i < txd_priv->handle_cnt; i++) {
829 			xge_assert(txd_priv->dma_handles[i]);
830 			(void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]);
831 			ddi_dma_free_handle(&txd_priv->dma_handles[i]);
832 			txd_priv->dma_handles[i] = 0;
833 		}
834 
835 		xge_hal_fifo_dtr_free(channelh, dtr);
836 
837 		freemsg(mp);
838 		lldev->resched_avail++;
839 
840 	} while (xge_hal_fifo_dtr_next_completed(channelh, &dtr, &t_code) ==
841 	    XGE_HAL_OK);
842 
843 	if (lldev->resched_retry &&
844 	    xge_queue_produce_context(xge_hal_device_queue(lldev->devh),
845 	    XGELL_EVENT_RESCHED_NEEDED, lldev) == XGE_QUEUE_OK) {
846 	    xge_debug_ll(XGE_TRACE, "%s%d: IRQ produced event for queue %d",
847 		XGELL_IFNAME, lldev->instance,
848 		((xge_hal_channel_t *)lldev->fifo_channel)->post_qid);
849 		lldev->resched_send = lldev->resched_avail;
850 		lldev->resched_retry = 0;
851 	}
852 
853 	return (XGE_HAL_OK);
854 }
855 
856 /*
857  * xgell_send
858  * @hldev: pointer to xge_hal_device_t strucutre
859  * @mblk: pointer to network buffer, i.e. mblk_t structure
860  *
861  * Called by the xgell_m_tx to transmit the packet to the XFRAME firmware.
862  * A pointer to an M_DATA message that contains the packet is passed to
863  * this routine.
864  */
865 static boolean_t
866 xgell_send(xgelldev_t *lldev, mblk_t *mp)
867 {
868 	mblk_t *bp;
869 	boolean_t retry;
870 	xge_hal_device_t *hldev = lldev->devh;
871 	xge_hal_status_e status;
872 	xge_hal_dtr_h dtr;
873 	xgell_txd_priv_t *txd_priv;
874 	uint32_t hckflags;
875 	uint32_t mss;
876 	int handle_cnt, frag_cnt, ret, i, copied;
877 	boolean_t used_copy;
878 
879 _begin:
880 	retry = B_FALSE;
881 	handle_cnt = frag_cnt = 0;
882 
883 	if (!lldev->is_initialized || lldev->in_reset)
884 		return (B_FALSE);
885 
886 	/*
887 	 * If the free Tx dtrs count reaches the lower threshold,
888 	 * inform the gld to stop sending more packets till the free
889 	 * dtrs count exceeds higher threshold. Driver informs the
890 	 * gld through gld_sched call, when the free dtrs count exceeds
891 	 * the higher threshold.
892 	 */
893 	if (xge_hal_channel_dtr_count(lldev->fifo_channel)
894 	    <= XGELL_TX_LEVEL_LOW) {
895 		xge_debug_ll(XGE_TRACE, "%s%d: queue %d: err on xmit,"
896 		    "free descriptors count at low threshold %d",
897 		    XGELL_IFNAME, lldev->instance,
898 		    ((xge_hal_channel_t *)lldev->fifo_channel)->post_qid,
899 		    XGELL_TX_LEVEL_LOW);
900 		retry = B_TRUE;
901 		goto _exit;
902 	}
903 
904 	status = xge_hal_fifo_dtr_reserve(lldev->fifo_channel, &dtr);
905 	if (status != XGE_HAL_OK) {
906 		switch (status) {
907 		case XGE_HAL_INF_CHANNEL_IS_NOT_READY:
908 			xge_debug_ll(XGE_ERR,
909 			    "%s%d: channel %d is not ready.", XGELL_IFNAME,
910 			    lldev->instance,
911 			    ((xge_hal_channel_t *)
912 			    lldev->fifo_channel)->post_qid);
913 			retry = B_TRUE;
914 			goto _exit;
915 		case XGE_HAL_INF_OUT_OF_DESCRIPTORS:
916 			xge_debug_ll(XGE_TRACE, "%s%d: queue %d: error in xmit,"
917 			    " out of descriptors.", XGELL_IFNAME,
918 			    lldev->instance,
919 			    ((xge_hal_channel_t *)
920 			    lldev->fifo_channel)->post_qid);
921 			retry = B_TRUE;
922 			goto _exit;
923 		default:
924 			return (B_FALSE);
925 		}
926 	}
927 
928 	txd_priv = xge_hal_fifo_dtr_private(dtr);
929 	txd_priv->mblk = mp;
930 
931 	/*
932 	 * VLAN tag should be passed down along with MAC header, so h/w needn't
933 	 * do insertion.
934 	 *
935 	 * For NIC driver that has to strip and re-insert VLAN tag, the example
936 	 * is the other implementation for xge. The driver can simple bcopy()
937 	 * ether_vlan_header to overwrite VLAN tag and let h/w insert the tag
938 	 * automatically, since it's impossible that GLD sends down mp(s) with
939 	 * splited ether_vlan_header.
940 	 *
941 	 * struct ether_vlan_header *evhp;
942 	 * uint16_t tci;
943 	 *
944 	 * evhp = (struct ether_vlan_header *)mp->b_rptr;
945 	 * if (evhp->ether_tpid == htons(VLAN_TPID)) {
946 	 *	tci = ntohs(evhp->ether_tci);
947 	 *	(void) bcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ,
948 	 *	    2 * ETHERADDRL);
949 	 *	mp->b_rptr += VLAN_TAGSZ;
950 	 *
951 	 *	xge_hal_fifo_dtr_vlan_set(dtr, tci);
952 	 * }
953 	 */
954 
955 	copied = 0;
956 	used_copy = B_FALSE;
957 	for (bp = mp; bp != NULL; bp = bp->b_cont) {
958 		int mblen;
959 		uint_t ncookies;
960 		ddi_dma_cookie_t dma_cookie;
961 		ddi_dma_handle_t dma_handle;
962 
963 		/* skip zero-length message blocks */
964 		mblen = MBLKL(bp);
965 		if (mblen == 0) {
966 			continue;
967 		}
968 
969 		/*
970 		 * Check the message length to decide to DMA or bcopy() data
971 		 * to tx descriptor(s).
972 		 */
973 		if (mblen < lldev->config.tx_dma_lowat &&
974 		    (copied + mblen) < lldev->tx_copied_max) {
975 			xge_hal_status_e rc;
976 			rc = xge_hal_fifo_dtr_buffer_append(lldev->fifo_channel,
977 			    dtr, bp->b_rptr, mblen);
978 			if (rc == XGE_HAL_OK) {
979 				used_copy = B_TRUE;
980 				copied += mblen;
981 				continue;
982 			} else if (used_copy) {
983 				xge_hal_fifo_dtr_buffer_finalize(
984 					lldev->fifo_channel, dtr, frag_cnt++);
985 				used_copy = B_FALSE;
986 			}
987 		} else if (used_copy) {
988 			xge_hal_fifo_dtr_buffer_finalize(lldev->fifo_channel,
989 			    dtr, frag_cnt++);
990 			used_copy = B_FALSE;
991 		}
992 
993 		ret = ddi_dma_alloc_handle(lldev->dev_info, &tx_dma_attr,
994 		    DDI_DMA_DONTWAIT, 0, &dma_handle);
995 		if (ret != DDI_SUCCESS) {
996 			xge_debug_ll(XGE_ERR,
997 			    "%s%d: can not allocate dma handle", XGELL_IFNAME,
998 			    lldev->instance);
999 			goto _exit_cleanup;
1000 		}
1001 
1002 		ret = ddi_dma_addr_bind_handle(dma_handle, NULL,
1003 		    (caddr_t)bp->b_rptr, mblen,
1004 		    DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
1005 		    &dma_cookie, &ncookies);
1006 
1007 		switch (ret) {
1008 		case DDI_DMA_MAPPED:
1009 			/* everything's fine */
1010 			break;
1011 
1012 		case DDI_DMA_NORESOURCES:
1013 			xge_debug_ll(XGE_ERR,
1014 			    "%s%d: can not bind dma address",
1015 			    XGELL_IFNAME, lldev->instance);
1016 			ddi_dma_free_handle(&dma_handle);
1017 			goto _exit_cleanup;
1018 
1019 		case DDI_DMA_NOMAPPING:
1020 		case DDI_DMA_INUSE:
1021 		case DDI_DMA_TOOBIG:
1022 		default:
1023 			/* drop packet, don't retry */
1024 			xge_debug_ll(XGE_ERR,
1025 			    "%s%d: can not map message buffer",
1026 			    XGELL_IFNAME, lldev->instance);
1027 			ddi_dma_free_handle(&dma_handle);
1028 			goto _exit_cleanup;
1029 		}
1030 
1031 		if (ncookies + frag_cnt > hldev->config.fifo.max_frags) {
1032 			xge_debug_ll(XGE_ERR, "%s%d: too many fragments, "
1033 			    "requested c:%d+f:%d", XGELL_IFNAME,
1034 			    lldev->instance, ncookies, frag_cnt);
1035 			(void) ddi_dma_unbind_handle(dma_handle);
1036 			ddi_dma_free_handle(&dma_handle);
1037 			goto _exit_cleanup;
1038 		}
1039 
1040 		/* setup the descriptors for this data buffer */
1041 		while (ncookies) {
1042 			xge_hal_fifo_dtr_buffer_set(lldev->fifo_channel, dtr,
1043 			    frag_cnt++, dma_cookie.dmac_laddress,
1044 			    dma_cookie.dmac_size);
1045 			if (--ncookies) {
1046 				ddi_dma_nextcookie(dma_handle, &dma_cookie);
1047 			}
1048 
1049 		}
1050 
1051 		txd_priv->dma_handles[handle_cnt++] = dma_handle;
1052 
1053 		if (bp->b_cont &&
1054 		    (frag_cnt + XGE_HAL_DEFAULT_FIFO_FRAGS_THRESHOLD >=
1055 			hldev->config.fifo.max_frags)) {
1056 			mblk_t *nmp;
1057 
1058 			xge_debug_ll(XGE_TRACE,
1059 			    "too many FRAGs [%d], pull up them", frag_cnt);
1060 
1061 			if ((nmp = msgpullup(bp->b_cont, -1)) == NULL) {
1062 				/* Drop packet, don't retry */
1063 				xge_debug_ll(XGE_ERR,
1064 				    "%s%d: can not pullup message buffer",
1065 				    XGELL_IFNAME, lldev->instance);
1066 				goto _exit_cleanup;
1067 			}
1068 			freemsg(bp->b_cont);
1069 			bp->b_cont = nmp;
1070 		}
1071 	}
1072 
1073 	/* finalize unfinished copies */
1074 	if (used_copy) {
1075 		xge_hal_fifo_dtr_buffer_finalize(lldev->fifo_channel, dtr,
1076 		    frag_cnt++);
1077 	}
1078 
1079 	txd_priv->handle_cnt = handle_cnt;
1080 
1081 	/*
1082 	 * If LSO is required, just call xge_hal_fifo_dtr_mss_set(dtr, mss) to
1083 	 * do all necessary work.
1084 	 */
1085 	hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, &mss, &hckflags);
1086 	if ((hckflags & HW_LSO) && (mss != 0)) {
1087 		xge_hal_fifo_dtr_mss_set(dtr, mss);
1088 	}
1089 
1090 	if (hckflags & HCK_IPV4_HDRCKSUM) {
1091 		xge_hal_fifo_dtr_cksum_set_bits(dtr,
1092 		    XGE_HAL_TXD_TX_CKO_IPV4_EN);
1093 	}
1094 	if (hckflags & HCK_FULLCKSUM) {
1095 		xge_hal_fifo_dtr_cksum_set_bits(dtr, XGE_HAL_TXD_TX_CKO_TCP_EN |
1096 		    XGE_HAL_TXD_TX_CKO_UDP_EN);
1097 	}
1098 
1099 	xge_hal_fifo_dtr_post(lldev->fifo_channel, dtr);
1100 
1101 	return (B_TRUE);
1102 
1103 _exit_cleanup:
1104 
1105 	for (i = 0; i < handle_cnt; i++) {
1106 		(void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]);
1107 		ddi_dma_free_handle(&txd_priv->dma_handles[i]);
1108 		txd_priv->dma_handles[i] = 0;
1109 	}
1110 
1111 	xge_hal_fifo_dtr_free(lldev->fifo_channel, dtr);
1112 
1113 _exit:
1114 	if (retry) {
1115 		if (lldev->resched_avail != lldev->resched_send &&
1116 		    xge_queue_produce_context(xge_hal_device_queue(lldev->devh),
1117 		    XGELL_EVENT_RESCHED_NEEDED, lldev) == XGE_QUEUE_OK) {
1118 			lldev->resched_send = lldev->resched_avail;
1119 			return (B_FALSE);
1120 		} else {
1121 			lldev->resched_retry = 1;
1122 		}
1123 	}
1124 
1125 	freemsg(mp);
1126 	return (B_TRUE);
1127 }
1128 
1129 /*
1130  * xge_m_tx
1131  * @arg: pointer to the xgelldev_t structure
1132  * @resid: resource id
1133  * @mp: pointer to the message buffer
1134  *
1135  * Called by MAC Layer to send a chain of packets
1136  */
1137 static mblk_t *
1138 xgell_m_tx(void *arg, mblk_t *mp)
1139 {
1140 	xgelldev_t *lldev = arg;
1141 	mblk_t *next;
1142 
1143 	while (mp != NULL) {
1144 		next = mp->b_next;
1145 		mp->b_next = NULL;
1146 
1147 		if (!xgell_send(lldev, mp)) {
1148 			mp->b_next = next;
1149 			break;
1150 		}
1151 		mp = next;
1152 	}
1153 
1154 	return (mp);
1155 }
1156 
1157 /*
1158  * xgell_rx_dtr_term
1159  *
1160  * Function will be called by HAL to terminate all DTRs for
1161  * Ring(s) type of channels.
1162  */
1163 static void
1164 xgell_rx_dtr_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
1165     xge_hal_dtr_state_e state, void *userdata, xge_hal_channel_reopen_e reopen)
1166 {
1167 	xgell_rxd_priv_t *rxd_priv =
1168 	    ((xgell_rxd_priv_t *)xge_hal_ring_dtr_private(channelh, dtrh));
1169 	xgell_rx_buffer_t *rx_buffer = rxd_priv->rx_buffer;
1170 
1171 	if (state == XGE_HAL_DTR_STATE_POSTED) {
1172 		xgelldev_t *lldev = rx_buffer->lldev;
1173 
1174 		mutex_enter(&lldev->bf_pool.pool_lock);
1175 		xge_hal_ring_dtr_free(channelh, dtrh);
1176 		xgell_rx_buffer_release(rx_buffer);
1177 		mutex_exit(&lldev->bf_pool.pool_lock);
1178 	}
1179 }
1180 
1181 /*
1182  * xgell_tx_term
1183  *
1184  * Function will be called by HAL to terminate all DTRs for
1185  * Fifo(s) type of channels.
1186  */
1187 static void
1188 xgell_tx_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
1189     xge_hal_dtr_state_e state, void *userdata, xge_hal_channel_reopen_e reopen)
1190 {
1191 	xgell_txd_priv_t *txd_priv =
1192 	    ((xgell_txd_priv_t *)xge_hal_fifo_dtr_private(dtrh));
1193 	mblk_t *mp = txd_priv->mblk;
1194 	int i;
1195 
1196 	/*
1197 	 * for Tx we must clean up the DTR *only* if it has been
1198 	 * posted!
1199 	 */
1200 	if (state != XGE_HAL_DTR_STATE_POSTED) {
1201 		return;
1202 	}
1203 
1204 	for (i = 0; i < txd_priv->handle_cnt; i++) {
1205 		xge_assert(txd_priv->dma_handles[i]);
1206 		(void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]);
1207 		ddi_dma_free_handle(&txd_priv->dma_handles[i]);
1208 		txd_priv->dma_handles[i] = 0;
1209 	}
1210 
1211 	xge_hal_fifo_dtr_free(channelh, dtrh);
1212 
1213 	freemsg(mp);
1214 }
1215 
1216 /*
1217  * xgell_tx_open
1218  * @lldev: the link layer object
1219  *
1220  * Initialize and open all Tx channels;
1221  */
1222 static boolean_t
1223 xgell_tx_open(xgelldev_t *lldev)
1224 {
1225 	xge_hal_status_e status;
1226 	u64 adapter_status;
1227 	xge_hal_channel_attr_t attr;
1228 
1229 	attr.post_qid		= 0;
1230 	attr.compl_qid		= 0;
1231 	attr.callback		= xgell_xmit_compl;
1232 	attr.per_dtr_space	= sizeof (xgell_txd_priv_t);
1233 	attr.flags		= 0;
1234 	attr.type		= XGE_HAL_CHANNEL_TYPE_FIFO;
1235 	attr.userdata		= lldev;
1236 	attr.dtr_init		= NULL;
1237 	attr.dtr_term		= xgell_tx_term;
1238 
1239 	if (xge_hal_device_status(lldev->devh, &adapter_status)) {
1240 		xge_debug_ll(XGE_ERR, "%s%d: device is not ready "
1241 		    "adaper status reads 0x%"PRIx64, XGELL_IFNAME,
1242 		    lldev->instance, (uint64_t)adapter_status);
1243 		return (B_FALSE);
1244 	}
1245 
1246 	status = xge_hal_channel_open(lldev->devh, &attr,
1247 	    &lldev->fifo_channel, XGE_HAL_CHANNEL_OC_NORMAL);
1248 	if (status != XGE_HAL_OK) {
1249 		xge_debug_ll(XGE_ERR, "%s%d: cannot open Tx channel "
1250 		    "got status code %d", XGELL_IFNAME,
1251 		    lldev->instance, status);
1252 		return (B_FALSE);
1253 	}
1254 
1255 	return (B_TRUE);
1256 }
1257 
1258 /*
1259  * xgell_rx_open
1260  * @lldev: the link layer object
1261  *
1262  * Initialize and open all Rx channels;
1263  */
1264 static boolean_t
1265 xgell_rx_open(xgelldev_t *lldev)
1266 {
1267 	xge_hal_status_e status;
1268 	u64 adapter_status;
1269 	xge_hal_channel_attr_t attr;
1270 
1271 	attr.post_qid		= XGELL_RING_MAIN_QID;
1272 	attr.compl_qid		= 0;
1273 	attr.callback		= xgell_rx_1b_compl;
1274 	attr.per_dtr_space	= sizeof (xgell_rxd_priv_t);
1275 	attr.flags		= 0;
1276 	attr.type		= XGE_HAL_CHANNEL_TYPE_RING;
1277 	attr.dtr_init		= xgell_rx_dtr_replenish;
1278 	attr.dtr_term		= xgell_rx_dtr_term;
1279 
1280 	if (xge_hal_device_status(lldev->devh, &adapter_status)) {
1281 		xge_debug_ll(XGE_ERR,
1282 		    "%s%d: device is not ready adaper status reads 0x%"PRIx64,
1283 		    XGELL_IFNAME, lldev->instance,
1284 		    (uint64_t)adapter_status);
1285 		return (B_FALSE);
1286 	}
1287 
1288 	lldev->ring_main.lldev = lldev;
1289 	attr.userdata = &lldev->ring_main;
1290 
1291 	status = xge_hal_channel_open(lldev->devh, &attr,
1292 	    &lldev->ring_main.channelh, XGE_HAL_CHANNEL_OC_NORMAL);
1293 	if (status != XGE_HAL_OK) {
1294 		xge_debug_ll(XGE_ERR, "%s%d: cannot open Rx channel got status "
1295 		    " code %d", XGELL_IFNAME, lldev->instance, status);
1296 		return (B_FALSE);
1297 	}
1298 
1299 	return (B_TRUE);
1300 }
1301 
1302 static int
1303 xgell_initiate_start(xgelldev_t *lldev)
1304 {
1305 	xge_hal_status_e status;
1306 	xge_hal_device_t *hldev = lldev->devh;
1307 	int maxpkt = hldev->config.mtu;
1308 
1309 	/* check initial mtu before enabling the device */
1310 	status = xge_hal_device_mtu_check(lldev->devh, maxpkt);
1311 	if (status != XGE_HAL_OK) {
1312 		xge_debug_ll(XGE_ERR, "%s%d: MTU size %d is invalid",
1313 		    XGELL_IFNAME, lldev->instance, maxpkt);
1314 		return (EINVAL);
1315 	}
1316 
1317 	/* set initial mtu before enabling the device */
1318 	status = xge_hal_device_mtu_set(lldev->devh, maxpkt);
1319 	if (status != XGE_HAL_OK) {
1320 		xge_debug_ll(XGE_ERR, "%s%d: can not set new MTU %d",
1321 		    XGELL_IFNAME, lldev->instance, maxpkt);
1322 		return (EIO);
1323 	}
1324 
1325 	/* tune jumbo/normal frame UFC counters */
1326 	hldev->config.ring.queue[XGELL_RING_MAIN_QID].rti.ufc_b = \
1327 		maxpkt > XGE_HAL_DEFAULT_MTU ?
1328 			XGE_HAL_DEFAULT_RX_UFC_B_J :
1329 			XGE_HAL_DEFAULT_RX_UFC_B_N;
1330 
1331 	hldev->config.ring.queue[XGELL_RING_MAIN_QID].rti.ufc_c = \
1332 		maxpkt > XGE_HAL_DEFAULT_MTU ?
1333 			XGE_HAL_DEFAULT_RX_UFC_C_J :
1334 			XGE_HAL_DEFAULT_RX_UFC_C_N;
1335 
1336 	/* now, enable the device */
1337 	status = xge_hal_device_enable(lldev->devh);
1338 	if (status != XGE_HAL_OK) {
1339 		xge_debug_ll(XGE_ERR, "%s%d: can not enable the device",
1340 		    XGELL_IFNAME, lldev->instance);
1341 		return (EIO);
1342 	}
1343 
1344 	if (!xgell_rx_open(lldev)) {
1345 		status = xge_hal_device_disable(lldev->devh);
1346 		if (status != XGE_HAL_OK) {
1347 			u64 adapter_status;
1348 			(void) xge_hal_device_status(lldev->devh,
1349 			    &adapter_status);
1350 			xge_debug_ll(XGE_ERR, "%s%d: can not safely disable "
1351 			    "the device. adaper status 0x%"PRIx64
1352 			    " returned status %d",
1353 			    XGELL_IFNAME, lldev->instance,
1354 			    (uint64_t)adapter_status, status);
1355 		}
1356 		xge_os_mdelay(1500);
1357 		return (ENOMEM);
1358 	}
1359 
1360 	if (!xgell_tx_open(lldev)) {
1361 		status = xge_hal_device_disable(lldev->devh);
1362 		if (status != XGE_HAL_OK) {
1363 			u64 adapter_status;
1364 			(void) xge_hal_device_status(lldev->devh,
1365 			    &adapter_status);
1366 			xge_debug_ll(XGE_ERR, "%s%d: can not safely disable "
1367 			    "the device. adaper status 0x%"PRIx64
1368 			    " returned status %d",
1369 			    XGELL_IFNAME, lldev->instance,
1370 			    (uint64_t)adapter_status, status);
1371 		}
1372 		xge_os_mdelay(1500);
1373 		xge_hal_channel_close(lldev->ring_main.channelh,
1374 		    XGE_HAL_CHANNEL_OC_NORMAL);
1375 		return (ENOMEM);
1376 	}
1377 
1378 	/* time to enable interrupts */
1379 	xge_hal_device_intr_enable(lldev->devh);
1380 
1381 	lldev->is_initialized = 1;
1382 
1383 	return (0);
1384 }
1385 
1386 static void
1387 xgell_initiate_stop(xgelldev_t *lldev)
1388 {
1389 	xge_hal_status_e status;
1390 
1391 	lldev->is_initialized = 0;
1392 
1393 	status = xge_hal_device_disable(lldev->devh);
1394 	if (status != XGE_HAL_OK) {
1395 		u64 adapter_status;
1396 		(void) xge_hal_device_status(lldev->devh, &adapter_status);
1397 		xge_debug_ll(XGE_ERR, "%s%d: can not safely disable "
1398 		    "the device. adaper status 0x%"PRIx64" returned status %d",
1399 		    XGELL_IFNAME, lldev->instance,
1400 		    (uint64_t)adapter_status, status);
1401 	}
1402 	xge_hal_device_intr_disable(lldev->devh);
1403 
1404 	xge_debug_ll(XGE_TRACE, "%s",
1405 	    "waiting for device irq to become quiescent...");
1406 	xge_os_mdelay(1500);
1407 
1408 	xge_queue_flush(xge_hal_device_queue(lldev->devh));
1409 
1410 	xge_hal_channel_close(lldev->ring_main.channelh,
1411 	    XGE_HAL_CHANNEL_OC_NORMAL);
1412 
1413 	xge_hal_channel_close(lldev->fifo_channel,
1414 	    XGE_HAL_CHANNEL_OC_NORMAL);
1415 }
1416 
1417 /*
1418  * xgell_m_start
1419  * @arg: pointer to device private strucutre(hldev)
1420  *
1421  * This function is called by MAC Layer to enable the XFRAME
1422  * firmware to generate interrupts and also prepare the
1423  * driver to call mac_rx for delivering receive packets
1424  * to MAC Layer.
1425  */
1426 static int
1427 xgell_m_start(void *arg)
1428 {
1429 	xgelldev_t *lldev = arg;
1430 	xge_hal_device_t *hldev = lldev->devh;
1431 	int ret;
1432 
1433 	xge_debug_ll(XGE_TRACE, "%s%d: M_START", XGELL_IFNAME,
1434 	    lldev->instance);
1435 
1436 	mutex_enter(&lldev->genlock);
1437 
1438 	if (lldev->is_initialized) {
1439 		xge_debug_ll(XGE_ERR, "%s%d: device is already initialized",
1440 		    XGELL_IFNAME, lldev->instance);
1441 		mutex_exit(&lldev->genlock);
1442 		return (EINVAL);
1443 	}
1444 
1445 	hldev->terminating = 0;
1446 	if (ret = xgell_initiate_start(lldev)) {
1447 		mutex_exit(&lldev->genlock);
1448 		return (ret);
1449 	}
1450 
1451 	lldev->timeout_id = timeout(xge_device_poll, hldev, XGE_DEV_POLL_TICKS);
1452 
1453 	mutex_exit(&lldev->genlock);
1454 
1455 	return (0);
1456 }
1457 
1458 /*
1459  * xgell_m_stop
1460  * @arg: pointer to device private data (hldev)
1461  *
1462  * This function is called by the MAC Layer to disable
1463  * the XFRAME firmware for generating any interrupts and
1464  * also stop the driver from calling mac_rx() for
1465  * delivering data packets to the MAC Layer.
1466  */
1467 static void
1468 xgell_m_stop(void *arg)
1469 {
1470 	xgelldev_t *lldev = arg;
1471 	xge_hal_device_t *hldev = lldev->devh;
1472 
1473 	xge_debug_ll(XGE_TRACE, "%s", "MAC_STOP");
1474 
1475 	mutex_enter(&lldev->genlock);
1476 	if (!lldev->is_initialized) {
1477 		xge_debug_ll(XGE_ERR, "%s", "device is not initialized...");
1478 		mutex_exit(&lldev->genlock);
1479 		return;
1480 	}
1481 
1482 	xge_hal_device_terminating(hldev);
1483 	xgell_initiate_stop(lldev);
1484 
1485 	/* reset device */
1486 	(void) xge_hal_device_reset(lldev->devh);
1487 
1488 	mutex_exit(&lldev->genlock);
1489 
1490 	if (lldev->timeout_id != 0) {
1491 		(void) untimeout(lldev->timeout_id);
1492 	}
1493 
1494 	xge_debug_ll(XGE_TRACE, "%s", "returning back to MAC Layer...");
1495 }
1496 
1497 /*
1498  * xgell_onerr_reset
1499  * @lldev: pointer to xgelldev_t structure
1500  *
1501  * This function is called by HAL Event framework to reset the HW
1502  * This function is must be called with genlock taken.
1503  */
1504 int
1505 xgell_onerr_reset(xgelldev_t *lldev)
1506 {
1507 	int rc = 0;
1508 
1509 	if (!lldev->is_initialized) {
1510 		xge_debug_ll(XGE_ERR, "%s%d: can not reset",
1511 		    XGELL_IFNAME, lldev->instance);
1512 		return (rc);
1513 	}
1514 
1515 	lldev->in_reset = 1;
1516 	xgell_initiate_stop(lldev);
1517 
1518 	/* reset device */
1519 	(void) xge_hal_device_reset(lldev->devh);
1520 
1521 	rc = xgell_initiate_start(lldev);
1522 	lldev->in_reset = 0;
1523 
1524 	return (rc);
1525 }
1526 
1527 
1528 /*
1529  * xgell_m_unicst
1530  * @arg: pointer to device private strucutre(hldev)
1531  * @mac_addr:
1532  *
1533  * This function is called by MAC Layer to set the physical address
1534  * of the XFRAME firmware.
1535  */
1536 static int
1537 xgell_m_unicst(void *arg, const uint8_t *macaddr)
1538 {
1539 	xge_hal_status_e status;
1540 	xgelldev_t *lldev = (xgelldev_t *)arg;
1541 	xge_hal_device_t *hldev = lldev->devh;
1542 	xge_debug_ll(XGE_TRACE, "%s", "MAC_UNICST");
1543 
1544 	xge_debug_ll(XGE_TRACE, "%s", "M_UNICAST");
1545 
1546 	mutex_enter(&lldev->genlock);
1547 
1548 	xge_debug_ll(XGE_TRACE,
1549 	    "setting macaddr: 0x%02x-%02x-%02x-%02x-%02x-%02x",
1550 	    macaddr[0], macaddr[1], macaddr[2],
1551 	    macaddr[3], macaddr[4], macaddr[5]);
1552 
1553 	status = xge_hal_device_macaddr_set(hldev, 0, (uchar_t *)macaddr);
1554 	if (status != XGE_HAL_OK) {
1555 		xge_debug_ll(XGE_ERR, "%s%d: can not set mac address",
1556 		    XGELL_IFNAME, lldev->instance);
1557 		mutex_exit(&lldev->genlock);
1558 		return (EIO);
1559 	}
1560 
1561 	mutex_exit(&lldev->genlock);
1562 
1563 	return (0);
1564 }
1565 
1566 
1567 /*
1568  * xgell_m_multicst
1569  * @arg: pointer to device private strucutre(hldev)
1570  * @add:
1571  * @mc_addr:
1572  *
1573  * This function is called by MAC Layer to enable or
1574  * disable device-level reception of specific multicast addresses.
1575  */
1576 static int
1577 xgell_m_multicst(void *arg, boolean_t add, const uint8_t *mc_addr)
1578 {
1579 	xge_hal_status_e status;
1580 	xgelldev_t *lldev = (xgelldev_t *)arg;
1581 	xge_hal_device_t *hldev = lldev->devh;
1582 
1583 	xge_debug_ll(XGE_TRACE, "M_MULTICAST add %d", add);
1584 
1585 	mutex_enter(&lldev->genlock);
1586 
1587 	if (!lldev->is_initialized) {
1588 		xge_debug_ll(XGE_ERR, "%s%d: can not set multicast",
1589 		    XGELL_IFNAME, lldev->instance);
1590 		mutex_exit(&lldev->genlock);
1591 		return (EIO);
1592 	}
1593 
1594 	/* FIXME: missing HAL functionality: enable_one() */
1595 
1596 	status = (add) ?
1597 	    xge_hal_device_mcast_enable(hldev) :
1598 	    xge_hal_device_mcast_disable(hldev);
1599 
1600 	if (status != XGE_HAL_OK) {
1601 		xge_debug_ll(XGE_ERR, "failed to %s multicast, status %d",
1602 		    add ? "enable" : "disable", status);
1603 		mutex_exit(&lldev->genlock);
1604 		return (EIO);
1605 	}
1606 
1607 	mutex_exit(&lldev->genlock);
1608 
1609 	return (0);
1610 }
1611 
1612 
1613 /*
1614  * xgell_m_promisc
1615  * @arg: pointer to device private strucutre(hldev)
1616  * @on:
1617  *
1618  * This function is called by MAC Layer to enable or
1619  * disable the reception of all the packets on the medium
1620  */
1621 static int
1622 xgell_m_promisc(void *arg, boolean_t on)
1623 {
1624 	xgelldev_t *lldev = (xgelldev_t *)arg;
1625 	xge_hal_device_t *hldev = lldev->devh;
1626 
1627 	mutex_enter(&lldev->genlock);
1628 
1629 	xge_debug_ll(XGE_TRACE, "%s", "MAC_PROMISC_SET");
1630 
1631 	if (!lldev->is_initialized) {
1632 		xge_debug_ll(XGE_ERR, "%s%d: can not set promiscuous",
1633 		    XGELL_IFNAME, lldev->instance);
1634 		mutex_exit(&lldev->genlock);
1635 		return (EIO);
1636 	}
1637 
1638 	if (on) {
1639 		xge_hal_device_promisc_enable(hldev);
1640 	} else {
1641 		xge_hal_device_promisc_disable(hldev);
1642 	}
1643 
1644 	mutex_exit(&lldev->genlock);
1645 
1646 	return (0);
1647 }
1648 
1649 /*
1650  * xgell_m_stat
1651  * @arg: pointer to device private strucutre(hldev)
1652  *
1653  * This function is called by MAC Layer to get network statistics
1654  * from the driver.
1655  */
1656 static int
1657 xgell_m_stat(void *arg, uint_t stat, uint64_t *val)
1658 {
1659 	xge_hal_stats_hw_info_t *hw_info;
1660 	xgelldev_t *lldev = (xgelldev_t *)arg;
1661 	xge_hal_device_t *hldev = lldev->devh;
1662 
1663 	xge_debug_ll(XGE_TRACE, "%s", "MAC_STATS_GET");
1664 
1665 	if (!mutex_tryenter(&lldev->genlock))
1666 		return (EAGAIN);
1667 
1668 	if (!lldev->is_initialized) {
1669 		mutex_exit(&lldev->genlock);
1670 		return (EAGAIN);
1671 	}
1672 
1673 	if (xge_hal_stats_hw(hldev, &hw_info) != XGE_HAL_OK) {
1674 		mutex_exit(&lldev->genlock);
1675 		return (EAGAIN);
1676 	}
1677 
1678 	switch (stat) {
1679 	case MAC_STAT_IFSPEED:
1680 		*val = 10000000000ull; /* 10G */
1681 		break;
1682 
1683 	case MAC_STAT_MULTIRCV:
1684 		*val = ((u64) hw_info->rmac_vld_mcst_frms_oflow << 32) |
1685 		    hw_info->rmac_vld_mcst_frms;
1686 		break;
1687 
1688 	case MAC_STAT_BRDCSTRCV:
1689 		*val = ((u64) hw_info->rmac_vld_bcst_frms_oflow << 32) |
1690 		    hw_info->rmac_vld_bcst_frms;
1691 		break;
1692 
1693 	case MAC_STAT_MULTIXMT:
1694 		*val = ((u64) hw_info->tmac_mcst_frms_oflow << 32) |
1695 		    hw_info->tmac_mcst_frms;
1696 		break;
1697 
1698 	case MAC_STAT_BRDCSTXMT:
1699 		*val = ((u64) hw_info->tmac_bcst_frms_oflow << 32) |
1700 		    hw_info->tmac_bcst_frms;
1701 		break;
1702 
1703 	case MAC_STAT_RBYTES:
1704 		*val = ((u64) hw_info->rmac_ttl_octets_oflow << 32) |
1705 		    hw_info->rmac_ttl_octets;
1706 		break;
1707 
1708 	case MAC_STAT_NORCVBUF:
1709 		*val = hw_info->rmac_drop_frms;
1710 		break;
1711 
1712 	case MAC_STAT_IERRORS:
1713 		*val = ((u64) hw_info->rmac_discarded_frms_oflow << 32) |
1714 		    hw_info->rmac_discarded_frms;
1715 		break;
1716 
1717 	case MAC_STAT_OBYTES:
1718 		*val = ((u64) hw_info->tmac_ttl_octets_oflow << 32) |
1719 		    hw_info->tmac_ttl_octets;
1720 		break;
1721 
1722 	case MAC_STAT_NOXMTBUF:
1723 		*val = hw_info->tmac_drop_frms;
1724 		break;
1725 
1726 	case MAC_STAT_OERRORS:
1727 		*val = ((u64) hw_info->tmac_any_err_frms_oflow << 32) |
1728 		    hw_info->tmac_any_err_frms;
1729 		break;
1730 
1731 	case MAC_STAT_IPACKETS:
1732 		*val = ((u64) hw_info->rmac_vld_frms_oflow << 32) |
1733 		    hw_info->rmac_vld_frms;
1734 		break;
1735 
1736 	case MAC_STAT_OPACKETS:
1737 		*val = ((u64) hw_info->tmac_frms_oflow << 32) |
1738 		    hw_info->tmac_frms;
1739 		break;
1740 
1741 	case ETHER_STAT_FCS_ERRORS:
1742 		*val = hw_info->rmac_fcs_err_frms;
1743 		break;
1744 
1745 	case ETHER_STAT_TOOLONG_ERRORS:
1746 		*val = hw_info->rmac_long_frms;
1747 		break;
1748 
1749 	case ETHER_STAT_LINK_DUPLEX:
1750 		*val = LINK_DUPLEX_FULL;
1751 		break;
1752 
1753 	default:
1754 		mutex_exit(&lldev->genlock);
1755 		return (ENOTSUP);
1756 	}
1757 
1758 	mutex_exit(&lldev->genlock);
1759 
1760 	return (0);
1761 }
1762 
1763 /*
1764  * xgell_device_alloc - Allocate new LL device
1765  */
1766 int
1767 xgell_device_alloc(xge_hal_device_h devh,
1768     dev_info_t *dev_info, xgelldev_t **lldev_out)
1769 {
1770 	xgelldev_t *lldev;
1771 	xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
1772 	int instance = ddi_get_instance(dev_info);
1773 
1774 	*lldev_out = NULL;
1775 
1776 	xge_debug_ll(XGE_TRACE, "trying to register etherenet device %s%d...",
1777 	    XGELL_IFNAME, instance);
1778 
1779 	lldev = kmem_zalloc(sizeof (xgelldev_t), KM_SLEEP);
1780 
1781 	lldev->devh = hldev;
1782 	lldev->instance = instance;
1783 	lldev->dev_info = dev_info;
1784 
1785 	*lldev_out = lldev;
1786 
1787 	ddi_set_driver_private(dev_info, (caddr_t)hldev);
1788 
1789 	return (DDI_SUCCESS);
1790 }
1791 
1792 /*
1793  * xgell_device_free
1794  */
1795 void
1796 xgell_device_free(xgelldev_t *lldev)
1797 {
1798 	xge_debug_ll(XGE_TRACE, "freeing device %s%d",
1799 	    XGELL_IFNAME, lldev->instance);
1800 
1801 	kmem_free(lldev, sizeof (xgelldev_t));
1802 }
1803 
1804 /*
1805  * xgell_ioctl
1806  */
1807 static void
1808 xgell_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
1809 {
1810 	xgelldev_t *lldev = arg;
1811 	struct iocblk *iocp;
1812 	int err = 0;
1813 	int cmd;
1814 	int need_privilege = 1;
1815 	int ret = 0;
1816 
1817 
1818 	iocp = (struct iocblk *)mp->b_rptr;
1819 	iocp->ioc_error = 0;
1820 	cmd = iocp->ioc_cmd;
1821 	xge_debug_ll(XGE_TRACE, "MAC_IOCTL cmd 0x%x", cmd);
1822 	switch (cmd) {
1823 	case ND_GET:
1824 		need_privilege = 0;
1825 		/* FALLTHRU */
1826 	case ND_SET:
1827 		break;
1828 	default:
1829 		xge_debug_ll(XGE_TRACE, "unknown cmd 0x%x", cmd);
1830 		miocnak(wq, mp, 0, EINVAL);
1831 		return;
1832 	}
1833 
1834 	if (need_privilege) {
1835 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
1836 		if (err != 0) {
1837 			xge_debug_ll(XGE_ERR,
1838 			    "drv_priv(): rejected cmd 0x%x, err %d",
1839 			    cmd, err);
1840 			miocnak(wq, mp, 0, err);
1841 			return;
1842 		}
1843 	}
1844 
1845 	switch (cmd) {
1846 	case ND_GET:
1847 		/*
1848 		 * If nd_getset() returns B_FALSE, the command was
1849 		 * not valid (e.g. unknown name), so we just tell the
1850 		 * top-level ioctl code to send a NAK (with code EINVAL).
1851 		 *
1852 		 * Otherwise, nd_getset() will have built the reply to
1853 		 * be sent (but not actually sent it), so we tell the
1854 		 * caller to send the prepared reply.
1855 		 */
1856 		ret = nd_getset(wq, lldev->ndp, mp);
1857 		xge_debug_ll(XGE_TRACE, "got ndd get ioctl");
1858 		break;
1859 
1860 	case ND_SET:
1861 		ret = nd_getset(wq, lldev->ndp, mp);
1862 		xge_debug_ll(XGE_TRACE, "got ndd set ioctl");
1863 		break;
1864 
1865 	default:
1866 		break;
1867 	}
1868 
1869 	if (ret == B_FALSE) {
1870 		xge_debug_ll(XGE_ERR,
1871 		    "nd_getset(): rejected cmd 0x%x, err %d",
1872 		    cmd, err);
1873 		miocnak(wq, mp, 0, EINVAL);
1874 	} else {
1875 		mp->b_datap->db_type = iocp->ioc_error == 0 ?
1876 		    M_IOCACK : M_IOCNAK;
1877 		qreply(wq, mp);
1878 	}
1879 }
1880 
1881 /* ARGSUSED */
1882 static boolean_t
1883 xgell_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
1884 {
1885 	xgelldev_t *lldev = arg;
1886 
1887 	switch (cap) {
1888 	case MAC_CAPAB_HCKSUM: {
1889 		uint32_t *hcksum_txflags = cap_data;
1890 		*hcksum_txflags = HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6 |
1891 		    HCKSUM_IPHDRCKSUM;
1892 		break;
1893 	}
1894 	case MAC_CAPAB_LSO: {
1895 		mac_capab_lso_t *cap_lso = cap_data;
1896 
1897 		if (lldev->config.lso_enable) {
1898 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
1899 			cap_lso->lso_basic_tcp_ipv4.lso_max = XGELL_LSO_MAXLEN;
1900 			break;
1901 		} else {
1902 			return (B_FALSE);
1903 		}
1904 	}
1905 	default:
1906 		return (B_FALSE);
1907 	}
1908 	return (B_TRUE);
1909 }
1910 
1911 static int
1912 xgell_stats_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
1913 {
1914 	xgelldev_t *lldev = (xgelldev_t *)cp;
1915 	xge_hal_status_e status;
1916 	int count = 0, retsize;
1917 	char *buf;
1918 
1919 	buf = kmem_alloc(XGELL_STATS_BUFSIZE, KM_SLEEP);
1920 	if (buf == NULL) {
1921 		return (ENOSPC);
1922 	}
1923 
1924 	status = xge_hal_aux_stats_tmac_read(lldev->devh, XGELL_STATS_BUFSIZE,
1925 	    buf, &retsize);
1926 	if (status != XGE_HAL_OK) {
1927 		kmem_free(buf, XGELL_STATS_BUFSIZE);
1928 		xge_debug_ll(XGE_ERR, "tmac_read(): status %d", status);
1929 		return (EINVAL);
1930 	}
1931 	count += retsize;
1932 
1933 	status = xge_hal_aux_stats_rmac_read(lldev->devh,
1934 	    XGELL_STATS_BUFSIZE - count,
1935 	    buf+count, &retsize);
1936 	if (status != XGE_HAL_OK) {
1937 		kmem_free(buf, XGELL_STATS_BUFSIZE);
1938 		xge_debug_ll(XGE_ERR, "rmac_read(): status %d", status);
1939 		return (EINVAL);
1940 	}
1941 	count += retsize;
1942 
1943 	status = xge_hal_aux_stats_pci_read(lldev->devh,
1944 	    XGELL_STATS_BUFSIZE - count, buf + count, &retsize);
1945 	if (status != XGE_HAL_OK) {
1946 		kmem_free(buf, XGELL_STATS_BUFSIZE);
1947 		xge_debug_ll(XGE_ERR, "pci_read(): status %d", status);
1948 		return (EINVAL);
1949 	}
1950 	count += retsize;
1951 
1952 	status = xge_hal_aux_stats_sw_dev_read(lldev->devh,
1953 	    XGELL_STATS_BUFSIZE - count, buf + count, &retsize);
1954 	if (status != XGE_HAL_OK) {
1955 		kmem_free(buf, XGELL_STATS_BUFSIZE);
1956 		xge_debug_ll(XGE_ERR, "sw_dev_read(): status %d", status);
1957 		return (EINVAL);
1958 	}
1959 	count += retsize;
1960 
1961 	status = xge_hal_aux_stats_hal_read(lldev->devh,
1962 	    XGELL_STATS_BUFSIZE - count, buf + count, &retsize);
1963 	if (status != XGE_HAL_OK) {
1964 		kmem_free(buf, XGELL_STATS_BUFSIZE);
1965 		xge_debug_ll(XGE_ERR, "pci_read(): status %d", status);
1966 		return (EINVAL);
1967 	}
1968 	count += retsize;
1969 
1970 	*(buf + count - 1) = '\0'; /* remove last '\n' */
1971 	(void) mi_mpprintf(mp, "%s", buf);
1972 	kmem_free(buf, XGELL_STATS_BUFSIZE);
1973 
1974 	return (0);
1975 }
1976 
1977 static int
1978 xgell_pciconf_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
1979 {
1980 	xgelldev_t *lldev = (xgelldev_t *)cp;
1981 	xge_hal_status_e status;
1982 	int retsize;
1983 	char *buf;
1984 
1985 	buf = kmem_alloc(XGELL_PCICONF_BUFSIZE, KM_SLEEP);
1986 	if (buf == NULL) {
1987 		return (ENOSPC);
1988 	}
1989 	status = xge_hal_aux_pci_config_read(lldev->devh, XGELL_PCICONF_BUFSIZE,
1990 	    buf, &retsize);
1991 	if (status != XGE_HAL_OK) {
1992 		kmem_free(buf, XGELL_PCICONF_BUFSIZE);
1993 		xge_debug_ll(XGE_ERR, "pci_config_read(): status %d", status);
1994 		return (EINVAL);
1995 	}
1996 	*(buf + retsize - 1) = '\0'; /* remove last '\n' */
1997 	(void) mi_mpprintf(mp, "%s", buf);
1998 	kmem_free(buf, XGELL_PCICONF_BUFSIZE);
1999 
2000 	return (0);
2001 }
2002 
2003 static int
2004 xgell_about_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2005 {
2006 	xgelldev_t *lldev = (xgelldev_t *)cp;
2007 	xge_hal_status_e status;
2008 	int retsize;
2009 	char *buf;
2010 
2011 	buf = kmem_alloc(XGELL_ABOUT_BUFSIZE, KM_SLEEP);
2012 	if (buf == NULL) {
2013 		return (ENOSPC);
2014 	}
2015 	status = xge_hal_aux_about_read(lldev->devh, XGELL_ABOUT_BUFSIZE,
2016 	    buf, &retsize);
2017 	if (status != XGE_HAL_OK) {
2018 		kmem_free(buf, XGELL_ABOUT_BUFSIZE);
2019 		xge_debug_ll(XGE_ERR, "about_read(): status %d", status);
2020 		return (EINVAL);
2021 	}
2022 	*(buf + retsize - 1) = '\0'; /* remove last '\n' */
2023 	(void) mi_mpprintf(mp, "%s", buf);
2024 	kmem_free(buf, XGELL_ABOUT_BUFSIZE);
2025 
2026 	return (0);
2027 }
2028 
2029 static unsigned long bar0_offset = 0x110; /* adapter_control */
2030 
2031 static int
2032 xgell_bar0_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2033 {
2034 	xgelldev_t *lldev = (xgelldev_t *)cp;
2035 	xge_hal_status_e status;
2036 	int retsize;
2037 	char *buf;
2038 
2039 	buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP);
2040 	if (buf == NULL) {
2041 		return (ENOSPC);
2042 	}
2043 	status = xge_hal_aux_bar0_read(lldev->devh, bar0_offset,
2044 	    XGELL_IOCTL_BUFSIZE, buf, &retsize);
2045 	if (status != XGE_HAL_OK) {
2046 		kmem_free(buf, XGELL_IOCTL_BUFSIZE);
2047 		xge_debug_ll(XGE_ERR, "bar0_read(): status %d", status);
2048 		return (EINVAL);
2049 	}
2050 	*(buf + retsize - 1) = '\0'; /* remove last '\n' */
2051 	(void) mi_mpprintf(mp, "%s", buf);
2052 	kmem_free(buf, XGELL_IOCTL_BUFSIZE);
2053 
2054 	return (0);
2055 }
2056 
2057 static int
2058 xgell_bar0_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *credp)
2059 {
2060 	unsigned long old_offset = bar0_offset;
2061 	char *end;
2062 
2063 	if (value && *value == '0' &&
2064 	    (*(value + 1) == 'x' || *(value + 1) == 'X')) {
2065 		value += 2;
2066 	}
2067 
2068 	bar0_offset = mi_strtol(value, &end, 16);
2069 	if (end == value) {
2070 		bar0_offset = old_offset;
2071 		return (EINVAL);
2072 	}
2073 
2074 	xge_debug_ll(XGE_TRACE, "bar0: new value %s:%lX", value, bar0_offset);
2075 
2076 	return (0);
2077 }
2078 
2079 static int
2080 xgell_debug_level_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2081 {
2082 	char *buf;
2083 
2084 	buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP);
2085 	if (buf == NULL) {
2086 		return (ENOSPC);
2087 	}
2088 	(void) mi_mpprintf(mp, "debug_level %d", xge_hal_driver_debug_level());
2089 	kmem_free(buf, XGELL_IOCTL_BUFSIZE);
2090 
2091 	return (0);
2092 }
2093 
2094 static int
2095 xgell_debug_level_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
2096     cred_t *credp)
2097 {
2098 	int level;
2099 	char *end;
2100 
2101 	level = mi_strtol(value, &end, 10);
2102 	if (level < XGE_NONE || level > XGE_ERR || end == value) {
2103 		return (EINVAL);
2104 	}
2105 
2106 	xge_hal_driver_debug_level_set(level);
2107 
2108 	return (0);
2109 }
2110 
2111 static int
2112 xgell_debug_module_mask_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2113 {
2114 	char *buf;
2115 
2116 	buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP);
2117 	if (buf == NULL) {
2118 		return (ENOSPC);
2119 	}
2120 	(void) mi_mpprintf(mp, "debug_module_mask 0x%08x",
2121 	    xge_hal_driver_debug_module_mask());
2122 	kmem_free(buf, XGELL_IOCTL_BUFSIZE);
2123 
2124 	return (0);
2125 }
2126 
2127 static int
2128 xgell_debug_module_mask_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
2129 			    cred_t *credp)
2130 {
2131 	u32 mask;
2132 	char *end;
2133 
2134 	if (value && *value == '0' &&
2135 	    (*(value + 1) == 'x' || *(value + 1) == 'X')) {
2136 		value += 2;
2137 	}
2138 
2139 	mask = mi_strtol(value, &end, 16);
2140 	if (end == value) {
2141 		return (EINVAL);
2142 	}
2143 
2144 	xge_hal_driver_debug_module_mask_set(mask);
2145 
2146 	return (0);
2147 }
2148 
2149 static int
2150 xgell_devconfig_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
2151 {
2152 	xgelldev_t *lldev = (xgelldev_t *)(void *)cp;
2153 	xge_hal_status_e status;
2154 	int retsize;
2155 	char *buf;
2156 
2157 	buf = kmem_alloc(XGELL_DEVCONF_BUFSIZE, KM_SLEEP);
2158 	if (buf == NULL) {
2159 		return (ENOSPC);
2160 	}
2161 	status = xge_hal_aux_device_config_read(lldev->devh,
2162 						XGELL_DEVCONF_BUFSIZE,
2163 						buf, &retsize);
2164 	if (status != XGE_HAL_OK) {
2165 		kmem_free(buf, XGELL_DEVCONF_BUFSIZE);
2166 		xge_debug_ll(XGE_ERR, "device_config_read(): status %d",
2167 		    status);
2168 		return (EINVAL);
2169 	}
2170 	*(buf + retsize - 1) = '\0'; /* remove last '\n' */
2171 	(void) mi_mpprintf(mp, "%s", buf);
2172 	kmem_free(buf, XGELL_DEVCONF_BUFSIZE);
2173 
2174 	return (0);
2175 }
2176 
2177 /*
2178  * xgell_device_register
2179  * @devh: pointer on HAL device
2180  * @config: pointer on this network device configuration
2181  * @ll_out: output pointer. Will be assigned to valid LL device.
2182  *
2183  * This function will allocate and register network device
2184  */
2185 int
2186 xgell_device_register(xgelldev_t *lldev, xgell_config_t *config)
2187 {
2188 	mac_register_t *macp = NULL;
2189 	xge_hal_device_t *hldev = (xge_hal_device_t *)lldev->devh;
2190 
2191 	if (nd_load(&lldev->ndp, "pciconf", xgell_pciconf_get, NULL,
2192 	    (caddr_t)lldev) == B_FALSE)
2193 		goto xgell_ndd_fail;
2194 
2195 	if (nd_load(&lldev->ndp, "about", xgell_about_get, NULL,
2196 	    (caddr_t)lldev) == B_FALSE)
2197 		goto xgell_ndd_fail;
2198 
2199 	if (nd_load(&lldev->ndp, "stats", xgell_stats_get, NULL,
2200 	    (caddr_t)lldev) == B_FALSE)
2201 		goto xgell_ndd_fail;
2202 
2203 	if (nd_load(&lldev->ndp, "bar0", xgell_bar0_get, xgell_bar0_set,
2204 	    (caddr_t)lldev) == B_FALSE)
2205 		goto xgell_ndd_fail;
2206 
2207 	if (nd_load(&lldev->ndp, "debug_level", xgell_debug_level_get,
2208 	    xgell_debug_level_set, (caddr_t)lldev) == B_FALSE)
2209 		goto xgell_ndd_fail;
2210 
2211 	if (nd_load(&lldev->ndp, "debug_module_mask",
2212 	    xgell_debug_module_mask_get, xgell_debug_module_mask_set,
2213 	    (caddr_t)lldev) == B_FALSE)
2214 		goto xgell_ndd_fail;
2215 
2216 	if (nd_load(&lldev->ndp, "devconfig", xgell_devconfig_get, NULL,
2217 	    (caddr_t)lldev) == B_FALSE)
2218 		goto xgell_ndd_fail;
2219 
2220 	bcopy(config, &lldev->config, sizeof (xgell_config_t));
2221 
2222 	if (xgell_rx_create_buffer_pool(lldev) != DDI_SUCCESS) {
2223 		nd_free(&lldev->ndp);
2224 		xge_debug_ll(XGE_ERR, "unable to create RX buffer pool");
2225 		return (DDI_FAILURE);
2226 	}
2227 
2228 	mutex_init(&lldev->genlock, NULL, MUTEX_DRIVER, hldev->irqh);
2229 
2230 	if ((macp = mac_alloc(MAC_VERSION)) == NULL)
2231 		goto xgell_register_fail;
2232 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
2233 	macp->m_driver = lldev;
2234 	macp->m_dip = lldev->dev_info;
2235 	macp->m_src_addr = hldev->macaddr[0];
2236 	macp->m_callbacks = &xgell_m_callbacks;
2237 	macp->m_min_sdu = 0;
2238 	macp->m_max_sdu = hldev->config.mtu;
2239 	/*
2240 	 * Finally, we're ready to register ourselves with the Nemo
2241 	 * interface; if this succeeds, we're all ready to start()
2242 	 */
2243 
2244 	if (mac_register(macp, &lldev->mh) != 0)
2245 		goto xgell_register_fail;
2246 
2247 	/* Always free the macp after register */
2248 	if (macp != NULL)
2249 		mac_free(macp);
2250 
2251 	/* Calculate tx_copied_max here ??? */
2252 	lldev->tx_copied_max = hldev->config.fifo.max_frags *
2253 		hldev->config.fifo.alignment_size *
2254 		hldev->config.fifo.max_aligned_frags;
2255 
2256 	xge_debug_ll(XGE_TRACE, "etherenet device %s%d registered",
2257 	    XGELL_IFNAME, lldev->instance);
2258 
2259 	return (DDI_SUCCESS);
2260 
2261 xgell_ndd_fail:
2262 	nd_free(&lldev->ndp);
2263 	xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
2264 	return (DDI_FAILURE);
2265 
2266 xgell_register_fail:
2267 	if (macp != NULL)
2268 		mac_free(macp);
2269 	nd_free(&lldev->ndp);
2270 	mutex_destroy(&lldev->genlock);
2271 	/* Ignore return value, since RX not start */
2272 	(void) xgell_rx_destroy_buffer_pool(lldev);
2273 	xge_debug_ll(XGE_ERR, "%s", "unable to register networking device");
2274 	return (DDI_FAILURE);
2275 }
2276 
2277 /*
2278  * xgell_device_unregister
2279  * @devh: pointer on HAL device
2280  * @lldev: pointer to valid LL device.
2281  *
2282  * This function will unregister and free network device
2283  */
2284 int
2285 xgell_device_unregister(xgelldev_t *lldev)
2286 {
2287 	/*
2288 	 * Destroy RX buffer pool.
2289 	 */
2290 	if (xgell_rx_destroy_buffer_pool(lldev) != DDI_SUCCESS) {
2291 		return (DDI_FAILURE);
2292 	}
2293 
2294 	if (mac_unregister(lldev->mh) != 0) {
2295 		xge_debug_ll(XGE_ERR, "unable to unregister device %s%d",
2296 		    XGELL_IFNAME, lldev->instance);
2297 		return (DDI_FAILURE);
2298 	}
2299 
2300 	mutex_destroy(&lldev->genlock);
2301 
2302 	nd_free(&lldev->ndp);
2303 
2304 	xge_debug_ll(XGE_TRACE, "etherenet device %s%d unregistered",
2305 	    XGELL_IFNAME, lldev->instance);
2306 
2307 	return (DDI_SUCCESS);
2308 }
2309