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.
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.
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]
22 * Copyright 2008 NetXen, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
29 #include <sys/types.h>
31 #include <sys/debug.h>
32 #include <sys/stropts.h>
33 #include <sys/stream.h>
34 #include <sys/strlog.h>
37 #include <sys/kstat.h>
38 #include <sys/vtrace.h>
40 #include <sys/strsun.h>
41 #include <sys/ethernet.h>
42 #include <sys/modctl.h>
43 #include <sys/errno.h>
44 #include <sys/dditypes.h>
46 #include <sys/sunddi.h>
47 #include <sys/sysmacros.h>
49 #include <sys/ddi_intr.h>
52 #include "unm_nic_hw.h"
53 #include "unm_brdcfg.h"
55 #include "nic_phan_reg.h"
56 #include "unm_nic_ioctl.h"
57 #include "nx_hw_pci_regs.h"
59 char ident
[] = "Netxen nic driver v" UNM_NIC_VERSIONID
;
60 char unm_nic_driver_name
[] = "ntxn";
63 static char txbcopythreshold_propname
[] = "tx_bcopy_threshold";
64 static char rxbcopythreshold_propname
[] = "rx_bcopy_threshold";
65 static char rxringsize_propname
[] = "rx_ring_size";
66 static char jumborxringsize_propname
[] = "jumbo_rx_ring_size";
67 static char txringsize_propname
[] = "tx_ring_size";
68 static char defaultmtu_propname
[] = "default_mtu";
69 static char dmesg_propname
[] = "verbose_driver";
71 #define STRUCT_COPY(a, b) bcopy(&(b), &(a), sizeof (a))
73 extern int unm_register_mac(unm_adapter
*adapter
);
74 extern void unm_fini_kstats(unm_adapter
* adapter
);
75 extern void unm_nic_remove(unm_adapter
*adapter
);
76 extern int unm_nic_suspend(unm_adapter
*);
77 extern uint_t
unm_intr(caddr_t
, caddr_t
);
79 /* Data access requirements. */
80 static struct ddi_device_acc_attr unm_dev_attr
= {
86 static struct ddi_device_acc_attr unm_buf_attr
= {
92 static ddi_dma_attr_t unm_dma_attr_desc
= {
93 DMA_ATTR_V0
, /* dma_attr_version */
94 0, /* dma_attr_addr_lo */
95 0xffffffffull
, /* dma_attr_addr_hi */
96 0x000fffffull
, /* dma_attr_count_max */
97 4096, /* dma_attr_align */
98 0x000fffffull
, /* dma_attr_burstsizes */
99 4, /* dma_attr_minxfer */
100 0x003fffffull
, /* dma_attr_maxxfer */
101 0xffffffffull
, /* dma_attr_seg */
102 1, /* dma_attr_sgllen */
103 1, /* dma_attr_granular */
104 0 /* dma_attr_flags */
107 static ddi_dma_attr_t unm_dma_attr_rxbuf
= {
108 DMA_ATTR_V0
, /* dma_attr_version */
109 0, /* dma_attr_addr_lo */
110 0x7ffffffffULL
, /* dma_attr_addr_hi */
111 0xffffull
, /* dma_attr_count_max */
112 4096, /* dma_attr_align */
113 0xfff8ull
, /* dma_attr_burstsizes */
114 1, /* dma_attr_minxfer */
115 0xffffffffull
, /* dma_attr_maxxfer */
116 0xffffull
, /* dma_attr_seg */
117 1, /* dma_attr_sgllen */
118 1, /* dma_attr_granular */
119 0 /* dma_attr_flags */
122 static ddi_dma_attr_t unm_dma_attr_cmddesc
= {
123 DMA_ATTR_V0
, /* dma_attr_version */
124 0, /* dma_attr_addr_lo */
125 0x7ffffffffULL
, /* dma_attr_addr_hi */
126 0xffffull
, /* dma_attr_count_max */
127 1, /* dma_attr_align */
128 0xfff8ull
, /* dma_attr_burstsizes */
129 1, /* dma_attr_minxfer */
130 0xffff0ull
, /* dma_attr_maxxfer */
131 0xffffull
, /* dma_attr_seg */
132 16, /* dma_attr_sgllen */
133 1, /* dma_attr_granular */
134 0 /* dma_attr_flags */
137 static struct nx_legacy_intr_set legacy_intr
[] = NX_LEGACY_INTR_CONFIG
;
140 check_hw_init(struct unm_adapter_s
*adapter
)
145 adapter
->unm_nic_hw_read_wx(adapter
, UNM_CAM_RAM(0x1fc), &val
, 4);
146 if (val
== 0x55555555) {
147 /* This is the first boot after power up */
148 adapter
->unm_nic_hw_read_wx(adapter
, UNM_ROMUSB_GLB_SW_RESET
,
153 if (NX_IS_REVISION_P2(adapter
->ahw
.revision_id
)) {
154 /* Start P2 boot loader */
155 adapter
->unm_nic_pci_write_normalize(adapter
,
156 UNM_CAM_RAM(0x1fc), UNM_BDINFO_MAGIC
);
157 adapter
->unm_nic_pci_write_normalize(adapter
,
158 UNM_ROMUSB_GLB_PEGTUNE_DONE
, 1);
166 unm_get_flash_block(unm_adapter
*adapter
, int base
, int size
, uint32_t *buf
)
173 for (i
= 0; i
< size
/ sizeof (uint32_t); i
++) {
174 if (rom_fast_read(adapter
, addr
, (int *)ptr32
) == -1)
177 addr
+= sizeof (uint32_t);
179 if ((char *)buf
+ size
> (char *)ptr32
) {
182 if (rom_fast_read(adapter
, addr
, &local
) == -1)
184 (void) memcpy(ptr32
, &local
,
185 (uintptr_t)((char *)buf
+ size
) - (uintptr_t)(char *)ptr32
);
193 get_flash_mac_addr(struct unm_adapter_s
*adapter
, u64 mac
[])
195 uint32_t *pmac
= (uint32_t *)&mac
[0];
197 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
)) {
198 uint32_t temp
, crbaddr
;
199 uint16_t *pmac16
= (uint16_t *)pmac
;
201 // FOR P3, read from CAM RAM
203 int pci_func
= adapter
->ahw
.pci_func
;
204 pmac16
+= (4 * pci_func
);
205 crbaddr
= CRB_MAC_BLOCK_START
+ (4 * ((pci_func
/2) * 3)) +
206 (4 * (pci_func
& 1));
208 adapter
->unm_nic_hw_read_wx(adapter
, crbaddr
, &temp
, 4);
210 *pmac16
++ = (temp
>> 16);
211 adapter
->unm_nic_hw_read_wx(adapter
, crbaddr
+4,
213 *pmac16
++ = (temp
& 0xffff);
214 *pmac16
++ = (temp
>> 16);
217 *pmac16
++ = (temp
& 0xffff);
218 *pmac16
++ = (temp
>> 16);
219 adapter
->unm_nic_hw_read_wx(adapter
, crbaddr
+4,
221 *pmac16
++ = (temp
& 0xffff);
228 if (unm_get_flash_block(adapter
, USER_START
+
229 offsetof(unm_user_info_t
, mac_addr
), FLASH_NUM_PORTS
* sizeof (U64
),
234 if (unm_get_flash_block(adapter
, USER_START_OLD
+
235 offsetof(unm_old_user_info_t
, mac_addr
),
236 FLASH_NUM_PORTS
* sizeof (U64
), pmac
) == -1)
247 unm_initialize_dummy_dma(unm_adapter
*adapter
)
249 uint32_t hi
, lo
, temp
;
250 ddi_dma_cookie_t cookie
;
252 if (unm_pci_alloc_consistent(adapter
, UNM_HOST_DUMMY_DMA_SIZE
,
253 (caddr_t
*)&adapter
->dummy_dma
.addr
, &cookie
,
254 &adapter
->dummy_dma
.dma_handle
,
255 &adapter
->dummy_dma
.acc_handle
) != DDI_SUCCESS
) {
256 cmn_err(CE_WARN
, "%s%d: Unable to alloc dummy dma buf\n",
257 adapter
->name
, adapter
->instance
);
261 adapter
->dummy_dma
.phys_addr
= cookie
.dmac_laddress
;
263 hi
= (adapter
->dummy_dma
.phys_addr
>> 32) & 0xffffffff;
264 lo
= adapter
->dummy_dma
.phys_addr
& 0xffffffff;
266 UNM_READ_LOCK(&adapter
->adapter_lock
);
267 adapter
->unm_nic_hw_write_wx(adapter
, CRB_HOST_DUMMY_BUF_ADDR_HI
,
269 adapter
->unm_nic_hw_write_wx(adapter
, CRB_HOST_DUMMY_BUF_ADDR_LO
,
271 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
)) {
272 temp
= DUMMY_BUF_INIT
;
273 adapter
->unm_nic_hw_write_wx(adapter
, CRB_HOST_DUMMY_BUF
,
276 UNM_READ_UNLOCK(&adapter
->adapter_lock
);
278 return (DDI_SUCCESS
);
282 unm_free_dummy_dma(unm_adapter
*adapter
)
284 if (adapter
->dummy_dma
.addr
) {
285 unm_pci_free_consistent(&adapter
->dummy_dma
.dma_handle
,
286 &adapter
->dummy_dma
.acc_handle
);
287 adapter
->dummy_dma
.addr
= NULL
;
292 unm_pci_cfg_init(unm_adapter
*adapter
)
294 hardware_context
*hwcontext
;
295 ddi_acc_handle_t pci_cfg_hdl
;
300 uint16_t vendor_id
, pci_cmd_word
;
301 uint8_t base_class
, sub_class
, prog_class
;
303 struct nx_legacy_intr_set
*legacy_intrp
;
305 hwcontext
= &adapter
->ahw
;
306 pci_cfg_hdl
= adapter
->pci_cfg_handle
;
309 vendor_id
= pci_config_get16(pci_cfg_hdl
, PCI_CONF_VENID
);
311 if (vendor_id
!= 0x4040) {
312 cmn_err(CE_WARN
, "%s%d: vendor id %x not 0x4040\n",
313 adapter
->name
, adapter
->instance
, vendor_id
);
314 return (DDI_FAILURE
);
317 ret
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
,
318 dip
, 0, "reg", ®_options
, &noptions
);
319 if (ret
!= DDI_PROP_SUCCESS
) {
320 cmn_err(CE_WARN
, "%s%d: Could not determine reg property\n",
321 adapter
->name
, adapter
->instance
);
322 return (DDI_FAILURE
);
325 hwcontext
->pci_func
= (reg_options
[0] >> 8) & 0x7;
326 ddi_prop_free(reg_options
);
328 base_class
= pci_config_get8(pci_cfg_hdl
, PCI_CONF_BASCLASS
);
329 sub_class
= pci_config_get8(pci_cfg_hdl
, PCI_CONF_SUBCLASS
);
330 prog_class
= pci_config_get8(pci_cfg_hdl
, PCI_CONF_PROGCLASS
);
333 * Need this check so that MEZZ card mgmt interface ntxn0 could fail
334 * attach & return and proceed to next interfaces ntxn1 and ntxn2
336 if ((base_class
!= 0x02) || (sub_class
!= 0) || (prog_class
!= 0)) {
337 cmn_err(CE_WARN
, "%s%d: Base/sub/prog class problem %d/%d/%d\n",
338 adapter
->name
, adapter
->instance
, base_class
, sub_class
,
340 return (DDI_FAILURE
);
343 hwcontext
->revision_id
= pci_config_get8(pci_cfg_hdl
, PCI_CONF_REVID
);
346 * Refuse to work with dubious P3 cards.
348 if ((hwcontext
->revision_id
>= NX_P3_A0
) &&
349 (hwcontext
->revision_id
< NX_P3_B1
)) {
350 cmn_err(CE_WARN
, "%s%d: NetXen chip revs between 0x%x-0x%x "
351 "is unsupported\n", adapter
->name
, adapter
->instance
,
353 return (DDI_FAILURE
);
357 * Save error reporting settings; clear [19:16] error status bits.
358 * Set max read request [14:12] to 0 for 128 bytes. Set max payload
359 * size[7:5] to 0 for for 128 bytes.
361 if (NX_IS_REVISION_P2(hwcontext
->revision_id
)) {
362 pexsizes
= pci_config_get32(pci_cfg_hdl
, 0xd8);
365 pci_config_put32(pci_cfg_hdl
, 0xd8, pexsizes
);
368 pci_cmd_word
= pci_config_get16(pci_cfg_hdl
, PCI_CONF_COMM
);
369 pci_cmd_word
|= (PCI_COMM_INTX_DISABLE
| PCI_COMM_SERR_ENABLE
);
370 pci_config_put16(pci_cfg_hdl
, PCI_CONF_COMM
, pci_cmd_word
);
372 if (hwcontext
->revision_id
>= NX_P3_B0
)
373 legacy_intrp
= &legacy_intr
[hwcontext
->pci_func
];
375 legacy_intrp
= &legacy_intr
[0];
377 adapter
->legacy_intr
.int_vec_bit
= legacy_intrp
->int_vec_bit
;
378 adapter
->legacy_intr
.tgt_status_reg
= legacy_intrp
->tgt_status_reg
;
379 adapter
->legacy_intr
.tgt_mask_reg
= legacy_intrp
->tgt_mask_reg
;
380 adapter
->legacy_intr
.pci_int_reg
= legacy_intrp
->pci_int_reg
;
382 return (DDI_SUCCESS
);
386 unm_free_tx_dmahdl(unm_adapter
*adapter
)
389 unm_dmah_node_t
*nodep
;
391 mutex_enter(&adapter
->tx_lock
);
392 nodep
= &adapter
->tx_dma_hdls
[0];
394 for (i
= 0; i
< adapter
->MaxTxDescCount
+ EXTRA_HANDLES
; i
++) {
395 if (nodep
->dmahdl
!= NULL
) {
396 ddi_dma_free_handle(&nodep
->dmahdl
);
397 nodep
->dmahdl
= NULL
;
403 adapter
->dmahdl_pool
= NULL
;
404 adapter
->freehdls
= 0;
405 mutex_exit(&adapter
->tx_lock
);
409 unm_alloc_tx_dmahdl(unm_adapter
*adapter
)
412 unm_dmah_node_t
*nodep
= &adapter
->tx_dma_hdls
[0];
414 mutex_enter(&adapter
->tx_lock
);
415 for (i
= 0; i
< adapter
->MaxTxDescCount
+ EXTRA_HANDLES
; i
++) {
416 if (ddi_dma_alloc_handle(adapter
->dip
, &unm_dma_attr_cmddesc
,
417 DDI_DMA_DONTWAIT
, NULL
, &nodep
->dmahdl
) != DDI_SUCCESS
) {
418 mutex_exit(&adapter
->tx_lock
);
423 nodep
->next
= nodep
- 1;
427 adapter
->dmahdl_pool
= nodep
- 1;
428 adapter
->freehdls
= i
;
429 mutex_exit(&adapter
->tx_lock
);
431 return (DDI_SUCCESS
);
434 unm_free_tx_dmahdl(adapter
);
435 cmn_err(CE_WARN
, "%s%d: Failed transmit ring dma handle allocation\n",
436 adapter
->name
, adapter
->instance
);
437 return (DDI_FAILURE
);
441 unm_free_dma_mem(dma_area_t
*dma_p
)
443 if (dma_p
->dma_hdl
!= NULL
) {
444 if (dma_p
->ncookies
) {
445 (void) ddi_dma_unbind_handle(dma_p
->dma_hdl
);
449 if (dma_p
->acc_hdl
!= NULL
) {
450 ddi_dma_mem_free(&dma_p
->acc_hdl
);
451 dma_p
->acc_hdl
= NULL
;
453 if (dma_p
->dma_hdl
!= NULL
) {
454 ddi_dma_free_handle(&dma_p
->dma_hdl
);
455 dma_p
->dma_hdl
= NULL
;
460 unm_alloc_dma_mem(unm_adapter
*adapter
, int size
, uint_t dma_flag
,
461 ddi_dma_attr_t
*dma_attr_p
, dma_area_t
*dma_p
)
466 ddi_dma_cookie_t cookie
;
468 ret
= ddi_dma_alloc_handle(adapter
->dip
,
469 dma_attr_p
, DDI_DMA_DONTWAIT
,
470 NULL
, &dma_p
->dma_hdl
);
471 if (ret
!= DDI_SUCCESS
) {
472 cmn_err(CE_WARN
, "%s%d: Failed ddi_dma_alloc_handle\n",
473 adapter
->name
, adapter
->instance
);
477 ret
= ddi_dma_mem_alloc(dma_p
->dma_hdl
,
478 size
, &adapter
->gc_attr_desc
,
479 dma_flag
& (DDI_DMA_STREAMING
| DDI_DMA_CONSISTENT
),
480 DDI_DMA_DONTWAIT
, NULL
, &vaddr
, &actual_size
,
482 if (ret
!= DDI_SUCCESS
) {
483 cmn_err(CE_WARN
, "%s%d: ddi_dma_mem_alloc() failed\n",
484 adapter
->name
, adapter
->instance
);
488 if (actual_size
< size
) {
489 cmn_err(CE_WARN
, "%s%d: ddi_dma_mem_alloc() allocated small\n",
490 adapter
->name
, adapter
->instance
);
494 ret
= ddi_dma_addr_bind_handle(dma_p
->dma_hdl
,
495 NULL
, vaddr
, size
, dma_flag
, DDI_DMA_DONTWAIT
,
496 NULL
, &cookie
, &dma_p
->ncookies
);
497 if (ret
!= DDI_DMA_MAPPED
|| dma_p
->ncookies
!= 1) {
498 cmn_err(CE_WARN
, "%s%d: ddi_dma_addr_bind_handle() failed, "
499 "%d, %d\n", adapter
->name
, adapter
->instance
, ret
,
504 dma_p
->dma_addr
= cookie
.dmac_laddress
;
505 dma_p
->vaddr
= vaddr
;
506 (void) memset(vaddr
, 0, size
);
508 return (DDI_SUCCESS
);
511 unm_free_dma_mem(dma_p
);
512 return (DDI_FAILURE
);
516 unm_free_tx_buffers(unm_adapter
*adapter
)
520 struct unm_cmd_buffer
*cmd_buf
;
521 unm_dmah_node_t
*nodep
;
523 cmd_buf
= &adapter
->cmd_buf_arr
[0];
525 for (i
= 0; i
< adapter
->MaxTxDescCount
; i
++) {
526 dma_p
= &cmd_buf
->dma_area
;
527 unm_free_dma_mem(dma_p
);
528 nodep
= cmd_buf
->head
;
529 while (nodep
!= NULL
) {
530 (void) ddi_dma_unbind_handle(nodep
->dmahdl
);
533 if (cmd_buf
->msg
!= NULL
)
534 freemsg(cmd_buf
->msg
);
537 adapter
->freecmds
= 0;
541 unm_alloc_tx_buffers(unm_adapter
*adapter
)
543 int i
, ret
, size
, allocated
= 0;
545 struct unm_cmd_buffer
*cmd_buf
;
547 cmd_buf
= &adapter
->cmd_buf_arr
[0];
548 size
= adapter
->maxmtu
;
550 for (i
= 0; i
< adapter
->MaxTxDescCount
; i
++) {
551 dma_p
= &cmd_buf
->dma_area
;
552 ret
= unm_alloc_dma_mem(adapter
, size
,
553 DDI_DMA_WRITE
| DDI_DMA_STREAMING
,
554 &unm_dma_attr_rxbuf
, dma_p
);
555 if (ret
!= DDI_SUCCESS
)
556 goto alloc_tx_buffer_fail
;
561 adapter
->freecmds
= adapter
->MaxTxDescCount
;
562 return (DDI_SUCCESS
);
564 alloc_tx_buffer_fail
:
566 cmd_buf
= &adapter
->cmd_buf_arr
[0];
567 for (i
= 0; i
< allocated
; i
++) {
568 dma_p
= &cmd_buf
->dma_area
;
569 unm_free_dma_mem(dma_p
);
572 cmn_err(CE_WARN
, "%s%d: Failed transmit ring memory allocation\n",
573 adapter
->name
, adapter
->instance
);
574 return (DDI_FAILURE
);
578 * Called by freemsg() to "free" the resource.
581 unm_rx_buffer_recycle(char *arg
)
583 unm_rx_buffer_t
*rx_buffer
= (unm_rx_buffer_t
*)(uintptr_t)arg
;
584 unm_adapter
*adapter
= rx_buffer
->adapter
;
585 unm_rcv_desc_ctx_t
*rcv_desc
= rx_buffer
->rcv_desc
;
587 rx_buffer
->mp
= desballoc(rx_buffer
->dma_info
.vaddr
,
588 rcv_desc
->dma_size
, 0, &rx_buffer
->rx_recycle
);
590 if (rx_buffer
->mp
== NULL
)
591 adapter
->stats
.desballocfailed
++;
593 mutex_enter(rcv_desc
->recycle_lock
);
594 rx_buffer
->next
= rcv_desc
->recycle_list
;
595 rcv_desc
->recycle_list
= rx_buffer
;
596 rcv_desc
->rx_buf_recycle
++;
597 mutex_exit(rcv_desc
->recycle_lock
);
601 unm_destroy_rx_ring(unm_rcv_desc_ctx_t
*rcv_desc
)
603 uint32_t i
, total_buf
;
604 unm_rx_buffer_t
*buf_pool
;
606 total_buf
= rcv_desc
->rx_buf_total
;
607 buf_pool
= rcv_desc
->rx_buf_pool
;
608 for (i
= 0; i
< total_buf
; i
++) {
609 if (buf_pool
->mp
!= NULL
)
610 freemsg(buf_pool
->mp
);
611 unm_free_dma_mem(&buf_pool
->dma_info
);
615 kmem_free(rcv_desc
->rx_buf_pool
, sizeof (unm_rx_buffer_t
) * total_buf
);
616 rcv_desc
->rx_buf_pool
= NULL
;
617 rcv_desc
->pool_list
= NULL
;
618 rcv_desc
->recycle_list
= NULL
;
619 rcv_desc
->rx_buf_free
= 0;
621 mutex_destroy(rcv_desc
->pool_lock
);
622 mutex_destroy(rcv_desc
->recycle_lock
);
626 unm_create_rx_ring(unm_adapter
*adapter
, unm_rcv_desc_ctx_t
*rcv_desc
)
628 int i
, ret
, allocate
= 0, sreoff
;
630 dma_area_t
*dma_info
;
631 unm_rx_buffer_t
*rx_buffer
;
633 sreoff
= adapter
->ahw
.cut_through
? 0 : IP_ALIGNMENT_BYTES
;
635 /* temporarily set the total rx buffers two times of MaxRxDescCount */
636 total_buf
= rcv_desc
->rx_buf_total
= rcv_desc
->MaxRxDescCount
* 2;
638 rcv_desc
->rx_buf_pool
= kmem_zalloc(sizeof (unm_rx_buffer_t
) *
639 total_buf
, KM_SLEEP
);
640 rx_buffer
= rcv_desc
->rx_buf_pool
;
641 for (i
= 0; i
< total_buf
; i
++) {
642 dma_info
= &rx_buffer
->dma_info
;
643 ret
= unm_alloc_dma_mem(adapter
, rcv_desc
->buf_size
,
644 DDI_DMA_READ
| DDI_DMA_STREAMING
,
645 &unm_dma_attr_rxbuf
, dma_info
);
646 if (ret
!= DDI_SUCCESS
)
647 goto alloc_mem_failed
;
650 dma_info
->vaddr
= (void *) ((char *)dma_info
->vaddr
+
652 dma_info
->dma_addr
+= sreoff
;
653 rx_buffer
->rx_recycle
.free_func
=
654 unm_rx_buffer_recycle
;
655 rx_buffer
->rx_recycle
.free_arg
= (caddr_t
)rx_buffer
;
656 rx_buffer
->next
= NULL
;
657 rx_buffer
->mp
= desballoc(dma_info
->vaddr
,
658 rcv_desc
->dma_size
, 0, &rx_buffer
->rx_recycle
);
659 if (rx_buffer
->mp
== NULL
)
660 adapter
->stats
.desballocfailed
++;
661 rx_buffer
->rcv_desc
= rcv_desc
;
662 rx_buffer
->adapter
= adapter
;
667 for (i
= 0; i
< (total_buf
- 1); i
++) {
668 rcv_desc
->rx_buf_pool
[i
].next
= &rcv_desc
->rx_buf_pool
[i
+ 1];
671 rcv_desc
->pool_list
= rcv_desc
->rx_buf_pool
;
672 rcv_desc
->recycle_list
= NULL
;
673 rcv_desc
->rx_buf_free
= total_buf
;
675 mutex_init(rcv_desc
->pool_lock
, NULL
,
676 MUTEX_DRIVER
, (DDI_INTR_PRI(adapter
->intr_pri
)));
677 mutex_init(rcv_desc
->recycle_lock
, NULL
,
678 MUTEX_DRIVER
, (DDI_INTR_PRI(adapter
->intr_pri
)));
680 return (DDI_SUCCESS
);
683 rx_buffer
= rcv_desc
->rx_buf_pool
;
684 for (i
= 0; i
< allocate
; i
++, rx_buffer
++) {
685 dma_info
= &rx_buffer
->dma_info
;
686 if (rx_buffer
->mp
!= NULL
)
687 freemsg(rx_buffer
->mp
);
688 unm_free_dma_mem(dma_info
);
691 kmem_free(rcv_desc
->rx_buf_pool
, sizeof (unm_rx_buffer_t
) * total_buf
);
692 rcv_desc
->rx_buf_pool
= NULL
;
694 cmn_err(CE_WARN
, "%s%d: Failed receive ring resource allocation\n",
695 adapter
->name
, adapter
->instance
);
696 return (DDI_FAILURE
);
700 unm_check_options(unm_adapter
*adapter
)
702 int i
, ring
, tx_desc
, rx_desc
, rx_jdesc
, maxrx
;
703 unm_recv_context_t
*recv_ctx
;
704 unm_rcv_desc_ctx_t
*rcv_desc
;
705 uint8_t revid
= adapter
->ahw
.revision_id
;
706 dev_info_t
*dip
= adapter
->dip
;
709 * Reduce number of regular rcv desc to half on x86.
711 maxrx
= MAX_RCV_DESCRIPTORS
;
716 verbmsg
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
719 adapter
->tx_bcopy_threshold
= ddi_prop_get_int(DDI_DEV_T_ANY
,
720 dip
, DDI_PROP_DONTPASS
, txbcopythreshold_propname
,
721 UNM_TX_BCOPY_THRESHOLD
);
722 adapter
->rx_bcopy_threshold
= ddi_prop_get_int(DDI_DEV_T_ANY
,
723 dip
, DDI_PROP_DONTPASS
, rxbcopythreshold_propname
,
724 UNM_RX_BCOPY_THRESHOLD
);
726 tx_desc
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
727 txringsize_propname
, MAX_CMD_DESCRIPTORS_HOST
);
728 if (tx_desc
>= 256 && tx_desc
<= MAX_CMD_DESCRIPTORS
&& ISP2(tx_desc
)) {
729 adapter
->MaxTxDescCount
= tx_desc
;
731 cmn_err(CE_WARN
, "%s%d: TxRingSize defaulting to %d, since "
732 ".conf value is not 2 power aligned in range 256 - %d\n",
733 adapter
->name
, adapter
->instance
, MAX_CMD_DESCRIPTORS_HOST
,
734 MAX_CMD_DESCRIPTORS
);
735 adapter
->MaxTxDescCount
= MAX_CMD_DESCRIPTORS_HOST
;
738 rx_desc
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
739 rxringsize_propname
, maxrx
);
740 if (rx_desc
>= NX_MIN_DRIVER_RDS_SIZE
&&
741 rx_desc
<= NX_MAX_SUPPORTED_RDS_SIZE
&& ISP2(rx_desc
)) {
742 adapter
->MaxRxDescCount
= rx_desc
;
744 cmn_err(CE_WARN
, "%s%d: RxRingSize defaulting to %d, since "
745 ".conf value is not 2 power aligned in range %d - %d\n",
746 adapter
->name
, adapter
->instance
, MAX_RCV_DESCRIPTORS
,
747 NX_MIN_DRIVER_RDS_SIZE
, NX_MAX_SUPPORTED_RDS_SIZE
);
748 adapter
->MaxRxDescCount
= MAX_RCV_DESCRIPTORS
;
751 rx_jdesc
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
752 jumborxringsize_propname
, MAX_JUMBO_RCV_DESCRIPTORS
);
753 if (rx_jdesc
>= NX_MIN_DRIVER_RDS_SIZE
&&
754 rx_jdesc
<= NX_MAX_SUPPORTED_JUMBO_RDS_SIZE
&& ISP2(rx_jdesc
)) {
755 adapter
->MaxJumboRxDescCount
= rx_jdesc
;
757 cmn_err(CE_WARN
, "%s%d: JumboRingSize defaulting to %d, since "
758 ".conf value is not 2 power aligned in range %d - %d\n",
759 adapter
->name
, adapter
->instance
, MAX_JUMBO_RCV_DESCRIPTORS
,
760 NX_MIN_DRIVER_RDS_SIZE
, NX_MAX_SUPPORTED_JUMBO_RDS_SIZE
);
761 adapter
->MaxJumboRxDescCount
= MAX_JUMBO_RCV_DESCRIPTORS
;
765 * Solaris does not use LRO, but older firmware needs to have a
766 * couple of descriptors for initialization.
768 adapter
->MaxLroRxDescCount
= (adapter
->fw_major
< 4) ? 2 : 0;
770 adapter
->mtu
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
,
771 DDI_PROP_DONTPASS
, defaultmtu_propname
, MTU_SIZE
);
773 if (adapter
->mtu
< MTU_SIZE
) {
774 cmn_err(CE_WARN
, "Raising mtu to %d\n", MTU_SIZE
);
775 adapter
->mtu
= MTU_SIZE
;
777 adapter
->maxmtu
= NX_IS_REVISION_P2(revid
) ? P2_MAX_MTU
: P3_MAX_MTU
;
778 if (adapter
->mtu
> adapter
->maxmtu
) {
779 cmn_err(CE_WARN
, "Lowering mtu to %d\n", adapter
->maxmtu
);
780 adapter
->mtu
= adapter
->maxmtu
;
783 adapter
->maxmtu
= adapter
->mtu
+ NX_MAX_ETHERHDR
;
786 * If we are not expecting to receive jumbo frames, save memory and
789 if (adapter
->mtu
<= MTU_SIZE
)
790 adapter
->MaxJumboRxDescCount
= NX_MIN_DRIVER_RDS_SIZE
;
792 for (i
= 0; i
< MAX_RCV_CTX
; ++i
) {
793 recv_ctx
= &adapter
->recv_ctx
[i
];
795 for (ring
= 0; ring
< adapter
->max_rds_rings
; ring
++) {
796 rcv_desc
= &recv_ctx
->rcv_desc
[ring
];
798 switch (RCV_DESC_TYPE(ring
)) {
799 case RCV_DESC_NORMAL
:
800 rcv_desc
->MaxRxDescCount
=
801 adapter
->MaxRxDescCount
;
802 if (adapter
->ahw
.cut_through
) {
804 NX_CT_DEFAULT_RX_BUF_LEN
;
805 rcv_desc
->buf_size
= rcv_desc
->dma_size
;
808 NX_RX_NORMAL_BUF_MAX_LEN
;
816 rcv_desc
->MaxRxDescCount
=
817 adapter
->MaxJumboRxDescCount
;
818 if (adapter
->ahw
.cut_through
) {
821 NX_P3_RX_JUMBO_BUF_MAX_LEN
;
823 if (NX_IS_REVISION_P2(revid
))
825 NX_P2_RX_JUMBO_BUF_MAX_LEN
;
828 NX_P3_RX_JUMBO_BUF_MAX_LEN
;
836 rcv_desc
->MaxRxDescCount
=
837 adapter
->MaxLroRxDescCount
;
838 rcv_desc
->buf_size
= MAX_RX_LRO_BUFFER_LENGTH
;
839 rcv_desc
->dma_size
= RX_LRO_DMA_MAP_LEN
;
849 vector128M(unm_adapter
*aptr
)
851 aptr
->unm_nic_pci_change_crbwindow
= &unm_nic_pci_change_crbwindow_128M
;
852 aptr
->unm_crb_writelit_adapter
= &unm_crb_writelit_adapter_128M
;
853 aptr
->unm_nic_hw_write_wx
= &unm_nic_hw_write_wx_128M
;
854 aptr
->unm_nic_hw_read_wx
= &unm_nic_hw_read_wx_128M
;
855 aptr
->unm_nic_hw_write_ioctl
= &unm_nic_hw_write_ioctl_128M
;
856 aptr
->unm_nic_hw_read_ioctl
= &unm_nic_hw_read_ioctl_128M
;
857 aptr
->unm_nic_pci_mem_write
= &unm_nic_pci_mem_write_128M
;
858 aptr
->unm_nic_pci_mem_read
= &unm_nic_pci_mem_read_128M
;
859 aptr
->unm_nic_pci_write_immediate
= &unm_nic_pci_write_immediate_128M
;
860 aptr
->unm_nic_pci_read_immediate
= &unm_nic_pci_read_immediate_128M
;
861 aptr
->unm_nic_pci_write_normalize
= &unm_nic_pci_write_normalize_128M
;
862 aptr
->unm_nic_pci_read_normalize
= &unm_nic_pci_read_normalize_128M
;
863 aptr
->unm_nic_pci_set_window
= &unm_nic_pci_set_window_128M
;
864 aptr
->unm_nic_clear_statistics
= &unm_nic_clear_statistics_128M
;
865 aptr
->unm_nic_fill_statistics
= &unm_nic_fill_statistics_128M
;
869 vector2M(unm_adapter
*aptr
)
871 aptr
->unm_nic_pci_change_crbwindow
= &unm_nic_pci_change_crbwindow_2M
;
872 aptr
->unm_crb_writelit_adapter
= &unm_crb_writelit_adapter_2M
;
873 aptr
->unm_nic_hw_write_wx
= &unm_nic_hw_write_wx_2M
;
874 aptr
->unm_nic_hw_read_wx
= &unm_nic_hw_read_wx_2M
;
875 aptr
->unm_nic_hw_write_ioctl
= &unm_nic_hw_write_wx_2M
;
876 aptr
->unm_nic_hw_read_ioctl
= &unm_nic_hw_read_wx_2M
;
877 aptr
->unm_nic_pci_mem_write
= &unm_nic_pci_mem_write_2M
;
878 aptr
->unm_nic_pci_mem_read
= &unm_nic_pci_mem_read_2M
;
879 aptr
->unm_nic_pci_write_immediate
= &unm_nic_pci_write_immediate_2M
;
880 aptr
->unm_nic_pci_read_immediate
= &unm_nic_pci_read_immediate_2M
;
881 aptr
->unm_nic_pci_write_normalize
= &unm_nic_pci_write_normalize_2M
;
882 aptr
->unm_nic_pci_read_normalize
= &unm_nic_pci_read_normalize_2M
;
883 aptr
->unm_nic_pci_set_window
= &unm_nic_pci_set_window_2M
;
884 aptr
->unm_nic_clear_statistics
= &unm_nic_clear_statistics_2M
;
885 aptr
->unm_nic_fill_statistics
= &unm_nic_fill_statistics_2M
;
889 unm_pci_map_setup(unm_adapter
*adapter
)
892 caddr_t reg_base
, db_base
;
893 caddr_t mem_ptr0
, mem_ptr1
= NULL
, mem_ptr2
= NULL
;
894 unsigned long pci_len0
;
895 unsigned long first_page_group_start
, first_page_group_end
;
897 off_t regsize
, dbsize
= UNM_DB_MAPSIZE_BYTES
;
898 dev_info_t
*dip
= adapter
->dip
;
900 adapter
->ahw
.qdr_sn_window
= adapter
->ahw
.ddr_mn_window
= -1;
902 /* map register space */
904 ret
= ddi_dev_regsize(dip
, 1, ®size
);
905 if (ret
!= DDI_SUCCESS
) {
906 cmn_err(CE_WARN
, "%s%d: failed to read reg size for bar0\n",
907 adapter
->name
, adapter
->instance
);
908 return (DDI_FAILURE
);
911 ret
= ddi_regs_map_setup(dip
, 1, ®_base
, 0,
912 regsize
, &unm_dev_attr
, &adapter
->regs_handle
);
913 if (ret
!= DDI_SUCCESS
) {
914 cmn_err(CE_WARN
, "%s%d: failed to map registers\n",
915 adapter
->name
, adapter
->instance
);
916 return (DDI_FAILURE
);
921 if (regsize
== UNM_PCI_128MB_SIZE
) {
922 pci_len0
= FIRST_PAGE_GROUP_SIZE
;
923 mem_ptr1
= mem_ptr0
+ SECOND_PAGE_GROUP_START
;
924 mem_ptr2
= mem_ptr0
+ THIRD_PAGE_GROUP_START
;
925 first_page_group_start
= FIRST_PAGE_GROUP_START
;
926 first_page_group_end
= FIRST_PAGE_GROUP_END
;
928 } else if (regsize
== UNM_PCI_32MB_SIZE
) {
931 mem_ptr2
= mem_ptr0
+
932 (THIRD_PAGE_GROUP_START
- SECOND_PAGE_GROUP_START
);
933 first_page_group_start
= 0;
934 first_page_group_end
= 0;
936 } else if (regsize
== UNM_PCI_2MB_SIZE
) {
937 pci_len0
= UNM_PCI_2MB_SIZE
;
938 first_page_group_start
= 0;
939 first_page_group_end
= 0;
940 adapter
->ahw
.ddr_mn_window
= adapter
->ahw
.qdr_sn_window
= 0;
941 adapter
->ahw
.mn_win_crb
= 0x100000 + PCIX_MN_WINDOW
+
942 (adapter
->ahw
.pci_func
* 0x20);
943 if (adapter
->ahw
.pci_func
< 4)
944 adapter
->ahw
.ms_win_crb
= 0x100000 + PCIX_SN_WINDOW
+
945 (adapter
->ahw
.pci_func
* 0x20);
947 adapter
->ahw
.ms_win_crb
= 0x100000 + PCIX_SN_WINDOW
+
948 0xA0 + ((adapter
->ahw
.pci_func
- 4) * 0x10);
951 cmn_err(CE_WARN
, "%s%d: invalid pci regs map size %ld\n",
952 adapter
->name
, adapter
->instance
, regsize
);
953 ddi_regs_map_free(&adapter
->regs_handle
);
954 return (DDI_FAILURE
);
957 adapter
->ahw
.pci_base0
= (unsigned long)mem_ptr0
;
958 adapter
->ahw
.pci_len0
= pci_len0
;
959 adapter
->ahw
.pci_base1
= (unsigned long)mem_ptr1
;
960 adapter
->ahw
.pci_len1
= SECOND_PAGE_GROUP_SIZE
;
961 adapter
->ahw
.pci_base2
= (unsigned long)mem_ptr2
;
962 adapter
->ahw
.pci_len2
= THIRD_PAGE_GROUP_SIZE
;
963 adapter
->ahw
.crb_base
=
964 PCI_OFFSET_SECOND_RANGE(adapter
, UNM_PCI_CRBSPACE
);
966 adapter
->ahw
.first_page_group_start
= first_page_group_start
;
967 adapter
->ahw
.first_page_group_end
= first_page_group_end
;
971 ret
= ddi_regs_map_setup(dip
, 2, &db_base
, 0,
972 dbsize
, &unm_dev_attr
, &adapter
->db_handle
);
973 if (ret
!= DDI_SUCCESS
) {
974 cmn_err(CE_WARN
, "%s%d: failed to map doorbell\n",
975 adapter
->name
, adapter
->instance
);
976 ddi_regs_map_free(&adapter
->regs_handle
);
977 return (DDI_FAILURE
);
980 adapter
->ahw
.db_base
= (unsigned long)db_base
;
981 adapter
->ahw
.db_len
= dbsize
;
983 return (DDI_SUCCESS
);
987 unm_initialize_intr(unm_adapter
*adapter
)
991 int type
, count
, avail
, actual
;
993 ret
= ddi_intr_get_supported_types(adapter
->dip
, &type
);
994 if (ret
!= DDI_SUCCESS
) {
995 cmn_err(CE_WARN
, "%s%d: ddi_intr_get_supported_types() "
996 "failed\n", adapter
->name
, adapter
->instance
);
997 return (DDI_FAILURE
);
1000 type
= DDI_INTR_TYPE_MSI
;
1001 ret
= ddi_intr_get_nintrs(adapter
->dip
, type
, &count
);
1002 if ((ret
== DDI_SUCCESS
) && (count
> 0))
1005 type
= DDI_INTR_TYPE_FIXED
;
1006 ret
= ddi_intr_get_nintrs(adapter
->dip
, type
, &count
);
1007 if ((ret
!= DDI_SUCCESS
) || (count
== 0)) {
1009 "ddi_intr_get_nintrs() failure ret=%d\n", ret
);
1010 return (DDI_FAILURE
);
1014 adapter
->intr_type
= type
;
1015 adapter
->flags
&= ~(UNM_NIC_MSI_ENABLED
| UNM_NIC_MSIX_ENABLED
);
1016 if (type
== DDI_INTR_TYPE_MSI
)
1017 adapter
->flags
|= UNM_NIC_MSI_ENABLED
;
1019 /* Get number of available interrupts */
1020 ret
= ddi_intr_get_navail(adapter
->dip
, type
, &avail
);
1021 if ((ret
!= DDI_SUCCESS
) || (avail
== 0)) {
1022 cmn_err(CE_WARN
, "ddi_intr_get_navail() failure, ret=%d\n",
1024 return (DDI_FAILURE
);
1027 ret
= ddi_intr_alloc(adapter
->dip
, &adapter
->intr_handle
,
1028 type
, 0, 1, &actual
, DDI_INTR_ALLOC_NORMAL
);
1029 if ((ret
!= DDI_SUCCESS
) || (actual
== 0)) {
1030 cmn_err(CE_WARN
, "ddi_intr_alloc() failure: %d\n", ret
);
1031 return (DDI_FAILURE
);
1034 ret
= ddi_intr_get_pri(adapter
->intr_handle
, &adapter
->intr_pri
);
1035 if (ret
!= DDI_SUCCESS
) {
1036 cmn_err(CE_WARN
, "ddi_intr_get_pri() failure: %d\n", ret
);
1039 /* Call ddi_intr_add_handler() */
1040 ret
= ddi_intr_add_handler(adapter
->intr_handle
, unm_intr
,
1041 (caddr_t
)adapter
, NULL
);
1042 if (ret
!= DDI_SUCCESS
) {
1043 cmn_err(CE_WARN
, "%s%d: ddi_intr_add_handler() failure\n",
1044 adapter
->name
, adapter
->instance
);
1045 (void) ddi_intr_free(adapter
->intr_handle
);
1046 return (DDI_FAILURE
);
1049 /* Add softintr if required */
1051 return (DDI_SUCCESS
);
1056 unm_destroy_intr(unm_adapter
*adapter
)
1058 /* disable interrupt */
1059 if (adapter
->intr_type
== DDI_INTR_TYPE_MSI
)
1060 (void) ddi_intr_block_disable(&adapter
->intr_handle
, 1);
1062 (void) ddi_intr_disable(adapter
->intr_handle
);
1064 (void) ddi_intr_remove_handler(adapter
->intr_handle
);
1065 (void) ddi_intr_free(adapter
->intr_handle
);
1067 /* Remove the software intr handler */
1071 netxen_set_port_mode(unm_adapter
*adapter
)
1073 static int wol_port_mode
= UNM_PORT_MODE_AUTO_NEG_1G
;
1074 static int port_mode
= UNM_PORT_MODE_AUTO_NEG
;
1075 int btype
= adapter
->ahw
.boardcfg
.board_type
, data
= 0;
1077 if (btype
== UNM_BRDTYPE_P3_HMEZ
|| btype
== UNM_BRDTYPE_P3_XG_LOM
) {
1078 data
= port_mode
; /* set to port_mode normally */
1079 if ((port_mode
!= UNM_PORT_MODE_802_3_AP
) &&
1080 (port_mode
!= UNM_PORT_MODE_XG
) &&
1081 (port_mode
!= UNM_PORT_MODE_AUTO_NEG_1G
) &&
1082 (port_mode
!= UNM_PORT_MODE_AUTO_NEG_XG
))
1083 data
= UNM_PORT_MODE_AUTO_NEG
;
1085 adapter
->unm_nic_hw_write_wx(adapter
, UNM_PORT_MODE_ADDR
,
1088 if ((wol_port_mode
!= UNM_PORT_MODE_802_3_AP
) &&
1089 (wol_port_mode
!= UNM_PORT_MODE_XG
) &&
1090 (wol_port_mode
!= UNM_PORT_MODE_AUTO_NEG_1G
) &&
1091 (wol_port_mode
!= UNM_PORT_MODE_AUTO_NEG_XG
))
1092 wol_port_mode
= UNM_PORT_MODE_AUTO_NEG
;
1094 adapter
->unm_nic_hw_write_wx(adapter
, UNM_WOL_PORT_MODE
,
1100 netxen_pcie_strap_init(unm_adapter
*adapter
)
1102 ddi_acc_handle_t pcihdl
= adapter
->pci_cfg_handle
;
1103 u32 chicken
, control
, c8c9value
= 0xF1000;
1105 adapter
->unm_nic_hw_read_wx(adapter
, UNM_PCIE_REG(PCIE_CHICKEN3
),
1108 chicken
&= 0xFCFFFFFF; /* clear chicken3 25:24 */
1109 control
= pci_config_get32(pcihdl
, 0xD0);
1110 if ((control
& 0x000F0000) != 0x00020000) /* is it gen1? */
1111 chicken
|= 0x01000000;
1112 adapter
->unm_nic_hw_write_wx(adapter
, UNM_PCIE_REG(PCIE_CHICKEN3
),
1114 control
= pci_config_get32(pcihdl
, 0xC8);
1115 control
= pci_config_get32(pcihdl
, 0xC8);
1116 pci_config_put32(pcihdl
, 0xC8, c8c9value
);
1120 netxen_read_mac_addr(unm_adapter
*adapter
)
1122 u64 mac_addr
[8 + 1];
1126 if (get_flash_mac_addr(adapter
, mac_addr
) != 0)
1129 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
))
1130 p
= (unsigned char *)&mac_addr
[adapter
->ahw
.pci_func
];
1132 p
= (unsigned char *)&mac_addr
[adapter
->portnum
];
1134 for (i
= 0; i
< 6; i
++)
1135 adapter
->mac_addr
[i
] = p
[5 - i
];
1137 if (unm_nic_macaddr_set(adapter
, adapter
->mac_addr
) != 0)
1144 unmattach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
1146 unm_adapter
*adapter
;
1147 int i
, first_driver
= 0;
1156 return (DDI_FAILURE
);
1159 adapter
= kmem_zalloc(sizeof (unm_adapter
), KM_SLEEP
);
1161 ddi_set_driver_private(dip
, adapter
);
1162 adapter
->instance
= ddi_get_instance(dip
);
1164 adapter
->name
= ddi_driver_name(dip
);
1166 ret
= pci_config_setup(dip
, &adapter
->pci_cfg_handle
);
1167 if (ret
!= DDI_SUCCESS
) {
1168 cmn_err(CE_WARN
, "%s%d: pci_config_setup failed\n",
1169 adapter
->name
, adapter
->instance
);
1170 goto attach_setup_err
;
1173 ret
= unm_pci_cfg_init(adapter
);
1174 if (ret
!= DDI_SUCCESS
)
1177 ret
= unm_pci_map_setup(adapter
);
1178 if (ret
!= DDI_SUCCESS
)
1181 if (unm_initialize_intr(adapter
) != DDI_SUCCESS
)
1182 goto attach_unmap_regs
;
1184 rw_init(&adapter
->adapter_lock
, NULL
,
1185 RW_DRIVER
, DDI_INTR_PRI(adapter
->intr_pri
));
1186 mutex_init(&adapter
->tx_lock
, NULL
,
1187 MUTEX_DRIVER
, (DDI_INTR_PRI(adapter
->intr_pri
)));
1188 mutex_init(&adapter
->lock
, NULL
,
1189 MUTEX_DRIVER
, (DDI_INTR_PRI(adapter
->intr_pri
)));
1191 adapter
->portnum
= (int8_t)adapter
->ahw
.pci_func
;
1194 * Set the CRB window to invalid. If any register in window 0 is
1195 * accessed it should set window to 0 and then reset it to 1.
1197 adapter
->curr_window
= 255;
1199 adapter
->fw_major
= adapter
->unm_nic_pci_read_normalize(adapter
,
1200 UNM_FW_VERSION_MAJOR
);
1202 if (adapter
->fw_major
< 4)
1203 adapter
->max_rds_rings
= 3;
1205 adapter
->max_rds_rings
= 2;
1207 STRUCT_COPY(adapter
->gc_dma_attr_desc
, unm_dma_attr_desc
);
1208 STRUCT_COPY(adapter
->gc_attr_desc
, unm_buf_attr
);
1210 ret
= unm_nic_get_board_info(adapter
);
1211 if (ret
!= DDI_SUCCESS
) {
1212 cmn_err(CE_WARN
, "%s%d: error reading board config\n",
1213 adapter
->name
, adapter
->instance
);
1214 goto attach_destroy_intr
;
1217 /* Mezz cards have PCI function 0, 2, 3 enabled */
1218 switch (adapter
->ahw
.boardcfg
.board_type
) {
1219 case UNM_BRDTYPE_P2_SB31_10G_IMEZ
:
1220 case UNM_BRDTYPE_P2_SB31_10G_HMEZ
:
1221 if (adapter
->ahw
.pci_func
>= 2) {
1222 adapter
->portnum
= adapter
->ahw
.pci_func
- 2;
1228 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
)) {
1229 temp
= UNM_CRB_READ_VAL_ADAPTER(UNM_MIU_MN_CONTROL
, adapter
);
1230 adapter
->ahw
.cut_through
= NX_IS_SYSTEM_CUT_THROUGH(temp
);
1231 if (adapter
->ahw
.pci_func
== 0)
1234 if (adapter
->portnum
== 0)
1238 unm_check_options(adapter
);
1241 int first_boot
= adapter
->unm_nic_pci_read_normalize(adapter
,
1242 UNM_CAM_RAM(0x1fc));
1244 if (check_hw_init(adapter
) != 0) {
1245 cmn_err(CE_WARN
, "%s%d: Error in HW init sequence\n",
1246 adapter
->name
, adapter
->instance
);
1247 goto attach_destroy_intr
;
1250 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
))
1251 netxen_set_port_mode(adapter
);
1253 if (first_boot
!= 0x55555555) {
1255 adapter
->unm_nic_hw_write_wx(adapter
, CRB_CMDPEG_STATE
,
1257 if (pinit_from_rom(adapter
, 0) != 0)
1258 goto attach_destroy_intr
;
1262 ret
= load_from_flash(adapter
);
1263 if (ret
!= DDI_SUCCESS
)
1264 goto attach_destroy_intr
;
1267 if (ret
= unm_initialize_dummy_dma(adapter
))
1268 goto attach_destroy_intr
;
1271 * Tell the hardware our version number.
1273 i
= (_UNM_NIC_MAJOR
<< 16) |
1274 ((_UNM_NIC_MINOR
<< 8)) | (_UNM_NIC_SUBVERSION
);
1275 adapter
->unm_nic_hw_write_wx(adapter
, CRB_DRIVER_VERSION
,
1278 /* Unlock the HW, prompting the boot sequence */
1279 if ((first_boot
== 0x55555555) &&
1280 (NX_IS_REVISION_P2(adapter
->ahw
.revision_id
)))
1281 adapter
->unm_nic_pci_write_normalize(adapter
,
1282 UNM_ROMUSB_GLB_PEGTUNE_DONE
, 1);
1284 /* Handshake with the card before we register the devices. */
1285 if (phantom_init(adapter
, 0) != DDI_SUCCESS
)
1286 goto attach_destroy_intr
;
1289 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
))
1290 netxen_pcie_strap_init(adapter
);
1293 * See if the firmware gave us a virtual-physical port mapping.
1295 adapter
->physical_port
= adapter
->portnum
;
1296 i
= adapter
->unm_nic_pci_read_normalize(adapter
,
1297 CRB_V2P(adapter
->portnum
));
1298 if (i
!= 0x55555555)
1299 adapter
->physical_port
= (uint16_t)i
;
1301 adapter
->ahw
.linkup
= 0;
1303 if (receive_peg_ready(adapter
)) {
1305 goto free_dummy_dma
;
1308 if (netxen_read_mac_addr(adapter
))
1309 cmn_err(CE_WARN
, "%s%d: Failed to read MAC addr\n",
1310 adapter
->name
, adapter
->instance
);
1312 unm_nic_flash_print(adapter
);
1315 switch (adapter
->ahw
.board_type
) {
1317 cmn_err(CE_NOTE
, "%s: QUAD GbE port %d initialized\n",
1318 unm_nic_driver_name
, adapter
->portnum
);
1322 cmn_err(CE_NOTE
, "%s: XGbE port %d initialized\n",
1323 unm_nic_driver_name
, adapter
->portnum
);
1328 ret
= unm_register_mac(adapter
);
1329 if (ret
!= DDI_SUCCESS
) {
1330 cmn_err(CE_NOTE
, "%s%d: Mac registration error\n",
1331 adapter
->name
, adapter
->instance
);
1332 goto free_dummy_dma
;
1335 return (DDI_SUCCESS
);
1339 unm_free_dummy_dma(adapter
);
1340 attach_destroy_intr
:
1341 unm_destroy_intr(adapter
);
1343 ddi_regs_map_free(&(adapter
->regs_handle
));
1344 ddi_regs_map_free(&(adapter
->db_handle
));
1346 pci_config_teardown(&adapter
->pci_cfg_handle
);
1348 kmem_free(adapter
, sizeof (unm_adapter
));
1353 unmdetach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
1355 unm_adapter
*adapter
= (unm_adapter
*)ddi_get_driver_private(dip
);
1357 if (adapter
== NULL
)
1358 return (DDI_FAILURE
);
1362 unm_fini_kstats(adapter
);
1363 adapter
->kstats
[0] = NULL
;
1365 if (adapter
->pci_cfg_handle
!= NULL
)
1366 pci_config_teardown(&adapter
->pci_cfg_handle
);
1368 unm_nd_cleanup(adapter
);
1369 unm_nic_remove(adapter
);
1370 return (DDI_SUCCESS
);
1373 return (unm_nic_suspend(adapter
));
1379 return (DDI_FAILURE
);
1383 create_rxtx_rings(unm_adapter
*adapter
)
1385 unm_recv_context_t
*recv_ctx
;
1386 unm_rcv_desc_ctx_t
*rcv_desc
;
1389 adapter
->cmd_buf_arr
= (struct unm_cmd_buffer
*)kmem_zalloc(
1390 sizeof (struct unm_cmd_buffer
) * adapter
->MaxTxDescCount
,
1393 for (i
= 0; i
< MAX_RCV_CTX
; ++i
) {
1394 recv_ctx
= &adapter
->recv_ctx
[i
];
1396 for (ring
= 0; ring
< adapter
->max_rds_rings
; ring
++) {
1397 rcv_desc
= &recv_ctx
->rcv_desc
[ring
];
1398 if (unm_create_rx_ring(adapter
, rcv_desc
) !=
1400 goto attach_free_cmdbufs
;
1404 if (unm_alloc_tx_dmahdl(adapter
) != DDI_SUCCESS
)
1405 goto attach_free_cmdbufs
;
1407 if (unm_alloc_tx_buffers(adapter
) != DDI_SUCCESS
)
1408 goto attach_free_tx_dmahdl
;
1410 return (DDI_SUCCESS
);
1412 attach_free_tx_buffers
:
1413 unm_free_tx_buffers(adapter
);
1414 attach_free_tx_dmahdl
:
1415 unm_free_tx_dmahdl(adapter
);
1416 attach_free_cmdbufs
:
1417 kmem_free(adapter
->cmd_buf_arr
, sizeof (struct unm_cmd_buffer
) *
1418 adapter
->MaxTxDescCount
);
1419 for (i
= 0; i
< MAX_RCV_CTX
; ++i
) {
1420 recv_ctx
= &adapter
->recv_ctx
[i
];
1422 for (ring
= 0; ring
< adapter
->max_rds_rings
; ring
++) {
1423 rcv_desc
= &recv_ctx
->rcv_desc
[ring
];
1424 if (rcv_desc
->rx_buf_pool
!= NULL
)
1425 unm_destroy_rx_ring(rcv_desc
);
1428 return (DDI_FAILURE
);
1432 destroy_rxtx_rings(unm_adapter
*adapter
)
1434 unm_recv_context_t
*recv_ctx
;
1435 unm_rcv_desc_ctx_t
*rcv_desc
;
1438 unm_free_tx_buffers(adapter
);
1439 unm_free_tx_dmahdl(adapter
);
1441 for (ctx
= 0; ctx
< MAX_RCV_CTX
; ++ctx
) {
1442 recv_ctx
= &adapter
->recv_ctx
[ctx
];
1443 for (ring
= 0; ring
< adapter
->max_rds_rings
; ring
++) {
1444 rcv_desc
= &recv_ctx
->rcv_desc
[ring
];
1445 if (rcv_desc
->rx_buf_pool
!= NULL
)
1446 unm_destroy_rx_ring(rcv_desc
);
1450 if (adapter
->cmd_buf_arr
!= NULL
)
1451 kmem_free(adapter
->cmd_buf_arr
,
1452 sizeof (struct unm_cmd_buffer
) * adapter
->MaxTxDescCount
);
1456 DDI_DEFINE_STREAM_OPS(unm_ops
, nulldev
, nulldev
, unmattach
, unmdetach
,
1457 nodev
, NULL
, D_MP
, NULL
, NULL
);
1459 DDI_DEFINE_STREAM_OPS(unm_ops
, nulldev
, nulldev
, unmattach
, unmdetach
,
1460 nodev
, NULL
, D_MP
, NULL
);
1463 static struct modldrv modldrv
= {
1464 &mod_driverops
, /* Type of module. This one is a driver */
1466 &unm_ops
, /* driver ops */
1469 static struct modlinkage modlinkage
= {
1481 unm_ops
.devo_cb_ops
->cb_str
= NULL
;
1482 mac_init_ops(&unm_ops
, "ntxn");
1484 ret
= mod_install(&modlinkage
);
1485 if (ret
!= DDI_SUCCESS
) {
1486 mac_fini_ops(&unm_ops
);
1487 cmn_err(CE_WARN
, "ntxn: mod_install failed\n");
1499 ret
= mod_remove(&modlinkage
);
1500 if (ret
== DDI_SUCCESS
)
1501 mac_fini_ops(&unm_ops
);
1506 _info(struct modinfo
*modinfop
)
1508 return (mod_info(&modlinkage
, modinfop
));