mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Move DiscImageChef.Device.Report to its own repository.
This commit is contained in:
1
DiscImageChef.Device.Report/.idea/.name
generated
1
DiscImageChef.Device.Report/.idea/.name
generated
@@ -1 +0,0 @@
|
||||
DiscImageChef_Device_Report
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
||||
@@ -1,5 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
@@ -1,8 +0,0 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="claunia">
|
||||
<words>
|
||||
<w>claunia</w>
|
||||
<w>discimagechef</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
4
DiscImageChef.Device.Report/.idea/misc.xml
generated
4
DiscImageChef.Device.Report/.idea/misc.xml
generated
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
</project>
|
||||
8
DiscImageChef.Device.Report/.idea/modules.xml
generated
8
DiscImageChef.Device.Report/.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/DiscImageChef.Device.Report.iml" filepath="$PROJECT_DIR$/.idea/DiscImageChef.Device.Report.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
DiscImageChef.Device.Report/.idea/vcs.xml
generated
6
DiscImageChef.Device.Report/.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,11 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.9)
|
||||
project(DiscImageChef_Device_Report C)
|
||||
|
||||
set(CMAKE_C_STANDARD 90)
|
||||
|
||||
find_package(LibXml2)
|
||||
|
||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||
|
||||
add_executable(DiscImageChef_Device_Report main.c scsi.c scsi.h main.h ata.h ata.c atapi.c atapi.h atapi_report.c atapi_report.h identify_decode.c identify_decode.h scsi_report.c scsi_report.h inquiry_decode.c inquiry_decode.h scsi_mode.h scsi_mode.c mmc_report.c mmc_report.h cdrom_mode.h ssc_report.c ssc_report.h ata_report.c ata_report.h)
|
||||
target_link_libraries(DiscImageChef_Device_Report ${LIBXML2_LIBRARIES})
|
||||
@@ -1,537 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ata.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains ATA commands.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <scsi/sg.h>
|
||||
#include <malloc.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "ata.h"
|
||||
#include "scsi.h"
|
||||
|
||||
int AtaProtocolToScsiDirection(int protocol)
|
||||
{
|
||||
switch(protocol)
|
||||
{
|
||||
case ATA_PROTOCOL_DEVICE_DIAGNOSTICS:
|
||||
case ATA_PROTOCOL_DEVICE_RESET:
|
||||
case ATA_PROTOCOL_HARD_RESET:
|
||||
case ATA_PROTOCOL_NO_DATA:
|
||||
case ATA_PROTOCOL_SOFT_RESET:
|
||||
case ATA_PROTOCOL_RETURN_RESPONSE:
|
||||
return SG_DXFER_NONE;
|
||||
case ATA_PROTOCOL_PIO_IN:
|
||||
case ATA_PROTOCOL_UDMA_IN:
|
||||
return SG_DXFER_FROM_DEV;
|
||||
case ATA_PROTOCOL_PIO_OUT:
|
||||
case ATA_PROTOCOL_UDMA_OUT:
|
||||
return SG_DXFER_TO_DEV;
|
||||
default:
|
||||
return SG_DXFER_TO_FROM_DEV;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *AtaToCString(unsigned char *string, int len)
|
||||
{
|
||||
unsigned char *buffer = malloc(len + 1);
|
||||
unsigned char *ptr = buffer;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < len; i += 2)
|
||||
{
|
||||
*ptr++ = *(string + i + 1);
|
||||
*ptr++ = *(string + i);
|
||||
}
|
||||
|
||||
buffer[len] = 0x00;
|
||||
*ptr = *(buffer + len);
|
||||
|
||||
for(i = len; i >= 0; i--, *ptr--)
|
||||
{
|
||||
if(*ptr == 0x20 || *ptr == 0x00)
|
||||
*ptr = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int SendAtaCommandChs(int fd, AtaRegistersCHS registers, AtaErrorRegistersCHS **errorRegisters, int protocol,
|
||||
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks)
|
||||
{
|
||||
unsigned char cdb[16];
|
||||
memset(&cdb, 0, 16);
|
||||
cdb[0] = SCSI_ATA_PASSTHROUGH_16;
|
||||
cdb[1] = (unsigned char)((protocol << 1) & 0x1E);
|
||||
if(transferRegister != ATA_TRANSFER_NONE && protocol != ATA_PROTOCOL_NO_DATA)
|
||||
{
|
||||
switch(protocol)
|
||||
{
|
||||
case ATA_PROTOCOL_PIO_IN:
|
||||
case ATA_PROTOCOL_UDMA_IN:
|
||||
cdb[2] = 0x08;
|
||||
break;
|
||||
default:
|
||||
cdb[2] = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
if(transferBlocks)
|
||||
cdb[2] |= 0x04;
|
||||
|
||||
cdb[2] |= (transferRegister & 0x03);
|
||||
}
|
||||
|
||||
cdb[4] = registers.feature;
|
||||
cdb[6] = registers.sectorCount;
|
||||
cdb[8] = registers.sector;
|
||||
cdb[10] = registers.cylinderLow;
|
||||
cdb[12] = registers.cylinderHigh;
|
||||
cdb[13] = registers.deviceHead;
|
||||
cdb[14] = registers.command;
|
||||
|
||||
unsigned char *sense_buf;
|
||||
int error = SendScsiCommand(fd, &cdb, 16, buffer, buffer_len, &sense_buf,
|
||||
AtaProtocolToScsiDirection(protocol));
|
||||
|
||||
*errorRegisters = malloc(sizeof(AtaErrorRegistersCHS));
|
||||
memset(*errorRegisters, 0, sizeof(AtaErrorRegistersCHS));
|
||||
(*errorRegisters)->error = sense_buf[11];
|
||||
(*errorRegisters)->sectorCount = sense_buf[13];
|
||||
(*errorRegisters)->sector = sense_buf[15];
|
||||
(*errorRegisters)->cylinderLow = sense_buf[17];
|
||||
(*errorRegisters)->cylinderHigh = sense_buf[19];
|
||||
(*errorRegisters)->deviceHead = sense_buf[20];
|
||||
(*errorRegisters)->status = sense_buf[21];
|
||||
|
||||
if(error != 0)
|
||||
return error;
|
||||
|
||||
return (*errorRegisters)->error;
|
||||
}
|
||||
|
||||
int SendAtaCommandLba28(int fd, AtaRegistersLBA28 registers, AtaErrorRegistersLBA28 **errorRegisters, int protocol,
|
||||
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks)
|
||||
{
|
||||
unsigned char cdb[16];
|
||||
memset(&cdb, 0, 16);
|
||||
cdb[0] = SCSI_ATA_PASSTHROUGH_16;
|
||||
cdb[1] = (unsigned char)((protocol << 1) & 0x1E);
|
||||
if(transferRegister != ATA_TRANSFER_NONE && protocol != ATA_PROTOCOL_NO_DATA)
|
||||
{
|
||||
switch(protocol)
|
||||
{
|
||||
case ATA_PROTOCOL_PIO_IN:
|
||||
case ATA_PROTOCOL_UDMA_IN:
|
||||
cdb[2] = 0x08;
|
||||
break;
|
||||
default:
|
||||
cdb[2] = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
if(transferBlocks)
|
||||
cdb[2] |= 0x04;
|
||||
|
||||
cdb[2] |= (transferRegister & 0x03);
|
||||
}
|
||||
|
||||
cdb[2] |= 0x20;
|
||||
|
||||
cdb[4] = registers.feature;
|
||||
cdb[6] = registers.sectorCount;
|
||||
cdb[8] = registers.lbaLow;
|
||||
cdb[10] = registers.lbaMid;
|
||||
cdb[12] = registers.lbaHigh;
|
||||
cdb[13] = registers.deviceHead;
|
||||
cdb[14] = registers.command;
|
||||
|
||||
unsigned char *sense_buf;
|
||||
int error = SendScsiCommand(fd, &cdb, 16, buffer, buffer_len, &sense_buf,
|
||||
AtaProtocolToScsiDirection(protocol));
|
||||
|
||||
*errorRegisters = malloc(sizeof(AtaErrorRegistersLBA28));
|
||||
memset(*errorRegisters, 0, sizeof(AtaErrorRegistersLBA28));
|
||||
(*errorRegisters)->error = sense_buf[11];
|
||||
(*errorRegisters)->sectorCount = sense_buf[13];
|
||||
(*errorRegisters)->lbaLow = sense_buf[15];
|
||||
(*errorRegisters)->lbaMid = sense_buf[17];
|
||||
(*errorRegisters)->lbaHigh = sense_buf[19];
|
||||
(*errorRegisters)->deviceHead = sense_buf[20];
|
||||
(*errorRegisters)->status = sense_buf[21];
|
||||
|
||||
if(error != 0)
|
||||
return error;
|
||||
|
||||
return (*errorRegisters)->error;
|
||||
}
|
||||
|
||||
int SendAtaCommandLba48(int fd, AtaRegistersLBA48 registers, AtaErrorRegistersLBA48 **errorRegisters, int protocol,
|
||||
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks)
|
||||
{
|
||||
unsigned char cdb[16];
|
||||
memset(&cdb, 0, 16);
|
||||
cdb[0] = SCSI_ATA_PASSTHROUGH_16;
|
||||
cdb[1] = (unsigned char)((protocol << 1) & 0x1E);
|
||||
cdb[1] |= 0x01;
|
||||
if(transferRegister != ATA_TRANSFER_NONE && protocol != ATA_PROTOCOL_NO_DATA)
|
||||
{
|
||||
switch(protocol)
|
||||
{
|
||||
case ATA_PROTOCOL_PIO_IN:
|
||||
case ATA_PROTOCOL_UDMA_IN:
|
||||
cdb[2] = 0x08;
|
||||
break;
|
||||
default:
|
||||
cdb[2] = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
if(transferBlocks)
|
||||
cdb[2] |= 0x04;
|
||||
|
||||
cdb[2] |= (transferRegister & 0x03);
|
||||
}
|
||||
|
||||
cdb[2] |= 0x20;
|
||||
|
||||
cdb[3] = (uint8_t)((registers.feature & 0xFF00) >> 8);
|
||||
cdb[4] = (uint8_t)(registers.feature & 0xFF);
|
||||
cdb[5] = (uint8_t)((registers.sectorCount & 0xFF00) >> 8);
|
||||
cdb[6] = (uint8_t)(registers.sectorCount & 0xFF);
|
||||
cdb[7] = (uint8_t)((registers.lbaLow & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(registers.lbaLow & 0xFF);
|
||||
cdb[9] = (uint8_t)((registers.lbaMid & 0xFF00) >> 8);
|
||||
cdb[10] = (uint8_t)(registers.lbaMid & 0xFF);
|
||||
cdb[11] = (uint8_t)((registers.lbaHigh & 0xFF00) >> 8);
|
||||
cdb[12] = (uint8_t)(registers.lbaHigh & 0xFF);
|
||||
cdb[13] = registers.deviceHead;
|
||||
cdb[14] = registers.command;
|
||||
|
||||
unsigned char *sense_buf;
|
||||
int error = SendScsiCommand(fd, &cdb, 16, buffer, buffer_len, &sense_buf,
|
||||
AtaProtocolToScsiDirection(protocol));
|
||||
|
||||
*errorRegisters = malloc(sizeof(AtaErrorRegistersLBA48));
|
||||
memset(*errorRegisters, 0, sizeof(AtaErrorRegistersLBA48));
|
||||
(*errorRegisters)->error = sense_buf[11];
|
||||
(*errorRegisters)->sectorCount = (uint16_t)((sense_buf[12] << 8) + sense_buf[13]);
|
||||
(*errorRegisters)->lbaLow = (uint16_t)((sense_buf[14] << 8) + sense_buf[15]);
|
||||
(*errorRegisters)->lbaMid = (uint16_t)((sense_buf[16] << 8) + sense_buf[17]);
|
||||
(*errorRegisters)->lbaHigh = (uint16_t)((sense_buf[18] << 8) + sense_buf[19]);
|
||||
(*errorRegisters)->deviceHead = sense_buf[20];
|
||||
(*errorRegisters)->status = sense_buf[21];
|
||||
|
||||
if(error != 0)
|
||||
return error;
|
||||
|
||||
return (*errorRegisters)->error;
|
||||
}
|
||||
|
||||
int Identify(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegisters)
|
||||
{
|
||||
*buffer = malloc(512);
|
||||
memset(*buffer, 0, 512);
|
||||
AtaRegistersCHS registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersCHS));
|
||||
|
||||
registers.command = ATA_IDENTIFY_DEVICE;
|
||||
|
||||
int error = SendAtaCommandChs(fd, registers, errorRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_NONE, *buffer, 512,
|
||||
0);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
Read(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head,
|
||||
uint8_t sector, uint8_t count)
|
||||
{
|
||||
int buffer_len;
|
||||
if(count == 0)
|
||||
buffer_len = 512 * 256;
|
||||
else
|
||||
buffer_len = 512 * count;
|
||||
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
AtaRegistersCHS registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersCHS));
|
||||
|
||||
if(retry)
|
||||
registers.command = ATA_READ_RETRY;
|
||||
else
|
||||
registers.command = ATA_READ_SECTORS;
|
||||
registers.sectorCount = count;
|
||||
registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100);
|
||||
registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1);
|
||||
registers.deviceHead = (uint8_t)(head & 0x0F);
|
||||
registers.sector = sector;
|
||||
|
||||
int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
|
||||
*buffer, buffer_len, 1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadLong(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder,
|
||||
uint8_t head, uint8_t sector, uint32_t blockSize)
|
||||
{
|
||||
*buffer = malloc(blockSize);
|
||||
memset(*buffer, 0, blockSize);
|
||||
AtaRegistersCHS registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersCHS));
|
||||
|
||||
if(retry)
|
||||
registers.command = ATA_READ_LONG_RETRY;
|
||||
else
|
||||
registers.command = ATA_READ_LONG;
|
||||
registers.sectorCount = 1;
|
||||
registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100);
|
||||
registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1);
|
||||
registers.deviceHead = (uint8_t)(head & 0x0F);
|
||||
registers.sector = sector;
|
||||
|
||||
int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
|
||||
*buffer, blockSize, 1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int Seek(int fd, AtaErrorRegistersCHS **statusRegisters, uint16_t cylinder, uint8_t head, uint8_t sector)
|
||||
{
|
||||
unsigned char *buffer = malloc(0);
|
||||
memset(*buffer, 0, 0);
|
||||
AtaRegistersCHS registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersCHS));
|
||||
|
||||
registers.command = ATA_SEEK;
|
||||
registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100);
|
||||
registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1);
|
||||
registers.deviceHead = (uint8_t)(head & 0x0F);
|
||||
registers.sector = sector;
|
||||
|
||||
int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_NO_DATA, ATA_TRANSFER_NONE, *buffer, 0,
|
||||
0);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadDma(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder,
|
||||
uint8_t head, uint8_t sector, uint8_t count)
|
||||
{
|
||||
int buffer_len;
|
||||
if(count == 0)
|
||||
buffer_len = 512 * 256;
|
||||
else
|
||||
buffer_len = 512 * count;
|
||||
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
AtaRegistersCHS registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersCHS));
|
||||
|
||||
if(retry)
|
||||
registers.command = ATA_READ_DMA_RETRY;
|
||||
else
|
||||
registers.command = ATA_READ_DMA;
|
||||
registers.sectorCount = count;
|
||||
registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100);
|
||||
registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1);
|
||||
registers.deviceHead = (uint8_t)(head & 0x0F);
|
||||
registers.sector = sector;
|
||||
|
||||
int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_DMA, ATA_TRANSFER_SECTORCOUNT, *buffer,
|
||||
buffer_len, 1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadDmaLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
|
||||
uint8_t count)
|
||||
{
|
||||
int buffer_len;
|
||||
if(count == 0)
|
||||
buffer_len = 512 * 256;
|
||||
else
|
||||
buffer_len = 512 * count;
|
||||
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
AtaRegistersLBA28 registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersLBA28));
|
||||
|
||||
if(retry)
|
||||
registers.command = ATA_READ_DMA_RETRY;
|
||||
else
|
||||
registers.command = ATA_READ_DMA;
|
||||
registers.sectorCount = count;
|
||||
registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000);
|
||||
registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000);
|
||||
registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100);
|
||||
registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1);
|
||||
registers.deviceHead += 0x40;
|
||||
|
||||
int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_DMA, ATA_TRANSFER_SECTORCOUNT, *buffer,
|
||||
buffer_len, 1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
|
||||
uint8_t count)
|
||||
{
|
||||
int buffer_len;
|
||||
if(count == 0)
|
||||
buffer_len = 512 * 256;
|
||||
else
|
||||
buffer_len = 512 * count;
|
||||
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
AtaRegistersLBA28 registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersLBA28));
|
||||
|
||||
if(retry)
|
||||
registers.command = ATA_READ_RETRY;
|
||||
else
|
||||
registers.command = ATA_READ_SECTORS;
|
||||
registers.sectorCount = count;
|
||||
registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000);
|
||||
registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000);
|
||||
registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100);
|
||||
registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1);
|
||||
registers.deviceHead += 0x40;
|
||||
|
||||
int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
|
||||
*buffer, buffer_len, 1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadLongLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
|
||||
uint32_t blockSize)
|
||||
{
|
||||
*buffer = malloc(blockSize);
|
||||
memset(*buffer, 0, blockSize);
|
||||
AtaRegistersLBA28 registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersLBA28));
|
||||
|
||||
if(retry)
|
||||
registers.command = ATA_READ_LONG_RETRY;
|
||||
else
|
||||
registers.command = ATA_READ_LONG;
|
||||
registers.sectorCount = 1;
|
||||
registers.sectorCount = 1;
|
||||
registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000);
|
||||
registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000);
|
||||
registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100);
|
||||
registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1);
|
||||
registers.deviceHead += 0x40;
|
||||
|
||||
int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
|
||||
*buffer, blockSize, 1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int SeekLba(int fd, AtaErrorRegistersLBA28 **statusRegisters, uint32_t lba)
|
||||
{
|
||||
unsigned char *buffer = malloc(0);
|
||||
memset(*buffer, 0, 0);
|
||||
AtaRegistersLBA28 registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersLBA28));
|
||||
|
||||
registers.command = ATA_SEEK;
|
||||
registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000);
|
||||
registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000);
|
||||
registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100);
|
||||
registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1);
|
||||
registers.deviceHead += 0x40;
|
||||
|
||||
int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_NO_DATA, ATA_TRANSFER_NONE, *buffer, 0,
|
||||
0);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadDmaLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count)
|
||||
{
|
||||
int buffer_len;
|
||||
if(count == 0)
|
||||
buffer_len = 512 * 65536;
|
||||
else
|
||||
buffer_len = 512 * count;
|
||||
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
AtaRegistersLBA48 registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersLBA48));
|
||||
|
||||
registers.command = ATA_READ_DMA_EXT;
|
||||
registers.sectorCount = count;
|
||||
registers.lbaHigh = (uint16_t)((lba & 0xFFFF00000000) / 0x100000000);
|
||||
registers.lbaMid = (uint16_t)((lba & 0xFFFF0000) / 0x10000);
|
||||
registers.lbaLow = (uint16_t)((lba & 0xFFFF) / 0x1);
|
||||
registers.deviceHead += 0x40;
|
||||
|
||||
int error = SendAtaCommandLba48(fd, registers, statusRegisters, ATA_PROTOCOL_DMA, ATA_TRANSFER_SECTORCOUNT, *buffer,
|
||||
buffer_len, 1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count)
|
||||
{
|
||||
int buffer_len;
|
||||
if(count == 0)
|
||||
buffer_len = 512 * 65536;
|
||||
else
|
||||
buffer_len = 512 * count;
|
||||
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
AtaRegistersLBA48 registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersLBA48));
|
||||
|
||||
registers.command = ATA_READ_EXT;
|
||||
registers.sectorCount = count;
|
||||
registers.lbaHigh = (uint16_t)((lba & 0xFFFF00000000) / 0x100000000);
|
||||
registers.lbaMid = (uint16_t)((lba & 0xFFFF0000) / 0x10000);
|
||||
registers.lbaLow = (uint16_t)((lba & 0xFFFF) / 0x1);
|
||||
registers.deviceHead += 0x40;
|
||||
|
||||
int error = SendAtaCommandLba48(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
|
||||
*buffer, buffer_len, 1);
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -1,919 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ata.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains ATA definitions.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_ATA_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_ATA_H
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t feature;
|
||||
uint8_t sectorCount;
|
||||
uint8_t sector;
|
||||
uint8_t cylinderLow;
|
||||
uint8_t cylinderHigh;
|
||||
uint8_t deviceHead;
|
||||
uint8_t command;
|
||||
} AtaRegistersCHS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t feature;
|
||||
uint8_t sectorCount;
|
||||
uint8_t lbaLow;
|
||||
uint8_t lbaMid;
|
||||
uint8_t lbaHigh;
|
||||
uint8_t deviceHead;
|
||||
uint8_t command;
|
||||
} AtaRegistersLBA28;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t feature;
|
||||
uint16_t sectorCount;
|
||||
uint16_t lbaLow;
|
||||
uint16_t lbaMid;
|
||||
uint16_t lbaHigh;
|
||||
uint8_t deviceHead;
|
||||
uint8_t command;
|
||||
} AtaRegistersLBA48;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t status;
|
||||
uint8_t error;
|
||||
uint8_t sectorCount;
|
||||
uint8_t sector;
|
||||
uint8_t cylinderLow;
|
||||
uint8_t cylinderHigh;
|
||||
uint8_t deviceHead;
|
||||
uint8_t command;
|
||||
} AtaErrorRegistersCHS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t status;
|
||||
uint8_t error;
|
||||
uint8_t sectorCount;
|
||||
uint8_t lbaLow;
|
||||
uint8_t lbaMid;
|
||||
uint8_t lbaHigh;
|
||||
uint8_t deviceHead;
|
||||
uint8_t command;
|
||||
} AtaErrorRegistersLBA28;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t status;
|
||||
uint8_t error;
|
||||
uint16_t sectorCount;
|
||||
uint16_t lbaLow;
|
||||
uint16_t lbaMid;
|
||||
uint16_t lbaHigh;
|
||||
uint8_t deviceHead;
|
||||
uint8_t command;
|
||||
} AtaErrorRegistersLBA48;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATA_TRANSFER_NONE = 0, ATA_TRANSFER_FEATURE, ATA_TRANSFER_SECTORCOUNT, ATA_TRANSFTER_SPTSIU
|
||||
} AtaTransferRegister;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATA_PROTOCOL_HARD_RESET = 0,
|
||||
ATA_PROTOCOL_SOFT_RESET = 1,
|
||||
ATA_PROTOCOL_NO_DATA = 3,
|
||||
ATA_PROTOCOL_PIO_IN = 4,
|
||||
ATA_PROTOCOL_PIO_OUT = 5,
|
||||
ATA_PROTOCOL_DMA = 6,
|
||||
ATA_PROTOCOL_DMA_QUEUED = 7,
|
||||
ATA_PROTOCOL_DEVICE_DIAGNOSTICS = 8,
|
||||
ATA_PROTOCOL_DEVICE_RESET = 9,
|
||||
ATA_PROTOCOL_UDMA_IN = 10,
|
||||
ATA_PROTOCOL_UDMA_OUT = 11,
|
||||
ATA_PROTOCOL_FPDMA = 12,
|
||||
ATA_PROTOCOL_RETURN_RESPONSE = 15
|
||||
} AtaProtocol;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATA_READ_RETRY = 0x20,
|
||||
ATA_READ_SECTORS = 0x21,
|
||||
ATA_READ_LONG_RETRY = 0x22,
|
||||
ATA_READ_LONG = 0x23,
|
||||
ATA_READ_EXT = 0x24,
|
||||
ATA_READ_DMA_EXT = 0x25,
|
||||
ATA_SEEK = 0x70,
|
||||
ATA_READ_DMA_RETRY = 0xC8,
|
||||
ATA_READ_DMA = 0xC9,
|
||||
ATA_IDENTIFY_PACKET_DEVICE = 0xA1,
|
||||
ATA_IDENTIFY_DEVICE = 0xEC
|
||||
} AtaCommands;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*
|
||||
Word 0
|
||||
General device configuration
|
||||
On ATAPI devices:
|
||||
Bits 12 to 8 indicate device type as SCSI defined
|
||||
Bits 6 to 5:
|
||||
0 = Device shall set DRQ within 3 ms of receiving PACKET
|
||||
1 = Device shall assert INTRQ when DRQ is set to one
|
||||
2 = Device shall set DRQ within 50 µs of receiving PACKET
|
||||
Bits 1 to 0:
|
||||
0 = 12 byte command packet
|
||||
1 = 16 byte command packet
|
||||
CompactFlash is 0x848A (non magnetic, removable, not MFM, hardsector, and UltraFAST)
|
||||
*/
|
||||
uint16_t GeneralConfiguration;
|
||||
/*
|
||||
Word 1
|
||||
Cylinders in default translation mode
|
||||
Obsoleted in ATA/ATAPI-6
|
||||
*/
|
||||
uint16_t Cylinders;
|
||||
/*
|
||||
Word 2
|
||||
Specific configuration
|
||||
*/
|
||||
uint16_t SpecificConfiguration;
|
||||
/*
|
||||
Word 3
|
||||
Heads in default translation mode
|
||||
Obsoleted in ATA/ATAPI-6
|
||||
*/
|
||||
uint16_t Heads;
|
||||
/*
|
||||
Word 4
|
||||
Unformatted bytes per track in default translation mode
|
||||
Obsoleted in ATA-2
|
||||
*/
|
||||
uint16_t UnformattedBPT;
|
||||
/*
|
||||
Word 5
|
||||
Unformatted bytes per sector in default translation mode
|
||||
Obsoleted in ATA-2
|
||||
*/
|
||||
uint16_t UnformattedBPS;
|
||||
/*
|
||||
Word 6
|
||||
Sectors per track in default translation mode
|
||||
Obsoleted in ATA/ATAPI-6
|
||||
*/
|
||||
uint16_t SectorsPerTrack;
|
||||
/*
|
||||
Words 7 to 8
|
||||
CFA: Number of sectors per card
|
||||
*/
|
||||
uint32_t SectorsPerCard;
|
||||
/*
|
||||
Word 9
|
||||
Vendor unique
|
||||
Obsoleted in ATA/ATAPI-4
|
||||
*/
|
||||
uint16_t VendorWord9;
|
||||
/*
|
||||
Words 10 to 19
|
||||
Device serial number, right justified, padded with spaces
|
||||
*/
|
||||
uint8_t SerialNumber[20];
|
||||
/*
|
||||
Word 20
|
||||
Manufacturer defined
|
||||
Obsoleted in ATA-2
|
||||
0x0001 = single ported single sector buffer
|
||||
0x0002 = dual ported multi sector buffer
|
||||
0x0003 = dual ported multi sector buffer with reading
|
||||
*/
|
||||
uint16_t BufferType;
|
||||
/*
|
||||
Word 21
|
||||
Size of buffer in 512 byte increments
|
||||
Obsoleted in ATA-2
|
||||
*/
|
||||
uint16_t BufferSize;
|
||||
/*
|
||||
Word 22
|
||||
Bytes of ECC available in READ/WRITE LONG commands
|
||||
Obsoleted in ATA/ATAPI-4
|
||||
*/
|
||||
uint16_t EccBytes;
|
||||
/*
|
||||
Words 23 to 26
|
||||
Firmware revision, left justified, padded with spaces
|
||||
*/
|
||||
uint8_t FirmwareRevision[8];
|
||||
/*
|
||||
Words 27 to 46
|
||||
Model number, left justified, padded with spaces
|
||||
*/
|
||||
uint8_t Model[40];
|
||||
/*
|
||||
Word 47 bits 7 to 0
|
||||
Maximum number of sectors that can be transferred per
|
||||
interrupt on read and write multiple commands
|
||||
*/
|
||||
uint8_t MultipleMaxSectors;
|
||||
/*
|
||||
Word 47 bits 15 to 8
|
||||
Vendor unique
|
||||
ATA/ATAPI-4 says it must be 0x80
|
||||
*/
|
||||
uint8_t VendorWord47;
|
||||
/*
|
||||
Word 48
|
||||
ATA-1: Set to 1 if it can perform doubleword I/O
|
||||
ATA-2 to ATA/ATAPI-7: Reserved
|
||||
ATA8-ACS: Trusted Computing feature set
|
||||
*/
|
||||
uint16_t TrustedComputing;
|
||||
/*
|
||||
Word 49
|
||||
Capabilities
|
||||
*/
|
||||
uint16_t Capabilities;
|
||||
/*
|
||||
Word 50
|
||||
Capabilities
|
||||
*/
|
||||
uint16_t Capabilities2;
|
||||
/*
|
||||
Word 51 bits 7 to 0
|
||||
Vendor unique
|
||||
Obsoleted in ATA/ATAPI-4
|
||||
*/
|
||||
uint8_t VendorWord51;
|
||||
/*
|
||||
Word 51 bits 15 to 8
|
||||
Transfer timing mode in PIO
|
||||
Obsoleted in ATA/ATAPI-4
|
||||
*/
|
||||
uint8_t PIOTransferTimingMode;
|
||||
/*
|
||||
Word 52 bits 7 to 0
|
||||
Vendor unique
|
||||
Obsoleted in ATA/ATAPI-4
|
||||
*/
|
||||
uint8_t VendorWord52;
|
||||
/*
|
||||
Word 52 bits 15 to 8
|
||||
Transfer timing mode in DMA
|
||||
Obsoleted in ATA/ATAPI-4
|
||||
*/
|
||||
uint8_t DMATransferTimingMode;
|
||||
/*
|
||||
Word 53 bits 7 to 0
|
||||
Reports if words 54 to 58 are valid
|
||||
*/
|
||||
uint8_t ExtendedIdentify;
|
||||
/*
|
||||
Word 53 bits 15 to 8
|
||||
Free-fall Control Sensitivity
|
||||
*/
|
||||
uint8_t FreeFallSensitivity;
|
||||
/*
|
||||
Word 54
|
||||
Cylinders in current translation mode
|
||||
Obsoleted in ATA/ATAPI-6
|
||||
*/
|
||||
uint16_t CurrentCylinders;
|
||||
/*
|
||||
Word 55
|
||||
Heads in current translation mode
|
||||
Obsoleted in ATA/ATAPI-6
|
||||
*/
|
||||
uint16_t CurrentHeads;
|
||||
/*
|
||||
Word 56
|
||||
Sectors per track in current translation mode
|
||||
Obsoleted in ATA/ATAPI-6
|
||||
*/
|
||||
uint16_t CurrentSectorsPerTrack;
|
||||
/*
|
||||
Words 57 to 58
|
||||
Total sectors currently user-addressable
|
||||
Obsoleted in ATA/ATAPI-6
|
||||
*/
|
||||
uint32_t CurrentSectors;
|
||||
/*
|
||||
Word 59 bits 7 to 0
|
||||
Number of sectors currently set to transfer on a READ/WRITE MULTIPLE command
|
||||
*/
|
||||
uint8_t MultipleSectorNumber;
|
||||
/*
|
||||
Word 59 bits 15 to 8
|
||||
Indicates if <see cref="MultipleSectorNumber"/> is valid
|
||||
*/
|
||||
uint8_t Capabilities3;
|
||||
/*
|
||||
Words 60 to 61
|
||||
If drive supports LBA, how many sectors are addressable using LBA
|
||||
*/
|
||||
uint32_t LBASectors;
|
||||
/*
|
||||
Word 62 bits 7 to 0
|
||||
Single word DMA modes available
|
||||
Obsoleted in ATA/ATAPI-4
|
||||
In ATAPI it's not obsolete, indicates UDMA mode (UDMA7 is instead MDMA0)
|
||||
*/
|
||||
uint8_t DMASupported;
|
||||
/*
|
||||
Word 62 bits 15 to 8
|
||||
Single word DMA mode currently active
|
||||
Obsoleted in ATA/ATAPI-4
|
||||
In ATAPI it's not obsolete, bits 0 and 1 indicate MDMA mode+1,
|
||||
bit 10 indicates DMA is supported and bit 15 indicates DMADIR bit
|
||||
in PACKET is required for DMA transfers
|
||||
*/
|
||||
uint8_t DMAActive;
|
||||
/*
|
||||
Word 63 bits 7 to 0
|
||||
Multiword DMA modes available
|
||||
*/
|
||||
uint8_t MDMASupported;
|
||||
/*
|
||||
Word 63 bits 15 to 8
|
||||
Multiword DMA mode currently active
|
||||
*/
|
||||
uint8_t MDMAActive;
|
||||
|
||||
/*
|
||||
Word 64 bits 7 to 0
|
||||
Supported Advanced PIO transfer modes
|
||||
*/
|
||||
uint8_t APIOSupported;
|
||||
/*
|
||||
Word 64 bits 15 to 8
|
||||
Reserved
|
||||
*/
|
||||
uint8_t ReservedWord64;
|
||||
/*
|
||||
Word 65
|
||||
Minimum MDMA transfer cycle time per word in nanoseconds
|
||||
*/
|
||||
uint16_t MinMDMACycleTime;
|
||||
/*
|
||||
Word 66
|
||||
Recommended MDMA transfer cycle time per word in nanoseconds
|
||||
*/
|
||||
uint16_t RecMDMACycleTime;
|
||||
/*
|
||||
Word 67
|
||||
Minimum PIO transfer cycle time without flow control in nanoseconds
|
||||
*/
|
||||
uint16_t MinPIOCycleTimeNoFlow;
|
||||
/*
|
||||
Word 68
|
||||
Minimum PIO transfer cycle time with IORDY flow control in nanoseconds
|
||||
*/
|
||||
uint16_t MinPIOCycleTimeFlow;
|
||||
|
||||
/*
|
||||
Word 69
|
||||
Additional supported
|
||||
*/
|
||||
uint16_t CommandSet5;
|
||||
/*
|
||||
Word 70
|
||||
Reserved
|
||||
*/
|
||||
uint16_t ReservedWord70;
|
||||
/*
|
||||
Word 71
|
||||
ATAPI: Typical time in ns from receipt of PACKET to release bus
|
||||
*/
|
||||
uint16_t PacketBusRelease;
|
||||
/*
|
||||
Word 72
|
||||
ATAPI: Typical time in ns from receipt of SERVICE to clear BSY
|
||||
*/
|
||||
uint16_t ServiceBusyClear;
|
||||
/*
|
||||
Word 73
|
||||
Reserved
|
||||
*/
|
||||
uint16_t ReservedWord73;
|
||||
/*
|
||||
Word 74
|
||||
Reserved
|
||||
*/
|
||||
uint16_t ReservedWord74;
|
||||
|
||||
/*
|
||||
Word 75
|
||||
Maximum Queue depth
|
||||
*/
|
||||
uint16_t MaxQueueDepth;
|
||||
|
||||
/*
|
||||
Word 76
|
||||
Serial ATA Capabilities
|
||||
*/
|
||||
uint16_t SATACapabilities;
|
||||
/*
|
||||
Word 77
|
||||
Serial ATA Additional Capabilities
|
||||
*/
|
||||
uint16_t SATACapabilities2;
|
||||
|
||||
/*
|
||||
Word 78
|
||||
Supported Serial ATA features
|
||||
*/
|
||||
uint16_t SATAFeatures;
|
||||
/*
|
||||
Word 79
|
||||
Enabled Serial ATA features
|
||||
*/
|
||||
uint16_t EnabledSATAFeatures;
|
||||
|
||||
/*
|
||||
Word 80
|
||||
Major version of ATA/ATAPI standard supported
|
||||
*/
|
||||
uint16_t MajorVersion;
|
||||
/*
|
||||
Word 81
|
||||
Minimum version of ATA/ATAPI standard supported
|
||||
*/
|
||||
uint16_t MinorVersion;
|
||||
|
||||
/*
|
||||
Word 82
|
||||
Supported command/feature sets
|
||||
*/
|
||||
uint16_t CommandSet;
|
||||
/*
|
||||
Word 83
|
||||
Supported command/feature sets
|
||||
*/
|
||||
uint16_t CommandSet2;
|
||||
/*
|
||||
Word 84
|
||||
Supported command/feature sets
|
||||
*/
|
||||
uint16_t CommandSet3;
|
||||
|
||||
/*
|
||||
Word 85
|
||||
Enabled command/feature sets
|
||||
*/
|
||||
uint16_t EnabledCommandSet;
|
||||
/*
|
||||
Word 86
|
||||
Enabled command/feature sets
|
||||
*/
|
||||
uint16_t EnabledCommandSet2;
|
||||
/*
|
||||
Word 87
|
||||
Enabled command/feature sets
|
||||
*/
|
||||
uint16_t EnabledCommandSet3;
|
||||
|
||||
/*
|
||||
Word 88 bits 7 to 0
|
||||
Supported Ultra DMA transfer modes
|
||||
*/
|
||||
uint8_t UDMASupported;
|
||||
/*
|
||||
Word 88 bits 15 to 8
|
||||
Selected Ultra DMA transfer modes
|
||||
*/
|
||||
uint8_t UDMAActive;
|
||||
|
||||
/*
|
||||
Word 89
|
||||
Time required for security erase completion
|
||||
*/
|
||||
uint16_t SecurityEraseTime;
|
||||
/*
|
||||
Word 90
|
||||
Time required for enhanced security erase completion
|
||||
*/
|
||||
uint16_t EnhancedSecurityEraseTime;
|
||||
/*
|
||||
Word 91
|
||||
Current advanced power management value
|
||||
*/
|
||||
uint16_t CurrentAPM;
|
||||
|
||||
/*
|
||||
Word 92
|
||||
Master password revision code
|
||||
*/
|
||||
uint16_t MasterPasswordRevisionCode;
|
||||
/*
|
||||
Word 93
|
||||
Hardware reset result
|
||||
*/
|
||||
uint16_t HardwareResetResult;
|
||||
|
||||
/*
|
||||
Word 94 bits 7 to 0
|
||||
Current AAM value
|
||||
*/
|
||||
uint8_t CurrentAAM;
|
||||
/*
|
||||
Word 94 bits 15 to 8
|
||||
Vendor's recommended AAM value
|
||||
*/
|
||||
uint8_t RecommendedAAM;
|
||||
|
||||
/*
|
||||
Word 95
|
||||
Stream minimum request size
|
||||
*/
|
||||
uint16_t StreamMinReqSize;
|
||||
/*
|
||||
Word 96
|
||||
Streaming transfer time in DMA
|
||||
*/
|
||||
uint16_t StreamTransferTimeDMA;
|
||||
/*
|
||||
Word 97
|
||||
Streaming access latency in DMA and PIO
|
||||
*/
|
||||
uint16_t StreamAccessLatency;
|
||||
/*
|
||||
Words 98 to 99
|
||||
Streaming performance granularity
|
||||
*/
|
||||
uint32_t StreamPerformanceGranularity;
|
||||
|
||||
/*
|
||||
Words 100 to 103
|
||||
48-bit LBA addressable sectors
|
||||
*/
|
||||
uint64_t LBA48Sectors;
|
||||
|
||||
/*
|
||||
Word 104
|
||||
Streaming transfer time in PIO
|
||||
*/
|
||||
uint16_t StreamTransferTimePIO;
|
||||
|
||||
/*
|
||||
Word 105
|
||||
Maximum number of 512-byte block per DATA SET MANAGEMENT command
|
||||
*/
|
||||
uint16_t DataSetMgmtSize;
|
||||
|
||||
/*
|
||||
Word 106
|
||||
Bit 15 should be zero
|
||||
Bit 14 should be one
|
||||
Bit 13 set indicates device has multiple logical sectors per physical sector
|
||||
Bit 12 set indicates logical sector has more than 256 words (512 bytes)
|
||||
Bits 11 to 4 are reserved
|
||||
Bits 3 to 0 indicate power of two of logical sectors per physical sector
|
||||
*/
|
||||
uint16_t PhysLogSectorSize;
|
||||
|
||||
/*
|
||||
Word 107
|
||||
Interseek delay for ISO-7779 acoustic testing, in microseconds
|
||||
*/
|
||||
uint16_t InterseekDelay;
|
||||
|
||||
/*
|
||||
Words 108 to 111
|
||||
World Wide Name
|
||||
*/
|
||||
uint64_t WWN;
|
||||
|
||||
/*
|
||||
Words 112 to 115
|
||||
Reserved for WWN extension to 128 bit
|
||||
*/
|
||||
uint64_t WWNExtension;
|
||||
|
||||
/*
|
||||
Word 116
|
||||
Reserved for technical report
|
||||
*/
|
||||
uint16_t ReservedWord116;
|
||||
|
||||
/*
|
||||
Words 117 to 118
|
||||
Words per logical sector
|
||||
*/
|
||||
uint32_t LogicalSectorWords;
|
||||
|
||||
/*
|
||||
Word 119
|
||||
Supported command/feature sets
|
||||
*/
|
||||
uint16_t CommandSet4;
|
||||
/*
|
||||
Word 120
|
||||
Supported command/feature sets
|
||||
*/
|
||||
uint16_t EnabledCommandSet4;
|
||||
|
||||
/*
|
||||
Words 121 to 125
|
||||
Reserved
|
||||
*/
|
||||
uint16_t ReservedWords121[5];
|
||||
|
||||
/*
|
||||
Word 126
|
||||
ATAPI byte count limit
|
||||
*/
|
||||
uint16_t ATAPIByteCount;
|
||||
|
||||
/*
|
||||
Word 127
|
||||
Removable Media Status Notification feature set support
|
||||
Bits 15 to 2 are reserved
|
||||
Bits 1 to 0 must be 0 for not supported or 1 for supported. 2 and 3 are reserved.
|
||||
Obsoleted in ATA8-ACS
|
||||
*/
|
||||
uint16_t RemovableStatusSet;
|
||||
|
||||
/*
|
||||
Word 128
|
||||
Security status
|
||||
*/
|
||||
uint16_t SecurityStatus;
|
||||
|
||||
/*
|
||||
Words 129 to 159
|
||||
*/
|
||||
uint16_t ReservedWords129[31];
|
||||
|
||||
/*
|
||||
Word 160
|
||||
CFA power mode
|
||||
Bit 15 must be set
|
||||
Bit 13 indicates mode 1 is required for one or more commands
|
||||
Bit 12 indicates mode 1 is disabled
|
||||
Bits 11 to 0 indicates maximum current in mA
|
||||
*/
|
||||
uint16_t CFAPowerMode;
|
||||
|
||||
/*
|
||||
Words 161 to 167
|
||||
Reserved for CFA
|
||||
*/
|
||||
uint16_t ReservedCFA[7];
|
||||
|
||||
/*
|
||||
Word 168
|
||||
Bits 15 to 4, reserved
|
||||
Bits 3 to 0, device nominal form factor
|
||||
*/
|
||||
uint16_t DeviceFormFactor;
|
||||
/*
|
||||
Word 169
|
||||
DATA SET MANAGEMENT support
|
||||
*/
|
||||
uint16_t DataSetMgmt;
|
||||
/*
|
||||
Words 170 to 173
|
||||
Additional product identifier
|
||||
*/
|
||||
uint8_t AdditionalPID[8];
|
||||
|
||||
/*
|
||||
Word 174
|
||||
Reserved
|
||||
*/
|
||||
uint16_t ReservedWord174;
|
||||
/*
|
||||
Word 175
|
||||
Reserved
|
||||
*/
|
||||
uint16_t ReservedWord175;
|
||||
|
||||
/*
|
||||
Words 176 to 195
|
||||
Current media serial number
|
||||
*/
|
||||
uint8_t MediaSerial[40];
|
||||
/*
|
||||
Words 196 to 205
|
||||
Current media manufacturer
|
||||
*/
|
||||
uint8_t MediaManufacturer[20];
|
||||
|
||||
/*
|
||||
Word 206
|
||||
SCT Command Transport features
|
||||
*/
|
||||
uint16_t SCTCommandTransport;
|
||||
|
||||
/*
|
||||
Word 207
|
||||
Reserved for CE-ATA
|
||||
*/
|
||||
uint16_t ReservedCEATAWord207;
|
||||
/*
|
||||
Word 208
|
||||
Reserved for CE-ATA
|
||||
*/
|
||||
uint16_t ReservedCEATAWord208;
|
||||
|
||||
/*
|
||||
Word 209
|
||||
Alignment of logical block within a larger physical block
|
||||
Bit 15 shall be cleared to zero
|
||||
Bit 14 shall be set to one
|
||||
Bits 13 to 0 indicate logical sector offset within the first physical sector
|
||||
*/
|
||||
uint16_t LogicalAlignment;
|
||||
|
||||
/*
|
||||
Words 210 to 211
|
||||
Write/Read/Verify sector count mode 3 only
|
||||
*/
|
||||
uint32_t WRVSectorCountMode3;
|
||||
/*
|
||||
Words 212 to 213
|
||||
Write/Read/Verify sector count mode 2 only
|
||||
*/
|
||||
uint32_t WRVSectorCountMode2;
|
||||
|
||||
/*
|
||||
Word 214
|
||||
NV Cache capabilities
|
||||
Bits 15 to 12 feature set version
|
||||
Bits 11 to 18 power mode feature set version
|
||||
Bits 7 to 5 reserved
|
||||
Bit 4 feature set enabled
|
||||
Bits 3 to 2 reserved
|
||||
Bit 1 power mode feature set enabled
|
||||
Bit 0 power mode feature set supported
|
||||
*/
|
||||
uint16_t NVCacheCaps;
|
||||
/*
|
||||
Words 215 to 216
|
||||
NV Cache Size in Logical BLocks
|
||||
*/
|
||||
uint32_t NVCacheSize;
|
||||
/*
|
||||
Word 217
|
||||
Nominal media rotation rate
|
||||
In ACS-1 meant NV Cache read speed in MB/s
|
||||
*/
|
||||
uint16_t NominalRotationRate;
|
||||
/*
|
||||
Word 218
|
||||
NV Cache write speed in MB/s
|
||||
Reserved since ACS-2
|
||||
*/
|
||||
uint16_t NVCacheWriteSpeed;
|
||||
/*
|
||||
Word 219 bits 7 to 0
|
||||
Estimated device spin up in seconds
|
||||
*/
|
||||
uint8_t NVEstimatedSpinUp;
|
||||
/*
|
||||
Word 219 bits 15 to 8
|
||||
NV Cache reserved
|
||||
*/
|
||||
uint8_t NVReserved;
|
||||
|
||||
/*
|
||||
Word 220 bits 7 to 0
|
||||
Write/Read/Verify feature set current mode
|
||||
*/
|
||||
uint8_t WRVMode;
|
||||
/*
|
||||
Word 220 bits 15 to 8
|
||||
Reserved
|
||||
*/
|
||||
uint8_t WRVReserved;
|
||||
|
||||
/*
|
||||
Word 221
|
||||
Reserved
|
||||
*/
|
||||
uint16_t ReservedWord221;
|
||||
|
||||
/*
|
||||
Word 222
|
||||
Transport major revision number
|
||||
Bits 15 to 12 indicate transport type. 0 parallel, 1 serial, 0xE PCIe.
|
||||
Bits 11 to 0 indicate revision
|
||||
*/
|
||||
uint16_t TransportMajorVersion;
|
||||
/*
|
||||
Word 223
|
||||
Transport minor revision number
|
||||
*/
|
||||
uint16_t TransportMinorVersion;
|
||||
|
||||
/*
|
||||
Words 224 to 229
|
||||
Reserved for CE-ATA
|
||||
*/
|
||||
uint16_t ReservedCEATA224[6];
|
||||
|
||||
/*
|
||||
Words 230 to 233
|
||||
48-bit LBA if Word 69 bit 3 is set
|
||||
*/
|
||||
uint64_t ExtendedUserSectors;
|
||||
|
||||
/*
|
||||
Word 234
|
||||
Minimum number of 512 byte units per DOWNLOAD MICROCODE mode 3
|
||||
*/
|
||||
uint16_t MinDownloadMicroMode3;
|
||||
/*
|
||||
Word 235
|
||||
Maximum number of 512 byte units per DOWNLOAD MICROCODE mode 3
|
||||
*/
|
||||
uint16_t MaxDownloadMicroMode3;
|
||||
|
||||
/*
|
||||
Words 236 to 254
|
||||
*/
|
||||
uint16_t ReservedWords[19];
|
||||
|
||||
/*
|
||||
Word 255 bits 7 to 0
|
||||
Should be 0xA5
|
||||
*/
|
||||
uint8_t Signature;
|
||||
/*
|
||||
Word 255 bits 15 to 8
|
||||
Checksum
|
||||
*/
|
||||
uint8_t Checksum;
|
||||
} IdentifyDevice;
|
||||
|
||||
unsigned char *AtaToCString(unsigned char *string, int len);
|
||||
|
||||
int SendAtaCommandChs(int fd, AtaRegistersCHS registers, AtaErrorRegistersCHS **errorRegisters, int protocol,
|
||||
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks);
|
||||
|
||||
int SendAtaCommandLba28(int fd, AtaRegistersLBA28 registers, AtaErrorRegistersLBA28 **errorRegisters, int protocol,
|
||||
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks);
|
||||
|
||||
int SendAtaCommandLba48(int fd, AtaRegistersLBA48 registers, AtaErrorRegistersLBA48 **errorRegisters, int protocol,
|
||||
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks);
|
||||
|
||||
int Identify(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegisters);
|
||||
|
||||
int
|
||||
Read(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head,
|
||||
uint8_t sector, uint8_t count);
|
||||
|
||||
int ReadLong(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder,
|
||||
uint8_t head, uint8_t sector, uint32_t blockSize);
|
||||
|
||||
int Seek(int fd, AtaErrorRegistersCHS **statusRegisters, uint16_t cylinder, uint8_t head, uint8_t sector);
|
||||
|
||||
int ReadDma(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder,
|
||||
uint8_t head, uint8_t sector, uint8_t count);
|
||||
|
||||
int ReadDmaLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
|
||||
uint8_t count);
|
||||
|
||||
int ReadLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
|
||||
uint8_t count);
|
||||
|
||||
int ReadLongLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
|
||||
uint32_t blockSize);
|
||||
|
||||
int SeekLba(int fd, AtaErrorRegistersLBA28 **statusRegisters, uint32_t lba);
|
||||
|
||||
int
|
||||
ReadDmaLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count);
|
||||
|
||||
int ReadLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count);
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_ATA_H
|
||||
@@ -1,812 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ata_report.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Creates report for ATA devices.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <libxml/xmlwriter.h>
|
||||
#include "ata_report.h"
|
||||
#include "ata.h"
|
||||
#include "identify_decode.h"
|
||||
|
||||
void AtaReport(int fd, xmlTextWriterPtr xmlWriter)
|
||||
{
|
||||
unsigned char *ata_ident = NULL;
|
||||
unsigned char *buffer = NULL;
|
||||
AtaErrorRegistersCHS *ata_error_chs;
|
||||
AtaErrorRegistersLBA28 *ata_error_lba;
|
||||
AtaErrorRegistersLBA48 *ata_error_lba48;
|
||||
int error;
|
||||
int removable = FALSE;
|
||||
char user_response = ' ';
|
||||
|
||||
printf("Querying ATA IDENTIFY...\n");
|
||||
error = Identify(fd, &ata_ident, &ata_error_chs);
|
||||
|
||||
if(error)
|
||||
{
|
||||
fprintf(stderr, "Error {0} requesting IDENTIFY DEVICE", error);
|
||||
return;
|
||||
}
|
||||
|
||||
IdentifyDevice *identify = malloc(512);
|
||||
memcpy(identify, ata_ident, 512);
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_ATA_REPORT_ELEMENT);
|
||||
|
||||
if(le16toh(identify->GeneralConfiguration) == 0x848A)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CompactFlash", "%s", "TRUE");
|
||||
removable = FALSE;
|
||||
}
|
||||
else if(identify->GeneralConfiguration & 0x0080)
|
||||
{
|
||||
do
|
||||
{
|
||||
printf("Is the media removable from the reading/writing elements (flash memories ARE NOT removable)? (Y/N): ");
|
||||
scanf("%c", &user_response);
|
||||
printf("\n");
|
||||
}while(user_response != 'Y' && user_response != 'y' && user_response != 'N' && user_response != 'n');
|
||||
|
||||
removable = (user_response == 'Y' || user_response == 'y');
|
||||
}
|
||||
|
||||
if(removable)
|
||||
{
|
||||
printf("Please remove any media from the device and press any key when it is out.\n");
|
||||
scanf("%c");
|
||||
printf("Querying ATA IDENTIFY...\n");
|
||||
error = Identify(fd, &ata_ident, &ata_error_chs);
|
||||
free(identify);
|
||||
identify = malloc(512);
|
||||
memcpy(identify, ata_ident, 512);
|
||||
}
|
||||
|
||||
if((uint64_t)*identify->AdditionalPID != 0 && (uint64_t)*identify->AdditionalPID != 0x2020202020202020)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "AdditionalPid", AtaToCString(identify->AdditionalPID, 8));
|
||||
if(identify->APIOSupported)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "APIOSupported",
|
||||
DecodeTransferMode(le16toh(identify->APIOSupported)));
|
||||
if(identify->BufferType)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferType", "%u", le16toh(identify->BufferType));
|
||||
if(identify->BufferSize)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferSize", "%u", le16toh(identify->BufferSize));
|
||||
if(identify->Capabilities)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities",
|
||||
DecodeCapabilities(le16toh(identify->Capabilities)));
|
||||
if(identify->Capabilities2)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities2",
|
||||
DecodeCapabilities2(le16toh(identify->Capabilities2)));
|
||||
if(identify->Capabilities3)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities3", DecodeCapabilities3(identify->Capabilities3));
|
||||
if(identify->CFAPowerMode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CFAPowerMode", "%u", le16toh(identify->CFAPowerMode));
|
||||
if(identify->CommandSet)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet", DecodeCommandSet(le16toh(identify->CommandSet)));
|
||||
if(identify->CommandSet2)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet2", DecodeCommandSet2(le16toh(identify->CommandSet2)));
|
||||
if(identify->CommandSet3)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet3", DecodeCommandSet3(le16toh(identify->CommandSet3)));
|
||||
if(identify->CommandSet4)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet4", DecodeCommandSet4(le16toh(identify->CommandSet4)));
|
||||
if(identify->CommandSet5)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet5", DecodeCommandSet5(le16toh(identify->CommandSet5)));
|
||||
if(identify->CurrentAAM)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAAM", "%u", identify->CurrentAAM);
|
||||
if(identify->CurrentAPM)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAPM", "%u", le16toh(identify->CurrentAPM));
|
||||
if(identify->DataSetMgmt)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DataSetMgmt", DecodeDataSetMgmt(le16toh(identify->DataSetMgmt)));
|
||||
if(identify->DataSetMgmtSize)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DataSetMgmtSize", "%u",
|
||||
le16toh(identify->DataSetMgmtSize));
|
||||
if(identify->DeviceFormFactor)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DeviceFormFactor",
|
||||
DecodeDeviceFormFactor(le16toh(identify->DeviceFormFactor)));
|
||||
if(identify->DMAActive)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMAActive", DecodeTransferMode(le16toh(identify->DMAActive)));
|
||||
if(identify->DMASupported)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMASupported",
|
||||
DecodeTransferMode(le16toh(identify->DMASupported)));
|
||||
if(identify->DMATransferTimingMode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DMATransferTimingMode", "%u",
|
||||
identify->DMATransferTimingMode);
|
||||
if(identify->EnhancedSecurityEraseTime)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "EnhancedSecurityEraseTime", "%u",
|
||||
le16toh(identify->EnhancedSecurityEraseTime));
|
||||
if(identify->EnabledCommandSet)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet",
|
||||
DecodeCommandSet(le16toh(identify->EnabledCommandSet)));
|
||||
if(identify->EnabledCommandSet2)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet2",
|
||||
DecodeCommandSet2(le16toh(identify->EnabledCommandSet2)));
|
||||
if(identify->EnabledCommandSet3)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet3",
|
||||
DecodeCommandSet3(le16toh(identify->EnabledCommandSet3)));
|
||||
if(identify->EnabledCommandSet4)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet4",
|
||||
DecodeCommandSet4(le16toh(identify->EnabledCommandSet4)));
|
||||
if(identify->EnabledSATAFeatures)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledSATAFeatures",
|
||||
DecodeSATAFeatures(le16toh(identify->EnabledSATAFeatures)));
|
||||
if(identify->ExtendedUserSectors)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ExtendedUserSectors", "%llu",
|
||||
le64toh(identify->ExtendedUserSectors));
|
||||
if(identify->FreeFallSensitivity)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "FreeFallSensitivity", "%u", identify->FreeFallSensitivity);
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "FirmwareRevision", AtaToCString(identify->FirmwareRevision, 8));
|
||||
if(identify->GeneralConfiguration)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "GeneralConfiguration",
|
||||
DecodeGeneralConfiguration(le16toh(identify->GeneralConfiguration)));
|
||||
if(identify->HardwareResetResult)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "HardwareResetResult", "%u",
|
||||
le16toh(identify->HardwareResetResult));
|
||||
if(identify->InterseekDelay)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "InterseekDelay", "%u", le16toh(identify->InterseekDelay));
|
||||
if(identify->MajorVersion)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MajorVersion",
|
||||
DecodeMajorVersion(le16toh(identify->MajorVersion)));
|
||||
if(identify->MasterPasswordRevisionCode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MasterPasswordRevisionCode", "%u",
|
||||
le16toh(identify->MasterPasswordRevisionCode));
|
||||
if(identify->MaxDownloadMicroMode3)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxDownloadMicroMode3", "%u",
|
||||
le16toh(identify->MaxDownloadMicroMode3));
|
||||
if(identify->MaxQueueDepth)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxQueueDepth", "%u", le16toh(identify->MaxQueueDepth));
|
||||
if(identify->MDMAActive)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMAActive", DecodeTransferMode(le16toh(identify->MDMAActive)));
|
||||
if(identify->MDMASupported)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMASupported",
|
||||
DecodeTransferMode(le16toh(identify->MDMASupported)));
|
||||
if(identify->MinDownloadMicroMode3)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinDownloadMicroMode3", "%u",
|
||||
le16toh(identify->MinDownloadMicroMode3));
|
||||
if(identify->MinMDMACycleTime)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinMDMACycleTime", "%u",
|
||||
le16toh(identify->MinMDMACycleTime));
|
||||
if(identify->MinorVersion)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinorVersion", "%u", le16toh(identify->MinorVersion));
|
||||
if(identify->MinPIOCycleTimeNoFlow)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeNoFlow", "%u",
|
||||
le16toh(identify->MinPIOCycleTimeNoFlow));
|
||||
if(identify->MinPIOCycleTimeFlow)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeFlow", "%u",
|
||||
le16toh(identify->MinPIOCycleTimeFlow));
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Model", AtaToCString(identify->Model, 40));
|
||||
if(identify->MultipleMaxSectors)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleMaxSectors", "%u", identify->MultipleMaxSectors);
|
||||
if(identify->MultipleSectorNumber)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleSectorNumber", "%u",
|
||||
identify->MultipleSectorNumber);
|
||||
if(identify->NVCacheCaps)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheCaps", "%u", le16toh(identify->NVCacheCaps));
|
||||
if(identify->NVCacheSize)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheSize", "%u", le32toh(identify->NVCacheSize));
|
||||
if(identify->NVCacheWriteSpeed)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheWriteSpeed", "%u",
|
||||
le16toh(identify->NVCacheWriteSpeed));
|
||||
if(identify->NVEstimatedSpinUp)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVEstimatedSpinUp", "%u", identify->NVEstimatedSpinUp);
|
||||
if(identify->PacketBusRelease)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PacketBusRelease", "%u",
|
||||
le16toh(identify->PacketBusRelease));
|
||||
if(identify->PIOTransferTimingMode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PIOTransferTimingMode", "%u",
|
||||
identify->PIOTransferTimingMode);
|
||||
if(identify->RecommendedAAM)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecommendedAAM", "%u", identify->RecommendedAAM);
|
||||
if(identify->RecMDMACycleTime)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecMDMACycleTime", "%u",
|
||||
le16toh(identify->RecMDMACycleTime));
|
||||
if(identify->RemovableStatusSet)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RemovableStatusSet", "%u",
|
||||
le16toh(identify->RemovableStatusSet));
|
||||
if(identify->SATACapabilities)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities",
|
||||
DecodeSATACapabilities(le16toh(identify->SATACapabilities)));
|
||||
if(identify->SATACapabilities2)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities2",
|
||||
DecodeSATACapabilities2(le16toh(identify->SATACapabilities2)));
|
||||
if(identify->SATAFeatures)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATAFeatures",
|
||||
DecodeSATAFeatures(le16toh(identify->SATAFeatures)));
|
||||
if(identify->SCTCommandTransport)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SCTCommandTransport",
|
||||
DecodeSCTCommandTransport(le16toh(identify->SCTCommandTransport)));
|
||||
if(identify->SectorsPerCard)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SectorsPerCard", "%u", le32toh(identify->SectorsPerCard));
|
||||
if(identify->SecurityEraseTime)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SecurityEraseTime", "%u",
|
||||
le16toh(identify->SecurityEraseTime));
|
||||
if(identify->SecurityStatus)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SecurityStatus",
|
||||
DecodeSecurityStatus(le16toh(identify->SecurityStatus)));
|
||||
if(identify->ServiceBusyClear)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ServiceBusyClear", "%u",
|
||||
le16toh(identify->ServiceBusyClear));
|
||||
if(identify->SpecificConfiguration)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SpecificConfiguration",
|
||||
DecodeSpecificConfiguration(le16toh(identify->SpecificConfiguration)));
|
||||
if(identify->StreamAccessLatency)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamAccessLatency", "%u",
|
||||
le16toh(identify->StreamAccessLatency));
|
||||
if(identify->StreamMinReqSize)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamMinReqSize", "%u",
|
||||
le16toh(identify->StreamMinReqSize));
|
||||
if(identify->StreamPerformanceGranularity)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamPerformanceGranularity", "%u",
|
||||
le32toh(identify->StreamPerformanceGranularity));
|
||||
if(identify->StreamTransferTimeDMA)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimeDMA", "%u",
|
||||
le16toh(identify->StreamTransferTimeDMA));
|
||||
if(identify->StreamTransferTimePIO)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimePIO", "%u",
|
||||
le16toh(identify->StreamTransferTimePIO));
|
||||
if(identify->TransportMajorVersion)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMajorVersion", "%u",
|
||||
le16toh(identify->TransportMajorVersion));
|
||||
if(identify->TransportMinorVersion)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMinorVersion", "%u",
|
||||
le16toh(identify->TransportMinorVersion));
|
||||
if(identify->TrustedComputing)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "TrustedComputing",
|
||||
DecodeTrustedComputing(le16toh(identify->TrustedComputing)));
|
||||
if(identify->UDMAActive)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMAActive", DecodeTransferMode(le16toh(identify->UDMAActive)));
|
||||
if(identify->UDMASupported)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMASupported",
|
||||
DecodeTransferMode(le16toh(identify->UDMASupported)));
|
||||
if(identify->WRVMode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVMode", "%u", identify->WRVMode);
|
||||
if(identify->WRVSectorCountMode3)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode3", "%u",
|
||||
le32toh(identify->WRVSectorCountMode3));
|
||||
if(identify->WRVSectorCountMode2)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode2", "%u",
|
||||
le32toh(identify->WRVSectorCountMode2));
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "Identify");
|
||||
xmlTextWriterWriteBase64(xmlWriter, ata_ident, 0, 512);
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
|
||||
if(removable)
|
||||
{
|
||||
user_response = ' ';
|
||||
int anyMedia = FALSE;
|
||||
|
||||
while(user_response != 'N' && user_response != 'n')
|
||||
{
|
||||
do
|
||||
{
|
||||
printf("Do you have media that you can insert in the drive? (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')
|
||||
{
|
||||
printf("Please insert it in the drive and press any key when it is ready.\n");
|
||||
scanf("%c");
|
||||
|
||||
char mediaManufacturer[256], mediaName[256], mediaModel[256];
|
||||
printf("Please write a description of the media type and press enter: ");
|
||||
gets(mediaName);
|
||||
printf("Please write the media manufacturer and press enter: ");
|
||||
gets(mediaManufacturer);
|
||||
printf("Please write the media model and press enter: ");
|
||||
gets(mediaModel);
|
||||
|
||||
error = Identify(fd, &ata_ident, &ata_error_chs);
|
||||
|
||||
if(!anyMedia)
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "RemovableMedias"); // <RemovableMedias>
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "testedMediaType"); // <testedMediaType>
|
||||
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediaIsRecognized", "%s",
|
||||
!error ? "TRUE" : "FALSE");
|
||||
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumTypeName", "%s", mediaName);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Model", "%s", mediaModel);
|
||||
|
||||
if(error)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", mediaManufacturer);
|
||||
xmlTextWriterEndElement(xmlWriter); // </testedMediaType>
|
||||
anyMedia = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
free(identify);
|
||||
identify = malloc(512);
|
||||
memcpy(identify, ata_ident, 512);
|
||||
|
||||
if(identify->UnformattedBPT)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPT", "%u",
|
||||
le16toh(identify->UnformattedBPT));
|
||||
if(identify->UnformattedBPS)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPS", "%u",
|
||||
le16toh(identify->UnformattedBPS));
|
||||
|
||||
uint64_t blocks = 0;
|
||||
|
||||
if(identify->Cylinders > 0 && identify->Heads > 0 && identify->SectorsPerTrack != 0)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "CHS"); // <CHS>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u",
|
||||
le16toh(identify->Cylinders));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->Heads));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u",
|
||||
le16toh(identify->SectorsPerTrack));
|
||||
blocks = le16toh(identify->Cylinders) * le16toh(identify->Heads) *
|
||||
le16toh(identify->SectorsPerTrack);
|
||||
xmlTextWriterEndElement(xmlWriter); // </CHS>
|
||||
}
|
||||
|
||||
if(identify->CurrentCylinders > 0 && identify->CurrentHeads > 0 &&
|
||||
identify->CurrentSectorsPerTrack != 0)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "CurrentCHS"); // <CurrentCHS>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u",
|
||||
le16toh(identify->CurrentCylinders));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->CurrentHeads));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u",
|
||||
le16toh(identify->CurrentSectorsPerTrack));
|
||||
if(blocks == 0)
|
||||
blocks = le16toh(identify->CurrentCylinders) * le16toh(identify->CurrentHeads) *
|
||||
le16toh(identify->CurrentSectorsPerTrack);
|
||||
xmlTextWriterEndElement(xmlWriter); // </CurrentCHS>
|
||||
}
|
||||
|
||||
if(le16toh(identify->Capabilities) & 0x0200)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBASectors", "%u",
|
||||
le32toh(identify->LBASectors));
|
||||
blocks = le32toh(identify->LBASectors);
|
||||
}
|
||||
|
||||
if(le16toh(identify->CommandSet2) & 0x0400)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBA48Sectors", "%llu",
|
||||
le64toh(identify->LBA48Sectors));
|
||||
blocks = le64toh(identify->LBA48Sectors);
|
||||
}
|
||||
|
||||
if(identify->NominalRotationRate != 0x0000 && identify->NominalRotationRate != 0xFFFF)
|
||||
{
|
||||
if(le16toh(identify->NominalRotationRate) == 0x0001)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE");
|
||||
else
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NominalRotationRate", "%u",
|
||||
le16toh(identify->NominalRotationRate));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t logicalsectorsize = 0;
|
||||
uint32_t physicalsectorsize = 0;
|
||||
|
||||
if((le16toh(identify->PhysLogSectorSize) & 0x8000) == 0x0000 &&
|
||||
(le16toh(identify->PhysLogSectorSize) & 0x4000) == 0x4000)
|
||||
{
|
||||
if(le16toh(identify->PhysLogSectorSize) & 0x1000)
|
||||
{
|
||||
if(le16toh(identify->LogicalSectorWords) <= 255 || identify->LogicalAlignment == 0xFFFF)
|
||||
logicalsectorsize = 512;
|
||||
else
|
||||
logicalsectorsize = le16toh(identify->LogicalSectorWords) * 2;
|
||||
}
|
||||
else
|
||||
logicalsectorsize = 512;
|
||||
|
||||
if(le16toh(identify->PhysLogSectorSize) & 0x2000)
|
||||
physicalsectorsize = logicalsectorsize * (1 << (le16toh(identify->PhysLogSectorSize) & 0xF));
|
||||
else
|
||||
physicalsectorsize = logicalsectorsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
logicalsectorsize = 512;
|
||||
physicalsectorsize = 512;
|
||||
}
|
||||
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSize", "%u", logicalsectorsize);
|
||||
if(physicalsectorsize != logicalsectorsize)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PhysicalBlockSize", "%u", physicalsectorsize);
|
||||
if((le16toh(identify->LogicalAlignment) & 0x8000) == 0x0000 &&
|
||||
(le16toh(identify->LogicalAlignment) & 0x4000) == 0x4000)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LogicalAlignment", "%u",
|
||||
le16toh(identify->LogicalAlignment) & 0x3FFF);
|
||||
}
|
||||
|
||||
uint16_t longblocksize = 0;
|
||||
if(identify->EccBytes != 0x0000 && identify->EccBytes != 0xFFFF)
|
||||
longblocksize = le16toh(identify->EccBytes);
|
||||
|
||||
if(le16toh(identify->UnformattedBPS) > logicalsectorsize &&
|
||||
(longblocksize == 0 || longblocksize == 516))
|
||||
longblocksize = le16toh(identify->UnformattedBPS);
|
||||
|
||||
if(longblocksize > 0)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%u", longblocksize);
|
||||
|
||||
if((le16toh(identify->CommandSet3) & 0x8000) == 0x0000 &&
|
||||
(le16toh(identify->CommandSet3) & 0x4000) == 0x4000 &&
|
||||
(le16toh(identify->EnabledCommandSet3) & 0x0004) == 0x0004)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CanReadMediaSerial", "%s", "TRUE");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s",
|
||||
AtaToCString(identify->MediaManufacturer, 20));
|
||||
}
|
||||
else
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", mediaManufacturer);
|
||||
|
||||
printf("Trying READ SECTOR(S) in CHS mode...\n");
|
||||
error = Read(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ SECTOR(S) RETRY in CHS mode...\n");
|
||||
error = Read(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetry", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA in CHS mode...\n");
|
||||
error = ReadDma(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDma", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA RETRY in CHS mode...\n");
|
||||
error = ReadDma(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetry", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying SEEK in CHS mode...\n");
|
||||
error = Seek(fd, &ata_error_chs, 0, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeek", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0) ? "true" : "false");
|
||||
|
||||
printf("Trying READ SECTOR(S) in LBA mode...\n");
|
||||
error = ReadLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ SECTOR(S) RETRY in LBA mode...\n");
|
||||
error = ReadLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetryLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA in LBA mode...\n");
|
||||
error = ReadDmaLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA RETRY in LBA mode...\n");
|
||||
error = ReadDmaLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetryLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying SEEK in LBA mode...\n");
|
||||
error = SeekLba(fd, &ata_error_lba, 0);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeekLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0) ? "true" : "false");
|
||||
|
||||
printf("Trying READ SECTOR(S) in LBA48 mode...\n");
|
||||
error = ReadLba48(fd, &buffer, &ata_error_lba48, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba48", "%s",
|
||||
(!error && (ata_error_lba48->status & 0x01) != 0x01 &&
|
||||
ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA in LBA48 mode...\n");
|
||||
error = ReadDmaLba48(fd, &buffer, &ata_error_lba48, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba48", "%s",
|
||||
(!error && (ata_error_lba48->status & 0x01) != 0x01 &&
|
||||
ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
|
||||
printf("Trying READ LONG in CHS mode...\n");
|
||||
error = ReadLong(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, longblocksize);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL &&
|
||||
(uint64_t)(*buffer) != 0) ? "true" : "false");
|
||||
|
||||
printf("Trying READ LONG RETRY in CHS mode...\n");
|
||||
error = ReadLong(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, longblocksize);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetry", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL &&
|
||||
(uint64_t)(*buffer) != 0) ? "true" : "false");
|
||||
|
||||
printf("Trying READ LONG in LBA mode...\n");
|
||||
error = ReadLongLba(fd, &buffer, &ata_error_lba, FALSE, 0, longblocksize);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL &&
|
||||
(uint64_t)(*buffer) != 0) ? "true" : "false");
|
||||
|
||||
printf("Trying READ LONG RETRY in LBA mode...\n");
|
||||
error = ReadLongLba(fd, &buffer, &ata_error_lba, TRUE, 0, longblocksize);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetryLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL &&
|
||||
(uint64_t)(*buffer) != 0) ? "true" : "false");
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </testedMediaType>
|
||||
|
||||
if(!anyMedia)
|
||||
anyMedia = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if(anyMedia)
|
||||
xmlTextWriterEndElement(xmlWriter); // </RemovableMedias>
|
||||
}
|
||||
else
|
||||
{
|
||||
error = Identify(fd, &ata_ident, &ata_error_chs);
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ReadCapabilities"); // <RemovableMedias>
|
||||
|
||||
free(identify);
|
||||
identify = malloc(512);
|
||||
memcpy(identify, ata_ident, 512);
|
||||
|
||||
if(identify->UnformattedBPT)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPT", "%u",
|
||||
le16toh(identify->UnformattedBPT));
|
||||
if(identify->UnformattedBPS)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPS", "%u",
|
||||
le16toh(identify->UnformattedBPS));
|
||||
|
||||
uint64_t blocks;
|
||||
|
||||
if(identify->Cylinders > 0 && identify->Heads > 0 && identify->SectorsPerTrack != 0)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "CHS"); // <CHS>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u", le16toh(identify->Cylinders));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->Heads));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u", le16toh(identify->SectorsPerTrack));
|
||||
blocks = le16toh(identify->Cylinders) * le16toh(identify->Heads) * le16toh(identify->SectorsPerTrack);
|
||||
xmlTextWriterEndElement(xmlWriter); // </CHS>
|
||||
}
|
||||
|
||||
if(identify->CurrentCylinders > 0 && identify->CurrentHeads > 0 && identify->CurrentSectorsPerTrack != 0)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "CurrentCHS"); // <CurrentCHS>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u", le16toh(identify->CurrentCylinders));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->CurrentHeads));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u",
|
||||
le16toh(identify->CurrentSectorsPerTrack));
|
||||
if(blocks == 0)
|
||||
blocks = le16toh(identify->CurrentCylinders) * le16toh(identify->CurrentHeads) *
|
||||
le16toh(identify->CurrentSectorsPerTrack);
|
||||
xmlTextWriterEndElement(xmlWriter); // </CurrentCHS>
|
||||
}
|
||||
|
||||
if(le16toh(identify->Capabilities) & 0x0200)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBASectors", "%u", le32toh(identify->LBASectors));
|
||||
blocks = le32toh(identify->LBASectors);
|
||||
}
|
||||
|
||||
if(le16toh(identify->CommandSet2) & 0x0400)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBA48Sectors", "%llu",
|
||||
le64toh(identify->LBA48Sectors));
|
||||
blocks = le64toh(identify->LBA48Sectors);
|
||||
}
|
||||
|
||||
if(identify->NominalRotationRate != 0x0000 && identify->NominalRotationRate != 0xFFFF)
|
||||
{
|
||||
if(le16toh(identify->NominalRotationRate) == 0x0001)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE");
|
||||
else
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NominalRotationRate", "%u",
|
||||
le16toh(identify->NominalRotationRate));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t logicalsectorsize = 0;
|
||||
uint32_t physicalsectorsize = 0;
|
||||
|
||||
if((le16toh(identify->PhysLogSectorSize) & 0x8000) == 0x0000 &&
|
||||
(le16toh(identify->PhysLogSectorSize) & 0x4000) == 0x4000)
|
||||
{
|
||||
if(le16toh(identify->PhysLogSectorSize) & 0x1000)
|
||||
{
|
||||
if(le16toh(identify->LogicalSectorWords) <= 255 || identify->LogicalAlignment == 0xFFFF)
|
||||
logicalsectorsize = 512;
|
||||
else
|
||||
logicalsectorsize = le16toh(identify->LogicalSectorWords) * 2;
|
||||
}
|
||||
else
|
||||
logicalsectorsize = 512;
|
||||
|
||||
if(le16toh(identify->PhysLogSectorSize) & 0x2000)
|
||||
physicalsectorsize = logicalsectorsize * (1 << (le16toh(identify->PhysLogSectorSize) & 0xF));
|
||||
else
|
||||
physicalsectorsize = logicalsectorsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
logicalsectorsize = 512;
|
||||
physicalsectorsize = 512;
|
||||
}
|
||||
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSize", "%u", logicalsectorsize);
|
||||
if(physicalsectorsize != logicalsectorsize)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PhysicalBlockSize", "%u", physicalsectorsize);
|
||||
if((le16toh(identify->LogicalAlignment) & 0x8000) == 0x0000 &&
|
||||
(le16toh(identify->LogicalAlignment) & 0x4000) == 0x4000)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LogicalAlignment", "%u",
|
||||
le16toh(identify->LogicalAlignment) & 0x3FFF);
|
||||
}
|
||||
|
||||
uint16_t longblocksize = 0;
|
||||
if(identify->EccBytes != 0x0000 && identify->EccBytes != 0xFFFF)
|
||||
longblocksize = le16toh(identify->EccBytes);
|
||||
|
||||
if(le16toh(identify->UnformattedBPS) > logicalsectorsize && (longblocksize == 0 || longblocksize == 516))
|
||||
longblocksize = le16toh(identify->UnformattedBPS);
|
||||
|
||||
if(longblocksize > 0)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%u", longblocksize);
|
||||
|
||||
if((le16toh(identify->CommandSet3) & 0x8000) == 0x0000 && (le16toh(identify->CommandSet3) & 0x4000) == 0x4000 &&
|
||||
(le16toh(identify->EnabledCommandSet3) & 0x0004) == 0x0004)
|
||||
{
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CanReadMediaSerial", "%s", "TRUE");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s",
|
||||
AtaToCString(identify->MediaManufacturer, 20));
|
||||
}
|
||||
|
||||
printf("Trying READ SECTOR(S) in CHS mode...\n");
|
||||
error = Read(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ SECTOR(S) RETRY in CHS mode...\n");
|
||||
error = Read(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetry", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA in CHS mode...\n");
|
||||
error = ReadDma(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDma", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA RETRY in CHS mode...\n");
|
||||
error = ReadDma(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetry", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying SEEK in CHS mode...\n");
|
||||
error = Seek(fd, &ata_error_chs, 0, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeek", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0)
|
||||
? "true" : "false");
|
||||
|
||||
printf("Trying READ SECTOR(S) in LBA mode...\n");
|
||||
error = ReadLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ SECTOR(S) RETRY in LBA mode...\n");
|
||||
error = ReadLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetryLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA in LBA mode...\n");
|
||||
error = ReadDmaLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA RETRY in LBA mode...\n");
|
||||
error = ReadDmaLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetryLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying SEEK in LBA mode...\n");
|
||||
error = SeekLba(fd, &ata_error_lba, 0);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeekLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0)
|
||||
? "true" : "false");
|
||||
|
||||
printf("Trying READ SECTOR(S) in LBA48 mode...\n");
|
||||
error = ReadLba48(fd, &buffer, &ata_error_lba48, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba48", "%s",
|
||||
(!error && (ata_error_lba48->status & 0x01) != 0x01 &&
|
||||
ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
printf("Trying READ DMA in LBA48 mode...\n");
|
||||
error = ReadDmaLba48(fd, &buffer, &ata_error_lba48, 0, 1);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba48", "%s",
|
||||
(!error && (ata_error_lba48->status & 0x01) != 0x01 &&
|
||||
ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false");
|
||||
|
||||
|
||||
printf("Trying READ LONG in CHS mode...\n");
|
||||
error = ReadLong(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, longblocksize);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0)
|
||||
? "true" : "false");
|
||||
|
||||
printf("Trying READ LONG RETRY in CHS mode...\n");
|
||||
error = ReadLong(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, longblocksize);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetry", "%s",
|
||||
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
|
||||
ata_error_chs->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0)
|
||||
? "true" : "false");
|
||||
|
||||
printf("Trying READ LONG in LBA mode...\n");
|
||||
error = ReadLongLba(fd, &buffer, &ata_error_lba, FALSE, 0, longblocksize);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0)
|
||||
? "true" : "false");
|
||||
|
||||
printf("Trying READ LONG RETRY in LBA mode...\n");
|
||||
error = ReadLongLba(fd, &buffer, &ata_error_lba, TRUE, 0, longblocksize);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetryLba", "%s",
|
||||
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
|
||||
ata_error_lba->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0)
|
||||
? "true" : "false");
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </ReadCapabilities>
|
||||
}
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ata_report.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains definitions used in ATA reports.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_ATA_REPORT_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_ATA_REPORT_H
|
||||
#define DIC_ATA_REPORT_ELEMENT "ATA"
|
||||
|
||||
void AtaReport(int fd, xmlTextWriterPtr xmlWriter);
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_ATA_REPORT_H
|
||||
@@ -1,52 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : atapi.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains ATAPI commands.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "ata.h"
|
||||
#include "atapi.h"
|
||||
|
||||
int IdentifyPacket(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegisters)
|
||||
{
|
||||
*buffer = malloc(512);
|
||||
memset(*buffer, 0, 512);
|
||||
AtaRegistersCHS registers;
|
||||
memset(®isters, 0, sizeof(AtaRegistersCHS));
|
||||
|
||||
registers.command = ATA_IDENTIFY_PACKET_DEVICE;
|
||||
|
||||
int error = SendAtaCommandChs(fd, registers, errorRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_NONE, *buffer, 512,
|
||||
0);
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : atapi.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains ATAPI definitions.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_ATAPI_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_ATAPI_H
|
||||
|
||||
int IdentifyPacket(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegisters);
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_ATAPI_H
|
||||
@@ -1,272 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : atapi_report.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Creates report for ATAPI devices.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <libxml/xmlwriter.h>
|
||||
#include "atapi_report.h"
|
||||
#include "ata.h"
|
||||
#include "atapi.h"
|
||||
#include "identify_decode.h"
|
||||
|
||||
void AtapiReport(int fd, xmlTextWriterPtr xmlWriter)
|
||||
{
|
||||
unsigned char *atapi_ident = NULL;
|
||||
AtaErrorRegistersCHS *ata_error_chs;
|
||||
int error;
|
||||
|
||||
printf("Querying ATAPI IDENTIFY...\n");
|
||||
|
||||
error = IdentifyPacket(fd, &atapi_ident, &ata_error_chs);
|
||||
|
||||
if(error)
|
||||
{
|
||||
fprintf(stderr, "Error {0} requesting IDENTIFY PACKET DEVICE", error);
|
||||
return;
|
||||
}
|
||||
|
||||
IdentifyDevice *identify = malloc(512);
|
||||
memcpy(identify, atapi_ident, 512);
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_ATAPI_REPORT_ELEMENT); // <ATA>
|
||||
|
||||
if((uint64_t)*identify->AdditionalPID != 0 && (uint64_t)*identify->AdditionalPID != 0x2020202020202020)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "AdditionalPid", AtaToCString(identify->AdditionalPID, 8));
|
||||
if(identify->APIOSupported)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "APIOSupported",
|
||||
DecodeTransferMode(le16toh(identify->APIOSupported)));
|
||||
if(identify->ATAPIByteCount)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ATAPIByteCount", "%u", le16toh(identify->ATAPIByteCount));
|
||||
if(identify->BufferType)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferType", "%u", le16toh(identify->BufferType));
|
||||
if(identify->BufferSize)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferSize", "%u", le16toh(identify->BufferSize));
|
||||
if(identify->Capabilities)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities",
|
||||
DecodeCapabilities(le16toh(identify->Capabilities)));
|
||||
if(identify->Capabilities2)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities2",
|
||||
DecodeCapabilities2(le16toh(identify->Capabilities2)));
|
||||
if(identify->Capabilities3)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities3", DecodeCapabilities3(identify->Capabilities3));
|
||||
if(identify->CFAPowerMode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CFAPowerMode", "%u", le16toh(identify->CFAPowerMode));
|
||||
if(identify->CommandSet)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet", DecodeCommandSet(le16toh(identify->CommandSet)));
|
||||
if(identify->CommandSet2)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet2", DecodeCommandSet2(le16toh(identify->CommandSet2)));
|
||||
if(identify->CommandSet3)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet3", DecodeCommandSet3(le16toh(identify->CommandSet3)));
|
||||
if(identify->CommandSet4)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet4", DecodeCommandSet4(le16toh(identify->CommandSet4)));
|
||||
if(identify->CommandSet5)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet5", DecodeCommandSet5(le16toh(identify->CommandSet5)));
|
||||
if(identify->CurrentAAM)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAAM", "%u", identify->CurrentAAM);
|
||||
if(identify->CurrentAPM)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAPM", "%u", le16toh(identify->CurrentAPM));
|
||||
if(identify->DataSetMgmt)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DataSetMgmt", DecodeDataSetMgmt(le16toh(identify->DataSetMgmt)));
|
||||
if(identify->DataSetMgmtSize)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DataSetMgmtSize", "%u",
|
||||
le16toh(identify->DataSetMgmtSize));
|
||||
if(identify->DeviceFormFactor)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DeviceFormFactor",
|
||||
DecodeDeviceFormFactor(le16toh(identify->DeviceFormFactor)));
|
||||
if(identify->DMAActive)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMAActive", DecodeTransferMode(le16toh(identify->DMAActive)));
|
||||
if(identify->DMASupported)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMASupported",
|
||||
DecodeTransferMode(le16toh(identify->DMASupported)));
|
||||
if(identify->DMATransferTimingMode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DMATransferTimingMode", "%u",
|
||||
identify->DMATransferTimingMode);
|
||||
if(identify->EnhancedSecurityEraseTime)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "EnhancedSecurityEraseTime", "%u",
|
||||
le16toh(identify->EnhancedSecurityEraseTime));
|
||||
if(identify->EnabledCommandSet)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet",
|
||||
DecodeCommandSet(le16toh(identify->EnabledCommandSet)));
|
||||
if(identify->EnabledCommandSet2)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet2",
|
||||
DecodeCommandSet2(le16toh(identify->EnabledCommandSet2)));
|
||||
if(identify->EnabledCommandSet3)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet3",
|
||||
DecodeCommandSet3(le16toh(identify->EnabledCommandSet3)));
|
||||
if(identify->EnabledCommandSet4)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet4",
|
||||
DecodeCommandSet4(le16toh(identify->EnabledCommandSet4)));
|
||||
if(identify->EnabledSATAFeatures)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledSATAFeatures",
|
||||
DecodeSATAFeatures(le16toh(identify->EnabledSATAFeatures)));
|
||||
if(identify->ExtendedUserSectors)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ExtendedUserSectors", "%llu",
|
||||
le64toh(identify->ExtendedUserSectors));
|
||||
if(identify->FreeFallSensitivity)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "FreeFallSensitivity", "%u", identify->FreeFallSensitivity);
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "FirmwareRevision", AtaToCString(identify->FirmwareRevision, 8));
|
||||
if(identify->GeneralConfiguration)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "GeneralConfiguration",
|
||||
DecodeGeneralConfiguration(le16toh(identify->GeneralConfiguration)));
|
||||
if(identify->HardwareResetResult)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "HardwareResetResult", "%u",
|
||||
le16toh(identify->HardwareResetResult));
|
||||
if(identify->InterseekDelay)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "InterseekDelay", "%u", le16toh(identify->InterseekDelay));
|
||||
if(identify->MajorVersion)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MajorVersion",
|
||||
DecodeMajorVersion(le16toh(identify->MajorVersion)));
|
||||
if(identify->MasterPasswordRevisionCode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MasterPasswordRevisionCode", "%u",
|
||||
le16toh(identify->MasterPasswordRevisionCode));
|
||||
if(identify->MaxDownloadMicroMode3)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxDownloadMicroMode3", "%u",
|
||||
le16toh(identify->MaxDownloadMicroMode3));
|
||||
if(identify->MaxQueueDepth)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxQueueDepth", "%u", le16toh(identify->MaxQueueDepth));
|
||||
if(identify->MDMAActive)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMAActive", DecodeTransferMode(le16toh(identify->MDMAActive)));
|
||||
if(identify->MDMASupported)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMASupported",
|
||||
DecodeTransferMode(le16toh(identify->MDMASupported)));
|
||||
if(identify->MinDownloadMicroMode3)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinDownloadMicroMode3", "%u",
|
||||
le16toh(identify->MinDownloadMicroMode3));
|
||||
if(identify->MinMDMACycleTime)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinMDMACycleTime", "%u",
|
||||
le16toh(identify->MinMDMACycleTime));
|
||||
if(identify->MinorVersion)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinorVersion", "%u", le16toh(identify->MinorVersion));
|
||||
if(identify->MinPIOCycleTimeNoFlow)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeNoFlow", "%u",
|
||||
le16toh(identify->MinPIOCycleTimeNoFlow));
|
||||
if(identify->MinPIOCycleTimeFlow)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeFlow", "%u",
|
||||
le16toh(identify->MinPIOCycleTimeFlow));
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Model", AtaToCString(identify->Model, 40));
|
||||
if(identify->MultipleMaxSectors)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleMaxSectors", "%u", identify->MultipleMaxSectors);
|
||||
if(identify->MultipleSectorNumber)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleSectorNumber", "%u",
|
||||
identify->MultipleSectorNumber);
|
||||
if(identify->NVCacheCaps)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheCaps", "%u", le16toh(identify->NVCacheCaps));
|
||||
if(identify->NVCacheSize)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheSize", "%u", le32toh(identify->NVCacheSize));
|
||||
if(identify->NVCacheWriteSpeed)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheWriteSpeed", "%u",
|
||||
le16toh(identify->NVCacheWriteSpeed));
|
||||
if(identify->NVEstimatedSpinUp)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVEstimatedSpinUp", "%u", identify->NVEstimatedSpinUp);
|
||||
if(identify->PacketBusRelease)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PacketBusRelease", "%u",
|
||||
le16toh(identify->PacketBusRelease));
|
||||
if(identify->PIOTransferTimingMode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PIOTransferTimingMode", "%u",
|
||||
identify->PIOTransferTimingMode);
|
||||
if(identify->RecommendedAAM)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecommendedAAM", "%u", identify->RecommendedAAM);
|
||||
if(identify->RecMDMACycleTime)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecMDMACycleTime", "%u",
|
||||
le16toh(identify->RecMDMACycleTime));
|
||||
if(identify->RemovableStatusSet)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RemovableStatusSet", "%u",
|
||||
le16toh(identify->RemovableStatusSet));
|
||||
if(identify->SATACapabilities)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities",
|
||||
DecodeSATACapabilities(le16toh(identify->SATACapabilities)));
|
||||
if(identify->SATACapabilities2)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities2",
|
||||
DecodeSATACapabilities2(le16toh(identify->SATACapabilities2)));
|
||||
if(identify->SATAFeatures)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATAFeatures",
|
||||
DecodeSATAFeatures(le16toh(identify->SATAFeatures)));
|
||||
if(identify->SCTCommandTransport)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SCTCommandTransport",
|
||||
DecodeSCTCommandTransport(le16toh(identify->SCTCommandTransport)));
|
||||
if(identify->SectorsPerCard)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SectorsPerCard", "%u", le32toh(identify->SectorsPerCard));
|
||||
if(identify->SecurityEraseTime)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SecurityEraseTime", "%u",
|
||||
le16toh(identify->SecurityEraseTime));
|
||||
if(identify->SecurityStatus)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SecurityStatus",
|
||||
DecodeSecurityStatus(le16toh(identify->SecurityStatus)));
|
||||
if(identify->ServiceBusyClear)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ServiceBusyClear", "%u",
|
||||
le16toh(identify->ServiceBusyClear));
|
||||
if(identify->SpecificConfiguration)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SpecificConfiguration",
|
||||
DecodeSpecificConfiguration(le16toh(identify->SpecificConfiguration)));
|
||||
if(identify->StreamAccessLatency)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamAccessLatency", "%u",
|
||||
le16toh(identify->StreamAccessLatency));
|
||||
if(identify->StreamMinReqSize)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamMinReqSize", "%u",
|
||||
le16toh(identify->StreamMinReqSize));
|
||||
if(identify->StreamPerformanceGranularity)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamPerformanceGranularity", "%u",
|
||||
le32toh(identify->StreamPerformanceGranularity));
|
||||
if(identify->StreamTransferTimeDMA)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimeDMA", "%u",
|
||||
le16toh(identify->StreamTransferTimeDMA));
|
||||
if(identify->StreamTransferTimePIO)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimePIO", "%u",
|
||||
le16toh(identify->StreamTransferTimePIO));
|
||||
if(identify->TransportMajorVersion)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMajorVersion", "%u",
|
||||
le16toh(identify->TransportMajorVersion));
|
||||
if(identify->TransportMinorVersion)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMinorVersion", "%u",
|
||||
le16toh(identify->TransportMinorVersion));
|
||||
if(identify->TrustedComputing)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "TrustedComputing",
|
||||
DecodeTrustedComputing(le16toh(identify->TrustedComputing)));
|
||||
if(identify->UDMAActive)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMAActive", DecodeTransferMode(le16toh(identify->UDMAActive)));
|
||||
if(identify->UDMASupported)
|
||||
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMASupported",
|
||||
DecodeTransferMode(le16toh(identify->UDMASupported)));
|
||||
if(identify->WRVMode)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVMode", "%u", identify->WRVMode);
|
||||
if(identify->WRVSectorCountMode3)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode3", "%u",
|
||||
le32toh(identify->WRVSectorCountMode3));
|
||||
if(identify->WRVSectorCountMode2)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode2", "%u",
|
||||
le32toh(identify->WRVSectorCountMode2));
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "Identify"); // <Identify>
|
||||
xmlTextWriterWriteBase64(xmlWriter, atapi_ident, 0, 512);
|
||||
xmlTextWriterEndElement(xmlWriter); // </Identify>
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </ATA>
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : atapi_report.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains definitions used in ATAPI reports.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_ATAPI_REPORT_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_ATAPI_REPORT_H
|
||||
|
||||
#define DIC_ATAPI_REPORT_ELEMENT "ATAPI"
|
||||
|
||||
void AtapiReport(int fd, xmlTextWriterPtr xmlWriter);
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_ATAPI_REPORT_H
|
||||
@@ -1,142 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : cdrom_mode.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains definitions for CD-ROM MODE PAGE (2Ah).
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_CDROM_MODE_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_CDROM_MODE_H
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Reserved1;
|
||||
uint8_t RotationControl : 3;
|
||||
uint8_t Reserved2 : 5;
|
||||
uint16_t WriteSpeed;
|
||||
} ModePage_2A_WriteDescriptor;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t PageCode : 6;
|
||||
uint8_t Reserved1 : 1;
|
||||
/* Parameters can be saved */
|
||||
uint8_t PS : 1;
|
||||
uint8_t PageLength;
|
||||
uint8_t ReadCDR : 1;
|
||||
uint8_t ReadCDRW : 1;
|
||||
uint8_t Method2 : 1;
|
||||
uint8_t ReadDVDROM : 1;
|
||||
uint8_t ReadDVDR : 1;
|
||||
uint8_t ReadDVDRAM : 1;
|
||||
uint8_t Reserved2 : 2;
|
||||
uint8_t WriteCDR : 1;
|
||||
uint8_t WriteCDRW : 1;
|
||||
uint8_t TestWrite : 1;
|
||||
uint8_t Reserved3 : 1;
|
||||
uint8_t WriteDVDR : 1;
|
||||
uint8_t WriteDVDRAM : 1;
|
||||
uint8_t Reserved4 : 2;
|
||||
/* Drive is capable of playing audio */
|
||||
uint8_t AudioPlay : 1;
|
||||
uint8_t Composite : 1;
|
||||
uint8_t DigitalPort1 : 1;
|
||||
uint8_t DigitalPort2 : 1;
|
||||
/* Drive is capable of reading sectors in Mode 2 Form 1 format */
|
||||
uint8_t Mode2Form1 : 1;
|
||||
/* Drive is capable of reading sectors in Mode 2 Form 2 format */
|
||||
uint8_t Mode2Form2 : 1;
|
||||
/* Drive supports multi-session and/or Photo-CD */
|
||||
uint8_t MultiSession : 1;
|
||||
uint8_t BUF : 1;
|
||||
/* Audio can be read as digital data */
|
||||
uint8_t CDDACommand : 1;
|
||||
/* Drive can continue from a loss of streaming on audio reading */
|
||||
uint8_t AccurateCDDA : 1;
|
||||
/* Drive can read interleaved and uncorrected R-W subchannels */
|
||||
uint8_t Subchannel : 1;
|
||||
/* Drive can read, deinterlave and correct R-W subchannels */
|
||||
uint8_t DeinterlaveSubchannel : 1;
|
||||
/* Drive can return C2 pointers */
|
||||
uint8_t C2Pointer : 1;
|
||||
/* Drive can return the media catalogue number */
|
||||
uint8_t UPC : 1;
|
||||
/* Drive can return the ISRC */
|
||||
uint8_t ISRC : 1;
|
||||
uint8_t ReadBarcode : 1;
|
||||
/* Drive can lock media */
|
||||
uint8_t Lock : 1;
|
||||
/* Current lock status */
|
||||
uint8_t LockState : 1;
|
||||
/* Drive's optional prevent jumper status */
|
||||
uint8_t PreventJumper : 1;
|
||||
/* Drive can eject discs */
|
||||
uint8_t Eject : 1;
|
||||
uint8_t Reserved5 : 1;
|
||||
/* Loading Mechanism Type */
|
||||
uint8_t LoadingMechanism : 3;
|
||||
/* Each channel's volume can be controlled independently */
|
||||
uint8_t SeparateChannelVolume : 1;
|
||||
/* Each channel can be muted independently */
|
||||
uint8_t SeparateChannelMute : 1;
|
||||
uint8_t SDP : 1;
|
||||
uint8_t SSS : 1;
|
||||
uint8_t SCC : 1;
|
||||
uint8_t LeadInPW : 1;
|
||||
uint8_t Reserved6 : 2;
|
||||
/* Maximum drive speed in Kbytes/second */
|
||||
uint16_t MaximumSpeed;
|
||||
/* Supported volume levels */
|
||||
uint16_t SupportedVolumeLevels;
|
||||
/* Buffer size in Kbytes */
|
||||
uint16_t BufferSize;
|
||||
/* Current drive speed in Kbytes/second */
|
||||
uint16_t CurrentSpeed;
|
||||
uint8_t Reserved7;
|
||||
uint8_t Reserved8 : 1;
|
||||
uint8_t BCK : 1;
|
||||
uint8_t RCK : 1;
|
||||
uint8_t LSBF : 1;
|
||||
uint8_t Length : 2;
|
||||
uint8_t Reserved9 : 2;
|
||||
uint16_t MaxWriteSpeed;
|
||||
uint16_t CurrentWriteSpeed;
|
||||
uint16_t CMRSupported;
|
||||
uint8_t Reserved10[3];
|
||||
uint8_t RotationControlSelected : 2;
|
||||
uint8_t Reserved11 : 6;
|
||||
uint16_t CurrentWriteSpeedSelected;
|
||||
uint16_t LogicalWriteSpeedDescriptors;
|
||||
ModePage_2A_WriteDescriptor WriteSpeedPerformanceDescriptors[56];
|
||||
} ModePage_2A;
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_CDROM_MODE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,76 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : identify_decode.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains definitions for ATA IDENTIFY (PACKET) DEVICE structure.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_IDENTIFY_DECODE_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_IDENTIFY_DECODE_H
|
||||
|
||||
char *DecodeGeneralConfiguration(uint16_t configuration);
|
||||
|
||||
char *DecodeTransferMode(uint16_t transferMode);
|
||||
|
||||
char *DecodeCapabilities(uint16_t capabilities);
|
||||
|
||||
char *DecodeCapabilities2(uint16_t capabilities);
|
||||
|
||||
char *DecodeCapabilities3(uint8_t capabilities);
|
||||
|
||||
char *DecodeCommandSet(uint16_t commandset);
|
||||
|
||||
char *DecodeCommandSet2(uint16_t commandset);
|
||||
|
||||
char *DecodeCommandSet3(uint16_t commandset);
|
||||
|
||||
char *DecodeCommandSet4(uint16_t commandset);
|
||||
|
||||
char *DecodeCommandSet5(uint16_t commandset);
|
||||
|
||||
char *DecodeDataSetMgmt(uint16_t datasetmgmt);
|
||||
|
||||
char *DecodeDeviceFormFactor(uint16_t formfactor);
|
||||
|
||||
char *DecodeSATAFeatures(uint16_t features);
|
||||
|
||||
char *DecodeMajorVersion(uint16_t capabilities);
|
||||
|
||||
char *DecodeSATACapabilities(uint16_t capabilities);
|
||||
|
||||
char *DecodeSATACapabilities2(uint16_t transport);
|
||||
|
||||
char *DecodeSCTCommandTransport(uint16_t transport);
|
||||
|
||||
char *DecodeSecurityStatus(uint16_t status);
|
||||
|
||||
char *DecodeSpecificConfiguration(uint16_t configuration);
|
||||
|
||||
char *DecodeTrustedComputing(uint16_t trutedcomputing);
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_IDENTIFY_DECODE_H
|
||||
@@ -1,141 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : inquiry_decode.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains decoders for SCSI INQUIRY structure.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "inquiry_decode.h"
|
||||
|
||||
char *DecodeTPGSValues(uint8_t capabilities)
|
||||
{
|
||||
switch(capabilities)
|
||||
{
|
||||
case 0:
|
||||
return "NotSupported";
|
||||
case 1:
|
||||
return "OnlyImplicit";
|
||||
case 2:
|
||||
return "OnlyExplicit";
|
||||
case 3:
|
||||
return "Both";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *DecodePeripheralDeviceType(uint8_t type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case 0x00:
|
||||
return "DirectAccess";
|
||||
case 0x01:
|
||||
return "SequentialAccess";
|
||||
case 0x02:
|
||||
return "PrinterDevice";
|
||||
case 0x03:
|
||||
return "ProcessorDevice";
|
||||
case 0x04:
|
||||
return "WriteOnceDevice";
|
||||
case 0x05:
|
||||
return "MultiMediaDevice";
|
||||
case 0x06:
|
||||
return "ScannerDevice";
|
||||
case 0x07:
|
||||
return "OpticalDevice";
|
||||
case 0x08:
|
||||
return "MediumChangerDevice";
|
||||
case 0x09:
|
||||
return "CommsDevice";
|
||||
case 0x0A:
|
||||
return "PrePressDevice1";
|
||||
case 0x0B:
|
||||
return "PrePressDevice2";
|
||||
case 0x0C:
|
||||
return "ArrayControllerDevice";
|
||||
case 0x0D:
|
||||
return "EnclosureServiceDevice";
|
||||
case 0x0E:
|
||||
return "SimplifiedDevice";
|
||||
case 0x0F:
|
||||
return "OCRWDevice";
|
||||
case 0x10:
|
||||
return "BridgingExpander";
|
||||
case 0x11:
|
||||
return "ObjectDevice";
|
||||
case 0x12:
|
||||
return "ADCDevice";
|
||||
case 0x13:
|
||||
return "SCSISecurityManagerDevice";
|
||||
case 0x14:
|
||||
return "SCSIZonedBlockDevice";
|
||||
case 0x1E:
|
||||
return "WellKnownDevice";
|
||||
case 0x1F:
|
||||
return "UnknownDevice";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *DecodePeripheralQualifier(uint8_t qualifier)
|
||||
{
|
||||
switch(qualifier)
|
||||
{
|
||||
case 0:
|
||||
return "Supported";
|
||||
case 1:
|
||||
return "Unconnected";
|
||||
case 2:
|
||||
return "Reserved";
|
||||
case 3:
|
||||
return "Unsupported";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *DecodeSPIClocking(uint8_t qualifier)
|
||||
{
|
||||
switch(qualifier)
|
||||
{
|
||||
case 0:
|
||||
return "ST";
|
||||
case 1:
|
||||
return "DT";
|
||||
case 2:
|
||||
return "Reserved";
|
||||
case 3:
|
||||
return "StandDT";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : inquiry_decode.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains definitions for SCSI INQUIRY structure.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_INQUIRY_DECODE_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_INQUIRY_DECODE_H
|
||||
|
||||
char *DecodeTPGSValues(uint8_t capabilities);
|
||||
|
||||
char *DecodePeripheralDeviceType(uint8_t capabilities);
|
||||
|
||||
char *DecodePeripheralQualifier(uint8_t capabilities);
|
||||
|
||||
char *DecodeSPIClocking(uint8_t capabilities);
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_INQUIRY_DECODE_H
|
||||
@@ -1,186 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : main.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
For Linux, opens a device and generates a report, without needing a .NET
|
||||
environment, for systems that don't have it.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <malloc.h>
|
||||
#include <libxml/xmlwriter.h>
|
||||
#include "main.h"
|
||||
#include "scsi.h"
|
||||
#include "ata.h"
|
||||
#include "atapi.h"
|
||||
#include "atapi_report.h"
|
||||
#include "scsi_report.h"
|
||||
#include "ata_report.h"
|
||||
|
||||
int main(int argc, void *argv[])
|
||||
{
|
||||
int fd, rc;
|
||||
unsigned char *scsi_sense = NULL;
|
||||
unsigned char *scsi_inq_data = NULL;
|
||||
unsigned char *ata_ident = NULL;
|
||||
unsigned char *atapi_ident = NULL;
|
||||
AtaErrorRegistersCHS *ata_error_chs;
|
||||
int scsi_error, ata_error;
|
||||
unsigned char *manufacturer;
|
||||
unsigned char *product;
|
||||
unsigned char *revision;
|
||||
int deviceType = DEVICE_TYPE_UNKNOWN;
|
||||
char *xmlFilename = malloc(NAME_MAX + 1);
|
||||
xmlTextWriterPtr xmlWriter;
|
||||
const char *ataName = "ATA";
|
||||
|
||||
printf("The Disc Image Chef Device Reporter for Linux %s\n", DIC_VERSION);
|
||||
printf("%s\n", DIC_COPYRIGHT);
|
||||
|
||||
if(argc != 2)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf("%s <device_path>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = open(argv[1], O_RDONLY | O_NONBLOCK);
|
||||
|
||||
if(fd < 0)
|
||||
{
|
||||
printf("Error opening device: %s\n", strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
|
||||
// TODO: Support MMC, USB, FireWire, PCMCIA
|
||||
|
||||
scsi_error = Inquiry(fd, &scsi_inq_data, &scsi_sense);
|
||||
|
||||
if(scsi_error)
|
||||
scsi_inq_data = NULL;
|
||||
|
||||
if(scsi_inq_data != NULL)
|
||||
{
|
||||
manufacturer = malloc(9);
|
||||
manufacturer[8] = 0;
|
||||
product = malloc(17);
|
||||
product[16] = 0;
|
||||
revision = malloc(5);
|
||||
revision[4] = 0;
|
||||
|
||||
strncpy(manufacturer, scsi_inq_data + 8, 8);
|
||||
strncpy(product, scsi_inq_data + 16, 16);
|
||||
strncpy(revision, scsi_inq_data + 32, 4);
|
||||
|
||||
deviceType = DEVICE_TYPE_SCSI;
|
||||
|
||||
ata_error = IdentifyPacket(fd, &atapi_ident, &ata_error_chs);
|
||||
|
||||
if(!ata_error)
|
||||
deviceType = DEVICE_TYPE_ATAPI;
|
||||
}
|
||||
|
||||
if(scsi_inq_data == NULL || !strncmp((const char *)manufacturer, ataName, 3))
|
||||
{
|
||||
ata_error = Identify(fd, &ata_ident, &ata_error_chs);
|
||||
|
||||
if(!ata_error)
|
||||
{
|
||||
deviceType = DEVICE_TYPE_ATA;
|
||||
revision = AtaToCString(ata_ident + (23 * 2), 8);
|
||||
product = AtaToCString(ata_ident + (27 * 2), 40);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Device type: %s\n", DeviceType[deviceType]);
|
||||
printf("Manufacturer: %s\n", manufacturer);
|
||||
printf("Product: %s\n", product);
|
||||
printf("Revision: %s\n", revision);
|
||||
|
||||
if(deviceType != DEVICE_TYPE_ATA && deviceType != DEVICE_TYPE_ATAPI && deviceType != DEVICE_TYPE_SCSI)
|
||||
{
|
||||
printf("Unsupported device type %s.", DeviceType[deviceType]);
|
||||
return 3;
|
||||
}
|
||||
|
||||
sprintf(xmlFilename, "%s_%s_%s.xml", manufacturer, product, revision);
|
||||
|
||||
xmlWriter = xmlNewTextWriterFilename(xmlFilename, 0);
|
||||
if(xmlWriter == NULL)
|
||||
{
|
||||
printf("Could not create XML report file.\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
rc = xmlTextWriterStartDocument(xmlWriter, NULL, XML_ENCODING, NULL);
|
||||
if(rc < 0)
|
||||
{
|
||||
printf("Could not create XML report file.\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
rc = xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_REPORT_ROOT);
|
||||
if(rc < 0)
|
||||
{
|
||||
printf("Could not create XML report file.\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
char *xmlComment = malloc(255);
|
||||
sprintf(xmlComment, "Report created with DiscImageChef.Device.Report v%s", DIC_VERSION);
|
||||
rc = xmlTextWriterWriteComment(xmlWriter, xmlComment);
|
||||
if(rc < 0)
|
||||
{
|
||||
printf("Could not create XML report file.\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
if(deviceType == DEVICE_TYPE_ATAPI)
|
||||
AtapiReport(fd, xmlWriter);
|
||||
|
||||
if(deviceType == DEVICE_TYPE_ATAPI || deviceType == DEVICE_TYPE_SCSI)
|
||||
ScsiReport(fd, xmlWriter);
|
||||
|
||||
if(deviceType == DEVICE_TYPE_ATA)
|
||||
AtaReport(fd, xmlWriter);
|
||||
|
||||
rc = xmlTextWriterEndDocument(xmlWriter);
|
||||
if(rc < 0)
|
||||
{
|
||||
printf("Could not close XML report file.\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : main.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains global definitions.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_MAIN_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_MAIN_H
|
||||
|
||||
#define DIC_VERSION "4.5.99.1693"
|
||||
#define DIC_COPYRIGHT "Copyright © 2011-2019 Natalia Portillo"
|
||||
#define XML_ENCODING "UTF-8"
|
||||
#define DIC_REPORT_ROOT "DicDeviceReport"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DEVICE_TYPE_UNKNOWN,
|
||||
DEVICE_TYPE_SCSI,
|
||||
DEVICE_TYPE_ATA,
|
||||
DEVICE_TYPE_ATAPI,
|
||||
DEVICE_TYPE_USB,
|
||||
DEVICE_TYPE_FIREWIRE,
|
||||
DEVICE_TYPE_PCMCIA,
|
||||
DEVICE_TYPE_MMC,
|
||||
DEVICE_TYPE_SD
|
||||
} DeviceTypes;
|
||||
|
||||
const char *DeviceType[] = {"Unknown", "SCSI", "ATA", "ATAPI", "USB", "FireWire", "PCMCIA", "MultiMediaCard",
|
||||
"SecureDigital"};
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_MAIN_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,51 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : mmc_report.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains definitions used in SCSI MultiMedia device reports.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_MMC_REPORT_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_MMC_REPORT_H
|
||||
|
||||
void MmcReport(int fd, xmlTextWriterPtr xmlWriter, unsigned char *cdromMode);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int present;
|
||||
size_t len;
|
||||
unsigned char *data;
|
||||
} FeatureDescriptors;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t DataLength;
|
||||
uint16_t CurrentProfile;
|
||||
FeatureDescriptors Descriptors[65536];
|
||||
} SeparatedFeatures;
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_MMC_REPORT_H
|
||||
@@ -1,978 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : scsi.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains SCSI commands.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <unitypes.h>
|
||||
#include <malloc.h>
|
||||
#include <scsi/sg.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "scsi.h"
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
int SendScsiCommand(int fd, void *cdb, unsigned char cdb_len, unsigned char *buffer, unsigned int buffer_len,
|
||||
unsigned char **senseBuffer, int direction)
|
||||
{
|
||||
if(buffer == NULL || cdb == NULL)
|
||||
return -1;
|
||||
|
||||
*senseBuffer = malloc(32);
|
||||
memset(*senseBuffer, 0, 32);
|
||||
|
||||
sg_io_hdr_t io_hdr;
|
||||
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
|
||||
|
||||
io_hdr.interface_id = 'S';
|
||||
io_hdr.cmd_len = cdb_len;
|
||||
io_hdr.mx_sb_len = 32;
|
||||
io_hdr.dxfer_direction = direction;
|
||||
io_hdr.dxfer_len = buffer_len;
|
||||
io_hdr.dxferp = buffer;
|
||||
io_hdr.cmdp = cdb;
|
||||
io_hdr.sbp = *senseBuffer;
|
||||
io_hdr.timeout = 10000;
|
||||
|
||||
int error = ioctl(fd, SG_IO, &io_hdr);
|
||||
|
||||
if(error < 0)
|
||||
error = errno;
|
||||
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;
|
||||
}
|
||||
|
||||
int Inquiry(int fd, unsigned char **buffer, unsigned char **senseBuffer)
|
||||
{
|
||||
unsigned char cmd_len = 6;
|
||||
*buffer = malloc(36);
|
||||
memset(*buffer, 0, 36);
|
||||
char cdb[] = {SCSI_INQUIRY, 0, 0, 0, 36, 0};
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, 36, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
unsigned char pagesLength = *(*buffer + 4) + 5;
|
||||
|
||||
free(*buffer);
|
||||
*buffer = malloc(pagesLength);
|
||||
memset(*buffer, 0, pagesLength);
|
||||
|
||||
cdb[4] = pagesLength;
|
||||
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, pagesLength, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int PreventMediumRemoval(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return PreventAllowMediumRemoval(fd, senseBuffer, FALSE, TRUE);
|
||||
}
|
||||
|
||||
int AllowMediumRemoval(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return PreventAllowMediumRemoval(fd, senseBuffer, FALSE, FALSE);
|
||||
}
|
||||
|
||||
int PreventAllowMediumRemoval(int fd, unsigned char **senseBuffer, int persistent, int prevent)
|
||||
{
|
||||
unsigned char cmd_len = 6;
|
||||
char cdb[] = {SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0};
|
||||
unsigned char *buffer = malloc(0);
|
||||
|
||||
if(prevent)
|
||||
cdb[4] += 0x01;
|
||||
if(persistent)
|
||||
cdb[4] += 0x02;
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int LoadTray(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return StartStopUnit(fd, senseBuffer, FALSE, 0, 0, FALSE, TRUE, TRUE);
|
||||
}
|
||||
|
||||
int EjectTray(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return StartStopUnit(fd, senseBuffer, FALSE, 0, 0, FALSE, TRUE, FALSE);
|
||||
}
|
||||
|
||||
int StartUnit(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return StartStopUnit(fd, senseBuffer, FALSE, 0, 0, FALSE, FALSE, TRUE);
|
||||
}
|
||||
|
||||
int StopUnit(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return StartStopUnit(fd, senseBuffer, FALSE, 0, 0, FALSE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
int StartStopUnit(int fd, unsigned char **senseBuffer, int immediate, uint8_t formatLayer, uint8_t powerConditions,
|
||||
int changeFormatLayer, int loadEject, int start)
|
||||
{
|
||||
unsigned char cmd_len = 6;
|
||||
char cdb[] = {SCSI_START_STOP_UNIT, 0, 0, 0, 0, 0};
|
||||
unsigned char *buffer = malloc(0);
|
||||
|
||||
if(immediate)
|
||||
cdb[1] += 0x01;
|
||||
if(changeFormatLayer)
|
||||
{
|
||||
cdb[3] = (formatLayer & 0x03);
|
||||
cdb[4] += 0x04;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(loadEject)
|
||||
cdb[4] += 0x02;
|
||||
if(start)
|
||||
cdb[4] += 0x01;
|
||||
}
|
||||
cdb[4] += ((powerConditions & 0x0F) << 4);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int SpcPreventMediumRemoval(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return SpcPreventAllowMediumRemoval(fd, senseBuffer, 0x01);
|
||||
}
|
||||
|
||||
int SpcAllowMediumRemoval(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return SpcPreventAllowMediumRemoval(fd, senseBuffer, 0x00);
|
||||
}
|
||||
|
||||
int SpcPreventAllowMediumRemoval(int fd, unsigned char **senseBuffer, uint8_t preventMode)
|
||||
{
|
||||
unsigned char cmd_len = 6;
|
||||
char cdb[] = {SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0};
|
||||
unsigned char *buffer = malloc(0);
|
||||
cdb[4] = (preventMode & 0x03);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int Load(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return LoadUnload(fd, senseBuffer, FALSE, TRUE, FALSE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
int Unload(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
return LoadUnload(fd, senseBuffer, FALSE, FALSE, FALSE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
int LoadUnload(int fd, unsigned char **senseBuffer, int immediate, int load, int retense, int endOfTape, int hold)
|
||||
{
|
||||
unsigned char cmd_len = 6;
|
||||
char cdb[] = {SCSI_LOAD_UNLOAD, 0, 0, 0, 0, 0};
|
||||
unsigned char *buffer = malloc(0);
|
||||
if(immediate)
|
||||
cdb[1] = 0x01;
|
||||
if(load)
|
||||
cdb[4] += 0x01;
|
||||
if(retense)
|
||||
cdb[4] += 0x02;
|
||||
if(endOfTape)
|
||||
cdb[4] += 0x04;
|
||||
if(hold)
|
||||
cdb[4] += 0x08;
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
ModeSense6(int fd, unsigned char **buffer, unsigned char **senseBuffer, int DBD, uint8_t pageControl, uint8_t pageCode,
|
||||
uint8_t subPageCode)
|
||||
{
|
||||
unsigned char cmd_len = 6;
|
||||
unsigned int buffer_len = 255;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
unsigned char cdb[] = {SCSI_MODE_SENSE, 0, 0, 0, 0, 0};
|
||||
if(DBD)
|
||||
cdb[1] |= 0x08;
|
||||
cdb[2] |= pageControl;
|
||||
cdb[2] |= (pageCode & 0x3F);
|
||||
cdb[3] = subPageCode;
|
||||
cdb[4] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
buffer_len = (unsigned int)*(*buffer + 0) + 1;
|
||||
|
||||
free(*buffer);
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
cdb[4] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ModeSense10(int fd, unsigned char **buffer, unsigned char **senseBuffer, int LLBAA, int DBD, uint8_t pageControl,
|
||||
uint8_t pageCode, uint8_t subPageCode)
|
||||
{
|
||||
unsigned char cmd_len = 10;
|
||||
unsigned int buffer_len = 4096;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
unsigned char cdb[] = {SCSI_MODE_SENSE_10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
if(LLBAA)
|
||||
cdb[1] |= 0x10;
|
||||
if(DBD)
|
||||
cdb[1] |= 0x08;
|
||||
cdb[2] |= pageControl;
|
||||
cdb[2] |= (pageCode & 0x3F);
|
||||
cdb[3] = subPageCode;
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(buffer_len & 0xFF);
|
||||
cdb[9] = 0;
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
buffer_len = (unsigned int)(*(*buffer + 0) << 8) + *(*buffer + 1) + 2;
|
||||
|
||||
free(*buffer);
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int TestUnitReady(int fd, unsigned char **senseBuffer)
|
||||
{
|
||||
unsigned char cmd_len = 6;
|
||||
char cdb[] = {SCSI_TEST_UNIT_READY, 0, 0, 0, 0, 0};
|
||||
unsigned char *buffer = malloc(0);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int GetConfiguration(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint16_t startingFeatureNumber,
|
||||
uint8_t RT)
|
||||
{
|
||||
unsigned char cmd_len = 10;
|
||||
uint16_t buffer_len = 8;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
char cdb[] = {MMC_GET_CONFIGURATION, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
cdb[1] = (uint8_t)(RT & 0x03);
|
||||
cdb[2] = (uint8_t)((startingFeatureNumber & 0xFF00) >> 8);
|
||||
cdb[3] = (uint8_t)(startingFeatureNumber & 0xFF);
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(buffer_len & 0xFF);
|
||||
cdb[9] = 0;
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
buffer_len = (uint16_t)(*(*buffer + 2) << 8) + *(*buffer + 3) + 2;
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
free(*buffer);
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadTocPmaAtip(int fd, unsigned char **buffer, unsigned char **senseBuffer, int MSF, uint8_t format,
|
||||
uint8_t trackSessionNumber)
|
||||
{
|
||||
unsigned char cmd_len = 10;
|
||||
uint16_t buffer_len = 1024;
|
||||
char cdb[] = {MMC_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
if((format & 0xF) == 5)
|
||||
buffer_len = 32768;
|
||||
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
if(MSF)
|
||||
cdb[1] = 0x02;
|
||||
cdb[2] = (uint8_t)(format & 0x0F);
|
||||
cdb[6] = trackSessionNumber;
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
buffer_len = (uint16_t)(*(*buffer + 0) << 8) + *(*buffer + 1) + 2;
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
free(*buffer);
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadDiscStructure(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t mediaType, uint32_t address,
|
||||
uint8_t layerNumber, uint8_t format, uint8_t AGID)
|
||||
{
|
||||
unsigned char cmd_len = 12;
|
||||
uint16_t buffer_len = 8;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
char cdb[] = {MMC_READ_DISC_STRUCTURE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
cdb[1] = (uint8_t)((uint8_t)mediaType & 0x0F);
|
||||
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);
|
||||
cdb[6] = layerNumber;
|
||||
cdb[7] = (uint8_t)format;
|
||||
cdb[8] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[9] = (uint8_t)(buffer_len & 0xFF);
|
||||
cdb[10] = (uint8_t)((AGID & 0x03) << 6);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
buffer_len = (uint16_t)(*(*buffer + 0) << 8) + *(*buffer + 1) + 2;
|
||||
cdb[8] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[9] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
free(*buffer);
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadCd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
|
||||
uint32_t transferLength, uint8_t expectedSectorType, int DAP, int relAddr, int sync, uint8_t headerCodes,
|
||||
int userData, int edcEcc, uint8_t C2Error, uint8_t subchannel)
|
||||
{
|
||||
unsigned char cmd_len = 12;
|
||||
uint32_t buffer_len = transferLength * blockSize;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
char cdb[] = {MMC_READ_CD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
cdb[1] = (uint8_t)((uint8_t)expectedSectorType << 2);
|
||||
if(DAP)
|
||||
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 & 0xFF0000) >> 16);
|
||||
cdb[7] = (uint8_t)((transferLength & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(transferLength & 0xFF);
|
||||
cdb[9] = (uint8_t)((uint8_t)C2Error << 1);
|
||||
cdb[9] += (uint8_t)((uint8_t)headerCodes << 5);
|
||||
if(sync)
|
||||
cdb[9] += 0x80;
|
||||
if(userData)
|
||||
cdb[9] += 0x10;
|
||||
if(edcEcc)
|
||||
cdb[9] += 0x08;
|
||||
cdb[10] = (uint8_t)subchannel;
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadCdMsf(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t startMsf, uint32_t endMsf,
|
||||
uint32_t blockSize, uint8_t expectedSectorType, int DAP, int sync, uint8_t headerCodes, int userData,
|
||||
int edcEcc, uint8_t C2Error, uint8_t subchannel)
|
||||
{
|
||||
unsigned char cmd_len = 12;
|
||||
char cdb[] = {MMC_READ_CD_MSF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
cdb[1] = (uint8_t)((uint8_t)expectedSectorType << 2);
|
||||
if(DAP)
|
||||
cdb[1] += 0x02;
|
||||
cdb[3] = (uint8_t)((startMsf & 0xFF0000) >> 16);
|
||||
cdb[4] = (uint8_t)((startMsf & 0xFF00) >> 8);
|
||||
cdb[5] = (uint8_t)(startMsf & 0xFF);
|
||||
cdb[6] = (uint8_t)((endMsf & 0xFF0000) >> 16);
|
||||
cdb[7] = (uint8_t)((endMsf & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(endMsf & 0xFF);
|
||||
cdb[9] = (uint8_t)((uint8_t)C2Error << 1);
|
||||
cdb[9] += (uint8_t)((uint8_t)headerCodes << 5);
|
||||
if(sync)
|
||||
cdb[9] += 0x80;
|
||||
if(userData)
|
||||
cdb[9] += 0x10;
|
||||
if(edcEcc)
|
||||
cdb[9] += 0x08;
|
||||
cdb[10] = (uint8_t)subchannel;
|
||||
|
||||
uint32_t transferLength = (uint32_t)((cdb[6] - cdb[3]) * 60 * 75 + (cdb[7] - cdb[4]) * 75 + (cdb[8] - cdb[5]));
|
||||
uint32_t buffer_len = transferLength * blockSize;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int PlextorReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
|
||||
uint32_t transferLength, uint8_t subchannel)
|
||||
{
|
||||
unsigned char cmd_len = 12;
|
||||
uint32_t buffer_len = transferLength * blockSize;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
char cdb[] = {PIONEER_READ_CDDA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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);
|
||||
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)subchannel;
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
PlextorReadRawDvd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength)
|
||||
{
|
||||
unsigned char cmd_len = 10;
|
||||
uint32_t buffer_len = transferLength * 2064;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
char cdb[] = {SCSI_READ_BUFFER, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
cdb[1] = 0x02;
|
||||
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
|
||||
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
|
||||
cdb[5] = (uint8_t)(lba & 0xFF);
|
||||
cdb[3] = (uint8_t)((buffer_len & 0xFF0000) >> 16);
|
||||
cdb[4] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[5] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int PioneerReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
|
||||
uint32_t transferLength, uint8_t subchannel)
|
||||
{
|
||||
unsigned char cmd_len = 12;
|
||||
uint32_t buffer_len = transferLength * blockSize;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
char cdb[] = {PIONEER_READ_CDDA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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);
|
||||
cdb[7] = (uint8_t)((transferLength & 0xFF0000) >> 16);
|
||||
cdb[8] = (uint8_t)((transferLength & 0xFF00) >> 8);
|
||||
cdb[9] = (uint8_t)(transferLength & 0xFF);
|
||||
cdb[10] = (uint8_t)subchannel;
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int PioneerReadCdDaMsf(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t startMsf, uint32_t endMsf,
|
||||
uint32_t blockSize, uint8_t subchannel)
|
||||
{
|
||||
unsigned char cmd_len = 12;
|
||||
char cdb[] = {PIONEER_READ_CDDA_MSF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
cdb[3] = (uint8_t)((startMsf & 0xFF0000) >> 16);
|
||||
cdb[4] = (uint8_t)((startMsf & 0xFF00) >> 8);
|
||||
cdb[5] = (uint8_t)(startMsf & 0xFF);
|
||||
cdb[7] = (uint8_t)((endMsf & 0xFF0000) >> 16);
|
||||
cdb[8] = (uint8_t)((endMsf & 0xFF00) >> 8);
|
||||
cdb[9] = (uint8_t)(endMsf & 0xFF);
|
||||
cdb[10] = (uint8_t)subchannel;
|
||||
|
||||
uint32_t transferLength = (uint)((cdb[7] - cdb[3]) * 60 * 75 + (cdb[8] - cdb[4]) * 75 + (cdb[9] - cdb[5]));
|
||||
uint32_t buffer_len = transferLength * blockSize;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int NecReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength)
|
||||
{
|
||||
unsigned char cmd_len = 12;
|
||||
uint32_t buffer_len = transferLength * 2352;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
char cdb[] = {NEC_READ_CDDA, 0, 0, 0, 0, 0, 0, 0, 0, 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);
|
||||
cdb[7] = (uint8_t)((transferLength & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(transferLength & 0xFF);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int HlDtStReadRawDvd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength)
|
||||
{
|
||||
unsigned char cmd_len = 12;
|
||||
uint32_t buffer_len = transferLength * 2064;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
char cdb[] = {HLDTST_VENDOR, 0x48, 0x49, 0x54, 0x01, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
cdb[6] = (uint8_t)((lba & 0xFF000000) >> 24);
|
||||
cdb[7] = (uint8_t)((lba & 0xFF0000) >> 16);
|
||||
cdb[8] = (uint8_t)((lba & 0xFF00) >> 8);
|
||||
cdb[9] = (uint8_t)(lba & 0xFF);
|
||||
cdb[10] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[11] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReadBlockLimits(int fd, unsigned char **buffer, unsigned char **senseBuffer)
|
||||
{
|
||||
unsigned char cmd_len = 6;
|
||||
unsigned int buffer_len = 6;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
unsigned char cdb[] = {SCSI_READ_BLOCK_LIMITS, 0, 0, 0, 0, 0};
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ReportDensitySupport(int fd, unsigned char **buffer, unsigned char **senseBuffer, int mediumType, int currentMedia)
|
||||
{
|
||||
unsigned char cmd_len = 10;
|
||||
unsigned int buffer_len = 256;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
unsigned char cdb[] = {SCSI_REPORT_DENSITY_SUPPORT, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
if(currentMedia)
|
||||
cdb[1] |= 0x01;
|
||||
if(mediumType)
|
||||
cdb[1] |= 0x02;
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
buffer_len = (unsigned int)(*(*buffer + 0) << 8) + *(*buffer + 1) + 2;
|
||||
|
||||
free(*buffer);
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[8] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int ReadMediaSerialNumber(int fd, unsigned char **buffer, unsigned char **senseBuffer)
|
||||
{
|
||||
unsigned char cmd_len = 12;
|
||||
unsigned int buffer_len = 256;
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
|
||||
unsigned char cdb[] = {SCSI_READ_MEDIA_SERIAL, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
cdb[6] = (uint8_t)((buffer_len & 0xFF000000) >> 24);
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF0000) >> 16);
|
||||
cdb[8] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[9] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
buffer_len =
|
||||
(unsigned int)((*(*buffer + 0) << 24) + (*(*buffer + 1) << 16)) + (*(*buffer + 2) << 8) + *(*buffer + 3) +
|
||||
4;
|
||||
|
||||
free(*buffer);
|
||||
*buffer = malloc(buffer_len);
|
||||
memset(*buffer, 0, buffer_len);
|
||||
cdb[6] = (uint8_t)((buffer_len & 0xFF000000) >> 24);
|
||||
cdb[7] = (uint8_t)((buffer_len & 0xFF0000) >> 16);
|
||||
cdb[8] = (uint8_t)((buffer_len & 0xFF00) >> 8);
|
||||
cdb[9] = (uint8_t)(buffer_len & 0xFF);
|
||||
|
||||
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -1,623 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : scsi.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains SCSI definitions.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_SCSI_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_SCSI_H
|
||||
|
||||
int SendScsiCommand(int fd, void *cdb, unsigned char cdb_len, unsigned char *buffer, unsigned int buffer_len,
|
||||
unsigned char **senseBuffer, int direction);
|
||||
|
||||
int Inquiry(int fd, unsigned char **buffer, unsigned char **senseBuffer);
|
||||
|
||||
int PreventMediumRemoval(int fd, unsigned char **senseBuffer);
|
||||
|
||||
int AllowMediumRemoval(int fd, unsigned char **senseBuffer);
|
||||
|
||||
int PreventAllowMediumRemoval(int fd, unsigned char **senseBuffer, int persistent, int prevent);
|
||||
|
||||
int LoadTray(int fd, unsigned char **senseBuffer);
|
||||
|
||||
int EjectTray(int fd, unsigned char **senseBuffer);
|
||||
|
||||
int StartUnit(int fd, unsigned char **senseBuffer);
|
||||
|
||||
int StopUnit(int fd, unsigned char **senseBuffer);
|
||||
|
||||
int StartStopUnit(int fd, unsigned char **senseBuffer, int immediate, uint8_t formatLayer, uint8_t powerConditions,
|
||||
int changeFormatLayer, int loadEject, int start);
|
||||
|
||||
int SpcPreventMediumRemoval(int fd, unsigned char **senseBuffer);
|
||||
|
||||
int SpcAllowMediumRemoval(int fd, unsigned char **senseBuffer);
|
||||
|
||||
int SpcPreventAllowMediumRemoval(int fd, unsigned char **senseBuffer, uint8_t preventMode);
|
||||
|
||||
int Load(int fd, unsigned char **senseBuffer);
|
||||
|
||||
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);
|
||||
|
||||
int TestUnitReady(int fd, unsigned char **senseBuffer);
|
||||
|
||||
int GetConfiguration(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint16_t startingFeatureNumber,
|
||||
uint8_t RT);
|
||||
|
||||
int ReadTocPmaAtip(int fd, unsigned char **buffer, unsigned char **senseBuffer, int MSF, uint8_t format,
|
||||
uint8_t trackSessionNumber);
|
||||
|
||||
int ReadDiscStructure(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t mediaType, uint32_t address,
|
||||
uint8_t layerNumber, uint8_t format, uint8_t AGID);
|
||||
|
||||
int ReadCd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
|
||||
uint32_t transferLength, uint8_t expectedSectorType, int DAP, int relAddr, int sync, uint8_t headerCodes,
|
||||
int userData, int edcEcc, uint8_t C2Error, uint8_t subchannel);
|
||||
|
||||
int ReadCdMsf(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t startMsf, uint32_t endMsf,
|
||||
uint32_t blockSize, uint8_t expectedSectorType, int DAP, int sync, uint8_t headerCodes, int userData,
|
||||
int edcEcc, uint8_t C2Error, uint8_t subchannel);
|
||||
|
||||
int PlextorReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
|
||||
uint32_t transferLength, uint8_t subchannel);
|
||||
|
||||
int
|
||||
PlextorReadRawDvd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength);
|
||||
|
||||
int PioneerReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
|
||||
uint32_t transferLength, uint8_t subchannel);
|
||||
|
||||
int PioneerReadCdDaMsf(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t startMsf, uint32_t endMsf,
|
||||
uint32_t blockSize, uint8_t subchannel);
|
||||
|
||||
int NecReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength);
|
||||
|
||||
int
|
||||
HlDtStReadRawDvd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength);
|
||||
|
||||
int ReadBlockLimits(int fd, unsigned char **buffer, unsigned char **senseBuffer);
|
||||
|
||||
int ReportDensitySupport(int fd, unsigned char **buffer, unsigned char **senseBuffer, int mediumType, int currentMedia);
|
||||
|
||||
int ReadMediaSerialNumber(int fd, unsigned char **buffer, unsigned char **senseBuffer);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SCSI_TEST_UNIT_READY = 0x00,
|
||||
SCSI_READ_BLOCK_LIMITS = 0x05,
|
||||
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_READ_BUFFER = 0x3C,
|
||||
MMC_READ_TOC_PMA_ATIP = 0x43,
|
||||
SCSI_REPORT_DENSITY_SUPPORT = 0x44,
|
||||
MMC_GET_CONFIGURATION = 0x46,
|
||||
SCSI_MODE_SENSE_10 = 0x5A,
|
||||
SCSI_ATA_PASSTHROUGH_16 = 0x85,
|
||||
SCSI_READ_16 = 0x88,
|
||||
SCSI_SERVICE_ACTION_IN = 0x9E,
|
||||
SCSI_READ_12 = 0xA8,
|
||||
SCSI_READ_MEDIA_SERIAL = 0xAB,
|
||||
MMC_READ_DISC_STRUCTURE = 0xAD,
|
||||
MMC_READ_CD_MSF = 0xB9,
|
||||
MMC_READ_CD = 0xBE,
|
||||
NEC_READ_CDDA = 0xD4,
|
||||
PIONEER_READ_CDDA = 0xD8,
|
||||
PIONEER_READ_CDDA_MSF = 0xD9,
|
||||
HLDTST_VENDOR = 0xE7,
|
||||
} ScsiCommands;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MODE_PAGE_CURRENT = 0x00, MODE_PAGE_CHANGEABLE = 0x40, MODE_PAGE_DEFAULT = 0x80, MODE_PAGE_SAVED = 0xC0
|
||||
} ScsiModeSensePageControl;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SCSI_READ_CAPACITY_16 = 0x10, SCSI_READ_LONG_16 = 0x11,
|
||||
} ScsiServiceActionIn;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DISC_STRUCTURE_DVD = 0x00, DISC_STRUCTURE_BD = 0x01,
|
||||
} MmcDiscStructureMediaType;
|
||||
|
||||
// TODO: Stylize this
|
||||
typedef enum
|
||||
{
|
||||
// Generic Format Codes
|
||||
|
||||
/// <summary>
|
||||
/// AACS Volume Identifier
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_AACSVolId = 0x80, /// <summary>
|
||||
/// AACS Pre-recorded Media Serial Number
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_AACSMediaSerial = 0x81, /// <summary>
|
||||
/// AACS Media Identifier
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_AACSMediaId = 0x82, /// <summary>
|
||||
/// AACS Lead-in Media Key Block
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_AACSMKB = 0x83, /// <summary>
|
||||
/// AACS Data Keys
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_AACSDataKeys = 0x84, /// <summary>
|
||||
/// AACS LBA extents
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_AACSLBAExtents = 0x85, /// <summary>
|
||||
/// CPRM Media Key Block specified by AACS
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_AACSMKBCPRM = 0x86, /// <summary>
|
||||
/// Recognized format layers
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_RecognizedFormatLayers = 0x90, /// <summary>
|
||||
/// Write protection status
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_WriteProtectionStatus = 0xC0, /// <summary>
|
||||
/// READ/SEND DISC STRUCTURE capability list
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_CapabilityList = 0xFF,
|
||||
|
||||
// DVD Disc Structures
|
||||
/// <summary>
|
||||
/// DVD Lead-in Physical Information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_PhysicalInformation = 0x00, /// <summary>
|
||||
/// DVD Lead-in Copyright Information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_CopyrightInformation = 0x01, /// <summary>
|
||||
/// CSS/CPPM Disc key
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DiscKey = 0x02, /// <summary>
|
||||
/// DVD Burst Cutting Area
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_BurstCuttingArea = 0x03, /// <summary>
|
||||
/// DVD Lead-in Disc Manufacturing Information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DiscManufacturingInformation = 0x04, /// <summary>
|
||||
/// DVD Copyright Information from specified sector
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_SectorCopyrightInformation = 0x05, /// <summary>
|
||||
/// CSS/CPPM Media Identifier
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_MediaIdentifier = 0x06, /// <summary>
|
||||
/// CSS/CPPM Media Key Block
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_MediaKeyBlock = 0x07, /// <summary>
|
||||
/// DDS from DVD-RAM
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DVDRAM_DDS = 0x08, /// <summary>
|
||||
/// DVD-RAM Medium Status
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DVDRAM_MediumStatus = 0x09, /// <summary>
|
||||
/// DVD-RAM Spare Area Information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DVDRAM_SpareAreaInformation = 0x0A, /// <summary>
|
||||
/// DVD-RAM Recording Type Information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DVDRAM_RecordingType = 0x0B, /// <summary>
|
||||
/// DVD-R/-RW RMD in last Border-out
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_LastBorderOutRMD = 0x0C, /// <summary>
|
||||
/// Specified RMD from last recorded Border-out
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_SpecifiedRMD = 0x0D, /// <summary>
|
||||
/// DVD-R/-RW Lead-in pre-recorded information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_PreRecordedInfo = 0x0E, /// <summary>
|
||||
/// DVD-R/-RW Media Identifier
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DVDR_MediaIdentifier = 0x0F, /// <summary>
|
||||
/// DVD-R/-RW Physical Format Information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DVDR_PhysicalInformation = 0x10, /// <summary>
|
||||
/// ADIP
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_ADIP = 0x11, /// <summary>
|
||||
/// HD DVD Lead-in Copyright Protection Information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_HDDVD_CopyrightInformation = 0x12, /// <summary>
|
||||
/// AACS Lead-in Copyright Data Section
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DVD_AACS = 0x15, /// <summary>
|
||||
/// HD DVD-R Medium Status
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_HDDVDR_MediumStatus = 0x19, /// <summary>
|
||||
/// HD DVD-R Last recorded RMD in the latest RMZ
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_HDDVDR_LastRMD = 0x1A, /// <summary>
|
||||
/// DVD+/-R DL and DVD-Download DL layer capacity
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DVDR_LayerCapacity = 0x20, /// <summary>
|
||||
/// DVD-R DL Middle Zone start address
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_MiddleZoneStart = 0x21, /// <summary>
|
||||
/// DVD-R DL Jump Interval Size
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_JumpIntervalSize = 0x22, /// <summary>
|
||||
/// DVD-R DL Start LBA of the manual layer jump
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_ManualLayerJumpStartLBA = 0x23, /// <summary>
|
||||
/// DVD-R DL Remapping information of the specified Anchor Point
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_RemapAnchorPoint = 0x24, /// <summary>
|
||||
/// Disc Control Block
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DCB = 0x30,
|
||||
|
||||
// BD Disc Structures
|
||||
/// <summary>
|
||||
/// Blu-ray Disc Information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_DiscInformation = 0x00, /// <summary>
|
||||
/// Blu-ray Burst Cutting Area
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_BD_BurstCuttingArea = 0x03, /// <summary>
|
||||
/// Blu-ray DDS
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_BD_DDS = 0x08, /// <summary>
|
||||
/// Blu-ray Cartridge Status
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_CartridgeStatus = 0x09, /// <summary>
|
||||
/// Blu-ray Spare Area Information
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_BD_SpareAreaInformation = 0x0A, /// <summary>
|
||||
/// Unmodified DFL
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_RawDFL = 0x12, /// <summary>
|
||||
/// Physical Access Control
|
||||
/// </summary>
|
||||
DISC_STRUCTURE_PAC = 0x30
|
||||
} MmcDiscStructureFormat;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MMC_SECTOR_ALL = 0,
|
||||
MMC_SECTOR_CDDA = 1,
|
||||
MMC_SECTOR_MODE1 = 2,
|
||||
MMC_SECTOR_MODE2 = 3,
|
||||
MMC_SECTOR_MODE2F1 = 4,
|
||||
MMC_SECTOR_MODE2F2 = 5
|
||||
} MmcSectorTypes;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MMC_HEADER_NONE = 0, MMC_HEADER_ONLY = 1, MMC_SUBHEADER_ONLY = 2, MMC_HEADER_ALL = 3
|
||||
} MmcHeaderCodes;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MMC_ERROR_NONE = 0, MMC_ERROR_C2 = 1, MMC_ERROR_C2_AND_BLOCK = 2
|
||||
} MmcErrorField;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MMC_SUBCHANNEL_NONE = 0, MMC_SUBCHANNEL_RAW = 1, MMC_SUBCHANNEL_Q16 = 2, MMC_SUBCHANNEL_RW = 4
|
||||
} MmcSubchannel;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PIONEER_SUBCHANNEL_NONE = 0, PIONEER_SUBCHANNEL_Q16 = 1, PIONEER_SUBCHANNEL_ALL = 2, PIONEER_SUBCHANNEL_ONLY = 3
|
||||
} PioneerSubchannel;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLEXTOR_SUBCHANNEL_NONE = 0,
|
||||
PLEXTOR_SUBCHANNEL_Q16 = 1,
|
||||
PLEXTOR_SUBCHANNEL_PACK = 2,
|
||||
PLEXTOR_SUBCHANNEL_ALL = 3,
|
||||
PLEXTOR_SUBCHANNEL_RAW_C2 = 8
|
||||
} PlextorSubchannel;
|
||||
|
||||
// SCSI INQUIRY command response
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
/// <summary>
|
||||
/// Peripheral device type
|
||||
/// Byte 0, bits 4 to 0
|
||||
/// </summary>
|
||||
uint8_t PeripheralDeviceType : 5;
|
||||
/// <summary>
|
||||
/// Peripheral qualifier
|
||||
/// Byte 0, bits 7 to 5
|
||||
/// </summary>
|
||||
uint8_t PeripheralQualifier : 3;
|
||||
/// <summary>
|
||||
/// SCSI-1 vendor-specific qualification codes
|
||||
/// Byte 1, bits 6 to 0
|
||||
/// </summary>
|
||||
uint8_t DeviceTypeModifier : 7;
|
||||
/// <summary>
|
||||
/// Removable device
|
||||
/// Byte 1, bit 7
|
||||
/// </summary>
|
||||
uint8_t RMB : 1;
|
||||
/// <summary>
|
||||
/// ANSI SCSI Standard Version
|
||||
/// Byte 2, bits 2 to 0, mask = 0x07
|
||||
/// </summary>
|
||||
uint8_t ANSIVersion : 3;
|
||||
/// <summary>
|
||||
/// ECMA SCSI Standard Version
|
||||
/// Byte 2, bits 5 to 3, mask = 0x38, >> 3
|
||||
/// </summary>
|
||||
uint8_t ECMAVersion : 3;
|
||||
/// <summary>
|
||||
/// ISO/IEC SCSI Standard Version
|
||||
/// Byte 2, bits 7 to 6, mask = 0xC0, >> 6
|
||||
/// </summary>
|
||||
uint8_t ISOVersion : 2;
|
||||
/// <summary>
|
||||
/// Responde data format
|
||||
/// Byte 3, bit 3 to 0
|
||||
/// </summary>
|
||||
uint8_t ResponseDataFormat : 4;
|
||||
/// <summary>
|
||||
/// Supports LUN hierarchical addressing
|
||||
/// Byte 3, bit 4
|
||||
/// </summary>
|
||||
uint8_t HiSup : 1;
|
||||
/// <summary>
|
||||
/// Supports setting Normal ACA
|
||||
/// Byte 3, bit 5
|
||||
/// </summary>
|
||||
uint8_t NormACA : 1;
|
||||
/// <summary>
|
||||
/// Device supports TERMINATE TASK command
|
||||
/// Byte 3, bit 6
|
||||
/// </summary>
|
||||
uint8_t TrmTsk : 1;
|
||||
/// <summary>
|
||||
/// Asynchronous Event Reporting Capability supported
|
||||
/// Byte 3, bit 7
|
||||
/// </summary>
|
||||
uint8_t AERC : 1;
|
||||
/// <summary>
|
||||
/// Lenght of total INQUIRY response minus 4
|
||||
/// Byte 4
|
||||
/// </summary>
|
||||
uint8_t AdditionalLength;
|
||||
/// <summary>
|
||||
/// Supports protection information
|
||||
/// Byte 5, bit 0
|
||||
/// </summary>
|
||||
uint8_t Protect : 1;
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// Byte 5, bits 2 to 1
|
||||
/// </summary>
|
||||
uint8_t Reserved2 : 2;
|
||||
/// <summary>
|
||||
/// Supports third-party copy commands
|
||||
/// Byte 5, bit 3
|
||||
/// </summary>
|
||||
uint8_t ThreePC : 1;
|
||||
/// <summary>
|
||||
/// Supports asymetrical logical unit access
|
||||
/// Byte 5, bits 5 to 4
|
||||
/// </summary>
|
||||
uint8_t TPGS : 2;
|
||||
/// <summary>
|
||||
/// Device contains an Access Control Coordinator
|
||||
/// Byte 5, bit 6
|
||||
/// </summary>
|
||||
uint8_t ACC : 1;
|
||||
/// <summary>
|
||||
/// Device contains an embedded storage array controller
|
||||
/// Byte 5, bit 7
|
||||
/// </summary>
|
||||
uint8_t SCCS : 1;
|
||||
/// <summary>
|
||||
/// Supports 16-bit wide SCSI addresses
|
||||
/// Byte 6, bit 0
|
||||
/// </summary>
|
||||
uint8_t Addr16 : 1;
|
||||
/// <summary>
|
||||
/// Supports 32-bit wide SCSI addresses
|
||||
/// Byte 6, bit 1
|
||||
/// </summary>
|
||||
uint8_t Addr32 : 1;
|
||||
/// <summary>
|
||||
/// Device supports request and acknowledge handshakes
|
||||
/// Byte 6, bit 2
|
||||
/// </summary>
|
||||
uint8_t ACKREQQ : 1;
|
||||
/// <summary>
|
||||
/// Device contains or is attached to a medium changer
|
||||
/// Byte 6, bit 3
|
||||
/// </summary>
|
||||
uint8_t MChngr : 1;
|
||||
/// <summary>
|
||||
/// Multi-port device
|
||||
/// Byte 6, bit 4
|
||||
/// </summary>
|
||||
uint8_t MultiP : 1;
|
||||
/// <summary>
|
||||
/// Vendor-specific
|
||||
/// Byte 6, bit 5
|
||||
/// </summary>
|
||||
uint8_t VS1 : 1;
|
||||
/// <summary>
|
||||
/// Device contains an embedded enclosure services component
|
||||
/// Byte 6, bit 6
|
||||
/// </summary>
|
||||
uint8_t EncServ : 1;
|
||||
/// <summary>
|
||||
/// Supports basic queueing
|
||||
/// Byte 6, bit 7
|
||||
/// </summary>
|
||||
uint8_t BQue : 1;
|
||||
/// <summary>
|
||||
/// Indicates that the devices responds to RESET with soft reset
|
||||
/// Byte 7, bit 0
|
||||
/// </summary>
|
||||
uint8_t SftRe : 1;
|
||||
/// <summary>
|
||||
/// Supports TCQ queue
|
||||
/// Byte 7, bit 1
|
||||
/// </summary>
|
||||
uint8_t CmdQue : 1;
|
||||
/// <summary>
|
||||
/// Supports CONTINUE TASK and TARGET TRANSFER DISABLE commands
|
||||
/// Byte 7, bit 2
|
||||
/// </summary>
|
||||
uint8_t TranDis : 1;
|
||||
/// <summary>
|
||||
/// Supports linked commands
|
||||
/// Byte 7, bit 3
|
||||
/// </summary>
|
||||
uint8_t Linked : 1;
|
||||
/// <summary>
|
||||
/// Supports synchronous data transfer
|
||||
/// Byte 7, bit 4
|
||||
/// </summary>
|
||||
uint8_t Sync : 1;
|
||||
/// <summary>
|
||||
/// Supports 16-bit wide data transfers
|
||||
/// Byte 7, bit 5
|
||||
/// </summary>
|
||||
uint8_t WBus16 : 1;
|
||||
/// <summary>
|
||||
/// Supports 32-bit wide data transfers
|
||||
/// Byte 7, bit 6
|
||||
/// </summary>
|
||||
uint8_t WBus32 : 1;
|
||||
/// <summary>
|
||||
/// Device supports relative addressing
|
||||
/// Byte 7, bit 7
|
||||
/// </summary>
|
||||
uint8_t RelAddr : 1;
|
||||
/// <summary>
|
||||
/// Vendor identification
|
||||
/// Bytes 8 to 15
|
||||
/// </summary>
|
||||
uint8_t VendorIdentification[8];
|
||||
/// <summary>
|
||||
/// Product identification
|
||||
/// Bytes 16 to 31
|
||||
/// </summary>
|
||||
uint8_t ProductIdentification[16];
|
||||
/// <summary>
|
||||
/// Product revision level
|
||||
/// Bytes 32 to 35
|
||||
/// </summary>
|
||||
uint8_t ProductRevisionLevel[4];
|
||||
/// <summary>
|
||||
/// Vendor-specific data
|
||||
/// Bytes 36 to 55
|
||||
/// </summary>
|
||||
uint8_t VendorSpecific[20];
|
||||
/// <summary>
|
||||
/// Supports information unit transfers
|
||||
/// Byte 56, bit 0
|
||||
/// </summary>
|
||||
uint8_t IUS : 1;
|
||||
/// <summary>
|
||||
/// Device supports Quick Arbitration and Selection
|
||||
/// Byte 56, bit 1
|
||||
/// </summary>
|
||||
uint8_t QAS : 1;
|
||||
/// <summary>
|
||||
/// Supported SPI clocking
|
||||
/// Byte 56, bits 3 to 2
|
||||
/// </summary>
|
||||
uint8_t Clocking : 2;
|
||||
/// <summary>
|
||||
/// Byte 56, bits 7 to 4
|
||||
/// </summary>
|
||||
uint8_t Reserved3 : 4;
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// Byte 57
|
||||
/// </summary>
|
||||
uint8_t Reserved4;
|
||||
/// <summary>
|
||||
/// Array of version descriptors
|
||||
/// Bytes 58 to 73
|
||||
/// </summary>
|
||||
uint16_t VersionDescriptors[8];
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// Bytes 74 to 95
|
||||
/// </summary>
|
||||
uint8_t Reserved5[22];
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// Bytes 96 to end
|
||||
/// </summary>
|
||||
uint8_t VendorSpecific2;
|
||||
} ScsiInquiry;
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_SCSI_H
|
||||
@@ -1,304 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : scsi_mode.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains decoders for SCSI MODE PAGEs.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <endian.h>
|
||||
#include <stdint.h>
|
||||
#include "scsi_mode.h"
|
||||
|
||||
ModeHeader *DecodeModeHeader10(unsigned char *modeResponse, uint8_t deviceType)
|
||||
{
|
||||
uint16_t blockDescLength = (uint16_t)((modeResponse[6] << 8) + modeResponse[7]);
|
||||
int i;
|
||||
ModeHeader *header = malloc(sizeof(ModeHeader));
|
||||
memset(header, 0, sizeof(ModeHeader));
|
||||
header->MediumType = modeResponse[2];
|
||||
|
||||
int longLBA = (modeResponse[4] & 0x01) == 0x01;
|
||||
|
||||
if(blockDescLength > 0)
|
||||
{
|
||||
if(longLBA)
|
||||
{
|
||||
header->descriptorsLength = blockDescLength / 16;
|
||||
for(i = 0; i < header->descriptorsLength; i++)
|
||||
{
|
||||
header->BlockDescriptors[i].Density = 0x00;
|
||||
header->BlockDescriptors[i].Blocks = be64toh((uint64_t)(*modeResponse + 0 + i * 16 + 8));
|
||||
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[15 + i * 16 + 8] << 24);
|
||||
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[14 + i * 16 + 8] << 16);
|
||||
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[13 + i * 16 + 8] << 8);
|
||||
header->BlockDescriptors[i].BlockLength += modeResponse[12 + i * 16 + 8];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header->descriptorsLength = blockDescLength / 8;
|
||||
for(i = 0; i < header->descriptorsLength; i++)
|
||||
{
|
||||
if(deviceType != 0x00)
|
||||
{
|
||||
header->BlockDescriptors[i].Density = modeResponse[0 + i * 8 + 8];
|
||||
}
|
||||
else
|
||||
{
|
||||
header->BlockDescriptors[i].Density = 0x00;
|
||||
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[0 + i * 8 + 8] << 24);
|
||||
}
|
||||
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[1 + i * 8 + 8] << 16);
|
||||
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[2 + i * 8 + 8] << 8);
|
||||
header->BlockDescriptors[i].Blocks += modeResponse[3 + i * 8 + 8];
|
||||
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[5 + i * 8 + 8] << 16);
|
||||
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[6 + i * 8 + 8] << 8);
|
||||
header->BlockDescriptors[i].BlockLength += modeResponse[7 + i * 8 + 8];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(deviceType == 0x00 || deviceType == 0x05)
|
||||
{
|
||||
header->WriteProtected = ((modeResponse[3] & 0x80) == 0x80);
|
||||
header->DPOFUA = ((modeResponse[3] & 0x10) == 0x10);
|
||||
}
|
||||
|
||||
if(deviceType == 0x01)
|
||||
{
|
||||
header->WriteProtected = ((modeResponse[3] & 0x80) == 0x80);
|
||||
header->Speed = (uint8_t)(modeResponse[3] & 0x0F);
|
||||
header->BufferedMode = (uint8_t)((modeResponse[3] & 0x70) >> 4);
|
||||
}
|
||||
|
||||
if(deviceType == 0x02)
|
||||
header->BufferedMode = (uint8_t)((modeResponse[3] & 0x70) >> 4);
|
||||
|
||||
if(deviceType == 0x07)
|
||||
{
|
||||
header->WriteProtected = ((modeResponse[3] & 0x80) == 0x80);
|
||||
header->EBC = ((modeResponse[3] & 0x01) == 0x01);
|
||||
header->DPOFUA = ((modeResponse[3] & 0x10) == 0x10);
|
||||
}
|
||||
|
||||
header->decoded = 1;
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
DecodedMode *DecodeMode10(unsigned char *modeResponse, uint8_t deviceType)
|
||||
{
|
||||
DecodedMode *decodedMode = malloc(sizeof(DecodedMode));
|
||||
|
||||
ModeHeader *hdrPtr = DecodeModeHeader10(modeResponse, deviceType);
|
||||
memcpy(&(decodedMode->Header), hdrPtr, sizeof(ModeHeader));
|
||||
free(hdrPtr);
|
||||
|
||||
if(!decodedMode->Header.decoded)
|
||||
return decodedMode;
|
||||
|
||||
decodedMode->decoded = 1;
|
||||
|
||||
int longlba = (modeResponse[4] & 0x01) == 0x01;
|
||||
int offset;
|
||||
|
||||
if(longlba)
|
||||
offset = 8 + decodedMode->Header.descriptorsLength * 16;
|
||||
else
|
||||
offset = 8 + decodedMode->Header.descriptorsLength * 8;
|
||||
int length = (modeResponse[0] << 8);
|
||||
length += modeResponse[1];
|
||||
length += 2;
|
||||
|
||||
while(offset < length)
|
||||
{
|
||||
int isSubpage = (modeResponse[offset] & 0x40) == 0x40;
|
||||
|
||||
uint8_t pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
|
||||
int subpage;
|
||||
|
||||
if(pageNo == 0)
|
||||
{
|
||||
decodedMode->pageSizes[0][0] = (size_t)(length - offset);
|
||||
decodedMode->Pages[0][0] = malloc(decodedMode->pageSizes[0][0]);
|
||||
memset(decodedMode->Pages[0][0], 0, decodedMode->pageSizes[0][0]);
|
||||
memcpy(decodedMode->Pages[0][0], modeResponse + offset, decodedMode->pageSizes[0][0]);
|
||||
offset += decodedMode->pageSizes[0][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isSubpage)
|
||||
{
|
||||
if(offset + 3 >= length)
|
||||
break;
|
||||
|
||||
pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
|
||||
subpage = modeResponse[offset + 1];
|
||||
decodedMode->pageSizes[pageNo][subpage] = (size_t)((modeResponse[offset + 2] << 8) +
|
||||
modeResponse[offset + 3] + 4);
|
||||
decodedMode->Pages[pageNo][subpage] = malloc(decodedMode->pageSizes[pageNo][subpage]);
|
||||
memset(decodedMode->Pages[pageNo][subpage], 0, decodedMode->pageSizes[pageNo][subpage]);
|
||||
memcpy(decodedMode->Pages[pageNo][subpage], modeResponse + offset,
|
||||
decodedMode->pageSizes[pageNo][subpage]);
|
||||
offset += decodedMode->pageSizes[pageNo][subpage];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(offset + 1 >= length)
|
||||
break;
|
||||
|
||||
pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
|
||||
decodedMode->pageSizes[pageNo][0] = (size_t)(modeResponse[offset + 1] + 2);
|
||||
decodedMode->Pages[pageNo][0] = malloc(decodedMode->pageSizes[pageNo][0]);
|
||||
memset(decodedMode->Pages[pageNo][0], 0, decodedMode->pageSizes[pageNo][0]);
|
||||
memcpy(decodedMode->Pages[pageNo][0], modeResponse + offset, decodedMode->pageSizes[pageNo][0]);
|
||||
offset += decodedMode->pageSizes[pageNo][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decodedMode;
|
||||
}
|
||||
|
||||
|
||||
ModeHeader *DecodeModeHeader6(unsigned char *modeResponse, uint8_t deviceType)
|
||||
{
|
||||
int i;
|
||||
ModeHeader *header = malloc(sizeof(ModeHeader));
|
||||
memset(header, 0, sizeof(ModeHeader));
|
||||
|
||||
if(modeResponse[3])
|
||||
{
|
||||
header->descriptorsLength = modeResponse[3] / 8;
|
||||
for(i = 0; i < header->descriptorsLength; i++)
|
||||
{
|
||||
header->BlockDescriptors[i].Density = modeResponse[0 + i * 8 + 4];
|
||||
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[1 + i * 8 + 4] << 16);
|
||||
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[2 + i * 8 + 4] << 8);
|
||||
header->BlockDescriptors[i].Blocks += modeResponse[3 + i * 8 + 4];
|
||||
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[5 + i * 8 + 4] << 16);
|
||||
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[6 + i * 8 + 4] << 8);
|
||||
header->BlockDescriptors[i].BlockLength += modeResponse[7 + i * 8 + 4];
|
||||
}
|
||||
}
|
||||
|
||||
if(deviceType == 0x00 || deviceType == 0x05)
|
||||
{
|
||||
header->WriteProtected = ((modeResponse[2] & 0x80) == 0x80);
|
||||
header->DPOFUA = ((modeResponse[2] & 0x10) == 0x10);
|
||||
}
|
||||
|
||||
if(deviceType == 0x01)
|
||||
{
|
||||
header->WriteProtected = ((modeResponse[2] & 0x80) == 0x80);
|
||||
header->Speed = (uint8_t)(modeResponse[2] & 0x0F);
|
||||
header->BufferedMode = (uint8_t)((modeResponse[2] & 0x70) >> 4);
|
||||
}
|
||||
|
||||
if(deviceType == 0x02)
|
||||
header->BufferedMode = (uint8_t)((modeResponse[2] & 0x70) >> 4);
|
||||
|
||||
if(deviceType == 0x07)
|
||||
{
|
||||
header->WriteProtected = ((modeResponse[2] & 0x80) == 0x80);
|
||||
header->EBC = ((modeResponse[2] & 0x01) == 0x01);
|
||||
header->DPOFUA = ((modeResponse[2] & 0x10) == 0x10);
|
||||
}
|
||||
|
||||
header->decoded = 1;
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
DecodedMode *DecodeMode6(unsigned char *modeResponse, uint8_t deviceType)
|
||||
{
|
||||
DecodedMode *decodedMode = malloc(sizeof(DecodedMode));
|
||||
|
||||
ModeHeader *hdrPtr = DecodeModeHeader6(modeResponse, deviceType);
|
||||
memcpy(&(decodedMode->Header), hdrPtr, sizeof(ModeHeader));
|
||||
free(hdrPtr);
|
||||
|
||||
if(!decodedMode->Header.decoded)
|
||||
return decodedMode;
|
||||
|
||||
decodedMode->decoded = 1;
|
||||
|
||||
int offset = 4 + decodedMode->Header.descriptorsLength * 8;
|
||||
int length = modeResponse[0] + 1;
|
||||
|
||||
while(offset < length)
|
||||
{
|
||||
int isSubpage = (modeResponse[offset] & 0x40) == 0x40;
|
||||
|
||||
uint8_t pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
|
||||
int subpage;
|
||||
|
||||
if(pageNo == 0)
|
||||
{
|
||||
decodedMode->pageSizes[0][0] = (size_t)(length - offset);
|
||||
decodedMode->Pages[0][0] = malloc(decodedMode->pageSizes[0][0]);
|
||||
memset(decodedMode->Pages[0][0], 0, decodedMode->pageSizes[0][0]);
|
||||
memcpy(decodedMode->Pages[0][0], modeResponse + offset, decodedMode->pageSizes[0][0]);
|
||||
offset += decodedMode->pageSizes[0][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isSubpage)
|
||||
{
|
||||
if(offset + 3 >= length)
|
||||
break;
|
||||
|
||||
pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
|
||||
subpage = modeResponse[offset + 1];
|
||||
decodedMode->pageSizes[pageNo][subpage] = (size_t)((modeResponse[offset + 2] << 8) +
|
||||
modeResponse[offset + 3] + 4);
|
||||
decodedMode->Pages[pageNo][subpage] = malloc(decodedMode->pageSizes[pageNo][subpage]);
|
||||
memset(decodedMode->Pages[pageNo][subpage], 0, decodedMode->pageSizes[pageNo][subpage]);
|
||||
memcpy(decodedMode->Pages[pageNo][subpage], modeResponse + offset,
|
||||
decodedMode->pageSizes[pageNo][subpage]);
|
||||
offset += decodedMode->pageSizes[pageNo][subpage];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(offset + 1 >= length)
|
||||
break;
|
||||
|
||||
pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
|
||||
decodedMode->pageSizes[pageNo][0] = (size_t)(modeResponse[offset + 1] + 2);
|
||||
decodedMode->Pages[pageNo][0] = malloc(decodedMode->pageSizes[pageNo][0]);
|
||||
memset(decodedMode->Pages[pageNo][0], 0, decodedMode->pageSizes[pageNo][0]);
|
||||
memcpy(decodedMode->Pages[pageNo][0], modeResponse + offset, decodedMode->pageSizes[pageNo][0]);
|
||||
offset += decodedMode->pageSizes[pageNo][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decodedMode;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : scsi_mode.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains definitions for SCSI MODE PAGEs.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_SCSI_MODE_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_SCSI_MODE_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Density;
|
||||
uint64_t Blocks;
|
||||
uint32_t BlockLength;
|
||||
} BlockDescriptor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t MediumType;
|
||||
int WriteProtected;
|
||||
BlockDescriptor BlockDescriptors[4096];
|
||||
int descriptorsLength;
|
||||
uint8_t Speed;
|
||||
uint8_t BufferedMode;
|
||||
int EBC;
|
||||
int DPOFUA;
|
||||
int decoded;
|
||||
} ModeHeader;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ModeHeader Header;
|
||||
unsigned char *Pages[256][256];
|
||||
size_t pageSizes[256][256];
|
||||
int decoded;
|
||||
} DecodedMode;
|
||||
|
||||
ModeHeader *DecodeModeHeader6(unsigned char *modeResponse, uint8_t deviceType);
|
||||
|
||||
ModeHeader *DecodeModeHeader10(unsigned char *modeResponse, uint8_t deviceType);
|
||||
|
||||
DecodedMode *DecodeMode6(unsigned char *modeResponse, uint8_t deviceType);
|
||||
|
||||
DecodedMode *DecodeMode10(unsigned char *modeResponse, uint8_t deviceType);
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_SCSI_MODE_H
|
||||
@@ -1,803 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : scsi_report.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Creates report for SCSI devices.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <libxml/xmlwriter.h>
|
||||
#include <unistd.h>
|
||||
#include "scsi_report.h"
|
||||
#include "scsi.h"
|
||||
#include "inquiry_decode.h"
|
||||
#include "scsi_mode.h"
|
||||
#include "mmc_report.h"
|
||||
#include "ssc_report.h"
|
||||
|
||||
void ScsiReport(int fd, xmlTextWriterPtr xmlWriter)
|
||||
{
|
||||
unsigned char *sense = NULL;
|
||||
unsigned char *buffer = NULL;
|
||||
int error;
|
||||
int page_len;
|
||||
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");
|
||||
|
||||
error = Inquiry(fd, &buffer, &sense);
|
||||
|
||||
if(error)
|
||||
{
|
||||
fprintf(stderr, "Error {0} requesting INQUIRY", error);
|
||||
return;
|
||||
}
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_SCSI_REPORT_ELEMENT); // <SCSI>
|
||||
page_len = *(buffer + 4) + 5;
|
||||
|
||||
ScsiInquiry *inquiry = malloc(sizeof(ScsiInquiry));
|
||||
memset(inquiry, 0, sizeof(ScsiInquiry));
|
||||
memcpy(inquiry, buffer, page_len > sizeof(ScsiInquiry) ? sizeof(ScsiInquiry) : page_len);
|
||||
|
||||
if(inquiry->RMB)
|
||||
{
|
||||
do
|
||||
{
|
||||
printf("Is the media removable from the reading/writing elements (flash memories ARE NOT removable)? (Y/N): ");
|
||||
scanf("%c", &user_response);
|
||||
printf("\n");
|
||||
}while(user_response != 'Y' && user_response != 'y' && user_response != 'N' && user_response != 'n');
|
||||
|
||||
removable = (user_response == 'Y' || user_response == 'y');
|
||||
}
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_SCSI_INQUIRY_ELEMENT); // <Inquiry>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "AccessControlCoordinator", "%s",
|
||||
inquiry->ACC ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ACKRequests", "%s", inquiry->ACKREQQ ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Address16", "%s", inquiry->Addr16 ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Address32", "%s", inquiry->Addr32 ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "AERCSupported", "%s", inquiry->AERC ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ANSIVersion", "%d", inquiry->ANSIVersion);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "AsymmetricalLUNAccess", "%s", DecodeTPGSValues(inquiry->TPGS));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BasicQueueing", "%s", inquiry->BQue ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DeviceTypeModifier", "%d", inquiry->DeviceTypeModifier);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ECMAVersion", "%d", inquiry->ECMAVersion);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "EnclosureServices", "%s", inquiry->EncServ ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "HierarchicalLUN", "%s", inquiry->HiSup ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ISOVersion", "%d", inquiry->ISOVersion);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "IUS", "%s", inquiry->IUS ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LinkedCommands", "%s", inquiry->Linked ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumChanger", "%s", inquiry->MChngr ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultiPortDevice", "%s", inquiry->MultiP ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NormalACA", "%s", inquiry->NormACA ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PeripheralDeviceType", "%s",
|
||||
DecodePeripheralDeviceType(inquiry->PeripheralDeviceType));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PeripheralQualifier", "%s",
|
||||
DecodePeripheralQualifier(inquiry->PeripheralQualifier));
|
||||
tmpString = malloc(17);
|
||||
memset(tmpString, 0, 17);
|
||||
memcpy(tmpString, inquiry->ProductIdentification, 16);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ProductIdentification", "%s", tmpString);
|
||||
free(tmpString);
|
||||
tmpString = malloc(5);
|
||||
memset(tmpString, 0, 5);
|
||||
memcpy(tmpString, inquiry->ProductRevisionLevel, 4);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ProductRevisionLevel", "%s", tmpString);
|
||||
free(tmpString);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Protection", "%s", inquiry->Protect ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "QAS", "%s", inquiry->QAS ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RelativeAddressing", "%s",
|
||||
inquiry->RelAddr ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Removable", "%s", inquiry->RMB ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ResponseDataFormat", "%d", inquiry->ResponseDataFormat);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SoftReset", "%s", inquiry->SftRe ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SPIClocking", "%s", DecodeSPIClocking(inquiry->Clocking));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StorageArrayController", "%s",
|
||||
inquiry->SCCS ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SyncTransfer", "%s", inquiry->Sync ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TaggedCommandQueue", "%s", inquiry->CmdQue ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TerminateTaskSupported", "%s",
|
||||
inquiry->TrmTsk ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ThirdPartyCopy", "%s", inquiry->ThreePC ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TranferDisable", "%s", inquiry->TranDis ? "true" : "false");
|
||||
tmpString = malloc(9);
|
||||
memset(tmpString, 0, 9);
|
||||
memcpy(tmpString, inquiry->VendorIdentification, 8);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "VendorIdentification", "%8s", tmpString);
|
||||
free(tmpString);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WideBus16", "%s", inquiry->WBus16 ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WideBus32", "%s", inquiry->WBus32 ? "true" : "false");
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "Data");
|
||||
xmlTextWriterWriteBase64(xmlWriter, buffer, 0, page_len);
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
xmlTextWriterEndElement(xmlWriter); // </Inquiry>
|
||||
|
||||
// TODO: EVPDs
|
||||
|
||||
if(removable)
|
||||
{
|
||||
if(inquiry->PeripheralDeviceType == 0x05) // MultiMediaDevice
|
||||
{
|
||||
AllowMediumRemoval(fd, &sense);
|
||||
EjectTray(fd, &sense);
|
||||
}
|
||||
else if(inquiry->PeripheralDeviceType == 0x05) // SequentialAccess
|
||||
{
|
||||
SpcAllowMediumRemoval(fd, &sense);
|
||||
printf("Asking drive to unload tape (can take a few minutes)...\n");
|
||||
Unload(fd, &sense);
|
||||
}
|
||||
printf("Please remove any media from the device and press any key when it is out.\n");
|
||||
scanf("%c");
|
||||
}
|
||||
|
||||
int supportsMode6 = FALSE;
|
||||
int supportsMode10 = FALSE;
|
||||
int supportsModeSubpages = FALSE;
|
||||
unsigned char *mode6Response = NULL;
|
||||
unsigned char *mode10Response = NULL;
|
||||
|
||||
printf("Querying all mode pages and subpages using SCSI MODE SENSE (10)...\n");
|
||||
error = ModeSense10(fd, &mode10Response, &sense, FALSE, TRUE, MODE_PAGE_DEFAULT, 0x3F, 0xFF);
|
||||
|
||||
if(error)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
supportsMode10 = TRUE;
|
||||
supportsModeSubpages = TRUE;
|
||||
}
|
||||
|
||||
printf("Querying all mode pages and subpages using SCSI MODE SENSE (6)...\n");
|
||||
error = ModeSense6(fd, &mode6Response, &sense, FALSE, MODE_PAGE_DEFAULT, 0x3F, 0xFF);
|
||||
if(error)
|
||||
{
|
||||
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)...\n");
|
||||
error = ModeSense6(fd, &mode6Response, &sense, FALSE, MODE_PAGE_DEFAULT, 0x00, 0x00);
|
||||
if(!error)
|
||||
supportsMode6 = TRUE;
|
||||
}
|
||||
else
|
||||
supportsMode6 = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
supportsMode6 = TRUE;
|
||||
supportsModeSubpages = TRUE;
|
||||
}
|
||||
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense6", "%s", supportsMode6 ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense10", "%s", supportsMode10 ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSubpages", "%s",
|
||||
supportsModeSubpages ? "true" : "false");
|
||||
|
||||
if(supportsMode6)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense6Data");
|
||||
xmlTextWriterWriteBase64(xmlWriter, mode6Response, 0, *(mode6Response + 0) + 1);
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
}
|
||||
|
||||
if(supportsMode10)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense10Data");
|
||||
xmlTextWriterWriteBase64(xmlWriter, mode10Response, 0,
|
||||
(*(mode10Response + 0) << 8) + *(mode10Response + 1) + 2);
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
}
|
||||
|
||||
DecodedMode *decMode = NULL;
|
||||
unsigned char *cdromMode = NULL;
|
||||
|
||||
if(supportsMode10)
|
||||
decMode = DecodeMode10(mode10Response, inquiry->PeripheralDeviceType);
|
||||
else if(supportsMode6)
|
||||
decMode = DecodeMode6(mode6Response, inquiry->PeripheralDeviceType);
|
||||
|
||||
if(decMode->decoded)
|
||||
{
|
||||
int page, subpage;
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense"); // <ModeSense>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlankCheckEnabled", "%s",
|
||||
decMode->Header.EBC ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DPOandFUA", "%s",
|
||||
decMode->Header.DPOFUA ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WriteProtected", "%s",
|
||||
decMode->Header.WriteProtected ? "true" : "false");
|
||||
|
||||
if(decMode->Header.BufferedMode > 0)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlankCheckEnabled", "%d",
|
||||
decMode->Header.BufferedMode);
|
||||
if(decMode->Header.Speed > 0)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Speed", "%d", decMode->Header.Speed);
|
||||
|
||||
for(page = 0; page < 256; page++)
|
||||
{
|
||||
for(subpage = 0; subpage < 256; subpage++)
|
||||
{
|
||||
if(decMode->pageSizes[page][subpage] > 0 && decMode->Pages[page][subpage] != NULL)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "modePageType");
|
||||
xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST "page", "%d", page);
|
||||
xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST "subpage", "%d", subpage);
|
||||
xmlTextWriterWriteBase64(xmlWriter, decMode->Pages[page][subpage], 0,
|
||||
decMode->pageSizes[page][subpage]);
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
|
||||
if(page == 0x2A && subpage == 0x00)
|
||||
{
|
||||
cdromMode = decMode->Pages[0x2A][0x00];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlTextWriterEndElement(xmlWriter); // </ModeSense>
|
||||
}
|
||||
|
||||
if(inquiry->PeripheralDeviceType == 0x05) // MultiMediaDevice
|
||||
{
|
||||
MmcReport(fd, xmlWriter, cdromMode);
|
||||
}
|
||||
else if(inquiry->PeripheralDeviceType == 0x01) // SequentialAccess
|
||||
{
|
||||
SscReport(fd, xmlWriter);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(removable)
|
||||
{
|
||||
user_response = ' ';
|
||||
int anyMedia = FALSE;
|
||||
|
||||
while(user_response != 'N' && user_response != 'n')
|
||||
{
|
||||
do
|
||||
{
|
||||
printf("Do you have media that you can insert in the drive? (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')
|
||||
{
|
||||
printf("Please insert it in the drive and press any key when it is ready.\n");
|
||||
scanf("%c");
|
||||
|
||||
char mediaManufacturer[256], mediaName[256], mediaModel[256];
|
||||
printf("Please write a description of the media type and press enter: ");
|
||||
gets(mediaName);
|
||||
printf("Please write the media manufacturer and press enter: ");
|
||||
gets(mediaManufacturer);
|
||||
printf("Please write the media model and press enter: ");
|
||||
gets(mediaModel);
|
||||
|
||||
error = TestUnitReady(fd, &sense);
|
||||
int mediaRecognized = TRUE;
|
||||
int leftRetries = 20;
|
||||
|
||||
if(error)
|
||||
{
|
||||
if((sense[0] == 0x70 || sense[0] == 0x71) && (sense[2] & 0x0F) != 0x00)
|
||||
{
|
||||
if(sense[12] == 0x3A || (sense[12] == 0x04 && sense[13] == 0x01))
|
||||
{
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
printf("\rWating for drive to become ready");
|
||||
sleep(2);
|
||||
error = TestUnitReady(fd, &sense);
|
||||
if(!error)
|
||||
break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
mediaRecognized = !error;
|
||||
}
|
||||
else
|
||||
mediaRecognized = FALSE;
|
||||
}
|
||||
else
|
||||
mediaRecognized = FALSE;
|
||||
}
|
||||
|
||||
if(!anyMedia)
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "RemovableMedias"); // <RemovableMedias>
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "testedMediaType"); // <testedMediaType>
|
||||
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediaIsRecognized", "%s",
|
||||
mediaRecognized ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", mediaManufacturer);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumTypeName", "%s", mediaName);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Model", "%s", mediaModel);
|
||||
|
||||
if(mediaRecognized)
|
||||
{
|
||||
uint64_t blocks = 0;
|
||||
uint32_t blockSize = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if(decMode != NULL)
|
||||
decMode->decoded = 0;
|
||||
|
||||
printf("Querying SCSI MODE SENSE (10)...\n");
|
||||
error = ModeSense10(fd, &mode10Response, &sense, FALSE, TRUE, MODE_PAGE_DEFAULT, 0x3F, 0x00);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense10", "%s",
|
||||
!error ? "true" : "false");
|
||||
if(!error)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense10Data");
|
||||
xmlTextWriterWriteBase64(xmlWriter, mode10Response, 0,
|
||||
(*(mode10Response + 0) << 8) + *(mode10Response + 1) + 2);
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
decMode = DecodeMode10(mode10Response, inquiry->PeripheralDeviceType);
|
||||
}
|
||||
|
||||
printf("Querying SCSI MODE SENSE (6)...\n");
|
||||
error = ModeSense6(fd, &mode6Response, &sense, FALSE, MODE_PAGE_DEFAULT, 0x00, 0x00);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense6", "%s",
|
||||
!error ? "true" : "false");
|
||||
if(!error)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense6Data");
|
||||
xmlTextWriterWriteBase64(xmlWriter, mode6Response, 0, *(mode6Response + 0) + 1);
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
if(!decMode->decoded)
|
||||
decMode = DecodeMode6(mode6Response, inquiry->PeripheralDeviceType);
|
||||
}
|
||||
|
||||
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 (16)...\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)
|
||||
{
|
||||
user_response = ' ';
|
||||
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");
|
||||
}
|
||||
|
||||
user_response = ' ';
|
||||
}
|
||||
|
||||
if(supportsReadLong10 && blockSize != longBlockSize)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%d", longBlockSize);
|
||||
}
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </testedMediaType>
|
||||
|
||||
if(!anyMedia)
|
||||
anyMedia = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(anyMedia)
|
||||
xmlTextWriterEndElement(xmlWriter); // </RemovableMedias>
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t blocks = 0;
|
||||
uint32_t blockSize = 0;
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ReadCapabilities"); // <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);
|
||||
}
|
||||
|
||||
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 (16)...\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)
|
||||
{
|
||||
user_response = ' ';
|
||||
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); // </ReadCapabilities>
|
||||
}
|
||||
}
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </SCSI>
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : scsi_report.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains definitions used in SCSI reports.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_SCSI_REPORT_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_SCSI_REPORT_H
|
||||
#define DIC_SCSI_REPORT_ELEMENT "SCSI"
|
||||
#define DIC_SCSI_INQUIRY_ELEMENT "Inquiry"
|
||||
|
||||
void ScsiReport(int fd, xmlTextWriterPtr xmlWriter);
|
||||
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_SCSI_REPORT_H
|
||||
@@ -1,375 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ssc_report.c
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Creates report for SCSI Streaming devices.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <libxml/xmlwriter.h>
|
||||
#include "ssc_report.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi_mode.h"
|
||||
|
||||
DensitySupport *DecodeDensity(unsigned char *response);
|
||||
|
||||
MediaTypeSupport *DecodeMediumTypes(unsigned char *response);
|
||||
|
||||
void SscReport(int fd, xmlTextWriterPtr xmlWriter)
|
||||
{
|
||||
unsigned char *sense = NULL;
|
||||
unsigned char *buffer = NULL;
|
||||
int i, error, len;
|
||||
char user_response = ' ';
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SequentialDevice"); // <SequentialDevice>
|
||||
|
||||
printf("Querying SCSI READ BLOCK LIMITS...\n");
|
||||
error = ReadBlockLimits(fd, &buffer, &sense);
|
||||
if(!error)
|
||||
{
|
||||
uint8_t granularity = (uint8_t)(buffer[0] & 0x1F);
|
||||
uint32_t maxBlockLen = (uint32_t)((buffer[1] << 16) + (buffer[2] << 8) + buffer[3]);
|
||||
uint16_t minBlockLen = (uint16_t)((buffer[4] << 8) + buffer[5]);
|
||||
|
||||
if(granularity > 0)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSizeGranularity", "%d", granularity);
|
||||
if(maxBlockLen > 0)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxBlockLength", "%d", maxBlockLen);
|
||||
if(minBlockLen > 0)
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinBlockLength", "%d", minBlockLen);
|
||||
}
|
||||
|
||||
printf("Querying SCSI REPORT DENSITY SUPPORT...\n");
|
||||
error = ReportDensitySupport(fd, &buffer, &sense, FALSE, FALSE);
|
||||
if(!error)
|
||||
{
|
||||
DensitySupport *dsh = DecodeDensity(buffer);
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensities"); // <SupportedDensities>
|
||||
|
||||
for(i = 0; i < dsh->count; i++)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensity"); // <SupportedDensity>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BitsPerMm", "%d",
|
||||
(dsh->descriptors[i]->bitsPerMm[0] << 16) +
|
||||
(dsh->descriptors[i]->bitsPerMm[1] << 8) +
|
||||
dsh->descriptors[i]->bitsPerMm[2]);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Capacity", "%d",
|
||||
be32toh(dsh->descriptors[i]->capacity));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DefaultDensity", "%s",
|
||||
dsh->descriptors[i]->deflt ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Description", "%20s",
|
||||
dsh->descriptors[i]->description);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Duplicate", "%s",
|
||||
dsh->descriptors[i]->dup ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Name", "%8s", dsh->descriptors[i]->densityName);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Organization", "%8s",
|
||||
dsh->descriptors[i]->organization);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PrimaryCode", "%d", dsh->descriptors[i]->primaryCode);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SecondaryCode", "%d",
|
||||
dsh->descriptors[i]->secondaryCode);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Tracks", "%d", be16toh(dsh->descriptors[i]->tracks));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Width", "%d",
|
||||
be16toh(dsh->descriptors[i]->mediaWidth));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Writable", "%s",
|
||||
dsh->descriptors[i]->wrtok ? "true" : "false");
|
||||
xmlTextWriterEndElement(xmlWriter); // </SupportedDensity>
|
||||
}
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </SupportedDensities>
|
||||
}
|
||||
|
||||
printf("Querying SCSI REPORT DENSITY SUPPORT for medium types...\n");
|
||||
error = ReportDensitySupport(fd, &buffer, &sense, TRUE, FALSE);
|
||||
if(!error)
|
||||
{
|
||||
MediaTypeSupport *mtsh = DecodeMediumTypes(buffer);
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedMediaTypes"); // <SupportedMediaTypes>
|
||||
|
||||
for(i = 0; i < mtsh->count; i++)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedMedia"); // <SupportedMedia>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Description", "%20s",
|
||||
mtsh->descriptors[i]->description);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Length", "%d", be16toh(mtsh->descriptors[i]->length));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumType", "%d", mtsh->descriptors[i]->mediumType);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Name", "%8s", mtsh->descriptors[i]->densityName);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Organization", "%8s",
|
||||
mtsh->descriptors[i]->organization);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Width", "%d",
|
||||
be16toh(mtsh->descriptors[i]->mediaWidth));
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensity"); // <SupportedDensity>
|
||||
// TODO: Density codes
|
||||
xmlTextWriterEndElement(xmlWriter); // </SupportedMedia>
|
||||
}
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </SupportedMediaTypes>
|
||||
}
|
||||
|
||||
user_response = ' ';
|
||||
int anyMedia = FALSE;
|
||||
DecodedMode *decMode;
|
||||
|
||||
while(user_response != 'N' && user_response != 'n')
|
||||
{
|
||||
do
|
||||
{
|
||||
printf("Do you have media that you can insert in the drive? (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')
|
||||
{
|
||||
printf("Please insert it in the drive and press any key when it is ready.\n");
|
||||
scanf("%c");
|
||||
|
||||
char mediaManufacturer[256], mediaName[256], mediaModel[256];
|
||||
printf("Please write a description of the media type and press enter: ");
|
||||
gets(mediaName);
|
||||
printf("Please write the media manufacturer and press enter: ");
|
||||
gets(mediaManufacturer);
|
||||
printf("Please write the media model and press enter: ");
|
||||
gets(mediaModel);
|
||||
|
||||
error = TestUnitReady(fd, &sense);
|
||||
int mediaRecognized = TRUE;
|
||||
int leftRetries = 20;
|
||||
|
||||
if(error)
|
||||
{
|
||||
if((sense[0] == 0x70 || sense[0] == 0x71) && (sense[2] & 0x0F) != 0x00)
|
||||
{
|
||||
if(sense[12] == 0x3A || (sense[12] == 0x04 && sense[13] == 0x01))
|
||||
{
|
||||
while(leftRetries > 0)
|
||||
{
|
||||
printf("\rWating for drive to become ready");
|
||||
sleep(2);
|
||||
error = TestUnitReady(fd, &sense);
|
||||
if(!error)
|
||||
break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
mediaRecognized = !error;
|
||||
}
|
||||
else
|
||||
mediaRecognized = FALSE;
|
||||
}
|
||||
else
|
||||
mediaRecognized = FALSE;
|
||||
}
|
||||
|
||||
if(!anyMedia)
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "TestedMedia"); // <TestedMedia>
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SequentialMedia"); // <SequentialMedia>
|
||||
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediaIsRecognized", "%s",
|
||||
mediaRecognized ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", mediaManufacturer);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumTypeName", "%s", mediaName);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Model", "%s", mediaModel);
|
||||
|
||||
if(mediaRecognized)
|
||||
{
|
||||
printf("Querying SCSI MODE SENSE (10)...\n");
|
||||
error = ModeSense10(fd, &buffer, &sense, FALSE, TRUE, MODE_PAGE_DEFAULT, 0x3F, 0x00);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense10", "%s",
|
||||
!error ? "true" : "false");
|
||||
if(!error)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense10Data");
|
||||
xmlTextWriterWriteBase64(xmlWriter, buffer, 0, (*(buffer + 0) << 8) + *(buffer + 1) + 2);
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
decMode = DecodeMode10(buffer, 0x01);
|
||||
}
|
||||
|
||||
printf("Querying SCSI MODE SENSE (6)...\n");
|
||||
error = ModeSense6(fd, &buffer, &sense, FALSE, MODE_PAGE_DEFAULT, 0x00, 0x00);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense6", "%s",
|
||||
!error ? "true" : "false");
|
||||
if(!error)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense6Data");
|
||||
xmlTextWriterWriteBase64(xmlWriter, buffer, 0, *(buffer + 0) + 1);
|
||||
xmlTextWriterEndElement(xmlWriter);
|
||||
if(decMode == NULL || !decMode->decoded)
|
||||
decMode = DecodeMode6(buffer, 0x01);
|
||||
}
|
||||
|
||||
if(decMode != NULL && 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("Querying SCSI REPORT DENSITY SUPPORT for current media...\n");
|
||||
error = ReportDensitySupport(fd, &buffer, &sense, FALSE, TRUE);
|
||||
if(!error)
|
||||
{
|
||||
DensitySupport *dsh = DecodeDensity(buffer);
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensities"); // <SupportedDensities>
|
||||
|
||||
for(i = 0; i < dsh->count; i++)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensity"); // <SupportedDensity>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BitsPerMm", "%d",
|
||||
(dsh->descriptors[i]->bitsPerMm[0] << 16) +
|
||||
(dsh->descriptors[i]->bitsPerMm[1] << 8) +
|
||||
dsh->descriptors[i]->bitsPerMm[2]);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Capacity", "%d",
|
||||
be32toh(dsh->descriptors[i]->capacity));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DefaultDensity", "%s",
|
||||
dsh->descriptors[i]->deflt ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Description", "%20s",
|
||||
dsh->descriptors[i]->description);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Duplicate", "%s",
|
||||
dsh->descriptors[i]->dup ? "true" : "false");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Name", "%8s",
|
||||
dsh->descriptors[i]->densityName);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Organization", "%8s",
|
||||
dsh->descriptors[i]->organization);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PrimaryCode", "%d",
|
||||
dsh->descriptors[i]->primaryCode);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SecondaryCode", "%d",
|
||||
dsh->descriptors[i]->secondaryCode);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Tracks", "%d",
|
||||
be16toh(dsh->descriptors[i]->tracks));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Width", "%d",
|
||||
be16toh(dsh->descriptors[i]->mediaWidth));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Writable", "%s",
|
||||
dsh->descriptors[i]->wrtok ? "true" : "false");
|
||||
xmlTextWriterEndElement(xmlWriter); // </SupportedDensity>
|
||||
}
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </SupportedDensities>
|
||||
}
|
||||
|
||||
|
||||
printf("Querying SCSI REPORT DENSITY SUPPORT for medium types for current media...\n");
|
||||
error = ReportDensitySupport(fd, &buffer, &sense, TRUE, TRUE);
|
||||
if(!error)
|
||||
{
|
||||
MediaTypeSupport *mtsh = DecodeMediumTypes(buffer);
|
||||
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedMediaTypes"); // <SupportedMediaTypes>
|
||||
|
||||
for(i = 0; i < mtsh->count; i++)
|
||||
{
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedMedia"); // <SupportedMedia>
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Description", "%20s",
|
||||
mtsh->descriptors[i]->description);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Length", "%d",
|
||||
be16toh(mtsh->descriptors[i]->length));
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumType", "%d",
|
||||
mtsh->descriptors[i]->mediumType);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Name", "%8s",
|
||||
mtsh->descriptors[i]->densityName);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Organization", "%8s",
|
||||
mtsh->descriptors[i]->organization);
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Width", "%d",
|
||||
be16toh(mtsh->descriptors[i]->mediaWidth));
|
||||
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensity"); // <SupportedDensity>
|
||||
// TODO: Density codes
|
||||
xmlTextWriterEndElement(xmlWriter); // </SupportedMedia>
|
||||
}
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </SupportedMediaTypes>
|
||||
}
|
||||
|
||||
printf("Trying SCSI READ MEDIA SERIAL NUMBER...\n");
|
||||
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s",
|
||||
!ReadMediaSerialNumber(fd, &buffer, &sense) ? "true" : "false");
|
||||
}
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </SequentialMedia>
|
||||
|
||||
if(!anyMedia)
|
||||
{
|
||||
xmlTextWriterEndElement(xmlWriter); // </TestedMedia>
|
||||
anyMedia = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xmlTextWriterEndElement(xmlWriter); // </SequentialDevice>
|
||||
}
|
||||
|
||||
DensitySupport *DecodeDensity(unsigned char *response)
|
||||
{
|
||||
DensitySupport *decoded = malloc(sizeof(DensitySupport));
|
||||
memset(decoded, 0, sizeof(DensitySupport));
|
||||
uint16_t responseLen = (uint16_t)((response[0] << 8) + response[1] + 2);
|
||||
int offset = 4;
|
||||
|
||||
while(offset + 3 < responseLen)
|
||||
{
|
||||
int lenValid = response[offset + 2] & 0x20;
|
||||
uint16_t descLen = (uint16_t)((response[offset + 3] << 8) + response[offset + 4] + 5);
|
||||
|
||||
decoded->descriptors[decoded->count] = malloc(sizeof(DensityDescriptor));
|
||||
memset(decoded->descriptors[decoded->count], 0, sizeof(DensityDescriptor));
|
||||
memcpy(decoded->descriptors[decoded->count], response + offset, sizeof(DensityDescriptor));
|
||||
|
||||
if(lenValid)
|
||||
offset += descLen;
|
||||
else
|
||||
offset += 52;
|
||||
|
||||
decoded->count++;
|
||||
}
|
||||
}
|
||||
|
||||
MediaTypeSupport *DecodeMediumTypes(unsigned char *response)
|
||||
{
|
||||
MediaTypeSupport *decoded = malloc(sizeof(MediaTypeSupport));
|
||||
memset(decoded, 0, sizeof(MediaTypeSupport));
|
||||
uint16_t responseLen = (uint16_t)((response[0] << 8) + response[1] + 2);
|
||||
int offset = 4;
|
||||
|
||||
while(offset + 3 < responseLen)
|
||||
{
|
||||
decoded->descriptors[decoded->count] = malloc(sizeof(MediumDescriptor));
|
||||
memset(decoded->descriptors[decoded->count], 0, sizeof(MediumDescriptor));
|
||||
memcpy(decoded->descriptors[decoded->count], response + offset, sizeof(MediumDescriptor));
|
||||
|
||||
offset += 56;
|
||||
decoded->count++;
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/***************************************************************************
|
||||
The Disc Image Chef
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Filename : ssc_report.h
|
||||
Author(s) : Natalia Portillo
|
||||
|
||||
Component : DiscImageChef.Device.Report
|
||||
|
||||
--[ Description ] ----------------------------------------------------------
|
||||
|
||||
Contains definitions used in SCSI Streaming device reports.
|
||||
|
||||
--[ License ] --------------------------------------------------------------
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
Copyright © 2011-2019 Natalia Portillo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DISCIMAGECHEF_DEVICE_REPORT_SSC_REPORT_H
|
||||
#define DISCIMAGECHEF_DEVICE_REPORT_SSC_REPORT_H
|
||||
|
||||
void SscReport(int fd, xmlTextWriterPtr xmlWriter);
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t primaryCode;
|
||||
uint8_t secondaryCode;
|
||||
uint8_t dlv : 1;
|
||||
uint8_t reserved : 4;
|
||||
uint8_t deflt : 1;
|
||||
uint8_t dup : 1;
|
||||
uint8_t wrtok : 1;
|
||||
uint16_t length;
|
||||
uint8_t bitsPerMm[3];
|
||||
uint16_t mediaWidth;
|
||||
uint16_t tracks;
|
||||
uint32_t capacity;
|
||||
unsigned char organization[8];
|
||||
unsigned char densityName[8];
|
||||
unsigned char description[20];
|
||||
} DensityDescriptor;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t mediumType;
|
||||
uint8_t reserved;
|
||||
uint16_t length;
|
||||
uint8_t codes_len;
|
||||
uint8_t codes[9];
|
||||
uint16_t mediaWidth;
|
||||
uint16_t mediumLength;
|
||||
uint16_t reserved2;
|
||||
unsigned char organization[8];
|
||||
unsigned char densityName[8];
|
||||
unsigned char description[20];
|
||||
} MediumDescriptor;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t count;
|
||||
DensityDescriptor *descriptors[1260];
|
||||
} DensitySupport;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t count;
|
||||
MediumDescriptor *descriptors[1170];
|
||||
} MediaTypeSupport;
|
||||
#endif //DISCIMAGECHEF_DEVICE_REPORT_SSC_REPORT_H
|
||||
Reference in New Issue
Block a user