/******************************************************************************* NAME $RCSfile: usbConfig.c,v $ SUMMARY USB device Test Library VERSION $Revision: 1.1 $ UPDATE DATE $Date: 2009/07/14 03:39:28 $ PROGRAMMER $Author: lecter $ Copyright 2009 LSI Corporation. All Rights Reserved. DESCRIPTION: The functions used to diagnose usb device REFERENCE: *******************************************************************************/ #define __SRCusbLib /*** INCLUDES ***/ #include #include #include #include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) #include #else #include #endif #include #include "usbStruct.h" #include "commPattern.h" #include "commRpt.h" #include "commSCSI.h" /*** EXTERNAL REFERENCES ***/ EXTERN UINT8 gExpUSBFlashDeviceNum; extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); /*** FORWARD REFERENCES ***/ LOCAL BOOLEAN usbDiagGetUSData(USBCB *pUCB); PUBLIC VOID usbShowAllDevice(VOID); /*** PROCEDURES ***/ /******************************************************************************* * PROCEDURE * * NAME: usbGetFlashDeviceList * SUMMARY: Get the flash devices list for USB test * SCOPE: public * * DESCRIPTION: This function scan the devices located on the USB bus and build the list for USB test * * RETURNS: * * NOTES: * */ PUBLIC VOID usbGetFlashDeviceList(struct list_head *pFlashDevList, UINT8 testItemCode) { USBCB *pUCB; struct usb_bus *pBus; struct usb_device *pUSBHub; struct usb_device *pUSBDev; struct usb_device *pUSBSubDev; UINT8 idxUSBDev; UINT8 idxSubUSBDev; UINT8 numFlashDevice = 0; mutex_lock(&usb_bus_list_lock); list_for_each_entry(pBus, &usb_bus_list, bus_list) { if (!pBus->root_hub) continue; usb_lock_device(pBus->root_hub); pUSBHub = pBus->root_hub; for(idxUSBDev = 0; idxUSBDev < pUSBHub->maxchild; ++idxUSBDev) { pUSBDev = pUSBHub->children[idxUSBDev]; if(pUSBDev) { pUCB = (USBCB *)kmalloc(sizeof(USBCB), GFP_KERNEL); pUCB->pUSBDev = pUSBDev; pUCB->pUSData = NULL; if(usbDiagGetUSData(pUCB)) { list_add_tail(&pUCB->nodeUCB, pFlashDevList); numFlashDevice++; usb_put_dev(pUCB->pUSBDev); } else { kfree(pUCB); for(idxSubUSBDev = 0; idxSubUSBDev < pUSBDev->maxchild; ++idxSubUSBDev) { pUSBSubDev = pUSBDev->children[idxSubUSBDev]; if(pUSBSubDev) { pUCB = (USBCB *)kmalloc(sizeof(USBCB), GFP_KERNEL); pUCB->pUSBDev = pUSBSubDev; pUCB->pUSData = NULL; if(usbDiagGetUSData(pUCB)) { list_add_tail(&pUCB->nodeUCB, pFlashDevList); numFlashDevice++; usb_put_dev(pUCB->pUSBDev); } else { kfree(pUCB); } } } } } } usb_unlock_device(pBus->root_hub); } mutex_unlock(&usb_bus_list_lock); if(numFlashDevice < gExpUSBFlashDeviceNum) { commReportError(MEC_COMP_CODE_TEMP, testItemCode, USB_DIAG_ERROR_CODE_DEVICE_DETECT_FAILED, USB_DIAG_ERROR_MSG_DEVICE_DETECT_FAILED, gExpUSBFlashDeviceNum, numFlashDevice, 0, DG_PCH_MSG_FORMAT); } } /******************************************************************************* * PROCEDURE * * NAME: usbDiagGetUSData * SUMMARY: Get Flash data information for USB test * SCOPE: public * * DESCRIPTION: This function use to get the diagnostic USB data * * RETURNS: * * NOTES: * */ LOCAL BOOLEAN usbDiagGetUSData(USBCB *pUCB) { UINT8 ixdUSBIntf; struct usb_interface* pUSBIntf; struct usb_host_interface* pUSBHostInf; struct usb_interface_descriptor* pUSBInfDesc; BOOLEAN rcCode = FALSE; usb_lock_device(pUCB->pUSBDev); usb_get_dev(pUCB->pUSBDev); for(ixdUSBIntf = 0; ixdUSBIntf < pUCB->pUSBDev->actconfig->desc.bNumInterfaces; ixdUSBIntf++) { pUSBIntf = pUCB->pUSBDev->actconfig->interface[ixdUSBIntf]; if(pUSBIntf) { pUSBHostInf = &pUSBIntf->cur_altsetting[0]; pUSBInfDesc = &pUSBHostInf->desc; if((pUSBInfDesc->bInterfaceClass == USB_STORAGE_INTERFACE_CLASS) &&(pUSBInfDesc->bInterfaceSubClass == USB_STORAGE_INTERFACE_SUB_CLASS)) { pUCB->pUSData = (struct us_data *)usb_get_intfdata(pUSBIntf); rcCode = TRUE; } } } usb_unlock_device(pUCB->pUSBDev); return rcCode; } /******************************************************************************* * PROCEDURE * * NAME: usbResetUSBDevice * SUMMARY: Reset USB device * SCOPE: public * * DESCRIPTION: This function reset USB device by issuing reset command * * RETURNS: * * NOTES: * */ PUBLIC VOID usbResetUSBDevice(USBCB *pUCB) { int result; result = 0; scsi_lock(us_to_host(pUCB->pUSData)); set_bit(US_FLIDX_RESETTING, &pUCB->pUSData->dflags); clear_bit(US_FLIDX_ABORTING, &pUCB->pUSData->dflags); scsi_unlock(us_to_host(pUCB->pUSData)); /* We must release the device lock because the pre_reset routine * will want to acquire it. */ mutex_unlock(&pUCB->pUSData->dev_mutex); //result = usb_stor_port_reset(pUCB->pUSData); mutex_lock(&pUCB->pUSData->dev_mutex); if (result < 0) { scsi_lock(us_to_host(pUCB->pUSData)); //usb_stor_report_device_reset(pUCB->pUSData); scsi_unlock(us_to_host(pUCB->pUSData)); pUCB->pUSData->transport_reset(pUCB->pUSData); } clear_bit(US_FLIDX_RESETTING, &pUCB->pUSData->dflags); msleep(30); } /******************************************************************************* * PROCEDURE * * NAME: usbTransferVerify * SUMMARY: Verify USB transfer result * SCOPE: public * * DESCRIPTION: This function verify the content that transfered by USB * * RETURNS: * * NOTES: * */ PUBLIC BOOLEAN usbTransferVerify(VOID *pSrcBuf, VOID *pDstBuf, UINT32 length) { UINT8* pVerifySrc; UINT8* pVerifyDest; pVerifySrc = (UINT8 *)pSrcBuf; pVerifyDest = (UINT8 *)pDstBuf; while(length) { if( (length >= sizeof(UINT32)) && ((UINT64)pVerifySrc % sizeof(UINT32)) == 0 ) { if(*((UINT32 *)pVerifySrc) != *((UINT32 *)pVerifyDest) ) { pSrcBuf = (VOID *)pVerifySrc; pDstBuf = (VOID *)pVerifyDest; return FALSE; } pVerifySrc+=sizeof(UINT32); pVerifyDest+=sizeof(UINT32); length-=sizeof(UINT32); } else { if(*pVerifySrc != *pVerifyDest ) { pSrcBuf = (VOID *)pVerifySrc; pDstBuf = (VOID *)pVerifyDest; return FALSE; } pVerifySrc++; pVerifyDest++; length--; } } return TRUE; } /******************************************************************************* * PROCEDURE * * NAME: usbShowCapacity * SUMMARY: Show the capacity of a USB devices * SCOPE: public * * DESCRIPTION: Show the capacity of a USB devices * * RETURNS: * * NOTES: * */ LOCAL VOID usbShowCapacity(USBCB *pUCB) { struct Scsi_Host *pSHost; struct scsi_device *pSDev; UINT8 buffer[16]; INT32 rcUSB; INT32 sizeSector = 0; sector_t numSector = 0; pSHost = us_to_host(pUCB->pUSData); shost_for_each_device(pSDev, pSHost) { rcUSB = scsiReadCapacity(pSDev, buffer); if(!rcUSB) { sizeSector = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; numSector = (((sector_t)buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]) + 1; printk("sector_size: %u sector_num: %u\n", (UINT32)sizeSector, (UINT32)numSector); } } } /******************************************************************************* * PROCEDURE * * NAME: usbAllUSBDevice * SUMMARY: Show all the USB devices * SCOPE: public * * DESCRIPTION: This function show all the devices on the USB bus * * RETURNS: * * NOTES: * */ PUBLIC VOID usbShowAllDevice(VOID) { USBCB* pUCB; struct list_head *pBusList; struct usb_bus *pBus; struct usb_device *pUSBHub; struct usb_device *pUSBDev; struct usb_interface *pUSBIntf; UINT8 idx; pUCB = (USBCB *)kmalloc(sizeof(USBCB), GFP_KERNEL); mutex_lock(&usb_bus_list_lock); for (pBusList = usb_bus_list.next; pBusList != &usb_bus_list; pBusList = pBusList->next) { pBus = container_of(pBusList, struct usb_bus, bus_list); if (!pBus->root_hub) continue; usb_lock_device(pBus->root_hub); pUSBHub = pBus->root_hub; printk("Hub: idVender %x idProduct %x %x %x\n", pUSBHub->descriptor.idVendor, pUSBHub->descriptor.idProduct, pUSBHub->descriptor.bcdUSB, pUSBHub->descriptor.bDeviceProtocol); for(idx = 0; idx < pUSBHub->maxchild; idx++) { pUSBDev = pUSBHub->children[idx]; if(pUSBDev) { pUCB->pUSBDev = pUSBDev; pUSBIntf = pUCB->pUSBDev->actconfig->interface[0]; pUCB->pUSData = (struct us_data *)usb_get_intfdata(pUSBIntf); usb_lock_device(pUCB->pUSBDev); printk("Device: idVender %x idProduct %x\n", pUSBDev->descriptor.idVendor, pUSBDev->descriptor.idProduct); usbShowCapacity(pUCB); usb_put_dev(pUCB->pUSBDev); usb_unlock_device(pUCB->pUSBDev); } } usb_unlock_device(pBus->root_hub); } mutex_unlock(&usb_bus_list_lock); kfree(pUCB); }