Author: akhaldi Date: Tue Jul 31 17:18:47 2012 New Revision: 57003
URL: http://svn.reactos.org/svn/reactos?rev=57003&view=rev Log: [ATACTL] * Add atactl from the Uniata suite. It should be useful for troubleshooting uniata.
Added: trunk/reactos/base/applications/atactl/ (with props) trunk/reactos/base/applications/atactl/CMakeLists.txt (with props) trunk/reactos/base/applications/atactl/atactl.cpp (with props) trunk/reactos/base/applications/atactl/helper.h (with props) Modified: trunk/reactos/base/applications/CMakeLists.txt
Modified: trunk/reactos/base/applications/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/CMakeList... ============================================================================== --- trunk/reactos/base/applications/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/base/applications/CMakeLists.txt [iso-8859-1] Tue Jul 31 17:18:47 2012 @@ -1,4 +1,5 @@
+add_subdirectory(atactl) add_subdirectory(cacls) add_subdirectory(calc) add_subdirectory(charmap)
Propchange: trunk/reactos/base/applications/atactl/ ------------------------------------------------------------------------------ --- bugtraq:logregex (added) +++ bugtraq:logregex Tue Jul 31 17:18:47 2012 @@ -1,0 +1,2 @@ +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+)
Propchange: trunk/reactos/base/applications/atactl/ ------------------------------------------------------------------------------ bugtraq:message = See issue #%BUGID% for more details.
Propchange: trunk/reactos/base/applications/atactl/ ------------------------------------------------------------------------------ bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: trunk/reactos/base/applications/atactl/ ------------------------------------------------------------------------------ tsvn:logminsize = 10
Added: trunk/reactos/base/applications/atactl/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/atactl/CM... ============================================================================== --- trunk/reactos/base/applications/atactl/CMakeLists.txt (added) +++ trunk/reactos/base/applications/atactl/CMakeLists.txt [iso-8859-1] Tue Jul 31 17:18:47 2012 @@ -1,0 +1,16 @@ + +add_definitions(-DUSER_MODE) +include_directories(${REACTOS_SOURCE_DIR}/drivers/storage/ide/uniata) + +add_executable(atactl atactl.cpp) + +set_module_type(atactl win32cui) +add_importlibs(atactl advapi32 msvcrt kernel32 ntdll) + +if(NOT MSVC) + # FIXME: http://www.cmake.org/Bug/view.php?id=12998 + #allow_warnings(atactl) + set_source_files_properties(atactl.cpp PROPERTIES COMPILE_FLAGS "-Wno-error") + target_link_libraries(atactl gcc) +endif() +add_cd_file(TARGET atactl DESTINATION reactos/system32 FOR all)
Propchange: trunk/reactos/base/applications/atactl/CMakeLists.txt ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/base/applications/atactl/atactl.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/atactl/at... ============================================================================== --- trunk/reactos/base/applications/atactl/atactl.cpp (added) +++ trunk/reactos/base/applications/atactl/atactl.cpp [iso-8859-1] Tue Jul 31 17:18:47 2012 @@ -1,0 +1,1710 @@ +#include <windows.h> +#include <WinIoCtl.h> +#include <stdio.h> +//#include <ntdddisk.h> +//#include <ntddscsi.h> +#include <ntddscsi.h> +#include <atapi.h> +#include <bm_devs.h> +#include <uata_ctl.h> +#include <tools.h> +#include <uniata_ver.h> + +#include "helper.h" + +#define DEFAULT_REMOVAL_LOCK_TIMEOUT 20 + +#define MOV_DW_SWP(a,b) \ +do \ +{ \ + *(unsigned short *)&(a) = _byteswap_ushort(*(unsigned short *)&(b)); \ +} \ +while (0) + +#define MOV_DD_SWP(a,b) \ +{ \ + PFOUR_BYTE _from_, _to_; \ + _from_ = ((PFOUR_BYTE)&(b)); \ + _to_ = ((PFOUR_BYTE)&(a)); \ + __asm mov ebx,_from_ \ + __asm mov eax,[ebx] \ + __asm bswap eax \ + __asm mov ebx,_to_ \ + __asm mov [ebx],eax \ +} + +int g_extended = 0; +int g_adapter_info = 0; +char* g_bb_list = NULL; +int gRadix = 16; + +void print_help() { + printf("Usage:\n" + " atactl -<switches> c|s<controller id>:b<bus id>:d<device id>[:l<lun>]\n" + "Switches:\n" + " l (L)ist devices on SCSI and ATA controllers bus(es)\n" + " Note: ATA Pri/Sec controller are usually represented\n" + " as Scsi0/Scsi1 under NT-family OSes\n" + " x show e(X)tended info\n" + " a show (A)dapter info\n" + " s (S)can for new devices on ATA/SATA bus(es) (experimental)\n" + " S (S)can for new devices on ATA/SATA bus(es) (experimental)\n" + " device, hidden with 'H' can be redetected\n" + " h (H)ide device on ATA/SATA bus for removal (experimental)\n" + " device can be redetected\n" + " H (H)ide device on ATA/SATA bus (experimental)\n" + " device can not be redetected until 'h' or 'S' is issued\n" + " m [MODE] set i/o (M)ode for device or revert to default\n" + " available MODEs are PIO, PIO0-PIO5, DMA, WDMA0-WDMA2,\n" + " UDMA33/44/66/100/133, UDMA0-UDMA5\n" + " d [XXX] lock ATA/SATA bus for device removal for XXX seconds or\n" + " for %d seconds if no lock timeout specified.\n" + " can be used with -h, -m or standalone.\n" + " r (R)eset device\n" + " ba (A)ssign (B)ad-block list\n" + " bl get assigned (B)ad-block (L)ist\n" + " br (R)eset assigned (B)ad-block list\n" + " f specify (F)ile for bad-block list\n" + " n XXX block (n)ubmering radix. XXX can be hex or dec\n" + "------\n" + "Examples:\n" + " atactl -l\n" + " will list all scsi buses and all connected devices\n" + " atactl -m udma0 s2:b1:d1\n" + " will switch device at Scsi2, bus 1, taget_id 1 to UDMA0 mode\n" + " atactl -h -d 30 c1:b0:d0:l0 \n" + " will hide Master (d0:l0) device on secondary (c1:b0) IDE channel\n" + " and lock i/o on this channel for 30 seconds to ensure safity\n" + " of removal process" + "------\n" + "Device address format:\n" + "\n" + "s<controller id> number of controller in system. Is assigned during hardware\n" + " detection. Usually s0/s1 are ATA Pri/Sec.\n" + " Note, due do NT internal desing ATA controllers are represented\n" + " as SCSI controllers.\n" + "b<bus id> For ATA controllers it is channel number.\n" + " Note, usually onboard controller is represented as 2 legacy\n" + " ISA-compatible single-channel controllers (Scsi9/Scsi1). Additional\n" + " ATA, ATA-RAID and some specific onboard controllers are represented\n" + " as multichannel controllers.\n" + "d<device id> For ATA controllers d0 is Master, d1 is Slave.\n" + "l<lun> Not used in ATA controller drivers, alway 0\n" + "------\n" + "Bad-block list format:\n" + "\n" + "# Comment\n" + "; Still one comment\n" + "hex: switch to hexadecimal mode\n" + "<Bad Area 1 Start LBA, e.g. FD50> <Block count 1, e.g. 60>\n" + "<Bad Area 2 Start LBA> <Block count 2>\n" + "...\n" + "dec: switch to decimal mode\n" + "<Bad Area N Start LBA, e.g. 16384> <Block count N, e.g. 48>\n" + "...\n" + "------\n" + "", + DEFAULT_REMOVAL_LOCK_TIMEOUT + ); + exit(0); +} + +#define CMD_ATA_LIST 0x01 +#define CMD_ATA_FIND 0x02 +#define CMD_ATA_HIDE 0x03 +#define CMD_ATA_MODE 0x04 +#define CMD_ATA_RESET 0x05 +#define CMD_ATA_BBLK 0x06 + +HANDLE +ata_open_dev( + char* Name + ) +{ + ULONG i; + HANDLE h; + + for(i=0; i<4; i++) { + h = CreateFile(Name, + READ_CONTROL | GENERIC_READ | GENERIC_WRITE , + ((i & 1) ? 0 : FILE_SHARE_READ) | ((i & 2) ? 0 : FILE_SHARE_WRITE), + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(h && (h != ((HANDLE)(-1))) ) { + return h; + } + } + + for(i=0; i<4; i++) { + h = CreateFile(Name, + GENERIC_READ | GENERIC_WRITE , + ((i & 1) ? 0 : FILE_SHARE_READ) | ((i & 2) ? 0 : FILE_SHARE_WRITE), + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(h && (h != ((HANDLE)(-1))) ) { + return h; + } + } + + for(i=0; i<4; i++) { + h = CreateFile(Name, + GENERIC_READ, + ((i & 1) ? 0 : FILE_SHARE_READ) | ((i & 2) ? 0 : FILE_SHARE_WRITE), + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(h && (h != ((HANDLE)(-1))) ) { + return h; + } + } + + for(i=0; i<4; i++) { + h = CreateFile(Name, + READ_CONTROL, + ((i & 1) ? 0 : FILE_SHARE_READ) | ((i & 2) ? 0 : FILE_SHARE_WRITE), + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(h && (h != ((HANDLE)(-1))) ) { + return h; + } + } + + return NULL; +} // end ata_open_dev() + +HANDLE +ata_open_file( + char* Name, + BOOLEAN create + ) +{ + ULONG i; + HANDLE h; + + if(!Name) { + if(create) { + return GetStdHandle(STD_OUTPUT_HANDLE); + } else { + return GetStdHandle(STD_INPUT_HANDLE); + } + } + + for(i=0; i<4; i++) { + h = CreateFile(Name, + create ? GENERIC_WRITE : GENERIC_READ , + ((i & 1) ? 0 : FILE_SHARE_READ) | ((i & 2) ? 0 : FILE_SHARE_WRITE), + NULL, + create ? CREATE_NEW : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if(h && (h != ((HANDLE)(-1))) ) { + return h; + } + } + + return NULL; +} // end ata_open_file() + +void +ata_close_dev( + HANDLE h + ) +{ + CloseHandle(h); +} // end ata_close_dev() + +int +ata_send_ioctl( + HANDLE h, + PSCSI_ADDRESS addr, + PCHAR Signature, + ULONG Ioctl, + PVOID inBuffer, + ULONG inBufferLength, + PVOID outBuffer, + ULONG outBufferLength, + PULONG returned + ) +{ + ULONG status; + PUNIATA_CTL AtaCtl; + ULONG data_len = max(inBufferLength, outBufferLength); + ULONG len; + + if(addr) { + len = data_len + offsetof(UNIATA_CTL, RawData); + } else { + len = data_len + sizeof(AtaCtl->hdr); + } + AtaCtl = (PUNIATA_CTL)GlobalAlloc(GMEM_FIXED, len); + AtaCtl->hdr.HeaderLength = sizeof(SRB_IO_CONTROL); + if(addr) { + AtaCtl->hdr.Length = data_len + offsetof(UNIATA_CTL, RawData) - sizeof(AtaCtl->hdr); + } else { + AtaCtl->hdr.Length = data_len; + } + + memcpy(&AtaCtl->hdr.Signature, Signature, 8); + + AtaCtl->hdr.Timeout = 10000; + AtaCtl->hdr.ControlCode = Ioctl; + AtaCtl->hdr.ReturnCode = 0; + + if(addr) { + AtaCtl->addr = *addr; + AtaCtl->addr.Length = sizeof(AtaCtl->addr); + } + + if(inBuffer && inBufferLength) { + if(addr) { + memcpy(&AtaCtl->RawData, inBuffer, inBufferLength); + } else { + memcpy(&AtaCtl->addr, inBuffer, inBufferLength); + } + } + + status = DeviceIoControl(h, + IOCTL_SCSI_MINIPORT, + AtaCtl, + len, + AtaCtl, + len, + returned, + FALSE); + + if(outBuffer && outBufferLength) { + if(addr) { + memcpy(outBuffer, &AtaCtl->RawData, outBufferLength); + } else { + memcpy(outBuffer, &AtaCtl->addr, outBufferLength); + } + } + GlobalFree(AtaCtl); + + if(!status) { + status = GetLastError(); + return FALSE; + } + return TRUE; +} // end ata_send_ioctl() + +IO_SCSI_CAPABILITIES g_capabilities; +UCHAR g_inquiry_buffer[2048]; + +int +ata_is_sata( + PIDENTIFY_DATA ident + ) +{ + return (ident->SataEnable && ident->SataEnable != 0xffff); +} + +int +ata_cur_mode_from_ident( + PIDENTIFY_DATA ident + ) +{ + if(ata_is_sata(ident)) { + return ATA_SA150-1; + } + + if (ident->UdmaModesValid) { + if (ident->UltraDMAActive & 0x40) + return ATA_UDMA0+6; + if (ident->UltraDMAActive & 0x20) + return ATA_UDMA0+5; + if (ident->UltraDMAActive & 0x10) + return ATA_UDMA0+4; + if (ident->UltraDMAActive & 0x08) + return ATA_UDMA0+3; + if (ident->UltraDMAActive & 0x04) + return ATA_UDMA0+2; + if (ident->UltraDMAActive & 0x02) + return ATA_UDMA0+1; + if (ident->UltraDMAActive & 0x01) + return ATA_UDMA0+0; + } + + if (ident->MultiWordDMAActive & 0x04) + return ATA_WDMA0+2; + if (ident->MultiWordDMAActive & 0x02) + return ATA_WDMA0+1; + if (ident->MultiWordDMAActive & 0x01) + return ATA_WDMA0+0; + + if (ident->SingleWordDMAActive & 0x04) + return ATA_SDMA0+2; + if (ident->SingleWordDMAActive & 0x02) + return ATA_SDMA0+1; + if (ident->SingleWordDMAActive & 0x01) + return ATA_SDMA0+0; + + if (ident->PioTimingsValid) { + if (ident->AdvancedPIOModes & AdvancedPIOModes_5) + return ATA_PIO0+5; + if (ident->AdvancedPIOModes & AdvancedPIOModes_4) + return ATA_PIO0+4; + if (ident->AdvancedPIOModes & AdvancedPIOModes_3) + return ATA_PIO0+3; + } + if (ident->PioCycleTimingMode == 2) + return ATA_PIO0+2; + if (ident->PioCycleTimingMode == 1) + return ATA_PIO0+1; + if (ident->PioCycleTimingMode == 0) + return ATA_PIO0+0; + + return ATA_PIO; +} // end ata_cur_mode_from_ident() + +void +ata_mode_to_str( + char* str, + int mode + ) +{ + if(mode == ATA_SA150-1) { + sprintf(str, "SATA"); + } else + if(mode >= ATA_SA300) { + sprintf(str, "SATA-300"); + } else + if(mode >= ATA_SA150) { + sprintf(str, "SATA-150"); + } else + if(mode >= ATA_UDMA0) { + sprintf(str, "UDMA%d", mode-ATA_UDMA0); + } else + if(mode >= ATA_WDMA0) { + sprintf(str, "WDMA%d", mode-ATA_WDMA0); + } else + if(mode >= ATA_SDMA0) { + sprintf(str, "SDMA%d", mode-ATA_SDMA0); + } else + if(mode >= ATA_PIO0) { + sprintf(str, "PIO%d", mode-ATA_PIO0); + } else + if(mode == ATA_PIO_NRDY) { + sprintf(str, "PIO nRDY"); + } else + { + sprintf(str, "PIO"); + } +} // end ata_mode_to_str() + +#define check_atamode_str(str, mode) \ + (!_stricmp(str, "UDMA" #mode) || \ + !_stricmp(str, "UDMA-" #mode) || \ + !_stricmp(str, "ATA-" #mode) || \ + !_stricmp(str, "ATA#" #mode)) + +int +ata_str_to_mode( + char* str + ) +{ + int mode; + int len; + + if(!_stricmp(str, "SATA")) + return ATA_SA150; + + if(check_atamode_str(str, 16)) + return ATA_UDMA0; + if(check_atamode_str(str, 25)) + return ATA_UDMA1; + if(check_atamode_str(str, 33)) + return ATA_UDMA2; + if(check_atamode_str(str, 44)) + return ATA_UDMA3; + if(check_atamode_str(str, 66)) + return ATA_UDMA4; + if(check_atamode_str(str, 100)) + return ATA_UDMA5; + if(check_atamode_str(str, 122)) + return ATA_UDMA6; + + len = strlen(str); + + if(len >= 4 && !_memicmp(str, "UDMA", 4)) { + if(len == 4) + return ATA_UDMA0; + if(len > 5) + return -1; + mode = str[4] - '0'; + if(mode < 0 || mode > 7) + return -1; + return ATA_UDMA0+mode; + } + if(len >= 4 && !_memicmp(str, "WDMA", 4)) { + if(len == 4) + return ATA_WDMA0; + if(len > 5) + return -1; + mode = str[4] - '0'; + if(mode < 0 || mode > 2) + return -1; + return ATA_WDMA0+mode; + } + if(len >= 4 && !_memicmp(str, "SDMA", 4)) { + if(len == 4) + return ATA_SDMA0; + if(len > 5) + return -1; + mode = str[4] - '0'; + if(mode < 0 || mode > 2) + return -1; + return ATA_SDMA0+mode; + } + if(len == 4 && !_memicmp(str, "DMA", 4)) { + return ATA_SDMA0; + } + if(len >= 3 && !_memicmp(str, "PIO", 3)) { + if(len == 3) + return ATA_PIO; + if(len > 4) + return -1; + mode = str[3] - '0'; + if(mode < 0 || mode > 5) + return -1; + return ATA_PIO0+mode; + } + + return -1; +} // end ata_str_to_mode() + +ULONG +EncodeVendorStr( + OUT char* Buffer, + IN PUCHAR Str, + IN ULONG Length, + IN ULONG Xorer + ) +{ + ULONG i,j; + UCHAR a; + + for(i=0, j=0; i<Length; i++, j++) { + a = Str[i ^ Xorer]; + if(!a) { + Buffer[j] = 0; + return j; + } else + if(a == ' ') { + Buffer[j] = '_'; + } else + if((a == '_') || + (a == '#') || + (a == '\') || + (a == '"') || + (a == ''') || + (a < ' ') || + (a >= 127)) { + Buffer[j] = '#'; + j++; + sprintf(Buffer+j, "%2.2x", a); + j++; + } else { + Buffer[j] = a; + } + } + Buffer[j] = 0; + return j; +} // end EncodeVendorStr() + +HKEY +ata_get_bblist_regh( + IN PIDENTIFY_DATA ident, + OUT char* DevSerial, + BOOLEAN read_only + ) +{ + HKEY hKey = NULL; + HKEY hKey2 = NULL; + ULONG Length; + REGSAM access = read_only ? KEY_READ : KEY_ALL_ACCESS; + + Length = EncodeVendorStr(DevSerial, (PUCHAR)ident->ModelNumber, sizeof(ident->ModelNumber), 0x01); + DevSerial[Length] = '-'; + Length++; + Length += EncodeVendorStr(DevSerial+Length, ident->SerialNumber, sizeof(ident->SerialNumber), 0x01); + + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\UniATA", NULL, access, &hKey) != ERROR_SUCCESS) { + hKey = NULL; + goto exit; + } + if(RegOpenKey(hKey, "Parameters", &hKey2) != ERROR_SUCCESS) { + hKey2 = NULL; + if(read_only || (RegCreateKey(hKey, "Parameters", &hKey2) != ERROR_SUCCESS)) { + hKey2 = NULL; + goto exit; + } + } + RegCloseKey(hKey2); + if(RegOpenKey(hKey, "Parameters\BadBlocks", &hKey2) != ERROR_SUCCESS) { + hKey2 = NULL; + if(read_only || (RegCreateKey(hKey, "Parameters\BadBlocks", &hKey2) != ERROR_SUCCESS)) { + hKey2 = NULL; + goto exit; + } + } + +exit: + if(hKey) + RegCloseKey(hKey); + + return hKey2; +} // end ata_get_bblist_regh() + +IDENTIFY_DATA g_ident; + +int +ata_check_unit( + HANDLE h, // handle to ScsiXXX: + int dev_id + ) +{ + ULONG status; + ULONG returned; + + PSCSI_ADAPTER_BUS_INFO adapterInfo; + PSCSI_INQUIRY_DATA inquiryData; + SCSI_ADDRESS addr; + ULONG i, j; + int l_dev_id; + ULONG len; + GETTRANSFERMODE IoMode; + PSENDCMDOUTPARAMS pout; + PIDENTIFY_DATA ident; + char buff[sizeof(SENDCMDOUTPARAMS)+/*sizeof(IDENTIFY_DATA)*/2048]; + char mode_str[12]; + ULONG bus_id = (dev_id >> 24) & 0xff; + BOOLEAN found = FALSE; + SENDCMDINPARAMS pin; + int io_mode = -1; + char SerNum[128]; + char DevSerial[128]; + char lun_str[10]; + HKEY hKey2; + ULONGLONG max_lba = -1; + USHORT chs[3]; + + if(dev_id != -1) { + dev_id &= 0x00ffffff; + } + if(dev_id == 0x007f7f7f) { + return TRUE; + } + + pout = (PSENDCMDOUTPARAMS)buff; + ident = (PIDENTIFY_DATA)&(pout->bBuffer); + + status = DeviceIoControl(h, + IOCTL_SCSI_GET_INQUIRY_DATA, + NULL, + 0, + g_inquiry_buffer, + sizeof(g_inquiry_buffer), + &returned, + FALSE); + + if(!status) { + printf("Can't get device info\n"); + return FALSE; + } + + adapterInfo = (PSCSI_ADAPTER_BUS_INFO)g_inquiry_buffer; + for (i = 0; i < adapterInfo->NumberOfBuses; i++) { + inquiryData = (PSCSI_INQUIRY_DATA) (g_inquiry_buffer + + adapterInfo->BusData[i].InquiryDataOffset); + while (adapterInfo->BusData[i].InquiryDataOffset) { + /* + if(dev_id/adapterInfo->BusData[i].NumberOfLogicalUnits == + inquiryData->TargetId && + dev_id%adapterInfo->BusData[i].NumberOfLogicalUnits == + inquiryData->Lun) { + printf(" %d %d %3d %s %.28s ", + i, + inquiryData->TargetId, + inquiryData->Lun, + (inquiryData->DeviceClaimed) ? "Y" : "N", + &inquiryData->InquiryData[8]); + }*/ + l_dev_id = (i << 16) | ((ULONG)(inquiryData->TargetId) << 8) | inquiryData->Lun; + + if(l_dev_id == dev_id || dev_id == -1) { + + if(!memcmp(&inquiryData->InquiryData[8], UNIATA_COMM_PORT_VENDOR_STR, 24)) { + // skip communication port + goto next_dev; + } + + found = TRUE; + + if(inquiryData->Lun) { + sprintf(lun_str, ":l%d", inquiryData->Lun); + } else { + sprintf(lun_str, " ", inquiryData->Lun); + } + + + /* + for (j = 0; j < 8; j++) { + printf("%02X ", inquiryData->InquiryData[j]); + } + */ + + addr.PortNumber = -1; + addr.PathId = inquiryData->PathId; + addr.TargetId = inquiryData->TargetId; + addr.Lun = inquiryData->Lun; + status = ata_send_ioctl(h, &addr, "-UNIATA-", + IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE, + NULL, 0, + &IoMode, sizeof(IoMode), + &returned); + if(status) { + //io_mode = min(IoMode.CurrentMode, IoMode.MaxMode); + io_mode = min(max(IoMode.CurrentMode,IoMode.OrigMode),IoMode.MaxMode); + } else { + io_mode = -1; + } + + memset(&pin, 0, sizeof(pin)); + memset(buff, 0, sizeof(buff)); + pin.irDriveRegs.bCommandReg = ID_CMD; + // this is valid for IDE/ATA, where only 2 devices can be attached to the bus. + // probably, we shall change this in future to support SATA splitters + pin.bDriveNumber = inquiryData->PathId*2+inquiryData->TargetId; + + status = ata_send_ioctl(h, NULL, "SCSIDISK", + IOCTL_SCSI_MINIPORT_IDENTIFY, + &pin, sizeof(pin), + buff, sizeof(buff), + &returned); + + if(!status) { + memset(&pin, 0, sizeof(pin)); + memset(buff, 0, sizeof(buff)); + pin.irDriveRegs.bCommandReg = ATAPI_ID_CMD; + // this is valid for IDE/ATA, where only 2 devices can be attached to the bus. + // probably, we shall change this in future to support SATA splitters + pin.bDriveNumber = inquiryData->PathId*2+inquiryData->TargetId; + + status = ata_send_ioctl(h, NULL, "SCSIDISK", + IOCTL_SCSI_MINIPORT_IDENTIFY, + &pin, sizeof(pin), + buff, sizeof(buff), + &returned); + + } + + if(status) { + if(!g_extended) { + printf(" b%d:d%d%s %24.24s %4.4s ", + i, + inquiryData->TargetId, + lun_str, + /*(inquiryData->DeviceClaimed) ? "Y" : "N",*/ + (g_extended ? (PUCHAR)"" : &inquiryData->InquiryData[8]), + (g_extended ? (PUCHAR)"" : &inquiryData->InquiryData[8+24]) + ); + } else { + printf(" b%d:d%d%s ", + i, + inquiryData->TargetId, + lun_str + ); + } + if(io_mode == -1) { + io_mode = ata_cur_mode_from_ident(ident); + } + } else { + goto next_dev; + + } + if(io_mode != -1) { + ata_mode_to_str(mode_str, io_mode); + } + if(!g_extended || !status) { + if(g_extended) { + printf(" %24.24s %4.4s ", + (&inquiryData->InquiryData[8]), + (&inquiryData->InquiryData[8+24]) + ); + } + if(io_mode != -1) { + printf(" %.12s ", mode_str); + } + } + printf("\n"); + + if(status && g_extended) { + + BOOLEAN BlockMode_valid = TRUE; + BOOLEAN print_geom = FALSE; + + switch(ident->DeviceType) { + case ATAPI_TYPE_DIRECT: + if(ident->Removable) { + printf(" Floppy "); + } else { + printf(" Hard Drive "); + } + break; + case ATAPI_TYPE_TAPE: + printf(" Tape Drive "); + break; + case ATAPI_TYPE_CDROM: + printf(" CD/DVD Drive "); + BlockMode_valid = FALSE; + break; + case ATAPI_TYPE_OPTICAL: + printf(" Optical Drive "); + BlockMode_valid = FALSE; + break; + default: + printf(" Hard Drive "); + print_geom = 1; + //MOV_DD_SWP(max_lba, ident->UserAddressableSectors); + max_lba = ident->UserAddressableSectors; + if(ident->FeaturesSupport.Address48) { + max_lba = ident->UserAddressableSectors48; + } + //MOV_DW_SWP(chs[0], ident->NumberOfCylinders); + //MOV_DW_SWP(chs[1], ident->NumberOfHeads); + //MOV_DW_SWP(chs[2], ident->SectorsPerTrack); + chs[0] = ident->NumberOfCylinders; + chs[1] = ident->NumberOfHeads; + chs[2] = ident->SectorsPerTrack; + } + if(io_mode != -1) { + printf(" %.12s\n", mode_str); + } + for (j = 0; j < 40; j += 2) { + MOV_DW_SWP(SerNum[j], ((PUCHAR)ident->ModelNumber)[j]); + } + printf(" Mod: %40.40s\n", SerNum); + for (j = 0; j < 8; j += 2) { + MOV_DW_SWP(SerNum[j], ((PUCHAR)ident->FirmwareRevision)[j]); + } + printf(" Rev: %8.8s\n", SerNum); + for (j = 0; j < 20; j += 2) { + MOV_DW_SWP(SerNum[j], ((PUCHAR)ident->SerialNumber)[j]); + } + printf(" S/N: %20.20s\n", SerNum); + + if(BlockMode_valid) { + if(ident->MaximumBlockTransfer) { + printf(" Multi-block mode: %d block%s\n", ident->MaximumBlockTransfer, ident->MaximumBlockTransfer == 1 ? "" : "s"); + } else { + printf(" Multi-block mode: N/A\n"); + } + } + if(print_geom) { + printf(" C/H/S: %d/%d/%d \n", chs[0], chs[1], chs[2]); + printf(" LBA: %d \n", max_lba); + if(max_lba < 2) { + printf(" Size: %d kb\n", max_lba/2); + } else + if(max_lba < 2*1024*1024) { + printf(" Size: %d Mb\n", max_lba/2048); + } else + if(max_lba < (ULONG)2*1024*1024*1024) { + printf(" Size: %d.%d (%d) Gb\n", (ULONG)(max_lba/2048/1024), + (ULONG)(((max_lba/2048)%1024)/10), + (ULONG)(max_lba*512/1000/1000/1000) + ); + } else { + printf(" Size: %d.%d (%d) Tb\n", (ULONG)(max_lba/2048/1024/1024), + (ULONG)((max_lba/2048/1024)%1024)/10, + (ULONG)(max_lba*512/1000/1000/1000) + ); + } + } + len = 0; + if(hKey2 = ata_get_bblist_regh(ident, DevSerial, TRUE)) { + if(RegQueryValueEx(hKey2, DevSerial, NULL, NULL, NULL, &len) == ERROR_SUCCESS) { + printf(" !!! Assigned bad-block list !!!\n"); + } + RegCloseKey(hKey2); + } + + } + memcpy(&g_ident, ident, sizeof(IDENTIFY_DATA)); + } +next_dev: + if (inquiryData->NextInquiryDataOffset == 0) { + break; + } + + inquiryData = (PSCSI_INQUIRY_DATA) (g_inquiry_buffer + + inquiryData->NextInquiryDataOffset); + } + } + if(!found) { + printf(" No device(s) found.\n"); + return FALSE; + } + + return TRUE; +} // end ata_check_unit() + +BOOLEAN +ata_adapter_info( + int bus_id, + int print_info + ) +{ + char dev_name[64]; + HANDLE h; + ADAPTERINFO AdapterInfo; + ULONG status; + ULONG returned; + SCSI_ADDRESS addr; + PCI_SLOT_NUMBER slotData; + + sprintf(dev_name, "\\.\Scsi%d:", bus_id); + h = ata_open_dev(dev_name); + if(!h) + return FALSE; + addr.PortNumber = bus_id; + + memset(&AdapterInfo, 0, sizeof(AdapterInfo)); + + status = ata_send_ioctl(h, &addr, "-UNIATA-", + IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO, + &AdapterInfo, sizeof(AdapterInfo), + &AdapterInfo, sizeof(AdapterInfo), + &returned); + printf("Scsi%d: %s\n", bus_id, status ? "[UniATA]" : ""); + if(print_info) { + if(!status) { + printf("Can't get adapter info\n"); + } else { + if(AdapterInfo.AdapterInterfaceType == PCIBus) { + slotData.u.AsULONG = AdapterInfo.slotNumber; + printf(" PCI Bus/Dev/Func: %d/%d/%d%s\n", + AdapterInfo.SystemIoBusNumber, slotData.u.bits.DeviceNumber, slotData.u.bits.FunctionNumber, + AdapterInfo.AdapterInterfaceType == AdapterInfo.OrigAdapterInterfaceType ? "" : " (ISA-Bridged)"); + printf(" VendorId/DevId/Rev: %#04x/%#04x/%#02x\n", AdapterInfo.DevID >> 16, AdapterInfo.DevID & 0xffff, AdapterInfo.RevID); + if(AdapterInfo.DeviceName[0]) { + printf(" Name: %s\n", AdapterInfo.DeviceName); + } + } else + if(AdapterInfo.AdapterInterfaceType == Isa) { + printf(" ISA Bus\n"); + } + printf(" IRQ: %d\n", AdapterInfo.BusInterruptLevel); + } + } + ata_close_dev(h); + return status ? TRUE : FALSE; +} // end ata_adapter_info() + +int +ata_check_controller( + HANDLE h, // handle to ScsiXXX: + PIO_SCSI_CAPABILITIES capabilities + ) +{ + ULONG status; + ULONG returned; + + status = DeviceIoControl(h, + IOCTL_SCSI_GET_CAPABILITIES, + NULL, + 0, + capabilities, + sizeof(IO_SCSI_CAPABILITIES), + &returned, + FALSE); + return status; +} // end ata_check_controller() + +BOOLEAN +ata_list( + int bus_id, + int dev_id + ) +{ + char dev_name[64]; + HANDLE h; + BOOLEAN uniata_driven; + + if(bus_id == -1) { + for(bus_id=0; TRUE; bus_id++) { + if(!ata_list(bus_id, dev_id)) + break; + } + return TRUE; + } + uniata_driven = ata_adapter_info(bus_id, g_adapter_info); + sprintf(dev_name, "\\.\Scsi%d:", bus_id); + h = ata_open_dev(dev_name); + if(!h) + return FALSE; + if(dev_id == -1) { + ata_check_controller(h, &g_capabilities); + ata_check_unit(h, -1); + ata_close_dev(h); + return TRUE; + } + ata_check_unit(h, dev_id | (bus_id << 24)); + ata_close_dev(h); + return TRUE; +} // end ata_list() + +BOOLEAN +ata_mode( + int bus_id, + int dev_id, + int mode + ) +{ + char dev_name[64]; + HANDLE h; + SETTRANSFERMODE IoMode; + ULONG status; + ULONG returned; + SCSI_ADDRESS addr; + + if(dev_id == -1) { + return FALSE; + } + sprintf(dev_name, "\\.\Scsi%d:", bus_id); + h = ata_open_dev(dev_name); + if(!h) + return FALSE; + addr.PortNumber = bus_id; + addr.PathId = (UCHAR)(dev_id >> 16); + addr.TargetId = (UCHAR)(dev_id >> 8); + addr.Lun = (UCHAR)(dev_id); + + IoMode.MaxMode = mode; + IoMode.ApplyImmediately = FALSE; +// IoMode.ApplyImmediately = TRUE; + IoMode.OrigMode = mode; + + status = ata_send_ioctl(h, &addr, "-UNIATA-", + IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE, + &IoMode, sizeof(IoMode), + NULL, 0, + &returned); + if(!status) { + printf("Can't apply specified transfer mode\n"); + } else { + ata_mode_to_str(dev_name, mode); + printf("Transfer rate switched to %s\n", dev_name); + } + ata_close_dev(h); + return status ? TRUE : FALSE; +} // end ata_mode() + +BOOLEAN +ata_reset( + int bus_id, + int dev_id + ) +{ + char dev_name[64]; + HANDLE h; + ULONG status; + ULONG returned; + SCSI_ADDRESS addr; + + if(dev_id == -1) { + return FALSE; + } + sprintf(dev_name, "\\.\Scsi%d:", bus_id); + h = ata_open_dev(dev_name); + if(!h) + return FALSE; + addr.PortNumber = bus_id; + addr.PathId = (UCHAR)(dev_id >> 16); + addr.TargetId = (UCHAR)(dev_id >> 8); + addr.Lun = (UCHAR)(dev_id); + + if(addr.TargetId == 0x7f && addr.Lun == 0x7f) { + addr.TargetId = (UCHAR)0xff; + addr.Lun = 0; + printf("Resetting channel...\n"); + } else { + printf("Resetting device...\n"); + } + + status = ata_send_ioctl(h, &addr, "-UNIATA-", + IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE, + NULL, 0, + NULL, 0, + &returned); + if(!status) { + printf("Reset failed\n"); + } else { + printf("Channel reset done\n"); + } + ata_close_dev(h); + return TRUE; +} // end ata_reset() + +BOOLEAN +ata_hide( + int bus_id, + int dev_id, + int lock, + int persistent_hide + ) +{ + char dev_name[64]; + HANDLE h; + ULONG status; + ULONG returned; + SCSI_ADDRESS addr; + ADDREMOVEDEV to; + + if(dev_id == -1) { + return FALSE; + } + if(lock < 0) { + lock = DEFAULT_REMOVAL_LOCK_TIMEOUT; + } + sprintf(dev_name, "\\.\Scsi%d:", bus_id); + h = ata_open_dev(dev_name); + if(!h) + return FALSE; + addr.PortNumber = bus_id; + addr.PathId = (UCHAR)(dev_id >> 16); + addr.TargetId = (UCHAR)(dev_id >> 8); + addr.Lun = (UCHAR)(dev_id); + + to.WaitForPhysicalLink = lock; + to.Flags = persistent_hide ? UNIATA_REMOVE_FLAGS_HIDE : 0; + + printf("Deleting device.\n"); + if(lock) { + printf("ATTENTION: you have %d seconds to disconnect cable\n", lock); + } + status = ata_send_ioctl(h, &addr, "-UNIATA-", + IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE, + &to, sizeof(to), + NULL, 0, + &returned); + ata_close_dev(h); + return TRUE; +} // end ata_hide() + +BOOLEAN +ata_scan( + int bus_id, + int dev_id, + int lock, + int unhide + ) +{ + char dev_name[64]; + HANDLE h; + ULONG status; + ULONG returned; + SCSI_ADDRESS addr; + ADDREMOVEDEV to; + + if(dev_id == -1) { + return FALSE; + } + if(lock < 0) { + lock = DEFAULT_REMOVAL_LOCK_TIMEOUT; + } + sprintf(dev_name, "\\.\Scsi%d:", bus_id); + h = ata_open_dev(dev_name); + if(!h) + return FALSE; + + if((UCHAR)(dev_id) != 0xff && + (UCHAR)(dev_id >> 8) != 0xff) { + + addr.PortNumber = bus_id; + addr.PathId = (UCHAR)(dev_id >> 16); + addr.TargetId = 0; + addr.Lun = 0; + + to.WaitForPhysicalLink = lock; + to.Flags = unhide ? UNIATA_ADD_FLAGS_UNHIDE : 0; + + printf("Scaning bus for new devices.\n"); + if(lock) { + printf("You have %d seconds to connect device.\n", lock); + } + status = ata_send_ioctl(h, &addr, "-UNIATA-", + IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES, + &to, sizeof(to), + NULL, 0, + &returned); + } else { + status = DeviceIoControl(h, + IOCTL_SCSI_RESCAN_BUS, + NULL, 0, + NULL, 0, + &returned, + FALSE); + } + ata_close_dev(h); + return TRUE; +} // end ata_scan() + +CHAR* +_fgets( + CHAR *string, + int count, + HANDLE stream + ) +{ + CHAR *pointer = string; + ULONG read_bytes; + + CHAR *retval = string; + int ch = 0; + + if (count <= 0) + return(NULL); + + while (--count) + { + if(!ReadFile(stream, &ch, 1, &read_bytes, NULL) || + !read_bytes) + { + if (pointer == string) { + retval=NULL; + goto done; + } + break; + } + + if ((*pointer++ = (CHAR)ch) == '\n') { + break; + } + } + + *pointer = '\0'; + +/* Common return */ +done: + return(retval); +} // end _fgets() + +BOOLEAN +ata_bblk( + int bus_id, + int dev_id, + int list_bb + ) +{ + char dev_name[64]; + char tmp[64]; + char DevSerial[128]; + HANDLE h = NULL; + HANDLE hf = NULL; + ULONG status; + ULONG returned; + SCSI_ADDRESS addr; + ULONG len; + ULONG Length; + BOOLEAN retval = FALSE; + HKEY hKey2 = NULL; + char* bblist = NULL; + LONGLONG tmp_bb_lba; + LONGLONG tmp_bb_len; + char BB_Msg[256]; + int radix=gRadix; + int i, j; + ULONG b; + + if(dev_id == -1) { + printf("\nERROR: Target device/bus ID must be specified\n\n"); + print_help(); + return FALSE; + } + if((dev_id >> 16) & 0xff == 0xff) { + printf("\nERROR: Target device bus number (channel) must be specified with b:<bus id>\n\n"); + print_help(); + return FALSE; + } + if((dev_id >> 8) & 0xff == 0xff) { + printf("\nERROR: Target device ID must be specified with d:<device id>\n\n"); + print_help(); + return FALSE; + } + sprintf(dev_name, "\\.\Scsi%d:", bus_id); + h = ata_open_dev(dev_name); + if(!h) { + if(bus_id == -1) { + printf("Controller number must be specified\n"); + } else { + printf("Can't open Controller %d\n", bus_id); + } + return FALSE; + } + + if(list_bb == 0) { + hf = ata_open_file(g_bb_list, FALSE); + if(!hf) { + printf("Can't open bad block list file:\n %s\n", g_bb_list); + ata_close_dev(h); + return FALSE; + } + + len = GetFileSize(hf, NULL); + if(!len || len == -1) + goto exit; + bblist = (char*)GlobalAlloc(GMEM_FIXED, len*8); + } + + if(!ata_check_unit(h, dev_id | (bus_id << 24))) { + goto exit; + } + + hKey2 = ata_get_bblist_regh(&g_ident, DevSerial, list_bb==1); + if(!hKey2) { + printf("Can't open registry key:\n HKLM\SYSTEM\CurrentControlSet\Services\UniATA\Parameters\BadBlocks\n"); + goto exit; + } + + if(list_bb == -1) { + if(RegDeleteValue(hKey2, DevSerial) != ERROR_SUCCESS) { + printf("Can't delete registry value:\n %s\n", DevSerial); + goto exit; + } + + addr.PortNumber = bus_id; + addr.PathId = (UCHAR)(dev_id >> 16); + addr.TargetId = (UCHAR)(dev_id >> 8); + addr.Lun = (UCHAR)(dev_id); + + status = ata_send_ioctl(h, &addr, "-UNIATA-", + IOCTL_SCSI_MINIPORT_UNIATA_RESETBB, + NULL, 0, + NULL, 0, + &returned); + if(!status) { + printf("Bad block list shall be cleared after reboot.\n"); + } else { + printf("Bad block list cleared\n"); + } + } else + if(list_bb == 0) { + LONGLONG* pData = ((LONGLONG*)bblist); + char a; + int k, k0; + Length=0; + i=0; + j=0; + k=0; + while(_fgets(BB_Msg, sizeof(BB_Msg), hf)) { + j++; + BB_Msg[sizeof(BB_Msg)-1] = 0; + k=0; + while(a = BB_Msg[k]) { + if(a == ' ' || a == '\t' || a == '\r') { + k++; + continue; + } + break; + } + if(!a || a == ';' || a == '#') { + continue; + } + if(!strncmp(BB_Msg+k, "hex:", 4)) { + radix=16; + continue; + } + if(!strncmp(BB_Msg+k, "dec:", 4)) { + radix=10; + continue; + } + k0 = k; + while(a = BB_Msg[k]) { + if(a == ' ' || a == '\t' || a == '\r') { + BB_Msg[k] = '\t'; + } + k++; + if(a == ';' || a == '#') { + break; + } + if(a >= '0' && a <= '9') { + continue; + } + if(radix == 16 && ((a >= 'A' && a <= 'F') || (a >= 'a' && a <= 'f'))) { + continue; + } + printf("Bad input BB list file:\n %s\n", g_bb_list); + printf("Illegal character '%1.1s' in line %d:\n%s\n", BB_Msg+k-1, j, BB_Msg); + k0=-1; + break; + } + if(k0 == -1) { + continue; + } + k = k0; + if(radix == 10) { + b = sscanf(BB_Msg+k, "%I64d\t%I64d", &tmp_bb_lba, &tmp_bb_len); + } else { + b = sscanf(BB_Msg+k, "%I64x\t%I64x", &tmp_bb_lba, &tmp_bb_len); + } + if(b == 1) { + tmp_bb_len = 1; + } else + if(b != 2) { + printf("Bad input BB list file:\n %s\n", g_bb_list); + printf("Can't parse line %d:\n%s\n", j, BB_Msg); + continue; + } + if(!tmp_bb_len) { + printf("Bad input BB list file:\n %s\n", g_bb_list); + printf("BlockCount evaluated to 0 in line %d:\n%s\n", j, BB_Msg); + continue; + } + if(tmp_bb_lba < 0) { + printf("Bad input BB list file:\n %s\n", g_bb_list); + printf("Start LBA evaluated to negative in line %d:\n%s\n", j, BB_Msg); + continue; + } + if(tmp_bb_len < 0) { + printf("Bad input BB list file:\n %s\n", g_bb_list); + printf("BlockCount evaluated to negative in line %d:\n%s\n", j, BB_Msg); + continue; + } + + if(i && + (pData[(i-1)*2+1] == tmp_bb_lba)) { + pData[(i-1)*2+1]+=tmp_bb_len; + } else { + pData[i*2+0]=tmp_bb_lba; + pData[i*2+1]=tmp_bb_lba+tmp_bb_len; + i++; + Length += sizeof(LONGLONG)*2; + } + } + + if(RegSetValueEx(hKey2, DevSerial, NULL, REG_BINARY, (const UCHAR*)bblist, Length) != ERROR_SUCCESS) { + printf("Can't set registry value:\n %s\n", DevSerial); + goto exit; + } +/* + addr.PortNumber = bus_id; + addr.PathId = (UCHAR)(dev_id >> 16); + addr.TargetId = (UCHAR)(dev_id >> 8); + addr.Lun = (UCHAR)(dev_id); + + status = ata_send_ioctl(h, &addr, "-UNIATA-", + IOCTL_SCSI_MINIPORT_UNIATA_SETBB, + NULL, 0, + NULL, 0, + &returned); +*/ + printf("Bad block list shall be applied after reboot\n"); + } else { + len = 0; + returned = RegQueryValueEx(hKey2, DevSerial, NULL, NULL, NULL, &len); + if(returned == 2) { + printf("No bad block list assigned\n"); + goto exit; + } else + if(returned != ERROR_SUCCESS) { + printf("Can't get registry value:\n %s\n", DevSerial); + goto exit; + } + + hf = ata_open_file(g_bb_list, TRUE); + if(!hf) { + printf("Can't create bad block list file:\n %s\n", g_bb_list); + goto exit; + } + + bblist = (char*)GlobalAlloc(GMEM_FIXED, len); + if(RegQueryValueEx(hKey2, DevSerial, NULL, NULL, (UCHAR*)bblist, &len) != ERROR_SUCCESS) { + printf("Can't get registry value:\n %s\n", DevSerial); + goto exit; + } + if(g_bb_list) { + for (j = 0; j < 20; j += 2) { + MOV_DW_SWP(tmp[j], ((PUCHAR)(&g_ident.ModelNumber))[j]); + } + b = sprintf(BB_Msg, "#model: %20.20s\n", tmp); + WriteFile(hf, BB_Msg, b, &returned, NULL); + for (j = 0; j < 4; j += 2) { + MOV_DW_SWP(tmp[j], ((PUCHAR)(&g_ident.FirmwareRevision))[j]); + } + b = sprintf(BB_Msg, "#rev: %4.4s\n", tmp); + WriteFile(hf, BB_Msg, b, &returned, NULL); + for (j = 0; j < 20; j += 2) { + MOV_DW_SWP(tmp[j], ((PUCHAR)(&g_ident.SerialNumber))[j]); + } + b = sprintf(BB_Msg, "#s/n: %20.20s\n", tmp); + WriteFile(hf, BB_Msg, b, &returned, NULL); + b = sprintf(BB_Msg, "#%s\n", DevSerial); + WriteFile(hf, BB_Msg, b, &returned, NULL); + b = sprintf(BB_Msg, "#Starting LBA\tNum. of Blocks\n"); + WriteFile(hf, BB_Msg, b, &returned, NULL); + b = sprintf(BB_Msg, "hex:\n"); + WriteFile(hf, BB_Msg, b, &returned, NULL); + } else { + b = sprintf(BB_Msg, "Starting LBA\tNum. of Blocks (HEX)\n"); + WriteFile(hf, BB_Msg, b, &returned, NULL); + } + i = 0; + while(len >= sizeof(LONGLONG)*2) { + tmp_bb_lba = ((LONGLONG*)bblist)[i*2+0]; + tmp_bb_len = ((LONGLONG*)bblist)[i*2+1] - tmp_bb_lba; + b = sprintf(BB_Msg, "%I64x\t%I64x\n", tmp_bb_lba, tmp_bb_len); + WriteFile(hf, BB_Msg, b, &returned, NULL); + i++; + len -= sizeof(LONGLONG)*2; + } + } + retval = TRUE; +exit: + if(hKey2) + RegCloseKey(hKey2); + if(bblist) { + GlobalFree(bblist); + } + ata_close_dev(hf); + ata_close_dev(h); + return retval; +} // end ata_bblk() + +int +ata_num_to_x_dev( + char a + ) +{ + if(a >= '0' && a <= '9') + return a-'0'; + return -1; +} + +int +main ( + int argc, + char* argv[] + ) +{ + ULONG Flags = 0; + int i, j; + char a; + int bus_id = -1; + int dev_id = -1; + int cmd = 0; + int lock = -1; + int b_dev=-1, d_dev=-1, l_dev=0; + int mode=-1; + int list_bb=0; + int persistent_hide=0; + + printf("Console ATA control utility for Windows NT3.51/NT4/2000/XP/2003\n" + "Version 0." UNIATA_VER_STR ", Copyright (c) Alexander A. Telyatnikov, 2003-2008\n" + "Home site: http://alter.org.ua%5Cn"); + + for(i=1; i<argc; i++) { + if(!argv[i]) + continue; + if((a = argv[i][0]) != '-') { + for(j=0; a = argv[i][j]; j++) { + switch(a) { + case 'a' : + case 's' : + case 'c' : + j++; + bus_id = ata_num_to_x_dev(argv[i][j]); + break; + case 'b' : + j++; + b_dev = ata_num_to_x_dev(argv[i][j]); + break; + case 'd' : + j++; + d_dev = ata_num_to_x_dev(argv[i][j]); + break; + case 'l' : + j++; + l_dev = ata_num_to_x_dev(argv[i][j]); + break; + case ':' : + break; + default: + print_help(); + } + } + continue; + } + j=1; + while(argv[i] && (a = argv[i][j]) && (a != ' ') && (a != '\t')) { + switch(a) { + case 'l' : + if(cmd || lock>0) { + print_help(); + } + cmd = CMD_ATA_LIST; + break; + case 'x' : + g_extended = 1; + break; + case 'a' : + g_adapter_info = 1; + break; + case 'S' : + persistent_hide = 1; + case 's' : + if(cmd || lock>0) { + print_help(); + } + cmd = CMD_ATA_FIND; + d_dev = 0; + break; + case 'H' : + persistent_hide = 1; + case 'h' : + if(cmd) { + print_help(); + } + cmd = CMD_ATA_HIDE; + d_dev = 0; + break; + case 'm' : + if(cmd) { + print_help(); + } + cmd = CMD_ATA_MODE; + i++; + if(!argv[i]) { + print_help(); + } + mode = ata_str_to_mode(argv[i]); + if(mode == -1) { + i--; + } else { + j = strlen(argv[i])-1; + } + break; + case 'r' : + if(cmd) { + print_help(); + } + cmd = CMD_ATA_RESET; + break; + case 'b' : + if(cmd) { + print_help(); + } + switch(argv[i][j+1]) { + case 'l': + list_bb = 1; + break; + case 'a': + list_bb = 0; + break; + case 'r': + list_bb = -1; + break; + default: + j--; + } + j++; + cmd = CMD_ATA_BBLK; + break; + case 'f' : + if(cmd != CMD_ATA_BBLK) { + print_help(); + } + i++; + if(!argv[i]) { + print_help(); + } + g_bb_list=argv[i]; + j = strlen(argv[i])-1; + break; + case 'd' : + if(cmd && cmd != CMD_ATA_FIND && cmd != CMD_ATA_HIDE) { + print_help(); + } + i++; + if(!argv[i]) { + print_help(); + } + if(!sscanf(argv[i], "%d", &lock)) { + lock = DEFAULT_REMOVAL_LOCK_TIMEOUT; + i--; + } + j = strlen(argv[i])-1; + break; + case 'n' : + if(cmd != CMD_ATA_BBLK) { + print_help(); + } + i++; + if(!argv[i]) { + print_help(); + } + if(!strcmp(argv[i], "hex") || + !strcmp(argv[i], "16")) { + gRadix = 16; + } else + if(!strcmp(argv[i], "dec") || + !strcmp(argv[i], "10")) { + gRadix = 10; + } else { + print_help(); + } + j = strlen(argv[i])-1; + break; + case '?' : + default: + print_help(); + } + j++; + } + } + + if(g_adapter_info && !cmd) { + cmd = CMD_ATA_LIST; + b_dev = 127; + d_dev = 127; + l_dev = 127; + } else + if(d_dev == -1 && b_dev != -1) { + d_dev = 127; + l_dev = 127; + } + + if(d_dev != -1 && b_dev != -1) { + dev_id = (b_dev << 16) | (d_dev << 8) | l_dev; + } + if(cmd == CMD_ATA_LIST) { + ata_list(bus_id, dev_id); + } else + if(cmd == CMD_ATA_MODE) { + ata_mode(bus_id, dev_id, mode); + } else + if(cmd == CMD_ATA_RESET) { + ata_reset(bus_id, dev_id); + } else + if(cmd == CMD_ATA_FIND) { + ata_scan(bus_id, dev_id, lock, persistent_hide); + } else + if(cmd == CMD_ATA_HIDE) { + ata_hide(bus_id, dev_id, lock, persistent_hide); + } else + if(cmd == CMD_ATA_BBLK) { + ata_bblk(bus_id, dev_id, list_bb); + } else { + print_help(); + } + exit(0); +} +
Propchange: trunk/reactos/base/applications/atactl/atactl.cpp ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/base/applications/atactl/helper.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/atactl/he... ============================================================================== --- trunk/reactos/base/applications/atactl/helper.h (added) +++ trunk/reactos/base/applications/atactl/helper.h [iso-8859-1] Tue Jul 31 17:18:47 2012 @@ -1,0 +1,38 @@ +typedef struct _DRIVERSTATUS { + UCHAR bDriverError; + UCHAR bIDEError; + UCHAR bReserved[2]; + ULONG dwReserved[2]; +} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS; + +typedef struct _IDEREGS { + UCHAR bFeaturesReg; + UCHAR bSectorCountReg; + UCHAR bSectorNumberReg; + UCHAR bCylLowReg; + UCHAR bCylHighReg; + UCHAR bDriveHeadReg; + UCHAR bCommandReg; + UCHAR bReserved; +} IDEREGS, *PIDEREGS, *LPIDEREGS; + +#define ATAPI_ID_CMD 0xA1 +#define ID_CMD 0xEC +#define SMART_CMD 0xB0 + +#include <pshpack1.h> +typedef struct _SENDCMDOUTPARAMS { + ULONG cBufferSize; + DRIVERSTATUS DriverStatus; + UCHAR bBuffer[1]; +} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS; + +typedef struct _SENDCMDINPARAMS { + ULONG cBufferSize; + IDEREGS irDriveRegs; + UCHAR bDriveNumber; + UCHAR bReserved[3]; + ULONG dwReserved[4]; + UCHAR bBuffer[1]; +} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS; +#include <poppack.h>
Propchange: trunk/reactos/base/applications/atactl/helper.h ------------------------------------------------------------------------------ svn:eol-style = native