summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraozima <[email protected]>2022-04-17 14:01:19 +0800
committersakumisu <[email protected]>2022-04-17 18:30:13 +0800
commit3e57cdcfc2a6bd0b369177cce55fa9441d4c442b (patch)
treef1f07e8cb60ea7b74e06659ef56344db35c068e9
parentcb395bbe271366a979c77f7c483ca393db5381f6 (diff)
[AX88772C] add axusbnet thread, can recv and send.
-rw-r--r--class/vendor/axusbnet.c384
1 files changed, 384 insertions, 0 deletions
diff --git a/class/vendor/axusbnet.c b/class/vendor/axusbnet.c
index 307524c6..6d92fe2c 100644
--- a/class/vendor/axusbnet.c
+++ b/class/vendor/axusbnet.c
@@ -454,6 +454,388 @@ out:
return ret;
}
+static void rt_thread_axusbnet_entry(void *parameter)
+{
+ int ret;
+ struct usbh_hubport *hport;
+ uint8_t intf;
+ uint8_t buf[2+8];
+
+ USB_LOG_INFO("%s L%d\r\n", __FUNCTION__, __LINE__);
+ rt_thread_delay(200);
+ USB_LOG_INFO("%s L%d\r\n\r\n\r\n\r\n", __FUNCTION__, __LINE__);
+
+ const char *dname = "/dev/u0";
+ struct usbh_axusbnet *class = (struct usbh_axusbnet *)usbh_find_class_instance(dname);
+ if (class == NULL) {
+ USB_LOG_ERR("do not find %s\r\n", dname);
+ return;
+ }
+ USB_LOG_INFO("axusbnet=%p\r\n", dname);
+
+ usbh_axusbnet_eth_device.class = class;
+
+ struct usbnet *dev = &usbh_axusbnet_eth_device;
+
+ ret = ax8817x_read_cmd(dev, AX_CMD_SW_PHY_STATUS,
+ 0, 0, 1, buf);
+ if (ret < 0) {
+ USB_LOG_ERR("AX_CMD_SW_PHY_STATUS ret=%d\r\n", ret);
+ return;
+ }
+ u8 tempphyselect = buf[0];
+ if (tempphyselect == AX_PHYSEL_SSRMII) {
+ USB_LOG_ERR("%s L%d AX_PHYSEL_SSRMII\r\n", __FUNCTION__, __LINE__);
+ dev->internalphy = false;
+ return;
+ // dev->OperationMode = OPERATION_MAC_MODE;
+ // dev->PhySelect = 0x00;
+ } else if (tempphyselect == AX_PHYSEL_SSRRMII) {
+ USB_LOG_ERR("%s L%d AX_PHYSEL_SSRRMII\r\n", __FUNCTION__, __LINE__);
+ dev->internalphy = true;
+ return;
+ // dev->OperationMode = OPERATION_PHY_MODE;
+ // dev->PhySelect = 0x00;
+ } else if (tempphyselect == AX_PHYSEL_SSMII) {
+ USB_LOG_INFO("%s L%d internalphy AX_PHYSEL_SSMII & OPERATION_MAC_MODE\r\n", __FUNCTION__, __LINE__);
+ dev->internalphy = true;
+ dev->OperationMode = OPERATION_MAC_MODE;
+ dev->PhySelect = 0x01;
+ } else {
+ // deverr(dev, "Unknown MII type\n");
+ USB_LOG_INFO("%s L%d Unknown MII type\r\n", __FUNCTION__, __LINE__);
+ return;
+ }
+
+ /* reload eeprom data */
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_RSE, 0, 0, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("reload eeprom data ret=%d\r\n", ret);
+ return;
+ }
+
+ /* Get the EEPROM data: power saving configuration*/
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 0x18, 0, 2, buf);
+ if (ret < 0) {
+ USB_LOG_ERR("read SROM address 18h failed: %d\r\n", ret);
+ goto err_out;
+ }
+ USB_LOG_INFO("reading AX88772C psc: %02x %02x\r\n", buf[0], buf[1]);
+ // le16_to_cpus(tmp16);
+ // ax772b_data->psc = *tmp16 & 0xFF00;
+ /* End of get EEPROM data */
+
+ ret = ax8817x_get_mac(dev, buf);
+ if (ret < 0) {
+ USB_LOG_ERR("Get HW address failed: %d\r\n", ret);
+ return;
+ }
+ dump_hex(buf, ETH_ALEN);
+ memcpy(dev->dev_addr, buf, ETH_ALEN);
+
+ uint16_t chipcode = 0xFFFF;
+ {
+ uint16_t smsr;
+ // asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
+ ax8817x_read_cmd(dev, AX_CMD_READ_STATMNGSTS_REG, 0, 0, 1, &chipcode);
+ USB_LOG_ERR("AX_CMD_READ_STATMNGSTS_REG ret: %d %04X\r\n", ret, chipcode);
+
+// #define AX_CHIPCODE_MASK 0x70
+// #define AX_AX88772_CHIPCODE 0x00
+// #define AX_AX88772A_CHIPCODE 0x10
+// #define AX_AX88772B_CHIPCODE 0x20
+// #define AX_HOST_EN 0x01
+
+ chipcode &= 0x70;//AX_CHIPCODE_MASK; AX_AX88772_CHIPCODE
+ if(chipcode == 0x00)
+ {
+ USB_LOG_ERR("AX_CMD_READ_STATMNGSTS_REG AX_AX88772_CHIPCODE\r\n");
+ }
+ else if(chipcode == 0x10)
+ {
+ USB_LOG_ERR("AX_CMD_READ_STATMNGSTS_REG AX_AX88772A_CHIPCODE\r\n");
+ }
+ else if(chipcode == 0x20)
+ {
+ USB_LOG_ERR("AX_CMD_READ_STATMNGSTS_REG AX_AX88772B_CHIPCODE\r\n");
+ }
+ }
+
+ /* Get the PHY id: E0 10 */
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
+ if (ret < 0) {
+ USB_LOG_ERR("Error reading PHY ID: %02x\r\n", ret);
+ return;
+ }
+ if (dev->internalphy) {
+ dev->mii.phy_id = *((u8 *)buf + 1);
+ } else {
+ dev->mii.phy_id = *((u8 *)buf);
+ }
+ USB_LOG_INFO("reading %s PHY ID: %02x\r\n", dev->internalphy?"internal":"external", dev->mii.phy_id);
+
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, dev->PhySelect, 0, 0, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("Select PHY #1 failed: %d", ret);
+ return;
+ }
+
+ ret = ax88772a_phy_powerup(dev);
+ if (ret < 0) {
+ USB_LOG_ERR("ax88772a_phy_powerup failed: %d", ret);
+ return;
+ }
+
+ /* stop MAC operation */
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+ AX_RX_CTL_STOP, 0, 0, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("Reset RX_CTL failed: %d", ret);
+ goto err_out;
+ }
+
+ /* make sure the driver can enable sw mii operation */
+ ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("Enabling software MII failed: %d\r\n", ret);
+ goto err_out;
+ }
+
+ if ((dev->OperationMode == OPERATION_MAC_MODE) &&
+ (dev->PhySelect == 0x00)) {
+ USB_LOG_ERR("not support the external phy\r\n");
+ goto err_out;
+ }
+
+ if (dev->OperationMode == OPERATION_PHY_MODE) {
+ ax8817x_mdio_write_le(dev, dev->mii.phy_id, MII_BMCR, 0x3900);
+ }
+
+ if (dev->mii.phy_id != 0x10)
+ {
+ USB_LOG_ERR("not support phy_id != 0x10\r\n");
+ // ax8817x_mdio_write_le(dev->net, 0x10, MII_BMCR, 0x3900);
+ }
+
+ if (dev->mii.phy_id == 0x10 && dev->OperationMode != OPERATION_PHY_MODE) {
+ u16 tmp16 = ax8817x_mdio_read_le(dev, dev->mii.phy_id, 0x12);
+ ax8817x_mdio_write_le(dev, dev->mii.phy_id, 0x12, ((tmp16 & 0xFF9F) | 0x0040));
+ }
+
+ ax8817x_mdio_write_le(dev, dev->mii.phy_id, MII_ADVERTISE,
+ ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+
+ // mii_nway_restart(&dev->mii);
+ {
+ /* if autoneg is off, it's an error */
+ uint16_t bmcr = ax8817x_mdio_read_le(dev, dev->mii.phy_id, MII_BMCR);
+ if (bmcr & BMCR_ANENABLE) {
+ bmcr |= BMCR_ANRESTART;
+ USB_LOG_ERR("BMCR_ANENABLE ==> BMCR_ANRESTART\r\n");
+ ax8817x_mdio_write_le(dev, dev->mii.phy_id, MII_BMCR, bmcr);
+ } else
+ {
+ USB_LOG_ERR("not BMCR_ANENABLE BMCR=%04X\r\n", bmcr);
+ }
+ }
+
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, 0, 0, 0, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to write medium mode: %d", ret);
+ goto err_out;
+ }
+
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+ AX88772A_IPG0_DEFAULT | AX88772A_IPG1_DEFAULT << 8,
+ AX88772A_IPG2_DEFAULT, 0, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to write interframe gap: %d", ret);
+ goto err_out;
+ }
+
+ memset(buf, 0, 4);
+ ret = ax8817x_read_cmd(dev, AX_CMD_READ_IPG012, 0, 0, 3, buf);
+ *((u8 *)buf + 3) = 0x00;
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to read IPG,IPG1,IPG2 failed: %d", ret);
+ goto err_out;
+ } else {
+ uint32_t tmp32 = *((u32*)buf);
+ le32_to_cpus(&tmp32);
+ if (tmp32 != (AX88772A_IPG2_DEFAULT << 16 |
+ AX88772A_IPG1_DEFAULT << 8 | AX88772A_IPG0_DEFAULT)) {
+ USB_LOG_ERR("Non-authentic ASIX product\nASIX does not support it\n");
+ // ret = -ENODEV;
+ goto err_out;
+ }
+ }
+
+ // TODO: optimized for high speed.
+ ret = ax8817x_write_cmd(dev, 0x2A, 0x8000, 0x8001, 0, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("Reset RX_CTL failed: %d", ret);
+ goto err_out;
+ }
+
+ ret = ax88772b_reset(dev);
+ if (ret < 0) {
+ USB_LOG_ERR("ax88772b_reset failed: %d", ret);
+ goto err_out;
+ }
+
+ // OUT 29 0 0 0 AX_CMD_WRITE_MONITOR_MODE
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, 0, 0, 0, NULL);
+ if (ret < 0) {
+ deverr(dev, "AX_CMD_WRITE_MONITOR_MODE failed: %d", ret);
+ }
+
+ /* Set the MAC address */
+ ret = ax8817x_write_cmd(dev, AX88772_CMD_WRITE_NODE_ID,
+ 0, 0, ETH_ALEN, dev->dev_addr);
+ if (ret < 0) {
+ deverr(dev, "set MAC address failed: %d", ret);
+ }
+
+ // update Multicast AX_CMD_WRITE_MULTI_FILTER.
+ const uint8_t multi_filter[] = {0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x40};
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, AX_MCAST_FILTER_SIZE, (void *)multi_filter);
+ if (ret < 0) {
+ USB_LOG_ERR("Reset RX_CTL failed: %d", ret);
+ goto err_out;
+ }
+
+ /* Configure RX header type */
+ // u16 rx_reg = (AX_RX_CTL_PRO | AX_RX_CTL_AMALL | AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_HEADER_DEFAULT);
+ u16 rx_reg = (AX_RX_CTL_AB | AX_RX_CTL_AM | AX_RX_CTL_START);
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, rx_reg, 0, 0, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("Reset RX_CTL failed: %d", ret);
+ goto err_out;
+ }
+
+ /* set the embedded Ethernet PHY in power-up state */
+ // ax772b_data->psc = *tmp16 & 0xFF00;
+ // psc: 15 5a AX88772C psc: %02x %02x\r\n", buf[0], buf[1]);
+ ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | (0x5a00 & 0x7FFF),
+ 0, 0, NULL);
+ if (ret < 0) {
+ deverr(dev, "Failed to reset PHY: %d", ret);
+ // return ret;
+ }
+
+ rt_thread_delay(1000);
+ u16 mode = AX88772_MEDIUM_DEFAULT;
+ ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("AX_CMD_WRITE_MEDIUM_MODE failed: %d", ret);
+ goto err_out;
+ }
+
+ // check link status.
+ {
+ u16 bmcr = ax8817x_mdio_read_le(dev, dev->mii.phy_id, MII_BMCR);
+ u16 mode = AX88772_MEDIUM_DEFAULT;
+
+ USB_LOG_ERR("%s L%d MII_BMCR=%04X\r\n", __FUNCTION__, __LINE__, bmcr);
+ if (!(bmcr & BMCR_FULLDPLX))
+ {
+ mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
+ USB_LOG_ERR("%s L%d not AX88772_MEDIUM_FULL_DUPLEX\r\n", __FUNCTION__, __LINE__);
+ }
+ if (!(bmcr & BMCR_SPEED100))
+ {
+ mode &= ~AX88772_MEDIUM_100MB;
+ USB_LOG_ERR("%s L%d not AX88772_MEDIUM_100MB\r\n", __FUNCTION__, __LINE__);
+ }
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+ }
+
+ while (1)
+ {
+ // USB_LOG_INFO("%s L%d\r\n", __FUNCTION__, __LINE__);
+
+ ret = usbh_ep_bulk_transfer(class->bulkin, class->bulkin_buf, sizeof(class->bulkin_buf), 1000);
+ if (ret < 0) {
+ if (ret != -2) {
+ USB_LOG_ERR("%s L%d bulk in error ret=%d\r\n", __FUNCTION__, __LINE__, ret);
+ }
+ continue;
+ }
+
+ {
+ const uint8_t *data = class->bulkin_buf;
+ uint16_t len1, len2;
+
+ len1 = data[0] | ((uint16_t)(data[1])<<8);
+ len2 = data[2] | ((uint16_t)(data[3])<<8);
+
+ // USB_LOG_INFO("transfer bulkin len1:%04X, len2:%04X, len2':%04X.\r\n", len1, len2, ~len2);
+
+ len1 &= 0x07ff;
+
+ if (data[0] != ((uint8_t)(~data[2]))) {
+ USB_LOG_ERR("transfer bulkin len1:%04X, len2:%04X, len2':%04X.\r\n", len1, len2, ~len2);
+
+ dump_hex(data, 32);
+ continue;
+ }
+
+ {
+ static uint32_t count = 0;
+ USB_LOG_INFO("recv: #%d, len=%d\r\n", count, ret);
+ dump_hex(data+4, 32);
+
+ if ((count % 10) == 0) {
+ // 192.168.89.14 ==> 255.255.255.255:7 echo hello world!
+ const uint8_t packet_bytes[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
+ 0x00, 0x36, 0xb0, 0xfd, 0x00, 0x00, 0x80, 0x11,
+ 0x00, 0x00, 0xc0, 0xa8, 0x59, 0x0e, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x07, 0x00, 0x07, 0x00, 0x22,
+ 0x53, 0x06, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20,
+ 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x41, 0x58, 0x38, 0x38, 0x37,
+ 0x37, 0x32, 0x43, 0x2e
+ };
+
+ uint8_t *send_buf = (uint8_t *)class->bulkin_buf;
+ send_buf[0] = sizeof(packet_bytes);
+ send_buf[1] = sizeof(packet_bytes) >> 8;
+ send_buf[2] = ~send_buf[0];
+ send_buf[3] = ~send_buf[1];
+ memcpy(send_buf+4, packet_bytes, sizeof(packet_bytes));
+ memcpy(send_buf+4+6, dev->dev_addr, 6);// update src mac.
+
+ ret = usbh_ep_bulk_transfer(class->bulkout, send_buf, 4 + sizeof(packet_bytes), 500);
+ USB_LOG_INFO("bulkout, ret=%d\r\n", ret);
+ dump_hex(send_buf, 64);
+ }
+
+ count++;
+ }
+ }
+ } // while (1)
+
+err_out:
+out2:
+
+ return;
+}
+
+static int axusbnet_startup(void)
+{
+ const char *tname = "axusbnet";
+ usb_osal_thread_t usb_thread;
+
+ usb_thread = usb_osal_thread_create(tname, 1024 * 6, CONFIG_USBHOST_PSC_PRIO, rt_thread_axusbnet_entry, NULL);
+ if (usb_thread == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
+
static int usbh_axusbnet_connect(struct usbh_hubport *hport, uint8_t intf)
{
int ret = 0;
@@ -513,6 +895,8 @@ static int usbh_axusbnet_connect(struct usbh_hubport *hport, uint8_t intf)
}
}
+ axusbnet_startup();
+
return ret;
}