usbPegasusEnd.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:91k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* usbPegasusEnd.c - USB Ethernet driver for the Pegasus USB-Ethernet adapter */
  2. /* Copyright 2000-2002 Wind river systems, Inc */
  3. /*
  4. modification history
  5. --------------------
  6. 01h,06mar02,wef  remove more automatic buffers identify memory leak.
  7. 01g,14nov01,wef  remove automatic buffer creations and repalce with OSS_xALLOC
  8.                  remove more warnings
  9. 01f,08aug01,dat  Removing warnings
  10. 01e,08aug01,dat  Removing compiler warnings
  11. 01d,09may01,wef  changed placement of dev structure connected flag being set
  12. 01c,01may01,wef  changed USB_DEV USB_PEGASUS_DEV
  13. 01b,28mar01,bri  Dynamic input and output Irp memory allocation added,
  14.  provsion for multiple device added.
  15. 01a,28jul00,bri  Created
  16. */
  17. /*
  18. DESCRIPTION
  19. This module is the USB communication class, Ethernet Sub class driver 
  20. for the vxWorks operating system. This module presents an interface which 
  21. becomes an underlying layer of the vxWorks END (Enhanced Network Driver) 
  22. model. It also adds certain APIs that are necessary for some additional 
  23. features supported by an usb - Ethernet adapter.
  24.  
  25. USB - Ethernet adapter devices are described in the USB Communication 
  26. Devices class definitions. The USB - Ethernet adapter falls under the 
  27. Ethernet Control model under the communications device class specification.
  28. This driver is meant for the usb-ethernet adapters built around the 
  29. Pegasus-ADM Tek AN986 chip.
  30.   
  31.  
  32. DEVICE FUNCTIONALITY
  33.  
  34. The Pegasus USB to ethernet adapter chip ASIC provides bridge from USB 
  35. to 10/100 MII and USB to 1M HomePNA network.The Pegasus Chip, is compliant 
  36. with supports USB 1.0 and 1.1 specifications. This device supports 4 End 
  37. Points. The first,is the default end point which is of control type (with 
  38. max 8 byte packet). The Second and the Third are BULK IN (Max 64 Byte 
  39. packet) and BULK OUT (Max 64 Byte Packet) end points for transfering the 
  40. data into the Host and from the Host respectively. The Fourth End Point, 
  41. is an Interrupt end point (Max 8 bytes) that is not currently used.
  42. This device supports One configuration which contains One Interface. This 
  43. interface contains the 3 end points i.e. the Bulk IN/Out and interrupt
  44. end points. 
  45.  
  46. Apart from the traditional commands, the device supports 3 Vendor specific 
  47. commands. These commands are described in the Pegasus specification manual.
  48. The device supports interface to EEPROM for storing the Ethernet MAC address 
  49. and other configuration details. It also supports interface to SRAM for 
  50. storing the packets received and to be transmitted.
  51. Packets are passed between the chip and host via bulk transfers.
  52. There is an interrupt endpoint mentioned in the specification manual. However
  53. it was not used. This device can work in 10Mbps half and Full duplex 
  54. and 100 Mbps half and Full Duplex modes. The MAC supports a 64 entry
  55. multicast filter. This device is IEEE 802.3 MII compliant and supports 
  56. IEEE 802.3x flow control. It also supports for configurable threshold for 
  57. transmitting PAUSE frame. Supports Wakeup frame, Link status change and
  58. magic packet frame.
  59. The device supports the following (vendor specific)commands :
  60.  
  61. .IP "USB_REQ_REG_GET"
  62. Retrieves the Contents of the specified register from the device. 
  63. .IP "USB_REQ_REG_SET_SINGLE"
  64. Sets the contents of the specified register (Single) in the device
  65. .IP "USB_REQ_REG_SET_MULTIPLE"
  66. Sets the contents of the specified register (Multiple) in the device
  67. DRIVER FUNCTIONALITY
  68.  
  69. The function usbPegasusEndInit() is called at the time of usb system 
  70. initialization. It registers as a client with the USBD. This function also
  71. registers for the dynamic attachment and removal of the usb devices.
  72. Ideally we should be registering for a specific Class ID and a Subclass
  73. Id..but since the device doesn't support these parameters in the Device
  74. descriptor, we register for ALL kinds of devices. 
  75. We maintain a linked list of the ethernet devices on USB in 
  76. a linked list "pegasusDevList". This list is created and maintained using 
  77. the linked list library provided as a part of the USBD. Useful API calls 
  78. are provided to find if the device exists in the list, by taking either
  79. the device "nodeId" or the vendorId and productId as the parameters.
  80. The Callback function registered for the dynamic attachment/removal, 
  81. pegasusAttachCallback() will be called if any device is found on/removed
  82. from the USB. This function first checks whether the device already exists 
  83. in the List. If not, it will parse through the device descriptor, findout 
  84. the Vendor Id and Product Id. If they match with Pegasus Ids, the device 
  85. will be added to the list of ethernet devices found on the USB.
  86. pegasusDevInit() does most of the device structure initialization 
  87. afterwards. This routine checks if the device corresponding to the 
  88. vendorId and productId matches to any of the devices in the "List". If yes
  89. a pointer structure on the list will be assigned to one of the device
  90. structure parameters. After this the driver will parse through the 
  91. configuration descriptor, interface descriptor to findout the InPut and OutPut
  92. end point details. Once we find these end point descriptors we create input 
  93. and output Pipes and assign them to the corresponding structure. 
  94. It then resets the device.
  95. This driver, is a Polled mode driver as such. It keeps listening on the 
  96. input pipe by calling "pegasusListenToInput" all the time, from the first
  97. time it is called by pegasusStart(). This acquires a buffer from the 
  98. endLayer and uses it in the IRP. Unless the IRP is cancelled (by 
  99. pegasusStop()), it will be submitted again and again. If cancelled, it
  100. will again start listening only if pegasusStart() is called. If there is 
  101. data (IRP successfull), then it will be passed on to END by calling
  102. pegasusEndRecv().
  103. Rest of the functionality of the driver is straight forward and most of 
  104. the places achieved by sending a vendor specific command from the list
  105. described above, to the device.
  106. INCLUDE FILES: 
  107. end.h endLib.h lstLib.h etherMultiLib.h usbPlatform.h usb.h usbListLib.h 
  108. usbdLib.h usbLib.h usbPegasusEnd.h
  109. SEE ALSO:
  110. muxLib, endLib,  usbLib, usbdLib, ossLib 
  111. .I "Writing and Enhanced Network Driver" and
  112. .I "USB Developer's Kit User's Guide"
  113. */
  114. /* includes */
  115. #include "vxWorks.h"
  116. #include "stdlib.h"
  117. #include "stdio.h"
  118. #include "string.h"
  119. #include "cacheLib.h"
  120. #include "intLib.h"
  121. #include "end.h" /* Common END structures. */
  122. #include "endLib.h"
  123. #include "lstLib.h" /* Needed to maintain protocol list. */
  124. #include "wdLib.h"
  125. #include "iv.h"
  126. #include "semLib.h"
  127. #include "etherLib.h"
  128. #include "logLib.h"
  129. #include "netLib.h"
  130. #include "stdio.h"
  131. #include "sysLib.h"
  132. #include "errno.h"
  133. #include "errnoLib.h"
  134. #include "memLib.h"
  135. #include "iosLib.h"
  136. #include "etherMultiLib.h" /* multicast stuff. */
  137. #include "net/mbuf.h"
  138. #include "net/unixLib.h"
  139. #include "net/protosw.h"
  140. #include "net/systm.h"
  141. #include "net/if_subr.h"
  142. #include "net/route.h"
  143. #include "sys/socket.h"
  144. #include "sys/ioctl.h"
  145. #include "sys/times.h"
  146. #include "usb/usbPlatform.h"
  147. #include "usb/ossLib.h"  /* operations system srvcs */
  148. #include "usb/usb.h" /* general USB definitions */
  149. #include "usb/usbListLib.h" /* linked list functions */
  150. #include "usb/usbdLib.h" /* USBD interface */
  151. #include "usb/usbLib.h"  /* USB utility functions */
  152. #include "drv/usb/usbPegasusEnd.h"
  153. /* defines */
  154. /* for debugging */
  155. #define PEGASUS_DBG
  156. #ifdef PEGASUS_DBG
  157. #define PEGASUS_DBG_OFF 0x0000
  158. #define PEGASUS_DBG_RX 0x0001
  159. #define PEGASUS_DBG_TX 0x0002
  160. #define PEGASUS_DBG_MCAST 0x0004
  161. #define PEGASUS_DBG_ATTACH 0x0008
  162. #define PEGASUS_DBG_INIT 0x0010
  163. #define PEGASUS_DBG_START 0x0020
  164. #define PEGASUS_DBG_STOP 0x0040
  165. #define PEGASUS_DBG_RESET 0x0080
  166. #define PEGASUS_DBG_MAC 0x0100
  167. #define PEGASUS_DBG_POLL_RX 0x0200
  168. #define PEGASUS_DBG_POLL_TX 0x0400
  169. #define PEGASUS_DBG_LOAD 0x0800
  170. #define PEGASUS_DBG_IOCTL 0x1000
  171. #define PEGASUS_DBG_DNLD 0x2000
  172. int pegasusDebug = (0x0000);
  173. #define PEGASUS_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)    
  174. if (pegasusDebug & FLG)                           
  175.             logMsg(X0, X1, X2, X3, X4, X5, X6);
  176. #define PEGASUS_PRINT(FLG,X)                             
  177. if (pegasusDebug & FLG) printf X;
  178. #else /*PEGASUS_DBG*/
  179. #define PEGASUS_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
  180. #define PEGASUS_PRINT(DBG_SW,X)
  181. #endif /*PEGASUS_DBG*/
  182. #define PEGASUS_CLIENT_NAME "usbPegasusLib"
  183. #define PEGASUS_BUFSIZ   ETHERMTU + EH_SIZE + 6
  184. #define EH_SIZE (14)
  185. #define END_SPEED_10M 10000000 /* 10Mbs */
  186. #define PEGASUS_SPEED    END_SPEED_10M
  187. /* A shortcut for getting the hardware address from the MIB II stuff. */
  188. #define END_HADDR(pEnd)
  189. ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  190. #define END_HADDR_LEN(pEnd) 
  191. ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  192. #define PEGASUS_MIN_FBUF (1514) /* min first buffer size */
  193. #define USB_PEGASUS_BUF_SIZE    (1550) /* transfer buffer size */
  194. #define DELAY(i)
  195. taskDelay(sysClkRateGet()*i);;
  196. /* typedefs */
  197. /*
  198.  * This will only work if there is only a single unit, for multiple
  199.  * unit device drivers these should be integrated into the PEGASUS_DEVICE
  200.  * structure.
  201.  */
  202. M_CL_CONFIG pegasusMclBlkConfig =  /* network mbuf configuration table */
  203.     {
  204.     /* 
  205.     no. mBlks no. clBlks memArea memSize
  206.     ----------- ---------- ------- -------
  207.     */
  208.     0,  0,  NULL,  0
  209.     };
  210. CL_DESC pegasusClDescTbl [] =  /* network cluster pool configuration table */
  211.     {
  212.     /* 
  213.     clusterSize num memArea memSize
  214.     ----------- ---- ------- -------
  215.     */
  216.     {PEGASUS_BUFSIZ, 0, NULL, 0}
  217.     }; 
  218. int pegasusClDescTblNumEnt = (NELEMENTS(pegasusClDescTbl));
  219. /* globals */
  220. BOOL usbPegasusEndMemoryIsNotSetup = TRUE; /* memory setup flag */
  221. NET_POOL * pUsbPegasusNetPool; /* netPool pointer */
  222. USBD_CLIENT_HANDLE pegasusHandle;  /* our USBD client handle */
  223. /* Locals */
  224. LOCAL UINT16  initCount = 0; /* Count of init nesting */
  225. LOCAL MUTEX_HANDLE  pegasusMutex; /* to protect internal structs */
  226. LOCAL LIST_HEAD pegasusDevList; /* linked list of Device Structs */
  227. LOCAL MUTEX_HANDLE  pegasusTxMutex; /* to protect internal structs */
  228. LOCAL MUTEX_HANDLE  pegasusRxMutex; /* to protect internal structs */
  229. LOCAL LIST_HEAD    reqList;           /* Attach callback request list */
  230. /* forward declarartions */
  231. /* END Specific Externally imported interfaces. */
  232. IMPORT int  endMultiLstCnt  (END_OBJ* pEnd);
  233. /* Externally visible interfaces. */
  234. END_OBJ *  usbPegasusEndLoad (char * initString);
  235. STATUS  usbPegasusEndInit  (void);
  236. /*  LOCAL functions */
  237. LOCAL int pegasusEndIoctl   (PEGASUS_DEVICE * pDrvCtrl, 
  238.   int cmd, caddr_t data);
  239. LOCAL STATUS usbPegasusEndUnload (PEGASUS_DEVICE * pDrvCtrl);
  240. LOCAL STATUS pegasusEndSend     (PEGASUS_DEVICE * pDrvCtrl, M_BLK_ID pBuf);
  241.   
  242. LOCAL STATUS pegasusEndMCastAdd (PEGASUS_DEVICE * pDrvCtrl, char * pAddress);
  243. LOCAL STATUS pegasusEndMCastDel (PEGASUS_DEVICE * pDrvCtrl, char * pAddress);
  244. LOCAL STATUS pegasusEndMCastGet (PEGASUS_DEVICE * pDrvCtrl, 
  245.    MULTI_TABLE * pTable);
  246. LOCAL STATUS pegasusEndPollSend (PEGASUS_DEVICE * pDrvCtrl, M_BLK_ID pBuf);
  247. LOCAL STATUS pegasusEndPollRcv  (PEGASUS_DEVICE * pDrvCtrl, M_BLK_ID pBuf);
  248. LOCAL STATUS pegasusEndParse (PEGASUS_DEVICE * pDrvCtrl, char * initString,
  249. UINT16 * pVendorId, UINT16 * pProductId );
  250. LOCAL STATUS pegasusEndMemInit  (PEGASUS_DEVICE * pDrvCtrl);
  251. LOCAL STATUS pegasusEndConfig   (PEGASUS_DEVICE * pDrvCtrl);
  252. LOCAL STATUS  pegasusDevInit     (PEGASUS_DEVICE * pDevCtrl, UINT16 vendorId, 
  253.        UINT16 productId);
  254. LOCAL STATUS  pegasusEndStart (PEGASUS_DEVICE * pDevCtrl);
  255. LOCAL STATUS  pegasusEndStop (PEGASUS_DEVICE * pDevCtrl);
  256. LOCAL void  pegasusTxCallback (pVOID p);
  257. LOCAL void  pegasusRxCallback (pVOID p);
  258. LOCAL STATUS  pegasusShutdown  (int errCode);
  259. LOCAL STATUS  pegasusSend (PEGASUS_DEVICE * pDevCtrl,UINT8* pBfr,
  260. UINT32 size);
  261. LOCAL STATUS  pegasusListenForInput   (PEGASUS_DEVICE * pDevCtrl);
  262. LOCAL USB_PEGASUS_DEV * pegasusFindDevice (USBD_NODE_ID nodeId);
  263. LOCAL USB_PEGASUS_DEV * pegasusEndFindDevice  (UINT16 vendorId, 
  264.  UINT16 productId);
  265. LOCAL VOID  pegasusDestroyDevice  (PEGASUS_DEVICE * pDevCtrl);
  266. LOCAL STATUS  pegasusMCastFilterSet (PEGASUS_DEVICE * pDevCtrl, 
  267.                                         UINT8* pAddress, UINT32 noOfFilters );
  268. LOCAL STATUS  pegasusAttachCallback (USBD_NODE_ID nodeId, UINT16 attachAction, 
  269.            UINT16 configuration, UINT16 interface,
  270.            UINT16 deviceClass, UINT16 deviceSubClass, 
  271.            UINT16 deviceProtocol );
  272. LOCAL STATUS  pegasusEndRecv    (PEGASUS_DEVICE * pDrvCtrl, UINT8 *  pData,              
  273.        UINT32  len );
  274. LOCAL STATUS usbPegasusInit (USBD_NODE_ID devId, UINT8 * macAdrs);
  275. LOCAL STATUS usbPegasusReadPhy  (USBD_NODE_ID devId, UINT8 offSet, 
  276.                                 UINT16 * phyWord);
  277. LOCAL STATUS usbPegasusWritePhy (USBD_NODE_ID devId, UINT8 direction, 
  278.                                 UINT8 offSet, UINT16 phyWord);
  279. LOCAL STATUS usbPegasusReadSrom (USBD_NODE_ID devId, UINT8 offSet,
  280.                                 UINT16 * phyWord);
  281. LOCAL  VOID notifyAttach        (USB_PEGASUS_DEV * pDev, UINT16 attachCode);
  282. /*
  283.  * Our driver function table.  This is static across all driver
  284.  * instances.
  285.  */
  286. LOCAL NET_FUNCS pegasusEndFuncTable =
  287.     {
  288.     (FUNCPTR) pegasusEndStart,    /* Function to start the device. */
  289.     (FUNCPTR) pegasusEndStop,      /* Function to stop the device. */
  290.     (FUNCPTR) usbPegasusEndUnload, /* Unloading function for the driver. */
  291.     (FUNCPTR) pegasusEndIoctl,    /* Ioctl function for the driver. */
  292.     (FUNCPTR) pegasusEndSend,      /* Send function for the driver. */
  293.     (FUNCPTR) pegasusEndMCastAdd, /* Multicast add function for the */
  294.   /* driver. */
  295.     (FUNCPTR) pegasusEndMCastDel, /* Multicast delete function for */
  296.   /* the driver. */
  297.     (FUNCPTR) pegasusEndMCastGet, /* Multicast retrieve function for */
  298.   /* the driver. */
  299.     (FUNCPTR) pegasusEndPollSend, /* Polling send function */
  300.     (FUNCPTR) pegasusEndPollRcv,  /* Polling receive function */
  301.     endEtherAddressForm, /* put address info into a NET_BUFFER */
  302.     endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
  303.     endEtherPacketAddrGet   /* Get packet addresses. */
  304.     };
  305. #define ADDR_LOGGING 0
  306. #if ADDR_LOGGING
  307. #define ADDR_BUF_SIZE 4096
  308. UINT32 addrBuf [ADDR_BUF_SIZE]; 
  309. UINT32 valueBuf [ADDR_BUF_SIZE]; 
  310. UINT16 bufferCounter = 0;
  311. void logAddr 
  312.     (
  313.     UINT32 value,
  314.     UINT8 * addr 
  315.     )
  316.     {
  317.     if (bufferCounter == ADDR_BUF_SIZE) 
  318. bufferCounter = 0;
  319.     addrBuf [bufferCounter] = addr; 
  320.     valueBuf [bufferCounter++] = value; 
  321.     }
  322. void displayAddr (void)
  323.     {
  324.     UINT16 i, j=0;
  325.     for (i=0; i<bufferCounter; i++)
  326. {
  327. printf ("%d", valueBuf [i]);
  328. printf (" - 0x%x ", addrBuf [i]);
  329. j++;
  330. if (j == 4)
  331.     {
  332.     printf ("n");
  333.     j=0;
  334.     }
  335. }
  336.     printf ("n");
  337.     }
  338. #endif
  339. /***************************************************************************
  340. *
  341. * pegasusAttachCallback - Gets called for attachment/detachment of devices
  342. *
  343. * The USBD will invoke this callback when a USB ethernet device is 
  344. * attached to or removed from the system.  
  345. * <nodeId> is the USBD_NODE_ID of the node being attached or removed.
  346. * <attachAction> is USBD_DYNA_ATTACH or USBD_DYNA_REMOVE.
  347. * Communication device functionality resides at the interface level, with
  348. * the exception of being the definition of the Communication device class
  349. * code.so <configuration> and <interface> will indicate the configuration
  350. * / interface that reports itself as a network device.
  351. * <deviceClass> and <deviceSubClass> will match the class/subclass for 
  352. * which we registered.  
  353. * <deviceProtocol> doesn't have meaning for the ethernet devices so we 
  354. * ignore this field.
  355. *
  356. * NOTE: The USBD will invoke this function once for each configuration/
  357. * interface which reports itself as a network device.
  358. * So, it is possible that a single device insertion/removal may trigger 
  359. * multiple callbacks.  We ignore all callbacks except the first for a 
  360. * given device.
  361. *
  362. * RETURNS: N/A
  363. *
  364. * NOMANUAL
  365. */
  366. STATUS  pegasusAttachCallback
  367.     (
  368.     USBD_NODE_ID nodeId, 
  369.     UINT16 attachAction, 
  370.     UINT16 configuration,
  371.     UINT16 interface,
  372.     UINT16 deviceClass, 
  373.     UINT16 deviceSubClass, 
  374.     UINT16 deviceProtocol
  375.     )
  376.     {
  377.     USB_PEGASUS_DEV * pNewDev;
  378.     UINT8 * pBfr;
  379.     UINT16 actLen;
  380.     UINT16 vendorId;
  381.     UINT16 productId;
  382.     int noOfSupportedDevices = (sizeof (pegasusAdapterList) /
  383.  (2 * sizeof (UINT16)));
  384.     int index = 0;
  385.     if ((pBfr = OSS_MALLOC (USB_MAX_DESCR_LEN)) == NULL)
  386. {
  387. PEGASUS_LOG (PEGASUS_DBG_ATTACH, "pegasusAttachCallback: could not"
  388.     "allocate pBfrn", 0, 0, 0, 0, 0, 0);
  389. return ERROR;
  390. }
  391.     OSS_MUTEX_TAKE (pegasusMutex, OSS_BLOCK);
  392.     switch (attachAction)
  393. {
  394. case USBD_DYNA_ATTACH :
  395.     /* a new device is found */
  396.     PEGASUS_LOG (PEGASUS_DBG_ATTACH, "New Device found : %0x Class "
  397. "%0x Subclass %0x Protocol %0x Configuration "
  398. "%0x Interface  %0x nodeId n", deviceClass,
  399. deviceSubClass, deviceProtocol, configuration,
  400. interface, (UINT)nodeId);
  401.     /* First Ensure that this device is not already on the list */
  402.     if (pegasusFindDevice (nodeId) != NULL)
  403. {
  404. PEGASUS_LOG (PEGASUS_DBG_ATTACH, "Device already exists, n",
  405.     0, 0, 0, 0, 0, 0);
  406.         break;
  407. }
  408.     /* Now, we have to ensure that its a PEGASUS device */
  409.             if (usbdDescriptorGet (pegasusHandle, 
  410.    nodeId, 
  411.    USB_RT_STANDARD | USB_RT_DEVICE, 
  412.    USB_DESCR_DEVICE, 
  413.    0, 
  414.    0, 
  415.    30, 
  416.    pBfr, 
  417.    &actLen) 
  418. != OK)
  419.         {
  420. break;
  421.              }
  422.             vendorId = USB_PEGASUS_SWAP_16 (((pUSB_DEVICE_DESCR) pBfr)->vendor);
  423.     productId = 
  424. USB_PEGASUS_SWAP_16 (((pUSB_DEVICE_DESCR) pBfr)->product);
  425.             for (index = 0; index < noOfSupportedDevices; index++)
  426. if (vendorId == pegasusAdapterList[index][0])
  427.     if (productId == pegasusAdapterList[index][1])
  428. break;
  429.   
  430.     if (index == noOfSupportedDevices )
  431. {
  432. /* device not supported */
  433. PEGASUS_LOG (PEGASUS_DBG_ATTACH, " Unsupported "
  434.      "device found vId %0x; pId %0x!!! n", 
  435.      vendorId, productId, 0, 0, 0, 0);
  436. break;
  437. }
  438.       PEGASUS_LOG (PEGASUS_DBG_ATTACH, " Found a PEGASUS "
  439. "Adapter!!!  %0x  %0xn", vendorId, productId, 0, 0, 0, 0);
  440.     /* 
  441.      * Now create a strcture for the newly found device and add 
  442.      * it to the linked list 
  443.      */
  444.             /* Try to allocate space for a new device struct */
  445.     if ((pNewDev = OSS_CALLOC (sizeof (USB_PEGASUS_DEV))) == NULL)
  446.        {
  447. break;     
  448. }
  449.     /* Fill in the device structure */
  450.     pNewDev->nodeId = nodeId;
  451.     pNewDev->configuration = configuration;
  452.     pNewDev->interface = interface;
  453.     pNewDev->vendorId = vendorId;
  454.     pNewDev->productId = productId;
  455.     /* Add this device to the linked list */
  456.     usbListLink (&pegasusDevList, pNewDev, &pNewDev->devLink, 
  457. LINK_TAIL);
  458.     /* Mark the device as being connected */
  459.     pNewDev->connected = TRUE;
  460.             /* Notify registered callers that a PEGASUS has been added */
  461.     notifyAttach (pNewDev, USB_PEGASUS_ATTACH); 
  462.     
  463.     PEGASUS_LOG (PEGASUS_DBG_ATTACH, " notify attach got called n",
  464.           0, 0, 0, 0, 0, 0);
  465.     break;
  466. case USBD_DYNA_REMOVE:
  467.             PEGASUS_LOG (PEGASUS_DBG_ATTACH, " pegasusAttachCallback "
  468. "USBD_DYNA_REMOVE case  n", 0, 0, 0, 0, 0, 0);
  469.     /* First Ensure that this device is on the list */
  470.     if ((pNewDev = pegasusFindDevice (nodeId)) == NULL)
  471.      {
  472.         PEGASUS_LOG (PEGASUS_DBG_ATTACH, "Device not found n",
  473.  0, 0, 0, 0, 0, 0);
  474.         break;
  475.         }
  476.     if (pNewDev->connected == FALSE)
  477. {
  478.           PEGASUS_LOG (PEGASUS_DBG_ATTACH, "Device not connected n",
  479.  0, 0, 0, 0, 0, 0);
  480.         
  481.                 break;    
  482. }
  483.     pNewDev->connected = FALSE;
  484.     /*
  485.      * we need not check for the vendor id/product id as if 
  486.              * the device is on the list, then it is our device only.
  487.      */
  488.             pNewDev->lockCount++;
  489.             notifyAttach (pNewDev, USB_PEGASUS_REMOVE); 
  490.        
  491.             pNewDev->lockCount--; 
  492.             /* De allocate Memory for the device */
  493.     if (pNewDev->lockCount == 0)
  494. pegasusDestroyDevice((PEGASUS_DEVICE *)pNewDev->pPegasusDev);
  495.     break;     
  496. }
  497.     OSS_FREE (pBfr);
  498.     OSS_MUTEX_RELEASE (pegasusMutex);
  499.     return OK;
  500.     }
  501. /***************************************************************************
  502. *
  503. * usbPegasusEndInit - Initializes the pegasus Library
  504. *
  505. * Initizes the pegasus Library. The Library maintains an initialization
  506. * count so that the calls to this function might be nested.
  507. *
  508. * This function initializes the system resources required for the library
  509. * initializes the linked list for the ethernet devices found.
  510. * This function reegisters the library as a client for the usbd calls and 
  511. * registers for dynamic attachment notification of usb communication device
  512. * class and Ethernet sub class of devices.
  513. *
  514. * RETURNS : OK if successful, ERROR if failure 
  515. *
  516. */
  517. STATUS usbPegasusEndInit(void)
  518.     {
  519.     
  520.     /* see if already initialized. if not, initialize the library */
  521.     initCount++;
  522.     if(initCount != 1) /* if its the first time */
  523. return OK;
  524.     memset (&pegasusDevList, 0, sizeof (pegasusDevList));
  525.     
  526.     pegasusMutex = NULL;
  527.     pegasusTxMutex = NULL;
  528.     pegasusRxMutex = NULL;
  529.     pegasusHandle = NULL;
  530.     /* create the mutex */
  531.     if (OSS_MUTEX_CREATE (&pegasusMutex) != OK)
  532. return pegasusShutdown (S_usbPegasusLib_OUT_OF_RESOURCES);
  533.     
  534.     if (OSS_MUTEX_CREATE (&pegasusTxMutex) != OK)
  535. return pegasusShutdown (S_usbPegasusLib_OUT_OF_RESOURCES);
  536.     
  537.     if (OSS_MUTEX_CREATE (&pegasusRxMutex) != OK)
  538. return pegasusShutdown (S_usbPegasusLib_OUT_OF_RESOURCES);
  539.     /* 
  540.      * Register the Library as a Client and register for 
  541.      * dynamic attachment callback.
  542.      */
  543.      if((usbdClientRegister (PEGASUS_CLIENT_NAME, &pegasusHandle) != OK) ||
  544. (usbdDynamicAttachRegister (pegasusHandle, USBD_NOTIFY_ALL,
  545.    USBD_NOTIFY_ALL, USBD_NOTIFY_ALL,
  546.    (USBD_ATTACH_CALLBACK) 
  547.    pegasusAttachCallback) != OK))
  548. {
  549. logMsg(" Registration Failed..n", 0, 0, 0, 0, 0, 0);
  550.      return pegasusShutdown (S_usbPegasusLib_USBD_FAULT);
  551. }
  552.     
  553.     return OK;
  554.     }
  555. /***************************************************************************
  556. *
  557. * findEndpoint - Searches for a BULK endpoint of the indicated direction.
  558. *
  559. * RETURNS: pointer to matching endpoint descriptor or NULL if not found
  560. * NOMANUAL
  561. */
  562. LOCAL pUSB_ENDPOINT_DESCR findEndpoint
  563.     (
  564.     pUINT8 pBfr, /* buffer to search for */
  565.     UINT16 bfrLen, /* buffer length */
  566.     UINT16 direction /* end point direction */
  567.     )
  568.     {
  569.     pUSB_ENDPOINT_DESCR pEp;
  570.     while ((pEp = (pUSB_ENDPOINT_DESCR) 
  571.     usbDescrParseSkip (&pBfr, &bfrLen, USB_DESCR_ENDPOINT)) 
  572. != NULL)
  573. {
  574. if ((pEp->attributes & USB_ATTR_EPTYPE_MASK) == USB_ATTR_BULK &&
  575.     (pEp->endpointAddress & USB_ENDPOINT_DIR_MASK) == direction)
  576.     break;
  577. }
  578.     return pEp;
  579.     }
  580. /***************************************************************************
  581. *
  582. * pegasusDevInit - Initializes the pegasus Device structure.
  583. *
  584. * This function initializes the usb ethernet device. It is called by 
  585. * usbPegasusEndLoad() as part of the end driver initialzation. 
  586. * usbPegasusEndLoad() expects this routine to perform all the device and usb 
  587. * specific initialization and fill in the corresponding member fields in the 
  588. * PEGASUS_DEVICE structure.
  589. *
  590. * This function first checks to see if the device corresponding to
  591. * <vendorId> and <productId> exits in the linkedlist pegasusDevList.
  592. * It allocates memory for the input and output buffers. The device 
  593. * descriptors will be retrieved and are used to findout the IN and OUT
  594. * bulk end points. Once the end points are found, the corresponding
  595. * pipes are constructed. The Pipe handles are stored in the device 
  596. * structure <pDevCtrl>. The device's Ethernet Address (MAC address) 
  597. * will be retrieved and the corresponding field in the device structure
  598. * will be updated. This is followed by setting up of the parameters 
  599. * like Multicast address filter list, Packet Filter bitmap etc.
  600. *
  601. * RETURNS : OK if every thing succeds and ERROR if any thing fails.
  602. *
  603. */
  604. STATUS pegasusDevInit
  605.     (
  606.     PEGASUS_DEVICE * pDevCtrl, /* the device structure to be updated */
  607.     UINT16 vendorId, /* manufacturer id of the device */
  608.     UINT16 productId     /* product id of the device */
  609.     )
  610.     {
  611.     USB_PEGASUS_DEV * pNewDev;
  612.     USB_CONFIG_DESCR * pCfgDescr;
  613.     USB_INTERFACE_DESCR * pIfDescr;
  614.     USB_ENDPOINT_DESCR * pOutEp;
  615.     USB_ENDPOINT_DESCR * pInEp;
  616.     UINT8 * pBfr;
  617.     UINT8 * pScratchBfr;
  618.     PEGASUS_ENET_IRP* pIrpBfrs;
  619.     UINT8** pInBfr;
  620.     UINT16 actLen;
  621.     int index, otherIndex = 0;
  622.     if(pDevCtrl == NULL)
  623. {
  624. PEGASUS_LOG (PEGASUS_DBG_INIT,"Null Device n", 0, 0, 0, 0, 0, 0);
  625. return ERROR;
  626. }
  627.     /* Find if the device is in the found devices list */
  628.    
  629.     if ((pNewDev = pegasusEndFindDevice (vendorId,productId)) == NULL)
  630. {
  631. PEGASUS_LOG (PEGASUS_DBG_INIT,"Could not find device..n",
  632.      0, 0, 0, 0, 0, 0);
  633. return ERROR;
  634. }
  635.     /* Link the End Structure and the device that is found */
  636.     pDevCtrl->pDev = pNewDev;
  637.     pNewDev->pPegasusDev = pDevCtrl;
  638.     
  639.     /* Allocate memory for the input and output buffers..*/
  640.     if ((pBfr = OSS_MALLOC (USB_MAX_DESCR_LEN)) == NULL)
  641. {
  642. PEGASUS_LOG (PEGASUS_DBG_INIT,"Could not allocate memory for Get"
  643.      "descriptor.n", 0, 0, 0, 0, 0, 0);
  644. return ERROR;
  645. }
  646.     if ((pIrpBfrs = OSS_MALLOC (pDevCtrl->noOfIrps * 
  647.          sizeof (PEGASUS_ENET_IRP)))  
  648.      == NULL)
  649. {
  650. PEGASUS_LOG (PEGASUS_DBG_INIT,"Could not allocate memory for IRPs.n",
  651.      0, 0, 0, 0, 0, 0);
  652. OSS_FREE (pBfr);
  653. return ERROR;
  654. }
  655.     if ((pInBfr = OSS_MALLOC (pDevCtrl->noOfInBfrs * sizeof (char *))) ==NULL)
  656. {
  657. PEGASUS_LOG (PEGASUS_DBG_INIT,"Could Not align Memory for pInBfrs ...n"
  658.       , 0, 0, 0, 0, 0, 0);
  659. OSS_FREE (pBfr);
  660. OSS_FREE (pIrpBfrs);
  661. return ERROR;
  662.         }
  663.     for (index=0;index<pDevCtrl->noOfInBfrs;index++)
  664. {
  665. if((pInBfr[index] = OSS_MALLOC (PEGASUS_IN_BFR_SIZE+8)) == NULL)
  666.     {
  667.     PEGASUS_LOG (PEGASUS_DBG_INIT,"Could Not align Memory "
  668.                         "for InBfrs  %d...n", index, 0, 0, 0, 0, 0);
  669.         OSS_FREE (pBfr);
  670.     OSS_FREE (pIrpBfrs);
  671.     for (otherIndex=0; otherIndex<index; otherIndex++)
  672. OSS_FREE (pInBfr[otherIndex]);
  673.  
  674.     OSS_FREE (pInBfr);
  675.     return ERROR;
  676.     }
  677. }
  678.     pDevCtrl->pEnetIrp = pIrpBfrs;
  679.     pDevCtrl->pInBfrArray = pInBfr;
  680.     for (index = 0; index < pDevCtrl->noOfIrps; index++)
  681. {
  682. pIrpBfrs->outIrpInUse = FALSE;
  683. pIrpBfrs ++;
  684. }
  685.     pDevCtrl->rxIndex = 0;    
  686.     pDevCtrl->txIrpIndex = 0;
  687.     pDevCtrl->outBfrLen = PEGASUS_OUT_BFR_SIZE;
  688.     pDevCtrl->inBfrLen = PEGASUS_IN_BFR_SIZE;
  689.     /* 
  690.      * Now we decifer the descriptors provided by the device ..
  691.      * we try finding out what end point is what..
  692.      * that doesn't mean we won't assume any thing, we assume certain
  693.      * things though..like there are no any alternate settings for interfaces
  694.      * etc..
  695.      */
  696.     /* To start with, get the configuration descriptor ..*/
  697.     if (usbdDescriptorGet (pegasusHandle, 
  698.    pNewDev->nodeId, 
  699.    USB_RT_STANDARD | USB_RT_DEVICE, 
  700.    USB_DESCR_CONFIGURATION, 
  701.    0, 
  702.    0, 
  703.    USB_MAX_DESCR_LEN, 
  704.    pBfr, 
  705.    &actLen) 
  706. != OK)
  707. {
  708. PEGASUS_LOG (PEGASUS_DBG_INIT, "Could not GET Desc...n",
  709.      0, 0, 0, 0, 0, 0);
  710. goto errorExit;
  711. }
  712.     if ((pCfgDescr = usbDescrParse (pBfr, 
  713.     actLen, 
  714.     USB_DESCR_CONFIGURATION)) 
  715.   == NULL)
  716. {
  717. PEGASUS_LOG (PEGASUS_DBG_INIT, "Could not find Config. Desc...n",
  718.      0, 0, 0, 0, 0, 0);
  719. goto errorExit;
  720. }
  721.     /*
  722.      * Since we registered for NOTIFY_ALL for attachment of devices,
  723.      * the configuration no and interface number as reported by the 
  724.      * call back function doesn't have any meanning.
  725.      * we refer to the PEGASUS document and it says, it has only one 
  726.      * interface with number 0. So the first (only) interface we find 
  727.      * is the interface we want. 
  728.      * If there are more interfaces and one of them meet our requirement
  729.      * (as reported by callback funtction), then we need to parse
  730.      * until we find our one..
  731.      */
  732.         
  733.     /*
  734.      * usbDescrParseSkip() modifies the value of the pointer it recieves
  735.      * so we pass it a copy of our buffer pointer
  736.      */
  737.     pScratchBfr = pBfr;     
  738.     if ((pIfDescr = usbDescrParseSkip (&pScratchBfr, 
  739.        &actLen, 
  740.        USB_DESCR_INTERFACE)) 
  741.     == NULL)
  742. {
  743. PEGASUS_LOG (PEGASUS_DBG_INIT, "Could not find Intrface Desc.n",
  744.      0, 0, 0, 0, 0, 0);
  745. goto errorExit;
  746. }
  747.     
  748.     /* Find out the output and input end points ..*/
  749.     if ((pOutEp = findEndpoint (pScratchBfr, 
  750. actLen, 
  751. USB_ENDPOINT_OUT)) 
  752.     == NULL)
  753. {
  754. PEGASUS_LOG (PEGASUS_DBG_INIT, "No Output End Point n",
  755.      0, 0, 0, 0, 0, 0);
  756.  
  757.         goto errorExit;
  758. }
  759.     if ((pInEp = findEndpoint (pScratchBfr, 
  760.        actLen, 
  761.        USB_ENDPOINT_IN)) 
  762.      == NULL)
  763. {
  764. PEGASUS_LOG (PEGASUS_DBG_INIT, "No Input End Point n",
  765.      0, 0, 0, 0, 0, 0);
  766.  
  767.         goto errorExit;
  768. }
  769.     pDevCtrl->maxPower = pCfgDescr->maxPower; 
  770.     /*
  771.      * Now, set the configuration.
  772.      */
  773.     if (usbdConfigurationSet (pegasusHandle, pNewDev->nodeId,
  774. pCfgDescr->configurationValue, 
  775. pCfgDescr->maxPower * USB_POWER_MA_PER_UNIT) != OK)
  776. {  
  777. PEGASUS_LOG (PEGASUS_DBG_INIT, "Could not set configutation. n",
  778.      0, 0, 0, 0, 0, 0);
  779.         goto errorExit;
  780. }
  781.     /* Now go off and initialize the chip and read the mac address */
  782.     usbPegasusInit (pNewDev->nodeId, (UINT8 *) pBfr);
  783.     pDevCtrl->macAdrs[0] = *pBfr;
  784.     pDevCtrl->macAdrs[1] = *(pBfr + 1);
  785.     pDevCtrl->macAdrs[2] = *(pBfr + 2);
  786.     pDevCtrl->macAdrs[3] = *(pBfr + 3);
  787.     pDevCtrl->macAdrs[4] = *(pBfr + 4);
  788.     pDevCtrl->macAdrs[5] = *(pBfr + 5);
  789.     PEGASUS_LOG (PEGASUS_DBG_INIT, "EthernetID %02x %02x %02x "
  790.     "%02x %02x %02xn", *pBfr, *(pBfr + 1), 
  791.     *(pBfr + 2), *(pBfr + 3), *(pBfr + 4), *(pBfr + 5));
  792.  
  793.     /* Now, Create the Pipes.. */
  794.     if (usbdPipeCreate (pegasusHandle, 
  795. pNewDev->nodeId, 
  796. pOutEp->endpointAddress, 
  797. pCfgDescr->configurationValue, 
  798. pNewDev->interface, 
  799. USB_XFRTYPE_BULK, 
  800. USB_DIR_OUT, 
  801. FROM_LITTLEW (pOutEp->maxPacketSize), 
  802. 0, 
  803. 0, 
  804. &pDevCtrl->outPipeHandle) 
  805. != OK)
  806. {
  807. PEGASUS_LOG (PEGASUS_DBG_INIT, "Pipe O/P coud not be created n",
  808.      0, 0, 0, 0, 0, 0);
  809.  
  810.         goto errorExit;
  811. }
  812.     
  813.     if (usbdPipeCreate (pegasusHandle, 
  814. pNewDev->nodeId, 
  815. pInEp->endpointAddress, 
  816. pCfgDescr->configurationValue, 
  817. pNewDev->interface, 
  818. USB_XFRTYPE_BULK, 
  819. USB_DIR_IN, 
  820. FROM_LITTLEW (pInEp->maxPacketSize), 
  821. 0, 
  822. 0, 
  823. &pDevCtrl->inPipeHandle) 
  824. != OK)
  825. {
  826. PEGASUS_LOG (PEGASUS_DBG_INIT, "Pipe I/P coud not be created n",
  827.            0, 0, 0, 0, 0, 0);
  828.  
  829.         goto errorExit;
  830. }
  831.     pDevCtrl->inIrpInUse = FALSE;
  832.     OSS_FREE (pBfr);
  833.     return OK;
  834. errorExit:
  835.     OSS_FREE (pBfr);
  836.     OSS_FREE (pIrpBfrs);
  837.     for (index=0; index<pDevCtrl->noOfInBfrs; index++)
  838.         OSS_FREE (pInBfr[index]);
  839.     OSS_FREE (pInBfr);
  840.     return ERROR;
  841.     }
  842. /***************************************************************************
  843. *
  844. * pegasusEndStart - Starts communications over Ethernet via usb (device)
  845. *
  846. * Since we don't have any interrupt, we have to prevent the device from 
  847. * communicating, in some other way. Here, since the reception is based 
  848. * on polling, and we do the pegasusListenForInput() for such polling,
  849. * we can delay listening to any packet coming in, by having
  850. * this function called in pegasusEndStart()... This way, we try to mimic the
  851. * traditional "interrupt enabling". This is for packet reception.
  852. *
  853. * For packet transmission, we use the communicateOk flag. We transmit data 
  854. * only if this flag is true. This flag will be set to TRUE in pegasusEndStart().
  855. * and will be reset to FALSE in pegasusEndStop().
  856. *
  857. * RETURNS : OK or ERROR
  858. */
  859. STATUS pegasusEndStart
  860.     (
  861.     PEGASUS_DEVICE * pDevCtrl         /* Device to be started */
  862.     )
  863.     {
  864.     PEGASUS_LOG (PEGASUS_DBG_START, "pegasusEndStart:..entered.n",
  865.  0, 0, 0, 0, 0, 0);
  866.     
  867.     /*
  868.      * what we do here is that we start listening on the 
  869.      * BULK input pipe..for any ethernet packet coming in.
  870.      * This is just simulating "connecting the interrupt" in End Model.
  871.      */
  872.     pDevCtrl->communicateOk = TRUE;
  873.     if (pegasusListenForInput (pDevCtrl) != OK)
  874. {
  875.         pDevCtrl->communicateOk = FALSE;
  876.         PEGASUS_LOG (PEGASUS_DBG_START, "pegasusEndStart:..Unable to listen "
  877.      "for input.n",0, 0, 0, 0, 0, 0);
  878. return ERROR;
  879. }
  880.     /* 
  881.      * The above will effectively preempt any possibility of packet reception,
  882.      * before the pegasusEndStart is called.
  883.      * for preempting such possiblity for transmission, we use the 
  884.      * communicateOk flag. Ideally we should use a semaphore here but
  885.      * i thought flag will suffice.
  886.      */
  887.     return OK;
  888.     }
  889. /***************************************************************************
  890. *
  891. * pegasusEndStop - Disables communication over Ethernet via usb (device)
  892. * The pipes will be aborted. If there are any pending transfers on these
  893. * Pipes, usbd will see to it that theu are also cancelled. The IRPs for
  894. * these transfers will be returned a S_usbHcdLib_IRP_CANCELED error code.
  895. * It waits for the IRPs to be informed of their Cancelled Status and then
  896. * the function returns.
  897. * RETURNS: OK or ERROR
  898. */
  899. STATUS pegasusEndStop
  900.     (
  901.     PEGASUS_DEVICE * pDevCtrl     /* Device to be Stopped */
  902.     )
  903.     {
  904.     pATTACH_REQUEST  pRequest; 
  905.     PEGASUS_LOG (PEGASUS_DBG_STOP, "pegasusEndStop:..entered.n",
  906.  0, 0, 0, 0, 0, 0);
  907.     /* mark the interface as down */
  908.     END_FLAGS_CLR (&pDevCtrl->endObj, (IFF_UP | IFF_RUNNING));
  909.     /* 
  910.      * We will Abort the transfers the input and output Pipes..
  911.      * once we issue such requests, usbd will take care of aborting the 
  912.      * outstanding transfers, if any, associated with the Pipes.
  913.      */
  914.     pDevCtrl->communicateOk = FALSE;
  915.     /* Dispose of any outstanding notification requests */
  916.     while ((pRequest = usbListFirst (&reqList)) != NULL)
  917. {
  918. usbListUnlink (&pRequest->reqLink);
  919. OSS_FREE (pRequest); 
  920. }
  921.     return OK;
  922.     }
  923. /***************************************************************************
  924. *
  925. * pegasusListenForInput - Listens for data on the ethernet (Bulk In Pipe) 
  926. *
  927. * Input IRP will be initialized to listen on the BULK input pipe and will
  928. * be submitted to the usbd.
  929. *
  930. * RETURNS : OK if successful or ERROR on failure.
  931. *
  932. * NOMANUAL
  933. */
  934.      
  935. LOCAL STATUS pegasusListenForInput
  936.     (
  937.     PEGASUS_DEVICE * pDevCtrl /* device to receive from */
  938.     )
  939.     {
  940.     pUSB_IRP pIrp = &pDevCtrl->inIrp;
  941.     if (pDevCtrl == NULL)
  942. return ERROR;
  943.     /* Initialize IRP */
  944.     memset (pIrp, 0, sizeof (*pIrp));
  945.     pIrp->userPtr = pDevCtrl;
  946.     pIrp->irpLen = sizeof (*pIrp);
  947.     pIrp->userCallback = pegasusRxCallback;
  948.     pIrp->timeout = USB_TIMEOUT_NONE;
  949.     pIrp->transferLen = pDevCtrl->inBfrLen; 
  950.     pIrp->flags = USB_FLAG_SHORT_OK;
  951.     pIrp->bfrCount = 1;
  952.     pIrp->bfrList[0].pid = USB_PID_IN;
  953.     pIrp->bfrList[0].bfrLen = pDevCtrl->inBfrLen; 
  954.     
  955.     pIrp->bfrList[0].pBfr = (pUINT8)pDevCtrl->pInBfrArray[pDevCtrl->rxIndex];  
  956.     /* Submit IRP */
  957.     if (usbdTransfer (pegasusHandle, pDevCtrl->inPipeHandle, pIrp) != OK)
  958. return ERROR;
  959.     pDevCtrl->inIrpInUse = TRUE;
  960.     return OK;
  961.     }
  962. /***************************************************************************
  963. *
  964. * pegasusSend - initiates data transmission to the device
  965. *
  966. * this function initiates transmission on the ethernet.
  967. *
  968. * RETURNS: OK, or ERROR if unable to initiate transmission
  969. */
  970. STATUS pegasusSend
  971.     (
  972.     PEGASUS_DEVICE * pDevCtrl, /* device to send to */
  973.     UINT8 * pBfr, /* data to send */
  974.     UINT32 size /* data size */
  975.     )
  976.     {
  977.     pUSB_IRP pIrp;
  978.     PEGASUS_ENET_IRP* pIrpBfr;
  979.     PEGASUS_LOG (PEGASUS_DBG_TX, "pegasusSend:..entered. %d bytesn", 
  980. size, 0, 0, 0, 0, 0); 
  981.     if ((pDevCtrl == NULL) || (pBfr == NULL))
  982. {
  983. return ERROR;
  984. }
  985.     if (size == 0)
  986. return ERROR;
  987.     pIrpBfr = pDevCtrl->pEnetIrp + pDevCtrl->txIrpIndex;
  988.     pIrp = &pIrpBfr -> outIrp;
  989.     pIrpBfr->outIrpInUse = TRUE;
  990.     PEGASUS_LOG (PEGASUS_DBG_TX, "pegasusSend: %d Irp put to usen", 
  991. pDevCtrl->txIrpIndex, 0, 0, 0, 0, 0); 
  992.     pDevCtrl->txIrpIndex++;
  993.     pDevCtrl->txIrpIndex %= pDevCtrl->noOfIrps;
  994.     /* Initialize IRP */
  995.     memset (pIrp, 0, sizeof (*pIrp));
  996.     pIrp->userPtr = pDevCtrl;
  997.     pIrp->irpLen = sizeof (*pIrp);
  998.     pIrp->userCallback = pegasusTxCallback;
  999.     pIrp->timeout = USB_TIMEOUT_NONE;
  1000.     pIrp->transferLen = size;
  1001.     pIrp->bfrCount = 1;
  1002.     pIrp->bfrList [0].pid = USB_PID_OUT;
  1003.     pIrp->bfrList [0].pBfr = pBfr;
  1004.     pIrp->bfrList [0].bfrLen = size;
  1005.     /* Submit IRP */
  1006.     if (usbdTransfer (pegasusHandle, pDevCtrl->outPipeHandle, pIrp) != OK)
  1007. return ERROR;
  1008.     return OK;
  1009.     }
  1010. /***************************************************************************
  1011. *
  1012. * pegasusTxCallback - Invoked upon Transmit IRP completion/cancellation
  1013. *
  1014. * NOMANUAL
  1015. */
  1016. LOCAL VOID pegasusTxCallback
  1017.     (
  1018.     pVOID p /* completed IRP */
  1019.     )
  1020.     {
  1021.     pUSB_IRP pIrp = (pUSB_IRP) p;
  1022.     int index = 0;
  1023.     PEGASUS_ENET_IRP* pIrpBfr;
  1024.     PEGASUS_DEVICE * pDevCtrl = pIrp->userPtr;
  1025.     /* Output IRP completed */
  1026.     for (index = 0; index < pDevCtrl->noOfIrps; index++)
  1027. {
  1028. pIrpBfr = pDevCtrl->pEnetIrp + index;
  1029. if (pIrp == &pIrpBfr->outIrp)
  1030.     {
  1031.     break;
  1032.     }
  1033. }
  1034.    
  1035.     if (index == pDevCtrl->noOfIrps)
  1036. return;
  1037.  
  1038.     PEGASUS_LOG (PEGASUS_DBG_TX, "Tx Callback for  %d IRP.n",
  1039.     index, 0, 0, 0, 0, 0);
  1040.     pIrpBfr = pDevCtrl->pEnetIrp + index;
  1041.     pIrpBfr->outIrpInUse = FALSE;
  1042.     OSS_FREE (pIrp->bfrList [0].pBfr);
  1043.     if (pIrp->result != OK)
  1044. {
  1045. PEGASUS_LOG (PEGASUS_DBG_TX, "Tx error %x.n",
  1046.     pIrp->result, 0, 0, 0, 0, 0);
  1047. if (pIrp->result == S_usbHcdLib_STALLED)
  1048.     {
  1049.     if (usbdFeatureClear (pegasusHandle, pDevCtrl->pDev->nodeId,
  1050.     USB_RT_STANDARD | USB_RT_ENDPOINT, 0, 1) == ERROR)
  1051. {
  1052. PEGASUS_LOG (PEGASUS_DBG_TX, "Could not clear STALL.n",
  1053.   pIrp->result, 0, 0, 0, 0, 0);
  1054. }
  1055.     }
  1056.   
  1057. pDevCtrl->outErrors++; /* Should also Update MIB */
  1058. }
  1059.     else
  1060. {
  1061. PEGASUS_LOG (PEGASUS_DBG_TX, "Tx finished.n",
  1062.   0, 0, 0, 0, 0, 0);
  1063. }
  1064.     }
  1065. /***************************************************************************
  1066. *
  1067. * pegasusRxCallback - Invoked when a Packet is received.
  1068. *
  1069. * NOMANUAL
  1070. */
  1071. LOCAL VOID pegasusRxCallback
  1072.     (
  1073.     pVOID p /* completed IRP */
  1074.     )
  1075.     {
  1076.     pUSB_IRP pIrp = (pUSB_IRP) p;
  1077.     PEGASUS_DEVICE * pDevCtrl = pIrp->userPtr;
  1078.     /* Input IRP completed */
  1079.     pDevCtrl->inIrpInUse = FALSE;
  1080.     /*
  1081.      * If the IRP was successful then pass the data back to the client.
  1082.      * Note that the netJobAdd() is not necessary here as the function 
  1083.      * is not getting executed in isr context.
  1084.      */
  1085.     if (pIrp->result != OK)
  1086. {
  1087. pDevCtrl->inErrors++; /* Should also update MIB */
  1088.   
  1089. if(pIrp->result == S_usbHcdLib_STALLED)
  1090.     {
  1091.     usbdFeatureClear (pegasusHandle,pDevCtrl->pDev->nodeId,
  1092.   USB_RT_STANDARD | USB_RT_ENDPOINT, 0, 0);
  1093.     }
  1094. }
  1095.     else
  1096. {
  1097. if( pIrp->bfrList [0].actLen >= 2)
  1098.     {
  1099.     pegasusEndRecv (pDevCtrl,pIrp->bfrList [0].pBfr, 
  1100.    pIrp->bfrList [0].actLen);
  1101.     pDevCtrl->rxIndex++;
  1102.     pDevCtrl->rxIndex %= pDevCtrl->noOfInBfrs;    
  1103.     }
  1104. }     
  1105.     /*
  1106.      * Unless the IRP was cancelled - implying the channel is being
  1107.      * torn down, re-initiate the "in" IRP to listen for more data from
  1108.      * the printer.
  1109.      */
  1110.     if (pIrp->result != S_usbHcdLib_IRP_CANCELED)
  1111. pegasusListenForInput (pDevCtrl);
  1112.     }
  1113. /***************************************************************************
  1114. *
  1115. * pegasusMCastFilterSet - Sets a Multicast Address Filter for the device
  1116. *
  1117. * Even if the host wishes to change a single multicast filter in the device,
  1118. * it must reprogram the entire list of filters using this function. 
  1119. * <pAddress> shall contain a pointer to this list of multicast addresses
  1120. * and <noOfFilters> shall hold the number of multicast address filters
  1121. * being programmed to the device.
  1122. *
  1123. * RETURNS : OK or ERROR if <noOfFilters> is BIG or if the device NAKs
  1124. */
  1125. STATUS pegasusMCastFilterSet
  1126.     (
  1127.     PEGASUS_DEVICE * pDevCtrl, /* device to add the mcast filters */
  1128.     UINT8 * pAddress, /* Mcast address filters list */
  1129.     UINT32 noOfFilters /* no. of filters to add */
  1130.     )
  1131.     {
  1132.     UINT16 actLen;
  1133.     PEGASUS_LOG (PEGASUS_DBG_MCAST, "pegasusMCastFilterSet:..entered.n",
  1134.  0, 0, 0, 0, 0, 0);
  1135.     if (pDevCtrl == NULL)
  1136. return ERROR;
  1137.     /* Check if  this many number of Filters are supported by the device */
  1138.     if ((noOfFilters < 0) || 
  1139. (noOfFilters > (pDevCtrl->mCastFilters.noMCastFilters)))
  1140. return ERROR;
  1141.     if (((noOfFilters == 0) && (pAddress != NULL)) ||
  1142. ((noOfFilters > 0) && (pAddress == NULL)))
  1143. return ERROR;
  1144.   
  1145.     /* Set the Filters */
  1146.     if (usbdVendorSpecific (pegasusHandle, 
  1147.     pDevCtrl->pDev->nodeId, 
  1148.     USB_PEGASUS_SET_BMREQ, 
  1149.     USB_PEGASUS_SET_BREQ, 
  1150.     0, 
  1151.     0x08, 
  1152.     noOfFilters*6, 
  1153.     pAddress, 
  1154.     &actLen) 
  1155.  != OK)
  1156. {
  1157. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registersn",
  1158. 0, 0, 0, 0, 0, 0);
  1159. return ERROR;
  1160. }
  1161.     return OK;
  1162.     }
  1163. /***************************************************************************
  1164. *
  1165. * pegasusFindDevice - Searches for a usb enet device for indicated <nodeId>
  1166. *
  1167. * RETURNS: pointer to matching dev struct or NULL if not found
  1168. * NOMANUAL
  1169. */
  1170. USB_PEGASUS_DEV * pegasusFindDevice
  1171.     (
  1172.     USBD_NODE_ID nodeId /* Node Id to find */
  1173.     )
  1174.     {
  1175.     USB_PEGASUS_DEV * pDev = usbListFirst (&pegasusDevList);
  1176.     while (pDev != NULL)
  1177. {
  1178. if (pDev->nodeId == nodeId)
  1179.     break;
  1180. pDev = usbListNext (&pDev->devLink);
  1181. }
  1182.     return pDev;
  1183.     }
  1184. /***************************************************************************
  1185. *
  1186. * pegasusEndFindDevice - Searches for a usb enet device for a given <productId>
  1187. * and <vendorId>.
  1188. *
  1189. * RETURNS: pointer to matching dev struct or NULL if not found
  1190. * NOMANUAL
  1191. */
  1192. USB_PEGASUS_DEV * pegasusEndFindDevice
  1193.     (
  1194.     UINT16 vendorId, /* Vendor Id to search for */
  1195.     UINT16 productId /* Product Id to search for */
  1196.     )
  1197.     {
  1198.     USB_PEGASUS_DEV * pDev = usbListFirst (&pegasusDevList);
  1199.     while (pDev != NULL)
  1200. {
  1201. if ((pDev->vendorId == vendorId) && (pDev->productId == productId))
  1202.     break;
  1203. pDev = usbListNext (&pDev->devLink);
  1204. }
  1205.     return pDev;
  1206.     }
  1207. /***************************************************************************
  1208. *
  1209. * pegasusShutdown - shuts down USB EnetLib
  1210. *
  1211. * <errCode> should be OK or S_pegasusLib_xxxx.  This value will be
  1212. * passed to ossStatus() and the return value from ossStatus() is the
  1213. * return value of this function.
  1214. *
  1215. * RETURNS: OK, or ERROR per value of <errCode> passed by caller
  1216. */
  1217. LOCAL STATUS pegasusShutdown
  1218.     (
  1219.     int errCode
  1220.     )
  1221.     {
  1222.    
  1223.     PEGASUS_DEVICE * pDev;
  1224.     /* Dispose of any open connections. */
  1225.     while ((pDev = usbListFirst (&pegasusDevList)) != NULL)
  1226. pegasusDestroyDevice (pDev);
  1227.     /*
  1228.      * Release our connection to the USBD.  The USBD automatically 
  1229.      * releases any outstanding dynamic attach requests when a client
  1230.      * unregisters.
  1231.      */
  1232.     if (pegasusHandle != NULL)
  1233. {
  1234. usbdClientUnregister (pegasusHandle);
  1235. pegasusHandle = NULL;
  1236. }
  1237.     /* Release resources. */
  1238.     if (pegasusMutex != NULL)
  1239. {
  1240. OSS_MUTEX_DESTROY (pegasusMutex);
  1241. pegasusMutex = NULL;
  1242. }
  1243.     
  1244.     if (pegasusTxMutex != NULL)
  1245. {
  1246. OSS_MUTEX_DESTROY (pegasusTxMutex);
  1247. pegasusTxMutex = NULL;
  1248. }
  1249.     
  1250.     if (pegasusRxMutex != NULL)
  1251. {
  1252. OSS_MUTEX_DESTROY (pegasusRxMutex);
  1253. pegasusRxMutex = NULL;
  1254. }
  1255.     return ossStatus (errCode);
  1256.     }
  1257. /***************************************************************************
  1258. *
  1259. * pegasusDestroyDevice - disposes of a PEGASUS_DEVICE structure
  1260. *
  1261. * Unlinks the indicated PEGASUS_DEVICE structure and de-allocates
  1262. * resources associated with the channel.
  1263. *
  1264. * RETURNS: N/A
  1265. */
  1266. void pegasusDestroyDevice
  1267.     (
  1268.     PEGASUS_DEVICE * pDevCtrl
  1269.     )
  1270.     {
  1271.     USB_PEGASUS_DEV * pDev;
  1272.     int index;
  1273.     if (pDevCtrl != NULL)
  1274. {
  1275. pDev = pDevCtrl->pDev;
  1276. /* Unlink the structure. */
  1277. usbListUnlink (&pDev->devLink);
  1278. /* Release pipes and wait for IRPs to be cancelled if necessary. */
  1279. if (pDevCtrl->outPipeHandle != NULL)
  1280.     usbdPipeDestroy (pegasusHandle, pDevCtrl->outPipeHandle);
  1281. if (pDevCtrl->inPipeHandle != NULL)
  1282.     usbdPipeDestroy (pegasusHandle, pDevCtrl->inPipeHandle);
  1283. while (pDevCtrl->pEnetIrp->outIrpInUse || pDevCtrl->inIrpInUse)
  1284.    OSS_THREAD_SLEEP (1);
  1285. for (index=0; index < pDevCtrl->noOfInBfrs; index++)
  1286.             OSS_FREE (pDevCtrl->pInBfrArray[index]);
  1287. if (pDevCtrl->pInBfrArray !=NULL)
  1288.     OSS_FREE(pDevCtrl->pInBfrArray);
  1289. if ( pDevCtrl->pEnetIrp != NULL)
  1290.     OSS_FREE(pDevCtrl->pEnetIrp);
  1291. /* Release structure. */
  1292. /* This constitutes a memory leak, however leaving it in 
  1293.  * causes failure.
  1294. if (pDev !=NULL)
  1295.     OSS_FREE (pDev);
  1296.  */
  1297. }
  1298.     }
  1299. /***************************************************************************
  1300. *
  1301. * usbPegasusEndLoad - initialize the driver and device
  1302. *
  1303. * This routine initializes the driver and the device to the operational state.
  1304. * All of the device specific parameters are passed in the initString.
  1305. * This function first extracts the vendorId and productId of the device 
  1306. * from the initialization string using the pegasusEndParse() function. It then 
  1307. * passes these parametsrs and its control strcuture to the pegasusDevInit()
  1308. * function. pegasusDevInit() does most of the device specific initialization
  1309. * and brings the device to the operational state. Please refer to pegasusLib.c
  1310. * for more details about usbenetDevInit(). This driver will be attached to MUX
  1311. * and then the memory initialization of the device is carriedout using
  1312. * pegasusEndMemInit(). 
  1313. * This function doesn't do any thing device specific. Instead, it delegates
  1314. * such initialization to pegasusDevInit(). This routine handles the other part
  1315. * of the driver initialization as required by MUX.
  1316. *
  1317. * muxDevLoad calls this function twice. First time this function is called, 
  1318. * initialization string will be NULL . We are required to fill in the device 
  1319. * name ("usb") in the string and return. The next time this function is called
  1320. * the intilization string will be proper.
  1321. *
  1322. * <initString> will be in the following format :
  1323. * "unit:vendorId:productId:noOfInBfrs:noOfIrps"
  1324. *
  1325. * PARAMETERS
  1326. *
  1327. *.IP <initString>
  1328. *The device initialization string.
  1329. *
  1330. * RETURNS: An END object pointer or NULL on error.
  1331. */
  1332. END_OBJ * usbPegasusEndLoad
  1333.     (
  1334.     char * initString                             /* initialization string */
  1335.     )
  1336.     {
  1337.     PEGASUS_DEVICE * pDrvCtrl;                      /* driver structure */
  1338.     UINT16 vendorId;                                /* vendor information */
  1339.     UINT16 productId;                               /* product information */
  1340.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Loading usb end...n", 1, 2, 3, 4, 5, 6);
  1341.     if (initString == NULL)
  1342. return (NULL);
  1343.     
  1344.     if (initString[0] == EOS)
  1345. {
  1346. /* Fill in the device name and return peacefully */
  1347. bcopy ((char *)PEGASUS_NAME, (void *)initString, PEGASUS_NAME_LEN);
  1348. return (0);
  1349. }
  1350.     /* allocate the device structure */
  1351.     pDrvCtrl = (PEGASUS_DEVICE *) OSS_CALLOC (sizeof (PEGASUS_DEVICE));
  1352.     if (pDrvCtrl == NULL)
  1353. {
  1354. PEGASUS_LOG (PEGASUS_DBG_LOAD, "No Memory!!...n", 1, 2, 3, 4, 5, 6);
  1355. goto errorExit;
  1356. }
  1357.     /* parse the init string, filling in the device structure */
  1358.     if (pegasusEndParse (pDrvCtrl, initString, &vendorId, &productId) == ERROR)
  1359. {
  1360. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Parse Failed.n", 1, 2, 3, 4, 5, 6);
  1361. goto errorExit;
  1362. }
  1363.     /* Ask the pegasusLib to do the necessary initilization. */
  1364.     if (pegasusDevInit(pDrvCtrl,vendorId,productId) == ERROR)
  1365. {
  1366. PEGASUS_LOG (PEGASUS_DBG_LOAD, "EnetDevInitFailed.n", 
  1367.     1, 2, 3, 4, 5, 6);
  1368. goto errorExit;
  1369. }
  1370.     /* initialize the END and MIB2 parts of the structure */
  1371.     if (END_OBJ_INIT (&pDrvCtrl->endObj, 
  1372.       (DEV_OBJ *)pDrvCtrl, 
  1373.       PEGASUS_NAME, 
  1374.       pDrvCtrl->unit, 
  1375.       &pegasusEndFuncTable,
  1376.       PEGASUS_DESCRIPTION) 
  1377.   == ERROR || 
  1378.  END_MIB_INIT (&pDrvCtrl->endObj, 
  1379.        M2_ifType_ethernet_csmacd, 
  1380.        &pDrvCtrl->macAdrs[0], 
  1381.        6, 
  1382.        PEGASUS_BUFSIZ, 
  1383.        PEGASUS_SPEED) 
  1384.   == ERROR)
  1385. {
  1386. PEGASUS_LOG (PEGASUS_DBG_LOAD, "END MACROS FAILED...n", 
  1387. 1, 2, 3, 4, 5, 6);
  1388. goto errorExit;
  1389. }
  1390.     /* Perform memory allocation/distribution */
  1391.     if (pegasusEndMemInit (pDrvCtrl) == ERROR)
  1392. {
  1393. PEGASUS_LOG (PEGASUS_DBG_LOAD, "endMemInit() Failed...n", 
  1394.     1, 2, 3, 4, 5, 6);
  1395. goto errorExit;
  1396. }
  1397.  
  1398.     /* set the flags to indicate readiness */
  1399.     END_OBJ_READY (&pDrvCtrl->endObj,
  1400.     IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST
  1401.     | IFF_MULTICAST);
  1402.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Done loading usb end..n", 
  1403. 1, 2, 3, 4, 5, 6);
  1404.     return (&pDrvCtrl->endObj);
  1405. errorExit:
  1406.     if (pDrvCtrl != NULL)
  1407. OSS_FREE ((char *)pDrvCtrl);
  1408.     return NULL;
  1409.     }
  1410. /***************************************************************************
  1411. *
  1412. * pegasusEndParse - parse the init string
  1413. *
  1414. * Parse the input string.  Fill in values in the driver control structure.
  1415. *
  1416. * The muxLib.o module automatically prepends the unit number to the user's
  1417. * initialization string from the BSP (configNet.h).
  1418. * This function parses the input string and fills in the places pointed
  1419. * to by <pVendorId> and <pProductId>. Unit Number of the string will be
  1420. * be stored in the device structure pointed to by <pDrvCtrl>.
  1421. *
  1422. * .IP <pDrvCtrl>
  1423. * Pointer to the device structure.
  1424. * .IP <initString>
  1425. * Initialization string for the device. It will be of the following format :
  1426. * "unit:vendorId:productId"
  1427. * Device unit number, a small integer.
  1428. * .IP <pVendorId>
  1429. * Pointer to the place holder of the device vendor id.
  1430. * .IP <pProductId>
  1431. *  Pointer to the place holder of the device product id.
  1432. *
  1433. * RETURNS: OK or ERROR for invalid arguments.
  1434. * NOMANUAL
  1435. */
  1436. STATUS pegasusEndParse
  1437.     (
  1438.     PEGASUS_DEVICE * pDrvCtrl, /* device pointer */
  1439.     char * initString, /* information string */
  1440.     UINT16 * pVendorId,
  1441.     UINT16 * pProductId
  1442.     )
  1443.     {
  1444.     char * tok;
  1445.     char * pHolder = NULL;
  1446.     
  1447.     /* Parse the initString */
  1448.     /* Unit number. (from muxLib.o) */
  1449.     tok = strtok_r (initString, ":", &pHolder);
  1450.     if (tok == NULL)
  1451. return ERROR;
  1452.     pDrvCtrl->unit = atoi (tok);
  1453.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Parse: Unit : %d..n", 
  1454. pDrvCtrl->unit, 2, 3, 4, 5, 6); 
  1455.     /* Vendor Id. */
  1456.     tok = strtok_r (NULL, ":", &pHolder);
  1457.     if (tok == NULL)
  1458. return ERROR;
  1459.     *pVendorId = atoi (tok);
  1460.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Parse: VendorId : 0x%x..n", 
  1461. *pVendorId, 2, 3, 4, 5, 6); 
  1462.     /* Product Id. */
  1463.     tok = strtok_r (NULL, ":", &pHolder);
  1464.     if (tok == NULL)
  1465. return ERROR;
  1466.     *pProductId = atoi (tok);
  1467.   
  1468.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Parse: ProductId : 0x%x..n", 
  1469. *pProductId, 2, 3, 4, 5, 6); 
  1470.     /* we have paresed the inbfrs and outirps here 
  1471.      * these vars are to be passed to pegasusEndParse from usbPegasusEndLoad. 
  1472.      */
  1473.     /* no of in buffers */
  1474.     tok = strtok_r (NULL, ":", &pHolder);
  1475.     if (tok == NULL)
  1476. return ERROR;
  1477.     pDrvCtrl->noOfInBfrs  = atoi (tok);
  1478.   
  1479.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Parse: NoInBfrs : %d..n", 
  1480. pDrvCtrl->noOfInBfrs, 2, 3, 4, 5, 6); 
  1481.     /* no of out IRPs */
  1482.     tok = strtok_r (NULL, ":", &pHolder);
  1483.     if (tok == NULL)
  1484. return ERROR;
  1485.     pDrvCtrl->noOfIrps = atoi (tok);
  1486.   
  1487.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Parse: NoOutIrps : %d..n", 
  1488.  pDrvCtrl->noOfIrps, 2, 3, 4, 5, 6);
  1489.     /*here ends the extra two parsing blocks */
  1490.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Parse: Processed all arugmentsn", 
  1491. 1, 2, 3, 4, 5, 6);
  1492.     return OK;
  1493.     }
  1494. /***************************************************************************
  1495. *
  1496. * pegasusEndSend - the driver send routine
  1497. *
  1498. * This routine takes a M_BLK_ID sends off the data in the M_BLK_ID. We copy
  1499. * the data contained in the MBlks to a character buffer and hand over the 
  1500. * buffer to pegasusSend().The buffer must already have the addressing 
  1501. * information properly installed in it.  This is done by a higher layer.   
  1502. * The device requires that the first two bytes of the data sent to it (for 
  1503. * transmission over ethernet) contain the length of the data. So we add this
  1504. * here. 
  1505. *
  1506. * During the course of our testing the driver, we found that if we send the 
  1507. * exact length of the data as handed over by MUX, the device is corrupting
  1508. * some bytes of the packet. This is resulting in packet not being received
  1509. * by the addresses destination, packet checksum errors etc. The remedy is to
  1510. * padup few bytes to the data packet. This, we found, solved the problem.
  1511. *
  1512. * RETURNS: OK or ERROR.
  1513. */
  1514. LOCAL STATUS pegasusEndSend
  1515.     (
  1516.     PEGASUS_DEVICE * pDrvCtrl, /* device ptr */
  1517.     M_BLK_ID     pMblk /* data to send */
  1518.     )
  1519.     {
  1520.     UINT8 *      pBuf;  /* buffer to hold the data */
  1521.     UINT32 noOfBytes;      /* noOfBytes to be transmitted */
  1522.     
  1523.     PEGASUS_LOG (PEGASUS_DBG_TX, "pegasusEndSend: Entered.n",
  1524. 0, 0, 0, 0, 0, 0);  
  1525.     if ((pDrvCtrl == NULL) || (pMblk == NULL))
  1526. return ERROR;
  1527.     pBuf = (UINT8 *) OSS_MALLOC (USB_PEGASUS_BUF_SIZE);
  1528.     if (pBuf == NULL)
  1529. {
  1530. PEGASUS_LOG (PEGASUS_DBG_TX," pegasusEndSend : "
  1531.     "Could not allocate memory n", 0, 0, 0, 0, 0, 0);
  1532. return ERROR;
  1533. }
  1534.     /* copy the MBlk chain to a buffer */
  1535.     noOfBytes = netMblkToBufCopy(pMblk,(char *)pBuf+2,NULL); 
  1536.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "pegasusEndSend: %d bytes to be sent.n", 
  1537. noOfBytes, 0, 0, 0, 0, 0);
  1538.     if (noOfBytes == 0) 
  1539. return ERROR;
  1540.     /* 
  1541.      * Padding : how much to pad is decided by trial and error.
  1542.      * Note that we need not add any extra bytes in the buffer.
  1543.      * since we are not using those bytes, they can be any junk 
  1544.      * whick is already in the buffer.
  1545.      * We are just interested in the count.
  1546.      */
  1547.     
  1548.     if (noOfBytes < 60)
  1549. noOfBytes = 60;
  1550.     /* (Required by the device) Fill in the Length in the first Two Bytes */
  1551.     *(UINT16 *)pBuf = noOfBytes; 
  1552.     /* Transmit the data */
  1553.     if (pegasusSend (pDrvCtrl, pBuf, noOfBytes+2) == ERROR)
  1554. return ERROR;
  1555.     PEGASUS_LOG (PEGASUS_DBG_TX, "pegasusEndSend: Pkt submitted for tx.n", 
  1556. 0, 0, 0, 0, 0, 0);
  1557.  
  1558.     /* Bump the statistic counter. */
  1559.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  1560.     /*
  1561.      * Cleanup.  The driver frees the packet now.
  1562.      */
  1563.     netMblkClChainFree (pMblk);
  1564.     return (OK);
  1565.     }
  1566. /***************************************************************************
  1567. *
  1568. * usbPegasusFreeRtn - pegasus Cluster Free Routine
  1569. *
  1570. * The pegasus driver does not use the netBufLib to free the cluster blocks.
  1571. * We do nothing when netBufLib is done with them because we allocate the 
  1572. * our buffers as IRP buffers.  The USB stack manages these buffers instead
  1573. * of netBufLib.
  1574. *
  1575. * RETURNS: N/A.
  1576. * NOMANUAL
  1577. */
  1578. void usbPegasusFreeRtn (void)
  1579.     {
  1580.     ;  /* We do nothing here.  */
  1581.     }
  1582. /***************************************************************************
  1583. *
  1584. * pegasusEndRecv - process the next incoming packet
  1585. *
  1586. * pegasusRecv is called by the pegasusIRPCallBack() upon successful execution
  1587. * of an input IRP. This means we got some proper data. This function will be 
  1588. * called with the pointer to be buffer and the length of data.
  1589. * What we do here is to construct an MBlk strcuture with the data received 
  1590. * and pass it onto the upper layer.
  1591. *
  1592. * RETURNS: N/A.
  1593. * NOMANUAL
  1594. */
  1595. STATUS pegasusEndRecv
  1596.     (
  1597.     PEGASUS_DEVICE * pDrvCtrl, /* device structure */
  1598.     UINT8 *  pData,              /* pointer to data buffer */
  1599.     UINT32  len                 /* length of data */
  1600.     )
  1601.     {
  1602.     char *      pNewCluster;    /* Clusuter to store the data */
  1603.     CL_BLK_ID pClBlk;         /* Control block to "control" the cluster */
  1604.     M_BLK_ID  pMblk;          /* and an MBlk to complete a MBlk contruct */
  1605.     PEGASUS_LOG (PEGASUS_DBG_RX, "pegasusEndRecv called...Entered len=%d n",
  1606. len, 0, 0, 0, 0, 0);
  1607.     /* Add one to our unicast data. */
  1608.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  1609.     pNewCluster = (char *)pData; 
  1610.     /* Grab a cluster block to marry to the cluster we received. */
  1611.     if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL)
  1612. {
  1613. netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pData);
  1614. PEGASUS_LOG (PEGASUS_DBG_RX, "Out of Cluster Blocks!n", 
  1615.     1, 2, 3, 4, 5, 6);
  1616. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1617. PEGASUS_LOG (PEGASUS_DBG_RX, "netClBlkGet...Errorn",
  1618.     0, 0, 0, 0, 0, 0);    
  1619. goto cleanRXD;
  1620. }
  1621.     /*
  1622.      * Let's get an M_BLK_ID and marry it to the one in the ring.
  1623.      */
  1624.     if ((pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)) 
  1625. == NULL)
  1626. {
  1627. netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk); 
  1628. netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pData);
  1629. PEGASUS_LOG (PEGASUS_DBG_RX, "Out of M Blocks!n", 
  1630.     1, 2, 3, 4, 5, 6);
  1631. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1632. PEGASUS_LOG (PEGASUS_DBG_RX, "mBlkGet...Errorn",
  1633.     0, 0, 0, 0, 0, 0);    
  1634. goto cleanRXD;
  1635. }
  1636.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  1637.     
  1638.     /* Join the cluster to the MBlock */
  1639.     if(netClBlkJoin (pClBlk, 
  1640.      pData, 
  1641.      len, 
  1642.      (FUNCPTR) usbPegasusFreeRtn, 
  1643.      0, 
  1644.      0, 
  1645.      0) 
  1646.   == NULL)
  1647. {
  1648. PEGASUS_LOG (PEGASUS_DBG_MCAST, "netClBlkJoin Failed...Errorn",
  1649.     0, 0, 0, 0, 0, 0);    
  1650. }
  1651.     if(netMblkClJoin (pMblk, pClBlk) == NULL)
  1652. {
  1653. PEGASUS_LOG (PEGASUS_DBG_RX, "mMblkClJoin...Errorn",
  1654.     0, 0, 0, 0, 0, 0);    
  1655. }
  1656.     bcopy (pData, pData+2, len & ~0xc000);
  1657.     pMblk->mBlkHdr.mData += 2;
  1658.     pMblk->mBlkHdr.mLen = len;
  1659.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1660.     pMblk->mBlkPktHdr.len = len;
  1661.     /* Call the upper layer's receive routine. */
  1662.     END_RCV_RTN_CALL(&pDrvCtrl->endObj, pMblk); 
  1663. cleanRXD:
  1664.     return OK;
  1665.     }
  1666. /***************************************************************************
  1667. *
  1668. * pegasusEndMemInit - initialize memory for the device.
  1669. *
  1670. * Setup the END's Network memory pool.  The memory allocation is done once
  1671. * when the device is first inserted.  Cluster block and M-Block memory area's
  1672. * are created and sorted in global structures:
  1673. *
  1674. * pegasusMclBlkConfig
  1675. * and 
  1676. * pegasusClDescTbl
  1677. * the netPool is created and stored in the global pointer:
  1678. *
  1679. * pUsbPegasusNetPool
  1680. * All subsequent insertions will reuse these memory area's.  
  1681. *
  1682. * RETURNS: OK or ERROR.
  1683. * NOMANUAL
  1684. */
  1685. STATUS pegasusEndMemInit
  1686.     (
  1687.     PEGASUS_DEVICE * pDrvCtrl /* device to be initialized */
  1688.     )
  1689.     {
  1690.     if (usbPegasusEndMemoryIsNotSetup)
  1691. {
  1692. pegasusMclBlkConfig.mBlkNum = PEGASUS_M_BLK_NUM;
  1693. pegasusClDescTbl[0].clNum = PEGASUS_CL_NUM;
  1694. pegasusMclBlkConfig.clBlkNum = pegasusClDescTbl[0].clNum;
  1695. /* Calulate the memory size for the mBlks and cBlks.  */
  1696. pegasusMclBlkConfig.memSize = 
  1697.     (pegasusMclBlkConfig.mBlkNum * (MSIZE + sizeof (long))) +
  1698.     (pegasusMclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof (long)));
  1699. /* Allocate the memory */
  1700. pegasusMclBlkConfig.memArea = 
  1701.     OSS_MALLOC (pegasusMclBlkConfig.memSize);
  1702. if (pegasusMclBlkConfig.memArea == NULL)
  1703.     {
  1704.     PEGASUS_LOG (PEGASUS_DBG_LOAD,"pegasusEndMemInit:system memory "
  1705.     "unavailable for mBlk clBlk arean", 1, 2, 3, 4, 5, 6);
  1706.     return (ERROR);
  1707.     }
  1708. /* Calulate the memory size for the clusters. */
  1709. pegasusClDescTbl[0].memSize = 
  1710.     (pegasusClDescTbl[0].clNum * (PEGASUS_BUFSIZ+ 8 + sizeof(int)));
  1711. /* Allocate the memory */
  1712. pegasusClDescTbl[0].memArea = OSS_MALLOC (pegasusClDescTbl[0].memSize);
  1713. if (pegasusClDescTbl[0].memArea == NULL)
  1714.     {
  1715.     /* Fatal, free the previously alloced area and return */
  1716.     
  1717.     PEGASUS_LOG (PEGASUS_DBG_LOAD,"pegasusEndMemInit:system memory "
  1718.     "unavailable for cluster arean", 1, 2, 3, 4, 5, 6);
  1719.     OSS_FREE (pegasusMclBlkConfig.memArea);
  1720.     return (ERROR);
  1721.     }
  1722. /* 
  1723.  * If we've made it here both memory area's have been succesfully
  1724.  * alloc'd, now initialize the memory pool
  1725.  */
  1726. /* Allocate an END netPool */
  1727.     
  1728. pUsbPegasusNetPool = OSS_MALLOC (sizeof (NET_POOL));
  1729. if (pUsbPegasusNetPool == NULL)
  1730.     {
  1731.     /* Fatal, free the previously alloced areas and return */
  1732.     PEGASUS_LOG (PEGASUS_DBG_LOAD,"pegasusEndMemInit:system memory "
  1733.     "unavailable for netPooln", 1, 2, 3, 4, 5, 6);
  1734.     OSS_FREE (pegasusMclBlkConfig.memArea);
  1735.     OSS_FREE (pegasusClDescTbl[0].memArea);
  1736.     return (ERROR);
  1737.     }
  1738. /* Now initialize the pool */
  1739. if (netPoolInit (pUsbPegasusNetPool, 
  1740.  &pegasusMclBlkConfig, 
  1741.  &pegasusClDescTbl[0], 
  1742.  pegasusClDescTblNumEnt, 
  1743.  NULL) 
  1744.       == ERROR)
  1745.     {
  1746.     /* Fatal, free the previously alloced areas and return */
  1747.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Could not init bufferingn",
  1748.     1, 2, 3, 4, 5, 6);
  1749.     OSS_FREE (pegasusMclBlkConfig.memArea);
  1750.     OSS_FREE (pegasusClDescTbl[0].memArea);
  1751.     return (ERROR);
  1752.     }
  1753.     
  1754. /* 
  1755.  * Mark the memory setup flag as false so we don't try to 
  1756.  * setup memory again.
  1757.  */
  1758. usbPegasusEndMemoryIsNotSetup = FALSE;
  1759. }  /* end of initial memory setup */
  1760.     pDrvCtrl->endObj.pNetPool = pUsbPegasusNetPool;
  1761.     if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool, 
  1762.        PEGASUS_BUFSIZ, 
  1763.        FALSE)) 
  1764.     == NULL)
  1765. {
  1766. PEGASUS_LOG (PEGASUS_DBG_LOAD, "netClPoolIdGet() not successfull n",
  1767.     1, 2, 3, 4, 5, 6);
  1768. return (ERROR);
  1769.     
  1770. }
  1771.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Memory setup completen", 
  1772. 1, 2, 3, 4, 5, 6);
  1773.     return OK;
  1774.     }
  1775. /***************************************************************************
  1776. *
  1777. * pegasusEndConfig - reconfigure the interface under us.
  1778. *
  1779. * Reconfigure the interface setting promiscuous/ broadcast etc modes, and 
  1780. * changing the multicast interface list.
  1781. *
  1782. * RETURNS: N/A.
  1783. */
  1784. LOCAL STATUS pegasusEndConfig
  1785.     (
  1786.     PEGASUS_DEVICE * pDrvCtrl /* device to be re-configured */
  1787.     )
  1788.     {
  1789.     UINT8 bitmap = 0x00;    
  1790.     MULTI_TABLE * pList = NULL;
  1791.     /* Set the modes asked for. */
  1792.     if (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_PROMISC)
  1793. {
  1794. PEGASUS_LOG (PEGASUS_DBG_IOCTL, "Setting Promiscuous mode on!n",
  1795. 1, 2, 3, 4, 5, 6);
  1796. bitmap |= PACKET_TYPE_PROMISCOUS;
  1797. }
  1798.     if (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_MULTICAST)
  1799. {
  1800. PEGASUS_LOG (PEGASUS_DBG_IOCTL, "Setting Multicast mode On!n",
  1801. 1, 2, 3, 4, 5, 6);
  1802. bitmap |= PACKET_TYPE_MULTICAST;
  1803. }
  1804.     if (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_ALLMULTI)
  1805. {
  1806. PEGASUS_LOG (PEGASUS_DBG_IOCTL, "Setting ALLMULTI mode On!n",
  1807. 1, 2, 3, 4, 5, 6);
  1808. bitmap |= PACKET_TYPE_ALL_MULTICAST;
  1809. }
  1810.     if (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_BROADCAST)
  1811. {
  1812. PEGASUS_LOG (PEGASUS_DBG_IOCTL, "Setting Broadcast mode On!n",
  1813. 1, 2, 3, 4, 5, 6);
  1814. bitmap |= PACKET_TYPE_BROADCAST;
  1815. }
  1816.     /* Set up address filter for multicasting. */
  1817.     if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0)
  1818. {
  1819. /* get the list of address to send to the device */
  1820. if (etherMultiGet (&pDrvCtrl->endObj.multiList, pList)
  1821.     == ERROR)
  1822.     return ERROR;
  1823. /* Set the Filter!!! */
  1824. if (pegasusMCastFilterSet(pDrvCtrl,(UINT8 *)pList->pTable,
  1825.     (pList->len) / 6) == ERROR)
  1826.     return ERROR; 
  1827. }
  1828.     return OK;
  1829.     }
  1830. /***************************************************************************
  1831. *
  1832. * pegasusEndMCastAdd - add a multicast address for the device
  1833. *
  1834. * This routine adds a multicast address to whatever the chip is already 
  1835. * listening for. The usb Ethernet device specifically requires that even 
  1836. * if we want a small modification (addtion or removal) of the filter list,
  1837. * we download the entire list to the device. We use the generic etherMultiLib
  1838. * functions and then call the pegasusMCastFilterSet() to achieve the
  1839. * functionality.
  1840. *
  1841. * RETURNS: OK or ERROR.
  1842. */
  1843. LOCAL STATUS pegasusEndMCastAdd
  1844.     (
  1845.     PEGASUS_DEVICE * pDrvCtrl, /* device pointer */
  1846.     char * pAddress /* new address to add */
  1847.     )
  1848.     {
  1849.     
  1850.     int error;
  1851.     char multiArray [6*6]; 
  1852.     MULTI_TABLE multiTable; 
  1853.     if ((pDrvCtrl == NULL) || (pAddress == NULL))
  1854. return ERROR;
  1855.     /* First, add this address to the local list */
  1856.     
  1857.     if ((error = etherMultiAdd (&pDrvCtrl->endObj.multiList,
  1858. pAddress)) 
  1859.    == ERROR)
  1860. return ERROR;
  1861.   
  1862.     /* Initialize multi table and array */     
  1863.     multiTable.len = sizeof (multiArray);
  1864.     multiTable.pTable = multiArray;
  1865.     /* Then get the list of address to send to the device */
  1866.     if ((error = etherMultiGet (&pDrvCtrl->endObj.multiList, &multiTable))
  1867. == ERROR)
  1868. return ERROR;   
  1869.     /* Set the Filter!!! */
  1870.     if ((error = pegasusMCastFilterSet (pDrvCtrl, 
  1871. (UINT8 *) multiTable.pTable, 
  1872. (multiTable.len) / 6)) 
  1873.    == ERROR)
  1874. return ERROR;
  1875.     return (OK);
  1876.     }
  1877. /***************************************************************************
  1878. *
  1879. * pegasusEndMCastDel - delete a multicast address for the device
  1880. *
  1881. * This routine removes a multicast address from whatever the driver 
  1882. * is listening for. The usb Ethernet device specifically requires that even 
  1883. * if we want a small modification (addtion or removal) of the filter list,
  1884. * we download the entire list to the device. We use the generic etherMultiLib
  1885. * functions and then call the pegasusMCastFilterSet() to achieve the
  1886. * functionality.
  1887. *
  1888. * RETURNS: OK or ERROR.
  1889. */
  1890. LOCAL STATUS pegasusEndMCastDel
  1891.     (
  1892.     PEGASUS_DEVICE * pDrvCtrl, /* device pointer */
  1893.     char * pAddress /* new address to add */
  1894.     )
  1895.     {
  1896.     MULTI_TABLE* pList = NULL;
  1897.     if ((pDrvCtrl == NULL) || (pAddress == NULL))
  1898. return ERROR;
  1899.     /* First, add this address to the local list */
  1900.     
  1901.     if (etherMultiDel (&pDrvCtrl->endObj.multiList, pAddress) == ERROR)
  1902. return ERROR;
  1903.      
  1904.     /* Then get the list of address to send to the device */
  1905.  
  1906.     if (etherMultiGet (&pDrvCtrl->endObj.multiList, pList) == ERROR)
  1907. return ERROR;   
  1908.     if (pegasusMCastFilterSet (pDrvCtrl, (UINT8 *)pList->pTable,
  1909. (pList->len) / 6) == ERROR)
  1910. return ERROR;
  1911.     return (OK);
  1912.     }
  1913. /***************************************************************************
  1914. *
  1915. * pegasusEndMCastGet - get the multicast address list for the device
  1916. *
  1917. * This routine gets the multicast list of whatever the driver
  1918. * is already listening for.
  1919. *
  1920. * RETURNS: OK or ERROR.
  1921. */
  1922. LOCAL STATUS pegasusEndMCastGet
  1923.     (
  1924.     PEGASUS_DEVICE * pDrvCtrl, /* device pointer */
  1925.     MULTI_TABLE * pTable /* address table to be filled in */
  1926.     )
  1927.     {
  1928.     return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable));
  1929.     }
  1930. /***************************************************************************
  1931. *
  1932. * pegasusEndIoctl - the driver I/O control routine
  1933. *
  1934. * Process an ioctl request.
  1935. *
  1936. * RETURNS: A command specific response, usually OK or ERROR.
  1937. */
  1938. int pegasusEndIoctl
  1939.     (
  1940.     PEGASUS_DEVICE * pDrvCtrl, /* device receiving command */
  1941.     int cmd, /* ioctl command code */
  1942.     caddr_t data /* command argument */
  1943.     )
  1944.     {
  1945.     int error = 0;
  1946.     long value;
  1947.     switch (cmd)
  1948. {
  1949. case EIOCSADDR : /* Set Device Address */
  1950.     if (data == NULL)
  1951. return (EINVAL);
  1952.     bcopy ((char *)data, 
  1953.    (char *) END_HADDR (&pDrvCtrl->endObj),
  1954.    END_HADDR_LEN (&pDrvCtrl->endObj));
  1955.     break;
  1956. case EIOCGADDR : /* Get Device Address */
  1957.     if (data == NULL)
  1958. return (EINVAL);
  1959.     bcopy ((char *)END_HADDR (&pDrvCtrl->endObj), (char *)data,
  1960.     END_HADDR_LEN (&pDrvCtrl->endObj));
  1961.     break;
  1962. case EIOCSFLAGS : /* Set Device Flags */
  1963.   
  1964.     value = (long)data;
  1965.     if (value < 0)
  1966. {
  1967. value = -(--value);
  1968. END_FLAGS_CLR (&pDrvCtrl->endObj, value);
  1969. }
  1970.     else
  1971. {
  1972. END_FLAGS_SET (&pDrvCtrl->endObj, value);
  1973. }
  1974.     pegasusEndConfig (pDrvCtrl);
  1975.     break;
  1976.         case EIOCGFLAGS: /* Get Device Flags */
  1977.     *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj);
  1978.             break;
  1979. case EIOCPOLLSTART : /* Begin polled operation */
  1980.     return EINVAL; /* Not supported */
  1981. case EIOCPOLLSTOP : /* End polled operation */
  1982.     return EINVAL; /* Not supported */
  1983.         case EIOCGMIB2 : /* return MIB information */
  1984.             if (data == NULL)
  1985.                 return (EINVAL);
  1986.             bcopy ((char *)&pDrvCtrl->endObj.mib2Tbl, 
  1987.      (char *)data, 
  1988.      sizeof(pDrvCtrl->endObj.mib2Tbl));
  1989.             break;
  1990.         case EIOCGFBUF : /* return minimum First Buffer for chaining */
  1991.             if (data == NULL)
  1992.                 return (EINVAL);
  1993.             *(int *)data = PEGASUS_MIN_FBUF;
  1994.             break;
  1995. case EIOCMULTIADD :  /* Add a Multicast Address */
  1996.     if (data == NULL)
  1997. return (EINVAL);
  1998.     if (pegasusEndMCastAdd (pDrvCtrl, (char *)data) == ERROR)
  1999.                 return ERROR;
  2000.     break;
  2001. case EIOCMULTIDEL :  /* Delete a Multicast Address */
  2002.     if (data == NULL)
  2003. return (EINVAL);
  2004.     if (pegasusEndMCastDel (pDrvCtrl, (char *)data) == ERROR)
  2005. return ERROR;
  2006.     break;
  2007. case EIOCMULTIGET :  /* Get the Multicast List */
  2008.     if (data == NULL)
  2009. return (EINVAL);
  2010.     if (pegasusEndMCastGet (pDrvCtrl, (MULTI_TABLE *)data) == ERROR)
  2011. return ERROR;
  2012.     break;
  2013.        default:
  2014.             error = EINVAL;
  2015.         }
  2016.     return (error);
  2017.     }
  2018. /***************************************************************************
  2019. *
  2020. * usbPegasusEndUnload - unload a driver from the system
  2021. *
  2022. * This function first brings down the device, and then frees any
  2023. * stuff that was allocated by the driver in the load function.
  2024. *
  2025. * RETURNS: OK or ERROR.
  2026. */
  2027. LOCAL STATUS usbPegasusEndUnload
  2028.     (
  2029.     PEGASUS_DEVICE * pDrvCtrl /* device to be unloaded */
  2030.     )
  2031.     {
  2032.     PEGASUS_LOG (PEGASUS_DBG_STOP, "UnloadEnd...n ", 1, 2, 3, 4, 5, 6);
  2033.     END_OBJECT_UNLOAD (&pDrvCtrl->endObj);
  2034.   
  2035.     if ((pDrvCtrl->pDev->lockCount == 0) && (!pDrvCtrl->pDev->connected))
  2036.        {
  2037.         PEGASUS_LOG (PEGASUS_DBG_STOP, "Lock count is 0 and No device"
  2038.      "connectedn", 1, 2, 3, 4, 5, 6);
  2039. }
  2040.     else
  2041. PEGASUS_LOG (PEGASUS_DBG_STOP, "Device lockCount = %x "
  2042.                     "connected =%xn",pDrvCtrl->pDev->lockCount,
  2043.                     pDrvCtrl->pDev->connected,3,4,5,6); 
  2044.     PEGASUS_LOG (PEGASUS_DBG_STOP,"Unloading End...Done!!!n",1,2,3,4,5,6);
  2045.     return (OK);
  2046.     }
  2047. /***************************************************************************
  2048. *
  2049. * pegasusEndPollRcv - routine to receive a packet in polled mode.
  2050. *
  2051. * This routine is NOT supported
  2052. *
  2053. * RETURNS: ERROR Always
  2054. */
  2055. LOCAL STATUS pegasusEndPollRcv
  2056.     (
  2057.     PEGASUS_DEVICE * pDrvCtrl, /* device to be polled */
  2058.     M_BLK_ID      pMblk /* ptr to buffer */
  2059.     )
  2060.     {
  2061.     
  2062.     PEGASUS_LOG (PEGASUS_DBG_POLL_RX, "Poll Recv: NOT SUPPORTED", 
  2063. 1, 2, 3, 4, 5, 6);
  2064.     return ERROR;
  2065.     }
  2066. /***************************************************************************
  2067. *
  2068. * pegasusEndPollSend - routine to send a packet in polled mode.
  2069. *
  2070. * This routine is NOT SUPPORTED
  2071. *
  2072. * RETURNS: ERROR always
  2073. */
  2074. LOCAL STATUS pegasusEndPollSend
  2075.     (
  2076.     PEGASUS_DEVICE *  pDrvCtrl, /* device to be polled */
  2077.     M_BLK_ID    pMblk /* packet to send */
  2078.     )
  2079.     {
  2080.     
  2081.     PEGASUS_LOG (PEGASUS_DBG_POLL_TX, "Poll Send : NOT SUPPORTED", 
  2082. 1, 2, 3, 4, 5, 6);
  2083.     return ERROR;
  2084.     }
  2085. /***************************************************************************
  2086. *
  2087. * notifyAttach - Notifies registered callers of attachment/removal
  2088. *
  2089. * RETURNS: N/A
  2090. */
  2091. LOCAL VOID notifyAttach
  2092.     (
  2093.     USB_PEGASUS_DEV * pDev,
  2094.     UINT16 attachCode
  2095.     )
  2096.     {
  2097.     pATTACH_REQUEST pRequest = usbListFirst (&reqList);
  2098.     
  2099.     PEGASUS_LOG (PEGASUS_DBG_ATTACH, "In notify attach, n",
  2100.      0, 0, 0, 0, 0, 0);    
  2101.     while (pRequest != NULL)
  2102.      {
  2103.      (*pRequest->callback) (pRequest->callbackArg, 
  2104.                        pDev, 
  2105.        attachCode);
  2106. PEGASUS_LOG (PEGASUS_DBG_ATTACH, "Callback executed for node Id %x n",
  2107.      (ULONG)pDev->nodeId, 0, 0, 0, 0, 0);    
  2108.      pRequest = usbListNext (&pRequest->reqLink);
  2109.     
  2110.      }
  2111.     }
  2112. /***************************************************************************
  2113. *
  2114. * usbPegasusDynamicAttachRegister - Register PEGASUS device attach callback.
  2115. *
  2116. * <callback> is a caller-supplied function of the form:
  2117. *
  2118. * .CS
  2119. * typedef (*USB_PEGASUS_ATTACH_CALLBACK) 
  2120. *     (
  2121. *     pVOID arg,
  2122. *     USB_PEGASUS_DEV * pDev,
  2123. *     UINT16 attachCode
  2124. *     );
  2125. * .CE
  2126. *
  2127. * usbPegasusDevLib will invoke <callback> each time a PEGASUS device
  2128. * is attached to or removed from the system.  <arg> is a caller-defined
  2129. * parameter which will be passed to the <callback> each time it is
  2130. * invoked.  The <callback> will also  pass the structure of the device 
  2131. * being created/destroyed and an attach code of USB_PEGASUS_ATTACH or 
  2132. * USB_PEGASUS_REMOVE.
  2133. *
  2134. * NOTE: The user callback routine should not invoke any driver function that
  2135. * submits IRPs.  Further processing must be done from a different task context.
  2136. * As the driver routines wait for IRP completion, they cannot be invoked from
  2137. * USBD client task's context created for this driver.
  2138. *
  2139. *
  2140. * RETURNS: OK, or ERROR if unable to register callback
  2141. *
  2142. * ERRNO:
  2143. *   S_usbPegasusLib_BAD_PARAM
  2144. *   S_usbPegasusLib_OUT_OF_MEMORY
  2145. */
  2146. STATUS usbPegasusDynamicAttachRegister
  2147.     (
  2148.     USB_PEGASUS_ATTACH_CALLBACK callback, /* new callback to be registered */
  2149.     pVOID arg                           /* user-defined arg to callback  */
  2150.     )
  2151.     {
  2152.     pATTACH_REQUEST   pRequest;
  2153.     USB_PEGASUS_DEV  *       pPegasusDev;
  2154.     int status = OK;
  2155.     /* Validate parameters */
  2156.     if (callback == NULL)
  2157.         return (ossStatus (S_usbPegasusLib_BAD_PARAM));
  2158.     OSS_MUTEX_TAKE (pegasusMutex, OSS_BLOCK);
  2159.     /* Create a new request structure to track this callback request. */
  2160.     if ((pRequest = OSS_CALLOC (sizeof (*pRequest))) == NULL)
  2161.         {
  2162.         status = ossStatus (S_usbPegasusLib_OUT_OF_MEMORY);
  2163.         }
  2164.     else
  2165.         {
  2166.         pRequest->callback    = callback;
  2167.         pRequest->callbackArg = arg;
  2168.         usbListLink (&reqList, pRequest, &pRequest->reqLink, LINK_TAIL);
  2169.     
  2170.        /* 
  2171.         * Perform an initial notification of all currrently attached
  2172.         * PEGASUS devices.
  2173.         */
  2174.         pPegasusDev = usbListFirst (&pegasusDevList);
  2175.         while (pPegasusDev != NULL)
  2176.     {
  2177.     if (pPegasusDev->connected)
  2178.                 (*callback) (arg, pPegasusDev, USB_PEGASUS_ATTACH);
  2179.                 
  2180.     PEGASUS_LOG (PEGASUS_DBG_ATTACH, "Callback executed for device"
  2181.  " nodeid %0x, n", (ULONG)pPegasusDev->nodeId, 
  2182.  0, 0, 0, 0, 0);    
  2183.     
  2184.     pPegasusDev = usbListNext (&pPegasusDev->devLink);
  2185.     
  2186.     }
  2187.         }
  2188.     OSS_MUTEX_RELEASE (pegasusMutex);
  2189.     return (ossStatus (status));
  2190.     }
  2191. /***************************************************************************
  2192. *
  2193. * usbPegasusDynamicAttachUnregister - Unregisters PEGASUS attach callback.
  2194. *
  2195. * This function cancels a previous request to be dynamically notified for
  2196. * PEGASUS device attachment and removal.  The <callback> and <arg> paramters 
  2197. * must exactly match those passed in a previous call to 
  2198. * usbPegasusDynamicAttachRegister().
  2199. *
  2200. * RETURNS: OK, or ERROR if unable to unregister callback
  2201. *
  2202. * ERRNO:
  2203. *   S_usbPegasusLib_NOT_REGISTERED
  2204. */
  2205. STATUS usbPegasusDynamicAttachUnregister
  2206.     (
  2207.     USB_PEGASUS_ATTACH_CALLBACK callback, /* callback to be unregistered  */
  2208.     pVOID arg                          /* user-defined arg to callback */
  2209.     )
  2210.     {
  2211.     pATTACH_REQUEST pRequest;
  2212.     int status = S_usbPegasusLib_NOT_REGISTERED;
  2213.     OSS_MUTEX_TAKE (pegasusMutex, OSS_BLOCK);
  2214.     pRequest = usbListFirst (&reqList);
  2215.     while (pRequest != NULL)
  2216.         {
  2217.         if ((callback == pRequest->callback) && (arg == pRequest->callbackArg))
  2218.     {
  2219.     /* Found a matching notification request. */
  2220.     usbListUnlink (&pRequest->reqLink);
  2221.             /* Dispose of structure */
  2222.             OSS_FREE (pRequest);
  2223.     status = OK;
  2224.     break;
  2225.     }
  2226.         pRequest = usbListNext (&pRequest->reqLink);
  2227. }
  2228.     OSS_MUTEX_RELEASE (pegasusMutex);
  2229.     return (ossStatus (status));
  2230.     }
  2231. /***************************************************************************
  2232. *
  2233. * usbPegasusDevLock - Marks USB_PEGASUS_DEV structure as in use.
  2234. *
  2235. * A caller uses usbPegasusDevLock() to notify usbPegasusDevLib that
  2236. * it is using the indicated PEGASUS device structure.  usbPegasusDevLib maintains
  2237. * a count of callers using a particular Pegasus Device structure so that it 
  2238. * knows when it is safe to dispose of a structure when the underlying
  2239. * Pegasus Device is removed from the system.  So long as the "lock count"
  2240. * is greater than zero, usbPegasusDevLib will not dispose of an Pegasus
  2241. * structure.
  2242. *
  2243. * RETURNS: OK, or ERROR if unable to mark Pegasus structure in use.
  2244. */
  2245. STATUS usbPegasusDevLock
  2246.     (
  2247.     USBD_NODE_ID nodeId    /* 
  2248.     * NodeId of the USB_PEGASUS_DEV 
  2249.     * to be marked as in use 
  2250.     */
  2251.     )
  2252.     {
  2253.     USB_PEGASUS_DEV * pPegasusDev = pegasusFindDevice (nodeId);
  2254.     if ( pPegasusDev == NULL)
  2255.         return (ERROR);
  2256.     pPegasusDev->lockCount++;
  2257.     return (OK);
  2258.     }
  2259. /***************************************************************************
  2260. *
  2261. * usbPegasusDevUnlock - Marks USB_PEGASUS_DEV structure as unused.
  2262. *
  2263. * This function releases a lock placed on an Pegasus Device structure.  When a
  2264. * caller no longer needs an Pegasus Device structure for which it has previously
  2265. * called usbPegasusDevLock(), then it should call this function to
  2266. * release the lock.
  2267. *
  2268. * NOTE: If the underlying Pegasus device has already been removed
  2269. * from the system, then this function will automatically dispose of the
  2270. * Pegasus Device structure if this call removes the last lock on the structure.
  2271. * Therefore, a caller must not reference the Pegasus Device structure after
  2272. * making this call.
  2273. *
  2274. * RETURNS: OK, or ERROR if unable to mark Pegasus Device structure unused
  2275. *
  2276. * ERRNO:
  2277. *   S_usbPegasusLib_NOT_LOCKED
  2278. */
  2279. STATUS usbPegasusDevUnlock
  2280.     (
  2281.     USBD_NODE_ID nodeId    /* NodeId of the BLK_DEV to be marked as unused */
  2282.     )
  2283.     {
  2284.     int status = OK;
  2285.     USB_PEGASUS_DEV * pPegasusDev = pegasusFindDevice (nodeId);
  2286.     if ( pPegasusDev == NULL)
  2287.    {
  2288.         return (ERROR);
  2289. }
  2290.     OSS_MUTEX_TAKE (pegasusMutex, OSS_BLOCK);
  2291.     if (pPegasusDev->lockCount == 0)
  2292.         {
  2293.         PEGASUS_LOG (PEGASUS_DBG_STOP,"usbPegasusDevUnlock..Not Locked!n",
  2294.                     1,2,3,4,5,6);
  2295.         status = S_usbPegasusLib_NOT_LOCKED;
  2296.         }
  2297.     else
  2298.     {
  2299.     /* If this is the last lock and the underlying PEGASUS device is
  2300.      * no longer connected, then dispose of the device.
  2301.      */
  2302.     if ((--pPegasusDev->lockCount == 0) && (!pPegasusDev->connected))
  2303.         {
  2304. pegasusDestroyDevice ((PEGASUS_DEVICE *)pPegasusDev->pPegasusDev);
  2305.        PEGASUS_LOG (PEGASUS_DBG_STOP,"Pegasus Device Destroyed inDevUnlockn",
  2306.                     1,2,3,4,5,6);
  2307.         }
  2308.     }
  2309.     OSS_MUTEX_RELEASE (pegasusMutex);
  2310.     return (ossStatus (status));
  2311.     }
  2312. /***************************************************************************
  2313. *
  2314. * usbPegasusInit - Chip Initialization for the Pegasus Chip
  2315. *
  2316. * This Function initializes the device specific registers for the PEGASUS
  2317. * chip. This function will reset the MAC and loads the Ethernet ID read from
  2318. * EEPROM.
  2319. *
  2320. * RETURNS: OK on Success and ERROR on failure
  2321. */
  2322. STATUS usbPegasusInit
  2323.     (
  2324.     USBD_NODE_ID devId,         /* Id of the Pegasus Device to be initialized */
  2325.     UINT8 * macAdrs             /* Ethernet ID to be returned */
  2326.     )
  2327.     {
  2328.     UINT16 phyWord;
  2329.     UINT8 * pBfr;
  2330.     UINT16 actLen;
  2331.     UINT8 * pEepromData;
  2332.     UINT8 tempIndex;
  2333.     UINT8 tempIndex2=0;
  2334.     int i;
  2335.     /* Create buffers for data transfer */
  2336.     pBfr = OSS_MALLOC (USB_MAX_DESCR_LEN);
  2337.     if (pBfr == NULL)
  2338. {
  2339. printf ("usbPegasusInit() could not allocate memoryn");
  2340. return ERROR;
  2341. }
  2342.     pEepromData = OSS_MALLOC (255);
  2343.     if (pEepromData == NULL)
  2344. {
  2345. printf ("usbPegasusInit() could not allocate memoryn");
  2346. OSS_FREE (pBfr);
  2347. return ERROR;
  2348. }
  2349.     /* Read the Ethernet ID registers from the device */
  2350.     if (usbdVendorSpecific (pegasusHandle, devId,
  2351.                            USB_PEGASUS_GET_BMREQ, 
  2352.                            USB_PEGASUS_GET_BREQ, 
  2353.                            0, 0x10, 0x6, pEepromData, &actLen) != OK)
  2354. {
  2355. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Reading Ethernet ID n",
  2356.     0, 0, 0, 0, 0, 0);
  2357. goto errorExit;
  2358. }
  2359.     /* Set USB test registers */
  2360.     *pBfr = 0x11;
  2361.     *(pBfr + 1) = 0x00;
  2362.     if (usbdVendorSpecific (pegasusHandle, devId,
  2363.                            USB_PEGASUS_SET_BMREQ, 
  2364.                            USB_PEGASUS_SET_BREQ, 
  2365.                            0, 0x80, 2, pBfr, &actLen) != OK)
  2366. {
  2367. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registersn",
  2368. 0, 0, 0, 0, 0, 0);
  2369. goto errorExit;
  2370. }
  2371.     
  2372.     /* Read the contents of EEPROM */
  2373.     for(tempIndex =0; tempIndex<16; tempIndex++)
  2374. {
  2375. if(usbPegasusReadSrom (devId, tempIndex, &phyWord) != OK)
  2376.     {
  2377.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error retreiving Ethernet "
  2378.  "descriptor n", 0, 0, 0, 0, 0, 0);
  2379.     goto errorExit;
  2380.     }
  2381. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Read %04x n", phyWord, 0, 0, 0, 0, 0);
  2382. *(pEepromData + tempIndex2++) = phyWord & 0x00ff;
  2383. *(pEepromData + tempIndex2++) = phyWord >> 8;
  2384. }
  2385.     for(tempIndex = 0; tempIndex<6; tempIndex++)
  2386. {
  2387.    macAdrs[tempIndex] = *(pEepromData + tempIndex);
  2388. }
  2389.     /* Set the Ethernet ID in the PEGASUS registers */
  2390.     if (usbdVendorSpecific (pegasusHandle, devId,
  2391.                            USB_PEGASUS_SET_BMREQ, 
  2392.                            USB_PEGASUS_SET_BREQ, 
  2393.                            0, 0x10, 0x6, pEepromData,   &actLen) != OK)
  2394. {
  2395. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Ethernet ID n",
  2396. 0, 0, 0, 0, 0, 0);
  2397. goto errorExit;
  2398. }
  2399.     /* Enable the GPIO registers */
  2400.     *pBfr = 0x24;
  2401.     *(pBfr + 1) = 0x00;
  2402.     if (usbdVendorSpecific (pegasusHandle, devId,
  2403.                            USB_PEGASUS_SET_BMREQ, 
  2404.                            USB_PEGASUS_SET_BREQ, 
  2405.                            0, 0x7e, 2, pBfr, &actLen) != OK)
  2406. {
  2407. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registers n",
  2408. 0, 0, 0, 0, 0, 0);
  2409. goto errorExit;
  2410. }
  2411.     *pBfr = 0x26;
  2412.     *(pBfr + 1) = 0x00;
  2413.     if (usbdVendorSpecific (pegasusHandle, devId,
  2414.                            USB_PEGASUS_SET_BMREQ, 
  2415.                            USB_PEGASUS_SET_BREQ, 
  2416.                            0, 0x7e, 2, pBfr, &actLen) != OK)
  2417. {
  2418. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registersn",
  2419. 0, 0, 0, 0, 0, 0);
  2420. goto errorExit;
  2421. }
  2422.     
  2423.     /* Read the PHY Identifier */
  2424.     if(usbPegasusReadPhy (devId, 0x2, &phyWord) != OK)
  2425. {
  2426. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Reading PHY Regsn",
  2427. 0, 0, 0, 0, 0, 0);
  2428. goto errorExit;
  2429. }
  2430.     i=2;
  2431.     DELAY(i)
  2432.     DELAY(i)
  2433.     /* Read the Status of the Link */
  2434.     if(usbPegasusReadPhy (devId, 0x1, &phyWord) != OK)
  2435. {
  2436. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Reading PHY Regsn",
  2437. 0, 0, 0, 0, 0, 0);
  2438. goto errorExit;
  2439. }
  2440.     /* Enable GPIO outputs */
  2441.     *pBfr = 0x26;
  2442.     *(pBfr + 1) = 0x11;
  2443.     if (usbdVendorSpecific (pegasusHandle, devId,
  2444.                            USB_PEGASUS_SET_BMREQ, 
  2445.                            USB_PEGASUS_SET_BREQ, 
  2446.                            0, 0x7f, 2, pBfr, &actLen) != OK)
  2447. {
  2448. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registersn",
  2449. 0, 0, 0, 0, 0, 0);
  2450. goto errorExit;
  2451. }
  2452.     /* Read the status of the Link */
  2453.     if(usbPegasusReadPhy (devId, 0x1, &phyWord) != OK)
  2454. {
  2455. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Reading PHY Regs n",
  2456. 0, 0, 0, 0, 0, 0);
  2457. goto errorExit;
  2458. }
  2459.     /* Enable the USB test pins */
  2460.     *pBfr = 0x11;
  2461.     *(pBfr + 1) = 0x00;
  2462.     if (usbdVendorSpecific (pegasusHandle, devId,
  2463.                            USB_PEGASUS_SET_BMREQ, 
  2464.                            USB_PEGASUS_SET_BREQ, 
  2465.                            0, 0x80, 2, pBfr, &actLen) != OK)
  2466. {
  2467. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registers n",
  2468. 0, 0, 0, 0, 0, 0);
  2469. goto errorExit;
  2470. }
  2471.     if(usbPegasusReadPhy (devId, 0x1, &phyWord) != OK)
  2472. {
  2473. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Reading PHY Regs n",
  2474. 0, 0, 0, 0, 0, 0);
  2475. goto errorExit;
  2476. }
  2477.  
  2478.     *pBfr = 0x39;
  2479.     *(pBfr + 1) = 0x00;
  2480.     if (usbdVendorSpecific (pegasusHandle, devId,
  2481.    USB_PEGASUS_SET_BMREQ, 
  2482.                            USB_PEGASUS_SET_BREQ, 
  2483.                            0, 0x0, 2, pBfr, &actLen) != OK)
  2484. {
  2485. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registers n",
  2486. 0, 0, 0, 0, 0, 0);
  2487. goto errorExit;
  2488. }
  2489.  
  2490.     /* GPIO Output */
  2491.     if (usbdVendorSpecific (pegasusHandle, devId,
  2492.    USB_PEGASUS_GET_BMREQ, 
  2493.                            USB_PEGASUS_GET_BREQ, 
  2494.                            0, 0x7a, 0x2, pBfr,   &actLen) != OK)
  2495. {
  2496. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registers n", 
  2497.     0, 0, 0, 0, 0, 0);
  2498. goto errorExit;
  2499. }
  2500.  
  2501.     *pBfr = 0x08;
  2502.     *(pBfr + 1) = 0x00;
  2503.     if (usbdVendorSpecific (pegasusHandle, devId,
  2504.                            USB_PEGASUS_SET_BMREQ, 
  2505.                            USB_PEGASUS_SET_BREQ, 
  2506.                            0, 0x01, 2, pBfr, &actLen) != OK)
  2507. {
  2508. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registers n",
  2509. 0, 0, 0, 0, 0, 0);
  2510. goto errorExit;
  2511. }
  2512.  
  2513.     phyWord = 0x2000;
  2514.     if(usbPegasusWritePhy (devId, 0x2, 0x0, phyWord))
  2515. {
  2516. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting PHY Registers 0x02 n",
  2517. 0, 0, 0, 0, 0, 0);
  2518. goto errorExit;
  2519. }
  2520.     /* Set Link partners Autonegatiation capability */
  2521.     phyWord = 0x0021;
  2522.     if(usbPegasusWritePhy (devId, 0x1, 0x5, phyWord))
  2523. {
  2524. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting PHY Registers 0x05 n",
  2525. 0, 0, 0, 0, 0, 0);
  2526. goto errorExit;
  2527. }
  2528.   
  2529.     phyWord = 0x0400;
  2530.     if(usbPegasusWritePhy (devId, 0x2, 0x0, phyWord))
  2531. {
  2532. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting PHY Registers 0x02 n",
  2533. 0, 0, 0, 0, 0, 0);
  2534. goto errorExit;
  2535. }
  2536.  
  2537.     *pBfr = 0xc4;
  2538.     *(pBfr + 1) = 0x00;
  2539.     if (usbdVendorSpecific (pegasusHandle, devId,
  2540.                            USB_PEGASUS_SET_BMREQ, 
  2541.                            USB_PEGASUS_SET_BREQ, 
  2542.                            0, 0x78, 2, pBfr,  &actLen) != OK)
  2543. {
  2544. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting GPIO Regs n",
  2545. 0, 0, 0, 0, 0, 0);
  2546. goto errorExit;
  2547. }
  2548.     /* Enable the Ethernet Receive and Transmit */  
  2549.     *pBfr = 0xfa;
  2550.     *(pBfr + 1) = 0x30;
  2551.     *(pBfr + 2) = 0x00;
  2552.     *(pBfr + 3) = 0x00;
  2553.     if (usbdVendorSpecific (pegasusHandle, devId,
  2554.                            USB_PEGASUS_SET_BMREQ, 
  2555.                            USB_PEGASUS_SET_BREQ, 
  2556.                            0, 0x00, 4, pBfr, &actLen) != OK)
  2557. {
  2558. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Ethernet Control Regs n",
  2559. 0, 0, 0, 0, 0, 0);
  2560. goto errorExit;
  2561. }
  2562.     OSS_FREE (pBfr);
  2563.     OSS_FREE (pEepromData);
  2564.     return OK;
  2565. errorExit:
  2566.     OSS_FREE (pBfr);
  2567.     OSS_FREE (pEepromData);
  2568.     return ERROR;
  2569.     }    
  2570. /***************************************************************************
  2571. *
  2572. * usbPegasusReadPHY - Read the Contents PHY registers
  2573. *
  2574. * Reads the Register contents of PHY device.
  2575. *
  2576. * RETURNS: OK if successful or ERROR on Failure
  2577. */
  2578. STATUS usbPegasusReadPhy
  2579.     (
  2580.     USBD_NODE_ID devId, 
  2581.     UINT8 offSet,
  2582.     UINT16 * phyWord
  2583.     )
  2584.     {
  2585.     UINT16 actLen=0;
  2586.     UINT8 * pBfr;
  2587.     pBfr = OSS_MALLOC (255);
  2588.  
  2589.     /* Create buffers for data transfer */
  2590.     if (pBfr == NULL)
  2591. {
  2592. printf ("usbPegasusReadPhy() could not allocate memoryn");
  2593. return ERROR;
  2594. }
  2595.  
  2596.     /* Write the off set into the PHy access registers */
  2597.     *pBfr = 1;
  2598.     *(pBfr + 1) = 0x0;
  2599.     *(pBfr + 2) = 0x0;
  2600.     *(pBfr + 3) = 0x40|(offSet&0x1f);
  2601.     if (usbdVendorSpecific (pegasusHandle, devId,
  2602.            USB_PEGASUS_SET_BMREQ, 
  2603.                            USB_PEGASUS_SET_BREQ, 
  2604.                            0, 0x25, 4, pBfr, &actLen) != OK)
  2605. {
  2606. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registers n",
  2607. 0, 0, 0, 0, 0, 0);
  2608. goto errorExit;
  2609. }
  2610.     /* Read the contents read from PHY */
  2611.     if (usbdVendorSpecific (pegasusHandle, devId,
  2612.    USB_PEGASUS_GET_BMREQ, 
  2613.                            USB_PEGASUS_GET_BREQ, 
  2614.                            0, 0x26, 3, pBfr,   &actLen) != OK)
  2615. {
  2616. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error reading Registersn",
  2617. 0, 0, 0, 0, 0, 0);
  2618. goto errorExit;
  2619. }
  2620.     /* If operation successful return the data */
  2621.     if (*(pBfr + 2) & 0x80) 
  2622. {
  2623. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Read Registers %d %02x, %02x  %02x n", 
  2624.     offSet, *pBfr, *(pBfr + 1), *(pBfr + 2), 0, 0);
  2625. *phyWord = *(UINT16 *)pBfr;
  2626. }
  2627.     else
  2628. goto errorExit;
  2629.     OSS_FREE (pBfr);
  2630.     return OK;
  2631. errorExit:
  2632.     OSS_FREE (pBfr);
  2633.     return ERROR;
  2634.     }
  2635. /***************************************************************************
  2636. *
  2637. * usbPegasusReadReg - Read contents of specified and print 
  2638. *
  2639. * This function will read the Register contents of Pegasus and print them for 
  2640. * debugging purpose.
  2641. *
  2642. * RETURNS: OK if successful or ERROR on Failure
  2643. */
  2644. STATUS usbPegasusReadReg
  2645.     (
  2646.     USBD_NODE_ID devId,        /* pointer to  device */
  2647.     UINT8 offSet,        /* Offset of the registers */
  2648.     UINT8 noOfRegs        /* No of registers to be read */
  2649.     )
  2650.     {
  2651.     UINT16 actLen=0;
  2652.     UINT8 * pBfr;
  2653.     int i;
  2654.     /* Create buffers for data transfer */
  2655.     pBfr = OSS_MALLOC (10);
  2656.  
  2657.     if (pBfr == NULL)
  2658. {
  2659. printf ("usbPegasusReadReg() could not allocate memoryn");
  2660. return ERROR;
  2661. }
  2662.  
  2663.     /* read the registers */
  2664.     for(i=offSet; i<(offSet+noOfRegs); i++)
  2665. {
  2666. *pBfr = 0;
  2667. if (usbdVendorSpecific (pegasusHandle, devId,
  2668.                         USB_PEGASUS_GET_BMREQ, 
  2669.                                 USB_PEGASUS_GET_BREQ, 
  2670.                                 0, i, 1, pBfr,   &actLen) != OK)
  2671.     {
  2672.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registersn",
  2673. 0, 0, 0, 0, 0, 0);
  2674.     OSS_FREE (pBfr);
  2675.     return ERROR;
  2676.     }
  2677.     PEGASUS_LOG (PEGASUS_DBG_LOAD, "Registers offSet %d %02x %d n",
  2678. i, (UINT32)pBfr, actLen, 0, 0, 0);
  2679. }
  2680.     OSS_FREE (pBfr);
  2681.     return OK;
  2682.     }
  2683. /***************************************************************************
  2684. *
  2685. * usbPegasusWritePHY - Write the data into PHY registers 
  2686. *
  2687. * Write the data into Registers of PHY device.
  2688. *
  2689. * RETURNS: OK if successful or ERROR on Failure
  2690. */
  2691. STATUS usbPegasusWritePhy
  2692.     (
  2693.     USBD_NODE_ID devId,        /* pointer to  device */
  2694.     UINT8 direction, /* PHY Identifier */
  2695.     UINT8 offSet, /* Register off set */
  2696.     UINT16 phyWord /* Data to be written */
  2697.     )
  2698.     {
  2699.     UINT16 actLen=0;
  2700.     UINT8 * pBfr;
  2701.     /* Create buffers for data transfer */
  2702.     pBfr = OSS_MALLOC (8);
  2703.  
  2704.     if (pBfr == NULL)
  2705. {
  2706. printf ("usbPegasusWritePhy() could not allocate memoryn");
  2707. return ERROR;
  2708. }
  2709.  
  2710.     /* Fill the Registers for accessing the PHY */
  2711.     *pBfr = direction;
  2712.     *(pBfr + 1) = (UINT8)(phyWord&0x00ff);
  2713.     *(pBfr + 2) = (UINT8)(phyWord>>8);
  2714.     *(pBfr + 3) = 0x20|(offSet&0x1f);
  2715.  
  2716.     /* Write into the control Registers */
  2717.     if (usbdVendorSpecific (pegasusHandle, devId,
  2718.                             USB_PEGASUS_SET_BMREQ, 
  2719.                             USB_PEGASUS_SET_BREQ, 
  2720.                             0, 0x25, 4, pBfr,   &actLen) != OK)
  2721. {
  2722. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registersn",
  2723. 0, 0, 0, 0, 0, 0);
  2724. goto errorExit;
  2725. }
  2726.     /* Read the PHY contents back */
  2727.     if (usbdVendorSpecific (pegasusHandle, devId,
  2728.                             USB_PEGASUS_GET_BMREQ, 
  2729.                             USB_PEGASUS_GET_BREQ, 
  2730.                             0, 0x28, 1, pBfr,   &actLen) != OK)
  2731. {
  2732. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Writing Registersn",
  2733. 0, 0, 0, 0, 0, 0);
  2734. goto errorExit;
  2735. }
  2736.     /* Check whether the opearation is succesful */
  2737.     if (*pBfr & 0x80) 
  2738. {
  2739. OSS_FREE (pBfr);
  2740. return OK;
  2741. }
  2742. errorExit:
  2743.     OSS_FREE (pBfr);
  2744.     return ERROR;
  2745.     }
  2746. /***************************************************************************
  2747. *
  2748. * usbPegasusReadSrom - Read the Contesnts of Serial EEPROM
  2749. *
  2750. * This function reads the Ethernet ID and other data from EEPROM 
  2751. *
  2752. * RETURNS: OK if successful or ERROR on Failure
  2753. * NOMANUAL
  2754. */
  2755. STATUS usbPegasusReadSrom
  2756.     (
  2757.     USBD_NODE_ID devId,  /* Pegasus Device ID */
  2758.     UINT8 offSet, /* Location Offset */
  2759.     UINT16 * phyWord /* Data word */
  2760.     )
  2761.     {
  2762.     UINT16 actLen=0;
  2763.     UINT8 * pBfr;
  2764.     /* Create buffers for data transfer */
  2765.     pBfr = OSS_MALLOC (255);
  2766.  
  2767.     if (pBfr == NULL)
  2768. {
  2769. printf ("usbPegasusReadSrom() could not allocate memoryn");
  2770. return ERROR;
  2771. }
  2772.  
  2773.     *pBfr = offSet;
  2774.     *(pBfr + 1) = 0x0;
  2775.     *(pBfr + 2) = 0x0;
  2776.     *(pBfr + 3) = 0x2;
  2777.     
  2778.     /* Write into the control registers for accessing the EEPROM */
  2779.     if (usbdVendorSpecific (pegasusHandle, devId,
  2780.                            USB_PEGASUS_SET_BMREQ, 
  2781.                            USB_PEGASUS_SET_BREQ, 
  2782.                            0, 0x20, 4, pBfr, &actLen) != OK)
  2783. {
  2784. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error Setting Registersn",
  2785. 0, 0, 0, 0, 0, 0);
  2786. goto errorExit;
  2787. }
  2788.     /* Read the Contents back */
  2789.     if (usbdVendorSpecific (pegasusHandle, devId,
  2790.                            USB_PEGASUS_GET_BMREQ, 
  2791.                            USB_PEGASUS_GET_BREQ, 
  2792.                            0, 0x21, 3, pBfr, &actLen) != OK)
  2793. {
  2794. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Error reading Registersn",
  2795. 0, 0, 0, 0, 0, 0);
  2796. goto errorExit;
  2797. }
  2798.     /* Check whether the opeartion is successful */
  2799.     if (*(pBfr + 2) & 0x4) 
  2800. {
  2801. PEGASUS_LOG (PEGASUS_DBG_LOAD, "Read Registers %d %02x, %02xn",
  2802. offSet, *(pBfr +0), *(pBfr + 1), 0, 0, 0);
  2803. *phyWord = *(UINT16 *)pBfr;
  2804. OSS_FREE (pBfr);
  2805. return OK;
  2806. }
  2807. errorExit:
  2808.     OSS_FREE (pBfr);
  2809.     return ERROR;
  2810.     }