2 * axf_usbgem.c : ASIX AX88172/772 USB to Fast Ethernet Driver for Solaris
4 * Copyright (c) 2004-2012 Masayuki Murayama. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * 3. Neither the name of the author nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34 #pragma ident "@(#)axf_usbgem.c 1.3 12/02/09"
42 * handle RXMODE_ENABLE in set_rx_filter()
44 /* ======================================================= */
47 * Solaris system header files and macros
50 /* minimum kernel headers for drivers */
51 #include <sys/types.h>
53 #include <sys/debug.h>
55 #include <sys/modctl.h>
56 #include <sys/errno.h>
58 #include <sys/sunddi.h>
59 #include <sys/byteorder.h>
62 #include <sys/ethernet.h>
64 /* interface card depend stuff */
65 #include <sys/stropts.h>
66 #include <sys/stream.h>
67 #include <sys/strlog.h>
68 #include <sys/usb/usba.h>
72 #include "usbgem_mii.h"
73 #include "ax88172reg.h"
75 char ident
[] = "ax88x72 usbnic driver v" VERSION
;
80 #define CHECK_AND_JUMP(err, label) if (err != USB_SUCCESS) goto label
81 #define LE16P(p) ((((uint8_t *)(p))[1] << 8) | ((uint8_t *)(p))[0])
84 (((struct axf_dev *)(dp)->private)->chip->type == CHIP_TYPE_AX88172)
87 (((struct axf_dev *)(dp)->private)->chip->type == CHIP_TYPE_AX88772)
93 static int axf_debug
= DEBUG_LEVEL
;
94 #define DPRINTF(n, args) if (axf_debug > (n)) cmn_err args
96 #define DPRINTF(n, args)
100 * Our configration for ax88172
103 #define ONESEC (drv_usectohz(1*1000000))
110 * Local device definitions
113 uint16_t vid
; /* usb vendor id */
114 uint16_t pid
; /* usb product id */
116 uint8_t gpio_reset
[2];
117 uint8_t gpio_speed
[2];
118 uint8_t gpio_duplex
[2];
120 #define CHIP_TYPE_AX88172 0
121 #define CHIP_TYPE_AX88772 1
122 #define CHIP_TYPE_AX88178 2
125 #define GPIO_DEFAULT {0x00, 0x15}, {0, 0}, {0, 0}
126 struct chip_info chiptbl_88x7x
[] = {
129 /* Planex UE2-100TX, Hawking UF200, TrendNet TU2-ET100 */
130 0x07b8, 0x420a, CHIP_TYPE_AX88172
,
133 * the default setting covers below:
134 * gpio bit2 has to be 0 and gpio bit0 has to be 1
137 {GPIO_EN1
, GPIO_DATA1
| GPIO_EN1
},
139 "Planex UE2-100TX", /* tested */
142 0x2001, 0x1a00, CHIP_TYPE_AX88172
,
143 {0x9f, 0x9e}, {0, 0}, {0, 0},
144 "D-Link dube100", /* XXX */
147 0x077b, 0x2226, CHIP_TYPE_AX88172
,
152 0x0846, 0x1040, CHIP_TYPE_AX88172
,
157 0x0b95, 0x1720, CHIP_TYPE_AX88172
,
159 "Intellinet, ST Lab USB Ethernet",
162 0x08dd, 0x90ff, CHIP_TYPE_AX88172
,
164 "Billionton Systems, USB2AR",
167 0x0557, 0x2009, CHIP_TYPE_AX88172
,
172 0x0411, 0x003d, CHIP_TYPE_AX88172
,
174 "Buffalo LUA-U2-KTX",
177 0x6189, 0x182d, CHIP_TYPE_AX88172
,
179 "Sitecom LN-029 USB 2.0 10/100 Ethernet adapter",
182 0x07aa, 0x0017, CHIP_TYPE_AX88172
,
184 "corega FEther USB2-TX",
187 0x1189, 0x0893, CHIP_TYPE_AX88172
,
189 "Surecom EP-1427X-2",
192 0x1631, 0x6200, CHIP_TYPE_AX88172
,
194 "goodway corp usb gwusb2e",
196 /* AX88772 and AX88178 */
198 0x13b1, 0x0018, CHIP_TYPE_AX88772
,
199 {0, 0}, {0, 0}, {0, 0},
200 "Linksys USB200M rev.2",
203 0x1557, 0x7720, CHIP_TYPE_AX88772
,
204 {0, 0}, {0, 0}, {0, 0},
205 "0Q0 cable ethernet",
208 0x07d1, 0x3c05, CHIP_TYPE_AX88772
,
209 {0, 0}, {0, 0}, {0, 0},
210 "DLink DUB E100 ver B1",
213 0x2001, 0x3c05, CHIP_TYPE_AX88772
,
214 {0, 0}, {0, 0}, {0, 0},
215 "DLink DUB E100 ver B1(2)",
218 0x05ac, 0x1402, CHIP_TYPE_AX88772
,
219 {0, 0}, {0, 0}, {0, 0},
220 "Apple Ethernet USB Adapter",
223 0x1737, 0x0039, CHIP_TYPE_AX88178
,
224 {0, 0}, {0, 0}, {0, 0},
228 0x0411, 0x006e, CHIP_TYPE_AX88178
,
229 {0, 0}, {0, 0}, {0, 0},
230 "Buffalo LUA-U2-KGT/LUA-U2-GT",
233 0x04bb, 0x0930, CHIP_TYPE_AX88178
,
234 {0, 0}, {0, 0}, {0, 0},
238 0x050d, 0x5055, CHIP_TYPE_AX88178
,
239 {0, 0}, {0, 0}, {0, 0},
243 /* generic ax88772 must be the last entry */
244 /* planex UE-200TX-G */
245 0x0b95, 0x7720, CHIP_TYPE_AX88772
,
246 {0, 0}, {0, 0}, {0, 0},
247 "ASIX AX88772/AX88178", /* tested */
251 #define CHIPTABLESIZE (sizeof (chiptbl_88x7x) / sizeof (struct chip_info))
255 * Misc HW information
257 struct chip_info
*chip
;
262 uint8_t last_link_state
;
263 boolean_t phy_has_reset
;
271 static uint16_t axf_mii_read(struct usbgem_dev
*, uint_t
, int *errp
);
272 static void axf_mii_write(struct usbgem_dev
*, uint_t
, uint16_t, int *errp
);
275 static int axf_reset_chip(struct usbgem_dev
*);
276 static int axf_init_chip(struct usbgem_dev
*);
277 static int axf_start_chip(struct usbgem_dev
*);
278 static int axf_stop_chip(struct usbgem_dev
*);
279 static int axf_set_media(struct usbgem_dev
*);
280 static int axf_set_rx_filter(struct usbgem_dev
*);
281 static int axf_get_stats(struct usbgem_dev
*);
282 static void axf_interrupt(struct usbgem_dev
*, mblk_t
*);
284 /* packet operations */
285 static mblk_t
*axf_tx_make_packet(struct usbgem_dev
*, mblk_t
*);
286 static mblk_t
*axf_rx_make_packet(struct usbgem_dev
*, mblk_t
*);
288 /* =============================================================== */
292 /* =============================================================== */
294 #define OUT(dp, req, val, ix, len, buf, errp, label) \
295 if ((*(errp) = usbgem_ctrl_out((dp), \
296 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \
297 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
298 /* bRequest */ (req), \
299 /* wValue */ (val), \
301 /* wLength */ (len), \
303 /* size */ (len))) != USB_SUCCESS) goto label
305 #define IN(dp, req, val, ix, len, buf, errp, label) \
306 if ((*(errp) = usbgem_ctrl_in((dp), \
307 /* bmRequestType */ USB_DEV_REQ_DEV_TO_HOST \
308 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
309 /* bRequest */ (req), \
310 /* wValue */ (val), \
312 /* wLength */ (len), \
313 /* valuep */ (buf), \
314 /* size */ (len))) != USB_SUCCESS) goto label
317 /* =============================================================== */
319 * Hardware manupilation
321 /* =============================================================== */
323 axf_reset_phy(struct usbgem_dev
*dp
)
328 struct axf_dev
*lp
= dp
->private;
330 DPRINTF(2, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
333 delay(drv_usectohz(5000));
334 IN(dp
, VCMD_READ_GPIO
, 0, 0, 1, &val8
, &err
, usberr
);
336 DPRINTF(0, (CE_CONT
, "!%s: %s: gpio 0x%b",
337 dp
->name
, __func__
, val8
, GPIO_BITS
));
340 val8
= lp
->chip
->gpio_reset
[1]
341 | lp
->chip
->gpio_speed
[dp
->speed
]
342 | lp
->chip
->gpio_duplex
[dp
->full_duplex
];
344 OUT(dp
, VCMD_WRITE_GPIO
,
345 val8
, 0, 0, NULL
, &err
, usberr
);
346 delay(drv_usectohz(5000));
348 val8
= lp
->chip
->gpio_reset
[0]
349 | lp
->chip
->gpio_speed
[dp
->speed
]
350 | lp
->chip
->gpio_duplex
[dp
->full_duplex
];
352 OUT(dp
, VCMD_WRITE_GPIO
,
353 val8
, 0, 0, NULL
, &err
, usberr
);
354 delay(drv_usectohz(5000));
356 lp
->gpio
= GPIO_RSE
| GPIO_DATA2
| GPIO_EN2
;
357 OUT(dp
, VCMD_WRITE_GPIO
, lp
->gpio
, 0,
358 0, NULL
, &err
, usberr
);
361 OUT(dp
, VCMD_WRITE_PHY_SELECT_88772
,
362 dp
->mii_phy_addr
== 16 ? 1 : 0, 0, 0, NULL
, &err
, usberr
);
364 OUT(dp
, VCMD_SOFTWARE_RESET_88772
,
365 SWRST_IPPD
| SWRST_PRL
, 0, 0, NULL
, &err
, usberr
);
366 delay(drv_usectohz(150*1000));
367 OUT(dp
, VCMD_SOFTWARE_RESET_88772
,
368 0, 0, 0, NULL
, &err
, usberr
);
370 OUT(dp
, VCMD_SOFTWARE_RESET_88772
,
371 dp
->mii_phy_addr
== 16 ? SWRST_IPRL
: SWRST_PRTE
,
372 0, 0, NULL
, &err
, usberr
);
373 delay(drv_usectohz(150*1000));
377 return (USB_SUCCESS
);
380 return (USB_FAILURE
);
384 axf_reset_chip(struct usbgem_dev
*dp
)
386 int err
= USB_SUCCESS
;
389 /* there are no ways to reset nic */
390 return (USB_SUCCESS
);
393 OUT(dp
, VCMD_SOFTWARE_RESET_88772
,
394 SWRST_RR
| SWRST_RT
, 0, 0, NULL
, &err
, usberr
);
395 OUT(dp
, VCMD_SOFTWARE_RESET_88772
,
396 0, 0, 0, NULL
, &err
, usberr
);
406 axf_init_chip(struct usbgem_dev
*dp
)
410 int err
= USB_SUCCESS
;
414 struct axf_dev
*lp
= dp
->private;
416 DPRINTF(2, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
418 /* rx conrol register: read default value */
420 /* clear rx control */
421 OUT(dp
, VCMD_WRITE_RXCTRL
, 0, 0, 0, NULL
, &err
, usberr
);
424 IN(dp
, VCMD_READ_RXCTRL
, 0, 0, 2, buf
, &err
, usberr
);
425 lp
->rcr
= LE16P(buf
);
426 DPRINTF(0, (CE_CONT
, "!%s: %s: rcr(default):%b",
427 dp
->name
, __func__
, lp
->rcr
, RCR_BITS
));
431 /* Media status register */
439 lp
->msr
= MSR_RE
| MSR_TXABT
;
441 DPRINTF(0, (CE_CONT
, "!%s: %s: msr:%b",
442 dp
->name
, __func__
, lp
->msr
, MSR_BITS
));
443 err
= axf_set_media(dp
);
444 CHECK_AND_JUMP(err
, usberr
);
446 /* write IPG0-2 registers */
448 OUT(dp
, VCMD_WRITE_IPG
, lp
->ipg
[0], 0, 0, NULL
, &err
, usberr
);
449 OUT(dp
, VCMD_WRITE_IPG1
, lp
->ipg
[1], 0, 0, NULL
, &err
, usberr
);
450 OUT(dp
, VCMD_WRITE_IPG2
, lp
->ipg
[2], 0, 0, NULL
, &err
, usberr
);
454 #ifdef ENABLE_RX_IN_INIT_CHIP
457 OUT(dp
, VCMD_WRITE_RXCTRL
, lp
->rcr
, 0, 0, NULL
, &err
, usberr
);
460 DPRINTF(2, (CE_CONT
, "!%s: %s: end (%s)",
462 err
, err
== USB_SUCCESS
? "success" : "error"));
467 axf_start_chip(struct usbgem_dev
*dp
)
469 int err
= USB_SUCCESS
;
470 struct axf_dev
*lp
= dp
->private;
471 #ifndef ENABLE_RX_IN_INIT_CHIP
474 OUT(dp
, VCMD_WRITE_RXCTRL
, lp
->rcr
, 0, 0, NULL
, &err
, usberr
);
477 DPRINTF(2, (CE_CONT
, "!%s: %s: end (%s)",
479 err
, err
== USB_SUCCESS
? "success" : "error"));
485 axf_stop_chip(struct usbgem_dev
*dp
)
487 int err
= USB_SUCCESS
;
488 struct axf_dev
*lp
= dp
->private;
492 OUT(dp
, VCMD_WRITE_RXCTRL
, lp
->rcr
, 0, 0, NULL
, &err
, usberr
);
495 * Restore factory mac address
496 * if we have changed current mac address
499 bcmp(dp
->dev_addr
.ether_addr_octet
,
500 dp
->cur_addr
.ether_addr_octet
,
502 OUT(dp
, VCMD_WRITE_NODE_ID_88772
, 0, 0,
503 ETHERADDRL
, dp
->cur_addr
.ether_addr_octet
, &err
, usberr
);
506 return (axf_reset_chip(dp
));
510 axf_get_stats(struct usbgem_dev
*dp
)
513 return (USB_SUCCESS
);
517 axf_mcast_hash(struct usbgem_dev
*dp
, const uint8_t *addr
)
519 return (usbgem_ether_crc_be(addr
) >> (32 - 6));
523 axf_set_rx_filter(struct usbgem_dev
*dp
)
530 int err
= USB_SUCCESS
;
531 struct axf_dev
*lp
= dp
->private;
533 DPRINTF(2, (CE_CONT
, "!%s: %s: called, rxmode:%x",
534 dp
->name
, __func__
, dp
->rxmode
));
536 if (lp
->rcr
& RCR_SO
) {
537 /* set promiscuous mode before changing it. */
538 OUT(dp
, VCMD_WRITE_RXCTRL
,
539 lp
->rcr
| RCR_PRO
, 0, 0, NULL
, &err
, usberr
);
542 lp
->rcr
&= ~(RCR_AP_88772
| RCR_AM
| RCR_SEP
| RCR_AMALL
| RCR_PRO
);
543 mode
= RCR_AB
; /* accept broadcast packets */
545 bzero(mhash
, sizeof (mhash
));
547 if (dp
->rxmode
& RXMODE_PROMISC
) {
548 /* promiscious mode implies all multicast and all physical */
550 } else if ((dp
->rxmode
& RXMODE_ALLMULTI
) || dp
->mc_count
> 32) {
551 /* accept all multicast packets */
553 } else if (dp
->mc_count
> 0) {
555 * make hash table to select interresting
556 * multicast address only.
559 for (i
= 0; i
< dp
->mc_count
; i
++) {
560 h
= dp
->mc_list
[i
].hash
;
561 mhash
[h
/ 8] |= 1 << (h
% 8);
565 if (bcmp(dp
->dev_addr
.ether_addr_octet
,
566 dp
->cur_addr
.ether_addr_octet
, ETHERADDRL
) != 0) {
568 * we use promiscious mode instead of changing the
569 * mac address in ax88172
574 OUT(dp
, VCMD_WRITE_NODE_ID_88772
, 0, 0,
575 ETHERADDRL
, dp
->cur_addr
.ether_addr_octet
, &err
, usberr
);
579 /* set multicast hash table */
581 /* need to set up multicast hash table */
582 OUT(dp
, VCMD_WRITE_MCAST_FILTER
, 0, 0,
583 sizeof (mhash
), mhash
, &err
, usberr
);
587 OUT(dp
, VCMD_WRITE_RXCTRL
, lp
->rcr
, 0,
588 0, NULL
, &err
, usberr
);
591 /* verify rxctrl reg */
592 IN(dp
, VCMD_READ_RXCTRL
, 0, 0, 2, buf
, &err
, usberr
);
593 cmn_err(CE_CONT
, "!%s: %s: rcr:%b returned",
594 dp
->name
, __func__
, LE16P(buf
), RCR_BITS
);
597 DPRINTF(2, (CE_CONT
, "!%s: %s: end (%s)",
599 err
, err
== USB_SUCCESS
? "success" : "error"));
604 axf_set_media(struct usbgem_dev
*dp
)
609 int err
= USB_SUCCESS
;
611 struct axf_dev
*lp
= dp
->private;
613 IN(dp
, VCMD_READ_GPIO
, 0, 0, 1, &gpio
, &err
, usberr
);
615 DPRINTF(0, (CE_CONT
, "!%s: %s: called, gpio:%b",
616 dp
->name
, __func__
, gpio
, GPIO_BITS
));
620 gpio
= lp
->chip
->gpio_reset
[0];
626 msr
&= ~(MSR_PS
| MSR_GM
| MSR_ENCK
);
629 case USBGEM_SPD_1000
:
630 msr
|= MSR_GM
| MSR_ENCK
;
641 gpio
|= lp
->chip
->gpio_speed
[dp
->speed
== USBGEM_SPD_100
? 1 : 0];
645 if (dp
->full_duplex
) {
648 /* select flow control */
651 switch (dp
->flow_control
) {
652 case FLOW_CONTROL_TX_PAUSE
:
653 case FLOW_CONTROL_SYMMETRIC
:
654 case FLOW_CONTROL_RX_PAUSE
:
659 msr
&= ~(MSR_RFC
| MSR_TFC
);
660 switch (dp
->flow_control
) {
661 case FLOW_CONTROL_TX_PAUSE
:
665 case FLOW_CONTROL_SYMMETRIC
:
666 msr
|= MSR_TFC
| MSR_RFC
;
669 case FLOW_CONTROL_RX_PAUSE
:
675 gpio
|= lp
->chip
->gpio_duplex
[dp
->full_duplex
? 1 : 0];
677 /* update medium status register */
679 OUT(dp
, VCMD_WRITE_MEDIUM_STATUS
, lp
->msr
, 0,
680 0, NULL
, &err
, usberr
);
682 if (gpio
!= gpio_old
) {
683 /* LED control required for some products */
684 OUT(dp
, VCMD_WRITE_GPIO
,
685 gpio
, 0, 0, NULL
, &err
, usberr
);
689 DPRINTF(2, (CE_CONT
, "!%s: %s: end (%s)",
691 err
, err
== USB_SUCCESS
? "success" : "error"));
695 #define FILL_PKT_HEADER(bp, len) { \
696 (bp)[0] = (uint8_t)(len); \
697 (bp)[1] = (uint8_t)((len) >> 8); \
698 (bp)[2] = (uint8_t)(~(len)); \
699 (bp)[3] = (uint8_t)((~(len)) >> 8); \
702 #define PKT_HEADER_SIZE 4
705 * send/receive packet check
708 axf_tx_make_packet(struct usbgem_dev
*dp
, mblk_t
*mp
)
731 if (len
>= ETHERMIN
&& mp
->b_cont
== NULL
&&
732 (len
& align_mask
) != 0) {
733 /* use the mp "as is" */
738 header_size
= PKT_HEADER_SIZE
;
744 /* minimum ethernet packet size of ETHERMIN */
745 pkt_size
= max(len
, ETHERMIN
);
747 if (((pkt_size
+ header_size
) & align_mask
) == 0) {
748 /* padding is required in usb communication */
749 pad_size
= PKT_HEADER_SIZE
;
754 if ((new = allocb(header_size
+ pkt_size
+ pad_size
, 0)) == NULL
) {
763 tmp
= (uint16_t)pkt_size
;
764 FILL_PKT_HEADER(bp
, tmp
);
768 /* copy contents of the buffer */
769 for (tp
= mp
; tp
; tp
= tp
->b_cont
) {
770 n
= (uintptr_t)tp
->b_wptr
- (uintptr_t)tp
->b_rptr
;
771 bcopy(tp
->b_rptr
, bp
, n
);
775 /* add pads for ethernet packets */
776 last_pos
= new->b_rptr
+ header_size
+ pkt_size
;
777 while (bp
< last_pos
) {
781 /* add a zero-length pad segment for usb communications */
783 /* add a dummy header for zero-length packet */
784 FILL_PKT_HEADER(bp
, 0);
788 /* close the payload of the packet */
795 axf_dump_packet(struct usbgem_dev
*dp
, uint8_t *bp
, int n
)
799 for (i
= 0; i
< n
; i
+= 8, bp
+= 8) {
800 cmn_err(CE_CONT
, "%02x %02x %02x %02x %02x %02x %02x %02x",
801 bp
[0], bp
[1], bp
[2], bp
[3], bp
[4], bp
[5], bp
[6], bp
[7]);
806 axf_rx_make_packet(struct usbgem_dev
*dp
, mblk_t
*mp
)
816 rest
= (uintptr_t)tp
->b_wptr
- (uintptr_t)tp
->b_rptr
;
818 if (rest
<= PKT_HEADER_SIZE
) {
820 * the usb bulk-in frame doesn't include any valid
830 /* analyse the header of the received usb frame */
831 len
= LE16P(tp
->b_rptr
+ 0);
832 cksum
= LE16P(tp
->b_rptr
+ 2);
834 /* test if the header is valid */
835 if (len
+ cksum
!= 0xffff) {
836 /* discard whole the packet */
838 "!%s: %s: corrupted header:%04x %04x",
839 dp
->name
, __func__
, len
, cksum
);
843 if (len
< ETHERMIN
|| len
> ETHERMAX
) {
845 "!%s: %s: incorrect pktsize:%d",
846 dp
->name
, __func__
, len
);
849 /* extract a ethernet packet from the bulk-in frame */
850 tp
->b_rptr
+= PKT_HEADER_SIZE
;
851 tp
->b_wptr
= tp
->b_rptr
+ len
;
855 * skip a tailing pad byte if the packet
860 rest
-= len
+ PKT_HEADER_SIZE
;
862 if (rest
<= PKT_HEADER_SIZE
) {
863 /* no more vaild ethernet packets */
868 axf_dump_packet(dp
, tp
->b_wptr
, 18);
870 /* allocate a mblk_t header for the next ethernet packet */
871 tp
->b_next
= dupb(mp
);
872 tp
->b_next
->b_rptr
= tp
->b_rptr
+ len
;
883 axf_mii_read(struct usbgem_dev
*dp
, uint_t index
, int *errp
)
888 DPRINTF(4, (CE_CONT
, "!%s: %s: called, ix:%d",
889 dp
->name
, __func__
, index
));
891 /* switch to software MII operation mode */
892 OUT(dp
, VCMD_SOFTWARE_MII_OP
, 0, 0, 0, NULL
, errp
, usberr
);
894 /* Read MII register */
895 IN(dp
, VCMD_READ_MII_REG
, dp
->mii_phy_addr
, index
,
896 2, buf
, errp
, usberr
);
898 /* switch to hardware MII operation mode */
899 OUT(dp
, VCMD_HARDWARE_MII_OP
, 0, 0, 0, NULL
, errp
, usberr
);
905 "!%s: %s: usberr(%d) detected", dp
->name
, __func__
, *errp
);
910 axf_mii_write(struct usbgem_dev
*dp
, uint_t index
, uint16_t val
, int *errp
)
914 DPRINTF(4, (CE_CONT
, "!%s: %s called, reg:%x val:%x",
915 dp
->name
, __func__
, index
, val
));
917 /* switch software MII operation mode */
918 OUT(dp
, VCMD_SOFTWARE_MII_OP
, 0, 0, 0, NULL
, errp
, usberr
);
920 /* Write to the specified MII register */
921 buf
[0] = (uint8_t)val
;
922 buf
[1] = (uint8_t)(val
>> 8);
923 OUT(dp
, VCMD_WRITE_MII_REG
, dp
->mii_phy_addr
, index
,
924 2, buf
, errp
, usberr
);
926 /* switch to hardware MII operation mode */
927 OUT(dp
, VCMD_HARDWARE_MII_OP
, 0, 0, 0, NULL
, errp
, usberr
);
934 axf_interrupt(struct usbgem_dev
*dp
, mblk_t
*mp
)
937 struct axf_dev
*lp
= dp
->private;
942 "!%s: %s: size:%d, %02x %02x %02x %02x %02x %02x %02x %02x",
943 dp
->name
, __func__
, mp
->b_wptr
- mp
->b_rptr
,
944 bp
[0], bp
[1], bp
[2], bp
[3], bp
[4], bp
[5], bp
[6], bp
[7]));
946 if (lp
->last_link_state
^ bp
[2]) {
947 usbgem_mii_update_link(dp
);
950 lp
->last_link_state
= bp
[2];
953 /* ======================================================== */
955 * OS depend (device driver DKI) routine
957 /* ======================================================== */
960 axf_eeprom_dump(struct usbgem_dev
*dp
, int size
)
964 uint8_t w0
[2], w1
[2], w2
[2], w3
[2];
966 cmn_err(CE_CONT
, "!%s: eeprom dump:", dp
->name
);
970 for (i
= 0; i
< size
; i
+= 4) {
971 IN(dp
, VCMD_READ_SROM
, i
+ 0, 0, 2, w0
, &err
, usberr
);
972 IN(dp
, VCMD_READ_SROM
, i
+ 1, 0, 2, w1
, &err
, usberr
);
973 IN(dp
, VCMD_READ_SROM
, i
+ 2, 0, 2, w2
, &err
, usberr
);
974 IN(dp
, VCMD_READ_SROM
, i
+ 3, 0, 2, w3
, &err
, usberr
);
975 cmn_err(CE_CONT
, "!0x%02x: 0x%04x 0x%04x 0x%04x 0x%04x",
977 (w0
[1] << 8) | w0
[0],
978 (w1
[1] << 8) | w1
[0],
979 (w2
[1] << 8) | w2
[0],
980 (w3
[1] << 8) | w3
[0]);
988 axf_attach_chip(struct usbgem_dev
*dp
)
994 #ifdef CONFIG_FULLSIZE_VLAN
995 uint8_t maxpktsize
[2];
996 uint16_t vlan_pktsize
;
1001 struct axf_dev
*lp
= dp
->private;
1003 DPRINTF(0, (CE_CONT
, "!%s: %s enter", dp
->name
, __func__
));
1007 * mac address in EEPROM has loaded to ID registers.
1009 vcmd
= AX88172(dp
) ? VCMD_READ_NODE_ID
: VCMD_READ_NODE_ID_88772
;
1011 ETHERADDRL
, dp
->dev_addr
.ether_addr_octet
, &err
, usberr
);
1021 * We cannot scan phy because the nic returns undefined
1022 * value, i.e. remained garbage, when MII phy is not at the
1026 if (lp
->chip
->vid
== 0x07b8 && lp
->chip
->pid
== 0x420a) {
1028 * restore the original phy address of brain
1029 * damaged Planex UE2-100TX
1031 OUT(dp
, VCMD_WRITE_SROM_ENABLE
, 0, 0, 0, NULL
, &err
, usberr
);
1032 OUT(dp
, VCMD_WRITE_SROM
, 0x11, 0xe004, 0, NULL
, &err
, usberr
);
1033 OUT(dp
, VCMD_WRITE_SROM_DISABLE
, 0, 0, 0, NULL
, &err
, usberr
);
1037 IN(dp
, VCMD_READ_PHY_IDS
, 0, 0, 2, &phys
, &err
, usberr
);
1038 dp
->mii_phy_addr
= phys
[1];
1039 DPRINTF(0, (CE_CONT
, "!%s: %s: phys_addr:%d %d",
1040 dp
->name
, __func__
, phys
[0], phys
[1]));
1042 /* use built-in phy */
1043 dp
->mii_phy_addr
= 0x10;
1046 dp
->misc_flag
|= USBGEM_VLAN
;
1047 #ifdef CONFIG_FULLSIZE_VLAN
1048 if (AX88172(dp
) || AX88772(dp
)) {
1049 /* check max packet size in srom */
1050 IN(dp
, VCMD_READ_SROM
, 0x10, 0, 2, maxpktsize
, &err
, usberr
);
1051 vlan_pktsize
= ETHERMAX
+ ETHERFCSL
+ 4 /* VTAG_SIZE */;
1053 if (LE16P(maxpktsize
) < vlan_pktsize
) {
1055 "!%s: %s: max packet size in srom is too small, "
1056 "changing %d -> %d, do power cycle for the device",
1058 LE16P(maxpktsize
), vlan_pktsize
);
1059 OUT(dp
, VCMD_WRITE_SROM_ENABLE
,
1060 0, 0, 0, NULL
, &err
, usberr
);
1061 OUT(dp
, VCMD_WRITE_SROM
, 0x10,
1062 vlan_pktsize
, 0, NULL
, &err
, usberr
);
1063 OUT(dp
, VCMD_WRITE_SROM_DISABLE
,
1064 0, 0, 0, NULL
, &err
, usberr
);
1066 /* need to power off the device */
1072 IN(dp
, VCMD_READ_GPIO
, 0, 0, 1, &val8
, &err
, usberr
);
1074 "!%s: %s: ipg 0x%02x 0x%02x 0x%02x, gpio 0x%b",
1075 dp
->name
, __func__
, lp
->ipg
[0], lp
->ipg
[1], lp
->ipg
[2],
1078 /* fix rx buffer size */
1080 dp
->rx_buf_len
= 2048;
1084 axf_eeprom_dump(dp
, 0x20);
1089 cmn_err(CE_WARN
, "%s: %s: usb error detected (%d)",
1090 dp
->name
, __func__
, err
);
1091 return (USB_FAILURE
);
1095 axf_scan_phy(struct usbgem_dev
*dp
)
1101 struct axf_dev
*lp
= dp
->private;
1103 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
1105 phy_addr_saved
= dp
->mii_phy_addr
;
1107 /* special probe routine for unreliable MII addr */
1109 (MII_ABILITY_100BASE_TX_FD | \
1110 MII_ABILITY_100BASE_TX | \
1111 MII_ABILITY_10BASE_T_FD | \
1112 MII_ABILITY_10BASE_T)
1114 for (i
= 0; i
< 32; i
++) {
1115 dp
->mii_phy_addr
= i
;
1116 axf_mii_write(dp
, MII_AN_ADVERT
, 0, &err
);
1117 if (err
!= USBGEM_SUCCESS
) {
1120 val
= axf_mii_read(dp
, MII_AN_ADVERT
, &err
);
1121 if (err
!= USBGEM_SUCCESS
) {
1125 DPRINTF(0, (CE_CONT
, "!%s: %s: index:%d, val %b != 0",
1126 dp
->name
, __func__
, i
, val
, MII_ABILITY_BITS
));
1130 axf_mii_write(dp
, MII_AN_ADVERT
, PROBE_PAT
, &err
);
1131 if (err
!= USBGEM_SUCCESS
) {
1134 val
= axf_mii_read(dp
, MII_AN_ADVERT
, &err
);
1135 if (err
!= USBGEM_SUCCESS
) {
1138 if ((val
& MII_ABILITY_TECH
) != PROBE_PAT
) {
1139 DPRINTF(0, (CE_CONT
, "!%s: %s: "
1140 "index:%d, pat:%x != val:%b",
1141 dp
->name
, __func__
, i
,
1142 PROBE_PAT
, val
, MII_ABILITY_BITS
));
1147 dp
->mii_phy_addr
= phy_addr_saved
;
1152 cmn_err(CE_CONT
, "!%s: %s: no mii phy found",
1153 dp
->name
, __func__
);
1155 cmn_err(CE_CONT
, "!%s: %s: i/o error while scanning phy",
1156 dp
->name
, __func__
);
1158 dp
->mii_phy_addr
= phy_addr_saved
;
1163 axf_mii_probe(struct usbgem_dev
*dp
)
1167 uint8_t old_11th
[2];
1168 uint8_t new_11th
[2];
1169 struct axf_dev
*lp
= dp
->private;
1171 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
1172 (void) axf_reset_phy(dp
);
1173 lp
->phy_has_reset
= B_TRUE
;
1176 my_guess
= axf_scan_phy(dp
);
1177 if (my_guess
>= 0 && my_guess
< 32 &&
1178 my_guess
!= dp
->mii_phy_addr
) {
1180 * phy addr in srom is wrong, need to fix it
1182 IN(dp
, VCMD_READ_SROM
,
1183 0x11, 0, 2, old_11th
, &err
, usberr
);
1185 new_11th
[0] = my_guess
;
1186 new_11th
[1] = old_11th
[1];
1188 OUT(dp
, VCMD_WRITE_SROM_ENABLE
,
1189 0, 0, 0, NULL
, &err
, usberr
);
1190 OUT(dp
, VCMD_WRITE_SROM
,
1191 0x11, LE16P(new_11th
), 0, NULL
, &err
, usberr
);
1192 OUT(dp
, VCMD_WRITE_SROM_DISABLE
,
1193 0, 0, 0, NULL
, &err
, usberr
);
1195 /* XXX - read back, but it doesn't work, why? */
1196 delay(drv_usectohz(1000*1000));
1197 IN(dp
, VCMD_READ_SROM
,
1198 0x11, 0, 2, new_11th
, &err
, usberr
);
1200 cmn_err(CE_NOTE
, "!%s: %s: phy addr in srom fixed: "
1203 LE16P(old_11th
), LE16P(new_11th
));
1204 return (USBGEM_FAILURE
);
1207 "!%s: %s: failed to patch phy addr, "
1209 dp
->name
, __func__
, LE16P(old_11th
));
1210 return (USBGEM_FAILURE
);
1213 return (usbgem_mii_probe_default(dp
));
1217 axf_mii_init(struct usbgem_dev
*dp
)
1219 struct axf_dev
*lp
= dp
->private;
1221 DPRINTF(2, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
1223 if (!lp
->phy_has_reset
) {
1224 (void) axf_reset_phy(dp
);
1227 /* prepare to reset phy on the next reconnect or resume */
1228 lp
->phy_has_reset
= B_FALSE
;
1230 return (USB_SUCCESS
);
1234 axfattach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
1237 ddi_iblock_cookie_t c
;
1243 struct chip_info
*p
;
1245 const char *drv_name
;
1246 struct usbgem_dev
*dp
;
1248 struct usbgem_conf
*ugcp
;
1251 unit
= ddi_get_instance(dip
);
1252 drv_name
= ddi_driver_name(dip
);
1254 DPRINTF(3, (CE_CONT
, "!%s%d: %s: called, cmd:%d",
1255 drv_name
, unit
, __func__
, cmd
));
1257 if (cmd
== DDI_ATTACH
) {
1259 * Check if the chip is supported.
1261 vid
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
1262 "usb-vendor-id", -1);
1263 pid
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
1264 "usb-product-id", -1);
1265 revid
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
1266 "usb-revision-id", -1);
1268 for (i
= 0, p
= chiptbl_88x7x
; i
< CHIPTABLESIZE
; i
++, p
++) {
1269 if (p
->vid
== vid
&& p
->pid
== pid
) {
1271 cmn_err(CE_CONT
, "!%s%d: %s "
1272 "(vid: 0x%04x, did: 0x%04x, revid: 0x%02x)",
1273 drv_name
, unit
, p
->name
, vid
, pid
, revid
);
1279 cmn_err(CE_WARN
, "!%s: %s: wrong usb venid/prodid (0x%x, 0x%x)",
1280 drv_name
, __func__
, vid
, pid
);
1283 p
= &chiptbl_88x7x
[CHIPTABLESIZE
- 1];
1286 * construct usbgem configration
1288 ugcp
= kmem_zalloc(sizeof (*ugcp
), KM_SLEEP
);
1292 * softmac requires that ppa is the instance number
1293 * of the device, otherwise it hangs in seaching the device.
1295 (void) sprintf(ugcp
->usbgc_name
, "%s%d", drv_name
, unit
);
1296 ugcp
->usbgc_ppa
= unit
;
1298 ugcp
->usbgc_ifnum
= 0;
1299 ugcp
->usbgc_alt
= 0;
1301 ugcp
->usbgc_tx_list_max
= 64;
1303 ugcp
->usbgc_rx_header_len
= 0;
1304 ugcp
->usbgc_rx_list_max
= 64;
1306 /* time out parameters */
1307 ugcp
->usbgc_tx_timeout
= USBGEM_TX_TIMEOUT
;
1308 ugcp
->usbgc_tx_timeout_interval
= USBGEM_TX_TIMEOUT_INTERVAL
;
1312 * XXX - flow control caused link down frequently under
1315 ugcp
->usbgc_flow_control
= FLOW_CONTROL_RX_PAUSE
;
1317 /* MII timeout parameters */
1318 ugcp
->usbgc_mii_link_watch_interval
= ONESEC
;
1319 ugcp
->usbgc_mii_an_watch_interval
= ONESEC
/5;
1320 ugcp
->usbgc_mii_reset_timeout
= MII_RESET_TIMEOUT
; /* 1 sec */
1321 ugcp
->usbgc_mii_an_timeout
= MII_AN_TIMEOUT
; /* 5 sec */
1322 ugcp
->usbgc_mii_an_wait
= 0;
1323 ugcp
->usbgc_mii_linkdown_timeout
= MII_LINKDOWN_TIMEOUT
;
1325 ugcp
->usbgc_mii_an_delay
= ONESEC
/10;
1326 ugcp
->usbgc_mii_linkdown_action
= MII_ACTION_RSA
;
1327 ugcp
->usbgc_mii_linkdown_timeout_action
= MII_ACTION_RESET
;
1328 ugcp
->usbgc_mii_dont_reset
= B_FALSE
;
1329 ugcp
->usbgc_mii_hw_link_detection
= B_TRUE
;
1330 ugcp
->usbgc_mii_stop_mac_on_linkdown
= B_FALSE
;
1335 ugcp
->usbgc_attach_chip
= &axf_attach_chip
;
1336 ugcp
->usbgc_reset_chip
= &axf_reset_chip
;
1337 ugcp
->usbgc_init_chip
= &axf_init_chip
;
1338 ugcp
->usbgc_start_chip
= &axf_start_chip
;
1339 ugcp
->usbgc_stop_chip
= &axf_stop_chip
;
1340 ugcp
->usbgc_multicast_hash
= &axf_mcast_hash
;
1342 ugcp
->usbgc_set_rx_filter
= &axf_set_rx_filter
;
1343 ugcp
->usbgc_set_media
= &axf_set_media
;
1344 ugcp
->usbgc_get_stats
= &axf_get_stats
;
1345 ugcp
->usbgc_interrupt
= &axf_interrupt
;
1347 /* packet operation */
1348 ugcp
->usbgc_tx_make_packet
= &axf_tx_make_packet
;
1349 ugcp
->usbgc_rx_make_packet
= &axf_rx_make_packet
;
1351 /* mii operations */
1352 ugcp
->usbgc_mii_probe
= &axf_mii_probe
;
1353 ugcp
->usbgc_mii_init
= &axf_mii_init
;
1354 ugcp
->usbgc_mii_config
= &usbgem_mii_config_default
;
1355 ugcp
->usbgc_mii_read
= &axf_mii_read
;
1356 ugcp
->usbgc_mii_write
= &axf_mii_write
;
1359 ugcp
->usbgc_min_mtu
= ETHERMTU
;
1360 ugcp
->usbgc_max_mtu
= ETHERMTU
;
1361 ugcp
->usbgc_default_mtu
= ETHERMTU
;
1363 lp
= kmem_zalloc(sizeof (struct axf_dev
), KM_SLEEP
);
1365 lp
->last_link_state
= 0;
1366 lp
->phy_has_reset
= B_FALSE
;
1368 dp
= usbgem_do_attach(dip
, ugcp
, lp
, sizeof (struct axf_dev
));
1370 kmem_free(ugcp
, sizeof (*ugcp
));
1373 return (DDI_SUCCESS
);
1377 kmem_free(lp
, sizeof (struct axf_dev
));
1380 return (DDI_FAILURE
);
1383 if (cmd
== DDI_RESUME
) {
1384 return (usbgem_resume(dip
));
1387 return (DDI_FAILURE
);
1391 axfdetach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
1395 if (cmd
== DDI_DETACH
) {
1396 ret
= usbgem_do_detach(dip
);
1397 if (ret
!= DDI_SUCCESS
) {
1398 return (DDI_FAILURE
);
1400 return (DDI_SUCCESS
);
1402 if (cmd
== DDI_SUSPEND
) {
1403 return (usbgem_suspend(dip
));
1405 return (DDI_FAILURE
);
1408 /* ======================================================== */
1410 * OS depend (loadable streams driver) routine
1412 /* ======================================================== */
1413 #ifdef USBGEM_CONFIG_GLDv3
1414 USBGEM_STREAM_OPS(axf_ops
, axfattach
, axfdetach
);
1416 static struct module_info axfminfo
= {
1418 "axf", /* mi_idname */
1420 ETHERMTU
, /* mi_maxpsz */
1421 ETHERMTU
*128, /* mi_hiwat */
1425 static struct qinit axfrinit
= {
1426 (int (*)()) NULL
, /* qi_putp */
1427 usbgem_rsrv
, /* qi_srvp */
1428 usbgem_open
, /* qi_qopen */
1429 usbgem_close
, /* qi_qclose */
1430 (int (*)()) NULL
, /* qi_qadmin */
1431 &axfminfo
, /* qi_minfo */
1435 static struct qinit axfwinit
= {
1436 usbgem_wput
, /* qi_putp */
1437 usbgem_wsrv
, /* qi_srvp */
1438 (int (*)()) NULL
, /* qi_qopen */
1439 (int (*)()) NULL
, /* qi_qclose */
1440 (int (*)()) NULL
, /* qi_qadmin */
1441 &axfminfo
, /* qi_minfo */
1445 static struct streamtab axf_info
= {
1446 &axfrinit
, /* st_rdinit */
1447 &axfwinit
, /* st_wrinit */
1448 NULL
, /* st_muxrinit */
1449 NULL
/* st_muxwrinit */
1452 static struct cb_ops cb_axf_ops
= {
1453 nulldev
, /* cb_open */
1454 nulldev
, /* cb_close */
1455 nodev
, /* cb_strategy */
1456 nodev
, /* cb_print */
1457 nodev
, /* cb_dump */
1458 nodev
, /* cb_read */
1459 nodev
, /* cb_write */
1460 nodev
, /* cb_ioctl */
1461 nodev
, /* cb_devmap */
1462 nodev
, /* cb_mmap */
1463 nodev
, /* cb_segmap */
1464 nochpoll
, /* cb_chpoll */
1465 ddi_prop_op
, /* cb_prop_op */
1466 &axf_info
, /* cb_stream */
1467 D_NEW
|D_MP
/* cb_flag */
1470 static struct dev_ops axf_ops
= {
1471 DEVO_REV
, /* devo_rev */
1472 0, /* devo_refcnt */
1473 usbgem_getinfo
, /* devo_getinfo */
1474 nulldev
, /* devo_identify */
1475 nulldev
, /* devo_probe */
1476 axfattach
, /* devo_attach */
1477 axfdetach
, /* devo_detach */
1478 nodev
, /* devo_reset */
1479 &cb_axf_ops
, /* devo_cb_ops */
1480 NULL
, /* devo_bus_ops */
1481 usbgem_power
, /* devo_power */
1483 usbgem_quiesce
, /* devo_quiesce */
1488 static struct modldrv modldrv
= {
1489 &mod_driverops
, /* Type of module. This one is a driver */
1491 &axf_ops
, /* driver ops */
1494 static struct modlinkage modlinkage
= {
1495 MODREV_1
, &modldrv
, NULL
1498 /* ======================================================== */
1502 /* ======================================================== */
1508 DPRINTF(2, (CE_CONT
, "!axf: _init: called"));
1510 status
= usbgem_mod_init(&axf_ops
, "axf");
1511 if (status
!= DDI_SUCCESS
) {
1514 status
= mod_install(&modlinkage
);
1515 if (status
!= DDI_SUCCESS
) {
1516 usbgem_mod_fini(&axf_ops
);
1529 DPRINTF(2, (CE_CONT
, "!axf: _fini: called"));
1530 status
= mod_remove(&modlinkage
);
1531 if (status
== DDI_SUCCESS
) {
1532 usbgem_mod_fini(&axf_ops
);
1538 _info(struct modinfo
*modinfop
)
1540 return (mod_info(&modlinkage
, modinfop
));