From 9c0eb889466b0cbd190168ebb4cdfccd29986347 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Wed, 19 Oct 2016 10:11:26 +0000 Subject: [PATCH] Add the driver for VIA Technology 6105/6106S Ethernet card --- minix/drivers/net/vt6105/Makefile | 14 + minix/drivers/net/vt6105/vt6105 | Bin 0 -> 81168 bytes minix/drivers/net/vt6105/vt6105.c | 807 +++++++++++++++++++++++++++ minix/drivers/net/vt6105/vt6105.conf | 16 + minix/drivers/net/vt6105/vt6105.h | 194 +++++++ 5 files changed, 1031 insertions(+) create mode 100755 minix/drivers/net/vt6105/Makefile create mode 100755 minix/drivers/net/vt6105/vt6105 create mode 100644 minix/drivers/net/vt6105/vt6105.c create mode 100755 minix/drivers/net/vt6105/vt6105.conf create mode 100644 minix/drivers/net/vt6105/vt6105.h diff --git a/minix/drivers/net/vt6105/Makefile b/minix/drivers/net/vt6105/Makefile new file mode 100755 index 000000000..50d1e75ea --- /dev/null +++ b/minix/drivers/net/vt6105/Makefile @@ -0,0 +1,14 @@ +# Makefile for the VIA Technology 6105/6106S Ethernet driver (vt6105) +PROG= vt6105 +SRCS= vt6105.c + +FILES=${PROG}.conf +FILESNAME=${PROG} +FILESDIR= /etc/system.conf.d + +DPADD+= ${LIBNETDRIVER} ${LIBSYS} +LDADD+= -lnetdriver -lsys + +CPPFLAGS+= -I${NETBSDSRCDIR}/minix + +.include diff --git a/minix/drivers/net/vt6105/vt6105 b/minix/drivers/net/vt6105/vt6105 new file mode 100755 index 0000000000000000000000000000000000000000..a367ab2d544b130b0eeb0b0809eda9dc7d9aa243 GIT binary patch literal 81168 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 literal 0 HcmV?d00001 diff --git a/minix/drivers/net/vt6105/vt6105.c b/minix/drivers/net/vt6105/vt6105.c new file mode 100644 index 000000000..85712bb28 --- /dev/null +++ b/minix/drivers/net/vt6105/vt6105.c @@ -0,0 +1,807 @@ +#include "vt6105.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); +static void vt_mode(unsigned int mode); +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); + +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 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); + +static const struct netdriver vt_table = { + .ndr_init = vt_init, + .ndr_stop = vt_stop, + .ndr_mode = vt_mode, + .ndr_recv = vt_recv, + .ndr_send = vt_send, + .ndr_stat = vt_stat, + .ndr_intr = vt_intr, + .ndr_alarm = vt_alarm +}; + +int main(int argc, char *argv[]) { + env_setargs(argc, argv); + netdriver_task(&vt_table); +} + +/* Initialize the driver */ +static int vt_init(unsigned int instance, ether_addr_t *addr) { + int ret = 0; + + /* 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_instance = instance; + + /* Probe the device */ + if (vt_probe(&g_driver, instance)) { + 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"); + ret = -ENODEV; + goto err_init_buf; + } + + /* Intialize hardware */ + if (vt_init_hw(&g_driver, addr)) { + printf("VT6105: Find to initialize hardware!\n"); + ret = -EIO; + goto err_init_hw; + } + + /* Use a synchronous alarm instead of a watchdog timer */ + sys_setalarm(sys_hz(), 0); + + /* Clear send and recv flag */ + g_driver.vt_send_flag = FALSE; + g_driver.vt_recv_flag = FALSE; + + return 0; + +err_init_hw: + free_contig(g_driver.vt_buf, g_driver.vt_buf_size); +err_init_buf: +err_probe: + return ret; +} + +/* Match the device and get base address */ +static int vt_probe(vt_driver *pdev, int instance) { + int devind; + u16_t cr, vid, did; + u32_t bar; + u8_t irq, rev; + + /* Find pci device */ + pci_init(); + if (!pci_first_dev(&devind, &vid, &did)) + return -EIO; + while (instance--) { + if (!pci_next_dev(&devind, &vid, &did)) + return -EIO; + } + pci_reserve(devind); + + /* Enable bus mastering */ + cr = pci_attr_r16(devind, PCI_CR); + if (!(cr & PCI_CR_MAST_EN)) + 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"); + return -EIO; + } + pdev->vt_base_addr = bar; + + /* Get irq number */ + irq = pci_attr_r8(devind, PCI_ILR); + pdev->vt_irq = irq; + + /* Get revision ID */ + rev = pci_attr_r8(devind, PCI_REV); + pdev->vt_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); +#endif + + return 0; +} + +/* Allocate and initialize buffer */ +static int vt_init_buf(vt_driver *pdev) { + size_t rx_desc_size, tx_desc_size, rx_buf_size, tx_buf_size, tot_buf_size; + vt_desc *desc; + phys_bytes buf_dma, next; + char *buf; + 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); + + /* Allocate Rx and Tx buffer */ + tx_buf_size = VT_TX_BUF_SIZE; + if (tx_buf_size % 4) + tx_buf_size += 4 - (tx_buf_size % 4); + rx_buf_size = VT_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; + 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"); + return -ENOMEM; + } + pdev->vt_buf_size = tot_buf_size; + pdev->vt_buf = buf; + + /* Rx descriptor */ + pdev->vt_rx_desc = (vt_desc *)buf; + pdev->vt_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; + 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++) { + /* Set Rx buffer */ + pdev->vt_rx[i].buf_dma = buf_dma; + pdev->vt_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; + else { + next += sizeof(vt_desc); + desc->next_desc = 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++) { + /* Set Tx buffer */ + pdev->vt_tx[i].busy = 0; + pdev->vt_tx[i].buf_dma = buf_dma; + pdev->vt_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; + else { + next += sizeof(vt_desc); + desc->next_desc = 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; + + return 0; +} + +/* Intialize hardware */ +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); + ret = -EFAULT; + goto err_irq_policy; + } + + /* Reset hardware */ + vt_reset_hw(pdev); + + /* Enable IRQ */ + if ((r = sys_irqenable(&pdev->vt_hook)) != OK) { + printf("VT6105: Fail to enable IRQ: %d!\n", r); + ret = -EFAULT; + goto err_irq_enable; + } + + /* Configure MAC address */ + vt_conf_addr(pdev, addr); + + /* Detect link status */ + vt_check_link(pdev); +#ifdef VT6105_DEBUG + if (pdev->vt_link) + printf("VT6105: Link up!\n"); + else + printf("VT6105: Link down!\n"); +#endif + + return 0; + +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); + + /* 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"); + } + else + printf("VT6105: Reset successfully!\n"); +#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); +#endif + + /* Enable interrupts */ + vt_outw(base, VT_REG_IMR, 0xfeff); + + /* 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); + +#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 +} + +static void vt_conf_addr(vt_driver *pdev, ether_addr_t *addr) { + u16_t dw, base = pdev->vt_base_addr; + int i; + + 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]); +#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; + + /* Free Rx and Tx buffer*/ + free_contig(g_driver.vt_buf, g_driver.vt_buf_size); + + /* Stop IRQ and device */ + vt_outw(base, VT_REG_IMR, 0x0000); + vt_outw(base, VT_REG_CR, VT_CMD_STOP); +} + +/* Set driver mode */ +static void vt_mode(unsigned int mode) { + vt_driver *pdev = &g_driver; + u16_t base = pdev->vt_base_addr; + u8_t rcr; + + pdev->vt_mode = mode; + vt_outl(base, VT_REG_MAR0, 0xffffffff); + vt_outl(base, VT_REG_MAR1, 0xffffffff); + + 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); +} + +/* Receive data */ +static ssize_t vt_recv(struct netdriver_data *data, size_t max) { + vt_driver *pdev = &g_driver; + u32_t rxstat, totlen, packlen; + vt_desc *desc; + int index, i; + + index = pdev->vt_rx_head; + desc = pdev->vt_rx_desc; + desc += index; + + /* Manage Rx buffer */ + for (;;) { + rxstat = desc->status; + + 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++; + } + } + + /* Get data length */ + totlen = (rxstat & VT_DESC_RX_LENMASK) >> 16; + if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) { + printf("VT6105: Bad data length: %d\n", totlen); + panic(NULL); + } + + /* Substract CRC to get packet */ + packlen = totlen - ETH_CRC_SIZE; + if (packlen > max) + packlen = max; + + /* Copy data to user */ + netdriver_copyout(data, 0, pdev->vt_rx[index].buf, packlen); + pdev->vt_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); + index = 0; + } + else { + desc->status = VT_DESC_OWN | + ((VT_RX_BUF_SIZE << 16) & VT_DESC_RX_LENMASK); + index++; + } + pdev->vt_rx_head = index; + +#ifdef VT6105_DEBUG + printf("VT6105: Successfully receive a packet, length = %d\n", packlen); +#endif + + return packlen; +} + +/* Transmit data */ +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; + + tx_head = pdev->vt_tx_head; + desc = pdev->vt_tx_desc; + desc += tx_head; + + if (pdev->vt_tx[tx_head].busy) + return SUSPEND; + + /* Copy data from user */ + netdriver_copyin(data, 0, pdev->vt_tx[tx_head].buf, size); + + /* Set busy */ + pdev->vt_tx[tx_head].busy = TRUE; + pdev->vt_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_head = 0; + else + tx_head++; + pdev->vt_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); + + return 0; +} + +/* Handle Interrupt */ +static void vt_intr(unsigned int mask) { + int s; + + /* Run interrupt handler at driver level */ + 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); + + /* Perform tasks based on the flagged conditions */ + vt_check_ints(&g_driver); +} + +/* 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; + int flag = 0, tx_head, tx_tail; + vt_desc *desc; + + /* Get interrupt status */ + intr_status = vt_inw(base, VT_REG_ISR); + + /* Clear interrupt */ + dw = intr_status & ~(VT_INTR_PCI_ERR | VT_INTR_PORT_CHANGE); + vt_outw(base, VT_REG_ISR, dw); + + /* Check link status */ + if (intr_status & VT_INTR_PORT_CHANGE) + printf("VT6105: Port state change!\n"); + + /* 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); + return; + } + + /* Perform tasks based on the flagged condition */ + vt_check_ints(pdev); +} + +/* Check interrupt and perform */ +static void vt_check_ints(vt_driver *pdev) { + if (!pdev->vt_recv_flag) + return; + pdev->vt_recv_flag = FALSE; + + /* Handle data receive */ + netdriver_recv(); + + /* Handle data transmit */ + if (pdev->vt_send_flag) { + pdev->vt_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); +} diff --git a/minix/drivers/net/vt6105/vt6105.conf b/minix/drivers/net/vt6105/vt6105.conf new file mode 100755 index 000000000..664d640fb --- /dev/null +++ b/minix/drivers/net/vt6105/vt6105.conf @@ -0,0 +1,16 @@ +service vt6105 +{ + type net; + descr "VIA Technology 6105/6106S Ethernet Card"; + system + UMAP # 14 + IRQCTL # 19 + DEVIO # 21 + ; + 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 new file mode 100644 index 000000000..51c842724 --- /dev/null +++ b/minix/drivers/net/vt6105/vt6105.h @@ -0,0 +1,194 @@ +#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 */ + +/* 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 */ + +/* 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 + +/* 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 + +/* 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 + +/* General Descriptor Flag */ +#define VT_DESC_OWN 0x80000000 /* Ownership */ +#define VT_DESC_FIRST 0x00000200 /* First Descriptor */ +#define VT_DESC_LAST 0x00000100 /* Last Descriptor */ + +/* 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) + +/* 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 + +/* Link status */ +#define VT_LINK_UP 1 +#define VT_LINK_DOWN 0 +#define VT_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 + +/* #define VT6105_DEBUG */ + +/* 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 */ +} 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; + + /* Buffer */ + size_t vt_buf_size; + char *vt_buf; + + /* Rx data */ + int vt_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 */ + + /* Tx data */ + int vt_tx_head; + int vt_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 */ + + int vt_hook; /* IRQ hook id at kernel */ + eth_stat_t vt_stat; + + char vt_name[20]; +} vt_driver;