📄 usbd_scsi.c
字号:
return;}void usbd_scsi_com_modesense_flexible(usbd_mass_instance *ma){ switch (ma->cbw.CBWCB[2] & 0xc0) { case 0x00: /* current */ case 0x80: /* default */ ma->buff[ma->buff_ptr++] = 0x05; /* page 5 */ ma->buff[ma->buff_ptr++] = 0x1e; /* length */ ma->buff[ma->buff_ptr++] = 0x0f; /* Transfer rate = 0x0fa0 */ ma->buff[ma->buff_ptr++] = 0xa0; ma->buff[ma->buff_ptr++] = ma->media.NoOfHead; ma->buff[ma->buff_ptr++] = ma->media.SectorPerTrack; ma->buff[ma->buff_ptr++] = (unsigned char)((ma->media.BytePerSector & 0xff00) >> 8); ma->buff[ma->buff_ptr++] = (unsigned char)(ma->media.BytePerSector & 0xff); ma->buff[ma->buff_ptr++] = (unsigned char)((ma->media.NoOfCylinder & 0xff00) >> 8); ma->buff[ma->buff_ptr++] = (unsigned char)(ma->media.NoOfCylinder & 0xff); ma->buff_ptr += 0x16; break; default: /* changeable */ ma->buff[ma->buff_ptr++] = 0x05; /* page 5 */ ma->buff[ma->buff_ptr++] = 0x1e; /* length */ ma->buff_ptr += 0x1e; break; } return;}char usbd_scsi_com_inquiry(usbd_mass_instance *ma){ unsigned char len; debugvs(1, "%s : %s - SCSI Inquiry\n", __FILE__, __FUNCTION__); if (ma->cbw.CBWCB[1] & 0x01) { usbd_scsi_set_error(ma, SCSI_ERROR_InvalidFieldCdb, 0); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; } usbd_scsi_clear_buff(ma); ma->buff[0] = 0; /* Direct-access device */ ma->buff[1] = 0x80; /* Removable deice */ ma->buff[2] = 2; /* Version - ANSI X3.131:1994 (SCSI-2) */ ma->buff[3] = 2; /* Response data format - Standard */ ma->buff[4] = 0x5b; /* Additional length */ ma->buff[5] = 0; /* Not support SCC */ usbd_scsi_strcpy(&ma->buff[8], SCSI_STRING_MANUFACTURER, 28); len = ma->cbw.CBWCB[4]; if (len > 0x60) len = 0x60; ma->buff_length = len; return usbd_scsi_command_end_send(ma);}char usbd_scsi_com_readformatcapacities(usbd_mass_instance *ma){ unsigned long lba; debugvs(1, "%s : %s - SCSI ReadFormatCapacities\n", __FILE__, __FUNCTION__); usbd_media_probe(ma); if (ma->media.status == ABSENT) { usbd_scsi_set_error(ma, SCSI_ERROR_MediumNotPresent, 0); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; } lba = ma->media.total_sector - 1; usbd_scsi_put_bigendian(ma->buff, 0, 4); /* Capacity List Header */ usbd_scsi_put_bigendian(ma->buff + 4, lba, 4); /* Number of Blocks */ ma->buff[8] = 0x02; /* Descriptor type = Foratted Media */ usbd_scsi_put_bigendian(ma->buff + 9, 0x200, 3); /* Block Length */ ma->buff_ptr = 0; ma->buff_length = 12; debugvs(2, "%s : %s - SCSI ReadFormatCapacities : Report %ld Sectors\n", __FILE__, __FUNCTION__, lba); return usbd_scsi_command_end_send(ma);}char usbd_scsi_com_readcapacity(usbd_mass_instance *ma){ unsigned long lba; debugvs(1, "%s : %s - SCSI ReadCapacity\n", __FILE__, __FUNCTION__); usbd_media_probe(ma); if (ma->media.status == ABSENT) { usbd_scsi_set_error(ma, SCSI_ERROR_MediumNotPresent, 0); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; } debugvs(2, "%s : %s - SCSI ReadCapacity PMI %d\n", __FILE__, __FUNCTION__, ma->cbw.CBWCB[8] & 0x01); if (ma->cbw.CBWCB[8] & 0x01) {/* PMI == 1 */ lba = usbd_scsi_get_bigendian(&ma->cbw.CBWCB[2], 4); if (!usbd_scsi_check_lba(ma, lba)) { ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; } } else {/* PMI == 0 */ lba = ma->media.total_sector - 1; } usbd_scsi_put_bigendian(ma->buff, lba, 4); usbd_scsi_put_bigendian(ma->buff + 4, 0x200, 4); ma->buff_ptr = 0; ma->buff_length = 8; debugvs(2, "%s : %s - SCSI ReadCapacity : Report %ld Sectors\n", __FILE__, __FUNCTION__, lba); return usbd_scsi_command_end_send(ma);}char usbd_scsi_com_read(usbd_mass_instance *ma){ unsigned short cnt; char ret; debugvs(1, "%s : %s - SCSI Read\n", __FILE__, __FUNCTION__); ma->state = MASS_TRANS; ret = usbd_scsi_check_media(ma); if (ret != CSW_STATUS_CommandPassed) { ma->state = SEND_CSW; return ret; } if (ma->cbw.CBWCB[0] == SCSI_ComRead6) { ma->lba = (usbd_scsi_get_bigendian(&ma->cbw.CBWCB[1], 3) & 0x1fffff); ma->req_sector_count = ma->cbw.CBWCB[4]; if (!ma->req_sector_count) ma->req_sector_count = 0x100; } else { ma->lba = usbd_scsi_get_bigendian(&ma->cbw.CBWCB[2], 4); ma->req_sector_count = usbd_scsi_get_bigendian(&ma->cbw.CBWCB[7], 2); } debugvs(2, "%s : %s - SCSI Read : LBA %08lx Sector count %04x\n", __FILE__, __FUNCTION__, ma->lba, ma->req_sector_count); if (!usbd_scsi_check_lba(ma, ma->lba + ma->req_sector_count)) { debugvs(2, "%s : %s - SCSI Read : LBA address out of range\n", __FILE__, __FUNCTION__); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; } if (ma->req_sector_count == 0) { ma->state = SEND_CSW; return CSW_STATUS_CommandPassed; } for (cnt = 0; cnt < ma->req_sector_count; cnt++) { usbd_media_read(ma); ma->buff_length = ma->media.BytePerSector; ma->buff_ptr = 0; usbd_scsi_send_data_wait(ma); ma->lba++; } return usbd_scsi_command_noerror_end(ma);}char usbd_scsi_com_write(usbd_mass_instance *ma){ unsigned short cnt; char ret; debugvs(1, "%s : %s - SCSI Write\n", __FILE__, __FUNCTION__); ma->state = MASS_RECV; ret = usbd_scsi_check_media(ma); if (ret != CSW_STATUS_CommandPassed) { ma->state = SEND_CSW; return ret; } if (ma->cbw.CBWCB[0] == SCSI_ComWrite6) { ma->lba = (usbd_scsi_get_bigendian(&ma->cbw.CBWCB[1], 3) & 0x1fffff); ma->req_sector_count = ma->cbw.CBWCB[4]; if (!ma->req_sector_count) ma->req_sector_count = 0x100; } else { ma->lba = usbd_scsi_get_bigendian(&ma->cbw.CBWCB[2], 4); ma->req_sector_count = usbd_scsi_get_bigendian(&ma->cbw.CBWCB[7], 2); } debugvs(2, "%s : %s - SCSI Write : LBA %08lx Sector count %04x\n", __FILE__, __FUNCTION__, ma->lba, ma->req_sector_count); if (!usbd_scsi_check_lba(ma, ma->lba + ma->req_sector_count)) { debugvs(2, "%s : %s - SCSI Write : LBA address out of range\n", __FILE__, __FUNCTION__); ma->state = SEND_CSW; return CSW_STATUS_CommandFailed; } if (ma->req_sector_count == 0) { ma->state = SEND_CSW; return CSW_STATUS_CommandPassed; } for (cnt = 0; cnt < ma->req_sector_count; cnt++) { ma->buff_ptr = 0; ma->buff_length = ma->media.BytePerSector; usbd_scsi_recv_data_wait(ma); usbd_media_write(ma); ma->lba++; } return usbd_scsi_command_noerror_end(ma);}char usbd_scsi_command_noerror_end(usbd_mass_instance *ma){ ma->state = SEND_CSW; usbd_scsi_set_error(ma, SCSI_ERROR_NoError, 0); return CSW_STATUS_CommandPassed;}char usbd_scsi_command_end_send(usbd_mass_instance *ma){ ma->state = MASS_TRANS; if (usbd_scsi_send_data_wait(ma)) { ma->state = SEND_CSW; usbd_scsi_set_error(ma, SCSI_ERROR_NoError, 0); return CSW_STATUS_CommandPassed; } ma->state = SEND_CSW; return CSW_STATUS_PhaseError;}int usbd_scsi_send_data_wait(usbd_mass_instance *ma){ int len, flag, temp; len = 0; flag = FALSE; while (ma->state == MASS_TRANS) { usbdmass_check_control_int(); if (ma->usb_reset == TRUE) { flag = FALSE; break; } if (usbd_24x0_chk_ep1_stall()) { flag = FALSE; break; } if (usbd_24x0_chk_ep1_busy()) continue; if (flag == TRUE) { ma->buff_ptr += len; ma->csw.dCSWDataResidue -= len; if (ma->buff_ptr == ma->buff_length) break; } temp = ma->buff_length - ma->buff_ptr; len = (temp > EP2_PKT_SIZE) ? EP2_PKT_SIZE : temp; usbd_24x0_write_fifo(ma->buff + ma->buff_ptr, len, INDEX_EP1); usbd_24x0_set_ep1_in_pkt_ready(); debughd(3, ma->buff + ma->buff_ptr, len); flag = TRUE; } return flag;}int usbd_scsi_recv_data_wait(usbd_mass_instance *ma){ int flag; unsigned char len; flag = FALSE; while (ma->state == MASS_RECV) { usbdmass_check_control_int(); if (ma->usb_reset == TRUE) { debugvs(2, "%s : %s - SCSI recv data : USB Reset\n", __FILE__, __FUNCTION__); flag = FALSE; break; } if (usbd_24x0_chk_ep2_stall()) { debugvs(2, "%s : %s - SCSI recv data : ep2 stall\n", __FILE__, __FUNCTION__); flag = FALSE; break; } if (!usbd_24x0_isr_ep2_chk()) continue; len = usbd_24x0_read_fifo(ma->buff + ma->buff_ptr, INDEX_EP2); debughd(3, ma->buff + ma->buff_ptr, len); ma->buff_ptr += len; ma->csw.dCSWDataResidue -= len; usbd_24x0_clr_ep2_out_pkt_ready(); if (ma->buff_ptr == ma->buff_length) break; flag = TRUE; } return flag;}char usbd_scsi_check_media(usbd_mass_instance *ma){ usbd_media_probe(ma); switch (ma->media.status) { case ABSENT: usbd_scsi_set_error(ma, SCSI_ERROR_MediumNotPresent, 0); return CSW_STATUS_CommandFailed; case CHANGED: usbd_scsi_set_error(ma, SCSI_ERROR_MediumChanged, 0); ma->media.status = PRESENT; return CSW_STATUS_CommandFailed; case PRESENT: default: break; } usbd_scsi_set_error(ma, SCSI_ERROR_NoError, 0); return CSW_STATUS_CommandPassed;}int usbd_scsi_check_lba(usbd_mass_instance *ma, unsigned long lba){ if (lba > ma->media.total_sector) { usbd_scsi_set_error(ma, SCSI_ERROR_AddressOutOfRange, ma->media.total_sector); return FALSE; } return TRUE;}void usbd_scsi_set_error(usbd_mass_instance *ma, int error_no, unsigned long error_info){ ma->scsi_error = error_no; ma->scsi_error_info = error_info; return;}unsigned long usbd_scsi_get_bigendian(unsigned char *ptr, int len){ int i; unsigned long ret_value; ret_value = 0; for (i = 0; i < len; i++) { ret_value = ret_value << 8; ret_value += *ptr; ptr++; } return ret_value;}void usbd_scsi_put_bigendian(unsigned char *ptr, unsigned long value, int len){ int i; for (i = 3; i >= 0; i--) { if (i < len) { ptr[i] = (unsigned char)(value & 0xff); value = value >> 8; } } return;}void usbd_scsi_strcpy(char *dest, char *src, int len){ int i; for (i = 0; i < len; i++) dest[i] = src[i]; return;}void usbd_scsi_clear_buff(usbd_mass_instance *ma){ int i; for (i = 0; i < MASS_BUFF_SIZE; i++) ma->buff[i] = 0; ma->buff_ptr = 0; return;}#endif /* CONFIG_AESOP_USBDMASS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -