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]
23 * Copyright 2008 NetXen, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/types.h>
29 #include <sys/debug.h>
30 #include <sys/stropts.h>
31 #include <sys/stream.h>
32 #include <sys/strlog.h>
35 #include <sys/kstat.h>
36 #include <sys/vtrace.h>
38 #include <sys/strsun.h>
39 #include <sys/ethernet.h>
40 #include <sys/modctl.h>
41 #include <sys/errno.h>
42 #include <sys/dditypes.h>
44 #include <sys/sunddi.h>
45 #include <sys/sysmacros.h>
52 static long phy_lock_timeout
= 100000000;
54 static int phy_lock(struct unm_adapter_s
*adapter
)
60 /* acquire semaphore3 from PCI HW block */
61 adapter
->unm_nic_pci_read_immediate(adapter
,
62 UNM_PCIE_REG(PCIE_SEM3_LOCK
), &done
);
65 if (timeout
>= phy_lock_timeout
)
70 adapter
->unm_crb_writelit_adapter(adapter
, UNM_PHY_LOCK_ID
,
76 phy_unlock(struct unm_adapter_s
*adapter
)
80 /* release semaphore3 */
81 adapter
->unm_nic_pci_read_immediate(adapter
,
82 UNM_PCIE_REG(PCIE_SEM3_UNLOCK
), &val
);
86 * unm_niu_gbe_phy_read - read a register from the GbE PHY via
87 * mii management interface.
89 * Note: The MII management interface goes through port 0.
90 * Individual phys are addressed as follows:
92 * [7:0] register number
99 unm_niu_gbe_phy_read(struct unm_adapter_s
*adapter
, long reg
,
100 unm_crbword_t
*readval
)
102 long phy
= adapter
->physical_port
;
103 unm_niu_gb_mii_mgmt_address_t address
;
104 unm_niu_gb_mii_mgmt_command_t command
;
105 unm_niu_gb_mii_mgmt_indicators_t status
;
110 unm_niu_gb_mac_config_0_t mac_cfg0
;
112 if (phy_lock(adapter
) != 0)
116 * MII mgmt all goes through port 0 MAC interface, so it cannot be
119 adapter
->unm_nic_hw_read_wx(adapter
, UNM_NIU_GB_MAC_CONFIG_0(0),
121 if (mac_cfg0
.soft_reset
) {
122 unm_niu_gb_mac_config_0_t temp
;
123 *(unm_crbword_t
*)&temp
= 0;
124 temp
.tx_reset_pb
= 1;
125 temp
.rx_reset_pb
= 1;
126 temp
.tx_reset_mac
= 1;
127 temp
.rx_reset_mac
= 1;
128 adapter
->unm_nic_hw_write_wx(adapter
,
129 UNM_NIU_GB_MAC_CONFIG_0(0), &temp
, 4);
133 *(unm_crbword_t
*)&address
= 0;
134 address
.reg_addr
= (unm_crbword_t
)reg
;
135 address
.phy_addr
= (unm_crbword_t
)phy
;
136 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_MII_MGMT_ADDR(0),
139 *(unm_crbword_t
*)&command
= 0; /* turn off any prior activity */
140 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_MII_MGMT_COMMAND(0),
143 /* send read command */
144 command
.read_cycle
= 1;
145 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_MII_MGMT_COMMAND(0),
148 *(unm_crbword_t
*)&status
= 0;
150 adapter
->unm_nic_hw_read_wx(adapter
,
151 UNM_NIU_GB_MII_MGMT_INDICATE(0), &status
, 4);
153 } while ((status
.busy
|| status
.notvalid
) &&
154 (timeout
++ < UNM_NIU_PHY_WAITMAX
));
156 if (timeout
< UNM_NIU_PHY_WAITMAX
) {
157 adapter
->unm_nic_hw_read_wx(adapter
,
158 UNM_NIU_GB_MII_MGMT_STATUS(0), readval
, 4);
164 adapter
->unm_nic_hw_write_wx(adapter
,
165 UNM_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0
, 4);
173 * Return the current station MAC address.
174 * Note that the passed-in value must already be in network byte order.
177 unm_niu_macaddr_get(struct unm_adapter_s
*adapter
, unsigned char *addr
)
180 int phy
= adapter
->physical_port
;
184 if ((phy
< 0) || (phy
> 3))
187 UNM_WRITE_LOCK_IRQS(&adapter
->adapter_lock
, flags
);
188 if (adapter
->curr_window
!= 0) {
189 adapter
->unm_nic_pci_change_crbwindow(adapter
, 0);
192 result
= UNM_NIC_PCI_READ_32((void *)pci_base_offset(adapter
,
193 UNM_NIU_GB_STATION_ADDR_1(phy
))) >> 16;
194 result
|= ((uint64_t)UNM_NIC_PCI_READ_32((void *)pci_base_offset(
195 adapter
, UNM_NIU_GB_STATION_ADDR_0(phy
)))) << 16;
197 (void) memcpy(addr
, &result
, sizeof (unm_ethernet_macaddr_t
));
199 adapter
->unm_nic_pci_change_crbwindow(adapter
, 1);
201 UNM_WRITE_UNLOCK_IRQR(&adapter
->adapter_lock
, flags
);
207 * Set the station MAC address.
208 * Note that the passed-in value must already be in network byte order.
211 unm_niu_macaddr_set(struct unm_adapter_s
*adapter
, unm_ethernet_macaddr_t addr
)
213 unm_crbword_t temp
= 0;
214 int phy
= adapter
->physical_port
;
216 if ((phy
< 0) || (phy
> 3))
219 (void) memcpy(&temp
, addr
, 2);
221 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_STATION_ADDR_1(phy
),
224 (void) memcpy(&temp
, ((__uint8_t
*)addr
)+2, sizeof (unm_crbword_t
));
225 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_STATION_ADDR_0(phy
),
230 /* Enable a GbE interface */
232 unm_niu_enable_gbe_port(struct unm_adapter_s
*adapter
)
234 unm_niu_gb_mac_config_0_t mac_cfg0
;
235 unm_niu_gb_mac_config_1_t mac_cfg1
;
236 unm_niu_gb_mii_mgmt_config_t mii_cfg
;
237 native_t port
= adapter
->physical_port
;
242 if ((port
< 0) || (port
> UNM_NIU_MAX_GBE_PORTS
)) {
246 if (adapter
->link_speed
!= MBPS_10
&&
247 adapter
->link_speed
!= MBPS_100
&&
248 adapter
->link_speed
!= MBPS_1000
) {
250 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
)) {
252 * Do NOT fail this call because the cable is unplugged.
253 * Updated when the link comes up...
255 adapter
->link_speed
= MBPS_1000
;
261 port_mode
= adapter
->unm_nic_pci_read_normalize(adapter
,
263 if (port_mode
== UNM_PORT_MODE_802_3_AP
) {
264 *(unm_crbword_t
*)&mac_cfg0
= 0x0000003f;
265 *(unm_crbword_t
*)&mac_cfg1
= 0x0000f2df;
266 unm_crb_write_adapter(UNM_NIU_AP_MAC_CONFIG_0(port
), &mac_cfg0
,
268 unm_crb_write_adapter(UNM_NIU_AP_MAC_CONFIG_1(port
), &mac_cfg1
,
271 *(unm_crbword_t
*)&mac_cfg0
= 0;
272 mac_cfg0
.soft_reset
= 1;
273 unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port
), &mac_cfg0
,
276 *(unm_crbword_t
*)&mac_cfg0
= 0;
277 mac_cfg0
.tx_enable
= 1;
278 mac_cfg0
.rx_enable
= 1;
279 mac_cfg0
.rx_flowctl
= 0;
280 mac_cfg0
.tx_reset_pb
= 1;
281 mac_cfg0
.rx_reset_pb
= 1;
282 mac_cfg0
.tx_reset_mac
= 1;
283 mac_cfg0
.rx_reset_mac
= 1;
285 unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port
), &mac_cfg0
,
288 *(unm_crbword_t
*)&mac_cfg1
= 0;
289 mac_cfg1
.preamblelen
= 0xf;
291 mac_cfg1
.crc_enable
= 1;
292 mac_cfg1
.padshort
= 1;
293 mac_cfg1
.checklength
= 1;
294 mac_cfg1
.hugeframes
= 1;
296 switch (adapter
->link_speed
) {
298 case MBPS_100
: /* Fall Through */
299 mac_cfg1
.intfmode
= 1;
300 unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_1
301 (port
), &mac_cfg1
, adapter
);
304 unm_crb_write_adapter(
305 UNM_NIU_GB0_GMII_MODE
+(port
<<3),
307 unm_crb_write_adapter(
308 UNM_NIU_GB0_MII_MODE
+(port
<< 3),
313 mac_cfg1
.intfmode
= 2;
314 unm_crb_write_adapter(
315 UNM_NIU_GB_MAC_CONFIG_1(port
),
319 unm_crb_write_adapter(
320 UNM_NIU_GB0_MII_MODE
+(port
<< 3),
322 unm_crb_write_adapter(
323 UNM_NIU_GB0_GMII_MODE
+(port
<< 3),
328 /* Will not happen */
332 *(unm_crbword_t
*)&mii_cfg
= 0;
333 mii_cfg
.clockselect
= 7;
334 unm_crb_write_adapter(UNM_NIU_GB_MII_MGMT_CONFIG(port
),
337 *(unm_crbword_t
*)&mac_cfg0
= 0;
338 mac_cfg0
.tx_enable
= 1;
339 mac_cfg0
.rx_enable
= 1;
340 mac_cfg0
.tx_flowctl
= 0;
341 mac_cfg0
.rx_flowctl
= 0;
342 unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port
),
349 /* Disable a GbE interface */
351 unm_niu_disable_gbe_port(struct unm_adapter_s
*adapter
)
353 native_t port
= adapter
->physical_port
;
354 unm_niu_gb_mac_config_0_t mac_cfg0
;
356 if ((port
< 0) || (port
> UNM_NIU_MAX_GBE_PORTS
))
359 *(unm_crbword_t
*)&mac_cfg0
= 0;
360 mac_cfg0
.soft_reset
= 1;
362 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
))
363 adapter
->unm_nic_hw_write_wx(adapter
,
364 UNM_NIU_GB_MAC_CONFIG_0(port
), &mac_cfg0
, 0);
366 adapter
->unm_nic_hw_write_wx(adapter
,
367 UNM_NIU_GB_MAC_CONFIG_0(port
), &mac_cfg0
, 4);
371 /* Disable an XG interface */
373 unm_niu_disable_xg_port(struct unm_adapter_s
*adapter
)
375 native_t port
= adapter
->physical_port
;
376 unm_niu_xg_mac_config_0_t mac_cfg
;
378 *(unm_crbword_t
*)&mac_cfg
= 0;
379 mac_cfg
.soft_reset
= 1;
381 if (NX_IS_REVISION_P3(adapter
->ahw
.revision_id
)) {
384 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_XGE_CONFIG_0
,
387 if ((port
< 0) || (port
>= UNM_NIU_MAX_XG_PORTS
))
389 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_XGE_CONFIG_0
+
390 (port
* 0x10000), &mac_cfg
, 4);
396 /* Set promiscuous mode for a GbE interface */
398 unm_niu_set_promiscuous_mode(struct unm_adapter_s
*adapter
,
399 unm_niu_prom_mode_t mode
)
401 native_t port
= adapter
->physical_port
;
402 unm_niu_gb_drop_crc_t reg
;
403 unm_niu_gb_mac_config_0_t mac_cfg
;
405 int cnt
= 0, ret
= 0;
408 if ((port
< 0) || (port
> UNM_NIU_MAX_GBE_PORTS
))
412 adapter
->unm_nic_hw_read_wx(adapter
, UNM_NIU_GB_MAC_CONFIG_0(port
),
414 mac_cfg
.rx_enable
= 0;
415 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_MAC_CONFIG_0(port
),
418 /* wait until mac is drained by sre */
419 /* Port 0 rx fifo bit 5 */
420 val
= (0x20 << port
);
421 adapter
->unm_crb_writelit_adapter(adapter
, UNM_NIU_FRAME_COUNT_SELECT
,
425 adapter
->unm_nic_hw_read_wx(adapter
, UNM_NIU_FRAME_COUNT
,
435 /* now set promiscuous mode */
437 if (mode
== UNM_NIU_PROMISCOUS_MODE
)
442 adapter
->unm_nic_hw_read_wx(adapter
, UNM_NIU_GB_DROP_WRONGADDR
,
461 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_DROP_WRONGADDR
,
465 /* turn the mac on back */
466 mac_cfg
.rx_enable
= 1;
467 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_MAC_CONFIG_0(port
),
474 * Set the MAC address for an XG port
475 * Note that the passed-in value must already be in network byte order.
478 unm_niu_xg_macaddr_set(struct unm_adapter_s
*adapter
,
479 unm_ethernet_macaddr_t addr
)
481 int phy
= adapter
->physical_port
;
482 unm_crbword_t temp
= 0;
485 if ((phy
< 0) || (phy
> 3))
490 (void) memcpy(&temp
, addr
, 2);
492 port_mode
= adapter
->unm_nic_pci_read_normalize(adapter
,
494 if (port_mode
== UNM_PORT_MODE_802_3_AP
) {
495 adapter
->unm_nic_hw_write_wx(adapter
,
496 UNM_NIU_AP_STATION_ADDR_1(phy
), &temp
, 4);
498 (void) memcpy(&temp
, ((__uint8_t
*)addr
) + 2,
499 sizeof (unm_crbword_t
));
500 adapter
->unm_nic_hw_write_wx(adapter
,
501 UNM_NIU_AP_STATION_ADDR_0(phy
), &temp
, 4);
503 adapter
->unm_nic_hw_write_wx(adapter
,
504 UNM_NIU_XGE_STATION_ADDR_0_1
, &temp
, 4);
506 (void) memcpy(&temp
, ((__uint8_t
*)addr
) + 2,
507 sizeof (unm_crbword_t
));
508 adapter
->unm_nic_hw_write_wx(adapter
,
509 UNM_NIU_XGE_STATION_ADDR_0_HI
, &temp
, 4);
514 (void) memcpy(&temp
, addr
, 2);
516 port_mode
= adapter
->unm_nic_pci_read_normalize(adapter
,
518 if (port_mode
== UNM_PORT_MODE_802_3_AP
) {
519 adapter
->unm_nic_hw_write_wx(adapter
,
520 UNM_NIU_AP_STATION_ADDR_1(phy
), &temp
, 4);
522 (void) memcpy(&temp
, ((__uint8_t
*)addr
) + 2,
523 sizeof (unm_crbword_t
));
524 adapter
->unm_nic_hw_write_wx(adapter
,
525 UNM_NIU_AP_STATION_ADDR_0(phy
), &temp
, 4);
527 adapter
->unm_nic_hw_write_wx(adapter
,
528 UNM_NIU_XGE_STATION_ADDR_0_1
, &temp
, 4);
530 (void) memcpy(&temp
, ((__uint8_t
*)addr
) + 2,
531 sizeof (unm_crbword_t
));
532 adapter
->unm_nic_hw_write_wx(adapter
,
533 UNM_NIU_XGE_STATION_ADDR_0_HI
, &temp
, 4);
538 cmn_err(CE_WARN
, "Unknown port %d\n", phy
);
539 return (DDI_FAILURE
);
546 unm_niu_xg_set_promiscuous_mode(struct unm_adapter_s
*adapter
,
547 unm_niu_prom_mode_t mode
)
550 unm_niu_xg_mac_config_0_t mac_cfg
;
551 native_t port
= adapter
->physical_port
;
556 if ((port
< 0) || (port
> UNM_NIU_MAX_XG_PORTS
))
559 port_mode
= adapter
->unm_nic_pci_read_normalize(adapter
,
562 if (port_mode
== UNM_PORT_MODE_802_3_AP
) {
564 adapter
->unm_nic_hw_write_wx(adapter
,
565 UNM_NIU_GB_DROP_WRONGADDR
, (void*)®
, 4);
568 adapter
->unm_nic_hw_read_wx(adapter
, UNM_NIU_XGE_CONFIG_0
+
569 (0x10000 * port
), &mac_cfg
, 4);
570 mac_cfg
.rx_enable
= 0;
571 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_XGE_CONFIG_0
+
572 (0x10000 * port
), &mac_cfg
, 4);
574 /* wait until mac is drained by sre */
575 if ((adapter
->ahw
.boardcfg
.board_type
!=
576 UNM_BRDTYPE_P2_SB31_10G_IMEZ
) &&
577 (adapter
->ahw
.boardcfg
.board_type
!=
578 UNM_BRDTYPE_P2_SB31_10G_HMEZ
)) {
579 /* single port case bit 9 */
581 adapter
->unm_crb_writelit_adapter(adapter
,
582 UNM_NIU_FRAME_COUNT_SELECT
, reg
);
584 /* Port 0 rx fifo bit 5 */
585 reg
= (0x20 << port
);
586 adapter
->unm_crb_writelit_adapter(adapter
,
587 UNM_NIU_FRAME_COUNT_SELECT
, reg
);
590 adapter
->unm_nic_hw_read_wx(adapter
,
591 UNM_NIU_FRAME_COUNT
, ®
, 4);
600 /* now set promiscuous mode */
602 adapter
->unm_nic_hw_read_wx(adapter
,
603 UNM_NIU_XGE_CONFIG_1
+ (0x10000 * port
), ®
, 4);
604 if (mode
== UNM_NIU_PROMISCOUS_MODE
) {
605 reg
= (reg
| 0x2000UL
);
606 } else { /* FIXME use the correct mode value here */
607 reg
= (reg
& ~0x2000UL
);
609 adapter
->unm_crb_writelit_adapter(adapter
,
610 UNM_NIU_XGE_CONFIG_1
+ (0x10000 * port
), reg
);
613 /* turn the mac back on */
614 mac_cfg
.rx_enable
= 1;
615 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_XGE_CONFIG_0
+
616 (0x10000 * port
), &mac_cfg
, 4);
623 unm_niu_xg_set_tx_flow_ctl(struct unm_adapter_s
*adapter
, int enable
)
625 int port
= adapter
->physical_port
;
626 unm_niu_xg_pause_ctl_t reg
;
628 if ((port
< 0) || (port
> UNM_NIU_MAX_XG_PORTS
))
631 adapter
->unm_nic_hw_read_wx(adapter
, UNM_NIU_XG_PAUSE_CTL
, ®
, 4);
633 reg
.xg0_mask
= !enable
;
635 reg
.xg1_mask
= !enable
;
637 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_XG_PAUSE_CTL
, ®
, 4);
643 unm_niu_gbe_set_tx_flow_ctl(struct unm_adapter_s
*adapter
, int enable
)
645 int port
= adapter
->physical_port
;
646 unm_niu_gb_pause_ctl_t reg
;
648 if ((port
< 0) || (port
> UNM_NIU_MAX_GBE_PORTS
))
651 adapter
->unm_nic_hw_read_wx(adapter
, UNM_NIU_GB_PAUSE_CTL
, ®
, 4);
654 reg
.gb0_mask
= !enable
;
657 reg
.gb1_mask
= !enable
;
660 reg
.gb2_mask
= !enable
;
664 reg
.gb3_mask
= !enable
;
667 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_PAUSE_CTL
, ®
, 4);
673 unm_niu_gbe_set_rx_flow_ctl(struct unm_adapter_s
*adapter
, int enable
)
675 int port
= adapter
->physical_port
;
676 unm_niu_gb_mac_config_0_t reg
;
678 if ((port
< 0) || (port
> UNM_NIU_MAX_GBE_PORTS
))
681 adapter
->unm_nic_hw_read_wx(adapter
, UNM_NIU_GB_MAC_CONFIG_0(port
),
683 reg
.rx_flowctl
= enable
;
684 adapter
->unm_nic_hw_write_wx(adapter
, UNM_NIU_GB_MAC_CONFIG_0(port
),