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:
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user