Bringing usb_davicom to life: part 1 of 3:
* Unfortunately I have to rollback r42712 completely because it was "the attempt in the wrong direction" and the working version was already implemented on top of previous revision. Just fixed version and code style refactored one are coming soon. Please be patient. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42747 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -33,11 +33,8 @@
|
|||||||
#define NSR 0x01 // Network status
|
#define NSR 0x01 // Network status
|
||||||
#define RCR 0x05 // RX Control
|
#define RCR 0x05 // RX Control
|
||||||
#define PAR 0x10 // 6 bits - Physical address (MAC)
|
#define PAR 0x10 // 6 bits - Physical address (MAC)
|
||||||
#define GPCR 0x1E // GPIO pins direction
|
#define GPCR 0x1E // General purpose control
|
||||||
#define GPR 0x1F // GPIO pins data
|
#define GPR 0x1F // General purpose
|
||||||
#define VID 0x28 // Vendor ID (16bit)
|
|
||||||
#define PID 0x2A // Product ID (16bit)
|
|
||||||
#define CHIPR 0x2C // Chip revision
|
|
||||||
|
|
||||||
#define NCR_EXT_PHY 0x80 // External PHY
|
#define NCR_EXT_PHY 0x80 // External PHY
|
||||||
#define NCR_FDX 0x08 // Full duplex
|
#define NCR_FDX 0x08 // Full duplex
|
||||||
@@ -63,7 +60,7 @@
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DavicomDevice::_ReadRegister(uint8 reg, size_t size, void* buffer)
|
DavicomDevice::_ReadRegister(uint8 reg, size_t size, uint8* buffer)
|
||||||
{
|
{
|
||||||
if (size > 255) return B_BAD_VALUE;
|
if (size > 255) return B_BAD_VALUE;
|
||||||
size_t actualLength;
|
size_t actualLength;
|
||||||
@@ -187,6 +184,14 @@ DavicomDevice::Open(uint32 flags)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup state notifications
|
||||||
|
result = gUSBModule->queue_interrupt(fNotifyEndpoint, fNotifyBuffer,
|
||||||
|
kNotifyBufferSize, _NotifyCallback, this);
|
||||||
|
if(result != B_OK) {
|
||||||
|
TRACE_ALWAYS("Error of requesting notify interrupt:%#010x\n", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK;
|
fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK;
|
||||||
fOpen = true;
|
fOpen = true;
|
||||||
return result;
|
return result;
|
||||||
@@ -357,11 +362,9 @@ DavicomDevice::Control(uint32 op, void *buffer, size_t length)
|
|||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case ETHER_INIT:
|
case ETHER_INIT:
|
||||||
TRACE_ALWAYS("ETHER_INIT\n");
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
case ETHER_GETADDR:
|
case ETHER_GETADDR:
|
||||||
TRACE_ALWAYS("ETHER_GETADDR\n");
|
|
||||||
memcpy(buffer, &fMACAddress, sizeof(fMACAddress));
|
memcpy(buffer, &fMACAddress, sizeof(fMACAddress));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
@@ -392,7 +395,6 @@ DavicomDevice::Control(uint32 op, void *buffer, size_t length)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
case ETHER_GET_LINK_STATE:
|
case ETHER_GET_LINK_STATE:
|
||||||
TRACE_ALWAYS("ETHER_GET_LINK_STATE\n");
|
|
||||||
return GetLinkState((ether_link_state *)buffer);
|
return GetLinkState((ether_link_state *)buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -431,10 +433,10 @@ DavicomDevice::Removed()
|
|||||||
status_t
|
status_t
|
||||||
DavicomDevice::SetupDevice(bool deviceReplugged)
|
DavicomDevice::SetupDevice(bool deviceReplugged)
|
||||||
{
|
{
|
||||||
/* First of all, we need to know the MAC address */
|
|
||||||
ether_address address;
|
ether_address address;
|
||||||
status_t result = ReadMACAddress(&address);
|
status_t result = ReadMACAddress(&address);
|
||||||
if(result != B_OK) {
|
if(result != B_OK) {
|
||||||
|
TRACE_ALWAYS("Error reading MAC address:%#010x\n", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,45 +445,18 @@ DavicomDevice::SetupDevice(bool deviceReplugged)
|
|||||||
address.ebyte[3], address.ebyte[4], address.ebyte[5]);
|
address.ebyte[3], address.ebyte[4], address.ebyte[5]);
|
||||||
|
|
||||||
if(deviceReplugged) {
|
if(deviceReplugged) {
|
||||||
// this might be the same device that was replugged - read the MAC
|
// this might be the same device that was replugged - read the MAC address
|
||||||
// address (which should be at the same index) to make sure
|
// (which should be at the same index) to make sure
|
||||||
if(memcmp(&address, &fMACAddress, sizeof(address)) != 0) {
|
if(memcmp(&address, &fMACAddress, sizeof(address)) != 0) {
|
||||||
TRACE_ALWAYS("Cannot replace device with MAC address:"
|
TRACE_ALWAYS("Cannot replace device with MAC address:"
|
||||||
"%02x:%02x:%02x:%02x:%02x:%02x\n",
|
"%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||||
fMACAddress.ebyte[0], fMACAddress.ebyte[1],
|
fMACAddress.ebyte[0], fMACAddress.ebyte[1], fMACAddress.ebyte[2],
|
||||||
fMACAddress.ebyte[2], fMACAddress.ebyte[3],
|
fMACAddress.ebyte[3], fMACAddress.ebyte[4], fMACAddress.ebyte[5]);
|
||||||
fMACAddress.ebyte[4], fMACAddress.ebyte[5]);
|
|
||||||
return B_BAD_VALUE; // is not the same
|
return B_BAD_VALUE; // is not the same
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
fMACAddress = address;
|
fMACAddress = address;
|
||||||
|
|
||||||
|
|
||||||
/* Read the product ID, vendor ID, and chip revision (not used so far, but
|
|
||||||
I feel the quirks coming in sooner or later !) */
|
|
||||||
|
|
||||||
uint16 vidpid[3];
|
|
||||||
vidpid[2] = 0; // We overwrite only the fist byte of this one.
|
|
||||||
|
|
||||||
result = _ReadRegister(VID, 5, vidpid);
|
|
||||||
if (result != B_OK)
|
|
||||||
TRACE_ALWAYS("Error reading CHIPR: %#010x.\n", result);
|
|
||||||
else
|
|
||||||
TRACE_ALWAYS("Chip %#04x:%#04x revision %d\n", vidpid[0], vidpid[1],
|
|
||||||
vidpid[2]);
|
|
||||||
|
|
||||||
// setup state notifications (we need this to get linkup/linkdown events)
|
|
||||||
result = gUSBModule->queue_interrupt(fNotifyEndpoint, fNotifyBuffer,
|
|
||||||
kNotifyBufferSize, _NotifyCallback, this);
|
|
||||||
if(result != B_OK) {
|
|
||||||
TRACE_ALWAYS("Error of requesting notify interrupt:%#010x\n", result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO enable "wakeup" at the device level or we'll never get anything !
|
|
||||||
// TODO check if link was already up before enabling interrupts. If so, we
|
|
||||||
// need to notify the network stack right now.
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,41 +532,34 @@ DavicomDevice::_SetupEndpoints()
|
|||||||
int writeEndpoint = -1;
|
int writeEndpoint = -1;
|
||||||
|
|
||||||
for(size_t ep = 0; ep < interface->endpoint_count; ep++) {
|
for(size_t ep = 0; ep < interface->endpoint_count; ep++) {
|
||||||
usb_endpoint_descriptor *epd = interface->endpoint[ep].descr;
|
usb_endpoint_descriptor *epd = interface->endpoint[ep].descr;
|
||||||
|
if((epd->attributes & USB_ENDPOINT_ATTR_MASK) == USB_ENDPOINT_ATTR_INTERRUPT) {
|
||||||
|
notifyEndpoint = ep;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Is it an interrupt enpoint ?
|
if((epd->attributes & USB_ENDPOINT_ATTR_MASK) != USB_ENDPOINT_ATTR_BULK) {
|
||||||
if((epd->attributes & USB_ENDPOINT_ATTR_MASK)
|
TRACE_ALWAYS("Error: USB endpoint type %#04x is unknown.\n", epd->attributes);
|
||||||
== USB_ENDPOINT_ATTR_INTERRUPT) {
|
continue;
|
||||||
notifyEndpoint = ep;
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is it a bulk one ?
|
if((epd->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
|
||||||
if((epd->attributes & USB_ENDPOINT_ATTR_MASK) != USB_ENDPOINT_ATTR_BULK) {
|
== USB_ENDPOINT_ADDR_DIR_IN) {
|
||||||
TRACE_ALWAYS("Error: USB endpoint type %#04x is unknown.\n",
|
readEndpoint = ep;
|
||||||
epd->attributes);
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If so, which direction ?
|
if((epd->endpoint_address & USB_ENDPOINT_ADDR_DIR_OUT)
|
||||||
if((epd->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
|
== USB_ENDPOINT_ADDR_DIR_OUT) {
|
||||||
== USB_ENDPOINT_ADDR_DIR_IN) {
|
writeEndpoint = ep;
|
||||||
readEndpoint = ep;
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if((epd->endpoint_address & USB_ENDPOINT_ADDR_DIR_OUT)
|
|
||||||
== USB_ENDPOINT_ADDR_DIR_OUT) {
|
|
||||||
writeEndpoint = ep;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did we find all the needed endpoints ?
|
|
||||||
if (notifyEndpoint == -1 || readEndpoint == -1 || writeEndpoint == -1) {
|
if (notifyEndpoint == -1 || readEndpoint == -1 || writeEndpoint == -1) {
|
||||||
TRACE_ALWAYS("Error: not all USB endpoints were found: "
|
TRACE_ALWAYS("Error: not all USB endpoints were found: "
|
||||||
"notify:%d; read:%d; write:%d\n", notifyEndpoint, readEndpoint,
|
"notify:%d; read:%d; write:%d\n",
|
||||||
writeEndpoint);
|
notifyEndpoint, readEndpoint, writeEndpoint);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,8 +576,7 @@ DavicomDevice::_SetupEndpoints()
|
|||||||
status_t
|
status_t
|
||||||
DavicomDevice::ReadMACAddress(ether_address_t *address)
|
DavicomDevice::ReadMACAddress(ether_address_t *address)
|
||||||
{
|
{
|
||||||
status_t result = _ReadRegister(PAR, sizeof(ether_address),
|
status_t result = _ReadRegister(PAR, sizeof(ether_address), (uint8*)address);
|
||||||
(uint8*)address);
|
|
||||||
if(result != B_OK) {
|
if(result != B_OK) {
|
||||||
TRACE_ALWAYS("Error of reading MAC address:%#010x\n", result);
|
TRACE_ALWAYS("Error of reading MAC address:%#010x\n", result);
|
||||||
return result;
|
return result;
|
||||||
@@ -720,6 +687,7 @@ DavicomDevice::_NotifyCallback(void *cookie, int32 status, void *data,
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse data in overriden class
|
||||||
device->OnNotify(actualLength);
|
device->OnNotify(actualLength);
|
||||||
|
|
||||||
// schedule next notification buffer
|
// schedule next notification buffer
|
||||||
@@ -733,10 +701,9 @@ status_t
|
|||||||
DavicomDevice::StartDevice()
|
DavicomDevice::StartDevice()
|
||||||
{
|
{
|
||||||
uint8 registerValue = 0;
|
uint8 registerValue = 0;
|
||||||
status_t result;
|
|
||||||
|
|
||||||
/* disable loopback */
|
/* disable loopback */
|
||||||
result = _ReadRegister(NCR, 1, ®isterValue);
|
status_t result = _ReadRegister(NCR, 1, ®isterValue);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE_ALWAYS("Error reading NCR: %#010x.\n", result);
|
TRACE_ALWAYS("Error reading NCR: %#010x.\n", result);
|
||||||
return result;
|
return result;
|
||||||
@@ -769,7 +736,7 @@ DavicomDevice::StartDevice()
|
|||||||
TRACE_ALWAYS("Error reading GPCR: %#010x.\n", result);
|
TRACE_ALWAYS("Error reading GPCR: %#010x.\n", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
registerValue |= GPCR_GEP_CNTL0;
|
registerValue &= GPCR_GEP_CNTL0;
|
||||||
result = _Write1Register(GPCR, registerValue);
|
result = _Write1Register(GPCR, registerValue);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE_ALWAYS("Error writing %#02X to GPCR: %#010x.\n", registerValue, result);
|
TRACE_ALWAYS("Error writing %#02X to GPCR: %#010x.\n", registerValue, result);
|
||||||
@@ -820,7 +787,7 @@ DavicomDevice::OnNotify(uint32 actualLength)
|
|||||||
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");
|
(fNotifyBuffer[0] & NSR_SPEED) ? "10" : "100");
|
||||||
} else
|
} else
|
||||||
TRACE("Link is now down.\n");
|
TRACE("Link is now down");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rxOverflow)
|
if (rxOverflow)
|
||||||
@@ -859,7 +826,7 @@ DavicomDevice::GetLinkState(ether_link_state *linkState)
|
|||||||
linkState->media |= IFM_ACTIVE;
|
linkState->media |= IFM_ACTIVE;
|
||||||
result = _ReadRegister(NCR, 1, ®isterValue);
|
result = _ReadRegister(NCR, 1, ®isterValue);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE_ALWAYS("Error reading NCR register: %s\n",strerror(result));
|
TRACE_ALWAYS("Error reading NCR register! %x\n",result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,7 @@
|
|||||||
|
|
||||||
class DavicomDevice {
|
class DavicomDevice {
|
||||||
public:
|
public:
|
||||||
DavicomDevice(usb_device device,
|
DavicomDevice(usb_device device, const char *description);
|
||||||
const char *description);
|
|
||||||
virtual ~DavicomDevice();
|
virtual ~DavicomDevice();
|
||||||
|
|
||||||
status_t InitCheck() { return fStatus; };
|
status_t InitCheck() { return fStatus; };
|
||||||
@@ -55,10 +54,8 @@ static void _NotifyCallback(void *cookie, int32 status,
|
|||||||
|
|
||||||
status_t _SetupEndpoints();
|
status_t _SetupEndpoints();
|
||||||
|
|
||||||
status_t _ReadRegister(uint8 reg, size_t size,
|
status_t _ReadRegister(uint8 reg, size_t size, uint8* buffer);
|
||||||
void* buffer);
|
status_t _WriteRegister(uint8 reg, size_t size, uint8* buffer);
|
||||||
status_t _WriteRegister(uint8 reg, size_t size,
|
|
||||||
uint8* buffer);
|
|
||||||
status_t _Write1Register(uint8 reg, uint8 buffer);
|
status_t _Write1Register(uint8 reg, uint8 buffer);
|
||||||
|
|
||||||
static const int kFrameSize = 1518;
|
static const int kFrameSize = 1518;
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ char *gDeviceNames[MAX_DEVICES + 1];
|
|||||||
usb_module_info *gUSBModule = NULL;
|
usb_module_info *gUSBModule = NULL;
|
||||||
|
|
||||||
usb_support_descriptor gSupportedDevices[] = {
|
usb_support_descriptor gSupportedDevices[] = {
|
||||||
{ 0, 0, 0, 0x0fe6, 0x8101}, // "Supereal SR9600"
|
{ 0, 0, 0, 0x0fe6, 0x8101}, // "Sunrising JP108"
|
||||||
{ 0, 0, 0, 0x07aa, 0x9601}, // "Corega FEther USB-TXC"
|
{ 0, 0, 0, 0x07aa, 0x9601}, // "Corega FEther USB-TXC"
|
||||||
{ 0, 0, 0, 0x0a46, 0x9601}, // "Davicom DM9601"
|
{ 0, 0, 0, 0x0a46, 0x9601}, // "Davicom USB-100"
|
||||||
{ 0, 0, 0, 0x0a46, 0x6688}, // "ZT6688 USB NIC"
|
{ 0, 0, 0, 0x0a46, 0x6688}, // "ZT6688 USB NIC"
|
||||||
{ 0, 0, 0, 0x0a46, 0x0268}, // "ShanTou ST268 USB NIC"
|
{ 0, 0, 0, 0x0a46, 0x0268}, // "ShanTou ST268 USB NIC"
|
||||||
{ 0, 0, 0, 0x0a46, 0x8515}, // "ADMtek ADM8515 USB NIC"
|
{ 0, 0, 0, 0x0a46, 0x8515}, // "ADMtek ADM8515 USB NIC"
|
||||||
@@ -67,22 +67,14 @@ create_davicom_device(usb_device device)
|
|||||||
#define IDS(__vendor, __product) (((__vendor) << 16) | (__product))
|
#define IDS(__vendor, __product) (((__vendor) << 16) | (__product))
|
||||||
|
|
||||||
switch(IDS(deviceDescriptor->vendor_id, deviceDescriptor->product_id)) {
|
switch(IDS(deviceDescriptor->vendor_id, deviceDescriptor->product_id)) {
|
||||||
case IDS(0x0fe6, 0x8101):
|
case IDS(0x0fe6, 0x8101): return new DavicomDevice(device, "Sunrising JP108");
|
||||||
return new DavicomDevice(device, "Sunrising JP108");
|
case IDS(0x07aa, 0x9601): return new DavicomDevice(device, "Corega FEther USB-TXC");
|
||||||
case IDS(0x07aa, 0x9601):
|
case IDS(0x0a46, 0x9601): return new DavicomDevice(device, "Davicom USB-100");
|
||||||
return new DavicomDevice(device, "Corega FEther USB-TXC");
|
case IDS(0x0a46, 0x6688): return new DavicomDevice(device, "ZT6688 USB NIC");
|
||||||
case IDS(0x0a46, 0x9601):
|
case IDS(0x0a46, 0x0268): return new DavicomDevice(device, "ShanTou ST268 USB NIC");
|
||||||
return new DavicomDevice(device, "Davicom USB-100");
|
case IDS(0x0a46, 0x8515): return new DavicomDevice(device, "ADMtek ADM8515 USB NIC");
|
||||||
case IDS(0x0a46, 0x6688):
|
case IDS(0x0a47, 0x9601): return new DavicomDevice(device, "Hirose USB-100");
|
||||||
return new DavicomDevice(device, "ZT6688 USB NIC");
|
case IDS(0x0a46, 0x9000): return new DavicomDevice(device, "DM9000E");
|
||||||
case IDS(0x0a46, 0x0268):
|
|
||||||
return new DavicomDevice(device, "ShanTou ST268 USB NIC");
|
|
||||||
case IDS(0x0a46, 0x8515):
|
|
||||||
return new DavicomDevice(device, "ADMtek ADM8515 USB NIC");
|
|
||||||
case IDS(0x0a47, 0x9601):
|
|
||||||
return new DavicomDevice(device, "Hirose USB-100");
|
|
||||||
case IDS(0x0a46, 0x9000):
|
|
||||||
return new DavicomDevice(device, "DM9000E");
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user