Warning, cross-references for /kernel/drivers/usb/asix.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <drivers/usb/usb.h>
0019 #include <drivers/usb/uhci.h>
0020 #include <drivers/net/ethernet.h>
0021 #include <util/printf.h>
0022 #include <kernel.h>
0023 #include "sched/sched.h"
0024
0025
0026
0027 #ifdef DEBUG_ASIX
0028 #define DLOG(fmt,...) DLOG_PREFIX("asix",fmt,##__VA_ARGS__)
0029 #else
0030 #define DLOG(fmt,...) ;
0031 #endif
0032
0033 static uint8 ethaddr[ETH_ADDR_LEN];
0034 static uint status_ept, status_maxpkt;
0035 static uint data_ept_in, data_ept_out, data_maxpkt;
0036
0037 static USB_DEVICE_INFO *ethusbdev;
0038 static ethernet_device usbnet_ethdev;
0039
0040 #define SOFTWARE_MII 0x06
0041 #define PHY_READ_REG 0x07
0042 #define PHY_WRITE_REG 0x08
0043 #define MII_STATUS 0x09
0044 #define HARDWARE_MII 0x0A
0045 #define RX_CTRL_READ 0x0F
0046 #define RX_CTRL_WRITE 0x10
0047 #define READ_IPG 0x11
0048 #define WRITE_IPG 0x12
0049 #define GET_NODE_ID 0x13
0050 #define ETH_PHY_ID 0x19
0051 #define MEDIUM_STATUS 0x1A
0052 #define MEDIUM_MODE 0x1B
0053 #define GPIO_WRITE 0x1F
0054 #define SW_RESET 0x20
0055 #define SW_PHY_SELECT 0x22
0056
0057 #define SWRESET_CLEAR 0x00
0058 #define SWRESET_RR 0x01
0059 #define SWRESET_RT 0x02
0060 #define SWRESET_PRTE 0x04
0061 #define SWRESET_PRL 0x08
0062 #define SWRESET_BZ 0x10
0063 #define SWRESET_IPRL 0x20
0064 #define SWRESET_IPPD 0x40
0065
0066 #define MII_BMCR 0x00
0067 #define MII_BMSR 0x01
0068 #define MII_PHYSID1 0x02
0069 #define MII_PHYSID2 0x03
0070 #define MII_ADVERTISE 0x04
0071
0072 #define BMCR_RESET 0x8000
0073 #define BMCR_ANRESTART 0x0200
0074 #define BMCR_ANENABLE 0x1000
0075 #define BMCR_LOOPBACK 0x4000
0076
0077 #define ADVERTISE_CSMA 0x0001
0078 #define ADVERTISE_10HALF 0x0020
0079 #define ADVERTISE_100HALF 0x0080
0080 #define ADVERTISE_10FULL 0x0040
0081 #define ADVERTISE_100FULL 0x100
0082 #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
0083 ADVERTISE_100HALF | ADVERTISE_100FULL)
0084
0085 #define MEDIUM_PF 0x0080
0086 #define MEDIUM_JFE 0x0040
0087 #define MEDIUM_TFC 0x0020
0088 #define MEDIUM_RFC 0x0010
0089 #define MEDIUM_ENCK 0x0008
0090 #define MEDIUM_AC 0x0004
0091 #define MEDIUM_FD 0x0002
0092 #define MEDIUM_GM 0x0001
0093 #define MEDIUM_SM 0x1000
0094 #define MEDIUM_SBP 0x0800
0095 #define MEDIUM_PS 0x0200
0096 #define MEDIUM_RE 0x0100
0097
0098 #define AX88772_MEDIUM_DEFAULT \
0099 (MEDIUM_FD | MEDIUM_RFC | \
0100 MEDIUM_TFC | MEDIUM_PS | \
0101 MEDIUM_AC | MEDIUM_RE )
0102
0103
0104 #define GPIO_GPO0EN 0x01
0105 #define GPIO_GPO_0 0x02
0106 #define GPIO_GPO1EN 0x04
0107 #define GPIO_GPO_1 0x08
0108 #define GPIO_GPO2EN 0x10
0109 #define GPIO_GPO_2 0x20
0110 #define GPIO_RESERVED 0x40
0111 #define GPIO_RSE 0x80
0112
0113 #define AX88772_IPG0_DEFAULT 0x15
0114 #define AX88772_IPG1_DEFAULT 0x0C
0115 #define AX88772_IPG2_DEFAULT 0x12
0116
0117 static bool
0118 send_cmd (bool input, uint8 cmd, uint16 val, uint16 index,
0119 uint16 len, uint8 *buf)
0120 {
0121 USB_DEV_REQ setup_req;
0122
0123 setup_req.bmRequestType = (input ? 0x80 : 0x00) | 0x40;
0124 setup_req.bRequest = cmd;
0125 setup_req.wValue = val;
0126 setup_req.wIndex = index;
0127 setup_req.wLength = len;
0128
0129 {
0130 uint8 *ptr = (uint8 *) &setup_req;
0131 DLOG ("send_cmd : %.02X%.02X_%.02X%.02X_%.02X%.02X_%.02X%.02X",
0132 ptr[0], ptr[1], ptr[2], ptr[3],
0133 ptr[4], ptr[5], ptr[6], ptr[7]);
0134 }
0135
0136 return usb_control_transfer (ethusbdev, &setup_req, sizeof (USB_DEV_REQ),
0137 buf, len) == 0;
0138 }
0139
0140 static inline bool
0141 sw_mii (void)
0142 {
0143 return send_cmd (FALSE, SOFTWARE_MII, 0, 0, 0, NULL);
0144 }
0145
0146 static inline bool
0147 hw_mii (void)
0148 {
0149 return send_cmd (FALSE, HARDWARE_MII, 0, 0, 0, NULL);
0150 }
0151
0152 static inline bool
0153 mdio_write (uint16 phy_id, uint16 loc, uint16 val)
0154 {
0155 bool ret;
0156 sw_mii ();
0157 ret = send_cmd (FALSE, PHY_WRITE_REG, phy_id, loc, 2, (uint8 *) &val);
0158 hw_mii ();
0159 return ret;
0160 }
0161
0162 static inline uint16
0163 mdio_read (uint16 phy_id, uint16 loc)
0164 {
0165 uint16 val;
0166 sw_mii ();
0167 if (!send_cmd (TRUE, PHY_READ_REG, phy_id, loc, 2, (uint8 *) &val))
0168 val = 0;
0169 hw_mii ();
0170 return val;
0171 }
0172
0173 static uint16
0174 read_rx_ctrl (void)
0175 {
0176 uint16 rx = 0;
0177 if (send_cmd (TRUE, RX_CTRL_READ, 0, 0, 2, (uint8 *) &rx))
0178 return rx;
0179 else
0180 return 0;
0181 }
0182
0183 static bool
0184 write_rx_ctrl (uint16 rx)
0185 {
0186 return send_cmd (FALSE, RX_CTRL_WRITE, rx, 0, 0, NULL);
0187 }
0188
0189 static bool
0190 reset (void)
0191 {
0192 uint32 phy_id, phy_reg1, phy_reg2;
0193 uint16 bmcr, medium;
0194
0195
0196 if (!send_cmd (FALSE, GPIO_WRITE, GPIO_RSE | GPIO_GPO_2 | GPIO_GPO2EN,
0197 0, 0, NULL))
0198 goto abort;
0199 delay (5);
0200
0201
0202 if (!send_cmd (TRUE, ETH_PHY_ID, 0, 0, 2, (uint8 *)&phy_id))
0203 goto abort;
0204
0205 if ((phy_id & 0xE0) == 0xE0) {
0206
0207 phy_id >>= 8;
0208 if ((phy_id & 0xE0) == 0xE0) {
0209 DLOG ("no supported PHY");
0210 goto abort;
0211 }
0212 }
0213
0214 phy_id &= 0x1F;
0215
0216 DLOG ("phy_id=0x%x", phy_id);
0217
0218 if (!send_cmd (FALSE, SW_PHY_SELECT,
0219 (phy_id & 0x1F) == 0x10 ? 1 : 0,
0220 0, 0, NULL))
0221 goto abort;
0222
0223 DLOG ("sending SW reset");
0224
0225 if (!send_cmd (FALSE, SW_RESET, SWRESET_IPPD | SWRESET_PRL, 0, 0, NULL))
0226 goto abort;
0227 delay (150);
0228 if (!send_cmd (FALSE, SW_RESET, SWRESET_CLEAR, 0, 0, NULL))
0229 goto abort;
0230 delay (150);
0231 if (!send_cmd (FALSE, SW_RESET,
0232 (phy_id & 0x1F) == 0x10 ? SWRESET_IPRL : SWRESET_PRTE,
0233 0, 0, NULL))
0234 goto abort;
0235 delay (150);
0236
0237
0238 DLOG ("RXCTRL=0x%x", read_rx_ctrl ());
0239 if (!write_rx_ctrl (0x0))
0240 goto abort;
0241 DLOG ("wrote 0x0 -- RXCTRL=0x%x", read_rx_ctrl ());
0242
0243
0244 memset (ethaddr, 0, ETH_ADDR_LEN);
0245 if (!send_cmd (TRUE, GET_NODE_ID, 0, 0, ETH_ADDR_LEN, ethaddr))
0246 goto abort;
0247
0248 DLOG ("ethaddr=%.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
0249 ethaddr[0], ethaddr[1], ethaddr[2], ethaddr[3], ethaddr[4], ethaddr[5]);
0250
0251
0252 phy_reg1 = mdio_read (phy_id, MII_PHYSID1);
0253 phy_reg2 = mdio_read (phy_id, MII_PHYSID2);
0254
0255 DLOG ("MII said PHY IDENTIFIER=0x%x",
0256 ((phy_reg1 & 0xffff) << 16) | (phy_reg2 & 0xffff));
0257
0258
0259
0260 DLOG ("resending SW reset");
0261 if (!send_cmd (FALSE, SW_RESET, SWRESET_PRL, 0, 0, NULL))
0262 goto abort;
0263 delay (150);
0264 if (!send_cmd (FALSE, SW_RESET, SWRESET_IPRL | SWRESET_PRL, 0, 0, NULL))
0265 goto abort;
0266 delay (150);
0267
0268
0269 mdio_write (phy_id, MII_BMCR, BMCR_RESET);
0270 mdio_write (phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA);
0271
0272
0273 bmcr = mdio_read (phy_id, MII_BMCR);
0274 DLOG ("enabling autonegotiation. BMCR=0x%x", bmcr);
0275 if (bmcr & BMCR_ANENABLE) {
0276 bmcr |= BMCR_ANRESTART;
0277 mdio_write (phy_id, MII_BMCR, bmcr);
0278 } else
0279 goto abort;
0280
0281 DLOG ("setting medium mode=0x%x", AX88772_MEDIUM_DEFAULT);
0282
0283 if (!send_cmd (FALSE, MEDIUM_MODE, AX88772_MEDIUM_DEFAULT, 0, 0, NULL))
0284 goto abort;
0285
0286
0287 DLOG ("setting IPG");
0288 if (!send_cmd (FALSE, WRITE_IPG,
0289 AX88772_IPG0_DEFAULT | (AX88772_IPG1_DEFAULT << 8),
0290 AX88772_IPG2_DEFAULT, 0, NULL))
0291 goto abort;
0292
0293 DLOG ("accepting broadcasts, starting operation");
0294
0295 if (!write_rx_ctrl (0x88))
0296 goto abort;
0297
0298 DLOG ("RXCTRL=0x%x at end of reset", read_rx_ctrl ());
0299
0300 if (!send_cmd (TRUE, MEDIUM_STATUS, 0, 0, 2, (uint8 *) &medium))
0301 goto abort;
0302 DLOG ("medium status=0x%x at end of reset", medium);
0303
0304 bmcr = mdio_read (phy_id, MII_BMCR);
0305 DLOG ("BMCR=0x%x at end of reset", bmcr);
0306
0307 DLOG ("BMSR=0x%x at end of reset", mdio_read (phy_id, MII_BMSR));
0308
0309 return TRUE;
0310 abort:
0311 DLOG ("reset failed");
0312 return FALSE;
0313 }
0314
0315 static bool
0316 get_hwaddr (uint8 addr[ETH_ADDR_LEN])
0317 {
0318 int i;
0319 for (i=0; i<ETH_ADDR_LEN; i++)
0320 addr[i] = ethaddr[i];
0321 return TRUE;
0322 }
0323
0324 static sint
0325 transmit (uint8* buf, sint len)
0326 {
0327 static uint8 frame[MAX_FRAME_SIZE];
0328 sint ret;
0329 uint32 act_len;
0330 uint32 prop_len = ((len ^ 0x0000ffff) << 16) | len;
0331
0332 memcpy (frame, &prop_len, 4);
0333 memcpy (frame+4, buf, len);
0334
0335 #ifdef DEBUG_ASIX_DATA
0336 DLOG ("transmitting data len=%d: %.02X %.02X %.02X %.02X", len,
0337 frame[0], frame[1], frame[2], frame[3]);
0338 DLOG (" %.02X %.02X %.02X %.02X",
0339 frame[4], frame[5], frame[6], frame[7]);
0340 DLOG (" %.02X %.02X %.02X %.02X",
0341 frame[8], frame[9], frame[10], frame[11]);
0342 DLOG (" %.02X %.02X %.02X %.02X",
0343 frame[12], frame[13], frame[14], frame[15]);
0344 #endif
0345
0346 if (usb_bulk_transfer (ethusbdev, data_ept_out, frame, len+4,
0347 data_maxpkt, DIR_OUT, &act_len) == 0)
0348 ret = act_len;
0349 else
0350 ret = 0;
0351 DLOG ("transmitted %d bytes", act_len);
0352 return ret;
0353 }
0354
0355 static void
0356 poll (void)
0357 {
0358 uint8 buffer[1600];
0359 uint32 act_len;
0360 if (usb_bulk_transfer (ethusbdev, data_ept_in, buffer, 1514,
0361 data_maxpkt, DIR_IN, &act_len) == 0) {
0362 if (act_len > 0) {
0363 #ifdef DEBUG_ASIX_DATA
0364 DLOG ("receiving data len=%.04d: %.02X %.02X %.02X %.02X",
0365 act_len, buffer[0], buffer[1], buffer[2], buffer[3]);
0366 DLOG (" %.02X %.02X %.02X %.02X",
0367 buffer[4], buffer[5], buffer[6], buffer[7]);
0368 DLOG (" %.02X %.02X %.02X %.02X",
0369 buffer[8], buffer[9], buffer[10], buffer[11]);
0370 DLOG (" %.02X %.02X %.02X %.02X",
0371 buffer[12], buffer[13], buffer[14], buffer[15]);
0372 #endif
0373 usbnet_ethdev.recv_func (&usbnet_ethdev, buffer+4, act_len-4);
0374 }
0375 }
0376 }
0377
0378 static void
0379 irq_loop (void)
0380 {
0381 uint32 tick = 0;
0382 DLOG ("irq_loop pid=0x%x", str ());
0383 for (;;) {
0384 poll ();
0385 DLOG ("iteration %d", tick);
0386 tick++;
0387 }
0388 }
0389
0390 static void
0391 status_loop (void)
0392 {
0393 uint32 tick = 0, act_len;
0394 uint32 status[2];
0395 DLOG ("status_loop pid=0x%x", str ());
0396 for (;;) {
0397 if (usb_bulk_transfer (ethusbdev, status_ept, (uint8 *)&status, 8,
0398 status_maxpkt, DIR_IN, &act_len) == 0) {
0399 if (act_len > 0) {
0400 DLOG ("status update 0x%.08X %.08X", status[1], status[0]);
0401 if (status[0] & 0x10000)
0402 DLOG (" primary link UP");
0403 if (status[0] & 0x20000)
0404 DLOG (" secondary link UP");
0405 if (status[0] & 0x40000)
0406 DLOG (" Bulk Out Ethernet Frame Length Error");
0407 }
0408 }
0409 DLOG ("status iteration %d", tick);
0410 tick++;
0411 delay (100);
0412 }
0413 }
0414
0415
0416 static uint32 irq_stack[1024] ALIGNED(0x1000);
0417 static task_id irq_pid;
0418
0419 static uint32 status_stack[1024] ALIGNED(0x1000);
0420 static task_id status_pid;
0421
0422 static bool
0423 probe (USB_DEVICE_INFO *info, USB_CFG_DESC *cfgd, USB_IF_DESC *ifd)
0424 {
0425 uint i;
0426 USB_EPT_DESC *eptd;
0427
0428 DLOG ("examining 0x%x 0x%x 0x%x",
0429 ifd->bInterfaceClass,
0430 info->devd.idVendor,
0431 info->devd.idProduct);
0432
0433 if (!(ifd->bInterfaceClass == 0xFF &&
0434 ifd->bInterfaceSubClass == 0xFF &&
0435 ifd->bInterfaceProtocol == 0x00 &&
0436
0437 info->devd.idVendor == 0x0b95 &&
0438
0439 info->devd.idProduct == 0x772a))
0440 return FALSE;
0441
0442
0443 eptd = (USB_EPT_DESC *) &ifd[1];
0444
0445 status_ept = data_ept_in = data_ept_out = 0;
0446
0447
0448 for (i=0; i<3; i++) {
0449 if ((eptd->bmAttributes & 0x3) == 0x3) {
0450
0451 status_ept = eptd->bEndpointAddress & 0x7F;
0452 status_maxpkt = eptd->wMaxPacketSize;
0453 } else if ((eptd->bmAttributes & 0x3) == 0x2) {
0454
0455 data_maxpkt = eptd->wMaxPacketSize;
0456 if (eptd->bEndpointAddress & 0x80)
0457 data_ept_in = eptd->bEndpointAddress & 0x7F;
0458 else
0459 data_ept_out = eptd->bEndpointAddress & 0x7F;
0460 }
0461 eptd = &eptd[1];
0462 }
0463
0464 DLOG ("status_ept=%d data_ept_in=%d data_ept_out=%d data_maxpkt=%d",
0465 status_ept, data_ept_in, data_ept_out, data_maxpkt);
0466
0467 if (!status_ept || !data_ept_in || !data_ept_out)
0468 return FALSE;
0469
0470 if (usb_set_configuration (info, cfgd->bConfigurationValue) != 0) {
0471 DLOG ("set_configuration: failed");
0472 return FALSE;
0473 }
0474
0475 ethusbdev = info;
0476
0477 if (!reset ())
0478 return FALSE;
0479
0480
0481 usbnet_ethdev.recv_func = NULL;
0482 usbnet_ethdev.send_func = transmit;
0483 usbnet_ethdev.get_hwaddr_func = get_hwaddr;
0484 usbnet_ethdev.poll_func = poll;
0485
0486 if (!net_register_device (&usbnet_ethdev)) {
0487 DLOG ("registration failed");
0488 return FALSE;
0489 }
0490
0491 irq_pid = start_kernel_thread ((uint) irq_loop, (uint) &irq_stack[1023]);
0492 #if 0
0493 status_pid = start_kernel_thread ((uint) status_loop,
0494 (uint) &status_stack[1023]);
0495 #endif
0496
0497 return TRUE;
0498 }
0499
0500 static USB_DRIVER asix_driver = {
0501 .probe = probe
0502 };
0503
0504 extern bool
0505 usb_asix_driver_init (void)
0506 {
0507 DLOG ("init");
0508 return usb_register_driver (&asix_driver);
0509 }
0510
0511 #include "module/header.h"
0512
0513 static const struct module_ops mod_ops = {
0514 .init = usb_asix_driver_init
0515 };
0516
0517 DEF_MODULE (usb___asix, "USB asix network driver", &mod_ops, {"usb", "net___ethernet"});
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529