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