From dcdcfafa87824be86a250ef9e2b45e71f4cf0b00 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 16 Dec 2017 23:31:17 +0000 Subject: [PATCH] Added SCSI non-removable report to DiscImageChef.Device.Report. --- DiscImageChef.Device.Report/scsi.c | 271 +++++++++++++++++++++- DiscImageChef.Device.Report/scsi.h | 28 ++- DiscImageChef.Device.Report/scsi_report.c | 240 ++++++++++++++++++- 3 files changed, 530 insertions(+), 9 deletions(-) diff --git a/DiscImageChef.Device.Report/scsi.c b/DiscImageChef.Device.Report/scsi.c index 6411109f..14dfeca6 100644 --- a/DiscImageChef.Device.Report/scsi.c +++ b/DiscImageChef.Device.Report/scsi.c @@ -39,8 +39,12 @@ int SendScsiCommand(int fd, void *cdb, unsigned char cdb_len, unsigned char *buf if(error < 0) error = errno; - else - free(*senseBuffer); + else if(io_hdr.status != 0) + error = io_hdr.status; + else if(io_hdr.host_status != 0) + error = io_hdr.host_status; + else if(io_hdr.info != 0) + error = io_hdr.info & SG_INFO_OK_MASK; return error; } @@ -262,4 +266,265 @@ int ModeSense10(int fd, unsigned char **buffer, unsigned char **senseBuffer, int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV); return error; -} \ No newline at end of file +} + +int ReadCapacity(int fd, unsigned char **buffer, unsigned char **senseBuffer, int RelAddr, uint32_t address, int PMI) +{ + unsigned char cmd_len = 10; + unsigned int buffer_len = 8; + *buffer = malloc(buffer_len); + memset(*buffer, 0, buffer_len); + + unsigned char cdb[] = {SCSI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + if(PMI) + { + cdb[8] = 0x01; + if(RelAddr) + cdb[1] = 0x01; + + cdb[2] = (uint8_t)((address & 0xFF000000) >> 24); + cdb[3] = (uint8_t)((address & 0xFF0000) >> 16); + cdb[4] = (uint8_t)((address & 0xFF00) >> 8); + cdb[5] = (uint8_t)(address & 0xFF); + } + + int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV); + + return error; +} + +int ReadCapacity16(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint64_t address, int PMI) +{ + unsigned char cmd_len = 16; + unsigned int buffer_len = 32; + *buffer = malloc(buffer_len); + memset(*buffer, 0, buffer_len); + + unsigned char cdb[] = {SCSI_SERVICE_ACTION_IN, SCSI_READ_CAPACITY_16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + if(PMI) + { + cdb[14] = 0x01; + cdb[2] = (uint8_t)((address & 0xFF00000000000000ULL) >> 56); + cdb[3] = (uint8_t)((address & 0xFF000000000000ULL) >> 48); + cdb[4] = (uint8_t)((address & 0xFF0000000000ULL) >> 40); + cdb[5] = (uint8_t)((address & 0xFF00000000ULL) >> 32); + cdb[6] = (uint8_t)((address & 0xFF000000ULL) >> 24); + cdb[7] = (uint8_t)((address & 0xFF0000ULL) >> 16); + cdb[8] = (uint8_t)((address & 0xFF00ULL) >> 8); + cdb[9] = (uint8_t)(address & 0xFFULL); + } + + cdb[10] = (uint8_t)((buffer_len & 0xFF000000) >> 24); + cdb[11] = (uint8_t)((buffer_len & 0xFF0000) >> 16); + cdb[12] = (uint8_t)((buffer_len & 0xFF00) >> 8); + cdb[13] = (uint8_t)(buffer_len & 0xFF); + + int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV); + + return error; +} + +int Read6(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize, uint8_t transferLength) +{ + unsigned char cmd_len = 6; + unsigned int buflen = transferLength == 0 ? 256 * blockSize : transferLength * blockSize; + *buffer = malloc(buflen); + memset(*buffer, 0, buflen); + + unsigned char cdb[] = {SCSI_READ, 0, 0, 0, 0, 0}; + + cdb[1] = (uint8_t)((lba & 0x1F0000) >> 16); + cdb[2] = (uint8_t)((lba & 0xFF00) >> 8); + cdb[3] = (uint8_t)(lba & 0xFF); + cdb[4] = transferLength; + + int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buflen, senseBuffer, SG_DXFER_FROM_DEV); + + return error; +} + +int Read10(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv, int relAddr, uint32_t lba, uint32_t blockSize, uint8_t groupNumber, uint16_t transferLength) +{ + unsigned char cmd_len = 10; + unsigned int buflen = transferLength * blockSize; + *buffer = malloc(buflen); + memset(*buffer, 0, buflen); + + unsigned char cdb[] = {SCSI_READ_10, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + cdb[1] = (uint8_t)((rdprotect & 0x07) << 5); + if(dpo) + cdb[1] += 0x10; + if(fua) + cdb[1] += 0x08; + if(fuaNv) + cdb[1] += 0x02; + if(relAddr) + cdb[1] += 0x01; + cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24); + cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16); + cdb[4] = (uint8_t)((lba & 0xFF00) >> 8); + cdb[5] = (uint8_t)(lba & 0xFF); + cdb[6] = (uint8_t)(groupNumber & 0x1F); + cdb[7] = (uint8_t)((transferLength & 0xFF00) >> 8); + cdb[8] = (uint8_t)(transferLength & 0xFF); + + int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buflen, senseBuffer, SG_DXFER_FROM_DEV); + + return error; +} + +int Read12(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv, int relAddr, uint32_t lba, uint32_t blockSize, uint8_t groupNumber, uint32_t transferLength, int streaming) +{ + unsigned char cmd_len = 12; + unsigned int buflen = transferLength * blockSize; + *buffer = malloc(buflen); + memset(*buffer, 0, buflen); + + unsigned char cdb[] = {SCSI_READ_12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + cdb[1] = (uint8_t)((rdprotect & 0x07) << 5); + if(dpo) + cdb[1] += 0x10; + if(fua) + cdb[1] += 0x08; + if(fuaNv) + cdb[1] += 0x02; + if(relAddr) + cdb[1] += 0x01; + cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24); + cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16); + cdb[4] = (uint8_t)((lba & 0xFF00) >> 8); + cdb[5] = (uint8_t)(lba & 0xFF); + cdb[6] = (uint8_t)((transferLength & 0xFF000000) >> 24); + cdb[7] = (uint8_t)((transferLength & 0xFF0000) >> 16); + cdb[8] = (uint8_t)((transferLength & 0xFF00) >> 8); + cdb[9] = (uint8_t)(transferLength & 0xFF); + cdb[10] = (uint8_t)(groupNumber & 0x1F); + if(streaming) + cdb[10] += 0x80; + + int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buflen, senseBuffer, SG_DXFER_FROM_DEV); + + return error; +} + +int Read16(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv, uint64_t lba, uint32_t blockSize, uint8_t groupNumber, uint32_t transferLength, int streaming) +{ + unsigned char cmd_len = 16; + unsigned int buflen = transferLength * blockSize; + *buffer = malloc(buflen); + memset(*buffer, 0, buflen); + + unsigned char cdb[] = {SCSI_READ_16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + cdb[1] = (uint8_t)((rdprotect & 0x07) << 5); + if(dpo) + cdb[1] += 0x10; + if(fua) + cdb[1] += 0x08; + if(fuaNv) + cdb[1] += 0x02; + cdb[2] = (uint8_t)((lba & 0xFF00000000000000ULL) >> 56); + cdb[3] = (uint8_t)((lba & 0xFF000000000000ULL) >> 48); + cdb[4] = (uint8_t)((lba & 0xFF0000000000ULL) >> 40); + cdb[5] = (uint8_t)((lba & 0xFF00000000ULL) >> 32); + cdb[6] = (uint8_t)((lba & 0xFF000000ULL) >> 24); + cdb[7] = (uint8_t)((lba & 0xFF0000ULL) >> 16); + cdb[8] = (uint8_t)((lba & 0xFF00ULL) >> 8); + cdb[9] = (uint8_t)(lba & 0xFFULL); + cdb[10] = (uint8_t)((transferLength & 0xFF000000) >> 24); + cdb[11] = (uint8_t)((transferLength & 0xFF0000) >> 16); + cdb[12] = (uint8_t)((transferLength & 0xFF00) >> 8); + cdb[13] = (uint8_t)(transferLength & 0xFF); + cdb[14] = (uint8_t)(groupNumber & 0x1F); + if(streaming) + cdb[14] += 0x80; + + int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buflen, senseBuffer, SG_DXFER_FROM_DEV); + + return error; +} + +int ReadLong10(int fd, unsigned char **buffer, unsigned char **senseBuffer, int correct, int relAddr, uint32_t lba, uint16_t transferBytes) +{ + unsigned char cmd_len = 10; + *buffer = malloc(transferBytes); + memset(*buffer, 0, transferBytes); + + unsigned char cdb[] = {SCSI_READ_LONG, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + if(correct) + cdb[1] += 0x02; + if(relAddr) + cdb[1] += 0x01; + cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24); + cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16); + cdb[4] = (uint8_t)((lba & 0xFF00) >> 8); + cdb[5] = (uint8_t)(lba & 0xFF); + cdb[7] = (uint8_t)((transferBytes & 0xFF00) >> 8); + cdb[8] = (uint8_t)(transferBytes & 0xFF); + + int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, transferBytes, senseBuffer, SG_DXFER_FROM_DEV); + + return error; +} + +int ReadLong16(int fd, unsigned char **buffer, unsigned char **senseBuffer, int correct, uint64_t lba, uint32_t transferBytes) +{ + unsigned char cmd_len = 16; + *buffer = malloc(transferBytes); + memset(*buffer, 0, transferBytes); + + unsigned char cdb[] = {SCSI_SERVICE_ACTION_IN, SCSI_READ_LONG_16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + cdb[2] = (uint8_t)((lba & 0xFF00000000000000ULL) >> 56); + cdb[3] = (uint8_t)((lba & 0xFF000000000000ULL) >> 48); + cdb[4] = (uint8_t)((lba & 0xFF0000000000ULL) >> 40); + cdb[5] = (uint8_t)((lba & 0xFF00000000ULL) >> 32); + cdb[6] = (uint8_t)((lba & 0xFF000000ULL) >> 24); + cdb[7] = (uint8_t)((lba & 0xFF0000ULL) >> 16); + cdb[8] = (uint8_t)((lba & 0xFF00ULL) >> 8); + cdb[9] = (uint8_t)(lba & 0xFFULL); + cdb[12] = (uint8_t)((transferBytes & 0xFF00) >> 8); + cdb[13] = (uint8_t)(transferBytes & 0xFF); + if(correct) + cdb[14] += 0x01; + + int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, transferBytes, senseBuffer, SG_DXFER_FROM_DEV); + + return error; +} + +int Seek6(int fd, unsigned char **senseBuffer, uint32_t lba) +{ + unsigned char cmd_len = 6; + char cdb[] = {SCSI_SEEK, 0, 0, 0, 0, 0}; + unsigned char *buffer = malloc(0); + + cdb[1] = (uint8_t)((lba & 0x1F0000) >> 16); + cdb[2] = (uint8_t)((lba & 0xFF00) >> 8); + cdb[3] = (uint8_t)(lba & 0xFF); + + int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE); + + return error; +} + +int Seek10(int fd, unsigned char **senseBuffer, uint32_t lba) +{ + unsigned char cmd_len = 10; + char cdb[] = {SCSI_SEEK_10, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + unsigned char *buffer = malloc(0); + + cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24); + cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16); + cdb[4] = (uint8_t)((lba & 0xFF00) >> 8); + cdb[5] = (uint8_t)(lba & 0xFF); + + int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE); + + return error; +} diff --git a/DiscImageChef.Device.Report/scsi.h b/DiscImageChef.Device.Report/scsi.h index 20ee3089..cef817cf 100644 --- a/DiscImageChef.Device.Report/scsi.h +++ b/DiscImageChef.Device.Report/scsi.h @@ -25,16 +25,36 @@ int Unload(int fd, unsigned char **senseBuffer); int LoadUnload(int fd, unsigned char **senseBuffer, int immediate, int load, int retense, int endOfTape, int hold); int ModeSense6(int fd, unsigned char **buffer, unsigned char **senseBuffer, int DBD, uint8_t pageControl, uint8_t pageCode, uint8_t subPageCode); int ModeSense10(int fd, unsigned char **buffer, unsigned char **senseBuffer, int LLBAA, int DBD, uint8_t pageContorl, uint8_t pageCode, uint8_t subPageCode); +int ReadCapacity(int fd, unsigned char **buffer, unsigned char **senseBuffer, int RelAddr, uint32_t address, int PMI); +int ReadCapacity16(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint64_t address, int PMI); +int Read6(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize, uint8_t transferLength); +int Read10(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv, int relAddr, uint32_t lba, uint32_t blockSize, uint8_t groupNumber, uint16_t transferLength); +int Read12(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv, int relAddr, uint32_t lba, uint32_t blockSize, uint8_t groupNumber, uint32_t transferLength, int streaming); +int Read16(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv, uint64_t lba, uint32_t blockSize, uint8_t groupNumber, uint32_t transferLength, int streaming); +int ReadLong10(int fd, unsigned char **buffer, unsigned char **senseBuffer, int correct, int relAddr, uint32_t lba, uint16_t transferBytes); +int ReadLong16(int fd, unsigned char **buffer, unsigned char **senseBuffer, int correct, uint64_t lba, uint32_t transferBytes); +int Seek6(int fd, unsigned char **senseBuffer, uint32_t lba); +int Seek10(int fd, unsigned char **senseBuffer, uint32_t lba); typedef enum { + SCSI_TEST_UNIT_READY = 0x00, + SCSI_READ = 0x08, + SCSI_SEEK = 0x0B, SCSI_INQUIRY = 0x12, SCSI_START_STOP_UNIT = 0x1B, SCSI_LOAD_UNLOAD = SCSI_START_STOP_UNIT, SCSI_MODE_SENSE = 0x1A, SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E, + SCSI_READ_CAPACITY = 0x25, + SCSI_READ_10 = 0x28, + SCSI_READ_LONG = 0x3E, + SCSI_SEEK_10 = 0x2B, SCSI_MODE_SENSE_10 = 0x5A, - SCSI_ATA_PASSTHROUGH_16 = 0x85 + SCSI_ATA_PASSTHROUGH_16 = 0x85, + SCSI_READ_16 = 0x88, + SCSI_SERVICE_ACTION_IN = 0x9E, + SCSI_READ_12 = 0xA8, } ScsiCommands; typedef enum @@ -45,6 +65,12 @@ typedef enum MODE_PAGE_SAVED = 0xC0 } ScsiModeSensePageControl; +typedef enum +{ + SCSI_READ_CAPACITY_16 = 0x10, + SCSI_READ_LONG_16 = 0x11, +} ScsiServiceActionIn; + // SCSI INQUIRY command response #pragma pack(1) typedef struct diff --git a/DiscImageChef.Device.Report/scsi_report.c b/DiscImageChef.Device.Report/scsi_report.c index cdda20dd..01d54e00 100644 --- a/DiscImageChef.Device.Report/scsi_report.c +++ b/DiscImageChef.Device.Report/scsi_report.c @@ -17,6 +17,19 @@ void ScsiReport(int fd, xmlTextWriterPtr xmlWriter) int removable = FALSE; char user_response = ' '; unsigned char* tmpString; + const int testSize512[] = {514, + // Long sector sizes for SuperDisk + 536, 558, + // Long sector sizes for 512-byte magneto-opticals + 600, 610, 630}; + const int testSize1024[] = { + // Long sector sizes for floppies + 1026, + // Long sector sizes for 1024-byte magneto-opticals + 1200}; + const int testSize2048[] = {2380}; + const int testSize4096[] = {4760}; + const int testSize8192[] = {9424}; printf("Querying SCSI INQUIRY...\n"); @@ -134,7 +147,7 @@ void ScsiReport(int fd, xmlTextWriterPtr xmlWriter) if(error) { - printf("Querying all mode pages using SCSI MODE SENSE (10)..."); + printf("Querying all mode pages using SCSI MODE SENSE (10)...\n"); error = ModeSense10(fd, &mode10Response, &sense, FALSE, TRUE, MODE_PAGE_DEFAULT, 0x3F, 0x00); if(!error) supportsMode10 = TRUE; @@ -149,11 +162,11 @@ void ScsiReport(int fd, xmlTextWriterPtr xmlWriter) error = ModeSense6(fd, &mode6Response, &sense, FALSE, MODE_PAGE_DEFAULT, 0x3F, 0xFF); if(error) { - printf("Querying all mode pages using SCSI MODE SENSE (6)..."); + printf("Querying all mode pages using SCSI MODE SENSE (6)...\n"); error = ModeSense6(fd, &mode6Response, &sense, FALSE, MODE_PAGE_DEFAULT, 0x3F, 0x00); if(error) { - printf("Querying SCSI MODE SENSE (6)..."); + printf("Querying SCSI MODE SENSE (6)...\n"); error = ModeSense6(fd, &mode6Response, &sense, FALSE, MODE_PAGE_DEFAULT, 0x00, 0x00); if(!error) supportsMode6 = TRUE; @@ -186,12 +199,22 @@ void ScsiReport(int fd, xmlTextWriterPtr xmlWriter) } DecodedMode decMode; + DecodedMode decMode6; + DecodedMode decMode10; memset(&decMode, 0, sizeof(DecodedMode)); + memset(&decMode6, 0, sizeof(DecodedMode)); + memset(&decMode10, 0, sizeof(DecodedMode)); if(supportsMode10) - decMode = DecodeMode10(mode10Response, inquiry->PeripheralDeviceType); + { + decMode10 = DecodeMode10(mode10Response, inquiry->PeripheralDeviceType); + memcpy(&decMode, &decMode10, sizeof(DecodedMode)); + } else if(supportsMode6) - decMode = DecodeMode6(mode6Response, inquiry->PeripheralDeviceType); + { + decMode6 = DecodeMode6(mode6Response, inquiry->PeripheralDeviceType); + memcpy(&decMode, &decMode6, sizeof(DecodedMode)); + } if(decMode.decoded) { @@ -229,6 +252,212 @@ void ScsiReport(int fd, xmlTextWriterPtr xmlWriter) xmlTextWriterEndElement(xmlWriter); // } + if(inquiry->PeripheralDeviceType == 0x05) // MultiMediaDevice + { + // TODO: Report MMC + } + else if(inquiry->PeripheralDeviceType == 0x01) // SequentialAccess + { + // TODO: Report SSC + } + else + { + if(removable) + { + // TODO: Removable + } + else + { + uint64_t blocks = 0; + uint32_t blockSize = 0; + + xmlTextWriterStartElement(xmlWriter, BAD_CAST "ReadCapabilities"); // + + printf("Querying SCSI READ CAPACITY...\n"); + error = ReadCapacity(fd, &buffer, &sense, FALSE, 0, FALSE); + if(!error) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadCapacity", "%s", "true"); + blocks = (uint64_t)(buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3]) + 1; + blockSize = (uint32_t)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7])); + } + + printf("Querying SCSI READ CAPACITY (16)...\n"); + error = ReadCapacity16(fd, &buffer, &sense, FALSE, 0); + if(!error) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadCapacity16", "%s", "true"); + blocks = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3]); + blocks <<= 32; + blocks += (buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]); + blocks++; + blockSize = (uint32_t)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + (buffer[11])); + } + + if(blocks != 0) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Blocks", "%llu", blocks); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSize", "%lu", blockSize); + } + + decMode.decoded = 0; + + if(supportsMode10) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense10", "%s", "true"); + xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense10Data"); + xmlTextWriterWriteBase64(xmlWriter, mode10Response, 0, (*(mode10Response + 0) << 8) + *(mode10Response + 1) + 2); + xmlTextWriterEndElement(xmlWriter); + } + + if(supportsMode6) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense6", "%s", "true"); + xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense6Data"); + xmlTextWriterWriteBase64(xmlWriter, mode6Response, 0, *(mode6Response + 0) + 1); + xmlTextWriterEndElement(xmlWriter); + } + + if(decMode.decoded) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumType", "%d", decMode.Header.MediumType); + if(decMode.Header.descriptorsLength > 0) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Density", "%d", decMode.Header.BlockDescriptors[0].Density); + } + + printf("Trying SCSI READ (6)...\n"); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s", !Read6(fd, &buffer, &sense, 0, blockSize, 1) ? "true" : "false"); + + printf("Trying SCSI READ (10)...\n"); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead10", "%s", !Read10(fd, &buffer, &sense, 0, FALSE, TRUE, FALSE, FALSE, 0, blockSize, 0, 1) ? "true" : "false"); + + printf("Trying SCSI READ (12)...\n"); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead12", "%s", !Read12(fd, &buffer, &sense, 0, FALSE, TRUE, FALSE, FALSE, 0, blockSize, 0, 1, FALSE) ? "true" : "false"); + + printf("Trying SCSI READ (16)...\n"); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead16", "%s", !Read16(fd, &buffer, &sense, 0, FALSE, TRUE, FALSE, 0, blockSize, 0, 1, FALSE) ? "true" : "false"); + + uint32_t longBlockSize = blockSize; + + int supportsReadLong10 = FALSE; + + printf("Trying SCSI READ LONG (10)...\n"); + ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, 0xFFFF); + if((sense[0] == 0x70 || sense[0] == 0x71) && (sense[2] & 0x0F) == 0x05 && sense[12] == 0x24 && sense[13] == 0x00) + { + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong", "%s", "true"); + supportsReadLong10 = TRUE; + if(sense[0] & 0x80 && sense[2] & 0x20) + { + uint32_t information = (sense[3] << 24) + (sense[4] << 16) + (sense[5] << 8) + sense[6]; + longBlockSize = 0xFFFF - (information & 0xFFFF); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%d", longBlockSize); + } + } + + printf("Trying SCSI READ LONG (10)...\n"); + ReadLong16(fd, &buffer, &sense, FALSE, 0, 0xFFFF); + if((sense[0] == 0x70 || sense[0] == 0x71) && (sense[2] & 0x0F) == 0x05 && sense[12] == 0x24 && sense[13] == 0x00) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong16", "%s", "true"); + + int i; + + if(supportsReadLong10 && blockSize == longBlockSize) + { + if(blockSize == 512) + { + for(i = 0; i < sizeof(testSize512) / sizeof(int); i++) + { + error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize512[i]); + if(!error) + { + longBlockSize = testSize512[i]; + break; + } + } + } + else if(blockSize == 1024) + { + for(i = 0; i < sizeof(testSize1024) / sizeof(int); i++) + { + error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize1024[i]); + if(!error) + { + longBlockSize = testSize1024[i]; + break; + } + } + } + else if(blockSize == 2048) + { + for(i = 0; i < sizeof(testSize2048) / sizeof(int); i++) + { + error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize2048[i]); + if(!error) + { + longBlockSize = testSize2048[i]; + break; + } + } + } + else if(blockSize == 4096) + { + for(i = 0; i < sizeof(testSize4096) / sizeof(int); i++) + { + error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize4096[i]); + if(!error) + { + longBlockSize = testSize4096[i]; + break; + } + } + } + else if(blockSize == 8192) + { + for(i = 0; i < sizeof(testSize8192) / sizeof(int); i++) + { + error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize8192[i]); + if(!error) + { + longBlockSize = testSize8192[i]; + break; + } + } + } + } + + if(supportsReadLong10 && blockSize == longBlockSize) + { + do + { + printf("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): "); + scanf("%c", &user_response); + printf("\n"); + } while(user_response != 'Y' && user_response != 'y' && user_response != 'N' && user_response != 'n'); + + if(user_response == 'Y' || user_response == 'y') + { + for(i = blockSize; i <= 65536; i++) + { + printf("\rTrying to READ LONG with a size of %d bytes", i); + error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, i); + if(!error) + { + longBlockSize = i; + break; + } + } + printf("\n"); + } + } + + if(supportsReadLong10 && blockSize != longBlockSize) + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%d", longBlockSize); + + xmlTextWriterEndElement(xmlWriter); // + } + } + xmlTextWriterEndElement(xmlWriter); // } @@ -442,6 +671,7 @@ DecodedMode DecodeMode10(unsigned char* modeResponse, uint8_t deviceType) while(offset < length) { + printf("%doff\n", offset); int isSubpage = (modeResponse[offset] & 0x40) == 0x40; uint8_t pageNo = (uint8_t)(modeResponse[offset] & 0x3F);