xref: /illumos-gate/usr/src/uts/common/io/chxge/com/ch_mac.c (revision 2d6eb4a5)
1*d39a76e7Sxw /*
2*d39a76e7Sxw  * CDDL HEADER START
3*d39a76e7Sxw  *
4*d39a76e7Sxw  * The contents of this file are subject to the terms of the
5*d39a76e7Sxw  * Common Development and Distribution License (the "License").
6*d39a76e7Sxw  * You may not use this file except in compliance with the License.
7*d39a76e7Sxw  *
8*d39a76e7Sxw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*d39a76e7Sxw  * or http://www.opensolaris.org/os/licensing.
10*d39a76e7Sxw  * See the License for the specific language governing permissions
11*d39a76e7Sxw  * and limitations under the License.
12*d39a76e7Sxw  *
13*d39a76e7Sxw  * When distributing Covered Code, include this CDDL HEADER in each
14*d39a76e7Sxw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*d39a76e7Sxw  * If applicable, add the following below this CDDL HEADER, with the
16*d39a76e7Sxw  * fields enclosed by brackets "[]" replaced with your own identifying
17*d39a76e7Sxw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*d39a76e7Sxw  *
19*d39a76e7Sxw  * CDDL HEADER END
20*d39a76e7Sxw  */
21*d39a76e7Sxw 
22*d39a76e7Sxw /*
23*d39a76e7Sxw  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
24*d39a76e7Sxw  */
25*d39a76e7Sxw 
26*d39a76e7Sxw #include "gmac.h"
27*d39a76e7Sxw #include "regs.h"
28*d39a76e7Sxw #include "fpga_defs.h"
29*d39a76e7Sxw 
30*d39a76e7Sxw #define	MAC_CSR_INTERFACE_GMII	0x0
31*d39a76e7Sxw #define	MAC_CSR_INTERFACE_TBI	0x1
32*d39a76e7Sxw #define	MAC_CSR_INTERFACE_MII	0x2
33*d39a76e7Sxw #define	MAC_CSR_INTERFACE_RMII	0x3
34*d39a76e7Sxw 
35*d39a76e7Sxw /* Chelsio's MAC statistics. */
36*d39a76e7Sxw struct mac_statistics {
37*d39a76e7Sxw 
38*d39a76e7Sxw 	/* Transmit */
39*d39a76e7Sxw 	u32 TxFramesTransmittedOK;
40*d39a76e7Sxw 	u32 TxReserved1;
41*d39a76e7Sxw 	u32 TxReserved2;
42*d39a76e7Sxw 	u32 TxOctetsTransmittedOK;
43*d39a76e7Sxw 	u32 TxFramesWithDeferredXmissions;
44*d39a76e7Sxw 	u32 TxLateCollisions;
45*d39a76e7Sxw 	u32 TxFramesAbortedDueToXSCollisions;
46*d39a76e7Sxw 	u32 TxFramesLostDueToIntMACXmitError;
47*d39a76e7Sxw 	u32 TxReserved3;
48*d39a76e7Sxw 	u32 TxMulticastFrameXmittedOK;
49*d39a76e7Sxw 	u32 TxBroadcastFramesXmittedOK;
50*d39a76e7Sxw 	u32 TxFramesWithExcessiveDeferral;
51*d39a76e7Sxw 	u32 TxPAUSEMACCtrlFramesTransmitted;
52*d39a76e7Sxw 
53*d39a76e7Sxw 	/* Receive */
54*d39a76e7Sxw 	u32 RxFramesReceivedOK;
55*d39a76e7Sxw 	u32 RxFrameCheckSequenceErrors;
56*d39a76e7Sxw 	u32 RxAlignmentErrors;
57*d39a76e7Sxw 	u32 RxOctetsReceivedOK;
58*d39a76e7Sxw 	u32 RxFramesLostDueToIntMACRcvError;
59*d39a76e7Sxw 	u32 RxMulticastFramesReceivedOK;
60*d39a76e7Sxw 	u32 RxBroadcastFramesReceivedOK;
61*d39a76e7Sxw 	u32 RxInRangeLengthErrors;
62*d39a76e7Sxw 	u32 RxTxOutOfRangeLengthField;
63*d39a76e7Sxw 	u32 RxFrameTooLongErrors;
64*d39a76e7Sxw 	u32 RxPAUSEMACCtrlFramesReceived;
65*d39a76e7Sxw };
66*d39a76e7Sxw 
67*d39a76e7Sxw static int static_aPorts[] = {
68*d39a76e7Sxw 	FPGA_GMAC_INTERRUPT_PORT0,
69*d39a76e7Sxw 	FPGA_GMAC_INTERRUPT_PORT1,
70*d39a76e7Sxw 	FPGA_GMAC_INTERRUPT_PORT2,
71*d39a76e7Sxw 	FPGA_GMAC_INTERRUPT_PORT3
72*d39a76e7Sxw };
73*d39a76e7Sxw 
74*d39a76e7Sxw struct _cmac_instance {
75*d39a76e7Sxw 	u32 index;
76*d39a76e7Sxw };
77*d39a76e7Sxw 
mac_intr_enable(struct cmac * mac)78*d39a76e7Sxw static int mac_intr_enable(struct cmac *mac)
79*d39a76e7Sxw {
80*d39a76e7Sxw 	u32 mac_intr;
81*d39a76e7Sxw 
82*d39a76e7Sxw 	if (t1_is_asic(mac->adapter)) {
83*d39a76e7Sxw 		/* ASIC */
84*d39a76e7Sxw 		/*EMPTY*/
85*d39a76e7Sxw 		/* We don't use the on chip MAC for ASIC products. */
86*d39a76e7Sxw 	} else {
87*d39a76e7Sxw 		/* FPGA */
88*d39a76e7Sxw 
89*d39a76e7Sxw 		/* Set parent gmac interrupt. */
90*d39a76e7Sxw 		mac_intr = t1_read_reg_4(mac->adapter, A_PL_ENABLE);
91*d39a76e7Sxw 		mac_intr |= FPGA_PCIX_INTERRUPT_GMAC;
92*d39a76e7Sxw 		t1_write_reg_4(mac->adapter, A_PL_ENABLE, mac_intr);
93*d39a76e7Sxw 
94*d39a76e7Sxw 		mac_intr = t1_read_reg_4(mac->adapter,
95*d39a76e7Sxw 			FPGA_GMAC_ADDR_INTERRUPT_ENABLE);
96*d39a76e7Sxw 		mac_intr |= static_aPorts[mac->instance->index];
97*d39a76e7Sxw 		t1_write_reg_4(mac->adapter,
98*d39a76e7Sxw 			FPGA_GMAC_ADDR_INTERRUPT_ENABLE, mac_intr);
99*d39a76e7Sxw 	}
100*d39a76e7Sxw 
101*d39a76e7Sxw 	return (0);
102*d39a76e7Sxw }
103*d39a76e7Sxw 
mac_intr_disable(struct cmac * mac)104*d39a76e7Sxw static int mac_intr_disable(struct cmac *mac)
105*d39a76e7Sxw {
106*d39a76e7Sxw 	u32 mac_intr;
107*d39a76e7Sxw 
108*d39a76e7Sxw 	if (t1_is_asic(mac->adapter)) {
109*d39a76e7Sxw 		/* ASIC */
110*d39a76e7Sxw 		/*EMPTY*/
111*d39a76e7Sxw 		/* We don't use the on chip MAC for ASIC products. */
112*d39a76e7Sxw 	} else {
113*d39a76e7Sxw 		/* FPGA */
114*d39a76e7Sxw 
115*d39a76e7Sxw 		/* Set parent gmac interrupt. */
116*d39a76e7Sxw 		mac_intr = t1_read_reg_4(mac->adapter, A_PL_ENABLE);
117*d39a76e7Sxw 		mac_intr &= ~FPGA_PCIX_INTERRUPT_GMAC;
118*d39a76e7Sxw 		t1_write_reg_4(mac->adapter, A_PL_ENABLE, mac_intr);
119*d39a76e7Sxw 
120*d39a76e7Sxw 		mac_intr = t1_read_reg_4(mac->adapter,
121*d39a76e7Sxw 			FPGA_GMAC_ADDR_INTERRUPT_ENABLE);
122*d39a76e7Sxw 		mac_intr &= ~(static_aPorts[mac->instance->index]);
123*d39a76e7Sxw 		t1_write_reg_4(mac->adapter,
124*d39a76e7Sxw 			FPGA_GMAC_ADDR_INTERRUPT_ENABLE, mac_intr);
125*d39a76e7Sxw 	}
126*d39a76e7Sxw 
127*d39a76e7Sxw 	return (0);
128*d39a76e7Sxw }
129*d39a76e7Sxw 
mac_intr_clear(struct cmac * mac)130*d39a76e7Sxw static int mac_intr_clear(struct cmac *mac)
131*d39a76e7Sxw {
132*d39a76e7Sxw 	u32 mac_intr;
133*d39a76e7Sxw 
134*d39a76e7Sxw 	if (t1_is_asic(mac->adapter)) {
135*d39a76e7Sxw 		/* ASIC */
136*d39a76e7Sxw 		/*EMPTY*/
137*d39a76e7Sxw 		/* We don't use the on chip MAC for ASIC products. */
138*d39a76e7Sxw 	} else {
139*d39a76e7Sxw 		/* FPGA */
140*d39a76e7Sxw 
141*d39a76e7Sxw 		/* Set parent gmac interrupt. */
142*d39a76e7Sxw 		t1_write_reg_4(mac->adapter, A_PL_CAUSE,
143*d39a76e7Sxw 			FPGA_PCIX_INTERRUPT_GMAC);
144*d39a76e7Sxw 
145*d39a76e7Sxw 		mac_intr = t1_read_reg_4(mac->adapter,
146*d39a76e7Sxw 			FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
147*d39a76e7Sxw 		mac_intr |= (static_aPorts[mac->instance->index]);
148*d39a76e7Sxw 		t1_write_reg_4(mac->adapter,
149*d39a76e7Sxw 			FPGA_GMAC_ADDR_INTERRUPT_CAUSE, mac_intr);
150*d39a76e7Sxw 	}
151*d39a76e7Sxw 
152*d39a76e7Sxw 	return (0);
153*d39a76e7Sxw }
154*d39a76e7Sxw 
mac_get_address(struct cmac * mac,u8 addr[6])155*d39a76e7Sxw static int mac_get_address(struct cmac *mac, u8 addr[6])
156*d39a76e7Sxw {
157*d39a76e7Sxw 	u32 data32_lo, data32_hi;
158*d39a76e7Sxw 
159*d39a76e7Sxw 	data32_lo = t1_read_reg_4(mac->adapter,
160*d39a76e7Sxw 			MAC_REG_IDLO(mac->instance->index));
161*d39a76e7Sxw 	data32_hi = t1_read_reg_4(mac->adapter,
162*d39a76e7Sxw 			MAC_REG_IDHI(mac->instance->index));
163*d39a76e7Sxw 
164*d39a76e7Sxw 	addr[0] = (u8) ((data32_hi >> 8) & 0xFF);
165*d39a76e7Sxw 	addr[1] = (u8) ((data32_hi) & 0xFF);
166*d39a76e7Sxw 	addr[2] = (u8) ((data32_lo >> 24) & 0xFF);
167*d39a76e7Sxw 	addr[3] = (u8) ((data32_lo >> 16) & 0xFF);
168*d39a76e7Sxw 	addr[4] = (u8) ((data32_lo >> 8) & 0xFF);
169*d39a76e7Sxw 	addr[5] = (u8) ((data32_lo) & 0xFF);
170*d39a76e7Sxw 	return (0);
171*d39a76e7Sxw }
172*d39a76e7Sxw 
mac_reset(struct cmac * mac)173*d39a76e7Sxw static int mac_reset(struct cmac *mac)
174*d39a76e7Sxw {
175*d39a76e7Sxw 	u32 data32;
176*d39a76e7Sxw 	int mac_in_reset, time_out = 100;
177*d39a76e7Sxw 	int idx = mac->instance->index;
178*d39a76e7Sxw 
179*d39a76e7Sxw 	data32 = t1_read_reg_4(mac->adapter, MAC_REG_CSR(idx));
180*d39a76e7Sxw 	t1_write_reg_4(mac->adapter, MAC_REG_CSR(idx),
181*d39a76e7Sxw 		data32 | F_MAC_RESET);
182*d39a76e7Sxw 
183*d39a76e7Sxw 	do {
184*d39a76e7Sxw 		data32 = t1_read_reg_4(mac->adapter,
185*d39a76e7Sxw 			MAC_REG_CSR(idx));
186*d39a76e7Sxw 		mac_in_reset = data32 & F_MAC_RESET;
187*d39a76e7Sxw 		if (mac_in_reset)
188*d39a76e7Sxw 			DELAY_US(1);
189*d39a76e7Sxw 	} while (mac_in_reset && --time_out);
190*d39a76e7Sxw 
191*d39a76e7Sxw 	if (mac_in_reset) {
192*d39a76e7Sxw 		CH_ERR("%s: MAC %d reset timed out\n",
193*d39a76e7Sxw 			adapter_name(mac->adapter), idx);
194*d39a76e7Sxw 		return (2);
195*d39a76e7Sxw 	}
196*d39a76e7Sxw 
197*d39a76e7Sxw 	return (0);
198*d39a76e7Sxw }
199*d39a76e7Sxw 
mac_set_rx_mode(struct cmac * mac,struct t1_rx_mode * rm)200*d39a76e7Sxw static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
201*d39a76e7Sxw {
202*d39a76e7Sxw 	u32 val;
203*d39a76e7Sxw 
204*d39a76e7Sxw 	val = t1_read_reg_4(mac->adapter,
205*d39a76e7Sxw 			    MAC_REG_CSR(mac->instance->index));
206*d39a76e7Sxw 	val &= ~(F_MAC_PROMISC | F_MAC_MC_ENABLE);
207*d39a76e7Sxw 	val |= V_MAC_PROMISC(t1_rx_mode_promisc(rm) != 0);
208*d39a76e7Sxw 	val |= V_MAC_MC_ENABLE(t1_rx_mode_allmulti(rm) != 0);
209*d39a76e7Sxw 	t1_write_reg_4(mac->adapter,
210*d39a76e7Sxw 		MAC_REG_CSR(mac->instance->index), val);
211*d39a76e7Sxw 
212*d39a76e7Sxw 	return (0);
213*d39a76e7Sxw }
214*d39a76e7Sxw 
mac_set_speed_duplex_fc(struct cmac * mac,int speed,int duplex,int fc)215*d39a76e7Sxw static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
216*d39a76e7Sxw 	int fc)
217*d39a76e7Sxw {
218*d39a76e7Sxw 	u32 data32;
219*d39a76e7Sxw 
220*d39a76e7Sxw 	data32 = t1_read_reg_4(mac->adapter,
221*d39a76e7Sxw 		MAC_REG_CSR(mac->instance->index));
222*d39a76e7Sxw 	data32 &= ~(F_MAC_HALF_DUPLEX | V_MAC_SPEED(M_MAC_SPEED) |
223*d39a76e7Sxw 		V_INTERFACE(M_INTERFACE) | F_MAC_TX_PAUSE_ENABLE |
224*d39a76e7Sxw 		F_MAC_RX_PAUSE_ENABLE);
225*d39a76e7Sxw 
226*d39a76e7Sxw 	switch (speed) {
227*d39a76e7Sxw 	case SPEED_10:
228*d39a76e7Sxw 	case SPEED_100:
229*d39a76e7Sxw 		data32 |= V_INTERFACE(MAC_CSR_INTERFACE_MII);
230*d39a76e7Sxw 		data32 |= V_MAC_SPEED(speed == SPEED_10 ? 0 : 1);
231*d39a76e7Sxw 		break;
232*d39a76e7Sxw 	case SPEED_1000:
233*d39a76e7Sxw 		data32 |= V_INTERFACE(MAC_CSR_INTERFACE_GMII);
234*d39a76e7Sxw 		data32 |= V_MAC_SPEED(2);
235*d39a76e7Sxw 		break;
236*d39a76e7Sxw 	}
237*d39a76e7Sxw 
238*d39a76e7Sxw 	if (duplex >= 0)
239*d39a76e7Sxw 		data32 |= V_MAC_HALF_DUPLEX(duplex == DUPLEX_HALF);
240*d39a76e7Sxw 
241*d39a76e7Sxw 	if (fc >= 0) {
242*d39a76e7Sxw 		data32 |= V_MAC_RX_PAUSE_ENABLE((fc & PAUSE_RX) != 0);
243*d39a76e7Sxw 		data32 |= V_MAC_TX_PAUSE_ENABLE((fc & PAUSE_TX) != 0);
244*d39a76e7Sxw 	}
245*d39a76e7Sxw 
246*d39a76e7Sxw 	t1_write_reg_4(mac->adapter,
247*d39a76e7Sxw 		MAC_REG_CSR(mac->instance->index), data32);
248*d39a76e7Sxw 	return (0);
249*d39a76e7Sxw }
250*d39a76e7Sxw 
mac_enable(struct cmac * mac,int which)251*d39a76e7Sxw static int mac_enable(struct cmac *mac, int which)
252*d39a76e7Sxw {
253*d39a76e7Sxw 	u32 val;
254*d39a76e7Sxw 
255*d39a76e7Sxw 	val = t1_read_reg_4(mac->adapter,
256*d39a76e7Sxw 			    MAC_REG_CSR(mac->instance->index));
257*d39a76e7Sxw 	if (which & MAC_DIRECTION_RX)
258*d39a76e7Sxw 		val |= F_MAC_RX_ENABLE;
259*d39a76e7Sxw 	if (which & MAC_DIRECTION_TX)
260*d39a76e7Sxw 		val |= F_MAC_TX_ENABLE;
261*d39a76e7Sxw 	t1_write_reg_4(mac->adapter,
262*d39a76e7Sxw 		MAC_REG_CSR(mac->instance->index), val);
263*d39a76e7Sxw 	return (0);
264*d39a76e7Sxw }
265*d39a76e7Sxw 
mac_disable(struct cmac * mac,int which)266*d39a76e7Sxw static int mac_disable(struct cmac *mac, int which)
267*d39a76e7Sxw {
268*d39a76e7Sxw 	u32 val;
269*d39a76e7Sxw 
270*d39a76e7Sxw 	val = t1_read_reg_4(mac->adapter,
271*d39a76e7Sxw 		MAC_REG_CSR(mac->instance->index));
272*d39a76e7Sxw 	if (which & MAC_DIRECTION_RX)
273*d39a76e7Sxw 		val &= ~F_MAC_RX_ENABLE;
274*d39a76e7Sxw 	if (which & MAC_DIRECTION_TX)
275*d39a76e7Sxw 		val &= ~F_MAC_TX_ENABLE;
276*d39a76e7Sxw 	t1_write_reg_4(mac->adapter,
277*d39a76e7Sxw 		MAC_REG_CSR(mac->instance->index), val);
278*d39a76e7Sxw 	return (0);
279*d39a76e7Sxw }
280*d39a76e7Sxw 
281*d39a76e7Sxw int
mac_set_ifs(struct cmac * mac,u32 mode)282*d39a76e7Sxw mac_set_ifs(struct cmac *mac, u32 mode)
283*d39a76e7Sxw {
284*d39a76e7Sxw 	t1_write_reg_4(mac->adapter,
285*d39a76e7Sxw 		MAC_REG_IFS(mac->instance->index), mode);
286*d39a76e7Sxw 
287*d39a76e7Sxw 	return (0);
288*d39a76e7Sxw }
289*d39a76e7Sxw 
290*d39a76e7Sxw int
mac_enable_isl(struct cmac * mac)291*d39a76e7Sxw mac_enable_isl(struct cmac *mac)
292*d39a76e7Sxw {
293*d39a76e7Sxw 	u32 data32 = t1_read_reg_4(mac->adapter,
294*d39a76e7Sxw 		MAC_REG_CSR(mac->instance->index));
295*d39a76e7Sxw 	data32 |= F_MAC_RX_ENABLE | F_MAC_TX_ENABLE;
296*d39a76e7Sxw 	t1_write_reg_4(mac->adapter,
297*d39a76e7Sxw 		MAC_REG_CSR(mac->instance->index), data32);
298*d39a76e7Sxw 
299*d39a76e7Sxw 	return (0);
300*d39a76e7Sxw }
301*d39a76e7Sxw 
mac_set_mtu(struct cmac * mac,int mtu)302*d39a76e7Sxw static int mac_set_mtu(struct cmac *mac, int mtu)
303*d39a76e7Sxw {
304*d39a76e7Sxw 	if (mtu > 9600)
305*d39a76e7Sxw 		return (-EINVAL);
306*d39a76e7Sxw 	t1_write_reg_4(mac->adapter,
307*d39a76e7Sxw 		MAC_REG_LARGEFRAMELENGTH(mac->instance->index),
308*d39a76e7Sxw 		mtu + 14 + 4);
309*d39a76e7Sxw 	return (0);
310*d39a76e7Sxw }
311*d39a76e7Sxw 
312*d39a76e7Sxw /* ARGSUSED */
mac_update_statistics(struct cmac * mac,int flag)313*d39a76e7Sxw static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
314*d39a76e7Sxw 	int flag)
315*d39a76e7Sxw {
316*d39a76e7Sxw 	struct mac_statistics st;
317*d39a76e7Sxw 	u32 *p = (u32 *) & st, i;
318*d39a76e7Sxw 
319*d39a76e7Sxw 	t1_write_reg_4(mac->adapter,
320*d39a76e7Sxw 		MAC_REG_RMCNT(mac->instance->index), 0);
321*d39a76e7Sxw 	for (i = 0; i < sizeof (st) / sizeof (u32); i++)
322*d39a76e7Sxw 		*p++ = t1_read_reg_4(mac->adapter,
323*d39a76e7Sxw 			MAC_REG_RMDATA(mac->instance->index));
324*d39a76e7Sxw 
325*d39a76e7Sxw 	/* XXX convert stats */
326*d39a76e7Sxw 	return (&mac->stats);
327*d39a76e7Sxw }
328*d39a76e7Sxw 
mac_destroy(struct cmac * mac)329*d39a76e7Sxw static void mac_destroy(struct cmac *mac)
330*d39a76e7Sxw {
331*d39a76e7Sxw 	t1_os_free((void *)mac, sizeof (*mac) + sizeof (cmac_instance));
332*d39a76e7Sxw }
333*d39a76e7Sxw 
334*d39a76e7Sxw #ifdef C99_NOT_SUPPORTED
335*d39a76e7Sxw static struct cmac_ops chelsio_mac_ops = {
336*d39a76e7Sxw 	mac_destroy,
337*d39a76e7Sxw 	mac_reset,
338*d39a76e7Sxw 	mac_intr_enable,
339*d39a76e7Sxw 	mac_intr_disable,
340*d39a76e7Sxw 	mac_intr_clear,
341*d39a76e7Sxw 	NULL,
342*d39a76e7Sxw 	mac_enable,
343*d39a76e7Sxw 	mac_disable,
344*d39a76e7Sxw 	NULL,
345*d39a76e7Sxw 	NULL,
346*d39a76e7Sxw 	mac_set_mtu,
347*d39a76e7Sxw 	mac_set_rx_mode,
348*d39a76e7Sxw 	mac_set_speed_duplex_fc,
349*d39a76e7Sxw 	NULL,
350*d39a76e7Sxw 	mac_update_statistics,
351*d39a76e7Sxw 	mac_get_address,
352*d39a76e7Sxw 	NULL
353*d39a76e7Sxw };
354*d39a76e7Sxw #else
355*d39a76e7Sxw static struct cmac_ops chelsio_mac_ops = {
356*d39a76e7Sxw 	.destroy		= mac_destroy,
357*d39a76e7Sxw 	.reset			= mac_reset,
358*d39a76e7Sxw 	.interrupt_enable	= mac_intr_enable,
359*d39a76e7Sxw 	.interrupt_disable	= mac_intr_disable,
360*d39a76e7Sxw 	.interrupt_clear	= mac_intr_clear,
361*d39a76e7Sxw 	.enable			= mac_enable,
362*d39a76e7Sxw 	.disable		= mac_disable,
363*d39a76e7Sxw 	.set_mtu		= mac_set_mtu,
364*d39a76e7Sxw 	.set_rx_mode		= mac_set_rx_mode,
365*d39a76e7Sxw 	.set_speed_duplex_fc	= mac_set_speed_duplex_fc,
366*d39a76e7Sxw 	.macaddress_get		= mac_get_address,
367*d39a76e7Sxw 	.statistics_update	= mac_update_statistics,
368*d39a76e7Sxw };
369*d39a76e7Sxw #endif
370*d39a76e7Sxw 
mac_create(adapter_t * adapter,int index)371*d39a76e7Sxw static struct cmac *mac_create(adapter_t *adapter, int index)
372*d39a76e7Sxw {
373*d39a76e7Sxw 	struct cmac *mac;
374*d39a76e7Sxw 	u32 data32;
375*d39a76e7Sxw 
376*d39a76e7Sxw 	if (index >= 4)
377*d39a76e7Sxw 		return (NULL);
378*d39a76e7Sxw 
379*d39a76e7Sxw 	mac = t1_os_malloc_wait_zero(sizeof (*mac) + sizeof (cmac_instance));
380*d39a76e7Sxw 	if (!mac)
381*d39a76e7Sxw 		return (NULL);
382*d39a76e7Sxw 
383*d39a76e7Sxw 	mac->ops = &chelsio_mac_ops;
384*d39a76e7Sxw 	mac->instance = (cmac_instance *) (mac + 1);
385*d39a76e7Sxw 
386*d39a76e7Sxw 	mac->instance->index = index;
387*d39a76e7Sxw 	mac->adapter = adapter;
388*d39a76e7Sxw 
389*d39a76e7Sxw 	data32 = t1_read_reg_4(adapter, MAC_REG_CSR(mac->instance->index));
390*d39a76e7Sxw 	data32 &= ~(F_MAC_RESET | F_MAC_PROMISC | F_MAC_PROMISC |
391*d39a76e7Sxw 		    F_MAC_LB_ENABLE | F_MAC_RX_ENABLE | F_MAC_TX_ENABLE);
392*d39a76e7Sxw 	data32 |= F_MAC_JUMBO_ENABLE;
393*d39a76e7Sxw 	t1_write_reg_4(adapter, MAC_REG_CSR(mac->instance->index), data32);
394*d39a76e7Sxw 
395*d39a76e7Sxw 	/* Initialize the random backoff seed. */
396*d39a76e7Sxw 	data32 = 0x55aa + (3 * index);
397*d39a76e7Sxw 	t1_write_reg_4(adapter,
398*d39a76e7Sxw 		MAC_REG_GMRANDBACKOFFSEED(mac->instance->index), data32);
399*d39a76e7Sxw 
400*d39a76e7Sxw 	/* Check to see if the mac address needs to be set manually. */
401*d39a76e7Sxw 	data32 = t1_read_reg_4(adapter, MAC_REG_IDLO(mac->instance->index));
402*d39a76e7Sxw 	if (data32 == 0 || data32 == 0xffffffff) {
403*d39a76e7Sxw 		/*
404*d39a76e7Sxw 		 * Add a default MAC address if we can't read one.
405*d39a76e7Sxw 		 */
406*d39a76e7Sxw 		t1_write_reg_4(adapter, MAC_REG_IDLO(mac->instance->index),
407*d39a76e7Sxw 			0x43FFFFFF - index);
408*d39a76e7Sxw 		t1_write_reg_4(adapter, MAC_REG_IDHI(mac->instance->index),
409*d39a76e7Sxw 			0x0007);
410*d39a76e7Sxw 	}
411*d39a76e7Sxw 
412*d39a76e7Sxw 	(void) mac_set_mtu(mac, 1500);
413*d39a76e7Sxw 	return (mac);
414*d39a76e7Sxw }
415*d39a76e7Sxw 
416*d39a76e7Sxw struct gmac t1_chelsio_mac_ops = {
417*d39a76e7Sxw 	0,
418*d39a76e7Sxw 	mac_create
419*d39a76e7Sxw };
420