From deaba45849420e60bd0aa52f445ff943ad370de6 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Mon, 10 Sep 2012 19:38:32 +0000 Subject: [PATCH] [UNIATA]: Sync to 0.43f5. [ATACTL]: Sync to 0.43f5. svn path=/trunk/; revision=57265 --- reactos/base/applications/atactl/atactl.cpp | 452 ++++++--- reactos/drivers/storage/ide/uniata/atapi.h | 56 +- reactos/drivers/storage/ide/uniata/bm_devs.h | 39 +- reactos/drivers/storage/ide/uniata/bsmaster.h | 43 +- reactos/drivers/storage/ide/uniata/id_ata.cpp | 915 +++++++++++++----- reactos/drivers/storage/ide/uniata/id_dma.cpp | 42 +- .../drivers/storage/ide/uniata/id_init.cpp | 74 +- .../drivers/storage/ide/uniata/id_probe.cpp | 553 +++-------- .../drivers/storage/ide/uniata/id_sata.cpp | 358 ++++++- reactos/drivers/storage/ide/uniata/id_sata.h | 24 + reactos/drivers/storage/ide/uniata/inc/misc.h | 2 +- reactos/drivers/storage/ide/uniata/scsi.h | 31 +- reactos/drivers/storage/ide/uniata/todo.txt | 5 +- reactos/drivers/storage/ide/uniata/uata_ctl.h | 40 +- .../drivers/storage/ide/uniata/uniata_ver.h | 14 +- 15 files changed, 1762 insertions(+), 886 deletions(-) diff --git a/reactos/base/applications/atactl/atactl.cpp b/reactos/base/applications/atactl/atactl.cpp index 69ea2f99224..63a04168063 100644 --- a/reactos/base/applications/atactl/atactl.cpp +++ b/reactos/base/applications/atactl/atactl.cpp @@ -39,6 +39,13 @@ char* g_bb_list = NULL; int gRadix = 16; PADAPTERINFO g_AdapterInfo = NULL; +BOOLEAN +ata_power_mode( + int bus_id, + int dev_id, + int power_mode + ); + void print_help() { printf("Usage:\n" " atactl - c|s:b:d[:l]\n" @@ -61,6 +68,12 @@ void print_help() { " 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" @@ -116,6 +129,7 @@ void print_help() { #define CMD_ATA_MODE 0x04 #define CMD_ATA_RESET 0x05 #define CMD_ATA_BBLK 0x06 +#define CMD_ATA_POWER 0x07 HANDLE ata_open_dev( @@ -304,6 +318,76 @@ ata_send_ioctl( return TRUE; } // end ata_send_ioctl() +int +ata_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]; @@ -535,9 +619,10 @@ ata_check_unit( 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; + //ULONG bus_id = (dev_id >> 24) & 0xff; BOOLEAN found = FALSE; SENDCMDINPARAMS pin; int io_mode = -1; @@ -546,7 +631,7 @@ ata_check_unit( char lun_str[10]; HKEY hKey2; ULONGLONG max_lba = -1; - USHORT chs[3]; + USHORT chs[3] = { 0 }; if(dev_id != -1) { dev_id &= 0x00ffffff; @@ -594,7 +679,7 @@ ata_check_unit( } else { mode_str[0] = 0; } - printf(" b%u [%s]\n", + printf(" b%lu [%s]\n", i, mode_str ); @@ -617,7 +702,8 @@ ata_check_unit( if(l_dev_id == dev_id || dev_id == -1) { - if(!memcmp(&(inquiryData->InquiryData[8]), UNIATA_COMM_PORT_VENDOR_STR, 24)) { + scsi_ident = (PINQUIRYDATA)&(inquiryData->InquiryData); + if(!memcmp(&(scsi_ident->VendorId[0]), UNIATA_COMM_PORT_VENDOR_STR, 24)) { // skip communication port goto next_dev; } @@ -685,29 +771,27 @@ ata_check_unit( } - if(status) { - if(!g_extended) { - printf(" b%u: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%u:d%d%s ", - i, - inquiryData->TargetId, - lun_str - ); - } - if(io_mode == -1) { - io_mode = ata_cur_mode_from_ident(ident); - } + 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 { - goto next_dev; + 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); @@ -725,100 +809,139 @@ ata_check_unit( } printf("\n"); - if(status && g_extended) { + if(g_extended) { + if(status) { - BOOLEAN BlockMode_valid = TRUE; - BOOLEAN print_geom = FALSE; + BOOLEAN BlockMode_valid = TRUE; + BOOLEAN print_geom = FALSE; - switch(ident->DeviceType) { - case ATAPI_TYPE_DIRECT: - if(ident->Removable) { - printf(" Floppy "); - } else { + 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]); + } } - 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; + if(io_mode != -1) { + printf(" %.12s\n", mode_str); } - //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]); + for (j = 0; j < 40; j += 2) { + MOV_DW_SWP(SerNum[j], ((PUCHAR)ident->ModelNumber)[j]); } - } - 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); + 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(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: %u kb\n", max_lba/2); - } else - if(max_lba < 2*1024*1024) { - printf(" Size: %u Mb\n", max_lba/2048); - } else - if(max_lba < (ULONG)2*1024*1024*1024) { - printf(" Size: %u.%u (%u) Gb\n", (ULONG)(max_lba/2048/1024), - (ULONG)(((max_lba/2048)%1024)/10), - (ULONG)(max_lba*512/1000/1000/1000) - ); - } else { - printf(" Size: %u.%u (%u) Tb\n", (ULONG)(max_lba/2048/1024/1024), - (ULONG)((max_lba/2048/1024)%1024)/10, - (ULONG)(max_lba*512/1000/1000/1000) - ); + 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"); + 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); } - 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)); } @@ -887,7 +1010,7 @@ ata_adapter_info( } else { if(AdapterInfo->AdapterInterfaceType == PCIBus) { slotData.u.AsULONG = AdapterInfo->slotNumber; - printf(" PCI Bus/Dev/Func: %u/%u/%u%s\n", + 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", @@ -901,7 +1024,7 @@ ata_adapter_info( if(AdapterInfo->AdapterInterfaceType == Isa) { printf(" ISA Bus\n"); } - printf(" IRQ: %d\n", AdapterInfo->BusInterruptLevel); + printf(" IRQ: %ld\n", AdapterInfo->BusInterruptLevel); } } ata_close_dev(h); @@ -1060,7 +1183,8 @@ ata_hide( int bus_id, int dev_id, int lock, - int persistent_hide + int persistent_hide, + int power_mode ) { char dev_name[64]; @@ -1073,6 +1197,11 @@ ata_hide( 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; } @@ -1261,7 +1390,7 @@ ata_bblk( } len = GetFileSize(hf, NULL); - if(!len || len == -1) + if(!len || len == INVALID_FILE_SIZE) goto exit; bblist = (char*)GlobalAlloc(GMEM_FIXED, len*8); } @@ -1310,7 +1439,7 @@ ata_bblk( j++; BB_Msg[sizeof(BB_Msg)-1] = 0; k=0; - while(a = BB_Msg[k]) { + while((a = BB_Msg[k])) { if(a == ' ' || a == '\t' || a == '\r') { k++; continue; @@ -1329,7 +1458,7 @@ ata_bblk( continue; } k0 = k; - while(a = BB_Msg[k]) { + while((a = BB_Msg[k])) { if(a == ' ' || a == '\t' || a == '\r') { BB_Msg[k] = '\t'; } @@ -1480,6 +1609,52 @@ exit: return retval; } // end ata_bblk() +BOOLEAN +ata_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 TRUE; +} // end ata_power_mode() + int ata_num_to_x_dev( char a @@ -1496,7 +1671,7 @@ main ( char* argv[] ) { - ULONG Flags = 0; + //ULONG Flags = 0; int i, j; char a; int bus_id = -1; @@ -1507,6 +1682,7 @@ main ( 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" @@ -1516,7 +1692,7 @@ main ( if(!argv[i]) continue; if((a = argv[i][0]) != '-') { - for(j=0; a = argv[i][j]; j++) { + for(j=0; (a = argv[i][j]); j++) { switch(a) { case 'a' : case 's' : @@ -1630,10 +1806,47 @@ main ( g_bb_list=argv[i]; j = strlen(argv[i])-1; break; - case 'd' : + 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(); @@ -1699,10 +1912,13 @@ main ( ata_scan(bus_id, dev_id, lock, persistent_hide); } else if(cmd == CMD_ATA_HIDE) { - ata_hide(bus_id, dev_id, lock, persistent_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(); } diff --git a/reactos/drivers/storage/ide/uniata/atapi.h b/reactos/drivers/storage/ide/uniata/atapi.h index 7eec3d58172..f191a784535 100644 --- a/reactos/drivers/storage/ide/uniata/atapi.h +++ b/reactos/drivers/storage/ide/uniata/atapi.h @@ -387,7 +387,9 @@ typedef struct _MODE_PARAMETER_HEADER_10 { #define IDE_COMMAND_DOOR_LOCK 0xDE #define IDE_COMMAND_DOOR_UNLOCK 0xDF #define IDE_COMMAND_STANDBY_IMMED 0xE0 // flush and spin down +#define IDE_COMMAND_IDLE_IMMED 0xE1 #define IDE_COMMAND_STANDBY 0xE2 // flush and spin down and enable autopowerdown timer +#define IDE_COMMAND_IDLE 0xE3 #define IDE_COMMAND_READ_PM 0xE4 // SATA PM #define IDE_COMMAND_SLEEP 0xE6 // flush, spin down and deactivate interface #define IDE_COMMAND_FLUSH_CACHE 0xE7 @@ -559,6 +561,25 @@ typedef union _ATAPI_REGISTERS_2 { #define ATA_C_F_ENAB_MEDIASTAT 0x95 /* enable media status */ #define ATA_C_F_DIS_MEDIASTAT 0x31 /* disable media status */ +#define ATA_C_F_ENAB_APM 0x05 /* enable advanced power management */ +#define ATA_C_F_DIS_APM 0x85 /* disable advanced power management */ +#define ATA_C_F_APM_CNT_MAX_PERF 0xfe /* maximum performance */ +#define ATA_C_F_APM_CNT_MIN_NO_STANDBY 0x80 /* min. power w/o standby */ +#define ATA_C_F_APM_CNT_MIN_STANDBY 0x01 /* min. power with standby */ + +#define ATA_C_F_ENAB_ACOUSTIC 0x42 /* enable acoustic management */ +#define ATA_C_F_DIS_ACOUSTIC 0xc2 /* disable acoustic management */ +#define ATA_C_F_AAM_CNT_MAX_PERF 0xfe /* maximum performance */ +#define ATA_C_F_AAM_CNT_MAX_POWER_SAVE 0x80 /* min. power */ + +// New SMART Feature definitions +#ifndef READ_LOG_SECTOR +#define READ_LOG_SECTOR 0xD5 +#define WRITE_LOG_SECTOR 0xD6 +#define WRITE_THRESHOLDS 0xD7 +#define AUTO_OFFLINE 0xDB +#endif // READ_LOG_SECTOR + // // ATAPI interrupt reasons // @@ -920,6 +941,7 @@ typedef struct _IDENTIFY_DATA { union { USHORT Integrity; // 255 struct { +#define ATA_ChecksumValid 0xA5 USHORT ChecksumValid:8; USHORT Checksum:8; }; @@ -1538,12 +1560,17 @@ ata_is_sata( return (ident->SataCapabilities && ident->SataCapabilities != 0xffff); } // end ata_is_sata() +#define IDENT_MODE_MAX FALSE +#define IDENT_MODE_ACTIVE TRUE + __inline LONG ata_cur_mode_from_ident( - PIDENTIFY_DATA ident + PIDENTIFY_DATA ident, + BOOLEAN Active ) { + USHORT mode; if(ata_is_sata(ident)) { if(ident->SataCapabilities & ATA_SATA_GEN3) { return ATA_SA600; @@ -1558,22 +1585,24 @@ ata_cur_mode_from_ident( } if (ident->UdmaModesValid) { - if (ident->UltraDMAActive & 0x40) + mode = Active ? ident->UltraDMAActive : ident->UltraDMASupport; + if (mode & 0x40) return ATA_UDMA0+6; - if (ident->UltraDMAActive & 0x20) + if (mode & 0x20) return ATA_UDMA0+5; - if (ident->UltraDMAActive & 0x10) + if (mode & 0x10) return ATA_UDMA0+4; - if (ident->UltraDMAActive & 0x08) + if (mode & 0x08) return ATA_UDMA0+3; - if (ident->UltraDMAActive & 0x04) + if (mode & 0x04) return ATA_UDMA0+2; - if (ident->UltraDMAActive & 0x02) + if (mode & 0x02) return ATA_UDMA0+1; - if (ident->UltraDMAActive & 0x01) + if (mode & 0x01) return ATA_UDMA0+0; } + mode = Active ? ident->MultiWordDMAActive : ident->MultiWordDMASupport; if (ident->MultiWordDMAActive & 0x04) return ATA_WDMA0+2; if (ident->MultiWordDMAActive & 0x02) @@ -1581,6 +1610,7 @@ ata_cur_mode_from_ident( if (ident->MultiWordDMAActive & 0x01) return ATA_WDMA0+0; + mode = Active ? ident->SingleWordDMAActive : ident->SingleWordDMASupport; if (ident->SingleWordDMAActive & 0x04) return ATA_SDMA0+2; if (ident->SingleWordDMAActive & 0x02) @@ -1589,13 +1619,15 @@ ata_cur_mode_from_ident( return ATA_SDMA0+0; if (ident->PioTimingsValid) { - if (ident->AdvancedPIOModes & AdvancedPIOModes_5) + mode = ident->AdvancedPIOModes; + if (mode & AdvancedPIOModes_5) return ATA_PIO0+5; - if (ident->AdvancedPIOModes & AdvancedPIOModes_4) + if (mode & AdvancedPIOModes_4) return ATA_PIO0+4; - if (ident->AdvancedPIOModes & AdvancedPIOModes_3) + if (mode & AdvancedPIOModes_3) return ATA_PIO0+3; - } + } + mode = ident->PioCycleTimingMode; if (ident->PioCycleTimingMode == 2) return ATA_PIO0+2; if (ident->PioCycleTimingMode == 1) diff --git a/reactos/drivers/storage/ide/uniata/bm_devs.h b/reactos/drivers/storage/ide/uniata/bm_devs.h index 039f111a4ee..7abe0ad524f 100644 --- a/reactos/drivers/storage/ide/uniata/bm_devs.h +++ b/reactos/drivers/storage/ide/uniata/bm_devs.h @@ -50,11 +50,12 @@ Revision History: #ifndef __IDE_BUSMASTER_DEVICES_H__ #define __IDE_BUSMASTER_DEVICES_H__ -#ifdef USER_MODE +/*#ifdef USER_MODE #define PVEN_STR PCSTR #else // USER_MODE #define PVEN_STR PCHAR -#endif // USER_MODE +#endif // USER_MODE*/ +#define PVEN_STR PCSTR typedef struct _BUSMASTER_CONTROLLER_INFORMATION { PVEN_STR VendorId; @@ -76,15 +77,18 @@ typedef struct _BUSMASTER_CONTROLLER_INFORMATION { CHAR MasterDev; BOOLEAN Known; #ifndef USER_MODE - CHAR ChanInitOk; // 0x01 - primary, 0x02 - secondary + UCHAR ChanInitOk; // 0x01 - primary, 0x02 - secondary, 0x80 - PciIde claimed BOOLEAN Isr2Enable; - PDEVICE_OBJECT Isr2DevObj; + union { + PDEVICE_OBJECT Isr2DevObj; + PDEVICE_OBJECT PciIdeDevObj; + }; KIRQL Isr2Irql; KAFFINITY Isr2Affinity; ULONG Isr2Vector; PKINTERRUPT Isr2InterruptObject; CHAR AltInitMasterDev; // 0xff - uninitialized, 0x00 - normal, 0x01 - change ISA to PCI - CHAR NeedAltInit; // 0x01 - try change ISA to PCI + CHAR NeedAltInit; // 0x01 - try change ISA to PCI #endif }BUSMASTER_CONTROLLER_INFORMATION, *PBUSMASTER_CONTROLLER_INFORMATION; @@ -634,7 +638,8 @@ typedef struct _BUSMASTER_CONTROLLER_INFORMATION { #define ICH5 0x0200 #define I6CH 0x0400 #define I6CH2 0x0800 -#define I1CH 0x1000 +//#define I1CH 0x1000 // obsolete +#define ICH7 0x1000 #define NV4OFF 0x0100 #define NVQ 0x0200 @@ -717,7 +722,7 @@ BUSMASTER_CONTROLLER_INFORMATION const BusMasterAdapters[] = { PCI_DEV_HW_SPEC_BM( 1230, 8086, 0x00, ATA_WDMA2, "Intel PIIX" , 0 ), PCI_DEV_HW_SPEC_BM( 7010, 8086, 0x00, ATA_WDMA2, "Intel PIIX3" , 0 ), - PCI_DEV_HW_SPEC_BM( 7111, 8086, 0x00, ATA_UDMA3, "Intel PIIX4" , 0 ), + PCI_DEV_HW_SPEC_BM( 7111, 8086, 0x00, ATA_UDMA2, "Intel PIIX3" , 0 ), PCI_DEV_HW_SPEC_BM( 7199, 8086, 0x00, ATA_UDMA2, "Intel PIIX4" , 0 ), PCI_DEV_HW_SPEC_BM( 84ca, 8086, 0x00, ATA_UDMA2, "Intel PIIX4" , 0 ), PCI_DEV_HW_SPEC_BM( 7601, 8086, 0x00, ATA_UDMA2, "Intel ICH0" , 0 ), @@ -747,15 +752,15 @@ BUSMASTER_CONTROLLER_INFORMATION const BusMasterAdapters[] = { PCI_DEV_HW_SPEC_BM( 2652, 8086, 0x00, ATA_SA150, "Intel ICH6" , UNIATA_SATA | UNIATA_AHCI ), PCI_DEV_HW_SPEC_BM( 2653, 8086, 0x00, ATA_SA150, "Intel ICH6M" , UNIATA_SATA | UNIATA_AHCI ), - PCI_DEV_HW_SPEC_BM( 27df, 8086, 0x00, ATA_UDMA5, "Intel ICH7" , I1CH ), - PCI_DEV_HW_SPEC_BM( 27c0, 8086, 0x00, ATA_SA300, "Intel ICH7 S1" , UNIATA_SATA ), + PCI_DEV_HW_SPEC_BM( 27df, 8086, 0x00, ATA_UDMA5, "Intel ICH7" , 0 ), + PCI_DEV_HW_SPEC_BM( 27c0, 8086, 0x00, ATA_SA300, "Intel ICH7 S1" , ICH7 | UNIATA_SATA ), PCI_DEV_HW_SPEC_BM( 27c1, 8086, 0x00, ATA_SA300, "Intel ICH7" , UNIATA_SATA | UNIATA_AHCI ), PCI_DEV_HW_SPEC_BM( 27c3, 8086, 0x00, ATA_SA300, "Intel ICH7" , UNIATA_SATA ), - PCI_DEV_HW_SPEC_BM( 27c4, 8086, 0x00, ATA_SA150, "Intel ICH7M R1" , UNIATA_SATA ), + PCI_DEV_HW_SPEC_BM( 27c4, 8086, 0x00, ATA_SA150, "Intel ICH7M R1" , ICH7 | UNIATA_SATA ), PCI_DEV_HW_SPEC_BM( 27c5, 8086, 0x00, ATA_SA150, "Intel ICH7M" , UNIATA_SATA | UNIATA_AHCI ), PCI_DEV_HW_SPEC_BM( 27c6, 8086, 0x00, ATA_SA150, "Intel ICH7M" , UNIATA_SATA ), - PCI_DEV_HW_SPEC_BM( 269e, 8086, 0x00, ATA_UDMA5, "Intel 63XXESB2" , I1CH ), + PCI_DEV_HW_SPEC_BM( 269e, 8086, 0x00, ATA_UDMA5, "Intel 63XXESB2" , 0 ), PCI_DEV_HW_SPEC_BM( 2680, 8086, 0x00, ATA_SA300, "Intel 63XXESB2" , UNIATA_SATA ), PCI_DEV_HW_SPEC_BM( 2681, 8086, 0x00, ATA_SA300, "Intel 63XXESB2" , UNIATA_SATA | UNIATA_AHCI ), PCI_DEV_HW_SPEC_BM( 2682, 8086, 0x00, ATA_SA300, "Intel 63XXESB2" , UNIATA_SATA | UNIATA_AHCI ), @@ -769,7 +774,7 @@ BUSMASTER_CONTROLLER_INFORMATION const BusMasterAdapters[] = { PCI_DEV_HW_SPEC_BM( 2828, 8086, 0x00, ATA_SA300, "Intel ICH8M" , I6CH | UNIATA_SATA ), PCI_DEV_HW_SPEC_BM( 2829, 8086, 0x00, ATA_SA300, "Intel ICH8M" , UNIATA_SATA | UNIATA_AHCI ), PCI_DEV_HW_SPEC_BM( 282a, 8086, 0x00, ATA_SA300, "Intel ICH8M" , UNIATA_SATA | UNIATA_AHCI ), - PCI_DEV_HW_SPEC_BM( 2850, 8086, 0x00, ATA_UDMA5, "Intel ICH8M" , I1CH ), + PCI_DEV_HW_SPEC_BM( 2850, 8086, 0x00, ATA_UDMA5, "Intel ICH8M" , 0 ), PCI_DEV_HW_SPEC_BM( 2920, 8086, 0x00, ATA_SA300, "Intel ICH9" , I6CH | UNIATA_SATA ), PCI_DEV_HW_SPEC_BM( 2926, 8086, 0x00, ATA_SA300, "Intel ICH9" , I6CH2 | UNIATA_SATA ), @@ -779,10 +784,10 @@ BUSMASTER_CONTROLLER_INFORMATION const BusMasterAdapters[] = { PCI_DEV_HW_SPEC_BM( 2923, 8086, 0x00, ATA_SA300, "Intel ICH9" , UNIATA_SATA | UNIATA_AHCI ), PCI_DEV_HW_SPEC_BM( 2925, 8086, 0x00, ATA_SA300, "Intel ICH9" , UNIATA_SATA | UNIATA_AHCI ), - PCI_DEV_HW_SPEC_BM( 2928, 8086, 0x00, ATA_SA300, "Intel ICH9M" , I6CH2 | UNIATA_SATA ), - PCI_DEV_HW_SPEC_BM( 2929, 8086, 0x00, ATA_SA300, "Intel ICH9M" , UNIATA_SATA | UNIATA_AHCI ), - PCI_DEV_HW_SPEC_BM( 292a, 8086, 0x00, ATA_SA300, "Intel ICH9M" , UNIATA_SATA | UNIATA_AHCI ), - PCI_DEV_HW_SPEC_BM( 292d, 8086, 0x00, ATA_SA300, "Intel ICH9M" , I6CH2 | UNIATA_SATA ), + PCI_DEV_HW_SPEC_BM( 2928, 8086, 0x00, ATA_SA300, "Intel ICH9M" , I6CH2 | UNIATA_SATA ), + PCI_DEV_HW_SPEC_BM( 2929, 8086, 0x00, ATA_SA300, "Intel ICH9M" , UNIATA_SATA | UNIATA_AHCI ), + PCI_DEV_HW_SPEC_BM( 292a, 8086, 0x00, ATA_SA300, "Intel ICH9M" , UNIATA_SATA | UNIATA_AHCI ), + PCI_DEV_HW_SPEC_BM( 292d, 8086, 0x00, ATA_SA300, "Intel ICH9M" , I6CH2 | UNIATA_SATA ), PCI_DEV_HW_SPEC_BM( 3a20, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH | UNIATA_SATA ), PCI_DEV_HW_SPEC_BM( 3a26, 8086, 0x00, ATA_SA300, "Intel ICH10" , I6CH2 | UNIATA_SATA ), @@ -842,7 +847,7 @@ BUSMASTER_CONTROLLER_INFORMATION const BusMasterAdapters[] = { PCI_DEV_HW_SPEC_BM( 1e0f, 8086, 0x00, ATA_SA300, "Intel Panther Point" , UNIATA_SATA | UNIATA_AHCI ), // PCI_DEV_HW_SPEC_BM( 3200, 8086, 0x00, ATA_SA150, "Intel 31244" , UNIATA_SATA ), - PCI_DEV_HW_SPEC_BM( 811a, 8086, 0x00, ATA_UDMA5, "Intel SCH" , I1CH ), + PCI_DEV_HW_SPEC_BM( 811a, 8086, 0x00, ATA_UDMA5, "Intel SCH" , 0 ), PCI_DEV_HW_SPEC_BM( 2323, 8086, 0x00, ATA_SA300, "Intel DH98xxCC" , UNIATA_SATA | UNIATA_AHCI ), PCI_DEV_HW_SPEC_BM( 2360, 197b, 0x00, ATA_SA300, "JMB360" , UNIATA_SATA | UNIATA_AHCI ), diff --git a/reactos/drivers/storage/ide/uniata/bsmaster.h b/reactos/drivers/storage/ide/uniata/bsmaster.h index 864f7eab5db..ca6f963f0a0 100644 --- a/reactos/drivers/storage/ide/uniata/bsmaster.h +++ b/reactos/drivers/storage/ide/uniata/bsmaster.h @@ -562,9 +562,9 @@ typedef struct _IDE_AHCI_PORT_REGISTERS { ULONG Reg; // signature struct { UCHAR SectorCount; - UCHAR LbaLow; - UCHAR LbaMid; - UCHAR LbaHigh; + UCHAR LbaLow; // IDX_IO1_i_BlockNumber + UCHAR LbaMid; // IDX_IO1_i_CylinderLow + UCHAR LbaHigh; // IDX_IO1_i_CylinderHigh }; } SIG; // 0x100 + 0x80*c + 0x0024 union { @@ -1060,6 +1060,7 @@ typedef struct _HW_CHANNEL { #define CTRFLAGS_DSC_BSY 0x0080 #define CTRFLAGS_NO_SLAVE 0x0100 //#define CTRFLAGS_PATA 0x0200 +//#define CTRFLAGS_NOT_PRESENT 0x0200 #define CTRFLAGS_AHCI_PM 0x0400 #define CTRFLAGS_AHCI_PM2 0x0800 @@ -1086,7 +1087,7 @@ typedef struct _HW_LU_EXTENSION { BOOLEAN DWordIO; // Indicates use of 32-bit PIO UCHAR ReturningMediaStatus; UCHAR MaximumBlockXfer; - UCHAR Padding0[1]; // padding + UCHAR PowerState; UCHAR TransferMode; // current transfer mode UCHAR LimitedTransferMode; // user-defined or IDE cable limitation @@ -1117,8 +1118,10 @@ typedef struct _HW_LU_EXTENSION { BOOLEAN opt_ReadCacheEnable; BOOLEAN opt_WriteCacheEnable; UCHAR opt_ReadOnly; - // padding - BOOLEAN opt_reserved[1]; + UCHAR opt_AdvPowerMode; + UCHAR opt_AcousticMode; + UCHAR opt_StandbyTimer; + UCHAR opt_Padding[2]; // padding struct _SBadBlockListItem* bbListDescr; struct _SBadBlockRange* arrBadBlocks; @@ -1216,6 +1219,9 @@ typedef struct _HW_DEVICE_EXTENSION { BOOLEAN MasterDev; BOOLEAN Host64; BOOLEAN DWordIO; // Indicates use of 32-bit PIO +/* // Indicates, that HW Initialized is already called for this controller + // 0 bit for Primary, 1 - for Secondary. Is used to manage AltInit under w2k+ + UCHAR Initialized; */ UCHAR Reserved1[2]; LONG ReCheckIntr; @@ -1238,6 +1244,7 @@ typedef struct _HW_DEVICE_EXTENSION { IORES BaseIoAHCI_0; //PIDE_AHCI_PORT_REGISTERS BaseIoAHCIPort[AHCI_MAX_PORT]; ULONG AHCI_CAP; + ULONG AHCI_PI; PATA_REQ AhciInternalAtaReq0; PSCSI_REQUEST_BLOCK AhciInternalSrb0; @@ -1260,6 +1267,9 @@ typedef struct _ISR2_DEVICE_EXTENSION { ULONG DevIndex; } ISR2_DEVICE_EXTENSION, *PISR2_DEVICE_EXTENSION; +typedef ISR2_DEVICE_EXTENSION PCIIDE_DEVICE_EXTENSION; +typedef PISR2_DEVICE_EXTENSION PPCIIDE_DEVICE_EXTENSION; + #define HBAFLAGS_DMA_DISABLED 0x01 #define HBAFLAGS_DMA_DISABLED_LBA48 0x02 @@ -1268,6 +1278,7 @@ extern PBUSMASTER_CONTROLLER_INFORMATION BMList; extern ULONG BMListLen; extern ULONG IsaCount; extern ULONG MCACount; +extern UNICODE_STRING SavedRegPath; //extern const CHAR retry_Wdma[MAX_RETRIES+1]; //extern const CHAR retry_Udma[MAX_RETRIES+1]; @@ -1322,14 +1333,10 @@ UniataFindBusMasterController( OUT PBOOLEAN Again ); -extern ULONG NTAPI -UniataFindFakeBusMasterController( - IN PVOID HwDeviceExtension, - IN PVOID Context, - IN PVOID BusInformation, - IN PCHAR ArgumentString, - IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, - OUT PBOOLEAN Again +extern NTSTATUS +NTAPI +UniataClaimLegacyPCIIDE( + ULONG i ); extern NTSTATUS @@ -1508,6 +1515,14 @@ AtapiGetIoRange( IN ULONG length //range id ); +extern USHORT +NTAPI +UniataEnableIoPCI( + IN ULONG busNumber, + IN ULONG slotNumber, + IN OUT PPCI_COMMON_CONFIG pciData + ); + /****************** 1 *****************/ #define GetPciConfig1(offs, op) { \ ScsiPortGetBusDataByOffset(HwDeviceExtension, \ diff --git a/reactos/drivers/storage/ide/uniata/id_ata.cpp b/reactos/drivers/storage/ide/uniata/id_ata.cpp index 08933792018..852bd24395f 100644 --- a/reactos/drivers/storage/ide/uniata/id_ata.cpp +++ b/reactos/drivers/storage/ide/uniata/id_ata.cpp @@ -47,7 +47,7 @@ Revision History: 5. W2k support (binary compatibility) 6. HDD hot swap under NT4 7. XP support (binary compatibility) - 8. Serial ATA (SATA/SATA2) support + 8. Serial ATA (SATA/SATA2/SATA3) support 9. NT 3.51 support (binary compatibility) etc. (See todo.txt) @@ -121,6 +121,14 @@ AtapiHwInitialize__( IN ULONG lChannel ); +VOID +NTAPI +UniataUserDeviceReset( + PHW_DEVICE_EXTENSION deviceExtension, + PHW_LU_EXTENSION LunExt, + ULONG lChannel + ); + #define RESET_COMPLETE_CURRENT 0x00 #define RESET_COMPLETE_ALL 0x01 #define RESET_COMPLETE_NONE 0x02 @@ -482,6 +490,7 @@ AtapiSuckPort2( UCHAR statusByte; ULONG i; + // Assume, proper drive is already seleted WaitOnBusyLong(chan); for (i = 0; i < 0x10000; i++) { @@ -1270,6 +1279,42 @@ UniataDumpATARegs( } // end UniataDumpATARegs() #endif +VOID +NTAPI +UniataSnapAtaRegs( + IN PHW_CHANNEL chan, + IN ULONG DeviceNumber, + IN OUT PIDEREGS_EX regs + ) +{ + if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { + // AHCI + UniataAhciSnapAtaRegs(chan, DeviceNumber, regs); + } else { + // SATA/PATA, assume drive is selected + ULONG j; + UCHAR statusByteAlt; + + if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { + for(j=IDX_IO1_i_Error; j<=IDX_IO1_i_Status; j++) { + statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j); + ((PUCHAR)regs)[j-1] = statusByteAlt; + } + regs->bOpFlags = 0; + } else { + regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect); + for(j=IDX_IO1_i_Error; jbCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status); + } + } + return; +} // end UniataSnapAtaRegs() + /*++ Routine Description: @@ -1491,7 +1536,7 @@ IssueIdentify( break; } } - // Device didn't respond correctly. It will be given one more chances. + // Device didn't respond correctly. It will be given one more chance. KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n", statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error))); GetBaseStatus(chan, statusByte); @@ -1542,33 +1587,13 @@ IssueIdentify( if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) { KdPrint2((PRINT_PREFIX " use 16bit IO\n")); -#if 0 - USHORT w; - ULONG i; + // ATI/SII chipsets with memory-mapped IO hangs when // I call ReadBuffer(), probably due to PCI burst/prefetch enabled - // Unfortunately, I don't know yet how to workaround it except the way you see below. - KdPrint2((PRINT_PREFIX - " IO_%#x (%#x), %s:\n", - IDX_IO1_i_Data, - chan->RegTranslation[IDX_IO1_i_Data].Addr, - chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO")); - for(i=0; i<256; i++) { - /* - KdPrint2((PRINT_PREFIX - " IO_%#x (%#x):\n", - IDX_IO1_i_Data, - chan->RegTranslation[IDX_IO1_i_Data].Addr)); - */ - w = AtapiReadPort2(chan, IDX_IO1_i_Data); - KdPrint2((PRINT_PREFIX - " %x\n", w)); - AtapiStallExecution(1); - ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w; - } -#else + // Unfortunately, I don't know yet how to workaround it except + // spacifying manual delay in the way you see below. ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING); -#endif + // Work around for some IDE and one model Atapi that will present more than // 256 bytes for the Identify data. KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte)); @@ -1600,7 +1625,7 @@ IssueIdentify( KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive)); KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive)); if(deviceExtension->FullIdentifyData.UdmaModesValid) { - KdPrint2((PRINT_PREFIX "UDMA: %x\n", deviceExtension->FullIdentifyData.UltraDMAActive)); + KdPrint2((PRINT_PREFIX "UDMA: %x/%x\n", deviceExtension->FullIdentifyData.UltraDMAActive, deviceExtension->FullIdentifyData.UltraDMASupport)); } KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable)); KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n", @@ -1609,9 +1634,18 @@ IssueIdentify( LunExt->LimitedTransferMode = LunExt->OrigTransferMode = - (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData)); + (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_MAX); + LunExt->TransferMode = + (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_ACTIVE); - KdPrint2((PRINT_PREFIX "OrigTransferMode: %x\n", LunExt->OrigTransferMode)); + KdPrint2((PRINT_PREFIX "OrigTransferMode: %x, Active: %x\n", LunExt->OrigTransferMode, LunExt->TransferMode)); + KdPrint2((PRINT_PREFIX "Accoustic %d, cur %d\n", + deviceExtension->FullIdentifyData.VendorAcoustic, + deviceExtension->FullIdentifyData.CurrentAcoustic + )); + KdPrint2((PRINT_PREFIX "AdvPowerMode %d, cur %d\n", + deviceExtension->FullIdentifyData.CfAdvPowerMode + )); // Check out a few capabilities / limitations of the device. if (deviceExtension->FullIdentifyData.RemovableStatus & 1) { @@ -1841,7 +1875,6 @@ IssueIdentify( } } } - KdPrint2((PRINT_PREFIX "final LunExt->opt_GeomType=%x\n", LunExt->opt_GeomType)); if(LunExt->opt_GeomType == GEOM_STD) { deviceExtension->FullIdentifyData.CurrentSectorsPerTrack = @@ -2025,6 +2058,7 @@ UniataForgetDevice( PHW_LU_EXTENSION LunExt ) { + // keep only DFLAGS_HIDDEN flag LunExt->DeviceFlags &= DFLAGS_HIDDEN; LunExt->AtapiReadyWaitDelay = 0; } // end UniataForgetDevice() @@ -2034,6 +2068,7 @@ UniataForgetDevice( Routine Description: Reset IDE controller and/or Atapi device. + ->HwResetBus Arguments: HwDeviceExtension - HBA miniport driver's adapter data storage @@ -2054,7 +2089,6 @@ AtapiResetController( return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL); } // end AtapiResetController() - BOOLEAN NTAPI AtapiResetController__( @@ -2188,14 +2222,21 @@ AtapiResetController__( InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE); + for (i = 0; i < MaxLuns; i++) { + chan->lun[i]->PowerState = 0; + } // Reset controller if(ChipFlags & UNIATA_AHCI) { KdPrint2((PRINT_PREFIX " AHCI path\n")); + if(UniataAhciChanImplemented(deviceExtension, j)) { #if DBG - UniataDumpAhciPortRegs(chan); + UniataDumpAhciPortRegs(chan); #endif - AtapiDisableInterrupts(deviceExtension, j); - UniataAhciReset(HwDeviceExtension, j); + AtapiDisableInterrupts(deviceExtension, j); + UniataAhciReset(HwDeviceExtension, j); + } else { + KdPrint2((PRINT_PREFIX " skip not implemented\n")); + } } else { KdPrint2((PRINT_PREFIX " ATA path, chan %#x\n", chan)); KdPrint2((PRINT_PREFIX " disable intr (0)\n")); @@ -2843,6 +2884,7 @@ Routine Description: Arguments: HwDeviceExtension - HBA miniport driver's adapter data storage + ->HwInitialize Return Value: TRUE - if initialization successful. @@ -2864,6 +2906,11 @@ AtapiHwInitialize( if(WinVer_WDM_Model) { AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL); } + if(deviceExtension->MasterDev) { + KdPrint2((PRINT_PREFIX " mark chan %d of master controller [%x] as inited\n", + deviceExtension->Channel, deviceExtension->DevIndex)); + BMList[deviceExtension->DevIndex].ChanInitOk |= 0x01 << deviceExtension->Channel; + } /* do extra chipset specific setups */ AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED); @@ -2894,6 +2941,11 @@ AtapiHwInitialize__( // ULONG tmp32; ULONG PreferedMode = 0xffffffff; + if((deviceExtension->HwFlags & UNIATA_AHCI) && + !UniataAhciChanImplemented(deviceExtension, lChannel)) { + return; + } + AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel); FindDevices(deviceExtension, 0, lChannel); @@ -2998,9 +3050,65 @@ AtapiHwInitialize__( KdPrint2((PRINT_PREFIX " Disable Write Cache\n")); statusByte = AtaCommand(deviceExtension, i, lChannel, IDE_COMMAND_SET_FEATURES, 0, 0, 0, - 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY); + 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY); LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED; } + + if(LunExt->IdentifyData.FeaturesSupport.PowerMngt || + LunExt->IdentifyData.FeaturesSupport.APM) { + + if(LunExt->opt_AdvPowerMode) { + KdPrint2((PRINT_PREFIX " Try Enable Adv. Power Mgmt\n")); + // setup APM + statusByte = AtaCommand(deviceExtension, i, lChannel, + IDE_COMMAND_SET_FEATURES, 0, 0, 0, + LunExt->opt_AdvPowerMode, ATA_C_F_ENAB_APM, ATA_WAIT_BASE_READY); + // Check for errors. + if (statusByte & IDE_STATUS_ERROR) { + KdPrint2((PRINT_PREFIX + "AtapiHwInitialize: Enable APM on Device %d failed\n", + i)); + } + } else { + KdPrint2((PRINT_PREFIX " Disable Adv. Power Mgmt\n")); + statusByte = AtaCommand(deviceExtension, i, lChannel, + IDE_COMMAND_SET_FEATURES, 0, 0, 0, + 0, ATA_C_F_DIS_APM, ATA_WAIT_BASE_READY); + } + } + if(LunExt->IdentifyData.FeaturesSupport.AutoAcoustic) { + if(LunExt->opt_AcousticMode) { + KdPrint2((PRINT_PREFIX " Try Enable Acoustic Mgmt\n")); + // setup acoustic mgmt + statusByte = AtaCommand(deviceExtension, i, lChannel, + IDE_COMMAND_SET_FEATURES, 0, 0, 0, + LunExt->opt_AcousticMode, ATA_C_F_ENAB_ACOUSTIC, ATA_WAIT_BASE_READY); + // Check for errors. + if (statusByte & IDE_STATUS_ERROR) { + KdPrint2((PRINT_PREFIX + "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n", + i)); + } + } else { + KdPrint2((PRINT_PREFIX " Disable Acoustic Mgmt\n")); + statusByte = AtaCommand(deviceExtension, i, lChannel, + IDE_COMMAND_SET_FEATURES, 0, 0, 0, + 0, ATA_C_F_DIS_ACOUSTIC, ATA_WAIT_BASE_READY); + } + } + if(LunExt->IdentifyData.FeaturesSupport.Standby) { + KdPrint2((PRINT_PREFIX " Try init standby timer: %d\n")); + // setup standby timer + statusByte = AtaCommand(deviceExtension, i, lChannel, + IDE_COMMAND_IDLE, 0, 0, 0, + LunExt->opt_StandbyTimer, 0, ATA_WAIT_BASE_READY); + // Check for errors. + if (statusByte & IDE_STATUS_ERROR) { + KdPrint2((PRINT_PREFIX + "AtapiHwInitialize: standby timer on Device %d failed\n", + i)); + } + } } } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){ @@ -3498,7 +3606,10 @@ AtapiInterrupt( if(!hIS) { return FALSE; } - checked = ~hIS; // assume all non-interrupted ports to be already checked + // assume all non-interrupted ports to be already checked + checked = ~hIS; + // assume all not implemented ports to be already checked + checked |= ~deviceExtension->AHCI_PI; } else { checked = 0; // assume all ports are not checked } @@ -3661,7 +3772,11 @@ AtapiInterrupt2( if(!hIS) { return FALSE; } - checked = ~hIS; // assume all non-interrupted ports to be already checked + // assume all non-interrupted ports to be already checked + checked = ~hIS; + // assume all not implemented ports to be already checked + checked |= ~deviceExtension->AHCI_PI; + } else { checked = 0; // assume all ports are not checked } @@ -3844,6 +3959,12 @@ AtapiEnableInterrupts( KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c)); return; } + if((deviceExtension->HwFlags & UNIATA_AHCI) && + !UniataAhciChanImplemented(deviceExtension, c)) { + KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c)); + return; + } + chan = &(deviceExtension->chan[c]); KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr)); if(!InterlockedDecrement(&chan->DisableIntr)) { @@ -3977,6 +4098,11 @@ AtapiCheckInterrupt__( if((ChipFlags & UNIATA_AHCI) && UniataIsSATARangeAvailable(deviceExtension, lChannel)) { + + if(!UniataAhciChanImplemented(deviceExtension, lChannel)) { + return OurInterrupt; + } + OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED); if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) && (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) { @@ -4929,27 +5055,27 @@ continue_err: KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n")); KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n", AtaReq->retry, - chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry], - chan->lun[DeviceNumber]->BlockIoCount + LunExt->RecoverCount[AtaReq->retry], + LunExt->BlockIoCount )); - chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry]++; - if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 || + LunExt->RecoverCount[AtaReq->retry]++; + if(LunExt->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 || (deviceExtension->HwFlags & UNIATA_NO80CHK) ) { #else if(deviceExtension->HwFlags & UNIATA_NO80CHK) { #endif //IO_STATISTICS - KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", deviceExtension->lun[DeviceNumber].TransferMode)); - deviceExtension->lun[DeviceNumber].LimitedTransferMode = - deviceExtension->lun[DeviceNumber].TransferMode; + KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", LunExt->TransferMode)); + LunExt->LimitedTransferMode = + LunExt->TransferMode; } } #ifdef IO_STATISTICS if(AtaReq->bcount) { // we need stats for Read/Write operations - chan->lun[DeviceNumber]->BlockIoCount++; + LunExt->BlockIoCount++; } - chan->lun[DeviceNumber]->IoCount++; + LunExt->IoCount++; #endif //IO_STATISTICS continue_PIO: @@ -5063,9 +5189,9 @@ IntrPrepareResetController: } else { AtaReq->WordsLeft -= AtaReq->WordsTransfered; } - if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) { - status = SRB_STATUS_DATA_OVERRUN; - } + //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) { + // status = SRB_STATUS_DATA_OVERRUN; + //} status = SRB_STATUS_SUCCESS; chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; goto CompleteRequest; @@ -5074,7 +5200,9 @@ IntrPrepareResetController: // Write the packet. KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n")); // Send CDB to device. - WriteBuffer(chan, (PUSHORT)srb->Cdb, 6, 0); + WriteBuffer(chan, (PUSHORT)srb->Cdb, + LunExt->IdentifyData.AtapiCmdSize ? 8 : 6, + 0); AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { @@ -5457,7 +5585,7 @@ CompleteRequest: // Check and see if we are processing our secret (mechanism status/request sense) srb if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) { - KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_SUCCESS\n", AtaReq->WordsLeft)); + KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq->WordsLeft)); status = SRB_STATUS_DATA_OVERRUN; } @@ -5785,31 +5913,35 @@ IntrCompleteReq: } else { KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n")); - PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); if (status != SRB_STATUS_SUCCESS) { error = AtapiReadPort1(chan, IDX_IO1_i_Error); KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error)); } - // Build the SMART status block depending upon the completion status. - cmdOutParameters->cBufferSize = wordCount; - cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0; - cmdOutParameters->DriverStatus.bIDEError = error; + if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) { - // If the sub-command is return smart status, jam the value from cylinder low and high, into the - // data buffer. - if (chan->SmartCommand == RETURN_SMART_STATUS) { - cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS; - cmdOutParameters->bBuffer[1] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason); - cmdOutParameters->bBuffer[2] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Unused1); - cmdOutParameters->bBuffer[3] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow); - cmdOutParameters->bBuffer[4] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh); - cmdOutParameters->bBuffer[5] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_DriveSelect); - cmdOutParameters->bBuffer[6] = SMART_CMD; - cmdOutParameters->cBufferSize = 8; + PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); + // Build the SMART status block depending upon the completion status. + cmdOutParameters->cBufferSize = wordCount; + cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0; + cmdOutParameters->DriverStatus.bIDEError = error; + + // If the sub-command is return smart status, jam the value from cylinder low and high, into the + // data buffer. + if (chan->SmartCommand == RETURN_SMART_STATUS) { + PIDEREGS_EX regs = (PIDEREGS_EX)&(cmdOutParameters->bBuffer); + + regs->bOpFlags = 0; + UniataSnapAtaRegs(chan, 0, regs); + + regs->bCommandReg = SMART_CMD; + regs->bFeaturesReg = RETURN_SMART_STATUS; + + cmdOutParameters->cBufferSize = 8; + } + chan->SmartCommand = 0; // cleanup after execution } - // Indicate command complete. goto IntrCompleteReq; } @@ -5971,19 +6103,20 @@ ULONG NTAPI IdeSendSmartCommand( IN PVOID HwDeviceExtension, - IN PSCSI_REQUEST_BLOCK Srb + IN PSCSI_REQUEST_BLOCK Srb, + IN ULONG targetId // assume it is always valid ) { PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; - ULONG c = GET_CHANNEL(Srb); - PHW_CHANNEL chan = &(deviceExtension->chan[c]); + ULONG c ; // = GET_CHANNEL(Srb); may be invalid + PHW_CHANNEL chan ; // = &(deviceExtension->chan[c]); PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); PIDEREGS regs = &cmdInParameters.irDriveRegs; // ULONG i; - UCHAR statusByte,targetId; - + UCHAR statusByte; + ULONG DeviceNumber; if (regs->bCommandReg != SMART_CMD) { KdPrint2((PRINT_PREFIX @@ -5991,14 +6124,11 @@ IdeSendSmartCommand( return SRB_STATUS_INVALID_REQUEST; } - targetId = cmdInParameters.bDriveNumber; + c = targetId / deviceExtension->NumberLuns; + DeviceNumber = targetId % deviceExtension->NumberLuns; + KdPrint2((PRINT_PREFIX " c %d, dev %d\n", c, DeviceNumber)); - //TODO optimize this check - if ((!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) || - (deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) { - - return SRB_STATUS_SELECTION_TIMEOUT; - } + chan = &(deviceExtension->chan[c]); chan->SmartCommand = regs->bFeaturesReg; @@ -6006,6 +6136,14 @@ IdeSendSmartCommand( switch(regs->bFeaturesReg) { case READ_ATTRIBUTES: case READ_THRESHOLDS: + case READ_LOG_SECTOR: + case WRITE_LOG_SECTOR: + + if(Srb->DataTransferLength < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1) { + KdPrint2((PRINT_PREFIX + "IdeSendSmartCommand: wrong buffer size\n")); + return SRB_STATUS_DATA_OVERRUN; + } statusByte = WaitOnBusy(chan); @@ -6022,7 +6160,7 @@ IdeSendSmartCommand( AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer; AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2; - statusByte = AtaCommand(deviceExtension, targetId & 0x1, c, + statusByte = AtaCommand(deviceExtension, DeviceNumber, c, regs->bCommandReg, (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8), 0, @@ -6043,6 +6181,7 @@ IdeSendSmartCommand( case ENABLE_DISABLE_AUTOSAVE: case EXECUTE_OFFLINE_DIAGS: case SAVE_ATTRIBUTE_VALUES: + case AUTO_OFFLINE: statusByte = WaitOnBusy(chan); @@ -6059,7 +6198,7 @@ IdeSendSmartCommand( AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer; AtaReq->WordsLeft = 0; - statusByte = AtaCommand(deviceExtension, targetId & 0x1, c, + statusByte = AtaCommand(deviceExtension, DeviceNumber, c, regs->bCommandReg, (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8), 0, @@ -6070,6 +6209,7 @@ IdeSendSmartCommand( if(!(statusByte & IDE_STATUS_ERROR)) { // Wait for interrupt. + UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt return SRB_STATUS_PENDING; } return SRB_STATUS_ERROR; @@ -6615,7 +6755,6 @@ AtapiSendCommand( PHW_LU_EXTENSION LunExt; //ULONG ldev = GET_LDEV(Srb); ULONG DeviceNumber = GET_CDEV(Srb); - ULONG i; ULONG flags; UCHAR statusByte,byteCountLow,byteCountHigh; BOOLEAN use_dma = FALSE; @@ -6709,6 +6848,7 @@ AtapiSendCommand( if(CmdAction == CMD_ACTION_PREPARE) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb))); + switch (Srb->Cdb[0]) { case SCSIOP_RECEIVE: case SCSIOP_SEND: @@ -6775,6 +6915,13 @@ AtapiSendCommand( (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) { KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb))); + + if(!LunExt->IdentifyData.AtapiCmdSize && + (Srb->CdbLength > 12)) { + KdPrint2((PRINT_PREFIX "Cdb16 not supported\n")); + return SRB_STATUS_INVALID_REQUEST; + } + // Set data buffer pointer and words left. AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer; AtaReq->WordsLeft = Srb->DataTransferLength / 2; @@ -7110,6 +7257,8 @@ retry: // Try to drain the data that one preliminary device thinks that it has // to transfer. Hopefully this random assertion of DRQ will not be present // in production devices. + statusByte = AtapiSuckPort2(chan); +/* for (i = 0; i < 0x10000; i++) { GetStatus(chan, statusByte); if(statusByte & IDE_STATUS_DRQ) { @@ -7118,8 +7267,8 @@ retry: break; } } - - if (i == 0x10000) { +*/ + if (statusByte & IDE_STATUS_DRQ) { make_reset: KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte)); @@ -7282,7 +7431,7 @@ make_reset: WriteBuffer(chan, (PUSHORT)Srb->Cdb, - 6, + LunExt->IdentifyData.AtapiCmdSize ? 8 : 6, 0); if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) { @@ -7342,13 +7491,15 @@ IdeSendCommand( SetCheckPoint(4); UCHAR statusByte,errorByte; - ULONG status; + ULONG status = SRB_STATUS_INVALID_REQUEST; ULONG i; ULONGLONG lba; PMODE_PARAMETER_HEADER modeData; //ULONG ldev; ULONG DeviceNumber; PATA_REQ AtaReq; + UCHAR command; + SetCheckPoint(5); //ULONG __ebp__ = 0; @@ -7510,21 +7661,61 @@ default_no_prep: break; + case SCSIOP_REPORT_LUNS: { + + ULONG alen; + PREPORT_LUNS_INFO_HDR LunInfo; + + KdPrint2((PRINT_PREFIX + "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n", + Srb->PathId, Srb->Lun, Srb->TargetId)); + + MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength); + + if(alen < 16) { + goto invalid_cdb; + } + alen = 8; + + LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer); + RtlZeroMemory(LunInfo, 16); + + MOV_DD_SWP( LunInfo->ListLength, alen ); + Srb->DataTransferLength = 16; + status = SRB_STATUS_SUCCESS; + + break; } + case SCSIOP_MODE_SENSE: KdPrint2((PRINT_PREFIX "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n", Srb->PathId, Srb->Lun, Srb->TargetId)); - // This is used to determine if the media is write-protected. - // Since IDE does not support mode sense then we will modify just the portion we need - // so the higher level driver can determine if media is protected. + + if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) { + PMODE_POWER_CONDITION_PAGE modeData; + + KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n")); + modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer); + if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) { + status = SRB_STATUS_DATA_OVERRUN; + } else { + RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE)); + modeData->PageCode = MODE_PAGE_POWER_CONDITION; + modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER); + modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle; + modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby; + Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE); + status = SRB_STATUS_SUCCESS; + } + } else if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) { PMODE_CACHING_PAGE modeData; KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n")); - modeData = (PMODE_CACHING_PAGE)Srb->DataBuffer; + modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer); if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) { - status = STATUS_BUFFER_TOO_SMALL; + status = SRB_STATUS_DATA_OVERRUN; } else { RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE)); modeData->PageCode = MODE_PAGE_CACHING; @@ -7537,6 +7728,10 @@ default_no_prep: } else if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) { + // This is used to determine if the media is write-protected. + // Since IDE does not support mode sense then we will modify just the portion we need + // so the higher level driver can determine if media is protected. + //SelectDrive(chan, DeviceNumber); //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS); //statusByte = WaitOnBusy(chan); @@ -7726,21 +7921,98 @@ default_no_prep: case SCSIOP_START_STOP_UNIT: KdPrint2((PRINT_PREFIX - "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n", - Srb->PathId, Srb->Lun, Srb->TargetId)); + "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n", + cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId)); //Determine what type of operation we should perform - cdb = (PCDB)Srb->Cdb; - if (cdb->START_STOP.LoadEject == 1){ + command = 0; - statusByte = WaitOnBaseBusy(chan); + if(cdb->START_STOP.FL || + cdb->START_STOP.FormatLayerNumber || + cdb->START_STOP.Reserved2 || + cdb->START_STOP.Reserved2_2 || + cdb->START_STOP.Reserved3 || + FALSE) { + goto invalid_cdb; + } + + if (cdb->START_STOP.PowerConditions) { + KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions)); + switch(cdb->START_STOP.PowerConditions) { + case StartStop_Power_Idle: + command = IDE_COMMAND_IDLE_IMMED; + break; + case StartStop_Power_Standby: + command = IDE_COMMAND_STANDBY_IMMED; + break; + case StartStop_Power_Sleep: + // TODO: we should save power state in order to know + // that RESET sould be issued to revert device into + // operable state + + command = IDE_COMMAND_SLEEP; + break; + default: + goto invalid_cdb; + } + LunExt->PowerState = cdb->START_STOP.PowerConditions; + } else + if (cdb->START_STOP.LoadEject == 1) { + KdPrint2((PRINT_PREFIX "START_STOP eject\n")); // Eject media, // first select device 0 or 1. //SelectDrive(chan, DeviceNumber); //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT); - statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_MEDIA_EJECT, 0, 0, 0, 0, 0, ATA_IMMEDIATE); + command = IDE_COMMAND_MEDIA_EJECT; + } else + if (cdb->START_STOP.Start == 0) { + KdPrint2((PRINT_PREFIX "START_STOP standby\n")); + command = IDE_COMMAND_STANDBY_IMMED; + } else { + // TODO: we may need to perform hard reset (after sleep) or + // issue IDE_COMMAND_IDLE_IMMED in order to activate device + KdPrint2((PRINT_PREFIX "START_STOP activate\n")); + + if(LunExt->PowerState == StartStop_Power_Sleep) { + UniataUserDeviceReset(deviceExtension, LunExt, lChannel); + status = SRB_STATUS_SUCCESS; + break; + } else + if(LunExt->PowerState > StartStop_Power_Idle) { + KdPrint2((PRINT_PREFIX " issue IDLE\n")); + command = IDE_COMMAND_IDLE_IMMED; + } else { + KdPrint2((PRINT_PREFIX " do nothing\n")); + status = SRB_STATUS_SUCCESS; + break; + } + } + if(command) { + statusByte = WaitOnBaseBusy(chan); + statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0, + cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY); + status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS; + //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt + + } else { +invalid_cdb: + KdPrint2((PRINT_PREFIX "START_STOP invalid\n")); + if (Srb->SenseInfoBuffer) { + + PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer; + + senseBuffer->ErrorCode = 0x70; + senseBuffer->Valid = 1; + senseBuffer->AdditionalSenseLength = 0xb; + senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST; + senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB; + senseBuffer->AdditionalSenseCodeQualifier = 0; + + Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID; + Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; + } + status = SRB_STATUS_ERROR; } - status = SRB_STATUS_SUCCESS; break; case SCSIOP_MEDIUM_REMOVAL: @@ -7802,25 +8074,59 @@ default_no_prep: regs = (PIDEREGS_EX) &(Srb->Cdb[2]); - lChannel = Srb->TargetId >> 1; - - regs->bDriveHeadReg &= 0x0f; - regs->bDriveHeadReg |= (UCHAR) (((Srb->TargetId & 0x1) << 4) | 0xA0); + if(chan->DeviceExtension->HwFlags & UNIATA_SATA) { + //lChannel = Srb->TargetId >> 1; + } else { + DeviceNumber = max(DeviceNumber, 1); + regs->bDriveHeadReg &= 0x0f; + regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0); + } if((regs->bOpFlags & 1) == 0) { // execute ATA command KdPrint2((PRINT_PREFIX - "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n", + "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n", Srb->PathId, Srb->Lun, Srb->TargetId)); + if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) { + to_lim = Srb->TimeOutValue; + } else { + if(Srb->TimeOutValue <= 2) { + to_lim = Srb->TimeOutValue*900; + } else { + to_lim = (Srb->TimeOutValue*999) - 500; + } + } AtapiDisableInterrupts(deviceExtension, lChannel); + if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { + // AHCI + statusByte = UniataAhciSendPIOCommandDirect( + deviceExtension, + lChannel, + DeviceNumber, + Srb, + regs, + ATA_WAIT_INTR, + to_lim + ); + if(statusByte == IDE_STATUS_WRONG) { + goto passthrough_err; + } + if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) { + UniataAhciAbortOperation(chan); + goto passthrough_err; + } + goto passthrough_done; + } + + // SATA/PATA if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) { - if((chan->lun[Srb->TargetId & 0x1]->LimitedTransferMode >= ATA_DMA)) { + if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) { use_dma = TRUE; // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success - if(!AtapiDmaSetup(HwDeviceExtension, Srb->TargetId & 0x1, lChannel, Srb, + if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb, (PUCHAR)(Srb->DataBuffer), ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) { use_dma = FALSE; @@ -7828,7 +8134,7 @@ default_no_prep: } } - AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg); + AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg); AtapiStallExecution(10); if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command @@ -7856,20 +8162,11 @@ default_no_prep: if(statusByte & IDE_STATUS_ERROR) { goto passthrough_err; } - AtapiDmaStart(HwDeviceExtension, (Srb->TargetId & 0x1), lChannel, Srb); + AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb); } ScsiPortStallExecution(1); // wait for busy to be set - if(regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) { - to_lim = Srb->TimeOutValue; - } else { - if(Srb->TimeOutValue <= 2) { - to_lim = Srb->TimeOutValue*900; - } else { - to_lim = (Srb->TimeOutValue*999) - 500; - } - } for(i=0; iTargetId & 0x1), lChannel, NULL); + AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL); GetBaseStatus(chan, statusByte); if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) { @@ -7930,34 +8227,33 @@ passthrough_err: } status = SRB_STATUS_SUCCESS; } - +passthrough_done:; AtapiEnableInterrupts(deviceExtension, lChannel); } else { // read task register + BOOLEAN use48; regs = (PIDEREGS_EX) Srb->DataBuffer; - regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect); + KdPrint2((PRINT_PREFIX + "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n", + Srb->PathId, Srb->Lun, Srb->TargetId)); - if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command - regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error); - regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount); - regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber); - regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow); - regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh); + if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) && + (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) { + use48 = TRUE; + } else + if(Srb->DataTransferLength >= sizeof(IDEREGS)) { + use48 = FALSE; } else { - regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error); - regs->bFeaturesRegH = AtapiReadPort1(chan, IDX_IO1_i_Error); - regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount); - regs->bSectorCountRegH = AtapiReadPort1(chan, IDX_IO1_i_BlockCount); - regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber); - regs->bSectorNumberRegH= AtapiReadPort1(chan, IDX_IO1_i_BlockNumber); - regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow); - regs->bCylLowRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow); - regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh); - regs->bCylHighRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh); + KdPrint2((PRINT_PREFIX " buffer too small \n")); + status = SRB_STATUS_DATA_OVERRUN; + break; } - regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status); + RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS)); + regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0; + UniataSnapAtaRegs(chan, 0, regs); + status = SRB_STATUS_SUCCESS; } break; @@ -8132,23 +8428,24 @@ NTAPI UniataUserDeviceReset( PHW_DEVICE_EXTENSION deviceExtension, PHW_LU_EXTENSION LunExt, - ULONG PathId + ULONG lChannel ) { ULONG i; - AtapiDisableInterrupts(deviceExtension, PathId); - if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { + AtapiDisableInterrupts(deviceExtension, lChannel); + if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) && + (LunExt->PowerState != StartStop_Power_Sleep)) { KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n")); - AtapiSoftReset(&(deviceExtension->chan[PathId]), LunExt->Lun); + AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun); } else { KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n")); - AtapiResetController__(deviceExtension, PathId, RESET_COMPLETE_NONE); + AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE); for(i=0; iNumberLuns; i++) { - deviceExtension->chan[PathId].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA; + deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA; } } LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit - AtapiEnableInterrupts(deviceExtension, PathId); + AtapiEnableInterrupts(deviceExtension, lChannel); return; } // end UniataUserDeviceReset() @@ -8194,6 +8491,7 @@ Routine Description: This routine is called from the SCSI port driver synchronized with the kernel to start an IO request. + ->HwStartIo Arguments: @@ -8257,13 +8555,14 @@ AtapiStartIo__( UniAtaClearAtaReq(Srb->SrbExtension); } - do { + do { // fetch all queued commands for the channel (if valid) lChannel = GET_CHANNEL(Srb); //ldev = GET_LDEV(Srb); chan = NULL; LunExt = NULL; DeviceNumber = GET_CDEV(Srb); + commPort = FALSE; //ASSERT(deviceExtension); //ASSERT(chan); @@ -8283,6 +8582,14 @@ AtapiStartIo__( "AtapiStartIo: Communication port\n")); if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) { + if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) { + KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength, + sizeof(PINQUIRYDATA) )); +wrong_buffer_size: + status = SRB_STATUS_DATA_OVERRUN; + goto complete_req; + } + PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer); KdPrint2((PRINT_PREFIX @@ -8302,22 +8609,26 @@ AtapiStartIo__( /* Pass IOCTL request down */ } else if(lChannel >= deviceExtension->NumberChannels || - Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns || - Srb->Lun) { + Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns || + Srb->Lun) { - if(lChannel >= deviceExtension->NumberChannels) { - chan = NULL; - } + if(lChannel >= deviceExtension->NumberChannels) { + chan = NULL; + } reject_srb: //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) { - KdPrint3((PRINT_PREFIX + KdPrint3((PRINT_PREFIX "AtapiStartIo: SRB rejected\n")); - // Indicate no device found at this address. - KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); - status = SRB_STATUS_SELECTION_TIMEOUT; - goto complete_req; + // Indicate no device found at this address. + KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); + status = SRB_STATUS_SELECTION_TIMEOUT; + goto complete_req; //} + } else + if((deviceExtension->HwFlags & UNIATA_AHCI) && + !UniataAhciChanImplemented(deviceExtension, lChannel)) { + chan = NULL; } if(!commPort) { @@ -8426,6 +8737,7 @@ reject_srb: KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth)); } else { + // Send command to device. KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0])); if(TopLevel) { @@ -8465,7 +8777,8 @@ reject_srb: #endif //NAVO_TEST if(atapiDev && - (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) { + (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* && + (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) { KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0])); status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL); } else { @@ -8660,11 +8973,108 @@ do_bus_reset: if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) { + ULONG targetId = (ULONG)(-1); + + if(len < sizeof(SRB_IO_CONTROL)) { + goto wrong_buffer_size; + } + + // extract bogus bus address + switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) { + case IOCTL_SCSI_MINIPORT_SMART_VERSION: { + PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); + + if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) { + goto wrong_buffer_size; + } + + targetId = versionParameters->bIDEDeviceMap; + KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId)); + break; } + case IOCTL_SCSI_MINIPORT_IDENTIFY: + case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS: + case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS: + case IOCTL_SCSI_MINIPORT_ENABLE_SMART: + case IOCTL_SCSI_MINIPORT_DISABLE_SMART: + case IOCTL_SCSI_MINIPORT_RETURN_STATUS: + case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE: + case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES: + case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS: + case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE: + case IOCTL_SCSI_MINIPORT_READ_SMART_LOG: + case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG: + { + PSENDCMDINPARAMS cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); + + if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) { + goto wrong_buffer_size; + } + + targetId = cmdInParameters->bDriveNumber; + KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId)); + break; } + default: +invalid_request: + KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n", + ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode )); + status = SRB_STATUS_INVALID_REQUEST; + goto complete_req; + } // end switch() + + // adjust (if necessary) bus address + if(targetId != (ULONG)(-1)) { + + // This is done because of how the IOCTL_SCSI_MINIPORT + // determines 'targetid's'. Disk.sys places the real target id value + // in the DeviceMap field. Once we do some parameter checking, the value passed + // back to the application will be determined. + + if (deviceExtension->NumberChannels == 1) { + // do this for legacy controllers and legacy callers + KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n")); + DeviceNumber = (targetId & 0x01); + lChannel = 0; + } else + if(commPort) { + // do this for smartmontools, sending IOCTLs to PhysicalDrive%d + // due to DISK.SYS design bug, we have invalid SCSI address in SRB + KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n")); + if(deviceExtension->HwFlags & UNIATA_AHCI) { + lChannel = (UCHAR)targetId / 2; + DeviceNumber = 0; + } else { + lChannel = (UCHAR)(targetId / 2); + DeviceNumber = targetId & 0x01; + } + } else { + // otherwise assume lChannel and DeviceNumber from Srb are ok + } + if(lChannel >= deviceExtension->NumberChannels || + DeviceNumber >= deviceExtension->NumberLuns) { + KdPrint2((PRINT_PREFIX + "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n", + targetId)); + // Indicate no device found at this address. + goto reject_srb; + } + targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber; + chan = &(deviceExtension->chan[lChannel]); + LunExt = chan->lun[DeviceNumber]; + if(!LunExt) { + goto reject_srb; + } + atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE; + + if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) { + goto reject_srb; + } + } + switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) { case IOCTL_SCSI_MINIPORT_SMART_VERSION: { PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); - UCHAR deviceNumber; + UCHAR deviceNumberMap; KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n")); @@ -8677,27 +9087,8 @@ do_bus_reset: // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands. versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD); - // This is done because of how the IOCTL_SCSI_MINIPORT - // determines 'targetid's'. Disk.sys places the real target id value - // in the DeviceMap field. Once we do some parameter checking, the value passed - // back to the application will be determined. - - deviceNumber = versionParameters->bIDEDeviceMap; - - if(commPort) { - KdPrint2((PRINT_PREFIX - "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n")); - // Indicate no device found at this address. - KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); - status = SRB_STATUS_SELECTION_TIMEOUT; - break; - } - - if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) || - atapiDev) { - - status = SRB_STATUS_SELECTION_TIMEOUT; - break; + if (atapiDev) { + goto invalid_request; } // NOTE: This will only set the bit @@ -8709,19 +9100,20 @@ do_bus_reset: // 3 2 1 0 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { - deviceNumber = 1 << lChannel; + deviceNumberMap = 1 << lChannel; + DeviceNumber = 0; } else if (deviceExtension->NumberChannels == 1) { if (chan->PrimaryAddress) { - deviceNumber = 1 << DeviceNumber; + deviceNumberMap = 1 << DeviceNumber; } else { - deviceNumber = 4 << DeviceNumber; + deviceNumberMap = 4 << DeviceNumber; } } else { - deviceNumber = 1 << (DeviceNumber+lChannel*2); + deviceNumberMap = 1 << (DeviceNumber+lChannel*2); } - versionParameters->bIDEDeviceMap = deviceNumber; + versionParameters->bIDEDeviceMap = deviceNumberMap; status = SRB_STATUS_SUCCESS; break; @@ -8731,41 +9123,24 @@ do_bus_reset: PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL)); - UCHAR targetId; KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n")); // Extract the target. - targetId = cmdInParameters.bDriveNumber; KdPrint2((PRINT_PREFIX "targetId %d\n", targetId)); - if(deviceExtension->HwFlags & UNIATA_AHCI) { - // cheat code for AHCI :) - // upper layer assumes that we have 2 devices per channel - // TODO: we should invent something to handle PM here - targetId /= 2; - } - - if((targetId >= deviceExtension->NumberChannels*deviceExtension->NumberLuns) || - !(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) { - KdPrint2((PRINT_PREFIX "Error: xxx_ID_CMD for non-existant device\n")); - status = SRB_STATUS_SELECTION_TIMEOUT; - break; - } switch(cmdInParameters.irDriveRegs.bCommandReg) { case ID_CMD: - if((deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) { + if(atapiDev) { KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n")); - status = SRB_STATUS_INVALID_REQUEST; - break; + goto invalid_request; } /* FALL THROUGH */ case ATAPI_ID_CMD: - if(!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE) && + if(!atapiDev && (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) { KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n")); - status = SRB_STATUS_INVALID_REQUEST; - break; + goto invalid_request; } len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE); @@ -8781,9 +9156,21 @@ do_bus_reset: cmdOutParameters->DriverStatus.bIDEError = 0; // Extract the identify data from the device extension. - ScsiPortMoveMemory (cmdOutParameters->bBuffer, &deviceExtension->lun[targetId].IdentifyData, + ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData), cmdOutParameters->cBufferSize); + if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) && + (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) { + // adjust checksum if it is possible + CHAR csum = 0; + ULONG i; + + for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) { + csum += (CHAR)(cmdOutParameters->bBuffer[i]); + } + cmdOutParameters->bBuffer[i] = -csum; + KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n")); + } KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n")); status = SRB_STATUS_SUCCESS; @@ -8797,7 +9184,7 @@ do_bus_reset: } break; } - +/* case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS: case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS: case IOCTL_SCSI_MINIPORT_ENABLE_SMART: @@ -8806,14 +9193,15 @@ do_bus_reset: case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE: case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES: case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS: - +*/ + default: + // *all* IOCTLs here are SMART if(commPort) { KdPrint2((PRINT_PREFIX "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n")); - // Indicate no device found at this address. - KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n")); - status = SRB_STATUS_SELECTION_TIMEOUT; - break; + } + if (atapiDev) { + goto invalid_request; } PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel); @@ -8832,16 +9220,17 @@ do_bus_reset: KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth)); } else { - status = IdeSendSmartCommand(HwDeviceExtension,Srb); + status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId); } break; - default : + // we should not get here, checked above +/* default : KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n", ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode )); status = SRB_STATUS_INVALID_REQUEST; break; - +*/ } } else if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) { @@ -8857,8 +9246,7 @@ do_bus_reset: if(len < pos) { KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, FIELD_OFFSET(UNIATA_CTL, RawData) )); - status = SRB_STATUS_DATA_OVERRUN; - break; + goto wrong_buffer_size; } if(AtaCtl->addr.Lun || @@ -8927,8 +9315,7 @@ handle_bad_ldev: if(len < pos+sizeof(AtaCtl->SetMode)) { KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, pos+sizeof(AtaCtl->SetMode) )); - status = SRB_STATUS_DATA_OVERRUN; - goto complete_req; + goto wrong_buffer_size; } if(!AtaCtl->SetMode.ApplyImmediately) { break; @@ -8963,8 +9350,7 @@ uata_ctl_queue: if(len < pos+sizeof(AtaCtl->FindDelDev)) { KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, pos+sizeof(AtaCtl->FindDelDev) )); - status = SRB_STATUS_DATA_OVERRUN; - goto complete_req; + goto wrong_buffer_size; } if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) { KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n")); @@ -8993,8 +9379,7 @@ uata_ctl_queue: if(len < pos+sizeof(AtaCtl->FindDelDev)) { KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, pos+sizeof(AtaCtl->FindDelDev) )); - status = SRB_STATUS_DATA_OVERRUN; - goto complete_req; + goto wrong_buffer_size; } LunExt->DeviceFlags = 0; if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) { @@ -9017,8 +9402,7 @@ uata_ctl_queue: if(len < pos+sizeof(AtaCtl->SetMode)) { KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, pos+sizeof(AtaCtl->SetMode) )); - status = SRB_STATUS_DATA_OVERRUN; - goto complete_req; + goto wrong_buffer_size; } if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) { LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode); @@ -9050,8 +9434,7 @@ uata_ctl_queue: if(len < pos+sizeof(AtaCtl->GetMode)) { KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, pos+sizeof(AtaCtl->GetMode) )); - status = SRB_STATUS_DATA_OVERRUN; - goto complete_req; + goto wrong_buffer_size; } AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode; AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode; @@ -9068,8 +9451,7 @@ uata_ctl_queue: if(len < pos+sizeof(AtaCtl->Version)) { KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, pos+sizeof(AtaCtl->Version) )); - status = SRB_STATUS_DATA_OVERRUN; - goto complete_req; + goto wrong_buffer_size; } AtaCtl->Version.Length = sizeof(GETDRVVERSION); AtaCtl->Version.VersionMj = UNIATA_VER_MJ; @@ -9087,8 +9469,7 @@ uata_ctl_queue: if(len < pos+sizeof(AtaCtl->AdapterInfo)) { KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len, pos+sizeof(AtaCtl->AdapterInfo) )); - status = SRB_STATUS_DATA_OVERRUN; - goto complete_req; + goto wrong_buffer_size; } AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO); @@ -9216,8 +9597,10 @@ complete_req: // Set status in SRB. Srb->SrbStatus = (UCHAR)status; - KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb)); - AtapiDmaDBSync(chan, Srb); + if(chan && Srb) { + KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb)); + AtapiDmaDBSync(chan, Srb); + } KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb)); UniataRemoveRequest(chan, Srb); // Indicate command complete. @@ -9652,6 +10035,15 @@ DriverEntry( if(GlobalConfig->AtDiskSecondaryAddressClaimed) SecondaryClaimed = TRUE; + if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed && + !(BMList[i].ChanInitOk & 0x80)) { + newStatus = UniataClaimLegacyPCIIDE(i); + if(newStatus != STATUS_SUCCESS) { + KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n")); + break; + } + } + if(g_opt_Verbose) { _PrintNtConsole("Init standard Dual-channel PCI ATA controller:"); } @@ -9710,7 +10102,15 @@ DriverEntry( statusToReturn = newStatus; } if (newStatus == STATUS_SUCCESS) { - BMList[i].ChanInitOk |= 0x01 << c; + if(WinVer_Id() < WinVer_2k) { + // This should be done in HwInitialize under w2k+ to ensure that + // channel is actually initialized + BMList[i].ChanInitOk |= 0x01 << c; + } else { + if(BMList[i].ChanInitOk & (0x01 << c)) { + KdPrint2((PRINT_PREFIX "HwInit passed\n")); + } + } /* if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) { c = 1; // this will break our for() @@ -9719,43 +10119,28 @@ DriverEntry( */ } } - if(WinVer_Id() >= WinVer_2k) { - // the following doesn't work under higher OSes +/* if(WinVer_Id() >= WinVer_2k) { + // the following didn't work under higher OSes, + // until we move setting of FLAGS to HwInit KdPrint2((PRINT_PREFIX "make still one attempt\n")); continue; - } + }*/ if(BMList[i].ChanInitOk & 0x03) { - // under NT we receive status immediately, so - // we can omit alternative init method id STATUS_SUCCESS returned + // Under NT we receive status immediately, so + // we can omit alternative init method if STATUS_SUCCESS returned. + // Under w2k+ we relay on flags, set in HwInitialize. KdPrint2((PRINT_PREFIX "Ok, no more retries required\n")); break; + } else + if(WinVer_Id() >= WinVer_2k) { + // try AltInit if HwInit was not called immediately under w2k+ + KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n")); + } else { + // if (WinVer_Id() == WinVer_NT) and some error occured + // try alternative init method + KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n")); } - // if (WinVer_Id() == WinVer_NT) and some error occured - // try alternative init method } // for(alt...) -#if 0 - if(WinVer_WDM_Model) { - hwInitializationData.comm.HwFindAdapter = UniataFindFakeBusMasterController; - hwInitializationData.comm.NumberOfAccessRanges = 5; - hwInitializationData.comm.AdapterInterfaceType = PCIBus; - - hwInitializationData.comm.VendorId = BMList[i].VendorId; - hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength; - hwInitializationData.comm.DeviceId = BMList[i].DeviceId; - hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength; - - //BMList[i].channel = 0/*(UCHAR)c*/; - - KdPrint2((PRINT_PREFIX "Try init fake: %4.4s %4.4s \n", - hwInitializationData.comm.VendorId, - hwInitializationData.comm.DeviceId)); - newStatus = ScsiPortInitialize(DriverObject, - Argument2, - &hwInitializationData.comm, - (PVOID)i); - KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus)); - } -#endif //0 if(g_opt_Verbose) { if(BMList[i].ChanInitOk & 0x03) { _PrintNtConsole(" OK\n"); @@ -9793,9 +10178,9 @@ DriverEntry( hwInitializationData.comm.NumberOfAccessRanges = 6; hwInitializationData.comm.AdapterInterfaceType = PCIBus; - hwInitializationData.comm.VendorId = BMList[i].VendorId; + hwInitializationData.comm.VendorId = (PVOID)BMList[i].VendorId; hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength; - hwInitializationData.comm.DeviceId = BMList[i].DeviceId; + hwInitializationData.comm.DeviceId = (PVOID)BMList[i].DeviceId; hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength; BMList[i].channel = 0/*(UCHAR)c*/; diff --git a/reactos/drivers/storage/ide/uniata/id_dma.cpp b/reactos/drivers/storage/ide/uniata/id_dma.cpp index 208f07dda91..f27e2d99bd1 100644 --- a/reactos/drivers/storage/ide/uniata/id_dma.cpp +++ b/reactos/drivers/storage/ide/uniata/id_dma.cpp @@ -944,19 +944,19 @@ AtapiDmaInit( } // Limit transfer mode (controller limitation) - if((LONG)deviceExtension->MaxTransferMode >= ATA_UDMA) { - KdPrint2((PRINT_PREFIX "AtapiDmaInit: deviceExtension->MaxTransferMode >= ATA_UDMA\n")); - udmamode = min( udmamode, (CHAR)(deviceExtension->MaxTransferMode - ATA_UDMA)); + if((LONG)chan->MaxTransferMode >= ATA_UDMA) { + KdPrint2((PRINT_PREFIX "AtapiDmaInit: chan->MaxTransferMode >= ATA_UDMA\n")); + udmamode = min( udmamode, (CHAR)(chan->MaxTransferMode - ATA_UDMA)); } else - if((LONG)deviceExtension->MaxTransferMode >= ATA_WDMA) { - KdPrint2((PRINT_PREFIX "AtapiDmaInit: deviceExtension->MaxTransferMode >= ATA_WDMA\n")); + if((LONG)chan->MaxTransferMode >= ATA_WDMA) { + KdPrint2((PRINT_PREFIX "AtapiDmaInit: chan->MaxTransferMode >= ATA_WDMA\n")); udmamode = -1; - wdmamode = min( wdmamode, (CHAR)(deviceExtension->MaxTransferMode - ATA_WDMA)); + wdmamode = min( wdmamode, (CHAR)(chan->MaxTransferMode - ATA_WDMA)); } else - if((LONG)deviceExtension->MaxTransferMode >= ATA_PIO0) { + if((LONG)chan->MaxTransferMode >= ATA_PIO0) { KdPrint2((PRINT_PREFIX "AtapiDmaInit: NO DMA\n")); wdmamode = udmamode = -1; - apiomode = min( apiomode, (CHAR)(deviceExtension->MaxTransferMode - ATA_PIO0)); + apiomode = min( apiomode, (CHAR)(chan->MaxTransferMode - ATA_PIO0)); } else { KdPrint2((PRINT_PREFIX "AtapiDmaInit: PIO0\n")); wdmamode = udmamode = -1; @@ -1003,14 +1003,16 @@ AtapiDmaInit( } //} - if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { + if(UniataIsSATARangeAvailable(deviceExtension, lChannel) || + (ChipFlags & UNIATA_AHCI) || (chan->MaxTransferMode >= ATA_SA150) + ) { //if(ChipFlags & (UNIATA_SATA | UNIATA_AHCI)) { /****************/ /* SATA Generic */ /****************/ KdPrint2((PRINT_PREFIX "SATA Generic\n")); - if((udmamode >= 5) || (ChipFlags & UNIATA_AHCI) || chan->MaxTransferMode >= ATA_SA150) { + if((udmamode >= 5) || (ChipFlags & UNIATA_AHCI) || (chan->MaxTransferMode >= ATA_SA150)) { /* some drives report UDMA6, some UDMA5 */ /* ATAPI may not have SataCapabilities set in IDENTIFY DATA */ if(ata_is_sata(&(LunExt->IdentifyData))) { @@ -1024,7 +1026,7 @@ AtapiDmaInit( } else { KdPrint2((PRINT_PREFIX "SATA -> PATA adapter ?\n")); - if (udmamode > 2 && (!LunExt->IdentifyData.HwResCableId || (LunExt->IdentifyData.HwResValid != IDENTIFY_CABLE_ID_VALID) )) { + if (udmamode > 2 && (!LunExt->IdentifyData.HwResCableId && (LunExt->IdentifyData.HwResValid == IDENTIFY_CABLE_ID_VALID) )) { KdPrint2((PRINT_PREFIX "AtapiDmaInit: DMA limited to UDMA33, non-ATA66 compliant cable\n")); udmamode = 2; apiomode = min( apiomode, (CHAR)(LunExt->LimitedTransferMode - ATA_PIO0)); @@ -1054,7 +1056,7 @@ AtapiDmaInit( goto try_generic_dma; } - if(udmamode > 2 && (!LunExt->IdentifyData.HwResCableId || (LunExt->IdentifyData.HwResValid != IDENTIFY_CABLE_ID_VALID)) ) { + if(udmamode > 2 && (!LunExt->IdentifyData.HwResCableId && (LunExt->IdentifyData.HwResValid == IDENTIFY_CABLE_ID_VALID)) ) { if(ata_is_sata(&(LunExt->IdentifyData))) { KdPrint2((PRINT_PREFIX "AtapiDmaInit: SATA beyond adapter or Controller compat mode\n")); } else { @@ -1384,6 +1386,7 @@ set_new_acard: UCHAR new44 = 0; UCHAR intel_timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 }; + UCHAR intel_utimings[] = { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 }; if(deviceExtension->DevID == ATA_I82371FB) { if (wdmamode >= 2 && apiomode >= 4) { @@ -1466,17 +1469,24 @@ set_new_acard: for(i=udmamode; i>=0; i--) { if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) { - /* Set UDMA reference clock (33/66/133MHz). */ + /* Set UDMA reference clock (33 MHz or more). */ SetPciConfig1(0x48, reg48 | (0x0001 << dev)); if(!(ChipFlags & ICH4_FIX)) { - SetPciConfig2(0x4a, (reg4a & ~(0x3 << (dev<<2))) | - (0x01 + !(i & 0x01)) ); + if(deviceExtension->MaxTransferMode == ATA_UDMA3) { + // Special case (undocumented overclock !) for PIIX4e + SetPciConfig2(0x4a, (reg4a | (0x03 << (dev<<2)) ) ); + } else { + SetPciConfig2(0x4a, (reg4a & ~(0x03 << (dev<<2))) | + (((USHORT)(intel_utimings[i])) << (dev<<2) ) ); + } } - if(i >= 2) { + /* Set UDMA reference clock (66 MHz or more). */ + if(i > 2) { reg54 |= (0x1 << dev); } else { reg54 &= ~(0x1 << dev); } + /* Set UDMA reference clock (133 MHz). */ if(i >= 5) { reg54 |= (0x1000 << dev); } else { diff --git a/reactos/drivers/storage/ide/uniata/id_init.cpp b/reactos/drivers/storage/ide/uniata/id_init.cpp index bc844ca4c15..94ee5ab6069 100644 --- a/reactos/drivers/storage/ide/uniata/id_init.cpp +++ b/reactos/drivers/storage/ide/uniata/id_init.cpp @@ -178,6 +178,7 @@ UniataChipDetectChannels( KdPrint2((PRINT_PREFIX "New ITE PATA 1 chan\n")); } break; +#if 0 case ATA_INTEL_ID: /* New Intel PATA controllers */ if(g_opt_VirtualMachine != VM_VBOX && @@ -193,6 +194,7 @@ UniataChipDetectChannels( KdPrint2((PRINT_PREFIX "New Intel PATA 1 chan\n")); } break; +#endif // this code is removed from newer FreeBSD case ATA_JMICRON_ID: /* New JMicron PATA controllers */ if(deviceExtension->DevID == ATA_JMB361 || @@ -1418,6 +1420,11 @@ generic_cable80( ULONG slotNumber = deviceExtension->slotNumber; ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; + if(deviceExtension->MaxTransferMode <= ATA_UDMA2) { + KdPrint2((PRINT_PREFIX "generic_cable80(%d, %#x, %d) <= UDMA2\n", channel, pci_reg, bit_offs)); + return FALSE; + } + //ULONG ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK; PHW_CHANNEL chan; ULONG c; // logical channel (for Compatible Mode controllers) @@ -1468,6 +1475,27 @@ UniAtaReadLunConfig( tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"PreferedTransferMode", 0xffffffff); LunExt->opt_PreferedTransferMode = tmp32; + tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"AdvancedPowerMode", ATA_C_F_APM_CNT_MIN_NO_STANDBY); + if(tmp32 > 0xfe) { + tmp32 = 0xfe; // max. performance + } + LunExt->opt_AdvPowerMode = (UCHAR)tmp32; + + tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"AcousticMgmt", ATA_C_F_AAM_CNT_MAX_POWER_SAVE); + if(tmp32 > 0xfe) { + tmp32 = 0xfe; // max. performance + } else + if(tmp32 < 0x80) { + tmp32 = 0x0; // disable feature + } + LunExt->opt_AcousticMode = (UCHAR)tmp32; + + tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"StandbyTimer", 0); + if(tmp32 == 0xfe) { + tmp32 = 0xff; + } + LunExt->opt_StandbyTimer = (UCHAR)tmp32; + tmp32 = AtapiRegCheckDevValue(deviceExtension, channel, DeviceNumber, L"ReadOnly", 0); if(tmp32 <= 2) { LunExt->opt_ReadOnly = (UCHAR)tmp32; @@ -1623,6 +1651,7 @@ AtapiChipInit( ULONG tmp32; ULONG c; // logical channel (for Compatible Mode controllers) BOOLEAN CheckCable = FALSE; + BOOLEAN GlobalInit = FALSE; //ULONG BaseIoAddress; switch(channel) { @@ -1631,6 +1660,7 @@ AtapiChipInit( /* FALLTHROUGH */ case CHAN_NOT_SPECIFIED: c = CHAN_NOT_SPECIFIED; + GlobalInit = TRUE; break; default: //c = channel - deviceExtension->Channel; // logical channel (for Compatible Mode controllers) @@ -1669,6 +1699,27 @@ AtapiChipInit( } } + if((WinVer_Id() > WinVer_NT) && + GlobalInit && + deviceExtension->MasterDev) { + PCI_COMMON_CONFIG pciData; + ULONG busDataRead; + + KdPrint2((PRINT_PREFIX " re-enable IO resources of MasterDev\n" )); + + busDataRead = HalGetBusData + //ScsiPortGetBusData + ( + //HwDeviceExtension, + PCIConfiguration, SystemIoBusNumber, slotNumber, + &pciData, PCI_COMMON_HDR_LENGTH); + if(busDataRead == PCI_COMMON_HDR_LENGTH) { + UniataEnableIoPCI(SystemIoBusNumber, slotNumber, &pciData); + } else { + KdPrint2((PRINT_PREFIX " re-enable IO resources of MasterDev FAILED\n" )); + } + } + switch(VendorID) { // case ATA_ACARD_ID: // break; @@ -1778,8 +1829,16 @@ AtapiChipInit( KdPrint2((PRINT_PREFIX "Base init\n")); /* force all ports active "the legacy way" */ ChangePciConfig2(0x92, (a | 0x0f)); + + if(deviceExtension->BaseIoAddressSATA_0.Addr && (ChipFlags & ICH7)) { + /* Set SCRAE bit to enable registers access. */ + ChangePciConfig4(0x94, (a | (1 << 9))); + /* Set Ports Implemented register bits. */ + AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x0c, + AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x0c) | 0xff); + } /* enable PCI interrupt */ - ChangePciConfig2(/*PCIR_COMMAND*/0x04, (a & ~0x0400)); + ChangePciConfig2(offsetof(PCI_COMMON_CONFIG, Command), (a & ~0x0400)); } else { @@ -1867,7 +1926,7 @@ AtapiChipInit( break; } - if(deviceExtension->MaxTransferMode < ATA_UDMA2) + if(deviceExtension->MaxTransferMode <= ATA_UDMA2) break; // check 80-pin cable if(c == CHAN_NOT_SPECIFIED) { @@ -1875,7 +1934,12 @@ AtapiChipInit( } else { chan = &deviceExtension->chan[c]; GetPciConfig2(0x54, reg54); - if( ((reg54 >> (channel*2)) & 30) != 30) { + KdPrint2((PRINT_PREFIX " intel 80-pin check (reg54=%x)\n", reg54)); + if(reg54 == 0x0000 || reg54 == 0xffff) { + KdPrint2((PRINT_PREFIX " check failed (not supported)\n")); + } else + if( ((reg54 >> (channel*2)) & 30) == 0) { + KdPrint2((PRINT_PREFIX " intel 40-pin\n")); chan->MaxTransferMode = min(deviceExtension->MaxTransferMode, ATA_UDMA2); } } @@ -2179,7 +2243,7 @@ AtapiChipInit( // no init for SATA if(ChipFlags & (UNIATA_SATA | VIASATA)) { /* enable PCI interrupt */ - ChangePciConfig2(/*PCIR_COMMAND*/0x04, (a & ~0x0400)); + ChangePciConfig2(offsetof(PCI_COMMON_CONFIG, Command), (a & ~0x0400)); /* * vt6420/1 has problems talking to some drives. The following @@ -2238,6 +2302,8 @@ AtapiChipInit( // no init for SATA if(ChipFlags & (UNIATA_SATA | VIASATA)) { if((ChipFlags & VIABAR) && (c >= 2)) { + // this is PATA channel + chan->MaxTransferMode = ATA_UDMA5; break; } UniataSataWritePort4(chan, IDX_SATA_SError, 0xffffffff, 0); diff --git a/reactos/drivers/storage/ide/uniata/id_probe.cpp b/reactos/drivers/storage/ide/uniata/id_probe.cpp index 5a4336f6e30..1c01a29d28c 100644 --- a/reactos/drivers/storage/ide/uniata/id_probe.cpp +++ b/reactos/drivers/storage/ide/uniata/id_probe.cpp @@ -83,6 +83,50 @@ AtapiDoNothing(VOID) #endif //UNIATA_CORE +USHORT +NTAPI +UniataEnableIoPCI( + IN ULONG busNumber, + IN ULONG slotNumber, + IN OUT PPCI_COMMON_CONFIG pciData + ) +{ + ULONG i; + ULONG busDataRead; + + // Enable Busmastering, IO-space and Mem-space + KdPrint2((PRINT_PREFIX "Enabling Mem/Io spaces and busmastering...\n")); + KdPrint2((PRINT_PREFIX "Initial pciData.Command = %#x\n", pciData->Command)); + for(i=0; i<3; i++) { + switch(i) { + case 0: + KdPrint2((PRINT_PREFIX "PCI_ENABLE_IO_SPACE\n")); + pciData->Command |= PCI_ENABLE_IO_SPACE; + break; + case 1: + KdPrint2((PRINT_PREFIX "PCI_ENABLE_MEMORY_SPACE\n")); + pciData->Command |= PCI_ENABLE_MEMORY_SPACE; + break; + case 2: + KdPrint2((PRINT_PREFIX "PCI_ENABLE_BUS_MASTER\n")); + pciData->Command |= PCI_ENABLE_BUS_MASTER; + break; + } + HalSetBusDataByOffset( PCIConfiguration, busNumber, slotNumber, + &(pciData->Command), + offsetof(PCI_COMMON_CONFIG, Command), + sizeof(pciData->Command)); + KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData->u.type0.InterruptLine)); + + // reread config space + busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotNumber, + pciData, PCI_COMMON_HDR_LENGTH); + KdPrint2((PRINT_PREFIX "New pciData.Command = %#x\n", pciData->Command)); + } + KdPrint2((PRINT_PREFIX "Final pciData.Command = %#x\n", pciData->Command)); + return pciData->Command; +} // end UniataEnableIoPCI() + /* Get PCI address by ConfigInfo and RID */ @@ -329,7 +373,6 @@ UniataEnumBusMasterController__( SubVendorID = pciData.u.type0.SubVendorID; SubSystemID = pciData.u.type0.SubSystemID; - //KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass )); // check for (g_opt_VirtualMachine == VM_AUTO) is performed inside each @@ -367,6 +410,14 @@ UniataEnumBusMasterController__( found = FALSE; known = FALSE; + if(pciData.u.type0.InterruptPin == 14 || + pciData.u.type0.InterruptPin == 15 || + pciData.u.type0.InterruptLine == 14 || + pciData.u.type0.InterruptLine == 15) { + KdPrint2((PRINT_PREFIX "(!) InterruptPin = %#x\n", pciData.u.type0.InterruptPin)); + KdPrint2((PRINT_PREFIX "(!) InterruptLine = %#x\n", pciData.u.type0.InterruptLine)); + } + if(deviceExtension) { deviceExtension->slotNumber = slotData.u.AsULONG; deviceExtension->SystemIoBusNumber = busNumber; @@ -426,36 +477,7 @@ UniataEnumBusMasterController__( KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData.u.type0.InterruptLine)); if(!pass && known) { - // Enable Busmastering, IO-space and Mem-space - KdPrint2((PRINT_PREFIX "Enabling Mem/Io spaces and busmastering...\n")); - KdPrint2((PRINT_PREFIX "Initial pciData.Command = %#x\n", pciData.Command)); - for(i=0; i<3; i++) { - switch(i) { - case 0: - KdPrint2((PRINT_PREFIX "PCI_ENABLE_IO_SPACE\n")); - pciData.Command |= PCI_ENABLE_IO_SPACE; - break; - case 1: - KdPrint2((PRINT_PREFIX "PCI_ENABLE_MEMORY_SPACE\n")); - pciData.Command |= PCI_ENABLE_MEMORY_SPACE; - break; - case 2: - KdPrint2((PRINT_PREFIX "PCI_ENABLE_BUS_MASTER\n")); - pciData.Command |= PCI_ENABLE_BUS_MASTER; - break; - } - HalSetBusDataByOffset( PCIConfiguration, busNumber, slotData.u.AsULONG, - &(pciData.Command), - offsetof(PCI_COMMON_CONFIG, Command), - sizeof(pciData.Command)); - KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData.u.type0.InterruptLine)); - - // reread config space - busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotData.u.AsULONG, - &pciData, PCI_COMMON_HDR_LENGTH); - KdPrint2((PRINT_PREFIX "New pciData.Command = %#x\n", pciData.Command)); - } - KdPrint2((PRINT_PREFIX "Final pciData.Command = %#x\n", pciData.Command)); + UniataEnableIoPCI(busNumber, slotData.u.AsULONG, &pciData); } // validate Mem/Io ranges no_ranges = TRUE; @@ -1175,37 +1197,7 @@ UniataFindBusMasterController( deviceExtension->BusMaster = DMA_MODE_NONE; if(WinVer_WDM_Model && !deviceExtension->UnknownDev) { - ULONG i; - // Enable Busmastering, IO-space and Mem-space - KdPrint2((PRINT_PREFIX "Enabling Mem/Io spaces and busmastering...\n")); - KdPrint2((PRINT_PREFIX "Initial pciData.Command = %#x\n", pciData.Command)); - for(i=0; i<3; i++) { - switch(i) { - case 0: - KdPrint2((PRINT_PREFIX "PCI_ENABLE_IO_SPACE\n")); - pciData.Command |= PCI_ENABLE_IO_SPACE; - break; - case 1: - KdPrint2((PRINT_PREFIX "PCI_ENABLE_MEMORY_SPACE\n")); - pciData.Command |= PCI_ENABLE_MEMORY_SPACE; - break; - case 2: - KdPrint2((PRINT_PREFIX "PCI_ENABLE_BUS_MASTER\n")); - pciData.Command |= PCI_ENABLE_BUS_MASTER; - break; - } - HalSetBusDataByOffset( PCIConfiguration, SystemIoBusNumber, slotData.u.AsULONG, - &(pciData.Command), - offsetof(PCI_COMMON_CONFIG, Command), - sizeof(pciData.Command)); - KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData.u.type0.InterruptLine)); - - // reread config space - busDataRead = HalGetBusData(PCIConfiguration, SystemIoBusNumber, slotData.u.AsULONG, - &pciData, PCI_COMMON_HDR_LENGTH); - KdPrint2((PRINT_PREFIX "New pciData.Command = %#x\n", pciData.Command)); - } - KdPrint2((PRINT_PREFIX "Final pciData.Command = %#x\n", pciData.Command)); + UniataEnableIoPCI(ConfigInfo->SystemIoBusNumber, slotData.u.AsULONG, &pciData); } // validate Mem/Io ranges //no_ranges = TRUE; @@ -1364,6 +1356,7 @@ UniataFindBusMasterController( KdPrint2((PRINT_PREFIX "!MasterDev\n")); ConfigInfo->SlotNumber = slotNumber; ConfigInfo->SystemIoBusNumber = SystemIoBusNumber; + ConfigInfo->InterruptMode = LevelSensitive; /* primary and secondary channels share the same interrupt */ if(!ConfigInfo->BusInterruptVector || @@ -1394,8 +1387,13 @@ UniataFindBusMasterController( } if((WinVer_Id() > WinVer_2k) || (ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4) + sizeof(_ConfigInfo->w2k))) { - KdPrint2((PRINT_PREFIX "update ConfigInfo->w2k\n")); - _ConfigInfo->w2k.Dma64BitAddresses = 0; + KdPrint2((PRINT_PREFIX "update ConfigInfo->w2k: 64bit %d\n", + deviceExtension->Host64)); +#ifdef USE_OWN_DMA + // We need not set Dma64BitAddresses since we perform address translation manually. +#else + _ConfigInfo->w2k.Dma64BitAddresses = deviceExtension->Host64; +#endif //USE_OWN_DMA _ConfigInfo->w2k.ResetTargetSupported = TRUE; _ConfigInfo->w2k.MaximumNumberOfLogicalUnits = (UCHAR)deviceExtension->NumberLuns; } @@ -1411,20 +1409,32 @@ UniataFindBusMasterController( deviceExtension->AlignmentMask = ConfigInfo->AlignmentMask; deviceExtension->AdapterInterfaceType = PCIBus; + KdPrint2((PRINT_PREFIX "chan[%d] InterruptMode: %d, Level %d, Level2 %d, Vector %d, Vector2 %d\n", + channel, + ConfigInfo->InterruptMode, + ConfigInfo->BusInterruptLevel, + ConfigInfo->BusInterruptLevel2, + ConfigInfo->BusInterruptVector, + ConfigInfo->BusInterruptVector2 + )); + found = FALSE; if(deviceExtension->BusMaster) { KdPrint2((PRINT_PREFIX "Reconstruct ConfigInfo\n")); - ConfigInfo->MapBuffers = TRUE; #ifdef USE_OWN_DMA ConfigInfo->NeedPhysicalAddresses = FALSE; #else ConfigInfo->NeedPhysicalAddresses = TRUE; #endif //USE_OWN_DMA if(!MasterDev) { +//#ifdef USE_OWN_DMA +// KdPrint2((PRINT_PREFIX "!MasterDev, own DMA\n")); +//#else KdPrint2((PRINT_PREFIX "set Dma32BitAddresses\n")); ConfigInfo->Dma32BitAddresses = TRUE; +//#endif //USE_OWN_DMA } // thanks to Vitaliy Vorobyov aka deathsoft@yandex.ru for @@ -1451,9 +1461,10 @@ UniataFindBusMasterController( ConfigInfo->Master = TRUE; ConfigInfo->DmaWidth = Width16Bits; #endif //USE_OWN_DMA - ConfigInfo->CachesData = TRUE; ConfigInfo->ScatterGather = TRUE; } + ConfigInfo->MapBuffers = TRUE; // Need for PIO and OWN_DMA + ConfigInfo->CachesData = TRUE; KdPrint2((PRINT_PREFIX "BMList[i].channel %#x, NumberChannels %#x, channel %#x\n",BMList[i].channel, deviceExtension->NumberChannels, channel)); @@ -1486,14 +1497,6 @@ UniataFindBusMasterController( (*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeStart = ScsiPortConvertUlongToPhysicalAddress((channel ? IO_WD2 : IO_WD1) + ATA_ALTOFFSET); (*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeLength = ATA_ALTIOSIZE; - - // do not claim 2nd BM io-range for Secondary channel of - // Compatible-mode controllers - if(/*(WinVer_Id() <= WinVer_NT) &&*/ !c && channel == 1) { - KdPrint2((PRINT_PREFIX "cheat ScsiPort for 2nd channel, BM io-range\n")); - (*ConfigInfo->AccessRanges)[4].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0); - (*ConfigInfo->AccessRanges)[4].RangeLength = 0; - } } else if(AltInit && !(*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeStart.QuadPart && @@ -1552,8 +1555,8 @@ UniataFindBusMasterController( // Get the system physical address for this IO range. ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension, - PCIBus /*ConfigInfo->AdapterInterfaceType*/, - SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/, + MasterDev ? ConfigInfo->AdapterInterfaceType : PCIBus /*ConfigInfo->AdapterInterfaceType*/, + MasterDev ? ConfigInfo->SystemIoBusNumber : SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/, IoBasePort1, ATA_IOSIZE, TRUE); @@ -1577,8 +1580,8 @@ UniataFindBusMasterController( // Get the system physical address for the second IO range. ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension, - PCIBus /*ConfigInfo->AdapterInterfaceType*/, - SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/, + MasterDev ? ConfigInfo->AdapterInterfaceType : PCIBus /*ConfigInfo->AdapterInterfaceType*/, + MasterDev ? ConfigInfo->SystemIoBusNumber : SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/, IoBasePort2, ATA_ALTIOSIZE, TRUE); @@ -1744,12 +1747,12 @@ exit_findbm: KdPrint2((PRINT_PREFIX "MasterDev=%#x, NumberChannels=%#x, Isr2DevObj=%#x\n", MasterDev, deviceExtension->NumberChannels, BMList[i].Isr2DevObj)); - if(WinVer_WDM_Model && MasterDev) { - KdPrint2((PRINT_PREFIX "do not tell system, that we know about this:\n")); - if(BaseIoAddressBM_0) { + if(/*WinVer_WDM_Model &&*/ MasterDev) { + KdPrint2((PRINT_PREFIX "do not tell system, that we know about PCI IO ranges\n")); +/* if(BaseIoAddressBM_0) { ScsiPortFreeDeviceBase(HwDeviceExtension, BaseIoAddressBM_0); - } + }*/ (*ConfigInfo->AccessRanges)[4].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0); (*ConfigInfo->AccessRanges)[4].RangeLength = 0; (*ConfigInfo->AccessRanges)[5].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0); @@ -1761,6 +1764,17 @@ exit_findbm: found = FALSE; goto exit_findbm; } + + KdPrint2((PRINT_PREFIX "final chan[%d] InterruptMode: %d, Level %d, Level2 %d, Vector %d, Vector2 %d\n", + channel, + ConfigInfo->InterruptMode, + ConfigInfo->BusInterruptLevel, + ConfigInfo->BusInterruptLevel2, + ConfigInfo->BusInterruptVector, + ConfigInfo->BusInterruptVector2 + )); + + } #endif //UNIATA_CORE @@ -1790,331 +1804,78 @@ exit_notfound: /* This is for claiming PCI Busmaster in compatible mode under WDM OSes */ -ULONG +NTSTATUS NTAPI -UniataFindFakeBusMasterController( - IN PVOID HwDeviceExtension, - IN PVOID Context, - IN PVOID BusInformation, - IN PCHAR ArgumentString, - IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, - OUT PBOOLEAN Again +UniataClaimLegacyPCIIDE( + ULONG i ) { - PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; - //PHW_CHANNEL chan = NULL; - // this buffer must be global for UNIATA_CORE build - PCI_COMMON_CONFIG pciData; - - ULONG slotNumber; - ULONG busDataRead; - ULONG SystemIoBusNumber; - - UCHAR vendorString[5]; - UCHAR deviceString[5]; - PUCHAR vendorStrPtr; - PUCHAR deviceStrPtr; - - UCHAR BaseClass; - UCHAR SubClass; - ULONG VendorID; - ULONG DeviceID; - ULONG RevID; - ULONG dev_id; - PCI_SLOT_NUMBER slotData; - - ULONG i; -// PUCHAR ioSpace; -// UCHAR statusByte; - -// UCHAR tmp8; -// ULONG irq; - - BOOLEAN found = FALSE; - BOOLEAN MasterDev; - BOOLEAN simplexOnly = FALSE; - //BOOLEAN skip_find_dev = FALSE; - //BOOLEAN AltInit = FALSE; - - PIDE_BUSMASTER_REGISTERS BaseIoAddressBM_0 = NULL; - NTSTATUS status; - PPORT_CONFIGURATION_INFORMATION_COMMON _ConfigInfo = - (PPORT_CONFIGURATION_INFORMATION_COMMON)ConfigInfo; + PCM_RESOURCE_LIST resourceList; + UNICODE_STRING devname; - *Again = FALSE; + KdPrint2((PRINT_PREFIX "UniataClaimLegacyPCIIDE:\n")); - if(InDriverEntry) { - i = (ULONG)Context; - } else { - for(i=0; iSlotNumber && - BMList[i].busNumber == ConfigInfo->SystemIoBusNumber) { - break; - } - } - if(i >= BMListLen) { - KdPrint2((PRINT_PREFIX "unexpected device arrival => SP_RETURN_NOT_FOUND\n")); - goto exit_notfound; - } + if(BMList[i].PciIdeDevObj) { + KdPrint2((PRINT_PREFIX "Already initialized\n")); + return STATUS_UNSUCCESSFUL; } - KdPrint2((PRINT_PREFIX "UniataFindFakeBusMasterController (WDM)\n")); + RtlInitUnicodeString(&devname, L"\\Device\\uniata_PCIIDE"); + status = IoCreateDevice(SavedDriverObject, sizeof(PCIIDE_DEVICE_EXTENSION), + /*NULL*/ &devname, FILE_DEVICE_UNKNOWN, + 0, FALSE, &(BMList[i].PciIdeDevObj)); - if (!deviceExtension) { - KdPrint2((PRINT_PREFIX "!deviceExtension => SP_RETURN_ERROR\n")); - return SP_RETURN_ERROR; - } - RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION)); - - vendorStrPtr = vendorString; - deviceStrPtr = deviceString; - - slotNumber = BMList[i].slotNumber; - SystemIoBusNumber = BMList[i].busNumber; - - KdPrint2((PRINT_PREFIX "AdapterInterfaceType=%#x\n",ConfigInfo->AdapterInterfaceType)); - KdPrint2((PRINT_PREFIX "IoBusNumber=%#x\n",ConfigInfo->SystemIoBusNumber)); - KdPrint2((PRINT_PREFIX "slotNumber=%#x\n",slotNumber)); - - // this buffer must be global and already filled for UNIATA_CORE build - busDataRead = HalGetBusData( - //busDataRead = ScsiPortGetBusData(HwDeviceExtension, - PCIConfiguration, - SystemIoBusNumber, - slotNumber, - &pciData, - PCI_COMMON_HDR_LENGTH); - - if (busDataRead < PCI_COMMON_HDR_LENGTH) { - KdPrint2((PRINT_PREFIX "busDataRead < PCI_COMMON_HDR_LENGTH => SP_RETURN_ERROR\n")); - goto exit_error; + if(!NT_SUCCESS(status)) { + KdPrint2((PRINT_PREFIX "IoCreateDevice failed %#x\n", status)); + return status; } - KdPrint2((PRINT_PREFIX "busDataRead\n")); - if (pciData.VendorID == PCI_INVALID_VENDORID) { - KdPrint2((PRINT_PREFIX "PCI_INVALID_VENDORID\n")); - goto exit_error; + resourceList = (PCM_RESOURCE_LIST) ExAllocatePool(PagedPool, + sizeof(CM_RESOURCE_LIST)); + + if (!resourceList) { + KdPrint2((PRINT_PREFIX "!resourceList\n")); + status = STATUS_INSUFFICIENT_RESOURCES; +del_do: + IoDeleteDevice(BMList[i].PciIdeDevObj); + BMList[i].PciIdeDevObj = NULL; + return status; } - VendorID = pciData.VendorID; - DeviceID = pciData.DeviceID; - BaseClass = pciData.BaseClass; - SubClass = pciData.SubClass; - RevID = pciData.RevisionID; - dev_id = VendorID | (DeviceID << 16); - slotData.u.AsULONG = slotNumber; - KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass )); + RtlZeroMemory( + resourceList, + sizeof(CM_RESOURCE_LIST)); - deviceExtension->slotNumber = slotNumber; - deviceExtension->SystemIoBusNumber = SystemIoBusNumber; - deviceExtension->DevID = dev_id; - deviceExtension->RevID = RevID; - deviceExtension->NumberChannels = IDE_DEFAULT_MAX_CHAN; // default - deviceExtension->NumberLuns = IDE_MAX_LUN_PER_CHAN; // default - deviceExtension->DevIndex = i; + // IoReportDetectedDevice() should be used for WDM OSes - _snprintf(deviceExtension->Signature, sizeof(deviceExtension->Signature), - "UATA%8.8x/%1.1x@%8.8x", dev_id, 0xff, slotNumber); + resourceList->Count = 1; + resourceList->List[0].InterfaceType = PCIBus; + resourceList->List[0].BusNumber = BMList[i].busNumber; + // we do not report IO ranges since they are used/claimed by ISA part(s) + resourceList->List[0].PartialResourceList.Count = 0; - if(BaseClass != PCI_DEV_CLASS_STORAGE) { - KdPrint2((PRINT_PREFIX "BaseClass != PCI_DEV_CLASS_STORAGE => SP_RETURN_NOT_FOUND\n")); - goto exit_notfound; + RtlInitUnicodeString(&devname, L"PCIIDE"); + status = HalAssignSlotResources(&SavedRegPath, + &devname, + SavedDriverObject, + BMList[i].PciIdeDevObj, + PCIBus, + BMList[i].busNumber, + BMList[i].slotNumber, + &resourceList); + + if (!NT_SUCCESS(status)) { + KdPrint2((PRINT_PREFIX "HalAssignSlotResources failed %#x\n", status)); + ExFreePool(resourceList); + goto del_do; } - KdPrint2((PRINT_PREFIX "Storage Class\n")); + KdPrint2((PRINT_PREFIX "ok %#x\n", status)); + BMList[i].ChanInitOk |= 0x80; - // look for known chipsets - if(VendorID != BMList[i].nVendorId || - DeviceID != BMList[i].nDeviceId) { - KdPrint2((PRINT_PREFIX "device not suitable\n")); - goto exit_notfound; - } - - if((BMList[i].RaidFlags & UNIATA_RAID_CONTROLLER) && - SkipRaids) { - KdPrint2((PRINT_PREFIX "RAID support disabled\n")); - goto exit_notfound; - } - - if(!UniataCheckPCISubclass(FALSE, BMList[i].RaidFlags, SubClass)) { - KdPrint2((PRINT_PREFIX "Subclass not supported\n")); - goto exit_notfound; - } - - ConfigInfo->AlignmentMask = 0x00000003; - - status = UniataChipDetect(HwDeviceExtension, &pciData, i, ConfigInfo, &simplexOnly); - switch(status) { - case STATUS_SUCCESS: - found = TRUE; - break; - case STATUS_NOT_FOUND: - found = FALSE; - break; - default: - KdPrint2((PRINT_PREFIX "FAILED => SP_RETURN_ERROR\n")); - goto exit_error; - } - KdPrint2((PRINT_PREFIX "ForceSimplex = %d\n", simplexOnly)); - KdPrint2((PRINT_PREFIX "HwFlags = %x\n (0)", deviceExtension->HwFlags)); - switch(dev_id) { - /* additional checks for some supported chipsets */ - case 0xc6931080: - if (SubClass != PCI_DEV_SUBCLASS_IDE) { - KdPrint2((PRINT_PREFIX "0xc6931080, SubClass != PCI_DEV_SUBCLASS_IDE => found = FALSE\n")); - found = FALSE; - } else { - found = FALSE; - } - break; - - /* unknown chipsets, try generic DMA if it seems possible */ - default: - if (found) - break; - KdPrint2((PRINT_PREFIX "Default device\n")); - if(Ata_is_supported_dev(&pciData)) { - KdPrint2((PRINT_PREFIX "Ata_is_supported_dev\n")); - found = TRUE; - } else { - KdPrint2((PRINT_PREFIX "!Ata_is_supported_dev => found = FALSE\n")); - found = FALSE; - } - deviceExtension->UnknownDev = TRUE; - break; - } - - KdPrint2((PRINT_PREFIX "HwFlags = %x\n (1)", deviceExtension->HwFlags)); - if(!found) { - KdPrint2((PRINT_PREFIX "!found => SP_RETURN_NOT_FOUND\n")); - goto exit_notfound; - } - - KdPrint2((PRINT_PREFIX "HwFlags = %x\n (2)", deviceExtension->HwFlags)); - KdPrint2((PRINT_PREFIX "found suitable device\n")); - - /***********************************************************/ - /***********************************************************/ - /***********************************************************/ - - deviceExtension->UseDpc = TRUE; - KdPrint2((PRINT_PREFIX "HwFlags = %x\n (3)", deviceExtension->HwFlags)); - if(deviceExtension->HwFlags & UNIATA_NO_DPC) { - /* CMD 649, ROSB SWK33, ICH4 */ - KdPrint2((PRINT_PREFIX "UniataFindBusMasterController: UNIATA_NO_DPC (0)\n")); - deviceExtension->UseDpc = FALSE; - } - - MasterDev = IsMasterDev(&pciData); - - if(MasterDev) { - KdPrint2((PRINT_PREFIX "MasterDev\n")); - deviceExtension->MasterDev = TRUE; - deviceExtension->NumberChannels = 1; - } else { - KdPrint2((PRINT_PREFIX "!MasterDev => SP_RETURN_NOT_FOUND\n")); - goto exit_notfound; - } - - if(deviceExtension->AltRegMap) { - KdPrint2((PRINT_PREFIX " Non-standard registers layout => SP_RETURN_NOT_FOUND\n")); - goto exit_notfound; - } - if(IsBusMaster(&pciData)) { - KdPrint2((PRINT_PREFIX " !BusMaster => SP_RETURN_NOT_FOUND\n")); - goto exit_notfound; - } - - KdPrint2((PRINT_PREFIX "IsBusMaster == TRUE\n")); - BaseIoAddressBM_0 = (PIDE_BUSMASTER_REGISTERS) - (AtapiGetIoRange(HwDeviceExtension, ConfigInfo, &pciData, SystemIoBusNumber, - 4, 0, 0x10/*ATA_BMIOSIZE*/)/* - bm_offset*/); //range id - if(BaseIoAddressBM_0) { - UniataInitMapBM(deviceExtension, - BaseIoAddressBM_0, - (*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE); - deviceExtension->BusMaster = DMA_MODE_BM; - deviceExtension->BaseIoAddressBM_0.Addr = (ULONGIO_PTR)BaseIoAddressBM_0; - if((*ConfigInfo->AccessRanges)[4].RangeInMemory) { - deviceExtension->BaseIoAddressBM_0.MemIo = TRUE; - } - } - KdPrint2((PRINT_PREFIX " BusMasterAddress (base): %#x\n", BaseIoAddressBM_0)); - - /* - * the Cypress chip is a mess, it contains two ATA functions, but - * both channels are visible on the first one. - * simply ignore the second function for now, as the right - * solution (ignoring the second channel on the first function) - * doesn't work with the crappy ATA interrupt setup on the alpha. - */ - if (dev_id == 0xc6931080 && slotData.u.bits.FunctionNumber > 1) { - KdPrint2((PRINT_PREFIX "dev_id == 0xc6931080 && FunctionNumber > 1 => exit_findbm\n")); - goto exit_findbm; - } - - // Indicate number of buses. - ConfigInfo->NumberOfBuses = 0; - if(!ConfigInfo->InitiatorBusId[0]) { - ConfigInfo->InitiatorBusId[0] = (CHAR)(IoGetConfigurationInformation()->ScsiPortCount); - KdPrint2((PRINT_PREFIX "set ConfigInfo->InitiatorBusId[0] = %#x\n", ConfigInfo->InitiatorBusId[0])); - } - // Indicate four devices can be attached to the adapter - ConfigInfo->MaximumNumberOfTargets = 0; - - ConfigInfo->MultipleRequestPerLu = FALSE; - ConfigInfo->AutoRequestSense = FALSE; - ConfigInfo->TaggedQueuing = FALSE; - - if((WinVer_Id() >= WinVer_NT) || - (ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4))) { - _ConfigInfo->nt4.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); - _ConfigInfo->nt4.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION); - _ConfigInfo->nt4.SrbExtensionSize = sizeof(ATA_REQ); - } - if((WinVer_Id() > WinVer_2k) || - (ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4) + sizeof(_ConfigInfo->w2k))) { - _ConfigInfo->w2k.Dma64BitAddresses = 0; - _ConfigInfo->w2k.ResetTargetSupported = FALSE; - _ConfigInfo->w2k.MaximumNumberOfLogicalUnits = 0; - } - - // Save the Interrupe Mode for later use - deviceExtension->InterruptMode = ConfigInfo->InterruptMode; - deviceExtension->BusInterruptLevel = ConfigInfo->BusInterruptLevel; - deviceExtension->BusInterruptVector = ConfigInfo->BusInterruptVector; - deviceExtension->Channel = 0; - deviceExtension->DevIndex = i; - deviceExtension->OrigAdapterInterfaceType - = ConfigInfo->AdapterInterfaceType; - deviceExtension->AlignmentMask = ConfigInfo->AlignmentMask; - deviceExtension->AdapterInterfaceType = PCIBus; - - KdPrint2((PRINT_PREFIX "Reconstruct ConfigInfo\n")); - ConfigInfo->MapBuffers = TRUE; -#ifdef USE_OWN_DMA - ConfigInfo->NeedPhysicalAddresses = FALSE; -#else - ConfigInfo->NeedPhysicalAddresses = TRUE; -#endif //USE_OWN_DMA - -exit_findbm: - - KdPrint2((PRINT_PREFIX "return SP_RETURN_FOUND\n")); - //PrintNtConsole("return SP_RETURN_FOUND, de %#x, c0.lun0 %#x\n", deviceExtension, deviceExtension->chan[0].lun[0]); - - return SP_RETURN_FOUND; - -exit_error: - UniataFreeLunExt(deviceExtension); - return SP_RETURN_ERROR; - -exit_notfound: - UniataFreeLunExt(deviceExtension); - return SP_RETURN_NOT_FOUND; - -} // end UniataFindFakeBusMasterController() + return status; +} // end UniataClaimLegacyPCIIDE() /*++ @@ -2148,11 +1909,6 @@ UniataConnectIntr2( KdPrint2((PRINT_PREFIX "Init ISR:\n")); - if(BMList[i].Isr2DevObj) { - KdPrint2((PRINT_PREFIX "Already initialized %#x\n", BMList[i].Isr2DevObj)); - return STATUS_SUCCESS; - } - if(!deviceExtension->MasterDev && (deviceExtension->NumberChannels > 1) && // do not touch MasterDev !deviceExtension->simplexOnly && /* // this is unnecessary on simplex controllers !BMList[i].Isr2DevObj*/ // handle re-init under w2k+ @@ -2172,6 +1928,11 @@ UniataConnectIntr2( return STATUS_SUCCESS; } + if(BMList[i].Isr2DevObj) { + KdPrint2((PRINT_PREFIX "Already initialized [%d] %#x\n", i, BMList[i].Isr2DevObj)); + return STATUS_SUCCESS; + } + KdPrint2((PRINT_PREFIX "Create DO\n")); devname.Length = @@ -2188,7 +1949,7 @@ UniataConnectIntr2( 0, FALSE, &(BMList[i].Isr2DevObj)); if(!NT_SUCCESS(status)) { - KdPrint2((PRINT_PREFIX "IoCreateDevice failed %#x\n")); + KdPrint2((PRINT_PREFIX "IoCreateDevice failed %#x\n", status)); return status; } @@ -2907,6 +2668,10 @@ CheckDevice( } LunExt = chan->lun[deviceNumber]; + if(ResetDev) { + LunExt->PowerState = 0; + } + if(ResetDev && (deviceExtension->HwFlags & UNIATA_AHCI)) { KdPrint2((PRINT_PREFIX "CheckDevice: reset AHCI dev\n")); if(UniataAhciSoftReset(HwDeviceExtension, chan->lChannel, deviceNumber) == (ULONG)(-1)) { diff --git a/reactos/drivers/storage/ide/uniata/id_sata.cpp b/reactos/drivers/storage/ide/uniata/id_sata.cpp index 6f6c8ac5c8d..188019ba636 100644 --- a/reactos/drivers/storage/ide/uniata/id_sata.cpp +++ b/reactos/drivers/storage/ide/uniata/id_sata.cpp @@ -619,7 +619,26 @@ UniataAhciInit( UniataDumpAhciRegs(deviceExtension); #endif //DBG - /* reset AHCI controller */ + /* disable AHCI interrupts, for MSI compatibility issue + see http://www.intel.com/Assets/PDF/specupdate/307014.pdf + 26. AHCI Reset and MSI Request + */ + + KdPrint2((PRINT_PREFIX " get GHC\n")); + /* enable AHCI mode */ + GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + if(!(GHC & AHCI_GHC_AE)) { + KdPrint2((PRINT_PREFIX " enable AHCI mode, disable intr, GHC %#x\n", GHC)); + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, + (GHC | AHCI_GHC_AE) & ~AHCI_GHC_IE); + } else { + KdPrint2((PRINT_PREFIX " disable intr, GHC %#x\n", GHC)); + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, + GHC & ~AHCI_GHC_IE); + } + AtapiStallExecution(100); + + /* read GHC again and reset AHCI controller */ GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); KdPrint2((PRINT_PREFIX " reset AHCI controller, GHC %#x\n", GHC)); UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, @@ -638,12 +657,14 @@ UniataAhciInit( return FALSE; } - /* enable AHCI mode */ - GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); - KdPrint2((PRINT_PREFIX " enable AHCI mode, GHC %#x\n", GHC)); - UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, - GHC | AHCI_GHC_AE); + /* re-enable AHCI mode */ GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + if(!(GHC & AHCI_GHC_AE)) { + KdPrint2((PRINT_PREFIX " re-enable AHCI mode, GHC %#x\n", GHC)); + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, + GHC | AHCI_GHC_AE); + GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + } KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC)); if(!(GHC & AHCI_GHC_AE)) { KdPrint2((PRINT_PREFIX " Can't enable AHCI mode\n")); @@ -652,7 +673,6 @@ UniataAhciInit( deviceExtension->AHCI_CAP = CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); - PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); KdPrint2((PRINT_PREFIX " AHCI CAP %#x\n", CAP)); if(CAP & AHCI_CAP_S64A) { KdPrint2((PRINT_PREFIX " AHCI 64bit\n")); @@ -689,6 +709,8 @@ UniataAhciInit( KdPrint2((PRINT_PREFIX " chan %d, offs %#x\n", c, offs)); + chan->MaxTransferMode = deviceExtension->MaxTransferMode; + AtapiSetupLunPtrs(chan, deviceExtension, c); chan->BaseIoAHCI_Port = deviceExtension->BaseIoAHCI_0; @@ -719,6 +741,11 @@ UniataAhciInit( AtapiDmaAlloc(HwDeviceExtension, NULL, c); + if(!UniataAhciChanImplemented(deviceExtension, c)) { + KdPrint2((PRINT_PREFIX " chan %d not implemented\n", c)); + continue; + } + UniataAhciResume(chan); chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE; @@ -727,6 +754,35 @@ UniataAhciInit( return TRUE; } // end UniataAhciInit() +BOOLEAN +NTAPI +UniAtaAhciValidateVersion( + IN PHW_DEVICE_EXTENSION deviceExtension, + IN ULONG version, + IN BOOLEAN Strict + ) +{ + switch(version) { + case 0x00000000: + case 0xffffffff: + KdPrint((" wrong AHCI revision %#x\n", version)); + return FALSE; + case 0x00000905: + case 0x00010000: + case 0x00010100: + case 0x00010200: + case 0x00010300: + break; + default: + KdPrint2((PRINT_PREFIX " Unknown AHCI revision\n")); + if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"CheckAhciRevision", Strict)) { + KdPrint((" AHCI revision excluded\n")); + return FALSE; + } + } + return TRUE; +} // end UniAtaAhciValidateVersion() + BOOLEAN NTAPI UniataAhciDetect( @@ -743,12 +799,13 @@ UniataAhciDetect( ULONG PI; ULONG CAP; ULONG CAP2; - ULONG GHC; + ULONG GHC, GHC0; ULONG BOHC; ULONG NumberChannels; ULONG v_Mn, v_Mj; ULONG BaseMemAddress; - BOOLEAN MemIo; + BOOLEAN MemIo = FALSE; + BOOLEAN found = FALSE; KdPrint2((PRINT_PREFIX " UniataAhciDetect:\n")); @@ -762,7 +819,7 @@ UniataAhciDetect( KdPrint2((PRINT_PREFIX " AHCI init failed - no IoRange\n")); return FALSE; } - if(BaseMemAddress && (*ConfigInfo->AccessRanges)[5].RangeInMemory) { + if((*ConfigInfo->AccessRanges)[5].RangeInMemory) { KdPrint2((PRINT_PREFIX "MemIo\n")); MemIo = TRUE; } @@ -779,12 +836,29 @@ UniataAhciDetect( return FALSE; } - /* enable AHCI mode */ + /* check AHCI mode. Save state and try enable */ + GHC0 = GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); KdPrint2((PRINT_PREFIX " check AHCI mode, GHC %#x\n", GHC)); + + version = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_VS); + if(!(GHC & AHCI_GHC_AE)) { - KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE)\n")); - return FALSE; + KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE), check revision %#x\n", version)); + if(!UniAtaAhciValidateVersion(deviceExtension, version, FALSE)) { + KdPrint2((PRINT_PREFIX " Non-AHCI\n")); + goto exit_detect; + } + KdPrint2((PRINT_PREFIX " try enable\n")); + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, + (GHC | AHCI_GHC_AE) & ~AHCI_GHC_IE); + GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); + + KdPrint2((PRINT_PREFIX " re-check AHCI mode, GHC %#x\n", GHC)); + if(!(GHC & AHCI_GHC_AE)) { + KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE)\n")); + goto exit_detect; + } } CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); @@ -792,7 +866,7 @@ UniataAhciDetect( KdPrint2((PRINT_PREFIX " AHCI CAP %#x, CAP2 %#x\n", CAP, CAP2)); if(CAP & AHCI_CAP_S64A) { KdPrint2((PRINT_PREFIX " 64bit")); - //deviceExtension->Host64 = TRUE; + //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything } if(CAP2 & AHCI_CAP2_BOH) { BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC); @@ -811,6 +885,7 @@ UniataAhciDetect( /* get the number of HW channels */ PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); + deviceExtension->AHCI_PI = PI; KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI)); for(i=PI, n=0; i; n++, i=i>>1); NumberChannels = @@ -834,10 +909,10 @@ UniataAhciDetect( if(!NumberChannels) { KdPrint2((PRINT_PREFIX " Non-AHCI - NumberChannels=0\n")); - return FALSE; + found = FALSE; + goto exit_detect; } - version = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_VS); v_Mj = ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f); v_Mn = ((version >> 4) & 0xf0) + (version & 0x0f); @@ -862,19 +937,8 @@ UniataAhciDetect( deviceExtension->NumberLuns = 1; } - switch(version) { - case 0x00000905: - case 0x00010000: - case 0x00010100: - case 0x00010200: - case 0x00010300: - break; - default: - KdPrint2((PRINT_PREFIX " Unknown AHCI revision\n")); - if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"CheckAhciRevision", 1)) { - KdPrint((" AHCI revision excluded\n")); - return FALSE; - } + if(!UniAtaAhciValidateVersion(deviceExtension, version, TRUE)) { + goto exit_detect; } deviceExtension->HwFlags |= UNIATA_SATA | UNIATA_AHCI; @@ -887,7 +951,13 @@ UniataAhciDetect( deviceExtension->BusMaster = DMA_MODE_AHCI; deviceExtension->MaxTransferMode = max(deviceExtension->MaxTransferMode, ATA_SA150+(((CAP & AHCI_CAP_ISS_MASK) >> 20)-1) ); - return TRUE; + found = TRUE; + +exit_detect: + UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, GHC0); + KdPrint((" AHCI detect status %d\n", found)); + + return found; } // end UniataAhciDetect() UCHAR @@ -974,6 +1044,31 @@ UniataAhciStatus( } // end UniataAhciStatus() +VOID +NTAPI +UniataAhciSnapAtaRegs( + IN PHW_CHANNEL chan, + IN ULONG DeviceNumber, + IN OUT PIDEREGS_EX regs + ) +{ + ULONG TFD, SIG; + + regs->bDriveHeadReg = IDE_DRIVE_SELECT_1; + TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); + regs->bCommandReg = (UCHAR)(TFD & 0xff); + regs->bFeaturesReg = (UCHAR)((TFD >> 8) & 0xff); + + SIG = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG); + regs->bSectorCountReg = (UCHAR)(SIG & 0xff); + regs->bSectorNumberReg = (UCHAR)((SIG >> 8) & 0xff); + regs->bCylLowReg = (UCHAR)((SIG >> 16) & 0xff); + regs->bCylHighReg = (UCHAR)((SIG >> 24) & 0xff); + regs->bOpFlags = 0; + + return; +} // end UniataAhciSnapAtaRegs() + ULONG NTAPI UniataAhciSetupFIS_H2D( @@ -1083,6 +1178,99 @@ UniataAhciSetupFIS_H2D( return 20; } // end UniataAhciSetupFIS_H2D() +ULONG +NTAPI +UniataAhciSetupFIS_H2D_Direct( + IN PHW_DEVICE_EXTENSION deviceExtension, + IN ULONG DeviceNumber, + IN ULONG lChannel, + OUT PUCHAR fis, + IN PIDEREGS_EX regs + ) +{ + //ULONG i; + //PUCHAR plba; + BOOLEAN need48; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + UCHAR command; + + command = regs->bCommandReg; + + KdPrint2((PRINT_PREFIX " AHCI setup FIS Direct %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber)); + //i = 0; + //plba = (PUCHAR)&lba; + + RtlZeroMemory(fis, 20); + + fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */ + fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */ + fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 | + ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0); + fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT; + + // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command, + // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET + if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) && + */ + command == IDE_COMMAND_ATAPI_PACKET) { +/* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET; + if(feature & ATA_F_DMA) { + fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff); + } else { + fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff); + fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff; + }*/ + return 0; + //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT; + } else { + + need48 = (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) && + chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48; + + /* translate command into 48bit version */ + if(need48) { + if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { + command = AtaCommands48[command]; + } else { + KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n")); + return 0; + } + } + + fis[IDX_AHCI_o_Command] = command; + fis[IDX_AHCI_o_Feature] = regs->bFeaturesReg; + + fis[IDX_AHCI_o_BlockNumber] = regs->bSectorNumberReg; + fis[IDX_AHCI_o_CylinderLow] = regs->bCylLowReg; + fis[IDX_AHCI_o_CylinderHigh] = regs->bCylHighReg; + + fis[IDX_AHCI_o_BlockCount] = regs->bSectorCountReg; + + if(need48) { + //i++; + fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB; + + fis[IDX_AHCI_o_BlockNumberExp] = regs->bSectorNumberRegH; + fis[IDX_AHCI_o_CylinderLowExp] = regs->bCylLowRegH; + fis[IDX_AHCI_o_CylinderHighExp] = regs->bCylHighRegH; + + fis[IDX_AHCI_o_BlockCountExp] = regs->bSectorCountRegH; + + fis[IDX_AHCI_o_FeatureExp] = regs->bFeaturesRegH; + + chan->ChannelCtrlFlags |= CTRFLAGS_LBA48; + } else { + //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f); + chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48; + } + fis[IDX_AHCI_o_DriveSelect] |= regs->bDriveHeadReg & 0x0f; + } + + KdDump(fis, 20); + + return 20; +} // end UniataAhciSetupFIS_H2D_Direct() + UCHAR NTAPI UniataAhciWaitCommandReady( @@ -1304,6 +1492,116 @@ UniataAhciSendPIOCommand( } // end UniataAhciSendPIOCommand() +UCHAR +NTAPI +UniataAhciSendPIOCommandDirect( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, + IN ULONG DeviceNumber, + IN PSCSI_REQUEST_BLOCK Srb, + IN PIDEREGS_EX regs, + IN ULONG wait_flags, + IN ULONG timeout + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + UCHAR statusByte; + PATA_REQ AtaReq; + ULONG fis_size; + //ULONG tag=0; + //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); + PIDE_AHCI_CMD AHCI_CMD = NULL; + USHORT ahci_flags=0; +// USHORT bcount=0; + + //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); + + KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n", + deviceExtension->DevIndex, lChannel, DeviceNumber, Srb->DataBuffer, Srb->DataTransferLength, wait_flags )); + +// if(Srb->DataTransferLength/DEV_BSIZE != bcount) { +// KdPrint((" length/DEV_BSIZE != bcount\n")); +// } + +#ifdef DBG + //UniataDumpAhciPortRegs(chan); +#endif // DBG + + if(!Srb) { + KdPrint((" !Srb\n")); + return IDE_STATUS_WRONG; + //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup + //should be already called on init + } + AtaReq = (PATA_REQ)(Srb->SrbExtension); + //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq)); + + AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr; + if(!AHCI_CMD) { + KdPrint((" !AHCI_CMD\n")); + return IDE_STATUS_WRONG; + } + + if(Srb->DataTransferLength) { + if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { + ahci_flags |= ATA_AHCI_CMD_WRITE; + AtaReq->Flags &= ~REQ_FLAG_READ; + } else { + AtaReq->Flags |= REQ_FLAG_READ; + } + } + + fis_size = UniataAhciSetupFIS_H2D_Direct(deviceExtension, DeviceNumber, lChannel, + &(AHCI_CMD->cfis[0]), + regs); + + if(!fis_size) { + KdPrint2(("!fis_size\n")); + return IDE_STATUS_WRONG; + } + + //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n")); + ahci_flags = UniAtaAhciAdjustIoFlags(regs->bCommandReg, ahci_flags, fis_size, DeviceNumber); + KdPrint2(("ahci_flags %#x\n", ahci_flags)); + + if(Srb->DataTransferLength) { + if(!AtapiDmaSetup(HwDeviceExtension, + DeviceNumber, + lChannel, // logical channel, + Srb, + (PUCHAR)(Srb->DataBuffer), + Srb->DataTransferLength)) { + KdPrint2((" can't setup buffer\n")); + return IDE_STATUS_WRONG; + } + } + + AtaReq->ahci.io_cmd_flags = ahci_flags; + +#ifdef DBG + //UniataDumpAhciPortRegs(chan); +#endif // DBG + + UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); + +#ifdef DBG + //UniataDumpAhciPortRegs(chan); +#endif // DBG + + if(wait_flags == ATA_IMMEDIATE) { + statusByte = 0; + KdPrint2((" return imemdiately\n")); + } else { + statusByte = UniataAhciWaitCommandReady(chan, timeout); + UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber); + UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); + } + + return statusByte; + +} // end UniataAhciSendPIOCommandDirect() + BOOLEAN NTAPI UniataAhciAbortOperation( diff --git a/reactos/drivers/storage/ide/uniata/id_sata.h b/reactos/drivers/storage/ide/uniata/id_sata.h index 0d04f2aafaf..aa6665278ba 100644 --- a/reactos/drivers/storage/ide/uniata/id_sata.h +++ b/reactos/drivers/storage/ide/uniata/id_sata.h @@ -147,6 +147,14 @@ UniataAhciStatus( IN ULONG DeviceNumber ); +VOID +NTAPI +UniataAhciSnapAtaRegs( + IN PHW_CHANNEL chan, + IN ULONG DeviceNumber, + IN OUT PIDEREGS_EX regs + ); + ULONG NTAPI UniataAhciSetupFIS_H2D( @@ -195,6 +203,18 @@ UniataAhciSendPIOCommand( IN ULONG timeout ); +UCHAR +NTAPI +UniataAhciSendPIOCommandDirect( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, + IN ULONG DeviceNumber, + IN PSCSI_REQUEST_BLOCK Srb, + IN PIDEREGS_EX regs, + IN ULONG wait_flags, + IN ULONG timeout + ); + BOOLEAN NTAPI UniataAhciAbortOperation( @@ -387,4 +407,8 @@ BuildAhciInternalSrb ( IN ULONG Length = 0 ); +#define UniataAhciChanImplemented(deviceExtension, c) \ + (((deviceExtension)->AHCI_PI) & (1 << c)) + + #endif //__UNIATA_SATA__H__ diff --git a/reactos/drivers/storage/ide/uniata/inc/misc.h b/reactos/drivers/storage/ide/uniata/inc/misc.h index 0a9983050a1..94f406b3660 100644 --- a/reactos/drivers/storage/ide/uniata/inc/misc.h +++ b/reactos/drivers/storage/ide/uniata/inc/misc.h @@ -5,7 +5,7 @@ /* The definitions look so crappy, because the code doesn't care whether the source is an array or an integer */ -#define MOV_DD_SWP(a,b) ((a) = RtlUlongByteSwap(*(PULONG)&(b))) +#define MOV_DD_SWP(a,b) ( ((PULONG)&(a))[0] = RtlUlongByteSwap(*(PULONG)&(b))) #define MOV_DW_SWP(a,b) ( ((PUSHORT)&(a))[0] = RtlUshortByteSwap(*(PUSHORT)&(b))) #define MOV_SWP_DW2DD(a,b) ((a) = RtlUshortByteSwap(*(PUSHORT)&(b))) #define MOV_QD_SWP(a,b) { ((PULONG)&(a))[0] = RtlUlongByteSwap( ((PULONG)&(b))[1]); ((PULONG)&(a))[1] = RtlUlongByteSwap( ((PULONG)&(b))[0]); } diff --git a/reactos/drivers/storage/ide/uniata/scsi.h b/reactos/drivers/storage/ide/uniata/scsi.h index a93c1cb4fa1..3506cff3345 100644 --- a/reactos/drivers/storage/ide/uniata/scsi.h +++ b/reactos/drivers/storage/ide/uniata/scsi.h @@ -392,13 +392,22 @@ typedef union _CDB { UCHAR Immediate: 1; UCHAR Reserved1 : 4; UCHAR Lun : 3; - UCHAR Reserved2[2]; + UCHAR Reserved2; + UCHAR FormatLayerNumber : 2; + UCHAR Reserved2_2 : 6; UCHAR Start : 1; UCHAR LoadEject : 1; - UCHAR Reserved3 : 6; + UCHAR FL : 1; + UCHAR Reserved3 : 1; + UCHAR PowerConditions : 4; UCHAR Control; } START_STOP, *PSTART_STOP; +#define StartStop_Power_NoChg 0x00 +#define StartStop_Power_Idle 0x02 +#define StartStop_Power_Standby 0x03 +#define StartStop_Power_Sleep 0x05 + struct _MEDIA_REMOVAL { UCHAR OperationCode; UCHAR Reserved1 : 5; @@ -685,6 +694,14 @@ typedef union _CDB { UCHAR Control; } SET_READ_AHEAD, *PSET_READ_AHEAD; + struct _REPORT_LUNS { + UCHAR OperationCode; // 0xA0 - SCSIOP_REPORT_LUNS + UCHAR Reserved1[5]; + UCHAR AllocationLength[4]; + UCHAR Reserved2[1]; + UCHAR Control; + } REPORT_LUNS, *PREPORT_LUNS; + #define SendOpc_DoOpc 0x01 struct _SEND_OPC_INFO { @@ -901,6 +918,7 @@ typedef union _CDB { #define SCSIOP_SA_READ_CAPACITY16 0x10 +#define SCSIOP_REPORT_LUNS 0xA0 #define SCSIOP_BLANK 0xA1 #define SCSIOP_SEND_KEY 0xA3 #define SCSIOP_REPORT_KEY 0xA4 @@ -1393,6 +1411,9 @@ typedef struct _SENSE_DATA { #define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE ((FILE_DEVICE_SCSI << 16) + 0x0507) #define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES ((FILE_DEVICE_SCSI << 16) + 0x0508) #define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS ((FILE_DEVICE_SCSI << 16) + 0x0509) +#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE ((FILE_DEVICE_SCSI << 16) + 0x050a) +#define IOCTL_SCSI_MINIPORT_READ_SMART_LOG ((FILE_DEVICE_SCSI << 16) + 0x050b) +#define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG ((FILE_DEVICE_SCSI << 16) + 0x050c) // Read Capacity Data - returned in Big Endian format @@ -2902,6 +2923,12 @@ typedef struct _DVD_RPC_KEY { UCHAR Reserved2[1]; } DVD_RPC_KEY, * PDVD_RPC_KEY; +typedef struct _REPORT_LUNS_INFO_HDR { + UCHAR ListLength[4]; + UCHAR Reserved[4]; +} REPORT_LUNS_INFO_HDR, *PREPORT_LUNS_INFO_HDR; + + #pragma pack(pop) #endif //__CDRW_DEVICE_H__ diff --git a/reactos/drivers/storage/ide/uniata/todo.txt b/reactos/drivers/storage/ide/uniata/todo.txt index 1674c2f7885..677b348d438 100644 --- a/reactos/drivers/storage/ide/uniata/todo.txt +++ b/reactos/drivers/storage/ide/uniata/todo.txt @@ -251,4 +251,7 @@ 156.use http://www.winimage.com/readfi15.zip for performance checks 157.use IOCTL_SCSI_MINIPORT_IDENTIFY in atactl.exe to determine ... PIO/DMA when no uniata.sys is installed (+++) -158. +158.implement .INF generator +159.fix bug with invalid INF section under XP+ (43e2) +160.add INF handler for SCSI\NET\VEN_UNIATA&PROD_MANAGEMENT_PORT +161. \ No newline at end of file diff --git a/reactos/drivers/storage/ide/uniata/uata_ctl.h b/reactos/drivers/storage/ide/uniata/uata_ctl.h index 9a2ccce4714..c3e671edcbe 100644 --- a/reactos/drivers/storage/ide/uniata/uata_ctl.h +++ b/reactos/drivers/storage/ide/uniata/uata_ctl.h @@ -204,8 +204,14 @@ typedef struct _ATA_PASS_THROUGH_DIRECT { ULONG TimeOutValue; ULONG ReservedAsUlong; PVOID DataBuffer; - UCHAR PreviousTaskFile[8]; - UCHAR CurrentTaskFile[8]; + union { + UCHAR PreviousTaskFile[8]; + IDEREGS Regs; + }; + union { + UCHAR CurrentTaskFile[8]; + IDEREGS RegsH; + }; } ATA_PASS_THROUGH_DIRECT, *PATA_PASS_THROUGH_DIRECT; #define ATA_FLAGS_DRDY_REQUIRED 0x01 // Wait for DRDY status from the device before sending the command to the device. @@ -214,6 +220,8 @@ typedef struct _ATA_PASS_THROUGH_DIRECT { #define ATA_FLAGS_48BIT_COMMAND 0x08 // The ATA command to be send uses the 48 bit LBA feature set. // When this flag is set, the contents of the PreviousTaskFile member in the // ATA_PASS_THROUGH_DIRECT structure should be valid. +#define ATA_FLAGS_USE_DMA 0x10 // Set the transfer mode to DMA. +#define ATA_FLAGS_NO_MULTIPLE 0x20 // Read single sector only. #endif //ATA_FLAGS_DRDY_REQUIRED @@ -221,13 +229,19 @@ typedef struct _ATA_PASS_THROUGH_DIRECT { #pragma pack(push, 1) typedef struct _IDEREGS_EX { - UCHAR bFeaturesReg; // Used for specifying SMART "commands". + union { + UCHAR bFeaturesReg; // Used for specifying SMART "commands" on input. + UCHAR bErrorReg; // Error on output. + }; UCHAR bSectorCountReg; // IDE sector count register UCHAR bSectorNumberReg; // IDE sector number register UCHAR bCylLowReg; // IDE low order cylinder value UCHAR bCylHighReg; // IDE high order cylinder value UCHAR bDriveHeadReg; // IDE drive/head register + union { UCHAR bCommandReg; // Actual IDE command. + UCHAR bStatusReg; // Status register. + }; UCHAR bOpFlags; // 00 - send // 01 - read regs // 08 - lba48 @@ -236,9 +250,12 @@ typedef struct _IDEREGS_EX { #define UNIATA_SPTI_EX_SND 0x00 #define UNIATA_SPTI_EX_RCV 0x01 #define UNIATA_SPTI_EX_LBA48 0x08 -#define UNIATA_SPTI_EX_SPEC_TO 0x10 +//#define UNIATA_SPTI_EX_SPEC_TO 0x10 //#define UNIATA_SPTI_EX_FREEZE_TO 0x20 // do not reset device on timeout and keep interrupts disabled -#define UNIATA_SPTI_EX_USE_DMA 0x20 // Force DMA transfer mode +#define UNIATA_SPTI_EX_USE_DMA 0x10 // Force DMA transfer mode + +// use 'invalid' combination to specify special TO options +#define UNIATA_SPTI_EX_SPEC_TO (ATA_FLAGS_DATA_OUT | ATA_FLAGS_DATA_IN) UCHAR bFeaturesRegH; // feature (high part for LBA48 mode) UCHAR bSectorCountRegH; // IDE sector count register (high part for LBA48 mode) @@ -288,6 +305,19 @@ typedef struct _UNIATA_CTL { }; } UNIATA_CTL, *PUNIATA_CTL; +typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS { + SCSI_PASS_THROUGH spt; + ULONG Filler; // realign buffers to double word boundary + UCHAR ucSenseBuf[32]; + UCHAR ucDataBuf[512]; // recommended minimum +} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; + +typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER { + SCSI_PASS_THROUGH_DIRECT sptd; + ULONG Filler; // realign buffer to double word boundary + UCHAR ucSenseBuf[32]; +} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; + #endif //UNIATA_CORE #ifdef __cplusplus diff --git a/reactos/drivers/storage/ide/uniata/uniata_ver.h b/reactos/drivers/storage/ide/uniata/uniata_ver.h index 087b1610e24..9c3b5b34604 100644 --- a/reactos/drivers/storage/ide/uniata/uniata_ver.h +++ b/reactos/drivers/storage/ide/uniata/uniata_ver.h @@ -1,10 +1,10 @@ -#define UNIATA_VER_STR "42i2" -#define UNIATA_VER_DOT 0.42.9.2 +#define UNIATA_VER_STR "43f5" +#define UNIATA_VER_DOT 0.43.6.5 #define UNIATA_VER_MJ 0 -#define UNIATA_VER_MN 42 -#define UNIATA_VER_SUB_MJ 9 -#define UNIATA_VER_SUB_MN 2 -#define UNIATA_VER_DOT_COMMA 0,42,9,2 -#define UNIATA_VER_DOT_STR "0.42.9.2" +#define UNIATA_VER_MN 43 +#define UNIATA_VER_SUB_MJ 6 +#define UNIATA_VER_SUB_MN 5 +#define UNIATA_VER_DOT_COMMA 0,43,6,5 +#define UNIATA_VER_DOT_STR "0.43.6.5" #define UNIATA_VER_YEAR 2012 #define UNIATA_VER_YEAR_STR "2012"