diff --git a/minix/drivers/net/ip1000/Makefile b/minix/drivers/net/ip1000/Makefile index 6cb4e4aaf..d8ac6c81c 100755 --- a/minix/drivers/net/ip1000/Makefile +++ b/minix/drivers/net/ip1000/Makefile @@ -1,4 +1,4 @@ -# Makefile for the ip1000 Ethernet drivers +# Makefile for the Ethernet drivers PROG= ip1000 SRCS= ip1000.c diff --git a/minix/drivers/net/ip1000/README b/minix/drivers/net/ip1000/README index 21863614b..399dba793 100644 --- a/minix/drivers/net/ip1000/README +++ b/minix/drivers/net/ip1000/README @@ -9,6 +9,10 @@ Maybe the Ethernet cards of other PCI numbers for IC Plus can be supported. Revision 1.0 2016/11/02 Authored by Jia-Ju Bai +Revision 1.1 2016/11/12 +Modification: Remove and rewrite Linux-derived code +Authored by Jia-Ju Bai + Something can be improved: 1. Ethernet address can not be modified at present. 2. Dump interfaces are not provided. diff --git a/minix/drivers/net/ip1000/io.h b/minix/drivers/net/ip1000/io.h new file mode 100644 index 000000000..14d67d531 --- /dev/null +++ b/minix/drivers/net/ip1000/io.h @@ -0,0 +1,84 @@ +#ifndef _IO_H +#define _IO_H + +#include +#include +#include "ip1000.h" + +/* I/O function */ +static u8_t my_inb(u32_t port) { + u32_t value; + int r; +#ifdef DMA_REG_MODE + value = *(u8_t *)(port); +#else + if ((r = sys_inb(port, &value)) != OK) + printf("ip1000: sys_inb failed: %d\n", r); +#endif + return (u8_t)value; +} +#define ic_in8(port, offset) (my_inb((port) + (offset))) + +static u16_t my_inw(u32_t port) { + u32_t value; + int r; +#ifdef DMA_REG_MODE + value = *(u16_t *)(port); +#else + if ((r = sys_inw(port, &value)) != OK) + printf("ip1000: sys_inw failed: %d\n", r); +#endif + return (u16_t)value; +} +#define ic_in16(port, offset) (my_inw((port) + (offset))) + +static u32_t my_inl(u32_t port) { + u32_t value; + int r; +#ifdef DMA_REG_MODE + value = *(u32_t *)(port); +#else + if ((r = sys_inl(port, &value)) != OK) + printf("ip1000: sys_inl failed: %d\n", r); +#endif + return value; +} +#define ic_in32(port, offset) (my_inl((port) + (offset))) + +static void my_outb(u32_t port, u8_t value) { + int r; +#ifdef DMA_REG_MODE + *(u8_t *)(port) = value; +#else + if ((r = sys_outb(port, value)) != OK) + printf("ip1000: sys_outb failed: %d\n", r); +#endif +} +#define ic_out8(port, offset, value) \ + (my_outb(((port) + (offset)), (value))) + +static void my_outw(u32_t port, u16_t value) { + int r; +#ifdef DMA_REG_MODE + *(u16_t *)(port) = value; +#else + if ((r = sys_outw(port, value)) != OK) + printf("ip1000: sys_outw failed: %d\n", r); +#endif +} +#define ic_out16(port, offset, value) \ + (my_outw(((port) + (offset)), (value))) + +static void my_outl(u16_t port, u32_t value) { + int r; +#ifdef DMA_REG_MODE + *(u32_t *)(port) = value; +#else + if ((r = sys_outl(port, value)) != OK) + printf("ip1000: sys_outl failed: %d\n", r); +#endif +} +#define ic_out32(port, offset, value) \ + (my_outl(((port) + (offset)), (value))) + +#endif diff --git a/minix/drivers/net/ip1000/ip1000.c b/minix/drivers/net/ip1000/ip1000.c index 9eb0e6fc9..11413f3af 100644 --- a/minix/drivers/net/ip1000/ip1000.c +++ b/minix/drivers/net/ip1000/ip1000.c @@ -1,179 +1,13 @@ +#include +#include +#include #include "ip1000.h" +#include "io.h" /* global value */ static ic_driver g_driver; static int g_instance; -/* I/O function */ -static u8_t my_inb(u16_t port) { - u32_t value; - int r; - if ((r = sys_inb(port, &value)) != OK) - printf("IP1000: sys_inb failed: %d\n", r); - return (u8_t)value; -} -#define ic_inb(port, offset) (my_inb((port) + (offset))) - -static u16_t my_inw(u16_t port) { - u32_t value; - int r; - if ((r = sys_inw(port, &value)) != OK) - printf("IP1000: sys_inw failed: %d\n", r); - return (u16_t)value; -} -#define ic_inw(port, offset) (my_inw((port) + (offset))) - -static u32_t my_inl(u16_t port) { - u32_t value; - int r; - if ((r = sys_inl(port, &value)) != OK) - printf("IP1000: sys_inl failed: %d\n", r); - return value; -} -#define ic_inl(port, offset) (my_inl((port) + (offset))) - -static void my_outb(u16_t port, u8_t value) { - int r; - if ((r = sys_outb(port, value)) != OK) - printf("IP1000: sys_outb failed: %d\n", r); -} -#define ic_outb(port, offset, value) (my_outb((port) + (offset), (value))) - -static void my_outw(u16_t port, u16_t value) { - int r; - if ((r = sys_outw(port, value)) != OK) - printf("IP1000: sys_outw failed: %d\n", r); -} -#define ic_outw(port, offset, value) (my_outw((port) + (offset), (value))) - -static void my_outl(u16_t port, u32_t value) { - int r; - if ((r = sys_outl(port, value)) != OK) - printf("IP1000: sys_outl failed: %d\n", r); -} -#define ic_outl(port, offset, value) (my_outl((port) + (offset), (value))) - -static int udelay(int n) { - int i, j; - int ret = 0; - - for (i=0; iic_base_addr; - int i; - - val = IC_EC_READ | (addr & 0xff); - ic_outw(base, IC_REG_EEPROM_CTRL, val); - for (i = 0; i < 100; i++) { - usleep(100000); - data = ic_inw(base, IC_REG_EEPROM_CTRL); - if (!(data & IC_EC_BUSY)) { - ret = ic_inw(base, IC_REG_EEPROM_DATA); - break; - } - } - if (i == 100) - printf("IP1000: Fail to read EEPROM\n"); - return ret; -} - -static int mdio_read(ic_driver *pdev, int phy_id, int phy_reg) { - u16_t bit_data, base = pdev->ic_base_addr; - struct { - u32_t field; - u32_t len; - } p[] = { - {0xffffffff, 32}, {0x01, 2}, {0x02, 2}, - {phy_id, 5}, {phy_reg, 5}, {0x00, 2}, {0x00, 16}, {0x00, 1}}; - int i, j; - u8_t polarity, data; - - polarity = ic_inb(base, IC_REG_PHY_CTRL); - polarity &= (IC_PC_DUPLEX_POLARITY | IC_PC_LINK_POLARITY); - for (j = 0; j < 5; j++) { - for (i = 0; i < p[j].len; i++) { - data = (p[j].field >> (p[j].len - 1 - i)) << 1; - data &= IC_PC_MGMTDATA; - data |= polarity | IC_PC_MGMTDIR; - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_LO | data); - udelay(10); - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_HI | data); - udelay(10); - } - } - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_LO | - (polarity | IC_PC_MGMTDIR)); - udelay(10); - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_HI | - (polarity | IC_PC_MGMTDIR)); - udelay(10); - - ic_outb(base, IC_REG_PHY_CTRL, polarity | IC_PC_MGMTCLK_LO); - udelay(10); - bit_data = ((ic_inb(base, IC_REG_PHY_CTRL) & IC_PC_MGMTDATA) >> 1) & 1; - ic_outb(base, IC_REG_PHY_CTRL, polarity | IC_PC_MGMTCLK_HI); - udelay(10); - - for (i = 0; i < p[6].len; i++) { - ic_outb(base, IC_REG_PHY_CTRL, polarity | IC_PC_MGMTCLK_LO); - udelay(10); - bit_data = ((ic_inb(base, IC_REG_PHY_CTRL) & IC_PC_MGMTDATA) >> 1) & 1; - ic_outb(base, IC_REG_PHY_CTRL, polarity | IC_PC_MGMTCLK_HI); - udelay(10); - p[6].field |= (bit_data << (p[6].len - 1 - i)); - } - - for (i = 0; i < 3; i++) { - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_LO | - (polarity | IC_PC_MGMTDIR)); - udelay(10); - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_HI | - (polarity | IC_PC_MGMTDIR)); - udelay(10); - } - ic_outb(base, IC_REG_PHY_CTRL, polarity | IC_PC_MGMTCLK_LO | IC_PC_MGMTDIR); - - return p[6].field; -} - -static void mdio_write(ic_driver *pdev, int phy_id, int phy_reg, int val) { - u16_t bit_data, base = pdev->ic_base_addr; - struct { - u32_t field; - u32_t len; - } p[] = { - {0xffffffff, 32}, {0x01, 2}, {0x01, 2}, - {phy_id, 5}, {phy_reg, 5}, {0x02, 2}, {val & 0xffff, 16}, {0x00, 1}}; - int i, j; - u8_t polarity, data; - - polarity = ic_inb(base, IC_REG_PHY_CTRL); - polarity &= (IC_PC_DUPLEX_POLARITY | IC_PC_LINK_POLARITY); - for (j = 0; j < 7; j++) { - for (i = 0; i < p[j].len; i++) { - data = (p[j].field >> (p[j].len - 1 - i)) << 1; - data &= IC_PC_MGMTDATA; - data |= polarity | IC_PC_MGMTDIR; - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_LO | data); - udelay(10); - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_HI | data); - udelay(10); - } - } - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_LO | polarity); - udelay(10); - ic_inb(base, IC_REG_PHY_CTRL); - ic_outb(base, IC_REG_PHY_CTRL, IC_PC_MGMTCLK_HI | polarity); - udelay(10); -} - /* driver interface */ static int ic_init(unsigned int instance, ether_addr_t *addr); static void ic_stop(void); @@ -182,20 +16,381 @@ static ssize_t ic_recv(struct netdriver_data *data, size_t max); static int ic_send(struct netdriver_data *data, size_t size); static void ic_intr(unsigned int mask); static void ic_stat(eth_stat_t *stat); -static void ic_alarm(clock_t stamp); +/* internal function */ static int ic_probe(ic_driver *pdev, int instance); static int ic_init_buf(ic_driver *pdev); static int ic_init_hw(ic_driver *pdev, ether_addr_t *addr); static int ic_reset_hw(ic_driver *pdev); -static void ic_power_init(ic_driver *pdev); -static void ic_init_mii(ic_driver *pdev); -static void ic_init_mode(ic_driver *pdev); -static void ic_check_link(ic_driver *pdev); static void ic_conf_addr(ic_driver *pdev, ether_addr_t *addr); static void ic_handler(ic_driver *pdev); static void ic_check_ints(ic_driver *pdev); +/* developer interface */ +static void ic_init_rx_desc(ic_desc *desc, size_t size, phys_bytes dma); +static void ic_init_tx_desc(ic_desc *desc, size_t size, phys_bytes dma); +static int ic_real_reset(u32_t base); +static int ic_init_power(u32_t base); +static int ic_init_mii(u32_t base); +static int ic_init_io(u32_t base); +static void ic_start_rx_tx(u32_t base); +static void ic_get_addr(u32_t base, u8_t *pa); +static int ic_check_link(u32_t base); +static void ic_stop_rx_tx(u32_t base); +static int ic_rx_status_ok(ic_desc *desc); +static int ic_get_rx_len(ic_desc *desc); +static void ic_tx_desc_start(ic_desc *desc, size_t size); +static void ic_wakeup_tx(u32_t base); +static int ic_tx_status_ok(ic_desc *desc); + +/* ======= Developer-defined function ======= */ +/* ====== Self-defined function ======*/ + +static u16_t read_eeprom(u32_t base, int addr) { + u16_t ret, data, val; + int i; + + val = EC_READ | (addr & 0xff); + ic_out16(base, REG_EEPROM_CTRL, val); + for (i = 0; i < 100; i++) { + micro_delay(10000); + data = ic_in16(base, REG_EEPROM_CTRL); + if (!(data & EC_BUSY)) { + ret = ic_in16(base, REG_EEPROM_DATA); + break; + } + } + if (i == 100) + printf("IP1000: Fail to read EEPROM\n"); + return ret; +} + +static u16_t read_phy_reg(u32_t base, int phy_addr, int phy_reg) { + int i, j, fieldlen[8]; + u32_t field[8]; + u8_t data, polar; + + field[0] = 0xffffffff; fieldlen[0] = 32; + field[1] = 0x0001; fieldlen[1] = 2; + field[2] = 0x0002; fieldlen[2] = 2; + field[3] = phy_addr; fieldlen[3] = 5; + field[4] = phy_reg; fieldlen[4] = 5; + field[5] = 0x0000; fieldlen[5] = 2; + field[6] = 0x0000; fieldlen[6] = 16; + field[7] = 0x0000; fieldlen[7] = 1; + + polar = ic_in8(base, REG_PHY_CTRL) & 0x28; + for (i = 0; i < 5; i++) { + for (j = 0; j < fieldlen[i]; j++) { + data = (field[i] >> (fieldlen[i] - j - 1)) << 1; + data = (0x02 & data) | (0x04 | polar); + ic_out8(base, REG_PHY_CTRL, data); + micro_delay(10); + ic_out8(base, REG_PHY_CTRL, (data | 0x01)); + micro_delay(10); + } + } + ic_out8(base, REG_PHY_CTRL, (polar | 0x04)); + micro_delay(10); + ic_out8(base, REG_PHY_CTRL, (polar | 0x05)); + micro_delay(10); + ic_out8(base, REG_PHY_CTRL, polar); + micro_delay(10); + data = ic_in8(base, REG_PHY_CTRL); + ic_out8(base, REG_PHY_CTRL, (polar | 0x01)); + micro_delay(10); + for (i = 0; i < fieldlen[6]; i++) { + ic_out8(base, REG_PHY_CTRL, polar); + micro_delay(10); + data = ((ic_in8(base, REG_PHY_CTRL) & 0x02) >> 1) & 0x01; + ic_out8(base, REG_PHY_CTRL, (polar | 0x01)); + micro_delay(10); + field[6] |= (data << (fieldlen[6] - i - 1)); + } + + for (i = 0; i < 3; i++) { + ic_out8(base, REG_PHY_CTRL, (polar | 0x04)); + micro_delay(10); + ic_out8(base, REG_PHY_CTRL, (polar | 0x05)); + micro_delay(10); + } + ic_out8(base, REG_PHY_CTRL, (polar | 0x04)); + return field[6]; +} + +static void write_phy_reg(u32_t base, int phy_addr, int phy_reg, u16_t val) { + int i, j, fieldlen[8]; + u32_t field[8]; + u8_t data, polar; + + field[0] = 0xffffffff; fieldlen[0] = 32; + field[1] = 0x0001; fieldlen[1] = 2; + field[2] = 0x0001; fieldlen[2] = 2; + field[3] = phy_addr; fieldlen[3] = 5; + field[4] = phy_reg; fieldlen[4] = 5; + field[5] = 0x0002; fieldlen[5] = 2; + field[6] = val; fieldlen[6] = 16; + field[7] = 0x0000; fieldlen[7] = 1; + + polar = ic_in8(base, REG_PHY_CTRL) & 0x28; + for (i = 0; i < 7; i++) { + for (j = 0; j < fieldlen[i]; j++) { + data = (field[i] >> (field[j] - j - 1)) << 1; + data = (0x02 & data) | (0x04 | polar); + ic_out8(base, REG_PHY_CTRL, data); + micro_delay(10); + ic_out8(base, REG_PHY_CTRL, (data | 0x01)); + micro_delay(10); + } + } + for (i = 0; i < fieldlen[7]; i ++) { + ic_out8(base, REG_PHY_CTRL, polar); + micro_delay(10); + field[7] |= ((ic_in8(base, REG_PHY_CTRL) & 0x02) >> 1) + << (fieldlen[7] - i -1); + ic_out8(base, REG_PHY_CTRL, (data | 0x01)); + micro_delay(10); + } +} + +/* ====== Developer interface ======*/ + +/* Intialize Rx descriptor (### RX_DESC_INIT ###) */ +static void ic_init_rx_desc(ic_desc *desc, size_t size, phys_bytes dma) { + desc->status = 0x0000000000000000ULL; + desc->frag_info = (u64_t)dma; + desc->frag_info |= ((u64_t)size << 48) & RFI_FRAG_LEN; +} + +/* Intialize Tx descriptor (### TX_DESC_INIT ###) */ +static void ic_init_tx_desc(ic_desc *desc, size_t size, phys_bytes dma) { + desc->status = TFS_TFD_DONE; + desc->frag_info = (u64_t)dma; +} + +/* Real hardware reset (### RESET_HARDWARE_CAN_FAIL ###) + * -- Return OK means success, Others means failure */ +static int ic_real_reset(u32_t base) { + u32_t data; + data = ic_in32(base, REG_ASIC_CTRL); + data |= AC_RESET_ALL; + ic_out32(base, REG_ASIC_CTRL, data); + micro_delay(10000); + if (ic_in32(base, REG_ASIC_CTRL) & AC_RESET_BUSY) + return -EIO; + return OK; +} + +/* Intialize power (### POWER_INIT_CAN_FAIL ###) + * -- Return OK means success, Others means failure */ +static int ic_init_power(u32_t base) { + u8_t physet; + u32_t mode0, mode1; + + mode0 = read_eeprom(base, 6); + mode1 = ic_in16(base, REG_ASIC_CTRL); + mode1 &= ~(AC_LED_MODE_B1 | AC_LED_MODE | AC_LED_SPEED); + if ((mode0 & 0x03) > 1) + mode1 |= AC_LED_MODE_B1; + if ((mode0 & 0x01) == 1) + mode1 |= AC_LED_MODE; + if ((mode0 & 0x08) == 8) + mode1 |= AC_LED_SPEED; + ic_out32(base, REG_ASIC_CTRL, mode1); + + physet = ic_in8(base, REG_PHY_SET); + physet &= ~(0x07); + physet |= (mode0 & 0x70) >> 4; + ic_out8(base, REG_PHY_SET, physet); + + return OK; +} + +/* Intialize MII interface (### MII_INIT_CAN_FAIL ###) + * -- Return OK means success, Others means failure */ +static int ic_init_mii(u32_t base) { + int i, phyaddr; + u8_t revision; + u16_t phyctrl, cr1000, length, address, value; + u16_t *param; + u32_t status; + + for (i = 0; i < 32; i++) { + phyaddr = (i + 0x01) % 32; + status = read_phy_reg(base, phyaddr, 0x01); + if ((status != 0xffff) && (status != 0)) + break; + } + if (i == 32) + return -EIO; + if (phyaddr != -1) { + cr1000 = read_phy_reg(base, phyaddr, 0x09); + cr1000 |= 0x0700; + write_phy_reg(base, phyaddr, 0x09, cr1000); + phyctrl = read_phy_reg(base, phyaddr, 0x00); + } + + param = &PhyParam[0]; + length = (*param) & 0x00ff; + revision = (u8_t)((*param) >> 8); + param++; + while (length != 0) { + if (g_driver.revision == revision) { + while (length > 1) { + address = *param; + value = *(param + 1); + param += 2; + write_phy_reg(base, phyaddr, address, value); + length -= 4; + } + break; + } + else { + param += length / 2; + length = *param & 0x00ff; + revision = (u8_t)((*param) >> 8); + param++; + } + } + + phyctrl |= 0x8200; + write_phy_reg(base, phyaddr, 0x00, phyctrl); + + return OK; +} + +/* Intialize other hardware I/O registers (### INIT_HARDWARE_IO_CAN_FAIL ###) + * -- Return OK means success, Others means failure */ +static int ic_init_io(u32_t base) { + u32_t mac_ctrl; + + mac_ctrl = ic_in32(base, REG_MAC_CTRL); + mac_ctrl |= (MC_STAT_DISABLE | MC_TX_FC_ENA | MC_RX_FC_ENA); + ic_out32(base, REG_MAC_CTRL, 0x00000000); + ic_out16(base, REG_MAX_FRAME, RX_BUF_SIZE); + ic_out8(base, REG_RX_DMA_PERIOD, 0x01); + ic_out8(base, REG_RX_DMA_UTH, 0x30); + ic_out8(base, REG_RX_DMA_BTH, 0x30); + ic_out8(base, REG_TX_DMA_PERIOD, 0x26); + ic_out8(base, REG_TX_DMA_UTH, 0x04); + ic_out8(base, REG_TX_DMA_BTH, 0x30); + ic_out16(base, REG_FLOW_ON_TH, 0x0740); + ic_out16(base, REG_FLOW_OFF_TH, 0x00bf); + ic_out32(base, REG_MAC_CTRL, mac_ctrl); + return OK; +} + +/* Start Rx/Tx (### START_RX_TX ###) */ +static void ic_start_rx_tx(u32_t base) { + u32_t mac_ctrl; + + mac_ctrl = ic_in32(base, REG_MAC_CTRL); + mac_ctrl |= (MC_RX_ENABLE | MC_TX_ENABLE); + ic_out32(base, REG_MAC_CTRL, mac_ctrl); +} + +/* Get MAC address to the array 'pa' (### GET_MAC_ADDR ###) */ +static void ic_get_addr(u32_t base, u8_t *pa) { + int i, sta_addr[3]; + for (i = 0; i < 3; i++) { + sta_addr[i] = read_eeprom(base, 16 + i); + ic_out16(base, (REG_STA_ADDR0 + i * 2), sta_addr[i]); + } + pa[0] = (u8_t)(ic_in16(base, REG_STA_ADDR0) & 0x00ff); + pa[1] = (u8_t)((ic_in16(base, REG_STA_ADDR0) & 0xff00) >> 8); + pa[2] = (u8_t)(ic_in16(base, REG_STA_ADDR1) & 0x00ff); + pa[3] = (u8_t)((ic_in16(base, REG_STA_ADDR1) & 0xff00) >> 8); + pa[4] = (u8_t)(ic_in16(base, REG_STA_ADDR2) & 0x00ff); + pa[5] = (u8_t)((ic_in16(base, REG_STA_ADDR2) & 0xff00) >> 8); +} + +/* Check link status (### CHECK_LINK ###) + * -- Return LINK_UP or LINK_DOWN */ +static int ic_check_link(u32_t base) { + u8_t phy_ctrl; + u32_t mac_ctrl; + int ret; + char speed[20], duplex[20]; + + phy_ctrl = ic_in8(base, REG_PHY_CTRL); + mac_ctrl = ic_in8(base, REG_MAC_CTRL); + switch (phy_ctrl & PC_LINK_SPEED) { + case PC_LINK_SPEED10: + strcpy(speed, "10Mbps"); + ret = LINK_UP; + break; + case PC_LINK_SPEED100: + strcpy(speed, "100Mbps"); + ret = LINK_UP; + break; + case PC_LINK_SPEED1000: + strcpy(speed, "1000Mbps"); + ret = LINK_UP; + break; + default: + strcpy(speed, "unknown"); + ret = LINK_DOWN; + break; + } + if (phy_ctrl & PC_DUPLEX_STS) { + strcpy(duplex, "full"); + mac_ctrl |= (MC_DUPLEX_SEL | MC_TX_FC_ENA | MC_RX_FC_ENA); + } + else + strcpy(duplex, "half"); + ic_out32(base, REG_MAC_CTRL, mac_ctrl); +#ifdef MY_DEBUG + printf("ip1000: Link speed is %s, %s duplex\n", speed, duplex); +#endif + return ret; +} + +/* Stop Rx/Tx (### STOP_RX_TX ###) */ +static void ic_stop_rx_tx(u32_t base) { + ic_out32(base, REG_ASIC_CTRL, AC_RESET_ALL); +} + +/* Check whether Rx status OK (### CHECK_RX_STATUS_OK ###) + * -- Return TRUE or FALSE */ +static int ic_rx_status_ok(ic_desc *desc) { + if ((desc->status & RFS_NORMAL) == RFS_NORMAL) + return TRUE; + return FALSE; +} + +/* Get Rx data length from descriptor (### GET_RX_LEN ###) + * --- Return the length */ +static int ic_get_rx_len(ic_desc *desc) { + int totlen; + totlen = (u32_t)(desc->status & RFS_FRAME_LEN); + return totlen; +} + +/* Set Tx descriptor in send (### TX_DESC_START ###) */ +static void ic_tx_desc_start(ic_desc *desc, size_t size) { + desc->status = TFS_TFD_DONE; + desc->status |= (u64_t)(TFS_WORD_ALIGN | (TFS_FRAMEID & (g_driver.tx_head)) + | (TFS_FRAG_COUNT & (1 << 24))); + desc->status |= TFS_TX_DMA_INDICATE; + desc->frag_info |= TFI_FRAG_LEN & ((u64_t)((size >= 60 ? size : 60) & + 0xffff) << 48); + desc->status &= (u64_t)(~(TFS_TFD_DONE)); +} + +/* Wake up Tx channel (### WAKE_UP_TX ###) */ +static void ic_wakeup_tx(u32_t base) { + ic_out32(base, REG_DMA_CTRL, 0x00001000); +} + +/* Check whether Tx status OK (### CHECK_TX_STATUS_OK ###) + * -- Return TRUE or FALSE */ +static int ic_tx_status_ok(ic_desc *desc) { + if (desc->status & TFS_TFD_DONE) + return TRUE; + return FALSE; +} + +/* Driver interface table */ static const struct netdriver ic_table = { .ndr_init = ic_init, .ndr_stop = ic_stop, @@ -203,7 +398,7 @@ static const struct netdriver ic_table = { .ndr_recv = ic_recv, .ndr_send = ic_send, .ndr_stat = ic_stat, - .ndr_intr = ic_intr + .ndr_intr = ic_intr, }; int main(int argc, char *argv[]) { @@ -217,28 +412,28 @@ static int ic_init(unsigned int instance, ether_addr_t *addr) { /* Intialize driver data structure */ memset(&g_driver, 0, sizeof(g_driver)); - g_driver.ic_link = IC_LINK_UNKNOWN; - strcpy(g_driver.ic_name, "ip1000#0"); - g_driver.ic_name[7] += instance; + g_driver.link = LINK_UNKNOWN; + strcpy(g_driver.name, "netdriver#0"); + g_driver.name[10] += instance; g_instance = instance; /* Probe the device */ if (ic_probe(&g_driver, instance)) { - printf("IP1000: Device is not found\n"); + printf("ip1000: Device is not found\n"); ret = -ENODEV; goto err_probe; } /* Allocate and initialize buffer */ if (ic_init_buf(&g_driver)) { - printf("IP1000: Fail to initialize buffer\n"); + printf("ip1000: Fail to initialize buffer\n"); ret = -ENODEV; goto err_init_buf; } /* Intialize hardware */ if (ic_init_hw(&g_driver, addr)) { - printf("IP1000: Find to initialize hardware\n"); + printf("ip1000: Fail to initialize hardware\n"); ret = -EIO; goto err_init_hw; } @@ -247,13 +442,13 @@ static int ic_init(unsigned int instance, ether_addr_t *addr) { sys_setalarm(sys_hz(), 0); /* Clear send and recv flag */ - g_driver.ic_send_flag = FALSE; - g_driver.ic_recv_flag = FALSE; + g_driver.send_flag = FALSE; + g_driver.recv_flag = FALSE; return 0; err_init_hw: - free_contig(g_driver.ic_buf, g_driver.ic_buf_size); + free_contig(g_driver.buf, g_driver.buf_size); err_init_buf: err_probe: return ret; @@ -261,10 +456,11 @@ err_probe: /* Match the device and get base address */ static int ic_probe(ic_driver *pdev, int instance) { - int devind; + int devind, ioflag; u16_t cr, vid, did; - u32_t bar; + u32_t bar, size; u8_t irq, rev; + u8_t *reg; /* Find pci device */ pci_init(); @@ -282,25 +478,41 @@ static int ic_probe(ic_driver *pdev, int instance) { pci_attr_w16(devind, PCI_CR, cr | PCI_CR_MAST_EN); /* Get base address */ - bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; - if (bar < 0x400) { - printf("IP1000: Base address is not properly configured\n"); +#ifdef DMA_REG_MODE + if (pci_get_bar(devind, PCI_BAR, &base, &size, &ioflag)) { + printf("ip1000: Fail to get PCI BAR\n"); return -EIO; } - pdev->ic_base_addr = bar; + if (ioflag) { + printf("ip1000: PCI BAR is not for memory\n"); + return -EIO; + } + if ((reg = vm_map_phys(SELF, (void *)base, size)) == MAP_FAILED) { + printf("ip1000: Fail to map hardware registers from PCI\n"); + return -EIO; + } + pdev->base_addr = (u32_t)reg; +#else + bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; + if (bar < 0x400) { + printf("ip1000: Base address is not properly configured\n"); + return -EIO; + } + pdev->base_addr = bar; +#endif /* Get irq number */ irq = pci_attr_r8(devind, PCI_ILR); - pdev->ic_irq = irq; + pdev->irq = irq; /* Get revision ID */ rev = pci_attr_r8(devind, PCI_REV); - pdev->ic_revision = rev; + pdev->revision = rev; -#ifdef IP1000_DEBUG - printf("IP1000: Base address is 0x%08x\n", pdev->ic_base_addr); - printf("IP1000: IRQ number is 0x%08x\n", pdev->ic_irq); - printf("IP1000: Revision ID is 0x%08x\n", pdev->ic_revision); +#ifdef MY_DEBUG + printf("ip1000: Base address is 0x%08x\n", pdev->base_addr); + printf("ip1000: IRQ number is 0x%02x\n", pdev->irq); + printf("ip1000: Revision ID is 0x%02x\n", pdev->revision); #endif return 0; @@ -313,96 +525,90 @@ static int ic_init_buf(ic_driver *pdev) { phys_bytes buf_dma, next; char *buf; int i; - u64_t frag_size; /* Build Rx and Tx descriptor buffer */ - rx_desc_size = IC_RX_DESC_NUM * sizeof(ic_desc); - tx_desc_size = IC_TX_DESC_NUM * sizeof(ic_desc); + rx_desc_size = RX_DESC_NUM * sizeof(ic_desc); + tx_desc_size = TX_DESC_NUM * sizeof(ic_desc); /* Allocate Rx and Tx buffer */ - tx_buf_size = IC_TX_BUF_SIZE; + tx_buf_size = TX_BUF_SIZE; if (tx_buf_size % 4) tx_buf_size += 4 - (tx_buf_size % 4); - rx_buf_size = IC_RX_BUF_SIZE; - if (rx_buf_size % 4) - rx_buf_size += 4 - (rx_buf_size % 4); + rx_buf_size = RX_BUF_SIZE; tot_buf_size = rx_desc_size + tx_desc_size; - tot_buf_size += IC_TX_DESC_NUM * tx_buf_size + IC_RX_DESC_NUM * rx_buf_size; + tot_buf_size += TX_DESC_NUM * tx_buf_size + RX_DESC_NUM * rx_buf_size; if (tot_buf_size % 4096) tot_buf_size += 4096 - (tot_buf_size % 4096); if (!(buf = alloc_contig(tot_buf_size, 0, &buf_dma))) { - printf("IP1000: Fail to allocate memory!\n"); + printf("ip1000: Fail to allocate memory\n"); return -ENOMEM; } - pdev->ic_buf_size = tot_buf_size; - pdev->ic_buf = buf; + pdev->buf_size = tot_buf_size; + pdev->buf = buf; /* Rx descriptor */ - pdev->ic_rx_desc = (ic_desc *)buf; - pdev->ic_rx_desc_dma = buf_dma; + pdev->rx_desc = (ic_desc *)buf; + pdev->rx_desc_dma = buf_dma; memset(buf, 0, rx_desc_size); buf += rx_desc_size; buf_dma += rx_desc_size; /* Tx descriptor */ - pdev->ic_tx_desc = (ic_desc *)buf; - pdev->ic_tx_desc_dma = buf_dma; + pdev->tx_desc = (ic_desc *)buf; + pdev->tx_desc_dma = buf_dma; memset(buf, 0, tx_desc_size); buf += tx_desc_size; buf_dma += tx_desc_size; /* Rx buffer assignment */ - desc = pdev->ic_rx_desc; - next = pdev->ic_rx_desc_dma; - for (i = 0; i < IC_RX_DESC_NUM; i++) { + desc = pdev->rx_desc; + next = pdev->rx_desc_dma; + for (i = 0; i < RX_DESC_NUM; i++) { /* Set Rx buffer */ - pdev->ic_rx[i].buf_dma = buf_dma; - pdev->ic_rx[i].buf = buf; + pdev->rx[i].buf_dma = buf_dma; + pdev->rx[i].buf = buf; buf_dma += rx_buf_size; buf += rx_buf_size; /* Set Rx descriptor */ - frag_size = (u64_t)rx_buf_size; - desc->status = 0x0000000000000000ULL; - desc->frag_info = (u64_t)(pdev->ic_rx[i].buf_dma); - desc->frag_info |= (u64_t)((frag_size << 48) & IC_RFI_FRAG_LEN); - if (i == (IC_RX_DESC_NUM - 1)) - desc->next_desc = (u64_t)(pdev->ic_rx_desc_dma); + /* ### RX_DESC_INIT ### */ + ic_init_rx_desc(desc, rx_buf_size, pdev->rx[i].buf_dma); + if (i == (RX_DESC_NUM - 1)) + desc->next = pdev->rx_desc_dma; else { next += sizeof(ic_desc); - desc->next_desc = (u64_t)next; + desc->next = next; desc++; } } /* Tx buffer assignment */ - desc = pdev->ic_tx_desc; - next = pdev->ic_tx_desc_dma; - for (i = 0; i < IC_TX_DESC_NUM; i++) { + desc = pdev->tx_desc; + next = pdev->tx_desc_dma; + for (i = 0; i < TX_DESC_NUM; i++) { /* Set Tx buffer */ - pdev->ic_tx[i].busy = 0; - pdev->ic_tx[i].buf_dma = buf_dma; - pdev->ic_tx[i].buf = buf; + pdev->tx[i].busy = 0; + pdev->tx[i].buf_dma = buf_dma; + pdev->tx[i].buf = buf; buf_dma += tx_buf_size; buf += tx_buf_size; /* Set Rx descriptor */ - desc->status = IC_TFS_TFD_DONE; - desc->frag_info = (u64_t)(pdev->ic_tx[i].buf_dma); - if (i == (IC_TX_DESC_NUM - 1)) - desc->next_desc = (u64_t)(pdev->ic_tx_desc_dma); + /* ### TX_DESC_INIT ### */ + ic_init_tx_desc(desc, tx_buf_size, pdev->tx[i].buf_dma); + if (i == (TX_DESC_NUM - 1)) + desc->next = pdev->tx_desc_dma; else { next += sizeof(ic_desc); - desc->next_desc = (u64_t)next; + desc->next = next; desc++; } } - pdev->ic_tx_busy_num = 0; - pdev->ic_tx_head = 0; - pdev->ic_tx_tail = 0; - pdev->ic_rx_head = 0; - pdev->ic_tx_alive = FALSE; + pdev->tx_busy_num = 0; + pdev->tx_head = 0; + pdev->tx_tail = 0; + pdev->rx_head = 0; return 0; } @@ -411,24 +617,24 @@ static int ic_init_buf(ic_driver *pdev) { static int ic_init_hw(ic_driver *pdev, ether_addr_t *addr) { int r, ret; - /* Set the interrupt handler */ - pdev->ic_hook = pdev->ic_irq; - if ((r = sys_irqsetpolicy(pdev->ic_irq, 0, &pdev->ic_hook)) != OK) { - printf("IP1000: Fail to set IRQ policy: %d\n", r); + /* Set the OS interrupt handler */ + pdev->hook = pdev->irq; + if ((r = sys_irqsetpolicy(pdev->irq, 0, &pdev->hook)) != OK) { + printf("ip1000: Fail to set OS IRQ policy: %d\n", r); ret = -EFAULT; goto err_irq_policy; } /* Reset hardware */ if (ic_reset_hw(pdev)) { - printf("IP1000: Fail to reset the hardware\n"); + printf("ip1000: Fail to reset the device\n"); ret = -EIO; - goto err_reset; + goto err_reset_hw; } - /* Enable IRQ */ - if ((r = sys_irqenable(&pdev->ic_hook)) != OK) { - printf("IP1000: Fail to enable IRQ: %d\n", r); + /* Enable OS IRQ */ + if ((r = sys_irqenable(&pdev->hook)) != OK) { + printf("ip1000: Fail to enable OS IRQ: %d\n", r); ret = -EFAULT; goto err_irq_enable; } @@ -436,364 +642,196 @@ static int ic_init_hw(ic_driver *pdev, ether_addr_t *addr) { /* Configure MAC address */ ic_conf_addr(pdev, addr); + /* Detect link status */ + pdev->link = ic_check_link(pdev->base_addr); +#ifdef MY_DEBUG + if (pdev->link) + printf("ip1000: Link up\n"); + else + printf("ip1000: Link down\n"); +#endif + return 0; +err_reset_hw: err_irq_enable: -err_reset: err_irq_policy: return ret; } /* Reset hardware */ static int ic_reset_hw(ic_driver *pdev) { - u16_t base = pdev->ic_base_addr; - u32_t dl, mac_ctrl; + u32_t base = pdev->base_addr; + int ret; /* Reset the chip */ - dl = ic_inl(base, IC_REG_ASIC_CTRL); - dl |= IC_AC_RESET_ALL; - ic_outl(base, IC_REG_ASIC_CTRL, dl); - usleep(10000); - dl = ic_inl(base, IC_REG_ASIC_CTRL); - if (dl & IC_AC_RESET_BUSY) { -#ifdef IP1000_DEBUG - printf("IP1000: Fail to completely reset\n"); -#endif - return -EIO; + /* ### RESET_HARDWARE_CAN_FAIL ### */ + if (ic_real_reset(base)) { + printf("ip1000: Fail to reset the hardware\n"); + ret = -EIO; + goto err_real_reset; } -#ifdef IP1000_DEBUG - printf("IP1000: Reset successfully\n"); + + /* Initialize power */ + /* ### POWER_INIT_CAN_FAIL ### */ + if (ic_init_power(base)) { + printf("ip1000: Fail to initialize power\n"); + ret = -EIO; + goto err_init_power; + } + + /* Initialize MII interface */ + /* ### MII_INIT_CAN_FAIL ### */ + if (ic_init_mii(base)) { + printf("ip1000: Fail to initialize MII interface\n"); + ret = -EIO; + goto err_init_mii; + } + + /* Initialize hardware I/O registers */ + /* ### SET_RX_DESC_REG ### */ + if (ic_init_io(base)) { + printf("ip1000: Fail to initialize I/O registers\n"); + ret = -EIO; + goto err_init_io; + } + + /* Set Rx/Tx descriptor into register */ + /* ### SET_RX_DESC_REG ### */ + ic_out32(base, REG_RX_DESC_BASEL, pdev->rx_desc_dma); +#ifdef DESC_BASE_DMA64 + ic_out32(base, REG_RX_DESC_BASEU, 0x00000000); #endif - - /* Let power registers into sane state */ - ic_power_init(pdev); - - /* Initialize MII registers */ - ic_init_mii(pdev); - - /* Initialize hardware mode */ - ic_init_mode(pdev); - - /* Set Rx/Tx descriptor base address */ - ic_outl(base, IC_REG_RX_DESC0, pdev->ic_rx_desc_dma); - ic_outl(base, IC_REG_RX_DESC1, 0x00000000); - ic_outl(base, IC_REG_TX_DESC0, pdev->ic_tx_desc_dma); - ic_outl(base, IC_REG_TX_DESC1, 0x00000000); - -#ifdef IP1000_DEBUG - dl = ic_inl(base, IC_REG_RX_DESC0); - printf("IP1000: Rx descriptor DMA address is: 0x%08x\n", dl); - dl = ic_inl(base, IC_REG_TX_DESC0); - printf("IP1000: Tx descriptor DMA address is: 0x%08x\n", dl); + /* ### SET_TX_DESC_REG ### */ + ic_out32(base, REG_TX_DESC_BASEL, pdev->tx_desc_dma); +#ifdef DESC_BASE_DMA64 + ic_out32(base, REG_TX_DESC_BASEU, 0x00000000); #endif /* Enable interrupts */ - ic_outw(base, IC_REG_INTR_ENA, IC_IR_COMMON); + /* ### ENABLE_INTR ### */ + ic_out16(base, REG_IMR, INTR_IMR_ENABLE); - /* Start Rx and Tx */ - mac_ctrl = ic_inl(base, IC_REG_MAC_CTRL); - mac_ctrl |= (IC_MC_RX_ENABLE | IC_MC_TX_ENABLE); - ic_outl(base, IC_REG_MAC_CTRL, mac_ctrl); + /* Start the device, Rx and Tx */ + /* ### START_RX_TX ### */ + ic_start_rx_tx(base); return 0; -} -/* Initialize power registers */ -static void ic_power_init(ic_driver *pdev) { - u8_t physet; - u16_t base = pdev->ic_base_addr; - u32_t mode; - - /* Read LED mode from EEPROM and set LED mode*/ - pdev->ic_led_mode = read_eeprom(pdev, 6); - mode = ic_inl(base, IC_REG_ASIC_CTRL); - mode &= ~(IC_AC_LED_MODE_BIT1 | IC_AC_LED_MODE | IC_AC_LED_SPEED); - if ((pdev->ic_led_mode & 0x03) > 1) - mode |= IC_AC_LED_MODE_BIT1; - if ((pdev->ic_led_mode & 0x01) == 1) - mode |= IC_AC_LED_MODE; - if ((pdev->ic_led_mode & 0x08) == 8) - mode |= IC_AC_LED_SPEED; - ic_outl(base, IC_REG_ASIC_CTRL, mode); - - /* Set physet register*/ - physet = ic_inb(base, IC_REG_PHY_SET); - physet &= ~(0x07); - physet |= ((pdev->ic_led_mode & 0x70) >> 4); - ic_outb(base, IC_REG_PHY_SET, physet); -} - -/* Initialize MII registers */ -static void ic_init_mii(ic_driver *pdev) { - u8_t revision; - u16_t base = pdev->ic_base_addr; - u32_t status; - u16_t length, address, value, mii_phyctrl, mii_1000cr; - const u16_t *phy_param; - int i, phyaddr; - - /* Read MII physical address */ - for (i = 0; i < 32; i++) { - phyaddr = (0x01 + i) % 32; - status = mdio_read(pdev, phyaddr, 0x01); - if ((status != 0xffff) && (status != 0)) - break; - } - if (i == 32) { - printf("IP1000: Fail to read MII phyical address\n"); - return; - } -#ifdef IP1000_DEBUG - printf("IP1000: MII Physical address is %d\n", phyaddr); -#endif - - mii_1000cr = mdio_read(pdev, phyaddr, 0x09); - mii_1000cr |= 0x0700; - mdio_write(pdev, phyaddr, 0x09, mii_1000cr); - mii_phyctrl = mdio_read(pdev, phyaddr, 0x00); - - phy_param = &DefaultPhyParam[0]; - length = *phy_param & 0x00ff; - revision = (u8_t)((*phy_param) >> 8); - phy_param++; - while (length != 0) { - if (pdev->ic_revision == revision) { - while (length > 1) { - address = *phy_param; - value = *(phy_param + 1); - phy_param += 2; - mdio_write(pdev, phyaddr, address, value); - length -= 4; - } - break; - } - else { - phy_param += length / 2; - length = *phy_param & 0x00ff; - revision = (u8_t)((*phy_param) >> 8); - phy_param++; - } - } - - mii_phyctrl |= 0x8200; - mdio_write(pdev, phyaddr, 0x00, mii_phyctrl); -} - -/* Intialize hardware mode */ -static void ic_init_mode(ic_driver *pdev) { - u16_t base = pdev->ic_base_addr; - u32_t mac_ctrl, mac_ctrl1; - - /* Disable interrupt first */ - ic_outw(base, IC_REG_INTR_ENA, 0x0000); - - /* Configure MAC register */ - mac_ctrl = ic_inl(base, IC_REG_MAC_CTRL); - mac_ctrl1 = mac_ctrl | IC_MC_STAT_DISABLE; - if (mac_ctrl & IC_MC_TX_ENABLED) - mac_ctrl1 |= IC_MC_TX_ENABLE; - if (mac_ctrl & IC_MC_RX_ENABLED) - mac_ctrl1 |= IC_MC_RX_ENABLE; - ic_outl(base, IC_REG_MAC_CTRL, (mac_ctrl & (IC_MC_RX_DISABLE | - IC_MC_TX_DISABLE))); - ic_outl(base, IC_REG_MAC_CTRL, 0x00000000); - - /* Set ic Rx mode */ - ic_mode(0x00); - - /* Set RX max frame size */ - ic_outw(base, IC_REG_MAX_FRAME, IC_RX_BUF_SIZE); - - /* Set some values */ - ic_outb(base, IC_REG_RX_DMA_PERIOD, 0x01); - ic_outb(base, IC_REG_RX_DMA_UTH, 0x30); - ic_outb(base, IC_REG_RX_DMA_BTH, 0x30); - ic_outb(base, IC_REG_TX_DMA_PERIOD, 0x26); - ic_outb(base, IC_REG_TX_DMA_UTH, 0x04); - ic_outb(base, IC_REG_TX_DMA_BTH, 0x30); - ic_outw(base, IC_REG_FLOW_ON_TH, 0x0740); - ic_outw(base, IC_REG_FLOW_OFF_TH, 0x00bf); - - ic_outw(base, IC_REG_DEBUG_CTRL, ic_inw(base, IC_REG_DEBUG_CTRL) | 0x0200); - ic_outw(base, IC_REG_DEBUG_CTRL, ic_inw(base, IC_REG_DEBUG_CTRL) | 0x0010); - ic_outw(base, IC_REG_DEBUG_CTRL, ic_inw(base, IC_REG_DEBUG_CTRL) | 0x0020); - - ic_outl(base, 0x98, 0x0fffffff); - - /* Restore MAC register */ - ic_outl(base, IC_REG_MAC_CTRL, mac_ctrl1); - - /* Check link state */ - ic_check_link(pdev); -} - -/* Check link state */ -static void ic_check_link(ic_driver *pdev) { - u8_t phy_ctrl; - u16_t base = pdev->ic_base_addr; - u32_t mac_ctrl; - char speed[20], duplex[20]; - - phy_ctrl = ic_inb(base, IC_REG_PHY_CTRL); - mac_ctrl = ic_inl(base, IC_REG_MAC_CTRL); - - /* Check link speed */ - switch (phy_ctrl & IC_PC_LINK_SPEED) { - case IC_PC_LINK_SPEED10: - strcpy(speed, "10Mbps"); - pdev->ic_link = IC_LINK_UP; - break; - case IC_PC_LINK_SPEED100: - strcpy(speed, "100Mbps"); - pdev->ic_link = IC_LINK_UP; - break; - case IC_PC_LINK_SPEED1000: - strcpy(speed, "1000Mbps"); - pdev->ic_link = IC_LINK_UP; - break; - default: - strcpy(speed, "unknown"); - pdev->ic_link = IC_LINK_DOWN; - break; - } - - /* Check link duplex */ - if (phy_ctrl & IC_PC_DUPLEX_STS) { - strcpy(duplex, "full"); - mac_ctrl |= (IC_MC_DUPLEX_SEL | IC_MC_TX_FC_ENA | IC_MC_RX_FC_ENA); - } - else - strcpy(duplex, "half"); - -#ifdef IP1000_DEBUG - printf("IP1000: Link speed is %s, %s duplex\n", speed, duplex); -#endif - - ic_outl(base, IC_REG_MAC_CTRL, mac_ctrl); +err_init_io: +err_init_mii: +err_init_power: +err_real_reset: + return ret; } /* Configure MAC address */ static void ic_conf_addr(ic_driver *pdev, ether_addr_t *addr) { - u16_t dw, base = pdev->ic_base_addr; - int i; + u8_t pa[6]; + u32_t base = pdev->base_addr; - /* Read station address from EEPROM */ - for (i = 0; i< 3; i++) - pdev->sta_addr[i] = read_eeprom(pdev, 16 + i); - for (i = 0; i < 3; i++) - ic_outw(base, IC_REG_STA_ADDR0 + i * 2, pdev->sta_addr[i]); - - /* Read MAC address */ - addr->ea_addr[0] = (u8_t)(ic_inw(base, IC_REG_STA_ADDR0) & 0x00ff); - addr->ea_addr[1] = (u8_t)((ic_inw(base, IC_REG_STA_ADDR0) & 0xff00) >> 8); - addr->ea_addr[2] = (u8_t)(ic_inw(base, IC_REG_STA_ADDR1) & 0x00ff); - addr->ea_addr[3] = (u8_t)((ic_inw(base, IC_REG_STA_ADDR1) & 0xff00) >> 8); - addr->ea_addr[4] = (u8_t)(ic_inw(base, IC_REG_STA_ADDR2) & 0x00ff); - addr->ea_addr[5] = (u8_t)((ic_inw(base, IC_REG_STA_ADDR2) & 0xff00) >> 8); - -#ifdef IP1000_DEBUG - printf("IP1000: Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n", - addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2], - addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5]); + /* Get MAC address */ + /* ### GET_MAC_ADDR ### */ + ic_get_addr(base, pa); + addr->ea_addr[0] = pa[0]; + addr->ea_addr[1] = pa[1]; + addr->ea_addr[2] = pa[2]; + addr->ea_addr[3] = pa[3]; + addr->ea_addr[4] = pa[4]; + addr->ea_addr[5] = pa[5]; +#ifdef MY_DEBUG + printf("ip1000: Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n", + addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2], + addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5]); #endif } /* Stop the driver */ static void ic_stop(void) { - u16_t base = g_driver.ic_base_addr; + u32_t base = g_driver.base_addr; /* Free Rx and Tx buffer*/ - free_contig(g_driver.ic_buf, g_driver.ic_buf_size); + free_contig(g_driver.buf, g_driver.buf_size); - /* Stop IRQ, Rx and Tx */ - ic_outw(base, IC_REG_INTR_ENA, 0x0000); - ic_outl(base, IC_REG_ASIC_CTRL, IC_AC_RESET_ALL); + /* Stop interrupt */ + /* ### DISABLE_INTR ### */ + ic_out16(base, REG_IMR, INTR_IMR_DISABLE); + + /* Stop Rx/Tx */ + /* ### STOP_RX_TX ### */ + ic_stop_rx_tx(base); } /* Set driver mode */ static void ic_mode(unsigned int mode) { ic_driver *pdev = &g_driver; - u16_t base = pdev->ic_base_addr; - u8_t rm; + u32_t base = pdev->base_addr; + u8_t rcr; - pdev->ic_mode = mode; - ic_outl(base, IC_REG_HASH_TLB0, 0x00000000); - ic_outl(base, IC_REG_HASH_TLB1, 0x00000000); + pdev->mode = mode; - rm = ic_inb(base, IC_REG_RX_MODE); - rm &= ~(IC_RM_UNICAST | IC_RM_MULTICAST | IC_RM_BROADCAST | - IC_RM_ALLFRAMES); - if (pdev->ic_mode & NDEV_PROMISC) - rm |= IC_RM_ALLFRAMES; - if (pdev->ic_mode & NDEV_BROAD) - rm |= IC_RM_BROADCAST; - if (pdev->ic_mode & NDEV_MULTI) - rm |= IC_RM_MULTICAST; - rm |= (IC_RM_UNICAST | IC_RM_BROADCAST); - ic_outb(base, IC_REG_RX_MODE, rm); + /* ### READ_RCR ### */ + rcr = ic_in8(base, REG_RCR); + rcr &= ~(RCR_UNICAST | RCR_MULTICAST | RCR_BROADCAST); + if (pdev->mode & NDEV_PROMISC) + rcr |= RCR_UNICAST | RCR_MULTICAST; + if (pdev->mode & NDEV_BROAD) + rcr |= RCR_BROADCAST; + if (pdev->mode & NDEV_MULTI) + rcr |= RCR_MULTICAST; + rcr |= RCR_UNICAST; + /* ### WRITE_RCR ### */ + ic_out8(base, REG_RCR, rcr); } /* Receive data */ static ssize_t ic_recv(struct netdriver_data *data, size_t max) { ic_driver *pdev = &g_driver; u32_t totlen, packlen; - u64_t rxstat; ic_desc *desc; int index, i; - index = pdev->ic_rx_head; - desc = pdev->ic_rx_desc; + index = pdev->rx_head; + desc = pdev->rx_desc; desc += index; - /* Manage Rx buffer */ - rxstat = desc->status; - - if ((rxstat & IC_RFS_NORMAL) != IC_RFS_NORMAL) + /* Check whether the receiving is OK */ + /* ### CHECK_RX_STATUS_OK ### */ + if (ic_rx_status_ok(desc) != TRUE) return SUSPEND; - if (rxstat & IC_RFS_ALL_ERR) { -#ifdef IP1000_DEBUG - printf("IP1000: Rx error: 0x%016llx\n", rxstat); -#endif - if (rxstat & IC_RFS_OVERRUN) { -#ifdef IP1000_DEBUG - printf("IP1000: Rx buffer overflow\n"); -#endif - pdev->ic_stat.ets_fifoOver++; - } - if (rxstat & IC_RFS_ALIGN_ERR) { -#ifdef IP1000_DEBUG - printf("IP1000: Rx frames not align\n"); -#endif - pdev->ic_stat.ets_frameAll++; - } - } + /* Check Rx status error */ + /* ### CHECK_RX_STATUS_ERROR ### */ + if (desc->status & DESC_STATUS_RX_RECV_ERR) + printf("ip1000: Rx error\n"); /* Get data length */ - totlen = (u32_t)(rxstat & IC_RFS_FRAME_LEN); + /* ### Get Rx data length ### */ + totlen = ic_get_rx_len(desc); if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) { - printf("IP1000: Bad data length: %d\n", totlen); + printf("ip1000: Bad data length: %d\n", totlen); panic(NULL); } - /* Do not need to substract CRC to get packet */ packlen = totlen; + if (packlen > max) + packlen = max; /* Copy data to user */ - netdriver_copyout(data, 0, pdev->ic_rx[index].buf, packlen); - pdev->ic_stat.ets_packetR++; + netdriver_copyout(data, 0, pdev->rx[index].buf, packlen); + pdev->stat.ets_packetR++; /* Set Rx descriptor status */ - desc->status = 0x0000000000000000ULL; - if (index == IC_RX_DESC_NUM - 1) + /* ### SET_RX_STATUS_INTR ### */ + desc->status = DESC_STATUS_RX_RECV_CLEAR; + if (index == RX_DESC_NUM - 1) index = 0; else index++; + pdev->rx_head = index; - pdev->ic_rx_head = index; - -#ifdef IP1000_DEBUG - printf("IP1000: Successfully receive a packet, length = %d\n", packlen); +#ifdef MY_DEBUG + printf("ip1000: Successfully receive a packet, length = %d\n", packlen); #endif return packlen; @@ -804,39 +842,34 @@ static int ic_send(struct netdriver_data *data, size_t size) { ic_driver *pdev = &g_driver; ic_desc *desc; int tx_head, i; - u16_t base = pdev->ic_base_addr; + u32_t base = pdev->base_addr; - tx_head = pdev->ic_tx_head; - desc = pdev->ic_tx_desc; + tx_head = pdev->tx_head; + desc = pdev->tx_desc; desc += tx_head; - if (pdev->ic_tx[tx_head].busy) + if (pdev->tx[tx_head].busy) return SUSPEND; /* Copy data from user */ - netdriver_copyin(data, 0, pdev->ic_tx[tx_head].buf, size); + netdriver_copyin(data, 0, pdev->tx[tx_head].buf, size); /* Set busy */ - pdev->ic_tx[tx_head].busy = TRUE; - pdev->ic_tx_busy_num++; + pdev->tx[tx_head].busy = TRUE; + pdev->tx_busy_num++; /* Set Tx descriptor status */ - desc->status = IC_TFS_TFD_DONE; - desc->status |= (u64_t)(IC_TFS_WORD_ALIGN | (IC_TFS_FRAMEID & tx_head) | - (IC_TFS_FRAG_COUNT & (1 << 24))); - desc->status |= IC_TFS_TX_DMA_INDICATE; - desc->frag_info |= IC_TFI_FRAG_LEN & - ((u64_t)((size >= 60 ? size : 60) & 0xffff) << 48); - desc->status &= (u64_t)(~(IC_TFS_TFD_DONE)); - - if (tx_head == IC_TX_DESC_NUM - 1) + /* ### TX_DESC_START ### */ + ic_tx_desc_start(desc, size); + if (tx_head == TX_DESC_NUM - 1) tx_head = 0; else tx_head++; - pdev->ic_tx_head = tx_head; + pdev->tx_head = tx_head; /* Wake up transmit channel */ - ic_outl(base, IC_REG_DMA_CTRL, IC_DC_TX_POLL); + /* ### WAKE_UP_TX ### */ + ic_wakeup_tx(base); return 0; } @@ -849,8 +882,8 @@ static void ic_intr(unsigned int mask) { ic_handler(&g_driver); /* Reenable interrupts for this hook */ - if ((s = sys_irqenable(&g_driver.ic_hook)) != OK) - printf("IP1000: Cannot enable interrupts: %d\n", s); + if ((s = sys_irqenable(&g_driver.hook)) != OK) + printf("ip1000: Cannot enable OS interrupts: %d\n", s); /* Perform tasks based on the flagged conditions */ ic_check_ints(&g_driver); @@ -858,99 +891,116 @@ static void ic_intr(unsigned int mask) { /* Real handler interrupt */ static void ic_handler(ic_driver *pdev) { - u16_t intr_status, base = pdev->ic_base_addr; + u32_t base = pdev->base_addr; + u16_t intr_status; int flag = 0, tx_head, tx_tail; ic_desc *desc; /* Get interrupt status */ - intr_status = ic_inw(base, IC_REG_INTR_STS_ACK); + /* ### GET_INTR_STATUS ### */ + intr_status = ic_in16(base, REG_ISR); - /* Clear interrupt */ - ic_outw(base, IC_REG_INTR_ENA, IC_IR_COMMON); + /* Clear interrupt */ + /* ### CLEAR_INTR ### */ + ic_out16(base, REG_ISR, intr_status & INTR_ISR_CLEAR); - /* Check link status */ - if (intr_status & IC_IR_LINK_EVENT) { -#ifdef IP1000_DEBUG - printf("IP1000: Link state change!\n"); -#endif - flag++; - ic_check_link(pdev); - } + /* Enable interrupt */ + /* ### ENABLE_INTR ### */ + ic_out16(base, REG_IMR, INTR_IMR_ENABLE); /* Check interrupt error */ - if (intr_status & IC_IR_HOST_ERR) - printf("IP1000: Host error in interrupt: 0x%04x\n", intr_status); - if (intr_status & IC_IR_RFD_END) - printf("IP1000: Rx list end in interrupt: 0x%04x\n", intr_status); - if (intr_status & IC_IR_MAC_CTRL) - printf("IP1000: MAC control frame in interrupt: 0x%04x\n", intr_status); - if (intr_status & IC_IR_RX_EARLY) - printf("IP1000: Rx early in interrupt: 0x%04x\n", intr_status); - if (intr_status & IC_IR_UPDATE_STS) - printf("IP1000: Status update in interrupt: 0x%04x\n", intr_status); + /* ### CHECK_INTR_ERROR ### */ + if (intr_status & INTR_ISR_ERR) { + printf("ip1000: interrupt error\n"); + return; + } - /* Check interrupt status */ - if (intr_status & IC_IR_RX_DMA_DONE) { - pdev->ic_recv_flag = TRUE; + /* Check link status */ + /* ### CHECK_LINK_INTR ### */ + if (intr_status & INTR_ISR_LINK_EVENT) { + pdev->link = ic_check_link(base); +#ifdef MY_DEBUG + printf("ip1000: Link state change\n"); +#endif flag++; } - if (intr_status & IC_IR_TX_DMA_DONE) { - pdev->ic_send_flag = TRUE; + + /* Check Rx request status */ + /* ### CHECK_RX_INTR ### */ + if (intr_status & INTR_ISR_RX_DONE) { + pdev->recv_flag = TRUE; + flag++; + } + + /* Check Tx request status */ + /* ### CHECK_TX_INTR ### */ + if (intr_status & INTR_ISR_TX_DONE) { + pdev->send_flag = TRUE; flag++; /* Manage Tx Buffer */ - tx_head = pdev->ic_tx_head; - tx_tail = pdev->ic_tx_tail; + tx_head = pdev->tx_head; + tx_tail = pdev->tx_tail; while (tx_tail != tx_head) { - desc = pdev->ic_tx_desc; + desc = pdev->tx_desc; desc += tx_tail; - if (!pdev->ic_tx[tx_tail].busy) - printf("IP1000: Strange, buffer not busy?\n"); + if (!pdev->tx[tx_tail].busy) + printf("ip1000: Strange, buffer not busy?\n"); - if (!(desc->status & IC_TFS_TFD_DONE)) + /* Check whether the transmiting is OK */ + /* ### CHECK_TX_STATUS_OK ### */ + if (ic_tx_status_ok(desc) != TRUE) break; - pdev->ic_stat.ets_packetT++; - pdev->ic_tx[tx_tail].busy = FALSE; - pdev->ic_tx_busy_num--; + /* Check Tx status error */ + /* ### CHECK_TX_STATUS_ERROR ### */ + if (desc->status & DESC_STATUS_TX_SEND_ERR) + printf("ip1000: Tx error\n"); + + pdev->stat.ets_packetT++; + pdev->tx[tx_tail].busy = FALSE; + pdev->tx_busy_num--; - if (++tx_tail >= IC_TX_DESC_NUM) + if (++tx_tail >= TX_DESC_NUM) tx_tail = 0; - pdev->ic_send_flag = TRUE; - pdev->ic_recv_flag = TRUE; - pdev->ic_tx_alive = TRUE; + pdev->send_flag = TRUE; + pdev->recv_flag = TRUE; -#ifdef IP1000_DEBUG - printf("IP1000: Successfully send a packet\n"); + /* Set Tx descriptor status in interrupt */ + /* ### SET_TX_STATUS_INTR ### */ + desc->status = DESC_STATUS_TX_SEND_CLEAR; + +#ifdef MY_DEBUG + printf("ip1000: Successfully send a packet\n"); #endif } - pdev->ic_tx_tail = tx_tail; + pdev->tx_tail = tx_tail; } +#ifdef MY_DEBUG if (!flag) { -#ifdef IP1000_DEBUG - printf("IP1000: Unknown error in interrupt: 0x%04x\n", intr_status); -#endif + printf("ip1000: Unknown error in interrupt\n"); return; } +#endif } /* Check interrupt and perform */ static void ic_check_ints(ic_driver *pdev) { - if (!pdev->ic_recv_flag) + if (!pdev->recv_flag) return; - pdev->ic_recv_flag = FALSE; + pdev->recv_flag = FALSE; /* Handle data receive */ netdriver_recv(); /* Handle data transmit */ - if (pdev->ic_send_flag) { - pdev->ic_send_flag = FALSE; + if (pdev->send_flag) { + pdev->send_flag = FALSE; netdriver_send(); } } static void ic_stat(eth_stat_t *stat) { - memcpy(stat, &g_driver.ic_stat, sizeof(*stat)); + memcpy(stat, &g_driver.stat, sizeof(*stat)); } diff --git a/minix/drivers/net/ip1000/ip1000.h b/minix/drivers/net/ip1000/ip1000.h index cfbab782d..9323e997f 100644 --- a/minix/drivers/net/ip1000/ip1000.h +++ b/minix/drivers/net/ip1000/ip1000.h @@ -1,262 +1,193 @@ +#ifndef _ic_H +#define _ic_H + #include -#include -#include -#include -#include -/* PCI Register */ -#define IC_PCI_VID 0x00 /* Vendor ID */ -#define IC_PCI_DID 0x02 /* Device ID */ -#define IC_PCI_CMD 0x04 /* Command */ -#define IC_PCI_STS 0x06 /* Status */ -#define IC_PCI_RID 0x08 /* Revision ID */ -#define IC_PCI_CC 0x09 /* Class Code */ -#define IC_PCI_CLS 0x0c /* Cache Line Size */ -#define IC_PCI_LT 0x0d /* Latency Timer */ -#define IC_PCI_HT 0x0e /* Header Type */ +/* ======= General Parameter ======= */ +/* Global configure */ +#define DESC_BASE64 -/* Internal Register */ -#define IC_REG_DMA_CTRL 0x00 /* DMA Control */ -#define IC_REG_TX_DESC0 0x10 /* Tx Descriptor Address 0 */ -#define IC_REG_TX_DESC1 0x14 /* Tx Descriptor Address 1 */ -#define IC_REG_TX_DMA_BTH 0x18 /* Tx DMA Burst Threshold */ -#define IC_REG_TX_DMA_UTH 0x19 /* Tx DMA Urgent Threshold */ -#define IC_REG_TX_DMA_PERIOD 0x1a /* Tx DMA Poll Period */ -#define IC_REG_RX_DESC0 0x1c /* Rx Descriptor Address 0 */ -#define IC_REG_RX_DESC1 0x20 /* Rx Descriptor Address 1 */ -#define IC_REG_RX_DMA_BTH 0x24 /* Rx DMA Burst Threshold */ -#define IC_REG_RX_DMA_UTH 0x25 /* Rx DMA Urgent Threshold */ -#define IC_REG_RX_DMA_PERIOD 0x26 /* Rx DMA Poll Period */ -#define IC_REG_DEBUG_CTRL 0x2c /* Debug Control */ -#define IC_REG_ASIC_CTRL 0x30 /* Main Control */ -#define IC_REG_FLOW_OFF_TH 0x3c /* Flow Off Threshold */ -#define IC_REG_FLOW_ON_TH 0x3e /* Flow On Threshold */ -#define IC_REG_EEPROM_DATA 0x48 /* EEPROM Data */ -#define IC_REG_EEPROM_CTRL 0x4a /* EEPROM Control */ -#define IC_REG_INTR_STS_ACK 0x5a /* Interrupt Status Acknowlege */ -#define IC_REG_INTR_ENA 0x5c /* Interrupt Enable */ -#define IC_REG_INTR_STS 0x5e /* Interrupt Status */ -#define IC_REG_TX_STS 0x60 /* Tx Status */ -#define IC_REG_MAC_CTRL 0x6c /* MAC Control */ -#define IC_REG_PHY_SET 0x75 /* Physical Register Set */ -#define IC_REG_PHY_CTRL 0x76 /* Physical Register Control */ -#define IC_REG_STA_ADDR0 0x78 /* Station Address 0 */ -#define IC_REG_STA_ADDR1 0x7a /* Station Address 1 */ -#define IC_REG_STA_ADDR2 0x7c /* Station Address 2 */ -#define IC_REG_MAX_FRAME 0x86 /* Max Frame Size */ -#define IC_REG_RX_MODE 0x88 /* Receive Mode */ -#define IC_REG_HASH_TLB0 0x8c /* Hash Table 0 */ -#define IC_REG_HASH_TLB1 0x90 /* Hash Table 1 */ +/* Rx/Tx buffer parameter */ +#define RX_BUF_SIZE 1536 +#define TX_BUF_SIZE 1536 +#define RX_DESC_NUM 64 +#define TX_DESC_NUM 64 -/* Receive Configure Mode */ -#define IC_RM_UNICAST 0x01 -#define IC_RM_MULTICAST 0x02 -#define IC_RM_BROADCAST 0x04 -#define IC_RM_ALLFRAMES 0x08 +/* Key internal register */ +#define REG_RCR 0x88 +#define REG_ISR 0x5a +#define REG_IMR 0x5c +#define REG_RX_DESC_BASEL 0x1c +#define REG_TX_DESC_BASEL 0x10 -/* Interrupt Enable/Status Command */ -#define IC_IR_IRQ_STS 0x0001 -#define IC_IR_HOST_ERR 0x0002 -#define IC_IR_TX_DONE 0x0004 -#define IC_IR_MAC_CTRL 0x0008 -#define IC_IR_RX_DONE 0x0010 -#define IC_IR_RX_EARLY 0x0020 -#define IC_IR_REQUESTED 0x0040 -#define IC_IR_UPDATE_STS 0x0080 -#define IC_IR_LINK_EVENT 0x0100 -#define IC_IR_TX_DMA_DONE 0x0200 -#define IC_IR_RX_DMA_DONE 0x0400 -#define IC_IR_RFD_END 0x0800 -#define IC_IR_RX_DMA_PRIOR 0x1000 -#define IC_IR_COMMON (IC_IR_HOST_ERR | IC_IR_TX_DMA_DONE | \ - IC_IR_TX_DONE | IC_IR_REQUESTED | \ - IC_IR_UPDATE_STS | IC_IR_LINK_EVENT | \ - IC_IR_RX_DMA_DONE | IC_IR_RX_DONE | \ - IC_IR_RX_DMA_PRIOR) +#ifdef DESC_BASE_DMA64 +#define REG_RX_DESC_BASEU 0x20 +#define REG_TX_DESC_BASEU 0x14 +#endif -/* ASIC Control Register Command */ -#define IC_AC_SPEED10 0x00000010 -#define IC_AC_SPEED100 0x00000020 -#define IC_AC_SPEED1000 0x00000040 -#define IC_AC_LED_MODE 0x00004000 -#define IC_AC_GB_RESET 0x00010000 -#define IC_AC_RX_RESET 0x00020000 -#define IC_AC_TX_RESET 0x00040000 -#define IC_AC_DMA 0x00080000 -#define IC_AC_FIFO 0x00100000 -#define IC_AC_NETWORK 0x00200000 -#define IC_AC_HOST 0x00400000 -#define IC_AC_AUTO_INIT 0x00800000 -#define IC_AC_INTR_IRQ 0x02000000 -#define IC_AC_RESET_BUSY 0x04000000 -#define IC_AC_LED_SPEED 0x08000000 -#define IC_AC_LED_MODE_BIT1 0x20000000 -#define IC_AC_RESET_ALL (IC_AC_GB_RESET | IC_AC_RX_RESET | \ - IC_AC_TX_RESET | IC_AC_DMA | IC_AC_FIFO | \ - IC_AC_NETWORK | IC_AC_HOST | IC_AC_AUTO_INIT) +/* Key internal register width */ +#define WIDTH_REG_RCR 8 +#define WIDTH_REG_ISR 16 +#define WIDTH_REG_IMR 16 -/* EEPROM Control Command */ -#define IC_EC_ADDDR 0x83ff -#define IC_EC_OPCODE 0x00ff -#define IC_EC_WRITE 0x0100 -#define IC_EC_READ 0x0200 -#define IC_EC_ERASE 0x0300 -#define IC_EC_BUSY 0x8000 +/* Interrupt statu and command */ +#define INTR_ISR_ERR 0x0002 +#define INTR_ISR_LINK_EVENT 0x0100 +#define INTR_ISR_RX_DONE 0x0400 +#define INTR_ISR_TX_DONE 0x0200 +#define INTR_ISR_CLEAR 0x0000 +#define INTR_IMR_ENABLE 0x17f6 +#define INTR_IMR_DISABLE 0x0000 -/* MAC Control Command */ -#define IC_MC_DUPLEX_SEL 0x00000020 -#define IC_MC_TX_FC_ENA 0x00000080 -#define IC_MC_RX_FC_ENA 0x00000100 -#define IC_MC_STAT_DISABLE 0x00400000 -#define IC_MC_TX_ENABLE 0x01000000 -#define IC_MC_TX_DISABLE 0x02000000 -#define IC_MC_TX_ENABLED 0x04000000 -#define IC_MC_RX_ENABLE 0x08000000 -#define IC_MC_RX_DISABLE 0x10000000 -#define IC_MC_RX_ENABLED 0x20000000 -#define IC_MC_PAUSED 0x40000000 +/* Descriptor status */ +#define DESC_STATUS_RX_RECV_ERR 0x00000000003f0000ULL +#define DESC_STATUS_RX_RECV_CLEAR 0x0000000000000000ULL +#define DESC_STATUS_TX_SEND_ERR 0x0000000000000000ULL +#define DESC_STATUS_TX_SEND_CLEAR 0x0000000000000000ULL -/* DMA Control Command */ -#define IC_DC_TX_POLL 0x00001000 +/* Rx mode */ +#define RCR_UNICAST 0x01 +#define RCR_MULTICAST 0x02 +#define RCR_BROADCAST 0x04 -/* Physical Control Command */ -#define IC_PC_MGMTCLK_LO 0x00 -#define IC_PC_MGMTCLK_HI 0x01 -#define IC_PC_MGMTDATA 0x02 -#define IC_PC_MGMTDIR 0x04 -#define IC_PC_DUPLEX_POLARITY 0x08 -#define IC_PC_DUPLEX_STS 0x10 -#define IC_PC_LINK_POLARITY 0x20 -#define IC_PC_LINK_SPEED 0xc0 -#define IC_PC_LINK_SPEED10 0x40 -#define IC_PC_LINK_SPEED100 0x80 -#define IC_PC_LINK_SPEED1000 0xc0 +/* Link status */ +#define LINK_UP 1 +#define LINK_DOWN 0 +#define LINK_UNKNOWN -1 -/* Tx Status */ -#define IC_TS_TX_ERR 0x00000001 -#define IC_TS_TX_COLLISION 0x00000004 -#define IC_TS_TX_MAX_COLL 0x00000008 -#define IC_TS_TX_UNDERRUN 0x00000010 -#define IC_TS_TX_IND_REQD 0x00000040 -#define IC_TS_TX_DONE 0x00000080 -#define IC_TS_TX_FRAMEID 0xffff0000 +/* Basic Rx/Tx parameters */ +#define RX_BUF_SIZE 1536 +#define TX_BUF_SIZE 1536 +#define RX_DESC_NUM 256 +#define TX_DESC_NUM 256 -/* Tx Frame Status */ -#define IC_TFS_FRAMEID 0x000000000000ffffULL -#define IC_TFS_WORD_ALIGN 0x0000000000030000ULL -#define IC_TFS_TCP_CHECKSUM 0x0000000000040000ULL -#define IC_TFS_UDP_CHECKSUM 0x0000000000080000ULL -#define IC_TFS_IP_CHECKSUM 0x0000000000100000ULL -#define IC_TFS_FRAG_COUNT 0x000000000f000000ULL -#define IC_TFS_WORD_ALIGN 0x0000000000030000ULL -#define IC_TFS_TX_DMA_INDICATE 0x0000000000800000ULL -#define IC_TFS_TFD_DONE 0x0000000080000000ULL +/* ======= Self-defined Parameter ======= */ +#define RFI_FRAG_LEN 0xffff000000000000ULL +#define RFS_FRAME_LEN 0x000000000000ffffULL +#define RFS_FRAME_START 0x0000000020000000ULL +#define RFS_FRAME_END 0x0000000040000000ULL +#define RFS_RFD_DONE 0x0000000080000000ULL +#define RFS_NORMAL (RFS_RFD_DONE | RFS_FRAME_START | RFS_FRAME_END) -/* Tx Frame Information */ -#define IC_TFI_FRAG_ADDR 0x000000ffffffffffULL -#define IC_TFI_FRAG_LEN 0xffff000000000000ULL +#define TFI_FRAG_LEN 0xffff000000000000ULL +#define TFS_FRAMEID 0x000000000000ffffULL +#define TFS_WORD_ALIGN 0x0000000000030000ULL +#define TFS_TX_DMA_INDICATE 0x0000000000800000ULL +#define TFS_FRAG_COUNT 0x000000000f000000ULL +#define TFS_TFD_DONE 0x0000000080000000ULL -/* Rx Frame Status */ -#define IC_RFS_FRAME_LEN 0x000000000000ffffULL -#define IC_RFS_OVERRUN 0x0000000000010000ULL -#define IC_RFS_RUNT 0x0000000000020000ULL -#define IC_RFS_ALIGN_ERR 0x0000000000040000ULL -#define IC_RFS_FCS_ERR 0x0000000000080000ULL -#define IC_RFS_OVERSIZE 0x0000000000100000ULL -#define IC_RFS_LEN_ERR 0x0000000000200000ULL -#define IC_RFS_VLAN_DETECT 0x0000000000400000ULL -#define IC_RFS_TCP_DETECT 0x0000000000800000ULL -#define IC_RFS_TCP_ERR 0x0000000001000000ULL -#define IC_RFS_UCP_DETECT 0x0000000002000000ULL -#define IC_RFS_UCP_ERR 0x0000000004000000ULL -#define IC_RFS_IP_DETECT 0x0000000008000000ULL -#define IC_RFS_IP_ERR 0x0000000010000000ULL -#define IC_RFS_FRAME_START 0x0000000020000000ULL -#define IC_RFS_FRAME_END 0x0000000040000000ULL -#define IC_RFS_RFD_DONE 0x0000000080000000ULL -#define IC_RFS_TCI 0x0000ffff00000000ULL -#define IC_RFS_NORMAL (IC_RFS_RFD_DONE | IC_RFS_FRAME_START | \ - IC_RFS_FRAME_END) -#define IC_RFS_ALL_ERR (IC_RFS_OVERRUN | IC_RFS_RUNT | \ - IC_RFS_ALIGN_ERR | IC_RFS_FCS_ERR | \ - IC_RFS_OVERSIZE | IC_RFS_LEN_ERR) +#define REG_DMA_CTRL 0x00 +#define REG_TX_DMA_BTH 0x18 +#define REG_TX_DMA_UTH 0x19 +#define REG_TX_DMA_PERIOD 0x1a +#define REG_RX_DMA_BTH 0x24 +#define REG_RX_DMA_UTH 0x25 +#define REG_RX_DMA_PERIOD 0x26 +#define REG_ASIC_CTRL 0x30 +#define REG_FLOW_OFF_TH 0x3c +#define REG_FLOW_ON_TH 0x3e +#define REG_EEPROM_DATA 0x48 +#define REG_EEPROM_CTRL 0x4a +#define REG_MAC_CTRL 0x6c +#define REG_PHY_SET 0x75 +#define REG_PHY_CTRL 0x76 +#define REG_STA_ADDR0 0x78 +#define REG_STA_ADDR1 0x7a +#define REG_STA_ADDR2 0x7c +#define REG_MAX_FRAME 0x86 -/* Rx Frame Information */ -#define IC_RFI_FRAG_ADDR 0x000000ffffffffffULL -#define IC_RFI_FRAG_LEN 0xffff000000000000ULL +#define AC_LED_MODE 0x00004000 +#define AC_GB_RESET 0x00010000 +#define AC_RX_RESET 0x00020000 +#define AC_TX_RESET 0x00040000 +#define AC_DMA 0x00080000 +#define AC_FIFO 0x00100000 +#define AC_NETWORK 0x00200000 +#define AC_HOST 0x00400000 +#define AC_AUTO_INIT 0x00800000 +#define AC_RESET_BUSY 0x04000000 +#define AC_LED_SPEED 0x08000000 +#define AC_LED_MODE_B1 0x20000000 +#define AC_RESET_ALL (AC_GB_RESET | AC_RX_RESET | AC_TX_RESET | AC_DMA | \ + AC_FIFO | AC_NETWORK | AC_HOST | AC_AUTO_INIT) -/* Link Status */ -#define IC_LINK_UP 1 -#define IC_LINK_DOWN 0 -#define IC_LINK_UNKNOWN -1 +#define MC_DUPLEX_SEL 0x00000020 +#define MC_TX_FC_ENA 0x00000080 +#define MC_RX_FC_ENA 0x00000100 +#define MC_STAT_DISABLE 0x00400000 +#define MC_TX_ENABLE 0x01000000 +#define MC_TX_DISABLE 0x02000000 +#define MC_RX_ENABLE 0x08000000 +#define MC_RX_DISABLE 0x10000000 +#define MC_PAUSED 0x40000000 -#define IC_RX_BUF_SIZE 1536 -#define IC_TX_BUF_SIZE 1536 -#define IC_RX_DESC_NUM 256 -#define IC_TX_DESC_NUM 256 +#define PC_DUPLEX_STS 0x10 +#define PC_LINK_SPEED 0xc0 +#define PC_LINK_SPEED10 0x40 +#define PC_LINK_SPEED100 0x80 +#define PC_LINK_SPEED1000 0xc0 -/* #define IP1000_DEBUG */ +#define EC_READ 0x0200 +#define EC_BUSY 0x8000 -/* Physical parameters */ -static const u16_t DefaultPhyParam[] = { - (0x4000 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, - 0x0000, 30, 0x005e, 9, 0x0700, - (0x4100 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, - 0x0000, 30, 0x005e, 9, 0x0700, 0x0000 +static u16_t PhyParam[] = { + (0x4000|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + (0x4100|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + (0x4200|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, + (0x4300|(07*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, 0x0000, + 30, 0x005e, 9, 0x0700, 0x0000 }; -/* Data Descriptor */ +/* ======= Data Descriptor ======= */ typedef struct ic_desc { - u64_t next_desc; /* Next descriptor */ - u64_t status; /* Status information */ - u64_t frag_info; /* Length and DMA buffer address */ + u64_t next;; + u64_t status;; + u64_t frag_info;; } ic_desc; /* Driver Data Structure */ typedef struct ic_driver { - u16_t ic_base_addr; /* Base address */ - int ic_revision; /* Revision ID */ - int ic_irq; /* IRQ number */ - int ic_mode; - int ic_link; /* Whether link-up */ - int ic_recv_flag; /* Receive flag */ - int ic_send_flag; /* Send flag */ - int ic_tx_alive; - int ic_tx_busy; - - /* LED mode read from EEPROM */ - u16_t ic_led_mode; - - /* Station address read from EEPROM */ - u16_t sta_addr[3]; + u32_t base_addr; /* Base address */ + int revision; /* Revision ID */ + int irq; /* IRQ number */ + int mode; + int link; /* Whether link-up */ + int recv_flag; /* Receive flag */ + int send_flag; /* Send flag */ + int tx_busy; /* Buffer */ - size_t ic_buf_size; - char *ic_buf; + size_t buf_size; + char *buf; /* Rx data */ - int ic_rx_head; + int rx_head; struct { phys_bytes buf_dma; char *buf; - } ic_rx[IC_RX_DESC_NUM]; - ic_desc *ic_rx_desc; /* Rx descriptor buffer */ - phys_bytes ic_rx_desc_dma; /* Rx descriptor DMA buffer */ + } rx[RX_DESC_NUM]; + ic_desc *rx_desc; /* Rx descriptor buffer */ + phys_bytes rx_desc_dma; /* Rx descriptor DMA buffer */ /* Tx data */ - int ic_tx_head; - int ic_tx_tail; + int tx_head; + int tx_tail; struct { int busy; phys_bytes buf_dma; char *buf; - } ic_tx[IC_TX_DESC_NUM]; - ic_desc *ic_tx_desc; /* Tx descriptor buffer */ - phys_bytes ic_tx_desc_dma; /* Tx descriptor DMA buffer */ - int ic_tx_busy_num; /* Number of busy Tx descriptors */ + } tx[TX_DESC_NUM]; + ic_desc *tx_desc; /* Tx descriptor buffer */ + phys_bytes tx_desc_dma; /* Tx descriptor DMA buffer */ + int tx_busy_num; /* Number of busy Tx descriptors */ - int ic_hook; /* IRQ hook id at kernel */ - eth_stat_t ic_stat; + int hook; /* IRQ hook id at kernel */ + eth_stat_t stat; - char ic_name[20]; + char name[20]; } ic_driver; + +#endif diff --git a/minix/drivers/net/vt6105/Makefile b/minix/drivers/net/vt6105/Makefile index 8ac42452f..50d1e75ea 100755 --- a/minix/drivers/net/vt6105/Makefile +++ b/minix/drivers/net/vt6105/Makefile @@ -1,5 +1,5 @@ # Makefile for the VIA Technology 6105/6106S Ethernet driver (vt6105) -PROG= vt6105 +PROG= vt6105 SRCS= vt6105.c FILES=${PROG}.conf diff --git a/minix/drivers/net/vt6105/README b/minix/drivers/net/vt6105/README index be49e63e8..fbc0e4fec 100644 --- a/minix/drivers/net/vt6105/README +++ b/minix/drivers/net/vt6105/README @@ -1,15 +1,16 @@ The vt6105 driver is for VIA Technology 6105/6106S Ethernet card. -This driver is referred to Minix(3.4.0) rtl8169 driver, +This driver is referred to Minix(3.4.0) rtl8169 driver, Linux(4.2.1) via-rhine driver and VT6105 Rhine III Specification(Rev 1.2). -The supported PCI number is 1106:3106:1186:1403. -Maybe other PCI numbers for VIA Rhine III can be supported. - Revision 1.0 2016/10/18 Authored by Jia-Ju Bai -Something can be improved: +Revision 1.1 2016/11/12 +Modification: Remove and rewrite Linux-derived code +Authored by Jia-Ju Bai + +Something can be improved: 1. MII, WOL functions are not adequately defined and used. 2. Link status report does not work well. 3. Ethernet address can not be modified at present. diff --git a/minix/drivers/net/vt6105/io.h b/minix/drivers/net/vt6105/io.h new file mode 100644 index 000000000..90f9901a6 --- /dev/null +++ b/minix/drivers/net/vt6105/io.h @@ -0,0 +1,84 @@ +#ifndef _IO_H +#define _IO_H + +#include +#include +#include "vt6105.h" + +/* I/O function */ +static u8_t my_inb(u32_t port) { + u32_t value; + int r; +#ifdef DMA_REG_MODE + value = *(u8_t *)(port); +#else + if ((r = sys_inb(port, &value)) != OK) + printf("vt6105: sys_inb failed: %d\n", r); +#endif + return (u8_t)value; +} +#define vt_in8(port, offset) (my_inb((port) + (offset))) + +static u16_t my_inw(u32_t port) { + u32_t value; + int r; +#ifdef DMA_REG_MODE + value = *(u16_t *)(port); +#else + if ((r = sys_inw(port, &value)) != OK) + printf("vt6105: sys_inw failed: %d\n", r); +#endif + return (u16_t)value; +} +#define vt_in16(port, offset) (my_inw((port) + (offset))) + +static u32_t my_inl(u32_t port) { + u32_t value; + int r; +#ifdef DMA_REG_MODE + value = *(u32_t *)(port); +#else + if ((r = sys_inl(port, &value)) != OK) + printf("vt6105: sys_inl failed: %d\n", r); +#endif + return value; +} +#define vt_in32(port, offset) (my_inl((port) + (offset))) + +static void my_outb(u32_t port, u8_t value) { + int r; +#ifdef DMA_REG_MODE + *(u8_t *)(port) = value; +#else + if ((r = sys_outb(port, value)) != OK) + printf("vt6105: sys_outb failed: %d\n", r); +#endif +} +#define vt_out8(port, offset, value) \ + (my_outb(((port) + (offset)), (value))) + +static void my_outw(u32_t port, u16_t value) { + int r; +#ifdef DMA_REG_MODE + *(u16_t *)(port) = value; +#else + if ((r = sys_outw(port, value)) != OK) + printf("vt6105: sys_outw failed: %d\n", r); +#endif +} +#define vt_out16(port, offset, value) \ + (my_outw(((port) + (offset)), (value))) + +static void my_outl(u16_t port, u32_t value) { + int r; +#ifdef DMA_REG_MODE + *(u32_t *)(port) = value; +#else + if ((r = sys_outl(port, value)) != OK) + printf("vt6105: sys_outl failed: %d\n", r); +#endif +} +#define vt_out32(port, offset, value) \ + (my_outl(((port) + (offset)), (value))) + +#endif diff --git a/minix/drivers/net/vt6105/vt6105.c b/minix/drivers/net/vt6105/vt6105.c index 92b628977..38f527e0f 100644 --- a/minix/drivers/net/vt6105/vt6105.c +++ b/minix/drivers/net/vt6105/vt6105.c @@ -1,58 +1,13 @@ +#include +#include +#include #include "vt6105.h" +#include "io.h" /* global value */ static vt_driver g_driver; static int g_instance; -/* I/O function */ -static u8_t my_inb(u16_t port) { - u32_t value; - int r; - if ((r = sys_inb(port, &value)) != OK) - printf("VT6105: sys_inb failed: %d\n", r); - return (u8_t)value; -} -#define vt_inb(port, offset) (my_inb((port) + (offset))) - -static u16_t my_inw(u16_t port) { - u32_t value; - int r; - if ((r = sys_inw(port, &value)) != OK) - printf("VT6105: sys_inw failed: %d\n", r); - return (u16_t)value; -} -#define vt_inw(port, offset) (my_inw((port) + (offset))) - -static u32_t my_inl(u16_t port) { - u32_t value; - int r; - if ((r = sys_inl(port, &value)) != OK) - printf("VT6105: sys_inl failed: %d\n", r); - return value; -} -#define vt_inl(port, offset) (my_inl((port) + (offset))) - -static void my_outb(u16_t port, u8_t value) { - int r; - if ((r = sys_outb(port, value)) != OK) - printf("VT6105: sys_outb failed: %d\n", r); -} -#define vt_outb(port, offset, value) (my_outb((port) + (offset), (value))) - -static void my_outw(u16_t port, u16_t value) { - int r; - if ((r = sys_outw(port, value)) != OK) - printf("VT6105: sys_outw failed: %d\n", r); -} -#define vt_outw(port, offset, value) (my_outw((port) + (offset), (value))) - -static void my_outl(u16_t port, u32_t value) { - int r; - if ((r = sys_outl(port, value)) != OK) - printf("VT6105: sys_outl failed: %d\n", r); -} -#define vt_outl(port, offset, value) (my_outl((port) + (offset), (value))) - /* driver interface */ static int vt_init(unsigned int instance, ether_addr_t *addr); static void vt_stop(void); @@ -61,18 +16,159 @@ static ssize_t vt_recv(struct netdriver_data *data, size_t max); static int vt_send(struct netdriver_data *data, size_t size); static void vt_intr(unsigned int mask); static void vt_stat(eth_stat_t *stat); -static void vt_alarm(clock_t stamp); +/* internal function */ static int vt_probe(vt_driver *pdev, int instance); static int vt_init_buf(vt_driver *pdev); static int vt_init_hw(vt_driver *pdev, ether_addr_t *addr); -static void vt_reset_hw(vt_driver *pdev); -static void vt_power_init(vt_driver *pdev); +static int vt_reset_hw(vt_driver *pdev); static void vt_conf_addr(vt_driver *pdev, ether_addr_t *addr); -static void vt_check_link(vt_driver *pdev); static void vt_handler(vt_driver *pdev); static void vt_check_ints(vt_driver *pdev); +/* developer interface */ +static void vt_init_rx_desc(vt_desc *desc, size_t size, phys_bytes dma); +static void vt_init_tx_desc(vt_desc *desc, size_t size, phys_bytes dma); +static int vt_real_reset(u32_t base); +static int vt_init_power(u32_t base); +static int vt_init_mii(u32_t base); +static int vt_init_io(u32_t base); +static void vt_start_rx_tx(u32_t base); +static void vt_get_addr(u32_t base, u8_t *pa); +static int vt_check_link(u32_t base); +static void vt_stop_rx_tx(u32_t base); +static int vt_rx_status_ok(vt_desc *desc); +static int vt_get_rx_len(vt_desc *desc); +static void vt_tx_desc_start(vt_desc *desc, size_t size); +static void vt_wakeup_tx(u32_t base); +static int vt_tx_status_ok(vt_desc *desc); + +/* ======= Developer-defined function ======= */ +/* Intialize Rx descriptor (### RX_DESC_INIT ###) */ +static void vt_init_rx_desc(vt_desc *desc, size_t size, phys_bytes dma) { + desc->status = DESC_OWN | ((size << 16) & DESC_RX_LENMASK); + desc->addr = dma; + desc->length = size; +} + +/* Intialize Tx descriptor (### TX_DESC_INIT ###) */ +static void vt_init_tx_desc(vt_desc *desc, size_t size, phys_bytes dma) { + desc->addr = dma; + desc->length = size; +} + +/* Real hardware reset (### RESET_HARDWARE_CAN_FAIL ###) + * -- Return OK means success, Others means failure */ +static int vt_real_reset(u32_t base) { + vt_out16(base, REG_CR, CMD_RESET); + micro_delay(10000); + if (vt_in16(base, REG_CR) & CMD_RESET) { + vt_out8(base, REG_MCR1, 0x40); + micro_delay(10000); + if (vt_in16(base, REG_CR) & CMD_RESET) + return -EIO; + } + return OK; +} + +/* Intialize power (### POWER_INIT_CAN_FAIL ###) + * -- Return OK means success, Others means failure */ +static int vt_init_power(u32_t base) { + u8_t stick; + stick = vt_in8(base, REG_STICK); + vt_out8(base, REG_STICK, stick & 0xfc); + return OK; +} + +/* Intialize MII interface (### MII_INIT_CAN_FAIL ###) + * -- Return OK means success, Others means failure */ +static int vt_init_mii(u32_t base) { + return OK; +} + +/* Intialize other hardware I/O registers (### INIT_HARDWARE_IO_CAN_FAIL ###) + * -- Return OK means success, Others means failure */ +static int vt_init_io(u32_t base) { + vt_out16(base, REG_BCR0, 0x0006); + vt_out8(base, REG_TCR, 0x20); + vt_out8(base, REG_RCR, 0x78); + return OK; +} + +/* Start Rx/Tx (### START_RX_TX ###) */ +static void vt_start_rx_tx(u32_t base) { + u16_t cmd = CMD_START | CMD_RX_ON | CMD_TX_ON | CMD_NO_POLL | CMD_FDUPLEX; + vt_out16(base, REG_CR, cmd); + micro_delay(1000); +} + +/* Get MAC address to the array 'pa' (### GET_MAC_ADDR ###) */ +static void vt_get_addr(u32_t base, u8_t *pa) { + int i; + for (i = 0; i < 6; i++) + pa[i] = vt_in8(base, REG_ADDR + i); +} + +/* Check link status (### CHECK_LINK ###) + * -- Return LINK_UP or LINK_DOWN */ +static int vt_check_link(u32_t base) { + u32_t r; + vt_out8(base, REG_MII_CFG, 0x01); + vt_out8(base, REG_MII_ADDR, 0x01); + vt_out8(base, REG_MII_CR, 0x40); + micro_delay(10000); + r = vt_in16(base, REG_MII_DATA); + if (r & 0x0004) + return LINK_UP; + return LINK_DOWN; +} + +/* Stop Rx/Tx (### STOP_RX_TX ###) */ +static void vt_stop_rx_tx(u32_t base) { + vt_out16(base, REG_CR, CMD_STOP); +} + +/* Check whether Rx status OK (### CHECK_RX_STATUS_OK ###) + * -- Return TRUE or FALSE */ +static int vt_rx_status_ok(vt_desc *desc) { + if (!(desc->status & DESC_OWN)) { + if ((desc->status & DESC_RX_NORMAL) == DESC_RX_NORMAL) + return TRUE; + } + return FALSE; +} + +/* Get Rx data length from descriptor (### GET_RX_LEN ###) + * --- Return the length */ +static int vt_get_rx_len(vt_desc *desc) { + int len; + len = ((desc->status & DESC_RX_LENMASK) >> 16) - ETH_CRC_SIZE; + return len; +} + +/* Set Tx descriptor in send (### TX_DESC_START ###) */ +static void vt_tx_desc_start(vt_desc *desc, size_t size) { + desc->status = DESC_OWN | DESC_FIRST | DESC_LAST; + desc->length = 0x00e08000 | (size > 60 ? size : 60); +} + +/* Wake up Tx channel (### WAKE_UP_TX ###) */ +static void vt_wakeup_tx(u32_t base) { + u8_t cmd; + cmd = vt_in8(base, REG_CR); + cmd |= CMD_TX_DEMAND; + vt_out8(base, REG_CR, cmd); +} + +/* Check whether Tx status OK (### CHECK_TX_STATUS_OK ###) + * -- Return TRUE or FALSE */ +static int vt_tx_status_ok(vt_desc *desc) { + if (!(desc->status & DESC_OWN)) + return TRUE; + return FALSE; +} + +/* Driver interface table */ static const struct netdriver vt_table = { .ndr_init = vt_init, .ndr_stop = vt_stop, @@ -81,7 +177,6 @@ static const struct netdriver vt_table = { .ndr_send = vt_send, .ndr_stat = vt_stat, .ndr_intr = vt_intr, - .ndr_alarm = vt_alarm }; int main(int argc, char *argv[]) { @@ -95,28 +190,28 @@ static int vt_init(unsigned int instance, ether_addr_t *addr) { /* Intialize driver data structure */ memset(&g_driver, 0, sizeof(g_driver)); - g_driver.vt_link = VT_LINK_UNKNOWN; - strcpy(g_driver.vt_name, "vt6105#0"); - g_driver.vt_name[7] += instance; + g_driver.link = LINK_UNKNOWN; + strcpy(g_driver.name, "netdriver#0"); + g_driver.name[10] += instance; g_instance = instance; /* Probe the device */ if (vt_probe(&g_driver, instance)) { - printf("VT6105: Device is not found!\n"); + printf("vt6105: Device is not found\n"); ret = -ENODEV; goto err_probe; } /* Allocate and initialize buffer */ if (vt_init_buf(&g_driver)) { - printf("VT6105: Device is not found!\n"); + printf("vt6105: Fail to initialize buffer\n"); ret = -ENODEV; goto err_init_buf; } /* Intialize hardware */ if (vt_init_hw(&g_driver, addr)) { - printf("VT6105: Find to initialize hardware!\n"); + printf("vt6105: Fail to initialize hardware\n"); ret = -EIO; goto err_init_hw; } @@ -125,13 +220,13 @@ static int vt_init(unsigned int instance, ether_addr_t *addr) { sys_setalarm(sys_hz(), 0); /* Clear send and recv flag */ - g_driver.vt_send_flag = FALSE; - g_driver.vt_recv_flag = FALSE; + g_driver.send_flag = FALSE; + g_driver.recv_flag = FALSE; return 0; err_init_hw: - free_contig(g_driver.vt_buf, g_driver.vt_buf_size); + free_contig(g_driver.buf, g_driver.buf_size); err_init_buf: err_probe: return ret; @@ -139,10 +234,11 @@ err_probe: /* Match the device and get base address */ static int vt_probe(vt_driver *pdev, int instance) { - int devind; + int devind, ioflag; u16_t cr, vid, did; - u32_t bar; + u32_t bar, size; u8_t irq, rev; + u8_t *reg; /* Find pci device */ pci_init(); @@ -160,25 +256,41 @@ static int vt_probe(vt_driver *pdev, int instance) { pci_attr_w16(devind, PCI_CR, cr | PCI_CR_MAST_EN); /* Get base address */ - bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; - if (bar < 0x400) { - printf("VT6105: base address is not properly configured!\n"); +#ifdef DMA_REG_MODE + if (pci_get_bar(devind, PCI_BAR, &base, &size, &ioflag)) { + printf("vt6105: Fail to get PCI BAR\n"); return -EIO; } - pdev->vt_base_addr = bar; - + if (ioflag) { + printf("vt6105: PCI BAR is not for memory\n"); + return -EIO; + } + if ((reg = vm_map_phys(SELF, (void *)base, size)) == MAP_FAILED) { + printf("vt6105: Fail to map hardware registers from PCI\n"); + return -EIO; + } + pdev->base_addr = (u32_t)reg; +#else + bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; + if (bar < 0x400) { + printf("vt6105: Base address is not properly configured\n"); + return -EIO; + } + pdev->base_addr = bar; +#endif + /* Get irq number */ irq = pci_attr_r8(devind, PCI_ILR); - pdev->vt_irq = irq; + pdev->irq = irq; /* Get revision ID */ rev = pci_attr_r8(devind, PCI_REV); - pdev->vt_revision = rev; + pdev->revision = rev; -#ifdef VT6105_DEBUG - printf("VT6105: Base address is 0x%08x\n", pdev->vt_base_addr); - printf("VT6105: IRQ number is 0x%08x\n", pdev->vt_irq); - printf("VT6105: Revision ID is 0x%08x\n", pdev->vt_revision); +#ifdef MY_DEBUG + printf("vt6105: Base address is 0x%08x\n", pdev->base_addr); + printf("vt6105: IRQ number is 0x%02x\n", pdev->irq); + printf("vt6105: Revision ID is 0x%02x\n", pdev->revision); #endif return 0; @@ -193,91 +305,88 @@ static int vt_init_buf(vt_driver *pdev) { int i; /* Build Rx and Tx descriptor buffer */ - rx_desc_size = VT_RX_DESC_NUM * sizeof(vt_desc); - tx_desc_size = VT_TX_DESC_NUM * sizeof(vt_desc); + rx_desc_size = RX_DESC_NUM * sizeof(vt_desc); + tx_desc_size = TX_DESC_NUM * sizeof(vt_desc); /* Allocate Rx and Tx buffer */ - tx_buf_size = VT_TX_BUF_SIZE; + tx_buf_size = TX_BUF_SIZE; if (tx_buf_size % 4) tx_buf_size += 4 - (tx_buf_size % 4); - rx_buf_size = VT_RX_BUF_SIZE; + rx_buf_size = RX_BUF_SIZE; tot_buf_size = rx_desc_size + tx_desc_size; - tot_buf_size += VT_TX_DESC_NUM * tx_buf_size + VT_RX_DESC_NUM * rx_buf_size; + tot_buf_size += TX_DESC_NUM * tx_buf_size + RX_DESC_NUM * rx_buf_size; if (tot_buf_size % 4096) tot_buf_size += 4096 - (tot_buf_size % 4096); if (!(buf = alloc_contig(tot_buf_size, 0, &buf_dma))) { - printf("VT6105: Fail to allocate memory!\n"); + printf("vt6105: Fail to allocate memory\n"); return -ENOMEM; } - pdev->vt_buf_size = tot_buf_size; - pdev->vt_buf = buf; + pdev->buf_size = tot_buf_size; + pdev->buf = buf; /* Rx descriptor */ - pdev->vt_rx_desc = (vt_desc *)buf; - pdev->vt_rx_desc_dma = buf_dma; + pdev->rx_desc = (vt_desc *)buf; + pdev->rx_desc_dma = buf_dma; memset(buf, 0, rx_desc_size); buf += rx_desc_size; buf_dma += rx_desc_size; /* Tx descriptor */ - pdev->vt_tx_desc = (vt_desc *)buf; - pdev->vt_tx_desc_dma = buf_dma; + pdev->tx_desc = (vt_desc *)buf; + pdev->tx_desc_dma = buf_dma; memset(buf, 0, tx_desc_size); buf += tx_desc_size; buf_dma += tx_desc_size; /* Rx buffer assignment */ - desc = pdev->vt_rx_desc; - next = pdev->vt_rx_desc_dma; - for (i = 0; i < VT_RX_DESC_NUM; i++) { + desc = pdev->rx_desc; + next = pdev->rx_desc_dma; + for (i = 0; i < RX_DESC_NUM; i++) { /* Set Rx buffer */ - pdev->vt_rx[i].buf_dma = buf_dma; - pdev->vt_rx[i].buf = buf; + pdev->rx[i].buf_dma = buf_dma; + pdev->rx[i].buf = buf; buf_dma += rx_buf_size; buf += rx_buf_size; /* Set Rx descriptor */ - desc->status = VT_DESC_OWN | - ((VT_RX_BUF_SIZE << 16) & VT_DESC_RX_LENMASK); - desc->addr = pdev->vt_rx[i].buf_dma; - desc->length = VT_RX_BUF_SIZE; - if (i == (VT_RX_DESC_NUM - 1)) - desc->next_desc = pdev->vt_rx_desc_dma; + /* ### RX_DESC_INIT ### */ + vt_init_rx_desc(desc, rx_buf_size, pdev->rx[i].buf_dma); + if (i == (RX_DESC_NUM - 1)) + desc->next = pdev->rx_desc_dma; else { next += sizeof(vt_desc); - desc->next_desc = next; + desc->next = next; desc++; } } /* Tx buffer assignment */ - desc = pdev->vt_tx_desc; - next = pdev->vt_tx_desc_dma; - for (i = 0; i < VT_TX_DESC_NUM; i++) { + desc = pdev->tx_desc; + next = pdev->tx_desc_dma; + for (i = 0; i < TX_DESC_NUM; i++) { /* Set Tx buffer */ - pdev->vt_tx[i].busy = 0; - pdev->vt_tx[i].buf_dma = buf_dma; - pdev->vt_tx[i].buf = buf; + pdev->tx[i].busy = 0; + pdev->tx[i].buf_dma = buf_dma; + pdev->tx[i].buf = buf; buf_dma += tx_buf_size; buf += tx_buf_size; /* Set Rx descriptor */ - desc->addr = pdev->vt_tx[i].buf_dma; - desc->length = VT_TX_BUF_SIZE; - if (i == (VT_TX_DESC_NUM - 1)) - desc->next_desc = pdev->vt_tx_desc_dma; + /* ### TX_DESC_INIT ### */ + vt_init_tx_desc(desc, tx_buf_size, pdev->tx[i].buf_dma); + if (i == (TX_DESC_NUM - 1)) + desc->next = pdev->tx_desc_dma; else { next += sizeof(vt_desc); - desc->next_desc = next; + desc->next = next; desc++; } } - pdev->vt_tx_busy_num = 0; - pdev->vt_tx_head = 0; - pdev->vt_tx_tail = 0; - pdev->vt_rx_head = 0; - pdev->vt_tx_alive = FALSE; + pdev->tx_busy_num = 0; + pdev->tx_head = 0; + pdev->tx_tail = 0; + pdev->rx_head = 0; return 0; } @@ -286,20 +395,24 @@ static int vt_init_buf(vt_driver *pdev) { static int vt_init_hw(vt_driver *pdev, ether_addr_t *addr) { int r, ret; - /* Set the interrupt handler */ - pdev->vt_hook = pdev->vt_irq; - if ((r = sys_irqsetpolicy(pdev->vt_irq, 0, &pdev->vt_hook)) != OK) { - printf("VT6105: Fail to set IRQ policy: %d!\n", r); + /* Set the OS interrupt handler */ + pdev->hook = pdev->irq; + if ((r = sys_irqsetpolicy(pdev->irq, 0, &pdev->hook)) != OK) { + printf("vt6105: Fail to set OS IRQ policy: %d\n", r); ret = -EFAULT; goto err_irq_policy; } /* Reset hardware */ - vt_reset_hw(pdev); + if (vt_reset_hw(pdev)) { + printf("vt6105: Fail to reset the device\n"); + ret = -EIO; + goto err_reset_hw; + } - /* Enable IRQ */ - if ((r = sys_irqenable(&pdev->vt_hook)) != OK) { - printf("VT6105: Fail to enable IRQ: %d!\n", r); + /* Enable OS IRQ */ + if ((r = sys_irqenable(&pdev->hook)) != OK) { + printf("vt6105: Fail to enable OS IRQ: %d\n", r); ret = -EFAULT; goto err_irq_enable; } @@ -308,279 +421,195 @@ static int vt_init_hw(vt_driver *pdev, ether_addr_t *addr) { vt_conf_addr(pdev, addr); /* Detect link status */ - vt_check_link(pdev); -#ifdef VT6105_DEBUG - if (pdev->vt_link) - printf("VT6105: Link up!\n"); + pdev->link = vt_check_link(pdev->base_addr); +#ifdef MY_DEBUG + if (pdev->link) + printf("vt6105: Link up\n"); else - printf("VT6105: Link down!\n"); + printf("vt6105: Link down\n"); #endif return 0; +err_reset_hw: err_irq_enable: err_irq_policy: return ret; } /* Reset hardware */ -static void vt_reset_hw(vt_driver *pdev) { - u16_t base = pdev->vt_base_addr; - u8_t db; - u16_t dw; - u32_t dl; - - /* Let power registers into sane state */ - vt_power_init(pdev); +static int vt_reset_hw(vt_driver *pdev) { + u32_t base = pdev->base_addr; + int ret; /* Reset the chip */ - vt_outw(base, VT_REG_CR, VT_CMD_RESET); - vt_inb(base, VT_REG_ADDR); - -#ifdef VT6105_DEBUG - if (vt_inw(base, VT_REG_CR) & VT_CMD_RESET) { - vt_outb(base, VT_REG_MCR1, 0x40); - usleep(100000); - if (vt_inw(base, VT_REG_CR) & VT_CMD_RESET) - printf("VT6105: Fail to completely reset!\n"); + /* ### RESET_HARDWARE_CAN_FAIL ### */ + if (vt_real_reset(base)) { + printf("vt6105: Fail to reset the hardware\n"); + ret = -EIO; + goto err_real_reset; } - else - printf("VT6105: Reset successfully!\n"); + + /* Initialize power */ + /* ### POWER_INIT_CAN_FAIL ### */ + if (vt_init_power(base)) { + printf("vt6105: Fail to initialize power\n"); + ret = -EIO; + goto err_init_power; + } + + /* Initialize MII interface */ + /* ### MII_INIT_CAN_FAIL ### */ + if (vt_init_mii(base)) { + printf("vt6105: Fail to initialize MII interface\n"); + ret = -EIO; + goto err_init_mii; + } + + /* Initialize hardware I/O registers */ + /* ### SET_RX_DESC_REG ### */ + if (vt_init_io(base)) { + printf("vt6105: Fail to initialize I/O registers\n"); + ret = -EIO; + goto err_init_io; + } + + /* Set Rx/Tx descriptor into register */ + /* ### SET_RX_DESC_REG ### */ + vt_out32(base, REG_RX_DESC_BASEL, pdev->rx_desc_dma); +#ifdef DESC_BASE_DMA64 + vt_out32(base, REG_RX_DESC_BASEU, 0x00000000); #endif - - /* Initialize regsiters */ - vt_outw(base, VT_REG_BCR0, 0x0006); - vt_outb(base, VT_REG_TCR, 0x20); /* Tx threshold is 256 bytes */ - vt_outb(base, VT_REG_RCR, 0x78); /* Rx threshold is 256 bytes */ - vt_outl(base, VT_REG_RD_BASE, pdev->vt_rx_desc_dma); /* Set Rx descriptor base address */ - vt_outl(base, VT_REG_TD_BASE, pdev->vt_tx_desc_dma); /* Set Tx descriptor base address */ - -#ifdef VT6105_DEBUG - dl = vt_inl(base, VT_REG_RD_BASE); - printf("VT6105: Rx descriptor DMA address is: 0x%08x\n", dl); - dl = vt_inl(base, VT_REG_TD_BASE); - printf("VT6105: Tx descriptor DMA address is: 0x%08x\n", dl); + /* ### SET_TX_DESC_REG ### */ + vt_out32(base, REG_TX_DESC_BASEL, pdev->tx_desc_dma); +#ifdef DESC_BASE_DMA64 + vt_out32(base, REG_TX_DESC_BASEU, 0x00000000); #endif /* Enable interrupts */ - vt_outw(base, VT_REG_IMR, 0xfeff); + /* ### ENABLE_INTR ### */ + vt_out16(base, REG_IMR, INTR_IMR_ENABLE); /* Start the device, Rx and Tx */ - dw = VT_CMD_START | VT_CMD_RX_ON | VT_CMD_TX_ON | VT_CMD_NO_POLL | VT_CMD_FDUPLEX; - vt_outw(base, VT_REG_CR, dw); - dw = vt_inw(base, VT_REG_CR); + /* ### START_RX_TX ### */ + vt_start_rx_tx(base); -#ifdef VT6105_DEBUG - dw = vt_inw(base, VT_REG_CR); - printf("VT6105: Control status is 0x%04x\n", dw); -#endif -} - -/* Initialize power registers */ -static void vt_power_init(vt_driver *pdev) { - u8_t db, wolstat; - u16_t dw, base = pdev->vt_base_addr; - u32_t dl; - - /* Make sure chip is in power state D0 */ - db = vt_inb(base, VT_REG_STICK); - vt_outb(base, VT_REG_STICK, db & 0xfc); - - /* Disable "force PME-enable" */ - vt_outb(base, VT_REG_WOLC_SET, 0x80); - - /* Clear power-event config bits (WOL) */ - vt_outb(base, VT_REG_WOL_SET, 0xff); - - /* Save power-event status bits */ - wolstat = vt_inb(base, VT_REG_WOLS_SET); - - /* Clear power-event status bits */ - vt_outb(base, VT_REG_WOLS_CLR, 0xff); - -#ifdef VT6105_DEBUG - if (wolstat) { - char reason[50]; - switch (wolstat) { - case VT_WOL_MAGIC: - strcpy(reason, "Magic packet"); - break; - case VT_WOL_LINK_UP: - strcpy(reason, "Link up"); - break; - case VT_WOL_LINK_DOWN: - strcpy(reason, "Link down"); - break; - case VT_WOL_UCAST: - strcpy(reason, "Unicast packet"); - break; - case VT_WOL_MCAST: - strcpy(reason, "Multicast/Broadcast packet"); - break; - default: - strcpy(reason, "Unknown"); - } - printf("VT6105: Wake system up: %s\n", reason); - } -#endif + return 0; + +err_init_io: +err_init_mii: +err_init_power: +err_real_reset: + return ret; } +/* Configure MAC address */ static void vt_conf_addr(vt_driver *pdev, ether_addr_t *addr) { - u16_t dw, base = pdev->vt_base_addr; - int i; + u8_t pa[6]; + u32_t base = pdev->base_addr; - for (i=0; i<6; i++) - addr->ea_addr[i] = vt_inb(base, VT_REG_ADDR + i); - -#ifdef VT6105_DEBUG - printf("VT6105: Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n", - addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2], - addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5]); + /* Get MAC address */ + /* ### GET_MAC_ADDR ### */ + vt_get_addr(base, pa); + addr->ea_addr[0] = pa[0]; + addr->ea_addr[1] = pa[1]; + addr->ea_addr[2] = pa[2]; + addr->ea_addr[3] = pa[3]; + addr->ea_addr[4] = pa[4]; + addr->ea_addr[5] = pa[5]; +#ifdef MY_DEBUG + printf("vt6105: Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n", + addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2], + addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5]); #endif } -/* Detect link status (MII interface) */ -static void vt_check_link(vt_driver *pdev) { - u16_t base = pdev->vt_base_addr; - u32_t res; - - vt_outb(base, VT_REG_MII_CFG, 0x01); - vt_outb(base, VT_REG_MII_ADDR, 0x01); - vt_outb(base, VT_REG_MII_CR, 0x40); - usleep(10000); - res = vt_inw(base, VT_REG_MII_DATA); - if (res & 0x0004) - pdev->vt_link = TRUE; - else - pdev->vt_link = FALSE; -} - /* Stop the driver */ -static void vt_stop(void) { - u16_t base = g_driver.vt_base_addr; +static void vt_stop(void) { + u32_t base = g_driver.base_addr; /* Free Rx and Tx buffer*/ - free_contig(g_driver.vt_buf, g_driver.vt_buf_size); + free_contig(g_driver.buf, g_driver.buf_size); - /* Stop IRQ and device */ - vt_outw(base, VT_REG_IMR, 0x0000); - vt_outw(base, VT_REG_CR, VT_CMD_STOP); + /* Stop interrupt */ + /* ### DISABLE_INTR ### */ + vt_out16(base, REG_IMR, INTR_IMR_DISABLE); + + /* Stop Rx/Tx */ + /* ### STOP_RX_TX ### */ + vt_stop_rx_tx(base); } /* Set driver mode */ static void vt_mode(unsigned int mode) { vt_driver *pdev = &g_driver; - u16_t base = pdev->vt_base_addr; + u32_t base = pdev->base_addr; u8_t rcr; - pdev->vt_mode = mode; - vt_outl(base, VT_REG_MAR0, 0xffffffff); - vt_outl(base, VT_REG_MAR1, 0xffffffff); + pdev->mode = mode; - rcr = vt_inb(base, VT_REG_RCR); - rcr &= ~(VT_RCR_AB | VT_RCR_AM | VT_RCR_AP | VT_RCR_AE | VT_RCR_AR); - if (pdev->vt_mode & NDEV_PROMISC) - rcr |= VT_RCR_AB | VT_RCR_AM | VT_RCR_AE | VT_RCR_AR; - if (pdev->vt_mode & NDEV_BROAD) - rcr |= VT_RCR_AB; - if (pdev->vt_mode & NDEV_MULTI) - rcr |= VT_RCR_AM; - rcr |= VT_RCR_AP; - vt_outb(base, VT_REG_RCR, 0x60 | rcr); + /* ### READ_RCR ### */ + rcr = vt_in8(base, REG_RCR); + rcr &= ~(RCR_UNICAST | RCR_MULTICAST | RCR_BROADCAST); + if (pdev->mode & NDEV_PROMISC) + rcr |= RCR_UNICAST | RCR_MULTICAST; + if (pdev->mode & NDEV_BROAD) + rcr |= RCR_BROADCAST; + if (pdev->mode & NDEV_MULTI) + rcr |= RCR_MULTICAST; + rcr |= RCR_UNICAST; + /* ### WRITE_RCR ### */ + vt_out8(base, REG_RCR, rcr); } /* Receive data */ static ssize_t vt_recv(struct netdriver_data *data, size_t max) { vt_driver *pdev = &g_driver; - u32_t rxstat, totlen, packlen; + u32_t totlen, packlen; vt_desc *desc; int index, i; - index = pdev->vt_rx_head; - desc = pdev->vt_rx_desc; + index = pdev->rx_head; + desc = pdev->rx_desc; desc += index; - /* Manage Rx buffer */ - for (;;) { - rxstat = desc->status; + /* Check whether the receiving is OK */ + /* ### CHECK_RX_STATUS_OK ### */ + if (vt_rx_status_ok(desc) != TRUE) + return SUSPEND; - if (rxstat & VT_DESC_OWN) - return SUSPEND; - - if (rxstat & VT_DESC_RX_ALL_ERR) { -#ifdef VT6105_DEBUG - printf("VT6105: Rx error: 0x%08x\n", rxstat); -#endif - if (rxstat & VT_DESC_RX_FOV) { -#ifdef VT6105_DEBUG - printf("VT6105: Rx buffer overflow\n"); -#endif - pdev->vt_stat.ets_fifoOver++; - } - if (rxstat & VT_DESC_RX_FAE) { -#ifdef VT6105_DEBUG - printf("VT6105: Rx frames not align\n"); -#endif - pdev->vt_stat.ets_frameAll++; - } - if (rxstat & VT_DESC_RX_CRCE) { -#ifdef VT6105_DEBUG - printf("VT6105: Rx CRC error\n"); -#endif - pdev->vt_stat.ets_CRCerr++; - } - } - - /* Normal packet */ - if ((rxstat & VT_DESC_RX_PACK) == VT_DESC_RX_PACK) - break; - - /* Other packet */ - if (index == VT_RX_DESC_NUM - 1) { - desc->status = VT_DESC_OWN | - ((VT_RX_BUF_SIZE << 16) & VT_DESC_RX_LENMASK); - index = 0; - desc = pdev->vt_rx_desc; - } - else { - desc->status = VT_DESC_OWN | - ((VT_RX_BUF_SIZE << 16) & VT_DESC_RX_LENMASK); - index++; - desc++; - } - } + /* Check Rx status error */ + /* ### CHECK_RX_STATUS_ERROR ### */ + if (desc->status & DESC_STATUS_RX_RECV_ERR) + printf("vt6105: Rx error\n"); /* Get data length */ - totlen = (rxstat & VT_DESC_RX_LENMASK) >> 16; + /* ### Get Rx data length ### */ + totlen = vt_get_rx_len(desc); if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) { - printf("VT6105: Bad data length: %d\n", totlen); + printf("vt6105: Bad data length: %d\n", totlen); panic(NULL); } - /* Substract CRC to get packet */ - packlen = totlen - ETH_CRC_SIZE; + packlen = totlen; if (packlen > max) packlen = max; /* Copy data to user */ - netdriver_copyout(data, 0, pdev->vt_rx[index].buf, packlen); - pdev->vt_stat.ets_packetR++; + netdriver_copyout(data, 0, pdev->rx[index].buf, packlen); + pdev->stat.ets_packetR++; /* Set Rx descriptor status */ - if (index == VT_RX_DESC_NUM - 1) { - desc->status = VT_DESC_OWN | - ((VT_RX_BUF_SIZE << 16) & VT_DESC_RX_LENMASK); + /* ### SET_RX_STATUS_INTR ### */ + desc->status = DESC_STATUS_RX_RECV_CLEAR; + if (index == RX_DESC_NUM - 1) index = 0; - } - else { - desc->status = VT_DESC_OWN | - ((VT_RX_BUF_SIZE << 16) & VT_DESC_RX_LENMASK); + else index++; - } - pdev->vt_rx_head = index; + pdev->rx_head = index; -#ifdef VT6105_DEBUG - printf("VT6105: Successfully receive a packet, length = %d\n", packlen); +#ifdef MY_DEBUG + printf("vt6105: Successfully receive a packet, length = %d\n", packlen); #endif return packlen; @@ -591,36 +620,34 @@ static int vt_send(struct netdriver_data *data, size_t size) { vt_driver *pdev = &g_driver; vt_desc *desc; int tx_head, i; - u8_t db; - u16_t base = pdev->vt_base_addr; + u32_t base = pdev->base_addr; - tx_head = pdev->vt_tx_head; - desc = pdev->vt_tx_desc; + tx_head = pdev->tx_head; + desc = pdev->tx_desc; desc += tx_head; - if (pdev->vt_tx[tx_head].busy) + if (pdev->tx[tx_head].busy) return SUSPEND; /* Copy data from user */ - netdriver_copyin(data, 0, pdev->vt_tx[tx_head].buf, size); + netdriver_copyin(data, 0, pdev->tx[tx_head].buf, size); /* Set busy */ - pdev->vt_tx[tx_head].busy = TRUE; - pdev->vt_tx_busy_num++; + pdev->tx[tx_head].busy = TRUE; + pdev->tx_busy_num++; /* Set Tx descriptor status */ - desc->status = VT_DESC_OWN | VT_DESC_FIRST | VT_DESC_LAST; - desc->length = 0x00e08000 | (size >= 60 ? size : 60); - if (tx_head == VT_TX_DESC_NUM - 1) + /* ### TX_DESC_START ### */ + vt_tx_desc_start(desc, size); + if (tx_head == TX_DESC_NUM - 1) tx_head = 0; else tx_head++; - pdev->vt_tx_head = tx_head; + pdev->tx_head = tx_head; /* Wake up transmit channel */ - db = vt_inb(base, VT_REG_CR); - db |= VT_CMD_TX_DEMAND; - vt_outb(base, VT_REG_CR, db); + /* ### WAKE_UP_TX ### */ + vt_wakeup_tx(base); return 0; } @@ -633,8 +660,8 @@ static void vt_intr(unsigned int mask) { vt_handler(&g_driver); /* Reenable interrupts for this hook */ - if ((s = sys_irqenable(&g_driver.vt_hook)) != OK) - printf("VT6105: Cannot enable interrupts: %d\n", s); + if ((s = sys_irqenable(&g_driver.hook)) != OK) + printf("vt6105: Cannot enable OS interrupts: %d\n", s); /* Perform tasks based on the flagged conditions */ vt_check_ints(&g_driver); @@ -642,166 +669,116 @@ static void vt_intr(unsigned int mask) { /* Real handler interrupt */ static void vt_handler(vt_driver *pdev) { - u16_t base = pdev->vt_base_addr; - int intr_status; - u8_t db; - u16_t dw; - u32_t dl, txstat; + u32_t base = pdev->base_addr; + u16_t intr_status; int flag = 0, tx_head, tx_tail; vt_desc *desc; /* Get interrupt status */ - intr_status = vt_inw(base, VT_REG_ISR); + /* ### GET_INTR_STATUS ### */ + intr_status = vt_in16(base, REG_ISR); - /* Clear interrupt */ - dw = intr_status & ~(VT_INTR_PCI_ERR | VT_INTR_PORT_CHANGE); - vt_outw(base, VT_REG_ISR, dw); + /* Clear interrupt */ + /* ### CLEAR_INTR ### */ + vt_out16(base, REG_ISR, intr_status & INTR_ISR_CLEAR); - /* Check link status */ - if (intr_status & VT_INTR_PORT_CHANGE) - printf("VT6105: Port state change!\n"); + /* Enable interrupt */ + /* ### ENABLE_INTR ### */ + vt_out16(base, REG_IMR, INTR_IMR_ENABLE); - /* Check interrupt status */ - if (intr_status & VT_INTR_RX_DONE) { - pdev->vt_recv_flag = TRUE; - flag++; - - if (intr_status & VT_INTR_RX_ERR) { - pdev->vt_stat.ets_recvErr++; - printf("VT6105: Rx error in interrupt: 0x%04x\n", intr_status); - } - if (intr_status & VT_INTR_RX_NOBUF) - printf("VT6105: Rx no buffer in interrupt: 0x%04x\n", intr_status); - if (intr_status & VT_INTR_RX_EMPTY) - printf("VT6105: Rx buffer empty in interrupt: 0x%04x\n", intr_status); - if (intr_status & VT_INTR_RX_OVERFLOW) - printf("VT6105: Rx buffer overflow in interrupt: 0x%04x\n", intr_status); - if (intr_status & VT_INTR_RX_DROPPED) - printf("VT6105: Rx buffer dropped in interrupt: 0x%04x\n", intr_status); - } - if (intr_status & VT_INTR_TX_DONE) { - pdev->vt_send_flag = TRUE; - flag++; - - if (intr_status & VT_INTR_TX_ERR) { - pdev->vt_stat.ets_sendErr++; - printf("VT6105: Tx error in interrupt: 0x%04x\n", intr_status); - } - if (intr_status & VT_INTR_TX_UNDER_RUN) - printf("VT6105: Tx buffer underflow in interrupt: 0x%04x\n", intr_status); - if (intr_status & VT_INTR_TX_ABORT) - printf("VT6105: Tx abort in interrupt: 0x%04x\n", intr_status); - - /* Manage Tx Buffer */ - tx_head = pdev->vt_tx_head; - tx_tail = pdev->vt_tx_tail; - while (tx_tail != tx_head) { - desc = pdev->vt_tx_desc; - desc += tx_tail; - if (!pdev->vt_tx[tx_tail].busy) - printf("VT6105: Strange, buffer not busy?\n"); - txstat = desc->status; - - /* Check whether the buffer is ready */ - if (txstat & VT_DESC_OWN) { - break; - } - - if (txstat & VT_DESC_TX_ERR) { -#ifdef VT6105_DEBUG - printf("VT6105: Tx error: 0x%08x\n", txstat); -#endif - if (txstat & VT_DESC_TX_UDF) { -#ifdef VT6105_DEBUG - printf("VT6105: Tx buffer underflow\n"); -#endif - pdev->vt_stat.ets_fifoUnder++; - } - if (txstat & VT_DESC_TX_CRS) { -#ifdef VT6105_DEBUG - printf("VT6105: Tx carrier sense lost\n"); -#endif - pdev->vt_stat.ets_carrSense++; - } - if (txstat & VT_DESC_TX_CDH) { -#ifdef VT6105_DEBUG - printf("VT6105: Tx collision detect\n"); -#endif - pdev->vt_stat.ets_collision++; - } - if (txstat & VT_DESC_TX_OWC) { -#ifdef VT6105_DEBUG - printf("VT6105: Tx buffer out of winidow\n"); -#endif - pdev->vt_stat.ets_OWC++; - } - } - - pdev->vt_stat.ets_packetT++; - pdev->vt_tx[tx_tail].busy = FALSE; - pdev->vt_tx_busy_num--; - - if (++tx_tail >= VT_TX_DESC_NUM) - tx_tail = 0; - - pdev->vt_send_flag = TRUE; - pdev->vt_recv_flag = TRUE; - pdev->vt_tx_alive = TRUE; - -#ifdef VT6105_DEBUG - printf("VT6105: Successfully send a packet\n"); -#endif - } - pdev->vt_tx_tail = tx_tail; - } - if (!flag) { - printf("VT6105: Unknown error in interrupt: 0x%04x\n", intr_status); + /* Check interrupt error */ + /* ### CHECK_INTR_ERROR ### */ + if (intr_status & INTR_ISR_ERR) { + printf("vt6105: interrupt error\n"); return; } - /* Perform tasks based on the flagged condition */ - vt_check_ints(pdev); + /* Check link status */ + /* ### CHECK_LINK_INTR ### */ + if (intr_status & INTR_ISR_LINK_EVENT) { + pdev->link = vt_check_link(base); +#ifdef MY_DEBUG + printf("vt6105: Link state change\n"); +#endif + flag++; + } + + /* Check Rx request status */ + /* ### CHECK_RX_INTR ### */ + if (intr_status & INTR_ISR_RX_DONE) { + pdev->recv_flag = TRUE; + flag++; + } + + /* Check Tx request status */ + /* ### CHECK_TX_INTR ### */ + if (intr_status & INTR_ISR_TX_DONE) { + pdev->send_flag = TRUE; + flag++; + + /* Manage Tx Buffer */ + tx_head = pdev->tx_head; + tx_tail = pdev->tx_tail; + while (tx_tail != tx_head) { + desc = pdev->tx_desc; + desc += tx_tail; + if (!pdev->tx[tx_tail].busy) + printf("vt6105: Strange, buffer not busy?\n"); + + /* Check whether the transmiting is OK */ + /* ### CHECK_TX_STATUS_OK ### */ + if (vt_tx_status_ok(desc) != TRUE) + break; + + /* Check Tx status error */ + /* ### CHECK_TX_STATUS_ERROR ### */ + if (desc->status & DESC_STATUS_TX_SEND_ERR) + printf("vt6105: Tx error\n"); + + pdev->stat.ets_packetT++; + pdev->tx[tx_tail].busy = FALSE; + pdev->tx_busy_num--; + + if (++tx_tail >= TX_DESC_NUM) + tx_tail = 0; + + pdev->send_flag = TRUE; + pdev->recv_flag = TRUE; + + /* Set Tx descriptor status in interrupt */ + /* ### SET_TX_STATUS_INTR ### */ + desc->status = DESC_STATUS_TX_SEND_CLEAR; + +#ifdef MY_DEBUG + printf("vt6105: Successfully send a packet\n"); +#endif + } + pdev->tx_tail = tx_tail; + } +#ifdef MY_DEBUG + if (!flag) { + printf("vt6105: Unknown error in interrupt\n"); + return; + } +#endif } /* Check interrupt and perform */ static void vt_check_ints(vt_driver *pdev) { - if (!pdev->vt_recv_flag) + if (!pdev->recv_flag) return; - pdev->vt_recv_flag = FALSE; + pdev->recv_flag = FALSE; /* Handle data receive */ netdriver_recv(); /* Handle data transmit */ - if (pdev->vt_send_flag) { - pdev->vt_send_flag = FALSE; + if (pdev->send_flag) { + pdev->send_flag = FALSE; netdriver_send(); } } static void vt_stat(eth_stat_t *stat) { - memcpy(stat, &g_driver.vt_stat, sizeof(*stat)); -} - -static void vt_alarm(clock_t stamp) { - vt_driver *pdev = &g_driver; - - /* Use a synchronous alarm instead of a watchdog timer */ - sys_setalarm(sys_hz(), 0); - - /* Assume the an idle system is alive */ - if (!pdev->vt_tx_busy_num) { - pdev->vt_tx_alive = TRUE; - return; - } - if (pdev->vt_tx_alive) { - pdev->vt_tx_alive = FALSE; - return; - } - - printf("VT6105: Resetting the driver\n"); - vt_reset_hw(pdev); - pdev->vt_recv_flag = TRUE; - - vt_check_ints(pdev); + memcpy(stat, &g_driver.stat, sizeof(*stat)); } diff --git a/minix/drivers/net/vt6105/vt6105.conf b/minix/drivers/net/vt6105/vt6105.conf index 00076ca69..5fb39f8ae 100755 --- a/minix/drivers/net/vt6105/vt6105.conf +++ b/minix/drivers/net/vt6105/vt6105.conf @@ -1,16 +1,17 @@ service vt6105 { - type net; - descr "VIA Technology 6105/6106S Ethernet Card"; - system - UMAP # 14 - IRQCTL # 19 - DEVIO # 21 - ; - pci device 1106:3053; - pci device 1106:3106; - ipc - SYSTEM pm rs log tty ds vm - pci inet lwip amddev - ; + type net; + descr "VIA Technology 6105/6106S Ethernet Card"; + system + UMAP # 14 + IRQCTL # 19 + DEVIO # 21 + ; + pci device 1106:3053; + pci device 1106:3106; + ipc + SYSTEM pm rs log tty ds vm + pci inet lwip amddev + ; }; + diff --git a/minix/drivers/net/vt6105/vt6105.h b/minix/drivers/net/vt6105/vt6105.h index 51c842724..fec019beb 100644 --- a/minix/drivers/net/vt6105/vt6105.h +++ b/minix/drivers/net/vt6105/vt6105.h @@ -1,194 +1,146 @@ +#ifndef _vt_H +#define _vt_H + #include -#include -#include -#include -#include -/* PCI Register */ -#define VT_PCI_VID 0x00 /* Vendor ID */ -#define VT_PCI_DID 0x02 /* Device ID */ -#define VT_PCI_CMD 0x04 /* Command */ -#define VT_PCI_STS 0x06 /* Status */ -#define VT_PCI_RID 0x08 /* Revision ID */ -#define VT_PCI_CC 0x09 /* Class Code */ -#define VT_PCI_CLS 0x0c /* Cache Line Size */ -#define VT_PCI_LT 0x0d /* Latency Timer */ -#define VT_PCI_HT 0x0e /* Header Type */ +/* ======= General Parameter ======= */ +/* Global configure */ +#define DESC_BASE64 -/* Internal Register */ -#define VT_REG_ADDR 0x00 /* Ethernet Address */ -#define VT_REG_RCR 0x06 /* Receive Configure Request */ -#define VT_REG_TCR 0x07 /* Transmit Configure Request */ -#define VT_REG_CR 0x08 /* Control 0 */ -#define VT_REG_ISR 0x0c /* Interrupt Status */ -#define VT_REG_IMR 0x0e /* Interrupt Mask */ -#define VT_REG_MAR0 0x10 /* Multicast Address 0 */ -#define VT_REG_MAR1 0x14 /* Multicast Address 1 */ -#define VT_REG_RD_BASE 0x18 /* Receive Descriptor Base Address */ -#define VT_REG_TD_BASE 0x1c /* Transmit Descriptor Base Address */ -#define VT_REG_MII_CFG 0x6c /* MII Configuration */ -#define VT_REG_MII_STS 0x6d /* MII Status */ -#define VT_REG_BCR0 0x6e /* Bus Control 0 */ -#define VT_REG_BCR1 0x6f /* Bus Control 1 */ -#define VT_REG_MII_CR 0x70 /* MII Control */ -#define VT_REG_MII_ADDR 0x71 /* MII Interface Address*/ -#define VT_REG_MII_DATA 0x72 /* MII Data Port */ -#define VT_REG_EECSR 0x74 /* EEPROM Control/Status */ -#define VT_REG_CFG_A 0x78 /* Chip Configuration A */ -#define VT_REG_CFG_B 0x79 /* Chip Configuration B */ -#define VT_REG_CFG_C 0x7a /* Chip Configuration C */ -#define VT_REG_CFG_D 0x7b /* Chip Configuration D */ -#define VT_REG_MCR0 0x80 /* Miscellaneous Control 0 */ -#define VT_REG_MCR1 0x81 /* Miscellaneous Control 1 */ -#define VT_REG_STICK 0x83 /* Sticky Hardware Control */ -#define VT_REG_MISR 0x84 /* MII Interrupt Status */ -#define VT_REG_MIMR 0x86 /* MII Interrupt Mask */ -#define VT_REG_FCR0 0x98 /* Flow Control 0 */ -#define VT_REG_FCR1 0x99 /* Flow Control 1 */ -#define VT_REG_WOL_SET 0xA4 /* Wake On LAN Set */ -#define VT_REG_WOL_CLR 0xA0 /* Wake On LAN Clear */ -#define VT_REG_PCS_CLR 0xA5 /* Power Configuration Set */ -#define VT_REG_PCS_SET 0xA1 /* Power Configuration Clear */ -#define VT_REG_WOLC_SET 0xA7 /* WOL Configuration Set */ -#define VT_REG_WOLC_CLR 0xA3 /* WOL Configuration Clear */ -#define VT_REG_WOLS_SET 0xA8 /* WOL Status Clear */ -#define VT_REG_WOLS_CLR 0xAC /* WOL Status Set */ +/* Rx/Tx buffer parameter */ +#define RX_BUF_SIZE 1536 +#define TX_BUF_SIZE 1536 +#define RX_DESC_NUM 64 +#define TX_DESC_NUM 64 -/* Interrupt Status/Mask Register */ -#define VT_INTR_RX_DONE 0x0001 -#define VT_INTR_TX_DONE 0x0002 -#define VT_INTR_RX_ERR 0x0004 -#define VT_INTR_TX_ERR 0x0008 -#define VT_INTR_RX_EMPTY 0x0020 -#define VT_INTR_PCI_ERR 0x0040 -#define VT_INTR_STS_MAX 0x0080 -#define VT_INTR_RX_EARLY 0x0100 -#define VT_INTR_TX_UNDER_RUN 0x0210 -#define VT_INTR_RX_OVERFLOW 0x0400 -#define VT_INTR_RX_DROPPED 0x0800 -#define VT_INTR_RX_NOBUF 0x1000 -#define VT_INTR_TX_ABORT 0x2000 -#define VT_INTR_PORT_CHANGE 0x4000 -#define VT_INTR_RX_WAKE_UP 0x8000 +/* Key internal register */ +#define REG_RCR 0x06 +#define REG_ISR 0x0c +#define REG_IMR 0x0e +#define REG_RX_DESC_BASEL 0x18 +#define REG_TX_DESC_BASEL 0x1c -/* Control Register Command */ -#define VT_CMD_START 0x0002 -#define VT_CMD_STOP 0x0004 -#define VT_CMD_RX_ON 0x0008 -#define VT_CMD_TX_ON 0x0010 -#define VT_CMD_TX_DEMAND 0x0020 -#define VT_CMD_RX_DEMAND 0x0040 -#define VT_CMD_EARLY_RX 0x0100 -#define VT_CMD_EARLY_TX 0x0200 -#define VT_CMD_FDUPLEX 0x0400 -#define VT_CMD_NO_POLL 0x0800 -#define VT_CMD_RESET 0x8000 +#ifdef DESC_BASE_DMA64 +#define REG_RX_DESC_BASEU 0 +#define REG_TX_DESC_BASEU 0 +#endif -/* Receive Configure Mode */ -#define VT_RCR_AP 0x10 -#define VT_RCR_AB 0x08 -#define VT_RCR_AM 0x04 -#define VT_RCR_AR 0x02 -#define VT_RCR_AE 0x01 +/* Key internal register width */ +#define WIDTH_REG_RCR 8 +#define WIDTH_REG_ISR 16 +#define WIDTH_REG_IMR 16 -/* General Descriptor Flag */ -#define VT_DESC_OWN 0x80000000 /* Ownership */ -#define VT_DESC_FIRST 0x00000200 /* First Descriptor */ -#define VT_DESC_LAST 0x00000100 /* Last Descriptor */ +/* Interrupt statu and command */ +#define INTR_ISR_ERR 0x3ffc +#define INTR_ISR_LINK_EVENT 0x4000 +#define INTR_ISR_RX_DONE 0x0001 +#define INTR_ISR_TX_DONE 0x0002 +#define INTR_ISR_CLEAR 0xbfbf +#define INTR_IMR_ENABLE 0xfeff +#define INTR_IMR_DISABLE 0x0000 -/* Rx Descriptor Flag */ -#define VT_DESC_RX_LENMASK 0x7fff0000 /* Receive Frame Length Mask */ -#define VT_DESC_RX_OK 0x00008000 /* Receive OK */ -#define VT_DESC_RX_MAR 0x00002000 /* Multicast Address Received */ -#define VT_DESC_RX_BAR 0x00001000 /* Broadcast Address Received */ -#define VT_DESC_RX_PHY 0x00000800 /* Physical Address Received */ -#define VT_DESC_RX_LINK_ERR 0x00000080 /* Descriptor Link Structure Error */ -#define VT_DESC_RX_RUNT 0x00000020 /* Runt Packet */ -#define VT_DESC_RX_LONG 0x00000010 /* Long Packet */ -#define VT_DESC_RX_FOV 0x00000008 /* FIFO Overflow */ -#define VT_DESC_RX_FAE 0x00000004 /* Frame Align Error */ -#define VT_DESC_RX_CRCE 0x00000002 /* CRC Error */ -#define VT_DESC_RX_ERR 0x00000001 /* Receive Error */ -#define VT_DESC_RX_ALL_ERR (VT_DESC_RX_LINK_ERR | VT_DESC_RX_RUNT | \ - VT_DESC_RX_LONG | VT_DESC_RX_FOV | \ - VT_DESC_RX_FAE | VT_DESC_RX_CRCE | VT_DESC_RX_ERR) -#define VT_DESC_RX_PACK (VT_DESC_FIRST | VT_DESC_LAST) +/* Descriptor status */ +#define DESC_STATUS_RX_RECV_ERR 0x000000bf +#define DESC_STATUS_RX_RECV_CLEAR 0x80000000 +#define DESC_STATUS_TX_SEND_ERR 0x00008f10 +#define DESC_STATUS_TX_SEND_CLEAR 0x00000000 -/* Tx Descriptor Flag */ -#define VT_DESC_TX_ERR 0x00008000 /* Transmit Error */ -#define VT_DESC_TX_UDF 0x00000800 /* FIFO Underflow */ -#define VT_DESC_TX_CRS 0x00000400 /* Carrier Sense Lost Detect */ -#define VT_DESC_TX_OWC 0x00000200 /* Out of Window Collision */ -#define VT_DESC_TX_ABT 0x00000100 /* Excessive Collision Abort */ -#define VT_DESC_TX_CDH 0x00000010 /* Collision Detect */ - -/* WOL status */ -#define VT_WOL_UCAST 0x10 -#define VT_WOL_MAGIC 0x20 -#define VT_WOL_MCAST 0x30 -#define VT_WOL_LINK_UP 0x40 -#define VT_WOL_LINK_DOWN 0x80 +/* Rx mode */ +#define RCR_UNICAST 0x10 +#define RCR_MULTICAST 0x04 +#define RCR_BROADCAST 0x08 /* Link status */ -#define VT_LINK_UP 1 -#define VT_LINK_DOWN 0 -#define VT_LINK_UNKNOWN -1 +#define LINK_UP 1 +#define LINK_DOWN 0 +#define LINK_UNKNOWN -1 -#define VT_RX_BUF_SIZE 1536 -#define VT_TX_BUF_SIZE 1536 -#define VT_RX_DESC_NUM 64 -#define VT_TX_DESC_NUM 64 +/* Basic Rx/Tx parameters */ +#define RX_BUF_SIZE 1536 +#define TX_BUF_SIZE 1536 +#define RX_DESC_NUM 64 +#define TX_DESC_NUM 64 -/* #define VT6105_DEBUG */ +/* ======= Self-defined Parameter ======= */ +#define DESC_OWN 0x80000000 +#define DESC_FIRST 0x00000200 +#define DESC_LAST 0x00000100 -/* Data Descriptor */ +#define DESC_RX_LENMASK 0x7fff0000 +#define DESC_RX_OK 0x00008000 +#define DESC_RX_NORMAL (DESC_FIRST | DESC_LAST) + +#define REG_ADDR 0x00 +#define REG_TCR 0x07 +#define REG_CR 0x08 +#define REG_BCR0 0x6e +#define REG_MCR1 0x81 +#define REG_STICK 0x83 +#define REG_MII_CFG 0x6c +#define REG_MII_CR 0x70 +#define REG_MII_ADDR 0x71 +#define REG_MII_DATA 0x72 +#define REG_WOL_SET 0xa4 +#define REG_WOLC_SET 0xa7 + +#define CMD_START 0x0002 +#define CMD_STOP 0x0004 +#define CMD_RX_ON 0x0008 +#define CMD_TX_ON 0x0010 +#define CMD_TX_DEMAND 0x0020 +#define CMD_RX_DEMAND 0x0040 +#define CMD_FDUPLEX 0x0400 +#define CMD_NO_POLL 0x0800 +#define CMD_RESET 0x8000 + +/* ======= Data Descriptor ======= */ typedef struct vt_desc { - u32_t status; /* command/status */ - u32_t length; /* Buffer/Frame length */ - u32_t addr; /* DMA buffer address */ - u32_t next_desc; /* Next descriptor */ + u32_t status; + u32_t length; + u32_t addr; + u32_t next; } vt_desc; /* Driver Data Structure */ typedef struct vt_driver { - u16_t vt_base_addr; /* Base address */ - int vt_revision; /* Revision ID */ - int vt_irq; /* IRQ number */ - int vt_mode; - int vt_link; /* Whether link-up */ - int vt_recv_flag; /* Receive flag */ - int vt_send_flag; /* Send flag */ - int vt_report_link; - int vt_tx_alive; - int vt_tx_busy; + u32_t base_addr; /* Base address */ + int revision; /* Revision ID */ + int irq; /* IRQ number */ + int mode; + int link; /* Whether link-up */ + int recv_flag; /* Receive flag */ + int send_flag; /* Send flag */ + int tx_busy; /* Buffer */ - size_t vt_buf_size; - char *vt_buf; + size_t buf_size; + char *buf; /* Rx data */ - int vt_rx_head; + int rx_head; struct { phys_bytes buf_dma; char *buf; - } vt_rx[VT_RX_DESC_NUM]; - vt_desc *vt_rx_desc; /* Rx descriptor buffer */ - phys_bytes vt_rx_desc_dma; /* Rx descriptor DMA buffer */ + } rx[RX_DESC_NUM]; + vt_desc *rx_desc; /* Rx descriptor buffer */ + phys_bytes rx_desc_dma; /* Rx descriptor DMA buffer */ /* Tx data */ - int vt_tx_head; - int vt_tx_tail; + int tx_head; + int tx_tail; struct { int busy; phys_bytes buf_dma; char *buf; - } vt_tx[VT_TX_DESC_NUM]; - vt_desc *vt_tx_desc; /* Tx descriptor buffer */ - phys_bytes vt_tx_desc_dma; /* Tx descriptor DMA buffer */ - int vt_tx_busy_num; /* Number of busy Tx descriptors */ + } tx[TX_DESC_NUM]; + vt_desc *tx_desc; /* Tx descriptor buffer */ + phys_bytes tx_desc_dma; /* Tx descriptor DMA buffer */ + int tx_busy_num; /* Number of busy Tx descriptors */ - int vt_hook; /* IRQ hook id at kernel */ - eth_stat_t vt_stat; + int hook; /* IRQ hook id at kernel */ + eth_stat_t stat; - char vt_name[20]; + char name[20]; } vt_driver; + +#endif