diff --git a/src/add-ons/kernel/drivers/network/wb840/device.c b/src/add-ons/kernel/drivers/network/wb840/device.c index 9be3375139..6e599b5ec1 100644 --- a/src/add-ons/kernel/drivers/network/wb840/device.c +++ b/src/add-ons/kernel/drivers/network/wb840/device.c @@ -24,6 +24,7 @@ wb840_open(const char *name, uint32 flags, void** cookie) int32 i; int32 mask; struct wb_device *data; + status_t status; LOG((DEVICE_NAME ": open()\n")); @@ -39,9 +40,8 @@ wb840_open(const char *name, uint32 flags, void** cookie) /* There can be only one access at time */ mask = 1L << i; - if (atomic_or(&gOpenMask, mask) & mask) { + if (atomic_or(&gOpenMask, mask) & mask) return B_BUSY; - } /* Allocate a wb_device structure */ if (!(data = (wb_device *)malloc(sizeof(wb_device)))) { @@ -61,45 +61,73 @@ wb840_open(const char *name, uint32 flags, void** cookie) data->pciInfo = gDevList[i]; data->deviceName = gDevNameList[i]; data->blockFlag = 0; - - /* Let's map card registers to host's memory */ data->reg_base = data->pciInfo->u.h0.base_registers[0]; - LOG(("wb840: reg_base=%x\n", (int)data->reg_base)); - - wb_read_eeprom(data, &data->myaddr, 0, 3, 0); - data->wb_cachesize = gPci->read_pci_config(data->pciInfo->bus, data->pciInfo->device, data->pciInfo->function, PCI_line_size, sizeof (PCI_line_size)) & 0xff; - if (wb_create_semaphores(data) == B_OK) { - wb_initPHYs(data); - wb_init(data); - - /* Setup interrupts */ - data->irq = data->pciInfo->u.h0.interrupt_line; - install_io_interrupt_handler(data->irq, wb_interrupt, data, 0); - LOG(("Interrupts installed at irq line %x\n", data->irq)); - - wb_enable_interrupts(data); - wb_create_rings(data); - - WB_SETBIT(data->reg_base + WB_NETCFG, WB_NETCFG_RX_ON); - write32(data->reg_base + WB_RXSTART, 0xFFFFFFFF); - WB_SETBIT(data->reg_base + WB_NETCFG, WB_NETCFG_TX_ON); - - add_timer(&data->timer, wb_tick, 1000000LL, B_PERIODIC_TIMER); - - return B_OK; // Everything after this line is an error - - } else + wb_read_eeprom(data, &data->MAC_Address, 0, 3, 0); + + status = wb_create_semaphores(data); + if (status < B_OK) { LOG((DEVICE_NAME ": Couldn't create semaphores\n")); + goto err; + } + + status = wb_stop(data); + if (status < B_OK) { + LOG((DEVICE_NAME": Can't stop device\n")); + goto err1; + } + status = wb_initPHYs(data); + if (status < B_OK) { + LOG((DEVICE_NAME": Can't init PHYs\n")); + goto err1; + } + + wb_init(data); + + /* Setup interrupts */ + data->irq = data->pciInfo->u.h0.interrupt_line; + status = install_io_interrupt_handler(data->irq, wb_interrupt, data, 0); + if (status < B_OK) { + LOG((DEVICE_NAME + " can't install interrupt handler: %s\n", strerror(status))); + goto err1; + } + + LOG(("Interrupts installed at irq line %x\n", data->irq)); + + status = wb_create_rings(data); + if (status < B_OK) { + LOG((DEVICE_NAME": can't create ring buffers\n")); + goto err2; + } + + wb_enable_interrupts(data); + wb_set_rx_filter(data); + + WB_SETBIT(data->reg_base + WB_NETCFG, WB_NETCFG_RX_ON); + write32(data->reg_base + WB_RXSTART, 0xFFFFFFFF); + WB_SETBIT(data->reg_base + WB_NETCFG, WB_NETCFG_TX_ON); + + add_timer(&data->timer, wb_tick, 1000000LL, B_PERIODIC_TIMER); + + return B_OK; // Everything after this line is an error + +err2: + remove_io_interrupt_handler(data->irq, wb_interrupt, data); + +err1: + wb_delete_semaphores(data); + +err: gOpenMask &= ~(1L << i); free(data); LOG(("wb840: Open Failed\n")); - return B_ERROR; + return status; } @@ -121,8 +149,8 @@ wb840_read(void* cookie, off_t position, void *buf, size_t* num_bytes) *num_bytes = 0; return B_ERROR; } - - if ((status = acquire_sem_etc(device->rxSem, 1, B_CAN_INTERRUPT | blockFlag, 0)) != B_OK) { + + if ((status = acquire_sem_etc(device->rxSem, 1, B_CAN_INTERRUPT | blockFlag, 0)) < B_OK) { atomic_and(&device->rxLock, 0); *num_bytes = 0; return status; @@ -143,9 +171,9 @@ wb840_read(void* cookie, off_t position, void *buf, size_t* num_bytes) } else { size = WB_RXBYTES(check); size -= CRC_SIZE; - LOG((DEVICE_NAME": received %d bytes\n", (int)size)); + LOG((DEVICE_NAME": received %ld bytes\n", size)); if (size > WB_MAX_FRAMELEN || size > *num_bytes) { - LOG(("ERROR: Bad frame size: %d", (int)size)); + LOG(("ERROR: Bad frame size: %ld", size)); size = *num_bytes; } *num_bytes = size; @@ -194,14 +222,13 @@ wb840_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes) // block until a free tx descriptor is available if ((status = acquire_sem_etc(device->txSem, 1, B_TIMEOUT, ETHER_TRANSMIT_TIMEOUT)) < B_OK) { write32(device->reg_base + WB_TXSTART, 0xFFFFFFFF); - LOG(("write: acquiring sem failed: %d, %s\n", (int)status, strerror(status))); + LOG(("write: acquiring sem failed: %ld, %s\n", status, strerror(status))); atomic_add(&device->txLock, -1); *num_bytes = 0; return status; } check = device->txDescriptor[current].wb_status; - if (check & WB_TXSTAT_OWN) { // descriptor is still in use dprintf(DEVICE_NAME ": card owns buffer %d\n", (int)current); @@ -219,7 +246,8 @@ wb840_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes) former = disable_interrupts(); acquire_spinlock(&device->txSpinlock); - device->txDescriptor[current].wb_ctl |= frameSize | WB_TXCTL_FIRSTFRAG | WB_TXCTL_LASTFRAG; + device->txDescriptor[current].wb_ctl = WB_TXCTL_TLINK | frameSize; + device->txDescriptor[current].wb_ctl |= WB_TXCTL_FIRSTFRAG | WB_TXCTL_LASTFRAG; device->txDescriptor[current].wb_status = WB_TXSTAT_OWN; device->txSent++; @@ -249,7 +277,7 @@ wb840_control (void *cookie, uint32 op, void *arg, size_t len) case ETHER_GETADDR: LOG(("%s: ETHER_GETADDR\n", data->deviceName)); - memcpy(arg, &data->myaddr, sizeof(data->myaddr)); + memcpy(arg, &data->MAC_Address, sizeof(data->MAC_Address)); print_address(arg); return B_OK; @@ -293,8 +321,7 @@ wb840_close(void* cookie) cancel_timer(&device->timer); - // disable the transmitter's and receiver's state machine - WB_CLRBIT(device->reg_base + WB_NETCFG, (WB_NETCFG_RX_ON|WB_NETCFG_TX_ON)); + wb_stop(device); write32(device->reg_base + WB_TXADDR, 0x00000000); write32(device->reg_base + WB_RXADDR, 0x00000000); diff --git a/src/add-ons/kernel/drivers/network/wb840/wb840.c b/src/add-ons/kernel/drivers/network/wb840/wb840.c index d2f6cefab9..526b4da7a3 100644 --- a/src/add-ons/kernel/drivers/network/wb840/wb840.c +++ b/src/add-ons/kernel/drivers/network/wb840/wb840.c @@ -66,10 +66,10 @@ physicalAddress(volatile void *addr, uint32 length) // Prepares a RX descriptor to be used by the chip void -wb_put_rx_descriptor(wb_desc *descriptor) +wb_put_rx_descriptor(volatile wb_desc *descriptor) { descriptor->wb_status = WB_RXSTAT_OWN; - descriptor->wb_ctl = WB_MAX_FRAMELEN | WB_RXCTL_RLINK; + descriptor->wb_ctl |= WB_MAX_FRAMELEN | WB_RXCTL_RLINK; } @@ -188,14 +188,9 @@ wb_init(wb_device *device) write32(device->reg_base + WB_BUSCTL_SKIPLEN, WB_SKIPLEN_4LONG); - // Enable early TX/RX interrupt - WB_SETBIT(device->reg_base + WB_NETCFG, (WB_NETCFG_TX_EARLY_ON|WB_NETCFG_RX_EARLY_ON)); - - //Disable promiscuos mode - WB_CLRBIT(device->reg_base + WB_NETCFG, WB_NETCFG_RX_ALLPHYS); - - //Disable capture broadcast - WB_CLRBIT(device->reg_base + WB_NETCFG, WB_NETCFG_RX_BROAD); + // Disable early TX/RX interrupt, as we can't take advantage + // from them, at least for now. + WB_CLRBIT(device->reg_base + WB_NETCFG, (WB_NETCFG_TX_EARLY_ON|WB_NETCFG_RX_EARLY_ON)); } @@ -227,6 +222,29 @@ wb_reset(wb_device *device) } +status_t +wb_stop(wb_device *device) +{ + uint32 cfgAddress = (uint32)device->reg_base + WB_NETCFG; + int32 i = 0; + + if (read32(cfgAddress) & (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)) { + WB_CLRBIT(cfgAddress, (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)); + + for (i = 0; i < WB_TIMEOUT; i++) { + if ((read32(device->reg_base + WB_ISR) & WB_ISR_TX_IDLE) && + (read32(device->reg_base + WB_ISR) & WB_ISR_RX_IDLE)) + break; + } + } + + if (i < WB_TIMEOUT) + return B_OK; + + return B_ERROR; +} + + void wb_updateLink(struct wb_device *device) { @@ -267,6 +285,20 @@ wb_tick(timer *arg) } +/* + * Program the rx filter. + */ +void +wb_set_rx_filter(wb_device *device) +{ + // TODO: Basically we just config the filter to accept broadcasts + // packets. We'll need also to configure it to multicast. + int32 rxFilter = read32(device->reg_base + WB_NETCFG); + + write32(device->reg_base + WB_NETCFG, rxFilter | WB_NETCFG_RX_BROAD); +} + + /***************** Interrupt handling ******************************/ static status_t wb_rxok(struct wb_device *device) @@ -350,9 +382,10 @@ wb_interrupt(void *arg) struct wb_device *device = (wb_device*)arg; int32 retval = B_UNHANDLED_INTERRUPT; uint32 status; + + //TODO: Handle others interrupts acquire_spinlock(&device->intLock); - wb_disable_interrupts(device); status = read32(device->reg_base + WB_ISR); @@ -391,8 +424,13 @@ wb_interrupt(void *arg) // ??? } - if (status & (WB_ISR_TX_NOBUF | WB_ISR_TX_EARLY)) { - LOG(("WB_ISR_TX_NOBUF/TX_EARLY\n")); + if (status & WB_ISR_TX_EARLY) { + LOG(("WB_ISR_TX_EARLY\n")); + + } + + if (status & WB_ISR_TX_NOBUF) { + LOG(("WB_ISR_TX_NOBUF\n")); retval = wb_tx_nobuf(device); } @@ -421,7 +459,6 @@ wb_interrupt(void *arg) } } - wb_enable_interrupts(device); release_spinlock(&device->intLock); return retval; @@ -471,6 +508,16 @@ wb_create_semaphores(struct wb_device *device) } +void +wb_delete_semaphores(wb_device *device) +{ + if (device->rxSem >= 0) + delete_sem(device->rxSem); + if (device->txSem >= 0) + delete_sem(device->txSem); +} + + status_t wb_create_rings(struct wb_device *device) { @@ -486,13 +533,15 @@ wb_create_rings(struct wb_device *device) device->rxBuffer[i] = (void *)(((uint32)device->rxBuffer[0]) + (i * WB_BUFBYTES)); for (i = 0; i < WB_RX_LIST_CNT; i++) { + device->rxDescriptor[i].wb_status = 0; + device->rxDescriptor[i].wb_ctl = WB_RXCTL_RLINK; wb_put_rx_descriptor(&device->rxDescriptor[i]); device->rxDescriptor[i].wb_data = physicalAddress(device->rxBuffer[i], WB_BUFBYTES); - device->rxDescriptor[i].wb_next = physicalAddress(&device->rxDescriptor[(i + 1) - & WB_RX_CNT_MASK], sizeof(struct wb_desc)); + device->rxDescriptor[i].wb_next = physicalAddress(&device->rxDescriptor[(i + 1) & WB_RX_CNT_MASK], + sizeof(struct wb_desc)); } + device->rxFree = WB_RX_LIST_CNT; - device->rxDescriptor[WB_RX_LIST_CNT - 1].wb_ctl |= WB_RXCTL_RLAST; device->txArea = create_area("wb840 tx buffer", (void **)&device->txBuffer[0], B_ANY_KERNEL_ADDRESS, ROUND_TO_PAGE_SIZE(WB_BUFBYTES * WB_TX_LIST_CNT), @@ -509,21 +558,16 @@ wb_create_rings(struct wb_device *device) device->txDescriptor[i].wb_status = 0; device->txDescriptor[i].wb_ctl = WB_TXCTL_TLINK; device->txDescriptor[i].wb_data = physicalAddress(device->txBuffer[i], WB_BUFBYTES); - device->txDescriptor[i].wb_next = physicalAddress(&device->txDescriptor[(i + 1) - & WB_TX_CNT_MASK], sizeof(struct wb_desc)); + device->txDescriptor[i].wb_next = physicalAddress(&device->txDescriptor[(i + 1) & WB_TX_CNT_MASK], + sizeof(struct wb_desc)); } - device->txDescriptor[WB_TX_LIST_CNT - 1].wb_ctl |= WB_TXCTL_TLAST; - - /* Load the address of the RX list */ - WB_CLRBIT(device->reg_base + WB_NETCFG, WB_NETCFG_RX_ON); - write32(device->reg_base + WB_RXADDR, physicalAddress(&device->rxDescriptor[0], - sizeof(struct wb_desc))); - - /* Load the address of the TX list */ - WB_CLRBIT(device->reg_base + WB_NETCFG, WB_NETCFG_TX_ON); - write32(device->reg_base + WB_TXADDR, physicalAddress(&device->txDescriptor[0], - sizeof(struct wb_desc))); + if (wb_stop(device) == B_OK) { + write32(device->reg_base + WB_RXADDR, + physicalAddress(&device->rxDescriptor[0], sizeof(struct wb_desc))); + write32(device->reg_base + WB_TXADDR, + physicalAddress(&device->txDescriptor[0], sizeof(struct wb_desc))); + } return B_OK; } @@ -545,7 +589,7 @@ wb_read_mode(wb_device *info) uint16 status = mii_readstatus(info); if (!(status & MII_STATUS_LINK)) { - dprintf(DEVICE_NAME ": no link detected (status = %x)\n", status); + LOG((DEVICE_NAME ": no link detected (status = %x)\n", status)); return 0; } @@ -559,9 +603,9 @@ wb_read_mode(wb_device *info) info->autoNegotiationComplete = true; - dprintf(DEVICE_NAME ": linked, 10%s MBit, %s duplex\n", + LOG((DEVICE_NAME ": linked, 10%s MBit, %s duplex\n", speed == LINK_SPEED_100_MBIT ? "0" : "", - duplex == LINK_FULL_DUPLEX ? "full" : "half"); + duplex == LINK_FULL_DUPLEX ? "full" : "half")); return speed | duplex; } @@ -573,25 +617,10 @@ wb_set_mode(wb_device *info, int mode) uint32 cfgAddress = (uint32)info->reg_base + WB_NETCFG; int32 speed = mode & LINK_SPEED_MASK; uint32 configFlags = 0; + status_t status; - bool restart = false; - int32 i = 0; - - // Stop TX and RX queue. - if (read32(cfgAddress) & (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)) { - restart = true; - WB_CLRBIT(cfgAddress, (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)); - - for (i = 0; i < WB_TIMEOUT; i++) { - if ((read32(info->reg_base + WB_ISR) & WB_ISR_TX_IDLE) && - (read32(info->reg_base + WB_ISR) & WB_ISR_RX_IDLE)) - break; - } - - if (i == WB_TIMEOUT) - dprintf(DEVICE_NAME" Failed to put RX and TX in idle state\n"); - } - + status = wb_stop(info); + if ((mode & LINK_DUPLEX_MASK) == LINK_FULL_DUPLEX) configFlags |= WB_NETCFG_FULLDUPLEX; @@ -600,6 +629,6 @@ wb_set_mode(wb_device *info, int mode) write32(cfgAddress, configFlags); - if (restart) + if (status == B_OK) WB_SETBIT(cfgAddress, WB_NETCFG_TX_ON|WB_NETCFG_RX_ON); } diff --git a/src/add-ons/kernel/drivers/network/wb840/wb840.h b/src/add-ons/kernel/drivers/network/wb840/wb840.h index e1dd09e899..a8ba6848c0 100644 --- a/src/add-ons/kernel/drivers/network/wb840/wb840.h +++ b/src/add-ons/kernel/drivers/network/wb840/wb840.h @@ -29,7 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * This file has been adapted to BeOS by Stefano Ceccherini + * This file has been adapted for BeOS by Stefano Ceccherini */ #ifndef __WB840_H @@ -43,28 +43,29 @@ * Winbond register definitions. */ enum registers { - WB_BUSCTL = 0x00, /* bus control */ - WB_TXSTART = 0x04, /* tx start demand */ - WB_RXSTART = 0x08, /* rx start demand */ - WB_RXADDR = 0x0C, /* rx descriptor list start addr */ - WB_TXADDR = 0x10, /* tx descriptor list start addr */ - WB_ISR = 0x14, /* interrupt status register */ - WB_NETCFG = 0x18, /* network config register */ - WB_IMR = 0x1C, /* interrupt mask */ - WB_FRAMESDISCARDED = 0x20, /* # of discarded frames */ - WB_SIO = 0x24, /* MII and ROM/EEPROM access */ - WB_BOOTROMADDR = 0x28, - WB_TIMER = 0x2C, /* general timer */ - WB_CURRXCTL = 0x30, /* current RX descriptor */ - WB_CURRXBUF = 0x34, /* current RX buffer */ - WB_MAR0 = 0x38, /* multicast filter 0 */ - WB_MAR1 = 0x3C, /* multicast filter 1 */ - WB_NODE0 = 0x40, /* physical address 0 */ - WB_NODE1 = 0x44, /* physical address 1 */ - WB_BOOTROMSIZE = 0x48, /* boot ROM size */ - WB_CURTXCTL = 0x4C, /* current TX descriptor */ - WB_CURTXBUF = 0x50, /* current TX buffer */ + WB_BUSCTL = 0x00, /* bus control */ + WB_TXSTART = 0x04, /* tx start demand */ + WB_RXSTART = 0x08, /* rx start demand */ + WB_RXADDR = 0x0C, /* rx descriptor list start addr */ + WB_TXADDR = 0x10, /* tx descriptor list start addr */ + WB_ISR = 0x14, /* interrupt status register */ + WB_NETCFG = 0x18, /* network config register */ + WB_IMR = 0x1C, /* interrupt mask */ + WB_FRAMESDISCARDED = 0x20, /* # of discarded frames */ + WB_SIO = 0x24, /* MII and ROM/EEPROM access */ + WB_BOOTROMADDR = 0x28, + WB_TIMER = 0x2C, /* general timer */ + WB_CURRXCTL = 0x30, /* current RX descriptor */ + WB_CURRXBUF = 0x34, /* current RX buffer */ + WB_MAR0 = 0x38, /* multicast filter 0 */ + WB_MAR1 = 0x3C, /* multicast filter 1 */ + WB_NODE0 = 0x40, /* physical address 0 */ + WB_NODE1 = 0x44, /* physical address 1 */ + WB_BOOTROMSIZE = 0x48, /* boot ROM size */ + WB_CURTXCTL = 0x4C, /* current TX descriptor */ + WB_CURTXBUF = 0x50, /* current TX buffer */ }; + /* * Bus control bits. */ @@ -124,6 +125,7 @@ enum InterruptStatusBits { WB_ISR_TX_STATE = 0x00700000, WB_ISR_BUSERRTYPE = 0x03800000, }; + /* * The RX_STATE and TX_STATE fields are not described anywhere in the * Winbond datasheet, however it appears that the Winbond chip is an @@ -132,44 +134,44 @@ enum InterruptStatusBits { * the tulip documentation. */ enum rxState { - WB_RXSTATE_STOPPED = 0x00000000, /* 000 - Stopped */ - WB_RXSTATE_FETCH = 0x00020000, /* 001 - Fetching descriptor */ - WB_RXSTATE_ENDCHECK = 0x00040000, /* 010 - check for rx end */ - WB_RXSTATE_WAIT = 0x00060000, /* 011 - waiting for packet */ - WB_RXSTATE_SUSPEND = 0x00080000, /* 100 - suspend rx */ - WB_RXSTATE_CLOSE = 0x000A0000, /* 101 - close tx desc */ - WB_RXSTATE_FLUSH = 0x000C0000, /* 110 - flush from FIFO */ - WB_RXSTATE_DEQUEUE = 0x000E0000, /* 111 - dequeue from FIFO */ + WB_RXSTATE_STOPPED = 0x00000000, /* 000 - Stopped */ + WB_RXSTATE_FETCH = 0x00020000, /* 001 - Fetching descriptor */ + WB_RXSTATE_ENDCHECK = 0x00040000, /* 010 - check for rx end */ + WB_RXSTATE_WAIT = 0x00060000, /* 011 - waiting for packet */ + WB_RXSTATE_SUSPEND = 0x00080000, /* 100 - suspend rx */ + WB_RXSTATE_CLOSE = 0x000A0000, /* 101 - close tx desc */ + WB_RXSTATE_FLUSH = 0x000C0000, /* 110 - flush from FIFO */ + WB_RXSTATE_DEQUEUE = 0x000E0000, /* 111 - dequeue from FIFO */ }; enum txState { - WB_TXSTATE_RESET = 0x00000000, /* 000 - reset */ - WB_TXSTATE_FETCH = 0x00100000, /* 001 - fetching descriptor */ + WB_TXSTATE_RESET = 0x00000000, /* 000 - reset */ + WB_TXSTATE_FETCH = 0x00100000, /* 001 - fetching descriptor */ WB_TXSTATE_WAITEND = 0x00200000, /* 010 - wait for tx end */ WB_TXSTATE_READING = 0x00300000, /* 011 - read and enqueue */ - WB_TXSTATE_RSVD = 0x00400000, /* 100 - reserved */ - WB_TXSTATE_SETUP = 0x00500000, /* 101 - setup packet */ + WB_TXSTATE_RSVD = 0x00400000, /* 100 - reserved */ + WB_TXSTATE_SETUP = 0x00500000, /* 101 - setup packet */ WB_TXSTATE_SUSPEND = 0x00600000, /* 110 - suspend tx */ - WB_TXSTATE_CLOSE = 0x00700000, /* 111 - close tx desc */ + WB_TXSTATE_CLOSE = 0x00700000, /* 111 - close tx desc */ }; /* * Network config bits. */ enum networkConfigBits { - WB_NETCFG_RX_ON = 0x00000002, - WB_NETCFG_RX_ALLPHYS = 0x00000008, - WB_NETCFG_RX_MULTI = 0x00000010, - WB_NETCFG_RX_BROAD = 0x00000020, - WB_NETCFG_RX_RUNT = 0x00000040, - WB_NETCFG_RX_ERR = 0x00000080, - WB_NETCFG_FULLDUPLEX = 0x00000200, - WB_NETCFG_LOOPBACK = 0x00000C00, - WB_NETCFG_TX_ON = 0x00002000, - WB_NETCFG_TX_THRESH = 0x001FC000, - WB_NETCFG_RX_EARLYTHRSH = 0x1FE00000, - WB_NETCFG_100MBPS = 0x20000000, - WB_NETCFG_TX_EARLY_ON = 0x40000000, - WB_NETCFG_RX_EARLY_ON = 0x80000000, + WB_NETCFG_RX_ON = 0x00000002, + WB_NETCFG_RX_ALLPHYS = 0x00000008, + WB_NETCFG_RX_MULTI = 0x00000010, + WB_NETCFG_RX_BROAD = 0x00000020, + WB_NETCFG_RX_RUNT = 0x00000040, + WB_NETCFG_RX_ERR = 0x00000080, + WB_NETCFG_FULLDUPLEX = 0x00000200, + WB_NETCFG_LOOPBACK = 0x00000C00, + WB_NETCFG_TX_ON = 0x00002000, + WB_NETCFG_TX_THRESH = 0x001FC000, + WB_NETCFG_RX_EARLYTHRSH = 0x1FE00000, + WB_NETCFG_100MBPS = 0x20000000, + WB_NETCFG_TX_EARLY_ON = 0x40000000, + WB_NETCFG_RX_EARLY_ON = 0x80000000, }; /* * The tx threshold can be adjusted in increments of 32 bytes. @@ -182,47 +184,47 @@ enum networkConfigBits { * Interrupt mask bits. */ enum interruptMaskBits { - WB_IMR_TX_OK = 0x00000001, - WB_IMR_TX_IDLE = 0x00000002, - WB_IMR_TX_NOBUF = 0x00000004, - WB_IMR_TX_UNDERRUN = 0x00000020, - WB_IMR_TX_EARLY = 0x00000400, - WB_IMR_RX_EARLY = 0x00000008, - WB_IMR_RX_ERR = 0x00000010, - WB_IMR_RX_OK = 0x00000040, - WB_IMR_RX_NOBUF = 0x00000080, - WB_IMR_RX_IDLE = 0x00000100, - WB_IMR_TIMER_EXPIRED = 0x00000800, - WB_IMR_BUS_ERR = 0x00002000, - WB_IMR_ABNORMAL = 0x00008000, - WB_IMR_NORMAL = 0x00010000, + WB_IMR_TX_OK = 0x00000001, + WB_IMR_TX_IDLE = 0x00000002, + WB_IMR_TX_NOBUF = 0x00000004, + WB_IMR_TX_UNDERRUN = 0x00000020, + WB_IMR_TX_EARLY = 0x00000400, + WB_IMR_RX_EARLY = 0x00000008, + WB_IMR_RX_ERR = 0x00000010, + WB_IMR_RX_OK = 0x00000040, + WB_IMR_RX_NOBUF = 0x00000080, + WB_IMR_RX_IDLE = 0x00000100, + WB_IMR_TIMER_EXPIRED = 0x00000800, + WB_IMR_BUS_ERR = 0x00002000, + WB_IMR_ABNORMAL = 0x00008000, + WB_IMR_NORMAL = 0x00010000, }; #define WB_INTRS \ - (WB_IMR_RX_OK|WB_IMR_RX_IDLE|WB_IMR_RX_ERR|WB_IMR_TX_OK| \ - WB_IMR_RX_NOBUF|WB_IMR_RX_ERR|WB_IMR_RX_EARLY| \ - WB_IMR_TX_NOBUF|WB_IMR_TX_UNDERRUN|WB_IMR_BUS_ERR| \ - WB_IMR_ABNORMAL|WB_IMR_NORMAL|WB_IMR_TX_EARLY) + (WB_IMR_RX_OK|WB_IMR_RX_IDLE|WB_IMR_RX_ERR|WB_IMR_RX_NOBUF \ + |WB_IMR_RX_EARLY|WB_IMR_TX_OK|WB_IMR_TX_EARLY|WB_IMR_TX_NOBUF \ + |WB_IMR_TX_UNDERRUN|WB_IMR_TX_IDLE|WB_IMR_BUS_ERR \ + |WB_IMR_ABNORMAL|WB_IMR_NORMAL|WB_IMR_TIMER_EXPIRED) /* * Serial I/O (EEPROM/ROM) bits. */ enum EEpromBits { - WB_SIO_EE_CS = 0x00000001, /* EEPROM chip select */ - WB_SIO_EE_CLK = 0x00000002, /* EEPROM clock */ - WB_SIO_EE_DATAIN = 0x00000004, /* EEPROM data output */ - WB_SIO_EE_DATAOUT = 0x00000008, /* EEPROM data input */ - WB_SIO_ROMDATA4 = 0x00000010, - WB_SIO_ROMDATA5 = 0x00000020, - WB_SIO_ROMDATA6 = 0x00000040, - WB_SIO_ROMDATA7 = 0x00000080, - WB_SIO_ROMCTL_WRITE = 0x00000200, - WB_SIO_ROMCTL_READ = 0x00000400, - WB_SIO_EESEL = 0x00000800, - WB_SIO_MII_CLK = 0x00010000, /* MDIO clock */ - WB_SIO_MII_DATAIN = 0x00020000, /* MDIO data out */ - WB_SIO_MII_DIR = 0x00040000, /* MDIO dir */ - WB_SIO_MII_DATAOUT = 0x00080000, /* MDIO data in */ + WB_SIO_EE_CS = 0x00000001, /* EEPROM chip select */ + WB_SIO_EE_CLK = 0x00000002, /* EEPROM clock */ + WB_SIO_EE_DATAIN = 0x00000004, /* EEPROM data output */ + WB_SIO_EE_DATAOUT = 0x00000008, /* EEPROM data input */ + WB_SIO_ROMDATA4 = 0x00000010, + WB_SIO_ROMDATA5 = 0x00000020, + WB_SIO_ROMDATA6 = 0x00000040, + WB_SIO_ROMDATA7 = 0x00000080, + WB_SIO_ROMCTL_WRITE = 0x00000200, + WB_SIO_ROMCTL_READ = 0x00000400, + WB_SIO_EESEL = 0x00000800, + WB_SIO_MII_CLK = 0x00010000, /* MDIO clock */ + WB_SIO_MII_DATAIN = 0x00020000, /* MDIO data out */ + WB_SIO_MII_DIR = 0x00040000, /* MDIO dir */ + WB_SIO_MII_DATAOUT = 0x00080000, /* MDIO data in */ }; enum EEpromCmd { @@ -243,51 +245,60 @@ struct wb_desc { uint32 wb_next; }; -#define WB_RXSTAT_CRCERR 0x00000002 -#define WB_RXSTAT_DRIBBLE 0x00000004 -#define WB_RXSTAT_MIIERR 0x00000008 -#define WB_RXSTAT_LATEEVENT 0x00000040 -#define WB_RXSTAT_GIANT 0x00000080 -#define WB_RXSTAT_LASTFRAG 0x00000100 -#define WB_RXSTAT_FIRSTFRAG 0x00000200 -#define WB_RXSTAT_MULTICAST 0x00000400 -#define WB_RXSTAT_RUNT 0x00000800 -#define WB_RXSTAT_RXTYPE 0x00003000 -#define WB_RXSTAT_RXERR 0x00008000 -#define WB_RXSTAT_RXLEN 0x3FFF0000 -#define WB_RXSTAT_RXCMP 0x40000000 -#define WB_RXSTAT_OWN 0x80000000 +enum rxStatusBits { + WB_RXSTAT_CRCERR = 0x00000002, + WB_RXSTAT_DRIBBLE = 0x00000004, + WB_RXSTAT_MIIERR = 0x00000008, + WB_RXSTAT_LATEEVENT = 0x00000040, + WB_RXSTAT_GIANT = 0x00000080, + WB_RXSTAT_LASTFRAG = 0x00000100, + WB_RXSTAT_FIRSTFRAG = 0x00000200, + WB_RXSTAT_MULTICAST = 0x00000400, + WB_RXSTAT_RUNT = 0x00000800, + WB_RXSTAT_RXTYPE = 0x00003000, + WB_RXSTAT_RXERR = 0x00008000, + WB_RXSTAT_RXLEN = 0x3FFF0000, + WB_RXSTAT_RXCMP = 0x40000000, + WB_RXSTAT_OWN = 0x80000000 +}; #define WB_RXBYTES(x) ((x & WB_RXSTAT_RXLEN) >> 16) #define WB_RXSTAT (WB_RXSTAT_FIRSTFRAG|WB_RXSTAT_LASTFRAG|WB_RXSTAT_OWN) -#define WB_RXCTL_BUFLEN1 0x00000FFF -#define WB_RXCTL_BUFLEN2 0x00FFF000 -#define WB_RXCTL_RLINK 0x01000000 -#define WB_RXCTL_RLAST 0x02000000 +enum rxControlBits { + WB_RXCTL_BUFLEN1 = 0x00000FFF, + WB_RXCTL_BUFLEN2 = 0x00FFF000, + WB_RXCTL_RLINK = 0x01000000, + WB_RXCTL_RLAST = 0x02000000 +}; -#define WB_TXSTAT_DEFER 0x00000001 -#define WB_TXSTAT_UNDERRUN 0x00000002 -#define WB_TXSTAT_COLLCNT 0x00000078 -#define WB_TXSTAT_SQE 0x00000080 -#define WB_TXSTAT_ABORT 0x00000100 -#define WB_TXSTAT_LATECOLL 0x00000200 -#define WB_TXSTAT_NOCARRIER 0x00000400 -#define WB_TXSTAT_CARRLOST 0x00000800 -#define WB_TXSTAT_TXERR 0x00001000 -#define WB_TXSTAT_OWN 0x80000000 -#define WB_TXCTL_BUFLEN1 0x000007FF -#define WB_TXCTL_BUFLEN2 0x003FF800 -#define WB_TXCTL_PAD 0x00800000 -#define WB_TXCTL_TLINK 0x01000000 -#define WB_TXCTL_TLAST 0x02000000 -#define WB_TXCTL_NOCRC 0x08000000 -#define WB_TXCTL_FIRSTFRAG 0x20000000 -#define WB_TXCTL_LASTFRAG 0x40000000 -#define WB_TXCTL_FINT 0x80000000 +enum txStatusBits { + WB_TXSTAT_DEFER = 0x00000001, + WB_TXSTAT_UNDERRUN = 0x00000002, + WB_TXSTAT_COLLCNT = 0x00000078, + WB_TXSTAT_SQE = 0x00000080, + WB_TXSTAT_ABORT = 0x00000100, + WB_TXSTAT_LATECOLL = 0x00000200, + WB_TXSTAT_NOCARRIER = 0x00000400, + WB_TXSTAT_CARRLOST = 0x00000800, + WB_TXSTAT_TXERR = 0x00001000, + WB_TXSTAT_OWN = 0x80000000 +}; -#define WB_MAXFRAGS 16 +enum txControlBits { + WB_TXCTL_BUFLEN1 = 0x000007FF, + WB_TXCTL_BUFLEN2 = 0x003FF800, + WB_TXCTL_PAD = 0x00800000, + WB_TXCTL_TLINK = 0x01000000, + WB_TXCTL_TLAST = 0x02000000, + WB_TXCTL_NOCRC = 0x08000000, + WB_TXCTL_FIRSTFRAG = 0x20000000, + WB_TXCTL_LASTFRAG = 0x40000000, + WB_TXCTL_FINT = 0x80000000 +}; + +#define WB_MAXFRAGS 16 #define WB_RX_LIST_CNT 64 #define WB_TX_LIST_CNT 64 #define WB_RX_CNT_MASK (WB_RX_LIST_CNT - 1) @@ -322,7 +333,6 @@ struct wb_mii_frame { #define WB_MII_TURNAROUND 0x02 typedef struct wb_device wb_device; - struct wb_device { timer timer; int32 devId; @@ -360,7 +370,7 @@ struct wb_device { uint16 fixedMode; volatile int32 blockFlag; - ether_address_t myaddr; + ether_address_t MAC_Address; spinlock intLock; const char* deviceName; @@ -378,6 +388,7 @@ struct mii_phy { uint8 types; }; + // taken from Axel's Sis900 driver enum MII_address { // standard registers @@ -471,25 +482,31 @@ enum link_modes { #define WB_CLRBIT(reg, x) write32(reg, read32(reg) & ~x) // Prototypes -extern int32 wb_interrupt(void *arg); -extern status_t wb_create_semaphores(wb_device *device); -extern status_t wb_create_rings(wb_device *device); -extern void wb_delete_rings(wb_device *device); +extern int32 wb_interrupt(void *arg); -extern void wb_init(wb_device *device); -extern void wb_reset(wb_device *device); +extern status_t wb_create_semaphores(wb_device *device); +extern void wb_delete_semaphores(wb_device *device); + +extern status_t wb_create_rings(wb_device *device); +extern void wb_delete_rings(wb_device *device); + +extern void wb_init(wb_device *device); +extern void wb_reset(wb_device *device); +extern status_t wb_stop(wb_device *device); extern status_t wb_initPHYs(wb_device *device); -extern void wb_disable_interrupts(wb_device *device); -extern void wb_enable_interrupts(wb_device *device); +extern void wb_disable_interrupts(wb_device *device); +extern void wb_enable_interrupts(wb_device *device); -extern void wb_set_mode(wb_device *device, int mode); -extern int32 wb_read_mode(wb_device *device); +extern void wb_set_mode(wb_device *device, int mode); +extern int32 wb_read_mode(wb_device *device); -extern int32 wb_tick(timer *arg); -extern void wb_put_rx_descriptor(wb_desc *desc); +extern void wb_set_rx_filter(wb_device *device); -extern void print_address(ether_address_t *addr); +extern int32 wb_tick(timer *arg); +extern void wb_put_rx_descriptor(volatile wb_desc *desc); + +extern void print_address(ether_address_t *addr); #endif //__WB840_H