Some fixes, some warning fixed, added a lot of code for the MII handling (almost completely "stolen" from Axel's sis900 driver), not yet working.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6988 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -67,14 +67,13 @@ wb840_open(const char *name, uint32 flags, void** cookie)
|
||||
LOG(("wb840: reg_base=%x\n", (int)data->reg_base));
|
||||
|
||||
wb_read_eeprom(data, &data->myaddr, 0, 3, 0);
|
||||
print_address((void*)&data->myaddr);
|
||||
|
||||
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) {
|
||||
/* reset the card */
|
||||
wb_reset(data);
|
||||
wb_initPHYs(data);
|
||||
wb_init(data);
|
||||
|
||||
/* Setup interrupts */
|
||||
data->irq = data->pciInfo->u.h0.interrupt_line;
|
||||
@@ -87,15 +86,9 @@ wb840_open(const char *name, uint32 flags, void** cookie)
|
||||
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);
|
||||
//write32(data->reg_base + WB_TXSTART, 0xFFFFFFFF);
|
||||
|
||||
//dump_registers(data);
|
||||
|
||||
add_timer(&data->timer, wb_tick, 1000000LL, B_PERIODIC_TIMER);
|
||||
|
||||
#if DEBUG
|
||||
dump_registers(data);
|
||||
#endif
|
||||
return B_OK; // Everything after this line is an error
|
||||
|
||||
} else
|
||||
@@ -149,11 +142,13 @@ wb840_read(void* cookie, off_t position, void *buf, size_t* num_bytes)
|
||||
*num_bytes = 0;
|
||||
} else {
|
||||
size = WB_RXBYTES(check);
|
||||
size -= CRC_SIZE;
|
||||
LOG((DEVICE_NAME": received %d bytes\n", (int)size));
|
||||
if (size > WB_MAX_FRAMELEN || size > *num_bytes) {
|
||||
LOG(("ERROR: Bad frame size: %d", (int)size));
|
||||
size = *num_bytes;
|
||||
}
|
||||
*num_bytes = size;
|
||||
memcpy(buf, (void *)device->rxBuffer[current], size);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,43 +51,7 @@
|
||||
|
||||
#define MII_DELAY(x) read32(x->reg_base + WB_SIO)
|
||||
|
||||
|
||||
void
|
||||
wb_eeprom_putbyte(wb_device *device, int addr)
|
||||
{
|
||||
int d, i;
|
||||
int delay;
|
||||
|
||||
d = addr | WB_EECMD_READ;
|
||||
|
||||
/*
|
||||
* Feed in each bit and strobe the clock.
|
||||
*/
|
||||
for (i = 0x400; i; i >>= 1) {
|
||||
if (d & i) {
|
||||
SIO_SET(WB_SIO_EE_DATAIN);
|
||||
} else {
|
||||
SIO_CLR(WB_SIO_EE_DATAIN);
|
||||
}
|
||||
for (delay = 0; delay < 100; delay++)
|
||||
MII_DELAY(device);
|
||||
|
||||
SIO_SET(WB_SIO_EE_CLK);
|
||||
|
||||
for (delay = 0; delay < 150; delay++)
|
||||
MII_DELAY(device);
|
||||
|
||||
SIO_CLR(WB_SIO_EE_CLK);
|
||||
|
||||
for (delay = 0; delay < 100; delay++)
|
||||
MII_DELAY(device);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
mii_sync(struct wb_device *device)
|
||||
{
|
||||
@@ -269,7 +233,7 @@ wb_miibus_readreg(wb_device *device, int phy, int reg)
|
||||
frame.mii_regaddr = reg;
|
||||
wb_mii_readreg(device, &frame);
|
||||
|
||||
return(frame.mii_data);
|
||||
return frame.mii_data;
|
||||
}
|
||||
|
||||
|
||||
@@ -298,6 +262,42 @@ wb_miibus_statchg(wb_device *device)
|
||||
|
||||
|
||||
#define EEPROM_DELAY(x) read32(x->reg_base + WB_SIO)
|
||||
|
||||
void
|
||||
wb_eeprom_putbyte(wb_device *device, int addr)
|
||||
{
|
||||
int d, i;
|
||||
int delay;
|
||||
|
||||
d = addr | WB_EECMD_READ;
|
||||
|
||||
/*
|
||||
* Feed in each bit and strobe the clock.
|
||||
*/
|
||||
for (i = 0x400; i; i >>= 1) {
|
||||
if (d & i) {
|
||||
SIO_SET(WB_SIO_EE_DATAIN);
|
||||
} else {
|
||||
SIO_CLR(WB_SIO_EE_DATAIN);
|
||||
}
|
||||
for (delay = 0; delay < 100; delay++)
|
||||
MII_DELAY(device);
|
||||
|
||||
SIO_SET(WB_SIO_EE_CLK);
|
||||
|
||||
for (delay = 0; delay < 150; delay++)
|
||||
MII_DELAY(device);
|
||||
|
||||
SIO_CLR(WB_SIO_EE_CLK);
|
||||
|
||||
for (delay = 0; delay < 100; delay++)
|
||||
MII_DELAY(device);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
wb_eeprom_askdata(wb_device *device, int addr)
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
#include "wb840.h"
|
||||
|
||||
extern void wb_read_eeprom(struct wb_device *, void* dest, int offset, int count, int swap);
|
||||
extern uint16 mii_read(struct wb_device *, int phy_id, int location);
|
||||
|
||||
extern int wb_miibus_readreg(struct wb_device *, int phy_id, int location);
|
||||
extern void wb_miibus_writereg(struct wb_device *, int phy, int location, int data);
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,40 @@
|
||||
|
||||
#define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1))
|
||||
|
||||
// MII chip info table
|
||||
|
||||
#define PHY_ID0_WB840_INTERNAL 0x0181
|
||||
#define PHY_ID1_WB840_INTERNAL 0xb800
|
||||
#define MII_HOME 0x0001
|
||||
#define MII_LAN 0x0002
|
||||
|
||||
const static struct mii_chip_info
|
||||
{
|
||||
const char *name;
|
||||
uint16 id0, id1;
|
||||
uint8 types;
|
||||
}
|
||||
|
||||
gMIIChips[] = {
|
||||
{"WB840 Internal MII PHY", PHY_ID0_WB840_INTERNAL, PHY_ID1_WB840_INTERNAL, MII_LAN},
|
||||
{NULL,0,0,0}
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
mii_readstatus(wb_device *device)
|
||||
{
|
||||
// status bit has to be retrieved 2 times
|
||||
int i = 0;
|
||||
int status;
|
||||
|
||||
while (i++ < 2)
|
||||
status = wb_miibus_readreg(device, device->phy, MII_STATUS);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
physicalAddress(volatile void *addr, uint32 length)
|
||||
{
|
||||
@@ -85,35 +119,117 @@ wb_disable_interrupts(struct wb_device *device)
|
||||
|
||||
|
||||
void
|
||||
wb_reset(wb_device *device)
|
||||
wb_selectPHY(wb_device *device)
|
||||
{
|
||||
int i = 0;
|
||||
cpu_status status;
|
||||
uint16 status;
|
||||
|
||||
LOG((DEVICE_NAME": reset()\n"));
|
||||
// ToDo: need to be changed, select PHY in relation to the link mode
|
||||
device->currentPHY = device->firstPHY;
|
||||
device->phy = device->currentPHY->address;
|
||||
status = wb_miibus_readreg(device, device->phy, MII_CONTROL);
|
||||
status &= ~MII_CONTROL_ISOLATE;
|
||||
|
||||
wb_miibus_writereg(device, device->phy, MII_CONTROL, status);
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
wb_resetPHY(wb_device *device)
|
||||
{
|
||||
uint16 status = mii_readstatus(device);
|
||||
dprintf("wb_resetPHY: %d\n", status);
|
||||
wb_miibus_writereg(device, device->phy, MII_CONTROL, MII_CONTROL_RESET);
|
||||
|
||||
status = disable_interrupts();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
wb_initPHYs(wb_device *device)
|
||||
{
|
||||
uint16 phy;
|
||||
// search for total of 32 possible MII PHY addresses
|
||||
for (phy = 0; phy < 32; phy++) {
|
||||
struct mii_phy *mii;
|
||||
uint16 status;
|
||||
int i = 0;
|
||||
|
||||
device->wb_txthresh = WB_TXTHRESH_INIT;
|
||||
status = wb_miibus_readreg(device, phy, MII_STATUS);
|
||||
status = wb_miibus_readreg(device, phy, MII_STATUS);
|
||||
|
||||
if (status == 0xffff || status == 0x0000)
|
||||
// this MII is not accessable
|
||||
continue;
|
||||
|
||||
mii = (struct mii_phy *)malloc(sizeof(struct mii_phy));
|
||||
if (mii == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
mii->address = phy;
|
||||
mii->id0 = wb_miibus_readreg(device, phy, MII_PHY_ID0);
|
||||
mii->id1 = wb_miibus_readreg(device, phy, MII_PHY_ID1);
|
||||
mii->types = MII_HOME;
|
||||
mii->next = device->firstPHY;
|
||||
device->firstPHY = mii;
|
||||
|
||||
write32(device->reg_base + WB_NETCFG, 0L);
|
||||
write32(device->reg_base + WB_BUSCTL, 0L);
|
||||
write32(device->reg_base + WB_TXADDR, 0L);
|
||||
write32(device->reg_base + WB_RXADDR, 0L);
|
||||
|
||||
WB_SETBIT(device->reg_base + WB_BUSCTL, WB_BUSCTL_RESET);
|
||||
WB_SETBIT(device->reg_base + WB_BUSCTL, WB_BUSCTL_RESET);
|
||||
|
||||
for (i = 0; i < WB_TIMEOUT; i++) {
|
||||
if (!(read32(device->reg_base + WB_BUSCTL) & WB_BUSCTL_RESET))
|
||||
break;
|
||||
while (gMIIChips[i].name != NULL) {
|
||||
if (gMIIChips[i].id0 == mii->id0 && gMIIChips[i].id1 == (mii->id1 & 0xfff0)) {
|
||||
dprintf("Found MII PHY: %s\n", gMIIChips[i].name);
|
||||
mii->types = gMIIChips[i].types;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (gMIIChips[i].name == NULL)
|
||||
dprintf("Unknown MII PHY transceiver: id = (%x, %x).\n",mii->id0, mii->id1);
|
||||
}
|
||||
|
||||
if (device->firstPHY == NULL) {
|
||||
dprintf("No MII PHY transceiver found!\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (i == WB_TIMEOUT)
|
||||
LOG(("reset hasn't completed!!!"));
|
||||
wb_selectPHY(device);
|
||||
|
||||
// if the internal PHY is selected, reset it
|
||||
if (device->currentPHY->id0 == PHY_ID0_WB840_INTERNAL
|
||||
&& (device->currentPHY->id1 & 0xfff0) == PHY_ID1_WB840_INTERNAL) {
|
||||
if (wb_resetPHY(device) & MII_STATUS_LINK) {
|
||||
uint16 poll = MII_STATUS_LINK;
|
||||
while (poll) {
|
||||
poll ^= wb_miibus_readreg(device, device->phy, MII_STATUS) & poll;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
// workaround for ICS1893 PHY
|
||||
if (info->currentPHY->id0 == PHY_ID0_ICS_1893
|
||||
&& (info->currentPHY->id1 & 0xfff0) == PHY_ID1_ICS_1893)
|
||||
mdio_write(info, 0x0018, 0xD200);
|
||||
|
||||
// SiS 630E has some bugs on default value of PHY registers
|
||||
if (info->pciInfo->revision == SiS900_REVISION_SiS630E) {
|
||||
mdio_write(info, MII_AUTONEG_ADV, 0x05e1);
|
||||
mdio_write(info, MII_CONFIG1, 0x22);
|
||||
mdio_write(info, MII_CONFIG2, 0xff00);
|
||||
mdio_write(info, MII_MASK, 0xffc0);
|
||||
}
|
||||
*/
|
||||
|
||||
write32(device->reg_base + WB_BUSCTL, WB_BUSCTL_MUSTBEONE|WB_BUSCTL_ARBITRATION);
|
||||
WB_SETBIT(device->reg_base + WB_BUSCTL, WB_BURSTLEN_16LONG);
|
||||
device->link = mii_readstatus(device) & MII_STATUS_LINK;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wb_init(wb_device *device)
|
||||
{
|
||||
LOG((DEVICE_NAME": init()\n"));
|
||||
|
||||
wb_reset(device);
|
||||
|
||||
device->wb_txthresh = WB_TXTHRESH_INIT;
|
||||
|
||||
switch(device->wb_cachesize) {
|
||||
case 32:
|
||||
@@ -131,6 +247,9 @@ wb_reset(wb_device *device)
|
||||
break;
|
||||
}
|
||||
|
||||
write32(device->reg_base + WB_BUSCTL, WB_BUSCTL_MUSTBEONE|WB_BUSCTL_ARBITRATION);
|
||||
WB_SETBIT(device->reg_base + WB_BUSCTL, WB_BURSTLEN_16LONG);
|
||||
|
||||
write32(device->reg_base + WB_BUSCTL_SKIPLEN, WB_SKIPLEN_4LONG);
|
||||
|
||||
/* Early TX interrupt; doesn't tend to work too well at 100Mbps */
|
||||
@@ -150,7 +269,36 @@ wb_reset(wb_device *device)
|
||||
|
||||
//Disable capture broadcast
|
||||
WB_CLRBIT(device->reg_base + WB_NETCFG, WB_NETCFG_RX_BROAD);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wb_reset(wb_device *device)
|
||||
{
|
||||
int i = 0;
|
||||
cpu_status status;
|
||||
|
||||
LOG((DEVICE_NAME": reset()\n"));
|
||||
|
||||
status = disable_interrupts();
|
||||
// XXX: What about a spinlock here ?
|
||||
|
||||
write32(device->reg_base + WB_NETCFG, 0L);
|
||||
write32(device->reg_base + WB_BUSCTL, 0L);
|
||||
write32(device->reg_base + WB_TXADDR, 0L);
|
||||
write32(device->reg_base + WB_RXADDR, 0L);
|
||||
|
||||
WB_SETBIT(device->reg_base + WB_BUSCTL, WB_BUSCTL_RESET);
|
||||
WB_SETBIT(device->reg_base + WB_BUSCTL, WB_BUSCTL_RESET);
|
||||
|
||||
for (i = 0; i < WB_TIMEOUT; i++) {
|
||||
if (!(read32(device->reg_base + WB_BUSCTL) & WB_BUSCTL_RESET))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == WB_TIMEOUT)
|
||||
LOG(("reset hasn't completed!!!"));
|
||||
|
||||
restore_interrupts(status);
|
||||
|
||||
/* Wait a bit while the chip reorders his toughts */
|
||||
@@ -159,9 +307,42 @@ wb_reset(wb_device *device)
|
||||
//XXX Initialize MII interface
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wb_updateLink(struct wb_device *device)
|
||||
{
|
||||
{
|
||||
if (!device->autoNegotiationComplete) {
|
||||
int32 mode = wb_read_mode(device);
|
||||
if (mode)
|
||||
wb_set_mode(device, mode);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (device->link) { // link lost
|
||||
uint16 status = mii_readstatus(device);
|
||||
|
||||
if ((status & MII_STATUS_LINK) == 0) {
|
||||
device->link = false;
|
||||
dprintf(DEVICE_NAME ": link lost\n");
|
||||
|
||||
// if it's the internal SiS900 MII PHY, reset it
|
||||
//if (device->currentPHY->id0 == PHY_ID0_SiS900_INTERNAL
|
||||
// && (device->currentPHY->id1 & 0xfff0) == PHY_ID1_SiS900_INTERNAL)
|
||||
// sis900_resetPHY(device);
|
||||
}
|
||||
}
|
||||
if (!device->link) { // new link established
|
||||
uint16 status;
|
||||
|
||||
wb_selectPHY(device);
|
||||
|
||||
status = mii_readstatus(device);
|
||||
if (status & MII_STATUS_LINK) {
|
||||
//sis900_checkMode(device);
|
||||
device->link = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -362,17 +543,19 @@ wb_create_semaphores(struct wb_device *device)
|
||||
{
|
||||
device->rxSem = create_sem(0, "wb840 receive");
|
||||
if (device->rxSem < B_OK) {
|
||||
LOG(("Couldn't create sem, sem_id %d\n", (int)device->rxSem));
|
||||
LOG(("Couldn't create sem, sem_id %ld\n", device->rxSem));
|
||||
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 %d\n", (int)device->txSem));
|
||||
LOG(("Couldn't create sem, sem_id %ld\n", device->txSem));
|
||||
delete_sem(device->rxSem);
|
||||
return device->txSem;
|
||||
}
|
||||
|
||||
set_sem_owner(device->txSem, B_SYSTEM_TEAM);
|
||||
|
||||
device->rxLock = 0;
|
||||
@@ -387,9 +570,10 @@ wb_create_rings(struct wb_device *device)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((device->rxArea = create_area("wb840 rx buffer", (void **)&device->rxBuffer[0],
|
||||
device->rxArea = create_area("wb840 rx buffer", (void **)&device->rxBuffer[0],
|
||||
B_ANY_KERNEL_ADDRESS, ROUND_TO_PAGE_SIZE(WB_BUFBYTES * WB_RX_LIST_CNT),
|
||||
B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA)) < B_OK)
|
||||
B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
if (device->rxArea < B_OK)
|
||||
return device->rxArea;
|
||||
|
||||
for (i = 1; i < WB_RX_LIST_CNT; i++)
|
||||
@@ -404,9 +588,10 @@ wb_create_rings(struct wb_device *device)
|
||||
device->rxFree = WB_RX_LIST_CNT;
|
||||
device->rxDescriptor[WB_RX_LIST_CNT - 1].wb_ctl |= WB_RXCTL_RLAST;
|
||||
|
||||
if ((device->txArea = create_area("wb840 tx buffer", (void **)&device->txBuffer[0],
|
||||
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),
|
||||
B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA)) < B_OK) {
|
||||
B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
if (device->txArea < B_OK) {
|
||||
delete_area(device->rxArea);
|
||||
return device->txArea;
|
||||
}
|
||||
@@ -444,3 +629,79 @@ wb_delete_rings(struct wb_device *device)
|
||||
delete_area(device->rxArea);
|
||||
delete_area(device->txArea);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
wb_read_mode(wb_device *info)
|
||||
{
|
||||
uint16 autoAdv, autoLinkPartner;
|
||||
int32 speed, duplex;
|
||||
|
||||
uint16 status = mii_readstatus(info);
|
||||
if (!(status & MII_STATUS_LINK)) {
|
||||
//dprintf(DEVICE_NAME ": no link detected (status = %x)\n", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// auto negotiation completed
|
||||
autoAdv = wb_miibus_readreg(info, info->phy, MII_AUTONEG_ADV);
|
||||
autoLinkPartner = wb_miibus_readreg(info, info->phy, MII_AUTONEG_LINK_PARTNER);
|
||||
status = autoAdv & autoLinkPartner;
|
||||
|
||||
speed = status & (MII_NWAY_TX | MII_NWAY_TX_FDX) ? LINK_SPEED_100_MBIT : LINK_SPEED_10_MBIT;
|
||||
duplex = status & (MII_NWAY_TX_FDX | MII_NWAY_T_FDX) ? LINK_FULL_DUPLEX : LINK_HALF_DUPLEX;
|
||||
|
||||
dprintf("status: 0x%x\n", status);
|
||||
info->autoNegotiationComplete = true;
|
||||
|
||||
// workaround for Realtek RTL8201 PHY issue
|
||||
/*if (phy->id0 == PHY_ID0_REALTEK_8201 && (phy->id1 & 0xFFF0) == PHY_ID1_REALTEK_8201) {
|
||||
if (mdio_read(info, MII_CONTROL) & MII_CONTROL_FULL_DUPLEX)
|
||||
duplex = LINK_FULL_DUPLEX;
|
||||
if (mdio_read(info, 0x0019) & 0x01)
|
||||
speed = LINK_SPEED_100_MBIT;
|
||||
}
|
||||
*/
|
||||
//dprintf(DEVICE_NAME ": linked, 10%s MBit, %s duplex\n",
|
||||
// speed == LINK_SPEED_100_MBIT ? "0" : "",
|
||||
// duplex == LINK_FULL_DUPLEX ? "full" : "half");
|
||||
|
||||
return speed | duplex;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wb_set_mode(wb_device *info, int mode)
|
||||
{
|
||||
/*uint32 address = (uint32)info->registers + SiS900_MAC_CONFIG;
|
||||
uint32 txFlags = SiS900_Tx_AUTO_PADDING | SiS900_Tx_FILL_THRES;
|
||||
uint32 rxFlags = 0;
|
||||
int32 speed = mode & LINK_SPEED_MASK;
|
||||
|
||||
if (read32(address) & SiS900_MAC_CONFIG_EDB_MASTER) {
|
||||
TRACE((DEVICE_NAME ": EDB master is set!\n"));
|
||||
txFlags |= 5 << SiS900_DMA_SHIFT;
|
||||
rxFlags = 5 << SiS900_DMA_SHIFT;
|
||||
}
|
||||
|
||||
// link speed FIFO thresholds
|
||||
|
||||
if (speed == LINK_SPEED_HOME || speed == LINK_SPEED_10_MBIT) {
|
||||
rxFlags |= SiS900_Rx_10_MBIT_DRAIN_THRES;
|
||||
txFlags |= SiS900_Tx_10_MBIT_DRAIN_THRES;
|
||||
} else {
|
||||
rxFlags |= SiS900_Rx_100_MBIT_DRAIN_THRES;
|
||||
txFlags |= SiS900_Tx_100_MBIT_DRAIN_THRES;
|
||||
}
|
||||
|
||||
// duplex mode
|
||||
|
||||
if ((mode & LINK_DUPLEX_MASK) == LINK_FULL_DUPLEX) {
|
||||
txFlags |= SiS900_Tx_CS_IGNORE | SiS900_Tx_HB_IGNORE;
|
||||
rxFlags |= SiS900_Rx_ACCEPT_Tx_PACKETS;
|
||||
}
|
||||
|
||||
write32((uint32)info->registers + SiS900_MAC_Tx_CONFIG, txFlags);
|
||||
write32((uint32)info->registers + SiS900_MAC_Rx_CONFIG, rxFlags);
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -197,17 +197,13 @@ enum interruptMaskBits {
|
||||
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)
|
||||
|
||||
/*#define WB_INTRS \
|
||||
(WB_IMR_RX_OK|WB_IMR_TX_OK|WB_IMR_RX_ERR| \
|
||||
WB_IMR_TX_UNDERRUN|WB_IMR_BUS_ERR| \
|
||||
WB_IMR_ABNORMAL|WB_IMR_NORMAL|WB_IMR_TX_EARLY)
|
||||
*/
|
||||
/*
|
||||
* Serial I/O (EEPROM/ROM) bits.
|
||||
*/
|
||||
@@ -300,11 +296,12 @@ struct wb_desc {
|
||||
#define WB_MAX_FRAMELEN 1536
|
||||
|
||||
#define WB_UNSENT 0x1234
|
||||
#define WB_BUFBYTES (1024 * sizeof(uint32))
|
||||
#define WB_BUFBYTES 2048
|
||||
|
||||
/* Ethernet defines */
|
||||
#define CRC_SIZE 4
|
||||
#define ETHER_TRANSMIT_TIMEOUT ((bigtime_t)5000000) /* five seconds */
|
||||
#define WB_TIMEOUT 1000
|
||||
|
||||
typedef struct wb_mii_frame wb_mii_frame;
|
||||
struct wb_mii_frame {
|
||||
@@ -355,9 +352,15 @@ struct wb_device {
|
||||
int16 txInterruptIndex;
|
||||
int16 txSent;
|
||||
|
||||
struct mii_phy *firstPHY;
|
||||
struct mii_phy *currentPHY;
|
||||
uint16 phy;
|
||||
bool autoNegotiationComplete;
|
||||
bool link;
|
||||
uint16 fixedMode;
|
||||
|
||||
volatile int32 blockFlag;
|
||||
ether_address_t myaddr; /* my ethernet address */
|
||||
//volatile int interrupted; /* interrupted system call */
|
||||
ether_address_t myaddr;
|
||||
|
||||
spinlock intLock;
|
||||
const char* deviceName;
|
||||
@@ -366,7 +369,99 @@ struct wb_device {
|
||||
int wb_cachesize;
|
||||
};
|
||||
|
||||
#define WB_TIMEOUT 1000
|
||||
|
||||
|
||||
|
||||
/* MII Interface */
|
||||
|
||||
struct mii_phy {
|
||||
struct mii_phy *next;
|
||||
uint16 id0, id1;
|
||||
uint16 address;
|
||||
uint8 types;
|
||||
};
|
||||
|
||||
// taken from Axel's Sis900 driver
|
||||
enum MII_address {
|
||||
// standard registers
|
||||
MII_CONTROL = 0x00,
|
||||
MII_STATUS = 0x01,
|
||||
MII_PHY_ID0 = 0x02,
|
||||
MII_PHY_ID1 = 0x03,
|
||||
MII_AUTONEG_ADV = 0x04,
|
||||
MII_AUTONEG_LINK_PARTNER = 0x05,
|
||||
MII_AUTONEG_EXT = 0x06
|
||||
|
||||
// SiS900 specific registers
|
||||
/*MII_CONFIG1 = 0x10,
|
||||
MII_CONFIG2 = 0x11,
|
||||
MII_LINK_STATUS = 0x12,
|
||||
MII_MASK = 0x13,
|
||||
MII_RESERVED = 0x14*/
|
||||
};
|
||||
|
||||
enum MII_control {
|
||||
MII_CONTROL_RESET = 0x8000,
|
||||
MII_CONTROL_RESET_AUTONEG = 0x0200,
|
||||
MII_CONTROL_AUTO = 0x1000,
|
||||
MII_CONTROL_FULL_DUPLEX = 0x0100,
|
||||
MII_CONTROL_ISOLATE = 0x0400
|
||||
};
|
||||
|
||||
enum MII_commands {
|
||||
MII_CMD_READ = 0x6000,
|
||||
MII_CMD_WRITE = 0x5002,
|
||||
|
||||
MII_PHY_SHIFT = 7,
|
||||
MII_REG_SHIFT = 2,
|
||||
};
|
||||
|
||||
enum MII_status_bits {
|
||||
MII_STATUS_EXT = 0x0001,
|
||||
MII_STATUS_JAB = 0x0002,
|
||||
MII_STATUS_LINK = 0x0004,
|
||||
MII_STATUS_CAN_AUTO = 0x0008,
|
||||
MII_STATUS_FAULT = 0x0010,
|
||||
MII_STATUS_AUTO_DONE = 0x0020,
|
||||
MII_STATUS_CAN_T = 0x0800,
|
||||
MII_STATUS_CAN_T_FDX = 0x1000,
|
||||
MII_STATUS_CAN_TX = 0x2000,
|
||||
MII_STATUS_CAN_TX_FDX = 0x4000,
|
||||
MII_STATUS_CAN_T4 = 0x8000
|
||||
};
|
||||
|
||||
enum MII_auto_negotiation {
|
||||
MII_NWAY_NODE_SEL = 0x001f,
|
||||
MII_NWAY_CSMA_CD = 0x0001,
|
||||
MII_NWAY_T = 0x0020,
|
||||
MII_NWAY_T_FDX = 0x0040,
|
||||
MII_NWAY_TX = 0x0080,
|
||||
MII_NWAY_TX_FDX = 0x0100,
|
||||
MII_NWAY_T4 = 0x0200,
|
||||
MII_NWAY_PAUSE = 0x0400,
|
||||
MII_NWAY_RF = 0x2000,
|
||||
MII_NWAY_ACK = 0x4000,
|
||||
MII_NWAY_NP = 0x8000
|
||||
};
|
||||
|
||||
|
||||
enum MII_link_status {
|
||||
MII_LINK_FAIL = 0x4000,
|
||||
MII_LINK_100_MBIT = 0x0080,
|
||||
MII_LINK_FULL_DUPLEX = 0x0040
|
||||
};
|
||||
|
||||
enum link_modes {
|
||||
LINK_HALF_DUPLEX = 0x0100,
|
||||
LINK_FULL_DUPLEX = 0x0200,
|
||||
LINK_DUPLEX_MASK = 0xff00,
|
||||
|
||||
LINK_SPEED_HOME = 1,
|
||||
LINK_SPEED_10_MBIT = 10,
|
||||
LINK_SPEED_100_MBIT = 100,
|
||||
LINK_SPEED_DEFAULT = LINK_SPEED_100_MBIT,
|
||||
LINK_SPEED_MASK = 0x00ff
|
||||
};
|
||||
|
||||
/*
|
||||
* Vendor and Card IDs
|
||||
@@ -387,13 +482,24 @@ struct wb_device {
|
||||
|
||||
// Prototypes
|
||||
extern int32 wb_interrupt(void *arg);
|
||||
extern status_t wb_create_semaphores(struct wb_device *device);
|
||||
extern status_t wb_create_rings(struct wb_device *device);
|
||||
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 void wb_init(wb_device *device);
|
||||
extern void wb_reset(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_set_mode(wb_device *device, int mode);
|
||||
extern int32 wb_read_mode(wb_device *device);
|
||||
|
||||
extern int32 wb_tick(timer *arg);
|
||||
extern void wb_free_rx_descriptor(wb_desc *desc);
|
||||
|
||||
extern void print_address(ether_address_t *addr);
|
||||
|
||||
#endif //__WB840_H
|
||||
|
||||
Reference in New Issue
Block a user