xref: /illumos-gate/usr/src/uts/common/io/ntxn/niu.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 NetXen, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/conf.h>
29 #include <sys/debug.h>
30 #include <sys/stropts.h>
31 #include <sys/stream.h>
32 #include <sys/strlog.h>
33 #include <sys/kmem.h>
34 #include <sys/stat.h>
35 #include <sys/kstat.h>
36 #include <sys/vtrace.h>
37 #include <sys/dlpi.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>
43 #include <sys/ddi.h>
44 #include <sys/sunddi.h>
45 #include <sys/sysmacros.h>
46 
47 #include <sys/pci.h>
48 
49 #include "unm_inc.h"
50 #include "unm_nic.h"
51 
52 static long phy_lock_timeout = 100000000;
53 
54 static int phy_lock(struct unm_adapter_s *adapter)
55 {
56 	u32	done = 0;
57 	int	timeout = 0;
58 
59 	while (!done) {
60 		/* acquire semaphore3 from PCI HW block */
61 		adapter->unm_nic_pci_read_immediate(adapter,
62 		    UNM_PCIE_REG(PCIE_SEM3_LOCK), &done);
63 		if (done == 1)
64 			break;
65 		if (timeout >= phy_lock_timeout)
66 			return (-1);
67 		timeout++;
68 	}
69 
70 	adapter->unm_crb_writelit_adapter(adapter, UNM_PHY_LOCK_ID,
71 	    PHY_LOCK_DRIVER);
72 	return (0);
73 }
74 
75 static void
76 phy_unlock(struct unm_adapter_s *adapter)
77 {
78 	u32	val;
79 
80 	/* release semaphore3 */
81 	adapter->unm_nic_pci_read_immediate(adapter,
82 	    UNM_PCIE_REG(PCIE_SEM3_UNLOCK), &val);
83 }
84 
85 /*
86  * unm_niu_gbe_phy_read - read a register from the GbE PHY via
87  * mii management interface.
88  *
89  * Note: The MII management interface goes through port 0.
90  *	   Individual phys are addressed as follows:
91  *	   [15:8]  phy id
92  *	   [7:0]   register number
93  *
94  * Returns:  0 success
95  *	  -1 error
96  *
97  */
98 long
99 unm_niu_gbe_phy_read(struct unm_adapter_s *adapter, long reg,
100     unm_crbword_t *readval)
101 {
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;
106 
107 	long timeout = 0;
108 	long result = 0;
109 	long restore = 0;
110 	unm_niu_gb_mac_config_0_t mac_cfg0;
111 
112 	if (phy_lock(adapter) != 0)
113 		return (-1);
114 
115 	/*
116 	 * MII mgmt all goes through port 0 MAC interface, so it cannot be
117 	 * in reset
118 	 */
119 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(0),
120 	    &mac_cfg0, 4);
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);
130 		restore = 1;
131 	}
132 
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),
137 	    &address, 4);
138 
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),
141 	    &command, 4);
142 
143 	/* send read command */
144 	command.read_cycle = 1;
145 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MII_MGMT_COMMAND(0),
146 	    &command, 4);
147 
148 	*(unm_crbword_t *)&status = 0;
149 	do {
150 		adapter->unm_nic_hw_read_wx(adapter,
151 		    UNM_NIU_GB_MII_MGMT_INDICATE(0), &status, 4);
152 		timeout++;
153 	} while ((status.busy || status.notvalid) &&
154 	    (timeout++ < UNM_NIU_PHY_WAITMAX));
155 
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);
159 		result = 0;
160 	} else
161 		result = -1;
162 
163 	if (restore)
164 		adapter->unm_nic_hw_write_wx(adapter,
165 		    UNM_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0, 4);
166 
167 	phy_unlock(adapter);
168 
169 	return (result);
170 }
171 
172 /*
173  * Return the current station MAC address.
174  * Note that the passed-in value must already be in network byte order.
175  */
176 int
177 unm_niu_macaddr_get(struct unm_adapter_s *adapter, unsigned char *addr)
178 {
179 	__uint64_t result;
180 	int phy = adapter->physical_port;
181 
182 	if (addr == NULL)
183 		return (-1);
184 	if ((phy < 0) || (phy > 3))
185 		return (-1);
186 
187 	UNM_WRITE_LOCK_IRQS(&adapter->adapter_lock, flags);
188 	if (adapter->curr_window != 0) {
189 		adapter->unm_nic_pci_change_crbwindow(adapter, 0);
190 	}
191 
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;
196 
197 	(void) memcpy(addr, &result, sizeof (unm_ethernet_macaddr_t));
198 
199 	adapter->unm_nic_pci_change_crbwindow(adapter, 1);
200 
201 	UNM_WRITE_UNLOCK_IRQR(&adapter->adapter_lock, flags);
202 
203 	return (0);
204 }
205 
206 /*
207  * Set the station MAC address.
208  * Note that the passed-in value must already be in network byte order.
209  */
210 int
211 unm_niu_macaddr_set(struct unm_adapter_s *adapter, unm_ethernet_macaddr_t addr)
212 {
213 	unm_crbword_t temp = 0;
214 	int phy = adapter->physical_port;
215 
216 	if ((phy < 0) || (phy > 3))
217 		return (-1);
218 
219 	(void) memcpy(&temp, addr, 2);
220 	temp <<= 16;
221 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_STATION_ADDR_1(phy),
222 	    &temp, 4);
223 	temp = 0;
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),
226 	    &temp, 4);
227 	return (0);
228 }
229 
230 /* Enable a GbE interface */
231 /* ARGSUSED */
232 native_t unm_niu_enable_gbe_port(struct unm_adapter_s *adapter,
233 		unm_niu_gbe_ifmode_t mode_dont_care)
234 {
235 	unm_niu_gb_mac_config_0_t mac_cfg0;
236 	unm_niu_gb_mac_config_1_t mac_cfg1;
237 	unm_niu_gb_mii_mgmt_config_t mii_cfg;
238 	native_t port = adapter->physical_port;
239 	int zero = 0;
240 	int one = 1;
241 	u32 port_mode = 0;
242 
243 	mode_dont_care = 0;
244 
245 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS)) {
246 		return (-1);
247 	}
248 
249 	if (adapter->link_speed != MBPS_10 &&
250 	    adapter->link_speed != MBPS_100 &&
251 	    adapter->link_speed != MBPS_1000) {
252 
253 		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
254 /*
255  * Do NOT fail this call because the cable is unplugged.
256  * Updated when the link comes up...
257  */
258 		adapter->link_speed = MBPS_1000;
259 		} else {
260 			return (-1);
261 		}
262 	}
263 
264 	port_mode = adapter->unm_nic_pci_read_normalize(adapter,
265 	    UNM_PORT_MODE_ADDR);
266 	if (port_mode == UNM_PORT_MODE_802_3_AP) {
267 		*(unm_crbword_t *)&mac_cfg0 = 0x0000003f;
268 		*(unm_crbword_t *)&mac_cfg1 = 0x0000f2df;
269 		unm_crb_write_adapter(UNM_NIU_AP_MAC_CONFIG_0(port), &mac_cfg0,
270 		    adapter);
271 		unm_crb_write_adapter(UNM_NIU_AP_MAC_CONFIG_1(port), &mac_cfg1,
272 		    adapter);
273 	} else {
274 		*(unm_crbword_t *)&mac_cfg0 = 0;
275 		mac_cfg0.soft_reset = 1;
276 		unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0,
277 		    adapter);
278 
279 		*(unm_crbword_t *)&mac_cfg0 = 0;
280 		mac_cfg0.tx_enable = 1;
281 		mac_cfg0.rx_enable = 1;
282 		mac_cfg0.rx_flowctl = 0;
283 		mac_cfg0.tx_reset_pb = 1;
284 		mac_cfg0.rx_reset_pb = 1;
285 		mac_cfg0.tx_reset_mac = 1;
286 		mac_cfg0.rx_reset_mac = 1;
287 
288 		unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0,
289 		    adapter);
290 
291 		*(unm_crbword_t *)&mac_cfg1 = 0;
292 		mac_cfg1.preamblelen = 0xf;
293 		mac_cfg1.duplex = 1;
294 		mac_cfg1.crc_enable = 1;
295 		mac_cfg1.padshort = 1;
296 		mac_cfg1.checklength = 1;
297 		mac_cfg1.hugeframes = 1;
298 
299 		switch (adapter->link_speed) {
300 			case MBPS_10:
301 			case MBPS_100: /* Fall Through */
302 				mac_cfg1.intfmode = 1;
303 				unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_1
304 				    (port), &mac_cfg1, adapter);
305 
306 				/* set mii mode */
307 				unm_crb_write_adapter(
308 				    UNM_NIU_GB0_GMII_MODE+(port<<3),
309 				    &zero, adapter);
310 				unm_crb_write_adapter(
311 				    UNM_NIU_GB0_MII_MODE+(port<< 3),
312 				    &one, adapter);
313 				break;
314 
315 			case MBPS_1000:
316 				mac_cfg1.intfmode = 2;
317 				unm_crb_write_adapter(
318 				    UNM_NIU_GB_MAC_CONFIG_1(port),
319 				    &mac_cfg1, adapter);
320 
321 				/* set gmii mode */
322 				unm_crb_write_adapter(
323 				    UNM_NIU_GB0_MII_MODE+(port << 3),
324 				    &zero, adapter);
325 				unm_crb_write_adapter(
326 				    UNM_NIU_GB0_GMII_MODE+(port << 3),
327 				    &one, adapter);
328 				break;
329 
330 			default:
331 				/* Will not happen */
332 				break;
333 		}
334 
335 		*(unm_crbword_t *)&mii_cfg = 0;
336 		mii_cfg.clockselect = 7;
337 		unm_crb_write_adapter(UNM_NIU_GB_MII_MGMT_CONFIG(port),
338 		    &mii_cfg, adapter);
339 
340 		*(unm_crbword_t *)&mac_cfg0 = 0;
341 		mac_cfg0.tx_enable = 1;
342 		mac_cfg0.rx_enable = 1;
343 		mac_cfg0.tx_flowctl = 0;
344 		mac_cfg0.rx_flowctl = 0;
345 		unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port),
346 		    &mac_cfg0, adapter);
347 	}
348 
349 	return (0);
350 }
351 
352 /* Disable a GbE interface */
353 native_t
354 unm_niu_disable_gbe_port(struct unm_adapter_s *adapter)
355 {
356 	native_t			port = adapter->physical_port;
357 	unm_niu_gb_mac_config_0_t	mac_cfg0;
358 
359 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
360 		return (-1);
361 
362 	*(unm_crbword_t *)&mac_cfg0 = 0;
363 	mac_cfg0.soft_reset = 1;
364 
365 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
366 		adapter->unm_nic_hw_write_wx(adapter,
367 		    UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0, 0);
368 	else
369 		adapter->unm_nic_hw_write_wx(adapter,
370 		    UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0, 4);
371 	return (0);
372 }
373 
374 /* Disable an XG interface */
375 native_t
376 unm_niu_disable_xg_port(struct unm_adapter_s *adapter)
377 {
378 	native_t			port = adapter->physical_port;
379 	unm_niu_xg_mac_config_0_t	mac_cfg;
380 
381 	*(unm_crbword_t *)&mac_cfg = 0;
382 	mac_cfg.soft_reset = 1;
383 
384 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
385 		if (port != 0)
386 			return (-1);
387 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0,
388 		    &mac_cfg, 4);
389 	} else {
390 		if ((port < 0) || (port >= UNM_NIU_MAX_XG_PORTS))
391 			return (-1);
392 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
393 		    (port * 0x10000), &mac_cfg, 4);
394 	}
395 	return (0);
396 }
397 
398 
399 /* Set promiscuous mode for a GbE interface */
400 native_t
401 unm_niu_set_promiscuous_mode(struct unm_adapter_s *adapter,
402     unm_niu_prom_mode_t mode)
403 {
404 	native_t port = adapter->physical_port;
405 	unm_niu_gb_drop_crc_t reg;
406 	unm_niu_gb_mac_config_0_t mac_cfg;
407 	unm_crbword_t data;
408 	int cnt = 0, ret = 0;
409 	ulong_t val;
410 
411 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
412 		return (-1);
413 
414 	/* Turn off mac */
415 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
416 	    &mac_cfg, 4);
417 	mac_cfg.rx_enable = 0;
418 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
419 	    &mac_cfg, 4);
420 
421 	/* wait until mac is drained by sre */
422 	/* Port 0 rx fifo bit 5 */
423 	val = (0x20 << port);
424 	adapter->unm_crb_writelit_adapter(adapter, UNM_NIU_FRAME_COUNT_SELECT,
425 	    val);
426 
427 	do {
428 		adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_FRAME_COUNT,
429 		    &val, 4);
430 		cnt++;
431 		if (cnt > 2000) {
432 			ret = -1;
433 			break;
434 		}
435 		drv_usecwait(10);
436 	} while (val);
437 
438 	/* now set promiscuous mode */
439 	if (ret != -1) {
440 		if (mode == UNM_NIU_PROMISCOUS_MODE)
441 			data = 0;
442 		else
443 			data = 1;
444 
445 		adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_DROP_WRONGADDR,
446 		    &reg, 4);
447 		switch (port) {
448 		case 0:
449 			reg.drop_gb0 = data;
450 			break;
451 		case 1:
452 			reg.drop_gb1 = data;
453 			break;
454 		case 2:
455 			reg.drop_gb2 = data;
456 			break;
457 		case 3:
458 			reg.drop_gb3 = data;
459 			break;
460 		default:
461 			ret  = -1;
462 			break;
463 		}
464 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_DROP_WRONGADDR,
465 		    &reg, 4);
466 	}
467 
468 	/* turn the mac on back */
469 	mac_cfg.rx_enable = 1;
470 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
471 	    &mac_cfg, 4);
472 
473 	return (ret);
474 }
475 
476 /*
477  * Set the MAC address for an XG port
478  * Note that the passed-in value must already be in network byte order.
479  */
480 int
481 unm_niu_xg_macaddr_set(struct unm_adapter_s *adapter,
482 		unm_ethernet_macaddr_t addr)
483 {
484 	int		phy = adapter->physical_port;
485 	unm_crbword_t	temp = 0;
486 	u32		port_mode = 0;
487 
488 	if ((phy < 0) || (phy > 3))
489 		return (-1);
490 
491 	switch (phy) {
492 	case 0:
493 		(void) memcpy(&temp, addr, 2);
494 		temp <<= 16;
495 		port_mode = adapter->unm_nic_pci_read_normalize(adapter,
496 		    UNM_PORT_MODE_ADDR);
497 		if (port_mode == UNM_PORT_MODE_802_3_AP) {
498 			adapter->unm_nic_hw_write_wx(adapter,
499 			    UNM_NIU_AP_STATION_ADDR_1(phy), &temp, 4);
500 			temp = 0;
501 			(void) memcpy(&temp, ((__uint8_t *)addr) + 2,
502 			    sizeof (unm_crbword_t));
503 			adapter->unm_nic_hw_write_wx(adapter,
504 			    UNM_NIU_AP_STATION_ADDR_0(phy), &temp, 4);
505 		} else {
506 			adapter->unm_nic_hw_write_wx(adapter,
507 			    UNM_NIU_XGE_STATION_ADDR_0_1, &temp, 4);
508 			temp = 0;
509 			(void) memcpy(&temp, ((__uint8_t *)addr) + 2,
510 			    sizeof (unm_crbword_t));
511 			adapter->unm_nic_hw_write_wx(adapter,
512 			    UNM_NIU_XGE_STATION_ADDR_0_HI, &temp, 4);
513 		}
514 		break;
515 
516 	case 1:
517 		(void) memcpy(&temp, addr, 2);
518 		temp <<= 16;
519 		port_mode = adapter->unm_nic_pci_read_normalize(adapter,
520 		    UNM_PORT_MODE_ADDR);
521 		if (port_mode == UNM_PORT_MODE_802_3_AP) {
522 			adapter->unm_nic_hw_write_wx(adapter,
523 			    UNM_NIU_AP_STATION_ADDR_1(phy), &temp, 4);
524 			temp = 0;
525 			(void) memcpy(&temp, ((__uint8_t *)addr) + 2,
526 			    sizeof (unm_crbword_t));
527 			adapter->unm_nic_hw_write_wx(adapter,
528 			    UNM_NIU_AP_STATION_ADDR_0(phy), &temp, 4);
529 		} else {
530 			adapter->unm_nic_hw_write_wx(adapter,
531 			    UNM_NIU_XGE_STATION_ADDR_0_1, &temp, 4);
532 			temp = 0;
533 			(void) memcpy(&temp, ((__uint8_t *)addr) + 2,
534 			    sizeof (unm_crbword_t));
535 			adapter->unm_nic_hw_write_wx(adapter,
536 			    UNM_NIU_XGE_STATION_ADDR_0_HI, &temp, 4);
537 		}
538 		break;
539 
540 	default:
541 		cmn_err(CE_WARN, "Unknown port %d\n", phy);
542 		return (DDI_FAILURE);
543 	}
544 
545 	return (0);
546 }
547 
548 native_t
549 unm_niu_xg_set_promiscuous_mode(struct unm_adapter_s *adapter,
550     unm_niu_prom_mode_t mode)
551 {
552 	long  reg;
553 	unm_niu_xg_mac_config_0_t mac_cfg;
554 	native_t port = adapter->physical_port;
555 	int cnt = 0;
556 	int result = 0;
557 	u32 port_mode = 0;
558 
559 	if ((port < 0) || (port > UNM_NIU_MAX_XG_PORTS))
560 		return (-1);
561 
562 	port_mode = adapter->unm_nic_pci_read_normalize(adapter,
563 	    UNM_PORT_MODE_ADDR);
564 
565 	if (port_mode == UNM_PORT_MODE_802_3_AP) {
566 		reg = 0;
567 		adapter->unm_nic_hw_write_wx(adapter,
568 		    UNM_NIU_GB_DROP_WRONGADDR, (void*)&reg, 4);
569 	} else {
570 		/* Turn off mac */
571 		adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
572 		    (0x10000 * port), &mac_cfg, 4);
573 		mac_cfg.rx_enable = 0;
574 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
575 		    (0x10000 * port), &mac_cfg, 4);
576 
577 		/* wait until mac is drained by sre */
578 		if ((adapter->ahw.boardcfg.board_type !=
579 		    UNM_BRDTYPE_P2_SB31_10G_IMEZ) &&
580 		    (adapter->ahw.boardcfg.board_type !=
581 		    UNM_BRDTYPE_P2_SB31_10G_HMEZ)) {
582 			/* single port case bit 9 */
583 			reg = 0x0200;
584 			adapter->unm_crb_writelit_adapter(adapter,
585 			    UNM_NIU_FRAME_COUNT_SELECT, reg);
586 		} else {
587 			/* Port 0 rx fifo bit 5 */
588 			reg = (0x20 << port);
589 			adapter->unm_crb_writelit_adapter(adapter,
590 			    UNM_NIU_FRAME_COUNT_SELECT, reg);
591 		}
592 		do {
593 			adapter->unm_nic_hw_read_wx(adapter,
594 			    UNM_NIU_FRAME_COUNT, &reg, 4);
595 			cnt++;
596 			if (cnt > 2000) {
597 				result = -1;
598 				break;
599 			}
600 			drv_usecwait(10);
601 		} while (reg);
602 
603 		/* now set promiscuous mode */
604 		if (result != -1) {
605 			adapter->unm_nic_hw_read_wx(adapter,
606 			    UNM_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4);
607 			if (mode == UNM_NIU_PROMISCOUS_MODE) {
608 				reg = (reg | 0x2000UL);
609 			} else { /* FIXME  use the correct mode value here */
610 				reg = (reg & ~0x2000UL);
611 			}
612 			adapter->unm_crb_writelit_adapter(adapter,
613 			    UNM_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
614 		}
615 
616 		/* turn the mac back on */
617 		mac_cfg.rx_enable = 1;
618 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
619 		    (0x10000 * port), &mac_cfg, 4);
620 	}
621 
622 	return (result);
623 }
624 
625 int
626 unm_niu_xg_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable)
627 {
628 	int port = adapter->physical_port;
629 	unm_niu_xg_pause_ctl_t reg;
630 
631 	if ((port < 0) || (port > UNM_NIU_MAX_XG_PORTS))
632 		return (-1);
633 
634 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_XG_PAUSE_CTL, &reg, 4);
635 	if (port == 0)
636 		reg.xg0_mask = !enable;
637 	else
638 		reg.xg1_mask = !enable;
639 
640 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XG_PAUSE_CTL, &reg, 4);
641 
642 	return (0);
643 }
644 
645 int
646 unm_niu_gbe_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable)
647 {
648 	int port = adapter->physical_port;
649 	unm_niu_gb_pause_ctl_t reg;
650 
651 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
652 		return (-1);
653 
654 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_PAUSE_CTL, &reg, 4);
655 	switch (port) {
656 	case (0):
657 		reg.gb0_mask = !enable;
658 		break;
659 	case (1):
660 		reg.gb1_mask = !enable;
661 		break;
662 	case (2):
663 		reg.gb2_mask = !enable;
664 		break;
665 	case (3):
666 	default:
667 		reg.gb3_mask = !enable;
668 		break;
669 	}
670 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_PAUSE_CTL, &reg, 4);
671 
672 	return (0);
673 }
674 
675 int
676 unm_niu_gbe_set_rx_flow_ctl(struct unm_adapter_s *adapter, int enable)
677 {
678 	int port = adapter->physical_port;
679 	unm_niu_gb_mac_config_0_t reg;
680 
681 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
682 		return (-1);
683 
684 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
685 	    &reg, 4);
686 	reg.rx_flowctl = enable;
687 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
688 	    &reg, 4);
689 
690 	return (0);
691 }
692