[AX88772C] add axusbnet thread, can recv and send.

This commit is contained in:
aozima
2022-04-17 14:01:19 +08:00
committed by sakumisu
parent cb395bbe27
commit 3e57cdcfc2

View File

@@ -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;
}