From 85bbb77938224e5674838a6df9779957b98d2c87 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 5 Apr 2004 07:06:26 +0000 Subject: [PATCH] Almost completely rewritten the interrupt handler, some cleanups git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7164 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/drivers/network/wb840/debug.h | 4 +- .../kernel/drivers/network/wb840/device.c | 4 +- .../kernel/drivers/network/wb840/driver.c | 5 +- .../kernel/drivers/network/wb840/wb840.c | 165 +++++++----------- 4 files changed, 71 insertions(+), 107 deletions(-) diff --git a/src/add-ons/kernel/drivers/network/wb840/debug.h b/src/add-ons/kernel/drivers/network/wb840/debug.h index ce66d80ff3..3f8f81a4a6 100644 --- a/src/add-ons/kernel/drivers/network/wb840/debug.h +++ b/src/add-ons/kernel/drivers/network/wb840/debug.h @@ -4,9 +4,9 @@ #define ARGS (const char *, ...) #ifdef DEBUG - #define LOG(ARGS) dprintf ARGS + #define LOG(ARGS) dprintf ARGS #else - #define LOG(ARGS) ; + #define LOG(ARGS) #endif // DEBUG #endif //__MYDEBUG_H diff --git a/src/add-ons/kernel/drivers/network/wb840/device.c b/src/add-ons/kernel/drivers/network/wb840/device.c index f6a8e47e0f..9be3375139 100644 --- a/src/add-ons/kernel/drivers/network/wb840/device.c +++ b/src/add-ons/kernel/drivers/network/wb840/device.c @@ -319,13 +319,15 @@ wb840_free(void* cookie) gOpenMask &= ~(1L << device->devId); wb_delete_rings(device); + free(device->firstPHY); free(device); return B_OK; } -device_hooks gDeviceHooks = { +device_hooks +gDeviceHooks = { wb840_open, /* -> open entry point */ wb840_close, /* -> close entry point */ wb840_free, /* -> free cookie */ diff --git a/src/add-ons/kernel/drivers/network/wb840/driver.c b/src/add-ons/kernel/drivers/network/wb840/driver.c index d552c4e55d..053620793b 100644 --- a/src/add-ons/kernel/drivers/network/wb840/driver.c +++ b/src/add-ons/kernel/drivers/network/wb840/driver.c @@ -22,6 +22,7 @@ pci_module_info *gPci; char* gDevNameList[MAX_CARDS + 1]; pci_info *gDevList[MAX_CARDS]; + static bool probe(pci_info *item) { @@ -120,8 +121,8 @@ publish_devices() device_hooks* find_device(const char* name) { - int32 i; - char *item; + int32 i; + char *item; LOG((DEVICE_NAME ": find_device()\n")); // Find device name diff --git a/src/add-ons/kernel/drivers/network/wb840/wb840.c b/src/add-ons/kernel/drivers/network/wb840/wb840.c index fa6305126c..74cf9258cd 100644 --- a/src/add-ons/kernel/drivers/network/wb840/wb840.c +++ b/src/add-ons/kernel/drivers/network/wb840/wb840.c @@ -1,7 +1,8 @@ /* Copyright (c) 2003-2004 * Stefano Ceccherini . All rights reserved. */ - + +#define DEBUG 1 #include "device.h" #include "driver.h" #include "debug.h" @@ -19,20 +20,22 @@ #define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1)) // MII chip info table - #define PHY_ID0_DAVICOM_DM9101 0x0181 #define PHY_ID1_DAVICOM_DM9101 0xb800 #define MII_HOME 0x0001 #define MII_LAN 0x0002 -const static struct mii_chip_info +struct mii_chip_info { const char *name; uint16 id0, id1; uint8 types; -} +}; + + +const static struct mii_chip_info gMIIChips[] = { - {"DAVICOM_DM9101 MII PHY", PHY_ID0_DAVICOM_DM9101, PHY_ID1_DAVICOM_DM9101, MII_LAN}, + {"DAVICOM_DM9101", PHY_ID0_DAVICOM_DM9101, PHY_ID1_DAVICOM_DM9101, MII_LAN}, {NULL,0,0,0} }; @@ -62,36 +65,6 @@ physicalAddress(volatile void *addr, uint32 length) } -#if DEBUG -static void -dump_registers(wb_device *device) -{ - LOG(("Registers dump:\n")); - LOG(("WB_BUSCTL: %x\n", (int)read32(device->reg_base + WB_BUSCTL))); - LOG(("WB_TXSTART: %x\n", (int)read32(device->reg_base + WB_TXSTART))); - LOG(("WB_RXSTART: %x\n", (int)read32(device->reg_base + WB_RXSTART))); - LOG(("WB_RXADDR: %x\n", (int)read32(device->reg_base + WB_RXADDR))); - LOG(("WB_TXADDR: %x\n", (int)read32(device->reg_base + WB_TXADDR))); - LOG(("WB_ISR: %x\n", (int)read32(device->reg_base + WB_ISR))); - LOG(("WB_NETCFG: %x\n", (int)read32(device->reg_base + WB_NETCFG))); - LOG(("WB_IMR: %x\n", (int)read32(device->reg_base + WB_IMR))); - LOG(("WB_FRAMESDISCARDED: %x\n", (int)read32(device->reg_base + WB_FRAMESDISCARDED))); - LOG(("WB_SIO: %x\n", (int)read32(device->reg_base + WB_SIO))); - LOG(("WB_BOOTROMADDR: %x\n", (int)read32(device->reg_base + WB_BOOTROMADDR))); - LOG(("WB_TIMER: %x\n", (int)read32(device->reg_base + WB_TIMER))); - LOG(("WB_CURRXCTL: %x\n", (int)read32(device->reg_base + WB_CURRXCTL))); - LOG(("WB_CURRXBUF: %x\n", (int)read32(device->reg_base + WB_CURRXBUF))); - LOG(("WB_MAR0: %x\n", (int)read32(device->reg_base + WB_MAR0))); - LOG(("WB_MAR1: %x\n", (int)read32(device->reg_base + WB_MAR1))); - LOG(("WB_NODE0: %x\n", (int)read32(device->reg_base + WB_NODE0))); - LOG(("WB_NODE1: %x\n", (int)read32(device->reg_base + WB_NODE1))); - LOG(("WB_BOOTROMSIZE: %x\n", (int)read32(device->reg_base + WB_BOOTROMSIZE))); - LOG(("WB_CURTXCTL: %x\n", (int)read32(device->reg_base + WB_CURTXCTL))); - LOG(("WB_CURTXBUF: %x\n", (int)read32(device->reg_base + WB_CURTXBUF))); -} -#endif - - // Prepares a RX descriptor to be used by the chip void wb_put_rx_descriptor(wb_desc *descriptor) @@ -216,18 +189,9 @@ wb_init(wb_device *device) write32(device->reg_base + WB_BUSCTL_SKIPLEN, WB_SKIPLEN_4LONG); - // Early TX interrupt + // Enable early TX/RX interrupt WB_SETBIT(device->reg_base + WB_NETCFG, (WB_NETCFG_TX_EARLY_ON|WB_NETCFG_RX_EARLY_ON)); - - // fullduplex - //WB_SETBIT(device->reg_base + WB_NETCFG, WB_NETCFG_FULLDUPLEX); - - //100 MBits - //WB_SETBIT(device->reg_base + WB_NETCFG, WB_NETCFG_100MBPS); - - /* Program the multicast filter, if necessary */ - //wb_setmulti(device); - + //Disable promiscuos mode WB_CLRBIT(device->reg_base + WB_NETCFG, WB_NETCFG_RX_ALLPHYS); @@ -257,7 +221,7 @@ wb_reset(wb_device *device) } if (i == WB_TIMEOUT) - LOG(("reset hasn't completed!!!")); + LOG((DEVICE_NAME": reset hasn't completed!!!")); /* Wait a bit while the chip reorders his toughts */ snooze(1000); @@ -275,17 +239,17 @@ wb_updateLink(struct wb_device *device) return; } - if (device->link) { // link lost + if (device->link) { uint16 status = mii_readstatus(device); + // Check if link lost if ((status & MII_STATUS_LINK) == 0) device->link = false; - } - - if (!device->link) { // new link established + } else { uint16 status; wb_selectPHY(device); - + + // Check if we have a new link status = mii_readstatus(device); if (status & MII_STATUS_LINK) device->link = true; @@ -304,12 +268,11 @@ wb_tick(timer *arg) } /***************** Interrupt handling ******************************/ -status_t +static status_t wb_rxok(struct wb_device *device) { uint32 releaseRxSem = 0; int16 limit; - LOG(("Rx interrupt\n")); acquire_spinlock(&device->rxSpinlock); @@ -327,10 +290,8 @@ wb_rxok(struct wb_device *device) write32(device->reg_base + WB_RXSTART, 0xFFFFFFFF); release_spinlock(&device->rxSpinlock); - - + if (releaseRxSem > 0) { - //dprintf("releasing read sem %d times\n", releaseRxSem); release_sem_etc(device->rxSem, releaseRxSem, B_DO_NOT_RESCHEDULE); return B_INVOKE_SCHEDULER; } @@ -339,7 +300,7 @@ wb_rxok(struct wb_device *device) } -status_t +static status_t wb_tx_nobuf(struct wb_device *info) { int16 releaseTxSem = 0; @@ -350,16 +311,20 @@ wb_tx_nobuf(struct wb_device *info) for (limit = info->txSent; limit > 0; limit--) { status = info->txDescriptor[info->txInterruptIndex].wb_status; - + + LOG(("wb_tx_nobuf, status: %lx\n", status)); if (status & WB_TXSTAT_TXERR) { LOG(("TX_STAT_ERR\n")); break; } else if (status & WB_UNSENT) { LOG(("TX_STAT_UNSENT\n")); break; - } else { + } else if (status & WB_TXSTAT_OWN) { + LOG((DEVICE_NAME": Device still owns the descriptor\n")); + break; + } else info->txDescriptor[info->txInterruptIndex].wb_status = 0; - } + releaseTxSem++; // this many buffers are free info->txInterruptIndex = (info->txInterruptIndex + 1) & WB_TX_CNT_MASK; info->txSent--; @@ -384,78 +349,76 @@ wb_interrupt(void *arg) { struct wb_device *device = (wb_device*)arg; int32 retval = B_UNHANDLED_INTERRUPT; - int16 worklimit = 20; uint32 status; acquire_spinlock(&device->intLock); wb_disable_interrupts(device); - while (worklimit-- > 0) { - status = read32(device->reg_base + WB_ISR); + status = read32(device->reg_base + WB_ISR); - /* Is our card the one which requested the interrupt ? */ - if (!(status & WB_INTRS)) { - /* No, bail out. */ - break; - } - - // Clean all the interrupts + // Did this card request the interrupt ? + if (status & WB_INTRS) { + // Clean all the interrupts bits if (status) write32(device->reg_base + WB_ISR, status); - - LOG((DEVICE_NAME":*** Interrupt received ***\n")); - + + if (status & WB_ISR_ABNORMAL) + LOG((DEVICE_NAME": *** Abnormal Interrupt received ***\n")); + else + LOG((DEVICE_NAME": interrupt received: \n")); + + if (status & WB_ISR_RX_EARLY) { + LOG(("WB_ISR_RX_EARLY\n")); + } + if (status & WB_ISR_RX_NOBUF) { - LOG((DEVICE_NAME ": WB_ISR_RX_NOBUF\n")); - //retval = wb_rx_nobuf(device); - continue; + LOG(("WB_ISR_RX_NOBUF\n")); + // Something is screwed } if (status & WB_ISR_RX_ERR) { - LOG((DEVICE_NAME": WB_ISR_RX_ERR\n")); - continue; + LOG(("WB_ISR_RX_ERR\n")); + // TODO: Do something useful } if (status & WB_ISR_RX_OK) { - LOG((DEVICE_NAME": WB_ISR_RX_OK\n")); + LOG(("WB_ISR_RX_OK\n")); retval = wb_rxok(device); - continue; } if (status & WB_ISR_RX_IDLE) { - LOG((DEVICE_NAME": WB_ISR_RX_IDLE\n")); - continue; + LOG(("WB_ISR_RX_IDLE\n")); + // ??? } - - if (status & WB_ISR_TX_NOBUF) { - LOG((DEVICE_NAME ": WB_ISR_TX_NOBUF\n")); + + if (status & (WB_ISR_TX_NOBUF | WB_ISR_TX_EARLY)) { + LOG(("WB_ISR_TX_NOBUF/TX_EARLY\n")); retval = wb_tx_nobuf(device); - continue; } if (status & WB_ISR_TX_UNDERRUN) { - LOG((DEVICE_NAME ": WB_ISR_TX_UNDERRUN\n")); + LOG(("WB_ISR_TX_UNDERRUN\n")); // TODO: Jack up TX Threshold - continue; } if (status & WB_ISR_TX_IDLE) { - LOG((DEVICE_NAME ": WB_ISR_TX_IDLE\n")); - continue; + LOG(("WB_ISR_TX_IDLE\n")); } if (status & WB_ISR_TX_OK) { - LOG((DEVICE_NAME": WB_ISR_TX_OK\n")); - continue; + LOG(("WB_ISR_TX_OK\n")); + // So what ? } - + if (status & WB_ISR_BUS_ERR) { - LOG((DEVICE_NAME": BUS_ERROR: %x\n", (int)(status & WB_ISR_BUSERRTYPE) >> 4)); + LOG(("WB_ISR_BUS_ERROR: %lx\n", (status & WB_ISR_BUSERRTYPE) >> 4)); //wb_reset(device); - continue; } - - LOG((DEVICE_NAME ": unknown interrupt received\n")); + + if (status & WB_ISR_TIMER_EXPIRED) { + LOG(("WB_ISR_TIMER_EXPIRED\n")); + // ?? + } } wb_enable_interrupts(device); @@ -491,8 +454,6 @@ wb_create_semaphores(struct wb_device *device) return device->rxSem; } - set_sem_owner(device->rxSem, B_SYSTEM_TEAM); - device->txSem = create_sem(WB_TX_LIST_CNT, "wb840 transmit"); if (device->txSem < B_OK) { LOG(("Couldn't create sem, sem_id %ld\n", device->txSem)); @@ -500,6 +461,7 @@ wb_create_semaphores(struct wb_device *device) return device->txSem; } + set_sem_owner(device->rxSem, B_SYSTEM_TEAM); set_sem_owner(device->txSem, B_SYSTEM_TEAM); device->rxLock = 0; @@ -617,11 +579,10 @@ wb_set_mode(wb_device *info, int mode) // Stop TX and RX queue. if (read32(cfgAddress) & (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)) { - restart = 1; + restart = true; WB_CLRBIT(cfgAddress, (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)); for (i = 0; i < WB_TIMEOUT; i++) { - //delay(10) if ((read32(info->reg_base + WB_ISR) & WB_ISR_TX_IDLE) && (read32(info->reg_base + WB_ISR) & WB_ISR_RX_IDLE)) break;