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/CMakeLis…
==============================================================================
--- 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/C…
==============================================================================
--- 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/a…
==============================================================================
--- 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\n")uot;);
+
+ 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/h…
==============================================================================
--- 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