xref: /illumos-gate/usr/src/uts/common/io/ntxn/niu.c (revision 4c28a617e3922d92a58e813a5b955eb526b9c386)
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 native_t
232 unm_niu_enable_gbe_port(struct unm_adapter_s *adapter)
233 {
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;
238 	int zero = 0;
239 	int one = 1;
240 	u32 port_mode = 0;
241 
242 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS)) {
243 		return (-1);
244 	}
245 
246 	if (adapter->link_speed != MBPS_10 &&
247 	    adapter->link_speed != MBPS_100 &&
248 	    adapter->link_speed != MBPS_1000) {
249 
250 		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
251 			/*
252 			 * Do NOT fail this call because the cable is unplugged.
253 			 * Updated when the link comes up...
254 			 */
255 			adapter->link_speed = MBPS_1000;
256 		} else {
257 			return (-1);
258 		}
259 	}
260 
261 	port_mode = adapter->unm_nic_pci_read_normalize(adapter,
262 	    UNM_PORT_MODE_ADDR);
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,
267 		    adapter);
268 		unm_crb_write_adapter(UNM_NIU_AP_MAC_CONFIG_1(port), &mac_cfg1,
269 		    adapter);
270 	} else {
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,
274 		    adapter);
275 
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;
284 
285 		unm_crb_write_adapter(UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0,
286 		    adapter);
287 
288 		*(unm_crbword_t *)&mac_cfg1 = 0;
289 		mac_cfg1.preamblelen = 0xf;
290 		mac_cfg1.duplex = 1;
291 		mac_cfg1.crc_enable = 1;
292 		mac_cfg1.padshort = 1;
293 		mac_cfg1.checklength = 1;
294 		mac_cfg1.hugeframes = 1;
295 
296 		switch (adapter->link_speed) {
297 			case MBPS_10:
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);
302 
303 				/* set mii mode */
304 				unm_crb_write_adapter(
305 				    UNM_NIU_GB0_GMII_MODE+(port<<3),
306 				    &zero, adapter);
307 				unm_crb_write_adapter(
308 				    UNM_NIU_GB0_MII_MODE+(port<< 3),
309 				    &one, adapter);
310 				break;
311 
312 			case MBPS_1000:
313 				mac_cfg1.intfmode = 2;
314 				unm_crb_write_adapter(
315 				    UNM_NIU_GB_MAC_CONFIG_1(port),
316 				    &mac_cfg1, adapter);
317 
318 				/* set gmii mode */
319 				unm_crb_write_adapter(
320 				    UNM_NIU_GB0_MII_MODE+(port << 3),
321 				    &zero, adapter);
322 				unm_crb_write_adapter(
323 				    UNM_NIU_GB0_GMII_MODE+(port << 3),
324 				    &one, adapter);
325 				break;
326 
327 			default:
328 				/* Will not happen */
329 				break;
330 		}
331 
332 		*(unm_crbword_t *)&mii_cfg = 0;
333 		mii_cfg.clockselect = 7;
334 		unm_crb_write_adapter(UNM_NIU_GB_MII_MGMT_CONFIG(port),
335 		    &mii_cfg, adapter);
336 
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),
343 		    &mac_cfg0, adapter);
344 	}
345 
346 	return (0);
347 }
348 
349 /* Disable a GbE interface */
350 native_t
351 unm_niu_disable_gbe_port(struct unm_adapter_s *adapter)
352 {
353 	native_t			port = adapter->physical_port;
354 	unm_niu_gb_mac_config_0_t	mac_cfg0;
355 
356 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
357 		return (-1);
358 
359 	*(unm_crbword_t *)&mac_cfg0 = 0;
360 	mac_cfg0.soft_reset = 1;
361 
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);
365 	else
366 		adapter->unm_nic_hw_write_wx(adapter,
367 		    UNM_NIU_GB_MAC_CONFIG_0(port), &mac_cfg0, 4);
368 	return (0);
369 }
370 
371 /* Disable an XG interface */
372 native_t
373 unm_niu_disable_xg_port(struct unm_adapter_s *adapter)
374 {
375 	native_t			port = adapter->physical_port;
376 	unm_niu_xg_mac_config_0_t	mac_cfg;
377 
378 	*(unm_crbword_t *)&mac_cfg = 0;
379 	mac_cfg.soft_reset = 1;
380 
381 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
382 		if (port != 0)
383 			return (-1);
384 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0,
385 		    &mac_cfg, 4);
386 	} else {
387 		if ((port < 0) || (port >= UNM_NIU_MAX_XG_PORTS))
388 			return (-1);
389 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XGE_CONFIG_0 +
390 		    (port * 0x10000), &mac_cfg, 4);
391 	}
392 	return (0);
393 }
394 
395 
396 /* Set promiscuous mode for a GbE interface */
397 native_t
398 unm_niu_set_promiscuous_mode(struct unm_adapter_s *adapter,
399     unm_niu_prom_mode_t mode)
400 {
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;
404 	unm_crbword_t data;
405 	int cnt = 0, ret = 0;
406 	ulong_t val;
407 
408 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
409 		return (-1);
410 
411 	/* Turn off mac */
412 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
413 	    &mac_cfg, 4);
414 	mac_cfg.rx_enable = 0;
415 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
416 	    &mac_cfg, 4);
417 
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,
422 	    val);
423 
424 	do {
425 		adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_FRAME_COUNT,
426 		    &val, 4);
427 		cnt++;
428 		if (cnt > 2000) {
429 			ret = -1;
430 			break;
431 		}
432 		drv_usecwait(10);
433 	} while (val);
434 
435 	/* now set promiscuous mode */
436 	if (ret != -1) {
437 		if (mode == UNM_NIU_PROMISCOUS_MODE)
438 			data = 0;
439 		else
440 			data = 1;
441 
442 		adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_DROP_WRONGADDR,
443 		    &reg, 4);
444 		switch (port) {
445 		case 0:
446 			reg.drop_gb0 = data;
447 			break;
448 		case 1:
449 			reg.drop_gb1 = data;
450 			break;
451 		case 2:
452 			reg.drop_gb2 = data;
453 			break;
454 		case 3:
455 			reg.drop_gb3 = data;
456 			break;
457 		default:
458 			ret  = -1;
459 			break;
460 		}
461 		adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_DROP_WRONGADDR,
462 		    &reg, 4);
463 	}
464 
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),
468 	    &mac_cfg, 4);
469 
470 	return (ret);
471 }
472 
473 /*
474  * Set the MAC address for an XG port
475  * Note that the passed-in value must already be in network byte order.
476  */
477 int
478 unm_niu_xg_macaddr_set(struct unm_adapter_s *adapter,
479     unm_ethernet_macaddr_t addr)
480 {
481 	int		phy = adapter->physical_port;
482 	unm_crbword_t	temp = 0;
483 	u32		port_mode = 0;
484 
485 	if ((phy < 0) || (phy > 3))
486 		return (-1);
487 
488 	switch (phy) {
489 	case 0:
490 		(void) memcpy(&temp, addr, 2);
491 		temp <<= 16;
492 		port_mode = adapter->unm_nic_pci_read_normalize(adapter,
493 		    UNM_PORT_MODE_ADDR);
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);
497 			temp = 0;
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);
502 		} else {
503 			adapter->unm_nic_hw_write_wx(adapter,
504 			    UNM_NIU_XGE_STATION_ADDR_0_1, &temp, 4);
505 			temp = 0;
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);
510 		}
511 		break;
512 
513 	case 1:
514 		(void) memcpy(&temp, addr, 2);
515 		temp <<= 16;
516 		port_mode = adapter->unm_nic_pci_read_normalize(adapter,
517 		    UNM_PORT_MODE_ADDR);
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);
521 			temp = 0;
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);
526 		} else {
527 			adapter->unm_nic_hw_write_wx(adapter,
528 			    UNM_NIU_XGE_STATION_ADDR_0_1, &temp, 4);
529 			temp = 0;
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);
534 		}
535 		break;
536 
537 	default:
538 		cmn_err(CE_WARN, "Unknown port %d\n", phy);
539 		return (DDI_FAILURE);
540 	}
541 
542 	return (0);
543 }
544 
545 native_t
546 unm_niu_xg_set_promiscuous_mode(struct unm_adapter_s *adapter,
547     unm_niu_prom_mode_t mode)
548 {
549 	long  reg;
550 	unm_niu_xg_mac_config_0_t mac_cfg;
551 	native_t port = adapter->physical_port;
552 	int cnt = 0;
553 	int result = 0;
554 	u32 port_mode = 0;
555 
556 	if ((port < 0) || (port > UNM_NIU_MAX_XG_PORTS))
557 		return (-1);
558 
559 	port_mode = adapter->unm_nic_pci_read_normalize(adapter,
560 	    UNM_PORT_MODE_ADDR);
561 
562 	if (port_mode == UNM_PORT_MODE_802_3_AP) {
563 		reg = 0;
564 		adapter->unm_nic_hw_write_wx(adapter,
565 		    UNM_NIU_GB_DROP_WRONGADDR, (void*)&reg, 4);
566 	} else {
567 		/* Turn off mac */
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);
573 
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 */
580 			reg = 0x0200;
581 			adapter->unm_crb_writelit_adapter(adapter,
582 			    UNM_NIU_FRAME_COUNT_SELECT, reg);
583 		} else {
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);
588 		}
589 		do {
590 			adapter->unm_nic_hw_read_wx(adapter,
591 			    UNM_NIU_FRAME_COUNT, &reg, 4);
592 			cnt++;
593 			if (cnt > 2000) {
594 				result = -1;
595 				break;
596 			}
597 			drv_usecwait(10);
598 		} while (reg);
599 
600 		/* now set promiscuous mode */
601 		if (result != -1) {
602 			adapter->unm_nic_hw_read_wx(adapter,
603 			    UNM_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 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);
608 			}
609 			adapter->unm_crb_writelit_adapter(adapter,
610 			    UNM_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
611 		}
612 
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);
617 	}
618 
619 	return (result);
620 }
621 
622 int
623 unm_niu_xg_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable)
624 {
625 	int port = adapter->physical_port;
626 	unm_niu_xg_pause_ctl_t reg;
627 
628 	if ((port < 0) || (port > UNM_NIU_MAX_XG_PORTS))
629 		return (-1);
630 
631 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_XG_PAUSE_CTL, &reg, 4);
632 	if (port == 0)
633 		reg.xg0_mask = !enable;
634 	else
635 		reg.xg1_mask = !enable;
636 
637 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_XG_PAUSE_CTL, &reg, 4);
638 
639 	return (0);
640 }
641 
642 int
643 unm_niu_gbe_set_tx_flow_ctl(struct unm_adapter_s *adapter, int enable)
644 {
645 	int port = adapter->physical_port;
646 	unm_niu_gb_pause_ctl_t reg;
647 
648 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
649 		return (-1);
650 
651 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_PAUSE_CTL, &reg, 4);
652 	switch (port) {
653 	case (0):
654 		reg.gb0_mask = !enable;
655 		break;
656 	case (1):
657 		reg.gb1_mask = !enable;
658 		break;
659 	case (2):
660 		reg.gb2_mask = !enable;
661 		break;
662 	case (3):
663 	default:
664 		reg.gb3_mask = !enable;
665 		break;
666 	}
667 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_PAUSE_CTL, &reg, 4);
668 
669 	return (0);
670 }
671 
672 int
673 unm_niu_gbe_set_rx_flow_ctl(struct unm_adapter_s *adapter, int enable)
674 {
675 	int port = adapter->physical_port;
676 	unm_niu_gb_mac_config_0_t reg;
677 
678 	if ((port < 0) || (port > UNM_NIU_MAX_GBE_PORTS))
679 		return (-1);
680 
681 	adapter->unm_nic_hw_read_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
682 	    &reg, 4);
683 	reg.rx_flowctl = enable;
684 	adapter->unm_nic_hw_write_wx(adapter, UNM_NIU_GB_MAC_CONFIG_0(port),
685 	    &reg, 4);
686 
687 	return (0);
688 }
689