static s32 __usbstorage_clearerrors(usbstorage_handle *dev, u8 lun) { s32 retval; u8 cmd[16]; u8 *sense= USB_Alloc(SCSI_SENSE_REPLY_SIZE); u8 status = 0; memset(cmd, 0, sizeof(cmd)); cmd[0] = SCSI_TEST_UNIT_READY; retval = __cycle(dev, lun, NULL, 0, cmd, 1, 1, &status, NULL); if(retval < 0) return retval; if(status != 0) { cmd[0] = SCSI_REQUEST_SENSE; cmd[1] = lun << 5; cmd[4] = SCSI_SENSE_REPLY_SIZE; cmd[5] = 0; memset(sense, 0, SCSI_SENSE_REPLY_SIZE); retval = __cycle(dev, lun, sense, SCSI_SENSE_REPLY_SIZE, cmd, 6, 0, NULL, NULL); if(retval < 0) goto error; status = sense[2] & 0x0F; if(status == SCSI_SENSE_NOT_READY || status == SCSI_SENSE_MEDIUM_ERROR || status == SCSI_SENSE_HARDWARE_ERROR) retval = USBSTORAGE_ESENSE; } error: USB_Free(sense); return retval; }
static s32 __usbstorage_clearerrors(struct ehci_hcd * ehci, usbstorage_handle *dev, u8 lun) { s32 retval; u8 cmd[16]; u8 *sense = USB_Alloc(SCSI_SENSE_REPLY_SIZE); u8 status = 0; memset(cmd, 0, sizeof (cmd)); cmd[0] = SCSI_TEST_UNIT_READY; int n; if (!sense) return -ENOMEM; for (n = 0; n < 5; n++) { retval = __cycle(ehci, dev, lun, NULL, 0, cmd, 6, 1, &status, NULL); #ifdef MEM_PRINT s_printf(" SCSI_TEST_UNIT_READY %i# ret %i\n", n, retval); #endif if (retval == -ENODEV) goto error; if (retval == 0) break; } if (retval < 0) goto error; if (status != 0) { cmd[0] = SCSI_REQUEST_SENSE; cmd[1] = lun << 5; cmd[4] = SCSI_SENSE_REPLY_SIZE; cmd[5] = 0; memset(sense, 0, SCSI_SENSE_REPLY_SIZE); retval = __cycle(ehci, dev, lun, sense, SCSI_SENSE_REPLY_SIZE, cmd, 6, 0, NULL, NULL); #ifdef MEM_PRINT s_printf(" SCSI_REQUEST_SENSE ret %i\n", retval); #endif if (retval < 0) goto error; status = sense[2] & 0x0F; #ifdef MEM_PRINT s_printf(" SCSI_REQUEST_SENSE status %x\n", status); #endif if (status == SCSI_SENSE_NOT_READY || status == SCSI_SENSE_MEDIUM_ERROR || status == SCSI_SENSE_HARDWARE_ERROR) retval = USBSTORAGE_ESENSE; } error: USB_Free(sense); return retval; }
s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd) { dev->ep_in = bulkInNumber; dev->ep_out = bulkOutNumber; dev->max_lun = fMaxLogicalUnitNumber; dev->altInterface = gAlt_Interface; dev->interface = gInterface; dev->buffer = USB_Alloc(512); return 0; }
s32 USBStorage_Inquiry(usbstorage_handle *dev, u8 lun) { s32 retval; u8 cmd[] = {SCSI_INQUIRY, lun << 5,0,0,36,0}; u8 *response = USB_Alloc(36); USB_LOG("Inquiring about SCSI drive\n"); retval = __cycle(dev, lun, response, 36, cmd, 6, 0, NULL, NULL); //print_hex_dump_bytes("inquiry result:",DUMP_PREFIX_OFFSET,response,36); USB_Free(response); return retval; }
s32 USBStorage_Inquiry(struct ehci_hcd * ehci, usbstorage_handle *dev, u8 lun) { s32 retval; u8 cmd[] = {SCSI_INQUIRY, lun << 5, 0, 0, 36, 0}; u8 *response = USB_Alloc(36); if (!response) return -ENOMEM; retval = __cycle(ehci, dev, lun, response, 36, cmd, 6, 0, NULL, NULL); //print_hex_dump_bytes("inquiry result:",DUMP_PREFIX_OFFSET,response,36); USB_Free(response); return retval; }
void init_thread_ehci(void) { disable_EHCI_IRQ(); ehci1_queuehandle= os_message_queue_create( USB_Alloc(4*32)/*os_heap_alloc(heaphandle, 4*32)*/, 32); os_unregister_event_handler(DEV_EHCI); os_register_event_handler(DEV_EHCI, ehci1_queuehandle, 0); // register interrupt event handler enable_EHCI_IRQ(); os_software_IRQ(DEV_EHCI); }
s32 USB_GetConfiguration(struct ehci_hcd * ehci,struct ehci_device *fd, u8 *configuration) { u8 *_configuration; s32 retval; _configuration = USB_Alloc( 1); if(_configuration == NULL) return -ENOMEM; retval = __usb_control_message(ehci, fd, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_DEVICE), USB_REQ_GETCONFIG, 0, 0, 1, _configuration, NULL, NULL); if(retval >= 0) *configuration = *_configuration; USB_Free( _configuration); return retval; }
s32 USBStorage_ReadCapacity(struct ehci_hcd * ehci, usbstorage_handle *dev, u8 lun, u32 *sector_size, u32 *n_sectors) { s32 retval; u8 cmd[] = {SCSI_READ_CAPACITY, lun << 5}; u8 *response = USB_Alloc(8); u32 val; if (!response) return -ENOMEM; retval = __cycle(ehci, dev, lun, response, 8, cmd, 2, 0, NULL, NULL); if (retval >= 0) { memcpy(&val, response, 4); if (n_sectors != NULL) *n_sectors = be32_to_cpu(val); memcpy(&val, response + 4, 4); if (sector_size != NULL) *sector_size = be32_to_cpu(val); retval = USBSTORAGE_OK; } USB_Free(response); return retval; }
s32 USB_GetDescriptors(struct ehci_hcd * ehci,struct ehci_device * fd, usb_devdesc *udd) { u8 *buffer = NULL; u8 *ptr = NULL; usb_configurationdesc *ucd = NULL; usb_interfacedesc *uid = NULL; usb_endpointdesc *ued = NULL; s32 retval = 0; u32 size,i; u32 iConf, iInterface, iEndpoint; buffer = USB_Alloc(sizeof(*udd)); if(buffer == NULL) { retval = -ENOMEM; goto free_and_error; } retval = __usb_getdesc(ehci, fd, buffer, USB_DT_DEVICE, 0, USB_DT_DEVICE_SIZE); if(retval < 0) goto free_and_error; memcpy(udd, buffer, USB_DT_DEVICE_SIZE); USB_Free(buffer); udd->bcdUSB = cpu_to_le16(udd->bcdUSB); udd->idVendor = cpu_to_le16(udd->idVendor); udd->idProduct = cpu_to_le16(udd->idProduct); udd->bcdDevice = cpu_to_le16(udd->bcdDevice); udd->configurations = USB_Alloc(udd->bNumConfigurations* sizeof(*udd->configurations)); if(udd->configurations == NULL) { retval = -ENOMEM; goto free_and_error; } memset(udd->configurations,0,udd->bNumConfigurations* sizeof(*udd->configurations)); for(iConf = 0; iConf < udd->bNumConfigurations; iConf++) { buffer = USB_Alloc( USB_DT_CONFIG_SIZE); if(buffer == NULL) { retval = -ENOMEM; goto free_and_error; } retval = __usb_getdesc(ehci, fd, buffer, USB_DT_CONFIG, iConf, USB_DT_CONFIG_SIZE); ucd = &udd->configurations[iConf]; memcpy(ucd, buffer, USB_DT_CONFIG_SIZE); USB_Free( buffer); ucd->wTotalLength = cpu_to_le16(ucd->wTotalLength); size = ucd->wTotalLength; buffer = USB_Alloc( ucd->wTotalLength); if(buffer == NULL) { retval = -ENOMEM; goto free_and_error; } retval = __usb_getdesc(ehci, fd, buffer, USB_DT_CONFIG, iConf, ucd->wTotalLength); if(retval < 0) goto free_and_error; ptr = buffer; ptr += ucd->bLength; size -= ucd->bLength; retval = -ENOMEM; ucd->interfaces = USB_Alloc(ucd->bNumInterfaces* sizeof(*ucd->interfaces)); if(ucd->interfaces == NULL) goto free_and_error; memset(ucd->interfaces,0,ucd->bNumInterfaces* sizeof(*ucd->interfaces)); for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; memcpy(uid, ptr, USB_DT_INTERFACE_SIZE); ptr += uid->bLength; size -= uid->bLength; uid->endpoints = USB_Alloc(uid->bNumEndpoints* sizeof(*uid->endpoints)); if(uid->endpoints == NULL) goto free_and_error; memset(uid->endpoints,0,uid->bNumEndpoints* sizeof(*uid->endpoints)); // This skips vendor and class specific descriptors i = __find_next_endpoint(ptr, size); uid->extra_size = i; if(i>0) { uid->extra = USB_Alloc(i); if(uid->extra == NULL) goto free_and_error; memcpy(uid->extra, ptr, i); ptr += i; size -= i; } for(iEndpoint = 0; iEndpoint < uid->bNumEndpoints; iEndpoint++) { ued = &uid->endpoints[iEndpoint]; memcpy(ued, ptr, USB_DT_ENDPOINT_SIZE); ptr += ued->bLength; ued->wMaxPacketSize = cpu_to_le16(ued->wMaxPacketSize); } } USB_Free( buffer); buffer = NULL; } retval = 0; free_and_error: if(buffer != NULL) USB_Free(buffer); if(retval < 0) USB_FreeDescriptors(udd); return retval; }
s32 USBStorage_Open(ehci_device_data * device_data) { s32 retval = -1; u8 conf, *max_lun = NULL; u32 iConf, iInterface, iEp; static usb_devdesc udd; usb_configurationdesc *ucd; usb_interfacedesc *uid; usb_endpointdesc *ued; struct ehci_hcd * ehci = device_data->__ehci; usbstorage_handle *dev = &device_data->__usbfd; struct ehci_device *fd = device_data->__dev; device_data->__lun = 16; // select bad LUN max_lun = USB_Alloc(1); if (max_lun == NULL) return -ENOMEM; memset(dev, 0, sizeof (*dev)); dev->tag = TAG_START; dev->usb_fd = fd; retval = USB_GetDescriptors(ehci, dev->usb_fd, &udd); #ifdef MEM_PRINT s_printf("USBStorage_Open(): USB_GetDescriptors %i\n", retval); #ifdef MEM_PRINT log_status(ehci, "after USB_GetDescriptors"); #endif #endif if (retval < 0) goto free_and_return; /* // test device changed without unmount (prevent device write corruption) if (ums_init_done) { if (my_memcmp((void *) &_old_udd, (void *) &udd, sizeof (usb_devdesc) - 4)) { USB_Free(max_lun); USB_FreeDescriptors(&udd); #ifdef MEM_PRINT s_printf("USBStorage_Open(): device changed!!!\n"); #endif return -ENODEV; } } */ _old_udd = udd; try_status = -128; for (iConf = 0; iConf < udd.bNumConfigurations; iConf++) { ucd = &udd.configurations[iConf]; for (iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; // debug_printf("interface %d, class:%x subclass %x protocol %x\n",iInterface,uid->bInterfaceClass,uid->bInterfaceSubClass, uid->bInterfaceProtocol); if (uid->bInterfaceClass == USB_CLASS_MASS_STORAGE && (uid->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_RBC_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_ATA_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_QIC_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_UFI_COMMANDS || uid->bInterfaceSubClass == MASS_STORAGE_SFF8070_COMMANDS) && uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY && uid->bNumEndpoints >= 2) { dev->ata_protocol = 0; if (uid->bInterfaceSubClass != MASS_STORAGE_SCSI_COMMANDS || uid->bInterfaceSubClass != MASS_STORAGE_RBC_COMMANDS) dev->ata_protocol = 1; #ifdef MEM_PRINT s_printf("USBStorage_Open(): interface subclass %i ata_prot %i \n", uid->bInterfaceSubClass, dev->ata_protocol); #endif dev->ep_in = dev->ep_out = 0; for (iEp = 0; iEp < uid->bNumEndpoints; iEp++) { ued = &uid->endpoints[iEp]; if (ued->bmAttributes != USB_ENDPOINT_BULK) continue; if (ued->bEndpointAddress & USB_ENDPOINT_IN) dev->ep_in = ued->bEndpointAddress; else dev->ep_out = ued->bEndpointAddress; } if (dev->ep_in != 0 && dev->ep_out != 0) { dev->configuration = ucd->bConfigurationValue; dev->interface = uid->bInterfaceNumber; dev->altInterface = uid->bAlternateSetting; goto found; } } else { if (uid->endpoints != NULL) USB_Free(uid->endpoints); uid->endpoints = NULL; if (uid->extra != NULL) USB_Free(uid->extra); uid->extra = NULL; if (uid->bInterfaceClass == USB_CLASS_HUB) { retval = USBSTORAGE_ENOINTERFACE; try_status = -20000; USB_FreeDescriptors(&udd); goto free_and_return; } if (uid->bInterfaceClass == USB_CLASS_MASS_STORAGE && uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY && uid->bNumEndpoints >= 2) { try_status = -(10000 + uid->bInterfaceSubClass); } } } } #ifdef MEM_PRINT s_printf("USBStorage_Open(): cannot find any interface!!!\n"); #endif USB_FreeDescriptors(&udd); retval = USBSTORAGE_ENOINTERFACE; debug_printf("cannot find any interface\n"); goto free_and_return; found: USB_FreeDescriptors(&udd); retval = USBSTORAGE_EINIT; try_status = -1201; #ifdef MEM_PRINT s_printf("USBStorage_Open(): conf: %x altInterface: %x\n", dev->configuration, dev->altInterface); #endif if (USB_GetConfiguration(ehci, dev->usb_fd, &conf) < 0) goto free_and_return; try_status = -1202; #ifdef MEM_PRINT log_status(ehci, "after USB_GetConfiguration"); #endif #ifdef MEM_PRINT if (conf != dev->configuration) s_printf("USBStorage_Open(): changing conf from %x\n", conf); #endif if (/*conf != dev->configuration &&*/ USB_SetConfiguration(ehci, dev->usb_fd, dev->configuration) < 0) goto free_and_return; try_status = -1203; if (dev->altInterface != 0 && USB_SetAlternativeInterface(ehci, dev->usb_fd, dev->interface, dev->altInterface) < 0) goto free_and_return; try_status = -1204; #ifdef MEM_PRINT log_status(ehci, "Before USBStorage_Reset"); #endif retval = USBStorage_Reset(ehci, dev); #ifdef MEM_PRINT log_status(ehci, "After USBStorage_Reset"); #endif if (retval < 0) goto free_and_return; /* retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_GET_MAX_LUN, 0, dev->interface, 1, max_lun); if(retval < 0 ) dev->max_lun = 1; else dev->max_lun = (*max_lun+1); if(retval == USBSTORAGE_ETIMEDOUT)*/ /* NOTE: from usbmassbulk_10.pdf "Devices that do not support multiple LUNs may STALL this command." */ dev->max_lun = 8; // max_lun can be from 1 to 16, but some devices do not support lun retval = USBSTORAGE_OK; /*if(dev->max_lun == 0) dev->max_lun++;*/ /* taken from linux usbstorage module (drivers/usb/storage/transport.c) */ /* * Some devices (i.e. Iomega Zip100) need this -- apparently * the bulk pipes get STALLed when the GetMaxLUN request is * processed. This is, in theory, harmless to all other devices * (regardless of if they stall or not). */ //USB_ClearHalt(dev->usb_fd, dev->ep_in); //USB_ClearHalt(dev->usb_fd, dev->ep_out); dev->buffer = USB_Alloc(MAX_TRANSFER_SIZE + 16); if (dev->buffer == NULL) { retval = -ENOMEM; try_status = -1205; } else retval = USBSTORAGE_OK; free_and_return: if (max_lun != NULL) USB_Free(max_lun); if (retval < 0) { if (dev->buffer != NULL) USB_Free(dev->buffer); memset(dev, 0, sizeof (*dev)); #ifdef MEM_PRINT s_printf("USBStorage_Open(): try_status %i\n", try_status); #endif return retval; } #ifdef MEM_PRINT s_printf("USBStorage_Open(): return 0\n"); #endif return 0; }
s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd) { s32 retval = -1; u8 conf,*max_lun = NULL; u32 iConf, iInterface, iEp; usb_devdesc udd; usb_configurationdesc *ucd; usb_interfacedesc *uid; usb_endpointdesc *ued; max_lun = USB_Alloc(1); if(max_lun==NULL) return -ENOMEM; memset(dev, 0, sizeof(*dev)); dev->tag = TAG_START; dev->usb_fd = fd; retval = USB_GetDescriptors(dev->usb_fd, &udd); if(retval < 0) goto free_and_return; for(iConf = 0; iConf < udd.bNumConfigurations; iConf++) { ucd = &udd.configurations[iConf]; for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) { uid = &ucd->interfaces[iInterface]; if(uid->bInterfaceClass == USB_CLASS_MASS_STORAGE && uid->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS && uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY) { if(uid->bNumEndpoints < 2) continue; dev->ep_in = dev->ep_out = 0; for(iEp = 0; iEp < uid->bNumEndpoints; iEp++) { ued = &uid->endpoints[iEp]; if(ued->bmAttributes != USB_ENDPOINT_BULK) continue; if(ued->bEndpointAddress & USB_ENDPOINT_IN) dev->ep_in = ued->bEndpointAddress; else dev->ep_out = ued->bEndpointAddress; } if(dev->ep_in != 0 && dev->ep_out != 0) { dev->configuration = ucd->bConfigurationValue; dev->interface = uid->bInterfaceNumber; dev->altInterface = uid->bAlternateSetting; goto found; } } } } USB_FreeDescriptors(&udd); retval = USBSTORAGE_ENOINTERFACE; goto free_and_return; found: USB_FreeDescriptors(&udd); retval = USBSTORAGE_EINIT; if(USB_GetConfiguration(dev->usb_fd, &conf) < 0) goto free_and_return; if(conf != dev->configuration && USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0) goto free_and_return; if(dev->altInterface != 0 && USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0) goto free_and_return; dev->suspended = 0; retval = USBStorage_Reset(dev); if(retval < 0) goto free_and_return; retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_GET_MAX_LUN, 0, dev->interface, 1, max_lun); if(retval < 0) dev->max_lun = 1; else dev->max_lun = *max_lun; if(retval == USBSTORAGE_ETIMEDOUT) goto free_and_return; retval = USBSTORAGE_OK; if(dev->max_lun == 0) dev->max_lun++; /* taken from linux usbstorage module (drivers/usb/storage/transport.c) */ /* * Some devices (i.e. Iomega Zip100) need this -- apparently * the bulk pipes get STALLed when the GetMaxLUN request is * processed. This is, in theory, harmless to all other devices * (regardless of if they stall or not). */ USB_ClearHalt(dev->usb_fd, dev->ep_in); USB_ClearHalt(dev->usb_fd, dev->ep_out); dev->buffer = USB_Alloc(MAX_TRANSFER_SIZE); if(dev->buffer == NULL) retval = -ENOMEM; else retval = USBSTORAGE_OK; free_and_return: if(max_lun!=NULL) USB_Free(max_lun); if(retval < 0) { if(dev->buffer != NULL) USB_Free(dev->buffer); memset(dev, 0, sizeof(*dev)); return retval; } return 0; }