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

VxWorks

开发平台:

C/C++

  1. /* usbCbiUfiDevLib.c - USB CBI Mass Storage class driver for UFI sub-class */
  2. /* Copyright 2000-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01h,30apr02,wef  fix little endian swap problem in usbCbiUfiPhysDevCreate
  7. 01g,05mar02,wef  fix bug - sizeof a macro
  8. 01f,19nov01,dee  fix continuation line syntax error
  9. 01e,06nov01,wef  Remove automatic buffer creations and repalce with OSS_xALLOC
  10.                  remove more warnings, fix condition where no disk is in drive 
  11.  - SPR #69753.
  12. 01d,08aug01,dat  Removing warnings
  13. 01c,02sep00,bri  added support for multiple devices.
  14. 01b,04aug00,bri  updated as per review.
  15. 01a,26jun00,bri  written.
  16. */
  17. /*
  18. DESCRIPTION
  19. This module implements the USB Mass Storage class driver for the vxWorks 
  20. operating system.  This module presents an interface which is a superset 
  21. of the vxWorks Block Device driver model.  The driver implements external 
  22. APIs which would be expected of a standard block device driver. 
  23. This class driver restricts to Mass Storage class devices with UFI subclass,
  24. that follow CBI (Control/Bulk/Interrupt) transport.  For CBI devices 
  25. transport of command, data and status occurs via control, bulk and interrupt 
  26. endpoints respectively. Interrupt endpoint is used to signal command completion.
  27. The class driver is a client of the Universal Serial Bus Driver (USBD).  All
  28. interaction with the USB buses and devices is handled through the USBD.
  29. INITIALISATION
  30. The driver initialisation routine usbCbiUfiDevInit() must be invoked first 
  31. prior to any other driver routines.  It is assumed that USBD is already 
  32. initialised and attached to atleast one USB Host Controller.  
  33. usbCbiUfiDevInit() registers the class driver as a client module with USBD.  It 
  34. also registers a callback routine to get notified whenever a USB MSC/UFI/CBI 
  35. device is attached or removed from the system.  The callback routine
  36. creates a USB_CBI_UFI_DEV structure to represent the USB device attached.  It 
  37. also sets device configuration, interface settings and creates pipes for 
  38. BULK_IN, BULK_OUT and INTERRUPT transfers.
  39. DATA FLOW
  40. For every USB/CBI/UFI device detected, the device configuration is set to the
  41. configuration that follows the CBI/UFI command set.  Pipes are created for bulk
  42. in, bulk out and interrupt endpoints.  To initiate transactions, ADSC class 
  43. specific request is used to send a command block on the control endpoint.  
  44. Command blocks are formed as per the UFI command specifications.  If the 
  45. command requires transport of data to/from the device, it is done via 
  46. bulk-out/bulk-in pipes using IRPs.  This is followed by status transport via 
  47. interrupt endpoint.
  48. OTHER FUNCTIONS
  49. Number of USB CBI_UFI devices supported by this driver is not fixed.  UFI 
  50. devices may be added or removed from the USB system at any point of time.  The 
  51. user of this client driver must be aware of the device attachment and removal.
  52. To facilitate this, an user-specific callback routine may be registered, using
  53. usbCbiUfiDynamicAttachRegister() routine. The USBD_NODE_ID assigned to the 
  54. device being attached or removed, is passed on to the user callback routine. 
  55. This unique ID may be used to create a block device using 
  56. usbCbiUfiBlkDevCreate() and further launch file system.
  57. NOTE : The user callback routine is invoked from the USBD client task created 
  58. for this class driver. The callback routine should not invoke any class driver
  59. function, which will further submit IRPs. For example,  usbCbiUfiBlkDevCreate() 
  60. should not be invoked from the user's callback. 
  61. Typically, the user may create a task, as a client of UFI driver, and invoke
  62. the driver routines from the task's context.  The user callback routine may
  63. be used to notify device attachment and removal to the task.
  64.  
  65. INCLUDE FILES: usbCbiUfiDevLib.h, blkIo.h
  66. SEE ALSO:
  67. .I "USB Mass Storage Class - Control/Bulk/Interrupt Transport Specification Revision 1.0,"
  68. .I "USB Mass Storage Class - UFI Command specification Revision 1.0"
  69. */
  70. /* includes */
  71. #include "vxWorks.h"
  72. #include "string.h"
  73. #include "errno.h"
  74. #include "errnoLib.h"
  75. #include "ioLib.h"
  76. #include "blkIo.h"
  77. #include "stdio.h"
  78. #include "logLib.h"
  79. #include "usb/usbPlatform.h"
  80. #include "usb/ossLib.h"             /* operations system srvcs */
  81. #include "usb/usb.h"                /* general USB definitions */
  82. #include "usb/usbListLib.h"         /* linked list functions   */
  83. #include "usb/usbdLib.h"            /* USBD interface          */
  84. #include "usb/usbLib.h"             /* USB utility functions   */
  85. #include "drv/usb/usbCbiUfiDevLib.h"
  86. /* defines */
  87. #define USB_DEBUG_MSG        0x01
  88. #define USB_DEBUG_ERR        0x02
  89. #define USB_CBI_UFI_DEBUG                     
  90.         if (usbCbiUfiDebug & USB_DEBUG_MSG)    
  91.             logMsg
  92. #define USB_CBI_UFI_ERR                    
  93.         if (usbCbiUfiDebug & USB_DEBUG_ERR)   
  94.             logMsg
  95. /* typedefs */
  96. typedef struct usbCbiUfiDev
  97.     {
  98.     BLK_DEV           blkDev;         /* Vxworks block device structure */
  99.                                       /* Must be the first one          */
  100.     USBD_NODE_ID      cbiUfiDevId;    /* USBD node ID of the device     */  
  101.     UINT16            configuration;  /* Configuration value            */    
  102.     UINT16            interface;      /* Interface number               */
  103.     UINT16            altSetting;     /* Alternate setting of interface */ 
  104.     UINT16            outEpAddress;   /* Bulk out EP address            */   
  105.     UINT16            inEpAddress;    /* Bulk in EP address             */
  106.     UINT16            intrEpAddress;  /* Interrupt EP address           */
  107.     USBD_PIPE_HANDLE  outPipeHandle;  /* Pipe handle for Bulk out EP    */
  108.     USBD_PIPE_HANDLE  inPipeHandle;   /* Pipe handle for Bulk in EP     */
  109.     USBD_PIPE_HANDLE  intrPipeHandle; /* Pipe handle for interrupt EP   */
  110.     USB_IRP           inIrp;          /* IRP used for bulk-in data      */
  111.     USB_IRP           outIrp;         /* IRP used for bulk-out data     */
  112.     USB_IRP           statusIrp;      /* IRP used for status data       */   
  113.     USB_UFI_CMD_BLOCK ufiCmdBlk;      /* Store for UFI Command block    */
  114.     UINT8 *           bulkInData;     /* Pointer for bulk-in data       */
  115.     UINT8 *           bulkOutData;    /* Pointer for bulk-out data      */   
  116.     UINT8             intrStatus[2];  /* Store for Status bytes         */
  117.     UINT16            lockCount;      /* Count of times structure locked*/
  118.     BOOL              connected;      /* TRUE if CBI_UFI device connected  */    
  119.     LINK              cbiUfiDevLink;  /* Link to other USB_CBI_UFI devices */  
  120.     } USB_CBI_UFI_DEV, *pUSB_CBI_UFI_DEV;
  121. /* Attach request for user callback */
  122. typedef struct attach_request
  123.     {
  124.     LINK reqLink;                       /* linked list of requests */
  125.     USB_UFI_ATTACH_CALLBACK callback;   /* client callback routine */
  126.     pVOID callbackArg;                  /* client callback argument*/
  127.     } ATTACH_REQUEST, *pATTACH_REQUEST;
  128. /* globals */
  129. BOOL usbCbiUfiDebug = 0;
  130. /* locals */
  131. LOCAL UINT16 initCount = 0;           /* Count for UFI device initialisation */
  132. LOCAL USBD_CLIENT_HANDLE usbdHandle;  /* Handle for this class driver */
  133. LOCAL MUTEX_HANDLE cbiUfiDevMutex;    /* Mutex used to protect internal structs */
  134. LOCAL SEM_HANDLE   cbiUfiIrpSem;      /* Semaphore for IRP Synchronisation */
  135. LOCAL LIST_HEAD    cbiUfiDevList;     /* Linked list of USB_CBI_UFI_DEV */
  136. LOCAL LIST_HEAD    reqList;           /* Attach callback request list */
  137. /* forward declarations */
  138. LOCAL  STATUS usbCbiUfiDescShow (USBD_NODE_ID nodeId);
  139. LOCAL  STATUS usbCbiUfiConfigDescShow  (USBD_NODE_ID nodeId, UINT8 index);
  140. LOCAL  pUSB_CBI_UFI_DEV usbCbiUfiPhysDevCreate (USBD_NODE_ID nodeId, 
  141.                                                 UINT16 config, 
  142. UINT16 interface);
  143. LOCAL  pUSB_CBI_UFI_DEV usbCbiUfiDevFind (USBD_NODE_ID nodeId);
  144. LOCAL  STATUS usbCbiUfiDevBlkRd (BLK_DEV *blkDev, 
  145.  UINT32 offset, 
  146.  UINT32 num, 
  147.  char * buf);
  148. LOCAL  STATUS usbCbiUfiDevBlkWrt (BLK_DEV *blkDev, 
  149.   UINT32 offset, 
  150.   UINT32 num, 
  151.   char * buf);
  152. LOCAL  STATUS usbCbiUfiDevStChk (BLK_DEV *blkDev);
  153. LOCAL  STATUS usbCbiUfiDevReset (BLK_DEV *blkDev);
  154. LOCAL  VOID   usbCbiUfiIrpCallback (pVOID p);
  155. LOCAL  STATUS usbCbiUfiFormCmd (pUSB_CBI_UFI_DEV pCbiUfiDev, 
  156. UINT ufiCmd, 
  157. UINT cmdParam1, 
  158. UINT cmdParam2);
  159. LOCAL  USB_COMMAND_STATUS usbCbiUfiCmdExecute (pUSB_CBI_UFI_DEV pCbiUfiDev);
  160. LOCAL  VOID usbCbiUfiDevDestroy (pUSB_CBI_UFI_DEV pCbiUfiDev); 
  161. LOCAL  VOID notifyAttach (USBD_NODE_ID nodeId, UINT16 attachCode);
  162. /***************************************************************************
  163. *
  164. * usbCbiUfiAttachCallback - called by USBD when UFI device is attached/detached
  165. *
  166. * This function is invoked by the USBD driver when a mass storage device, 
  167. * following CBI protocol and UFI command set, is attached or removed.  
  168. * <nodeId> is the USBD_NODE_ID of the node being attached or removed.
  169. * <attachAction> is USBD_DYNA_ATTACH or USBD_DYNA_REMOVE.
  170. * <configuration> and <interface> indicate the configuration/interface
  171. * that reports itself as a MSC/CBI/UFI device.  
  172. * <deviceClass>, <deviceSubClass>, and <deviceProtocol> will identify a 
  173. * MSC/CBI/UFI device.
  174. *
  175. * NOTE: The USBD will invoke this function once for each configuration/
  176. * interface which reports itself as a MSC/CBI/UFI.  So, it is possible 
  177. * that a single device insertion/removal may trigger multiple callbacks. 
  178. *
  179. *
  180. * RETURNS: N/A
  181. */
  182. LOCAL VOID usbCbiUfiAttachCallback
  183.     (
  184.     USBD_NODE_ID nodeId,        /* USBD Node ID of the device attached       */
  185.     UINT16 attachAction,        /* Whether device attached / detached        */
  186.     UINT16 configuration,       /* Configur'n value for  MSC/CBI/UFI         */
  187.     UINT16 interface,           /* Interface number for  MSC/CBI/UFI         */
  188.     UINT16 deviceClass,         /* Interface class   - 0x8  for MSC          */
  189.     UINT16 deviceSubClass,      /* Device sub-class  - 0x4  for UFI command  */    UINT16 deviceProtocol       /* Interfaceprotocol - 0x00 for CBI          */
  190.     )
  191.     {
  192.     pUSB_CBI_UFI_DEV  pCbiUfiDev;  
  193.     OSS_MUTEX_TAKE (cbiUfiDevMutex, OSS_BLOCK);
  194.  
  195.     switch (attachAction)
  196.         { 
  197.         case USBD_DYNA_ATTACH: 
  198.             /* MSC/CBI/UFI Device attached */
  199.             USB_CBI_UFI_DEBUG ("usbCbiUfiAttachCallback : New MSC/CBI/UFI device "
  200.                                "attachedn", 0, 0, 0, 0, 0, 0);
  201.             /* Check out whether we already have a structure for this device */
  202.             USB_CBI_UFI_DEBUG ("usbCbiUfiAttachCallback: Configuration = %d, " 
  203.                                "Interface = %d, Node Id = %d n", configuration,
  204.                                interface, (UINT)nodeId, 0, 0, 0); 
  205.             if (usbCbiUfiDevFind (nodeId) != NULL)
  206.                 break;
  207.             /* create a USB_CBI_UFI_DEV structure for the device detected */
  208.            
  209.             if ((pCbiUfiDev = usbCbiUfiPhysDevCreate (nodeId, 
  210.       configuration, 
  211.                                                       interface)) ==NULL )
  212.                 {
  213.                 USB_CBI_UFI_ERR ("usbCbiUfiAttachCallback : Error creating " 
  214.                                  "MSC/CBI/UFI devicen", 0, 0, 0, 0, 0, 0);
  215.                 break;
  216.                 } 
  217.              
  218.             /* Notify registered callers that a CBI_UFI_DEV has been added */
  219.     notifyAttach (pCbiUfiDev->cbiUfiDevId, USB_UFI_ATTACH); 
  220.             break;
  221.         case USBD_DYNA_REMOVE:
  222.             /* MSC/CBI/UFI Device detached */
  223.             USB_CBI_UFI_DEBUG ("usbCbiUfiAttachCallback : MSC/CBI/UFI Mass storage "
  224.                                "device detachedn", 0, 0, 0, 0, 0, 0);
  225.             if ((pCbiUfiDev = usbCbiUfiDevFind (nodeId)) == NULL)
  226.                 break;
  227.             /* Check the connected flag  */
  228.             if (pCbiUfiDev->connected == FALSE)
  229.                 break;
  230.             
  231.             pCbiUfiDev->connected = FALSE;
  232.     /* Notify registered callers that the CBI_UFI device has been
  233.      * removed 
  234.      *
  235.      * NOTE: We temporarily increment the device's lock count
  236.      * to prevent usbCbiUfiDevUnlock() from destroying the
  237.      * structure while we're still using it.
  238.      */
  239.             pCbiUfiDev->lockCount++; 
  240.             notifyAttach (pCbiUfiDev->cbiUfiDevId, USB_UFI_REMOVE); 
  241.             pCbiUfiDev->lockCount--; 
  242.             
  243.             if (pCbiUfiDev->lockCount == 0) 
  244.                 usbCbiUfiDevDestroy (pCbiUfiDev); 
  245.                 
  246.             break;
  247.         default :
  248.             break; 
  249.         }
  250.     OSS_MUTEX_RELEASE (cbiUfiDevMutex);  
  251.     }
  252. /***************************************************************************
  253. *
  254. * usbCbiUfiDevInit - registers USB CBI mass storage class driver for UFI 
  255. *      devices.
  256. *
  257. * This routine registers the CBI mass storage class driver for UFI devices.  
  258. * It also registers a callback routine to request notification whenever
  259. * USB/MSC/CBI/UFI devices are attached or removed.    
  260. *
  261. * RETURNS: OK, or ERROR if unable to register with USBD.
  262. *
  263. * ERRNO:
  264. *   S_usbCbiUfiDevLib_OUT_OF_RESOURCES
  265. *   S_usbCbiUfiDevLib_USBD_FAULT
  266. */
  267. STATUS usbCbiUfiDevInit (VOID)
  268.     {
  269.     /* 
  270.      * Check whether already initialised. If not, then initialise the required
  271.      * structures and registers the class driver with USBD.
  272.      */
  273.     if (initCount == 0)
  274.         {
  275.         memset (&cbiUfiDevList, 0, sizeof (cbiUfiDevList));
  276.         memset (&reqList, 0, sizeof (reqList));
  277.         cbiUfiDevMutex = NULL;
  278.         cbiUfiIrpSem   = NULL;
  279.         usbdHandle     = NULL;
  280.         if (OSS_MUTEX_CREATE (&cbiUfiDevMutex) != OK)
  281.             return (usbCbiUfiDevShutDown (S_usbCbiUfiDevLib_OUT_OF_RESOURCES));
  282.         if (OSS_SEM_CREATE (1, 1 , &cbiUfiIrpSem) != OK)
  283.             return (usbCbiUfiDevShutDown (S_usbCbiUfiDevLib_OUT_OF_RESOURCES));
  284.         /* Establish connection to USBD */
  285.         if (usbdClientRegister ("CBI_UFI_CLASS", &usbdHandle) != OK ||
  286.             usbdDynamicAttachRegister (usbdHandle, USB_CLASS_MASS_STORAGE,
  287.                                        USB_SUBCLASS_UFI_COMMAND_SET, 
  288.                                        USB_INTERFACE_PROTOCOL_CBI,
  289.                                        usbCbiUfiAttachCallback) != OK)
  290.             {
  291.             USB_CBI_UFI_ERR ("usbCbiUfiDevInit: Client Registration Failed n",
  292.                              0, 0, 0, 0, 0, 0); 
  293.             return (usbCbiUfiDevShutDown (S_usbCbiUfiDevLib_USBD_FAULT));
  294.             }
  295.         }
  296.     initCount++;
  297.     return (OK);
  298.     }
  299. /***************************************************************************
  300. *
  301. * usbCbiUfiDevShutDown - shuts down the USB CBI mass storage class driver.
  302. * This routine unregisters UFI driver from USBD and releases any resources 
  303. * allocated for the devices.
  304. *
  305. * RETURNS: OK or ERROR.
  306. */
  307. STATUS usbCbiUfiDevShutDown 
  308.     (
  309.     int errCode                  /* Error code - reason for shutdown */
  310.     )
  311.     {
  312.     pUSB_CBI_UFI_DEV pCbiUfiDev;
  313.     pATTACH_REQUEST  pRequest;
  314.     if (initCount == 0)
  315.         return ossStatus (S_usbCbiUfiDevLib_NOT_INITIALIZED);
  316.     /* release any UFI devices */
  317.     while ((pCbiUfiDev = usbListFirst (&cbiUfiDevList)) != NULL)
  318.         usbCbiUfiDevDestroy (pCbiUfiDev); 
  319.     /* Dispose of any outstanding notification requests */
  320.     while ((pRequest = usbListFirst (&reqList)) != NULL)
  321.         {
  322.        usbListUnlink (&pRequest->reqLink);
  323.         OSS_FREE (pRequest); 
  324.         }
  325.     /* 
  326.      * Unregister with the USBD. USBD will automatically release any pending
  327.      * IRPs or attach requests.
  328.      */
  329.     if (usbdHandle != NULL)
  330.         {
  331.         usbdClientUnregister (usbdHandle);
  332.         usbdHandle = NULL;
  333.         USB_CBI_UFI_DEBUG ("usbCbiUfiDevShutDown : CBI Mass storage class driver "
  334.                            "for UFI devices unregistered n", 0, 0, 0, 0, 0, 0);
  335.         }
  336.     /* release resources */
  337.     if (cbiUfiDevMutex != NULL)
  338.         {
  339.         OSS_MUTEX_DESTROY (cbiUfiDevMutex);
  340.         cbiUfiDevMutex = NULL;
  341.         }
  342.     if (cbiUfiIrpSem != NULL)
  343.         {
  344.         OSS_MUTEX_DESTROY (cbiUfiIrpSem);
  345.         cbiUfiIrpSem = NULL;
  346.         }
  347.     initCount--; 
  348.    
  349.     return (ossStatus (errCode)); 
  350.     }
  351. /***************************************************************************
  352. *
  353. * usbCbiUfiDevDestroy - releases USB_CBI_UFI_DEV structure and its links
  354. *
  355. * Unlinks the indicated USB_CBI_UFI_DEV structure and de-allocates
  356. * resources associated with the device.
  357. *
  358. * RETURNS: N/A
  359. */
  360. LOCAL VOID usbCbiUfiDevDestroy
  361.     (
  362.     pUSB_CBI_UFI_DEV  pCbiUfiDev     /* pointer to MSC/CBI/UFI device   */
  363.     )
  364.     {
  365.     if (pCbiUfiDev != NULL)
  366.         {
  367.         /* Unlink the structure. */
  368.         usbListUnlink (&pCbiUfiDev->cbiUfiDevLink);
  369.         /* Release pipes and wait for IRPs. */
  370.         if (pCbiUfiDev->outPipeHandle != NULL)
  371.             usbdPipeDestroy (usbdHandle, pCbiUfiDev->outPipeHandle);
  372.         if (pCbiUfiDev->inPipeHandle != NULL)
  373.             usbdPipeDestroy (usbdHandle, pCbiUfiDev->inPipeHandle);
  374.         /* wait for any IRP to complete */
  375.         OSS_SEM_TAKE (cbiUfiIrpSem, OSS_BLOCK); 
  376.         OSS_SEM_GIVE (cbiUfiIrpSem);
  377.         /* Release structure. */
  378.         OSS_FREE (pCbiUfiDev);
  379.         }
  380.     }
  381. /***************************************************************************
  382. *
  383. * usbCbiUfiDevIoctl - perform a device-specific control.
  384. *
  385. * Typically called by file system to invoke device-specific functions beyond 
  386. * file handling.  The following control requests are supported
  387. *
  388. * .IP "FIODISKFORMAT (0x05)"
  389. * Formats the entire disk with appropriate hardware track and sector marks. 
  390. * No file system is initialized on the disk by this request.  This control
  391. * function is defined by the file system, but provided by the driver.
  392. * .IP "USB UFI ALL DESCRIPTOR GET (0xF0)"
  393. * Invokes show routine for displaying configuration, device and interface 
  394. * descriptors.
  395. * .IP "USB UFI DEV RESET (0xF1)" 
  396. * Issues a command block reset and clears stall condition on bulk-in and 
  397. * bulk-out endpoints.
  398. *
  399. * RETURNS: The status of the request, or ERROR if the request is unsupported.
  400. */
  401. STATUS usbCbiUfiDevIoctl
  402.     (
  403.     BLK_DEV * pBlkDev,           /* pointer to MSC/CBI/UFI device */
  404.     UINT32 request,          /* request type                  */
  405.     UINT32 someArg          /* arguments related to request  */
  406.     )
  407.     {
  408.     /* get a pointer to the MSC/CBI/UFI  device */
  409.     pUSB_CBI_UFI_DEV  pCbiUfiDev = (USB_CBI_UFI_DEV *)pBlkDev;   
  410.     if ( pCbiUfiDev == (pUSB_CBI_UFI_DEV)NULL )
  411.         return (ERROR);
  412.     /* Check whether the device exists or not */
  413.     if (usbCbiUfiDevFind (pCbiUfiDev->cbiUfiDevId) != pCbiUfiDev)
  414.         {
  415.         USB_CBI_UFI_ERR ("usbCbiUfiDevIoctl: MSC/CBI/UFI Device not foundn", 
  416.                       0, 0, 0, 0, 0, 0);
  417.         return (ERROR);
  418.         }
  419.     switch (request)
  420.         {
  421.         case FIODISKFORMAT: 
  422.             if ( usbCbiUfiFormCmd (pCbiUfiDev, 
  423.    USB_UFI_FORMAT_UNIT, 
  424.    0, 
  425.    0) 
  426. != OK)
  427.  
  428.                 {
  429.                 USB_CBI_UFI_ERR ("usbCbiUfiDevIoctl: Error forming commandn",
  430.                                  0, 0, 0, 0, 0, 0);
  431.                 return (ERROR); 
  432.                 } 
  433.             if ( usbCbiUfiCmdExecute (pCbiUfiDev) != USB_COMMAND_SUCCESS )
  434.                 {
  435.                 USB_CBI_UFI_ERR ("usbCbiUfiDevIoctl: Error executing "
  436.                                  "USB_UFI_FORMAT_UNIT commandn", 
  437.                                  0, 0, 0, 0, 0, 0);        
  438.                 OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  439.                 return (ERROR);
  440.                 }
  441.             break;
  442.         case USB_UFI_ALL_DESCRIPTOR_GET:
  443.             /* invoke routine to display all descriptors */
  444.             return (usbCbiUfiDescShow (pCbiUfiDev->cbiUfiDevId));
  445.         case USB_UFI_DEV_RESET:
  446.             /* send a command block reset */
  447.              
  448.             return (usbCbiUfiDevReset ((BLK_DEV *)pCbiUfiDev));
  449.         default:
  450.             errnoSet (S_ioLib_UNKNOWN_REQUEST);
  451.             USB_CBI_UFI_DEBUG ("usbCbiUfiDevIoctl: Unknown Requestn", 
  452.                                0, 0, 0, 0, 0, 0);
  453.             return (ERROR);
  454.             break;
  455.         }
  456.     return (OK);
  457.     }
  458.  
  459. /***************************************************************************
  460. *
  461. * usbCbiUfiFormCmd - forms a command block for requested UFI command. 
  462. *
  463. * This routine forms UFI command blocks as per the UFI command specifications.  
  464. * The following are the input parameters 
  465. *
  466. * .IP <pCbiUfiDev>
  467. * pointer to USB/CBI/UFI device for which the command has to be formed.
  468. *
  469. * .IP <ufiCmd>
  470. * identifies the UFI command to be formed.
  471. * .IP <cmdParam1>
  472. * parameter required to form a complete UFI comamnd, if any.
  473. *
  474. * .IP <cmdParam2>
  475. * parameter required to form a complete UFI comamnd, if any.
  476. *
  477. * RETURNS: OK, or ERROR if the command is unsupported.
  478. */
  479. LOCAL STATUS usbCbiUfiFormCmd 
  480.     (
  481.     pUSB_CBI_UFI_DEV pCbiUfiDev, /* pointer to cbi_ufi device  */
  482.     UINT ufiCmd,                 /* UFI command                */ 
  483.     UINT cmdParam1,              /* command parameter          */
  484.     UINT cmdParam2               /* command parameter          */
  485.     )
  486.     {
  487.     memset (&(pCbiUfiDev->ufiCmdBlk), 0, sizeof(USB_UFI_CMD_BLOCK));
  488.     switch (ufiCmd)
  489.         {
  490.         case USB_UFI_FORMAT_UNIT:    /* UFI Format Unit Command */
  491.       
  492.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = 0;
  493.             pCbiUfiDev->ufiCmdBlk.direction    = 0;
  494.       
  495.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_FORMAT_UNIT;
  496.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = (USB_UFI_FORMAT_FMTDATA | 
  497.                                              USB_UFI_FORMAT_FMT_DEFECT);
  498.             pCbiUfiDev->ufiCmdBlk.cmd[2]  = 0;  /* Track Number              */
  499.             pCbiUfiDev->ufiCmdBlk.cmd[3]  = 0;  /* Interleave factor MSB     */
  500.             pCbiUfiDev->ufiCmdBlk.cmd[4]  = 0;  /* Interleave factor LSB     */  
  501.             pCbiUfiDev->ufiCmdBlk.cmd[7]  = 0;  /* Parameter List length MSB */
  502.             pCbiUfiDev->ufiCmdBlk.cmd[8]  = 0x0C; /* Parameter List 
  503.  * length LSB 
  504.  */
  505.            
  506.             break;
  507.         case USB_UFI_INQUIRY:        /* UFI Inquiry command  */
  508.   
  509.              
  510.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = UFI_STD_INQUIRY_LEN;
  511.             pCbiUfiDev->ufiCmdBlk.direction    = USB_UFI_DIR_IN;
  512.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_INQUIRY;
  513.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0;   /* Enable Vital 
  514.   * Product data
  515.   */      
  516.             pCbiUfiDev->ufiCmdBlk.cmd[2]  = 0;   /* Page Code 
  517.   * Field
  518.   */      
  519.             pCbiUfiDev->ufiCmdBlk.cmd[4]  = UFI_STD_INQUIRY_LEN;
  520.   
  521.             break;
  522.         case USB_UFI_MODE_SELECT:   /* UFI Mode Select Command */
  523.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_MODE_SELECT;
  524.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = USB_UFI_MODE_SEL_PF;  
  525.  
  526.             /* TODO : Set the number of bytes as per the mode pages */ 
  527.  
  528.             pCbiUfiDev->ufiCmdBlk.cmd[7]  = 0; /* Parameter list length MSB */
  529.             pCbiUfiDev->ufiCmdBlk.cmd[8]  = 0; /* Parameter list length LSB */       
  530.             break;
  531.         case USB_UFI_MODE_SENSE:     /* UFI Request Mode Sense command */
  532.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = USB_UFI_MS_HEADER_LEN;
  533.             pCbiUfiDev->ufiCmdBlk.direction    = USB_UFI_DIR_IN;
  534.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_MODE_SENSE;
  535.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0;  
  536.             /* Check the basic header information only. */               
  537.             pCbiUfiDev->ufiCmdBlk.cmd[2]  = 1;  
  538.  
  539.             pCbiUfiDev->ufiCmdBlk.cmd[7]  = 0; /* Parameter list length MSB */
  540.             pCbiUfiDev->ufiCmdBlk.cmd[8]  = USB_UFI_MS_HEADER_LEN; /* Parameter list length LSB */       
  541.             break;
  542.         case USB_UFI_PREVENT_MEDIA_REMOVAL: /* Enable or disable media 
  543.      * removal 
  544.      */
  545.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = 0;
  546.             pCbiUfiDev->ufiCmdBlk.direction    = 0;
  547.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_PREVENT_MEDIA_REMOVAL;            
  548.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0;  
  549.             pCbiUfiDev->ufiCmdBlk.cmd[4]  = USB_UFI_MEDIA_REMOVAL_BIT;
  550.   
  551.             break;
  552.  
  553.         case USB_UFI_READ10:         /* UFI 10 byte READ Command */
  554.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = ((cmdParam2) * 
  555.                                                  (pCbiUfiDev->blkDev.bd_bytesPerBlk)); 
  556.             pCbiUfiDev->ufiCmdBlk.direction    = USB_UFI_DIR_IN;
  557.  
  558.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_READ10;
  559.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0;
  560.             /*
  561.              * cmdParam1 for this command will indicate the logical block 
  562.              * address at which the read operation begins.  cmdParam2 will
  563.              * indicate the number of logical blocks to be read. 
  564.              */ 
  565.             pCbiUfiDev->ufiCmdBlk.cmd[2]  =  (cmdParam1 & 0xFF000000) >> 24;
  566.             pCbiUfiDev->ufiCmdBlk.cmd[3]  =  (cmdParam1 & 0x00FF0000) >> 16;
  567.             pCbiUfiDev->ufiCmdBlk.cmd[4]  =  (cmdParam1 & 0x0000FF00) >> 8;
  568.             pCbiUfiDev->ufiCmdBlk.cmd[5]  =  (cmdParam1 & 0xFF);
  569.             pCbiUfiDev->ufiCmdBlk.cmd[7]  =  (cmdParam2 & 0xFF00) >> 8;
  570.             pCbiUfiDev->ufiCmdBlk.cmd[8]  =  (cmdParam2 & 0xFF);
  571.             break;
  572.     
  573.         case USB_UFI_READ_CAPACITY:  /* UFI Read Capacity command */
  574.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = 0x8;
  575.             pCbiUfiDev->ufiCmdBlk.direction    = USB_UFI_DIR_IN;
  576.             pCbiUfiDev->ufiCmdBlk.cmd[0]  =  USB_UFI_READ_CAPACITY;
  577.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0;  /* RelAdr bit should be zero */
  578.             pCbiUfiDev->ufiCmdBlk.cmd[2]  = 0;  /* Logical block address     */
  579.             pCbiUfiDev->ufiCmdBlk.cmd[3]  = 0;  /* should be set to zero     */
  580.             pCbiUfiDev->ufiCmdBlk.cmd[4]  = 0;
  581.             pCbiUfiDev->ufiCmdBlk.cmd[5]  = 0;
  582.             pCbiUfiDev->ufiCmdBlk.cmd[8]  = 0;  /* PMI bit should be zero    */
  583.             break;
  584.         case USB_UFI_REQUEST_SENSE:  /* UFI Request Sense command */
  585.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = 0x12;
  586.             pCbiUfiDev->ufiCmdBlk.direction    = USB_UFI_DIR_IN;
  587.  
  588.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_REQUEST_SENSE;
  589.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0;
  590.             pCbiUfiDev->ufiCmdBlk.cmd[4]  = UFI_STD_REQ_SENSE_LEN;
  591.             break;
  592.         case USB_UFI_SEND_DIAGNOSTIC: /* UFI Send Diagnostics command */     
  593.             /* Requests the device to perform self-test or reset */
  594.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_SEND_DIAGNOSTIC;            
  595.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0x04; /* Perform default 
  596.    * self test 
  597.    */
  598.         
  599.             break;
  600.  
  601.         case USB_UFI_START_STOP_UNIT: /* UFI Start Stop unit command */   
  602.             /* This command is basically used to update the media type and the
  603.              * write protect status. Load eject bit is not supported by 
  604.      * USB-FDU.
  605.              */ 
  606.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = 0x0;
  607.             pCbiUfiDev->ufiCmdBlk.direction    = 0;
  608.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_START_STOP_UNIT; 
  609.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0;
  610.             pCbiUfiDev->ufiCmdBlk.cmd[4]  = 0x01;   /* Start the media */
  611.                     
  612.             break;
  613.         case USB_UFI_TEST_UNIT_READY:  /* UFI Test Unit Ready Command */  
  614.             /* This command checks if the device is ready or not */
  615.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = 0x0;
  616.             pCbiUfiDev->ufiCmdBlk.direction    = 0;
  617.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_TEST_UNIT_READY; 
  618.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0; 
  619.             break;
  620.     
  621.         case USB_UFI_WRITE10:        /* UFI 10-byte Write Command */
  622.             
  623.             pCbiUfiDev->ufiCmdBlk.dataXferLen  = ((cmdParam2) * 
  624.                                                  (pCbiUfiDev->blkDev.bd_bytesPerBlk)); 
  625.             pCbiUfiDev->ufiCmdBlk.direction    = USB_UFI_DIR_OUT;
  626.             pCbiUfiDev->ufiCmdBlk.cmd[0]  = USB_UFI_WRITE10;
  627.             pCbiUfiDev->ufiCmdBlk.cmd[1]  = 0;
  628.             /*
  629.              * cmdParam1 for this command will indicate the logical block 
  630.              * address at which the write operation begins.  cmdParam2 will
  631.              * indicate the number of logical blocks to be written. 
  632.              */ 
  633.             pCbiUfiDev->ufiCmdBlk.cmd[2]  =  (cmdParam1 & 0xFF000000) >> 24;
  634.             pCbiUfiDev->ufiCmdBlk.cmd[3]  =  (cmdParam1 & 0x00FF0000) >> 16;
  635.             pCbiUfiDev->ufiCmdBlk.cmd[4]  =  (cmdParam1 & 0x0000FF00) >> 8;
  636.             pCbiUfiDev->ufiCmdBlk.cmd[5]  =  (cmdParam1 & 0xFF);
  637.             pCbiUfiDev->ufiCmdBlk.cmd[7]  =  (cmdParam2 & 0xFF00) >> 8;
  638.             pCbiUfiDev->ufiCmdBlk.cmd[8]  =  (cmdParam2 & 0xFF);
  639.             break;
  640.     
  641.         default: 
  642.             return (ERROR);
  643.         }
  644.  
  645.     return (OK);
  646.  
  647.     } 
  648. /***************************************************************************
  649. *
  650. * usbCbiUfiCmdExecute - Executes an UFI command block. 
  651. *
  652. * This routine executes previously formed UFI Command as per the CBI protocol.
  653. * First, the command block formed by usbCbiUfiFormCmd() is sent to the device
  654. * via the control endpoint.  This is done using Accept Device Specific Command
  655. * (ADSC) class specific request.  If the command block requires any data 
  656. * transfer to/from the device, then an IRP is submitted to perform the data
  657. * tranport via bulk in/out endpoints.  Finally, status bytes are read from the
  658. * interrupt endpoint.
  659. *
  660. * RETURNS: USB_COMMAND_STATUS, command execution status.
  661. */
  662. LOCAL USB_COMMAND_STATUS usbCbiUfiCmdExecute
  663.     ( 
  664.     pUSB_CBI_UFI_DEV pCbiUfiDev      /* pointer to cbi_ufi device  */
  665.     )
  666.     {
  667.     UINT16 actLen = 0xFFFF;
  668.     /* Send the UFI Command block along with the ADSC request */
  669.     if ((usbdVendorSpecific (usbdHandle, pCbiUfiDev->cbiUfiDevId,
  670.                 USB_RT_HOST_TO_DEV | USB_RT_CLASS | USB_RT_INTERFACE,
  671.                 0, 0, pCbiUfiDev->interface, USB_UFI_MAX_CMD_LEN, 
  672.                 (UINT8 *)&(pCbiUfiDev->ufiCmdBlk.cmd), &actLen )) != OK )
  673.         {
  674.         USB_CBI_UFI_ERR ("usbCbiUfiCmdExecute: Failed to execute ADSC n", 
  675.                          0, 0, 0, 0, 0, 0);  
  676.         return (USB_COMMAND_FAILED);
  677.         }    
  678.     if ( pCbiUfiDev->ufiCmdBlk.dataXferLen > 0 )
  679.         {
  680.         if ( OSS_SEM_TAKE (cbiUfiIrpSem, 
  681.    USB_CBI_IRP_TIME_OUT + 1000) 
  682.    == ERROR )
  683.             {
  684.             /* This should never occur unless the stack does'nt call 
  685.      * callback at all 
  686.      */
  687.             USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Irp in Use n", 
  688.                                0, 0, 0, 0, 0, 0);
  689.             return (USB_INTERNAL_ERROR);
  690.             }
  691.         if (pCbiUfiDev->ufiCmdBlk.direction == USB_UFI_DIR_IN)
  692.             {
  693.          
  694.             /* data is expected from the device. read from BULK_IN pipe */
  695.             memset (&(pCbiUfiDev->inIrp), 0, sizeof (USB_IRP));   
  696.             /* form an IRP to read from BULK_IN pipe */ 
  697.             pCbiUfiDev->inIrp.irpLen            = sizeof(USB_IRP);
  698.             pCbiUfiDev->inIrp.userCallback      = usbCbiUfiIrpCallback; 
  699.             pCbiUfiDev->inIrp.timeout           = USB_CBI_IRP_TIME_OUT;
  700.             pCbiUfiDev->inIrp.transferLen       = pCbiUfiDev->ufiCmdBlk.dataXferLen;
  701.             pCbiUfiDev->inIrp.bfrCount          = 0x01;  
  702.             pCbiUfiDev->inIrp.bfrList[0].pid    = USB_PID_IN;
  703.             pCbiUfiDev->inIrp.bfrList[0].pBfr   = pCbiUfiDev->bulkInData;
  704.             pCbiUfiDev->inIrp.bfrList[0].bfrLen = pCbiUfiDev->ufiCmdBlk.dataXferLen;
  705.             pCbiUfiDev->inIrp.userPtr           = pCbiUfiDev;            
  706.  
  707.             /* Submit IRP */
  708.  
  709.             if (usbdTransfer (usbdHandle, pCbiUfiDev->inPipeHandle, 
  710.                               &(pCbiUfiDev->inIrp)) != OK)
  711.                 {
  712.                 USB_CBI_UFI_ERR ("usbCbiUfiCmdExecute: Unable to submit IRP for "
  713.                                  "BULK_IN data transfern", 0, 0, 0, 0, 0, 0);
  714.                 return (USB_INTERNAL_ERROR);
  715.                 }
  716.             /* 
  717.              * wait till the data transfer ends on bulk in pipe before reading
  718.              * the command status 
  719.              */
  720.     if ( OSS_SEM_TAKE (cbiUfiIrpSem, USB_CBI_IRP_TIME_OUT + 1000)  == ERROR )
  721. {
  722. USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Irp time out n", 
  723.                                    0, 0, 0, 0, 0, 0);
  724. OSS_SEM_GIVE (cbiUfiIrpSem);
  725. return (USB_INTERNAL_ERROR);
  726. }
  727.           
  728.             /* Check whether data transfer was complete or not */
  729.             if ( pCbiUfiDev->inIrp.result != OK)
  730.                 {
  731.                 USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Data transfer failed n", 
  732.                                    0, 0, 0, 0, 0, 0);
  733.                 OSS_SEM_GIVE (cbiUfiIrpSem);
  734.                 return (USB_COMMAND_FAILED); 
  735.                 }
  736.             }
  737.         else if (pCbiUfiDev->ufiCmdBlk.direction == USB_UFI_DIR_OUT)
  738.             {
  739.             /* device is expecting data over BULK_OUT pipe. send it */
  740.         
  741.             memset (&pCbiUfiDev->outIrp, 0, sizeof (USB_IRP));
  742.             /* form an IRP to write to BULK_OUT pipe */ 
  743.             pCbiUfiDev->outIrp.irpLen            = sizeof(USB_IRP);
  744.             pCbiUfiDev->outIrp.userCallback      = usbCbiUfiIrpCallback; 
  745.             pCbiUfiDev->outIrp.timeout           = USB_CBI_IRP_TIME_OUT;
  746.             pCbiUfiDev->outIrp.transferLen       = pCbiUfiDev->ufiCmdBlk.dataXferLen;
  747.             pCbiUfiDev->outIrp.bfrCount          = 0x01;  
  748.             pCbiUfiDev->outIrp.bfrList[0].pid    = USB_PID_OUT;
  749.             pCbiUfiDev->outIrp.bfrList[0].pBfr   = pCbiUfiDev->bulkOutData;
  750.             pCbiUfiDev->outIrp.bfrList[0].bfrLen = pCbiUfiDev->ufiCmdBlk.dataXferLen;
  751.             pCbiUfiDev->outIrp.userPtr           = pCbiUfiDev;
  752.            /* Submit IRP */
  753.  
  754.             if (usbdTransfer (usbdHandle, pCbiUfiDev->outPipeHandle, 
  755.                               &(pCbiUfiDev->outIrp)) != OK)
  756.                 {
  757.                 USB_CBI_UFI_ERR ("usbCbiUfiCmdExecute: Unable to submit IRP for "
  758.                                  "BULK_OUT data transfern", 0, 0, 0, 0, 0, 0);
  759.                 return (USB_INTERNAL_ERROR);
  760.                 }
  761.             /* 
  762.              * wait till the data transfer ends on bulk out pipe before reading
  763.              * the command status 
  764.              */
  765.             if ( OSS_SEM_TAKE (cbiUfiIrpSem, USB_CBI_IRP_TIME_OUT + 1000)  == ERROR )
  766.                 {
  767.                 USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Irp time out n", 
  768.                                    0, 0, 0, 0, 0, 0);
  769.                 OSS_SEM_GIVE (cbiUfiIrpSem);
  770.                 return (USB_INTERNAL_ERROR);
  771.                 }
  772.           
  773.             /* Check whether data transfer was complete or not */
  774.             if (pCbiUfiDev->outIrp.result != OK)
  775.                 {
  776.                 USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Data transfer failed n", 
  777.                                    0, 0, 0, 0, 0, 0);
  778.                 OSS_SEM_GIVE (cbiUfiIrpSem);
  779.                 return (USB_COMMAND_FAILED); 
  780.                 }
  781.             }
  782.         OSS_SEM_GIVE (cbiUfiIrpSem);
  783.         }
  784.     if ( OSS_SEM_TAKE (cbiUfiIrpSem, USB_CBI_IRP_TIME_OUT + 1000)  == ERROR )
  785.         {
  786.         USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Irp time out n", 
  787.                            0, 0, 0, 0, 0, 0);
  788.         OSS_SEM_GIVE (cbiUfiIrpSem);
  789.         return (USB_INTERNAL_ERROR);
  790.         }
  791.     /* Read the status from the interrupt endpoint */
  792.     memset (&(pCbiUfiDev->statusIrp), 0, sizeof (USB_IRP));   
  793.     /* form an IRP to read status from interrupt endpoint */ 
  794.     pCbiUfiDev->statusIrp.irpLen            = sizeof(USB_IRP);
  795.     pCbiUfiDev->statusIrp.userCallback      = usbCbiUfiIrpCallback; 
  796.     pCbiUfiDev->statusIrp.timeout           = USB_TIMEOUT_NONE;
  797.     pCbiUfiDev->statusIrp.transferLen       = 0x02;
  798.     pCbiUfiDev->statusIrp.bfrCount          = 0x01;  
  799.     pCbiUfiDev->statusIrp.bfrList[0].pid    = USB_PID_IN;
  800.     pCbiUfiDev->statusIrp.bfrList[0].pBfr   = pCbiUfiDev->intrStatus;
  801.     pCbiUfiDev->statusIrp.bfrList[0].bfrLen = 0x02;
  802.     pCbiUfiDev->statusIrp.userPtr           = pCbiUfiDev;            
  803.     /* Submit IRP */
  804.  
  805.     if (usbdTransfer (usbdHandle, pCbiUfiDev->intrPipeHandle, 
  806.                       &(pCbiUfiDev->statusIrp)) != OK)
  807.         {
  808.         USB_CBI_UFI_ERR ("usbCbiUfiCmdExecute: Unable to submit IRP for "
  809.                          "Interrupt statusn", 0, 0, 0, 0, 0, 0);
  810.         return (USB_INTERNAL_ERROR);
  811.         }
  812.     /* wait till the status bytes are read */
  813.     if ( OSS_SEM_TAKE (cbiUfiIrpSem, USB_CBI_IRP_TIME_OUT + 1000)  == ERROR )
  814.         {
  815.         USB_CBI_UFI_DEBUG ("usbCbiUfiCmdExecute: Irp time out n", 
  816.                            0, 0, 0, 0, 0, 0);
  817.         OSS_SEM_GIVE (cbiUfiIrpSem);
  818.         return (USB_INTERNAL_ERROR);
  819.         }
  820.     OSS_SEM_GIVE (cbiUfiIrpSem);    
  821.     /* check for the status bytes read..stalled condition */
  822.     if (pCbiUfiDev->statusIrp.result != OK)
  823.         {
  824.         return (USB_BULK_IO_ERROR);
  825.         } 
  826.     else
  827.         {
  828.         return (USB_COMMAND_SUCCESS);
  829.         }
  830.     } 
  831. /***************************************************************************
  832. *
  833. * usbCbiUfiReqSense - Executes an Request Sense command block. 
  834. *
  835. * Forms and executes Request Sense command on the specified device.
  836. *
  837. * RETURNS: N/A
  838. */
  839. LOCAL VOID usbCbiUfiReqSense
  840.     (
  841.     pUSB_CBI_UFI_DEV pCbiUfiDev      /* pointer to cbi_ufi device  */
  842.     )
  843.     {
  844.     UINT8 * pReqSense;
  845.     UINT16 status = 0xFFFF;
  846.     if ((pReqSense = OSS_MALLOC (UFI_STD_REQ_SENSE_LEN)) == NULL)
  847. {
  848. return;
  849. }
  850.     pCbiUfiDev->bulkInData  = pReqSense; 
  851.     if ( usbCbiUfiFormCmd (pCbiUfiDev, USB_UFI_REQUEST_SENSE, 0, 0) != OK )
  852.         {
  853.         USB_CBI_UFI_ERR ("usbCbiUfiReqSense: Error forming commandn",
  854.                          0, 0, 0, 0, 0, 0);
  855.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  856.         } 
  857.     if ( usbCbiUfiCmdExecute (pCbiUfiDev) != USB_COMMAND_SUCCESS )
  858.         {
  859.         USB_CBI_UFI_ERR ("usbCbiUfiReqSense: Error executing "
  860.                          "USB_UFI_REQUEST_SENSE commandn", 0, 0, 0, 0, 0, 0);        
  861.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  862.         }
  863.     else 
  864.         {
  865.         
  866.          /* Request Sense command success. Check the sense key & qualifiers. */
  867.         switch (*(pReqSense + USB_UFI_SENSE_KEY_OFFSET))
  868.             {
  869.             case USB_UFI_NO_SENSE:
  870.                 USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: No Sense key, %d, %dn",
  871.                                    *(pReqSense + USB_UFI_SENSE_ASC), 
  872.                                    *(pReqSense + USB_UFI_SENSE_ASCQ), 0, 0, 0, 0);
  873.                 break;
  874.             case USB_UFI_RECOVERED_ERROR:
  875.                 USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Recovered Error, %d, %dn",
  876.                                    *(pReqSense + USB_UFI_SENSE_ASC), 
  877.                                    *(pReqSense + USB_UFI_SENSE_ASCQ), 0, 0, 0, 0);
  878.                 break;
  879.             case USB_UFI_NOT_READY:
  880.                 USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Device not ready, %d, %d n",
  881.                                    *(pReqSense + USB_UFI_SENSE_ASC), 
  882.                                    *(pReqSense + USB_UFI_SENSE_ASCQ), 0, 0, 0, 0);
  883.                 break;
  884.             case USB_UFI_MEDIUM_ERROR:
  885.                 USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Medium Error, %d, %dn",
  886.                                    *(pReqSense + USB_UFI_SENSE_ASC), 
  887.                                    *(pReqSense + USB_UFI_SENSE_ASCQ), 0, 0, 0, 0);
  888.                 break;
  889.             case USB_UFI_HARDWARE_ERROR:
  890.                 USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Hardware Error, %d, %dn",
  891.     *(pReqSense + USB_UFI_SENSE_ASC), 
  892.                                    *(pReqSense + USB_UFI_SENSE_ASCQ), 0, 0, 0, 0);
  893.                 break;
  894.             case USB_UFI_ILL_REQUEST:
  895.                 USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Illegal Request, %d, %dn",
  896.                                    *(pReqSense + USB_UFI_SENSE_ASC), 
  897.                                    *(pReqSense + USB_UFI_SENSE_ASCQ), 0, 0, 0, 0);
  898.                 break;
  899.             case USB_UFI_UNIT_ATTN:
  900.                 USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Unit Attention, %d, %dn",
  901.                                    *(pReqSense + USB_UFI_SENSE_ASC), 
  902.                                    *(pReqSense + USB_UFI_SENSE_ASCQ), 0, 0, 0, 0);
  903.                 /* If Unit attention condition, check the ASC and ASCQ */  
  904.                 status = (*(pReqSense + 12)  << 8) & 0xFF00;
  905.                 status = status | *(pReqSense + 13);
  906.                 switch (status)
  907.                     {
  908.                     case USB_UFI_WRITE_PROTECT :
  909.                         USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Media write "
  910.                                            "protectedn", 0, 0, 0, 0, 0 ,0);
  911.                         break;
  912.  
  913.                     case USB_UFI_MEDIA_CHANGE :  
  914.                         USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Media changedn",
  915.                                            0, 0, 0, 0, 0 ,0);
  916.                         break;
  917.                     case USB_UFI_POWER_ON_RESET :  
  918.                         USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Power on reset"
  919.                                            " Bus device resetn",0, 0, 0, 0, 0 ,0);
  920.                         break;
  921.                     case USB_UFI_COMMAND_SUCCESS :  
  922.                         USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: No sense"
  923.                                            "Bus device resetn",0, 0, 0, 0, 0 ,0);
  924.                         break;
  925.                     }
  926.                 break;
  927.             case USB_UFI_DATA_PROTECT:  
  928.                 USB_CBI_UFI_DEBUG ("usbCbiUfiReqSense: Write Protectn",
  929.                                    0, 0, 0, 0, 0, 0);
  930.                 break;
  931.             default :
  932.                 break;
  933.             }
  934.         }
  935.     OSS_FREE (pReqSense);
  936.     }        
  937. /***************************************************************************
  938. *
  939. * usbCbiUfiDevFind - Searches for a USB_CBI_UFI_DEV for indicated node ID
  940. *
  941. * RETURNS: pointer to matching USB_CBI_UFI_DEV or NULL if not found
  942. */
  943. LOCAL pUSB_CBI_UFI_DEV usbCbiUfiDevFind
  944.     (
  945.     USBD_NODE_ID nodeId          /* node ID to be looked for */
  946.     )
  947.     {
  948.     pUSB_CBI_UFI_DEV pCbiUfiDev = usbListFirst (&cbiUfiDevList);
  949.     /* browse through the list */
  950.     while (pCbiUfiDev != NULL)
  951.         {
  952.         if (pCbiUfiDev->cbiUfiDevId == nodeId)
  953.             break;
  954.         pCbiUfiDev = usbListNext (&pCbiUfiDev->cbiUfiDevLink);
  955.         }
  956.     return (pCbiUfiDev);
  957.     }
  958. /***************************************************************************
  959. *
  960. * findEndpoint - Searches for a BULK endpoint of the indicated direction.
  961. *
  962. * RETURNS: pointer to matching endpoint descriptor or NULL if not found
  963. */
  964. LOCAL pUSB_ENDPOINT_DESCR findEndpoint
  965.     (
  966.     pUINT8 pBfr,
  967.     UINT16 bfrLen,
  968.     UINT8  attribute, 
  969.     UINT16 direction
  970.     )
  971.     {
  972.     pUSB_ENDPOINT_DESCR pEp;
  973.     while ((pEp = usbDescrParseSkip (&pBfr, &bfrLen, USB_DESCR_ENDPOINT)) 
  974.            != NULL)
  975.         {
  976.         if ((pEp->attributes & USB_ATTR_EPTYPE_MASK) == attribute &&
  977.             (pEp->endpointAddress & USB_ENDPOINT_DIR_MASK) == direction)
  978.             break;
  979.         }
  980.     return (pEp);
  981.     }
  982. /***************************************************************************
  983. *
  984. * usbCbiUfiPhysDevCreate - create USB_CBI_UFI_DEV Structure for the device 
  985. * This function is invoked from the dynamic attach callback routine whenever 
  986. * a USB_CBI_UFI_DEV device is attached.  It allocates memory for the structure,
  987. * sets device configuration, and creates pipe for bulk-in,bulk-out and interrupt
  988. * endpoints.  It also sets the device configuration so that it follows UFI
  989. * command set.
  990. * RETURNS: pUSB_CBI_UFI_DEV on success, NULL if failed to create device.
  991. */
  992. LOCAL pUSB_CBI_UFI_DEV usbCbiUfiPhysDevCreate
  993.     (
  994.     USBD_NODE_ID nodeId,         /* USBD Node Id ofthe device  */     
  995.     UINT16       configuration,  /* Configuration value        */ 
  996.     UINT16       interface       /* Interface Number           */ 
  997.     )
  998.     {
  999.     UINT16   actLength;
  1000.     UINT8 * pBfr;           /* store for descriptors      */ 
  1001.     UINT8 * pScratchBfr;    /* pointer to the above store */ 
  1002.     UINT     ifNo;
  1003.   
  1004.     USB_CBI_UFI_DEV * pCbiUfiDev;
  1005.     USB_CONFIG_DESCR * pCfgDescr;
  1006.     USB_INTERFACE_DESCR * pIfDescr;
  1007.     USB_ENDPOINT_DESCR * pOutEp;
  1008.     USB_ENDPOINT_DESCR * pInEp;
  1009.     USB_ENDPOINT_DESCR * pIntrEp;
  1010.     /*
  1011.      * A new device is being attached. Check if we already 
  1012.      * have a structure for this device.
  1013.      */
  1014.     if ((pCbiUfiDev = usbCbiUfiDevFind (nodeId)) != NULL)
  1015.         return (pCbiUfiDev);
  1016.     /* Allocate memory for a new structure to represent this device */
  1017.     if ((pBfr = OSS_MALLOC (USB_MAX_DESCR_LEN)) == NULL)
  1018.         {
  1019.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Unable to allocate 
  1020. memory:pBfrn", 0, 0, 0, 0, 0, 0);
  1021.         goto errorExit;
  1022.         }
  1023.     if ((pCbiUfiDev = OSS_CALLOC (sizeof (*pCbiUfiDev))) == NULL)
  1024.         {
  1025.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Unable to allocate 
  1026. memory:pCbiUfiDevn", 0, 0, 0, 0, 0, 0);
  1027.         goto errorExit;
  1028.         }
  1029.     pCbiUfiDev->cbiUfiDevId     = nodeId; 
  1030.     pCbiUfiDev->configuration   = configuration;
  1031.     pCbiUfiDev->interface       = interface;
  1032.     pCbiUfiDev->connected       = TRUE;
  1033.     /* Check out the device configuration */
  1034.     /* Configuration index is assumed to be one less than config'n value */
  1035.     if (usbdDescriptorGet (usbdHandle, 
  1036.    pCbiUfiDev->cbiUfiDevId, 
  1037.    USB_RT_STANDARD | USB_RT_DEVICE, 
  1038.    USB_DESCR_CONFIGURATION, 
  1039.    (configuration - 1), 
  1040.    0, 
  1041.    USB_MAX_DESCR_LEN, 
  1042.    pBfr, 
  1043.    &actLength) 
  1044. != OK)
  1045.         {
  1046.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Unable to read configuration "
  1047.                          "descriptorn", 0, 0, 0, 0, 0, 0);
  1048.         goto errorExit;
  1049.         }
  1050.     if ((pCfgDescr = usbDescrParse (pBfr, 
  1051.     actLength, 
  1052.     USB_DESCR_CONFIGURATION)) 
  1053.   == NULL)
  1054.         {
  1055.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Unable to find configuration "
  1056.                          "descriptorn", 0, 0, 0, 0, 0, 0);
  1057.         goto errorExit;
  1058.         }
  1059.    
  1060.     /* Look for the interface representing the USB_CBI_UFI Device. */
  1061.     ifNo = 0;
  1062.     /*
  1063.      * usbDescrParseSkip() modifies the value of the pointer it recieves
  1064.      * so we pass it a copy of our buffer pointer
  1065.      */
  1066.     pScratchBfr = pBfr;
  1067.     while ((pIfDescr = usbDescrParseSkip (&pScratchBfr, 
  1068.   &actLength, 
  1069.   USB_DESCR_INTERFACE)) 
  1070. != NULL)
  1071.         {
  1072.         if (ifNo == pCbiUfiDev->interface)
  1073.             break;
  1074.         ifNo++;
  1075.         }
  1076.     if (pIfDescr == NULL)
  1077.         goto errorExit;
  1078.     pCbiUfiDev->altSetting = pIfDescr->alternateSetting;
  1079.     /* 
  1080.      * Retrieve the endpoint descriptor(s) following the identified interface
  1081.      * descriptor.
  1082.      */
  1083.     if ((pOutEp = findEndpoint (pScratchBfr, 
  1084. actLength, 
  1085. USB_ATTR_BULK, 
  1086. USB_ENDPOINT_OUT)) 
  1087.     == NULL)
  1088.         goto errorExit;
  1089.     if ((pInEp = findEndpoint (pScratchBfr, 
  1090.        actLength, 
  1091.        USB_ATTR_BULK, 
  1092.        USB_ENDPOINT_IN)) 
  1093.    == NULL)
  1094.         goto errorExit;
  1095.     if ((pIntrEp = findEndpoint (pScratchBfr, 
  1096.  actLength, 
  1097.  USB_ATTR_INTERRUPT, 
  1098.  USB_ENDPOINT_IN)) 
  1099.       == NULL)
  1100.         goto errorExit; 
  1101.     pCbiUfiDev->outEpAddress = pOutEp->endpointAddress;
  1102.     pCbiUfiDev->inEpAddress  = pInEp->endpointAddress;
  1103.     pCbiUfiDev->intrEpAddress  = pIntrEp->endpointAddress;
  1104.     /* Set the device configuration corresponding to USB_CBI_UFI_DEV */
  1105.     if ((usbdConfigurationSet (usbdHandle, pCbiUfiDev->cbiUfiDevId, 
  1106.                                pCbiUfiDev->configuration, 
  1107.                                pCfgDescr->maxPower * USB_POWER_MA_PER_UNIT)) 
  1108.       != OK )
  1109.         {
  1110.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Unable to set device "
  1111.                          "configuration n", 0, 0, 0, 0, 0, 0);
  1112.         goto errorExit;
  1113.         }
  1114.     else
  1115.         {
  1116.         USB_CBI_UFI_DEBUG ("usbCbiUfiPhysDevCreate: Configuration set to 0x%x n",
  1117.                            pCbiUfiDev->configuration, 0, 0, 0, 0, 0);
  1118.         }
  1119.     
  1120.    /* Select interface 
  1121.     * 
  1122.     * NOTE: Some devices may reject this command, and this does not represent
  1123.     * a fatal error.  Therefore, we ignore the return status.
  1124.     */
  1125.     usbdInterfaceSet (usbdHandle, 
  1126.       pCbiUfiDev->cbiUfiDevId, 
  1127.       pCbiUfiDev->interface, 
  1128.       pCbiUfiDev->altSetting);
  1129.     /* Create a Bulk-out pipe for the USB_CBI_UFI_DEV device */
  1130.     if (usbdPipeCreate (usbdHandle, 
  1131. pCbiUfiDev->cbiUfiDevId, 
  1132. pOutEp->endpointAddress, 
  1133. pCbiUfiDev->configuration, 
  1134. pCbiUfiDev->interface, 
  1135. USB_XFRTYPE_BULK, 
  1136. USB_DIR_OUT, 
  1137. FROM_LITTLEW(pOutEp->maxPacketSize),
  1138. 0, 
  1139. 0, 
  1140. &(pCbiUfiDev->outPipeHandle)) 
  1141. != OK)
  1142.         {
  1143.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Error creating bulk out pipen",
  1144.                          0, 0, 0, 0, 0, 0);
  1145.         goto errorExit;
  1146.         } 
  1147.     /* Create a Bulk-in pipe for the USB_CBI_UFI_DEV device */
  1148.        
  1149.     if (usbdPipeCreate (usbdHandle, pCbiUfiDev->cbiUfiDevId, 
  1150.                         pInEp->endpointAddress, pCbiUfiDev->configuration, 
  1151.                         pCbiUfiDev->interface, USB_XFRTYPE_BULK, USB_DIR_IN, 
  1152.                         FROM_LITTLEW(pInEp->maxPacketSize), 0, 0, 
  1153.                         &(pCbiUfiDev->inPipeHandle)) != OK)
  1154.         {
  1155.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Error creating bulk in pipen",
  1156.                          0, 0, 0, 0, 0, 0);
  1157.         goto errorExit;
  1158.         } 
  1159.     /* Create a Interrupt pipe for the USB_CBI_UFI_DEV device */
  1160.     if ((usbdPipeCreate (usbdHandle, pCbiUfiDev->cbiUfiDevId, 
  1161.                         (pIntrEp->endpointAddress & 0xf), 
  1162. pCbiUfiDev->configuration, 
  1163.                         pCbiUfiDev->interface, 
  1164. USB_XFRTYPE_INTERRUPT, 
  1165. USB_DIR_IN, 
  1166.                         2, 
  1167. 2, 
  1168. 0x10, 
  1169.                         &(pCbiUfiDev->intrPipeHandle))) 
  1170. != OK)
  1171.         {
  1172.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Error creating interrupt pipe %xn",
  1173.                          0, 0, 0, 0, 0, 0);
  1174.         goto errorExit;
  1175.         } 
  1176.     /* Clear HALT feauture on the endpoints */
  1177.     if ((usbdFeatureClear (usbdHandle, 
  1178.    pCbiUfiDev->cbiUfiDevId, 
  1179.    USB_RT_ENDPOINT, 
  1180.                            USB_FSEL_DEV_ENDPOINT_HALT, 
  1181.                            (pOutEp->endpointAddress & 0x0F))) 
  1182.    != OK)
  1183.         {
  1184.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Failed to clear HALT feauture "
  1185.                          "on bulk out Endpoint %xn", 0, 0, 0, 0, 0, 0);
  1186.         }  
  1187.     if ((usbdFeatureClear (usbdHandle, 
  1188.    pCbiUfiDev->cbiUfiDevId, 
  1189.    USB_RT_ENDPOINT, 
  1190.                            USB_FSEL_DEV_ENDPOINT_HALT, 
  1191.                            (pOutEp->endpointAddress & 0x0F))) 
  1192.    != OK)
  1193.         {
  1194.         USB_CBI_UFI_ERR ("usbCbiUfiPhysDevCreate: Failed to clear HALT feauture "
  1195.                          "on bulk in Endpoint %xn", 0, 0, 0, 0, 0, 0);
  1196.         } 
  1197.     /* Link the newly created structure. */
  1198.     usbListLink (&cbiUfiDevList, pCbiUfiDev, 
  1199.                  &pCbiUfiDev->cbiUfiDevLink, LINK_TAIL);
  1200.     OSS_FREE (pBfr);
  1201.     return (pCbiUfiDev);
  1202. errorExit:
  1203.     /* Error in creating CBI UFI Device */
  1204.     usbCbiUfiDevDestroy (pCbiUfiDev);
  1205.     OSS_FREE (pBfr);
  1206.     return (NULL);
  1207.     }
  1208. /***************************************************************************
  1209. *
  1210. * usbCbiUfiBlkDevCreate - create a block device.
  1211. *
  1212. * This routine  initializes a BLK_DEV structure, which describes a 
  1213. * logical partition on a USB_CBI_UFI_DEV device.  A logical partition is 
  1214. * an array of contiguously addressed blocks; it can be completely described 
  1215. * by the number of blocks and the address of the first block in the partition.  
  1216. *
  1217. * RETURNS: A pointer to the BLK_DEV, or NULL if no CBI/UFI device exists.
  1218. */
  1219. BLK_DEV * usbCbiUfiBlkDevCreate 
  1220.     (
  1221.     USBD_NODE_ID nodeId        /* Node Id of the CBI_UFI device */ 
  1222.     )
  1223.     {
  1224.     UINT8 * pInquiry;    /* store for INQUIRY data  */    
  1225.     USB_COMMAND_STATUS  s;
  1226.  
  1227.     pUSB_CBI_UFI_DEV pCbiUfiDev = usbCbiUfiDevFind (nodeId);
  1228.     if (pCbiUfiDev == NULL)
  1229.         {
  1230.         USB_CBI_UFI_ERR ("usbCbiUfiBlkDevCreate: No MSC/CBI/UFI foundn",
  1231.                          0, 0, 0, 0, 0, 0);
  1232.         return (NULL);
  1233.         }
  1234.     OSS_MUTEX_TAKE (cbiUfiDevMutex, OSS_BLOCK); 
  1235.     /* 
  1236.      * Initialise the standard block device structure for use 
  1237.      * with file systems 
  1238.      */
  1239.     pCbiUfiDev->blkDev.bd_blkRd        = (FUNCPTR) usbCbiUfiDevBlkRd;
  1240.     pCbiUfiDev->blkDev.bd_blkWrt       = (FUNCPTR) usbCbiUfiDevBlkWrt;
  1241.     pCbiUfiDev->blkDev.bd_ioctl        = (FUNCPTR) usbCbiUfiDevIoctl;
  1242.     pCbiUfiDev->blkDev.bd_reset        = (FUNCPTR) NULL; 
  1243.     pCbiUfiDev->blkDev.bd_statusChk    = (FUNCPTR) usbCbiUfiDevStChk;
  1244.     pCbiUfiDev->blkDev.bd_retry        = 1;
  1245.     pCbiUfiDev->blkDev.bd_mode         = O_RDWR;
  1246.     pCbiUfiDev->blkDev.bd_readyChanged = TRUE;
  1247.     if ((pInquiry = OSS_MALLOC (UFI_STD_INQUIRY_LEN)) == NULL)
  1248. {
  1249. return NULL;
  1250. }
  1251.     /* 
  1252.      * Read out the standard INQUIRY information from the device, mainly to
  1253.      * check whether the media is removable or not.
  1254.      */
  1255.     pCbiUfiDev->bulkInData  = pInquiry;
  1256.     if ( usbCbiUfiFormCmd (pCbiUfiDev, USB_UFI_INQUIRY, 0, 0) != OK )
  1257.         {
  1258.         USB_CBI_UFI_ERR ("usbCbiUfiBlkDevCreate: Error forming commandn",
  1259.                          0, 0, 0, 0, 0, 0);
  1260. OSS_FREE (pInquiry);
  1261.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1262.         return (NULL); 
  1263.         } 
  1264.     if ( usbCbiUfiCmdExecute (pCbiUfiDev) != USB_COMMAND_SUCCESS)
  1265.         {
  1266.         USB_CBI_UFI_ERR ("usbCbiUfiBlkDevCreate: Error executing "
  1267.                          "USB_UFI_INQUIRY commandn", 0, 0, 0, 0, 0, 0);        
  1268.         usbCbiUfiReqSense (pCbiUfiDev);
  1269.         OSS_FREE (pInquiry);
  1270.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1271.         return (NULL);
  1272.         }
  1273.     /* Check the media type bit  */
  1274.     if (*(pInquiry + 1) & USB_UFI_INQUIRY_RMB_BIT)
  1275.         {
  1276.         pCbiUfiDev->blkDev.bd_removable = TRUE;
  1277.         }
  1278.     else
  1279.         {
  1280.         pCbiUfiDev->blkDev.bd_removable = FALSE;      
  1281.         }
  1282.     /*  
  1283.      *  The CBI Spec states that request sense should be called after
  1284.      *  every command whether successful or not.
  1285.      *  
  1286.      *  This request sense should return:
  1287.      *  POWER ON RESET OR BUS DEVICE RESET OCCURED (0X29)
  1288.      */ 
  1289.     usbCbiUfiReqSense (pCbiUfiDev);
  1290.     pCbiUfiDev->bulkInData  = pInquiry;
  1291.     /* 
  1292.      *  Read the block size and capacity of device (in terms of blocks)
  1293.      *  ---------------------------------------------------------------
  1294.      *
  1295.      *  The first read capacity should fail. It will stall the pipe.  After 
  1296.      *  the feature clear the following request sense should return:
  1297.      *
  1298.      *  NOT READY TO READY TRANSITION - MEDIA CHANGED
  1299.      *  or 
  1300.      *  NO MEDIA
  1301.      *  if no disk is present.  In the first case just try again, 
  1302.      *  how ever if there is no media, fake the disk size and return
  1303.      *  the BLK_DEV.
  1304.      */
  1305.     if ( usbCbiUfiFormCmd (pCbiUfiDev, 
  1306.    USB_UFI_READ_CAPACITY, 
  1307.    0, 
  1308.    0)   
  1309.   != OK )
  1310.         {
  1311.         OSS_FREE (pInquiry);
  1312.         OSS_MUTEX_RELEASE (cbiUfiDevMutex); 
  1313.         return (NULL); 
  1314.         } 
  1315.     if ( (s = usbCbiUfiCmdExecute (pCbiUfiDev)) == USB_COMMAND_FAILED )
  1316. {
  1317. usbCbiUfiReqSense (pCbiUfiDev);
  1318.     
  1319. /*  
  1320.  *  We ignore the sense data and instead look at the 
  1321.  *  interrupt data block which is the same.
  1322.  */ 
  1323. if (pCbiUfiDev->intrStatus[0] == USB_UFI_ASC_NO_MEDIA) 
  1324.             {
  1325.     USB_CBI_UFI_DEBUG ("usbCbiUfiDevStChk: Media not presentn",
  1326.                                0, 0, 0, 0, 0, 0);
  1327.    
  1328.             /* declare that device has to be mounted on next IO operation */
  1329.     if (pCbiUfiDev->blkDev.bd_removable == TRUE)
  1330.                 pCbiUfiDev->blkDev.bd_readyChanged = TRUE;
  1331.     /* fake the disk size */
  1332.  
  1333.     pCbiUfiDev->blkDev.bd_nBlocks =  (UINT32) 0xb40;
  1334.  
  1335.     pCbiUfiDev->blkDev.bd_bytesPerBlk = (UINT32)  0x200;
  1336.     printf ("No disk in driven");
  1337.  
  1338.             OSS_FREE (pInquiry);
  1339.     OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1340.     return (&pCbiUfiDev->blkDev);
  1341.     }
  1342. /*  Here we go with the second try */
  1343. if (pCbiUfiDev->intrStatus[0] == USB_UFI_ASC_MEDIA_CHANGE) 
  1344.     {
  1345.             pCbiUfiDev->bulkInData  = pInquiry;
  1346.             if ( usbCbiUfiFormCmd (pCbiUfiDev, 
  1347.                 USB_UFI_READ_CAPACITY, 
  1348.            0, 
  1349.            0) 
  1350.            != OK )
  1351.                 {
  1352.          OSS_FREE (pInquiry);
  1353.                 OSS_MUTEX_RELEASE (cbiUfiDevMutex); 
  1354.                 return (NULL); 
  1355.                 } 
  1356.             if ( usbCbiUfiCmdExecute (pCbiUfiDev) != USB_COMMAND_SUCCESS )
  1357.                 {
  1358.          USB_CBI_UFI_ERR ("usbCbiUfiBlkDevCreate: Error executing "
  1359.                          "USB_UFI_READ_CAPACITY commandn", 0, 0, 0, 0, 0, 0);
  1360.         OSS_FREE (pInquiry);
  1361.      OSS_MUTEX_RELEASE (cbiUfiDevMutex); 
  1362.     return (NULL);
  1363.              }
  1364.     
  1365.     /* This guy should return no sense data */
  1366.             usbCbiUfiReqSense (pCbiUfiDev);
  1367.     }
  1368.  
  1369.         }
  1370.     else if ( s != USB_COMMAND_SUCCESS)
  1371.         { 
  1372.         USB_CBI_UFI_ERR ("usbCbiUfiBlkDevCreate: Error executing "
  1373.                          "USB_UFI_READ_CAPACITY commandn", 0, 0, 0, 0, 0, 0);
  1374.         OSS_FREE (pInquiry);
  1375.         OSS_MUTEX_RELEASE (cbiUfiDevMutex); 
  1376.         return (NULL);     
  1377.         }
  1378.     /* 
  1379.      * Response is in BIG endian format. Swap it to get correct value.
  1380.      * Also, READ_CAPACITY returns the address of the last logical block,
  1381.      * NOT the number of blocks.  Since the blkDev structure wants the 
  1382.      * number of blocks, we add 1 (numBlocks = last address + 1).  
  1383.      */
  1384.     pCbiUfiDev->blkDev.bd_nBlocks =  USB_SWAP_32 (*((UINT32 *) pInquiry)) + 1; 
  1385.  
  1386.     pCbiUfiDev->blkDev.bd_bytesPerBlk = 
  1387.  USB_SWAP_32 (*((UINT32 *) (pInquiry+4))); 
  1388.     USB_CBI_UFI_DEBUG ("usbCbiUfiBlkDevCreate: Number of Blocks : %x, "
  1389.                        "Block Size: %x n", pCbiUfiDev->blkDev.bd_nBlocks, 
  1390.                        pCbiUfiDev->blkDev.bd_bytesPerBlk, 0, 0, 0, 0 );   
  1391.     OSS_FREE (pInquiry);
  1392.     OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1393.     return (&pCbiUfiDev->blkDev);
  1394.     }        
  1395. /***************************************************************************
  1396. *
  1397. * usbCbiUfiDevBlkRd - routine to read one or more blocks from the device.
  1398. *
  1399. * This routine reads the specified physical sector(s) from a specified
  1400. * physical device.  Typically called by file system when data is to be
  1401. * read from a particular device.
  1402. *
  1403. * RETURNS: OK on success, or ERROR if failed to read from device
  1404. */
  1405. LOCAL STATUS usbCbiUfiDevBlkRd
  1406.     (
  1407.     BLK_DEV * pBlkDev,           /* pointer to UFI  device   */ 
  1408.     UINT32       blkNum,            /* logical block number     */
  1409.     UINT32       numBlks,           /* number of blocks to read */
  1410.     char *    pBuf               /* store for data           */ 
  1411.     )
  1412.     {
  1413.     USB_COMMAND_STATUS s;
  1414.     pUSB_CBI_UFI_DEV  pCbiUfiDev = (USB_CBI_UFI_DEV *)pBlkDev;   
  1415.     USB_CBI_UFI_DEBUG ("usbCbiUfiDevBlkRd: Reading from block number: %xn",
  1416.                        blkNum, 0, 0, 0, 0, 0);
  1417.  
  1418.     OSS_MUTEX_TAKE (cbiUfiDevMutex, OSS_BLOCK); 
  1419.     /* initialise the pointer to fetch bulk out data */
  1420.     pCbiUfiDev->bulkInData = (UINT8 *)pBuf;
  1421.     if ( usbCbiUfiFormCmd (pCbiUfiDev, USB_UFI_READ10, 
  1422.                            blkNum, numBlks) != OK )
  1423.         {
  1424.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1425.         return (ERROR);  
  1426.         }
  1427.   
  1428.     s = usbCbiUfiCmdExecute (pCbiUfiDev);
  1429.    
  1430.     if ( s != USB_COMMAND_SUCCESS )
  1431.         {
  1432.         if ( s == USB_COMMAND_FAILED)
  1433.             usbCbiUfiDevReset (pBlkDev); 
  1434.        
  1435.         usbCbiUfiReqSense (pCbiUfiDev);
  1436.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1437.         return (ERROR); 
  1438.         }
  1439.     OSS_MUTEX_RELEASE (cbiUfiDevMutex); 
  1440.     return (OK);
  1441.     }
  1442. /***************************************************************************
  1443. *
  1444. * usbCbiUfiDevBlkWrt - routine to write one or more blocks to the device.
  1445. *
  1446. * This routine writes the specified physical sector(s) to a specified physical
  1447. * device.
  1448. *
  1449. * RETURNS: OK on success, or ERROR if failed to write to device
  1450. */
  1451. LOCAL STATUS usbCbiUfiDevBlkWrt
  1452.     (
  1453.     BLK_DEV * pBlkDev,           /* pointer to UFI device     */  
  1454.     UINT32       blkNum,            /* logical block number      */
  1455.     UINT32       numBlks,           /* number of blocks to write */ 
  1456.     char *    pBuf               /* data to be written        */ 
  1457.     )
  1458.     {
  1459.     USB_COMMAND_STATUS s;
  1460.     pUSB_CBI_UFI_DEV  pCbiUfiDev = (USB_CBI_UFI_DEV *)pBlkDev;   
  1461.     USB_CBI_UFI_DEBUG ("usbCbiUfiDevBlkWrt: Writing from block number: %xn",
  1462.                         blkNum, 0, 0, 0, 0, 0);
  1463.     OSS_MUTEX_TAKE (cbiUfiDevMutex, OSS_BLOCK); 
  1464.     /* initialise the pointer to fetch bulk out data */
  1465.     pCbiUfiDev->bulkOutData = (UINT8 *)pBuf;
  1466.     if ( usbCbiUfiFormCmd (pCbiUfiDev, USB_UFI_WRITE10, blkNum, 
  1467.                            numBlks) != OK )
  1468.         {
  1469.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1470.         return (ERROR); 
  1471.         }
  1472.     s = usbCbiUfiCmdExecute (pCbiUfiDev);
  1473.     /*
  1474.      * check for the status of the write operation. If failed while
  1475.      * transferring ADSC or any FATAL error, do a block reset.
  1476.      */   
  1477.     if ( s != USB_COMMAND_SUCCESS )
  1478.         {
  1479.         if ( s == USB_COMMAND_FAILED)
  1480.             {
  1481.             usbCbiUfiDevReset (pBlkDev); 
  1482.             }
  1483.         usbCbiUfiReqSense (pCbiUfiDev);   
  1484.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1485.         return (ERROR); 
  1486.         }
  1487.     OSS_MUTEX_RELEASE (cbiUfiDevMutex); 
  1488.     return (OK);
  1489.     }
  1490. /***************************************************************************
  1491. *
  1492. * usbCbiUfiIrpCallback - Invoked upon IRP completion
  1493. *
  1494. * Examines the status of the IRP submitted.  
  1495. *
  1496. * RETURNS: N/A
  1497. */
  1498. LOCAL VOID usbCbiUfiIrpCallback
  1499.     (
  1500.     pVOID p                      /* pointer to the IRP submitted */
  1501.     )
  1502.     {
  1503.     pUSB_IRP      pIrp     = (pUSB_IRP) p;
  1504.     pUSB_CBI_UFI_DEV pCbiUfiDev = pIrp->userPtr;
  1505.     /* check whether the IRP was for bulk out/ bulk in / status transport */
  1506.     if (pIrp == &(pCbiUfiDev->outIrp))
  1507.         {  
  1508.         if (pIrp->result == OK)     /* check the result of IRP */
  1509.             {
  1510.             USB_CBI_UFI_DEBUG ("usbCbiUfiIrpCallback: Num of Bytes transferred on "
  1511.                                "out pipe %dn", pIrp->bfrList[0].actLen, 
  1512.                                0, 0, 0, 0, 0); 
  1513.             }
  1514.         else
  1515.             {
  1516.             USB_CBI_UFI_ERR ("usbCbiUfiIrpCallback: Irp failed on Bulk Out %x n",
  1517.                             pIrp->result, 0, 0, 0, 0, 0); 
  1518.             /* Clear HALT Feature on Bulk out Endpoint */ 
  1519.             if ((usbdFeatureClear (usbdHandle, pCbiUfiDev->cbiUfiDevId, 
  1520.                            USB_RT_ENDPOINT, USB_FSEL_DEV_ENDPOINT_HALT, 
  1521.                            (pCbiUfiDev->outEpAddress & 0x0F))) != OK)
  1522.                 {
  1523.                 USB_CBI_UFI_ERR ("usbCbiUfiIrpCallback: Failed to clear HALT "
  1524.                                  "feature on bulk out Endpoint %xn", 0, 0, 0, 
  1525.                                  0, 0, 0);
  1526.                 }
  1527.             }
  1528.         } 
  1529.      else  if (pIrp == &(pCbiUfiDev->inIrp))   /* IRP for bulk_in data */
  1530.         {
  1531.         if (pIrp->result == OK)
  1532.             {
  1533.             USB_CBI_UFI_DEBUG ("usbCbiUfiIrpCallback: Num of Bytes read from Bulk "
  1534.                                "In =%dn", pIrp->bfrList[0].actLen, 0, 0, 0, 0, 0); 
  1535.             }
  1536.         else   /* IRP on BULK IN failed */
  1537.             {
  1538.             USB_CBI_UFI_ERR ("usbCbiUfiIrpCallback : Irp failed on Bulk in ,%xn", 
  1539.                           pIrp->result, 0, 0, 0, 0, 0);
  1540.             /* Clear HALT Feature on Bulk in Endpoint */
  1541.             if ((usbdFeatureClear (usbdHandle, 
  1542.    pCbiUfiDev->cbiUfiDevId, 
  1543.    USB_RT_ENDPOINT, 
  1544.                                    USB_FSEL_DEV_ENDPOINT_HALT, 
  1545.                                    (pCbiUfiDev->inEpAddress & 0x0F))) 
  1546.   != OK)
  1547.                 {
  1548.                 USB_CBI_UFI_ERR ("usbCbiUfiIrpCallback: Failed to clear HALT "
  1549.                         "feature on bulk in Endpoint %xn", 0, 0, 0, 0, 0, 0);
  1550.                 }
  1551.              }
  1552.         }
  1553.      else  if (pIrp == &(pCbiUfiDev->statusIrp))   /* IRP for bulk_in data */
  1554.         {
  1555.         if (pIrp->result == OK)
  1556.             {
  1557.             USB_CBI_UFI_DEBUG ("usbCbiUfiIrpCallback: Num of Bytes read from "
  1558.                                "status pipe =%d, %d, %dn", pIrp->bfrList[0].actLen, 
  1559.                                 pCbiUfiDev->intrStatus[0], 
  1560.                                 pCbiUfiDev->intrStatus[1], 0, 0, 0); 
  1561.             }
  1562.         else   /* IRP on BULK IN failed */
  1563.             {
  1564.             USB_CBI_UFI_ERR ("usbCbiUfiIrpCallback : Irp failed on interrupt pipe ,%xn", 
  1565.                           pIrp->result, 0, 0, 0, 0, 0);
  1566.             /* Clear HALT Feature on Bulk in Endpoint */
  1567.             if ((usbdFeatureClear (usbdHandle, 
  1568.    pCbiUfiDev->cbiUfiDevId, 
  1569.    USB_RT_ENDPOINT, 
  1570.                                    USB_FSEL_DEV_ENDPOINT_HALT, 
  1571.                                   (pCbiUfiDev->intrEpAddress & 0x0F))) 
  1572.    != OK)
  1573.                 {
  1574.                 USB_CBI_UFI_ERR ("usbCbiUfiIrpCallback: Failed to clear HALT "
  1575.                         "feature on bulk in Endpoint %xn", 0, 0, 0, 0, 0, 0);
  1576.                 }
  1577.             }
  1578.         }
  1579.    
  1580.     OSS_SEM_GIVE (cbiUfiIrpSem);
  1581.     }   
  1582.   
  1583. /***************************************************************************
  1584. *
  1585. * usbCbiUfiDevStChk - routine to check device status
  1586. *
  1587. * Typically called by the file system before doing a read/write to the device.
  1588. * The routine issues a TEST_UNIT_READY command.  Also, if the device is not
  1589. * ready, then the sense data is read from the device to check for presence/
  1590. * change of media.  For removable devices, the ready change flag is set to 
  1591. * indicate media change.  File system checks this flag, and remounts the device
  1592. *
  1593. * RETURNS: OK if the device is ready for IO, or ERROR if device is busy. 
  1594. */
  1595. LOCAL STATUS usbCbiUfiDevStChk
  1596.     (
  1597.     BLK_DEV * pBlkDev                /* pointer to MSC/CBI/UFI device */
  1598.     )
  1599.     {
  1600.     UINT8 * pSenseData;  /* store for SENSE data  */                 
  1601.     UINT8 * pInquiry;  /* store for SENSE data  */                 
  1602.     USB_COMMAND_STATUS s ;
  1603.     STATUS  rtnStatus = OK;
  1604.     pUSB_CBI_UFI_DEV pCbiUfiDev = (USB_CBI_UFI_DEV *)pBlkDev;
  1605.  
  1606.     OSS_MUTEX_TAKE (cbiUfiDevMutex, OSS_BLOCK);
  1607.     if ((pSenseData = OSS_MALLOC (USB_UFI_MS_HEADER_LEN)) == NULL)
  1608. {
  1609.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1610. return ERROR;
  1611. }
  1612.     if ((pInquiry = OSS_MALLOC (UFI_STD_INQUIRY_LEN)) == NULL)
  1613. {
  1614.    OSS_FREE (pSenseData);
  1615.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1616.         return ERROR;
  1617. }
  1618.     USB_CBI_UFI_DEBUG ("usbCbiUfiDevStChk: About to send TEST_UNIT_READYn",
  1619.                        0, 0, 0, 0, 0, 0);    
  1620.     /* Form a Test Unit Ready command and send it */ 
  1621.  
  1622.     if ( usbCbiUfiFormCmd (pCbiUfiDev, USB_UFI_TEST_UNIT_READY, 0, 0) != OK )
  1623.         {
  1624.         USB_CBI_UFI_ERR ("usbCbiUfiDevStChk: Error forming commandn",
  1625.                          0, 0, 0, 0, 0, 0);
  1626.    OSS_FREE (pSenseData);
  1627.    OSS_FREE (pInquiry);
  1628.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1629.         return (ERROR); 
  1630.         } 
  1631.     if (usbCbiUfiCmdExecute (pCbiUfiDev) != USB_COMMAND_SUCCESS)
  1632.         {
  1633.         usbCbiUfiReqSense (pCbiUfiDev);
  1634.         USB_CBI_UFI_DEBUG ("usbCbiUfiDevStChk: device not readyn",
  1635.                            0, 0, 0, 0, 0, 0);
  1636.         OSS_FREE (pSenseData);
  1637.         OSS_FREE (pInquiry);
  1638.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1639.         return (ERROR);
  1640.         }
  1641.     else if (pCbiUfiDev->intrStatus[0] != USB_UFI_NO_SENSE) 
  1642.         {
  1643.         if (pCbiUfiDev->intrStatus[0] == USB_UFI_ASC_NO_MEDIA) 
  1644.             {
  1645.             USB_CBI_UFI_DEBUG ("usbCbiUfiDevStChk: Media not presentn",
  1646.                                0, 0, 0, 0, 0, 0);
  1647.    
  1648.             /* declare that device has to be mounted on next IO operation */
  1649.             if (pCbiUfiDev->blkDev.bd_removable == TRUE)
  1650.                 pCbiUfiDev->blkDev.bd_readyChanged = TRUE;
  1651.             rtnStatus = ERROR; 
  1652.             }
  1653.         /* check for media change */
  1654.         else if (pCbiUfiDev->intrStatus[0] == USB_UFI_ASC_MEDIA_CHANGE) 
  1655.             {
  1656.             USB_CBI_UFI_DEBUG ("usbCbiUfiDevStChk: Media changedn",
  1657.                                0, 0, 0, 0, 0, 0);
  1658.    
  1659.             /* declare that device has to be mounted on next IO operation */
  1660.             if (pCbiUfiDev->blkDev.bd_removable == TRUE)
  1661.                 pCbiUfiDev->blkDev.bd_readyChanged = TRUE;
  1662.     /*  
  1663.      *  Re-submit the read capacity command now that a disk
  1664.      * has been inserted
  1665.      */
  1666.     usbCbiUfiReqSense (pCbiUfiDev);
  1667.     /* set pointer */
  1668.     pCbiUfiDev->bulkInData  = pInquiry;
  1669.     if ( usbCbiUfiFormCmd (pCbiUfiDev, 
  1670.    USB_UFI_READ_CAPACITY, 
  1671.    0, 
  1672.    0) 
  1673.    != OK )
  1674. {
  1675. rtnStatus = ERROR; 
  1676.     if ( usbCbiUfiCmdExecute (pCbiUfiDev) != USB_COMMAND_SUCCESS )
  1677. {
  1678. usbCbiUfiReqSense (pCbiUfiDev);
  1679. rtnStatus = ERROR; 
  1680. }
  1681.     else
  1682. {
  1683.      /*
  1684.       * Response is in BIG endian format. Swap it to get correct 
  1685.  * value.  * Also, READ_CAPACITY returns the address of the 
  1686.  * last logical block, NOT the number of blocks.  Since the 
  1687.  * blkDev structure wants the number of blocks, we add 1.
  1688.        */
  1689.  
  1690.      pCbiUfiDev->blkDev.bd_nBlocks = 
  1691.  USB_SWAP_32 (*((UINT32 *) pInquiry)) + 1;
  1692.  
  1693. pCbiUfiDev->blkDev.bd_bytesPerBlk = 
  1694.                                  USB_SWAP_32 (*((UINT32 *) (pInquiry+4)));
  1695.                 rtnStatus = OK; 
  1696. }
  1697.     }    
  1698.         /* For all other sense data return ERROR */ 
  1699.         else
  1700.             rtnStatus = ERROR;
  1701.         } 
  1702.     usbCbiUfiReqSense (pCbiUfiDev);
  1703.     if ( rtnStatus == ERROR )     
  1704.         {
  1705.         OSS_FREE (pSenseData);
  1706.         OSS_FREE (pInquiry);
  1707.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1708.         return (ERROR);  
  1709.         } 
  1710.     /* if we are here, then TEST UNIT READY command returned device is READY */
  1711.     /* 
  1712.      * Based on the status of write-protect status bit update the
  1713.      * access mode of the device. Issue a Mode Sense for reading
  1714.      * basic header information.
  1715.      */
  1716.     pCbiUfiDev->bulkInData = pSenseData;
  1717.     if ( usbCbiUfiFormCmd (pCbiUfiDev, USB_UFI_MODE_SENSE, 0, 0) != OK )
  1718.         {
  1719.         USB_CBI_UFI_ERR ("usbCbiUfiDevStChk: Error forming commandn",
  1720.                          0, 0, 0, 0, 0, 0);
  1721.         OSS_FREE (pSenseData);
  1722.         OSS_FREE (pInquiry);
  1723.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1724.         return (ERROR); 
  1725.         } 
  1726.     if ( (s = usbCbiUfiCmdExecute (pCbiUfiDev)) != USB_COMMAND_SUCCESS )
  1727.         {
  1728.         usbCbiUfiReqSense (pCbiUfiDev);
  1729.         if ( s == USB_COMMAND_FAILED )
  1730.             usbCbiUfiDevReset (pBlkDev); 
  1731.  
  1732.         USB_CBI_UFI_ERR ("usbCbiUfiDevStChk: Error executing " 
  1733.                         "USB_UFI_MODE_SENSE commandn", 0, 0, 0, 0, 0, 0);        
  1734.         OSS_FREE (pSenseData);
  1735.         OSS_FREE (pInquiry);
  1736.         OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1737.         return (ERROR);  
  1738.         }
  1739.    
  1740.     if ((*(pSenseData + 3) & USB_UFI_WRITE_PROTECT_BIT) 
  1741. == USB_UFI_WRITE_PROTECT_BIT)
  1742.         {
  1743.         USB_CBI_UFI_DEBUG ("usbCbiUfiDevStChk: Media Write protectedn",
  1744.                            0, 0, 0, 0, 0, 0);
  1745.         pCbiUfiDev->blkDev.bd_mode = O_RDONLY;
  1746.         }
  1747.     else 
  1748.         pCbiUfiDev->blkDev.bd_mode = O_RDWR;
  1749.  
  1750.     OSS_FREE (pSenseData);
  1751.     OSS_FREE (pInquiry);
  1752.     OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1753.     return (OK);
  1754.     }
  1755. /***************************************************************************
  1756. *
  1757. * usbCbiUfiDevReset -  routine to reset the MSC/CBI/UFI device.
  1758. *
  1759. * This routine issues a command block reset and followed by a port reset if 
  1760. * needed.  It also clears stall condition on bulk-in and bulk-out endpoints.
  1761. *
  1762. * RETURNS: OK if reset succcssful, or ERROR
  1763. */
  1764. LOCAL STATUS usbCbiUfiDevReset
  1765.     (
  1766.     BLK_DEV * pBlkDev                /* pointer to MSC/CBI/UFI device */
  1767.     )
  1768.     {
  1769.     USBD_NODE_INFO    ufiNodeInfo;
  1770.     pUSB_CBI_UFI_DEV pCbiUfiDev = (USB_CBI_UFI_DEV *)pBlkDev;
  1771.     USB_CBI_UFI_DEBUG ("usbCbiUfiDevReset: Sending Command block resetn",
  1772.                        0, 0, 0, 0, 0, 0);
  1773.     /* issue a command block reset as mentioned in CBI specification */
  1774.  
  1775.     pCbiUfiDev->ufiCmdBlk.dataXferLen = 0;
  1776.     pCbiUfiDev->ufiCmdBlk.direction   = 0;
  1777.     memset (&(pCbiUfiDev->ufiCmdBlk.cmd), 0xFF, USB_UFI_MAX_CMD_LEN);    
  1778.  
  1779.     pCbiUfiDev->ufiCmdBlk.cmd[0]      = 0x1D;     
  1780.     pCbiUfiDev->ufiCmdBlk.cmd[1]      = 0x04;
  1781.     /* Send the CBI Command block reset along with the ADSC request */
  1782.     if ( usbCbiUfiCmdExecute (pCbiUfiDev) != USB_COMMAND_SUCCESS )
  1783.         {
  1784.         USB_CBI_UFI_ERR ("usbCbiUfiDevReset: Error executing " 
  1785.                          "Class specific Reset commandn", 0, 0, 0, 0, 0, 0);
  1786.                 
  1787.         if (usbdNodeInfoGet (usbdHandle, pCbiUfiDev->cbiUfiDevId, &ufiNodeInfo,
  1788.                              sizeof (USBD_NODE_INFO) ) != OK )
  1789.             {
  1790.             OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1791.             return (ERROR);  
  1792.             }
  1793.         /* Issue a port reset on the HUB port to which UFI device is attached */
  1794.         if ( usbdFeatureSet (usbdHandle, pCbiUfiDev->cbiUfiDevId,
  1795.                              USB_RT_CLASS | USB_RT_OTHER, 
  1796.                              USB_HUB_FSEL_PORT_RESET, 
  1797.                              ufiNodeInfo.parentHubPort) != OK)
  1798.             {
  1799.             OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1800.             return (ERROR);  
  1801.             } 
  1802.         }
  1803.     /* Clear STALL condition on bulk-in and bulk-out endpoints */
  1804.     if ((usbdFeatureClear (usbdHandle,  
  1805.    pCbiUfiDev->cbiUfiDevId, 
  1806.    USB_RT_ENDPOINT, 
  1807.                            USB_FSEL_DEV_ENDPOINT_HALT, 
  1808.                            (pCbiUfiDev->inEpAddress & 0x0F))) 
  1809.    != OK)
  1810.         {
  1811.         USB_CBI_UFI_ERR ("usbCbiUfiDevReset: Failed to clear HALT feauture"
  1812.                       " on bulk in Endpoint %xn", 0, 0, 0, 0, 0, 0);
  1813.         }  
  1814.     if ((usbdFeatureClear (usbdHandle,  
  1815.    pCbiUfiDev->cbiUfiDevId, 
  1816.    USB_RT_ENDPOINT, 
  1817.                            USB_FSEL_DEV_ENDPOINT_HALT, 
  1818.                            (pCbiUfiDev->outEpAddress & 0x0F))) 
  1819.    != OK)
  1820.         {
  1821.         USB_CBI_UFI_ERR ("usbCbiUfiDevReset: Failed to clear HALT feauture"
  1822.                       " on bulk out Endpoint %xn", 0, 0, 0, 0, 0, 0);
  1823.         } 
  1824.     return (OK);
  1825.     }
  1826. /***************************************************************************
  1827. *
  1828. * notifyAttach - Notifies registered callers of attachment/removal
  1829. *
  1830. * RETURNS: N/A
  1831. */
  1832. LOCAL VOID notifyAttach
  1833.     (
  1834.     USBD_NODE_ID cbiUfiDevId,
  1835.     UINT16 attachCode
  1836.     )
  1837.     {
  1838.     pATTACH_REQUEST pRequest = usbListFirst (&reqList);
  1839.     while (pRequest != NULL)
  1840.     {
  1841.     (*pRequest->callback) (pRequest->callbackArg, 
  1842.                    cbiUfiDevId, attachCode);
  1843.     pRequest = usbListNext (&pRequest->reqLink);
  1844.     }
  1845.     }
  1846. /***************************************************************************
  1847. *
  1848. * usbCbiUfiDynamicAttachRegister - Register UFI device attach callback.
  1849. *
  1850. * <callback> is a caller-supplied function of the form:
  1851. *
  1852. * .CS
  1853. * typedef (*USB_UFI_ATTACH_CALLBACK) 
  1854. *     (
  1855. *     pVOID arg,
  1856. *     USBD_NODE_ID cbiUfiDevId,
  1857. *     UINT16 attachCode
  1858. *     );
  1859. * .CE
  1860. *
  1861. * usbCBiUfiDevLib will invoke <callback> each time a CBI_UFI device
  1862. * is attached to or removed from the system.  <arg> is a caller-defined
  1863. * parameter which will be passed to the <callback> each time it is
  1864. * invoked.  The <callback> will also be passed the nodeID of the device 
  1865. * being created/destroyed and an attach code of USB_UFI_ATTACH or 
  1866. * USB_UFI_REMOVE.
  1867. *
  1868. * NOTE: The user callback routine should not invoke any driver function that
  1869. * submits IRPs.  Further processing must be done from a different task context.
  1870. * As the driver routines wait for IRP completion, they cannot be invoked from
  1871. * USBD client task's context created for this driver.
  1872. *
  1873. *
  1874. * RETURNS: OK, or ERROR if unable to register callback
  1875. *
  1876. * ERRNO:
  1877. *   S_usbCbiUfiDevLib_BAD_PARAM
  1878. *   S_usbCbiUfiDevLib_OUT_OF_MEMORY
  1879. */
  1880. STATUS usbCbiUfiDynamicAttachRegister
  1881.     (
  1882.     USB_UFI_ATTACH_CALLBACK callback, /* new callback to be registered */
  1883.     pVOID arg                           /* user-defined arg to callback  */
  1884.     )
  1885.     {
  1886.     pATTACH_REQUEST   pRequest;
  1887.     pUSB_CBI_UFI_DEV  pCbiUfiDev;
  1888.     int status = OK;
  1889.     /* Validate parameters */
  1890.     if (callback == NULL)
  1891.         return (ossStatus (S_usbCbiUfiDevLib_BAD_PARAM));
  1892.     OSS_MUTEX_TAKE (cbiUfiDevMutex, OSS_BLOCK);
  1893.     /* Create a new request structure to track this callback request. */
  1894.     if ((pRequest = OSS_CALLOC (sizeof (*pRequest))) == NULL)
  1895.         {
  1896.         status = S_usbCbiUfiDevLib_OUT_OF_MEMORY;
  1897.         }
  1898.     else
  1899.         {
  1900.         pRequest->callback    = callback;
  1901.         pRequest->callbackArg = arg;
  1902.         usbListLink (&reqList, pRequest, &pRequest->reqLink, LINK_TAIL) ;
  1903.     
  1904.        /* 
  1905.         * Perform an initial notification of all currrently attached
  1906.         * CBI_UFI devices.
  1907.         */
  1908.         pCbiUfiDev = usbListFirst (&cbiUfiDevList);
  1909.         while (pCbiUfiDev != NULL)
  1910.     {
  1911.             if (pCbiUfiDev->connected)
  1912.                 (*callback) (arg, pCbiUfiDev->cbiUfiDevId, USB_UFI_ATTACH);
  1913.     pCbiUfiDev = usbListNext (&pCbiUfiDev->cbiUfiDevLink);
  1914.     }
  1915.         }
  1916.     OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1917.     return (ossStatus (status));
  1918.     }
  1919. /***************************************************************************
  1920. *
  1921. * usbCbiUfiDynamicAttachUnregister - Unregisters CBI_UFI attach callback.
  1922. *
  1923. * This function cancels a previous request to be dynamically notified for
  1924. * CBI_UFI device attachment and removal.  The <callback> and <arg> paramters 
  1925. * must exactly match those passed in a previous call to 
  1926. * usbCbiUfiDynamicAttachRegister().
  1927. *
  1928. * RETURNS: OK, or ERROR if unable to unregister callback
  1929. *
  1930. * ERRNO:
  1931. *   S_usbCbiUfiDevLib_NOT_REGISTERED
  1932. */
  1933. STATUS usbCbiUfiDynamicAttachUnregister
  1934.     (
  1935.     USB_UFI_ATTACH_CALLBACK callback,  /* callback to be unregistered  */
  1936.     pVOID arg                          /* user-defined arg to callback */
  1937.     )
  1938.     {
  1939.     pATTACH_REQUEST pRequest;
  1940.     int status = S_usbCbiUfiDevLib_NOT_REGISTERED;
  1941.     OSS_MUTEX_TAKE (cbiUfiDevMutex, OSS_BLOCK);
  1942.     pRequest = usbListFirst (&reqList);
  1943.     while (pRequest != NULL)
  1944.         {
  1945.         if ((callback == pRequest->callback) && (arg == pRequest->callbackArg))
  1946.     {
  1947.     /* We found a matching notification request. */
  1948.     usbListUnlink (&pRequest->reqLink);
  1949.             /* Dispose of structure */
  1950.             OSS_FREE (pRequest);
  1951.     status = OK;
  1952.     break;
  1953.     }
  1954.         pRequest = usbListNext (&pRequest->reqLink);
  1955.         }
  1956.     OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  1957.     return (ossStatus (status));
  1958.     }
  1959. /***************************************************************************
  1960. *
  1961. * usbCbiUfiDevLock - Marks CBI_UFI_DEV structure as in use.
  1962. *
  1963. * A caller uses usbCbiUfiDevLock() to notify usbCBiUfiDevLib that
  1964. * it is using the indicated CBI_UFI_DEV structure.  usbCBiUfiDevLib maintains
  1965. * a count of callers using a particular CBI_UFI_DEV structure so that it 
  1966. * knows when it is safe to dispose of a structure when the underlying
  1967. * CBI_UFI_DEV is removed from the system.  So long as the "lock count"
  1968. * is greater than zero, usbCbiUfiDevLib will not dispose of an CBI_UFI_DEV
  1969. * structure.
  1970. *
  1971. * RETURNS: OK, or ERROR if unable to mark CBI_UFI_DEV structure in use.
  1972. */
  1973. STATUS usbCbiUfiDevLock
  1974.     (
  1975.     USBD_NODE_ID nodeId    /* NodeId of the BLK_DEV to be marked as in use */
  1976.     )
  1977.     {
  1978.     pUSB_CBI_UFI_DEV pCbiUfiDev = usbCbiUfiDevFind (nodeId);
  1979.     if ( pCbiUfiDev == NULL)
  1980.         return (ERROR);
  1981.     pCbiUfiDev->lockCount++;
  1982.     return (OK);
  1983.     }
  1984. /***************************************************************************
  1985. *
  1986. * usbCbiUfiDevUnlock - Marks CBI_UFI_DEV structure as unused.
  1987. *
  1988. * This function releases a lock placed on an CBI_UFI_DEV structure.  When a
  1989. * caller no longer needs an CBI_UFI_DEV structure for which it has previously
  1990. * called usbCbiUfiDevLock(), then it should call this function to
  1991. * release the lock.
  1992. *
  1993. * NOTE: If the underlying CBI_UFI device has already been removed
  1994. * from the system, then this function will automatically dispose of the
  1995. * CBI_UFI_DEV structure if this call removes the last lock on the structure.
  1996. * Therefore, a caller must not reference the CBI_UFI_DEV structure after
  1997. * making this call.
  1998. *
  1999. * RETURNS: OK, or ERROR if unable to mark CBI_UFI_DEV structure unused
  2000. *
  2001. * ERRNO:
  2002. *   S_usbCBiUfiDevLib_NOT_LOCKED
  2003. */
  2004. STATUS usbCbiUfiDevUnlock
  2005.     (
  2006.     USBD_NODE_ID nodeId    /* NodeId of the BLK_DEV to be marked as unused */
  2007.     )
  2008.     {
  2009.     int status = OK;
  2010.     pUSB_CBI_UFI_DEV pCbiUfiDev = usbCbiUfiDevFind (nodeId);
  2011.  
  2012.     if ( pCbiUfiDev == NULL)
  2013.         return (ERROR);
  2014.     OSS_MUTEX_TAKE (cbiUfiDevMutex, OSS_BLOCK);
  2015.     if (pCbiUfiDev->lockCount == 0)
  2016.         {
  2017.         status = S_usbCBiUfiDevLib_NOT_LOCKED;
  2018.         }
  2019.     else
  2020.     {
  2021.     /* If this is the last lock and the underlying CBI_UFI device is
  2022.      * no longer connected, then dispose of the device.
  2023.      */
  2024.     if ((--pCbiUfiDev->lockCount == 0) && (!pCbiUfiDev->connected))
  2025. usbCbiUfiDevDestroy (pCbiUfiDev);
  2026.     }
  2027.     OSS_MUTEX_RELEASE (cbiUfiDevMutex);
  2028.     return (ossStatus (status));
  2029.     }
  2030. /***************************************************************************
  2031. *
  2032. * usbCbiUfiDescShow - displays configuration, device and interface descriptors.
  2033. *
  2034. * RETURNS: OK on success or ERROR is unable to read descriptors. 
  2035. */
  2036. LOCAL STATUS usbCbiUfiDescShow 
  2037.     (
  2038.     USBD_NODE_ID nodeId           /* node ID of the device        */
  2039.     )
  2040.     {
  2041.     UINT8    bfr[255];            /* store for descriptors         */
  2042.     UINT8    index;               
  2043.     UINT8    numCfg;              /* number of configuration       */
  2044.     UINT8    mfcIndex;            /* index for manufacturer string */
  2045.     UINT8    productIndex;        /* index for product string      */
  2046.     UINT16   actLength;           /* actual length of descriptor   */
  2047.     pUSB_DEVICE_DESCR  pDevDescr; /* pointer to device descriptor  */
  2048.     pUSB_STRING_DESCR  pStrDescr; /* pointer to string descriptor  */   
  2049.     /* Get the Device descriptor first */
  2050.     if (usbdDescriptorGet (usbdHandle, nodeId, 
  2051.                            USB_RT_STANDARD | USB_RT_DEVICE,
  2052.                            USB_DESCR_DEVICE, 0, 0, 20, bfr, &actLength) != OK)
  2053.         {
  2054.         USB_CBI_UFI_ERR ("usbCbiUfiDescShow: Failed to read Device descriptorn",
  2055.                          0, 0, 0, 0, 0, 0);
  2056.         return (ERROR);
  2057.         }
  2058.     if ((pDevDescr = usbDescrParse (bfr, actLength, USB_DESCR_DEVICE)) == NULL)
  2059.         {
  2060.          USB_CBI_UFI_ERR ("usbCbiUfiDescShow: No Device descriptor was found "
  2061.                           "in the buffer n", 0, 0, 0, 0, 0, 0);
  2062.          return (ERROR);
  2063.         }
  2064.     /* store the num. of configurations, string indices locally */
  2065.     numCfg       = pDevDescr->numConfigurations;
  2066.     mfcIndex     = pDevDescr->manufacturerIndex;
  2067.     productIndex = pDevDescr->productIndex;
  2068.     printf ("DEVICE DESCRIPTOR:n");
  2069.     printf ("------------------n");
  2070.     printf (" Length                    = 0x%xn", pDevDescr->length);
  2071.     printf (" Descriptor Type           = 0x%xn", pDevDescr->descriptorType);
  2072.     printf (" USB release in BCD        = 0x%xn", pDevDescr->bcdUsb);
  2073.     printf (" Device Class              = 0x%xn", pDevDescr->deviceClass);
  2074.     printf (" Device Sub-Class          = 0x%xn", pDevDescr->deviceSubClass);
  2075.     printf (" Device Protocol           = 0x%xn", pDevDescr->deviceProtocol);
  2076.     printf (" Max Packet Size           = 0x%xn", pDevDescr->maxPacketSize0);
  2077.     printf (" Vendor ID                 = 0x%xn", pDevDescr->vendor);
  2078.     printf (" Product ID                = 0x%xn", pDevDescr->product);
  2079.     printf (" Dev release in BCD        = 0x%xn", pDevDescr->bcdDevice);
  2080.     printf (" Manufacturer              = 0x%xn", pDevDescr->manufacturerIndex);
  2081.     printf (" Product                   = 0x%xn", pDevDescr->productIndex);
  2082.     printf (" Serial Number             = 0x%xn", 
  2083.             pDevDescr->serialNumberIndex);
  2084.     printf (" Number of Configurations  = 0x%xnn", 
  2085.             pDevDescr->numConfigurations);
  2086.     /* get the manufacturer string descriptor  */     
  2087.     if (usbdDescriptorGet (usbdHandle, nodeId, 
  2088.                            USB_RT_STANDARD | USB_RT_DEVICE,
  2089.                            USB_DESCR_STRING , mfcIndex,
  2090.                            0x0409, 100, bfr, &actLength) != OK)
  2091.         {
  2092.         USB_CBI_UFI_ERR ("usbCbiUfiDescShow: Failed to read String descriptorn",
  2093.                          0, 0, 0, 0, 0, 0);
  2094.         }
  2095.     else
  2096.         {
  2097.         if ((pStrDescr = usbDescrParse (bfr, actLength, 
  2098.                                         USB_DESCR_STRING)) == NULL)
  2099.             {
  2100.             USB_CBI_UFI_ERR ("usbCbiUfiDescShow: No String descriptor was "
  2101.                              "found in the buffer n", 0, 0, 0, 0, 0, 0);
  2102.             }
  2103.         else
  2104.             {
  2105.             printf ("STRING DESCRIPTOR : %dn",1);
  2106.             printf ("----------------------n");
  2107.             printf (" Length              = 0x%xn", pStrDescr->length);
  2108.             printf (" Descriptor Type     = 0x%xn", pStrDescr->descriptorType); 
  2109.             printf (" Manufacturer String = ");  
  2110.             for (index = 0; index < (pStrDescr->length -2) ; index++)
  2111.                 printf("%c", pStrDescr->string [index]);
  2112.             printf("nn");
  2113.             }
  2114.         }  
  2115.     /* get the product string descriptor  */
  2116.     if (usbdDescriptorGet (usbdHandle, nodeId, 
  2117.                            USB_RT_STANDARD | USB_RT_DEVICE,
  2118.                            USB_DESCR_STRING , productIndex,
  2119.                            0x0409, 100, bfr, &actLength) != OK)
  2120.         {
  2121.         USB_CBI_UFI_ERR ("usbCbiUfiDescShow: Failed to read String descriptorn", 
  2122.                          0, 0, 0, 0, 0, 0);
  2123.         }
  2124.     else
  2125.         {
  2126.         if ((pStrDescr = usbDescrParse (bfr, actLength, 
  2127.                                         USB_DESCR_STRING)) == NULL)
  2128.             {
  2129.             USB_CBI_UFI_ERR ("usbCbiUfiDescShow: No String descriptor was "
  2130.                              "found in the buffer n", 0, 0, 0, 0, 0, 0);
  2131.             }
  2132.         else
  2133.             {
  2134.             printf ("STRING DESCRIPTOR : %dn",2);
  2135.             printf ("----------------------n");
  2136.             printf (" Length              = 0x%xn", pStrDescr->length);
  2137.             printf (" Descriptor Type     = 0x%xn", pStrDescr->descriptorType); 
  2138.             printf (" Product String      = ");  
  2139.             for (index = 0; index < (pStrDescr->length -2) ; index++)
  2140.                 printf("%c", pStrDescr->string [index]);
  2141.             printf("nn");
  2142.             }
  2143.         }
  2144.     /* get the configuration descriptors one by one for each configuration */
  2145.     for (index = 0; index < numCfg; index++) 
  2146.        if (usbCbiUfiConfigDescShow ( nodeId, index ) == ERROR)
  2147.           return (ERROR);
  2148.     return  (OK);
  2149.     }
  2150. /***************************************************************************
  2151. *
  2152. * usbCbiUfiConfigDescShow - shows configuration and its interface descriptors
  2153. *
  2154. *
  2155. * RETURNS: OK on success or ERROR is unable to read descriptors.
  2156. */
  2157. LOCAL STATUS usbCbiUfiConfigDescShow 
  2158.     (
  2159.     USBD_NODE_ID nodeId,         /* node ID of the device       */
  2160.     UINT8 cfgIndex               /* index of configuration      */
  2161.     )
  2162.     {
  2163.     UINT8    bfr[255];           /* store for config descriptor */
  2164.     UINT8  * pBfr = bfr;         /* pointer to the above store  */
  2165.     UINT8    ifIndex;            /* index for interfaces        */
  2166.     UINT8    epIndex;            /* index for endpoints         */
  2167.     UINT16   actLength;          /* actual length of descriptor */
  2168.     pUSB_CONFIG_DESCR pCfgDescr;    /* pointer to config'n descriptor   */
  2169.     pUSB_INTERFACE_DESCR pIntDescr; /* pointer to interface descriptor  */ 
  2170.     pUSB_ENDPOINT_DESCR pEndptDescr;/* pointer to endpointer descriptor */ 
  2171.  
  2172.     /* get the configuration descriptor */
  2173.     if (usbdDescriptorGet (usbdHandle, nodeId, 
  2174.                            USB_RT_STANDARD | USB_RT_DEVICE,
  2175.                            USB_DESCR_CONFIGURATION, cfgIndex, 0, 
  2176.                            255, bfr, &actLength) != OK)
  2177.         {
  2178.         USB_CBI_UFI_ERR ("usbCbiUfiConfigDescShow: Failed to read Config'n "
  2179.                          "descriptorn", 0, 0, 0, 0, 0, 0);
  2180.         return (ERROR);
  2181.         }
  2182.         
  2183.     if ((pCfgDescr = usbDescrParseSkip (&pBfr, &actLength, 
  2184.                                         USB_DESCR_CONFIGURATION)) == NULL)
  2185.         {
  2186.         USB_CBI_UFI_ERR ("usbCbiUfiConfigDescShow: No Config'n descriptor was found "
  2187.                          "in the buffer n", 0, 0, 0, 0, 0, 0);
  2188.         return (ERROR);
  2189.         }
  2190.     printf ("CONFIGURATION DESCRIPTOR: %dn", cfgIndex);
  2191.     printf ("----------------------------n");
  2192.     printf (" Length                    = 0x%xn", pCfgDescr->length);
  2193.     printf (" Descriptor Type           = 0x%xn", pCfgDescr->descriptorType);
  2194.     printf (" Total Length              = 0x%xn", pCfgDescr->totalLength);
  2195.     printf (" Number of Interfaces      = 0x%xn", pCfgDescr->numInterfaces);
  2196.     printf (" Configuration Value       = 0x%xn", pCfgDescr->configurationValue);
  2197.     printf (" Configuration Index       = 0x%xn", pCfgDescr->configurationIndex);
  2198.     printf (" Attributes                = 0x%xn", pCfgDescr->attributes);
  2199.     printf (" Maximum Power             = 0x%xnn", pCfgDescr->maxPower);
  2200.     /* Parse for the interface and its related endpoint descriptors */   
  2201.     for (ifIndex = 0; ifIndex < pCfgDescr->numInterfaces; ifIndex++)
  2202.         {
  2203.         if ((pIntDescr = usbDescrParseSkip (&pBfr, &actLength, 
  2204.                                             USB_DESCR_INTERFACE)) == NULL)
  2205.             {
  2206.             USB_CBI_UFI_ERR ("usbCbiUfiConfigDescShow: No Interface descriptor "
  2207.                              "was found n", 0, 0, 0, 0, 0, 0);
  2208.             return (ERROR);
  2209.             }
  2210.         printf ("INTERFACE DESCRIPTOR: %dn", ifIndex);
  2211.         printf ("-----------------------n");
  2212.         printf (" Length                    = 0x%xn", pIntDescr->length);
  2213.         printf (" Descriptor Type           = 0x%xn", pIntDescr->descriptorType);
  2214.         printf (" Interface Number          = 0x%xn", pIntDescr->interfaceNumber);
  2215.         printf (" Alternate setting         = 0x%xn", 
  2216.                 pIntDescr->alternateSetting);
  2217.         printf (" Number of Endpoints       = 0x%xn", pIntDescr->numEndpoints) ;
  2218.         printf (" Interface Class           = 0x%xn", 
  2219.                 pIntDescr->interfaceClass);
  2220.         printf (" Interface Sub-Class       = 0x%xn", 
  2221.                 pIntDescr->interfaceSubClass);
  2222.         printf (" Interface Protocol        = 0x%xn", 
  2223.                 pIntDescr->interfaceProtocol);
  2224.         printf (" Interface Index           = 0x%xnn", pIntDescr->interfaceIndex); 
  2225.         
  2226.         for ( epIndex = 0; epIndex < pIntDescr->numEndpoints; epIndex++)
  2227.             { 
  2228.             if ((pEndptDescr = usbDescrParseSkip (&pBfr, &actLength, 
  2229.                                                   USB_DESCR_ENDPOINT)) == NULL)
  2230.                 {
  2231.                 USB_CBI_UFI_ERR ("usbCbiUfiConfigDescShow: No Endpoint descriptor" 
  2232.                                  "was found n", 0, 0, 0, 0, 0, 0);
  2233.                 return (ERROR);
  2234.                 }
  2235.             printf ("ENDPOINT DESCRIPTOR: %dn", epIndex);
  2236.             printf ("-----------------------n");
  2237.             printf (" Length                    = 0x%xn", pEndptDescr->length);
  2238.             printf (" Descriptor Type           = 0x%xn", 
  2239.                     pEndptDescr->descriptorType);
  2240.             printf (" Endpoint Address          = 0x%xn", 
  2241.                     pEndptDescr->endpointAddress);
  2242.             printf (" Attributes                = 0x%xn", 
  2243.                     pEndptDescr->attributes);
  2244.             printf (" Max Packet Size           = 0x%xn", 
  2245.                     pEndptDescr->maxPacketSize);
  2246.             printf (" Interval                  = 0x%xnn", 
  2247.                     pEndptDescr->interval);
  2248.             }
  2249.         }
  2250.   
  2251.     return (OK);
  2252.     }