[haiku-commits] r34953 - haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom

  • From: pulkomandy@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 8 Jan 2010 19:39:06 +0100 (CET)

Author: pulkomandy
Date: 2010-01-08 19:39:05 +0100 (Fri, 08 Jan 2010)
New Revision: 34953
Changeset: http://dev.haiku-os.org/changeset/34953/haiku

Added:
   haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/DavicomDevice.cpp
   haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/DavicomDevice.h
Removed:
   haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/ASIXDevice.cpp
   haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/ASIXDevice.h
Modified:
   
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/usb_davicom.settings
Log:
These files were missing from a previous commit.


Copied: 
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/DavicomDevice.cpp 
(from rev 34946, 
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/ASIXDevice.cpp)
===================================================================
--- 
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/DavicomDevice.cpp    
                            (rev 0)
+++ 
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/DavicomDevice.cpp    
    2010-01-08 18:39:05 UTC (rev 34953)
@@ -0,0 +1,819 @@
+/*
+ *     Davicom DM9601 USB 1.1 Ethernet Driver.
+ *     Copyright (c) 2009 Adrien Destugues <pulkomandy@xxxxxxxxx>
+ *     Distributed under the terms of the MIT license.
+ *
+ *     Heavily based on code of 
+ *     ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver.
+ *     Copyright (c) 2008 S.Zharski <imker@xxxxxx>
+ *     Distributed under the terms of the MIT license.
+ *     
+ *     Driver for USB Ethernet Control Model devices
+ *     Copyright (C) 2008 Michael Lotz <mmlr@xxxxxxxx>
+ *     Distributed under the terms of the MIT license.
+ *
+ */
+
+#include "Driver.h"
+#include "Settings.h"
+#include "DavicomDevice.h"
+
+
+// Vendor commands
+#define READ_REGISTER 0
+#define WRITE_REGISTER 1
+#define WRITE1_REGISTER 3
+#define READ_MEMORY 2
+#define WRITE_MEMORY 5
+#define WRITE1_MEMORY 7
+
+
+// Registers
+#define PAR 0x10       // 6 bits - Physical address (MAC)
+
+//TODO: multicast support
+//TODO: set media state support
+
+
+// frame header used during transfer data 
+struct TRXHeader {
+       uint16  fLength;
+       uint16  fInvertedLength;
+       
+       TRXHeader(uint16 length = 0){ SetLength(length); }
+       bool    IsValid() { return (fLength ^ fInvertedLength) == 0xffff; }
+       uint16  Length()  { return fLength; }
+       //TODO: low-endian convertion?
+       void    SetLength(uint16 length) {
+                               fLength = length;
+                               fInvertedLength = ~fLength;
+                       }
+};
+
+
+status_t
+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, 
+               USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN,
+               READ_REGISTER, 0, reg, size, buffer, &actualLength);
+       if (size != actualLength) TRACE_ALWAYS("Size mismatch reading register 
! asked %d got %d",size,actualLength);
+       return B_OK;
+}
+
+
+DavicomDevice::DavicomDevice(usb_device device, const char *description)
+       :       fStatus(B_ERROR),
+               fOpen(false),
+               fRemoved(false),
+               fInsideNotify(0),
+               fDevice(device),
+               fDescription(description), 
+               fNonBlocking(false),            
+               fFrameSize(0),
+               fNotifyEndpoint(0), 
+               fReadEndpoint(0), 
+               fWriteEndpoint(0),
+               fNotifyReadSem(-1), 
+               fNotifyWriteSem(-1), 
+               fNotifyBuffer(NULL),
+               fNotifyBufferLength(0), 
+               fLinkStateChangeSem(-1), 
+               fHasConnection(false),
+               fUseTRXHeader(false), 
+               fReadNodeIDRequest(kInvalidRequest),
+               fReadRXControlRequest(kInvalidRequest),
+               fWriteRXControlRequest(kInvalidRequest),
+               fPromiscuousBits(0)
+{ 
+       const usb_device_descriptor
+                       *deviceDescriptor = 
gUSBModule->get_device_descriptor(device);
+
+       if (deviceDescriptor == NULL) {
+               TRACE_ALWAYS("Error of getting USB device descriptor.\n");
+               return;
+       }
+
+       fIPG[0] = 0x15;
+       fIPG[1] = 0x0c;
+       fIPG[2] = 0x12;
+
+       fVendorID = deviceDescriptor->vendor_id;
+       fProductID = deviceDescriptor->product_id;
+
+       fNotifyReadSem = create_sem(0, DRIVER_NAME"_notify_read");
+       if (fNotifyReadSem < B_OK) {
+               TRACE_ALWAYS("Error of creating read notify semaphore:%#010x\n",
+                                                                               
                                        fNotifyReadSem);
+               return;
+       }
+
+       fNotifyWriteSem = create_sem(0, DRIVER_NAME"_notify_write");
+       if (fNotifyWriteSem < B_OK) {
+               TRACE_ALWAYS("Error of creating write notify 
semaphore:%#010x\n", 
+                                                                               
                                        fNotifyWriteSem);
+               return;
+       }
+
+       if (_SetupEndpoints() != B_OK) {
+               return;
+       }
+       
+       // TODO : others inits here ?
+
+       fStatus = B_OK;
+}
+
+
+DavicomDevice::~DavicomDevice()
+{
+       if (fNotifyReadSem >= B_OK)
+               delete_sem(fNotifyReadSem);
+       if (fNotifyWriteSem >= B_OK)
+               delete_sem(fNotifyWriteSem);
+       
+       if (!fRemoved) //???
+               gUSBModule->cancel_queued_transfers(fNotifyEndpoint);
+
+       if(fNotifyBuffer)
+               free(fNotifyBuffer);
+}
+
+
+status_t
+DavicomDevice::Open(uint32 flags)
+{
+       if (fOpen)
+               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,
+                                                               
fNotifyBufferLength, _NotifyCallback, this);
+       if(result != B_OK) {
+               TRACE_ALWAYS("Error of requesting notify interrupt:%#010x\n", 
result);
+               return result;
+       }
+
+       fNonBlocking = (flags & O_NONBLOCK) == O_NONBLOCK;
+       fOpen = true;
+       return result; 
+}
+
+
+status_t
+DavicomDevice::Close()
+{
+       if (fRemoved) {
+               fOpen = false;
+               return B_OK;
+       }
+
+       // wait until possible notification handling finished...
+       while (atomic_add(&fInsideNotify, 0) != 0)
+               snooze(100);
+       gUSBModule->cancel_queued_transfers(fNotifyEndpoint);
+       gUSBModule->cancel_queued_transfers(fReadEndpoint);
+       gUSBModule->cancel_queued_transfers(fWriteEndpoint);
+
+       fOpen = false;
+       
+       return StopDevice();
+}
+
+
+status_t
+DavicomDevice::Free()
+{
+       return B_OK;
+}
+
+
+status_t
+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", 
+                                                                               
                                        numBytesToRead);
