Switch link speed unit to bit/s to support low bitrate speed too

(hello slow dialup line...)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39581 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2010-11-23 13:35:30 +00:00
parent d945edf9c7
commit 172971a18f
13 changed files with 483 additions and 338 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ typedef struct ether_address {
typedef struct ether_link_state {
uint32 media; /* as specified in net/if_media.h */
uint32 quality; /* in one tenth of a percent */
uint64 speed; /* in Kbit/s */
uint64 speed; /* in bit/s */
} ether_link_state_t;
#endif /* _ETHER_DRIVER_H */
@@ -280,11 +280,11 @@ b44_ioctl(void *cookie,uint32 op, void *data, size_t len)
switch (pUmDevice->lm_dev.LineSpeed) {
case LM_LINE_SPEED_10MBPS:
state.media |= IFM_10_T;
state.speed = 10000;
state.speed = 10000000;
break;
case LM_LINE_SPEED_100MBPS:
state.media |= IFM_100_TX;
state.speed = 100000;
state.speed = 100000000;
break;
default:
state.speed = 0;
@@ -509,15 +509,15 @@ b57_ioctl(void *cookie,uint32 op,void *data,size_t len)
switch (pUmDevice->lm_dev.LineSpeed) {
case LM_LINE_SPEED_10MBPS:
state.media |= IFM_10_T;
state.speed = 10000;
state.speed = 10000000;
break;
case LM_LINE_SPEED_100MBPS:
state.media |= IFM_100_TX;
state.speed = 100000;
state.speed = 100000000;
break;
case LM_LINE_SPEED_1000MBPS:
state.media |= IFM_1000_T;
state.speed = 1000000;
state.speed = 1000000000;
break;
default:
state.speed = 0;
@@ -1,7 +1,7 @@
/* Intel PRO/1000 Family Driver
* Copyright (C) 2004 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
*
* Permission to use, copy, modify and distribute this software and its
* Permission to use, copy, modify and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies, and that both the
* copyright notice and this permission notice appear in supporting documentation.
@@ -52,11 +52,11 @@ ipro1000_read_settings(ipro1000_device *device)
void *handle;
const char *param;
int mtu;
handle = load_driver_settings("ipro1000");
if (!handle)
return;
param = get_driver_parameter(handle, "mtu", "-1", "-1");
mtu = atoi(param);
if (mtu >= 50 && mtu <= 1500)
@@ -75,36 +75,36 @@ ipro1000_open(const char *name, uint32 flags, void** cookie)
char *deviceName;
int dev_id;
int mask;
DEVICE_DEBUGOUT("ipro1000_open()");
for (dev_id = 0; (deviceName = gDevNameList[dev_id]) != NULL; dev_id++) {
if (!strcmp(name, deviceName))
break;
}
}
if (deviceName == NULL) {
ERROROUT("invalid device name");
return B_ERROR;
}
// allow only one concurrent access
mask = 1 << dev_id;
if (atomic_or(&gOpenMask, mask) & mask)
return B_BUSY;
*cookie = device = (ipro1000_device *)malloc(sizeof(ipro1000_device));
if (!device) {
atomic_and(&gOpenMask, ~(1 << dev_id));
return B_NO_MEMORY;
}
memset(device, 0, sizeof(*device));
device->devId = dev_id;
device->pciInfo = gDevList[dev_id];
device->nonblocking = (flags & O_NONBLOCK) ? true : false;
device->closed = false;
device->pciBus = device->pciInfo->bus;
device->pciDev = device->pciInfo->device;
device->pciFunc = device->pciInfo->function;
@@ -114,14 +114,14 @@ ipro1000_open(const char *name, uint32 flags, void** cookie)
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
device->linkChangeSem = -1;
#endif
ipro1000_read_settings(device);
if (em_attach(device) != 0) {
DEVICE_DEBUGOUT("em_attach failed");
goto err;
}
return B_OK;
err:
@@ -137,7 +137,7 @@ ipro1000_close(void* cookie)
ipro1000_device *device = (ipro1000_device *)cookie;
struct ifnet *ifp = &device->adapter->interface_data.ac_if;
DEVICE_DEBUGOUT("ipro1000_close()");
device->closed = true;
release_sem(ifp->if_rcv_sem);
@@ -169,9 +169,9 @@ ipro1000_read(void* cookie, off_t position, void *buf, size_t* num_bytes)
struct mbuf *mb;
status_t stat;
int len;
// DEVICE_DEBUGOUT("ipro1000_read() enter");
if (device->closed) {
DEVICE_DEBUGOUT("ipro1000_read() interrupted 1");
return B_INTERRUPTED;
@@ -191,13 +191,13 @@ retry:
DEVICE_DEBUGOUT("ipro1000_read() error");
return B_ERROR;
}
IF_DEQUEUE(&ifp->if_rcv, mb);
if (!mb) {
ERROROUT("ipro1000_read() mbuf not ready");
goto retry;
}
len = mb->m_len;
if (len < 0)
len = 0;
@@ -206,9 +206,9 @@ retry:
memcpy(buf, mtod(mb, uint8 *), len); // XXX this is broken for jumbo frames
*num_bytes = len;
m_freem(mb);
// DEVICE_DEBUGOUT1("ipro1000_read() leave, %d bytes", len);
return B_OK;
}
@@ -221,10 +221,10 @@ ipro1000_write(void* cookie, off_t position, const void* buffer, size_t* num_byt
ipro1000_device *device = (ipro1000_device *)cookie;
struct ifnet *ifp = &device->adapter->interface_data.ac_if;
struct mbuf *mb;
// DEVICE_DEBUGOUT("ipro1000_write() enter");
// allocate mbuf
// allocate mbuf
for (;;) {
MGETHDR(mb, M_DONTWAIT, MT_DATA);
if (mb)
@@ -271,7 +271,7 @@ ipro1000_write(void* cookie, off_t position, const void* buffer, size_t* num_byt
}
// DEVICE_DEBUGOUT("ipro1000_write() 5");
// send everything (if still required)
if (ifp->if_snd.ifq_head != NULL)
ifp->if_start(ifp);
@@ -284,14 +284,14 @@ ipro1000_write(void* cookie, off_t position, const void* buffer, size_t* num_byt
// return B_INTERRUPTED;
// }
// }
// t = system_time() - t;
// if (t > 20)
// DEVICE_DEBUGOUT("write %Ld", t);
// DEVICE_DEBUGOUT("ipro1000_write() finished");
return B_OK;
}
@@ -312,12 +312,12 @@ ipro1000_control(void *cookie, uint32 op, void *arg, size_t len)
case ETHER_INIT:
DEVICE_DEBUGOUT("ipro1000_control() ETHER_INIT");
return B_OK;
case ETHER_GETADDR:
DEVICE_DEBUGOUT("ipro1000_control() ETHER_GETADDR");
memcpy(arg, &device->macaddr, sizeof(device->macaddr));
return B_OK;
case ETHER_NONBLOCK:
if (*(int32 *)arg) {
DEVICE_DEBUGOUT("non blocking mode on");
@@ -375,11 +375,11 @@ ipro1000_control(void *cookie, uint32 op, void *arg, size_t len)
if (mediareq.ifm_status & IFM_ACTIVE)
state.media |= IFM_ACTIVE;
if (mediareq.ifm_active & IFM_10_T)
state.speed = 10000;
state.speed = 10000000;
else if (mediareq.ifm_active & IFM_100_TX)
state.speed = 100000;
state.speed = 100000000;
else
state.speed = 1000000;
state.speed = 1000000000;
state.quality = 1000;
return user_memcpy(arg, &state, sizeof(ether_link_state_t));
@@ -386,12 +386,12 @@ rtl8169_rx_int(rtl8169_device *device)
static status_t
rtl8169_get_link_state(rtl8169_device *device)
{
bool link_ok = false;
bool link_ok = false;
bool full_duplex = false;
uint32 speed = 0;
uint32 speed = 0;
bool linkStateChange = false;
uint32 phy;
dump_phy_stat(device);
print_link_status(device);
@@ -414,11 +414,11 @@ rtl8169_get_link_state(rtl8169_device *device)
}
}
}
linkStateChange = (link_ok != device->link_ok
|| full_duplex != device->full_duplex
|| full_duplex != device->full_duplex
|| speed != device->speed);
device->link_ok = link_ok;
device->full_duplex = full_duplex;
device->speed = speed;
@@ -970,17 +970,17 @@ rtl8169_control(void *cookie, uint32 op, void *arg, size_t len)
case ETHER_GET_LINK_STATE:
{
ether_link_state_t state;
state.media = IFM_ETHER;
state.media |= (device->link_ok ? IFM_ACTIVE : 0);
state.media |= (device->full_duplex ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX);
if (device->speed == 1000000)
if (device->speed == 1000000000)
state.media |= IFM_1000_T;
else if (device->speed == 100000)
else if (device->speed == 100000000)
state.media |= IFM_100_TX;
else if (device->speed == 10000)
else if (device->speed == 10000000)
state.media |= IFM_10_T;
state.speed = device->speed;
state.quality = 1000;
@@ -62,11 +62,11 @@ bug(const char *format, ...)
char c[2048];
int i;
int file;
if ((file = open("/boot/home/sis900-driver.log", O_RDWR | O_APPEND | O_CREAT)) >= 0) {
// time_t timer = time(NULL);
// strftime(c, 2048, "%H:%M:S: ", localtime(&timer));
va_start(vl, format);
i = vsprintf(c, format, vl);
va_end(vl);
@@ -84,7 +84,7 @@ void
dumpBlock(const char *buffer, int size, const char *prefix)
{
int i;
for (i = 0; i < size;)
{
int start = i;
@@ -162,7 +162,7 @@ createSemaphores(struct sis_info *info)
#endif
info->rxLock = info->txLock = 0;
return B_OK;
}
@@ -195,7 +195,7 @@ readSettings(struct sis_info *info)
if ((info->fixedMode & LINK_DUPLEX_MASK) == 0
|| (info->fixedMode & LINK_SPEED_MASK) == 0)
info->fixedMode = 0;
unload_driver_settings(handle);
}
@@ -224,7 +224,7 @@ device_open(const char *name, uint32 flags, void **cookie)
}
if (!thisName)
return EINVAL;
// check if device is already open
mask = 1L << id;
if (atomic_or(&gDeviceOpenMask, mask) & mask)
@@ -278,7 +278,7 @@ device_open(const char *name, uint32 flags, void **cookie)
// check link mode & add timer (once every second)
sis900_checkMode(info);
add_timer(&info->timer, sis900_timer, 1000000LL, B_PERIODIC_TIMER);
add_timer(&info->timer, sis900_timer, 1000000LL, B_PERIODIC_TIMER);
return B_OK;
}
@@ -390,7 +390,7 @@ device_ioctl(void *data, uint32 msg, void *buffer, size_t bufferLength)
| (info->full_duplex ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX)
| (info->speed == LINK_SPEED_100_MBIT ? IFM_100_TX : IFM_10_T);
state.speed = info->speed == LINK_SPEED_100_MBIT
? 100000 : 10000;
? 100000000 : 10000000;
state.quality = 1000;
return user_memcpy(buffer, &state, sizeof(ether_link_state_t));
@@ -2,8 +2,8 @@
* ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver.
* Copyright (c) 2008 S.Zharski <imker@gmx.li>
* Distributed under the terms of the MIT license.
*
* Heavily based on code of the
*
* Heavily based on code of the
* Driver for USB Ethernet Control Model devices
* Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
@@ -37,7 +37,7 @@ enum AX88172_Requests {
READ_MF_ARRAY = 0x15, // C0 15 00 00 00 00 0800 Read Multi-Filter Array
WRITE_MF_ARRAY = 0x16, // 40 16 00 00 00 00 0800 Write Multi-Filter Array
READ_NODEID = 0x17, // C0 17 00 00 00 00 0600 Read Node ID
WRITE_NODEID = 0x18, //
WRITE_NODEID = 0x18, //
READ_PHYID = 0x19, // C0 19 00 00 00 00 0200 Read Ethernet/HomePNA PhyID
READ_MEDIUM_STATUS = 0x1A, // C0 1A 00 00 00 00 0100 Read Medium Status
WRITE_MEDIUM_MODE = 0x1B, // 40 1B MM 00 00 00 0000 Write Medium Mode
@@ -49,21 +49,21 @@ enum AX88172_Requests {
// RX Control Register bits
enum AX88172_RXControl {
RXCTL_PROMISCUOUS = 0x0001, //
RXCTL_ALL_MULTICAT = 0x0002, //
RXCTL_PROMISCUOUS = 0x0001, //
RXCTL_ALL_MULTICAT = 0x0002, //
RXCTL_UNICAST = 0x0004, // ???
RXCTL_BROADCAST = 0x0008, //
RXCTL_MULTICAST = 0x0010, //
RXCTL_MULTICAST = 0x0010, //
RXCTL_START = 0x0080 //
};
// PHY IDs request answer data layout
struct PhyIDs {
uint8 PhyID1;
uint8 PhyID1;
uint8 PhyID2;
} _PACKED;
// Medium state bits
// Medium state bits
enum AX88172_MediumState {
MEDIUM_STATE_FULL_DUPLEX = 0x02,
MEDIUM_STATE_TX_ABORT_ALLOW = 0x04,
@@ -88,19 +88,19 @@ enum AX88172_GPIO {
GPIO_IO_2 = 0x20
};
// Notification data layout
// Notification data layout
struct AX88172Notify {
uint8 btA1;
uint8 bt01;
uint8 btNN; // AX88172_LinkState below
uint8 bt03;
uint8 bt04;
uint8 bt80; // 90h
uint8 bt06;
uint8 bt07;
uint8 btA1;
uint8 bt01;
uint8 btNN; // AX88172_LinkState below
uint8 bt03;
uint8 bt04;
uint8 bt80; // 90h
uint8 bt06;
uint8 bt07;
} _PACKED;
// Link-State bits
// Link-State bits
enum AX88172_LinkState {
LINK_STATE_PHY1 = 0x01,
LINK_STATE_PHY2 = 0x02
@@ -119,7 +119,7 @@ status_t
AX88172Device::InitDevice()
{
fFrameSize = maxFrameSize;
fReadNodeIDRequest = READ_NODEID;
fReadRXControlRequest = READ_RX_CONTROL;
fWriteRXControlRequest = WRITE_RX_CONTROL;
@@ -132,7 +132,7 @@ AX88172Device::InitDevice()
TRACE_ALWAYS("Error of allocating memory for notify buffer.\n");
return B_NO_MEMORY;
}
TRACE_RET(B_OK);
return B_OK;
}
@@ -145,12 +145,12 @@ AX88172Device::SetupDevice(bool deviceReplugged)
}
result = fMII.Init(fDevice,
SW_MII_OP, READ_MII, WRITE_MII,
SW_MII_OP, READ_MII, WRITE_MII,
READ_MII_OP_MODE, HW_MII_OP, READ_PHYID);
if(result == B_OK)
if(result == B_OK)
return fMII.SetupPHY();
TRACE_RET(result);
return result;
}
@@ -162,10 +162,10 @@ AX88172Device::StartDevice()
size_t actualLength = 0;
for(size_t i = 0; i < sizeof(fIPG)/sizeof(fIPG[0]); i++) {
status_t result = gUSBModule->send_request(fDevice,
status_t result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_IPG0, 0, 0, sizeof(fIPG[i]), &fIPG[i], &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error writing IPG%d: %#010x\n", i, result);
return result;
@@ -177,15 +177,15 @@ AX88172Device::StartDevice()
}
}
uint16 rxcontrol = RXCTL_START | RXCTL_MULTICAST
uint16 rxcontrol = RXCTL_START | RXCTL_MULTICAST
| RXCTL_UNICAST | RXCTL_BROADCAST;
status_t result = WriteRXControlRegister(rxcontrol);
if(result != B_OK) {
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result);
}
}
TRACE_RET(result);
return result;
return result;
}
@@ -195,26 +195,26 @@ AX88172Device::OnNotify(uint32 actualLength)
if (actualLength < sizeof(AX88172Notify)) {
TRACE_ALWAYS("Data underrun error. %d of %d bytes received\n",
actualLength, sizeof(AX88172Notify));
return B_BAD_DATA;
return B_BAD_DATA;
}
AX88172Notify *notification = (AX88172Notify *)fNotifyBuffer;
AX88172Notify *notification = (AX88172Notify *)fNotifyBuffer;
if(notification->btA1 != 0xa1) {
TRACE_ALWAYS("Notify magic byte is invalid: %#02x\n",
TRACE_ALWAYS("Notify magic byte is invalid: %#02x\n",
notification->btA1);
}
uint phyIndex = 0;
bool linkIsUp = fHasConnection;
switch(fMII.ActivePHY()) {
case PrimaryPHY:
phyIndex = 1;
linkIsUp = (notification->btNN & LINK_STATE_PHY1) == LINK_STATE_PHY1;
linkIsUp = (notification->btNN & LINK_STATE_PHY1) == LINK_STATE_PHY1;
break;
case SecondaryPHY:
phyIndex = 2;
linkIsUp = (notification->btNN & LINK_STATE_PHY2) == LINK_STATE_PHY2;
linkIsUp = (notification->btNN & LINK_STATE_PHY2) == LINK_STATE_PHY2;
break;
default:
case CurrentPHY:
@@ -226,7 +226,7 @@ AX88172Device::OnNotify(uint32 actualLength)
fHasConnection = linkIsUp;
if(linkStateChange) {
TRACE("Link state of PHY%d has been changed to '%s'\n",
TRACE("Link state of PHY%d has been changed to '%s'\n",
phyIndex, fHasConnection ? "up" : "down");
}
@@ -255,20 +255,20 @@ AX88172Device::GetLinkState(ether_link_state *linkState)
}
TRACE_FLOW("ANAR:%04x ANLPAR:%04x\n", miiANAR, miiANLPAR);
uint16 mediumStatus = miiANAR & miiANLPAR;
linkState->quality = 1000;
linkState->media = IFM_ETHER | (fHasConnection ? IFM_ACTIVE : 0);
linkState->media |= mediumStatus & (ANLPAR_TX_FD | ANLPAR_10_FD) ?
linkState->media |= mediumStatus & (ANLPAR_TX_FD | ANLPAR_10_FD) ?
IFM_FULL_DUPLEX : IFM_HALF_DUPLEX;
linkState->speed = mediumStatus & (ANLPAR_TX_FD | ANLPAR_TX_HD) ? 100000 : 10000;
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
linkState->speed = mediumStatus & (ANLPAR_TX_FD | ANLPAR_TX_HD) ? 100000000 : 10000000;
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
linkState->speed / 1000,
linkState->speed,
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
return B_OK;
}
@@ -2,8 +2,8 @@
* ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver.
* Copyright (c) 2008 S.Zharski <imker@gmx.li>
* Distributed under the terms of the MIT license.
*
* Heavily based on code of the
*
* Heavily based on code of the
* Driver for USB Ethernet Control Model devices
* Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
@@ -15,45 +15,45 @@
// Vendor USB requests for AX88178
enum AX88178_Requests {
READ_RXTX_SRAM = 0x02, //C002_AA0B_0C00_0800 Rx/Tx SRAM Read
WRITE_RXTX_SRAM = 0x03, //4003_AA0B_0C00_0800 Rx/Tx SRAM Write
READ_RXTX_SRAM = 0x02, //C002_AA0B_0C00_0800 Rx/Tx SRAM Read
WRITE_RXTX_SRAM = 0x03, //4003_AA0B_0C00_0800 Rx/Tx SRAM Write
SW_MII_OP = 0x06, //4006_0000_0000_0000 SW Serial Management Control
READ_MII = 0x07, //c007_aa00_cc00_0200 PHY Read
WRITE_MII = 0x08, //4008_aa00_cc00_0200 PHY Write
READ_MII_STATUS = 0x09, //c009_0000_0000_0100 Serial Management Status
READ_MII = 0x07, //c007_aa00_cc00_0200 PHY Read
WRITE_MII = 0x08, //4008_aa00_cc00_0200 PHY Write
READ_MII_STATUS = 0x09, //c009_0000_0000_0100 Serial Management Status
HW_MII_OP = 0x0A, //400a_0000_0000_0000 HW Serial Management Control
READ_SROM = 0x0B, //C00B_AA00_0000_0200 SROM Read
WRITE_SROM = 0x0C, //400C_AA00_CCDD_0000 SROM Write
WRITE_SROM_ENABLE = 0x0D, //400D_0000_0000_0000 SROM Write Enable
WRITE_SROM_DISABLE = 0x0E, //400E_0000_0000_0000 SROM Write Disable
READ_RX_CONTROL = 0x0F, //C00F_0000_0000_0200 Read Rx Control
WRITE_RX_CONTROL = 0x10, //4010_AABB_0000_0000 Write Rx Control
READ_IPGS = 0x11, //C011_0000_0000_0300 Read IPG/IPG1/IPG2 Register
READ_SROM = 0x0B, //C00B_AA00_0000_0200 SROM Read
WRITE_SROM = 0x0C, //400C_AA00_CCDD_0000 SROM Write
WRITE_SROM_ENABLE = 0x0D, //400D_0000_0000_0000 SROM Write Enable
WRITE_SROM_DISABLE = 0x0E, //400E_0000_0000_0000 SROM Write Disable
READ_RX_CONTROL = 0x0F, //C00F_0000_0000_0200 Read Rx Control
WRITE_RX_CONTROL = 0x10, //4010_AABB_0000_0000 Write Rx Control
READ_IPGS = 0x11, //C011_0000_0000_0300 Read IPG/IPG1/IPG2 Register
WRITE_IPGS = 0x12, //4012_AABB_CC00_0000 Write IPG/IPG1/IPG2 Register
READ_NODEID = 0x13, //C013_0000_0000_0600 Read Node ID
WRITE_NODEID = 0x14, //4014_0000_0000_0600 Write Node ID
READ_MF_ARRAY = 0x15, //C015_0000_0000_0800 Read Multicast Filter Array
READ_NODEID = 0x13, //C013_0000_0000_0600 Read Node ID
WRITE_NODEID = 0x14, //4014_0000_0000_0600 Write Node ID
READ_MF_ARRAY = 0x15, //C015_0000_0000_0800 Read Multicast Filter Array
WRITE_MF_ARRAY = 0x16, //4016_0000_0000_0800 Write Multicast Filter Array
READ_TEST = 0x17, //4017_AA00_0000_0000 Write Test Register
READ_TEST = 0x17, //4017_AA00_0000_0000 Write Test Register
READ_PHYID = 0x19, //C019_0000_0000_0200 Read Ethernet/HomePNA PHY Address
READ_MEDIUM_STATUS = 0x1A, //C01A_0000_0000_0200 Read Medium Status
WRITE_MEDIUM_MODE = 0x1B, //401B_AABB_0000_0000 Write Medium Mode Register
GET_MONITOR_MODE = 0x1C, //C01C_0000_0000_0100 Read Monitor Mode Status
READ_MEDIUM_STATUS = 0x1A, //C01A_0000_0000_0200 Read Medium Status
WRITE_MEDIUM_MODE = 0x1B, //401B_AABB_0000_0000 Write Medium Mode Register
GET_MONITOR_MODE = 0x1C, //C01C_0000_0000_0100 Read Monitor Mode Status
SET_MONITOR_MODE = 0x1D, //401D_AA00_0000_0000 Write Monitor Mode Register
READ_GPIOS = 0x1E, //C01E_0000_0000_0100 Read GPIOs Status
WRITE_GPIOS = 0x1F, //401F_AA00_0000_0000 Write GPIOs
WRITE_SOFT_RESET = 0x20, //4020_AA00_0000_0000 Write Software Reset
READ_MIIS_IF_STATE = 0x21, //C021_AA00_0000_0100 Read MII/GMII/RGMII Interface Status
READ_GPIOS = 0x1E, //C01E_0000_0000_0100 Read GPIOs Status
WRITE_GPIOS = 0x1F, //401F_AA00_0000_0000 Write GPIOs
WRITE_SOFT_RESET = 0x20, //4020_AA00_0000_0000 Write Software Reset
READ_MIIS_IF_STATE = 0x21, //C021_AA00_0000_0100 Read MII/GMII/RGMII Interface Status
WRITE_MIIS_IF_STATE = 0x22 //4022_AA00_0000_0000 Write MII/GMII/RGMII Interface Control
};
// RX Control Register bits
enum AX88178_RXControl {
RXCTL_PROMISCUOUS = 0x0001, //
RXCTL_ALL_MULTICAT = 0x0002, //
RXCTL_PROMISCUOUS = 0x0001, //
RXCTL_ALL_MULTICAT = 0x0002, //
// RXCTL_SEP = 0x0004, // do not set it!
RXCTL_BROADCAST = 0x0008, //
RXCTL_MULTICAST = 0x0010, //
RXCTL_MULTICAST = 0x0010, //
RXCTL_AP = 0x0020, //
RXCTL_START = 0x0080, //
RXCTL_USB_MFB = 0x0100 // Max Frame Burst TX on USB
@@ -61,7 +61,7 @@ enum AX88178_RXControl {
// PHY IDs request answer data layout
struct AX88178_PhyIDs {
uint8 SecPhyID;
uint8 SecPhyID;
uint8 PriPhyID2;
} _PACKED;
@@ -84,7 +84,7 @@ enum AX88178_MediumState {
MEDIUM_STATE_SM_ON = 0x1000
};
// Monitor Mode bits
// Monitor Mode bits
enum AX88178_MonitorMode {
MONITOR_MODE_MOM = 0x01,
MONITOR_MODE_RWLU = 0x02,
@@ -92,7 +92,7 @@ enum AX88178_MonitorMode {
MONITOR_MODE_US = 0x10
};
// General Purpose I/O Register
// General Purpose I/O Register
enum AX88178_GPIO {
GPIO_OO_0EN = 0x01,
GPIO_IO_0 = 0x02,
@@ -103,7 +103,7 @@ enum AX88178_GPIO {
GPIO_RSE = 0x80
};
// Software Reset Register bits
// Software Reset Register bits
enum AX88178_SoftwareReset {
SW_RESET_RR = 0x01,
SW_RESET_RT = 0x02,
@@ -121,12 +121,12 @@ enum AX88178_MIISInterfaceStatus {
// Notification data layout
struct AX88178_Notify {
uint8 btA1;
uint8 bt01;
uint8 btA1;
uint8 bt01;
uint8 btBB; // AX88178_BBState below
uint8 bt03;
uint16 regCCDD;
uint16 regEEFF;
uint8 bt03;
uint16 regCCDD;
uint16 regEEFF;
} _PACKED;
// Link-State bits
@@ -151,20 +151,20 @@ AX88178Device::InitDevice()
{
fFrameSize = maxFrameSize;
fUseTRXHeader = true;
fReadNodeIDRequest = READ_NODEID;
fReadRXControlRequest = READ_RX_CONTROL;
fWriteRXControlRequest = WRITE_RX_CONTROL;
fPromiscuousBits = RXCTL_PROMISCUOUS;
fNotifyBufferLength = sizeof(AX88178_Notify);
fNotifyBuffer = (uint8 *)malloc(fNotifyBufferLength);
if (fNotifyBuffer == NULL) {
TRACE_ALWAYS("Error of allocating memory for notify buffer.\n");
return B_NO_MEMORY;
}
TRACE_RET(B_OK);
return B_OK;
}
@@ -179,7 +179,7 @@ AX88178Device::SetupDevice(bool deviceReplugged)
}
result = fMII.Init(fDevice,
SW_MII_OP, READ_MII, WRITE_MII,
SW_MII_OP, READ_MII, WRITE_MII,
READ_MII_STATUS, HW_MII_OP, READ_PHYID);
if(result != B_OK) {
@@ -188,35 +188,35 @@ AX88178Device::SetupDevice(bool deviceReplugged)
size_t actualLength = 0;
// get the "magic" word from EEPROM
result = gUSBModule->send_request(fDevice,
result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_SROM_ENABLE, 0, 0, 0, 0, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of enabling SROM access:%#010x\n", result);
return result;
}
uint16 eepromData = 0;
status_t op_result = gUSBModule->send_request(fDevice,
status_t op_result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN,
READ_SROM, 0x17, 0,
READ_SROM, 0x17, 0,
sizeof(eepromData), &eepromData, &actualLength);
if(op_result != B_OK) {
TRACE_ALWAYS("Error of reading SROM data:%#010x\n", result);
}
if(actualLength != sizeof(eepromData)) {
TRACE_ALWAYS("Mismatch of reading SROM data."
"Read %d bytes instead of %d\n",
"Read %d bytes instead of %d\n",
actualLength, sizeof(eepromData));
}
result = gUSBModule->send_request(fDevice,
result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_SROM_DISABLE, 0, 0, 0, 0, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of disabling SROM access: %#010x\n", result);
return result;
@@ -241,21 +241,21 @@ AX88178Device::SetupDevice(bool deviceReplugged)
{ 30000 , GPIO_OO_1EN },
{ 30000 , GPIO_OO_1EN | GPIO_IO_1 },
};
bool bCase8 = (eepromData >> 8) != 1;
size_t from = bCase8 ? 0 : 4;
size_t to = bCase8 ? 3 : 6;
for(size_t i = from; i <= to; i++) {
result = gUSBModule->send_request(fDevice,
result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_GPIOS, GPIOCommands[i].value,
WRITE_GPIOS, GPIOCommands[i].value,
0, 0, 0, &actualLength);
snooze(GPIOCommands[i].delay);
if(result != B_OK) {
TRACE_ALWAYS("Error of GPIO setup command %d:[%#04x]: %#010x\n",
TRACE_ALWAYS("Error of GPIO setup command %d:[%#04x]: %#010x\n",
i, GPIOCommands[i].value, result);
return result;
}
@@ -263,34 +263,34 @@ AX88178Device::SetupDevice(bool deviceReplugged)
uint8 uSWReset = 0;
// finally a bit of exercises for SW reset register...
result = gUSBModule->send_request(fDevice,
result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_SOFT_RESET, uSWReset, 0, 0, 0, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of SW reset to %#02x: %#010x\n", uSWReset, result);
return result;
}
snooze(150000);
uSWReset = SW_RESET_PRL | SW_RESET_BIT6;
result = gUSBModule->send_request(fDevice,
result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_SOFT_RESET, uSWReset, 0, 0, 0, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of SW reset to %#02x: %#010x\n", uSWReset, result);
return result;
}
snooze(150000);
result = WriteRXControlRegister(0);
if(result != B_OK) {
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result);
return result;
}
}
result = fMII.SetupPHY();
@@ -303,10 +303,10 @@ status_t
AX88178Device::StartDevice()
{
size_t actualLength = 0;
status_t result = gUSBModule->send_request(fDevice,
status_t result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_IPGS, 0, 0, sizeof(fIPG), fIPG, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of writing IPGs:%#010x\n", result);
return result;
@@ -324,7 +324,7 @@ AX88178Device::StartDevice()
}
TRACE_RET(result);
return result;
return result;
}
@@ -334,13 +334,13 @@ AX88178Device::OnNotify(uint32 actualLength)
if (actualLength < sizeof(AX88178_Notify)) {
TRACE_ALWAYS("Data underrun error. %d of %d bytes received\n",
actualLength, sizeof(AX88178_Notify));
return B_BAD_DATA;
return B_BAD_DATA;
}
AX88178_Notify *notification = (AX88178_Notify *)fNotifyBuffer;
AX88178_Notify *notification = (AX88178_Notify *)fNotifyBuffer;
if(notification->btA1 != 0xa1) {
TRACE_ALWAYS("Notify magic byte is invalid: %#02x\n",
TRACE_ALWAYS("Notify magic byte is invalid: %#02x\n",
notification->btA1);
}
@@ -349,11 +349,11 @@ AX88178Device::OnNotify(uint32 actualLength)
switch(fMII.ActivePHY()) {
case PrimaryPHY:
phyIndex = 1;
linkIsUp = (notification->btBB & LINK_STATE_PPLS) == LINK_STATE_PPLS;
linkIsUp = (notification->btBB & LINK_STATE_PPLS) == LINK_STATE_PPLS;
break;
case SecondaryPHY:
phyIndex = 2;
linkIsUp = (notification->btBB & LINK_STATE_SPLS) == LINK_STATE_SPLS;
linkIsUp = (notification->btBB & LINK_STATE_SPLS) == LINK_STATE_SPLS;
break;
default:
case CurrentPHY:
@@ -365,7 +365,7 @@ AX88178Device::OnNotify(uint32 actualLength)
fHasConnection = linkIsUp;
if(linkStateChange) {
TRACE("Link state of PHY%d has been changed to '%s'\n",
TRACE("Link state of PHY%d has been changed to '%s'\n",
phyIndex, fHasConnection ? "up" : "down");
}
@@ -381,37 +381,37 @@ AX88178Device::GetLinkState(ether_link_state *linkState)
{
size_t actualLength = 0;
uint16 mediumStatus = 0;
status_t result = gUSBModule->send_request(fDevice,
status_t result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN,
READ_MEDIUM_STATUS, 0, 0, sizeof(mediumStatus),
READ_MEDIUM_STATUS, 0, 0, sizeof(mediumStatus),
&mediumStatus, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of reading medium status:%#010x.\n", result);
return result;
}
if(actualLength != sizeof(mediumStatus)) {
TRACE_ALWAYS("Mismatch of reading medium status."
"Read %d bytes instead of %d\n",
"Read %d bytes instead of %d\n",
actualLength, sizeof(mediumStatus));
}
TRACE_FLOW("Medium status is %#04x\n", mediumStatus);
linkState->quality = 1000;
linkState->media = IFM_ETHER | (fHasConnection ? IFM_ACTIVE : 0);
linkState->media |= (mediumStatus & MEDIUM_STATE_FD) ?
linkState->media |= (mediumStatus & MEDIUM_STATE_FD) ?
IFM_FULL_DUPLEX : IFM_HALF_DUPLEX;
linkState->speed = (mediumStatus & MEDIUM_STATE_PS_100) ? 100000 : 10000;
linkState->speed = (mediumStatus & MEDIUM_STATE_GM) ?
1000000 : linkState->speed;
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
linkState->speed = (mediumStatus & MEDIUM_STATE_PS_100) ? 100000000 : 10000000;
linkState->speed = (mediumStatus & MEDIUM_STATE_GM) ?
1000000000 : linkState->speed;
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
linkState->speed / 1000,
linkState->speed,
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
return B_OK;
}
@@ -2,8 +2,8 @@
* ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver.
* Copyright (c) 2008 S.Zharski <imker@gmx.li>
* Distributed under the terms of the MIT license.
*
* Heavily based on code of the
*
* Heavily based on code of the
* Driver for USB Ethernet Control Model devices
* Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
@@ -48,11 +48,11 @@ enum AX88772_Requests {
// RX Control Register bits
enum AX88772_RXControl {
RXCTL_PROMISCUOUS = 0x0001, //
RXCTL_ALL_MULTICAT = 0x0002, //
RXCTL_PROMISCUOUS = 0x0001, //
RXCTL_ALL_MULTICAT = 0x0002, //
// RXCTL_SEP = 0x0004, // do not set it!
RXCTL_BROADCAST = 0x0008, //
RXCTL_MULTICAST = 0x0010, //
RXCTL_MULTICAST = 0x0010, //
RXCTL_AP = 0x0020, //
RXCTL_START = 0x0080, //
RXCTL_USB_MFB = 0x0100 // Max Frame Burst TX on USB
@@ -60,7 +60,7 @@ enum AX88772_RXControl {
// PHY IDs request answer data layout
struct AX88772_PhyIDs {
uint8 SecPhyID;
uint8 SecPhyID;
uint8 PriPhyID2;
} _PACKED;
@@ -120,12 +120,12 @@ enum AX88772_SoftwarePHYSelStatus {
// Notification data layout
struct AX88772_Notify {
uint8 btA1;
uint8 bt01;
uint8 btA1;
uint8 bt01;
uint8 btBB; // AX88772_BBState below
uint8 bt03;
uint16 regCCDD;
uint16 regEEFF;
uint8 bt03;
uint16 regCCDD;
uint16 regEEFF;
} _PACKED;
// Link-State bits
@@ -150,20 +150,20 @@ AX88772Device::InitDevice()
{
fFrameSize = maxFrameSize;
fUseTRXHeader = true;
fReadNodeIDRequest = READ_NODEID;
fReadRXControlRequest = READ_RX_CONTROL;
fWriteRXControlRequest = WRITE_RX_CONTROL;
fPromiscuousBits = RXCTL_PROMISCUOUS;
fNotifyBufferLength = sizeof(AX88772_Notify);
fNotifyBuffer = (uint8 *)malloc(fNotifyBufferLength);
if (fNotifyBuffer == NULL) {
TRACE_ALWAYS("Error of allocating memory for notify buffer.\n");
return B_NO_MEMORY;
}
return B_OK;
}
@@ -176,17 +176,17 @@ AX88772Device::SetupDevice(bool deviceReplugged)
return result;
}
result = fMII.Init(fDevice,
SW_MII_OP, READ_MII, WRITE_MII,
result = fMII.Init(fDevice,
SW_MII_OP, READ_MII, WRITE_MII,
READ_MII_OP_MODE, HW_MII_OP, READ_PHYID);
size_t actualLength = 0;
// enable GPIO2 - magic from FreeBSD's if_axe
uint16 GPIOs = GPIO_OO_2EN | GPIO_IO_2 | GPIO_RSE;
result = gUSBModule->send_request(fDevice,
result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_GPIOS, GPIOs, 0, 0, 0, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of wrinting GPIOs: %#010x\n", result);
return result;
@@ -194,17 +194,17 @@ AX88772Device::SetupDevice(bool deviceReplugged)
// select PHY
bool useEmbeddedPHY = fMII.PHYID() == PHYIDEmbedded;
uint16 selectPHY = useEmbeddedPHY ?
uint16 selectPHY = useEmbeddedPHY ?
SW_PHY_SEL_STATUS_INT : SW_PHY_SEL_STATUS_EXT;
result = gUSBModule->send_request(fDevice,
result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_PHY_SEL, selectPHY, 0, 0, 0, &actualLength);
snooze(10000);
TRACE("Selecting %s PHY[%#02x].\n",
TRACE("Selecting %s PHY[%#02x].\n",
useEmbeddedPHY ? "embedded" : "external", selectPHY);
if(result != B_OK) {
TRACE_ALWAYS("Error of selecting PHY:%#010x\n", result);
return result;
@@ -215,16 +215,16 @@ AX88772Device::SetupDevice(bool deviceReplugged)
bigtime_t delay;
} resetCommands[] = {
// EMBEDDED PHY
// power down and reset state, pin reset state
// power down and reset state, pin reset state
{ SW_RESET_CLR, 60000 },
// power down/reset state, pin operating state
// power down/reset state, pin operating state
{ SW_RESET_PRL | SW_RESET_IPPD, 150000 },
// power up, reset
// power up, reset
{ SW_RESET_PRL, 0 },
// power up, operating
// power up, operating
{ SW_RESET_PRL | SW_RESET_IPRL, 0 },
// EXTERNAL PHY
// power down/reset state, pin operating state
// power down/reset state, pin operating state
{ SW_RESET_PRL | SW_RESET_IPPD, 0 }
};
@@ -232,22 +232,22 @@ AX88772Device::SetupDevice(bool deviceReplugged)
size_t to = useEmbeddedPHY ? 3 : 4;
for(size_t i = from; i <= to; i++) {
result = gUSBModule->send_request(fDevice,
result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_SOFT_RESET, resetCommands[i].reset,
WRITE_SOFT_RESET, resetCommands[i].reset,
0, 0, 0, &actualLength);
snooze(resetCommands[i].delay);
if(result != B_OK) {
TRACE_ALWAYS("Error of SW reset command %d:[%#04x]: %#010x\n",
TRACE_ALWAYS("Error of SW reset command %d:[%#04x]: %#010x\n",
i, resetCommands[i].reset, result);
return result;
}
}
snooze(150000);
result = WriteRXControlRegister(0);
if(result != B_OK) {
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result);
@@ -259,14 +259,14 @@ AX88772Device::SetupDevice(bool deviceReplugged)
return result;
}
result = gUSBModule->send_request(fDevice,
result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_MEDIUM_MODE,
WRITE_MEDIUM_MODE,
MEDIUM_STATE_FD | MEDIUM_STATE_BIT2 |
MEDIUM_STATE_RFC| MEDIUM_STATE_TFC |
MEDIUM_STATE_RE | MEDIUM_STATE_PS_100,
MEDIUM_STATE_RE | MEDIUM_STATE_PS_100,
0, 0, 0, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of setting medium mode: %#010x\n", result);
}
@@ -280,15 +280,15 @@ status_t
AX88772Device::StartDevice()
{
size_t actualLength = 0;
status_t result = gUSBModule->send_request(fDevice,
status_t result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_IPGS, 0, 0, sizeof(fIPG), fIPG, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of writing IPGs:%#010x\n", result);
return result;
}
if(actualLength != sizeof(fIPG)) {
TRACE_ALWAYS("Mismatch of written IPGs data. "
"%d bytes of %d written.\n", actualLength, sizeof(fIPG));
@@ -298,10 +298,10 @@ AX88772Device::StartDevice()
result = WriteRXControlRegister(rxcontrol);
if(result != B_OK) {
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result);
}
}
TRACE_RET(result);
return result;
return result;
}
@@ -311,13 +311,13 @@ AX88772Device::OnNotify(uint32 actualLength)
if (actualLength < sizeof(AX88772_Notify)) {
TRACE_ALWAYS("Data underrun error. %d of %d bytes received\n",
actualLength, sizeof(AX88772_Notify));
return B_BAD_DATA;
return B_BAD_DATA;
}
AX88772_Notify *notification = (AX88772_Notify *)fNotifyBuffer;
AX88772_Notify *notification = (AX88772_Notify *)fNotifyBuffer;
if(notification->btA1 != 0xa1) {
TRACE_ALWAYS("Notify magic byte is invalid: %#02x\n",
TRACE_ALWAYS("Notify magic byte is invalid: %#02x\n",
notification->btA1);
}
@@ -326,11 +326,11 @@ AX88772Device::OnNotify(uint32 actualLength)
switch(fMII.ActivePHY()) {
case PrimaryPHY:
phyIndex = 1;
linkIsUp = (notification->btBB & LINK_STATE_PPLS) == LINK_STATE_PPLS;
linkIsUp = (notification->btBB & LINK_STATE_PPLS) == LINK_STATE_PPLS;
break;
case SecondaryPHY:
phyIndex = 2;
linkIsUp = (notification->btBB & LINK_STATE_SPLS) == LINK_STATE_SPLS;
linkIsUp = (notification->btBB & LINK_STATE_SPLS) == LINK_STATE_SPLS;
break;
default:
case CurrentPHY:
@@ -342,7 +342,7 @@ AX88772Device::OnNotify(uint32 actualLength)
fHasConnection = linkIsUp;
if(linkStateChange) {
TRACE("Link state of PHY%d has been changed to '%s'\n",
TRACE("Link state of PHY%d has been changed to '%s'\n",
phyIndex, fHasConnection ? "up" : "down");
}
@@ -352,41 +352,41 @@ AX88772Device::OnNotify(uint32 actualLength)
return B_OK;
}
status_t
AX88772Device::GetLinkState(ether_link_state *linkState)
{
size_t actualLength = 0;
uint16 mediumStatus = 0;
status_t result = gUSBModule->send_request(fDevice,
status_t result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN,
READ_MEDIUM_STATUS, 0, 0, sizeof(mediumStatus),
READ_MEDIUM_STATUS, 0, 0, sizeof(mediumStatus),
&mediumStatus, &actualLength);
if(result != B_OK) {
TRACE_ALWAYS("Error of reading medium status:%#010x.\n", result);
return result;
}
if(actualLength != sizeof(mediumStatus)) {
TRACE_ALWAYS("Mismatch of reading medium status."
"Read %d bytes instead of %d\n",
"Read %d bytes instead of %d\n",
actualLength, sizeof(mediumStatus));
}
TRACE_FLOW("Medium status is %#04x\n", mediumStatus);
linkState->quality = 1000;
linkState->media = IFM_ETHER | (fHasConnection ? IFM_ACTIVE : 0);
linkState->media |= (mediumStatus & MEDIUM_STATE_FD) ?
linkState->media |= (mediumStatus & MEDIUM_STATE_FD) ?
IFM_FULL_DUPLEX : IFM_HALF_DUPLEX;
linkState->speed = (mediumStatus & MEDIUM_STATE_PS_100) ? 100000 : 10000;
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
linkState->speed = (mediumStatus & MEDIUM_STATE_PS_100) ? 100000000 : 10000000;
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
linkState->speed / 1000,
linkState->speed,
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
return B_OK;
}
@@ -3,11 +3,11 @@
* Copyright (c) 2009 Adrien Destugues <pulkomandy@gmail.com>
* Distributed under the terms of the MIT license.
*
* Heavily based on code of
* Heavily based on code of
* ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver.
* Copyright (c) 2008 S.Zharski <imker@gmx.li>
* Distributed under the terms of the MIT license.
*
*
* Driver for USB Ethernet Control Model devices
* Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
* Distributed under the terms of the MIT license.
@@ -64,7 +64,7 @@ DavicomDevice::_ReadRegister(uint8 reg, size_t size, uint8* buffer)
{
if (size > 255) return B_BAD_VALUE;
size_t actualLength;
status_t result = gUSBModule->send_request(fDevice,
status_t result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN,
READ_REGISTER, 0, reg, size, buffer, &actualLength);
if (size != actualLength) {
@@ -80,7 +80,7 @@ DavicomDevice::_WriteRegister(uint8 reg, size_t size, uint8* buffer)
{
if (size > 255) return B_BAD_VALUE;
size_t actualLength;
status_t result = gUSBModule->send_request(fDevice,
status_t result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE_REGISTER, 0, reg, size, buffer, &actualLength);
return result;
@@ -91,7 +91,7 @@ status_t
DavicomDevice::_Write1Register(uint8 reg, uint8 value)
{
size_t actualLength;
status_t result = gUSBModule->send_request(fDevice,
status_t result = gUSBModule->send_request(fDevice,
USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
WRITE1_REGISTER, 0, reg, 1, &value, &actualLength);
return result;
@@ -104,17 +104,17 @@ DavicomDevice::DavicomDevice(usb_device device, const char *description)
fRemoved(false),
fInsideNotify(0),
fDevice(device),
fDescription(description),
fNonBlocking(false),
fNotifyEndpoint(0),
fReadEndpoint(0),
fDescription(description),
fNonBlocking(false),
fNotifyEndpoint(0),
fReadEndpoint(0),
fWriteEndpoint(0),
fNotifyReadSem(-1),
fNotifyWriteSem(-1),
fNotifyReadSem(-1),
fNotifyWriteSem(-1),
fNotifyBuffer(NULL),
fLinkStateChangeSem(-1),
fLinkStateChangeSem(-1),
fHasConnection(false)
{
{
const usb_device_descriptor
*deviceDescriptor = gUSBModule->get_device_descriptor(device);
@@ -135,7 +135,7 @@ DavicomDevice::DavicomDevice(usb_device device, const char *description)
fNotifyWriteSem = create_sem(0, DRIVER_NAME"_notify_write");
if (fNotifyWriteSem < B_OK) {
TRACE_ALWAYS("Error of creating write notify semaphore:%#010x\n",
TRACE_ALWAYS("Error of creating write notify semaphore:%#010x\n",
fNotifyWriteSem);
return;
}
@@ -149,7 +149,7 @@ DavicomDevice::DavicomDevice(usb_device device, const char *description)
if (_SetupEndpoints() != B_OK) {
return;
}
// TODO : others inits here ?
fStatus = B_OK;
@@ -162,7 +162,7 @@ DavicomDevice::~DavicomDevice()
delete_sem(fNotifyReadSem);
if (fNotifyWriteSem >= B_OK)
delete_sem(fNotifyWriteSem);
if (!fRemoved) //???
gUSBModule->cancel_queued_transfers(fNotifyEndpoint);
@@ -178,12 +178,12 @@ DavicomDevice::Open(uint32 flags)
return B_BUSY;
if (fRemoved)
return B_ERROR;
status_t result = StartDevice();
if (result != B_OK) {
return result;
}
// setup state notifications
result = gUSBModule->queue_interrupt(fNotifyEndpoint, fNotifyBuffer,
kNotifyBufferSize, _NotifyCallback, this);
@@ -194,7 +194,7 @@ DavicomDevice::Open(uint32 flags)
fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK;
fOpen = true;
return result;
return result;
}
@@ -214,7 +214,7 @@ DavicomDevice::Close()
gUSBModule->cancel_queued_transfers(fWriteEndpoint);
fOpen = false;
return StopDevice();
}
@@ -231,9 +231,9 @@ DavicomDevice::Read(uint8 *buffer, size_t *numBytes)
{
size_t numBytesToRead = *numBytes;
*numBytes = 0;
if (fRemoved) {
TRACE_ALWAYS("Error of receiving %d bytes from removed device.\n",
TRACE_ALWAYS("Error of receiving %d bytes from removed device.\n",
numBytesToRead);
return B_DEVICE_NOT_FOUND;
}
@@ -246,7 +246,7 @@ DavicomDevice::Read(uint8 *buffer, size_t *numBytes)
{ buffer, numBytesToRead }
};
status_t result = gUSBModule->queue_bulk_v(fReadEndpoint,
status_t result = gUSBModule->queue_bulk_v(fReadEndpoint,
rxData, 1, _ReadCallback, this);
if (result != B_OK) {
TRACE_ALWAYS("Error of queue_bulk_v request:%#010x\n", result);
@@ -259,14 +259,14 @@ DavicomDevice::Read(uint8 *buffer, size_t *numBytes)
TRACE_ALWAYS("Error of acquiring notify semaphore:%#010x.\n", result);
return result;
}
if (fStatusRead != B_OK && fStatusRead != B_CANCELED && !fRemoved) {
TRACE_ALWAYS("Device status error:%#010x\n", fStatusRead);
return fStatusRead;
}
if(fActualLengthRead < kRXHeaderSize) {
TRACE_ALWAYS("Error: no place for TRXHeader:only %d of %d bytes.\n",
TRACE_ALWAYS("Error: no place for TRXHeader:only %d of %d bytes.\n",
fActualLengthRead, kRXHeaderSize);
return B_ERROR; //TODO: ???
}
@@ -274,12 +274,12 @@ DavicomDevice::Read(uint8 *buffer, size_t *numBytes)
/*
* TODO :see what the first byte holds ?
if(!header.IsValid()) {
TRACE_ALWAYS("Error:TRX Header is invalid: len:%#04x; ilen:%#04x\n",
TRACE_ALWAYS("Error:TRX Header is invalid: len:%#04x; ilen:%#04x\n",
header.fLength, header.fInvertedLength);
return B_ERROR; //TODO: ???
}
*/
*numBytes = header[1] | ( header[2] << 8 );
if (header[0] & 0xBF ) {
@@ -301,9 +301,9 @@ DavicomDevice::Write(const uint8 *buffer, size_t *numBytes)
{
size_t numBytesToWrite = *numBytes;
*numBytes = 0;
if (fRemoved) {
TRACE_ALWAYS("Error of writing %d bytes to removed device.\n",
TRACE_ALWAYS("Error of writing %d bytes to removed device.\n",
numBytesToWrite);
return B_DEVICE_NOT_FOUND;
}
@@ -321,7 +321,7 @@ DavicomDevice::Write(const uint8 *buffer, size_t *numBytes)
}
TRACE_FLOW("Write %d bytes.\n", numBytesToWrite);
uint8 header[kTXHeaderSize];
header[0] = *numBytes & 0xFF;
header[1] = *numBytes >> 8;
@@ -330,8 +330,8 @@ DavicomDevice::Write(const uint8 *buffer, size_t *numBytes)
{ &header, kTXHeaderSize },
{ (uint8*)buffer, numBytesToWrite }
};
status_t result = gUSBModule->queue_bulk_v(fWriteEndpoint,
status_t result = gUSBModule->queue_bulk_v(fWriteEndpoint,
txData, 2, _WriteCallback, this);
if (result != B_OK) {
TRACE_ALWAYS("Error of queue_bulk_v request:%#010x\n", result);
@@ -339,7 +339,7 @@ DavicomDevice::Write(const uint8 *buffer, size_t *numBytes)
}
result = acquire_sem_etc(fNotifyWriteSem, 1, B_CAN_INTERRUPT, 0);
if (result < B_OK) {
TRACE_ALWAYS("Error of acquiring notify semaphore:%#010x.\n", result);
return result;
@@ -367,28 +367,28 @@ DavicomDevice::Control(uint32 op, void *buffer, size_t length)
case ETHER_GETADDR:
memcpy(buffer, &fMACAddress, sizeof(fMACAddress));
return B_OK;
case ETHER_GETFRAMESIZE:
*(uint32 *)buffer = 1518 /* fFrameSize */;
return B_OK;
case ETHER_NONBLOCK:
case ETHER_NONBLOCK:
TRACE("ETHER_NONBLOCK\n");
fNonBlocking = *((uint8*)buffer);
return B_OK;
case ETHER_SETPROMISC:
case ETHER_SETPROMISC:
TRACE("ETHER_SETPROMISC\n");
return SetPromiscuousMode(*((uint8*)buffer));
case ETHER_ADDMULTI:
TRACE("ETHER_ADDMULTI\n");
return ModifyMulticastTable(true, *((uint8*)buffer));
case ETHER_REMMULTI:
TRACE("ETHER_REMMULTI\n");
return ModifyMulticastTable(false, *((uint8*)buffer));
#if HAIKU_TARGET_PLATFORM_HAIKU
case ETHER_SET_LINK_STATE_SEM:
fLinkStateChangeSem = *(sem_id *)buffer;
@@ -441,7 +441,7 @@ DavicomDevice::SetupDevice(bool deviceReplugged)
}
TRACE("MAC address is:%02x:%02x:%02x:%02x:%02x:%02x\n",
address.ebyte[0], address.ebyte[1], address.ebyte[2],
address.ebyte[0], address.ebyte[1], address.ebyte[2],
address.ebyte[3], address.ebyte[4], address.ebyte[5]);
if(deviceReplugged) {
@@ -450,14 +450,14 @@ DavicomDevice::SetupDevice(bool deviceReplugged)
if(memcmp(&address, &fMACAddress, sizeof(address)) != 0) {
TRACE_ALWAYS("Cannot replace device with MAC address:"
"%02x:%02x:%02x:%02x:%02x:%02x\n",
fMACAddress.ebyte[0], fMACAddress.ebyte[1], fMACAddress.ebyte[2],
fMACAddress.ebyte[0], fMACAddress.ebyte[1], fMACAddress.ebyte[2],
fMACAddress.ebyte[3], fMACAddress.ebyte[4], fMACAddress.ebyte[5]);
return B_BAD_VALUE; // is not the same
}
} else
} else
fMACAddress = address;
return B_OK;
return B_OK;
}
@@ -492,7 +492,7 @@ DavicomDevice::CompareAndReattach(usb_device device)
// we need to setup hardware on device replug
result = SetupDevice(true);
if (result != B_OK) {
return result;
return result;
}
if (fOpen) {
@@ -526,7 +526,7 @@ DavicomDevice::_SetupEndpoints()
"USB device configuration\n");
return B_ERROR;
}
int notifyEndpoint = -1;
int readEndpoint = -1;
int writeEndpoint = -1;
@@ -537,25 +537,25 @@ DavicomDevice::_SetupEndpoints()
notifyEndpoint = ep;
continue;
}
if((epd->attributes & USB_ENDPOINT_ATTR_MASK) != USB_ENDPOINT_ATTR_BULK) {
TRACE_ALWAYS("Error: USB endpoint type %#04x is unknown.\n", epd->attributes);
continue;
}
if((epd->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
if((epd->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
== USB_ENDPOINT_ADDR_DIR_IN) {
readEndpoint = ep;
continue;
}
if((epd->endpoint_address & USB_ENDPOINT_ADDR_DIR_OUT)
if((epd->endpoint_address & USB_ENDPOINT_ADDR_DIR_OUT)
== USB_ENDPOINT_ADDR_DIR_OUT) {
writeEndpoint = ep;
continue;
}
}
if (notifyEndpoint == -1 || readEndpoint == -1 || writeEndpoint == -1) {
TRACE_ALWAYS("Error: not all USB endpoints were found: "
"notify:%d; read:%d; write:%d\n",
@@ -568,7 +568,7 @@ DavicomDevice::_SetupEndpoints()
fNotifyEndpoint = interface->endpoint[notifyEndpoint].handle;
fReadEndpoint = interface->endpoint[readEndpoint ].handle;
fWriteEndpoint = interface->endpoint[writeEndpoint ].handle;
return B_OK;
}
@@ -591,13 +591,13 @@ DavicomDevice::StopDevice()
{
/*
status_t result = WriteRXControlRegister(0);
if(result != B_OK) {
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result);
}
}
TRACE_RET(result);
return result;
return result;
*/
TRACE_ALWAYS("Stop device not implemented\n");
return B_ERROR;
@@ -627,7 +627,7 @@ DavicomDevice::SetPromiscuousMode(bool on)
result = _Write1Register(RCR, rxmode);
if(result != B_OK) {
TRACE_ALWAYS("Error writing %#04x to RX Control:%#010x\n", rxmode, result);
}
}
return result;
}
@@ -686,7 +686,7 @@ DavicomDevice::_NotifyCallback(void *cookie, int32 status, void *data,
TRACE_ALWAYS("Error during clearing of HALT state:%#010x.\n", result);
*/
}
// parse data in overriden class
device->OnNotify(actualLength);
@@ -765,7 +765,7 @@ DavicomDevice::OnNotify(uint32 actualLength)
if (actualLength != kNotifyBufferSize) {
TRACE_ALWAYS("Data underrun error. %d of 8 bytes received\n",
actualLength);
return B_BAD_DATA;
return B_BAD_DATA;
}
// 3 = RX status
@@ -773,7 +773,7 @@ DavicomDevice::OnNotify(uint32 actualLength)
// 5 = Received packet counter
// 6 = Transmit packet counter
// 7 = GPR
// 0 = Network status (NSR)
bool linkIsUp = (fNotifyBuffer[0] & NSR_LINKST) != 0;
fTXBufferFull = (fNotifyBuffer[0] & NSR_TXFULL) != 0;
@@ -784,7 +784,7 @@ DavicomDevice::OnNotify(uint32 actualLength)
if (linkStateChange) {
if (fHasConnection) {
TRACE("Link is now up at %s Mb/s\n",
TRACE("Link is now up at %s Mb/s\n",
(fNotifyBuffer[0] & NSR_SPEED) ? "10" : "100");
} else
TRACE("Link is now down");
@@ -815,9 +815,9 @@ DavicomDevice::GetLinkState(ether_link_state *linkState)
}
if (registerValue & NSR_SPEED)
linkState->speed = 10000;
linkState->speed = 10000000;
else
linkState->speed = 100000;
linkState->speed = 100000000;
linkState->quality = 1000;
@@ -839,9 +839,9 @@ DavicomDevice::GetLinkState(ether_link_state *linkState)
linkState->media |= IFM_LOOP;
}
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
linkState->speed / 1000,
linkState->speed,
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
return B_OK;
}
@@ -273,7 +273,7 @@ ECMDevice::Control(uint32 op, void *buffer, size_t length)
state->media = IFM_ETHER | IFM_FULL_DUPLEX
| (fHasConnection ? IFM_ACTIVE : 0);
state->quality = 1000;
state->speed = fDownstreamSpeed / 1000;
state->speed = fDownstreamSpeed;
return B_OK;
}
#endif
@@ -41,6 +41,7 @@ struct dialup_device : net_device {
int fd;
struct termios line_config;
dialup_state state;
bool data_mode;
char init_string[64];
char dial_string[64];
char escape_string[8];
@@ -51,6 +52,123 @@ struct dialup_device : net_device {
net_buffer_module_info* gBufferModule;
static net_stack_module_info* sStackModule;
// #pragma mark -
static status_t
send_command(dialup_device* device, const char* command)
{
status_t status;
if (device->data_mode) {
status = switch_to_command_mode(device);
if (status != B_OK)
return status;
}
ssize_t bytesWritten = write(device->fd, command, strlen(command);
if (bytesWritten != (ssize_t)strlen(command))
return B_IO_ERROR;
if (write(fd, "\r", 1) != 1)
return B_IO_ERROR;
return B_OK;
}
static status_t
read_command_reply(dialup_device* device, const char* command,
char* reply, int replyMaxSize)
{
if (device->data_mode)
return B_ERROR;
int i = 0;
while (i < replyMaxSize) {
ssize_t bytesRead = read(device->fd, &reply[i], 1);
if (bytesRead != 1)
return B_IO_ERROR;
if (reply[i] == '\n') {
// filter linefeed char
continue;
}
if (reply[i] == '\r') {
reply[i] = '\0';
// is command reply or command echo (if any) ?
if (!strcasecmp(reply, command))
return B_OK;
// It's command echo line. Just ignore it.
i = 0;
continue;
}
i++;
}
// replyMaxSize not large enough to store the full reply line.
return B_NO_MEMORY;
}
static status_t
switch_to_command_mode(dialup_device* device)
{
if (device->state != UP || !device->data_mode)
return B_ERROR;
snooze(device->escape_silence);
ssize_t size = write(device->fd, device->escape_string,
strlen(device->escape_string));
if (size != (ssize_t)strlen(device->escape_string))
return B_IO_ERROR;
snooze(device->escape_silence);
device->data_mode = false;
return B_OK;
}
static status_t
switch_to_data_mode(dialup_device* device)
{
if (device->state != UP)
return B_OK;
// TODO: check if it's needed, as these days any
// escaped AT commands switch back to data mode automatically
// after their completion...
status_t status = send_command(device, "ATO");
if (status == B_OK);
device->data_mode = true;
return status;
}
static status_t
hangup_device(dialup_device* device)
{
if (device->state != UP)
return B_ERROR;
// TODO: turn device's DTR down instead. Or do that too after sending command
char reply[8];
if (send_command(device, device->hangup_string) != B_OK
|| read_command_reply(device, device->hangup_string,
reply, sizeof(reply)) != B_OK
|| strcmp(reply, "OK"))
return B_ERROR;
device->flags &= ~IFF_LINK;
}
// #pragma mark -
@@ -81,6 +199,7 @@ dialup_init(const char* name, net_device** _device)
device->header_length = 8; // HDLC_HEADER_LENGTH;
device->fd = -1;
device->state = DOWN;
device->data_mode = false;
// default AT strings
strncpy(device->init_string, "ATZ", sizeof(device->init_string));
@@ -115,6 +234,8 @@ dialup_up(net_device* _device)
if (device->fd < 0)
return errno;
device->media = IFM_ACTIVE;
// init port
if (ioctl(device->fd, TCGETA, &device->line_config,
sizeof(device->line_config)) < 0)
@@ -136,11 +257,44 @@ dialup_up(net_device* _device)
// TODO: init modem & start dialing phase
device->state = DIALING;
char reply[32];
// Send modem init string
if (send_command(device, device->init_string) != B_OK
|| read_command_reply(device, device->init_string,
reply, sizeof(reply)) != B_OK
|| strcmp(reply, "OK")) {
errno = B_IO_ERROR;
goto err;
}
// Send dialing string
if (send_command(device, device->dialing_string) != B_OK
|| read_command_reply(device, device->dialing_string,
reply, sizeof(reply)) != B_OK
|| strncmp(reply, "CONNECT", 7)) {
errno = B_IO_ERROR;
goto err;
}
device->data_mode = true;
device->media |= IFM_FULL_DUPLEX
device->flags |= IFF_LINK;
device->link_quality = 1000;
if (strlen(reply) > 7) {
device->link_speed = atoi(&reply[8]);
else
device->link_speed = 19200; // check default baudrate
return B_OK;
err:
close(device->fd);
device->fd = -1;
device->media = 0;
return errno;
}
@@ -150,18 +304,9 @@ dialup_down(net_device* _device)
{
dialup_device* device = (dialup_device*)_device;
// TODO: hangup if needed
if (device->flags & IFF_LINK) {
snooze(device->escape_silence);
if (write(device->fd, device->escape_string,
strlen(device->escape_string)) > 0) {
snooze(device->escape_silence);
// TODO: send hangup string and check for OK ack
write(device->fd, device->hangup_string,
strlen(device->hangup_string));
}
if (device->flags & IFF_LINK &&
hangup_device(device) == B_OK)
device->flags &= ~IFF_LINK;
}
close(device->fd);
device->fd = -1;
+4 -4
View File
@@ -74,7 +74,7 @@ compat_close(void *cookie)
if_printf(ifp, "compat_close()\n");
atomic_or(&ifp->flags, DEVICE_CLOSED);
atomic_or(&ifp->flags, DEVICE_CLOSED);
wlan_close(cookie);
@@ -265,11 +265,11 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length)
if ((mediareq.ifm_status & IFM_ACTIVE) != 0)
state.media |= IFM_ACTIVE;
if ((mediareq.ifm_active & IFM_10_T) != 0)
state.speed = 10000;
state.speed = 10000000;
else if ((mediareq.ifm_active & IFM_100_TX) != 0)
state.speed = 100000;
state.speed = 100000000;
else
state.speed = 1000000;
state.speed = 1000000000;
state.quality = 1000;
return user_memcpy(arg, &state, sizeof(ether_link_state_t));