From b2b8d968ef1a4c37d2774aa2df46976b9ec3ebe2 Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Sat, 19 Jan 2002 15:35:56 +0000 Subject: [PATCH] Bring the rtl8139 (network card) driver up to date. It had died a while back but no one had noticed. sad... git-svn-id: svn+ssh://newos.org/var/svn/newos/newos@411 c25cc9d1-44fa-0310-b259-ad778cb1d433 --- kernel/dev/arch/i386/rtl8139/rtl8139.c | 21 ++++++------ kernel/dev/arch/i386/rtl8139/rtl8139_dev.c | 51 +++++++++++++++-------------- kernel/dev/arch/i386/rtl8139/rtl8139_priv.h | 2 +- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/kernel/dev/arch/i386/rtl8139/rtl8139.c b/kernel/dev/arch/i386/rtl8139/rtl8139.c index a12672d..e0ffdd8 100644 --- a/kernel/dev/arch/i386/rtl8139/rtl8139.c +++ b/kernel/dev/arch/i386/rtl8139/rtl8139.c @@ -9,16 +9,16 @@ #include #include #include +#include +#include #include "rtl8139_priv.h" -/* allow multiple 8139s */ -static rtl8139 *rtl = NULL; - static int rtl8139_open(dev_ident ident, dev_cookie *cookie) { - if(!rtl) - return ERR_IO_ERROR; + rtl8139 *rtl = (rtl8139 *)ident; + + *cookie = rtl; return 0; } @@ -40,21 +40,21 @@ static int rtl8139_close(dev_cookie cookie) static ssize_t rtl8139_read(dev_cookie cookie, void *buf, off_t pos, ssize_t len) { + rtl8139 *rtl = (rtl8139 *)cookie; + if(len < 1500) return ERR_VFS_INSUFFICIENT_BUF; - if(!rtl) - return ERR_IO_ERROR; return rtl8139_rx(rtl, buf, len); } static ssize_t rtl8139_write(dev_cookie cookie, const void *buf, off_t pos, ssize_t len) { + rtl8139 *rtl = (rtl8139 *)cookie; + if(len > 1500) return ERR_VFS_INSUFFICIENT_BUF; if(len < 0) return ERR_INVALID_ARGS; - if(!rtl) - return ERR_IO_ERROR; rtl8139_xmit(rtl, buf, len); return len; @@ -62,6 +62,7 @@ static ssize_t rtl8139_write(dev_cookie cookie, const void *buf, off_t pos, ssiz static int rtl8139_ioctl(dev_cookie cookie, int op, void *buf, size_t len) { + rtl8139 *rtl = (rtl8139 *)cookie; int err; dprintf("rtl8139_ioctl: op %d, buf 0x%x, len %d\n", op, buf, len); @@ -116,7 +117,7 @@ int rtl8139_dev_init(kernel_args *ka) rtl8139_init(rtl); // create device node - devfs_publish_device("net/rtl8139/0", NULL, &rtl8139_hooks); + devfs_publish_device("net/rtl8139/0", rtl, &rtl8139_hooks); return 0; } diff --git a/kernel/dev/arch/i386/rtl8139/rtl8139_dev.c b/kernel/dev/arch/i386/rtl8139/rtl8139_dev.c index 7343564..90fce0f 100644 --- a/kernel/dev/arch/i386/rtl8139/rtl8139_dev.c +++ b/kernel/dev/arch/i386/rtl8139/rtl8139_dev.c @@ -50,8 +50,6 @@ #define MYRT_INTS (RT_INT_PCIERR | RT_INT_RX_ERR | RT_INT_RX_OK | RT_INT_TX_ERR | RT_INT_TX_OK | RT_INT_RXBUF_OVERFLOW) -static rtl8139 *grtl; - static int rtl8139_int(void*); int rtl8139_detect(rtl8139 **rtl) @@ -129,12 +127,13 @@ int rtl8139_init(rtl8139 *rtl) // try to reset the device time = system_time(); RTL_WRITE_8(rtl, RT_CHIPCMD, RT_CMD_RESET); - while((RTL_READ_8(rtl, RT_CHIPCMD) & RT_CMD_RESET)) { + do { + thread_snooze(10000); // 10ms if(system_time() - time > 1000000) { err = -1; goto err1; } - } + } while((RTL_READ_8(rtl, RT_CHIPCMD) & RT_CMD_RESET)); // create a rx and tx buf rtl->rxbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8139_rxbuf", (void **)&rtl->rxbuf, @@ -150,8 +149,7 @@ int rtl8139_init(rtl8139 *rtl) rtl->rx_sem = sem_create(0, "rtl8139_rxsem"); // set up the interrupt handler - grtl = rtl; - int_set_io_interrupt_handler(rtl->irq + 0x20, &rtl8139_int, NULL); + int_set_io_interrupt_handler(rtl->irq + 0x20, &rtl8139_int, rtl); // read the mac address rtl->mac_addr[0] = RTL_READ_8(rtl, RT_IDR0); @@ -190,13 +188,17 @@ int rtl8139_init(rtl8139 *rtl) RTL_WRITE_8(rtl, RT_CFG9346, 0); // Setup RX buffers + *(int *)rtl->rxbuf = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), rtl->rxbuf, &temp); + dprintf("rx buffer will be at 0x%x\n", temp); RTL_WRITE_32(rtl, RT_RXBUF, temp); // Setup TX buffers + *(int *)rtl->txbuf = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), rtl->txbuf, &temp); RTL_WRITE_32(rtl, RT_TXADDR0, temp); RTL_WRITE_32(rtl, RT_TXADDR1, temp + 2*1024); + *(int *)(rtl->txbuf + 4*1024) = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), rtl->txbuf + 4*1024, &temp); RTL_WRITE_32(rtl, RT_TXADDR2, temp); RTL_WRITE_32(rtl, RT_TXADDR3, temp + 2*1024); @@ -307,7 +309,7 @@ restart: // copy the buffer if(entry->len > buf_len) { dprintf("rtl8139_rx: packet too large for buffer\n"); - RTL_WRITE_16(grtl, RT_RXBUFTAIL, TAILREG_TO_TAIL(RTL_READ_16(grtl, RT_RXBUFHEAD))); + RTL_WRITE_16(rtl, RT_RXBUFTAIL, TAILREG_TO_TAIL(RTL_READ_16(rtl, RT_RXBUFHEAD))); mutex_unlock(&rtl->lock); sem_release(rtl->rx_sem, 1); return -1; @@ -315,7 +317,7 @@ restart: if(tail + entry->len > 0xffff) { int pos = 0; - dprintf("packet wraps around\n"); +// dprintf("packet wraps around\n"); memcpy(buf, (const void *)&entry->data[0], 0x10000 - tail); memcpy((uint8 *)buf + 0x10000 - tail, (const void *)rtl->rxbuf, entry->len - (0x10000 - tail)); } else { @@ -362,22 +364,22 @@ static int rtl8139_txint(rtl8139 *rtl, uint16 int_status) int rc = INT_NO_RESCHEDULE; // transmit ok - dprintf("tx\n"); +// dprintf("tx\n"); for(i=0; i<4; i++) { - if(grtl->last_txbn == grtl->txbn) + if(rtl->last_txbn == rtl->txbn) break; - txstat = RTL_READ_32(grtl, RT_TXSTATUS0 + grtl->last_txbn*4); -// dprintf("txstat[%d] = 0x%x\n", grtl->last_txbn, txstat); + txstat = RTL_READ_32(rtl, RT_TXSTATUS0 + rtl->last_txbn*4); +// dprintf("txstat[%d] = 0x%x\n", rtl->last_txbn, txstat); if(txstat & RT_TX_HOST_OWNS) { // dprintf("host now owns the buffer\n"); } else { // dprintf("host no own\n"); break; } - if(++grtl->last_txbn >= 4) - grtl->last_txbn = 0; - sem_release_etc(grtl->tx_sem, 1, SEM_FLAG_NO_RESCHED); + if(++rtl->last_txbn >= 4) + rtl->last_txbn = 0; + sem_release_etc(rtl->tx_sem, 1, SEM_FLAG_NO_RESCHED); rc = INT_RESCHEDULE; } return rc; @@ -386,31 +388,32 @@ static int rtl8139_txint(rtl8139 *rtl, uint16 int_status) static int rtl8139_int(void* data) { int rc = INT_NO_RESCHEDULE; + rtl8139 *rtl = (rtl8139 *)data; // Disable interrupts - RTL_WRITE_16(grtl, RT_INTRMASK, 0); + RTL_WRITE_16(rtl, RT_INTRMASK, 0); for(;;) { - uint16 status = RTL_READ_16(grtl, RT_INTRSTATUS); + uint16 status = RTL_READ_16(rtl, RT_INTRSTATUS); if(status) - RTL_WRITE_16(grtl, RT_INTRSTATUS, status); + RTL_WRITE_16(rtl, RT_INTRSTATUS, status); else break; if(status & RT_INT_TX_OK || status & RT_INT_TX_ERR) { - if(rtl8139_txint(grtl, status) == INT_RESCHEDULE) + if(rtl8139_txint(rtl, status) == INT_RESCHEDULE) rc = INT_RESCHEDULE; } if(status & RT_INT_RX_ERR || status & RT_INT_RX_OK) { - if(rtl8139_rxint(grtl, status) == INT_RESCHEDULE) + if(rtl8139_rxint(rtl, status) == INT_RESCHEDULE) rc = INT_RESCHEDULE; } if(status & RT_INT_RXBUF_OVERFLOW) { dprintf("RX buffer overflow!\n"); dprintf("buf 0x%x, head 0x%x, tail 0x%x\n", - RTL_READ_32(grtl, RT_RXBUF), RTL_READ_16(grtl, RT_RXBUFHEAD), RTL_READ_16(grtl, RT_RXBUFTAIL)); - RTL_WRITE_32(grtl, RT_RXMISSED, 0); - RTL_WRITE_16(grtl, RT_RXBUFTAIL, TAILREG_TO_TAIL(RTL_READ_16(grtl, RT_RXBUFHEAD))); + RTL_READ_32(rtl, RT_RXBUF), RTL_READ_16(rtl, RT_RXBUFHEAD), RTL_READ_16(rtl, RT_RXBUFTAIL)); + RTL_WRITE_32(rtl, RT_RXMISSED, 0); + RTL_WRITE_16(rtl, RT_RXBUFTAIL, TAILREG_TO_TAIL(RTL_READ_16(rtl, RT_RXBUFHEAD))); } if(status & RT_INT_RXFIFO_OVERFLOW) { dprintf("RX fifo overflow!\n"); @@ -421,7 +424,7 @@ static int rtl8139_int(void* data) } // reenable interrupts - RTL_WRITE_16(grtl, RT_INTRMASK, MYRT_INTS); + RTL_WRITE_16(rtl, RT_INTRMASK, MYRT_INTS); return rc; } diff --git a/kernel/dev/arch/i386/rtl8139/rtl8139_priv.h b/kernel/dev/arch/i386/rtl8139/rtl8139_priv.h index d23b032..f840638 100644 --- a/kernel/dev/arch/i386/rtl8139/rtl8139_priv.h +++ b/kernel/dev/arch/i386/rtl8139/rtl8139_priv.h @@ -1,4 +1,4 @@ -/* +/* ** Copyright 2001, Travis Geiselbrecht. All rights reserved. ** Distributed under the terms of the NewOS License. */ -- 2.11.4.GIT