/* * Davicom DM9601 USB 1.1 Ethernet Driver. * Copyright (c) 2008, 2011 Siarzhuk Zharski * Copyright (c) 2009 Adrien Destugues * Distributed under the terms of the MIT license. * * Heavily based on code of the * Driver for USB Ethernet Control Model devices * Copyright (C) 2008 Michael Lotz * Distributed under the terms of the MIT license. */ #ifndef _USB_DAVICOM_DEVICE_H_ #define _USB_DAVICOM_DEVICE_H_ #include #include #include "Driver.h" struct DM9601NotifyData { // Network Status Register uint RXRDY :1; uint RXOV :1; uint TX1END :1; uint TX2END :1; uint TXFULL :1; uint WAKEST :1; uint LINKST :1; uint SPEED :1; struct { uint :2; uint EC :1; uint COL :1; uint LC :1; uint NC :1; uint LCR :1; uint :1; } __attribute__((__packed__)) TSR1, TSR2; // RX Status Register uint FOE :1; uint CE :1; uint AE :1; uint PLE :1; uint RWTO :1; uint LCS :1; uint MF :1; uint RT :1; // RX Overflows Count uint RXFU :1; uint ROC :7; uint RXC :8; uint TXC :8; uint GPR :8; DM9601NotifyData() { memset(this, 0, sizeof(DM9601NotifyData)); } } __attribute__((__packed__)); struct DeviceInfo { uint16 fIds[2]; const char* fName; inline uint16 VendorId() { return fIds[0]; } inline uint16 ProductId() { return fIds[1]; } inline uint32 Key() { return fIds[0] << 16 | fIds[1]; } }; class DavicomDevice { struct _Statistics { // NSR int txFull; int rxOverflow; int rxOvCount; // RSR int runtFrames; int lateRXCollisions; int rwTOs; int physLayerErros; int alignmentErros; int crcErrors; int overErrors; // TSR 1/2 int lateTXCollisions; int lostOfCarrier; int noCarrier; int txCollisions; int excCollisions; int notifyCount; int readCount; int writeCount; _Statistics() { memset(this, 0, sizeof(_Statistics)); } }; public: DavicomDevice(usb_device device, DeviceInfo& Info); ~DavicomDevice(); status_t InitCheck() { return fStatus; }; status_t Open(uint32 flags); bool IsOpen() { return fOpen; }; status_t Close(); status_t Free(); status_t Read(uint8 *buffer, size_t *numBytes); status_t Write(const uint8 *buffer, size_t *numBytes); status_t Control(uint32 op, void *buffer, size_t length); void Removed(); bool IsRemoved() { return fRemoved; }; status_t CompareAndReattach(usb_device device); status_t SetupDevice(bool deviceReplugged); private: static void _ReadCallback(void *cookie, int32 status, void *data, size_t actualLength); static void _WriteCallback(void *cookie, int32 status, void *data, size_t actualLength); static void _NotifyCallback(void *cookie, int32 status, void *data, size_t actualLength); status_t _SetupEndpoints(); status_t _StartDevice(); status_t _StopDevice(); status_t _OnNotify(uint32 actualLength); status_t _GetLinkState(ether_link_state *state); status_t _SetPromiscuousMode(bool bOn); uint32 _EthernetCRC32(const uint8* buffer, size_t length); status_t _ModifyMulticastTable(bool join, ether_address_t *group); status_t _ReadMACAddress(ether_address_t *address); status_t _ReadRegister(uint8 reg, size_t size, uint8* buffer); status_t _WriteRegister(uint8 reg, size_t size, uint8* buffer); status_t _Write1Register(uint8 reg, uint8 buffer); status_t _ReadMII(uint8 reg, uint16* data); status_t _WriteMII(uint8 reg, uint16 data); status_t _InitMII(); status_t _EnableInterrupts(bool enable); // device info usb_device fDevice; DeviceInfo fDeviceInfo; ether_address_t fMACAddress; // state tracking status_t fStatus; bool fOpen; bool fRemoved; bool fHasConnection; bool fTXBufferFull; bool fNonBlocking; int32 fInsideNotify; // pipes for notifications, data io and tx packet size usb_pipe fNotifyEndpoint; usb_pipe fReadEndpoint; usb_pipe fWriteEndpoint; uint16 fMaxTXPacketSize; // data stores for async usb transfers uint32 fActualLengthRead; uint32 fActualLengthWrite; int32 fStatusRead; int32 fStatusWrite; sem_id fNotifyReadSem; sem_id fNotifyWriteSem; sem_id fLinkStateChangeSem; DM9601NotifyData* fNotifyData; _Statistics fStats; Vector fMulticastHashes; }; #endif // _USB_DAVICOM_DEVICE_H_