[UNIATA]: Sync to 0.43f5.

[ATACTL]: Sync to 0.43f5.

svn path=/trunk/; revision=57265
This commit is contained in:
Amine Khaldi 2012-09-10 19:38:32 +00:00
parent 583fb33611
commit deaba45849
15 changed files with 1762 additions and 886 deletions

View File

@ -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 -<switches> c|s<controller id>:b<bus id>:d<device id>[:l<lun>]\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();
}

View File

@ -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)

View File

@ -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 ),

View File

@ -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, \

File diff suppressed because it is too large Load Diff

View File

@ -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 {

View File

@ -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);

View File

@ -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; i<BMListLen; i++) {
if(BMList[i].slotNumber == ConfigInfo->SlotNumber &&
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)) {

View File

@ -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(

View File

@ -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__

View File

@ -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]); }

View File

@ -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__

View File

@ -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.

View File

@ -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

View File

@ -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"