Now configures RX filter to receive broadcast transmissions also. This fixes the issue of

the card not receiving anything if the transmission was started from another box.
Fixed a couple of warnings. Many cleanups.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9116 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini 2004-09-30 06:34:16 +00:00
parent 43c1e26809
commit dbce0eca86
3 changed files with 300 additions and 227 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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