+               return B_ERROR;
+       }
+
+       TRACE_FLOW("Request %d bytes.\n", numBytesToRead);
+
+       TRXHeader header;
+       iovec rxData[] = {
+               { &header, sizeof(TRXHeader) },
+               { buffer,  numBytesToRead }
+       };
+
+       size_t startIndex = fUseTRXHeader ? 0 : 1 ;
+       size_t chunkCount = fUseTRXHeader ? 2 : 1 ;
+
+       status_t result = gUSBModule->queue_bulk_v(fReadEndpoint, 
+                                               &rxData[startIndex], 
chunkCount, _ReadCallback, this);
+       if (result != B_OK) {
+               TRACE_ALWAYS("Error of queue_bulk_v request:%#010x\n", result);
+               return result;
+       }
+
+       uint32 flags = B_CAN_INTERRUPT | (fNonBlocking ? B_TIMEOUT : 0);
+       result = acquire_sem_etc(fNotifyReadSem, 1, flags, 0);
+       if (result < B_OK) {
+               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);
+               result = gUSBModule->clear_feature(fReadEndpoint,
+                       USB_FEATURE_ENDPOINT_HALT);
+               if (result != B_OK) {
+                       TRACE_ALWAYS("Error during clearing of HALT 
state:%#010x.\n", result);
+                       return result;
+               }
+       }
+    
+       if(fUseTRXHeader) {
+               if(fActualLengthRead < sizeof(TRXHeader)) {
+                       TRACE_ALWAYS("Error: no place for TRXHeader:only %d of 
%d bytes.\n", 
+                                                                               
fActualLengthRead, sizeof(TRXHeader));
+                       return B_ERROR; //TODO: ???
+               }
+               
+               if(!header.IsValid()) {
+                       TRACE_ALWAYS("Error:TRX Header is invalid: len:%#04x; 
ilen:%#04x\n", 
+                                                       header.fLength, 
header.fInvertedLength);
+                       return B_ERROR; //TODO: ???
+               }
+               
+               *numBytes = header.Length();
+
+               if(fActualLengthRead - sizeof(TRXHeader) > header.Length()) {
+                       TRACE_ALWAYS("MISMATCH of the frame length: hdr %d; 
received:%d\n",
+                                               header.Length(), 
fActualLengthRead - sizeof(TRXHeader));
+               }
+
+       } else {
+
+               *numBytes = fActualLengthRead;
+       }
+
+       TRACE_FLOW("Read %d bytes.\n", *numBytes);
+       return B_OK;
+}
+
+
+status_t
+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", 
+                                                                               
                                numBytesToWrite);
