[UNIATA] [ATACTL]
authorAmine Khaldi <amine.khaldi@reactos.org>
Mon, 13 Aug 2012 16:25:08 +0000 (16:25 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Mon, 13 Aug 2012 16:25:08 +0000 (16:25 +0000)
* Sync to 0.43a1.
See issue #7237 for more details.

svn path=/trunk/; revision=57072

reactos/base/applications/atactl/atactl.cpp
reactos/drivers/storage/ide/uniata/atapi.h
reactos/drivers/storage/ide/uniata/bm_devs.h
reactos/drivers/storage/ide/uniata/bsmaster.h
reactos/drivers/storage/ide/uniata/id_ata.cpp
reactos/drivers/storage/ide/uniata/id_dma.cpp
reactos/drivers/storage/ide/uniata/id_init.cpp
reactos/drivers/storage/ide/uniata/id_sata.cpp
reactos/drivers/storage/ide/uniata/uata_ctl.h

index 113945e..69ea2f9 100644 (file)
@@ -37,6 +37,7 @@ int g_extended = 0;
 int g_adapter_info = 0;
 char* g_bb_list = NULL;
 int gRadix = 16;
+PADAPTERINFO g_AdapterInfo = NULL;
 
 void print_help() {
     printf("Usage:\n"
@@ -262,6 +263,14 @@ ata_send_ioctl(
         AtaCtl->addr.Length = sizeof(AtaCtl->addr);
     }
 
+    if(outBufferLength) {
+        if(addr) {
+            memset(&AtaCtl->RawData, 0, outBufferLength);
+        } else {
+            memset(&AtaCtl->addr, 0, outBufferLength);
+        }
+    }
+
     if(inBuffer && inBufferLength) {
         if(addr) {
             memcpy(&AtaCtl->RawData, inBuffer, inBufferLength);
@@ -298,80 +307,17 @@ ata_send_ioctl(
 IO_SCSI_CAPABILITIES g_capabilities;
 UCHAR g_inquiry_buffer[2048];
 
-int
-ata_is_sata(
-    PIDENTIFY_DATA ident
-    )
-{
-    return (ident->SataEnable && ident->SataEnable != 0xffff);
-}
-
-int
-ata_cur_mode_from_ident(
-    PIDENTIFY_DATA ident
-    )
-{
-    if(ata_is_sata(ident)) {
-        return ATA_SA150-1;
-    }
-
-    if (ident->UdmaModesValid) {
-        if (ident->UltraDMAActive & 0x40)
-            return ATA_UDMA0+6;
-        if (ident->UltraDMAActive & 0x20)
-            return ATA_UDMA0+5;
-        if (ident->UltraDMAActive & 0x10)
-            return ATA_UDMA0+4;
-        if (ident->UltraDMAActive & 0x08)
-            return ATA_UDMA0+3;
-        if (ident->UltraDMAActive & 0x04)
-            return ATA_UDMA0+2;
-        if (ident->UltraDMAActive & 0x02)
-            return ATA_UDMA0+1;
-        if (ident->UltraDMAActive & 0x01)
-            return ATA_UDMA0+0;
-    }
-
-    if (ident->MultiWordDMAActive & 0x04)
-        return ATA_WDMA0+2;
-    if (ident->MultiWordDMAActive & 0x02)
-        return ATA_WDMA0+1;
-    if (ident->MultiWordDMAActive & 0x01)
-        return ATA_WDMA0+0;
-
-    if (ident->SingleWordDMAActive & 0x04)
-        return ATA_SDMA0+2;
-    if (ident->SingleWordDMAActive & 0x02)
-        return ATA_SDMA0+1;
-    if (ident->SingleWordDMAActive & 0x01)
-        return ATA_SDMA0+0;
-
-    if (ident->PioTimingsValid) {
-        if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
-            return ATA_PIO0+5;
-        if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
-            return ATA_PIO0+4;
-        if (ident->AdvancedPIOModes & AdvancedPIOModes_3) 
-            return ATA_PIO0+3;
-    }        
-    if (ident->PioCycleTimingMode == 2)
-        return ATA_PIO0+2;
-    if (ident->PioCycleTimingMode == 1)
-        return ATA_PIO0+1;
-    if (ident->PioCycleTimingMode == 0)
-        return ATA_PIO0+0;
-
-    return ATA_PIO;
-} // end ata_cur_mode_from_ident()
-
 void
 ata_mode_to_str(
     char* str,
     int mode
     )
 {
-    if(mode == ATA_SA150-1) {
-        sprintf(str, "SATA");
+    if(mode > ATA_SA600) {
+        sprintf(str, "SATA-600+");
+    } else
+    if(mode >= ATA_SA600) {
+        sprintf(str, "SATA-600");
     } else
     if(mode >= ATA_SA300) {
         sprintf(str, "SATA-300");
@@ -413,6 +359,12 @@ ata_str_to_mode(
     int mode;
     int len;
 
+    if(!_stricmp(str, "SATA600"))
+        return ATA_SA600;
+    if(!_stricmp(str, "SATA300"))
+        return ATA_SA300;
+    if(!_stricmp(str, "SATA150"))
+        return ATA_SA150;
     if(!_stricmp(str, "SATA"))
         return ATA_SA150;
 
@@ -620,10 +572,34 @@ ata_check_unit(
         return FALSE;
     }
 
+    // Note: adapterInfo->NumberOfBuses is 1 greater than g_AdapterInfo->NumberChannels
+    // because of virtual communication port
     adapterInfo = (PSCSI_ADAPTER_BUS_INFO)g_inquiry_buffer;
-    for (i = 0; i < adapterInfo->NumberOfBuses; i++) {
+    for (i = 0; i+1 < adapterInfo->NumberOfBuses; i++) {
         inquiryData = (PSCSI_INQUIRY_DATA) (g_inquiry_buffer +
             adapterInfo->BusData[i].InquiryDataOffset);
+
+        if(g_extended && g_AdapterInfo && g_AdapterInfo->ChanHeaderLengthValid &&
+              g_AdapterInfo->NumberChannels < i) {
+            PCHANINFO ChanInfo;
+
+            ChanInfo = (PCHANINFO)
+                         (((PCHAR)g_AdapterInfo)+
+                            sizeof(ADAPTERINFO)+
+                            g_AdapterInfo->ChanHeaderLength*i);
+
+            io_mode = ChanInfo->MaxTransferMode;
+            if(io_mode != -1) {
+                ata_mode_to_str(mode_str, io_mode);
+            } else {
+                mode_str[0] = 0;
+            }
+            printf(" b%u [%s]\n",
+                i,
+                mode_str
+                );
+        }
+
         while (adapterInfo->BusData[i].InquiryDataOffset) {
             /*
             if(dev_id/adapterInfo->BusData[i].NumberOfLogicalUnits ==
@@ -641,7 +617,7 @@ ata_check_unit(
             
             if(l_dev_id == dev_id || dev_id == -1) {
 
-                if(!memcmp(&inquiryData->InquiryData[8], UNIATA_COMM_PORT_VENDOR_STR, 24)) {
+                if(!memcmp(&(inquiryData->InquiryData[8]), UNIATA_COMM_PORT_VENDOR_STR, 24)) {
                     // skip communication port
                     goto next_dev;
                 }
@@ -651,7 +627,7 @@ ata_check_unit(
                 if(inquiryData->Lun) {
                     sprintf(lun_str, ":l%d", inquiryData->Lun);
                 } else {
-                    sprintf(lun_str, "  ", inquiryData->Lun);
+                    sprintf(lun_str, "  ");
                 }
 
 
@@ -665,14 +641,17 @@ ata_check_unit(
                 addr.PathId   = inquiryData->PathId;
                 addr.TargetId = inquiryData->TargetId;
                 addr.Lun      = inquiryData->Lun;
-                status = ata_send_ioctl(h, &addr, "-UNIATA-",
+                status = ata_send_ioctl(h, &addr, (PCHAR)"-UNIATA-",
                                         IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE,
                                         NULL, 0,
                                         &IoMode, sizeof(IoMode),
                                         &returned);
                 if(status) {
                     //io_mode = min(IoMode.CurrentMode, IoMode.MaxMode);
-                    io_mode = min(max(IoMode.CurrentMode,IoMode.OrigMode),IoMode.MaxMode);
+                    io_mode = IoMode.PhyMode;
+                    if(!io_mode) {
+                        io_mode = min(max(IoMode.CurrentMode,IoMode.OrigMode),IoMode.MaxMode);
+                    }
                 } else {
                     io_mode = -1;
                 }
@@ -684,7 +663,7 @@ ata_check_unit(
                 // probably, we shall change this in future to support SATA splitters
                 pin.bDriveNumber = inquiryData->PathId*2+inquiryData->TargetId;
 
-                status = ata_send_ioctl(h, NULL, "SCSIDISK",
+                status = ata_send_ioctl(h, NULL, (PCHAR)"SCSIDISK",
                                         IOCTL_SCSI_MINIPORT_IDENTIFY,
                                         &pin, sizeof(pin),
                                         buff, sizeof(buff),
@@ -698,7 +677,7 @@ ata_check_unit(
                     // probably, we shall change this in future to support SATA splitters
                     pin.bDriveNumber = inquiryData->PathId*2+inquiryData->TargetId;
 
-                    status = ata_send_ioctl(h, NULL, "SCSIDISK",
+                    status = ata_send_ioctl(h, NULL, (PCHAR)"SCSIDISK",
                                             IOCTL_SCSI_MINIPORT_IDENTIFY,
                                             &pin, sizeof(pin),
                                             buff, sizeof(buff),
@@ -708,7 +687,7 @@ ata_check_unit(
 
                 if(status) {
                     if(!g_extended) {
-                        printf("  b%d:d%d%s    %24.24s %4.4s ",
+                        printf("  b%u:d%d%s    %24.24s %4.4s ",
                             i,
                             inquiryData->TargetId,
                             lun_str,
@@ -717,7 +696,7 @@ ata_check_unit(
                             (g_extended ? (PUCHAR)"" : &inquiryData->InquiryData[8+24])
                             );
                     } else {
-                        printf("  b%d:d%d%s ",
+                        printf("  b%u:d%d%s ",
                             i,
                             inquiryData->TargetId,
                             lun_str
@@ -806,27 +785,27 @@ ata_check_unit(
 
                     if(BlockMode_valid) {
                         if(ident->MaximumBlockTransfer) {
-                            printf("    Multi-block mode:        %d block%s\n", ident->MaximumBlockTransfer, ident->MaximumBlockTransfer == 1 ? "" : "s");
+                            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:                   %d/%d/%d \n", chs[0], chs[1], chs[2]);
-                        printf("    LBA:                     %d \n", max_lba);
+                        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:                    %d kb\n", max_lba/2);
+                            printf("    Size:                    %u kb\n", max_lba/2);
                         } else
                         if(max_lba < 2*1024*1024) {
-                            printf("    Size:                    %d Mb\n", max_lba/2048);
+                            printf("    Size:                    %u Mb\n", max_lba/2048);
                         } else
                         if(max_lba < (ULONG)2*1024*1024*1024) {
-                            printf("    Size:                    %d.%d (%d) Gb\n", (ULONG)(max_lba/2048/1024),
+                            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:                    %d.%d (%d) Tb\n", (ULONG)(max_lba/2048/1024/1024),
+                            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)
                             );
@@ -868,11 +847,13 @@ ata_adapter_info(
 {
     char dev_name[64];
     HANDLE h;
-    ADAPTERINFO AdapterInfo;
+    PADAPTERINFO AdapterInfo;
     ULONG status;
     ULONG returned;
     SCSI_ADDRESS addr;
     PCI_SLOT_NUMBER       slotData;
+    char mode_str[12];
+    ULONG len;
 
     sprintf(dev_name, "\\\\.\\Scsi%d:", bus_id);
     h = ata_open_dev(dev_name);
@@ -880,35 +861,52 @@ ata_adapter_info(
         return FALSE;
     addr.PortNumber = bus_id;
 
-    memset(&AdapterInfo, 0, sizeof(AdapterInfo));
+    len = sizeof(ADAPTERINFO)+sizeof(CHANINFO)*AHCI_MAX_PORT;
+    if(!g_AdapterInfo) {
+        AdapterInfo = (PADAPTERINFO)GlobalAlloc(GMEM_FIXED, len);
+        if(!AdapterInfo) {
+            return FALSE;
+        }
+    } else {
+        AdapterInfo = g_AdapterInfo; 
+    }
+    memset(AdapterInfo, 0, len);
 
-    status = ata_send_ioctl(h, &addr, "-UNIATA-",
+    status = ata_send_ioctl(h, &addr, (PCHAR)"-UNIATA-",
                             IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO,
-                            &AdapterInfo, sizeof(AdapterInfo),
-                            &AdapterInfo, sizeof(AdapterInfo),
+                            AdapterInfo, len,
+                            AdapterInfo, len,
                             &returned);
-    printf("Scsi%d: %s\n", bus_id, status ? "[UniATA]" : "");
+    if(status) {
+        ata_mode_to_str(mode_str, AdapterInfo->MaxTransferMode);
+    }
+    printf("Scsi%d: %s     %s\n", bus_id, status ? "[UniATA]" : "", status ? mode_str : "");
     if(print_info) {
         if(!status) {
             printf("Can't get adapter info\n");
         } else {
-            if(AdapterInfo.AdapterInterfaceType == PCIBus) {
-                slotData.u.AsULONG = AdapterInfo.slotNumber;
-                printf("  PCI Bus/Dev/Func:   %d/%d/%d%s\n",
-                    AdapterInfo.SystemIoBusNumber, slotData.u.bits.DeviceNumber, slotData.u.bits.FunctionNumber,
-                    AdapterInfo.AdapterInterfaceType == AdapterInfo.OrigAdapterInterfaceType ? "" : " (ISA-Bridged)");
-                printf("  VendorId/DevId/Rev: %#04x/%#04x/%#02x\n", AdapterInfo.DevID >> 16, AdapterInfo.DevID & 0xffff, AdapterInfo.RevID);
-                if(AdapterInfo.DeviceName[0]) {
-                    printf("  Name:               %s\n", AdapterInfo.DeviceName);
+            if(AdapterInfo->AdapterInterfaceType == PCIBus) {
+                slotData.u.AsULONG = AdapterInfo->slotNumber;
+                printf("  PCI Bus/Dev/Func:   %u/%u/%u%s\n",
+                    AdapterInfo->SystemIoBusNumber, slotData.u.bits.DeviceNumber, slotData.u.bits.FunctionNumber,
+                    AdapterInfo->AdapterInterfaceType == AdapterInfo->OrigAdapterInterfaceType ? "" : " (ISA-Bridged)");
+                printf("  VendorId/DevId/Rev: %#04x/%#04x/%#02x\n",
+                    (USHORT)(AdapterInfo->DevID >> 16),
+                    (USHORT)(AdapterInfo->DevID & 0xffff),
+                    (UCHAR)(AdapterInfo->RevID));
+                if(AdapterInfo->DeviceName[0]) {
+                    printf("  Name:               %s\n", AdapterInfo->DeviceName);
                 }
             } else
-            if(AdapterInfo.AdapterInterfaceType == Isa) {
+            if(AdapterInfo->AdapterInterfaceType == Isa) {
                 printf("  ISA Bus\n");
             }
-            printf("  IRQ: %d\n", AdapterInfo.BusInterruptLevel);
+            printf("  IRQ: %d\n", AdapterInfo->BusInterruptLevel);
         }
     }
     ata_close_dev(h);
+    //GlobalFree(AdapterInfo);
+    g_AdapterInfo = AdapterInfo;
     return status ? TRUE : FALSE;
 } // end ata_adapter_info()
 
@@ -996,7 +994,7 @@ ata_mode(
 //    IoMode.ApplyImmediately = TRUE;
     IoMode.OrigMode = mode;
 
-    status = ata_send_ioctl(h, &addr, "-UNIATA-",
+    status = ata_send_ioctl(h, &addr, (PCHAR)"-UNIATA-",
                             IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE,
                             &IoMode, sizeof(IoMode),
                             NULL, 0,
@@ -1094,7 +1092,7 @@ ata_hide(
     if(lock) {
         printf("ATTENTION: you have %d seconds to disconnect cable\n", lock);
     }
-    status = ata_send_ioctl(h, &addr, "-UNIATA-",
+    status = ata_send_ioctl(h, &addr, (PCHAR)"-UNIATA-",
                             IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE,
                             &to, sizeof(to),
                             NULL, 0,
@@ -1144,7 +1142,7 @@ ata_scan(
         if(lock) {
             printf("You have %d seconds to connect device.\n", lock);
         }
-        status = ata_send_ioctl(h, &addr, "-UNIATA-",
+        status = ata_send_ioctl(h, &addr, (PCHAR)"-UNIATA-",
                                 IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES,
                                 &to, sizeof(to),
                                 NULL, 0,
@@ -1233,12 +1231,12 @@ ata_bblk(
         print_help();
         return FALSE;
     }
-    if((dev_id >> 16) & 0xff == 0xff) {
+    if(((dev_id >> 16) & 0xff) == 0xff) {
         printf("\nERROR: Target device bus number (channel) must be specified with b:<bus id>\n\n");
         print_help();
         return FALSE;
     }
-    if((dev_id >> 8) & 0xff == 0xff) {
+    if(((dev_id >> 8) & 0xff) == 0xff) {
         printf("\nERROR: Target device ID must be specified with d:<device id>\n\n");
         print_help();
         return FALSE;
@@ -1289,7 +1287,7 @@ ata_bblk(
         addr.TargetId = (UCHAR)(dev_id >> 8);
         addr.Lun      = (UCHAR)(dev_id);
 
-        status = ata_send_ioctl(h, &addr, "-UNIATA-",
+        status = ata_send_ioctl(h, &addr, (PCHAR)"-UNIATA-",
                                 IOCTL_SCSI_MINIPORT_UNIATA_RESETBB,
                                 NULL, 0,
                                 NULL, 0,
@@ -1355,7 +1353,7 @@ ata_bblk(
             }
             k = k0;
             if(radix == 10) {
-                b = sscanf(BB_Msg+k, "%I64d\t%I64d", &tmp_bb_lba, &tmp_bb_len);
+                b = sscanf(BB_Msg+k, "%I64u\t%I64u", &tmp_bb_lba, &tmp_bb_len);
             } else {
                 b = sscanf(BB_Msg+k, "%I64x\t%I64x", &tmp_bb_lba, &tmp_bb_len);
             }
@@ -1464,7 +1462,7 @@ ata_bblk(
         while(len >= sizeof(LONGLONG)*2) {
             tmp_bb_lba = ((LONGLONG*)bblist)[i*2+0];
             tmp_bb_len = ((LONGLONG*)bblist)[i*2+1] - tmp_bb_lba;
-            b = sprintf(BB_Msg, "%I64x\t%I64x\n", tmp_bb_lba, tmp_bb_len);
+            b = sprintf(BB_Msg, "%I64u\t%I64u\n", tmp_bb_lba, tmp_bb_len);
             WriteFile(hf, BB_Msg, b, &returned, NULL);
             i++;
             len -= sizeof(LONGLONG)*2;
@@ -1511,7 +1509,7 @@ main (
     int persistent_hide=0;
 
     printf("Console ATA control utility for Windows NT3.51/NT4/2000/XP/2003\n"
-           "Version 0." UNIATA_VER_STR ", Copyright (c) Alexander A. Telyatnikov, 2003-2008\n"
+           "Version 0." UNIATA_VER_STR ", Copyright (c) Alexander A. Telyatnikov, 2003-2012\n"
            "Home site: http://alter.org.ua\n");
 
     for(i=1; i<argc; i++) {
@@ -1633,7 +1631,7 @@ main (
                 j = strlen(argv[i])-1;
                 break;
             case 'd' :
-                if(cmd && cmd != CMD_ATA_FIND && cmd != CMD_ATA_HIDE) {
+                if(cmd && (cmd != CMD_ATA_FIND) && (cmd != CMD_ATA_HIDE)) {
                     print_help();
                 }
                 i++;
@@ -1680,12 +1678,12 @@ main (
         d_dev = 127;
         l_dev = 127;
     } else
-    if(d_dev == -1 && b_dev != -1) {
+    if((d_dev == -1) && (b_dev != -1)) {
         d_dev = 127;
         l_dev = 127;
     }
 
-    if(d_dev != -1 && b_dev != -1) {
+    if((d_dev != -1) && (b_dev != -1)) {
         dev_id = (b_dev << 16) | (d_dev << 8) | l_dev;
     }
     if(cmd == CMD_ATA_LIST) {
index 07781af..7eec3d5 100644 (file)
@@ -296,6 +296,44 @@ typedef struct _MODE_PARAMETER_HEADER_10 {
     UCHAR Reserved[5];
 }MODE_PARAMETER_HEADER_10, *PMODE_PARAMETER_HEADER_10;
 
+//
+// values for TransferMode
+//
+#define         ATA_PIO                 0x00
+#define        ATA_PIO_NRDY            0x01
+
+#define         ATA_PIO0                0x08
+#define         ATA_PIO1                0x09
+#define         ATA_PIO2                0x0a
+#define         ATA_PIO3                0x0b
+#define         ATA_PIO4                0x0c
+#define         ATA_PIO5                0x0d
+
+#define         ATA_DMA                 0x10
+#define         ATA_SDMA                0x10
+#define         ATA_SDMA0               0x10
+#define         ATA_SDMA1               0x11
+#define         ATA_SDMA2               0x12
+
+#define         ATA_WDMA                0x20
+#define         ATA_WDMA0               0x20
+#define         ATA_WDMA1               0x21
+#define         ATA_WDMA2               0x22
+
+#define         ATA_UDMA                0x40
+#define         ATA_UDMA0               0x40 // ATA-16
+#define         ATA_UDMA1               0x41 // ATA-25
+#define         ATA_UDMA2               0x42 // ATA-33
+#define         ATA_UDMA3               0x43 // ATA-44
+#define         ATA_UDMA4               0x44 // ATA-66
+#define         ATA_UDMA5               0x45 // ATA-100
+#define         ATA_UDMA6               0x46 // ATA-133
+//#define         ATA_UDMA7               0x47 // ATA-166
+
+#define         ATA_SA150               0x47 /*0x80*/
+#define         ATA_SA300               0x48 /*0x81*/
+#define         ATA_SA600               0x49 /*0x82*/
+
 //
 // IDE command definitions
 //
@@ -767,6 +805,8 @@ typedef struct _IDENTIFY_DATA {
     USHORT HwResCableId : 1;
     USHORT HwResValid : 2;
 
+#define IDENTIFY_CABLE_ID_VALID    0x01
+
     USHORT CurrentAcoustic : 8;             //     94
     USHORT VendorAcoustic : 8;
 
@@ -1489,6 +1529,83 @@ extern UCHAR AtaCommandFlags[256];
 
 #endif //USER_MODE
 
+__inline
+BOOLEAN
+ata_is_sata(
+    PIDENTIFY_DATA ident
+    )
+{
+    return (ident->SataCapabilities && ident->SataCapabilities != 0xffff);
+} // end ata_is_sata()
+
+__inline
+LONG
+ata_cur_mode_from_ident(
+    PIDENTIFY_DATA ident
+    )
+{
+    if(ata_is_sata(ident)) {
+        if(ident->SataCapabilities & ATA_SATA_GEN3) {
+            return ATA_SA600;
+        } else
+        if(ident->SataCapabilities & ATA_SATA_GEN2) {
+            return ATA_SA300;
+        } else
+        if(ident->SataCapabilities & ATA_SATA_GEN1) {
+            return ATA_SA150;
+        }
+        return ATA_SA150;
+    }
+
+    if (ident->UdmaModesValid) {
+        if (ident->UltraDMAActive & 0x40)
+            return ATA_UDMA0+6;
+        if (ident->UltraDMAActive & 0x20)
+            return ATA_UDMA0+5;
+        if (ident->UltraDMAActive & 0x10)
+            return ATA_UDMA0+4;
+        if (ident->UltraDMAActive & 0x08)
+            return ATA_UDMA0+3;
+        if (ident->UltraDMAActive & 0x04)
+            return ATA_UDMA0+2;
+        if (ident->UltraDMAActive & 0x02)
+            return ATA_UDMA0+1;
+        if (ident->UltraDMAActive & 0x01)
+            return ATA_UDMA0+0;
+    }
+
+    if (ident->MultiWordDMAActive & 0x04)
+        return ATA_WDMA0+2;
+    if (ident->MultiWordDMAActive & 0x02)
+        return ATA_WDMA0+1;
+    if (ident->MultiWordDMAActive & 0x01)
+        return ATA_WDMA0+0;
+
+    if (ident->SingleWordDMAActive & 0x04)
+        return ATA_SDMA0+2;
+    if (ident->SingleWordDMAActive & 0x02)
+        return ATA_SDMA0+1;
+    if (ident->SingleWordDMAActive & 0x01)
+        return ATA_SDMA0+0;
+
+    if (ident->PioTimingsValid) {
+        if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
+            return ATA_PIO0+5;
+        if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
+            return ATA_PIO0+4;
+        if (ident->AdvancedPIOModes & AdvancedPIOModes_3) 
+            return ATA_PIO0+3;
+    }        
+    if (ident->PioCycleTimingMode == 2)
+        return ATA_PIO0+2;
+    if (ident->PioCycleTimingMode == 1)
+        return ATA_PIO0+1;
+    if (ident->PioCycleTimingMode == 0)
+        return ATA_PIO0+0;
+
+    return ATA_PIO;
+} // end ata_cur_mode_from_ident()
+
 #pragma pack(pop)
 
 #endif // __GLOBAL_H__
index f14cca9..039f111 100644 (file)
@@ -41,44 +41,6 @@ Revision History:
 
 #define MAX_QUEUE_STAT        8
 
-//
-// values for TransferMode
-//
-#define         ATA_PIO                 0x00
-#define        ATA_PIO_NRDY            0x01
-
-#define         ATA_PIO0                0x08
-#define         ATA_PIO1                0x09
-#define         ATA_PIO2                0x0a
-#define         ATA_PIO3                0x0b
-#define         ATA_PIO4                0x0c
-#define         ATA_PIO5                0x0d
-
-#define         ATA_DMA                 0x10
-#define         ATA_SDMA                0x10
-#define         ATA_SDMA0               0x10
-#define         ATA_SDMA1               0x11
-#define         ATA_SDMA2               0x12
-
-#define         ATA_WDMA                0x20
-#define         ATA_WDMA0               0x20
-#define         ATA_WDMA1               0x21
-#define         ATA_WDMA2               0x22
-
-#define         ATA_UDMA                0x40
-#define         ATA_UDMA0               0x40 // ATA-16
-#define         ATA_UDMA1               0x41 // ATA-25
-#define         ATA_UDMA2               0x42 // ATA-33
-#define         ATA_UDMA3               0x43 // ATA-44
-#define         ATA_UDMA4               0x44 // ATA-66
-#define         ATA_UDMA5               0x45 // ATA-100
-#define         ATA_UDMA6               0x46 // ATA-133
-//#define         ATA_UDMA7               0x47 // ATA-166
-
-#define         ATA_SA150               0x47 /*0x80*/
-#define         ATA_SA300               0x48 /*0x81*/
-#define         ATA_SA600               0x49 /*0x82*/
-
 // define PIO timings in nanoseconds
 #define         PIO0_TIMING             600
 
index ba017b1..864f7ea 100644 (file)
@@ -1085,13 +1085,14 @@ typedef struct _HW_LU_EXTENSION {
     ULONG          DiscsPresent;   // Indicates number of platters on changer-ish devices.
     BOOLEAN        DWordIO;        // Indicates use of 32-bit PIO
     UCHAR          ReturningMediaStatus;
+    UCHAR          MaximumBlockXfer;
+    UCHAR          Padding0[1];    // padding
 
     UCHAR          TransferMode;          // current transfer mode
     UCHAR          LimitedTransferMode;   // user-defined or IDE cable limitation
     UCHAR          OrigTransferMode;      // transfer mode, returned by device IDENTIFY (can be changed via IOCTL)
+    UCHAR          PhyTransferMode;       // phy transfer mode (actual bus transfer mode for PATA DMA and SATA)
 
-    UCHAR          MaximumBlockXfer;
-    UCHAR          Padding0[2];    // padding
     ULONG          ErrorCount;     // Count of errors. Used to turn off features.
  //   ATA_QUEUE      cmd_queue;
     LONGLONG       ReadCmdCost;
index d362a76..0893379 100644 (file)
@@ -717,6 +717,14 @@ AtapiSoftReset(
     } else {
         AtapiStallExecution(500);
         AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
+        AtapiStallExecution(30);
+
+        // Wait for BUSY assertion, in some cases delay may occure
+        while (!(AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
+               i--)
+        {
+            AtapiStallExecution(30);
+        }
 
         // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
         // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
@@ -1066,6 +1074,24 @@ AtaUmode(PIDENTIFY_DATA2 ident)
     return IOMODE_NOT_SPECIFIED;
 } // end AtaUmode()
 
+LONG
+NTAPI
+AtaSAmode(PIDENTIFY_DATA2 ident) {
+    if(!ident->SataCapabilities || 
+       ident->SataCapabilities == 0xffff) {
+        return IOMODE_NOT_SPECIFIED;
+    }
+    if(ident->SataCapabilities & ATA_SATA_GEN3) {
+        return ATA_SA600;
+    } else
+    if(ident->SataCapabilities & ATA_SATA_GEN2) {
+        return ATA_SA300;
+    } else
+    if(ident->SataCapabilities & ATA_SATA_GEN1) {
+        return ATA_SA150;
+    }
+    return IOMODE_NOT_SPECIFIED;
+} // end AtaSAmode()
 
 #ifndef UNIATA_CORE
 
@@ -1581,6 +1607,12 @@ IssueIdentify(
         deviceExtension->FullIdentifyData.SataSupport,
         deviceExtension->FullIdentifyData.SataCapabilities));
 
+    LunExt->LimitedTransferMode =
+    LunExt->OrigTransferMode =
+        (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData));
+
+    KdPrint2((PRINT_PREFIX "OrigTransferMode: %x\n", LunExt->OrigTransferMode));
+
     // Check out a few capabilities / limitations of the device.
     if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
         // Determine if this drive supports the MSN functions.
@@ -3001,7 +3033,7 @@ AtapiHwInitialize__(
         }
 
         PreferedMode = LunExt->opt_MaxTransferMode;
-        if(PreferedMode == 0xffffffff) {
+        if((PreferedMode == 0xffffffff) || (PreferedMode > chan->MaxTransferMode)) {
             KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
             PreferedMode = chan->MaxTransferMode;
         }
@@ -3012,14 +3044,12 @@ AtapiHwInitialize__(
         }
 
         KdPrint2((PRINT_PREFIX "  try mode %#x\n", PreferedMode));
-        LunExt->OrigTransferMode =
         LunExt->LimitedTransferMode =
         LunExt->TransferMode =
             (CHAR)PreferedMode;
 
         AtapiDmaInit__(deviceExtension, LunExt);
 
-        LunExt->OrigTransferMode =
         LunExt->LimitedTransferMode =
             LunExt->TransferMode;
         KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
@@ -5033,11 +5063,10 @@ IntrPrepareResetController:
         } else {
             AtaReq->WordsLeft -= AtaReq->WordsTransfered;
         }
-        if(AtaReq->WordsLeft) {
+        if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
             status = SRB_STATUS_DATA_OVERRUN;
-        } else {
-            status = SRB_STATUS_SUCCESS;
         }
+        status = SRB_STATUS_SUCCESS;
         chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
         goto CompleteRequest;
     } else
@@ -5106,11 +5135,13 @@ IntrPrepareResetController:
                           "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
                 if(AtaReq->WordsLeft > wordCount) {
                     AtaReq->WordsLeft -= wordCount;
+                    AtaReq->WordsTransfered += wordCount;
                     AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
                     goto ReturnEnableIntr;
                 }
                 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
             }
+            AtaReq->WordsTransfered = AtaReq->WordsLeft;
             AtaReq->WordsLeft = 0;
             status = SRB_STATUS_SUCCESS;
             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
@@ -5152,6 +5183,7 @@ IntrPrepareResetController:
         // Advance data buffer pointer and bytes left.
         AtaReq->DataBuffer += wordCount;
         AtaReq->WordsLeft -= wordCount;
+        AtaReq->WordsTransfered += wordCount;
 
         if (atapiDev) {
             AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
@@ -5205,12 +5237,14 @@ IntrPrepareResetController:
                           "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
                 if(AtaReq->WordsLeft > wordCount) {
                     AtaReq->WordsLeft -= wordCount;
+                    AtaReq->WordsTransfered += wordCount;
                     AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
                     goto ReturnEnableIntr;
                 }
                 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
             }
             //ASSERT(AtaReq->WordsLeft == wordCount);
+            AtaReq->WordsTransfered = AtaReq->WordsLeft;
             AtaReq->WordsLeft = 0;
             status = SRB_STATUS_SUCCESS;
             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
@@ -5281,6 +5315,7 @@ IntrPrepareResetController:
         // Advance data buffer pointer and bytes left.
         AtaReq->DataBuffer += wordCount;
         AtaReq->WordsLeft -= wordCount;
+        AtaReq->WordsTransfered += wordCount;
 
         // Check for read command complete.
         if (AtaReq->WordsLeft == 0) {
@@ -5358,13 +5393,14 @@ IntrPrepareResetController:
         // Command complete.
         if(DmaTransfer) {
             KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
+            AtaReq->WordsTransfered = AtaReq->WordsLeft;
             AtaReq->WordsLeft = 0;
         }
-        if (AtaReq->WordsLeft) {
-            status = SRB_STATUS_DATA_OVERRUN;
-        } else {
+        //if (AtaReq->WordsLeft) {
+        //    status = SRB_STATUS_DATA_OVERRUN;
+        //} else {
             status = SRB_STATUS_SUCCESS;
-        }
+        //}
 
 #ifdef UNIATA_DUMP_ATAPI
         if(srb &&
@@ -5419,6 +5455,12 @@ CompleteRequest:
 
         KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, srbstatus %x\n", status));
         // 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));
+            status = SRB_STATUS_DATA_OVERRUN;
+        }
+
         if (AtaReq->OriginalSrb) {
 
             ULONG srbStatus;
@@ -5691,10 +5733,10 @@ PIO_wait_DRQ:
                 }
             }
             if(status == SRB_STATUS_SUCCESS) {
-                if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
-                    // This should be set in UniataAhciEndTransaction() for AHCI
-                    AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
-                }
+                //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
+                //    // This should be set in UniataAhciEndTransaction() for AHCI
+                //    AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
+                //}
                 if(!atapiDev &&
                    AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
                     KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
@@ -6788,7 +6830,6 @@ GetLba2:
 
         // check if DMA read/write
         if(deviceExtension->HwFlags & UNIATA_SATA) {
-            // DEBUG !!!! for TEST ONLY
             KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n"));
             use_dma = TRUE;
             goto setup_dma;
@@ -8809,8 +8850,16 @@ do_bus_reset:
                 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
                 ULONG DeviceNumber = AtaCtl->addr.TargetId;
                 BOOLEAN bad_ldev;
-                ULONG i;
+                ULONG i, pos;
+
+                pos = FIELD_OFFSET(UNIATA_CTL, RawData);
                 //chan = &(deviceExtension->chan[lChannel]);
+                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;
+                }
 
                 if(AtaCtl->addr.Lun ||
                    AtaCtl->addr.TargetId >= deviceExtension->NumberLuns || 
@@ -8875,6 +8924,12 @@ handle_bad_ldev:
                     }
                     goto uata_ctl_queue;
                 case  IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
+                    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;
+                    }
                     if(!AtaCtl->SetMode.ApplyImmediately) {
                         break;
                     }
@@ -8905,6 +8960,12 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
 
+                    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;
+                    }
                     if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
                         KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
                         if(AtaCtl->addr.TargetId != 0xff) {
@@ -8929,10 +8990,17 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
 
+                    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;
+                    }
                     LunExt->DeviceFlags = 0;
                     if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
                         KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
-                        LunExt->DeviceFlags |= DFLAGS_HIDDEN;
+                        //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
+                        UniataForgetDevice(LunExt);
                     }
 
                     for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
@@ -8946,6 +9014,12 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
 
+                    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;
+                    }
                     if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
                         LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
                     }
@@ -8973,9 +9047,16 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n"));
 
+                    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;
+                    }
                     AtaCtl->GetMode.OrigMode    = LunExt->OrigTransferMode;
                     AtaCtl->GetMode.MaxMode     = LunExt->LimitedTransferMode;
                     AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
+                    AtaCtl->GetMode.PhyMode     = LunExt->PhyTransferMode;
 
                     status = SRB_STATUS_SUCCESS;
                     break;
@@ -8984,6 +9065,12 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
 
+                    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;
+                    }
                     AtaCtl->Version.Length      = sizeof(GETDRVVERSION);
                     AtaCtl->Version.VersionMj   = UNIATA_VER_MJ;
                     AtaCtl->Version.VersionMn   = UNIATA_VER_MN;
@@ -8997,14 +9084,13 @@ uata_ctl_queue:
 
                     KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n"));
 
-                    AtaCtl->AdapterInfo.HeaderLength = FIELD_OFFSET(ADAPTERINFO, Chan);
-
-                    if(len < AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)) {
-                        KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", len,
-                            AtaCtl->AdapterInfo.HeaderLength + sizeof(AtaCtl->AdapterInfo.Chan)));
+                    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;
-                        break;
+                        goto complete_req;
                     }
+                    AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO);
 
                     AtaCtl->AdapterInfo.DevID      = deviceExtension->DevID;
                     AtaCtl->AdapterInfo.RevID      = deviceExtension->RevID;
@@ -9031,8 +9117,35 @@ uata_ctl_queue:
                     }
                     AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
                     AtaCtl->AdapterInfo.LunInfoValid = FALSE;
-
-                    RtlZeroMemory(&AtaCtl->AdapterInfo.Chan, sizeof(AtaCtl->AdapterInfo.Chan));
+                    AtaCtl->AdapterInfo.ChanHeaderLengthValid = TRUE;
+
+                    pos += AtaCtl->AdapterInfo.HeaderLength;
+
+                    // zero tail
+                    RtlZeroMemory(((PCHAR)AtaCtl)+pos,
+                        len-pos);
+
+                    if(len >= pos+AtaCtl->AdapterInfo.NumberChannels*sizeof(CHANINFO)) {
+                        PCHANINFO ChanInfo = (PCHANINFO)( ((PCHAR)AtaCtl)+pos );
+                        PHW_CHANNEL cur_chan;
+                        KdPrint2((PRINT_PREFIX "AtapiStartIo: Fill channel info\n"));
+                        for(i=0;i<AtaCtl->AdapterInfo.NumberChannels;i++) {
+                            KdPrint2((PRINT_PREFIX "chan[%d] %x\n", i, cur_chan));
+                            cur_chan = &(deviceExtension->chan[i]);
+                            ChanInfo->MaxTransferMode = cur_chan->MaxTransferMode;
+                            ChanInfo->ChannelCtrlFlags = cur_chan->ChannelCtrlFlags;
+                            RtlCopyMemory(&(ChanInfo->QueueStat), &(cur_chan->QueueStat), sizeof(ChanInfo->QueueStat));
+                            ChanInfo->ReorderCount        = cur_chan->ReorderCount;
+                            ChanInfo->IntersectCount      = cur_chan->IntersectCount;
+                            ChanInfo->TryReorderCount     = cur_chan->TryReorderCount;
+                            ChanInfo->TryReorderHeadCount = cur_chan->TryReorderHeadCount;
+                            ChanInfo->TryReorderTailCount = cur_chan->TryReorderTailCount;
+                            //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
+                            ChanInfo++;
+                        }
+                        AtaCtl->AdapterInfo.ChanInfoValid = TRUE;
+                        AtaCtl->AdapterInfo.ChanHeaderLength = sizeof(*ChanInfo);
+                    }
 
                     status = SRB_STATUS_SUCCESS;
                     break;
index 8c4c3da..208f07d 100644 (file)
@@ -879,9 +879,23 @@ AtaSetTransferMode(
         KdPrint3((PRINT_PREFIX "  assume that drive doesn't support mode swithing using PIO%d\n", apiomode));
         mode = ATA_PIO0 + apiomode;
     }
-    //if(mode <= ATA_UDMA6) {
-        LunExt->TransferMode = (UCHAR)mode;
-    //}
+    // SATA sets actual transfer rate in LunExt on init.
+    // There is no run-time SATA rate adjustment yet.
+    // On the other hand, we may turn SATA device in PIO mode
+    LunExt->TransferMode = (UCHAR)mode;
+    if(deviceExtension->HwFlags & UNIATA_SATA) {
+        if(mode < ATA_SA150) { 
+            LunExt->PhyTransferMode = max(LunExt->PhyTransferMode, LunExt->TransferMode);
+        } else {
+            LunExt->PhyTransferMode = LunExt->TransferMode;
+        }
+    } else {
+        if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
+            LunExt->PhyTransferMode = max(LunExt->LimitedTransferMode, LunExt->TransferMode);
+        } else {
+            LunExt->PhyTransferMode = LunExt->TransferMode;
+        }
+    }
     return TRUE;
 } // end AtaSetTransferMode()
 
