diff --git a/src/add-ons/kernel/drivers/network/usb_asix/ASIXDevice.cpp b/src/add-ons/kernel/drivers/network/usb_asix/ASIXDevice.cpp index 853df28fda..3bc5b86b0a 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/ASIXDevice.cpp +++ b/src/add-ons/kernel/drivers/network/usb_asix/ASIXDevice.cpp @@ -1,32 +1,34 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ -#include "Driver.h" -#include "Settings.h" + #include "ASIXDevice.h" -//TODO: multicast support -//TODO: set media state support +#include + +#include "ASIXVendorRequests.h" +#include "Driver.h" +#include "Settings.h" -// frame header used during transfer data +// frame header used during transfer data struct TRXHeader { uint16 fLength; uint16 fInvertedLength; - - TRXHeader(uint16 length = 0){ SetLength(length); } + + TRXHeader(uint16 length = 0) { SetLength(length); } bool IsValid() { return (fLength ^ fInvertedLength) == 0xffff; } uint16 Length() { return fLength; } - //TODO: low-endian convertion? + // TODO: low-endian convertion? void SetLength(uint16 length) { fLength = length; fInvertedLength = ~fLength; @@ -34,45 +36,37 @@ struct TRXHeader { }; -ASIXDevice::ASIXDevice(usb_device device, const char *description) - : fStatus(B_ERROR), +ASIXDevice::ASIXDevice(usb_device device, DeviceInfo& deviceInfo) + : + fDevice(device), + 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; - } + fNonBlocking(false), + fInsideNotify(0), + fFrameSize(0), + fNotifyEndpoint(0), + fReadEndpoint(0), + fWriteEndpoint(0), + fActualLengthRead(0), + fActualLengthWrite(0), + fStatusRead(B_OK), + fStatusWrite(B_OK), + fNotifyReadSem(-1), + fNotifyWriteSem(-1), + fNotifyBuffer(NULL), + fNotifyBufferLength(0), + fLinkStateChangeSem(-1), + fUseTRXHeader(false), + fReadNodeIDRequest(kInvalidRequest) +{ + fDeviceInfo = deviceInfo; 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", @@ -82,7 +76,7 @@ ASIXDevice::ASIXDevice(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; } @@ -90,7 +84,7 @@ ASIXDevice::ASIXDevice(usb_device device, const char *description) if (_SetupEndpoints() != B_OK) { return; } - + // must be set in derived class constructor // fStatus = B_OK; } @@ -102,11 +96,11 @@ ASIXDevice::~ASIXDevice() delete_sem(fNotifyReadSem); if (fNotifyWriteSem >= B_OK) delete_sem(fNotifyWriteSem); - - if (!fRemoved) //??? + + if (!fRemoved) // ??? gUSBModule->cancel_queued_transfers(fNotifyEndpoint); - if(fNotifyBuffer) + if (fNotifyBuffer) free(fNotifyBuffer); } @@ -118,23 +112,23 @@ ASIXDevice::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, fNotifyBufferLength, _NotifyCallback, this); - if(result != B_OK) { + 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; + return result; } @@ -154,7 +148,7 @@ ASIXDevice::Close() gUSBModule->cancel_queued_transfers(fWriteEndpoint); fOpen = false; - + return StopDevice(); } @@ -171,9 +165,9 @@ ASIXDevice::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; } @@ -189,7 +183,7 @@ ASIXDevice::Read(uint8 *buffer, size_t *numBytes) size_t startIndex = fUseTRXHeader ? 0 : 1 ; size_t chunkCount = fUseTRXHeader ? 2 : 1 ; - status_t result = gUSBModule->queue_bulk_v(fReadEndpoint, + 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); @@ -202,33 +196,34 @@ ASIXDevice::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); result = gUSBModule->clear_feature(fReadEndpoint, USB_FEATURE_ENDPOINT_HALT); if (result != B_OK) { - TRACE_ALWAYS("Error during clearing of HALT state:%#010x.\n", result); + 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", + + 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: ??? + return B_ERROR; // TODO: ??? } - - if(!header.IsValid()) { - TRACE_ALWAYS("Error:TRX Header is invalid: len:%#04x; ilen:%#04x\n", + + if (!header.IsValid()) { + TRACE_ALWAYS("Error:TRX Header is invalid: len:%#04x; ilen:%#04x\n", header.fLength, header.fInvertedLength); - return B_ERROR; //TODO: ??? + return B_ERROR; // TODO: ??? } - + *numBytes = header.Length(); - if(fActualLengthRead - sizeof(TRXHeader) > 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)); } @@ -248,25 +243,25 @@ ASIXDevice::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; } 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, + + 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); @@ -274,7 +269,7 @@ ASIXDevice::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; @@ -290,7 +285,7 @@ ASIXDevice::Write(const uint8 *buffer, size_t *numBytes) } } - if(fUseTRXHeader) { + if (fUseTRXHeader) { *numBytes = fActualLengthWrite - sizeof(TRXHeader); } else { *numBytes = fActualLengthWrite; @@ -311,36 +306,34 @@ ASIXDevice::Control(uint32 op, void *buffer, size_t length) case ETHER_GETADDR: memcpy(buffer, &fMACAddress, sizeof(fMACAddress)); return B_OK; - + case ETHER_GETFRAMESIZE: *(uint32 *)buffer = 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)); - + return ModifyMulticastTable(true, (ether_address_t*)buffer); + case ETHER_REMMULTI: TRACE("ETHER_REMMULTI\n"); - return ModifyMulticastTable(false, *((uint8*)buffer)); - -#if HAIKU_TARGET_PLATFORM_HAIKU + return ModifyMulticastTable(false, (ether_address_t*)buffer); + 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); @@ -379,29 +372,29 @@ ASIXDevice::SetupDevice(bool deviceReplugged) { ether_address address; status_t result = ReadMACAddress(&address); - if(result != B_OK) { + 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[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) { + 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], + "%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 + } else fMACAddress = address; - - return B_OK; + + return B_OK; } @@ -416,8 +409,8 @@ ASIXDevice::CompareAndReattach(usb_device device) return B_ERROR; } - if (deviceDescriptor->vendor_id != fVendorID - && deviceDescriptor->product_id != fProductID) { + if (deviceDescriptor->vendor_id != fDeviceInfo.VendorId() + && deviceDescriptor->product_id != fDeviceInfo.ProductId()) { // this certainly isn't the same device return B_BAD_VALUE; } @@ -436,7 +429,7 @@ ASIXDevice::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) { @@ -470,40 +463,47 @@ ASIXDevice::_SetupEndpoints() "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; - } + 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); + "notify:%d; read:%d; write:%d\n", + notifyEndpoint, readEndpoint, writeEndpoint); return B_ERROR; } @@ -512,7 +512,7 @@ ASIXDevice::_SetupEndpoints() fNotifyEndpoint = interface->endpoint[notifyEndpoint].handle; fReadEndpoint = interface->endpoint[readEndpoint ].handle; fWriteEndpoint = interface->endpoint[writeEndpoint ].handle; - + return B_OK; } @@ -521,16 +521,16 @@ status_t ASIXDevice::ReadMACAddress(ether_address_t *address) { size_t actual_length = 0; - status_t result = gUSBModule->send_request(fDevice, + status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN, fReadNodeIDRequest, 0, 0, sizeof(ether_address), address, &actual_length); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of reading MAC address:%#010x\n", result); return result; } - if(actual_length != sizeof(ether_address)) { + if (actual_length != sizeof(ether_address)) { TRACE_ALWAYS("Mismatch of NODE ID data size: %d instead of %d bytes\n", actual_length, sizeof(ether_address)); return B_ERROR; @@ -545,28 +545,28 @@ ASIXDevice::ReadRXControlRegister(uint16 *rxcontrol) { size_t actual_length = 0; *rxcontrol = 0; - - status_t result = gUSBModule->send_request(fDevice, + + status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN, - fReadRXControlRequest, 0, 0, + READ_RX_CONTROL, 0, 0, sizeof(*rxcontrol), rxcontrol, &actual_length); - if(sizeof(*rxcontrol) != actual_length) { + if (sizeof(*rxcontrol) != actual_length) { TRACE_ALWAYS("Mismatch during reading RX control register." - "Read %d bytes instead of %d.\n", + "Read %d bytes instead of %d.\n", actual_length, sizeof(*rxcontrol)); } - return result; + return result; } status_t ASIXDevice::WriteRXControlRegister(uint16 rxcontrol) { - status_t result = gUSBModule->send_request(fDevice, + status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - fWriteRXControlRequest, rxcontrol, 0, 0, 0, 0); + WRITE_RX_CONTROL, rxcontrol, 0, 0, 0, 0); return result; } @@ -575,13 +575,13 @@ status_t ASIXDevice::StopDevice() { status_t result = WriteRXControlRegister(0); - - if(result != B_OK) { + + if (result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); - } - + } + TRACE_RET(result); - return result; + return result; } @@ -589,35 +589,113 @@ status_t ASIXDevice::SetPromiscuousMode(bool on) { uint16 rxcontrol = 0; - + status_t result = ReadRXControlRegister(&rxcontrol); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of reading RX Control:%#010x\n", result); return result; } - if(on) - rxcontrol |= fPromiscuousBits; + if (on) + rxcontrol |= RXCTL_PROMISCUOUS; else - rxcontrol &= ~fPromiscuousBits; + rxcontrol &= ~RXCTL_PROMISCUOUS; result = WriteRXControlRegister(rxcontrol); - - if(result != B_OK ) { - TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result); + + if (result != B_OK ) { + TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", + rxcontrol, result); } - + TRACE_RET(result); - return result; + return result; +} + + +uint32 +ASIXDevice::EthernetCRC32(const uint8* buffer, size_t length) +{ + uint32 result = 0xffffffff; + for (size_t i = 0; i < length; i++) { + uint8 data = *buffer++; + for (int bit = 0; bit < 8; bit++, data >>= 1) { + uint32 carry = ((result & 0x80000000) ? 1 : 0) ^ (data & 0x01); + result <<= 1; + if (carry != 0) + result = (result ^ 0x04c11db6) | carry; + } + } + return result; } status_t -ASIXDevice::ModifyMulticastTable(bool add, uint8 address) +ASIXDevice::ModifyMulticastTable(bool join, ether_address_t* group) { - //TODO: !!! - TRACE_ALWAYS("Call for (%d, %#02x) is not implemented\n", add, address); - return B_OK; + char groupName[6 * 3 + 1] = { 0 }; + sprintf(groupName, "%02x:%02x:%02x:%02x:%02x:%02x", + group->ebyte[0], group->ebyte[1], group->ebyte[2], + group->ebyte[3], group->ebyte[4], group->ebyte[5]); + TRACE("%s multicast group %s\n", join ? "Joining" : "Leaving", groupName); + + uint32 hash = EthernetCRC32(group->ebyte, 6); + bool isInTable = fMulticastHashes.Find(hash) != fMulticastHashes.End(); + + if (isInTable && join) + return B_OK; // already listed - nothing to do + + if (!isInTable && !join) { + TRACE_ALWAYS("Cannot leave unlisted multicast group %s!\n", groupName); + return B_ERROR; + } + + const size_t hashLength = 8; + uint8 hashTable[hashLength] = { 0 }; + + if (join) + fMulticastHashes.PushBack(hash); + else + fMulticastHashes.Remove(hash); + + for (int32 i = 0; i < fMulticastHashes.Count(); i++) { + uint32 hash = fMulticastHashes[i] >> 26; + hashTable[hash / 8] |= 1 << (hash % 8); + } + + 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 (fMulticastHashes.Count() > 0) + rxcontrol |= RXCTL_MULTICAST; + else + rxcontrol &= ~RXCTL_MULTICAST; + + // write multicast hash table + size_t actualLength = 0; + result = gUSBModule->send_request(fDevice, + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + WRITE_MF_ARRAY, 0, 0, + hashLength, hashTable, &actualLength); + if (result != B_OK) { + TRACE_ALWAYS("Error writing hash table in MAR: %#010x.\n", result); + return result; + } + + if (actualLength != hashLength) + TRACE_ALWAYS("Incomplete writing of hash table: %d bytes of %d\n", + actualLength, hashLength); + + result = WriteRXControlRegister(rxcontrol); + if (result != B_OK) + TRACE_ALWAYS("Error writing %#02X to RXC:%#010x.\n", rxcontrol, result); + + return result; } @@ -660,10 +738,11 @@ ASIXDevice::_NotifyCallback(void *cookie, int32 status, void *data, 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); + if (result != B_OK) + TRACE_ALWAYS("Error during clearing of HALT state:%#010x.\n", + result); } - + // parse data in overriden class device->OnNotify(actualLength); diff --git a/src/add-ons/kernel/drivers/network/usb_asix/ASIXDevice.h b/src/add-ons/kernel/drivers/network/usb_asix/ASIXDevice.h index ff3807f7cc..af8be00be0 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/ASIXDevice.h +++ b/src/add-ons/kernel/drivers/network/usb_asix/ASIXDevice.h @@ -1,26 +1,48 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ - #ifndef _USB_ASIX_DEVICE_H_ #define _USB_ASIX_DEVICE_H_ -#include + +#include +#include #include "Driver.h" #include "MIIBus.h" + +struct DeviceInfo { + union Id { + uint16 fIds[2]; + uint32 fKey; + } fId; + + enum Type { + AX88172 = 0, + AX88772 = 1, + AX88178 = 2 + } fType; + + const char* fName; + + inline uint16 VendorId() { return fId.fIds[0]; } + inline uint16 ProductId() { return fId.fIds[1]; } + inline uint32 Key() { return fId.fKey; } +}; + + class ASIXDevice { public: - ASIXDevice(usb_device device, const char *description); + ASIXDevice(usb_device device, DeviceInfo& devInfo); virtual ~ASIXDevice(); status_t InitCheck() { return fStatus; }; @@ -40,7 +62,7 @@ public: status_t CompareAndReattach(usb_device device); virtual status_t SetupDevice(bool deviceReplugged); - + private: static void _ReadCallback(void *cookie, int32 status, void *data, uint32 actualLength); @@ -52,27 +74,31 @@ static void _NotifyCallback(void *cookie, int32 status, status_t _SetupEndpoints(); protected: - /* overrides */ + // overrides virtual status_t StartDevice() = 0; virtual status_t StopDevice(); virtual status_t OnNotify(uint32 actualLength) = 0; -virtual status_t GetLinkState(ether_link_state *state) = 0; +virtual status_t GetLinkState(ether_link_state *state) = 0; virtual status_t SetPromiscuousMode(bool bOn); -virtual status_t ModifyMulticastTable(bool add, uint8 address); + uint32 EthernetCRC32(const uint8* buffer, size_t length); +virtual status_t ModifyMulticastTable(bool add, + ether_address_t* group); status_t ReadMACAddress(ether_address_t *address); status_t ReadRXControlRegister(uint16 *rxcontrol); status_t WriteRXControlRegister(uint16 rxcontrol); - + + // device info + usb_device fDevice; + DeviceInfo fDeviceInfo; + ether_address_t fMACAddress; + // state tracking status_t fStatus; bool fOpen; bool fRemoved; - vint32 fInsideNotify; - usb_device fDevice; - uint16 fVendorID; - uint16 fProductID; -const char * fDescription; + bool fHasConnection; bool fNonBlocking; + vint32 fInsideNotify; // interface and device infos uint16 fFrameSize; @@ -89,23 +115,19 @@ const char * fDescription; int32 fStatusWrite; sem_id fNotifyReadSem; sem_id fNotifyWriteSem; - + uint8 * fNotifyBuffer; uint32 fNotifyBufferLength; + sem_id fLinkStateChangeSem; // MII bus handler MIIBus fMII; // connection data - sem_id fLinkStateChangeSem; - ether_address_t fMACAddress; - bool fHasConnection; bool fUseTRXHeader; uint8 fIPG[3]; uint8 fReadNodeIDRequest; - uint8 fReadRXControlRequest; - uint8 fWriteRXControlRequest; - uint16 fPromiscuousBits; + Vector fMulticastHashes; }; -#endif //_USB_ASIX_DEVICE_H_ +#endif // _USB_ASIX_DEVICE_H_ diff --git a/src/add-ons/kernel/drivers/network/usb_asix/ASIXVendorRequests.h b/src/add-ons/kernel/drivers/network/usb_asix/ASIXVendorRequests.h new file mode 100644 index 0000000000..59ec0ec61c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/usb_asix/ASIXVendorRequests.h @@ -0,0 +1,73 @@ +/* + * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. + * Copyright (c) 2011 S.Zharski + * Distributed under the terms of the MIT license. + * + */ +#ifndef _ASIX_VENDOR_REQUESTS_H_ +#define _ASIX_VENDOR_REQUESTS_H_ + + +// USB Vendor Requests used by all chip types +// For chip-spercific information look into +// corresponding AX88***Device.cpp files. +enum ASIXVendorRequests { + READ_RXTX_SRAM = 0x02, + WRITE_RXTX_SRAM = 0x03, // AX88178-772 + WRITE_RX_SRAM = 0x03, // AX88172 + WRITE_TX_SRAM = 0x04, // AX88172 + SW_MII_OP = 0x06, + READ_MII = 0x07, + WRITE_MII = 0x08, + READ_MII_OP_MODE = 0x09, // AX88172-772 + READ_MII_STATUS = 0x09, // AX88178 + HW_MII_OP = 0x0A, + READ_SROM = 0x0B, + WRITE_SROM = 0x0C, + WRITE_SROM_ENABLE = 0x0D, + WRITE_SROM_DISABLE = 0x0E, + READ_RX_CONTROL = 0x0F, + WRITE_RX_CONTROL = 0x10, + READ_IPGS = 0x11, + WRITE_IPGS = 0x12, // AX88178-772 + WRITE_IPG0 = 0x12, // AX88172 + WRITE_IPG1 = 0x13, // AX88172 + WRITE_IPG2 = 0x14, // AX88172 + READ_NODEID = 0x13, // AX88178-772 + WRITE_NODEID = 0x14, // AX88178-772 + READ_MF_ARRAY = 0x15, + WRITE_MF_ARRAY = 0x16, + READ_TEST = 0x17, // AX88178-772 + READ_NODEID_AX88172 = 0x17, // AX88172 + WRITE_NODEID_AX88172 = 0x18, // AX88172 + READ_PHYID = 0x19, + READ_MEDIUM_STATUS = 0x1A, + WRITE_MEDIUM_MODE = 0x1B, + GET_MONITOR_MODE = 0x1C, + SET_MONITOR_MODE = 0x1D, + READ_GPIOS = 0x1E, + WRITE_GPIOS = 0x1F, + WRITE_SOFT_RESET = 0x20, // AX88178-772 + READ_PHY_SEL_STATE = 0x21, // AX88772 + WRITE_PHY_SEL = 0x22, // AX88772 + READ_MIIS_IF_STATE = 0x21, // AX88178 + WRITE_MIIS_IF_STATE = 0x22 // AX88178 +}; + + +// RX Control Register bits +enum ASIXRXControl { + RXCTL_PROMISCUOUS = 0x0001, + RXCTL_ALL_MULTICAT = 0x0002, + RXCTL_UNICAST = 0x0004, // AX88172 + RXCTL_SEP = 0x0004, // AX88772-178 + RXCTL_BROADCAST = 0x0008, + RXCTL_MULTICAST = 0x0010, + RXCTL_AP = 0x0020, // AX88772-178 + RXCTL_START = 0x0080, + RXCTL_USB_MFB = 0x0100 // AX88772-178 +}; + + +#endif // _ASIX_VENDOR_REQUESTS_H_ + diff --git a/src/add-ons/kernel/drivers/network/usb_asix/AX88172Device.cpp b/src/add-ons/kernel/drivers/network/usb_asix/AX88172Device.cpp index fc49ffb9ea..3de0da38ad 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/AX88172Device.cpp +++ b/src/add-ons/kernel/drivers/network/usb_asix/AX88172Device.cpp @@ -1,6 +1,6 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * Distributed under the terms of the MIT license. * * Heavily based on code of the @@ -10,52 +10,60 @@ * */ -#include "Settings.h" + #include "AX88172Device.h" +#include -enum AX88172_Requests { - READ_RXTX_SRAM = 0x02, // C0 02 XX YY 0M 00 0200 Read Rx/Tx SRAM - // M = 0 : Rx, M=1 : Tx - WRITE_RX_SRAM = 0x03, // 40 03 XX YY PP QQ 0000 Write Rx SRAM - WRITE_TX_SRAM = 0x04, // 40 04 XX YY PP QQ 0000 Write Tx SRAM - SW_MII_OP = 0x06, // 40 06 00 00 00 00 0000 Software MII Operation - READ_MII = 0x07, // C0 07 PI 00 RG 00 0200 Read MII Register - WRITE_MII = 0x08, // 40 08 PI 00 RG 00 0200 Write MII Register - READ_MII_OP_MODE = 0x09, // C0 09 00 00 00 00 0100 Read MII Operation Mode - HW_MII_OP = 0x0A, // 40 0A 00 00 00 00 0000 Hardware MII Operation - READ_SROM = 0x0B, // C0 0B DR 00 00 00 0200 Read SROM - WRITE_SROM = 0x0C, // 40 0C DR 00 MM SS 0000 Write SROM - WRITE_SROM_ENABLE = 0x0D, // 40 0D 00 00 00 00 0000 Write SROM Enable - WRITE_SROM_DISABLE = 0x0E, // 40 0E 00 00 00 00 0000 Write SROM Disable - READ_RX_CONTROL = 0x0F, // C0 0F 00 00 00 00 0200 Read Rx Control Register - WRITE_RX_CONTROL = 0x10, // 40 10 RR 00 00 00 0000 Write Rx Control Register - READ_IPGS = 0x11, // C0 11 00 00 00 00 0300 Read IPG/IPG1/IPG2 Register - WRITE_IPG0 = 0x12, // 40 12 II 00 00 00 0000 Write IPG Register - WRITE_IPG1 = 0x13, // 40 13 II 00 00 00 0000 Write IPG1 Register - WRITE_IPG2 = 0x14, // 40 14 II 00 00 00 0000 Write IPG2 Register - 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, // - 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 - GET_MONITOR_MODE = 0x1C, // C0 1C 00 00 00 00 0100 Get Monitor Mode Status - SET_MONITOR_MODE = 0x1D, // 40 1D MM 00 00 00 0000 Set Monitor Mode On/Off - READ_GPIOS = 0x1E, // C0 1E 00 00 00 00 0100 Read GPIOs - WRITE_GPIOS = 0x1F // 40 1F MM 00 00 00 0000 Write GPIOs -}; +#include "ASIXVendorRequests.h" +#include "Settings.h" + + +// Most of vendor requests for all supported chip types use the same +// constants (see ASIXVendorRequests.h) but the layout of request data +// may be slightly diferrent for specific chip type. Below is a quick +// reference for AX88172 vendor requests data layout. +// +// READ_RXTX_SRAM, // C0 02 XX YY 0M 00 0200 Read Rx/Tx SRAM + // M = 0 : Rx, M=1 : Tx +// WRITE_RX_SRAM, // 40 03 XX YY PP QQ 0000 Write Rx SRAM +// WRITE_TX_SRAM, // 40 04 XX YY PP QQ 0000 Write Tx SRAM +// SW_MII_OP, // 40 06 00 00 00 00 0000 Software MII Operation +// READ_MII, // C0 07 PI 00 RG 00 0200 Read MII Register +// WRITE_MII, // 40 08 PI 00 RG 00 0200 Write MII Register +// READ_MII_OP_MODE, // C0 09 00 00 00 00 0100 Read MII Operation Mode +// HW_MII_OP, // 40 0A 00 00 00 00 0000 Hardware MII Operation +// READ_SROM, // C0 0B DR 00 00 00 0200 Read SROM +// WRITE_SROM, // 40 0C DR 00 MM SS 0000 Write SROM +// WRITE_SROM_ENABLE, // 40 0D 00 00 00 00 0000 Write SROM Enable +// WRITE_SROM_DISABLE, // 40 0E 00 00 00 00 0000 Write SROM Disable +// READ_RX_CONTROL, // C0 0F 00 00 00 00 0200 Read Rx Control Register +// WRITE_RX_CONTROL, // 40 10 RR 00 00 00 0000 Write Rx Control Register +// READ_IPGS, // C0 11 00 00 00 00 0300 Read IPG/IPG1/IPG2 Register +// WRITE_IPG0, // 40 12 II 00 00 00 0000 Write IPG Register +// WRITE_IPG1, // 40 13 II 00 00 00 0000 Write IPG1 Register +// WRITE_IPG2, // 40 14 II 00 00 00 0000 Write IPG2 Register +// READ_MF_ARRAY, // C0 15 00 00 00 00 0800 Read Multi-Filter Array +// WRITE_MF_ARRAY, // 40 16 00 00 00 00 0800 Write Multi-Filter Array +// READ_NODEID, // C0 17 00 00 00 00 0600 Read Node ID +// WRITE_NODEID, // +// READ_PHYID, // C0 19 00 00 00 00 0200 Read Ethernet/HomePNA PhyID +// READ_MEDIUM_STATUS, // C0 1A 00 00 00 00 0100 Read Medium Status +// WRITE_MEDIUM_MODE, // 40 1B MM 00 00 00 0000 Write Medium Mode +// GET_MONITOR_MODE, // C0 1C 00 00 00 00 0100 Get Monitor Mode Status +// SET_MONITOR_MODE, // 40 1D MM 00 00 00 0000 Set Monitor Mode On/Off +// READ_GPIOS, // C0 1E 00 00 00 00 0100 Read GPIOs +// WRITE_GPIOS, // 40 1F MM 00 00 00 0000 Write GPIOs // RX Control Register bits -enum AX88172_RXControl { - RXCTL_PROMISCUOUS = 0x0001, // - RXCTL_ALL_MULTICAT = 0x0002, // - RXCTL_UNICAST = 0x0004, // ??? - RXCTL_BROADCAST = 0x0008, // - RXCTL_MULTICAST = 0x0010, // - RXCTL_START = 0x0080 // -}; +// RXCTL_PROMISCUOUS, // forward all frames up to the host +// RXCTL_ALL_MULTICAT, // forward all multicast frames up to the host +// RXCTL_UNICAST, // ??? +// RXCTL_BROADCAST, // forward broadcast frames up to the host +// RXCTL_MULTICAST, // forward all multicast frames that are +// matching to multicast filter up to the host +// RXCTL_START, // ethernet MAC start operating + // PHY IDs request answer data layout struct PhyIDs { @@ -63,6 +71,7 @@ struct PhyIDs { uint8 PhyID2; } _PACKED; + // Medium state bits enum AX88172_MediumState { MEDIUM_STATE_FULL_DUPLEX = 0x02, @@ -70,6 +79,7 @@ enum AX88172_MediumState { MEDIUM_STATE_FLOW_CONTOL_EN = 0x10 }; + // Monitor Mode bits enum AX88172_MonitorMode { MONITOR_MODE = 0x01, @@ -78,6 +88,7 @@ enum AX88172_MonitorMode { MONITOR_MODE_HS_FS = 0x10 }; + // General Purpose I/O Register enum AX88172_GPIO { GPIO_OO_0EN = 0x01, @@ -88,6 +99,7 @@ enum AX88172_GPIO { GPIO_IO_2 = 0x20 }; + // Notification data layout struct AX88172Notify { uint8 btA1; @@ -100,16 +112,20 @@ struct AX88172Notify { uint8 bt07; } _PACKED; + // Link-State bits enum AX88172_LinkState { LINK_STATE_PHY1 = 0x01, LINK_STATE_PHY2 = 0x02 }; + const uint16 maxFrameSize = 1518; -AX88172Device::AX88172Device(usb_device device, const char *description) - : ASIXDevice(device, description) + +AX88172Device::AX88172Device(usb_device device, DeviceInfo& deviceInfo) + : + ASIXDevice(device, deviceInfo) { fStatus = InitDevice(); } @@ -120,11 +136,7 @@ AX88172Device::InitDevice() { fFrameSize = maxFrameSize; - fReadNodeIDRequest = READ_NODEID; - fReadRXControlRequest = READ_RX_CONTROL; - fWriteRXControlRequest = WRITE_RX_CONTROL; - - fPromiscuousBits = RXCTL_PROMISCUOUS; + fReadNodeIDRequest = READ_NODEID_AX88172; fNotifyBufferLength = sizeof(AX88172Notify); fNotifyBuffer = (uint8 *)malloc(fNotifyBufferLength); @@ -136,19 +148,19 @@ AX88172Device::InitDevice() TRACE_RET(B_OK); return B_OK; } + + status_t AX88172Device::SetupDevice(bool deviceReplugged) { status_t result = ASIXDevice::SetupDevice(deviceReplugged); - if(result != B_OK) { + if (result != B_OK) { return result; } - result = fMII.Init(fDevice, - SW_MII_OP, READ_MII, WRITE_MII, - READ_MII_OP_MODE, HW_MII_OP, READ_PHYID); + result = fMII.Init(fDevice); - if(result == B_OK) + if (result == B_OK) return fMII.SetupPHY(); TRACE_RET(result); @@ -161,27 +173,27 @@ AX88172Device::StartDevice() { size_t actualLength = 0; - for(size_t i = 0; i < sizeof(fIPG)/sizeof(fIPG[0]); i++) { + 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) { + if (result != B_OK) { TRACE_ALWAYS("Error writing IPG%d: %#010x\n", i, result); return result; } - if(actualLength != sizeof(fIPG[i])) { + if (actualLength != sizeof(fIPG[i])) { TRACE_ALWAYS("Mismatch of written IPG%d data. " - "%d bytes of %d written.\n", i, actualLength, sizeof(fIPG[i])); + "%d bytes of %d written.\n", i, actualLength, sizeof(fIPG[i])); } } - uint16 rxcontrol = RXCTL_START | RXCTL_MULTICAST - | RXCTL_UNICAST | RXCTL_BROADCAST; + uint16 rxcontrol = RXCTL_START | 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); + if (result != B_OK) { + TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", + rxcontrol, result); } TRACE_RET(result); @@ -200,7 +212,7 @@ AX88172Device::OnNotify(uint32 actualLength) AX88172Notify *notification = (AX88172Notify *)fNotifyBuffer; - if(notification->btA1 != 0xa1) { + if (notification->btA1 != 0xa1) { TRACE_ALWAYS("Notify magic byte is invalid: %#02x\n", notification->btA1); } @@ -225,7 +237,7 @@ AX88172Device::OnNotify(uint32 actualLength) bool linkStateChange = linkIsUp != fHasConnection; fHasConnection = linkIsUp; - if(linkStateChange) { + if (linkStateChange) { TRACE("Link state of PHY%d has been changed to '%s'\n", phyIndex, fHasConnection ? "up" : "down"); } @@ -236,6 +248,7 @@ AX88172Device::OnNotify(uint32 actualLength) return B_OK; } + status_t AX88172Device::GetLinkState(ether_link_state *linkState) { @@ -243,13 +256,13 @@ AX88172Device::GetLinkState(ether_link_state *linkState) uint16 miiANLPAR = 0; status_t result = fMII.Read(MII_ANAR, &miiANAR); - if(result != B_OK) { + 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) { + if (result != B_OK) { TRACE_ALWAYS("Error reading MII ANLPAR register:%#010x\n", result); return result; } @@ -261,14 +274,15 @@ AX88172Device::GetLinkState(ether_link_state *linkState) 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) ? 100000000 : 10000000; + 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, + linkState->speed / 1000000, (linkState->media & IFM_FULL_DUPLEX) ? "full" : "half"); return B_OK; } diff --git a/src/add-ons/kernel/drivers/network/usb_asix/AX88172Device.h b/src/add-ons/kernel/drivers/network/usb_asix/AX88172Device.h index b88c669786..aabaf8cbda 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/AX88172Device.h +++ b/src/add-ons/kernel/drivers/network/usb_asix/AX88172Device.h @@ -1,30 +1,31 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ - #ifndef _USB_AX88172_DEVICE_H_ #define _USB_AX88172_DEVICE_H_ + #include "ASIXDevice.h" + class AX88172Device : public ASIXDevice { public: - AX88172Device(usb_device device, const char *description); + AX88172Device(usb_device device, DeviceInfo& info); protected: status_t InitDevice(); virtual status_t SetupDevice(bool deviceReplugged); virtual status_t StartDevice(); virtual status_t OnNotify(uint32 actualLength); -virtual status_t GetLinkState(ether_link_state *state); +virtual status_t GetLinkState(ether_link_state *state); }; -#endif //_USB_AX88172_DEVICE_H_ +#endif // _USB_AX88172_DEVICE_H_ diff --git a/src/add-ons/kernel/drivers/network/usb_asix/AX88178Device.cpp b/src/add-ons/kernel/drivers/network/usb_asix/AX88178Device.cpp index da9cb85c05..092e7e04a7 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/AX88178Device.cpp +++ b/src/add-ons/kernel/drivers/network/usb_asix/AX88178Device.cpp @@ -1,6 +1,6 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * Distributed under the terms of the MIT license. * * Heavily based on code of the @@ -10,54 +10,63 @@ * */ -#include "Settings.h" + #include "AX88178Device.h" -// 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 - 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 - 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 - 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 - WRITE_MF_ARRAY = 0x16, //4016_0000_0000_0800 Write Multicast Filter Array - 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 - 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 - WRITE_MIIS_IF_STATE = 0x22 //4022_AA00_0000_0000 Write MII/GMII/RGMII Interface Control -}; +#include + +#include "ASIXVendorRequests.h" +#include "Settings.h" + + +// Most of vendor requests for all supported chip types use the same +// constants (see ASIXVendorRequests.h) but the layout of request data +// may be slightly diferrent for specific chip type. Below is a quick +// reference for AX88178 vendor requests data layout. + +// READ_RXTX_SRAM, //C002_AA0B_0C00_0800 Rx/Tx SRAM Read +// WRITE_RXTX_SRAM, //4003_AA0B_0C00_0800 Rx/Tx SRAM Write +// SW_MII_OP, //4006_0000_0000_0000 SW Serial Management Control +// READ_MII, //c007_aa00_cc00_0200 PHY Read +// WRITE_MII, //4008_aa00_cc00_0200 PHY Write +// READ_MII_STATUS, //c009_0000_0000_0100 Serial Management Status +// HW_MII_OP, //400a_0000_0000_0000 HW Serial Management Control +// READ_SROM, //C00B_AA00_0000_0200 SROM Read +// WRITE_SROM, //400C_AA00_CCDD_0000 SROM Write +// WRITE_SROM_ENABLE, //400D_0000_0000_0000 SROM Write Enable +// WRITE_SROM_DISABLE, //400E_0000_0000_0000 SROM Write Disable +// READ_RX_CONTROL, //C00F_0000_0000_0200 Read Rx Control +// WRITE_RX_CONTROL, //4010_AABB_0000_0000 Write Rx Control +// READ_IPGS, //C011_0000_0000_0300 Read IPG/IPG1/IPG2 Register +// WRITE_IPGS, //4012_AABB_CC00_0000 Write IPG/IPG1/IPG2 Register +// READ_NODEID, //C013_0000_0000_0600 Read Node ID +// WRITE_NODEID, //4014_0000_0000_0600 Write Node ID +// READ_MF_ARRAY, //C015_0000_0000_0800 Read Multicast Filter Array +// WRITE_MF_ARRAY, //4016_0000_0000_0800 Write Multicast Filter Array +// READ_TEST, //4017_AA00_0000_0000 Write Test Register +// READ_PHYID, //C019_0000_0000_0200 Read Ethernet/HomePNA PHY Address +// READ_MEDIUM_STATUS, //C01A_0000_0000_0200 Read Medium Status +// WRITE_MEDIUM_MODE, //401B_AABB_0000_0000 Write Medium Mode Register +// GET_MONITOR_MODE, //C01C_0000_0000_0100 Read Monitor Mode Status +// SET_MONITOR_MODE, //401D_AA00_0000_0000 Write Monitor Mode Register +// READ_GPIOS, //C01E_0000_0000_0100 Read GPIOs Status +// WRITE_GPIOS, //401F_AA00_0000_0000 Write GPIOs +// WRITE_SOFT_RESET, //4020_AA00_0000_0000 Write Software Reset +// READ_MIIS_IF_STATE, //C021_AA00_0000_0100 Read MII/GMII/RGMII Iface Status +// WRITE_MIIS_IF_STATE, //4022_AA00_0000_0000 Write MII/GMII/RGMII Iface Control // RX Control Register bits -enum AX88178_RXControl { - RXCTL_PROMISCUOUS = 0x0001, // - RXCTL_ALL_MULTICAT = 0x0002, // -// RXCTL_SEP = 0x0004, // do not set it! - RXCTL_BROADCAST = 0x0008, // - RXCTL_MULTICAST = 0x0010, // - RXCTL_AP = 0x0020, // - RXCTL_START = 0x0080, // - RXCTL_USB_MFB = 0x0100 // Max Frame Burst TX on USB -}; +// RXCTL_PROMISCUOUS, // forward all frames up to the host +// RXCTL_ALL_MULTICAT, // forward all multicast frames up to the host +// RXCTL_SEP, // forward frames with CRC error up to the host +// RXCTL_BROADCAST, // forward broadcast frames up to the host +// RXCTL_MULTICAST, // forward multicast frames that are +// matching to multicast filter up to the host +// RXCTL_AP, // forward unicast frames that are matching +// to multicast filter up to the host +// RXCTL_START, // ethernet MAC start operating +// RXCTL_USB_MFB, // Max Frame Burst TX on USB + // PHY IDs request answer data layout struct AX88178_PhyIDs { @@ -65,6 +74,7 @@ struct AX88178_PhyIDs { uint8 PriPhyID2; } _PACKED; + // Medium state bits enum AX88178_MediumState { MEDIUM_STATE_GM = 0x0001, @@ -84,6 +94,7 @@ enum AX88178_MediumState { MEDIUM_STATE_SM_ON = 0x1000 }; + // Monitor Mode bits enum AX88178_MonitorMode { MONITOR_MODE_MOM = 0x01, @@ -92,6 +103,7 @@ enum AX88178_MonitorMode { MONITOR_MODE_US = 0x10 }; + // General Purpose I/O Register enum AX88178_GPIO { GPIO_OO_0EN = 0x01, @@ -103,6 +115,7 @@ enum AX88178_GPIO { GPIO_RSE = 0x80 }; + // Software Reset Register bits enum AX88178_SoftwareReset { SW_RESET_RR = 0x01, @@ -113,12 +126,14 @@ enum AX88178_SoftwareReset { SW_RESET_BIT6 = 0x40 // always set to 1 }; + // MII/GMII/RGMII Interface Conttrol enum AX88178_MIISInterfaceStatus { MIIS_IF_STATE_DM = 0x01, MIIS_IF_STATE_RB = 0x02 }; + // Notification data layout struct AX88178_Notify { uint8 btA1; @@ -129,6 +144,7 @@ struct AX88178_Notify { uint16 regEEFF; } _PACKED; + // Link-State bits enum AX88178_BBState { LINK_STATE_PPLS = 0x01, @@ -137,10 +153,13 @@ enum AX88178_BBState { LINK_STATE_MDINT = 0x08 }; + const uint16 maxFrameSize = 1536; -AX88178Device::AX88178Device(usb_device device, const char *description) - : ASIXDevice(device, description) + +AX88178Device::AX88178Device(usb_device device, DeviceInfo& deviceInfo) + : + ASIXDevice(device, deviceInfo) { fStatus = InitDevice(); } @@ -153,10 +172,6 @@ AX88178Device::InitDevice() fUseTRXHeader = true; fReadNodeIDRequest = READ_NODEID; - fReadRXControlRequest = READ_RX_CONTROL; - fWriteRXControlRequest = WRITE_RX_CONTROL; - - fPromiscuousBits = RXCTL_PROMISCUOUS; fNotifyBufferLength = sizeof(AX88178_Notify); fNotifyBuffer = (uint8 *)malloc(fNotifyBufferLength); @@ -174,15 +189,13 @@ status_t AX88178Device::SetupDevice(bool deviceReplugged) { status_t result = ASIXDevice::SetupDevice(deviceReplugged); - if(result != B_OK) { + if (result != B_OK) { return result; } - result = fMII.Init(fDevice, - SW_MII_OP, READ_MII, WRITE_MII, - READ_MII_STATUS, HW_MII_OP, READ_PHYID); + result = fMII.Init(fDevice); - if(result != B_OK) { + if (result != B_OK) { return result; } @@ -192,7 +205,7 @@ AX88178Device::SetupDevice(bool deviceReplugged) USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_SROM_ENABLE, 0, 0, 0, 0, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of enabling SROM access:%#010x\n", result); return result; } @@ -203,26 +216,26 @@ AX88178Device::SetupDevice(bool deviceReplugged) READ_SROM, 0x17, 0, sizeof(eepromData), &eepromData, &actualLength); - if(op_result != B_OK) { + if (op_result != B_OK) { TRACE_ALWAYS("Error of reading SROM data:%#010x\n", result); } - if(actualLength != sizeof(eepromData)) { + if (actualLength != sizeof(eepromData)) { TRACE_ALWAYS("Mismatch of reading SROM data." "Read %d bytes instead of %d\n", - actualLength, sizeof(eepromData)); + actualLength, sizeof(eepromData)); } result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_SROM_DISABLE, 0, 0, 0, 0, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of disabling SROM access: %#010x\n", result); return result; } - if(op_result != B_OK) { + if (op_result != B_OK) { return op_result; } @@ -246,7 +259,7 @@ AX88178Device::SetupDevice(bool deviceReplugged) size_t from = bCase8 ? 0 : 4; size_t to = bCase8 ? 3 : 6; - for(size_t i = from; i <= to; i++) { + for (size_t i = from; i <= to; i++) { result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_GPIOS, GPIOCommands[i].value, @@ -254,7 +267,7 @@ AX88178Device::SetupDevice(bool deviceReplugged) snooze(GPIOCommands[i].delay); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of GPIO setup command %d:[%#04x]: %#010x\n", i, GPIOCommands[i].value, result); return result; @@ -267,7 +280,7 @@ AX88178Device::SetupDevice(bool deviceReplugged) USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_SOFT_RESET, uSWReset, 0, 0, 0, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of SW reset to %#02x: %#010x\n", uSWReset, result); return result; } @@ -279,7 +292,7 @@ AX88178Device::SetupDevice(bool deviceReplugged) USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_SOFT_RESET, uSWReset, 0, 0, 0, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of SW reset to %#02x: %#010x\n", uSWReset, result); return result; } @@ -287,7 +300,7 @@ AX88178Device::SetupDevice(bool deviceReplugged) snooze(150000); result = WriteRXControlRegister(0); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); return result; } @@ -307,20 +320,21 @@ AX88178Device::StartDevice() USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_IPGS, 0, 0, sizeof(fIPG), fIPG, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of writing IPGs:%#010x\n", result); return result; } - if(actualLength != sizeof(fIPG)) { + if (actualLength != sizeof(fIPG)) { TRACE_ALWAYS("Mismatch of written IPGs data. " "%d bytes of %d written.\n", actualLength, sizeof(fIPG)); } - uint16 rxcontrol = RXCTL_START | RXCTL_MULTICAST | RXCTL_BROADCAST; + uint16 rxcontrol = RXCTL_START | RXCTL_BROADCAST; result = WriteRXControlRegister(rxcontrol); - if(result != B_OK) { - TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result); + if (result != B_OK) { + TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", + rxcontrol, result); } TRACE_RET(result); @@ -339,9 +353,9 @@ AX88178Device::OnNotify(uint32 actualLength) AX88178_Notify *notification = (AX88178_Notify *)fNotifyBuffer; - if(notification->btA1 != 0xa1) { + if (notification->btA1 != 0xa1) { TRACE_ALWAYS("Notify magic byte is invalid: %#02x\n", - notification->btA1); + notification->btA1); } uint phyIndex = 0; @@ -364,7 +378,7 @@ AX88178Device::OnNotify(uint32 actualLength) bool linkStateChange = linkIsUp != fHasConnection; fHasConnection = linkIsUp; - if(linkStateChange) { + if (linkStateChange) { TRACE("Link state of PHY%d has been changed to '%s'\n", phyIndex, fHasConnection ? "up" : "down"); } @@ -386,12 +400,12 @@ AX88178Device::GetLinkState(ether_link_state *linkState) READ_MEDIUM_STATUS, 0, 0, sizeof(mediumStatus), &mediumStatus, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of reading medium status:%#010x.\n", result); return result; } - if(actualLength != sizeof(mediumStatus)) { + if (actualLength != sizeof(mediumStatus)) { TRACE_ALWAYS("Mismatch of reading medium status." "Read %d bytes instead of %d\n", actualLength, sizeof(mediumStatus)); @@ -402,16 +416,17 @@ AX88178Device::GetLinkState(ether_link_state *linkState) 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) ? 100000000 : 10000000; + 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, + linkState->speed / 1000000, (linkState->media & IFM_FULL_DUPLEX) ? "full" : "half"); return B_OK; } diff --git a/src/add-ons/kernel/drivers/network/usb_asix/AX88178Device.h b/src/add-ons/kernel/drivers/network/usb_asix/AX88178Device.h index 9f8841c057..2387b3e81e 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/AX88178Device.h +++ b/src/add-ons/kernel/drivers/network/usb_asix/AX88178Device.h @@ -1,29 +1,30 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ - #ifndef _USB_AX88178_DEVICE_H_ #define _USB_AX88178_DEVICE_H_ + #include "ASIXDevice.h" + class AX88178Device : public ASIXDevice { public: - AX88178Device(usb_device device, const char *description); + AX88178Device(usb_device device, DeviceInfo& info); protected: status_t InitDevice(); virtual status_t SetupDevice(bool deviceReplugged); virtual status_t StartDevice(); virtual status_t OnNotify(uint32 actualLength); -virtual status_t GetLinkState(ether_link_state *state); +virtual status_t GetLinkState(ether_link_state *state); }; -#endif //_USB_AX88178_DEVICE_H_ +#endif // _USB_AX88178_DEVICE_H_ diff --git a/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp b/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp index 8b35a5bba8..6f644c581d 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp +++ b/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp @@ -1,6 +1,6 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * Distributed under the terms of the MIT license. * * Heavily based on code of the @@ -10,53 +10,63 @@ * */ -#include "Settings.h" + #include "AX88772Device.h" -enum AX88772_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 - 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_OP_MODE = 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 - 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 - WRITE_MF_ARRAY = 0x16, //4016_0000_0000_0800 Write Multicast Filter Array - 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 - 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_PHY_SEL_STATE = 0x21, //C021_AA00_0000_0100 Read Software PHY Select Status - WRITE_PHY_SEL = 0x22 //4022_AA00_0000_0000 Write Software PHY Select -}; +#include + +#include "ASIXVendorRequests.h" +#include "Settings.h" + + +// Most of vendor requests for all supported chip types use the same +// constants (see ASIXVendorRequests.h) but the layout of request data +// may be slightly diferrent for specific chip type. Below is a quick +// reference for AX88772 vendor requests data layout. + +// READ_RXTX_SRAM, //C002_AA0B_0C00_0800 Rx/Tx SRAM Read +// WRITE_RXTX_SRAM, //4003_AA0B_0C00_0800 Rx/Tx SRAM Write +// SW_MII_OP, //4006_0000_0000_0000 SW Serial Management Control +// READ_MII, //c007_aa00_cc00_0200 PHY Read +// WRITE_MII, //4008_aa00_cc00_0200 PHY Write +// READ_MII_OP_MODE, //c009_0000_0000_0100 Serial Management Status +// HW_MII_OP, //400a_0000_0000_0000 HW Serial Management Control +// READ_SROM, //C00B_AA00_0000_0200 SROM Read +// WRITE_SROM, //400C_AA00_CCDD_0000 SROM Write +// WRITE_SROM_ENABLE, //400D_0000_0000_0000 SROM Write Enable +// WRITE_SROM_DISABLE, //400E_0000_0000_0000 SROM Write Disable +// READ_RX_CONTROL, //C00F_0000_0000_0200 Read Rx Control +// WRITE_RX_CONTROL, //4010_AABB_0000_0000 Write Rx Control +// READ_IPGS, //C011_0000_0000_0300 Read IPG/IPG1/IPG2 Register +// WRITE_IPGS, //4012_AABB_CC00_0000 Write IPG/IPG1/IPG2 Register +// READ_NODEID, //C013_0000_0000_0600 Read Node ID +// WRITE_NODEID, //4014_0000_0000_0600 Write Node ID +// READ_MF_ARRAY, //C015_0000_0000_0800 Read Multicast Filter Array +// WRITE_MF_ARRAY, //4016_0000_0000_0800 Write Multicast Filter Array +// READ_TEST, //4017_AA00_0000_0000 Write Test Register +// READ_PHYID, //C019_0000_0000_0200 Read Ethernet/HomePNA PHY Address +// READ_MEDIUM_STATUS, //C01A_0000_0000_0200 Read Medium Status +// WRITE_MEDIUM_MODE, //401B_AABB_0000_0000 Write Medium Mode Register +// GET_MONITOR_MODE, //C01C_0000_0000_0100 Read Monitor Mode Status +// SET_MONITOR_MODE, //401D_AA00_0000_0000 Write Monitor Mode Register +// READ_GPIOS, //C01E_0000_0000_0100 Read GPIOs Status +// WRITE_GPIOS, //401F_AA00_0000_0000 Write GPIOs +// WRITE_SOFT_RESET, //4020_AA00_0000_0000 Write Software Reset +// READ_PHY_SEL_STATE, //C021_AA00_0000_0100 Read Software PHY Select Status +// WRITE_PHY_SEL, //4022_AA00_0000_0000 Write Software PHY Select // RX Control Register bits -enum AX88772_RXControl { - RXCTL_PROMISCUOUS = 0x0001, // - RXCTL_ALL_MULTICAT = 0x0002, // -// RXCTL_SEP = 0x0004, // do not set it! - RXCTL_BROADCAST = 0x0008, // - RXCTL_MULTICAST = 0x0010, // - RXCTL_AP = 0x0020, // - RXCTL_START = 0x0080, // - RXCTL_USB_MFB = 0x0100 // Max Frame Burst TX on USB -}; +// RXCTL_PROMISCUOUS, // forward all frames up to the host +// RXCTL_ALL_MULTICAT, // forward all multicast frames up to the host +// RXCTL_SEP, // forward frames with CRC error up to the host +// RXCTL_BROADCAST, // forward broadcast frames up to the host +// RXCTL_MULTICAST, // forward multicast frames that are +// matching to multicast filter up to the host +// RXCTL_AP, // forward unicast frames that are matching +// to multicast filter up to the host +// RXCTL_START, // ethernet MAC start operating +// RXCTL_USB_MFB, // Max Frame Burst TX on USB + // PHY IDs request answer data layout struct AX88772_PhyIDs { @@ -64,6 +74,7 @@ struct AX88772_PhyIDs { uint8 PriPhyID2; } _PACKED; + // Medium state bits enum AX88772_MediumState { MEDIUM_STATE_FD = 0x0002, @@ -80,6 +91,7 @@ enum AX88772_MediumState { MEDIUM_STATE_SM_ON = 0x1000 }; + // Monitor Mode bits enum AX88772_MonitorMode { MONITOR_MODE_MOM = 0x01, @@ -88,6 +100,7 @@ enum AX88772_MonitorMode { MONITOR_MODE_US = 0x10 }; + // General Purpose I/O Register enum AX88772_GPIO { GPIO_OO_0EN = 0x01, @@ -99,6 +112,7 @@ enum AX88772_GPIO { GPIO_RSE = 0x80 }; + // Software Reset Register bits enum AX88772_SoftwareReset { SW_RESET_CLR = 0x00, @@ -111,6 +125,7 @@ enum AX88772_SoftwareReset { SW_RESET_IPPD = 0x40 }; + // Software PHY Select Status enum AX88772_SoftwarePHYSelStatus { SW_PHY_SEL_STATUS_EXT = 0x00, @@ -118,6 +133,7 @@ enum AX88772_SoftwarePHYSelStatus { SW_PHY_SEL_STATUS_ASEL = 0x02 }; + // Notification data layout struct AX88772_Notify { uint8 btA1; @@ -128,6 +144,7 @@ struct AX88772_Notify { uint16 regEEFF; } _PACKED; + // Link-State bits enum AX88772_BBState { LINK_STATE_PPLS = 0x01, @@ -136,10 +153,13 @@ enum AX88772_BBState { LINK_STATE_MDINT = 0x08 }; + const uint16 maxFrameSize = 1536; -AX88772Device::AX88772Device(usb_device device, const char *description) - : ASIXDevice(device, description) + +AX88772Device::AX88772Device(usb_device device, DeviceInfo& deviceInfo) + : + ASIXDevice(device, deviceInfo) { fStatus = InitDevice(); } @@ -152,10 +172,6 @@ AX88772Device::InitDevice() fUseTRXHeader = true; fReadNodeIDRequest = READ_NODEID; - fReadRXControlRequest = READ_RX_CONTROL; - fWriteRXControlRequest = WRITE_RX_CONTROL; - - fPromiscuousBits = RXCTL_PROMISCUOUS; fNotifyBufferLength = sizeof(AX88772_Notify); fNotifyBuffer = (uint8 *)malloc(fNotifyBufferLength); @@ -172,13 +188,11 @@ status_t AX88772Device::SetupDevice(bool deviceReplugged) { status_t result = ASIXDevice::SetupDevice(deviceReplugged); - if(result != B_OK) { + if (result != B_OK) { return result; } - result = fMII.Init(fDevice, - SW_MII_OP, READ_MII, WRITE_MII, - READ_MII_OP_MODE, HW_MII_OP, READ_PHYID); + result = fMII.Init(fDevice); size_t actualLength = 0; // enable GPIO2 - magic from FreeBSD's if_axe @@ -187,7 +201,7 @@ AX88772Device::SetupDevice(bool deviceReplugged) USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_GPIOS, GPIOs, 0, 0, 0, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of wrinting GPIOs: %#010x\n", result); return result; } @@ -205,7 +219,7 @@ AX88772Device::SetupDevice(bool deviceReplugged) TRACE("Selecting %s PHY[%#02x].\n", useEmbeddedPHY ? "embedded" : "external", selectPHY); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of selecting PHY:%#010x\n", result); return result; } @@ -231,7 +245,7 @@ AX88772Device::SetupDevice(bool deviceReplugged) size_t from = useEmbeddedPHY ? 0 : 4; size_t to = useEmbeddedPHY ? 3 : 4; - for(size_t i = from; i <= to; i++) { + for (size_t i = from; i <= to; i++) { result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_SOFT_RESET, resetCommands[i].reset, @@ -239,7 +253,7 @@ AX88772Device::SetupDevice(bool deviceReplugged) snooze(resetCommands[i].delay); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of SW reset command %d:[%#04x]: %#010x\n", i, resetCommands[i].reset, result); return result; @@ -249,13 +263,13 @@ AX88772Device::SetupDevice(bool deviceReplugged) snooze(150000); result = WriteRXControlRegister(0); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); return result; } result = fMII.SetupPHY(); - if(result != B_OK) { + if (result != B_OK) { return result; } @@ -267,7 +281,7 @@ AX88772Device::SetupDevice(bool deviceReplugged) MEDIUM_STATE_RE | MEDIUM_STATE_PS_100, 0, 0, 0, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of setting medium mode: %#010x\n", result); } @@ -284,20 +298,21 @@ AX88772Device::StartDevice() USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_IPGS, 0, 0, sizeof(fIPG), fIPG, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of writing IPGs:%#010x\n", result); return result; } - if(actualLength != sizeof(fIPG)) { + if (actualLength != sizeof(fIPG)) { TRACE_ALWAYS("Mismatch of written IPGs data. " "%d bytes of %d written.\n", actualLength, sizeof(fIPG)); } - uint16 rxcontrol = RXCTL_START | RXCTL_MULTICAST | RXCTL_BROADCAST; + uint16 rxcontrol = RXCTL_START | RXCTL_BROADCAST; result = WriteRXControlRegister(rxcontrol); - if(result != B_OK) { - TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result); + if (result != B_OK) { + TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", + rxcontrol, result); } TRACE_RET(result); @@ -316,7 +331,7 @@ AX88772Device::OnNotify(uint32 actualLength) AX88772_Notify *notification = (AX88772_Notify *)fNotifyBuffer; - if(notification->btA1 != 0xa1) { + if (notification->btA1 != 0xa1) { TRACE_ALWAYS("Notify magic byte is invalid: %#02x\n", notification->btA1); } @@ -341,7 +356,7 @@ AX88772Device::OnNotify(uint32 actualLength) bool linkStateChange = linkIsUp != fHasConnection; fHasConnection = linkIsUp; - if(linkStateChange) { + if (linkStateChange) { TRACE("Link state of PHY%d has been changed to '%s'\n", phyIndex, fHasConnection ? "up" : "down"); } @@ -363,12 +378,12 @@ AX88772Device::GetLinkState(ether_link_state *linkState) READ_MEDIUM_STATUS, 0, 0, sizeof(mediumStatus), &mediumStatus, &actualLength); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of reading medium status:%#010x.\n", result); return result; } - if(actualLength != sizeof(mediumStatus)) { + if (actualLength != sizeof(mediumStatus)) { TRACE_ALWAYS("Mismatch of reading medium status." "Read %d bytes instead of %d\n", actualLength, sizeof(mediumStatus)); @@ -379,14 +394,15 @@ AX88772Device::GetLinkState(ether_link_state *linkState) 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) ? 100000000 : 10000000; + 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, + linkState->speed / 1000000, (linkState->media & IFM_FULL_DUPLEX) ? "full" : "half"); return B_OK; } diff --git a/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.h b/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.h index ed7546d97b..0fd70a6685 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.h +++ b/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.h @@ -1,29 +1,30 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ - #ifndef _USB_AX88772_DEVICE_H_ #define _USB_AX88772_DEVICE_H_ + #include "ASIXDevice.h" + class AX88772Device : public ASIXDevice { public: - AX88772Device(usb_device device, const char *description); + AX88772Device(usb_device device, DeviceInfo& info); protected: status_t InitDevice(); virtual status_t SetupDevice(bool deviceReplugged); virtual status_t StartDevice(); virtual status_t OnNotify(uint32 actualLength); -virtual status_t GetLinkState(ether_link_state *state); +virtual status_t GetLinkState(ether_link_state *state); }; -#endif //_USB_AX88772_DEVICE_H_ +#endif // _USB_AX88772_DEVICE_H_ diff --git a/src/add-ons/kernel/drivers/network/usb_asix/Driver.cpp b/src/add-ons/kernel/drivers/network/usb_asix/Driver.cpp index e1135a28ce..ef397ef6c7 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/Driver.cpp +++ b/src/add-ons/kernel/drivers/network/usb_asix/Driver.cpp @@ -1,6 +1,6 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * Distributed under the terms of the MIT license. * * Heavily based on code of the @@ -10,71 +10,62 @@ * */ -#include -#include -#include - -#ifdef HAIKU_TARGET_PLATFORM_HAIKU -#include // for mutex -#else -#include "BeOSCompatibility.h" // for pseudo mutex -#endif #include "Driver.h" -#include "Settings.h" + +#include + +#include // for mutex +#include + #include "AX88172Device.h" -#include "AX88772Device.h" #include "AX88178Device.h" +#include "AX88772Device.h" +#include "Settings.h" + int32 api_version = B_CUR_DRIVER_API_VERSION; static const char *sDeviceBaseName = "net/usb_asix/"; ASIXDevice *gASIXDevices[MAX_DEVICES]; char *gDeviceNames[MAX_DEVICES + 1]; usb_module_info *gUSBModule = NULL; - mutex gDriverLock; -// auto-release helper class -class DriverSmartLock { -public: - DriverSmartLock() { mutex_lock(&gDriverLock); } - ~DriverSmartLock() { mutex_unlock(&gDriverLock); } -}; -usb_support_descriptor gSupportedDevices[] = { - // AX88172 - { 0, 0, 0, 0x0b95, 0x1720}, // "ASIX 88172 10/100" - { 0, 0, 0, 0x07b8, 0x420a}, // "ABOCOM UF200" - { 0, 0, 0, 0x1189, 0x0893}, // "Acer C&M EP-1427X-2" - { 0, 0, 0, 0x0557, 0x2009}, // "ATEN UC-210T" - { 0, 0, 0, 0x08dd, 0x90ff}, // "Billionton USB2AR" - { 0, 0, 0, 0x07aa, 0x0017}, // "Corega USB2TX" - { 0, 0, 0, 0x2001, 0x1A00}, // "D-Link DUB-E100" - { 0, 0, 0, 0x1631, 0x6200}, // "GoodWay USB2Ethernet" - { 0, 0, 0, 0x04f1, 0x3008}, // "JVC MP-PRX1" - { 0, 0, 0, 0x077b, 0x2226}, // "LinkSys USB 2.0" - { 0, 0, 0, 0x0411, 0x003d}, // "Melco LUA-U2-KTX" - { 0, 0, 0, 0x0846, 0x1040}, // "NetGear USB 2.0 Ethernet" - { 0, 0, 0, 0x086e, 0x1920}, // "System TALKS SGC-X2UL" - { 0, 0, 0, 0x6189, 0x182d}, // "Sitecom LN-029" - // AX88772 - { 0, 0, 0, 0x0b95, 0x7720}, // "ASIX 88772 10/100" - { 0, 0, 0, 0x13b1, 0x0018}, // "Linksys USB200M rev.2" - { 0, 0, 0, 0x07d1, 0x3c05}, // alternate D-Link DUB-E100 rev. B1 - { 0, 0, 0, 0x2001, 0x3c05}, // "D-Link DUB-E100 rev.B1" - { 0, 0, 0, 0x1557, 0x7720}, // "OQO 01+ Ethernet" - { 0, 0, 0, 0x05ac, 0x1402}, // "Apple A1277" - // AX88178 - { 0, 0, 0, 0x0b95, 0x1780}, // "ASIX 88178 10/100/1000" - { 0, 0, 0, 0x050d, 0x5055}, // "Belkin F5D5055" - { 0, 0, 0, 0x04bb, 0x0930}, // "I/O Data ETG-US2" - { 0, 0, 0, 0x1737, 0x0039}, // "LinkSys 1000" - { 0, 0, 0, 0x14ea, 0xab11}, // "Planex GU-1000T" - { 0, 0, 0, 0x0df6, 0x061c} // "Sitecom LN-028" -}; + +// IMPORTANT: keep entries sorted by ids to let the +// binary search lookup procedure work correctly !!! +DeviceInfo gSupportedDevices[] = { + { { { 0x0411, 0x003d } }, DeviceInfo::AX88172, "Melco LUA-U2-KTX" }, + { { { 0x04bb, 0x0930 } }, DeviceInfo::AX88178, "I/O Data ETG-US2" }, + { { { 0x04f1, 0x3008 } }, DeviceInfo::AX88172, "JVC MP-PRX1" }, + { { { 0x050d, 0x5055 } }, DeviceInfo::AX88178, "Belkin F5D5055" }, + { { { 0x0557, 0x2009 } }, DeviceInfo::AX88172, "ATEN UC-210T" }, + { { { 0x05ac, 0x1402 } }, DeviceInfo::AX88772, "Apple A1277" }, + { { { 0x077b, 0x2226 } }, DeviceInfo::AX88172, "LinkSys USB 2.0" }, + { { { 0x07aa, 0x0017 } }, DeviceInfo::AX88172, "Corega USB2TX" }, + { { { 0x07b8, 0x420a } }, DeviceInfo::AX88172, "ABOCOM UF200" }, + { { { 0x07d1, 0x3c05 } }, DeviceInfo::AX88772, "D-Link DUB-E100 rev.B1" }, + { { { 0x0846, 0x1040 } }, DeviceInfo::AX88172, "NetGear USB 2.0 Ethernet" }, + { { { 0x086e, 0x1920 } }, DeviceInfo::AX88172, "System TALKS SGC-X2UL" }, + { { { 0x08dd, 0x90ff } }, DeviceInfo::AX88172, "Billionton USB2AR" }, + { { { 0x0b95, 0x1720 } }, DeviceInfo::AX88172, "ASIX 88172 10/100" }, + { { { 0x0b95, 0x1780 } }, DeviceInfo::AX88178, "ASIX 88178 10/100/1000" }, + { { { 0x0b95, 0x7720 } }, DeviceInfo::AX88772, "ASIX 88772 10/100" }, + { { { 0x0df6, 0x061c } }, DeviceInfo::AX88178, "Sitecom LN-028" }, + { { { 0x1189, 0x0893 } }, DeviceInfo::AX88172, "Acer C&M EP-1427X-2" }, + { { { 0x13b1, 0x0018 } }, DeviceInfo::AX88772, "Linksys USB200M rev.2" }, + { { { 0x14ea, 0xab11 } }, DeviceInfo::AX88178, "Planex GU-1000T" }, + { { { 0x1557, 0x7720 } }, DeviceInfo::AX88772, "OQO 01+ Ethernet" }, + { { { 0x1631, 0x6200 } }, DeviceInfo::AX88172, "GoodWay USB2Ethernet" }, + { { { 0x1737, 0x0039 } }, DeviceInfo::AX88178, "LinkSys 1000" }, + { { { 0x2001, 0x1A00 } }, DeviceInfo::AX88172, "D-Link DUB-E100" }, + { { { 0x2001, 0x3c05 } }, DeviceInfo::AX88772, "D-Link DUB-E100 rev.B1" }, + { { { 0x6189, 0x182d } }, DeviceInfo::AX88172, "Sitecom LN-029" } +}; ASIXDevice * -create_asix_device(usb_device device) +lookup_and_create_device(usb_device device) { const usb_device_descriptor *deviceDescriptor = gUSBModule->get_device_descriptor(device); @@ -84,39 +75,34 @@ create_asix_device(usb_device device) return NULL; } -#define IDS(__vendor, __product) (((__vendor) << 16) | (__product)) - - switch(IDS(deviceDescriptor->vendor_id, deviceDescriptor->product_id)) { - // AX88172 - case IDS(0x0b95, 0x1720): return new AX88172Device(device, "ASIX 88172 10/100"); - case IDS(0x07b8, 0x420a): return new AX88172Device(device, "ABOCOM UF200"); - case IDS(0x1189, 0x0893): return new AX88172Device(device, "Acer C&M EP-1427X-2"); - case IDS(0x0557, 0x2009): return new AX88172Device(device, "ATEN UC-210T"); - case IDS(0x08dd, 0x90ff): return new AX88172Device(device, "Billionton USB2AR"); - case IDS(0x07aa, 0x0017): return new AX88172Device(device, "Corega USB2TX"); - case IDS(0x2001, 0x1A00): return new AX88172Device(device, "D-Link DUB-E100"); - case IDS(0x1631, 0x6200): return new AX88172Device(device, "GoodWay USB2Ethernet"); - case IDS(0x04f1, 0x3008): return new AX88172Device(device, "JVC MP-PRX1"); - case IDS(0x077b, 0x2226): return new AX88172Device(device, "LinkSys USB 2.0"); - case IDS(0x0411, 0x003d): return new AX88172Device(device, "Melco LUA-U2-KTX"); - case IDS(0x0846, 0x1040): return new AX88172Device(device, "NetGear USB 2.0 Ethernet"); - case IDS(0x086e, 0x1920): return new AX88172Device(device, "System TALKS SGC-X2UL"); - case IDS(0x6189, 0x182d): return new AX88172Device(device, "Sitecom LN-029"); - // AX88772 - case IDS(0x0b95, 0x7720): return new AX88772Device(device, "ASIX 88772 10/100"); - case IDS(0x13b1, 0x0018): return new AX88772Device(device, "Linksys USB200M rev.2"); - case IDS(0x07d1, 0x3c05): // alternate D-Link DUB-E100 rev. B1 - case IDS(0x2001, 0x3c05): return new AX88772Device(device, "D-Link DUB-E100 rev.B1"); - case IDS(0x1557, 0x7720): return new AX88772Device(device, "OQO 01+ Ethernet"); - case IDS(0x05ac, 0x1402): return new AX88772Device(device, "Apple A1277"); - // AX88178 - case IDS(0x0b95, 0x1780): return new AX88178Device(device, "ASIX 88178 10/100/1000"); - case IDS(0x050d, 0x5055): return new AX88178Device(device, "Belkin F5D5055"); - case IDS(0x04bb, 0x0930): return new AX88178Device(device, "I/O Data ETG-US2"); - case IDS(0x1737, 0x0039): return new AX88178Device(device, "LinkSys 1000"); - case IDS(0x14ea, 0xab11): return new AX88178Device(device, "Planex GU-1000T"); - case IDS(0x0df6, 0x061c): return new AX88178Device(device, "Sitecom LN-028"); + TRACE("trying %#06x:%#06x.\n", + deviceDescriptor->vendor_id, deviceDescriptor->product_id); + + // use binary search to lookup device in table + DeviceInfo::Id id = { { deviceDescriptor->vendor_id, + deviceDescriptor->product_id } }; + int left = -1; + int right = _countof(gSupportedDevices); + while ((right - left) > 1) { + int i = (left + right) / 2; + ((gSupportedDevices[i].Key() < id.fKey) ? left : right) = i; } + + if (gSupportedDevices[right].Key() == id.fKey) { + switch (gSupportedDevices[right].fType) { + case DeviceInfo::AX88172: + return new AX88172Device(device, gSupportedDevices[right]); + case DeviceInfo::AX88772: + return new AX88772Device(device, gSupportedDevices[right]); + case DeviceInfo::AX88178: + return new AX88178Device(device, gSupportedDevices[right]); + default: + TRACE_ALWAYS("Unknown device type:%#x ignored.\n", + static_cast(gSupportedDevices[right].fType)); + break; + } + } + return NULL; } @@ -126,7 +112,7 @@ usb_asix_device_added(usb_device device, void **cookie) { *cookie = NULL; - DriverSmartLock driverLock; // released on exit + MutexLocker lock(gDriverLock); // released on exit // check if this is a replug of an existing device first for (int32 i = 0; i < MAX_DEVICES; i++) { @@ -142,7 +128,7 @@ usb_asix_device_added(usb_device device, void **cookie) } // no such device yet, create a new one - ASIXDevice *asixDevice = create_asix_device(device); + ASIXDevice *asixDevice = lookup_and_create_device(device); if (asixDevice == 0) { return ENODEV; } @@ -181,7 +167,7 @@ usb_asix_device_added(usb_device device, void **cookie) status_t usb_asix_device_removed(void *cookie) { - DriverSmartLock driverLock; // released on exit + MutexLocker lock(gDriverLock); // released on exit ASIXDevice *device = (ASIXDevice *)cookie; for (int32 i = 0; i < MAX_DEVICES; i++) { @@ -202,7 +188,7 @@ usb_asix_device_removed(void *cookie) } -//#pragma mark - +// #pragma mark - status_t @@ -235,9 +221,17 @@ init_driver() &usb_asix_device_removed }; - gUSBModule->register_driver(DRIVER_NAME, gSupportedDevices, - sizeof(gSupportedDevices) / sizeof(usb_support_descriptor), NULL); + const size_t count = _countof(gSupportedDevices); + static usb_support_descriptor sDescriptors[count] = {{ 0 }}; + + for(size_t i = 0; i < count; i++) { + sDescriptors[i].vendor = gSupportedDevices[i].VendorId(); + sDescriptors[i].product = gSupportedDevices[i].ProductId(); + } + + gUSBModule->register_driver(DRIVER_NAME, sDescriptors, count, NULL); gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); + return B_OK; } @@ -270,7 +264,7 @@ uninit_driver() static status_t usb_asix_open(const char *name, uint32 flags, void **cookie) { - DriverSmartLock driverLock; // released on exit + MutexLocker lock(gDriverLock); // released on exit *cookie = NULL; status_t status = ENODEV; @@ -322,7 +316,7 @@ usb_asix_free(void *cookie) { ASIXDevice *device = (ASIXDevice *)cookie; - DriverSmartLock driverLock; // released on exit + MutexLocker lock(gDriverLock); // released on exit status_t status = device->Free(); for (int32 i = 0; i < MAX_DEVICES; i++) { @@ -348,7 +342,7 @@ publish_devices() gDeviceNames[i] = NULL; } - DriverSmartLock driverLock; // released on exit + MutexLocker lock(gDriverLock); // released on exit int32 deviceCount = 0; for (int32 i = 0; i < MAX_DEVICES; i++) { @@ -361,7 +355,7 @@ publish_devices() TRACE("publishing %s\n", gDeviceNames[deviceCount]); deviceCount++; } else - TRACE_ALWAYS("Error: out of memory during allocating device name.\n"); + TRACE_ALWAYS("Error: out of memory during allocating dev.name.\n"); } gDeviceNames[deviceCount] = NULL; diff --git a/src/add-ons/kernel/drivers/network/usb_asix/Driver.h b/src/add-ons/kernel/drivers/network/usb_asix/Driver.h index 7c718d191f..9ff1ece038 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/Driver.h +++ b/src/add-ons/kernel/drivers/network/usb_asix/Driver.h @@ -1,39 +1,31 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ - #ifndef _USB_ASIX_DRIVER_H_ #define _USB_ASIX_DRIVER_H_ -#include -#include + #include #include -#include -#include -#include -#include -#include -#include #define DRIVER_NAME "usb_asix" #define MAX_DEVICES 8 + const uint8 kInvalidRequest = 0xff; - -const char* const kVersion = "ver.0.8.3"; - +const char* const kVersion = "ver.0.9.1"; extern usb_module_info *gUSBModule; + extern "C" { status_t usb_asix_device_added(usb_device device, void **cookie); status_t usb_asix_device_removed(void *cookie); @@ -46,5 +38,5 @@ device_hooks *find_device(const char *name); } -#endif //_USB_ASIX_DRIVER_H_ +#endif // _USB_ASIX_DRIVER_H_ diff --git a/src/add-ons/kernel/drivers/network/usb_asix/Jamfile b/src/add-ons/kernel/drivers/network/usb_asix/Jamfile index 3b79667da6..ac2fc29568 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/Jamfile +++ b/src/add-ons/kernel/drivers/network/usb_asix/Jamfile @@ -3,6 +3,7 @@ SubDir HAIKU_TOP src add-ons kernel drivers network usb_asix ; SetSubDirSupportedPlatformsBeOSCompatible ; UsePrivateHeaders kernel net ; +UsePrivateKernelHeaders ; KernelAddon usb_asix : Driver.cpp diff --git a/src/add-ons/kernel/drivers/network/usb_asix/MIIBus.cpp b/src/add-ons/kernel/drivers/network/usb_asix/MIIBus.cpp index 235834143e..0906be8e37 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/MIIBus.cpp +++ b/src/add-ons/kernel/drivers/network/usb_asix/MIIBus.cpp @@ -1,105 +1,95 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ + +#include "MIIBus.h" + +#include "ASIXVendorRequests.h" #include "Driver.h" #include "Settings.h" -#include "MIIBus.h" + #define MII_OUI(id1, id2) (((id1) << 6) | ((id2) >> 10)) #define MII_MODEL(id2) (((id2) & 0x03f0) >> 4) #define MII_REV(id2) ((id2) & 0x000f) -MIIBus::MIIBus() : fDevice(0), - fSelectedPHY(CurrentPHY), - fSWOperationRequest(kInvalidRequest), - fReadValueRequest(kInvalidRequest), - fWriteValueRequest(kInvalidRequest), - fReadStatusRequest(kInvalidRequest), - fHWOperationRequest(kInvalidRequest), - fReadPHYIDsRequest(kInvalidRequest) + +MIIBus::MIIBus() + : + fStatus(B_NO_INIT), + fDevice(0), + fSelectedPHY(CurrentPHY) { - for(size_t i = 0; i < PHYsCount; i++) { + for (size_t i = 0; i < PHYsCount; i++) { fPHYs[i] = PHYNotInstalled; } } -status_t -MIIBus::Init(usb_device device, - uint8 SWOperationRequest, - uint8 ReadValueRequest, - uint8 WriteValueRequest, - uint8 ReadStatusRequest, - uint8 HWOperationRequest, - uint8 ReadPHYIDsRequest) +status_t +MIIBus::Init(usb_device device) { - fSWOperationRequest = SWOperationRequest; - fReadValueRequest = ReadValueRequest; - fWriteValueRequest = WriteValueRequest; - fReadStatusRequest = ReadStatusRequest; - fHWOperationRequest = HWOperationRequest; - fReadPHYIDsRequest = ReadPHYIDsRequest; - - // reset to default state + // reset to default state fDevice = 0; fSelectedPHY = CurrentPHY; - for(size_t i = 0; i < PHYsCount; i++) { + for (size_t i = 0; i < PHYsCount; i++) { fPHYs[i] = PHYNotInstalled; } - + size_t actual_length = 0; - status_t result = gUSBModule->send_request(device, + status_t result = gUSBModule->send_request(device, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN, - fReadPHYIDsRequest, 0, 0, sizeof(fPHYs), fPHYs, &actual_length); - - if(result != B_OK) { + READ_PHYID, 0, 0, sizeof(fPHYs), fPHYs, &actual_length); + + if (result != B_OK) { TRACE_ALWAYS("Request of the PHYIDs failed:%#010x\n", result); return result; } - if(sizeof(fPHYs) != actual_length) { - TRACE_ALWAYS("Mismatch of reading %d PHYIDs bytes instead of %d.\n", + if (sizeof(fPHYs) != actual_length) { + TRACE_ALWAYS("Mismatch of reading %d PHYIDs bytes instead of %d.\n", actual_length, sizeof(fPHYs)); } TRACE("PHYIDs are:%#02x:%#02x\n", fPHYs[0], fPHYs[1]); - + // simply tactic - we use first available PHY - if(PHYType(PrimaryPHY) != PHYNotInstalled) { + if (PHYType(PrimaryPHY) != PHYNotInstalled) { fSelectedPHY = PrimaryPHY; - } else - if(PHYType(SecondaryPHY) != PHYNotInstalled) { + } else + if (PHYType(SecondaryPHY) != PHYNotInstalled) { fSelectedPHY = SecondaryPHY; } - TRACE("PHYs are configured: Selected:%#02x; Primary:%#02x; Secondary:%#02x\n", + TRACE("PHYs are configured: Selected:%#02x; Primary:%#02x; 2ndary:%#02x\n", PHYID(CurrentPHY), PHYID(PrimaryPHY), PHYID(SecondaryPHY)); - if(fSelectedPHY == CurrentPHY) { + if (fSelectedPHY == CurrentPHY) { TRACE_ALWAYS("No PHYs found!\n"); - return B_ENTRY_NOT_FOUND; + return B_ENTRY_NOT_FOUND; } fDevice = device; - - return result; + fStatus = result; + + return fStatus; } -status_t +status_t MIIBus::SetupPHY() { uint16 control = 0; status_t result = Read(MII_BMCR, &control); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of reading control word:%#010x.\n", result); return result; } @@ -108,128 +98,121 @@ MIIBus::SetupPHY() control &= ~BMCR_Isolate; result = Write(MII_BMCR, control); - if(result != B_OK) { - TRACE_ALWAYS("Error of writing control word %#04x:%#010x.\n", control, result); + if (result != B_OK) { + TRACE_ALWAYS("Error of writing control word %#04x:%#010x.\n", + control, result); } result = Write(MII_BMCR, BMCR_Reset); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of resetting PHY:%#010x.\n", result); } uint16 id01 = 0, id02 = 0; result = Read(MII_PHYID0, &id01); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of reading PHY ID1:%#010x.\n", result); } result = Read(MII_PHYID1, &id02); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of reading PHY ID2:%#010x.\n", result); } - TRACE("MII Info: OUI:%04x; Model:%04x; rev:%02x.\n", + TRACE("MII Info: OUI:%04x; Model:%04x; rev:%02x.\n", MII_OUI(id01, id02), MII_MODEL(id02), MII_REV(id02)); - //Dump(); - + // Dump(); + return result; } -status_t +status_t MIIBus::InitCheck() { if (fSelectedPHY == CurrentPHY) { return B_ENTRY_NOT_FOUND; } - if(fSWOperationRequest == kInvalidRequest || - fReadValueRequest == kInvalidRequest || - fWriteValueRequest == kInvalidRequest || - fReadStatusRequest == kInvalidRequest || - fHWOperationRequest == kInvalidRequest || - fReadPHYIDsRequest == kInvalidRequest) { - return B_NO_INIT; - } - - return B_OK; + return fStatus; } uint8 MIIBus::PHYID(PHYIndex phyIndex /*= CurrentPHY*/) -{ - if(phyIndex == CurrentPHY) { - return (fSelectedPHY == CurrentPHY ? - 0 : fPHYs[fSelectedPHY]) & PHYIDMask; +{ + if (phyIndex == CurrentPHY) { + return (fSelectedPHY == CurrentPHY + ? 0 : fPHYs[fSelectedPHY]) & PHYIDMask; } - + return fPHYs[phyIndex] & PHYIDMask; } uint8 MIIBus::PHYType(PHYIndex phyIndex /*= CurrentPHY*/) -{ - if(phyIndex == CurrentPHY) { - return (fSelectedPHY == CurrentPHY ? - PHYNotInstalled : fPHYs[fSelectedPHY]) & PHYTypeMask; +{ + if (phyIndex == CurrentPHY) { + return (fSelectedPHY == CurrentPHY + ? PHYNotInstalled : fPHYs[fSelectedPHY]) & PHYTypeMask; } - + return fPHYs[phyIndex] & PHYTypeMask; } -status_t -MIIBus::Read(uint16 miiRegister, uint16 *value, PHYIndex phyIndex /*= CurrentPHY*/) + +status_t +MIIBus::Read(uint16 miiRegister, uint16 *value, PHYIndex phyIndex /*= CurrPHY*/) { status_t result = InitCheck(); - if(B_OK != result) { + if (B_OK != result) { TRACE_ALWAYS("Error: MII is not ready:%#010x\n", result); return result; } - if(PHYType(phyIndex) == PHYNotInstalled) { + if (PHYType(phyIndex) == PHYNotInstalled) { TRACE_ALWAYS("Error: Invalid PHY index:%#02x.\n", phyIndex); - return B_ENTRY_NOT_FOUND; + return B_ENTRY_NOT_FOUND; } uint16 phyId = PHYID(phyIndex); - - size_t actual_length = 0; - // switch to SW operation mode - result = gUSBModule->send_request(fDevice, - USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - fSWOperationRequest, 0, 0, 0, 0, &actual_length); - if(result != B_OK) { + size_t actual_length = 0; + // switch to SW operation mode + result = gUSBModule->send_request(fDevice, + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + SW_MII_OP, 0, 0, 0, 0, &actual_length); + + if (result != B_OK) { TRACE_ALWAYS("Error of switching MII to SW op.mode: %#010x\n", result); return result; } - // read register value - status_t op_result = gUSBModule->send_request(fDevice, + // read register value + status_t op_result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN, - fReadValueRequest, phyId, miiRegister, + READ_MII, phyId, miiRegister, sizeof(*value), value, &actual_length); - if(op_result != B_OK) { - TRACE_ALWAYS("Error of reading MII reg.%d at PHY%d:%#010x.\n", + if (op_result != B_OK) { + TRACE_ALWAYS("Error of reading MII reg.%d at PHY%d:%#010x.\n", miiRegister, phyId, op_result); } - if(sizeof(*value) != actual_length) { + if (sizeof(*value) != actual_length) { TRACE_ALWAYS("Mismatch of reading MII reg.%d at PHY %d. " "Read %d bytes instead of %d.\n", miiRegister, phyId, actual_length, sizeof(*value)); } - // switch to HW operation mode - result = gUSBModule->send_request(fDevice, + // switch to HW operation mode + result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - fHWOperationRequest, 0, 0, 0, 0, &actual_length); + HW_MII_OP, 0, 0, 0, 0, &actual_length); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of switching MII to HW op.mode: %#010x\n", result); } @@ -237,57 +220,57 @@ MIIBus::Read(uint16 miiRegister, uint16 *value, PHYIndex phyIndex /*= CurrentPHY } -status_t -MIIBus::Write(uint16 miiRegister, uint16 value, PHYIndex phyIndex /*= CurrentPHY*/) +status_t +MIIBus::Write(uint16 miiRegister, uint16 value, PHYIndex phyIndex /*= CurrPHY*/) { size_t actual_length = 0; status_t result = InitCheck(); - if(B_OK != result) { + if (B_OK != result) { TRACE_ALWAYS("Error: MII is not ready:%#010x\n", result); return result; } - if(PHYType(phyIndex) == PHYNotInstalled) { + if (PHYType(phyIndex) == PHYNotInstalled) { TRACE_ALWAYS("Error: Invalid PHY index:%#02x\n", phyIndex); - return B_ENTRY_NOT_FOUND; + return B_ENTRY_NOT_FOUND; } uint16 phyId = PHYID(phyIndex); - // switch to SW operation mode - result = gUSBModule->send_request(fDevice, + // switch to SW operation mode + result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - fSWOperationRequest, 0, 0, 0, 0, &actual_length); + SW_MII_OP, 0, 0, 0, 0, &actual_length); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of switching MII to SW op.mode: %#010x\n", result); return result; } // write register value - status_t op_result = gUSBModule->send_request(fDevice, + status_t op_result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - fWriteValueRequest, phyId, miiRegister, + WRITE_MII, phyId, miiRegister, sizeof(value), &value, &actual_length); - if(op_result != B_OK) { - TRACE_ALWAYS("Error of writing MII reg.%d at PHY %d:%#010x.\n", + if (op_result != B_OK) { + TRACE_ALWAYS("Error of writing MII reg.%d at PHY %d:%#010x.\n", miiRegister, phyId, op_result); } - if(sizeof(value) != actual_length) { + if (sizeof(value) != actual_length) { TRACE_ALWAYS("Mismatch of writing MII reg.%d at PHY %d." - "Write %d bytes instead of %d.\n", + "Write %d bytes instead of %d.\n", miiRegister, phyId, actual_length, sizeof(value)); } // switch to HW operation mode - result = gUSBModule->send_request(fDevice, + result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - fHWOperationRequest, 0, 0, 0, 0, &actual_length); + HW_MII_OP, 0, 0, 0, 0, &actual_length); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of switching MII to HW op.mode: %#010x\n", result); } @@ -295,75 +278,76 @@ MIIBus::Write(uint16 miiRegister, uint16 value, PHYIndex phyIndex /*= CurrentPHY } -status_t +status_t MIIBus::Status(uint16 *status, PHYIndex phyIndex /*= CurrentPHY*/) { return Read(MII_BMSR, status, phyIndex); } -status_t + +status_t MIIBus::Dump() { status_t result = InitCheck(); - if(B_OK != result) { + if (B_OK != result) { TRACE_ALWAYS("Error: MII is not ready:%#010x.\n", result); return result; } - if(PHYType(CurrentPHY) == PHYNotInstalled) { + if (PHYType(CurrentPHY) == PHYNotInstalled) { TRACE_ALWAYS("Error: Current PHY index is invalid!\n"); - return B_ENTRY_NOT_FOUND; + return B_ENTRY_NOT_FOUND; } uint16 phyId = PHYID(CurrentPHY); size_t actual_length = 0; - // switch to SW operation mode - result = gUSBModule->send_request(fDevice, + // switch to SW operation mode + result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - fSWOperationRequest, 0, 0, 0, 0, &actual_length); + SW_MII_OP, 0, 0, 0, 0, &actual_length); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of switching MII to SW op.mode: %#010x\n", result); return result; } - uint8 regs[] = { MII_BMCR, MII_BMSR, - MII_PHYID0, MII_PHYID1, + uint8 regs[] = { MII_BMCR, MII_BMSR, + MII_PHYID0, MII_PHYID1, MII_ANAR, MII_ANLPAR/*, MII_ANER*/}; - uint16 value = 0; - for(size_t i = 0; i < sizeof(regs)/ sizeof(regs[0]); i++) { + uint16 value = 0; + for (size_t i = 0; i < sizeof(regs)/ sizeof(regs[0]); i++) { - // read register value - status_t op_result = gUSBModule->send_request(fDevice, + // read register value + status_t op_result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN, - fReadValueRequest, phyId, regs[i], + READ_MII, phyId, regs[i], sizeof(value), &value, &actual_length); - if(op_result != B_OK) { - TRACE_ALWAYS("Error of reading MII reg.%d at PHY%d:%#010x.\n", + if (op_result != B_OK) { + TRACE_ALWAYS("Error of reading MII reg.%d at PHY%d:%#010x.\n", regs[i], phyId, op_result); } - if(sizeof(value) != actual_length) { + if (sizeof(value) != actual_length) { TRACE_ALWAYS("Mismatch of reading MII reg.%d at PHY%d." - " Read %d bytes instead of %d.\n", + " Read %d bytes instead of %d.\n", regs[i], phyId, actual_length, sizeof(value)); } TRACE_ALWAYS("MII reg: %d has %#04x\n", regs[i], value); } - // switch to HW operation mode - result = gUSBModule->send_request(fDevice, + // switch to HW operation mode + result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, - fHWOperationRequest, 0, 0, 0, 0, &actual_length); + HW_MII_OP, 0, 0, 0, 0, &actual_length); - if(result != B_OK) { + if (result != B_OK) { TRACE_ALWAYS("Error of switching MII to HW op.mode: %#010x\n", result); } return result; - + } diff --git a/src/add-ons/kernel/drivers/network/usb_asix/MIIBus.h b/src/add-ons/kernel/drivers/network/usb_asix/MIIBus.h index 2a719998fb..153ee3579f 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/MIIBus.h +++ b/src/add-ons/kernel/drivers/network/usb_asix/MIIBus.h @@ -1,20 +1,21 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ - #ifndef _USB_MII_BUS_H_ #define _USB_MII_BUS_H_ + #include "Driver.h" + enum MII_Register { MII_BMCR = 0x00, MII_BMSR = 0x01, @@ -23,7 +24,8 @@ enum MII_Register { MII_ANAR = 0x04, MII_ANLPAR = 0x05, MII_ANER = 0x06 -}; +}; + enum MII_BMCR { BMCR_Reset = 0x8000, @@ -37,24 +39,26 @@ enum MII_BMCR { BMCR_CollTest = 0x0080 }; + enum MII_BMSR { BMSR_CAP_100BASE_T4 = 0x8000, // PHY is able to perform 100base-T4 - BMSR_CAP_100BASE_TXFD = 0x4000, // PHY is able to perform 100base-TX full duplex - BMSR_CAP_100BASE_TXHD = 0x2000, // PHY is able to perform 100base-TX half duplex - BMSR_CAP_10BASE_TXFD = 0x1000, // PHY is able to perform 10base-TX full duplex - BMSR_CAP_10BASE_TXHD = 0x0800, // PHY is able to perform 10base-TX half duplex - BMSR_MFPS = 0x0040, // Management frame preamble supression - BMSR_ANC = 0x0020, // Auto-negotiation complete - BMSR_RF = 0x0010, // Remote fault - BMSR_CAP_AN = 0x0008, // PHY is able to perform auto-negotiation - BMSR_Link = 0x0004, // link state - BMSR_Jabber = 0x0002, // Jabber condition detected + BMSR_CAP_100BASE_TXFD = 0x4000, // PHY is able to perform 100base-TX FD + BMSR_CAP_100BASE_TXHD = 0x2000, // PHY is able to perform 100base-TX HD + BMSR_CAP_10BASE_TXFD = 0x1000, // PHY is able to perform 10base-TX FD + BMSR_CAP_10BASE_TXHD = 0x0800, // PHY is able to perform 10base-TX HD + BMSR_MFPS = 0x0040, // Management frame preamble supression + BMSR_ANC = 0x0020, // Auto-negotiation complete + BMSR_RF = 0x0010, // Remote fault + BMSR_CAP_AN = 0x0008, // PHY is able to perform a-negotiation + BMSR_Link = 0x0004, // link state + BMSR_Jabber = 0x0002, // Jabber condition detected BMSR_CAP_Ext = 0x0001 // Extended register capable }; + enum MII_ANAR { ANAR_NP = 0x8000, // Next page available - ANAR_ACK = 0x4000, // Link partner data reception ability acknowledged + ANAR_ACK = 0x4000, // Link partner data reception ability ack-ed ANAR_RF = 0x2000, // Fault condition detected and advertised ANAR_PAUSE = 0x0400, // Pause operation enabled for full-duplex links ANAR_T4 = 0x0200, // 100BASE-T4 supported @@ -62,40 +66,42 @@ enum MII_ANAR { ANAR_TX_HD = 0x0080, // 100BASE-TX half duplex supported ANAR_10_FD = 0x0040, // 10BASE-TX full duplex supported ANAR_10_HD = 0x0020, // 10BASE-TX half duplex supported - ANAR_SELECTOR = 0x0001 // Protocol selection bits (hardcoded to ethernet) + ANAR_SELECTOR = 0x0001 // Protocol sel. bits (hardcoded to ethernet) }; + enum MII_ANLPAR { ANLPAR_NP = 0x8000, // Link partner next page enabled - ANLPAR_ACK = 0x4000, // Link partner data reception ability acknowledged + ANLPAR_ACK = 0x4000, // Link partner data reception ability ack-ed ANLPAR_RF = 0x2000, // Remote fault indicated by link partner ANLPAR_PAUSE = 0x0400, // Pause operation supported by link partner ANLPAR_T4 = 0x0200, // 100BASE-T4 supported by link partner - ANLPAR_TX_FD = 0x0100, // 100BASE-TX full duplex supported by link partner - ANLPAR_TX_HD = 0x0080, // 100BASE-TX half duplex supported by link partner - ANLPAR_10_FD = 0x0040, // 10BASE-TX full duplex supported by link partner - ANLPAR_10_HD = 0x0020, // 10BASE-TX half duplex supported by link partner - ANLPAR_SELECTOR = 0x0001 // Link partner's binary encoded protocol selector + ANLPAR_TX_FD = 0x0100, // 100BASE-TX FD supported by link partner + ANLPAR_TX_HD = 0x0080, // 100BASE-TX HD supported by link partner + ANLPAR_10_FD = 0x0040, // 10BASE-TX FD supported by link partner + ANLPAR_10_HD = 0x0020, // 10BASE-TX HD supported by link partner + ANLPAR_SELECTOR = 0x0001 // Link partner's bin. encoded protocol selector }; // index used to different PHY on MII bus enum PHYIndex { - CurrentPHY = -1, // currently selected PHY. - // Internally used as default index in case on PHYs found. + CurrentPHY = -1, // currently selected PHY. + // Internally used as def. index in case no PHYs found. SecondaryPHY = 0, // secondary PHY PrimaryPHY = 1, // primary PHY PHYsCount = 2 // maximal count of PHYs on bus }; + // PHY type and id constants and masks. enum PHYType { PHYTypeMask = 0xe0, // mask for PHY type bits PHYNormal = 0x00, // 10/100 Ethernet PHY (Link reports as normal case) PHYLinkAState = 0x80, // Special case 1 (Link reports is always active) PHYGigabit = 0x20, // Gigabit Ethernet PHY on AX88178 - PHYNotInstalled = 0xe0, // non-supported PHY - + PHYNotInstalled = 0xe0, // non-supported PHY + PHYIDMask = 0x1f, // mask for PHY ID bits PHYIDEmbedded = 0x10 // id for embedded PHY on AX88772 }; @@ -104,40 +110,31 @@ enum PHYType { class MIIBus { public: MIIBus(); - - status_t Init(usb_device device, - uint8 SWOperationRequest, - uint8 ReadValueRequest, - uint8 WriteValueRequest, - uint8 ReadStatusRequest, - uint8 HWOperationRequest, - uint8 ReadPHYIDsRequest); + + status_t Init(usb_device device); status_t InitCheck(); - + status_t SetupPHY(); - + uint8 PHYID(PHYIndex phyIndex = CurrentPHY); uint8 PHYType(PHYIndex phyIndex = CurrentPHY); PHYIndex ActivePHY() { return fSelectedPHY; } - - status_t Read(uint16 miiRegister, uint16 *value, PHYIndex phyIndex = CurrentPHY); - status_t Write(uint16 miiRegister, uint16 value, PHYIndex phyIndex = CurrentPHY); - status_t Status(uint16 *status, PHYIndex phyIndex = CurrentPHY); + status_t Read(uint16 miiRegister, uint16 *value, + PHYIndex phyIndex = CurrentPHY); + status_t Write(uint16 miiRegister, uint16 value, + PHYIndex phyIndex = CurrentPHY); + + status_t Status(uint16 *status, + PHYIndex phyIndex = CurrentPHY); status_t Dump(); - + private: + status_t fStatus; usb_device fDevice; uint8 fPHYs[PHYsCount]; PHYIndex fSelectedPHY; - - uint8 fSWOperationRequest; - uint8 fReadValueRequest; - uint8 fWriteValueRequest; - uint8 fReadStatusRequest; - uint8 fHWOperationRequest; - uint8 fReadPHYIDsRequest; }; -#endif //_USB_MII_BUS_H_ +#endif // _USB_MII_BUS_H_ diff --git a/src/add-ons/kernel/drivers/network/usb_asix/Settings.cpp b/src/add-ons/kernel/drivers/network/usb_asix/Settings.cpp index 3ac77bde75..71ceb5b99f 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/Settings.cpp +++ b/src/add-ons/kernel/drivers/network/usb_asix/Settings.cpp @@ -1,19 +1,26 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008,2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ -#include // for mutex #include "Settings.h" +#include +#include +#include + +#include +#include + + bool gTraceOn = false; bool gTruncateLogFile = false; bool gAddTimeStamp = true; @@ -21,10 +28,10 @@ bool gTraceFlow = false; static char *gLogFilePath = NULL; mutex gLogLock; -static +static void create_log() { - if(gLogFilePath == NULL) + if (gLogFilePath == NULL) return; int flags = O_WRONLY | O_CREAT | ((gTruncateLogFile) ? O_TRUNC : 0); @@ -33,21 +40,23 @@ void create_log() mutex_init(&gLogLock, DRIVER_NAME"-logging"); } + void load_settings() { void *handle = load_driver_settings(DRIVER_NAME); - if(handle == 0) + if (handle == 0) return; gTraceOn = get_driver_boolean_parameter(handle, "trace", gTraceOn, true); - gTraceFlow = get_driver_boolean_parameter(handle, "trace_flow", gTraceFlow, true); - gTruncateLogFile = get_driver_boolean_parameter(handle, "truncate_logfile", + gTraceFlow = get_driver_boolean_parameter(handle, "trace_flow", + gTraceFlow, true); + gTruncateLogFile = get_driver_boolean_parameter(handle, "truncate_logfile", gTruncateLogFile, true); - gAddTimeStamp = get_driver_boolean_parameter(handle, "add_timestamp", + gAddTimeStamp = get_driver_boolean_parameter(handle, "add_timestamp", gAddTimeStamp, true); - const char * logFilePath = get_driver_parameter(handle, "logfile", + const char * logFilePath = get_driver_parameter(handle, "logfile", NULL, "/var/log/"DRIVER_NAME".log"); - if(logFilePath != NULL) { + if (logFilePath != NULL) { gLogFilePath = strdup(logFilePath); } @@ -56,17 +65,19 @@ void load_settings() create_log(); } + void release_settings() { - if(gLogFilePath != NULL) { + if (gLogFilePath != NULL) { mutex_destroy(&gLogLock); free(gLogFilePath); } } + void usb_asix_trace(bool force, const char* func, const char *fmt, ...) { - if(!(force || gTraceOn)) { + if (!(force || gTraceOn)) { return; } @@ -74,21 +85,21 @@ void usb_asix_trace(bool force, const char* func, const char *fmt, ...) static const char *prefix = "\33[33m"DRIVER_NAME":\33[0m"; static char buffer[1024]; char *buf_ptr = buffer; - if(gLogFilePath == NULL){ + if (gLogFilePath == NULL) { strcpy(buffer, prefix); buf_ptr += strlen(prefix); } - - if(gAddTimeStamp) { - bigtime_t time = system_time(); - uint32 msec = time / 1000; - uint32 sec = msec / 1000; - sprintf(buf_ptr, "%02ld.%02ld.%03ld:", - sec / 60, sec % 60, msec % 1000); - buf_ptr += strlen(buf_ptr); - } - if(func != NULL) { + if (gAddTimeStamp) { + bigtime_t time = system_time(); + uint32 msec = time / 1000; + uint32 sec = msec / 1000; + sprintf(buf_ptr, "%02ld.%02ld.%03ld:", + sec / 60, sec % 60, msec % 1000); + buf_ptr += strlen(buf_ptr); + } + + if (func != NULL) { sprintf(buf_ptr, "%s::", func); buf_ptr += strlen(buf_ptr); } @@ -97,7 +108,7 @@ void usb_asix_trace(bool force, const char* func, const char *fmt, ...) vsprintf(buf_ptr, fmt, arg_list); va_end(arg_list); - if(gLogFilePath == NULL) { + if (gLogFilePath == NULL) { dprintf(buffer); return; } diff --git a/src/add-ons/kernel/drivers/network/usb_asix/Settings.h b/src/add-ons/kernel/drivers/network/usb_asix/Settings.h index abea40151d..7ce86dcf8c 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/Settings.h +++ b/src/add-ons/kernel/drivers/network/usb_asix/Settings.h @@ -1,27 +1,36 @@ /* * ASIX AX88172/AX88772/AX88178 USB 2.0 Ethernet Driver. - * Copyright (c) 2008 S.Zharski + * Copyright (c) 2008, 2011 S.Zharski * 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 * Distributed under the terms of the MIT license. * */ +#ifndef _USB_ASIX_SETTINGS_H_ +#define _USB_ASIX_SETTINGS_H_ -#ifndef _USB_ASIX_SETTINGS_H_ - #define _USB_ASIX_SETTINGS_H_ -#include +#include #include "Driver.h" + +#ifdef _countof +#warning "_countof(...) WAS ALREADY DEFINED!!! Remove local definition!" +#undef _countof +#endif +#define _countof(array)(sizeof(array) / sizeof(array[0])) + + void load_settings(); void release_settings(); void usb_asix_trace(bool force, const char *func, const char *fmt, ...); + #define TRACE(x...) usb_asix_trace(false, __func__, x) #define TRACE_ALWAYS(x...) usb_asix_trace(true, __func__, x) @@ -31,4 +40,5 @@ extern bool gTraceFlow; #define TRACE_RET(result) usb_asix_trace(false, __func__, \ "Returns:%#010x\n", result); -#endif /*_USB_ASIX_SETTINGS_H_*/ + +#endif // _USB_ASIX_SETTINGS_H_