📄 usbpegasusend.c
字号:
/* usbPegasusEnd.c - USB Ethernet driver for the Pegasus USB-Ethernet adapter *//* Copyright 2004 Wind River Systems, Inc. *//*modification history--------------------01u,26oct04,ami Debug Messages Changes01t,20oct04,ami Fix for discoonection of Pegaus Device while loading01s,15oct04,ami Apigen Changes01s,07oct04,hch SPR #98211 98965 fix01r,06oct04,ami SPR #94684 Fix01q,05oct04,pdg SPR 75866 fix01p,03aug04,pdg Fixed coverity errors01o,21jul04,hch Fix SPR #9976101n,07jun04,hch Fix SPR #98112 for Pegasus multicast support01n,07jun04,dgp clean up formatting to correct doc build errors01m,02dec03,nrv fix diab compiler warning01m,18dec03,cfc Fix compiler warning error01l,14oct03,nrv complete fix for MAC endian issue01k,08oct03,cfc Fix for send buf alignment and queueing 01j,07oct03,cfc Fix for MAC Address ENDIAN issue01i,27aug03,nrv making mods for pegasus201h,06mar02,wef remove more automatic buffers identify memory leak.01g,14nov01,wef remove automatic buffer creations and repalce with OSS_xALLOC remove more warnings01f,08aug01,dat Removing warnings01e,08aug01,dat Removing compiler warnings01d,09may01,wef changed placement of dev structure connected flag being set01c,01may01,wef changed USB_DEV USB_PEGASUS_DEV01b,28mar01,bri Dynamic input and output Irp memory allocation added, provsion for multiple device added.01a,28jul00,bri Created*//*DESCRIPTIONThis module is the USB communication class, Ethernet Sub class driver for the vxWorks operating system. This module presents an interface which becomes an underlying layer of the vxWorks END (Enhanced Network Driver) model. It also adds certain APIs that are necessary for some additional features supported by an usb - Ethernet adapter. USB - Ethernet adapter devices are described in the USB Communication Devices class definitions. The USB - Ethernet adapter falls under the Ethernet Control model under the communications device class specification.This driver is meant for the usb-ethernet adapters built around the Pegasus-ADM Tek AN986 chip. DEVICE FUNCTIONALITY The Pegasus USB to ethernet adapter chip ASIC provides bridge from USB to 10/100 MII and USB to 1M HomePNA network.The Pegasus Chip, is compliant with supports USB 1.0 and 1.1 specifications. This device supports 4 End Points. The first,is the default end point which is of control type (with max 8 byte packet). The Second and the Third are BULK IN (Max 64 Byte packet) and BULK OUT (Max 64 Byte Packet) end points for transfering the data into the Host and from the Host respectively. The Fourth End Point, is an Interrupt end point (Max 8 bytes) that is not currently used.This device supports One configuration which contains One Interface. This interface contains the 3 end points i.e. the Bulk IN/Out and interruptend points. Apart from the traditional commands, the device supports 3 Vendor specific commands. These commands are described in the Pegasus specification manual.The device supports interface to EEPROM for storing the Ethernet MAC address and other configuration details. It also supports interface to SRAM for storing the packets received and to be transmitted.Packets are passed between the chip and host via bulk transfers.There is an interrupt endpoint mentioned in the specification manual. Howeverit was not used. This device can work in 10Mbps half and Full duplex and 100 Mbps half and Full Duplex modes. The MAC supports a 64 entrymulticast filter. This device is IEEE 802.3 MII compliant and supports IEEE 802.3x flow control. It also supports for configurable threshold for transmitting PAUSE frame. Supports Wakeup frame, Link status change andmagic packet frame.The device supports the following (vendor specific)commands :\is\i 'USB_REQ_REG_GET'Retrieves the Contents of the specified register from the device.\i 'USB_REQ_REG_SET_SINGLE'Sets the contents of the specified register (Single) in the device\i 'USB_REQ_REG_SET_MULTIPLE'Sets the contents of the specified register (Multiple) in the device\ieDRIVER FUNCTIONALITYThe function usbPegasusEndInit() is called at the time of usb system initialization. It registers as a client with the USBD. This function alsoregisters for the dynamic attachment and removal of the usb devices.Ideally we should be registering for a specific Class ID and a SubclassId..but since the device doesn't support these parameters in the Devicedescriptor, we register for ALL kinds of devices. We maintain a linked list of the ethernet devices on USB in a linked list "pegasusDevList". This list is created and maintained using the linked list library provided as a part of the USBD. Useful API calls are provided to find if the device exists in the list, by taking eitherthe device "nodeId" or the vendorId and productId as the parameters.The Callback function registered for the dynamic attachment/removal, pegasusAttachCallback() will be called if any device is found on/removedfrom the USB. This function first checks whether the device already exists in the List. If not, it will parse through the device descriptor, findout the Vendor Id and Product Id. If they match with Pegasus Ids, the device will be added to the list of ethernet devices found on the USB.pegasusDevInit() does most of the device structure initialization afterwards. This routine checks if the device corresponding to the vendorId and productId matches to any of the devices in the "List". If yesa pointer structure on the list will be assigned to one of the devicestructure parameters. After this the driver will parse through the configuration descriptor, interface descriptor to findout the InPut and OutPutend point details. Once we find these end point descriptors we create input and output Pipes and assign them to the corresponding structure. It then resets the device.This driver, is a Polled mode driver as such. It keeps listening on the input pipe by calling "pegasusListenToInput" all the time, from the firsttime it is called by pegasusStart(). This acquires a buffer from the endLayer and uses it in the IRP. Unless the IRP is cancelled (by pegasusStop()), it will be submitted again and again. If cancelled, itwill again start listening only if pegasusStart() is called. If there is data (IRP successfull), then it will be passed on to END by callingpegasusEndRecv().Rest of the functionality of the driver is straight forward and most of the places achieved by sending a vendor specific command from the listdescribed above, to the device.INCLUDE FILES: end.h, endLib.h, lstLib.h, etherMultiLib.h, usb/usbPlatform.h, usb/usb.h, usb/usbListLib.h, usb/usbdLib.h, usb/usbLib.h, drv/usb/usbPegasusEnd.hSEE ALSO:muxLib, endLib, usbLib, usbdLib, ossLib\tb "Writing and Enhanced Network Driver" and\tb "USB Developer's Kit User's Guide"*//* includes */#include "vxWorks.h"#include "stdlib.h"#include "stdio.h"#include "string.h"#include "cacheLib.h"#include "intLib.h"#include "end.h" /* Common END structures. */#include "endLib.h"#include "lstLib.h" /* Needed to maintain protocol list. */#include "wdLib.h"#include "iv.h"#include "semLib.h"#include "etherLib.h"#include "logLib.h"#include "netLib.h"#include "stdio.h"#include "sysLib.h"#include "errno.h"#include "errnoLib.h"#include "memLib.h"#include "iosLib.h"#include "etherMultiLib.h" /* multicast stuff. */#include "net/mbuf.h"#include "net/unixLib.h"#include "net/protosw.h"#include "net/systm.h"#include "net/if_subr.h"#include "net/route.h"#include "sys/socket.h"#include "sys/ioctl.h"#include "sys/times.h"#include "usb/usbPlatform.h"#include "usb/ossLib.h" /* operations system srvcs */#include "usb/usb.h" /* general USB definitions */#include "usb/usbListLib.h" /* linked list functions */#include "usb/usbdLib.h" /* USBD interface */#include "usb/usbLib.h" /* USB utility functions */#include "drv/usb/usbPegasusEnd.h"/* defines *//* for debugging */#define PEGASUS_DBG#ifdef PEGASUS_DBG#define PEGASUS_DBG_OFF 0x0000#define PEGASUS_DBG_RX 0x0001#define PEGASUS_DBG_TX 0x0002#define PEGASUS_DBG_MCAST 0x0004#define PEGASUS_DBG_ATTACH 0x0008#define PEGASUS_DBG_INIT 0x0010#define PEGASUS_DBG_START 0x0020#define PEGASUS_DBG_STOP 0x0040#define PEGASUS_DBG_RESET 0x0080#define PEGASUS_DBG_MAC 0x0100#define PEGASUS_DBG_POLL_RX 0x0200#define PEGASUS_DBG_POLL_TX 0x0400#define PEGASUS_DBG_LOAD 0x0800#define PEGASUS_DBG_IOCTL 0x1000#define PEGASUS_DBG_DNLD 0x2000#define PEGASUS_DBG_TX_STALL 0x4000int pegasusDebug = (0x0000); extern void usbLogMsg (char *,int,int,int,int,int,int);#define PEGASUS_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \ if (pegasusDebug & FLG) \ usbLogMsg(X0, X1, X2, X3, X4, X5, X6)#define PEGASUS_PRINT(FLG,X) \ if (pegasusDebug & FLG) printf X;#else /*PEGASUS_DBG*/#define PEGASUS_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)#define PEGASUS_PRINT(DBG_SW,X)#endif /*PEGASUS_DBG*/#define PEGASUS_CLIENT_NAME "usbPegasusLib"#define PEGASUS_BUFSIZ ETHERMTU + EH_SIZE + 6#define EH_SIZE (14)#define END_SPEED_10M 10000000 /* 10Mbs */#define PEGASUS_SPEED END_SPEED_10M/* Constants for computing the Pegasus multicast hash table value */#define PEGASUS_POLY 0xEDB88320#define PEGASUS_BITS 6/* A shortcut for getting the hardware address from the MIB II stuff. */#define END_HADDR(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)#define END_HADDR_LEN(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)#define PEGASUS_MIN_FBUF (1514) /* min first buffer size */#define USB_PEGASUS_BUF_SIZE (1550) /* transfer buffer size */#define DELAY(i)\ taskDelay(sysClkRateGet()*i);;/* typedefs *//* * This will only work if there is only a single unit, for multiple * unit device drivers these should be integrated into the PEGASUS_DEVICE * structure. */M_CL_CONFIG pegasusMclBlkConfig = /* network mbuf configuration table */ { /* no. mBlks no. clBlks memArea memSize ----------- ---------- ------- ------- */ 0, 0, NULL, 0 };CL_DESC pegasusClDescTbl [] = /* network cluster pool configuration table */ { /* clusterSize num memArea memSize ----------- ---- ------- ------- */ {PEGASUS_BUFSIZ, 0, NULL, 0} }; int pegasusClDescTblNumEnt = (NELEMENTS(pegasusClDescTbl));/* globals */BOOL usbPegasusEndMemoryIsNotSetup = TRUE; /* memory setup flag */NET_POOL * pUsbPegasusNetPool; /* netPool pointer */USBD_CLIENT_HANDLE pegasusHandle; /* our USBD client handle */USBD_NODE_ID pegasusNodeID; /* our USBD node ID *//* Locals */LOCAL UINT16 initCount = 0; /* Count of init nesting */LOCAL MUTEX_HANDLE pegasusMutex; /* to protect internal structs */LOCAL LIST_HEAD pegasusDevList; /* linked list of Device Structs */LOCAL MUTEX_HANDLE pegasusTxMutex; /* to protect internal structs */LOCAL MUTEX_HANDLE pegasusRxMutex; /* to protect internal structs */LOCAL LIST_HEAD reqList; /* Attach callback request list *//* forward declarartions *//* END Specific Externally imported interfaces. */IMPORT int endMultiLstCnt (END_OBJ* pEnd);IMPORT STATUS taskDelay(int);/* Externally visible interfaces. */END_OBJ * usbPegasusEndLoad (char * initString);STATUS usbPegasusEndInit (void);/* LOCAL functions */LOCAL int pegasusEndIoctl (PEGASUS_DEVICE * pDrvCtrl, int cmd, caddr_t data);LOCAL STATUS usbPegasusEndUnload (PEGASUS_DEVICE * pDrvCtrl);LOCAL STATUS pegasusEndSend (PEGASUS_DEVICE * pDrvCtrl, M_BLK_ID pBuf); LOCAL STATUS pegasusEndMCastAdd (PEGASUS_DEVICE * pDrvCtrl, char * pAddress);LOCAL STATUS pegasusEndMCastDel (PEGASUS_DEVICE * pDrvCtrl, char * pAddress);LOCAL STATUS pegasusEndMCastGet (PEGASUS_DEVICE * pDrvCtrl, MULTI_TABLE * pTable);LOCAL STATUS pegasusEndPollSend (PEGASUS_DEVICE * pDrvCtrl, M_BLK_ID pBuf);LOCAL STATUS pegasusEndPollRcv (PEGASUS_DEVICE * pDrvCtrl, M_BLK_ID pBuf);LOCAL STATUS pegasusEndParse (PEGASUS_DEVICE * pDrvCtrl, char * initString, UINT16 * pVendorId, UINT16 * pProductId );LOCAL STATUS pegasusEndMemInit (PEGASUS_DEVICE * pDrvCtrl);LOCAL STATUS pegasusEndConfig (PEGASUS_DEVICE * pDrvCtrl);LOCAL STATUS pegasusDevInit (PEGASUS_DEVICE * pDevCtrl, UINT16 vendorId, UINT16 productId);LOCAL STATUS pegasusEndStart (PEGASUS_DEVICE * pDevCtrl);LOCAL STATUS pegasusEndStop (PEGASUS_DEVICE * pDevCtrl);LOCAL void pegasusTxCallback (pVOID p);LOCAL void pegasusRxCallback (pVOID p);LOCAL STATUS pegasusShutdown (int errCode);LOCAL STATUS pegasusSend (PEGASUS_DEVICE * pDevCtrl,UINT8* pBfr, UINT32 size);LOCAL STATUS pegasusListenForInput (PEGASUS_DEVICE * pDevCtrl);LOCAL USB_PEGASUS_DEV * pegasusFindDevice (USBD_NODE_ID nodeId);LOCAL USB_PEGASUS_DEV * pegasusEndFindDevice (UINT16 vendorId, UINT16 productId);LOCAL VOID pegasusDestroyDevice (PEGASUS_DEVICE * pDevCtrl);LOCAL STATUS pegasusMCastFilterSet (PEGASUS_DEVICE * pDevCtrl);LOCAL STATUS pegasusAttachCallback (USBD_NODE_ID nodeId, UINT16 attachAction, UINT16 configuration, UINT16 interface, UINT16 deviceClass, UINT16 deviceSubClass, UINT16 deviceProtocol );LOCAL STATUS pegasusEndRecv (PEGASUS_DEVICE * pDrvCtrl, UINT8 * pData, UINT32 len );LOCAL STATUS usbPegasusInit (USBD_NODE_ID devId, UINT8 * macAdrs);LOCAL STATUS usbPegasusReadPhy (USBD_NODE_ID devId, UINT8 offSet, UINT16 * phyWord);LOCAL STATUS usbPegasusWritePhy (USBD_NODE_ID devId, UINT8 direction, UINT8 offSet, UINT16 phyWord);LOCAL STATUS usbPegasusReadSrom (USBD_NODE_ID devId, UINT8 offSet, UINT16 * phyWord);LOCAL VOID notifyAttach (USB_PEGASUS_DEV * pDev, UINT16 attachCode);BOOL pegasusOutputIrpInUse (PEGASUS_DEVICE *pDevCtrl);LOCAL int pegasusMchash (UINT8 * addr); /* * Our driver function table. This is static across all driver * instances. */LOCAL NET_FUNCS pegasusEndFuncTable = { (FUNCPTR) pegasusEndStart, /* Function to start the device. */ (FUNCPTR) pegasusEndStop, /* Function to stop the device. */ (FUNCPTR) usbPegasusEndUnload, /* Unloading function for the driver. */ (FUNCPTR) pegasusEndIoctl, /* Ioctl function for the driver. */ (FUNCPTR) pegasusEndSend, /* Send function for the driver. */ (FUNCPTR) pegasusEndMCastAdd, /* Multicast add function for the */ /* driver. */ (FUNCPTR) pegasusEndMCastDel, /* Multicast delete function for */ /* the driver. */ (FUNCPTR) pegasusEndMCastGet, /* Multicast retrieve function for */ /* the driver. */ (FUNCPTR) pegasusEndPollSend, /* Polling send function */ (FUNCPTR) pegasusEndPollRcv, /* Polling receive function */ endEtherAddressForm, /* put address info into a NET_BUFFER */ endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */ endEtherPacketAddrGet /* Get packet addresses. */ };#define ADDR_LOGGING 0#if ADDR_LOGGING#define ADDR_BUF_SIZE 4096UINT32 addrBuf [ADDR_BUF_SIZE]; UINT32 valueBuf [ADDR_BUF_SIZE]; UINT16 bufferCounter = 0;void logAddr ( UINT32 value, UINT8 * addr ) { if (bufferCounter == ADDR_BUF_SIZE) bufferCounter = 0; addrBuf [bufferCounter] = addr; valueBuf [bufferCounter++] = value; }void displayAddr (void) { UINT16 i, j=0; for (i=0; i<bufferCounter; i++) { printf ("%d", valueBuf [i]); printf (" - 0x%x ", addrBuf [i]); j++; if (j == 4) { printf ("\n"); j=0; } } printf ("\n"); }#endif/***************************************************************************** pegasusAttachCallback - gets called for attachment/detachment of devices** The USBD will invoke this callback when a USB ethernet device is * attached to or removed from the system. * <nodeId> is the USBD_NODE_ID of the node being attached or removed. * <attachAction> is USBD_DYNA_ATTACH or USBD_DYNA_REMOVE.* Communication device functionality resides at the interface level, with* the exception of being the definition of the Communication device class* code.so <configuration> and <interface> will indicate the configuration* or interface that reports itself as a network device.* <deviceClass> and <deviceSubClass> will match the class/subclass for * which we registered. * <deviceProtocol> doesn't have meaning for the ethernet devices so we * ignore this field.** NOTE* The USBD invokes this function once for each configuration or* interface which reports itself as a network device.* So, it is possible that a single device insertion or removal may trigger * multiple callbacks. We ignore all callbacks except the first for a * given device.*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -