[UNIATA]: Sync to 0.43f5.
[ATACTL]: Sync to 0.43f5.
CORE-6563 #comment Committed the 0.43f5 sync.
svn path=/trunk/; revision=57292
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"
" 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"
#define CMD_ATA_MODE 0x04
#define CMD_ATA_RESET 0x05
#define CMD_ATA_BBLK 0x06
+#define CMD_ATA_POWER 0x07
HANDLE
ata_open_dev(
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];
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;
char lun_str[10];
HKEY hKey2;
ULONGLONG max_lba = -1;
- USHORT chs[3];
+ USHORT chs[3] = { 0 };
if(dev_id != -1) {
dev_id &= 0x00ffffff;
} else {
mode_str[0] = 0;
}
- printf(" b%u [%s]\n",
+ printf(" b%lu [%s]\n",
i,
mode_str
);
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;
}
}
+ if(!g_extended) {
+ printf(" b%lu:d%d%s %24.24s %4.4s ",
+ i,
+ inquiryData->TargetId,
+ lun_str,
+ /*(inquiryData->DeviceClaimed) ? "Y" : "N",*/
+ (g_extended ? (PUCHAR)"" : &scsi_ident->VendorId[0]),
+ (g_extended ? (PUCHAR)"" : &scsi_ident->ProductRevisionLevel[0])
+ );
+ } else {
+ printf(" b%lu:d%d%s ",
+ i,
+ inquiryData->TargetId,
+ lun_str
+ );
+ }
+
if(status) {
- if(!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);
+ io_mode = ata_cur_mode_from_ident(ident, IDENT_MODE_ACTIVE);
}
- } else {
- goto next_dev;
-
}
if(io_mode != -1) {
ata_mode_to_str(mode_str, io_mode);
}
printf("\n");
- if(status && g_extended) {
-
- BOOLEAN BlockMode_valid = TRUE;
- BOOLEAN print_geom = FALSE;
-
- switch(ident->DeviceType) {
- case ATAPI_TYPE_DIRECT:
- if(ident->Removable) {
- printf(" Floppy ");
- } else {
+ if(g_extended) {
+ if(status) {
+
+ BOOLEAN BlockMode_valid = TRUE;
+ BOOLEAN print_geom = FALSE;
+
+ switch(ident->DeviceType) {
+ case ATAPI_TYPE_DIRECT:
+ if(ident->Removable) {
+ printf(" Floppy ");
+ } else {
+ printf(" Hard Drive ");
+ }
+ break;
+ case ATAPI_TYPE_TAPE:
+ printf(" Tape Drive ");
+ break;
+ case ATAPI_TYPE_CDROM:
+ printf(" CD/DVD Drive ");
+ BlockMode_valid = FALSE;
+ break;
+ case ATAPI_TYPE_OPTICAL:
+ printf(" Optical Drive ");
+ BlockMode_valid = FALSE;
+ break;
+ default:
printf(" Hard Drive ");
+ print_geom = TRUE;
+ //MOV_DD_SWP(max_lba, ident->UserAddressableSectors);
+ max_lba = ident->UserAddressableSectors;
+ if(ident->FeaturesSupport.Address48) {
+ max_lba = ident->UserAddressableSectors48;
+ }
+ //MOV_DW_SWP(chs[0], ident->NumberOfCylinders);
+ //MOV_DW_SWP(chs[1], ident->NumberOfHeads);
+ //MOV_DW_SWP(chs[2], ident->SectorsPerTrack);
+ chs[0] = ident->NumberOfCylinders;
+ chs[1] = ident->NumberOfHeads;
+ chs[2] = ident->SectorsPerTrack;
+ if(!max_lba) {
+ max_lba = (ULONG)(chs[0])*(ULONG)(chs[1])*(ULONG)(chs[2]);
+ }
}
- 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);
-
- 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");
+ printf(" Mod: %40.40s\n", SerNum);
+ for (j = 0; j < 8; j += 2) {
+ MOV_DW_SWP(SerNum[j], ((PUCHAR)ident->FirmwareRevision)[j]);
}
- }
- 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)
- );
+ printf(" Rev: %8.8s\n", SerNum);
+ for (j = 0; j < 20; j += 2) {
+ MOV_DW_SWP(SerNum[j], ((PUCHAR)ident->SerialNumber)[j]);
}
- }
- 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");
+ printf(" S/N: %20.20s\n", SerNum);
+
+ if(BlockMode_valid) {
+ if(ident->MaximumBlockTransfer) {
+ printf(" Multi-block mode: %u block%s\n", ident->MaximumBlockTransfer, ident->MaximumBlockTransfer == 1 ? "" : "s");
+ } else {
+ printf(" Multi-block mode: N/A\n");
+ }
+ }
+ if(print_geom) {
+ printf(" C/H/S: %u/%u/%u \n", chs[0], chs[1], chs[2]);
+ printf(" LBA: %I64u \n", max_lba);
+ if(max_lba < 2) {
+ printf(" Size: %lu kb\n", (ULONG)(max_lba/2));
+ } else
+ if(max_lba < 2*1024*1024) {
+ printf(" Size: %lu Mb\n", (ULONG)(max_lba/2048));
+ } else
+ if(max_lba < (ULONG)2*1024*1024*1024) {
+ printf(" Size: %lu.%lu (%lu) Gb\n", (ULONG)(max_lba/2048/1024),
+ (ULONG)(((max_lba/2048)%1024)/10),
+ (ULONG)(max_lba*512/1000/1000/1000)
+ );
+ } else {
+ printf(" Size: %lu.%lu (%lu) Tb\n", (ULONG)(max_lba/2048/1024/1024),
+ (ULONG)((max_lba/2048/1024)%1024)/10,
+ (ULONG)(max_lba*512/1000/1000/1000)
+ );
+ }
}
- RegCloseKey(hKey2);
+ len = 0;
+ if((hKey2 = ata_get_bblist_regh(ident, DevSerial, TRUE))) {
+ if(RegQueryValueEx(hKey2, DevSerial, NULL, NULL, NULL, &len) == ERROR_SUCCESS) {
+ printf(" !!! Assigned bad-block list !!!\n");
+ }
+ RegCloseKey(hKey2);
+ }
+ } else {
+ switch(scsi_ident->DeviceType) {
+ case DIRECT_ACCESS_DEVICE:
+ if(scsi_ident->RemovableMedia) {
+ printf(" Floppy ");
+ } else {
+ printf(" Hard Drive ");
+ }
+ break;
+ case SEQUENTIAL_ACCESS_DEVICE:
+ printf(" Tape Drive ");
+ break;
+ case PRINTER_DEVICE:
+ printf(" Printer ");
+ break;
+ case PROCESSOR_DEVICE:
+ printf(" Processor ");
+ break;
+ case WRITE_ONCE_READ_MULTIPLE_DEVICE:
+ printf(" WORM Drive ");
+ break;
+ case READ_ONLY_DIRECT_ACCESS_DEVICE:
+ printf(" CDROM Drive ");
+ break;
+ case SCANNER_DEVICE:
+ printf(" Scanner ");
+ break;
+ case OPTICAL_DEVICE:
+ printf(" Optical Drive ");
+ break;
+ case MEDIUM_CHANGER:
+ printf(" Changer ");
+ break;
+ case COMMUNICATION_DEVICE:
+ printf(" Comm. device ");
+ break;
+ }
+ printf("\n");
}
-
}
memcpy(&g_ident, ident, sizeof(IDENTIFY_DATA));
}
} 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",
if(AdapterInfo->AdapterInterfaceType == Isa) {
printf(" ISA Bus\n");
}
- printf(" IRQ: %d\n", AdapterInfo->BusInterruptLevel);
+ printf(" IRQ: %ld\n", AdapterInfo->BusInterruptLevel);
}
}
ata_close_dev(h);
int bus_id,
int dev_id,
int lock,
- int persistent_hide
+ int persistent_hide,
+ int power_mode
)
{
char dev_name[64];
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;
}
}
len = GetFileSize(hf, NULL);
- if(!len || len == -1)
+ if(!len || len == INVALID_FILE_SIZE)
goto exit;
bblist = (char*)GlobalAlloc(GMEM_FIXED, len*8);
}
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;
continue;
}
k0 = k;
- while(a = BB_Msg[k]) {
+ while((a = BB_Msg[k])) {
if(a == ' ' || a == '\t' || a == '\r') {
BB_Msg[k] = '\t';
}
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
char* argv[]
)
{
- ULONG Flags = 0;
+ //ULONG Flags = 0;
int i, j;
char a;
int bus_id = -1;
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"
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' :
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();
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();
}
#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
#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
//
union {
USHORT Integrity; // 255
struct {
+#define ATA_ChecksumValid 0xA5
USHORT ChecksumValid:8;
USHORT Checksum:8;
};
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;
}
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)
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)
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)
#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;
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;
#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
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 ),
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 ),
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 ),
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 ),
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 ),
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 {
#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
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
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;
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;
IORES BaseIoAHCI_0;
//PIDE_AHCI_PORT_REGISTERS BaseIoAHCIPort[AHCI_MAX_PORT];
ULONG AHCI_CAP;
+ ULONG AHCI_PI;
PATA_REQ AhciInternalAtaReq0;
PSCSI_REQUEST_BLOCK AhciInternalSrb0;
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
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];
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
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, \
5. W2k support (binary compatibility)
6. HDD hot swap under NT4
7. XP support (binary compatibility)
- 8. Serial ATA (SATA/SATA2) support
+ 8. Serial ATA (SATA/SATA2/SATA3) support
9. NT 3.51 support (binary compatibility)
etc. (See todo.txt)
IN ULONG lChannel
);
+VOID
+NTAPI
+UniataUserDeviceReset(
+ PHW_DEVICE_EXTENSION deviceExtension,
+ PHW_LU_EXTENSION LunExt,
+ ULONG lChannel
+ );
+
#define RESET_COMPLETE_CURRENT 0x00
#define RESET_COMPLETE_ALL 0x01
#define RESET_COMPLETE_NONE 0x02
UCHAR statusByte;
ULONG i;
+ // Assume, proper drive is already seleted
WaitOnBusyLong(chan);
for (i = 0; i < 0x10000; i++) {
} // end UniataDumpATARegs()
#endif
+VOID
+NTAPI
+UniataSnapAtaRegs(
+ IN PHW_CHANNEL chan,
+ IN ULONG DeviceNumber,
+ IN OUT PIDEREGS_EX regs
+ )
+{
+ if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
+ // AHCI
+ UniataAhciSnapAtaRegs(chan, DeviceNumber, regs);
+ } else {
+ // SATA/PATA, assume drive is selected
+ ULONG j;
+ UCHAR statusByteAlt;
+
+ if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {
+ for(j=IDX_IO1_i_Error; j<=IDX_IO1_i_Status; j++) {
+ statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
+ ((PUCHAR)regs)[j-1] = statusByteAlt;
+ }
+ regs->bOpFlags = 0;
+ } else {
+ regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
+ for(j=IDX_IO1_i_Error; j<IDX_IO1_i_DriveSelect; j++) {
+ statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
+ ((PUCHAR)regs)[j-1] = statusByteAlt;
+ statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
+ ((PUCHAR)regs)[j+8-1] = statusByteAlt;
+ }
+ regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status);
+ }
+ }
+ return;
+} // end UniataSnapAtaRegs()
+
/*++
Routine Description:
break;
}
}
- // Device didn't respond correctly. It will be given one more chances.
+ // Device didn't respond correctly. It will be given one more chance.
KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
GetBaseStatus(chan, statusByte);
if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
-#if 0
- USHORT w;
- ULONG i;
+
// ATI/SII chipsets with memory-mapped IO hangs when
// I call ReadBuffer(), probably due to PCI burst/prefetch enabled
- // Unfortunately, I don't know yet how to workaround it except the way you see below.
- KdPrint2((PRINT_PREFIX
- " IO_%#x (%#x), %s:\n",
- IDX_IO1_i_Data,
- chan->RegTranslation[IDX_IO1_i_Data].Addr,
- chan->RegTranslation[IDX_IO1_i_Data].MemIo ? "Mem" : "IO"));
- for(i=0; i<256; i++) {
- /*
- KdPrint2((PRINT_PREFIX
- " IO_%#x (%#x):\n",
- IDX_IO1_i_Data,
- chan->RegTranslation[IDX_IO1_i_Data].Addr));
- */
- w = AtapiReadPort2(chan, IDX_IO1_i_Data);
- KdPrint2((PRINT_PREFIX
- " %x\n", w));
- AtapiStallExecution(1);
- ((PUSHORT)&deviceExtension->FullIdentifyData)[i] = w;
- }
-#else
+ // Unfortunately, I don't know yet how to workaround it except
+ // spacifying manual delay in the way you see below.
ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
-#endif
+
// Work around for some IDE and one model Atapi that will present more than
// 256 bytes for the Identify data.
KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
if(deviceExtension->FullIdentifyData.UdmaModesValid) {
- KdPrint2((PRINT_PREFIX "UDMA: %x\n", deviceExtension->FullIdentifyData.UltraDMAActive));
+ KdPrint2((PRINT_PREFIX "UDMA: %x/%x\n", deviceExtension->FullIdentifyData.UltraDMAActive, deviceExtension->FullIdentifyData.UltraDMASupport));
}
KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable));
KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n",
LunExt->LimitedTransferMode =
LunExt->OrigTransferMode =
- (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData));
-
- KdPrint2((PRINT_PREFIX "OrigTransferMode: %x\n", LunExt->OrigTransferMode));
+ (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_MAX);
+ LunExt->TransferMode =
+ (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_ACTIVE);
+
+ KdPrint2((PRINT_PREFIX "OrigTransferMode: %x, Active: %x\n", LunExt->OrigTransferMode, LunExt->TransferMode));
+ KdPrint2((PRINT_PREFIX "Accoustic %d, cur %d\n",
+ deviceExtension->FullIdentifyData.VendorAcoustic,
+ deviceExtension->FullIdentifyData.CurrentAcoustic
+ ));
+ KdPrint2((PRINT_PREFIX "AdvPowerMode %d, cur %d\n",
+ deviceExtension->FullIdentifyData.CfAdvPowerMode
+ ));
// Check out a few capabilities / limitations of the device.
if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
}
}
}
- KdPrint2((PRINT_PREFIX "final LunExt->opt_GeomType=%x\n", LunExt->opt_GeomType));
if(LunExt->opt_GeomType == GEOM_STD) {
deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
PHW_LU_EXTENSION LunExt
)
{
+ // keep only DFLAGS_HIDDEN flag
LunExt->DeviceFlags &= DFLAGS_HIDDEN;
LunExt->AtapiReadyWaitDelay = 0;
} // end UniataForgetDevice()
Routine Description:
Reset IDE controller and/or Atapi device.
+ ->HwResetBus
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
} // end AtapiResetController()
-
BOOLEAN
NTAPI
AtapiResetController__(
InterlockedExchange(&(chan->CheckIntr),
CHECK_INTR_IDLE);
+ for (i = 0; i < MaxLuns; i++) {
+ chan->lun[i]->PowerState = 0;
+ }
// Reset controller
if(ChipFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX " AHCI path\n"));
+ if(UniataAhciChanImplemented(deviceExtension, j)) {
#if DBG
- UniataDumpAhciPortRegs(chan);
+ UniataDumpAhciPortRegs(chan);
#endif
- AtapiDisableInterrupts(deviceExtension, j);
- UniataAhciReset(HwDeviceExtension, j);
+ AtapiDisableInterrupts(deviceExtension, j);
+ UniataAhciReset(HwDeviceExtension, j);
+ } else {
+ KdPrint2((PRINT_PREFIX " skip not implemented\n"));
+ }
} else {
KdPrint2((PRINT_PREFIX " ATA path, chan %#x\n", chan));
KdPrint2((PRINT_PREFIX " disable intr (0)\n"));
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
+ ->HwInitialize
Return Value:
TRUE - if initialization successful.
if(WinVer_WDM_Model) {
AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL);
}
+ if(deviceExtension->MasterDev) {
+ KdPrint2((PRINT_PREFIX " mark chan %d of master controller [%x] as inited\n",
+ deviceExtension->Channel, deviceExtension->DevIndex));
+ BMList[deviceExtension->DevIndex].ChanInitOk |= 0x01 << deviceExtension->Channel;
+ }
/* do extra chipset specific setups */
AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
// ULONG tmp32;
ULONG PreferedMode = 0xffffffff;
+ if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+ !UniataAhciChanImplemented(deviceExtension, lChannel)) {
+ return;
+ }
+
AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
FindDevices(deviceExtension, 0, lChannel);
KdPrint2((PRINT_PREFIX " Disable Write Cache\n"));
statusByte = AtaCommand(deviceExtension, i, lChannel,
IDE_COMMAND_SET_FEATURES, 0, 0, 0,
- 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
+ 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
}
+
+ if(LunExt->IdentifyData.FeaturesSupport.PowerMngt ||
+ LunExt->IdentifyData.FeaturesSupport.APM) {
+
+ if(LunExt->opt_AdvPowerMode) {
+ KdPrint2((PRINT_PREFIX " Try Enable Adv. Power Mgmt\n"));
+ // setup APM
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+ LunExt->opt_AdvPowerMode, ATA_C_F_ENAB_APM, ATA_WAIT_BASE_READY);
+ // Check for errors.
+ if (statusByte & IDE_STATUS_ERROR) {
+ KdPrint2((PRINT_PREFIX
+ "AtapiHwInitialize: Enable APM on Device %d failed\n",
+ i));
+ }
+ } else {
+ KdPrint2((PRINT_PREFIX " Disable Adv. Power Mgmt\n"));
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+ 0, ATA_C_F_DIS_APM, ATA_WAIT_BASE_READY);
+ }
+ }
+ if(LunExt->IdentifyData.FeaturesSupport.AutoAcoustic) {
+ if(LunExt->opt_AcousticMode) {
+ KdPrint2((PRINT_PREFIX " Try Enable Acoustic Mgmt\n"));
+ // setup acoustic mgmt
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+ LunExt->opt_AcousticMode, ATA_C_F_ENAB_ACOUSTIC, ATA_WAIT_BASE_READY);
+ // Check for errors.
+ if (statusByte & IDE_STATUS_ERROR) {
+ KdPrint2((PRINT_PREFIX
+ "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
+ i));
+ }
+ } else {
+ KdPrint2((PRINT_PREFIX " Disable Acoustic Mgmt\n"));
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_SET_FEATURES, 0, 0, 0,
+ 0, ATA_C_F_DIS_ACOUSTIC, ATA_WAIT_BASE_READY);
+ }
+ }
+ if(LunExt->IdentifyData.FeaturesSupport.Standby) {
+ KdPrint2((PRINT_PREFIX " Try init standby timer: %d\n"));
+ // setup standby timer
+ statusByte = AtaCommand(deviceExtension, i, lChannel,
+ IDE_COMMAND_IDLE, 0, 0, 0,
+ LunExt->opt_StandbyTimer, 0, ATA_WAIT_BASE_READY);
+ // Check for errors.
+ if (statusByte & IDE_STATUS_ERROR) {
+ KdPrint2((PRINT_PREFIX
+ "AtapiHwInitialize: standby timer on Device %d failed\n",
+ i));
+ }
+ }
}
} else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
if(!hIS) {
return FALSE;
}
- checked = ~hIS; // assume all non-interrupted ports to be already checked
+ // assume all non-interrupted ports to be already checked
+ checked = ~hIS;
+ // assume all not implemented ports to be already checked
+ checked |= ~deviceExtension->AHCI_PI;
} else {
checked = 0; // assume all ports are not checked
}
if(!hIS) {
return FALSE;
}
- checked = ~hIS; // assume all non-interrupted ports to be already checked
+ // assume all non-interrupted ports to be already checked
+ checked = ~hIS;
+ // assume all not implemented ports to be already checked
+ checked |= ~deviceExtension->AHCI_PI;
+
} else {
checked = 0; // assume all ports are not checked
}
KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c));
return;
}
+ if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+ !UniataAhciChanImplemented(deviceExtension, c)) {
+ KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c));
+ return;
+ }
+
chan = &(deviceExtension->chan[c]);
KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr));
if(!InterlockedDecrement(&chan->DisableIntr)) {
if((ChipFlags & UNIATA_AHCI) &&
UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
+
+ if(!UniataAhciChanImplemented(deviceExtension, lChannel)) {
+ return OurInterrupt;
+ }
+
OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) &&
(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n",
AtaReq->retry,
- chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry],
- chan->lun[DeviceNumber]->BlockIoCount
+ LunExt->RecoverCount[AtaReq->retry],
+ LunExt->BlockIoCount
));
- chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry]++;
- if(chan->lun[DeviceNumber]->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
+ LunExt->RecoverCount[AtaReq->retry]++;
+ if(LunExt->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
(deviceExtension->HwFlags & UNIATA_NO80CHK)
) {
#else
if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
#endif //IO_STATISTICS
- KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", deviceExtension->lun[DeviceNumber].TransferMode));
- deviceExtension->lun[DeviceNumber].LimitedTransferMode =
- deviceExtension->lun[DeviceNumber].TransferMode;
+ KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", LunExt->TransferMode));
+ LunExt->LimitedTransferMode =
+ LunExt->TransferMode;
}
}
#ifdef IO_STATISTICS
if(AtaReq->bcount) {
// we need stats for Read/Write operations
- chan->lun[DeviceNumber]->BlockIoCount++;
+ LunExt->BlockIoCount++;
}
- chan->lun[DeviceNumber]->IoCount++;
+ LunExt->IoCount++;
#endif //IO_STATISTICS
continue_PIO:
} else {
AtaReq->WordsLeft -= AtaReq->WordsTransfered;
}
- if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
- status = SRB_STATUS_DATA_OVERRUN;
- }
+ //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
+ // status = SRB_STATUS_DATA_OVERRUN;
+ //}
status = SRB_STATUS_SUCCESS;
chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
goto CompleteRequest;
// Write the packet.
KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
// Send CDB to device.
- WriteBuffer(chan, (PUSHORT)srb->Cdb, 6, 0);
+ WriteBuffer(chan, (PUSHORT)srb->Cdb,
+ LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
+ 0);
AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
// Check and see if we are processing our secret (mechanism status/request sense) srb
if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
- KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_SUCCESS\n", AtaReq->WordsLeft));
+ KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq->WordsLeft));
status = SRB_STATUS_DATA_OVERRUN;
}
} else {
KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n"));
- PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
if (status != SRB_STATUS_SUCCESS) {
error = AtapiReadPort1(chan, IDX_IO1_i_Error);
KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
}
- // Build the SMART status block depending upon the completion status.
- cmdOutParameters->cBufferSize = wordCount;
- cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
- cmdOutParameters->DriverStatus.bIDEError = error;
+ if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
- // If the sub-command is return smart status, jam the value from cylinder low and high, into the
- // data buffer.
- if (chan->SmartCommand == RETURN_SMART_STATUS) {
- cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS;
- cmdOutParameters->bBuffer[1] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason);
- cmdOutParameters->bBuffer[2] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Unused1);
- cmdOutParameters->bBuffer[3] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
- cmdOutParameters->bBuffer[4] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh);
- cmdOutParameters->bBuffer[5] = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_DriveSelect);
- cmdOutParameters->bBuffer[6] = SMART_CMD;
- cmdOutParameters->cBufferSize = 8;
- }
+ PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
+ // Build the SMART status block depending upon the completion status.
+ cmdOutParameters->cBufferSize = wordCount;
+ cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
+ cmdOutParameters->DriverStatus.bIDEError = error;
+ // If the sub-command is return smart status, jam the value from cylinder low and high, into the
+ // data buffer.
+ if (chan->SmartCommand == RETURN_SMART_STATUS) {
+ PIDEREGS_EX regs = (PIDEREGS_EX)&(cmdOutParameters->bBuffer);
+
+ regs->bOpFlags = 0;
+ UniataSnapAtaRegs(chan, 0, regs);
+
+ regs->bCommandReg = SMART_CMD;
+ regs->bFeaturesReg = RETURN_SMART_STATUS;
+
+ cmdOutParameters->cBufferSize = 8;
+ }
+ chan->SmartCommand = 0; // cleanup after execution
+ }
// Indicate command complete.
goto IntrCompleteReq;
}
NTAPI
IdeSendSmartCommand(
IN PVOID HwDeviceExtension,
- IN PSCSI_REQUEST_BLOCK Srb
+ IN PSCSI_REQUEST_BLOCK Srb,
+ IN ULONG targetId // assume it is always valid
)
{
PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
- ULONG c = GET_CHANNEL(Srb);
- PHW_CHANNEL chan = &(deviceExtension->chan[c]);
+ ULONG c ; // = GET_CHANNEL(Srb); may be invalid
+ PHW_CHANNEL chan ; // = &(deviceExtension->chan[c]);
PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
PIDEREGS regs = &cmdInParameters.irDriveRegs;
// ULONG i;
- UCHAR statusByte,targetId;
-
+ UCHAR statusByte;
+ ULONG DeviceNumber;
if (regs->bCommandReg != SMART_CMD) {
KdPrint2((PRINT_PREFIX
return SRB_STATUS_INVALID_REQUEST;
}
- targetId = cmdInParameters.bDriveNumber;
+ c = targetId / deviceExtension->NumberLuns;
+ DeviceNumber = targetId % deviceExtension->NumberLuns;
+ KdPrint2((PRINT_PREFIX " c %d, dev %d\n", c, DeviceNumber));
- //TODO optimize this check
- if ((!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) ||
- (deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
-
- return SRB_STATUS_SELECTION_TIMEOUT;
- }
+ chan = &(deviceExtension->chan[c]);
chan->SmartCommand = regs->bFeaturesReg;
switch(regs->bFeaturesReg) {
case READ_ATTRIBUTES:
case READ_THRESHOLDS:
+ case READ_LOG_SECTOR:
+ case WRITE_LOG_SECTOR:
+
+ if(Srb->DataTransferLength < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1) {
+ KdPrint2((PRINT_PREFIX
+ "IdeSendSmartCommand: wrong buffer size\n"));
+ return SRB_STATUS_DATA_OVERRUN;
+ }
statusByte = WaitOnBusy(chan);
AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
- statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
regs->bCommandReg,
(USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
0,
case ENABLE_DISABLE_AUTOSAVE:
case EXECUTE_OFFLINE_DIAGS:
case SAVE_ATTRIBUTE_VALUES:
+ case AUTO_OFFLINE:
statusByte = WaitOnBusy(chan);
AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
AtaReq->WordsLeft = 0;
- statusByte = AtaCommand(deviceExtension, targetId & 0x1, c,
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
regs->bCommandReg,
(USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
0,
if(!(statusByte & IDE_STATUS_ERROR)) {
// Wait for interrupt.
+ UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
return SRB_STATUS_PENDING;
}
return SRB_STATUS_ERROR;
PHW_LU_EXTENSION LunExt;
//ULONG ldev = GET_LDEV(Srb);
ULONG DeviceNumber = GET_CDEV(Srb);
- ULONG i;
ULONG flags;
UCHAR statusByte,byteCountLow,byteCountHigh;
BOOLEAN use_dma = FALSE;
if(CmdAction == CMD_ACTION_PREPARE) {
KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb)));
+
switch (Srb->Cdb[0]) {
case SCSIOP_RECEIVE:
case SCSIOP_SEND:
(AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb)));
+
+ if(!LunExt->IdentifyData.AtapiCmdSize &&
+ (Srb->CdbLength > 12)) {
+ KdPrint2((PRINT_PREFIX "Cdb16 not supported\n"));
+ return SRB_STATUS_INVALID_REQUEST;
+ }
+
// Set data buffer pointer and words left.
AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
AtaReq->WordsLeft = Srb->DataTransferLength / 2;
// Try to drain the data that one preliminary device thinks that it has
// to transfer. Hopefully this random assertion of DRQ will not be present
// in production devices.
+ statusByte = AtapiSuckPort2(chan);
+/*
for (i = 0; i < 0x10000; i++) {
GetStatus(chan, statusByte);
if(statusByte & IDE_STATUS_DRQ) {
break;
}
}
-
- if (i == 0x10000) {
+*/
+ if (statusByte & IDE_STATUS_DRQ) {
make_reset:
KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
WriteBuffer(chan,
(PUSHORT)Srb->Cdb,
- 6,
+ LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
0);
if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
SetCheckPoint(4);
UCHAR statusByte,errorByte;
- ULONG status;
+ ULONG status = SRB_STATUS_INVALID_REQUEST;
ULONG i;
ULONGLONG lba;
PMODE_PARAMETER_HEADER modeData;
//ULONG ldev;
ULONG DeviceNumber;
PATA_REQ AtaReq;
+ UCHAR command;
+
SetCheckPoint(5);
//ULONG __ebp__ = 0;
break;
+ case SCSIOP_REPORT_LUNS: {
+
+ ULONG alen;
+ PREPORT_LUNS_INFO_HDR LunInfo;
+
+ KdPrint2((PRINT_PREFIX
+ "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
+ Srb->PathId, Srb->Lun, Srb->TargetId));
+
+ MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength);
+
+ if(alen < 16) {
+ goto invalid_cdb;
+ }
+ alen = 8;
+
+ LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer);
+ RtlZeroMemory(LunInfo, 16);
+
+ MOV_DD_SWP( LunInfo->ListLength, alen );
+ Srb->DataTransferLength = 16;
+ status = SRB_STATUS_SUCCESS;
+
+ break; }
+
case SCSIOP_MODE_SENSE:
KdPrint2((PRINT_PREFIX
"IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
Srb->PathId, Srb->Lun, Srb->TargetId));
- // This is used to determine if the media is write-protected.
- // Since IDE does not support mode sense then we will modify just the portion we need
- // so the higher level driver can determine if media is protected.
+
+ if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) {
+ PMODE_POWER_CONDITION_PAGE modeData;
+
+ KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n"));
+ modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer);
+ if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) {
+ status = SRB_STATUS_DATA_OVERRUN;
+ } else {
+ RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE));
+ modeData->PageCode = MODE_PAGE_POWER_CONDITION;
+ modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER);
+ modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle;
+ modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby;
+ Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE);
+ status = SRB_STATUS_SUCCESS;
+ }
+ } else
if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) {
PMODE_CACHING_PAGE modeData;
KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n"));
- modeData = (PMODE_CACHING_PAGE)Srb->DataBuffer;
+ modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer);
if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) {
- status = STATUS_BUFFER_TOO_SMALL;
+ status = SRB_STATUS_DATA_OVERRUN;
} else {
RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE));
modeData->PageCode = MODE_PAGE_CACHING;
} else
if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
+ // This is used to determine if the media is write-protected.
+ // Since IDE does not support mode sense then we will modify just the portion we need
+ // so the higher level driver can determine if media is protected.
+
//SelectDrive(chan, DeviceNumber);
//AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
//statusByte = WaitOnBusy(chan);
case SCSIOP_START_STOP_UNIT:
KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
- Srb->PathId, Srb->Lun, Srb->TargetId));
+ "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
+ cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId));
//Determine what type of operation we should perform
- cdb = (PCDB)Srb->Cdb;
- if (cdb->START_STOP.LoadEject == 1){
+ command = 0;
- statusByte = WaitOnBaseBusy(chan);
+ if(cdb->START_STOP.FL ||
+ cdb->START_STOP.FormatLayerNumber ||
+ cdb->START_STOP.Reserved2 ||
+ cdb->START_STOP.Reserved2_2 ||
+ cdb->START_STOP.Reserved3 ||
+ FALSE) {
+ goto invalid_cdb;
+ }
+
+ if (cdb->START_STOP.PowerConditions) {
+ KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions));
+ switch(cdb->START_STOP.PowerConditions) {
+ case StartStop_Power_Idle:
+ command = IDE_COMMAND_IDLE_IMMED;
+ break;
+ case StartStop_Power_Standby:
+ command = IDE_COMMAND_STANDBY_IMMED;
+ break;
+ case StartStop_Power_Sleep:
+ // TODO: we should save power state in order to know
+ // that RESET sould be issued to revert device into
+ // operable state
+
+ command = IDE_COMMAND_SLEEP;
+ break;
+ default:
+ goto invalid_cdb;
+ }
+ LunExt->PowerState = cdb->START_STOP.PowerConditions;
+ } else
+ if (cdb->START_STOP.LoadEject == 1) {
+ KdPrint2((PRINT_PREFIX "START_STOP eject\n"));
// Eject media,
// first select device 0 or 1.
//SelectDrive(chan, DeviceNumber);
//AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
- statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_MEDIA_EJECT, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
+ command = IDE_COMMAND_MEDIA_EJECT;
+ } else
+ if (cdb->START_STOP.Start == 0) {
+ KdPrint2((PRINT_PREFIX "START_STOP standby\n"));
+ command = IDE_COMMAND_STANDBY_IMMED;
+ } else {
+ // TODO: we may need to perform hard reset (after sleep) or
+ // issue IDE_COMMAND_IDLE_IMMED in order to activate device
+ KdPrint2((PRINT_PREFIX "START_STOP activate\n"));
+
+ if(LunExt->PowerState == StartStop_Power_Sleep) {
+ UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
+ status = SRB_STATUS_SUCCESS;
+ break;
+ } else
+ if(LunExt->PowerState > StartStop_Power_Idle) {
+ KdPrint2((PRINT_PREFIX " issue IDLE\n"));
+ command = IDE_COMMAND_IDLE_IMMED;
+ } else {
+ KdPrint2((PRINT_PREFIX " do nothing\n"));
+ status = SRB_STATUS_SUCCESS;
+ break;
+ }
+ }
+ if(command) {
+ statusByte = WaitOnBaseBusy(chan);
+ statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0,
+ cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY);
+ status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS;
+ //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
+
+ } else {
+invalid_cdb:
+ KdPrint2((PRINT_PREFIX "START_STOP invalid\n"));
+ if (Srb->SenseInfoBuffer) {
+
+ PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
+
+ senseBuffer->ErrorCode = 0x70;
+ senseBuffer->Valid = 1;
+ senseBuffer->AdditionalSenseLength = 0xb;
+ senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
+ senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB;
+ senseBuffer->AdditionalSenseCodeQualifier = 0;
+
+ Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
+ Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
+ }
+ status = SRB_STATUS_ERROR;
}
- status = SRB_STATUS_SUCCESS;
break;
case SCSIOP_MEDIUM_REMOVAL:
regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
- lChannel = Srb->TargetId >> 1;
-
- regs->bDriveHeadReg &= 0x0f;
- regs->bDriveHeadReg |= (UCHAR) (((Srb->TargetId & 0x1) << 4) | 0xA0);
+ if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
+ //lChannel = Srb->TargetId >> 1;
+ } else {
+ DeviceNumber = max(DeviceNumber, 1);
+ regs->bDriveHeadReg &= 0x0f;
+ regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0);
+ }
if((regs->bOpFlags & 1) == 0) { // execute ATA command
KdPrint2((PRINT_PREFIX
- "IdeSendCommand: SCSIOP_START_STOP_UNIT PATH:LUN:TID = %#x:%#x:%#x\n",
+ "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
Srb->PathId, Srb->Lun, Srb->TargetId));
+ if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) {
+ to_lim = Srb->TimeOutValue;
+ } else {
+ if(Srb->TimeOutValue <= 2) {
+ to_lim = Srb->TimeOutValue*900;
+ } else {
+ to_lim = (Srb->TimeOutValue*999) - 500;
+ }
+ }
AtapiDisableInterrupts(deviceExtension, lChannel);
+ if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
+ // AHCI
+ statusByte = UniataAhciSendPIOCommandDirect(
+ deviceExtension,
+ lChannel,
+ DeviceNumber,
+ Srb,
+ regs,
+ ATA_WAIT_INTR,
+ to_lim
+ );
+ if(statusByte == IDE_STATUS_WRONG) {
+ goto passthrough_err;
+ }
+ if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
+ UniataAhciAbortOperation(chan);
+ goto passthrough_err;
+ }
+ goto passthrough_done;
+ }
+
+ // SATA/PATA
if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
- if((chan->lun[Srb->TargetId & 0x1]->LimitedTransferMode >= ATA_DMA)) {
+ if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) {
use_dma = TRUE;
// this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
- if(!AtapiDmaSetup(HwDeviceExtension, Srb->TargetId & 0x1, lChannel, Srb,
+ if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
(PUCHAR)(Srb->DataBuffer),
((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
use_dma = FALSE;
}
}
- AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
+ AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
AtapiStallExecution(10);
if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
if(statusByte & IDE_STATUS_ERROR) {
goto passthrough_err;
}
- AtapiDmaStart(HwDeviceExtension, (Srb->TargetId & 0x1), lChannel, Srb);
+ AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
}
ScsiPortStallExecution(1); // wait for busy to be set
- if(regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) {
- to_lim = Srb->TimeOutValue;
- } else {
- if(Srb->TimeOutValue <= 2) {
- to_lim = Srb->TimeOutValue*900;
- } else {
- to_lim = (Srb->TimeOutValue*999) - 500;
- }
- }
for(i=0; i<to_lim;i+=2) { // 2 msec from WaitOnBaseBusy()
statusByte = WaitOnBaseBusy(chan); // wait for busy to be clear, up to 2 msec
GetBaseStatus(chan, statusByte);
if(use_dma) {
AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
}
- AtapiDmaDone(deviceExtension, (Srb->TargetId & 0x1), lChannel, NULL);
+ AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL);
GetBaseStatus(chan, statusByte);
if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
}
status = SRB_STATUS_SUCCESS;
}
-
+passthrough_done:;
AtapiEnableInterrupts(deviceExtension, lChannel);
} else { // read task register
+ BOOLEAN use48;
regs = (PIDEREGS_EX) Srb->DataBuffer;
- regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
+ KdPrint2((PRINT_PREFIX
+ "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
+ Srb->PathId, Srb->Lun, Srb->TargetId));
- if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
- regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error);
- regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
- regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
+ if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) &&
+ (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) {
+ use48 = TRUE;
+ } else
+ if(Srb->DataTransferLength >= sizeof(IDEREGS)) {
+ use48 = FALSE;
} else {
- regs->bFeaturesReg = AtapiReadPort1(chan, IDX_IO1_i_Error);
- regs->bFeaturesRegH = AtapiReadPort1(chan, IDX_IO1_i_Error);
- regs->bSectorCountReg = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
- regs->bSectorCountRegH = AtapiReadPort1(chan, IDX_IO1_i_BlockCount);
- regs->bSectorNumberReg = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- regs->bSectorNumberRegH= AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
- regs->bCylLowReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- regs->bCylLowRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
- regs->bCylHighReg = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
- regs->bCylHighRegH = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
+ KdPrint2((PRINT_PREFIX " buffer too small \n"));
+ status = SRB_STATUS_DATA_OVERRUN;
+ break;
}
- regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status);
+ RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS));
+ regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0;
+ UniataSnapAtaRegs(chan, 0, regs);
+
status = SRB_STATUS_SUCCESS;
}
break;
UniataUserDeviceReset(
PHW_DEVICE_EXTENSION deviceExtension,
PHW_LU_EXTENSION LunExt,
- ULONG PathId
+ ULONG lChannel
)
{
ULONG i;
- AtapiDisableInterrupts(deviceExtension, PathId);
- if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
+ AtapiDisableInterrupts(deviceExtension, lChannel);
+ if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
+ (LunExt->PowerState != StartStop_Power_Sleep)) {
KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
- AtapiSoftReset(&(deviceExtension->chan[PathId]), LunExt->Lun);
+ AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun);
} else {
KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
- AtapiResetController__(deviceExtension, PathId, RESET_COMPLETE_NONE);
+ AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE);
for(i=0; i<deviceExtension->NumberLuns; i++) {
- deviceExtension->chan[PathId].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
+ deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
}
}
LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
- AtapiEnableInterrupts(deviceExtension, PathId);
+ AtapiEnableInterrupts(deviceExtension, lChannel);
return;
} // end UniataUserDeviceReset()
This routine is called from the SCSI port driver synchronized
with the kernel to start an IO request.
+ ->HwStartIo
Arguments:
UniAtaClearAtaReq(Srb->SrbExtension);
}
- do {
+ do { // fetch all queued commands for the channel (if valid)
lChannel = GET_CHANNEL(Srb);
//ldev = GET_LDEV(Srb);
chan = NULL;
LunExt = NULL;
DeviceNumber = GET_CDEV(Srb);
+ commPort = FALSE;
//ASSERT(deviceExtension);
//ASSERT(chan);
"AtapiStartIo: Communication port\n"));
if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
+ if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) {
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength,
+ sizeof(PINQUIRYDATA) ));
+wrong_buffer_size:
+ status = SRB_STATUS_DATA_OVERRUN;
+ goto complete_req;
+ }
+
PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
KdPrint2((PRINT_PREFIX
/* Pass IOCTL request down */
} else
if(lChannel >= deviceExtension->NumberChannels ||
- Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
- Srb->Lun) {
+ Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
+ Srb->Lun) {
- if(lChannel >= deviceExtension->NumberChannels) {
- chan = NULL;
- }
+ if(lChannel >= deviceExtension->NumberChannels) {
+ chan = NULL;
+ }
reject_srb:
//if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
- KdPrint3((PRINT_PREFIX
+ KdPrint3((PRINT_PREFIX
"AtapiStartIo: SRB rejected\n"));
- // Indicate no device found at this address.
- KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- goto complete_req;
+ // Indicate no device found at this address.
+ KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
+ status = SRB_STATUS_SELECTION_TIMEOUT;
+ goto complete_req;
//}
+ } else
+ if((deviceExtension->HwFlags & UNIATA_AHCI) &&
+ !UniataAhciChanImplemented(deviceExtension, lChannel)) {
+ chan = NULL;
}
if(!commPort) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
} else {
+
// Send command to device.
KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0]));
if(TopLevel) {
#endif //NAVO_TEST
if(atapiDev &&
- (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
+ (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* &&
+ (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0]));
status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
} else {
if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
+ ULONG targetId = (ULONG)(-1);
+
+ if(len < sizeof(SRB_IO_CONTROL)) {
+ goto wrong_buffer_size;
+ }
+
+ // extract bogus bus address
switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
-
PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
- UCHAR deviceNumber;
- KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
+ if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) {
+ goto wrong_buffer_size;
+ }
- // Version and revision per SMART 1.03
+ targetId = versionParameters->bIDEDeviceMap;
+ KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId));
+ break; }
+ case IOCTL_SCSI_MINIPORT_IDENTIFY:
+ case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
+ case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
+ case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
+ case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
+ case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
+ case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
+ case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
+ case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
+ case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE:
+ case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
+ case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
+ {
+ PSENDCMDINPARAMS cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
+
+ if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) {
+ goto wrong_buffer_size;
+ }
- versionParameters->bVersion = 1;
- versionParameters->bRevision = 1;
- versionParameters->bReserved = 0;
+ targetId = cmdInParameters->bDriveNumber;
+ KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId));
+ break; }
+ default:
+invalid_request:
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
+ ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
+ status = SRB_STATUS_INVALID_REQUEST;
+ goto complete_req;
+ } // end switch()
- // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
- versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
+ // adjust (if necessary) bus address
+ if(targetId != (ULONG)(-1)) {
// This is done because of how the IOCTL_SCSI_MINIPORT
// determines 'targetid's'. Disk.sys places the real target id value
// in the DeviceMap field. Once we do some parameter checking, the value passed
// back to the application will be determined.
- deviceNumber = versionParameters->bIDEDeviceMap;
-
+ if (deviceExtension->NumberChannels == 1) {
+ // do this for legacy controllers and legacy callers
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n"));
+ DeviceNumber = (targetId & 0x01);
+ lChannel = 0;
+ } else
if(commPort) {
+ // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
+ // due to DISK.SYS design bug, we have invalid SCSI address in SRB
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n"));
+ if(deviceExtension->HwFlags & UNIATA_AHCI) {
+ lChannel = (UCHAR)targetId / 2;
+ DeviceNumber = 0;
+ } else {
+ lChannel = (UCHAR)(targetId / 2);
+ DeviceNumber = targetId & 0x01;
+ }
+ } else {
+ // otherwise assume lChannel and DeviceNumber from Srb are ok
+ }
+ if(lChannel >= deviceExtension->NumberChannels ||
+ DeviceNumber >= deviceExtension->NumberLuns) {
KdPrint2((PRINT_PREFIX
- "AtapiStartIo: SCSIDISK IOCTL for commPort -> EXECUTE_SCSI rejected (2)\n"));
+ "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
+ targetId));
// Indicate no device found at this address.
- KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
+ goto reject_srb;
}
-
- if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) ||
- atapiDev) {
+ targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber;
+ chan = &(deviceExtension->chan[lChannel]);
+ LunExt = chan->lun[DeviceNumber];
+ if(!LunExt) {
+ goto reject_srb;
+ }
+ atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
+ if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
+ goto reject_srb;
+ }
+ }
+
+ switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
+ case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
+
+ PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
+ UCHAR deviceNumberMap;
+
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
+
+ // Version and revision per SMART 1.03
+
+ versionParameters->bVersion = 1;
+ versionParameters->bRevision = 1;
+ versionParameters->bReserved = 0;
+
+ // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
+ versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
+
+ if (atapiDev) {
+ goto invalid_request;
}
// NOTE: This will only set the bit
// 3 2 1 0
if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
- deviceNumber = 1 << lChannel;
+ deviceNumberMap = 1 << lChannel;
+ DeviceNumber = 0;
} else
if (deviceExtension->NumberChannels == 1) {
if (chan->PrimaryAddress) {
- deviceNumber = 1 << DeviceNumber;
+ deviceNumberMap = 1 << DeviceNumber;
} else {
- deviceNumber = 4 << DeviceNumber;
+ deviceNumberMap = 4 << DeviceNumber;
}
} else {
- deviceNumber = 1 << (DeviceNumber+lChannel*2);
+ deviceNumberMap = 1 << (DeviceNumber+lChannel*2);
}
- versionParameters->bIDEDeviceMap = deviceNumber;
+ versionParameters->bIDEDeviceMap = deviceNumberMap;
status = SRB_STATUS_SUCCESS;
break;
PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
- UCHAR targetId;
KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
// Extract the target.
- targetId = cmdInParameters.bDriveNumber;
KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
- if(deviceExtension->HwFlags & UNIATA_AHCI) {
- // cheat code for AHCI :)
- // upper layer assumes that we have 2 devices per channel
- // TODO: we should invent something to handle PM here
- targetId /= 2;
- }
-
- if((targetId >= deviceExtension->NumberChannels*deviceExtension->NumberLuns) ||
- !(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
- KdPrint2((PRINT_PREFIX "Error: xxx_ID_CMD for non-existant device\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
- }
switch(cmdInParameters.irDriveRegs.bCommandReg) {
case ID_CMD:
- if((deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
+ if(atapiDev) {
KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
- status = SRB_STATUS_INVALID_REQUEST;
- break;
+ goto invalid_request;
}
/* FALL THROUGH */
case ATAPI_ID_CMD:
- if(!(deviceExtension->lun[targetId].DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
+ if(!atapiDev &&
(cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
- status = SRB_STATUS_INVALID_REQUEST;
- break;
+ goto invalid_request;
}
len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
cmdOutParameters->DriverStatus.bIDEError = 0;
// Extract the identify data from the device extension.
- ScsiPortMoveMemory (cmdOutParameters->bBuffer, &deviceExtension->lun[targetId].IdentifyData,
+ ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData),
cmdOutParameters->cBufferSize);
+ if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) &&
+ (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) {
+ // adjust checksum if it is possible
+ CHAR csum = 0;
+ ULONG i;
+
+ for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) {
+ csum += (CHAR)(cmdOutParameters->bBuffer[i]);
+ }
+ cmdOutParameters->bBuffer[i] = -csum;
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n"));
+ }
KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
status = SRB_STATUS_SUCCESS;
}
break;
}
-
+/*
case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
-
+*/
+ default:
+ // *all* IOCTLs here are SMART
if(commPort) {
KdPrint2((PRINT_PREFIX
"AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
- // Indicate no device found at this address.
- KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
- status = SRB_STATUS_SELECTION_TIMEOUT;
- break;
+ }
+ if (atapiDev) {
+ goto invalid_request;
}
PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
} else {
- status = IdeSendSmartCommand(HwDeviceExtension,Srb);
+ status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId);
}
break;
- default :
+ // we should not get here, checked above
+/* default :
KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
status = SRB_STATUS_INVALID_REQUEST;
break;
-
+*/
}
} else
if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) {
if(len < pos) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
FIELD_OFFSET(UNIATA_CTL, RawData) ));
- status = SRB_STATUS_DATA_OVERRUN;
- break;
+ goto wrong_buffer_size;
}
if(AtaCtl->addr.Lun ||
if(len < pos+sizeof(AtaCtl->SetMode)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->SetMode) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
if(!AtaCtl->SetMode.ApplyImmediately) {
break;
if(len < pos+sizeof(AtaCtl->FindDelDev)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->FindDelDev) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
if(len < pos+sizeof(AtaCtl->FindDelDev)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->FindDelDev) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
LunExt->DeviceFlags = 0;
if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
if(len < pos+sizeof(AtaCtl->SetMode)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->SetMode) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
if(len < pos+sizeof(AtaCtl->GetMode)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->GetMode) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode;
AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode;
if(len < pos+sizeof(AtaCtl->Version)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->Version) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
AtaCtl->Version.Length = sizeof(GETDRVVERSION);
AtaCtl->Version.VersionMj = UNIATA_VER_MJ;
if(len < pos+sizeof(AtaCtl->AdapterInfo)) {
KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
pos+sizeof(AtaCtl->AdapterInfo) ));
- status = SRB_STATUS_DATA_OVERRUN;
- goto complete_req;
+ goto wrong_buffer_size;
}
AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO);
// Set status in SRB.
Srb->SrbStatus = (UCHAR)status;
- KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
- AtapiDmaDBSync(chan, Srb);
+ if(chan && Srb) {
+ KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
+ AtapiDmaDBSync(chan, Srb);
+ }
KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb));
UniataRemoveRequest(chan, Srb);
// Indicate command complete.
if(GlobalConfig->AtDiskSecondaryAddressClaimed)
SecondaryClaimed = TRUE;
+ if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed &&
+ !(BMList[i].ChanInitOk & 0x80)) {
+ newStatus = UniataClaimLegacyPCIIDE(i);
+ if(newStatus != STATUS_SUCCESS) {
+ KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
+ break;
+ }
+ }
+
if(g_opt_Verbose) {
_PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
}
statusToReturn = newStatus;
}
if (newStatus == STATUS_SUCCESS) {
- BMList[i].ChanInitOk |= 0x01 << c;
+ if(WinVer_Id() < WinVer_2k) {
+ // This should be done in HwInitialize under w2k+ to ensure that
+ // channel is actually initialized
+ BMList[i].ChanInitOk |= 0x01 << c;
+ } else {
+ if(BMList[i].ChanInitOk & (0x01 << c)) {
+ KdPrint2((PRINT_PREFIX "HwInit passed\n"));
+ }
+ }
/*
if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
c = 1; // this will break our for()
*/
}
}
- if(WinVer_Id() >= WinVer_2k) {
- // the following doesn't work under higher OSes
+/* if(WinVer_Id() >= WinVer_2k) {
+ // the following didn't work under higher OSes,
+ // until we move setting of FLAGS to HwInit
KdPrint2((PRINT_PREFIX "make still one attempt\n"));
continue;
- }
+ }*/
if(BMList[i].ChanInitOk & 0x03) {
- // under NT we receive status immediately, so
- // we can omit alternative init method id STATUS_SUCCESS returned
+ // Under NT we receive status immediately, so
+ // we can omit alternative init method if STATUS_SUCCESS returned.
+ // Under w2k+ we relay on flags, set in HwInitialize.
KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
break;
+ } else
+ if(WinVer_Id() >= WinVer_2k) {
+ // try AltInit if HwInit was not called immediately under w2k+
+ KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
+ } else {
+ // if (WinVer_Id() == WinVer_NT) and some error occured
+ // try alternative init method
+ KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
}
- // if (WinVer_Id() == WinVer_NT) and some error occured
- // try alternative init method
} // for(alt...)
-#if 0
- if(WinVer_WDM_Model) {
- hwInitializationData.comm.HwFindAdapter = UniataFindFakeBusMasterController;
- hwInitializationData.comm.NumberOfAccessRanges = 5;
- hwInitializationData.comm.AdapterInterfaceType = PCIBus;
-
- hwInitializationData.comm.VendorId = BMList[i].VendorId;
- hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
- hwInitializationData.comm.DeviceId = BMList[i].DeviceId;
- hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
-
- //BMList[i].channel = 0/*(UCHAR)c*/;
-
- KdPrint2((PRINT_PREFIX "Try init fake: %4.4s %4.4s \n",
- hwInitializationData.comm.VendorId,
- hwInitializationData.comm.DeviceId));
- newStatus = ScsiPortInitialize(DriverObject,
- Argument2,
- &hwInitializationData.comm,
- (PVOID)i);
- KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
- }
-#endif //0
if(g_opt_Verbose) {
if(BMList[i].ChanInitOk & 0x03) {
_PrintNtConsole(" OK\n");
hwInitializationData.comm.NumberOfAccessRanges = 6;
hwInitializationData.comm.AdapterInterfaceType = PCIBus;
- hwInitializationData.comm.VendorId = BMList[i].VendorId;
+ hwInitializationData.comm.VendorId = (PVOID)BMList[i].VendorId;
hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
- hwInitializationData.comm.DeviceId = BMList[i].DeviceId;
+ hwInitializationData.comm.DeviceId = (PVOID)BMList[i].DeviceId;
hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
BMList[i].channel = 0/*(UCHAR)c*/;
}
// 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;
}
//}
- 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))) {
} 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));
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 {
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) {
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 {
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 &&
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 ||
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)
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;
ULONG tmp32;
ULONG c; // logical channel (for Compatible Mode controllers)
BOOLEAN CheckCable = FALSE;
+ BOOLEAN GlobalInit = FALSE;
//ULONG BaseIoAddress;
switch(channel) {
/* FALLTHROUGH */
case CHAN_NOT_SPECIFIED:
c = CHAN_NOT_SPECIFIED;
+ GlobalInit = TRUE;
break;
default:
//c = channel - deviceExtension->Channel; // logical channel (for Compatible Mode controllers)
}
}
+ 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;
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 {
break;
}
- if(deviceExtension->MaxTransferMode < ATA_UDMA2)
+ if(deviceExtension->MaxTransferMode <= ATA_UDMA2)
break;
// check 80-pin cable
if(c == CHAN_NOT_SPECIFIED) {
} 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);
}
}
// 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
// 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);
#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
*/
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
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;
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;
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;
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 ||
}
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;
}
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
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));
(*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 &&
// 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);
// 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);
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);
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
/*
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;
-
- *Again = FALSE;
-
- 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;
- }
- }
-
- KdPrint2((PRINT_PREFIX "UniataFindFakeBusMasterController (WDM)\n"));
-
- 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;
- }
-
- KdPrint2((PRINT_PREFIX "busDataRead\n"));
- if (pciData.VendorID == PCI_INVALID_VENDORID) {
- KdPrint2((PRINT_PREFIX "PCI_INVALID_VENDORID\n"));
- goto exit_error;
- }
-
- 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 ));
-
- 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;
-
- _snprintf(deviceExtension->Signature, sizeof(deviceExtension->Signature),
- "UATA%8.8x/%1.1x@%8.8x", dev_id, 0xff, slotNumber);
-
- if(BaseClass != PCI_DEV_CLASS_STORAGE) {
- KdPrint2((PRINT_PREFIX "BaseClass != PCI_DEV_CLASS_STORAGE => SP_RETURN_NOT_FOUND\n"));
- goto exit_notfound;
- }
-
- KdPrint2((PRINT_PREFIX "Storage Class\n"));
-
- // 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;
+ PCM_RESOURCE_LIST resourceList;
+ UNICODE_STRING devname;
- /* 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 "UniataClaimLegacyPCIIDE:\n"));
- KdPrint2((PRINT_PREFIX "HwFlags = %x\n (1)", deviceExtension->HwFlags));
- if(!found) {
- KdPrint2((PRINT_PREFIX "!found => SP_RETURN_NOT_FOUND\n"));
- goto exit_notfound;
+ if(BMList[i].PciIdeDevObj) {
+ KdPrint2((PRINT_PREFIX "Already initialized\n"));
+ return STATUS_UNSUCCESSFUL;
}
- KdPrint2((PRINT_PREFIX "HwFlags = %x\n (2)", deviceExtension->HwFlags));
- KdPrint2((PRINT_PREFIX "found suitable device\n"));
-
- /***********************************************************/
- /***********************************************************/
- /***********************************************************/
+ RtlInitUnicodeString(&devname, L"\\Device\\uniata_PCIIDE");
+ status = IoCreateDevice(SavedDriverObject, sizeof(PCIIDE_DEVICE_EXTENSION),
+ /*NULL*/ &devname, FILE_DEVICE_UNKNOWN,
+ 0, FALSE, &(BMList[i].PciIdeDevObj));
- 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;
+ if(!NT_SUCCESS(status)) {
+ KdPrint2((PRINT_PREFIX "IoCreateDevice failed %#x\n", status));
+ return status;
}
- MasterDev = IsMasterDev(&pciData);
+ resourceList = (PCM_RESOURCE_LIST) ExAllocatePool(PagedPool,
+ sizeof(CM_RESOURCE_LIST));
- 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 (!resourceList) {
+ KdPrint2((PRINT_PREFIX "!resourceList\n"));
+ status = STATUS_INSUFFICIENT_RESOURCES;
+del_do:
+ IoDeleteDevice(BMList[i].PciIdeDevObj);
+ BMList[i].PciIdeDevObj = NULL;
+ return status;
}
- 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;
- }
+ RtlZeroMemory(
+ resourceList,
+ sizeof(CM_RESOURCE_LIST));
- 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));
+ // IoReportDetectedDevice() should be used for WDM OSes
- /*
- * 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;
- }
+ 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;
- // 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;
+ RtlInitUnicodeString(&devname, L"PCIIDE");
+ status = HalAssignSlotResources(&SavedRegPath,
+ &devname,
+ SavedDriverObject,
+ BMList[i].PciIdeDevObj,
+ PCIBus,
+ BMList[i].busNumber,
+ BMList[i].slotNumber,
+ &resourceList);
- 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;
+ if (!NT_SUCCESS(status)) {
+ KdPrint2((PRINT_PREFIX "HalAssignSlotResources failed %#x\n", status));
+ ExFreePool(resourceList);
+ goto del_do;
}
- // 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;
+ KdPrint2((PRINT_PREFIX "ok %#x\n", status));
+ BMList[i].ChanInitOk |= 0x80;
-} // end UniataFindFakeBusMasterController()
+ return status;
+} // end UniataClaimLegacyPCIIDE()
/*++
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+
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 =
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;
}
}
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)) {
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,
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"));
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"));
KdPrint2((PRINT_PREFIX " chan %d, offs %#x\n", c, offs));
+ chan->MaxTransferMode = deviceExtension->MaxTransferMode;
+
AtapiSetupLunPtrs(chan, deviceExtension, c);
chan->BaseIoAHCI_Port = deviceExtension->BaseIoAHCI_0;
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;
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(
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"));
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;
}
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);
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);
/* 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 =
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);
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;
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
} // 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(
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(
} // 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(
IN ULONG DeviceNumber
);
+VOID
+NTAPI
+UniataAhciSnapAtaRegs(
+ IN PHW_CHANNEL chan,
+ IN ULONG DeviceNumber,
+ IN OUT PIDEREGS_EX regs
+ );
+
ULONG
NTAPI
UniataAhciSetupFIS_H2D(
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(
IN ULONG Length = 0
);
+#define UniataAhciChanImplemented(deviceExtension, c) \
+ (((deviceExtension)->AHCI_PI) & (1 << c))
+
+
#endif //__UNIATA_SATA__H__
/* 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]); }
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;
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 {
#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
#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
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__
156.use http://www.winimage.com/readfi15.zip for performance checks
157.use IOCTL_SCSI_MINIPORT_IDENTIFY in atactl.exe to determine ...
PIO/DMA when no uniata.sys is installed (+++)
-158.
+158.implement .INF generator
+159.fix bug with invalid INF section under XP+ (43e2)
+160.add INF handler for SCSI\NET\VEN_UNIATA&PROD_MANAGEMENT_PORT
+161.
\ No newline at end of file
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.
#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
#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
#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)
};
} 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
-#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"