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.
31 * Copyright (c) 2018, Joyent, Inc.
34 #include <sys/types.h>
36 #include <sys/debug.h>
37 #include <sys/stropts.h>
38 #include <sys/stream.h>
39 #include <sys/strlog.h>
42 #include <sys/kstat.h>
43 #include <sys/vtrace.h>
45 #include <sys/strsun.h>
46 #include <sys/ethernet.h>
47 #include <sys/modctl.h>
48 #include <sys/errno.h>
49 #include <sys/dditypes.h>
51 #include <sys/sunddi.h>
52 #include <sys/sysmacros.h>
54 #include <sys/ddi_intr.h>
57 #include "unm_nic_hw.h"
58 #include "unm_brdcfg.h"
60 #include "nic_phan_reg.h"
61 #include "unm_nic_ioctl.h"
62 #include "nx_hw_pci_regs.h"
64 char ident
[] = "Netxen nic driver v" UNM_NIC_VERSIONID
;
65 char unm_nic_driver_name
[] = "ntxn";
68 static char txbcopythreshold_propname
[] = "tx_bcopy_threshold";
69 static char rxbcopythreshold_propname
[] = "rx_bcopy_threshold";
70 static char rxringsize_propname
[] = "rx_ring_size";
71 static char jumborxringsize_propname
[] = "jumbo_rx_ring_size";
72 static char txringsize_propname
[] = "tx_ring_size";
73 static char defaultmtu_propname
[] = "default_mtu";
74 static char dmesg_propname
[] = "verbose_driver";
76 #define STRUCT_COPY(a, b) bcopy(&(b), &(a), sizeof (a))
78 extern int unm_register_mac(unm_adapter
*adapter
);
79 extern void unm_fini_kstats(unm_adapter
* adapter
);
80 extern void unm_nic_remove(unm_adapter
*adapter
);
81 extern int unm_nic_suspend(unm_adapter
*);
82 extern uint_t
unm_intr(caddr_t
, caddr_t
);
84 /* Data access requirements. */
85 static struct ddi_device_acc_attr unm_dev_attr
= {
91 static struct ddi_device_acc_attr unm_buf_attr
= {
97 static ddi_dma_attr_t unm_dma_attr_desc
= {
98 DMA_ATTR_V0
, /* dma_attr_version */
99 0, /* dma_attr_addr_lo */
100 0xffffffffull
, /* dma_attr_addr_hi */
101 0x000fffffull
, /* dma_attr_count_max */
102 4096, /* dma_attr_align */
103 0x000fffffull
, /* dma_attr_burstsizes */
104 4, /* dma_attr_minxfer */
105 0x003fffffull
, /* dma_attr_maxxfer */
106 0xffffffffull
, /* dma_attr_seg */
107 1, /* dma_attr_sgllen */
108 1, /* dma_attr_granular */
109 0 /* dma_attr_flags */
112 static ddi_dma_attr_t unm_dma_attr_rxbuf
= {
113 DMA_ATTR_V0
, /* dma_attr_version */
114 0, /* dma_attr_addr_lo */
115 0x7ffffffffULL
, /* dma_attr_addr_hi */
116 0xffffull
, /* dma_attr_count_max */
117 4096, /* dma_attr_align */
118 0xfff8ull
, /* dma_attr_burstsizes */
119 1, /* dma_attr_minxfer */
120 0xffffffffull
, /* dma_attr_maxxfer */
121 0xffffull
, /* dma_attr_seg */
122 1, /* dma_attr_sgllen */
123 1, /* dma_attr_granular */
124 0 /* dma_attr_flags */
127 static ddi_dma_attr_t unm_dma_attr_cmddesc
= {
128 DMA_ATTR_V0
, /* dma_attr_version */
129 0, /* dma_attr_addr_lo */
130 0x7ffffffffULL
, /* dma_attr_addr_hi */
131 0xffffull
, /* dma_attr_count_max */
132 1, /* dma_attr_align */
133 0xfff8ull
, /* dma_attr_burstsizes */
134 1, /* dma_attr_minxfer */
135 0xffff0ull
, /* dma_attr_maxxfer */
136 0xffffull
, /* dma_attr_seg */
137 16, /* dma_attr_sgllen */
138 1, /* dma_attr_granular */
139 0 /* dma_attr_flags */
142 static struct nx_legacy_intr_set legacy_intr
[] = NX_LEGACY_INTR_CONFIG
;
145 check_hw_init(struct unm_adapter_s
*adapter
)
150 adapter
->unm_nic_hw_read_wx(adapter
, UNM_CAM_RAM(0x1fc), &val
, 4);
151 if (val
== 0x55555555) {
152 /* This is the first boot after power up */
153 adapter
->unm_nic_hw_read_wx(adapter
, UNM_ROMUSB_GLB_SW_RESET
,
158 if (NX_IS_REVISION_P2(adapter
->ahw
.revision_id
)) {
159 /* Start P2 boot loader */
160 adapter
->unm_nic_pci_write_normalize(adapter
,
161 UNM_CAM_RAM(0x1fc), UNM_BDINFO_MAGIC
);
162 adapter
->unm_nic_pci_write_normalize(adapter
,
163 UNM_ROMUSB_GLB_PEGTUNE_DONE
, 1);
171 unm_get_flash_block(unm_adapter
*adapter
, int base
, int size
, uint32_t *buf
)
178 for (i
= 0; i
< size
/ sizeof (uint32_t); i
++) {
179 if (rom_fast_read(adapter
, addr
, (int *)ptr32
) == -1)
182 addr
+= sizeof (uint32_t);
184 if ((char *)buf
+ size
> (char *)ptr32
) {
187 if (rom_fast_read(adapter
, addr
, &local
) == -1)
189 (void) memcpy(ptr32
, &local
,
190 (uintptr_t)((char *)buf
+ size
) - (uintptr_t)(char *)ptr32
);
198 get_flash_mac_addr(struct unm_adapter_s
*adapter
, u64 mac
[])
200 uint32_t *pmac
= (uint32_t *)&mac
[0];
202 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
)) {
203 uint32_t temp
, crbaddr
;
204 uint16_t *pmac16
= (uint16_t *)pmac
;
206 // FOR P3, read from CAM RAM
208 int pci_func
= adapter
->ahw
.pci_func
;
209 pmac16
+= (4 * pci_func
);
210 crbaddr
= CRB_MAC_BLOCK_START
+ (4 * ((pci_func
/2) * 3)) +
211 (4 * (pci_func
& 1));
213 adapter
->unm_nic_hw_read_wx(adapter
, crbaddr
, &temp
, 4);
215 *pmac16
++ = (temp
>> 16);
216 adapter
->unm_nic_hw_read_wx(adapter
, crbaddr
+4,
218 *pmac16
++ = (temp
& 0xffff);
219 *pmac16
++ = (temp
>> 16);
222 *pmac16
++ = (temp
& 0xffff);
223 *pmac16
++ = (temp
>> 16);
224 adapter
->unm_nic_hw_read_wx(adapter
, crbaddr
+4,
226 *pmac16
++ = (temp
& 0xffff);
233 if (unm_get_flash_block(adapter
, USER_START
+
234 offsetof(unm_user_info_t
, mac_addr
), FLASH_NUM_PORTS
* sizeof (U64
),
239 if (unm_get_flash_block(adapter
, USER_START_OLD
+
240 offsetof(unm_old_user_info_t
, mac_addr
),
241 FLASH_NUM_PORTS
* sizeof (U64
), pmac
) == -1)
252 unm_initialize_dummy_dma(unm_adapter
*adapter
)
254 uint32_t hi
, lo
, temp
;
255 ddi_dma_cookie_t cookie
;
257 if (unm_pci_alloc_consistent(adapter
, UNM_HOST_DUMMY_DMA_SIZE
,
258 (caddr_t
*)&adapter
->dummy_dma
.addr
, &cookie
,
259 &adapter
->dummy_dma
.dma_handle
,
260 &adapter
->dummy_dma
.acc_handle
) != DDI_SUCCESS
) {
261 cmn_err(CE_WARN
, "%s%d: Unable to alloc dummy dma buf\n",
262 adapter
->name
, adapter
->instance
);
266 adapter
->dummy_dma
.phys_addr
= cookie
.dmac_laddress
;
268 hi
= (adapter
->dummy_dma
.phys_addr
>> 32) & 0xffffffff;
269 lo
= adapter
->dummy_dma
.phys_addr
& 0xffffffff;
271 UNM_READ_LOCK(&adapter
->adapter_lock
);
272 adapter
->unm_nic_hw_write_wx(adapter
, CRB_HOST_DUMMY_BUF_ADDR_HI
,
274 adapter
->unm_nic_hw_write_wx(adapter
, CRB_HOST_DUMMY_BUF_ADDR_LO
,
276 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
)) {
277 temp
= DUMMY_BUF_INIT
;
278 adapter
->unm_nic_hw_write_wx(adapter
, CRB_HOST_DUMMY_BUF
,
281 UNM_READ_UNLOCK(&adapter
->adapter_lock
);
283 return (DDI_SUCCESS
);
287 unm_free_dummy_dma(unm_adapter
*adapter
)
289 if (adapter
->dummy_dma
.addr
) {
290 unm_pci_free_consistent(&adapter
->dummy_dma
.dma_handle
,
291 &adapter
->dummy_dma
.acc_handle
);
292 adapter
->dummy_dma
.addr
= NULL
;
297 unm_pci_cfg_init(unm_adapter
*adapter
)
299 hardware_context
*hwcontext
;
300 ddi_acc_handle_t pci_cfg_hdl
;
305 uint16_t vendor_id
, pci_cmd_word
;
306 uint8_t base_class
, sub_class
, prog_class
;
308 struct nx_legacy_intr_set
*legacy_intrp
;
310 hwcontext
= &adapter
->ahw
;
311 pci_cfg_hdl
= adapter
->pci_cfg_handle
;
314 vendor_id
= pci_config_get16(pci_cfg_hdl
, PCI_CONF_VENID
);
316 if (vendor_id
!= 0x4040) {
317 cmn_err(CE_WARN
, "%s%d: vendor id %x not 0x4040\n",
318 adapter
->name
, adapter
->instance
, vendor_id
);
319 return (DDI_FAILURE
);
322 ret
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
,
323 dip
, 0, "reg", ®_options
, &noptions
);
324 if (ret
!= DDI_PROP_SUCCESS
) {
325 cmn_err(CE_WARN
, "%s%d: Could not determine reg property\n",
326 adapter
->name
, adapter
->instance
);
327 return (DDI_FAILURE
);
330 hwcontext
->pci_func
= (reg_options
[0] >> 8) & 0x7;
331 ddi_prop_free(reg_options
);
333 base_class
= pci_config_get8(pci_cfg_hdl
, PCI_CONF_BASCLASS
);
334 sub_class
= pci_config_get8(pci_cfg_hdl
, PCI_CONF_SUBCLASS
);
335 prog_class
= pci_config_get8(pci_cfg_hdl
, PCI_CONF_PROGCLASS
);
338 * Need this check so that MEZZ card mgmt interface ntxn0 could fail
339 * attach & return and proceed to next interfaces ntxn1 and ntxn2
341 if ((base_class
!= 0x02) || (sub_class
!= 0) || (prog_class
!= 0)) {
342 cmn_err(CE_WARN
, "%s%d: Base/sub/prog class problem %d/%d/%d\n",
343 adapter
->name
, adapter
->instance
, base_class
, sub_class
,
345 return (DDI_FAILURE
);
348 hwcontext
->revision_id
= pci_config_get8(pci_cfg_hdl
, PCI_CONF_REVID
);
351 * Refuse to work with dubious P3 cards.
353 if ((hwcontext
->revision_id
>= NX_P3_A0
) &&
354 (hwcontext
->revision_id
< NX_P3_B1
)) {
355 cmn_err(CE_WARN
, "%s%d: NetXen chip revs between 0x%x-0x%x "
356 "is unsupported\n", adapter
->name
, adapter
->instance
,
358 return (DDI_FAILURE
);
362 * Save error reporting settings; clear [19:16] error status bits.
363 * Set max read request [14:12] to 0 for 128 bytes. Set max payload
364 * size[7:5] to 0 for for 128 bytes.
366 if (NX_IS_REVISION_P2(hwcontext
->revision_id
)) {
367 pexsizes
= pci_config_get32(pci_cfg_hdl
, 0xd8);
370 pci_config_put32(pci_cfg_hdl
, 0xd8, pexsizes
);
373 pci_cmd_word
= pci_config_get16(pci_cfg_hdl
, PCI_CONF_COMM
);
374 pci_cmd_word
|= (PCI_COMM_INTX_DISABLE
| PCI_COMM_SERR_ENABLE
);
375 pci_config_put16(pci_cfg_hdl
, PCI_CONF_COMM
, pci_cmd_word
);
377 if (hwcontext
->revision_id
>= NX_P3_B0
)
378 legacy_intrp
= &legacy_intr
[hwcontext
->pci_func
];
380 legacy_intrp
= &legacy_intr
[0];
382 adapter
->legacy_intr
.int_vec_bit
= legacy_intrp
->int_vec_bit
;
383 adapter
->legacy_intr
.tgt_status_reg
= legacy_intrp
->tgt_status_reg
;
384 adapter
->legacy_intr
.tgt_mask_reg
= legacy_intrp
->tgt_mask_reg
;
385 adapter
->legacy_intr
.pci_int_reg
= legacy_intrp
->pci_int_reg
;
387 return (DDI_SUCCESS
);
391 unm_free_tx_dmahdl(unm_adapter
*adapter
)
394 unm_dmah_node_t
*nodep
;
396 mutex_enter(&adapter
->tx_lock
);
397 nodep
= &adapter
->tx_dma_hdls
[0];
399 for (i
= 0; i
< adapter
->MaxTxDescCount
+ EXTRA_HANDLES
; i
++) {
400 if (nodep
->dmahdl
!= NULL
) {
401 ddi_dma_free_handle(&nodep
->dmahdl
);
402 nodep
->dmahdl
= NULL
;
408 adapter
->dmahdl_pool
= NULL
;
409 adapter
->freehdls
= 0;
410 mutex_exit(&adapter
->tx_lock
);
414 unm_alloc_tx_dmahdl(unm_adapter
*adapter
)
417 unm_dmah_node_t
*nodep
= &adapter
->tx_dma_hdls
[0];
419 mutex_enter(&adapter
->tx_lock
);
420 for (i
= 0; i
< adapter
->MaxTxDescCount
+ EXTRA_HANDLES
; i
++) {
421 if (ddi_dma_alloc_handle(adapter
->dip
, &unm_dma_attr_cmddesc
,
422 DDI_DMA_DONTWAIT
, NULL
, &nodep
->dmahdl
) != DDI_SUCCESS
) {
423 mutex_exit(&adapter
->tx_lock
);
428 nodep
->next
= nodep
- 1;
432 adapter
->dmahdl_pool
= nodep
- 1;
433 adapter
->freehdls
= i
;
434 mutex_exit(&adapter
->tx_lock
);
436 return (DDI_SUCCESS
);
439 unm_free_tx_dmahdl(adapter
);
440 cmn_err(CE_WARN
, "%s%d: Failed transmit ring dma handle allocation\n",
441 adapter
->name
, adapter
->instance
);
442 return (DDI_FAILURE
);
446 unm_free_dma_mem(dma_area_t
*dma_p
)
448 if (dma_p
->dma_hdl
!= NULL
) {
449 if (dma_p
->ncookies
) {
450 (void) ddi_dma_unbind_handle(dma_p
->dma_hdl
);
454 if (dma_p
->acc_hdl
!= NULL
) {
455 ddi_dma_mem_free(&dma_p
->acc_hdl
);
456 dma_p
->acc_hdl
= NULL
;
458 if (dma_p
->dma_hdl
!= NULL
) {
459 ddi_dma_free_handle(&dma_p
->dma_hdl
);
460 dma_p
->dma_hdl
= NULL
;
465 unm_alloc_dma_mem(unm_adapter
*adapter
, int size
, uint_t dma_flag
,
466 ddi_dma_attr_t
*dma_attr_p
, dma_area_t
*dma_p
)
471 ddi_dma_cookie_t cookie
;
473 ret
= ddi_dma_alloc_handle(adapter
->dip
,
474 dma_attr_p
, DDI_DMA_DONTWAIT
,
475 NULL
, &dma_p
->dma_hdl
);
476 if (ret
!= DDI_SUCCESS
) {
477 cmn_err(CE_WARN
, "%s%d: Failed ddi_dma_alloc_handle\n",
478 adapter
->name
, adapter
->instance
);
482 ret
= ddi_dma_mem_alloc(dma_p
->dma_hdl
,
483 size
, &adapter
->gc_attr_desc
,
484 dma_flag
& (DDI_DMA_STREAMING
| DDI_DMA_CONSISTENT
),
485 DDI_DMA_DONTWAIT
, NULL
, &vaddr
, &actual_size
,
487 if (ret
!= DDI_SUCCESS
) {
488 cmn_err(CE_WARN
, "%s%d: ddi_dma_mem_alloc() failed\n",
489 adapter
->name
, adapter
->instance
);
493 if (actual_size
< size
) {
494 cmn_err(CE_WARN
, "%s%d: ddi_dma_mem_alloc() allocated small\n",
495 adapter
->name
, adapter
->instance
);
499 ret
= ddi_dma_addr_bind_handle(dma_p
->dma_hdl
,
500 NULL
, vaddr
, size
, dma_flag
, DDI_DMA_DONTWAIT
,
501 NULL
, &cookie
, &dma_p
->ncookies
);
502 if (ret
!= DDI_DMA_MAPPED
|| dma_p
->ncookies
!= 1) {
503 cmn_err(CE_WARN
, "%s%d: ddi_dma_addr_bind_handle() failed, "
504 "%d, %d\n", adapter
->name
, adapter
->instance
, ret
,
509 dma_p
->dma_addr
= cookie
.dmac_laddress
;
510 dma_p
->vaddr
= vaddr
;
511 (void) memset(vaddr
, 0, size
);
513 return (DDI_SUCCESS
);
516 unm_free_dma_mem(dma_p
);
517 return (DDI_FAILURE
);
521 unm_free_tx_buffers(unm_adapter
*adapter
)
525 struct unm_cmd_buffer
*cmd_buf
;
526 unm_dmah_node_t
*nodep
;
528 cmd_buf
= &adapter
->cmd_buf_arr
[0];
530 for (i
= 0; i
< adapter
->MaxTxDescCount
; i
++) {
531 dma_p
= &cmd_buf
->dma_area
;
532 unm_free_dma_mem(dma_p
);
533 nodep
= cmd_buf
->head
;
534 while (nodep
!= NULL
) {
535 (void) ddi_dma_unbind_handle(nodep
->dmahdl
);
538 if (cmd_buf
->msg
!= NULL
)
539 freemsg(cmd_buf
->msg
);
542 adapter
->freecmds
= 0;
546 unm_alloc_tx_buffers(unm_adapter
*adapter
)
548 int i
, ret
, size
, allocated
= 0;
550 struct unm_cmd_buffer
*cmd_buf
;
552 cmd_buf
= &adapter
->cmd_buf_arr
[0];
553 size
= adapter
->maxmtu
;
555 for (i
= 0; i
< adapter
->MaxTxDescCount
; i
++) {
556 dma_p
= &cmd_buf
->dma_area
;
557 ret
= unm_alloc_dma_mem(adapter
, size
,
558 DDI_DMA_WRITE
| DDI_DMA_STREAMING
,
559 &unm_dma_attr_rxbuf
, dma_p
);
560 if (ret
!= DDI_SUCCESS
)
561 goto alloc_tx_buffer_fail
;
566 adapter
->freecmds
= adapter
->MaxTxDescCount
;
567 return (DDI_SUCCESS
);
569 alloc_tx_buffer_fail
:
571 cmd_buf
= &adapter
->cmd_buf_arr
[0];
572 for (i
= 0; i
< allocated
; i
++) {
573 dma_p
= &cmd_buf
->dma_area
;
574 unm_free_dma_mem(dma_p
);
577 cmn_err(CE_WARN
, "%s%d: Failed transmit ring memory allocation\n",
578 adapter
->name
, adapter
->instance
);
579 return (DDI_FAILURE
);
583 * Called by freemsg() to "free" the resource.
586 unm_rx_buffer_recycle(char *arg
)
588 unm_rx_buffer_t
*rx_buffer
= (unm_rx_buffer_t
*)(uintptr_t)arg
;
589 unm_adapter
*adapter
= rx_buffer
->adapter
;
590 unm_rcv_desc_ctx_t
*rcv_desc
= rx_buffer
->rcv_desc
;
592 rx_buffer
->mp
= desballoc(rx_buffer
->dma_info
.vaddr
,
593 rcv_desc
->dma_size
, 0, &rx_buffer
->rx_recycle
);
595 if (rx_buffer
->mp
== NULL
)
596 adapter
->stats
.desballocfailed
++;
598 mutex_enter(rcv_desc
->recycle_lock
);
599 rx_buffer
->next
= rcv_desc
->recycle_list
;
600 rcv_desc
->recycle_list
= rx_buffer
;
601 rcv_desc
->rx_buf_recycle
++;
602 mutex_exit(rcv_desc
->recycle_lock
);
606 unm_destroy_rx_ring(unm_rcv_desc_ctx_t
*rcv_desc
)
608 uint32_t i
, total_buf
;
609 unm_rx_buffer_t
*buf_pool
;
611 total_buf
= rcv_desc
->rx_buf_total
;
612 buf_pool
= rcv_desc
->rx_buf_pool
;
613 for (i
= 0; i
< total_buf
; i
++) {
614 if (buf_pool
->mp
!= NULL
)
615 freemsg(buf_pool
->mp
);
616 unm_free_dma_mem(&buf_pool
->dma_info
);
620 kmem_free(rcv_desc
->rx_buf_pool
, sizeof (unm_rx_buffer_t
) * total_buf
);
621 rcv_desc
->rx_buf_pool
= NULL
;
622 rcv_desc
->pool_list
= NULL
;
623 rcv_desc
->recycle_list
= NULL
;
624 rcv_desc
->rx_buf_free
= 0;
626 mutex_destroy(rcv_desc
->pool_lock
);
627 mutex_destroy(rcv_desc
->recycle_lock
);
631 unm_create_rx_ring(unm_adapter
*adapter
, unm_rcv_desc_ctx_t
*rcv_desc
)
633 int i
, ret
, allocate
= 0, sreoff
;
635 dma_area_t
*dma_info
;
636 unm_rx_buffer_t
*rx_buffer
;
638 sreoff
= adapter
->ahw
.cut_through
? 0 : IP_ALIGNMENT_BYTES
;
640 /* temporarily set the total rx buffers two times of MaxRxDescCount */
641 total_buf
= rcv_desc
->rx_buf_total
= rcv_desc
->MaxRxDescCount
* 2;
643 rcv_desc
->rx_buf_pool
= kmem_zalloc(sizeof (unm_rx_buffer_t
) *
644 total_buf
, KM_SLEEP
);
645 rx_buffer
= rcv_desc
->rx_buf_pool
;
646 for (i
= 0; i
< total_buf
; i
++) {
647 dma_info
= &rx_buffer
->dma_info
;
648 ret
= unm_alloc_dma_mem(adapter
, rcv_desc
->buf_size
,
649 DDI_DMA_READ
| DDI_DMA_STREAMING
,
650 &unm_dma_attr_rxbuf
, dma_info
);
651 if (ret
!= DDI_SUCCESS
)
652 goto alloc_mem_failed
;
655 dma_info
->vaddr
= (void *) ((char *)dma_info
->vaddr
+
657 dma_info
->dma_addr
+= sreoff
;
658 rx_buffer
->rx_recycle
.free_func
=
659 unm_rx_buffer_recycle
;
660 rx_buffer
->rx_recycle
.free_arg
= (caddr_t
)rx_buffer
;
661 rx_buffer
->next
= NULL
;
662 rx_buffer
->mp
= desballoc(dma_info
->vaddr
,
663 rcv_desc
->dma_size
, 0, &rx_buffer
->rx_recycle
);
664 if (rx_buffer
->mp
== NULL
)
665 adapter
->stats
.desballocfailed
++;
666 rx_buffer
->rcv_desc
= rcv_desc
;
667 rx_buffer
->adapter
= adapter
;
672 for (i
= 0; i
< (total_buf
- 1); i
++) {
673 rcv_desc
->rx_buf_pool
[i
].next
= &rcv_desc
->rx_buf_pool
[i
+ 1];
676 rcv_desc
->pool_list
= rcv_desc
->rx_buf_pool
;
677 rcv_desc
->recycle_list
= NULL
;
678 rcv_desc
->rx_buf_free
= total_buf
;
680 mutex_init(rcv_desc
->pool_lock
, NULL
,
681 MUTEX_DRIVER
, (DDI_INTR_PRI(adapter
->intr_pri
)));
682 mutex_init(rcv_desc
->recycle_lock
, NULL
,
683 MUTEX_DRIVER
, (DDI_INTR_PRI(adapter
->intr_pri
)));
685 return (DDI_SUCCESS
);
688 rx_buffer
= rcv_desc
->rx_buf_pool
;
689 for (i
= 0; i
< allocate
; i
++, rx_buffer
++) {
690 dma_info
= &rx_buffer
->dma_info
;
691 if (rx_buffer
->mp
!= NULL
)
692 freemsg(rx_buffer
->mp
);
693 unm_free_dma_mem(dma_info
);
696 kmem_free(rcv_desc
->rx_buf_pool
, sizeof (unm_rx_buffer_t
) * total_buf
);
697 rcv_desc
->rx_buf_pool
= NULL
;
699 cmn_err(CE_WARN
, "%s%d: Failed receive ring resource allocation\n",
700 adapter
->name
, adapter
->instance
);
701 return (DDI_FAILURE
);
705 unm_check_options(unm_adapter
*adapter
)
707 int i
, ring
, tx_desc
, rx_desc
, rx_jdesc
, maxrx
;
708 unm_recv_context_t
*recv_ctx
;
709 unm_rcv_desc_ctx_t
*rcv_desc
;
710 uint8_t revid
= adapter
->ahw
.revision_id
;
711 dev_info_t
*dip
= adapter
->dip
;
714 * Reduce number of regular rcv desc to half on x86.
716 maxrx
= MAX_RCV_DESCRIPTORS
;
721 verbmsg
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
724 adapter
->tx_bcopy_threshold
= ddi_prop_get_int(DDI_DEV_T_ANY
,
725 dip
, DDI_PROP_DONTPASS
, txbcopythreshold_propname
,
726 UNM_TX_BCOPY_THRESHOLD
);
727 adapter
->rx_bcopy_threshold
= ddi_prop_get_int(DDI_DEV_T_ANY
,
728 dip
, DDI_PROP_DONTPASS
, rxbcopythreshold_propname
,
729 UNM_RX_BCOPY_THRESHOLD
);
731 tx_desc
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
732 txringsize_propname
, MAX_CMD_DESCRIPTORS_HOST
);
733 if (tx_desc
>= 256 && tx_desc
<= MAX_CMD_DESCRIPTORS
&& ISP2(tx_desc
)) {
734 adapter
->MaxTxDescCount
= tx_desc
;
736 cmn_err(CE_WARN
, "%s%d: TxRingSize defaulting to %d, since "
737 ".conf value is not 2 power aligned in range 256 - %d\n",
738 adapter
->name
, adapter
->instance
, MAX_CMD_DESCRIPTORS_HOST
,
739 MAX_CMD_DESCRIPTORS
);
740 adapter
->MaxTxDescCount
= MAX_CMD_DESCRIPTORS_HOST
;
743 rx_desc
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
744 rxringsize_propname
, maxrx
);
745 if (rx_desc
>= NX_MIN_DRIVER_RDS_SIZE
&&
746 rx_desc
<= NX_MAX_SUPPORTED_RDS_SIZE
&& ISP2(rx_desc
)) {
747 adapter
->MaxRxDescCount
= rx_desc
;
749 cmn_err(CE_WARN
, "%s%d: RxRingSize defaulting to %d, since "
750 ".conf value is not 2 power aligned in range %d - %d\n",
751 adapter
->name
, adapter
->instance
, MAX_RCV_DESCRIPTORS
,
752 NX_MIN_DRIVER_RDS_SIZE
, NX_MAX_SUPPORTED_RDS_SIZE
);
753 adapter
->MaxRxDescCount
= MAX_RCV_DESCRIPTORS
;
756 rx_jdesc
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
757 jumborxringsize_propname
, MAX_JUMBO_RCV_DESCRIPTORS
);
758 if (rx_jdesc
>= NX_MIN_DRIVER_RDS_SIZE
&&
759 rx_jdesc
<= NX_MAX_SUPPORTED_JUMBO_RDS_SIZE
&& ISP2(rx_jdesc
)) {
760 adapter
->MaxJumboRxDescCount
= rx_jdesc
;
762 cmn_err(CE_WARN
, "%s%d: JumboRingSize defaulting to %d, since "
763 ".conf value is not 2 power aligned in range %d - %d\n",
764 adapter
->name
, adapter
->instance
, MAX_JUMBO_RCV_DESCRIPTORS
,
765 NX_MIN_DRIVER_RDS_SIZE
, NX_MAX_SUPPORTED_JUMBO_RDS_SIZE
);
766 adapter
->MaxJumboRxDescCount
= MAX_JUMBO_RCV_DESCRIPTORS
;
770 * Solaris does not use LRO, but older firmware needs to have a
771 * couple of descriptors for initialization.
773 adapter
->MaxLroRxDescCount
= (adapter
->fw_major
< 4) ? 2 : 0;
775 adapter
->mtu
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
,
776 DDI_PROP_DONTPASS
, defaultmtu_propname
, MTU_SIZE
);
778 if (adapter
->mtu
< MTU_SIZE
) {
779 cmn_err(CE_WARN
, "Raising mtu to %d\n", MTU_SIZE
);
780 adapter
->mtu
= MTU_SIZE
;
782 adapter
->maxmtu
= NX_IS_REVISION_P2(revid
) ? P2_MAX_MTU
: P3_MAX_MTU
;
783 if (adapter
->mtu
> adapter
->maxmtu
) {
784 cmn_err(CE_WARN
, "Lowering mtu to %d\n", adapter
->maxmtu
);
785 adapter
->mtu
= adapter
->maxmtu
;
788 adapter
->maxmtu
= adapter
->mtu
+ NX_MAX_ETHERHDR
;
791 * If we are not expecting to receive jumbo frames, save memory and
794 if (adapter
->mtu
<= MTU_SIZE
)
795 adapter
->MaxJumboRxDescCount
= NX_MIN_DRIVER_RDS_SIZE
;
797 for (i
= 0; i
< MAX_RCV_CTX
; ++i
) {
798 recv_ctx
= &adapter
->recv_ctx
[i
];
800 for (ring
= 0; ring
< adapter
->max_rds_rings
; ring
++) {
801 rcv_desc
= &recv_ctx
->rcv_desc
[ring
];
803 switch (RCV_DESC_TYPE(ring
)) {
804 case RCV_DESC_NORMAL
:
805 rcv_desc
->MaxRxDescCount
=
806 adapter
->MaxRxDescCount
;
807 if (adapter
->ahw
.cut_through
) {
809 NX_CT_DEFAULT_RX_BUF_LEN
;
810 rcv_desc
->buf_size
= rcv_desc
->dma_size
;
813 NX_RX_NORMAL_BUF_MAX_LEN
;
821 rcv_desc
->MaxRxDescCount
=
822 adapter
->MaxJumboRxDescCount
;
823 if (adapter
->ahw
.cut_through
) {
826 NX_P3_RX_JUMBO_BUF_MAX_LEN
;
828 if (NX_IS_REVISION_P2(revid
))
830 NX_P2_RX_JUMBO_BUF_MAX_LEN
;
833 NX_P3_RX_JUMBO_BUF_MAX_LEN
;
841 rcv_desc
->MaxRxDescCount
=
842 adapter
->MaxLroRxDescCount
;
843 rcv_desc
->buf_size
= MAX_RX_LRO_BUFFER_LENGTH
;
844 rcv_desc
->dma_size
= RX_LRO_DMA_MAP_LEN
;
854 vector128M(unm_adapter
*aptr
)
856 aptr
->unm_nic_pci_change_crbwindow
= &unm_nic_pci_change_crbwindow_128M
;
857 aptr
->unm_crb_writelit_adapter
= &unm_crb_writelit_adapter_128M
;
858 aptr
->unm_nic_hw_write_wx
= &unm_nic_hw_write_wx_128M
;
859 aptr
->unm_nic_hw_read_wx
= &unm_nic_hw_read_wx_128M
;
860 aptr
->unm_nic_hw_write_ioctl
= &unm_nic_hw_write_ioctl_128M
;
861 aptr
->unm_nic_hw_read_ioctl
= &unm_nic_hw_read_ioctl_128M
;
862 aptr
->unm_nic_pci_mem_write
= &unm_nic_pci_mem_write_128M
;
863 aptr
->unm_nic_pci_mem_read
= &unm_nic_pci_mem_read_128M
;
864 aptr
->unm_nic_pci_write_immediate
= &unm_nic_pci_write_immediate_128M
;
865 aptr
->unm_nic_pci_read_immediate
= &unm_nic_pci_read_immediate_128M
;
866 aptr
->unm_nic_pci_write_normalize
= &unm_nic_pci_write_normalize_128M
;
867 aptr
->unm_nic_pci_read_normalize
= &unm_nic_pci_read_normalize_128M
;
868 aptr
->unm_nic_pci_set_window
= &unm_nic_pci_set_window_128M
;
869 aptr
->unm_nic_clear_statistics
= &unm_nic_clear_statistics_128M
;
870 aptr
->unm_nic_fill_statistics
= &unm_nic_fill_statistics_128M
;
874 vector2M(unm_adapter
*aptr
)
876 aptr
->unm_nic_pci_change_crbwindow
= &unm_nic_pci_change_crbwindow_2M
;
877 aptr
->unm_crb_writelit_adapter
= &unm_crb_writelit_adapter_2M
;
878 aptr
->unm_nic_hw_write_wx
= &unm_nic_hw_write_wx_2M
;
879 aptr
->unm_nic_hw_read_wx
= &unm_nic_hw_read_wx_2M
;
880 aptr
->unm_nic_hw_write_ioctl
= &unm_nic_hw_write_wx_2M
;
881 aptr
->unm_nic_hw_read_ioctl
= &unm_nic_hw_read_wx_2M
;
882 aptr
->unm_nic_pci_mem_write
= &unm_nic_pci_mem_write_2M
;
883 aptr
->unm_nic_pci_mem_read
= &unm_nic_pci_mem_read_2M
;
884 aptr
->unm_nic_pci_write_immediate
= &unm_nic_pci_write_immediate_2M
;
885 aptr
->unm_nic_pci_read_immediate
= &unm_nic_pci_read_immediate_2M
;
886 aptr
->unm_nic_pci_write_normalize
= &unm_nic_pci_write_normalize_2M
;
887 aptr
->unm_nic_pci_read_normalize
= &unm_nic_pci_read_normalize_2M
;
888 aptr
->unm_nic_pci_set_window
= &unm_nic_pci_set_window_2M
;
889 aptr
->unm_nic_clear_statistics
= &unm_nic_clear_statistics_2M
;
890 aptr
->unm_nic_fill_statistics
= &unm_nic_fill_statistics_2M
;
894 unm_pci_map_setup(unm_adapter
*adapter
)
897 caddr_t reg_base
, db_base
;
898 caddr_t mem_ptr0
, mem_ptr1
= NULL
, mem_ptr2
= NULL
;
899 unsigned long pci_len0
;
900 unsigned long first_page_group_start
, first_page_group_end
;
902 off_t regsize
, dbsize
= UNM_DB_MAPSIZE_BYTES
;
903 dev_info_t
*dip
= adapter
->dip
;
905 adapter
->ahw
.qdr_sn_window
= adapter
->ahw
.ddr_mn_window
= -1;
907 /* map register space */
909 ret
= ddi_dev_regsize(dip
, 1, ®size
);
910 if (ret
!= DDI_SUCCESS
) {
911 cmn_err(CE_WARN
, "%s%d: failed to read reg size for bar0\n",
912 adapter
->name
, adapter
->instance
);
913 return (DDI_FAILURE
);
916 ret
= ddi_regs_map_setup(dip
, 1, ®_base
, 0,
917 regsize
, &unm_dev_attr
, &adapter
->regs_handle
);
918 if (ret
!= DDI_SUCCESS
) {
919 cmn_err(CE_WARN
, "%s%d: failed to map registers\n",
920 adapter
->name
, adapter
->instance
);
921 return (DDI_FAILURE
);
926 if (regsize
== UNM_PCI_128MB_SIZE
) {
927 pci_len0
= FIRST_PAGE_GROUP_SIZE
;
928 mem_ptr1
= mem_ptr0
+ SECOND_PAGE_GROUP_START
;
929 mem_ptr2
= mem_ptr0
+ THIRD_PAGE_GROUP_START
;
930 first_page_group_start
= FIRST_PAGE_GROUP_START
;
931 first_page_group_end
= FIRST_PAGE_GROUP_END
;
933 } else if (regsize
== UNM_PCI_32MB_SIZE
) {
936 mem_ptr2
= mem_ptr0
+
937 (THIRD_PAGE_GROUP_START
- SECOND_PAGE_GROUP_START
);
938 first_page_group_start
= 0;
939 first_page_group_end
= 0;
941 } else if (regsize
== UNM_PCI_2MB_SIZE
) {
942 pci_len0
= UNM_PCI_2MB_SIZE
;
943 first_page_group_start
= 0;
944 first_page_group_end
= 0;
945 adapter
->ahw
.ddr_mn_window
= adapter
->ahw
.qdr_sn_window
= 0;
946 adapter
->ahw
.mn_win_crb
= 0x100000 + PCIX_MN_WINDOW
+
947 (adapter
->ahw
.pci_func
* 0x20);
948 if (adapter
->ahw
.pci_func
< 4)
949 adapter
->ahw
.ms_win_crb
= 0x100000 + PCIX_SN_WINDOW
+
950 (adapter
->ahw
.pci_func
* 0x20);
952 adapter
->ahw
.ms_win_crb
= 0x100000 + PCIX_SN_WINDOW
+
953 0xA0 + ((adapter
->ahw
.pci_func
- 4) * 0x10);
956 cmn_err(CE_WARN
, "%s%d: invalid pci regs map size %lld\n",
957 adapter
->name
, adapter
->instance
, regsize
);
958 ddi_regs_map_free(&adapter
->regs_handle
);
959 return (DDI_FAILURE
);
962 adapter
->ahw
.pci_base0
= (unsigned long)mem_ptr0
;
963 adapter
->ahw
.pci_len0
= pci_len0
;
964 adapter
->ahw
.pci_base1
= (unsigned long)mem_ptr1
;
965 adapter
->ahw
.pci_len1
= SECOND_PAGE_GROUP_SIZE
;
966 adapter
->ahw
.pci_base2
= (unsigned long)mem_ptr2
;
967 adapter
->ahw
.pci_len2
= THIRD_PAGE_GROUP_SIZE
;
968 adapter
->ahw
.crb_base
=
969 PCI_OFFSET_SECOND_RANGE(adapter
, UNM_PCI_CRBSPACE
);
971 adapter
->ahw
.first_page_group_start
= first_page_group_start
;
972 adapter
->ahw
.first_page_group_end
= first_page_group_end
;
976 ret
= ddi_regs_map_setup(dip
, 2, &db_base
, 0,
977 dbsize
, &unm_dev_attr
, &adapter
->db_handle
);
978 if (ret
!= DDI_SUCCESS
) {
979 cmn_err(CE_WARN
, "%s%d: failed to map doorbell\n",
980 adapter
->name
, adapter
->instance
);
981 ddi_regs_map_free(&adapter
->regs_handle
);
982 return (DDI_FAILURE
);
985 adapter
->ahw
.db_base
= (unsigned long)db_base
;
986 adapter
->ahw
.db_len
= dbsize
;
988 return (DDI_SUCCESS
);
992 unm_initialize_intr(unm_adapter
*adapter
)
996 int type
, count
, avail
, actual
;
998 ret
= ddi_intr_get_supported_types(adapter
->dip
, &type
);
999 if (ret
!= DDI_SUCCESS
) {
1000 cmn_err(CE_WARN
, "%s%d: ddi_intr_get_supported_types() "
1001 "failed\n", adapter
->name
, adapter
->instance
);
1002 return (DDI_FAILURE
);
1005 type
= DDI_INTR_TYPE_MSI
;
1006 ret
= ddi_intr_get_nintrs(adapter
->dip
, type
, &count
);
1007 if ((ret
== DDI_SUCCESS
) && (count
> 0))
1010 type
= DDI_INTR_TYPE_FIXED
;
1011 ret
= ddi_intr_get_nintrs(adapter
->dip
, type
, &count
);
1012 if ((ret
!= DDI_SUCCESS
) || (count
== 0)) {
1014 "ddi_intr_get_nintrs() failure ret=%d\n", ret
);
1015 return (DDI_FAILURE
);
1019 adapter
->intr_type
= type
;
1020 adapter
->flags
&= ~(UNM_NIC_MSI_ENABLED
| UNM_NIC_MSIX_ENABLED
);
1021 if (type
== DDI_INTR_TYPE_MSI
)
1022 adapter
->flags
|= UNM_NIC_MSI_ENABLED
;
1024 /* Get number of available interrupts */
1025 ret
= ddi_intr_get_navail(adapter
->dip
, type
, &avail
);
1026 if ((ret
!= DDI_SUCCESS
) || (avail
== 0)) {
1027 cmn_err(CE_WARN
, "ddi_intr_get_navail() failure, ret=%d\n",
1029 return (DDI_FAILURE
);
1032 ret
= ddi_intr_alloc(adapter
->dip
, &adapter
->intr_handle
,
1033 type
, 0, 1, &actual
, DDI_INTR_ALLOC_NORMAL
);
1034 if ((ret
!= DDI_SUCCESS
) || (actual
== 0)) {
1035 cmn_err(CE_WARN
, "ddi_intr_alloc() failure: %d\n", ret
);
1036 return (DDI_FAILURE
);
1039 ret
= ddi_intr_get_pri(adapter
->intr_handle
, &adapter
->intr_pri
);
1040 if (ret
!= DDI_SUCCESS
) {
1041 cmn_err(CE_WARN
, "ddi_intr_get_pri() failure: %d\n", ret
);
1044 /* Call ddi_intr_add_handler() */
1045 ret
= ddi_intr_add_handler(adapter
->intr_handle
, unm_intr
,
1046 (caddr_t
)adapter
, NULL
);
1047 if (ret
!= DDI_SUCCESS
) {
1048 cmn_err(CE_WARN
, "%s%d: ddi_intr_add_handler() failure\n",
1049 adapter
->name
, adapter
->instance
);
1050 (void) ddi_intr_free(adapter
->intr_handle
);
1051 return (DDI_FAILURE
);
1054 /* Add softintr if required */
1056 return (DDI_SUCCESS
);
1061 unm_destroy_intr(unm_adapter
*adapter
)
1063 /* disable interrupt */
1064 if (adapter
->intr_type
== DDI_INTR_TYPE_MSI
)
1065 (void) ddi_intr_block_disable(&adapter
->intr_handle
, 1);
1067 (void) ddi_intr_disable(adapter
->intr_handle
);
1069 (void) ddi_intr_remove_handler(adapter
->intr_handle
);
1070 (void) ddi_intr_free(adapter
->intr_handle
);
1072 /* Remove the software intr handler */
1076 netxen_set_port_mode(unm_adapter
*adapter
)
1078 static int wol_port_mode
= UNM_PORT_MODE_AUTO_NEG_1G
;
1079 static int port_mode
= UNM_PORT_MODE_AUTO_NEG
;
1080 int btype
= adapter
->ahw
.boardcfg
.board_type
, data
= 0;
1082 if (btype
== UNM_BRDTYPE_P3_HMEZ
|| btype
== UNM_BRDTYPE_P3_XG_LOM
) {
1083 data
= port_mode
; /* set to port_mode normally */
1084 if ((port_mode
!= UNM_PORT_MODE_802_3_AP
) &&
1085 (port_mode
!= UNM_PORT_MODE_XG
) &&
1086 (port_mode
!= UNM_PORT_MODE_AUTO_NEG_1G
) &&
1087 (port_mode
!= UNM_PORT_MODE_AUTO_NEG_XG
))
1088 data
= UNM_PORT_MODE_AUTO_NEG
;
1090 adapter
->unm_nic_hw_write_wx(adapter
, UNM_PORT_MODE_ADDR
,
1093 if ((wol_port_mode
!= UNM_PORT_MODE_802_3_AP
) &&
1094 (wol_port_mode
!= UNM_PORT_MODE_XG
) &&
1095 (wol_port_mode
!= UNM_PORT_MODE_AUTO_NEG_1G
) &&
1096 (wol_port_mode
!= UNM_PORT_MODE_AUTO_NEG_XG
))
1097 wol_port_mode
= UNM_PORT_MODE_AUTO_NEG
;
1099 adapter
->unm_nic_hw_write_wx(adapter
, UNM_WOL_PORT_MODE
,
1105 netxen_pcie_strap_init(unm_adapter
*adapter
)
1107 ddi_acc_handle_t pcihdl
= adapter
->pci_cfg_handle
;
1108 u32 chicken
, control
, c8c9value
= 0xF1000;
1110 adapter
->unm_nic_hw_read_wx(adapter
, UNM_PCIE_REG(PCIE_CHICKEN3
),
1113 chicken
&= 0xFCFFFFFF; /* clear chicken3 25:24 */
1114 control
= pci_config_get32(pcihdl
, 0xD0);
1115 if ((control
& 0x000F0000) != 0x00020000) /* is it gen1? */
1116 chicken
|= 0x01000000;
1117 adapter
->unm_nic_hw_write_wx(adapter
, UNM_PCIE_REG(PCIE_CHICKEN3
),
1119 control
= pci_config_get32(pcihdl
, 0xC8);
1120 control
= pci_config_get32(pcihdl
, 0xC8);
1121 pci_config_put32(pcihdl
, 0xC8, c8c9value
);
1125 netxen_read_mac_addr(unm_adapter
*adapter
)
1127 u64 mac_addr
[8 + 1];
1131 if (get_flash_mac_addr(adapter
, mac_addr
) != 0)
1134 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
))
1135 p
= (unsigned char *)&mac_addr
[adapter
->ahw
.pci_func
];
1137 p
= (unsigned char *)&mac_addr
[adapter
->portnum
];
1139 for (i
= 0; i
< 6; i
++)
1140 adapter
->mac_addr
[i
] = p
[5 - i
];
1142 if (unm_nic_macaddr_set(adapter
, adapter
->mac_addr
) != 0)
1149 unmattach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
1151 unm_adapter
*adapter
;
1152 int i
, first_driver
= 0;
1161 return (DDI_FAILURE
);
1164 adapter
= kmem_zalloc(sizeof (unm_adapter
), KM_SLEEP
);
1166 ddi_set_driver_private(dip
, adapter
);
1167 adapter
->instance
= ddi_get_instance(dip
);
1169 adapter
->name
= ddi_driver_name(dip
);
1171 ret
= pci_config_setup(dip
, &adapter
->pci_cfg_handle
);
1172 if (ret
!= DDI_SUCCESS
) {
1173 cmn_err(CE_WARN
, "%s%d: pci_config_setup failed\n",
1174 adapter
->name
, adapter
->instance
);
1175 goto attach_setup_err
;
1178 ret
= unm_pci_cfg_init(adapter
);
1179 if (ret
!= DDI_SUCCESS
)
1182 ret
= unm_pci_map_setup(adapter
);
1183 if (ret
!= DDI_SUCCESS
)
1186 if (unm_initialize_intr(adapter
) != DDI_SUCCESS
)
1187 goto attach_unmap_regs
;
1189 rw_init(&adapter
->adapter_lock
, NULL
,
1190 RW_DRIVER
, DDI_INTR_PRI(adapter
->intr_pri
));
1191 mutex_init(&adapter
->tx_lock
, NULL
,
1192 MUTEX_DRIVER
, (DDI_INTR_PRI(adapter
->intr_pri
)));
1193 mutex_init(&adapter
->lock
, NULL
,
1194 MUTEX_DRIVER
, (DDI_INTR_PRI(adapter
->intr_pri
)));
1196 adapter
->portnum
= (int8_t)adapter
->ahw
.pci_func
;
1199 * Set the CRB window to invalid. If any register in window 0 is
1200 * accessed it should set window to 0 and then reset it to 1.
1202 adapter
->curr_window
= 255;
1204 adapter
->fw_major
= adapter
->unm_nic_pci_read_normalize(adapter
,
1205 UNM_FW_VERSION_MAJOR
);
1207 if (adapter
->fw_major
< 4)
1208 adapter
->max_rds_rings
= 3;
1210 adapter
->max_rds_rings
= 2;
1212 STRUCT_COPY(adapter
->gc_dma_attr_desc
, unm_dma_attr_desc
);
1213 STRUCT_COPY(adapter
->gc_attr_desc
, unm_buf_attr
);
1215 ret
= unm_nic_get_board_info(adapter
);
1216 if (ret
!= DDI_SUCCESS
) {
1217 cmn_err(CE_WARN
, "%s%d: error reading board config\n",
1218 adapter
->name
, adapter
->instance
);
1219 goto attach_destroy_intr
;
1222 /* Mezz cards have PCI function 0, 2, 3 enabled */
1223 switch (adapter
->ahw
.boardcfg
.board_type
) {
1224 case UNM_BRDTYPE_P2_SB31_10G_IMEZ
:
1225 case UNM_BRDTYPE_P2_SB31_10G_HMEZ
:
1226 if (adapter
->ahw
.pci_func
>= 2) {
1227 adapter
->portnum
= adapter
->ahw
.pci_func
- 2;
1233 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
)) {
1234 temp
= UNM_CRB_READ_VAL_ADAPTER(UNM_MIU_MN_CONTROL
, adapter
);
1235 adapter
->ahw
.cut_through
= NX_IS_SYSTEM_CUT_THROUGH(temp
);
1236 if (adapter
->ahw
.pci_func
== 0)
1239 if (adapter
->portnum
== 0)
1243 unm_check_options(adapter
);
1246 int first_boot
= adapter
->unm_nic_pci_read_normalize(adapter
,
1247 UNM_CAM_RAM(0x1fc));
1249 if (check_hw_init(adapter
) != 0) {
1250 cmn_err(CE_WARN
, "%s%d: Error in HW init sequence\n",
1251 adapter
->name
, adapter
->instance
);
1252 goto attach_destroy_intr
;
1255 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
))
1256 netxen_set_port_mode(adapter
);
1258 if (first_boot
!= 0x55555555) {
1260 adapter
->unm_nic_hw_write_wx(adapter
, CRB_CMDPEG_STATE
,
1262 if (pinit_from_rom(adapter
, 0) != 0)
1263 goto attach_destroy_intr
;
1267 ret
= load_from_flash(adapter
);
1268 if (ret
!= DDI_SUCCESS
)
1269 goto attach_destroy_intr
;
1272 if (ret
= unm_initialize_dummy_dma(adapter
))
1273 goto attach_destroy_intr
;
1276 * Tell the hardware our version number.
1278 i
= (_UNM_NIC_MAJOR
<< 16) |
1279 ((_UNM_NIC_MINOR
<< 8)) | (_UNM_NIC_SUBVERSION
);
1280 adapter
->unm_nic_hw_write_wx(adapter
, CRB_DRIVER_VERSION
,
1283 /* Unlock the HW, prompting the boot sequence */
1284 if ((first_boot
== 0x55555555) &&
1285 (NX_IS_REVISION_P2(adapter
->ahw
.revision_id
)))
1286 adapter
->unm_nic_pci_write_normalize(adapter
,
1287 UNM_ROMUSB_GLB_PEGTUNE_DONE
, 1);
1289 /* Handshake with the card before we register the devices. */
1290 if (phantom_init(adapter
, 0) != DDI_SUCCESS
)
1291 goto attach_destroy_intr
;
1294 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
))
1295 netxen_pcie_strap_init(adapter
);
1298 * See if the firmware gave us a virtual-physical port mapping.
1300 adapter
->physical_port
= adapter
->portnum
;
1301 i
= adapter
->unm_nic_pci_read_normalize(adapter
,
1302 CRB_V2P(adapter
->portnum
));
1303 if (i
!= 0x55555555)
1304 adapter
->physical_port
= (uint16_t)i
;
1306 adapter
->ahw
.linkup
= 0;
1308 if (receive_peg_ready(adapter
)) {
1310 goto free_dummy_dma
;
1313 if (netxen_read_mac_addr(adapter
))
1314 cmn_err(CE_WARN
, "%s%d: Failed to read MAC addr\n",
1315 adapter
->name
, adapter
->instance
);
1317 unm_nic_flash_print(adapter
);
1320 switch (adapter
->ahw
.board_type
) {
1322 cmn_err(CE_NOTE
, "%s: QUAD GbE port %d initialized\n",
1323 unm_nic_driver_name
, adapter
->portnum
);
1327 cmn_err(CE_NOTE
, "%s: XGbE port %d initialized\n",
1328 unm_nic_driver_name
, adapter
->portnum
);
1333 ret
= unm_register_mac(adapter
);
1334 if (ret
!= DDI_SUCCESS
) {
1335 cmn_err(CE_NOTE
, "%s%d: Mac registration error\n",
1336 adapter
->name
, adapter
->instance
);
1337 goto free_dummy_dma
;
1340 return (DDI_SUCCESS
);
1344 unm_free_dummy_dma(adapter
);
1345 attach_destroy_intr
:
1346 unm_destroy_intr(adapter
);
1348 ddi_regs_map_free(&(adapter
->regs_handle
));
1349 ddi_regs_map_free(&(adapter
->db_handle
));
1351 pci_config_teardown(&adapter
->pci_cfg_handle
);
1353 kmem_free(adapter
, sizeof (unm_adapter
));
1358 unmdetach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
1360 unm_adapter
*adapter
= (unm_adapter
*)ddi_get_driver_private(dip
);
1362 if (adapter
== NULL
)
1363 return (DDI_FAILURE
);
1367 unm_fini_kstats(adapter
);
1368 adapter
->kstats
[0] = NULL
;
1370 if (adapter
->pci_cfg_handle
!= NULL
)
1371 pci_config_teardown(&adapter
->pci_cfg_handle
);
1373 unm_nd_cleanup(adapter
);
1374 unm_nic_remove(adapter
);
1375 return (DDI_SUCCESS
);
1378 return (unm_nic_suspend(adapter
));
1384 return (DDI_FAILURE
);
1388 create_rxtx_rings(unm_adapter
*adapter
)
1390 unm_recv_context_t
*recv_ctx
;
1391 unm_rcv_desc_ctx_t
*rcv_desc
;
1394 adapter
->cmd_buf_arr
= kmem_zalloc(
1395 sizeof (struct unm_cmd_buffer
) * adapter
->MaxTxDescCount
,
1398 for (i
= 0; i
< MAX_RCV_CTX
; ++i
) {
1399 recv_ctx
= &adapter
->recv_ctx
[i
];
1401 for (ring
= 0; ring
< adapter
->max_rds_rings
; ring
++) {
1402 rcv_desc
= &recv_ctx
->rcv_desc
[ring
];
1403 if (unm_create_rx_ring(adapter
, rcv_desc
) !=
1405 goto attach_free_cmdbufs
;
1409 if (unm_alloc_tx_dmahdl(adapter
) != DDI_SUCCESS
)
1410 goto attach_free_cmdbufs
;
1412 if (unm_alloc_tx_buffers(adapter
) != DDI_SUCCESS
)
1413 goto attach_free_tx_dmahdl
;
1415 return (DDI_SUCCESS
);
1417 attach_free_tx_buffers
:
1418 unm_free_tx_buffers(adapter
);
1419 attach_free_tx_dmahdl
:
1420 unm_free_tx_dmahdl(adapter
);
1421 attach_free_cmdbufs
:
1422 kmem_free(adapter
->cmd_buf_arr
, sizeof (struct unm_cmd_buffer
) *
1423 adapter
->MaxTxDescCount
);
1424 for (i
= 0; i
< MAX_RCV_CTX
; ++i
) {
1425 recv_ctx
= &adapter
->recv_ctx
[i
];
1427 for (ring
= 0; ring
< adapter
->max_rds_rings
; ring
++) {
1428 rcv_desc
= &recv_ctx
->rcv_desc
[ring
];
1429 if (rcv_desc
->rx_buf_pool
!= NULL
)
1430 unm_destroy_rx_ring(rcv_desc
);
1433 return (DDI_FAILURE
);
1437 destroy_rxtx_rings(unm_adapter
*adapter
)
1439 unm_recv_context_t
*recv_ctx
;
1440 unm_rcv_desc_ctx_t
*rcv_desc
;
1443 unm_free_tx_buffers(adapter
);
1444 unm_free_tx_dmahdl(adapter
);
1446 for (ctx
= 0; ctx
< MAX_RCV_CTX
; ++ctx
) {
1447 recv_ctx
= &adapter
->recv_ctx
[ctx
];
1448 for (ring
= 0; ring
< adapter
->max_rds_rings
; ring
++) {
1449 rcv_desc
= &recv_ctx
->rcv_desc
[ring
];
1450 if (rcv_desc
->rx_buf_pool
!= NULL
)
1451 unm_destroy_rx_ring(rcv_desc
);
1455 if (adapter
->cmd_buf_arr
!= NULL
)
1456 kmem_free(adapter
->cmd_buf_arr
,
1457 sizeof (struct unm_cmd_buffer
) * adapter
->MaxTxDescCount
);
1461 DDI_DEFINE_STREAM_OPS(unm_ops
, nulldev
, nulldev
, unmattach
, unmdetach
,
1462 nodev
, NULL
, D_MP
, NULL
, NULL
);
1464 DDI_DEFINE_STREAM_OPS(unm_ops
, nulldev
, nulldev
, unmattach
, unmdetach
,
1465 nodev
, NULL
, D_MP
, NULL
);
1468 static struct modldrv modldrv
= {
1469 &mod_driverops
, /* Type of module. This one is a driver */
1471 &unm_ops
, /* driver ops */
1474 static struct modlinkage modlinkage
= {
1486 unm_ops
.devo_cb_ops
->cb_str
= NULL
;
1487 mac_init_ops(&unm_ops
, "ntxn");
1489 ret
= mod_install(&modlinkage
);
1490 if (ret
!= DDI_SUCCESS
) {
1491 mac_fini_ops(&unm_ops
);
1492 cmn_err(CE_WARN
, "ntxn: mod_install failed\n");
1504 ret
= mod_remove(&modlinkage
);
1505 if (ret
== DDI_SUCCESS
)
1506 mac_fini_ops(&unm_ops
);
1511 _info(struct modinfo
*modinfop
)
1513 return (mod_info(&modlinkage
, modinfop
));