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:
parent
43c1e26809
commit
dbce0eca86
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user