+               return B_ERROR;
+       }
+
+       TRACE_FLOW("Write %d bytes.\n", numBytesToWrite);
+       
+       TRXHeader header(numBytesToWrite);
+       iovec txData[] = {
+               { &header, sizeof(TRXHeader) },
+               { (uint8*)buffer, numBytesToWrite }
+       };
+       
+       size_t startIndex = fUseTRXHeader ? 0 : 1 ;
+       size_t chunkCount = fUseTRXHeader ? 2 : 1 ;
+       
+       status_t result = gUSBModule->queue_bulk_v(fWriteEndpoint, 
+                                               &txData[startIndex], 
chunkCount, _WriteCallback, this);
+       if (result != B_OK) {
+               TRACE_ALWAYS("Error of queue_bulk_v request:%#010x\n", result);
+               return result;
+       }
+
+       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;
+       }
+
+       if (fStatusWrite != B_OK && fStatusWrite != B_CANCELED && !fRemoved) {
+               TRACE_ALWAYS("Device status error:%#010x\n", fStatusWrite);
+               result = gUSBModule->clear_feature(fWriteEndpoint,
+                       USB_FEATURE_ENDPOINT_HALT);
+               if (result != B_OK) {
+                       TRACE_ALWAYS("Error during clearing of HALT 
state:%#010x\n", result);
+                       return result;
+               }
+       }
+
+       if(fUseTRXHeader) {
+               *numBytes = fActualLengthWrite - sizeof(TRXHeader);
+       } else {
+               *numBytes = fActualLengthWrite;
+       }
+
+       TRACE_FLOW("Written %d bytes.\n", *numBytes);
+       return B_OK;
+}
+
+
+status_t
+DavicomDevice::Control(uint32 op, void *buffer, size_t length)
+{
+       switch (op) {
+               case ETHER_INIT:
+                       return B_OK;
+
+               case ETHER_GETADDR:
+                       memcpy(buffer, &fMACAddress, sizeof(fMACAddress));
+                       return B_OK;
+               
+               case ETHER_GETFRAMESIZE:
+                       *(uint32 *)buffer = fFrameSize;
+                       return B_OK;
+
+               case ETHER_NONBLOCK: 
+                       TRACE("ETHER_NONBLOCK\n");
+                       fNonBlocking = *((uint8*)buffer);
+                       return B_OK;
+                       
+               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;
+                       return B_OK;
+
+               case ETHER_GET_LINK_STATE:
+                       return GetLinkState((ether_link_state *)buffer);
+#endif
+
+               default:
+                       TRACE_ALWAYS("Unhandled IOCTL catched: %#010x\n", op);
+       }
+
+       return B_DEV_INVALID_IOCTL;
+}
+
+
+void
+DavicomDevice::Removed()
+{
+       fRemoved = true;
+       fHasConnection = false;
+
+       // the notify hook is different from the read and write hooks as it does
+       // itself schedule traffic (while the other hooks only release a 
semaphore
+       // to notify another thread which in turn safly checks for the removed
+       // case) - so we must ensure that we are not inside the notify hook 
anymore
+       // before returning, as we would otherwise violate the promise not to 
use
+       // any of the pipes after returning from the removed hook
+       while (atomic_add(&fInsideNotify, 0) != 0)
+               snooze(100);
+
+       gUSBModule->cancel_queued_transfers(fNotifyEndpoint);
+       gUSBModule->cancel_queued_transfers(fReadEndpoint);
+       gUSBModule->cancel_queued_transfers(fWriteEndpoint);
+
+       if (fLinkStateChangeSem >= B_OK)
+               release_sem_etc(fLinkStateChangeSem, 1, B_DO_NOT_RESCHEDULE);
+}
+
+
+status_t
+DavicomDevice::SetupDevice(bool deviceReplugged)
+{
+       ether_address address;
+       status_t result = ReadMACAddress(&address);
+       if(result != B_OK) {
+               TRACE_ALWAYS("Error of reading MAC address:%#010x\n", result);
+               return result;
+       }
+
+       TRACE("MAC address is:%02x:%02x:%02x:%02x:%02x:%02x\n",
+                               address.ebyte[0], address.ebyte[1], 
address.ebyte[2], 
+                               address.ebyte[3], address.ebyte[4], 
address.ebyte[5]);
+
+       if(deviceReplugged) {
+               // this might be the same device that was replugged - read the 
MAC address
+               // (which should be at the same index) to make sure
+               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[3], fMACAddress.ebyte[4], 
fMACAddress.ebyte[5]);
+                       return B_BAD_VALUE; // is not the same
+               }
+       } else 
+               fMACAddress = address;
+       
+       return B_OK; 
+}
+
+
+status_t
+DavicomDevice::CompareAndReattach(usb_device device)
+{
+       const usb_device_descriptor *deviceDescriptor
+               = gUSBModule->get_device_descriptor(device);
+
+       if (deviceDescriptor == NULL) {
+               TRACE_ALWAYS("Error of getting USB device descriptor.\n");
+               return B_ERROR;
+       }
+
+       if (deviceDescriptor->vendor_id != fVendorID
+               && deviceDescriptor->product_id != fProductID) {
+               // this certainly isn't the same device
+               return B_BAD_VALUE;
+       }
+
+       // this is the same device that was replugged - clear the removed state,
+       // re-setup the endpoints and transfers and open the device if it was
+       // previously opened
+       fDevice = device;
+       fRemoved = false;
+       status_t result = _SetupEndpoints();
+       if (result != B_OK) {
+               fRemoved = true;
+               return result;
+       }
+
+       // we need to setup hardware on device replug
+       result = SetupDevice(true);
+       if (result != B_OK) {
+               return result;  
+       }
+
+       if (fOpen) {
+               fOpen = false;
+               result = Open(fNonBlocking ? O_NONBLOCK : 0);
+       }
+
+       return result;
+}
+
+
+status_t
+DavicomDevice::_SetupEndpoints()
+{
+       const usb_configuration_info *config
+               = gUSBModule->get_nth_configuration(fDevice, 0);
+
+       if (config == NULL) {
+               TRACE_ALWAYS("Error of getting USB device configuration.\n");
+               return B_ERROR;
+       }
+
+       if (config->interface_count <= 0) {
+               TRACE_ALWAYS("Error:no interfaces found in USB device 
configuration\n");
+               return B_ERROR;
+       }
+
+       usb_interface_info *interface = config->interface[0].active;
+       if (interface == 0) {
+               TRACE_ALWAYS("Error:invalid active interface in "
+                                                                               
                "USB device configuration\n");
+               return B_ERROR;
+       }
+       
+       int notifyEndpoint = -1;
+       int readEndpoint   = -1;
+       int writeEndpoint  = -1;
+
+       for(size_t ep = 0; ep < interface->endpoint_count; ep++) {
+         usb_endpoint_descriptor *epd = interface->endpoint[ep].descr;
+         if((epd->attributes & USB_ENDPOINT_ATTR_MASK) == 
USB_ENDPOINT_ATTR_INTERRUPT) {
+           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) 
+                                                                               
                        == USB_ENDPOINT_ADDR_DIR_IN) {
+           readEndpoint = ep;
+               continue;
+         }
+         
+         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",
+                                                                               
        notifyEndpoint, readEndpoint, writeEndpoint);
+               return B_ERROR;
+       }
+
+       gUSBModule->set_configuration(fDevice, config);
+
+       fNotifyEndpoint = interface->endpoint[notifyEndpoint].handle;
+       fReadEndpoint   = interface->endpoint[readEndpoint  ].handle;
+       fWriteEndpoint  = interface->endpoint[writeEndpoint ].handle;
+       
+       return B_OK;
+}
+
+
+status_t
+DavicomDevice::ReadMACAddress(ether_address_t *address)
+{
+       status_t result = _ReadRegister(PAR, sizeof(ether_address), 
(uint8*)address);
+       if(result != B_OK) {
+               TRACE_ALWAYS("Error of reading MAC address:%#010x\n", result);
+               return result;
+       }
+
+       return B_OK;
+}
+
+
+status_t
+DavicomDevice::ReadRXControlRegister(uint16 *rxcontrol)
+{
+       size_t actual_length = 0;
+       *rxcontrol = 0;
+       
+       status_t result = gUSBModule->send_request(fDevice, 
+                                       USB_REQTYPE_VENDOR | 
USB_REQTYPE_DEVICE_IN,
+                                       fReadRXControlRequest, 0, 0, 
+                                       sizeof(*rxcontrol), rxcontrol, 
&actual_length);
+
+       if(sizeof(*rxcontrol) != actual_length) {
+               TRACE_ALWAYS("Mismatch during reading RX control register."
+                                                                               
        "Read %d bytes instead of %d.\n", 
+                                                                               
        actual_length, sizeof(*rxcontrol));
+       }
+
+       return result; 
+}
+
+
+status_t
+DavicomDevice::WriteRXControlRegister(uint16 rxcontrol)
+{
+       status_t result = gUSBModule->send_request(fDevice, 
+                                                       USB_REQTYPE_VENDOR | 
USB_REQTYPE_DEVICE_OUT,
+                                                       fWriteRXControlRequest, 
rxcontrol, 0, 0, 0, 0);
+       return result;
+}
+
+
+status_t
+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; 
+}
+
+
+status_t
+DavicomDevice::SetPromiscuousMode(bool on)
+{
+       uint16 rxcontrol = 0;
+       
+       status_t result = ReadRXControlRegister(&rxcontrol);
+       if(result != B_OK) {
+               TRACE_ALWAYS("Error of reading RX Control:%#010x\n", result);
+               return result;
+       }
+
+       if(on) 
+               rxcontrol |= fPromiscuousBits;
+       else
+               rxcontrol &= ~fPromiscuousBits;
+
+       result = WriteRXControlRegister(rxcontrol);
+       
+       if(result != B_OK ) {
+               TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 
rxcontrol, result);
+       }
+       
+       TRACE_RET(result);
+       return result; 
+}
+
+
+status_t
+DavicomDevice::ModifyMulticastTable(bool add, uint8 address)
+{
+               //TODO: !!!
+       TRACE_ALWAYS("Call for (%d, %#02x) is not implemented\n", add, address);
+       return B_OK;
+}
+
+
+void
+DavicomDevice::_ReadCallback(void *cookie, int32 status, void *data,
+       uint32 actualLength)
+{
+       TRACE_FLOW("ReadCB: %d bytes; status:%#010x\n", actualLength, status);
+       DavicomDevice *device = (DavicomDevice *)cookie;
+       device->fActualLengthRead = actualLength;
+       device->fStatusRead = status;
+       release_sem_etc(device->fNotifyReadSem, 1, B_DO_NOT_RESCHEDULE);
+}
+
+
+void
+DavicomDevice::_WriteCallback(void *cookie, int32 status, void *data,
+       uint32 actualLength)
+{
+       TRACE_FLOW("WriteCB: %d bytes; status:%#010x\n", actualLength, status);
+       DavicomDevice *device = (DavicomDevice *)cookie;
+       device->fActualLengthWrite = actualLength;
+       device->fStatusWrite = status;
+       release_sem_etc(device->fNotifyWriteSem, 1, B_DO_NOT_RESCHEDULE);
+}
+
+
+void
+DavicomDevice::_NotifyCallback(void *cookie, int32 status, void *data,
+       uint32 actualLength)
+{
+       DavicomDevice *device = (DavicomDevice *)cookie;
+       atomic_add(&device->fInsideNotify, 1);
+       if (status == B_CANCELED || device->fRemoved) {
+               atomic_add(&device->fInsideNotify, -1);
+               return;
+       }
+
+       if (status != B_OK) {
+               TRACE_ALWAYS("Device status error:%#010x\n", status);
+               status_t result = 
gUSBModule->clear_feature(device->fNotifyEndpoint,
+                                                                               
                        USB_FEATURE_ENDPOINT_HALT);
+               if(result != B_OK)
+                       TRACE_ALWAYS("Error during clearing of HALT 
state:%#010x.\n", result);
+       }
+       
+       // parse data in overriden class
+       device->OnNotify(actualLength);
+
+       // schedule next notification buffer
+       gUSBModule->queue_interrupt(device->fNotifyEndpoint, 
device->fNotifyBuffer,
+               device->fNotifyBufferLength, _NotifyCallback, device);
+       atomic_add(&device->fInsideNotify, -1);
+}
+
+
+status_t
+DavicomDevice::StartDevice()
+{
+       size_t actualLength = 0;
+/*ASX
+       for(size_t i = 0; i < sizeof(fIPG)/sizeof(fIPG[0]); i++) {
+               
+               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;
+               }
+
+               if(actualLength != sizeof(fIPG[i])) {
+                       TRACE_ALWAYS("Mismatch of written IPG%d data. "
+                                       "%d bytes of %d written.\n", i, 
actualLength, sizeof(fIPG[i]));
+               }
+       }
+       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 B_ERROR;
+}
+
+
+status_t
+DavicomDevice::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; 
+       }
+               
+       AX88172Notify *notification     = (AX88172Notify *)fNotifyBuffer; 
+
+       if(notification->btA1 != 0xa1) {
+               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; 
+                       break;
+               case SecondaryPHY:
+                       phyIndex = 2;
+                       linkIsUp = (notification->btNN & LINK_STATE_PHY2) == 
LINK_STATE_PHY2; 
+                       break;
+               default:
+               case CurrentPHY:
+                       TRACE_ALWAYS("Error: PHY is not initialized.\n");
+                       return B_NO_INIT;
+       }
+
+       bool linkStateChange = linkIsUp != fHasConnection;
+       fHasConnection = linkIsUp;
+
+       if(linkStateChange) {
+               TRACE("Link state of PHY%d has been changed to '%s'\n", 
+                                                                       
phyIndex, fHasConnection ? "up" : "down");
+       }
+
+       if (linkStateChange && fLinkStateChangeSem >= B_OK)
+               release_sem_etc(fLinkStateChangeSem, 1, B_DO_NOT_RESCHEDULE);
+*/
+       return B_ERROR; // shoulb be B_OK when implemented :)
+}
+
+status_t
+DavicomDevice::GetLinkState(ether_link_state *linkState)
+{
+/*
+       uint16 miiANAR = 0;
+       uint16 miiANLPAR = 0;
+
+       status_t result = fMII.Read(MII_ANAR, &miiANAR);
+       if(result != B_OK) {
+               TRACE_ALWAYS("Error reading MII ANAR register:%#010x\n", 
result);
+               return result;
+       }
+
+       result = fMII.Read(MII_ANLPAR, &miiANLPAR);
+       if(result != B_OK) {
+               TRACE_ALWAYS("Error reading MII ANLPAR register:%#010x\n", 
result);
+               return result;
+       }
+
+       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) ? 
+                                                                               
        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->media & IFM_ACTIVE) 
? "active" : "inactive",
+                                               linkState->speed / 1000,
+                                               (linkState->media & 
IFM_FULL_DUPLEX) ? "full" : "half");
+*/
+       return B_ERROR; // B_OK
+}
+

Copied: 
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/DavicomDevice.h 
(from rev 34946, 
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/ASIXDevice.h)
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/DavicomDevice.h  
                        (rev 0)
+++ haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/DavicomDevice.h  
2010-01-08 18:39:05 UTC (rev 34953)
@@ -0,0 +1,113 @@
+/*
+ *     Davicom DM9601 USB 1.1 Ethernet Driver.
+ *     Copyright (c) 2009 Adrien Destugues <pulkomandy@xxxxxxxxx>
+ *     Distributed under the terms of the MIT license.
+ *
+ *     ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver.
+ *     Copyright (c) 2008 S.Zharski <imker@xxxxxx>
+ *     Distributed under the terms of the MIT license.
+ *     
+ *     Heavily based on code of the 
+ *     Driver for USB Ethernet Control Model devices
+ *     Copyright (C) 2008 Michael Lotz <mmlr@xxxxxxxx>
+ *     Distributed under the terms of the MIT license.
+ *
+ */
+
+#ifndef _USB_Davicom_DEVICE_H_
+#define _USB_Davicom_DEVICE_H_
+
+#include <net/if_media.h>
+
+#include "Driver.h"
+
+class DavicomDevice {
+public:
+                                                       
DavicomDevice(usb_device device, const char *description);
+               virtual                         ~DavicomDevice();
+
+               status_t                        InitCheck() { return fStatus; };
+
+               status_t                        Open(uint32 flags);
+               bool                            IsOpen() { return fOpen; };
+
+               status_t                        Close();
+               status_t                        Free();
+
+               status_t                        Read(uint8 *buffer, size_t 
*numBytes);
+               status_t                        Write(const uint8 *buffer, 
size_t *numBytes);
+               status_t                        Control(uint32 op, void 
*buffer, size_t length);
+
+               void                            Removed();
+               bool                            IsRemoved() { return fRemoved; 
};
+
+               status_t                        CompareAndReattach(usb_device 
device);
+virtual        status_t                        SetupDevice(bool 
deviceReplugged);
+               
+private:
+static void                            _ReadCallback(void *cookie, int32 
status,
+                                                               void *data, 
uint32 actualLength);
+static void                            _WriteCallback(void *cookie, int32 
status,
+                                                               void *data, 
uint32 actualLength);
+static void                            _NotifyCallback(void *cookie, int32 
status,
+                                                               void *data, 
uint32 actualLength);
+
+               status_t                        _SetupEndpoints();
+
+               status_t                                _ReadRegister(uint8 
reg, size_t size, uint8* buffer);
+
+protected:
+               /* overrides */
+virtual        status_t                        StartDevice() ;
+virtual        status_t                        StopDevice();
+virtual status_t                       OnNotify(uint32 actualLength) ;
+virtual        status_t                        GetLinkState(ether_link_state 
*state) ;
+virtual        status_t                        SetPromiscuousMode(bool bOn);
+virtual        status_t                        ModifyMulticastTable(bool add, 
uint8 address);
+               status_t                        ReadMACAddress(ether_address_t 
*address);
+               status_t                        ReadRXControlRegister(uint16 
*rxcontrol);
+               status_t                        WriteRXControlRegister(uint16 
rxcontrol);
+               
+               // state tracking
+               status_t                        fStatus;
+               bool                            fOpen;
+               bool                            fRemoved;
+               vint32                          fInsideNotify;
+               usb_device                      fDevice;
+               uint16                          fVendorID;
+               uint16                          fProductID;
+const  char *                          fDescription;
+               bool                            fNonBlocking;
+
+               // interface and device infos
+               uint16                          fFrameSize;
+
+               // pipes for notifications and data io
+               usb_pipe                        fNotifyEndpoint;
+               usb_pipe                        fReadEndpoint;
+               usb_pipe                        fWriteEndpoint;
+
+               // data stores for async usb transfers
+               uint32                          fActualLengthRead;
+               uint32                          fActualLengthWrite;
+               int32                           fStatusRead;
+               int32                           fStatusWrite;
+               sem_id                          fNotifyReadSem;
+               sem_id                          fNotifyWriteSem;
+
+               uint8 *                         fNotifyBuffer;
+               uint32                          fNotifyBufferLength;
+
+               // connection data
+               sem_id                          fLinkStateChangeSem;
+               ether_address_t         fMACAddress;
+               bool                            fHasConnection;
+               bool                            fUseTRXHeader;
+               uint8                           fIPG[3];
+               uint8                           fReadNodeIDRequest;
+               uint8                           fReadRXControlRequest;
+               uint8                           fWriteRXControlRequest;
+               uint16                          fPromiscuousBits;
+};
+
+#endif //_USB_Davicom_DEVICE_H_

Modified: 
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/usb_davicom.settings
===================================================================
--- 
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/usb_davicom.settings 
    2010-01-08 17:24:29 UTC (rev 34952)
+++ 
haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom/usb_davicom.settings 
    2010-01-08 18:39:05 UTC (rev 34953)
@@ -10,7 +10,7 @@
 trace on 
 
 ## logfile [full path to private log file] 
-## default path value: /var/log/usb_asix.log
+## default path value: /var/log/usb_davicom.log
 ## if disabled - all output goes to syslog
 
 logfile /var/log/usb_davicom.log


Other related posts:

  • » [haiku-commits] r34953 - haiku/trunk/src/add-ons/kernel/drivers/network/usb_davicom - pulkomandy