xref: /illumos-gate/usr/src/uts/common/io/axf/axf_usbgem.c (revision 6716431b)
1*6716431bSRobert Mustacchi /*
2*6716431bSRobert Mustacchi  * axf_usbgem.c : ASIX AX88172/772 USB to Fast Ethernet Driver for Solaris
3*6716431bSRobert Mustacchi  *
4*6716431bSRobert Mustacchi  * Copyright (c) 2004-2012 Masayuki Murayama.  All rights reserved.
5*6716431bSRobert Mustacchi  *
6*6716431bSRobert Mustacchi  * Redistribution and use in source and binary forms, with or without
7*6716431bSRobert Mustacchi  * modification, are permitted provided that the following conditions are met:
8*6716431bSRobert Mustacchi  *
9*6716431bSRobert Mustacchi  * 1. Redistributions of source code must retain the above copyright notice,
10*6716431bSRobert Mustacchi  *    this list of conditions and the following disclaimer.
11*6716431bSRobert Mustacchi  *
12*6716431bSRobert Mustacchi  * 2. Redistributions in binary form must reproduce the above copyright notice,
13*6716431bSRobert Mustacchi  *    this list of conditions and the following disclaimer in the documentation
14*6716431bSRobert Mustacchi  *    and/or other materials provided with the distribution.
15*6716431bSRobert Mustacchi  *
16*6716431bSRobert Mustacchi  * 3. Neither the name of the author nor the names of its contributors may be
17*6716431bSRobert Mustacchi  *    used to endorse or promote products derived from this software without
18*6716431bSRobert Mustacchi  *    specific prior written permission.
19*6716431bSRobert Mustacchi  *
31*6716431bSRobert Mustacchi  * DAMAGE.
32*6716431bSRobert Mustacchi  */
33*6716431bSRobert Mustacchi 
34*6716431bSRobert Mustacchi #pragma ident "@(#)axf_usbgem.c	1.3 12/02/09"
35*6716431bSRobert Mustacchi 
36*6716431bSRobert Mustacchi /*
37*6716431bSRobert Mustacchi  *  Changelog:
38*6716431bSRobert Mustacchi  */
39*6716431bSRobert Mustacchi 
40*6716431bSRobert Mustacchi /*
41*6716431bSRobert Mustacchi  * TODO
42*6716431bSRobert Mustacchi  * handle RXMODE_ENABLE in set_rx_filter()
43*6716431bSRobert Mustacchi  */
44*6716431bSRobert Mustacchi /* ======================================================= */
45*6716431bSRobert Mustacchi 
46*6716431bSRobert Mustacchi /*
47*6716431bSRobert Mustacchi  * Solaris system header files and macros
48*6716431bSRobert Mustacchi  */
49*6716431bSRobert Mustacchi 
50*6716431bSRobert Mustacchi /* minimum kernel headers for drivers */
51*6716431bSRobert Mustacchi #include <sys/types.h>
52*6716431bSRobert Mustacchi #include <sys/conf.h>
53*6716431bSRobert Mustacchi #include <sys/debug.h>
54*6716431bSRobert Mustacchi #include <sys/kmem.h>
55*6716431bSRobert Mustacchi #include <sys/modctl.h>
56*6716431bSRobert Mustacchi #include <sys/errno.h>
57*6716431bSRobert Mustacchi #include <sys/ddi.h>
58*6716431bSRobert Mustacchi #include <sys/sunddi.h>
59*6716431bSRobert Mustacchi #include <sys/byteorder.h>
60*6716431bSRobert Mustacchi 
61*6716431bSRobert Mustacchi /* ethernet stuff */
62*6716431bSRobert Mustacchi #include <sys/ethernet.h>
63*6716431bSRobert Mustacchi 
64*6716431bSRobert Mustacchi /* interface card depend stuff */
65*6716431bSRobert Mustacchi #include <sys/stropts.h>
66*6716431bSRobert Mustacchi #include <sys/stream.h>
67*6716431bSRobert Mustacchi #include <sys/strlog.h>
68*6716431bSRobert Mustacchi #include <sys/usb/usba.h>
69*6716431bSRobert Mustacchi #include "usbgem.h"
70*6716431bSRobert Mustacchi 
71*6716431bSRobert Mustacchi /* hardware stuff */
72*6716431bSRobert Mustacchi #include "usbgem_mii.h"
73*6716431bSRobert Mustacchi #include "ax88172reg.h"
74*6716431bSRobert Mustacchi 
75*6716431bSRobert Mustacchi char	ident[] = "ax88x72 usbnic driver v" VERSION;
76*6716431bSRobert Mustacchi 
77*6716431bSRobert Mustacchi /*
78*6716431bSRobert Mustacchi  * Useful macros
79*6716431bSRobert Mustacchi  */
80*6716431bSRobert Mustacchi #define	CHECK_AND_JUMP(err, label)	if (err != USB_SUCCESS) goto label
81*6716431bSRobert Mustacchi #define	LE16P(p)	((((uint8_t *)(p))[1] << 8) | ((uint8_t *)(p))[0])
82*6716431bSRobert Mustacchi 
83*6716431bSRobert Mustacchi #define	AX88172(dp)	\
84*6716431bSRobert Mustacchi 	(((struct axf_dev *)(dp)->private)->chip->type == CHIP_TYPE_AX88172)
85*6716431bSRobert Mustacchi 
86*6716431bSRobert Mustacchi #define	AX88772(dp)	\
87*6716431bSRobert Mustacchi 	(((struct axf_dev *)(dp)->private)->chip->type == CHIP_TYPE_AX88772)
88*6716431bSRobert Mustacchi 
89*6716431bSRobert Mustacchi /*
90*6716431bSRobert Mustacchi  * Debugging
91*6716431bSRobert Mustacchi  */
92*6716431bSRobert Mustacchi #ifdef DEBUG_LEVEL
93*6716431bSRobert Mustacchi static int axf_debug = DEBUG_LEVEL;
94*6716431bSRobert Mustacchi #define	DPRINTF(n, args)	if (axf_debug > (n)) cmn_err args
95*6716431bSRobert Mustacchi #else
96*6716431bSRobert Mustacchi #define	DPRINTF(n, args)
97*6716431bSRobert Mustacchi #endif
98*6716431bSRobert Mustacchi 
99*6716431bSRobert Mustacchi /*
100*6716431bSRobert Mustacchi  * Our configration for ax88172
101*6716431bSRobert Mustacchi  */
102*6716431bSRobert Mustacchi /* timeouts */
103*6716431bSRobert Mustacchi #define	ONESEC		(drv_usectohz(1*1000000))
104*6716431bSRobert Mustacchi 
105*6716431bSRobert Mustacchi /*
106*6716431bSRobert Mustacchi  * RX/TX buffer size
107*6716431bSRobert Mustacchi  */
108*6716431bSRobert Mustacchi 
109*6716431bSRobert Mustacchi /*
110*6716431bSRobert Mustacchi  * Local device definitions
111*6716431bSRobert Mustacchi  */
112*6716431bSRobert Mustacchi struct chip_info {
113*6716431bSRobert Mustacchi 	uint16_t	vid;	/* usb vendor id */
114*6716431bSRobert Mustacchi 	uint16_t	pid;	/* usb product id */
115*6716431bSRobert Mustacchi 	int		type;
116*6716431bSRobert Mustacchi 	uint8_t		gpio_reset[2];
117*6716431bSRobert Mustacchi 	uint8_t		gpio_speed[2];
118*6716431bSRobert Mustacchi 	uint8_t		gpio_duplex[2];
119*6716431bSRobert Mustacchi 	char		*name;
120*6716431bSRobert Mustacchi #define	CHIP_TYPE_AX88172	0
121*6716431bSRobert Mustacchi #define	CHIP_TYPE_AX88772	1
122*6716431bSRobert Mustacchi #define	CHIP_TYPE_AX88178	2
123*6716431bSRobert Mustacchi };
124*6716431bSRobert Mustacchi 
125*6716431bSRobert Mustacchi #define	GPIO_DEFAULT	{0x00, 0x15}, {0, 0}, {0, 0}
126*6716431bSRobert Mustacchi struct chip_info chiptbl_88x7x[] = {
127*6716431bSRobert Mustacchi /* AX88172 */
128*6716431bSRobert Mustacchi {
129*6716431bSRobert Mustacchi 	/* Planex UE2-100TX, Hawking UF200, TrendNet TU2-ET100 */
130*6716431bSRobert Mustacchi 	0x07b8, 0x420a, CHIP_TYPE_AX88172,
131*6716431bSRobert Mustacchi 
132*6716431bSRobert Mustacchi 	/*
133*6716431bSRobert Mustacchi 	 * the default setting covers below:
134*6716431bSRobert Mustacchi 	 * gpio bit2 has to be 0 and gpio bit0 has to be 1
135*6716431bSRobert Mustacchi 	 */
136*6716431bSRobert Mustacchi 	{0, 0},
137*6716431bSRobert Mustacchi 	{GPIO_EN1, GPIO_DATA1 | GPIO_EN1},
138*6716431bSRobert Mustacchi 	{0, 0},
139*6716431bSRobert Mustacchi 	"Planex UE2-100TX",	/* tested */
140*6716431bSRobert Mustacchi },
141*6716431bSRobert Mustacchi {
142*6716431bSRobert Mustacchi 	0x2001, 0x1a00, CHIP_TYPE_AX88172,
143*6716431bSRobert Mustacchi 	{0x9f, 0x9e}, {0, 0}, {0, 0},
144*6716431bSRobert Mustacchi 	"D-Link dube100",	/* XXX */
145*6716431bSRobert Mustacchi },
146*6716431bSRobert Mustacchi {
147*6716431bSRobert Mustacchi 	0x077b, 0x2226, CHIP_TYPE_AX88172,
148*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
149*6716431bSRobert Mustacchi 	"Linksys USB200M",
150*6716431bSRobert Mustacchi },
151*6716431bSRobert Mustacchi {
152*6716431bSRobert Mustacchi 	0x0846, 0x1040, CHIP_TYPE_AX88172,
153*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
154*6716431bSRobert Mustacchi 	"Netgear FA120",
155*6716431bSRobert Mustacchi },
156*6716431bSRobert Mustacchi {
157*6716431bSRobert Mustacchi 	0x0b95, 0x1720, CHIP_TYPE_AX88172,
158*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
159*6716431bSRobert Mustacchi 	"Intellinet, ST Lab USB Ethernet",
160*6716431bSRobert Mustacchi },
161*6716431bSRobert Mustacchi {
162*6716431bSRobert Mustacchi 	0x08dd, 0x90ff, CHIP_TYPE_AX88172,
163*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
164*6716431bSRobert Mustacchi 	"Billionton Systems, USB2AR",
165*6716431bSRobert Mustacchi },
166*6716431bSRobert Mustacchi {
167*6716431bSRobert Mustacchi 	0x0557, 0x2009, CHIP_TYPE_AX88172,
168*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
169*6716431bSRobert Mustacchi 	"ATEN UC210T",
170*6716431bSRobert Mustacchi },
171*6716431bSRobert Mustacchi {
172*6716431bSRobert Mustacchi 	0x0411, 0x003d, CHIP_TYPE_AX88172,
173*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
174*6716431bSRobert Mustacchi 	"Buffalo LUA-U2-KTX",
175*6716431bSRobert Mustacchi },
176*6716431bSRobert Mustacchi {
177*6716431bSRobert Mustacchi 	0x6189, 0x182d, CHIP_TYPE_AX88172,
178*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
179*6716431bSRobert Mustacchi 	"Sitecom LN-029 USB 2.0 10/100 Ethernet adapter",
180*6716431bSRobert Mustacchi },
181*6716431bSRobert Mustacchi {
182*6716431bSRobert Mustacchi 	0x07aa, 0x0017, CHIP_TYPE_AX88172,
183*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
184*6716431bSRobert Mustacchi 	"corega FEther USB2-TX",
185*6716431bSRobert Mustacchi },
186*6716431bSRobert Mustacchi {
187*6716431bSRobert Mustacchi 	0x1189, 0x0893, CHIP_TYPE_AX88172,
188*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
189*6716431bSRobert Mustacchi 	"Surecom EP-1427X-2",
190*6716431bSRobert Mustacchi },
191*6716431bSRobert Mustacchi {
192*6716431bSRobert Mustacchi 	0x1631, 0x6200, CHIP_TYPE_AX88172,
193*6716431bSRobert Mustacchi 	GPIO_DEFAULT,
194*6716431bSRobert Mustacchi 	"goodway corp usb gwusb2e",
195*6716431bSRobert Mustacchi },
196*6716431bSRobert Mustacchi /* AX88772 and AX88178 */
197*6716431bSRobert Mustacchi {
198*6716431bSRobert Mustacchi 	0x13b1, 0x0018, CHIP_TYPE_AX88772,
199*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
200*6716431bSRobert Mustacchi 	"Linksys USB200M rev.2",
201*6716431bSRobert Mustacchi },
202*6716431bSRobert Mustacchi {
203*6716431bSRobert Mustacchi 	0x1557, 0x7720, CHIP_TYPE_AX88772,
204*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
205*6716431bSRobert Mustacchi 	"0Q0 cable ethernet",
206*6716431bSRobert Mustacchi },
207*6716431bSRobert Mustacchi {
208*6716431bSRobert Mustacchi 	0x07d1, 0x3c05, CHIP_TYPE_AX88772,
209*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
210*6716431bSRobert Mustacchi 	"DLink DUB E100 ver B1",
211*6716431bSRobert Mustacchi },
212*6716431bSRobert Mustacchi {
213*6716431bSRobert Mustacchi 	0x2001, 0x3c05, CHIP_TYPE_AX88772,
214*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
215*6716431bSRobert Mustacchi 	"DLink DUB E100 ver B1(2)",
216*6716431bSRobert Mustacchi },
217*6716431bSRobert Mustacchi {
218*6716431bSRobert Mustacchi 	0x05ac, 0x1402, CHIP_TYPE_AX88772,
219*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
220*6716431bSRobert Mustacchi 	"Apple Ethernet USB Adapter",
221*6716431bSRobert Mustacchi },
222*6716431bSRobert Mustacchi {
223*6716431bSRobert Mustacchi 	0x1737, 0x0039, CHIP_TYPE_AX88178,
224*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
225*6716431bSRobert Mustacchi 	"Linksys USB1000",
226*6716431bSRobert Mustacchi },
227*6716431bSRobert Mustacchi {
228*6716431bSRobert Mustacchi 	0x0411, 0x006e, CHIP_TYPE_AX88178,
229*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
230*6716431bSRobert Mustacchi 	"Buffalo LUA-U2-KGT/LUA-U2-GT",
231*6716431bSRobert Mustacchi },
232*6716431bSRobert Mustacchi {
233*6716431bSRobert Mustacchi 	0x04bb, 0x0930, CHIP_TYPE_AX88178,
234*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
235*6716431bSRobert Mustacchi 	"I/O DATA ETG-US2",
236*6716431bSRobert Mustacchi },
237*6716431bSRobert Mustacchi {
238*6716431bSRobert Mustacchi 	0x050d, 0x5055, CHIP_TYPE_AX88178,
239*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
240*6716431bSRobert Mustacchi 	"Belkin F5D5055",
241*6716431bSRobert Mustacchi },
242*6716431bSRobert Mustacchi {
243*6716431bSRobert Mustacchi 	/* generic ax88772 must be the last entry */
244*6716431bSRobert Mustacchi 	/* planex UE-200TX-G */
245*6716431bSRobert Mustacchi 	0x0b95, 0x7720, CHIP_TYPE_AX88772,
246*6716431bSRobert Mustacchi 	{0, 0}, {0, 0}, {0, 0},
247*6716431bSRobert Mustacchi 	"ASIX AX88772/AX88178",	/* tested */
248*6716431bSRobert Mustacchi },
249*6716431bSRobert Mustacchi };
250*6716431bSRobert Mustacchi 
251*6716431bSRobert Mustacchi #define	CHIPTABLESIZE	(sizeof (chiptbl_88x7x) / sizeof (struct chip_info))
252*6716431bSRobert Mustacchi 
253*6716431bSRobert Mustacchi struct axf_dev {
254*6716431bSRobert Mustacchi 	/*
255*6716431bSRobert Mustacchi 	 * Misc HW information
256*6716431bSRobert Mustacchi 	 */
257*6716431bSRobert Mustacchi 	struct chip_info	*chip;
258*6716431bSRobert Mustacchi 	uint8_t			ipg[3];
259*6716431bSRobert Mustacchi 	uint8_t			gpio;
260*6716431bSRobert Mustacchi 	uint16_t		rcr;
261*6716431bSRobert Mustacchi 	uint16_t		msr;
262*6716431bSRobert Mustacchi 	uint8_t			last_link_state;
263*6716431bSRobert Mustacchi 	boolean_t		phy_has_reset;
264*6716431bSRobert Mustacchi };
265*6716431bSRobert Mustacchi 
266*6716431bSRobert Mustacchi /*
267*6716431bSRobert Mustacchi  * private functions
268*6716431bSRobert Mustacchi  */
269*6716431bSRobert Mustacchi 
270*6716431bSRobert Mustacchi /* mii operations */
271*6716431bSRobert Mustacchi static uint16_t axf_mii_read(struct usbgem_dev *, uint_t, int *errp);
272*6716431bSRobert Mustacchi static void axf_mii_write(struct usbgem_dev *, uint_t, uint16_t, int *errp);
273*6716431bSRobert Mustacchi 
274*6716431bSRobert Mustacchi /* nic operations */
275*6716431bSRobert Mustacchi static int axf_reset_chip(struct usbgem_dev *);
276*6716431bSRobert Mustacchi static int axf_init_chip(struct usbgem_dev *);
277*6716431bSRobert Mustacchi static int axf_start_chip(struct usbgem_dev *);
278*6716431bSRobert Mustacchi static int axf_stop_chip(struct usbgem_dev *);
279*6716431bSRobert Mustacchi static int axf_set_media(struct usbgem_dev *);
280*6716431bSRobert Mustacchi static int axf_set_rx_filter(struct usbgem_dev *);
281*6716431bSRobert Mustacchi static int axf_get_stats(struct usbgem_dev *);
282*6716431bSRobert Mustacchi static void  axf_interrupt(struct usbgem_dev *, mblk_t *);
283*6716431bSRobert Mustacchi 
284*6716431bSRobert Mustacchi /* packet operations */
285*6716431bSRobert Mustacchi static mblk_t *axf_tx_make_packet(struct usbgem_dev *, mblk_t *);
286*6716431bSRobert Mustacchi static mblk_t *axf_rx_make_packet(struct usbgem_dev *, mblk_t *);
287*6716431bSRobert Mustacchi 
288*6716431bSRobert Mustacchi /* =============================================================== */
289*6716431bSRobert Mustacchi /*
290*6716431bSRobert Mustacchi  * I/O functions
291*6716431bSRobert Mustacchi  */
292*6716431bSRobert Mustacchi /* =============================================================== */
293*6716431bSRobert Mustacchi /* BEGIN CSTYLED */
294*6716431bSRobert Mustacchi #define	OUT(dp, req, val, ix, len, buf, errp, label)	\
295*6716431bSRobert Mustacchi 	if ((*(errp) = usbgem_ctrl_out((dp), 	\
296*6716431bSRobert Mustacchi 	/* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV	\
297*6716431bSRobert Mustacchi 		    | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV,	\
298*6716431bSRobert Mustacchi 	/* bRequest */ (req),	\
299*6716431bSRobert Mustacchi 	/* wValue */   (val),	\
300*6716431bSRobert Mustacchi 	/* wIndex */   (ix),	\
301*6716431bSRobert Mustacchi 	/* wLength */  (len),	\
302*6716431bSRobert Mustacchi 	/* value */    (buf),	\
303*6716431bSRobert Mustacchi 	/* size */     (len))) != USB_SUCCESS) goto label
304*6716431bSRobert Mustacchi 
305*6716431bSRobert Mustacchi #define	IN(dp, req, val, ix, len, buf, errp, label)	\
306*6716431bSRobert Mustacchi 	if ((*(errp) = usbgem_ctrl_in((dp), 	\
307*6716431bSRobert Mustacchi 	/* bmRequestType */ USB_DEV_REQ_DEV_TO_HOST	\
308*6716431bSRobert Mustacchi 		    | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV,	\
309*6716431bSRobert Mustacchi 	/* bRequest */ (req),	\
310*6716431bSRobert Mustacchi 	/* wValue */   (val),	\
311*6716431bSRobert Mustacchi 	/* wIndex */   (ix),	\
312*6716431bSRobert Mustacchi 	/* wLength */  (len),	\
313*6716431bSRobert Mustacchi 	/* valuep */   (buf),	\
314*6716431bSRobert Mustacchi 	/* size */     (len))) != USB_SUCCESS) goto label
315*6716431bSRobert Mustacchi /* END CSTYLED */
316*6716431bSRobert Mustacchi 
317*6716431bSRobert Mustacchi /* =============================================================== */
318*6716431bSRobert Mustacchi /*
319*6716431bSRobert Mustacchi  * Hardware manupilation
320*6716431bSRobert Mustacchi  */
321*6716431bSRobert Mustacchi /* =============================================================== */
322*6716431bSRobert Mustacchi static int
axf_reset_phy(struct usbgem_dev * dp)323*6716431bSRobert Mustacchi axf_reset_phy(struct usbgem_dev *dp)
324*6716431bSRobert Mustacchi {
325*6716431bSRobert Mustacchi 	uint8_t	phys[2];
326*6716431bSRobert Mustacchi 	uint8_t	val8;
327*6716431bSRobert Mustacchi 	int	err;
328*6716431bSRobert Mustacchi 	struct axf_dev	*lp = dp->private;
329*6716431bSRobert Mustacchi 
330*6716431bSRobert Mustacchi 	DPRINTF(2, (CE_CONT, "!%s: %s: called", dp->name, __func__));
331*6716431bSRobert Mustacchi 
332*6716431bSRobert Mustacchi 	if (AX88172(dp)) {
333*6716431bSRobert Mustacchi 		delay(drv_usectohz(5000));
334*6716431bSRobert Mustacchi 		IN(dp, VCMD_READ_GPIO, 0, 0, 1, &val8, &err, usberr);
335*6716431bSRobert Mustacchi 
336*6716431bSRobert Mustacchi 		DPRINTF(0, (CE_CONT, "!%s: %s: gpio 0x%b",
337*6716431bSRobert Mustacchi 		    dp->name, __func__, val8, GPIO_BITS));
338*6716431bSRobert Mustacchi 
339*6716431bSRobert Mustacchi 		/* reset MII PHY */
340*6716431bSRobert Mustacchi 		val8 = lp->chip->gpio_reset[1]
341*6716431bSRobert Mustacchi 		    | lp->chip->gpio_speed[dp->speed]
342*6716431bSRobert Mustacchi 		    | lp->chip->gpio_duplex[dp->full_duplex];
343*6716431bSRobert Mustacchi 
344*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_GPIO,
345*6716431bSRobert Mustacchi 		    val8, 0, 0, NULL, &err, usberr);
346*6716431bSRobert Mustacchi 		delay(drv_usectohz(5000));
347*6716431bSRobert Mustacchi 
348*6716431bSRobert Mustacchi 		val8 = lp->chip->gpio_reset[0]
349*6716431bSRobert Mustacchi 		    | lp->chip->gpio_speed[dp->speed]
350*6716431bSRobert Mustacchi 		    | lp->chip->gpio_duplex[dp->full_duplex];
351*6716431bSRobert Mustacchi 
352*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_GPIO,
353*6716431bSRobert Mustacchi 		    val8, 0, 0, NULL, &err, usberr);
354*6716431bSRobert Mustacchi 		delay(drv_usectohz(5000));
355*6716431bSRobert Mustacchi 	} else {
356*6716431bSRobert Mustacchi 		lp->gpio = GPIO_RSE | GPIO_DATA2 | GPIO_EN2;
357*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_GPIO, lp->gpio, 0,
358*6716431bSRobert Mustacchi 		    0, NULL, &err, usberr);
359*6716431bSRobert Mustacchi 		drv_usecwait(1000);
360*6716431bSRobert Mustacchi 
361*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_PHY_SELECT_88772,
362*6716431bSRobert Mustacchi 		    dp->mii_phy_addr == 16 ? 1 : 0, 0, 0, NULL, &err, usberr);
363*6716431bSRobert Mustacchi 
364*6716431bSRobert Mustacchi 		OUT(dp, VCMD_SOFTWARE_RESET_88772,
365*6716431bSRobert Mustacchi 		    SWRST_IPPD | SWRST_PRL, 0, 0, NULL, &err, usberr);
366*6716431bSRobert Mustacchi 		delay(drv_usectohz(150*1000));
367*6716431bSRobert Mustacchi 		OUT(dp, VCMD_SOFTWARE_RESET_88772,
368*6716431bSRobert Mustacchi 		    0, 0, 0, NULL, &err, usberr);
369*6716431bSRobert Mustacchi 
370*6716431bSRobert Mustacchi 		OUT(dp, VCMD_SOFTWARE_RESET_88772,
371*6716431bSRobert Mustacchi 		    dp->mii_phy_addr == 16 ? SWRST_IPRL : SWRST_PRTE,
372*6716431bSRobert Mustacchi 		    0, 0, NULL, &err, usberr);
373*6716431bSRobert Mustacchi 		delay(drv_usectohz(150*1000));
374*6716431bSRobert Mustacchi 	}
375*6716431bSRobert Mustacchi 
376*6716431bSRobert Mustacchi 
377*6716431bSRobert Mustacchi 	return (USB_SUCCESS);
378*6716431bSRobert Mustacchi 
379*6716431bSRobert Mustacchi usberr:
380*6716431bSRobert Mustacchi 	return (USB_FAILURE);
381*6716431bSRobert Mustacchi }
382*6716431bSRobert Mustacchi 
383*6716431bSRobert Mustacchi static int
axf_reset_chip(struct usbgem_dev * dp)384*6716431bSRobert Mustacchi axf_reset_chip(struct usbgem_dev *dp)
385*6716431bSRobert Mustacchi {
386*6716431bSRobert Mustacchi 	int	err = USB_SUCCESS;
387*6716431bSRobert Mustacchi 
388*6716431bSRobert Mustacchi 	if (AX88172(dp)) {
389*6716431bSRobert Mustacchi 		/* there are no ways to reset nic */
390*6716431bSRobert Mustacchi 		return (USB_SUCCESS);
391*6716431bSRobert Mustacchi 	}
392*6716431bSRobert Mustacchi #ifdef NEVER
393*6716431bSRobert Mustacchi 	OUT(dp, VCMD_SOFTWARE_RESET_88772,
394*6716431bSRobert Mustacchi 	    SWRST_RR | SWRST_RT, 0, 0, NULL, &err, usberr);
395*6716431bSRobert Mustacchi 	OUT(dp, VCMD_SOFTWARE_RESET_88772,
396*6716431bSRobert Mustacchi 	    0, 0, 0, NULL, &err, usberr);
397*6716431bSRobert Mustacchi usberr:
398*6716431bSRobert Mustacchi #endif
399*6716431bSRobert Mustacchi 	return (err);
400*6716431bSRobert Mustacchi }
401*6716431bSRobert Mustacchi 
402*6716431bSRobert Mustacchi /*
403*6716431bSRobert Mustacchi  * Setup ax88172
404*6716431bSRobert Mustacchi  */
405*6716431bSRobert Mustacchi static int
axf_init_chip(struct usbgem_dev * dp)406*6716431bSRobert Mustacchi axf_init_chip(struct usbgem_dev *dp)
407*6716431bSRobert Mustacchi {
408*6716431bSRobert Mustacchi 	int		i;
409*6716431bSRobert Mustacchi 	uint32_t	val;
410*6716431bSRobert Mustacchi 	int		err = USB_SUCCESS;
411*6716431bSRobert Mustacchi 	uint16_t	reg;
412*6716431bSRobert Mustacchi 	uint8_t		buf[2];
413*6716431bSRobert Mustacchi 	uint16_t	tmp16;
414*6716431bSRobert Mustacchi 	struct axf_dev	*lp = dp->private;
415*6716431bSRobert Mustacchi 
416*6716431bSRobert Mustacchi 	DPRINTF(2, (CE_CONT, "!%s: %s: called", dp->name, __func__));
417*6716431bSRobert Mustacchi 
418*6716431bSRobert Mustacchi 	/* rx conrol register: read default value */
419*6716431bSRobert Mustacchi 	if (!AX88172(dp)) {
420*6716431bSRobert Mustacchi 		/* clear rx control */
421*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_RXCTRL, 0, 0, 0, NULL, &err, usberr);
422*6716431bSRobert Mustacchi 	}
423*6716431bSRobert Mustacchi 
424*6716431bSRobert Mustacchi 	IN(dp, VCMD_READ_RXCTRL, 0, 0, 2, buf, &err, usberr);
425*6716431bSRobert Mustacchi 	lp->rcr = LE16P(buf);
426*6716431bSRobert Mustacchi 	DPRINTF(0, (CE_CONT, "!%s: %s: rcr(default):%b",
427*6716431bSRobert Mustacchi 	    dp->name, __func__, lp->rcr, RCR_BITS));
428*6716431bSRobert Mustacchi 
429*6716431bSRobert Mustacchi 	lp->rcr &= ~RCR_SO;
430*6716431bSRobert Mustacchi 
431*6716431bSRobert Mustacchi 	/* Media status register */
432*6716431bSRobert Mustacchi 	if (AX88172(dp)) {
433*6716431bSRobert Mustacchi #ifdef notdef
434*6716431bSRobert Mustacchi 		lp->msr = MSR_TXABT;
435*6716431bSRobert Mustacchi #else
436*6716431bSRobert Mustacchi 		lp->msr = 0;
437*6716431bSRobert Mustacchi #endif
438*6716431bSRobert Mustacchi 	} else {
439*6716431bSRobert Mustacchi 		lp->msr = MSR_RE | MSR_TXABT;
440*6716431bSRobert Mustacchi 	}
441*6716431bSRobert Mustacchi 	DPRINTF(0, (CE_CONT, "!%s: %s: msr:%b",
442*6716431bSRobert Mustacchi 	    dp->name, __func__, lp->msr, MSR_BITS));
443*6716431bSRobert Mustacchi 	err = axf_set_media(dp);
444*6716431bSRobert Mustacchi 	CHECK_AND_JUMP(err, usberr);
445*6716431bSRobert Mustacchi 
446*6716431bSRobert Mustacchi 	/* write IPG0-2 registers */
447*6716431bSRobert Mustacchi 	if (AX88172(dp)) {
448*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_IPG, lp->ipg[0], 0, 0, NULL, &err, usberr);
449*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_IPG1, lp->ipg[1], 0, 0, NULL, &err, usberr);
450*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_IPG2, lp->ipg[2], 0, 0, NULL, &err, usberr);
451*6716431bSRobert Mustacchi 	} else {
452*6716431bSRobert Mustacchi 		/* EMPTY */
453*6716431bSRobert Mustacchi 	}
454*6716431bSRobert Mustacchi #ifdef ENABLE_RX_IN_INIT_CHIP
455*6716431bSRobert Mustacchi 	/* enable Rx */
456*6716431bSRobert Mustacchi 	lp->rcr |= RCR_SO;
457*6716431bSRobert Mustacchi 	OUT(dp, VCMD_WRITE_RXCTRL, lp->rcr, 0, 0, NULL, &err, usberr);
458*6716431bSRobert Mustacchi #endif
459*6716431bSRobert Mustacchi usberr:
460*6716431bSRobert Mustacchi 	DPRINTF(2, (CE_CONT, "!%s: %s: end (%s)",
461*6716431bSRobert Mustacchi 	    dp->name, __func__,
462*6716431bSRobert Mustacchi 	    err, err == USB_SUCCESS ? "success" : "error"));
463*6716431bSRobert Mustacchi 	return (err);
464*6716431bSRobert Mustacchi }
465*6716431bSRobert Mustacchi 
466*6716431bSRobert Mustacchi static int
axf_start_chip(struct usbgem_dev * dp)467*6716431bSRobert Mustacchi axf_start_chip(struct usbgem_dev *dp)
468*6716431bSRobert Mustacchi {
469*6716431bSRobert Mustacchi 	int	err = USB_SUCCESS;
470*6716431bSRobert Mustacchi 	struct axf_dev	*lp = dp->private;
471*6716431bSRobert Mustacchi #ifndef ENABLE_RX_IN_INIT_CHIP
472*6716431bSRobert Mustacchi 	/* enable Rx */
473*6716431bSRobert Mustacchi 	lp->rcr |= RCR_SO;
474*6716431bSRobert Mustacchi 	OUT(dp, VCMD_WRITE_RXCTRL, lp->rcr, 0, 0, NULL, &err, usberr);
475*6716431bSRobert Mustacchi 
476*6716431bSRobert Mustacchi usberr:
477*6716431bSRobert Mustacchi 	DPRINTF(2, (CE_CONT, "!%s: %s: end (%s)",
478*6716431bSRobert Mustacchi 	    dp->name, __func__,
479*6716431bSRobert Mustacchi 	    err, err == USB_SUCCESS ? "success" : "error"));
480*6716431bSRobert Mustacchi #endif
481*6716431bSRobert Mustacchi 	return (err);
482*6716431bSRobert Mustacchi }
483*6716431bSRobert Mustacchi 
484*6716431bSRobert Mustacchi static int
axf_stop_chip(struct usbgem_dev * dp)485*6716431bSRobert Mustacchi axf_stop_chip(struct usbgem_dev *dp)
486*6716431bSRobert Mustacchi {
487*6716431bSRobert Mustacchi 	int	err = USB_SUCCESS;
488*6716431bSRobert Mustacchi 	struct axf_dev	*lp = dp->private;
489*6716431bSRobert Mustacchi 
490*6716431bSRobert Mustacchi 	/* Disable Rx */
491*6716431bSRobert Mustacchi 	lp->rcr &= ~RCR_SO;
492*6716431bSRobert Mustacchi 	OUT(dp, VCMD_WRITE_RXCTRL, lp->rcr, 0, 0, NULL, &err, usberr);
493*6716431bSRobert Mustacchi 
494*6716431bSRobert Mustacchi 	/*
495*6716431bSRobert Mustacchi 	 * Restore factory mac address
496*6716431bSRobert Mustacchi 	 * if we have changed current mac address
497*6716431bSRobert Mustacchi 	 */
498*6716431bSRobert Mustacchi 	if (!AX88172(dp) &&
499*6716431bSRobert Mustacchi 	    bcmp(dp->dev_addr.ether_addr_octet,
500*6716431bSRobert Mustacchi 	    dp->cur_addr.ether_addr_octet,
501*6716431bSRobert Mustacchi 	    ETHERADDRL) != 0) {
502*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_NODE_ID_88772, 0, 0,
503*6716431bSRobert Mustacchi 		    ETHERADDRL, dp->cur_addr.ether_addr_octet, &err, usberr);
504*6716431bSRobert Mustacchi 	}
505*6716431bSRobert Mustacchi usberr:
506*6716431bSRobert Mustacchi 	return (axf_reset_chip(dp));
507*6716431bSRobert Mustacchi }
508*6716431bSRobert Mustacchi 
509*6716431bSRobert Mustacchi static int
axf_get_stats(struct usbgem_dev * dp)510*6716431bSRobert Mustacchi axf_get_stats(struct usbgem_dev *dp)
511*6716431bSRobert Mustacchi {
512*6716431bSRobert Mustacchi 	/* empty */
513*6716431bSRobert Mustacchi 	return (USB_SUCCESS);
514*6716431bSRobert Mustacchi }
515*6716431bSRobert Mustacchi 
516*6716431bSRobert Mustacchi static uint_t
axf_mcast_hash(struct usbgem_dev * dp,const uint8_t * addr)517*6716431bSRobert Mustacchi axf_mcast_hash(struct usbgem_dev *dp, const uint8_t *addr)
518*6716431bSRobert Mustacchi {
519*6716431bSRobert Mustacchi 	return (usbgem_ether_crc_be(addr) >> (32 - 6));
520*6716431bSRobert Mustacchi }
521*6716431bSRobert Mustacchi 
522*6716431bSRobert Mustacchi static int
axf_set_rx_filter(struct usbgem_dev * dp)523*6716431bSRobert Mustacchi axf_set_rx_filter(struct usbgem_dev *dp)
524*6716431bSRobert Mustacchi {
525*6716431bSRobert Mustacchi 	int		i;
526*6716431bSRobert Mustacchi 	uint8_t		mode;
527*6716431bSRobert Mustacchi 	uint8_t		mhash[8];
528*6716431bSRobert Mustacchi 	uint8_t		buf[2];
529*6716431bSRobert Mustacchi 	uint_t		h;
530*6716431bSRobert Mustacchi 	int		err = USB_SUCCESS;
531*6716431bSRobert Mustacchi 	struct axf_dev	*lp = dp->private;
532*6716431bSRobert Mustacchi 
533*6716431bSRobert Mustacchi 	DPRINTF(2, (CE_CONT, "!%s: %s: called, rxmode:%x",
534*6716431bSRobert Mustacchi 	    dp->name, __func__, dp->rxmode));
535*6716431bSRobert Mustacchi 
536*6716431bSRobert Mustacchi 	if (lp->rcr & RCR_SO) {
537*6716431bSRobert Mustacchi 		/* set promiscuous mode  before changing it. */
538*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_RXCTRL,
539*6716431bSRobert Mustacchi 		    lp->rcr | RCR_PRO, 0, 0, NULL, &err, usberr);
540*6716431bSRobert Mustacchi 	}
541*6716431bSRobert Mustacchi 
542*6716431bSRobert Mustacchi 	lp->rcr &= ~(RCR_AP_88772 | RCR_AM | RCR_SEP | RCR_AMALL | RCR_PRO);
543*6716431bSRobert Mustacchi 	mode = RCR_AB;	/* accept broadcast packets */
544*6716431bSRobert Mustacchi 
545*6716431bSRobert Mustacchi 	bzero(mhash, sizeof (mhash));
546*6716431bSRobert Mustacchi 
547*6716431bSRobert Mustacchi 	if (dp->rxmode & RXMODE_PROMISC) {
548*6716431bSRobert Mustacchi 		/* promiscious mode implies all multicast and all physical */
549*6716431bSRobert Mustacchi 		mode |= RCR_PRO;
550*6716431bSRobert Mustacchi 	} else if ((dp->rxmode & RXMODE_ALLMULTI) || dp->mc_count > 32) {
551*6716431bSRobert Mustacchi 		/* accept all multicast packets */
552*6716431bSRobert Mustacchi 		mode |= RCR_AMALL;
553*6716431bSRobert Mustacchi 	} else if (dp->mc_count > 0) {
554*6716431bSRobert Mustacchi 		/*
555*6716431bSRobert Mustacchi 		 * make hash table to select interresting
556*6716431bSRobert Mustacchi 		 * multicast address only.
557*6716431bSRobert Mustacchi 		 */
558*6716431bSRobert Mustacchi 		mode |= RCR_AM;
559*6716431bSRobert Mustacchi 		for (i = 0; i < dp->mc_count; i++) {
560*6716431bSRobert Mustacchi 			h = dp->mc_list[i].hash;
561*6716431bSRobert Mustacchi 			mhash[h / 8] |= 1 << (h % 8);
562*6716431bSRobert Mustacchi 		}
563*6716431bSRobert Mustacchi 	}
564*6716431bSRobert Mustacchi 	if (AX88172(dp)) {
565*6716431bSRobert Mustacchi 		if (bcmp(dp->dev_addr.ether_addr_octet,
566*6716431bSRobert Mustacchi 		    dp->cur_addr.ether_addr_octet, ETHERADDRL) != 0) {
567*6716431bSRobert Mustacchi 			/*
568*6716431bSRobert Mustacchi 			 * we use promiscious mode instead of changing the
569*6716431bSRobert Mustacchi 			 * mac address in ax88172
570*6716431bSRobert Mustacchi 			 */
571*6716431bSRobert Mustacchi 			mode |= RCR_PRO;
572*6716431bSRobert Mustacchi 		}
573*6716431bSRobert Mustacchi 	} else {
574*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_NODE_ID_88772, 0, 0,
575*6716431bSRobert Mustacchi 		    ETHERADDRL, dp->cur_addr.ether_addr_octet, &err, usberr);
576*6716431bSRobert Mustacchi 	}
577*6716431bSRobert Mustacchi 	lp->rcr |= mode;
578*6716431bSRobert Mustacchi 
579*6716431bSRobert Mustacchi 	/* set multicast hash table */
580*6716431bSRobert Mustacchi 	if (mode & RCR_AM) {
581*6716431bSRobert Mustacchi 		/* need to set up multicast hash table */
582*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_MCAST_FILTER, 0, 0,
583*6716431bSRobert Mustacchi 		    sizeof (mhash), mhash, &err, usberr);
584*6716431bSRobert Mustacchi 	}
585*6716431bSRobert Mustacchi 
586*6716431bSRobert Mustacchi 	/* update rcr */
587*6716431bSRobert Mustacchi 	OUT(dp, VCMD_WRITE_RXCTRL, lp->rcr, 0,
588*6716431bSRobert Mustacchi 	    0, NULL, &err, usberr);
589*6716431bSRobert Mustacchi 
590*6716431bSRobert Mustacchi #if DEBUG_LEVEL > 1
591*6716431bSRobert Mustacchi 	/* verify rxctrl reg */
592*6716431bSRobert Mustacchi 	IN(dp, VCMD_READ_RXCTRL, 0, 0, 2, buf, &err, usberr);
593*6716431bSRobert Mustacchi 	cmn_err(CE_CONT, "!%s: %s: rcr:%b returned",
594*6716431bSRobert Mustacchi 	    dp->name, __func__, LE16P(buf), RCR_BITS);
595*6716431bSRobert Mustacchi #endif
596*6716431bSRobert Mustacchi usberr:
597*6716431bSRobert Mustacchi 	DPRINTF(2, (CE_CONT, "!%s: %s: end (%s)",
598*6716431bSRobert Mustacchi 	    dp->name, __func__,
599*6716431bSRobert Mustacchi 	    err, err == USB_SUCCESS ? "success" : "error"));
600*6716431bSRobert Mustacchi 	return (err);
601*6716431bSRobert Mustacchi }
602*6716431bSRobert Mustacchi 
603*6716431bSRobert Mustacchi static int
axf_set_media(struct usbgem_dev * dp)604*6716431bSRobert Mustacchi axf_set_media(struct usbgem_dev *dp)
605*6716431bSRobert Mustacchi {
606*6716431bSRobert Mustacchi 	uint8_t	val8;
607*6716431bSRobert Mustacchi 	uint8_t	gpio;
608*6716431bSRobert Mustacchi 	uint8_t	gpio_old;
609*6716431bSRobert Mustacchi 	int	err = USB_SUCCESS;
610*6716431bSRobert Mustacchi 	uint16_t	msr;
611*6716431bSRobert Mustacchi 	struct axf_dev	*lp = dp->private;
612*6716431bSRobert Mustacchi 
613*6716431bSRobert Mustacchi 	IN(dp, VCMD_READ_GPIO, 0, 0, 1, &gpio, &err, usberr);
614*6716431bSRobert Mustacchi 
615*6716431bSRobert Mustacchi 	DPRINTF(0, (CE_CONT, "!%s: %s: called, gpio:%b",
616*6716431bSRobert Mustacchi 	    dp->name, __func__, gpio, GPIO_BITS));
617*6716431bSRobert Mustacchi 
618*6716431bSRobert Mustacchi 	msr = lp->msr;
619*6716431bSRobert Mustacchi 	gpio_old = gpio;
620*6716431bSRobert Mustacchi 	gpio = lp->chip->gpio_reset[0];
621*6716431bSRobert Mustacchi 
622*6716431bSRobert Mustacchi 	/* setup speed */
623*6716431bSRobert Mustacchi 	if (AX88172(dp)) {
624*6716431bSRobert Mustacchi 		/* EMPTY */
625*6716431bSRobert Mustacchi 	} else {
626*6716431bSRobert Mustacchi 		msr &= ~(MSR_PS | MSR_GM | MSR_ENCK);
627*6716431bSRobert Mustacchi 
628*6716431bSRobert Mustacchi 		switch (dp->speed) {
629*6716431bSRobert Mustacchi 		case USBGEM_SPD_1000:
630*6716431bSRobert Mustacchi 			msr |= MSR_GM | MSR_ENCK;
631*6716431bSRobert Mustacchi 			break;
632*6716431bSRobert Mustacchi 
633*6716431bSRobert Mustacchi 		case USBGEM_SPD_100:
634*6716431bSRobert Mustacchi 			msr |= MSR_PS;
635*6716431bSRobert Mustacchi 			break;
636*6716431bSRobert Mustacchi 
637*6716431bSRobert Mustacchi 		case USBGEM_SPD_10:
638*6716431bSRobert Mustacchi 			break;
639*6716431bSRobert Mustacchi 		}
640*6716431bSRobert Mustacchi 	}
641*6716431bSRobert Mustacchi 	gpio |= lp->chip->gpio_speed[dp->speed == USBGEM_SPD_100 ? 1 : 0];
642*6716431bSRobert Mustacchi 
643*6716431bSRobert Mustacchi 	/* select duplex */
644*6716431bSRobert Mustacchi 	msr &= ~MSR_FDPX;
645*6716431bSRobert Mustacchi 	if (dp->full_duplex) {
646*6716431bSRobert Mustacchi 		msr |= MSR_FDPX;
647*6716431bSRobert Mustacchi 
648*6716431bSRobert Mustacchi 		/* select flow control */
649*6716431bSRobert Mustacchi 		if (AX88172(dp)) {
650*6716431bSRobert Mustacchi 			msr &= ~MSR_FCEN;
651*6716431bSRobert Mustacchi 			switch (dp->flow_control) {
652*6716431bSRobert Mustacchi 			case FLOW_CONTROL_TX_PAUSE:
653*6716431bSRobert Mustacchi 			case FLOW_CONTROL_SYMMETRIC:
654*6716431bSRobert Mustacchi 			case FLOW_CONTROL_RX_PAUSE:
655*6716431bSRobert Mustacchi 				msr |= MSR_FCEN;
656*6716431bSRobert Mustacchi 				break;
657*6716431bSRobert Mustacchi 			}
658*6716431bSRobert Mustacchi 		} else {
659*6716431bSRobert Mustacchi 			msr &= ~(MSR_RFC | MSR_TFC);
660*6716431bSRobert Mustacchi 			switch (dp->flow_control) {
661*6716431bSRobert Mustacchi 			case FLOW_CONTROL_TX_PAUSE:
662*6716431bSRobert Mustacchi 				msr |= MSR_TFC;
663*6716431bSRobert Mustacchi 				break;
664*6716431bSRobert Mustacchi 
665*6716431bSRobert Mustacchi 			case FLOW_CONTROL_SYMMETRIC:
666*6716431bSRobert Mustacchi 				msr |= MSR_TFC | MSR_RFC;
667*6716431bSRobert Mustacchi 				break;
668*6716431bSRobert Mustacchi 
669*6716431bSRobert Mustacchi 			case FLOW_CONTROL_RX_PAUSE:
670*6716431bSRobert Mustacchi 				msr |= MSR_RFC;
671*6716431bSRobert Mustacchi 				break;
672*6716431bSRobert Mustacchi 			}
673*6716431bSRobert Mustacchi 		}
674*6716431bSRobert Mustacchi 	}
675*6716431bSRobert Mustacchi 	gpio |= lp->chip->gpio_duplex[dp->full_duplex ? 1 : 0];
676*6716431bSRobert Mustacchi 
677*6716431bSRobert Mustacchi 	/* update medium status register */
678*6716431bSRobert Mustacchi 	lp->msr = msr;
679*6716431bSRobert Mustacchi 	OUT(dp, VCMD_WRITE_MEDIUM_STATUS, lp->msr, 0,
680*6716431bSRobert Mustacchi 	    0, NULL, &err, usberr);
681*6716431bSRobert Mustacchi 
682*6716431bSRobert Mustacchi 	if (gpio != gpio_old) {
683*6716431bSRobert Mustacchi 		/* LED control required for some products */
684*6716431bSRobert Mustacchi 		OUT(dp, VCMD_WRITE_GPIO,
685*6716431bSRobert Mustacchi 		    gpio, 0, 0, NULL, &err, usberr);
686*6716431bSRobert Mustacchi 	}
687*6716431bSRobert Mustacchi 
688*6716431bSRobert Mustacchi usberr:
689*6716431bSRobert Mustacchi 	DPRINTF(2, (CE_CONT, "!%s: %s: end (%s)",
690*6716431bSRobert Mustacchi 	    dp->name, __func__,
691*6716431bSRobert Mustacchi 	    err, err == USB_SUCCESS ? "success" : "error"));
692*6716431bSRobert Mustacchi 	return (err);
693*6716431bSRobert Mustacchi }
694*6716431bSRobert Mustacchi 
695*6716431bSRobert Mustacchi #define	FILL_PKT_HEADER(bp, len)	{	\
696*6716431bSRobert Mustacchi 	(bp)[0] = (uint8_t)(len);	\
697*6716431bSRobert Mustacchi 	(bp)[1] = (uint8_t)((len) >> 8);	\
698*6716431bSRobert Mustacchi 	(bp)[2] = (uint8_t)(~(len));	\
699*6716431bSRobert Mustacchi 	(bp)[3] = (uint8_t)((~(len)) >> 8);	\
700*6716431bSRobert Mustacchi }
701*6716431bSRobert Mustacchi 
702*6716431bSRobert Mustacchi #define	PKT_HEADER_SIZE	4
703*6716431bSRobert Mustacchi 
704*6716431bSRobert Mustacchi /*
705*6716431bSRobert Mustacchi  * send/receive packet check
706*6716431bSRobert Mustacchi  */
707*6716431bSRobert Mustacchi static mblk_t *
axf_tx_make_packet(struct usbgem_dev * dp,mblk_t * mp)708*6716431bSRobert Mustacchi axf_tx_make_packet(struct usbgem_dev *dp, mblk_t *mp)
709*6716431bSRobert Mustacchi {
710*6716431bSRobert Mustacchi 	int		n;
711*6716431bSRobert Mustacchi 	size_t		len;
712*6716431bSRobert Mustacchi 	size_t		pkt_size;
713*6716431bSRobert Mustacchi 	mblk_t		*new;
714*6716431bSRobert Mustacchi 	mblk_t		*tp;
715*6716431bSRobert Mustacchi 	uint8_t		*bp;
716*6716431bSRobert Mustacchi 	uint8_t		*last_pos;
717*6716431bSRobert Mustacchi 	uint_t		align_mask;
718*6716431bSRobert Mustacchi 	size_t		header_size;
719*6716431bSRobert Mustacchi 	int		pad_size;
720*6716431bSRobert Mustacchi 
721*6716431bSRobert Mustacchi 	len = msgdsize(mp);
722*6716431bSRobert Mustacchi 
723*6716431bSRobert Mustacchi 	if (AX88172(dp)) {
724*6716431bSRobert Mustacchi #ifdef notdef
725*6716431bSRobert Mustacchi 		align_mask = 63;
726*6716431bSRobert Mustacchi #else
727*6716431bSRobert Mustacchi 		align_mask = 511;
728*6716431bSRobert Mustacchi #endif
729*6716431bSRobert Mustacchi 		header_size = 0;
730*6716431bSRobert Mustacchi 
731*6716431bSRobert Mustacchi 		if (len >= ETHERMIN && mp->b_cont == NULL &&
732*6716431bSRobert Mustacchi 		    (len & align_mask) != 0) {
733*6716431bSRobert Mustacchi 			/* use the mp "as is" */
734*6716431bSRobert Mustacchi 			return (mp);
735*6716431bSRobert Mustacchi 		}
736*6716431bSRobert Mustacchi 	} else {
737*6716431bSRobert Mustacchi 		align_mask = 511;
738*6716431bSRobert Mustacchi 		header_size = PKT_HEADER_SIZE;
739*6716431bSRobert Mustacchi 	}
740*6716431bSRobert Mustacchi 
741*6716431bSRobert Mustacchi 	/*
742*6716431bSRobert Mustacchi 	 * re-allocate the mp
743*6716431bSRobert Mustacchi 	 */
744*6716431bSRobert Mustacchi 	/* minimum ethernet packet size of ETHERMIN */
745*6716431bSRobert Mustacchi 	pkt_size = max(len, ETHERMIN);
746*6716431bSRobert Mustacchi 
747*6716431bSRobert Mustacchi 	if (((pkt_size + header_size) & align_mask) == 0) {
748*6716431bSRobert Mustacchi 		/* padding is required in usb communication */
749*6716431bSRobert Mustacchi 		pad_size = PKT_HEADER_SIZE;
750*6716431bSRobert Mustacchi 	} else {
751*6716431bSRobert Mustacchi 		pad_size = 0;
752*6716431bSRobert Mustacchi 	}
753*6716431bSRobert Mustacchi 
754*6716431bSRobert Mustacchi 	if ((new = allocb(header_size + pkt_size + pad_size, 0)) == NULL) {
755*6716431bSRobert Mustacchi 		return (NULL);
756*6716431bSRobert Mustacchi 	}
757*6716431bSRobert Mustacchi 
758*6716431bSRobert Mustacchi 	bp = new->b_rptr;
759*6716431bSRobert Mustacchi 	if (header_size) {
760*6716431bSRobert Mustacchi 		uint16_t	tmp;
761*6716431bSRobert Mustacchi 
762*6716431bSRobert Mustacchi 		/* add a header */
763*6716431bSRobert Mustacchi 		tmp = (uint16_t)pkt_size;
764*6716431bSRobert Mustacchi 		FILL_PKT_HEADER(bp, tmp);
765*6716431bSRobert Mustacchi 		bp += header_size;
766*6716431bSRobert Mustacchi 	}
767*6716431bSRobert Mustacchi 
768*6716431bSRobert Mustacchi 	/* copy contents of the buffer */
769*6716431bSRobert Mustacchi 	for (tp = mp; tp; tp = tp->b_cont) {
770*6716431bSRobert Mustacchi 		n = (uintptr_t)tp->b_wptr - (uintptr_t)tp->b_rptr;
771*6716431bSRobert Mustacchi 		bcopy(tp->b_rptr, bp, n);
772*6716431bSRobert Mustacchi 		bp += n;
773*6716431bSRobert Mustacchi 	}
774*6716431bSRobert Mustacchi 
775*6716431bSRobert Mustacchi 	/* add pads for ethernet packets */
776*6716431bSRobert Mustacchi 	last_pos = new->b_rptr + header_size + pkt_size;
777*6716431bSRobert Mustacchi 	while (bp < last_pos) {
778*6716431bSRobert Mustacchi 		*bp++ = 0;
779*6716431bSRobert Mustacchi 	}
780*6716431bSRobert Mustacchi 
781*6716431bSRobert Mustacchi 	/* add a zero-length pad segment for usb communications */