@@ -999,8 +1013,7 @@ AtapiDmaInit(
         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(LunExt->IdentifyData.SataCapabilities != 0x0000 &&
-               LunExt->IdentifyData.SataCapabilities != 0xffff) {
+            if(ata_is_sata(&(LunExt->IdentifyData))) {
                 //udmamode = min(udmamode, 6);
                 KdPrint2((PRINT_PREFIX "LunExt->LimitedTransferMode %x, LunExt->OrigTransferMode %x\n",
                     LunExt->LimitedTransferMode, LunExt->OrigTransferMode));
@@ -1011,7 +1024,7 @@ AtapiDmaInit(
 
             } else {
                 KdPrint2((PRINT_PREFIX "SATA -> PATA adapter ?\n"));
-                if (udmamode > 2 && !LunExt->IdentifyData.HwResCableId) {
+                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));
@@ -1041,9 +1054,8 @@ AtapiDmaInit(
         goto try_generic_dma;
     }
 
-    if(udmamode > 2 && !LunExt->IdentifyData.HwResCableId) {
-        if(LunExt->IdentifyData.SataCapabilities != 0x0000 &&
-           LunExt->IdentifyData.SataCapabilities != 0xffff) {
+    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 {
             KdPrint2((PRINT_PREFIX "AtapiDmaInit: DMA limited to UDMA33, non-ATA66 compliant cable\n"));
index ea20552..bc844ca 100644 (file)
@@ -1350,10 +1350,11 @@ hpt_cable80(
     GetPciConfig1(0x5a, res);
     res = res & (channel ? 0x01 : 0x02);
     SetPciConfig1(reg, val);
+    KdPrint2((PRINT_PREFIX "hpt_cable80(%d) = %d\n", channel, !res));
     return !res;
 } // end hpt_cable80()
 
-
+/*
 ULONG
 NTAPI
 via_cable80(
@@ -1398,9 +1399,11 @@ via_cable80(
             res |= TRUE; //(1 << (1 - (i >> 4)));
         }
     }
+    KdPrint2((PRINT_PREFIX "via_cable80(%d) = %d\n", channel, res));
     return res;
 
 } // end via_cable80()
+*/
 
 BOOLEAN
 NTAPI
@@ -1426,9 +1429,11 @@ generic_cable80(
     GetPciConfig1(pci_reg, tmp8);
     if(!(tmp8 & (1 << (channel << bit_offs)))) {
         chan->MaxTransferMode = min(deviceExtension->MaxTransferMode, ATA_UDMA2);
+        KdPrint2((PRINT_PREFIX "generic_cable80(%d, %#x, %d) = 0\n", channel, pci_reg, bit_offs));
         return FALSE;
     }
 
+    KdPrint2((PRINT_PREFIX "generic_cable80(%d, %#x, %d) = 1\n", channel, pci_reg, bit_offs));
     return TRUE;
 } // end generic_cable80()
 
@@ -1599,7 +1604,7 @@ NTAPI
 AtapiChipInit(
     IN PVOID HwDeviceExtension,
     IN ULONG DeviceNumber,
-    IN ULONG channel // physical channel
+    IN ULONG channel // logical channel
     )
 {
     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
@@ -1628,10 +1633,12 @@ AtapiChipInit(
         c = CHAN_NOT_SPECIFIED;
         break;
     default:
-        c = channel - deviceExtension->Channel; // logical channel (for Compatible Mode controllers)
+        //c = channel - deviceExtension->Channel; // logical channel (for Compatible Mode controllers)
+        c = channel;
+        channel += deviceExtension->Channel;
     }
 
-    KdPrint2((PRINT_PREFIX "AtapiChipInit: dev %#x, ph chan %d\n", DeviceNumber, channel ));
+    KdPrint2((PRINT_PREFIX "AtapiChipInit: dev %#x, ph chan %d, c %d\n", DeviceNumber, channel, c));
 
     KdPrint2((PRINT_PREFIX "HwFlags: %#x\n", deviceExtension->HwFlags));
     KdPrint2((PRINT_PREFIX "VendorID/DeviceID/Rev %#x/%#x/%#x\n", VendorID, DeviceID, RevID));
@@ -2236,11 +2243,12 @@ AtapiChipInit(
                 UniataSataWritePort4(chan, IDX_SATA_SError, 0xffffffff, 0);
                 break;
             }
-
+/*
             // check 80-pin cable
             if(!via_cable80(deviceExtension, channel)) {
                 chan->MaxTransferMode = min(deviceExtension->MaxTransferMode, ATA_UDMA2);
             }
+*/
         }
 
         break;
index 70a8c86..6f6c8ac 100644 (file)
@@ -68,7 +68,14 @@ UniataSataConnect(
         if(SStatus.SPD == SStatus_SPD_Gen1 ||
            SStatus.SPD == SStatus_SPD_Gen2 ||
            SStatus.SPD == SStatus_SPD_Gen3) {
+            // SATA sets actual transfer rate in LunExt on init.
+            // There is no run-time SATA rate adjustment yet.
+            // On the other hand, we may turn SATA device in PIO mode
+            // TODO: make separate states for interface speed and transfer mode (DMA vs PIO)
+            chan->lun[0]->LimitedTransferMode =
+            chan->lun[0]->PhyTransferMode =
             chan->lun[0]->TransferMode = ATA_SA150 + (UCHAR)(SStatus.SPD - 1);
+
             KdPrint2((PRINT_PREFIX "SATA TransferMode %#x\n", chan->lun[0]->TransferMode));
             if(chan->MaxTransferMode < chan->lun[0]->TransferMode) {
                 KdPrint2((PRINT_PREFIX "SATA upd chan TransferMode\n"));
index e377be3..9a2ccce 100644 (file)
@@ -85,7 +85,7 @@ typedef struct _GETTRANSFERMODE {
     ULONG MaxMode;
     ULONG OrigMode;
     ULONG CurrentMode;
-    ULONG Reserved;
+    ULONG PhyMode; // since v0.42i6
 } GETTRANSFERMODE, *PGETTRANSFERMODE;
 
 typedef struct _GETDRVVERSION {
@@ -100,14 +100,13 @@ typedef struct _GETDRVVERSION {
 typedef struct _CHANINFO {
     ULONG               MaxTransferMode; // may differ from Controller's value due to 40-pin cable
     ULONG               ChannelCtrlFlags;
-//#ifdef QUEUE_STATISTICS
     LONGLONG QueueStat[MAX_QUEUE_STAT];
     LONGLONG ReorderCount;
     LONGLONG IntersectCount;
     LONGLONG TryReorderCount;
     LONGLONG TryReorderHeadCount;
     LONGLONG TryReorderTailCount; /* in-order requests */
-//#endif //QUEUE_STATISTICS
+//    ULONG               opt_MaxTransferMode; // user-specified
 } CHANINFO, *PCHANINFO;
 
 typedef struct _ADAPTERINFO {
@@ -143,13 +142,15 @@ typedef struct _ADAPTERINFO {
     ULONG NumberChannels;
     BOOLEAN ChanInfoValid;
 
-    UCHAR   NumberLuns;
+    UCHAR   NumberLuns;  // per channel
     BOOLEAN LunInfoValid;
-    CHAR    Reserved;
+    BOOLEAN ChanHeaderLengthValid; // since v0.42i8
 
     ULONG   AdapterInterfaceType;
+    ULONG   ChanHeaderLength;
+    ULONG   LunHeaderLength;
 
-    CHANINFO Chan[AHCI_MAX_PORT];
+    //CHANINFO Chan[0];
 
 } ADAPTERINFO, *PADAPTERINFO;
 
@@ -216,7 +217,9 @@ typedef struct _ATA_PASS_THROUGH_DIRECT {
 
 #endif //ATA_FLAGS_DRDY_REQUIRED
 
-#pragma pack(1)
+#pragma pack(pop)
+
+#pragma pack(push, 1)
 typedef struct _IDEREGS_EX {
         UCHAR    bFeaturesReg;           // Used for specifying SMART "commands".
         UCHAR    bSectorCountReg;        // IDE sector count register
@@ -263,11 +266,15 @@ typedef struct _UNIATA_REG_IO_HDR {
     ULONG          ItemCount;
     UNIATA_REG_IO  r[1];
 } UNIATA_REG_IO_HDR, *PUNIATA_REG_IO_HDR;
-#pragma pack()
+
+#pragma pack(pop)
+
+#pragma pack(push, 1)
 
 typedef struct _UNIATA_CTL {
     SRB_IO_CONTROL hdr;
     SCSI_ADDRESS   addr;
+    ULONG Reserved;
     union {
         UCHAR                   RawData[1];
         ADDREMOVEDEV            FindDelDev;