Something went wrong. Try again.
Reactos
Something went wrong. Try again.
61 kB · 1944 lines
C++
at listview
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945#include <stdarg.h>#include <windef.h>#include <winbase.h>#include <winreg.h>#include <winioctl.h>#include <stdlib.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;PADAPTERINFO g_AdapterInfo = NULL;
BOOLEANata_power_mode( int bus_id, int dev_id, int power_mode );
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" " D [XXX] disable device (turn into sleep mode) and lock ATA/SATA bus \n" " 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" " pX change power state to X, where X is\n" " 0 - active, 1 - idle, 2 - standby, 3 - sleep\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 safety\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 design 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, 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#define CMD_ATA_POWER 0x07
HANDLEata_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()
HANDLEata_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()
voidata_close_dev( HANDLE h ){ CloseHandle(h);} // end ata_close_dev()
intata_send_ioctl( HANDLE h, PSCSI_ADDRESS addr, PCCH 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(outBufferLength) { if(addr) { memset(&AtaCtl->RawData, 0, outBufferLength); } else { memset(&AtaCtl->addr, 0, outBufferLength); } }
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()
intata_send_scsi( HANDLE h, PSCSI_ADDRESS addr, PCDB cdb, UCHAR cdbLength, PVOID Buffer, ULONG BufferLength, BOOLEAN DataIn, PSENSE_DATA senseData, PULONG returned ){ ULONG status; PSCSI_PASS_THROUGH_WITH_BUFFERS sptwb; //ULONG data_len = BufferLength; ULONG len;
len = BufferLength + offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf);
sptwb = (PSCSI_PASS_THROUGH_WITH_BUFFERS)GlobalAlloc(GMEM_FIXED, len); if(!sptwb) { return FALSE; } memset(sptwb, 0, offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf));
sptwb->spt.Length = sizeof(SCSI_PASS_THROUGH); sptwb->spt.PathId = addr->PathId; sptwb->spt.TargetId = addr->TargetId; sptwb->spt.Lun = addr->Lun; sptwb->spt.CdbLength = cdbLength; sptwb->spt.SenseInfoLength = 24; sptwb->spt.DataIn = Buffer ? (DataIn ? SCSI_IOCTL_DATA_IN : SCSI_IOCTL_DATA_OUT) : 0; sptwb->spt.DataTransferLength = BufferLength; sptwb->spt.TimeOutValue = 10; sptwb->spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf); sptwb->spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf); memcpy(&sptwb->spt.Cdb, cdb, cdbLength);
if(Buffer && !DataIn) { memcpy(&sptwb->ucSenseBuf, Buffer, BufferLength); }
status = DeviceIoControl(h, IOCTL_SCSI_PASS_THROUGH, sptwb, (Buffer && !DataIn) ? len : sizeof(SCSI_PASS_THROUGH), sptwb, (Buffer && DataIn) ? len : offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf), returned, FALSE);
if(Buffer && DataIn) { memcpy(Buffer, &sptwb->ucDataBuf, BufferLength); } if(senseData) { memcpy(senseData, &sptwb->ucSenseBuf, sizeof(sptwb->ucSenseBuf)); }
GlobalFree(sptwb);
if(!status) { status = GetLastError(); return FALSE; } return TRUE;} // end ata_send_scsi()
IO_SCSI_CAPABILITIES g_capabilities;UCHAR g_inquiry_buffer[2048];
voidata_mode_to_str( char* str, int mode ){ if(mode > ATA_SA600) { sprintf(str, "SATA-600+"); } else if(mode >= ATA_SA600) { sprintf(str, "SATA-600"); } 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))
intata_str_to_mode( char* str ){ int mode; size_t len;
if(!_stricmp(str, "SATA600")) return ATA_SA600; if(!_stricmp(str, "SATA300")) return ATA_SA300; if(!_stricmp(str, "SATA150")) return ATA_SA150; 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()
ULONGEncodeVendorStr( 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()
HKEYata_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;
intata_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; PINQUIRYDATA scsi_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] = { 0 };
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; }
// Note: adapterInfo->NumberOfBuses is 1 greater than g_AdapterInfo->NumberChannels // because of virtual communication port adapterInfo = (PSCSI_ADAPTER_BUS_INFO)g_inquiry_buffer; for (i = 0; i+1 < adapterInfo->NumberOfBuses; i++) { inquiryData = (PSCSI_INQUIRY_DATA) (g_inquiry_buffer + adapterInfo->BusData[i].InquiryDataOffset);
if(g_extended && g_AdapterInfo && g_AdapterInfo->ChanHeaderLengthValid && g_AdapterInfo->NumberChannels < i) { PCHANINFO ChanInfo;
ChanInfo = (PCHANINFO) (((PCHAR)g_AdapterInfo)+ sizeof(ADAPTERINFO)+ g_AdapterInfo->ChanHeaderLength*i);
io_mode = ChanInfo->MaxTransferMode; if(io_mode != -1) { ata_mode_to_str(mode_str, io_mode); } else { mode_str[0] = 0; } printf(" b%lu [%s]\n", i, mode_str ); }
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) {
scsi_ident = (PINQUIRYDATA)&(inquiryData->InquiryData); if(!memcmp(&(scsi_ident->VendorId[0]), 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, " "); }
/* for (j = 0; j < 8; j++) { printf("%02X ", inquiryData->InquiryData[j]); } */
addr.Length = sizeof(addr); 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 = IoMode.PhyMode; if(!io_mode) { 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(!g_extended) { printf(" b%lu:d%d%s %24.24s %4.4s ", i, inquiryData->TargetId, lun_str, /*(inquiryData->DeviceClaimed) ? "Y" : "N",*/ (g_extended ? (PUCHAR)"" : &scsi_ident->VendorId[0]), (g_extended ? (PUCHAR)"" : &scsi_ident->ProductRevisionLevel[0]) ); } else { printf(" b%lu:d%d%s ", i, inquiryData->TargetId, lun_str ); }
if(status) { if(io_mode == -1) { io_mode = ata_cur_mode_from_ident(ident, IDENT_MODE_ACTIVE); } } 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(g_extended) { if(status) {
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 = TRUE; //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(!max_lba) { max_lba = (ULONG)(chs[0])*(ULONG)(chs[1])*(ULONG)(chs[2]); } } 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: %u block%s\n", ident->MaximumBlockTransfer, ident->MaximumBlockTransfer == 1 ? "" : "s"); } else { printf(" Multi-block mode: N/A\n"); } } if(print_geom) { printf(" C/H/S: %u/%u/%u \n", chs[0], chs[1], chs[2]); printf(" LBA: %I64u \n", max_lba); if(max_lba < 2) { printf(" Size: %lu kb\n", (ULONG)(max_lba/2)); } else if(max_lba < 2*1024*1024) { printf(" Size: %lu Mb\n", (ULONG)(max_lba/2048)); } else if(max_lba < (ULONG)2*1024*1024*1024) { printf(" Size: %lu.%lu (%lu) Gb\n", (ULONG)(max_lba/2048/1024), (ULONG)(((max_lba/2048)%1024)/10), (ULONG)(max_lba*512/1000/1000/1000) ); } else { printf(" Size: %lu.%lu (%lu) 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); } } else { switch(scsi_ident->DeviceType) { case DIRECT_ACCESS_DEVICE: if(scsi_ident->RemovableMedia) { printf(" Floppy "); } else { printf(" Hard Drive "); } break; case SEQUENTIAL_ACCESS_DEVICE: printf(" Tape Drive "); break; case PRINTER_DEVICE: printf(" Printer "); break; case PROCESSOR_DEVICE: printf(" Processor "); break; case WRITE_ONCE_READ_MULTIPLE_DEVICE: printf(" WORM Drive "); break; case READ_ONLY_DIRECT_ACCESS_DEVICE: printf(" CDROM Drive "); break; case SCANNER_DEVICE: printf(" Scanner "); break; case OPTICAL_DEVICE: printf(" Optical Drive "); break; case MEDIUM_CHANGER: printf(" Changer "); break; case COMMUNICATION_DEVICE: printf(" Comm. device "); break; } printf("\n"); } } 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()
BOOLEANata_adapter_info( int bus_id, int print_info ){ char dev_name[64]; HANDLE h; PADAPTERINFO AdapterInfo; ULONG status; ULONG returned; SCSI_ADDRESS addr; PCI_SLOT_NUMBER slotData; char mode_str[12]; ULONG len;
sprintf(dev_name, "\\\\.\\Scsi%d:", bus_id); h = ata_open_dev(dev_name); if(!h) return FALSE; addr.Length = sizeof(addr); addr.PortNumber = bus_id;
len = sizeof(ADAPTERINFO)+sizeof(CHANINFO)*AHCI_MAX_PORT; if(!g_AdapterInfo) { AdapterInfo = (PADAPTERINFO)GlobalAlloc(GMEM_FIXED, len); if(!AdapterInfo) { ata_close_dev(h); return FALSE; } } else { AdapterInfo = g_AdapterInfo; } memset(AdapterInfo, 0, len);
status = ata_send_ioctl(h, &addr, "-UNIATA-", IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO, AdapterInfo, len, AdapterInfo, len, &returned); if(status) { ata_mode_to_str(mode_str, AdapterInfo->MaxTransferMode); } printf("Scsi%d: %s %s\n", bus_id, status ? "[UniATA]" : "", status ? mode_str : ""); 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: %lu/%lu/%lu%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", (USHORT)(AdapterInfo->DevID >> 16), (USHORT)(AdapterInfo->DevID & 0xffff), (UCHAR)(AdapterInfo->RevID)); if(AdapterInfo->DeviceName[0]) { printf(" Name: %s\n", AdapterInfo->DeviceName); } } else if(AdapterInfo->AdapterInterfaceType == Isa) { printf(" ISA Bus\n"); } printf(" IRQ: %ld\n", AdapterInfo->BusInterruptLevel); } } ata_close_dev(h); //GlobalFree(AdapterInfo); g_AdapterInfo = AdapterInfo; return status ? TRUE : FALSE;} // end ata_adapter_info()
intata_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()
BOOLEANata_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()
BOOLEANata_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.Length = sizeof(addr); 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()
BOOLEANata_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.Length = sizeof(addr); 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()
BOOLEANata_hide( int bus_id, int dev_id, int lock, int persistent_hide, int power_mode ){ char dev_name[64]; HANDLE h; ULONG status; ULONG returned; SCSI_ADDRESS addr; ADDREMOVEDEV to;
if(dev_id == -1) { return FALSE; }
if(power_mode) { ata_power_mode(bus_id, dev_id, power_mode); }
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.Length = sizeof(addr); 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); if(!status) { printf("Delete failed\n"); } else { printf("Device is detached\n"); } ata_close_dev(h); return status ? TRUE : FALSE;} // end ata_hide()
BOOLEANata_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.Length = sizeof(addr); 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("Scanning 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 status ? TRUE : FALSE;} // 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()
BOOLEANata_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 == INVALID_FILE_SIZE) 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, "%I64u\t%I64u", &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, "%I64u\t%I64u\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()
BOOLEANata_power_mode( int bus_id, int dev_id, int power_mode ){ char dev_name[64]; HANDLE h; ULONG status; ULONG returned; SCSI_ADDRESS addr; CDB cdb; SENSE_DATA senseData;
if(dev_id == -1) { return FALSE; } if(!power_mode) { return TRUE; }
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);
memset(&cdb, 0, sizeof(cdb)); cdb.START_STOP.OperationCode = SCSIOP_START_STOP_UNIT; cdb.START_STOP.Immediate = 1; cdb.START_STOP.PowerConditions = power_mode; cdb.START_STOP.Start = (power_mode != StartStop_Power_Sleep);
printf("Changing power state to ...\n");
status = ata_send_scsi(h, &addr, &cdb, 6, NULL, 0, FALSE, &senseData, &returned); ata_close_dev(h); return status ? TRUE : FALSE;} // end ata_power_mode()
intata_num_to_x_dev( char a ){ if(a >= '0' && a <= '9') return a-'0'; return -1;}
intmain ( int argc, char* argv[] ){ //ULONG Flags = 0; intptr_t i; uintptr_t 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; int power_mode=StartStop_Power_NoChg;
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-2012\n" "Home site: http://alter.org.ua\n");
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 'p' : if(cmd && (cmd != CMD_ATA_FIND) && (cmd != CMD_ATA_HIDE)) { print_help(); } switch(argv[i][j+1]) { case '0': case 'a': // do nothing break; case '1': case 'i': power_mode = StartStop_Power_Idle; break; case '2': case 's': power_mode = StartStop_Power_Standby; break; case '3': case 'p': power_mode = StartStop_Power_Sleep; break; default: j--; } j++; if(power_mode && !cmd) { cmd = CMD_ATA_POWER; } break; case 'D' : power_mode = StartStop_Power_Sleep; if(cmd && (cmd != CMD_ATA_HIDE)) { print_help(); } case 'd' : if(cmd && (cmd != CMD_ATA_FIND) && (cmd != CMD_ATA_HIDE) && (cmd != CMD_ATA_POWER)) { print_help(); } if(!cmd) { cmd = CMD_ATA_HIDE; } 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, power_mode); } else if(cmd == CMD_ATA_BBLK) { ata_bblk(bus_id, dev_id, list_bb); } else if(cmd == CMD_ATA_POWER) { ata_power_mode(bus_id, dev_id, power_mode); } else { print_help(); } exit(0);}