ReactOS 0.4.15-dev-8207-gd73a838
atapi.c File Reference
#include <ntddk.h>
#include "atapi.h"
#include <ntddscsi.h>
#include <ntdddisk.h>
#include <ntddstor.h>
#include <debug.h>
Include dependency graph for atapi.c:

Go to the source code of this file.

Classes

struct  _HW_DEVICE_EXTENSION
 
struct  _HW_LU_EXTENSION
 

Typedefs

typedef struct _HW_DEVICE_EXTENSION HW_DEVICE_EXTENSION
 
typedef struct _HW_DEVICE_EXTENSIONPHW_DEVICE_EXTENSION
 
typedef struct _HW_LU_EXTENSION HW_LU_EXTENSION
 
typedef struct _HW_LU_EXTENSIONPHW_LU_EXTENSION
 

Functions

PSCSI_REQUEST_BLOCK NTAPI BuildMechanismStatusSrb (IN PVOID HwDeviceExtension, IN ULONG PathId, IN ULONG TargetId)
 
PSCSI_REQUEST_BLOCK NTAPI BuildRequestSenseSrb (IN PVOID HwDeviceExtension, IN ULONG PathId, IN ULONG TargetId)
 
VOID NTAPI AtapiHwInitializeChanger (IN PVOID HwDeviceExtension, IN ULONG TargetId, IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
 
ULONG NTAPI AtapiSendCommand (IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
 
VOID NTAPI AtapiZeroMemory (IN PUCHAR Buffer, IN ULONG Count)
 
VOID NTAPI AtapiHexToString (ULONG Value, PCHAR *Buffer)
 
LONG NTAPI AtapiStringCmp (PCHAR FirstStr, PCHAR SecondStr, ULONG Count)
 
BOOLEAN NTAPI AtapiInterrupt (IN PVOID HwDeviceExtension)
 
BOOLEAN NTAPI AtapiHwInitialize (IN PVOID HwDeviceExtension)
 
ULONG NTAPI IdeBuildSenseBuffer (IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
 
VOID NTAPI IdeMediaStatus (IN BOOLEAN EnableMSN, IN PVOID HwDeviceExtension, IN ULONG Channel)
 
BOOLEAN NTAPI IssueIdentify (IN PVOID HwDeviceExtension, IN ULONG DeviceNumber, IN ULONG Channel, IN UCHAR Command)
 
BOOLEAN NTAPI SetDriveParameters (IN PVOID HwDeviceExtension, IN ULONG DeviceNumber, IN ULONG Channel)
 
BOOLEAN NTAPI AtapiResetController (IN PVOID HwDeviceExtension, IN ULONG PathId)
 
ULONG NTAPI MapError (IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
 
BOOLEAN NTAPI FindDevices (IN PVOID HwDeviceExtension, IN BOOLEAN AtapiOnly, IN ULONG Channel)
 
ULONG NTAPI AtapiParseArgumentString (IN PCHAR String, IN PCHAR KeyWord)
 
ULONG NTAPI AtapiFindController (IN PVOID HwDeviceExtension, IN PVOID Context, IN PVOID BusInformation, IN PCHAR ArgumentString, IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, OUT PBOOLEAN Again)
 
BOOLEAN NTAPI FindBrokenController (IN PVOID DeviceExtension, IN PUCHAR VendorID, IN ULONG VendorIDLength, IN PUCHAR DeviceID, IN ULONG DeviceIDLength, IN OUT PULONG FunctionNumber, IN OUT PULONG SlotNumber, IN ULONG BusNumber, OUT PBOOLEAN LastSlot)
 
ULONG NTAPI AtapiFindNativeModeController (IN PVOID HwDeviceExtension, IN PVOID Context, IN PVOID BusInformation, IN PCHAR ArgumentString, IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, OUT PBOOLEAN Again)
 
ULONG NTAPI AtapiFindPCIController (IN PVOID HwDeviceExtension, IN PVOID Context, IN PVOID BusInformation, IN PCHAR ArgumentString, IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, OUT PBOOLEAN Again)
 
ULONG NTAPI Atapi2Scsi (IN PSCSI_REQUEST_BLOCK Srb, IN char *DataBuffer, IN ULONG ByteCount)
 
VOID NTAPI AtapiCallBack (IN PVOID HwDeviceExtension)
 
ULONG NTAPI IdeSendSmartCommand (IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
 
ULONG NTAPI IdeReadWrite (IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
 
ULONG NTAPI IdeVerify (IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
 
VOID NTAPI Scsi2Atapi (IN PSCSI_REQUEST_BLOCK Srb)
 
ULONG NTAPI IdeSendCommand (IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
 
VOID NTAPI IdeMediaStatus (BOOLEAN EnableMSN, IN PVOID HwDeviceExtension, ULONG Channel)
 
BOOLEAN NTAPI AtapiStartIo (IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
 
ULONG NTAPI DriverEntry (IN PVOID DriverObject, IN PVOID Argument2)
 
VOID NTAPI AtapiHexToString (IN ULONG Value, IN OUT PCHAR *Buffer)
 

Typedef Documentation

◆ HW_DEVICE_EXTENSION

◆ HW_LU_EXTENSION

◆ PHW_DEVICE_EXTENSION

◆ PHW_LU_EXTENSION

Function Documentation

◆ Atapi2Scsi()

ULONG NTAPI Atapi2Scsi ( IN PSCSI_REQUEST_BLOCK  Srb,
IN char DataBuffer,
IN ULONG  ByteCount 
)

Definition at line 3360 of file atapi.c.

3365{
3366 ULONG bytesAdjust = 0;
3367 if (Srb->Cdb[0] == ATAPI_MODE_SENSE) {
3368
3371
3372 header->ModeDataLength = header_10->ModeDataLengthLsb;
3373 header->MediumType = header_10->MediumType;
3374
3375 //
3376 // ATAPI Mode Parameter Header doesn't have these fields.
3377 //
3378
3379 header->DeviceSpecificParameter = header_10->Reserved[0];
3380 header->BlockDescriptorLength = header_10->Reserved[1];
3381
3383 if (ByteCount > 0)
3384 ScsiPortMoveMemory(DataBuffer+sizeof(MODE_PARAMETER_HEADER),
3385 DataBuffer+sizeof(MODE_PARAMETER_HEADER_10),
3386 ByteCount);
3387
3388 //
3389 // Change ATAPI_MODE_SENSE opcode back to SCSIOP_MODE_SENSE
3390 // so that we don't convert again.
3391 //
3392
3394
3395 bytesAdjust = sizeof(MODE_PARAMETER_HEADER_10) -
3396 sizeof(MODE_PARAMETER_HEADER);
3397
3398
3399 }
3400
3401 //
3402 // Convert to words.
3403 //
3404
3405 return bytesAdjust >> 1;
3406}
struct _MODE_PARAMETER_HEADER_10 MODE_PARAMETER_HEADER_10
struct _MODE_PARAMETER_HEADER_10 * PMODE_PARAMETER_HEADER_10
#define ATAPI_MODE_SENSE
Definition: atapi.h:61
VOID NTAPI ScsiPortMoveMemory(IN PVOID WriteBuffer, IN PVOID ReadBuffer, IN ULONG Length)
Definition: scsiport.c:1314
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
struct _MODE_PARAMETER_HEADER * PMODE_PARAMETER_HEADER
UCHAR Cdb[16]
Definition: srb.h:279
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099

Referenced by AtapiInterrupt().

◆ AtapiCallBack()

VOID NTAPI AtapiCallBack ( IN PVOID  HwDeviceExtension)

Definition at line 3411 of file atapi.c.

3414{
3415 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
3416 PSCSI_REQUEST_BLOCK srb = deviceExtension->CurrentSrb;
3417 PATAPI_REGISTERS_2 baseIoAddress2;
3418 UCHAR statusByte;
3419
3420 //
3421 // If the last command was DSC restrictive, see if it's set. If so, the device is
3422 // ready for a new request. Otherwise, reset the timer and come back to here later.
3423 //
3424
3425 if (srb && (!(deviceExtension->ExpectingInterrupt))) {
3426#if DBG
3427 if (!IS_RDP((srb->Cdb[0]))) {
3428 DebugPrint((1,
3429 "AtapiCallBack: Invalid CDB marked as RDP - %x\n",
3430 srb->Cdb[0]));
3431 }
3432#endif
3433
3434 baseIoAddress2 = (PATAPI_REGISTERS_2)deviceExtension->BaseIoAddress2[srb->TargetId >> 1];
3435 if (deviceExtension->RDP) {
3436 GetStatus(baseIoAddress2, statusByte);
3437 if (statusByte & IDE_STATUS_DSC) {
3438
3440 deviceExtension,
3441 srb);
3442
3443 //
3444 // Clear current SRB.
3445 //
3446
3447 deviceExtension->CurrentSrb = NULL;
3448 deviceExtension->RDP = FALSE;
3449
3450 //
3451 // Ask for next request.
3452 //
3453
3455 deviceExtension,
3456 NULL);
3457
3458
3459 return;
3460
3461 } else {
3462
3463 DebugPrint((3,
3464 "AtapiCallBack: Requesting another timer for Op %x\n",
3465 deviceExtension->CurrentSrb->Cdb[0]));
3466
3468 HwDeviceExtension,
3470 1000);
3471 return;
3472 }
3473 }
3474 }
3475
3476 DebugPrint((2,
3477 "AtapiCallBack: Calling ISR directly due to BUSY\n"));
3478 AtapiInterrupt(HwDeviceExtension);
3479}
#define GetStatus(BaseIoAddress, Status)
Definition: atapi.h:328
#define IS_RDP(OperationCode)
Definition: atapi.h:453
struct _ATAPI_REGISTERS_2 * PATAPI_REGISTERS_2
VOID NTAPI AtapiCallBack(IN PVOID HwDeviceExtension)
Definition: atapi.c:3411
BOOLEAN NTAPI AtapiInterrupt(IN PVOID HwDeviceExtension)
Definition: atapi.c:3484
VOID __cdecl ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, IN PVOID HwDeviceExtension, IN ...)
Definition: scsiport.c:1324
#define DebugPrint(x)
Definition: classpnp.h:125
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
@ RequestTimerCall
Definition: srb.h:537
@ RequestComplete
Definition: srb.h:531
@ NextRequest
Definition: srb.h:532
#define IDE_STATUS_DSC
Definition: hwide.h:114
if(dx< 0)
Definition: linetemp.h:194
BOOLEAN ExpectingInterrupt
Definition: atapi.c:99
PIDE_REGISTERS_2 BaseIoAddress2[2]
Definition: atapi.c:35
PSCSI_REQUEST_BLOCK CurrentSrb
Definition: atapi.c:28
UCHAR TargetId
Definition: srb.h:254
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by AtapiCallBack(), and AtapiInterrupt().

◆ AtapiFindController()

ULONG NTAPI AtapiFindController ( IN PVOID  HwDeviceExtension,
IN PVOID  Context,
IN PVOID  BusInformation,
IN PCHAR  ArgumentString,
IN OUT PPORT_CONFIGURATION_INFORMATION  ConfigInfo,
OUT PBOOLEAN  Again 
)

Definition at line 2106 of file atapi.c.

2136{
2137 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
2138 PULONG adapterCount = (PULONG)Context;
2139 PUCHAR ioSpace = NULL;
2140 ULONG i;
2141 ULONG irq;
2142 ULONG portBase;
2143 ULONG retryCount;
2144 PCI_SLOT_NUMBER slotData;
2145 PPCI_COMMON_CONFIG pciData;
2147 BOOLEAN atapiOnly;
2148 UCHAR statusByte;
2149 BOOLEAN preConfig = FALSE;
2150 //
2151 // The following table specifies the ports to be checked when searching for
2152 // an IDE controller. A zero entry terminates the search.
2153 //
2154
2155 CONST ULONG AdapterAddresses[5] = {0x1F0, 0x170, 0x1e8, 0x168, 0};
2156
2157 //
2158 // The following table specifies interrupt levels corresponding to the
2159 // port addresses in the previous table.
2160 //
2161
2162 CONST ULONG InterruptLevels[5] = {14, 15, 11, 10, 0};
2163
2164 if (!deviceExtension) {
2165 return SP_RETURN_ERROR;
2166 }
2167
2168 //
2169 // Check to see if this is a special configuration environment.
2170 //
2171
2172 portBase = irq = 0;
2173 if (ArgumentString) {
2174
2175 irq = AtapiParseArgumentString(ArgumentString, "Interrupt");
2176 if (irq ) {
2177
2178 //
2179 // Both parameters must be present to proceed
2180 //
2181
2182 portBase = AtapiParseArgumentString(ArgumentString, "BaseAddress");
2183 if (!portBase) {
2184
2185 //
2186 // Try a default search for the part.
2187 //
2188
2189 irq = 0;
2190 }
2191 }
2192 }
2193
2194
2195
2196 //
2197 // Scan though the adapter address looking for adapters.
2198 //
2199 if (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart) != 0) {
2200 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
2201 ConfigInfo->AdapterInterfaceType,
2202 ConfigInfo->SystemIoBusNumber,
2203 (*ConfigInfo->AccessRanges)[0].RangeStart,
2204 (*ConfigInfo->AccessRanges)[0].RangeLength,
2205 (BOOLEAN) !((*ConfigInfo->AccessRanges)[0].RangeInMemory));
2206 *Again = FALSE;
2207 //
2208 // Since we have pre-configured information we only need to go through this loop once
2209 //
2210 preConfig = TRUE;
2211 portBase = ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart);
2212
2213 }
2214
2215
2216
2217 while (AdapterAddresses[*adapterCount] != 0) {
2218
2219 retryCount = 4;
2220
2221 for (i = 0; i < 4; i++) {
2222
2223 //
2224 // Zero device fields to ensure that if earlier devices were found,
2225 // but not claimed, the fields are cleared.
2226 //
2227
2229 }
2230
2231 //
2232 // Get the system physical address for this IO range.
2233 //
2234
2235
2236 //
2237 // Check if configInfo has the default information
2238 // if not, we go and find ourselves
2239 //
2240
2241 if (preConfig == FALSE) {
2242
2243 if (portBase) {
2244 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
2245 ConfigInfo->AdapterInterfaceType,
2246 ConfigInfo->SystemIoBusNumber,
2248 8,
2249 TRUE);
2250 } else {
2251 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
2252 ConfigInfo->AdapterInterfaceType,
2253 ConfigInfo->SystemIoBusNumber,
2254 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount]),
2255 8,
2256 TRUE);
2257 }
2258
2259 }// ConfigInfo check
2260 //
2261 // Update the adapter count.
2262 //
2263
2264 (*adapterCount)++;
2265
2266 //
2267 // Check if ioSpace accessible.
2268 //
2269
2270 if (!ioSpace) {
2271 continue;
2272 }
2273
2274retryIdentifier:
2275
2276 //
2277 // Select master.
2278 //
2279
2280 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect, 0xA0);
2281
2282 //
2283 // Check if card at this address.
2284 //
2285
2286 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow, 0xAA);
2287
2288 //
2289 // Check if identifier can be read back.
2290 //
2291
2292 if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
2293
2294 DebugPrint((2,
2295 "AtapiFindController: Identifier read back from Master (%x)\n",
2296 statusByte));
2297
2298 statusByte = ScsiPortReadPortUchar(&((PATAPI_REGISTERS_2)ioSpace)->AlternateStatus);
2299
2300 if (statusByte & IDE_STATUS_BUSY) {
2301
2302 i = 0;
2303
2304 //
2305 // Could be the TEAC in a thinkpad. Their dos driver puts it in a sleep-mode that
2306 // warm boots don't clear.
2307 //
2308
2309 do {
2311 statusByte = ScsiPortReadPortUchar(&((PATAPI_REGISTERS_1)ioSpace)->Command);
2312 DebugPrint((3,
2313 "AtapiFindController: First access to status %x\n",
2314 statusByte));
2315 } while ((statusByte & IDE_STATUS_BUSY) && ++i < 10);
2316
2317 if (retryCount-- && (!(statusByte & IDE_STATUS_BUSY))) {
2318 goto retryIdentifier;
2319 }
2320 }
2321
2322 //
2323 // Select slave.
2324 //
2325
2326 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect, 0xB0);
2327
2328 //
2329 // See if slave is present.
2330 //
2331
2332 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow, 0xAA);
2333
2334 if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
2335
2336 DebugPrint((2,
2337 "AtapiFindController: Identifier read back from Slave (%x)\n",
2338 statusByte));
2339
2340 //
2341 //
2342 // No controller at this base address.
2343 //
2344
2345 ScsiPortFreeDeviceBase(HwDeviceExtension,
2346 ioSpace);
2347
2348 continue;
2349 }
2350 }
2351
2352 //
2353 // Record base IO address.
2354 //
2355
2356 deviceExtension->BaseIoAddress1[0] = (PIDE_REGISTERS_1)(ioSpace);
2357
2358 //
2359 // Fill in the access array information only if default params are not in there.
2360 //
2361 if (preConfig == FALSE) {
2362
2363 //
2364 // An adapter has been found request another call, only if we didn't get preconfigured info.
2365 //
2366 *Again = TRUE;
2367
2368 if (portBase) {
2369 (*ConfigInfo->AccessRanges)[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(portBase);
2370 } else {
2371 (*ConfigInfo->AccessRanges)[0].RangeStart =
2372 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount - 1]);
2373 }
2374
2375 (*ConfigInfo->AccessRanges)[0].RangeLength = 8;
2376 (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
2377
2378 //
2379 // Indicate the interrupt level corresponding to this IO range.
2380 //
2381
2382 if (irq) {
2383 ConfigInfo->BusInterruptLevel = irq;
2384 } else {
2385 ConfigInfo->BusInterruptLevel = InterruptLevels[*adapterCount - 1];
2386 }
2387
2388 if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
2389 ConfigInfo->InterruptMode = LevelSensitive;
2390 } else {
2391 ConfigInfo->InterruptMode = Latched;
2392 }
2393 }
2394 //
2395 // Get the system physical address for the second IO range.
2396 //
2397
2398
2399 if (portBase) {
2400 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
2401 ConfigInfo->AdapterInterfaceType,
2402 ConfigInfo->SystemIoBusNumber,
2403 ScsiPortConvertUlongToPhysicalAddress(portBase + 0x206),
2404 1,
2405 TRUE);
2406 } else {
2407 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
2408 ConfigInfo->AdapterInterfaceType,
2409 ConfigInfo->SystemIoBusNumber,
2410 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount - 1] + 0x206),
2411 1,
2412 TRUE);
2413 }
2414
2415 deviceExtension->BaseIoAddress2[0] = (PIDE_REGISTERS_2)(ioSpace);
2416
2417 deviceExtension->NumberChannels = 1;
2418
2419 ConfigInfo->NumberOfBuses = 1;
2420 ConfigInfo->MaximumNumberOfTargets = 2;
2421
2422 //
2423 // Indicate maximum transfer length is 64k.
2424 //
2425
2426 ConfigInfo->MaximumTransferLength = 0x10000;
2427
2428 DebugPrint((1,
2429 "AtapiFindController: Found IDE at %x\n",
2430 deviceExtension->BaseIoAddress1[0]));
2431
2432
2433 //
2434 // For Daytona, the atdisk driver gets the first shot at the
2435 // primary and secondary controllers.
2436 //
2437
2438 if (preConfig == FALSE) {
2439
2440
2441 if (*adapterCount - 1 < 2) {
2442
2443 //
2444 // Determine whether this driver is being initialized by the
2445 // system or as a crash dump driver.
2446 //
2447
2448 if (ArgumentString) {
2449
2450 if (AtapiParseArgumentString(ArgumentString, "dump") == 1) {
2451 DebugPrint((3,
2452 "AtapiFindController: Crash dump\n"));
2453 atapiOnly = FALSE;
2454 deviceExtension->DriverMustPoll = TRUE;
2455 } else {
2456 DebugPrint((3,
2457 "AtapiFindController: Atapi Only\n"));
2458 atapiOnly = TRUE;
2459 deviceExtension->DriverMustPoll = FALSE;
2460 }
2461 } else {
2462
2463 DebugPrint((3,
2464 "AtapiFindController: Atapi Only\n"));
2465 atapiOnly = TRUE;
2466 deviceExtension->DriverMustPoll = FALSE;
2467 }
2468
2469 } else {
2470 atapiOnly = FALSE;
2471 }
2472
2473 //
2474 // If this is a PCI machine, pick up all devices.
2475 //
2476
2477
2478 pciData = (PPCI_COMMON_CONFIG)&pciBuffer;
2479
2480 slotData.u.bits.DeviceNumber = 0;
2481 slotData.u.bits.FunctionNumber = 0;
2482
2483 if (ScsiPortGetBusData(deviceExtension,
2485 0, // BusNumber
2486 slotData.u.AsULONG,
2487 pciData,
2488 sizeof(ULONG))) {
2489
2490 atapiOnly = FALSE;
2491
2492 //
2493 // Wait on doing this, until a reliable method
2494 // of determining support is found.
2495 //
2496
2497 #if 0
2498 deviceExtension->DWordIO = TRUE;
2499 #endif
2500
2501 } else {
2502 deviceExtension->DWordIO = FALSE;
2503 }
2504
2505 } else {
2506
2507 atapiOnly = FALSE;
2508 deviceExtension->DriverMustPoll = FALSE;
2509
2510 }// preConfig check
2511
2512 //
2513 // Save the Interrupt Mode for later use
2514 //
2515 deviceExtension->InterruptMode = ConfigInfo->InterruptMode;
2516
2517 //
2518 // Search for devices on this controller.
2519 //
2520
2521 if (FindDevices(HwDeviceExtension,
2522 atapiOnly,
2523 0)) {
2524
2525 //
2526 // Claim primary or secondary ATA IO range.
2527 //
2528
2529 if (portBase) {
2530 switch (portBase) {
2531 case 0x170:
2532 ConfigInfo->AtdiskSecondaryClaimed = TRUE;
2533 deviceExtension->PrimaryAddress = FALSE;
2534 break;
2535 case 0x1f0:
2536 ConfigInfo->AtdiskPrimaryClaimed = TRUE;
2537 deviceExtension->PrimaryAddress = TRUE;
2538 break;
2539 default:
2540 break;
2541 }
2542 } else {
2543 if (*adapterCount == 1) {
2544 ConfigInfo->AtdiskPrimaryClaimed = TRUE;
2545 deviceExtension->PrimaryAddress = TRUE;
2546 } else if (*adapterCount == 2) {
2547 ConfigInfo->AtdiskSecondaryClaimed = TRUE;
2548 deviceExtension->PrimaryAddress = FALSE;
2549 }
2550 }
2551
2552 return(SP_RETURN_FOUND);
2553 }
2554 }
2555
2556 //
2557 // The entire table has been searched and no adapters have been found.
2558 // There is no need to call again and the device base can now be freed.
2559 // Clear the adapter count for the next bus.
2560 //
2561
2562 *Again = FALSE;
2563 *(adapterCount) = 0;
2564
2565 return(SP_RETURN_NOT_FOUND);
2566
2567} // end AtapiFindController()
unsigned char BOOLEAN
#define DFLAGS_ATAPI_DEVICE
Definition: atapi.h:41
struct _IDE_REGISTERS_2 * PIDE_REGISTERS_2
#define DFLAGS_TAPE_DEVICE
Definition: atapi.h:42
#define DFLAGS_DEVICE_PRESENT
Definition: atapi.h:40
struct _IDE_REGISTERS_1 * PIDE_REGISTERS_1
ULONG NTAPI AtapiParseArgumentString(IN PCHAR String, IN PCHAR KeyWord)
Definition: atapi.c:1852
SCSI_PHYSICAL_ADDRESS NTAPI ScsiPortConvertUlongToPhysicalAddress(IN ULONG_PTR UlongAddress)
Definition: scsiport.c:529
VOID NTAPI ScsiPortWritePortUchar(IN PUCHAR Port, IN UCHAR Value)
Definition: scsiport.c:1547
VOID NTAPI ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension, IN PVOID MappedAddress)
Definition: scsiport.c:549
VOID NTAPI ScsiPortStallExecution(IN ULONG Delay)
Definition: scsiport.c:1489
UCHAR NTAPI ScsiPortReadPortUchar(IN PUCHAR Port)
Definition: scsiport.c:1390
ULONG NTAPI ScsiPortGetBusData(IN PVOID DeviceExtension, IN ULONG BusDataType, IN ULONG SystemIoBusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Length)
Definition: scsiport.c:558
PVOID NTAPI ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension, IN INTERFACE_TYPE BusType, IN ULONG SystemIoBusNumber, IN SCSI_PHYSICAL_ADDRESS IoAddress, IN ULONG NumberOfBytes, IN BOOLEAN InIoSpace)
Definition: scsiport.c:571
UCHAR pciBuffer[256]
Definition: id_probe.cpp:66
#define TRUE
Definition: types.h:120
MMRESULT FindDevices()
Definition: utils.c:159
#define SP_RETURN_ERROR
Definition: srb.h:523
#define SP_RETURN_FOUND
Definition: srb.h:522
#define ScsiPortConvertPhysicalAddressToUlong(Address)
Definition: srb.h:957
#define SP_RETURN_NOT_FOUND
Definition: srb.h:521
unsigned char irq
Definition: dsp.h:13
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define IDE_STATUS_BUSY
Definition: hwide.h:119
@ MicroChannel
Definition: hwresource.cpp:140
#define CONST
Definition: pedump.c:81
@ Latched
Definition: miniport.h:81
@ LevelSensitive
Definition: miniport.h:80
@ PCIConfiguration
Definition: miniport.h:93
Definition: shell.h:41
ULONG NumberChannels
Definition: atapi.c:68
BOOLEAN DriverMustPoll
Definition: atapi.c:111
BOOLEAN PrimaryAddress
Definition: atapi.c:124
BOOLEAN DWordIO
Definition: atapi.c:117
ULONG InterruptMode
Definition: atapi.c:47
PIDE_REGISTERS_1 BaseIoAddress1[2]
Definition: atapi.c:34
USHORT DeviceFlags[4]
Definition: atapi.c:86
struct _PCI_SLOT_NUMBER::@4035::@4036 bits
union _PCI_SLOT_NUMBER::@4035 u
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PUCHAR
Definition: typedefs.h:53
struct _PCI_COMMON_CONFIG * PPCI_COMMON_CONFIG

Referenced by AtapiFindPCIController(), and DriverEntry().

◆ AtapiFindNativeModeController()

ULONG NTAPI AtapiFindNativeModeController ( IN PVOID  HwDeviceExtension,
IN PVOID  Context,
IN PVOID  BusInformation,
IN PCHAR  ArgumentString,
IN OUT PPORT_CONFIGURATION_INFORMATION  ConfigInfo,
OUT PBOOLEAN  Again 
)

Definition at line 2712 of file atapi.c.

2743{
2744 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
2745 ULONG nativeModeAdapterTableIndex = (ULONG_PTR)Context;
2746 ULONG channel;
2747 PUCHAR ioSpace;
2748 BOOLEAN atapiOnly,
2749 deviceFound = FALSE;
2750 UCHAR statusByte;
2751 PCI_SLOT_NUMBER slotData;
2752 PCI_COMMON_CONFIG pciData;
2753 ULONG funcNumber;
2754 ULONG busDataRead;
2755 UCHAR vendorString[5];
2756 UCHAR deviceString[5];
2757 PUCHAR vendorStrPtr;
2758 PUCHAR deviceStrPtr;
2759 SCSI_PHYSICAL_ADDRESS IoBasePort1;
2760 SCSI_PHYSICAL_ADDRESS IoBasePort2;
2761
2762 //
2763 // The following table specifies the ports to be checked when searching for
2764 // an IDE controller. A zero entry terminates the search.
2765 //
2766
2767 CONST ULONG AdapterAddresses[3] = {0x1F0, 0x170, 0};
2768
2769 if (!deviceExtension) {
2770 return SP_RETURN_ERROR;
2771 }
2772
2773 *Again = FALSE;
2774
2775 slotData.u.AsULONG = 0;
2776 slotData.u.bits.DeviceNumber = ConfigInfo->SlotNumber;
2777
2778 for (funcNumber= 0; funcNumber < 8; funcNumber++) {
2779
2780 slotData.u.bits.FunctionNumber = funcNumber;
2781
2782 busDataRead = ScsiPortGetBusData(HwDeviceExtension,
2784 ConfigInfo->SystemIoBusNumber,
2785 slotData.u.AsULONG,
2786 &pciData,
2787 sizeof (pciData));
2788 if (busDataRead != sizeof (pciData)) {
2789 return SP_RETURN_ERROR;
2790 }
2791 if (pciData.VendorID == PCI_INVALID_VENDORID) {
2792 return SP_RETURN_ERROR;
2793 }
2794
2795 //
2796 // Translate hex ids to strings.
2797 //
2798
2799 vendorStrPtr = vendorString;
2800 deviceStrPtr = deviceString;
2801 AtapiHexToString(pciData.VendorID, (PCHAR*)&vendorStrPtr);
2802 AtapiHexToString(pciData.DeviceID, (PCHAR*)&deviceStrPtr);
2803
2804 //
2805 // Compare strings.
2806 //
2807
2808 if (AtapiStringCmp((PCHAR)vendorString,
2809 NativeModeAdapters[nativeModeAdapterTableIndex].VendorId,
2810 NativeModeAdapters[nativeModeAdapterTableIndex].VendorIdLength) ||
2811 AtapiStringCmp((PCHAR)deviceString,
2812 NativeModeAdapters[nativeModeAdapterTableIndex].DeviceId,
2813 NativeModeAdapters[nativeModeAdapterTableIndex].DeviceIdLength)) {
2814 continue;
2815 }
2816
2817 if (pciData.ProgIf & ((1 << 2) | (1 << 0))) {
2818 // both primary and secondary channel are in native mode
2819
2820 // Found our device
2821 *Again = TRUE;
2822
2823 break;
2824 }
2825 }
2826
2827 if (*Again != FALSE) {
2828
2829 for (channel = 0; channel < 2; channel++) {
2830
2831 IoBasePort1 = (*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeStart;
2832 IoBasePort2 = (*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeStart;
2834
2835 //
2836 // Get the system physical address for this IO range.
2837 //
2838
2839 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
2840 ConfigInfo->AdapterInterfaceType,
2841 ConfigInfo->SystemIoBusNumber,
2842 IoBasePort1,
2843 8,
2844 TRUE);
2845
2846 //
2847 // Check if ioSpace accessible.
2848 //
2849
2850 if (!ioSpace) {
2851 continue;
2852 }
2853
2854 //
2855 // Select master.
2856 //
2857
2858 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect, 0xA0);
2859
2860 //
2861 // Check if card at this address.
2862 //
2863
2864 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow, 0xAA);
2865
2866 //
2867 // Check if identifier can be read back.
2868 //
2869
2870 if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
2871
2872 DebugPrint((2,
2873 "AtapiFindPciController: Identifier read back from Master (%x)\n",
2874 statusByte));
2875
2876
2877 //
2878 // Select slave.
2879 //
2880
2881 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect, 0xB0);
2882
2883 //
2884 // See if slave is present.
2885 //
2886
2887 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow, 0xAA);
2888
2889 if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
2890
2891 DebugPrint((2,
2892 "AtapiFindPciController: Identifier read back from Slave (%x)\n",
2893 statusByte));
2894
2895 //
2896 //
2897 // No controller at this base address.
2898 //
2899
2900 ScsiPortFreeDeviceBase(HwDeviceExtension,
2901 ioSpace);
2902
2903 //
2904 // If the chip is there, but we couldn't find the primary channel, try the secondary.
2905 // If we couldn't find a secondary, who cares.
2906 //
2907
2908 if (channel == 1) {
2909
2910 goto setStatusAndExit;
2911
2912 } else {
2913 continue;
2914 }
2915 }
2916 }
2917
2918 //
2919 // Record base IO address.
2920 //
2921
2922 deviceExtension->BaseIoAddress1[channel] = (PIDE_REGISTERS_1)(ioSpace);
2923
2924 //
2925 // Get the system physical address for the second IO range.
2926 //
2927
2928 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
2929 ConfigInfo->AdapterInterfaceType,
2930 ConfigInfo->SystemIoBusNumber,
2931 IoBasePort2,
2932 1,
2933 TRUE);
2934
2935 deviceExtension->BaseIoAddress2[channel] = (PIDE_REGISTERS_2)(ioSpace);
2936
2937 deviceExtension->NumberChannels = 2;
2938
2939 //
2940 // Indicate only one bus.
2941 //
2942
2943 ConfigInfo->NumberOfBuses = 1;
2944
2945 //
2946 // Indicate four devices can be attached to the adapter, since we
2947 // have to serialize access to the two channels.
2948 //
2949
2950 ConfigInfo->MaximumNumberOfTargets = 4;
2951
2952 //
2953 // Indicate maximum transfer length is 64k.
2954 //
2955
2956 ConfigInfo->MaximumTransferLength = 0x10000;
2957
2958 DebugPrint((1,
2959 "AtapiFindPciController: Found native mode IDE at %x\n",
2960 deviceExtension->BaseIoAddress1[channel]));
2961
2962 //
2963 // Since we will always pick up this part, and not atdisk, so indicate.
2964 //
2965
2966 atapiOnly = FALSE;
2967
2968 //
2969 // Save the Interrupt Mode for later use
2970 //
2971 deviceExtension->InterruptMode = ConfigInfo->InterruptMode;
2972
2973 //
2974 // Search for devices on this controller.
2975 //
2976
2977 if (FindDevices(HwDeviceExtension,
2978 atapiOnly,
2979 channel)){
2980 deviceFound = TRUE;
2981 }
2982
2983 //
2984 // Claim primary or secondary ATA IO range.
2985 //
2986
2987 if (ScsiPortConvertPhysicalAddressToUlong(IoBasePort1) == AdapterAddresses[0]) {
2988 ConfigInfo->AtdiskPrimaryClaimed = TRUE;
2989 deviceExtension->PrimaryAddress = TRUE;
2990
2991 } else if (ScsiPortConvertPhysicalAddressToUlong(IoBasePort2) == AdapterAddresses[1]) {
2992 ConfigInfo->AtdiskSecondaryClaimed = TRUE;
2993 deviceExtension->PrimaryAddress = FALSE;
2994 }
2995 }
2996 }
2997
2998setStatusAndExit:
2999
3000 if (deviceFound) {
3001
3002 *Again = TRUE;
3003 return SP_RETURN_FOUND;
3004 }
3005
3006 *Again = FALSE;
3007 return SP_RETURN_NOT_FOUND;
3008
3009} // end AtapiFindNativeModeController()
NATIVE_MODE_CONTROLLER_INFORMATION const NativeModeAdapters[]
Definition: atapi.h:319
VOID NTAPI AtapiHexToString(ULONG Value, PCHAR *Buffer)
#define ULONG_PTR
Definition: config.h:101
char * PCHAR
Definition: typedefs.h:51
#define AtapiStringCmp(s1, s2, n)
Definition: atapi.h:1256
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define PCI_INVALID_VENDORID
Definition: iotypes.h:3601

Referenced by DriverEntry().

◆ AtapiFindPCIController()

ULONG NTAPI AtapiFindPCIController ( IN PVOID  HwDeviceExtension,
IN PVOID  Context,
IN PVOID  BusInformation,
IN PCHAR  ArgumentString,
IN OUT PPORT_CONFIGURATION_INFORMATION  ConfigInfo,
OUT PBOOLEAN  Again 
)

Definition at line 3014 of file atapi.c.

3045{
3046 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
3047 PULONG adapterCount = (PULONG)Context;
3048 ULONG channel = 0;
3049 static ULONG functionNumber,
3050 slotNumber,
3052 ULONG i,j;
3053 PUCHAR ioSpace;
3054 BOOLEAN atapiOnly,
3055 lastSlot,
3056 controllerFound = FALSE,
3057 deviceFound = FALSE;
3058 UCHAR statusByte;
3059
3060 //
3061 // The following table specifies the ports to be checked when searching for
3062 // an IDE controller. A zero entry terminates the search.
3063 //
3064
3065 CONST ULONG AdapterAddresses[5] = {0x1F0, 0x170, 0x1e8, 0x168, 0};
3066
3067 //
3068 // The following table specifies interrupt levels corresponding to the
3069 // port addresses in the previous table.
3070 //
3071
3072 CONST ULONG InterruptLevels[5] = {14, 15, 11, 10, 0};
3073
3074 if (!deviceExtension) {
3075 return SP_RETURN_ERROR;
3076 }
3077
3078 //
3079 // Since scsiport will call this function first before it calls AtapiFindController
3080 // we need to bypass it if we have data installed in ConfigInfo, by the pcmcia driver.
3081 // In that case atapifindcontroller should be called first.
3082 // Instead of modifying atapi driverEntry to search of PCIBus first (now its ISA)
3083 // the check is put here.
3084 //
3085
3086 if (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart) != 0) {
3087
3088 return AtapiFindController(HwDeviceExtension,
3089 Context,
3091 ArgumentString,
3092 ConfigInfo,
3093 Again);
3094 }
3095
3096
3097 //
3098 // Gronk PCI config space looking for the broken PCI IDE controllers that have only
3099 // one FIFO for both channels.
3100 // Don't do this. It's incorrect and nasty. It has to be done to work around these
3101 // broken parts, no other reason can justify this.
3102 //
3103
3104 for (i = controllers; i < BROKEN_ADAPTERS; i++) {
3105
3106 //
3107 // Determine if both channels are enabled and have devices.
3108 //
3109
3110 lastSlot = FALSE;
3111
3112 if (FindBrokenController(deviceExtension,
3113 (PUCHAR)BrokenAdapters[i].VendorId,
3114 BrokenAdapters[i].VendorIdLength,
3115 (PUCHAR)BrokenAdapters[i].DeviceId,
3116 BrokenAdapters[i].DeviceIdLength,
3117 &functionNumber,
3118 &slotNumber,
3119 ConfigInfo->SystemIoBusNumber,
3120 &lastSlot)) {
3121
3122 slotNumber++;
3123 functionNumber = 0;
3124 controllerFound = TRUE;
3125
3126 DebugPrint((1,
3127 "Found broken PCI IDE controller: VendorId %s, DeviceId %s\n",
3128 BrokenAdapters[i].VendorId,
3129 BrokenAdapters[i].DeviceId));
3130
3131 if (AdapterAddresses[*adapterCount] != 0) {
3132
3133 for (j = 0; j < 2; j++) {
3134
3135 //
3136 // Get the system physical address for this IO range.
3137 //
3138
3139 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
3140 ConfigInfo->AdapterInterfaceType,
3141 ConfigInfo->SystemIoBusNumber,
3142 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount]),
3143 8,
3144 TRUE);
3145
3146 //
3147 // Update the adapter count.
3148 //
3149
3150 (*adapterCount)++;
3151
3152 //
3153 // Check if ioSpace accessible.
3154 //
3155
3156 if (!ioSpace) {
3157 continue;
3158 }
3159
3160 //
3161 // Select master.
3162 //
3163
3164 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect, 0xA0);
3165
3166 //
3167 // Check if card at this address.
3168 //
3169
3170 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow, 0xAA);
3171
3172 //
3173 // Check if identifier can be read back.
3174 //
3175
3176 if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
3177
3178 DebugPrint((2,
3179 "AtapiFindPciController: Identifier read back from Master (%x)\n",
3180 statusByte));
3181
3182
3183 //
3184 // Select slave.
3185 //
3186
3187 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->DriveSelect, 0xB0);
3188
3189 //
3190 // See if slave is present.
3191 //
3192
3193 ScsiPortWritePortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow, 0xAA);
3194
3195 if ((statusByte = ScsiPortReadPortUchar(&((PIDE_REGISTERS_1)ioSpace)->CylinderLow)) != 0xAA) {
3196
3197 DebugPrint((2,
3198 "AtapiFindPciController: Identifier read back from Slave (%x)\n",
3199 statusByte));
3200
3201 //
3202 //
3203 // No controller at this base address.
3204 //
3205
3206 ScsiPortFreeDeviceBase(HwDeviceExtension,
3207 ioSpace);
3208
3209 //
3210 // If the chip is there, but we couldn't find the primary channel, try the secondary.
3211 // If we couldn't find a secondary, who cares.
3212 //
3213
3214 if (j == 1) {
3215
3216 goto setStatusAndExit;
3217
3218 } else {
3219 continue;
3220 }
3221 }
3222 }
3223
3224 if (controllerFound) {
3225
3226 //
3227 // Record base IO address.
3228 //
3229
3230 deviceExtension->BaseIoAddress1[channel] = (PIDE_REGISTERS_1)(ioSpace);
3231
3232 //
3233 // Fill in the access array information.
3234 //
3235
3236 (*ConfigInfo->AccessRanges)[channel].RangeStart =
3237 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount - 1]);
3238
3239 (*ConfigInfo->AccessRanges)[channel].RangeLength = 8;
3240 (*ConfigInfo->AccessRanges)[channel].RangeInMemory = FALSE;
3241
3242 //
3243 // Indicate the interrupt level corresponding to this IO range.
3244 //
3245
3246 if (channel == 0) {
3247 ConfigInfo->BusInterruptLevel = InterruptLevels[*adapterCount - 1];
3248 ConfigInfo->InterruptMode = Latched;
3249 } else {
3250 ConfigInfo->BusInterruptLevel2 = InterruptLevels[*adapterCount - 1];
3251 ConfigInfo->InterruptMode2 = Latched;
3252 }
3253
3254 //
3255 // Get the system physical address for the second IO range.
3256 //
3257
3258 ioSpace = ScsiPortGetDeviceBase(HwDeviceExtension,
3259 ConfigInfo->AdapterInterfaceType,
3260 ConfigInfo->SystemIoBusNumber,
3261 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount - 1] + 0x206),
3262 1,
3263 TRUE);
3264
3265 deviceExtension->BaseIoAddress2[channel] = (PIDE_REGISTERS_2)(ioSpace);
3266
3267 deviceExtension->NumberChannels = 2;
3268
3269 //
3270 // Indicate only one bus.
3271 //
3272
3273 ConfigInfo->NumberOfBuses = 1;
3274
3275 //
3276 // Indicate four devices can be attached to the adapter, since we
3277 // have to serialize access to the two channels.
3278 //
3279
3280 ConfigInfo->MaximumNumberOfTargets = 4;
3281
3282 //
3283 // Indicate maximum transfer length is 64k.
3284 //
3285
3286 ConfigInfo->MaximumTransferLength = 0x10000;
3287
3288 DebugPrint((1,
3289 "AtapiFindPciController: Found broken IDE at %x\n",
3290 deviceExtension->BaseIoAddress1[channel]));
3291
3292 //
3293 // Since we will always pick up this part, and not atdisk, so indicate.
3294 //
3295
3296 atapiOnly = FALSE;
3297
3298 //
3299 // Save the Interrupt Mode for later use
3300 //
3301 deviceExtension->InterruptMode = ConfigInfo->InterruptMode;
3302
3303 //
3304 // Search for devices on this controller.
3305 //
3306
3307 if (FindDevices(HwDeviceExtension,
3308 atapiOnly,
3309 channel++)){
3310 deviceFound = TRUE;
3311 }
3312
3313 //
3314 // Claim primary or secondary ATA IO range.
3315 //
3316
3317 if (*adapterCount == 1) {
3318 ConfigInfo->AtdiskPrimaryClaimed = TRUE;
3319 deviceExtension->PrimaryAddress = TRUE;
3320
3321 } else if (*adapterCount == 2) {
3322 ConfigInfo->AtdiskSecondaryClaimed = TRUE;
3323 deviceExtension->PrimaryAddress = FALSE;
3324 }
3325 }
3326 }
3327 }
3328 }
3329
3330setStatusAndExit:
3331
3332 if (lastSlot) {
3333 slotNumber = 0;
3334 functionNumber = 0;
3335 }
3336
3337 controllers = i;
3338
3339 if (controllerFound && deviceFound) {
3340
3341 *Again = TRUE;
3342 return SP_RETURN_FOUND;
3343 }
3344 }
3345
3346
3347 //
3348 // The entire table has been searched and no adapters have been found.
3349 //
3350
3351 *Again = FALSE;
3352
3353 return SP_RETURN_NOT_FOUND;
3354
3355} // end AtapiFindPCIController()
#define BROKEN_ADAPTERS
Definition: atapi.h:310
BROKEN_CONTROLLER_INFORMATION const BrokenAdapters[]
Definition: atapi.h:305
BOOLEAN NTAPI FindBrokenController(IN PVOID DeviceExtension, IN PUCHAR VendorID, IN ULONG VendorIDLength, IN PUCHAR DeviceID, IN ULONG DeviceIDLength, IN OUT PULONG FunctionNumber, IN OUT PULONG SlotNumber, IN ULONG BusNumber, OUT PBOOLEAN LastSlot)
Definition: atapi.c:2575
ULONG NTAPI AtapiFindController(IN PVOID HwDeviceExtension, IN PVOID Context, IN PVOID BusInformation, IN PCHAR ArgumentString, IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, OUT PBOOLEAN Again)
Definition: atapi.c:2106
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
_In_ WDFDEVICE _In_ PPNP_BUS_INFORMATION BusInformation
Definition: wdfdevice.h:3915
struct @613 controllers[XUSER_MAX_COUNT]

Referenced by DriverEntry().

◆ AtapiHexToString() [1/2]

VOID NTAPI AtapiHexToString ( IN ULONG  Value,
IN OUT PCHAR Buffer 
)

Definition at line 6396 of file atapi.c.

6400{
6401 PCHAR string;
6402 PCHAR firstdig;
6403 CHAR temp;
6404 ULONG i;
6405 USHORT digval;
6406
6407 string = *Buffer;
6408
6409 firstdig = string;
6410
6411 for (i = 0; i < 4; i++) {
6412 digval = (USHORT)(Value % 16);
6413 Value /= 16;
6414
6415 //
6416 // convert to ascii and store. Note this will create
6417 // the buffer with the digits reversed.
6418 //
6419
6420 if (digval > 9) {
6421 *string++ = (char) (digval - 10 + 'a');
6422 } else {
6423 *string++ = (char) (digval + '0');
6424 }
6425
6426 }
6427
6428 //
6429 // Reverse the digits.
6430 //
6431
6432 *string-- = '\0';
6433
6434 do {
6435 temp = *string;
6436 *string = *firstdig;
6437 *firstdig = temp;
6438 --string;
6439 ++firstdig;
6440 } while (firstdig < string);
6441}
Definition: bufpool.h:45
unsigned char
Definition: typeof.h:29
char string[160]
Definition: util.h:11
unsigned short USHORT
Definition: pedump.c:61
static calc_node_t temp
Definition: rpn_ieee.c:38
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
char CHAR
Definition: xmlstorage.h:175

◆ AtapiHexToString() [2/2]

VOID NTAPI AtapiHexToString ( ULONG  Value,
PCHAR Buffer 
)

◆ AtapiHwInitialize()

BOOLEAN NTAPI AtapiHwInitialize ( IN PVOID  HwDeviceExtension)

Definition at line 1282 of file atapi.c.

1301{
1302 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
1303 PIDE_REGISTERS_1 baseIoAddress;
1304 ULONG i;
1305 UCHAR statusByte, errorByte;
1306
1307
1308 for (i = 0; i < 4; i++) {
1309 if (deviceExtension->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT) {
1310
1311 if (!(deviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE)) {
1312
1313 //
1314 // Enable media status notification
1315 //
1316
1317 baseIoAddress = deviceExtension->BaseIoAddress1[i >> 1];
1318
1319 IdeMediaStatus(TRUE,HwDeviceExtension,i);
1320
1321 //
1322 // If supported, setup Multi-block transfers.
1323 //
1324 if (deviceExtension->MaximumBlockXfer[i]) {
1325
1326 //
1327 // Select the device.
1328 //
1329
1330 ScsiPortWritePortUchar(&baseIoAddress->DriveSelect,
1331 (UCHAR)(((i & 0x1) << 4) | 0xA0));
1332
1333 //
1334 // Setup sector count to reflect the # of blocks.
1335 //
1336
1337 ScsiPortWritePortUchar(&baseIoAddress->BlockCount,
1338 deviceExtension->MaximumBlockXfer[i]);
1339
1340 //
1341 // Issue the command.
1342 //
1343
1344 ScsiPortWritePortUchar(&baseIoAddress->Command,
1346
1347 //
1348 // Wait for busy to drop.
1349 //
1350
1351 WaitOnBaseBusy(baseIoAddress,statusByte);
1352
1353 //
1354 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
1355 // command was aborted.
1356 //
1357
1358 if (statusByte & IDE_STATUS_ERROR) {
1359
1360 //
1361 // Read the error register.
1362 //
1363
1364 errorByte = ScsiPortReadPortUchar((PUCHAR)baseIoAddress + 1);
1365
1366 DebugPrint((1,
1367 "AtapiHwInitialize: Error setting multiple mode. Status %x, error byte %x\n",
1368 statusByte,
1369 errorByte));
1370 //
1371 // Adjust the devExt. value, if necessary.
1372 //
1373
1374 deviceExtension->MaximumBlockXfer[i] = 0;
1375
1376 } else {
1377 DebugPrint((2,
1378 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
1379 i,
1380 deviceExtension->MaximumBlockXfer[i]));
1381 }
1382 }
1383 } else if (!(deviceExtension->DeviceFlags[i] & DFLAGS_CHANGER_INITED)){
1384
1385 ULONG j;
1386 UCHAR vendorId[26];
1387
1388 //
1389 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
1390 //
1391
1392 for (j = 0; j < 13; j += 2) {
1393
1394 //
1395 // Build a buffer based on the identify data.
1396 //
1397
1398 vendorId[j] = ((PUCHAR)deviceExtension->IdentifyData[i].ModelNumber)[j + 1];
1399 vendorId[j+1] = ((PUCHAR)deviceExtension->IdentifyData[i].ModelNumber)[j];
1400 }
1401
1402 if (!AtapiStringCmp ((PCHAR)vendorId, "CD-ROM CDR", 11)) {
1403
1404 //
1405 // Inquiry string for older model had a '-', newer is '_'
1406 //
1407
1408 if (vendorId[12] == 'C') {
1409
1410 //
1411 // Torisan changer. Set the bit. This will be used in several places
1412 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
1413 //
1414
1416 deviceExtension->DiscsPresent[i] = 3;
1417 }
1418 }
1419 }
1420
1421 //
1422 // We need to get our device ready for action before
1423 // returning from this function
1424 //
1425 // According to the atapi spec 2.5 or 2.6, an atapi device
1426 // clears its status BSY bit when it is ready for atapi commands.
1427 // However, some devices (Panasonic SQ-TC500N) are still
1428 // not ready even when the status BSY is clear. They don't react
1429 // to atapi commands.
1430 //
1431 // Since there is really no other indication that tells us
1432 // the drive is really ready for action. We are going to check BSY
1433 // is clear and then just wait for an arbitrary amount of time!
1434 //
1435 if (deviceExtension->DeviceFlags[i] & DFLAGS_ATAPI_DEVICE) {
1436 //PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[i >> 1];
1437 PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[i >> 1];
1438 ULONG waitCount;
1439
1440 // have to get out of the loop sometime!
1441 // 10000 * 100us = 1000,000us = 1000ms = 1s
1442 waitCount = 10000;
1443 GetStatus(baseIoAddress2, statusByte);
1444 while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
1445 //
1446 // Wait for Busy to drop.
1447 //
1449 GetStatus(baseIoAddress2, statusByte);
1450 waitCount--;
1451 }
1452
1453 // 5000 * 100us = 500,000us = 500ms = 0.5s
1454 waitCount = 5000;
1455 do {
1457 } while (waitCount--);
1458 }
1459 }
1460 }
1461
1462 return TRUE;
1463
1464} // end AtapiHwInitialize()
#define DFLAGS_SANYO_ATAPI_CHANGER
Definition: atapi.h:49
#define DFLAGS_CHANGER_INITED
Definition: atapi.h:50
#define WaitOnBaseBusy(BaseIoAddress, Status)
Definition: atapi.h:373
#define IDE_COMMAND_SET_MULTIPLE
Definition: atapi.h:113
VOID NTAPI IdeMediaStatus(IN BOOLEAN EnableMSN, IN PVOID HwDeviceExtension, IN ULONG Channel)
#define IDE_STATUS_ERROR
Definition: hwide.h:110
ULONG DiscsPresent[4]
Definition: atapi.c:80
UCHAR MaximumBlockXfer[4]
Definition: atapi.c:93
IDENTIFY_DATA2 IdentifyData[4]
Definition: atapi.c:146
USHORT ModelNumber[20]
Definition: atapi.h:262
UCHAR BlockCount
Definition: atapi.h:18
UCHAR Command
Definition: atapi.h:23
UCHAR DriveSelect
Definition: atapi.h:22

Referenced by AtapiResetController(), and DriverEntry().

◆ AtapiHwInitializeChanger()

VOID NTAPI AtapiHwInitializeChanger ( IN PVOID  HwDeviceExtension,
IN ULONG  TargetId,
IN PMECHANICAL_STATUS_INFORMATION_HEADER  MechanismStatus 
)

Definition at line 1469 of file atapi.c.

1473{
1474 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
1475
1476 if (MechanismStatus) {
1477 deviceExtension->DiscsPresent[TargetId] = MechanismStatus->NumberAvailableSlots;
1478 if (deviceExtension->DiscsPresent[TargetId] > 1) {
1479 deviceExtension->DeviceFlags[TargetId] |= DFLAGS_ATAPI_CHANGER;
1480 }
1481 }
1482 return;
1483}
#define DFLAGS_ATAPI_CHANGER
Definition: atapi.h:48
_In_ ULONG _In_ BOOLEAN _In_ ULONG _In_ UCHAR _In_ UCHAR TargetId
Definition: classpnp.h:1314

Referenced by AtapiInterrupt(), and AtapiSendCommand().

◆ AtapiInterrupt()

BOOLEAN NTAPI AtapiInterrupt ( IN PVOID  HwDeviceExtension)

Definition at line 3484 of file atapi.c.

3504{
3505 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
3506 PSCSI_REQUEST_BLOCK srb = deviceExtension->CurrentSrb;
3507 PATAPI_REGISTERS_1 baseIoAddress1;
3508 PATAPI_REGISTERS_2 baseIoAddress2;
3509 ULONG wordCount = 0, wordsThisInterrupt = 256;
3510 ULONG status;
3511 ULONG i;
3512 UCHAR statusByte,interruptReason;
3513 BOOLEAN atapiDev = FALSE;
3514
3515 if (srb) {
3516 baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[srb->TargetId >> 1];
3517 baseIoAddress2 = (PATAPI_REGISTERS_2)deviceExtension->BaseIoAddress2[srb->TargetId >> 1];
3518 } else {
3519 DebugPrint((2,
3520 "AtapiInterrupt: CurrentSrb is NULL\n"));
3521 //
3522 // We can only support one ATAPI IDE master on Carolina, so find
3523 // the base address that is non NULL and clear its interrupt before
3524 // returning.
3525 //
3526
3527#ifdef _PPC_
3528
3529 if ((PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[0] != NULL) {
3530 baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[0];
3531 } else {
3532 baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[1];
3533 }
3534
3535 GetBaseStatus(baseIoAddress1, statusByte);
3536#else
3537
3538 if (deviceExtension->InterruptMode == LevelSensitive) {
3539 if (deviceExtension->BaseIoAddress1[0] != NULL) {
3540 baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[0];
3541 GetBaseStatus(baseIoAddress1, statusByte);
3542 }
3543 if (deviceExtension->BaseIoAddress1[1] != NULL) {
3544 baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[1];
3545 GetBaseStatus(baseIoAddress1, statusByte);
3546 }
3547 }
3548#endif
3549 return FALSE;
3550 }
3551
3552 if (!(deviceExtension->ExpectingInterrupt)) {
3553
3554 DebugPrint((3,
3555 "AtapiInterrupt: Unexpected interrupt.\n"));
3556 return FALSE;
3557 }
3558
3559 //
3560 // Clear interrupt by reading status.
3561 //
3562
3563 GetBaseStatus(baseIoAddress1, statusByte);
3564
3565 DebugPrint((3,
3566 "AtapiInterrupt: Entered with status (%x)\n",
3567 statusByte));
3568
3569
3570 if (statusByte & IDE_STATUS_BUSY) {
3571 if (deviceExtension->DriverMustPoll) {
3572
3573 //
3574 // Crashdump is polling and we got caught with busy asserted.
3575 // Just go away, and we will be polled again shortly.
3576 //
3577
3578 DebugPrint((3,
3579 "AtapiInterrupt: Hit BUSY while polling during crashdump.\n"));
3580
3581 return TRUE;
3582 }
3583
3584 //
3585 // Ensure BUSY is non-asserted.
3586 //
3587
3588 for (i = 0; i < 10; i++) {
3589
3590 GetBaseStatus(baseIoAddress1, statusByte);
3591 if (!(statusByte & IDE_STATUS_BUSY)) {
3592 break;
3593 }
3595 }
3596
3597 if (i == 10) {
3598
3599 DebugPrint((2,
3600 "AtapiInterrupt: BUSY on entry. Status %x, Base IO %x\n",
3601 statusByte,
3602 baseIoAddress1));
3603
3605 HwDeviceExtension,
3607 500);
3608 return TRUE;
3609 }
3610 }
3611
3612
3613 //
3614 // Check for error conditions.
3615 //
3616
3617 if (statusByte & IDE_STATUS_ERROR) {
3618
3619 if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
3620
3621 //
3622 // Fail this request.
3623 //
3624
3626 goto CompleteRequest;
3627 }
3628 }
3629
3630 //
3631 // check reason for this interrupt.
3632 //
3633
3634 if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
3635
3636 interruptReason = (ScsiPortReadPortUchar(&baseIoAddress1->InterruptReason) & 0x3);
3637 atapiDev = TRUE;
3638 wordsThisInterrupt = 256;
3639
3640 } else {
3641
3642 if (statusByte & IDE_STATUS_DRQ) {
3643
3644 if (deviceExtension->MaximumBlockXfer[srb->TargetId]) {
3645 wordsThisInterrupt = 256 * deviceExtension->MaximumBlockXfer[srb->TargetId];
3646
3647 }
3648
3649 if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
3650
3651 interruptReason = 0x2;
3652
3653 } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
3654 interruptReason = 0x0;
3655
3656 } else {
3658 goto CompleteRequest;
3659 }
3660
3661 } else if (statusByte & IDE_STATUS_BUSY) {
3662
3663 return FALSE;
3664
3665 } else {
3666
3667 if (deviceExtension->WordsLeft) {
3668
3669 ULONG k;
3670
3671 //
3672 // Funky behaviour seen with PCI IDE (not all, just one).
3673 // The ISR hits with DRQ low, but comes up later.
3674 //
3675
3676 for (k = 0; k < 5000; k++) {
3677 GetStatus(baseIoAddress2,statusByte);
3678 if (!(statusByte & IDE_STATUS_DRQ)) {
3680 } else {
3681 break;
3682 }
3683 }
3684
3685 if (k == 5000) {
3686
3687 //
3688 // reset the controller.
3689 //
3690
3691 DebugPrint((1,
3692 "AtapiInterrupt: Resetting due to DRQ not up. Status %x, Base IO %x\n",
3693 statusByte,
3694 baseIoAddress1));
3695
3696 AtapiResetController(HwDeviceExtension,srb->PathId);
3697 return TRUE;
3698 } else {
3699
3700 interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x2 : 0x0;
3701 }
3702
3703 } else {
3704
3705 //
3706 // Command complete - verify, write, or the SMART enable/disable.
3707 //
3708 // Also get_media_status
3709
3710 interruptReason = 0x3;
3711 }
3712 }
3713 }
3714
3715 if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) {
3716
3717 //
3718 // Write the packet.
3719 //
3720
3721 DebugPrint((2,
3722 "AtapiInterrupt: Writing Atapi packet.\n"));
3723
3724 //
3725 // Send CDB to device.
3726 //
3727
3728 WriteBuffer(baseIoAddress1,
3729 (PUSHORT)srb->Cdb,
3730 6);
3731
3732 return TRUE;
3733
3734 } else if (interruptReason == 0x0 && (statusByte & IDE_STATUS_DRQ)) {
3735
3736 //
3737 // Write the data.
3738 //
3739
3740 if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
3741
3742 //
3743 // Pick up bytes to transfer and convert to words.
3744 //
3745
3746 wordCount =
3747 ScsiPortReadPortUchar(&baseIoAddress1->ByteCountLow);
3748
3749 wordCount |=
3750 ScsiPortReadPortUchar(&baseIoAddress1->ByteCountHigh) << 8;
3751
3752 //
3753 // Covert bytes to words.
3754 //
3755
3756 wordCount >>= 1;
3757
3758 if (wordCount != deviceExtension->WordsLeft) {
3759 DebugPrint((3,
3760 "AtapiInterrupt: %d words requested; %d words xferred\n",
3761 deviceExtension->WordsLeft,
3762 wordCount));
3763 }
3764
3765 //
3766 // Verify this makes sense.
3767 //
3768
3769 if (wordCount > deviceExtension->WordsLeft) {
3770 wordCount = deviceExtension->WordsLeft;
3771 }
3772
3773 } else {
3774
3775 //
3776 // IDE path. Check if words left is at least 256.
3777 //
3778
3779 if (deviceExtension->WordsLeft < wordsThisInterrupt) {
3780
3781 //
3782 // Transfer only words requested.
3783 //
3784
3785 wordCount = deviceExtension->WordsLeft;
3786
3787 } else {
3788
3789 //
3790 // Transfer next block.
3791 //
3792
3793 wordCount = wordsThisInterrupt;
3794 }
3795 }
3796
3797 //
3798 // Ensure that this is a write command.
3799 //
3800
3801 if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
3802
3803 DebugPrint((3,
3804 "AtapiInterrupt: Write interrupt\n"));
3805
3806 WaitOnBusy(baseIoAddress2,statusByte);
3807
3808 if (atapiDev || !deviceExtension->DWordIO) {
3809
3810 WriteBuffer(baseIoAddress1,
3811 deviceExtension->DataBuffer,
3812 wordCount);
3813 } else {
3814
3815 PIDE_REGISTERS_3 address3 = (PIDE_REGISTERS_3)baseIoAddress1;
3816
3817 WriteBuffer2(address3,
3818 (PULONG)(deviceExtension->DataBuffer),
3819 wordCount / 2);
3820 }
3821 } else {
3822
3823 DebugPrint((1,
3824 "AtapiInterrupt: Int reason %x, but srb is for a write %x.\n",
3825 interruptReason,
3826 srb));
3827
3828 //
3829 // Fail this request.
3830 //
3831
3833 goto CompleteRequest;
3834 }
3835
3836
3837 //
3838 // Advance data buffer pointer and bytes left.
3839 //
3840
3841 deviceExtension->DataBuffer += wordCount;
3842 deviceExtension->WordsLeft -= wordCount;
3843
3844 return TRUE;
3845
3846 } else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) {
3847
3848
3849 if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
3850
3851 //
3852 // Pick up bytes to transfer and convert to words.
3853 //
3854
3855 wordCount =
3856 ScsiPortReadPortUchar(&baseIoAddress1->ByteCountLow);
3857
3858 wordCount |=
3859 ScsiPortReadPortUchar(&baseIoAddress1->ByteCountHigh) << 8;
3860
3861 //
3862 // Covert bytes to words.
3863 //
3864
3865 wordCount >>= 1;
3866
3867 if (wordCount != deviceExtension->WordsLeft) {
3868 DebugPrint((3,
3869 "AtapiInterrupt: %d words requested; %d words xferred\n",
3870 deviceExtension->WordsLeft,
3871 wordCount));
3872 }
3873
3874 //
3875 // Verify this makes sense.
3876 //
3877
3878 if (wordCount > deviceExtension->WordsLeft) {
3879 wordCount = deviceExtension->WordsLeft;
3880 }
3881
3882 } else {
3883
3884 //
3885 // Check if words left is at least 256.
3886 //
3887
3888 if (deviceExtension->WordsLeft < wordsThisInterrupt) {
3889
3890 //
3891 // Transfer only words requested.
3892 //
3893
3894 wordCount = deviceExtension->WordsLeft;
3895
3896 } else {
3897
3898 //
3899 // Transfer next block.
3900 //
3901
3902 wordCount = wordsThisInterrupt;
3903 }
3904 }
3905
3906 //
3907 // Ensure that this is a read command.
3908 //
3909
3910 if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
3911
3912 DebugPrint((3,
3913 "AtapiInterrupt: Read interrupt\n"));
3914
3915 WaitOnBusy(baseIoAddress2,statusByte);
3916
3917 if (atapiDev || !deviceExtension->DWordIO) {
3918 ReadBuffer(baseIoAddress1,
3919 deviceExtension->DataBuffer,
3920 wordCount);
3921
3922 } else {
3923 PIDE_REGISTERS_3 address3 = (PIDE_REGISTERS_3)baseIoAddress1;
3924
3925 ReadBuffer2(address3,
3926 (PULONG)(deviceExtension->DataBuffer),
3927 wordCount / 2);
3928 }
3929 } else {
3930
3931 DebugPrint((1,
3932 "AtapiInterrupt: Int reason %x, but srb is for a read %x.\n",
3933 interruptReason,
3934 srb));
3935
3936 //
3937 // Fail this request.
3938 //
3939
3941 goto CompleteRequest;
3942 }
3943
3944 //
3945 // Translate ATAPI data back to SCSI data if needed
3946 //
3947
3948 if (srb->Cdb[0] == ATAPI_MODE_SENSE &&
3949 deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
3950
3951 //
3952 //convert and adjust the wordCount
3953 //
3954
3955 wordCount -= Atapi2Scsi(srb, (char *)deviceExtension->DataBuffer,
3956 wordCount << 1);
3957 }
3958 //
3959 // Advance data buffer pointer and bytes left.
3960 //
3961
3962 deviceExtension->DataBuffer += wordCount;
3963 deviceExtension->WordsLeft -= wordCount;
3964
3965 //
3966 // Check for read command complete.
3967 //
3968
3969 if (deviceExtension->WordsLeft == 0) {
3970
3971 if (deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
3972
3973 //
3974 // Work around to make many atapi devices return correct sector size
3975 // of 2048. Also certain devices will have sector count == 0x00, check
3976 // for that also.
3977 //
3978
3979 if ((srb->Cdb[0] == 0x25) &&
3980 ((deviceExtension->IdentifyData[srb->TargetId].GeneralConfiguration >> 8) & 0x1f) == 0x05) {
3981
3982 deviceExtension->DataBuffer -= wordCount;
3983 if (deviceExtension->DataBuffer[0] == 0x00) {
3984
3985 *((ULONG *) &(deviceExtension->DataBuffer[0])) = 0xFFFFFF7F;
3986
3987 }
3988
3989 *((ULONG *) &(deviceExtension->DataBuffer[2])) = 0x00080000;
3990 deviceExtension->DataBuffer += wordCount;
3991 }
3992 } else {
3993
3994 //
3995 // Completion for IDE drives.
3996 //
3997
3998
3999 if (deviceExtension->WordsLeft) {
4000
4002
4003 } else {
4004
4006
4007 }
4008
4009 goto CompleteRequest;
4010
4011 }
4012 }
4013
4014 return TRUE;
4015
4016 } else if (interruptReason == 0x3 && !(statusByte & IDE_STATUS_DRQ)) {
4017
4018 //
4019 // Command complete.
4020 //
4021
4022 if (deviceExtension->WordsLeft) {
4023
4025
4026 } else {
4027
4029
4030 }
4031
4033
4034 //
4035 // Check and see if we are processing our secret (mechanism status/request sense) srb
4036 //
4037 if (deviceExtension->OriginalSrb) {
4038
4039 ULONG srbStatus;
4040
4041 if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
4042
4043 if (status == SRB_STATUS_SUCCESS) {
4044 // Bingo!!
4045 AtapiHwInitializeChanger (HwDeviceExtension,
4046 srb->TargetId,
4048
4049 // Get ready to issue the original srb
4050 srb = deviceExtension->CurrentSrb = deviceExtension->OriginalSrb;
4051 deviceExtension->OriginalSrb = NULL;
4052
4053 } else {
4054 // failed! Get the sense key and maybe try again
4055 srb = deviceExtension->CurrentSrb = BuildRequestSenseSrb (
4056 HwDeviceExtension,
4057 deviceExtension->OriginalSrb->PathId,
4058 deviceExtension->OriginalSrb->TargetId);
4059 }
4060
4061 srbStatus = AtapiSendCommand(HwDeviceExtension, deviceExtension->CurrentSrb);
4062 if (srbStatus == SRB_STATUS_PENDING) {
4063 return TRUE;
4064 }
4065
4066 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
4067
4068 PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
4069
4071 // Check to see if we at least get minimum number of bytes
4072 if ((srb->DataTransferLength - deviceExtension->WordsLeft) >
4073 (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) {
4075 }
4076 }
4077
4078 if (status == SRB_STATUS_SUCCESS) {
4079 if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
4080 deviceExtension->MechStatusRetryCount) {
4081
4082 // The sense key doesn't say the last request is illegal, so try again
4083 deviceExtension->MechStatusRetryCount--;
4084 srb = deviceExtension->CurrentSrb = BuildMechanismStatusSrb (
4085 HwDeviceExtension,
4086 deviceExtension->OriginalSrb->PathId,
4087 deviceExtension->OriginalSrb->TargetId);
4088 } else {
4089
4090 // last request was illegal. No point trying again
4091
4092 AtapiHwInitializeChanger (HwDeviceExtension,
4093 srb->TargetId,
4095
4096 // Get ready to issue the original srb
4097 srb = deviceExtension->CurrentSrb = deviceExtension->OriginalSrb;
4098 deviceExtension->OriginalSrb = NULL;
4099 }
4100
4101 srbStatus = AtapiSendCommand(HwDeviceExtension, deviceExtension->CurrentSrb);
4102 if (srbStatus == SRB_STATUS_PENDING) {
4103 return TRUE;
4104 }
4105 }
4106 }
4107
4108 // If we get here, it means AtapiSendCommand() has failed
4109 // Can't recover. Pretend the original srb has failed and complete it.
4110
4111 if (deviceExtension->OriginalSrb) {
4112 AtapiHwInitializeChanger (HwDeviceExtension,
4113 srb->TargetId,
4115 srb = deviceExtension->CurrentSrb = deviceExtension->OriginalSrb;
4116 deviceExtension->OriginalSrb = NULL;
4117 }
4118
4119 // fake an error and read no data
4121 srb->ScsiStatus = 0;
4122 deviceExtension->DataBuffer = srb->DataBuffer;
4123 deviceExtension->WordsLeft = srb->DataTransferLength;
4124 deviceExtension->RDP = FALSE;
4125
4126 } else if (status == SRB_STATUS_ERROR) {
4127
4128 //
4129 // Map error to specific SRB status and handle request sense.
4130 //
4131
4132 status = MapError(deviceExtension,
4133 srb);
4134
4135 deviceExtension->RDP = FALSE;
4136
4137 } else {
4138
4139 //
4140 // Wait for busy to drop.
4141 //
4142
4143 for (i = 0; i < 30; i++) {
4144 GetStatus(baseIoAddress2,statusByte);
4145 if (!(statusByte & IDE_STATUS_BUSY)) {
4146 break;
4147 }
4149 }
4150
4151 if (i == 30) {
4152
4153 //
4154 // reset the controller.
4155 //
4156
4157 DebugPrint((1,
4158 "AtapiInterrupt: Resetting due to BSY still up - %x. Base Io %x\n",
4159 statusByte,
4160 baseIoAddress1));
4161 AtapiResetController(HwDeviceExtension,srb->PathId);
4162 return TRUE;
4163 }
4164
4165 //
4166 // Check to see if DRQ is still up.
4167 //
4168
4169 if (statusByte & IDE_STATUS_DRQ) {
4170
4171 for (i = 0; i < 500; i++) {
4172 GetStatus(baseIoAddress2,statusByte);
4173 if (!(statusByte & IDE_STATUS_DRQ)) {
4174 break;
4175 }
4177
4178 }
4179
4180 if (i == 500) {
4181
4182 //
4183 // reset the controller.
4184 //
4185
4186 DebugPrint((1,
4187 "AtapiInterrupt: Resetting due to DRQ still up - %x\n",
4188 statusByte));
4189 AtapiResetController(HwDeviceExtension,srb->PathId);
4190 return TRUE;
4191 }
4192
4193 }
4194 }
4195
4196
4197 //
4198 // Clear interrupt expecting flag.
4199 //
4200
4201 deviceExtension->ExpectingInterrupt = FALSE;
4202
4203 //
4204 // Sanity check that there is a current request.
4205 //
4206
4207 if (srb != NULL) {
4208
4209 //
4210 // Set status in SRB.
4211 //
4212
4213 srb->SrbStatus = (UCHAR)status;
4214
4215 //
4216 // Check for underflow.
4217 //
4218
4219 if (deviceExtension->WordsLeft) {
4220
4221 //
4222 // Subtract out residual words and update if filemark hit,
4223 // setmark hit , end of data, end of media...
4224 //
4225
4226 if (!(deviceExtension->DeviceFlags[srb->TargetId] & DFLAGS_TAPE_DEVICE)) {
4228 srb->DataTransferLength -= deviceExtension->WordsLeft;
4229 } else {
4230 srb->DataTransferLength = 0;
4231 }
4232 } else {
4233 srb->DataTransferLength -= deviceExtension->WordsLeft;
4234 }
4235 }
4236
4237 if (srb->Function != SRB_FUNCTION_IO_CONTROL) {
4238
4239 //
4240 // Indicate command complete.
4241 //
4242
4243 if (!(deviceExtension->RDP)) {
4245 deviceExtension,
4246 srb);
4247
4248 }
4249 } else {
4250
4251 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
4252 UCHAR error = 0;
4253
4254 if (status != SRB_STATUS_SUCCESS) {
4255 error = ScsiPortReadPortUchar((PUCHAR)baseIoAddress1 + 1);
4256 }
4257
4258 //
4259 // Build the SMART status block depending upon the completion status.
4260 //
4261
4262 cmdOutParameters->cBufferSize = wordCount;
4263 cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
4264 cmdOutParameters->DriverStatus.bIDEError = error;
4265
4266 //
4267 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
4268 // data buffer.
4269 //
4270
4271 if (deviceExtension->SmartCommand == RETURN_SMART_STATUS) {
4272 cmdOutParameters->bBuffer[0] = RETURN_SMART_STATUS;
4273 cmdOutParameters->bBuffer[1] = ScsiPortReadPortUchar(&baseIoAddress1->InterruptReason);
4274 cmdOutParameters->bBuffer[2] = ScsiPortReadPortUchar(&baseIoAddress1->Unused1);
4275 cmdOutParameters->bBuffer[3] = ScsiPortReadPortUchar(&baseIoAddress1->ByteCountLow);
4276 cmdOutParameters->bBuffer[4] = ScsiPortReadPortUchar(&baseIoAddress1->ByteCountHigh);
4277 cmdOutParameters->bBuffer[5] = ScsiPortReadPortUchar(&baseIoAddress1->DriveSelect);
4278 cmdOutParameters->bBuffer[6] = SMART_CMD;
4279 cmdOutParameters->cBufferSize = 8;
4280 }
4281
4282 //
4283 // Indicate command complete.
4284 //
4285
4287 deviceExtension,
4288 srb);
4289
4290 }
4291
4292 } else {
4293
4294 DebugPrint((1,
4295 "AtapiInterrupt: No SRB!\n"));
4296 }
4297
4298 //
4299 // Indicate ready for next request.
4300 //
4301
4302 if (!(deviceExtension->RDP)) {
4303
4304 //
4305 // Clear current SRB.
4306 //
4307
4308 deviceExtension->CurrentSrb = NULL;
4309
4311 deviceExtension,
4312 NULL);
4313 } else {
4314
4316 HwDeviceExtension,
4318 2000);
4319 }
4320
4321 return TRUE;
4322
4323 } else {
4324
4325 //
4326 // Unexpected int.
4327 //
4328
4329 DebugPrint((3,
4330 "AtapiInterrupt: Unexpected interrupt. InterruptReason %x. Status %x.\n",
4331 interruptReason,
4332 statusByte));
4333 return FALSE;
4334 }
4335
4336 return TRUE;
4337
4338} // end AtapiInterrupt()
struct _IDE_REGISTERS_3 * PIDE_REGISTERS_3
#define GetBaseStatus(BaseIoAddress, Status)
Definition: atapi.h:331
#define WriteBuffer(BaseIoAddress, Buffer, Count)
Definition: atapi.h:344
#define ReadBuffer(BaseIoAddress, Buffer, Count)
Definition: atapi.h:339
#define WaitOnBusy(BaseIoAddress, Status)
Definition: atapi.h:359
#define WriteBuffer2(BaseIoAddress, Buffer, Count)
Definition: atapi.h:354
#define ReadBuffer2(BaseIoAddress, Buffer, Count)
Definition: atapi.h:349
struct _ATAPI_REGISTERS_1 * PATAPI_REGISTERS_1
ULONG NTAPI MapError(IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
Definition: atapi.c:905
ULONG NTAPI Atapi2Scsi(IN PSCSI_REQUEST_BLOCK Srb, IN char *DataBuffer, IN ULONG ByteCount)
Definition: atapi.c:3360
BOOLEAN NTAPI AtapiResetController(IN PVOID HwDeviceExtension, IN ULONG PathId)
Definition: atapi.c:733
PSCSI_REQUEST_BLOCK NTAPI BuildMechanismStatusSrb(IN PVOID HwDeviceExtension, IN ULONG PathId, IN ULONG TargetId)
Definition: atapi.c:6447
PSCSI_REQUEST_BLOCK NTAPI BuildRequestSenseSrb(IN PVOID HwDeviceExtension, IN ULONG PathId, IN ULONG TargetId)
Definition: atapi.c:6493
ULONG NTAPI AtapiSendCommand(IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
Definition: atapi.c:4981
VOID NTAPI AtapiHwInitializeChanger(IN PVOID HwDeviceExtension, IN ULONG TargetId, IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
Definition: atapi.c:1469
#define SMART_CMD
Definition: helper.h:21
struct _SENDCMDOUTPARAMS * PSENDCMDOUTPARAMS
#define SCSIOP_REQUEST_SENSE
Definition: cdrw_hw.h:870
struct _SENSE_DATA * PSENSE_DATA
#define SCSIOP_MECHANISM_STATUS
Definition: cdrw_hw.h:966
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
NTSTATUS NTAPI CompleteRequest(IN PIRP Irp, IN NTSTATUS Status, IN ULONG_PTR Information)
Definition: dispatch.c:19
#define SRB_FUNCTION_IO_CONTROL
Definition: srb.h:317
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SRB_STATUS_PENDING
Definition: srb.h:340
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define SRB_STATUS_ERROR
Definition: srb.h:344
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define IDE_STATUS_DRQ
Definition: hwide.h:113
#define error(str)
Definition: mkdosfs.c:1605
int k
Definition: mpi.c:3369
#define RETURN_SMART_STATUS
Definition: ntdddisk.h:753
#define SMART_IDE_ERROR
Definition: ntdddisk.h:706
struct _SRB_IO_CONTROL SRB_IO_CONTROL
UCHAR ByteCountLow
Definition: atapi.h:170
UCHAR InterruptReason
Definition: atapi.h:168
UCHAR ByteCountHigh
Definition: atapi.h:171
UCHAR DriveSelect
Definition: atapi.h:172
UCHAR bIDEError
Definition: helper.h:3
UCHAR bDriverError
Definition: helper.h:2
PSCSI_REQUEST_BLOCK OriginalSrb
Definition: atapi.c:151
PUSHORT DataBuffer
Definition: atapi.c:53
UCHAR SmartCommand
Definition: atapi.c:131
ULONG MechStatusRetryCount
Definition: atapi.c:155
USHORT GeneralConfiguration
Definition: atapi.h:249
PVOID DataBuffer
Definition: srb.h:263
UCHAR PathId
Definition: srb.h:253
UCHAR Function
Definition: srb.h:250
UCHAR ScsiStatus
Definition: srb.h:252
ULONG DataTransferLength
Definition: srb.h:261
ULONG SrbFlags
Definition: srb.h:260
UCHAR SrbStatus
Definition: srb.h:251
UCHAR bBuffer[1]
Definition: helper.h:27
ULONG cBufferSize
Definition: helper.h:25
DRIVERSTATUS DriverStatus
Definition: helper.h:26
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
UCHAR SenseKey
Definition: cdrw_hw.h:1167
Definition: ps.c:97
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint16_t * PUSHORT
Definition: typedefs.h:56

Referenced by AtapiCallBack(), and DriverEntry().

◆ AtapiParseArgumentString()

ULONG NTAPI AtapiParseArgumentString ( IN PCHAR  String,
IN PCHAR  KeyWord 
)

Definition at line 1852 of file atapi.c.

1876{
1877 PCHAR cptr;
1878 PCHAR kptr;
1879 ULONG value;
1880 ULONG stringLength = 0;
1881 ULONG keyWordLength = 0;
1882 ULONG index;
1883
1884 if (!String) {
1885 return 0;
1886 }
1887 if (!KeyWord) {
1888 return 0;
1889 }
1890
1891 //
1892 // Calculate the string length and lower case all characters.
1893 //
1894
1895 cptr = String;
1896 while (*cptr) {
1897 if (*cptr >= 'A' && *cptr <= 'Z') {
1898 *cptr = *cptr + ('a' - 'A');
1899 }
1900 cptr++;
1901 stringLength++;
1902 }
1903
1904 //
1905 // Calculate the keyword length and lower case all characters.
1906 //
1907
1908 cptr = KeyWord;
1909 while (*cptr) {
1910
1911 if (*cptr >= 'A' && *cptr <= 'Z') {
1912 *cptr = *cptr + ('a' - 'A');
1913 }
1914 cptr++;
1915 keyWordLength++;
1916 }
1917
1918 if (keyWordLength > stringLength) {
1919
1920 //
1921 // Can't possibly have a match.
1922 //
1923
1924 return 0;
1925 }
1926
1927 //
1928 // Now setup and start the compare.
1929 //
1930
1931 cptr = String;
1932
1933ContinueSearch:
1934
1935 //
1936 // The input string may start with white space. Skip it.
1937 //
1938
1939 while (*cptr == ' ' || *cptr == '\t') {
1940 cptr++;
1941 }
1942
1943 if (*cptr == '\0') {
1944
1945 //
1946 // end of string.
1947 //
1948
1949 return 0;
1950 }
1951
1952 kptr = KeyWord;
1953 while (*cptr++ == *kptr++) {
1954
1955 if (*(cptr - 1) == '\0') {
1956
1957 //
1958 // end of string
1959 //
1960
1961 return 0;
1962 }
1963 }
1964
1965 if (*(kptr - 1) == '\0') {
1966
1967 //
1968 // May have a match backup and check for blank or equals.
1969 //
1970
1971 cptr--;
1972 while (*cptr == ' ' || *cptr == '\t') {
1973 cptr++;
1974 }
1975
1976 //
1977 // Found a match. Make sure there is an equals.
1978 //
1979
1980 if (*cptr != '=') {
1981
1982 //
1983 // Not a match so move to the next semicolon.
1984 //
1985
1986 while (*cptr) {
1987 if (*cptr++ == ';') {
1988 goto ContinueSearch;
1989 }
1990 }
1991 return 0;
1992 }
1993
1994 //
1995 // Skip the equals sign.
1996 //
1997
1998 cptr++;
1999
2000 //
2001 // Skip white space.
2002 //
2003
2004 while ((*cptr == ' ') || (*cptr == '\t')) {
2005 cptr++;
2006 }
2007
2008 if (*cptr == '\0') {
2009
2010 //
2011 // Early end of string, return not found
2012 //
2013
2014 return 0;
2015 }
2016
2017 if (*cptr == ';') {
2018
2019 //
2020 // This isn't it either.
2021 //
2022
2023 cptr++;
2024 goto ContinueSearch;
2025 }
2026
2027 value = 0;
2028 if ((*cptr == '0') && (*(cptr + 1) == 'x')) {
2029
2030 //
2031 // Value is in Hex. Skip the "0x"
2032 //
2033
2034 cptr += 2;
2035 for (index = 0; *(cptr + index); index++) {
2036
2037 if (*(cptr + index) == ' ' ||
2038 *(cptr + index) == '\t' ||
2039 *(cptr + index) == ';') {
2040 break;
2041 }
2042
2043 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
2044 value = (16 * value) + (*(cptr + index) - '0');
2045 } else {
2046 if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
2047 value = (16 * value) + (*(cptr + index) - 'a' + 10);
2048 } else {
2049
2050 //
2051 // Syntax error, return not found.
2052 //
2053 return 0;
2054 }
2055 }
2056 }
2057 } else {
2058
2059 //
2060 // Value is in Decimal.
2061 //
2062
2063 for (index = 0; *(cptr + index); index++) {
2064
2065 if (*(cptr + index) == ' ' ||
2066 *(cptr + index) == '\t' ||
2067 *(cptr + index) == ';') {
2068 break;
2069 }
2070
2071 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
2072 value = (10 * value) + (*(cptr + index) - '0');
2073 } else {
2074
2075 //
2076 // Syntax error return not found.
2077 //
2078 return 0;
2079 }
2080 }
2081 }
2082
2083 return value;
2084 } else {
2085
2086 //
2087 // Not a match check for ';' to continue search.
2088 //
2089
2090 while (*cptr) {
2091 if (*cptr++ == ';') {
2092 goto ContinueSearch;
2093 }
2094 }
2095
2096 return 0;
2097 }
2098}
#define index(s, c)
Definition: various.h:29
GLuint index
Definition: glext.h:6031
Definition: pdh_main.c:94
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433

Referenced by AtapiFindController(), AtapiFindIsaController(), and AtapiReadArgumentString().

◆ AtapiResetController()

BOOLEAN NTAPI AtapiResetController ( IN PVOID  HwDeviceExtension,
IN ULONG  PathId 
)

Definition at line 733 of file atapi.c.

755{
756 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
757 ULONG numberChannels = deviceExtension->NumberChannels;
758 PIDE_REGISTERS_1 baseIoAddress1;
759 PIDE_REGISTERS_2 baseIoAddress2;
761 ULONG i,j;
762 UCHAR statusByte;
763
764 DebugPrint((2,"AtapiResetController: Reset IDE\n"));
765
766 //
767 // Check and see if we are processing an internal srb
768 //
769 if (deviceExtension->OriginalSrb) {
770 deviceExtension->CurrentSrb = deviceExtension->OriginalSrb;
771 deviceExtension->OriginalSrb = NULL;
772 }
773
774 //
775 // Check if request is in progress.
776 //
777
778 if (deviceExtension->CurrentSrb) {
779
780 //
781 // Complete outstanding request with SRB_STATUS_BUS_RESET.
782 //
783
784 ScsiPortCompleteRequest(deviceExtension,
785 deviceExtension->CurrentSrb->PathId,
786 deviceExtension->CurrentSrb->TargetId,
787 deviceExtension->CurrentSrb->Lun,
789
790 //
791 // Clear request tracking fields.
792 //
793
794 deviceExtension->CurrentSrb = NULL;
795 deviceExtension->WordsLeft = 0;
796 deviceExtension->DataBuffer = NULL;
797
798 //
799 // Indicate ready for next request.
800 //
801
803 deviceExtension,
804 NULL);
805 }
806
807 //
808 // Clear expecting interrupt flag.
809 //
810
811 deviceExtension->ExpectingInterrupt = FALSE;
812 deviceExtension->RDP = FALSE;
813
814 for (j = 0; j < numberChannels; j++) {
815
816 baseIoAddress1 = deviceExtension->BaseIoAddress1[j];
817 baseIoAddress2 = deviceExtension->BaseIoAddress2[j];
818
819 //
820 // Do special processing for ATAPI and IDE disk devices.
821 //
822
823 for (i = 0; i < 2; i++) {
824
825 //
826 // Check if device present.
827 //
828
829 if (deviceExtension->DeviceFlags[i + (j * 2)] & DFLAGS_DEVICE_PRESENT) {
830
831 //
832 // Check for ATAPI disk.
833 //
834
835 if (deviceExtension->DeviceFlags[i + (j * 2)] & DFLAGS_ATAPI_DEVICE) {
836
837 //
838 // Issue soft reset and issue identify.
839 //
840
841 GetStatus(baseIoAddress2,statusByte);
842 DebugPrint((1,
843 "AtapiResetController: Status before Atapi reset (%x).\n",
844 statusByte));
845
846 AtapiSoftReset(baseIoAddress1,i);
847
848 GetStatus(baseIoAddress2,statusByte);
849
850 if (statusByte == 0x0) {
851
852 IssueIdentify(HwDeviceExtension,
853 i,
854 j,
856 } else {
857
858 DebugPrint((1,
859 "AtapiResetController: Status after soft reset %x\n",
860 statusByte));
861 }
862
863 } else {
864
865 //
866 // Write IDE reset controller bits.
867 //
868
869 IdeHardReset(baseIoAddress2,result);
870
871 if (!result) {
872 return FALSE;
873 }
874
875 //
876 // Set disk geometry parameters.
877 //
878
879 if (!SetDriveParameters(HwDeviceExtension,
880 i,
881 j)) {
882
883 DebugPrint((1,
884 "AtapiResetController: SetDriveParameters failed\n"));
885 }
886 }
887 }
888 }
889 }
890
891 //
892 // Call the HwInitialize routine to setup multi-block.
893 //
894
895 AtapiHwInitialize(HwDeviceExtension);
896
897 return TRUE;
898
899} // end AtapiResetController()
#define IDE_COMMAND_ATAPI_IDENTIFY
Definition: atapi.h:110
#define IdeHardReset(BaseIoAddress, result)
Definition: atapi.h:432
#define AtapiSoftReset(BaseIoAddress, DeviceNumber)
Definition: atapi.h:418
BOOLEAN NTAPI AtapiHwInitialize(IN PVOID HwDeviceExtension)
Definition: atapi.c:1282
BOOLEAN NTAPI SetDriveParameters(IN PVOID HwDeviceExtension, IN ULONG DeviceNumber, IN ULONG Channel)
Definition: atapi.c:636
BOOLEAN NTAPI IssueIdentify(IN PVOID HwDeviceExtension, IN ULONG DeviceNumber, IN ULONG Channel, IN UCHAR Command)
Definition: atapi.c:251
VOID NTAPI ScsiPortCompleteRequest(IN PVOID HwDeviceExtension, IN UCHAR PathId, IN UCHAR TargetId, IN UCHAR Lun, IN UCHAR SrbStatus)
Definition: scsiport.c:507
#define SRB_STATUS_BUS_RESET
Definition: srb.h:353
GLuint64EXT * result
Definition: glext.h:11304

Referenced by AtapiInterrupt(), AtapiStartIo(), and DriverEntry().

◆ AtapiSendCommand()

ULONG NTAPI AtapiSendCommand ( IN PVOID  HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 4981 of file atapi.c.

5002{
5003 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
5004 PATAPI_REGISTERS_1 baseIoAddress1 = (PATAPI_REGISTERS_1)deviceExtension->BaseIoAddress1[Srb->TargetId >> 1];
5005 PATAPI_REGISTERS_2 baseIoAddress2 = (PATAPI_REGISTERS_2)deviceExtension->BaseIoAddress2[Srb->TargetId >> 1];
5006 ULONG i;
5007 ULONG flags;
5008 UCHAR statusByte,byteCountLow,byteCountHigh;
5009
5010 //
5011 // We need to know how many platters our atapi cd-rom device might have.
5012 // Before anyone tries to send a srb to our target for the first time,
5013 // we must "secretly" send down a separate mechanism status srb in order to
5014 // initialize our device extension changer data. That's how we know how
5015 // many platters our target has.
5016 //
5017 if (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_CHANGER_INITED) &&
5018 !deviceExtension->OriginalSrb) {
5019
5020 ULONG srbStatus;
5021
5022 //
5023 // Set this flag now. If the device hangs on the mech. status
5024 // command, we will not have the change to set it.
5025 //
5026 deviceExtension->DeviceFlags[Srb->TargetId] |= DFLAGS_CHANGER_INITED;
5027
5028 deviceExtension->MechStatusRetryCount = 3;
5029 deviceExtension->CurrentSrb = BuildMechanismStatusSrb (
5030 HwDeviceExtension,
5031 Srb->PathId,
5032 Srb->TargetId);
5033 deviceExtension->OriginalSrb = Srb;
5034
5035 srbStatus = AtapiSendCommand(HwDeviceExtension, deviceExtension->CurrentSrb);
5036 if (srbStatus == SRB_STATUS_PENDING) {
5037 return srbStatus;
5038 } else {
5039 deviceExtension->CurrentSrb = deviceExtension->OriginalSrb;
5040 deviceExtension->OriginalSrb = NULL;
5041 AtapiHwInitializeChanger (HwDeviceExtension,
5042 Srb->TargetId,
5044 // fall out
5045 }
5046 }
5047
5048 DebugPrint((2,
5049 "AtapiSendCommand: Command %x to TargetId %d lun %d\n",
5050 Srb->Cdb[0],
5051 Srb->TargetId,
5052 Srb->Lun));
5053
5054 //
5055 // Make sure command is to ATAPI device.
5056 //
5057
5058 flags = deviceExtension->DeviceFlags[Srb->TargetId];
5060 if ((Srb->Lun) > (deviceExtension->DiscsPresent[Srb->TargetId] - 1)) {
5061
5062 //
5063 // Indicate no device found at this address.
5064 //
5065
5067 }
5068 } else if (Srb->Lun > 0) {
5070 }
5071
5072 if (!(flags & DFLAGS_ATAPI_DEVICE)) {
5074 }
5075
5076 //
5077 // Select device 0 or 1.
5078 //
5079
5080 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
5081 (UCHAR)(((Srb->TargetId & 0x1) << 4) | 0xA0));
5082
5083 //
5084 // Verify that controller is ready for next command.
5085 //
5086
5087 GetStatus(baseIoAddress2,statusByte);
5088
5089 DebugPrint((2,
5090 "AtapiSendCommand: Entered with status %x\n",
5091 statusByte));
5092
5093 if (statusByte & IDE_STATUS_BUSY) {
5094 DebugPrint((1,
5095 "AtapiSendCommand: Device busy (%x)\n",
5096 statusByte));
5097 return SRB_STATUS_BUSY;
5098
5099 }
5100
5101 if (statusByte & IDE_STATUS_ERROR) {
5102 if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
5103
5104 DebugPrint((1,
5105 "AtapiSendCommand: Error on entry: (%x)\n",
5106 statusByte));
5107 //
5108 // Read the error reg. to clear it and fail this request.
5109 //
5110
5111 return MapError(deviceExtension,
5112 Srb);
5113 }
5114 }
5115
5116 //
5117 // If a tape drive has doesn't have DSC set and the last command is restrictive, don't send
5118 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
5119 //
5120
5121 if ((!(statusByte & IDE_STATUS_DSC)) &&
5122 (flags & DFLAGS_TAPE_DEVICE) && deviceExtension->RDP) {
5124 DebugPrint((2,"AtapiSendCommand: DSC not set. %x\n",statusByte));
5125 return SRB_STATUS_BUSY;
5126 }
5127
5128 if (IS_RDP(Srb->Cdb[0])) {
5129
5130 deviceExtension->RDP = TRUE;
5131
5132 DebugPrint((3,
5133 "AtapiSendCommand: %x mapped as DSC restrictive\n",
5134 Srb->Cdb[0]));
5135
5136 } else {
5137
5138 deviceExtension->RDP = FALSE;
5139 }
5140
5141 if (statusByte & IDE_STATUS_DRQ) {
5142
5143 DebugPrint((1,
5144 "AtapiSendCommand: Entered with status (%x). Attempting to recover.\n",
5145 statusByte));
5146 //
5147 // Try to drain the data that one preliminary device thinks that it has
5148 // to transfer. Hopefully this random assertion of DRQ will not be present
5149 // in production devices.
5150 //
5151
5152 for (i = 0; i < 0x10000; i++) {
5153
5154 GetStatus(baseIoAddress2, statusByte);
5155
5156 if (statusByte & IDE_STATUS_DRQ) {
5157
5158 ScsiPortReadPortUshort(&baseIoAddress1->Data);
5159
5160 } else {
5161
5162 break;
5163 }
5164 }
5165
5166 if (i == 0x10000) {
5167
5168 DebugPrint((1,
5169 "AtapiSendCommand: DRQ still asserted.Status (%x)\n",
5170 statusByte));
5171
5172 AtapiSoftReset(baseIoAddress1,Srb->TargetId);
5173
5174 DebugPrint((1,
5175 "AtapiSendCommand: Issued soft reset to Atapi device. \n"));
5176
5177 //
5178 // Re-initialize Atapi device.
5179 //
5180
5181 IssueIdentify(HwDeviceExtension,
5182 (Srb->TargetId & 0x1),
5183 (Srb->TargetId >> 1),
5185
5186 //
5187 // Inform the port driver that the bus has been reset.
5188 //
5189
5190 ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
5191
5192 //
5193 // Clean up device extension fields that AtapiStartIo won't.
5194 //
5195
5196 deviceExtension->ExpectingInterrupt = FALSE;
5197 deviceExtension->RDP = FALSE;
5198
5199 return SRB_STATUS_BUS_RESET;
5200
5201 }
5202 }
5203
5205
5206 //
5207 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
5208 //
5209
5210 Srb->Cdb[1] &= ~0xE0;
5211
5213
5214 //
5215 // Torisan changer. TUR's are overloaded to be platter switches.
5216 //
5217
5218 Srb->Cdb[7] = Srb->Lun;
5219
5220 }
5221 }
5222
5223 //
5224 // Convert SCSI to ATAPI commands if needed
5225 //
5226
5227 switch (Srb->Cdb[0]) {
5228 case SCSIOP_MODE_SENSE:
5229 case SCSIOP_MODE_SELECT:
5230 case SCSIOP_FORMAT_UNIT:
5231 if (!(flags & DFLAGS_TAPE_DEVICE)) {
5232 Scsi2Atapi(Srb);
5233 }
5234
5235 break;
5236 }
5237
5238 //
5239 // Set data buffer pointer and words left.
5240 //
5241
5242 deviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer;
5243 deviceExtension->WordsLeft = Srb->DataTransferLength / 2;
5244
5245 WaitOnBusy(baseIoAddress2,statusByte);
5246
5247 //
5248 // Write transfer byte count to registers.
5249 //
5250
5251 byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
5252 byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
5253
5254 if (Srb->DataTransferLength >= 0x10000) {
5255 byteCountLow = byteCountHigh = 0xFF;
5256 }
5257
5258 ScsiPortWritePortUchar(&baseIoAddress1->ByteCountLow,byteCountLow);
5259 ScsiPortWritePortUchar(&baseIoAddress1->ByteCountHigh, byteCountHigh);
5260
5261 ScsiPortWritePortUchar((PUCHAR)baseIoAddress1 + 1,0);
5262
5263
5264 if (flags & DFLAGS_INT_DRQ) {
5265
5266 //
5267 // This device interrupts when ready to receive the packet.
5268 //
5269 // Write ATAPI packet command.
5270 //
5271
5272 ScsiPortWritePortUchar(&baseIoAddress1->Command,
5274
5275 DebugPrint((3,
5276 "AtapiSendCommand: Wait for int. to send packet. Status (%x)\n",
5277 statusByte));
5278
5279 deviceExtension->ExpectingInterrupt = TRUE;
5280
5281 return SRB_STATUS_PENDING;
5282
5283 } else {
5284
5285 //
5286 // Write ATAPI packet command.
5287 //
5288
5289 ScsiPortWritePortUchar(&baseIoAddress1->Command,
5291
5292 //
5293 // Wait for DRQ.
5294 //
5295
5296 WaitOnBusy(baseIoAddress2, statusByte);
5297 WaitForDrq(baseIoAddress2, statusByte);
5298
5299 if (!(statusByte & IDE_STATUS_DRQ)) {
5300
5301 DebugPrint((1,
5302 "AtapiSendCommand: DRQ never asserted (%x)\n",
5303 statusByte));
5304 return SRB_STATUS_ERROR;
5305 }
5306 }
5307
5308 //
5309 // Need to read status register.
5310 //
5311
5312 GetBaseStatus(baseIoAddress1, statusByte);
5313
5314 //
5315 // Send CDB to device.
5316 //
5317
5318 WaitOnBusy(baseIoAddress2,statusByte);
5319
5320 WriteBuffer(baseIoAddress1,
5321 (PUSHORT)Srb->Cdb,
5322 6);
5323
5324 //
5325 // Indicate expecting an interrupt and wait for it.
5326 //
5327
5328 deviceExtension->ExpectingInterrupt = TRUE;
5329
5330 return SRB_STATUS_PENDING;
5331
5332} // end AtapiSendCommand()
#define WaitForDrq(BaseIoAddress, Status)
Definition: atapi.h:387
#define IDE_COMMAND_ATAPI_PACKET
Definition: atapi.h:109
#define DFLAGS_INT_DRQ
Definition: atapi.h:43
VOID NTAPI Scsi2Atapi(IN PSCSI_REQUEST_BLOCK Srb)
Definition: atapi.c:4913
USHORT NTAPI ScsiPortReadPortUshort(IN PUSHORT Port)
Definition: scsiport.c:1408
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
#define SCSIOP_FORMAT_UNIT
Definition: cdrw_hw.h:871
#define SCSIOP_MODE_SELECT
Definition: cdrw_hw.h:891
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
@ ResetDetected
Definition: srb.h:534
#define SRB_STATUS_BUSY
Definition: srb.h:345
GLbitfield flags
Definition: glext.h:7161

Referenced by AtapiInterrupt(), AtapiSendCommand(), and AtapiStartIo().

◆ AtapiStartIo()

BOOLEAN NTAPI AtapiStartIo ( IN PVOID  HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 5811 of file atapi.c.

5834{
5835 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
5836 ULONG status;
5837
5838 //
5839 // Determine which function.
5840 //
5841
5842 switch (Srb->Function) {
5843
5845
5846 //
5847 // Sanity check. Only one request can be outstanding on a
5848 // controller.
5849 //
5850
5851 if (deviceExtension->CurrentSrb) {
5852
5853 DebugPrint((1,
5854 "AtapiStartIo: Already have a request!\n"));
5857 deviceExtension,
5858 Srb);
5859 return FALSE;
5860 }
5861
5862 //
5863 // Indicate that a request is active on the controller.
5864 //
5865
5866 deviceExtension->CurrentSrb = Srb;
5867
5868 //
5869 // Send command to device.
5870 //
5871
5872 if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_ATAPI_DEVICE) {
5873
5874 status = AtapiSendCommand(HwDeviceExtension,
5875 Srb);
5876
5877 } else if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_DEVICE_PRESENT) {
5878
5879 status = IdeSendCommand(HwDeviceExtension,
5880 Srb);
5881 } else {
5882
5884 }
5885
5886 break;
5887
5889
5890 //
5891 // Verify that SRB to abort is still outstanding.
5892 //
5893
5894 if (!deviceExtension->CurrentSrb) {
5895
5896 DebugPrint((1, "AtapiStartIo: SRB to abort already completed\n"));
5897
5898 //
5899 // Complete abort SRB.
5900 //
5901
5903
5904 break;
5905 }
5906
5907 //
5908 // Abort function indicates that a request timed out.
5909 // Call reset routine. Card will only be reset if
5910 // status indicates something is wrong.
5911 // Fall through to reset code.
5912 //
5913
5915
5916 //
5917 // Reset Atapi and SCSI bus.
5918 //
5919
5920 DebugPrint((1, "AtapiStartIo: Reset bus request received\n"));
5921
5922 if (!AtapiResetController(deviceExtension,
5923 Srb->PathId)) {
5924
5925 DebugPrint((1,"AtapiStartIo: Reset bus failed\n"));
5926
5927 //
5928 // Log reset failure.
5929 //
5930
5932 HwDeviceExtension,
5933 NULL,
5934 0,
5935 0,
5936 0,
5938 5 << 8
5939 );
5940
5942
5943 } else {
5944
5946 }
5947
5948 break;
5949
5951
5952 if (deviceExtension->CurrentSrb) {
5953
5954 DebugPrint((1,
5955 "AtapiStartIo: Already have a request!\n"));
5958 deviceExtension,
5959 Srb);
5960 return FALSE;
5961 }
5962
5963 //
5964 // Indicate that a request is active on the controller.
5965 //
5966
5967 deviceExtension->CurrentSrb = Srb;
5968
5969 if (AtapiStringCmp( (PCHAR)((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,"SCSIDISK",strlen("SCSIDISK"))) {
5970
5971 DebugPrint((1,
5972 "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s\n",
5973 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
5974 "SCSIDISK"));
5975
5977 break;
5978 }
5979
5980 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
5981
5983
5984 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
5985 UCHAR deviceNumber;
5986
5987 //
5988 // Version and revision per SMART 1.03
5989 //
5990
5991 versionParameters->bVersion = 1;
5992 versionParameters->bRevision = 1;
5993 versionParameters->bReserved = 0;
5994
5995 //
5996 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
5997 //
5998
6000
6001 //
6002 // This is done because of how the IOCTL_SCSI_MINIPORT
6003 // determines 'targetid's'. Disk.sys places the real target id value
6004 // in the DeviceMap field. Once we do some parameter checking, the value passed
6005 // back to the application will be determined.
6006 //
6007
6008 deviceNumber = versionParameters->bIDEDeviceMap;
6009
6010 if (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_DEVICE_PRESENT) ||
6011 (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_ATAPI_DEVICE)) {
6012
6014 break;
6015 }
6016
6017 //
6018 // NOTE: This will only set the bit
6019 // corresponding to this drive's target id.
6020 // The bit mask is as follows:
6021 //
6022 // Sec Pri
6023 // S M S M
6024 // 3 2 1 0
6025 //
6026
6027 if (deviceExtension->NumberChannels == 1) {
6028 if (deviceExtension->PrimaryAddress) {
6029 deviceNumber = 1 << Srb->TargetId;
6030 } else {
6031 deviceNumber = 4 << Srb->TargetId;
6032 }
6033 } else {
6034 deviceNumber = 1 << Srb->TargetId;
6035 }
6036
6037 versionParameters->bIDEDeviceMap = deviceNumber;
6038
6040 break;
6041 }
6042
6044
6045 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6046 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6047 ULONG i;
6048 UCHAR targetId;
6049
6050
6051 if (cmdInParameters.irDriveRegs.bCommandReg == ID_CMD) {
6052
6053 //
6054 // Extract the target.
6055 //
6056
6057 targetId = cmdInParameters.bDriveNumber;
6058
6059 if (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_DEVICE_PRESENT) ||
6060 (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_ATAPI_DEVICE)) {
6061
6063 break;
6064 }
6065
6066 //
6067 // Zero the output buffer
6068 //
6069
6070 for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
6071 ((PUCHAR)cmdOutParameters)[i] = 0;
6072 }
6073
6074 //
6075 // Build status block.
6076 //
6077
6078 cmdOutParameters->cBufferSize = IDENTIFY_BUFFER_SIZE;
6079 cmdOutParameters->DriverStatus.bDriverError = 0;
6080 cmdOutParameters->DriverStatus.bIDEError = 0;
6081
6082 //
6083 // Extract the identify data from the device extension.
6084 //
6085
6086 ScsiPortMoveMemory (cmdOutParameters->bBuffer, &deviceExtension->IdentifyData[targetId], IDENTIFY_DATA_SIZE);
6087
6089
6090
6091 } else {
6093 }
6094 break;
6095 }
6096
6105
6106 status = IdeSendSmartCommand(HwDeviceExtension,Srb);
6107 break;
6108
6109 default :
6110
6112 break;
6113
6114 }
6115
6116 break;
6117
6118 default:
6119
6120 //
6121 // Indicate unsupported command.
6122 //
6123
6125
6126 break;
6127
6128 } // end switch
6129
6130 //
6131 // Check if command complete.
6132 //
6133
6134 if (status != SRB_STATUS_PENDING) {
6135
6136 DebugPrint((2,
6137 "AtapiStartIo: Srb %x complete with status %x\n",
6138 Srb,
6139 status));
6140
6141 //
6142 // Clear current SRB.
6143 //
6144
6145 deviceExtension->CurrentSrb = NULL;
6146
6147 //
6148 // Set status in SRB.
6149 //
6150
6152
6153 //
6154 // Indicate command complete.
6155 //
6156
6158 deviceExtension,
6159 Srb);
6160
6161 //
6162 // Indicate ready for next request.
6163 //
6164
6166 deviceExtension,
6167 NULL);
6168 }
6169
6170 return TRUE;
6171
6172} // end AtapiStartIo()
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
ULONG NTAPI IdeSendCommand(IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
Definition: atapi.c:5336
ULONG NTAPI IdeSendSmartCommand(IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
Definition: atapi.c:4343
#define ID_CMD
Definition: helper.h:20
struct _SENDCMDOUTPARAMS SENDCMDOUTPARAMS
struct _SENDCMDINPARAMS * PSENDCMDINPARAMS
VOID NTAPI ScsiPortLogError(IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, IN UCHAR PathId, IN UCHAR TargetId, IN UCHAR Lun, IN ULONG ErrorCode, IN ULONG UniqueId)
Definition: scsiport.c:1299
#define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
Definition: cdrw_hw.h:1465
#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
Definition: cdrw_hw.h:1459
#define IOCTL_SCSI_MINIPORT_DISABLE_SMART
Definition: cdrw_hw.h:1462
#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
Definition: cdrw_hw.h:1464
#define IOCTL_SCSI_MINIPORT_IDENTIFY
Definition: cdrw_hw.h:1458
#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
Definition: cdrw_hw.h:1466
#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
Definition: cdrw_hw.h:1460
#define IOCTL_SCSI_MINIPORT_ENABLE_SMART
Definition: cdrw_hw.h:1461
#define IOCTL_SCSI_MINIPORT_RETURN_STATUS
Definition: cdrw_hw.h:1463
#define IOCTL_SCSI_MINIPORT_SMART_VERSION
Definition: cdrw_hw.h:1457
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FUNCTION_RESET_BUS
Definition: srb.h:326
#define SP_INTERNAL_ADAPTER_ERROR
Definition: srb.h:509
#define SRB_STATUS_ABORT_FAILED
Definition: srb.h:343
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
#define SRB_FUNCTION_ABORT_COMMAND
Definition: srb.h:324
#define IDENTIFY_DATA_SIZE
Definition: hwide.h:284
#define CAP_ATAPI_ID_CMD
Definition: ntdddisk.h:662
#define IDENTIFY_BUFFER_SIZE
Definition: ntdddisk.h:732
struct _GETVERSIONINPARAMS * PGETVERSIONINPARAMS
#define CAP_ATA_ID_CMD
Definition: ntdddisk.h:661
#define CAP_SMART_CMD
Definition: ntdddisk.h:663
UCHAR bCommandReg
Definition: helper.h:15
UCHAR bDriveNumber
Definition: helper.h:33
IDEREGS irDriveRegs
Definition: helper.h:32

Referenced by DriverEntry().

◆ AtapiStringCmp()

LONG NTAPI AtapiStringCmp ( PCHAR  FirstStr,
PCHAR  SecondStr,
ULONG  Count 
)

Definition at line 6333 of file atapi.c.

6338{
6339 UCHAR first ,last;
6340
6341 if (Count) {
6342 do {
6343
6344 //
6345 // Get next char.
6346 //
6347
6348 first = *FirstStr++;
6349 last = *SecondStr++;
6350
6351 if (first != last) {
6352
6353 //
6354 // If no match, try lower-casing.
6355 //
6356
6357 if (first>='A' && first<='Z') {
6358 first = first - 'A' + 'a';
6359 }
6360 if (last>='A' && last<='Z') {
6361 last = last - 'A' + 'a';
6362 }
6363 if (first != last) {
6364
6365 //
6366 // No match
6367 //
6368
6369 return first - last;
6370 }
6371 }
6372 }while (--Count && first);
6373 }
6374
6375 return 0;
6376}
const GLint * first
Definition: glext.h:5794
static UINT UINT last
Definition: font.c:45
int Count
Definition: noreturn.cpp:7

◆ AtapiZeroMemory()

VOID NTAPI AtapiZeroMemory ( IN PUCHAR  Buffer,
IN ULONG  Count 
)

Definition at line 6381 of file atapi.c.

6385{
6386 ULONG i;
6387
6388 for (i = 0; i < Count; i++) {
6389 Buffer[i] = 0;
6390 }
6391}

Referenced by BuildMechanismStatusSrb(), BuildRequestSenseSrb(), DriverEntry(), and Scsi2Atapi().

◆ BuildMechanismStatusSrb()

PSCSI_REQUEST_BLOCK NTAPI BuildMechanismStatusSrb ( IN PVOID  HwDeviceExtension,
IN ULONG  PathId,
IN ULONG  TargetId 
)

Definition at line 6447 of file atapi.c.

6452{
6453 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
6455 PCDB cdb;
6456
6457 srb = &deviceExtension->InternalSrb;
6458
6460
6461 srb->PathId = (UCHAR) PathId;
6462 srb->TargetId = (UCHAR) TargetId;
6463 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
6464 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
6465
6466 //
6467 // Set flags to disable synchronous negotiation.
6468 //
6470
6471 //
6472 // Set timeout to 2 seconds.
6473 //
6474 srb->TimeOutValue = 4;
6475
6476 srb->CdbLength = 6;
6477 srb->DataBuffer = &deviceExtension->MechStatusData;
6478 srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
6479
6480 //
6481 // Set CDB operation code.
6482 //
6483 cdb = (PCDB)srb->Cdb;
6484 cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS;
6485 cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
6486
6487 return srb;
6488}
VOID NTAPI AtapiZeroMemory(IN PUCHAR Buffer, IN ULONG Count)
Definition: atapi.c:6381
struct _MECHANICAL_STATUS_INFORMATION_HEADER MECHANICAL_STATUS_INFORMATION_HEADER
union _CDB * PCDB
_In_ ULONG _In_ BOOLEAN _In_ ULONG _In_ UCHAR PathId
Definition: classpnp.h:1313
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
SCSI_REQUEST_BLOCK InternalSrb
Definition: atapi.c:152
MECHANICAL_STATUS_INFORMATION_HEADER MechStatusData
Definition: atapi.c:153
Definition: cdrw_hw.h:28
struct _CDB::_MECH_STATUS MECH_STATUS

Referenced by AtapiInterrupt(), and AtapiSendCommand().

◆ BuildRequestSenseSrb()

PSCSI_REQUEST_BLOCK NTAPI BuildRequestSenseSrb ( IN PVOID  HwDeviceExtension,
IN ULONG  PathId,
IN ULONG  TargetId 
)

Definition at line 6493 of file atapi.c.

6498{
6499 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
6501 PCDB cdb;
6502
6503 srb = &deviceExtension->InternalSrb;
6504
6506
6507 srb->PathId = (UCHAR) PathId;
6508 srb->TargetId = (UCHAR) TargetId;
6509 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
6510 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
6511
6512 //
6513 // Set flags to disable synchronous negotiation.
6514 //
6516
6517 //
6518 // Set timeout to 2 seconds.
6519 //
6520 srb->TimeOutValue = 4;
6521
6522 srb->CdbLength = 6;
6523 srb->DataBuffer = &deviceExtension->MechStatusSense;
6524 srb->DataTransferLength = sizeof(SENSE_DATA);
6525
6526 //
6527 // Set CDB operation code.
6528 //
6529 cdb = (PCDB)srb->Cdb;
6530 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
6531 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
6532
6533 return srb;
6534}
struct _SENSE_DATA SENSE_DATA
SENSE_DATA MechStatusSense
Definition: atapi.c:154
struct _CDB::_CDB6INQUIRY CDB6INQUIRY

Referenced by AtapiInterrupt().

◆ DriverEntry()

ULONG NTAPI DriverEntry ( IN PVOID  DriverObject,
IN PVOID  Argument2 
)

Definition at line 6177 of file atapi.c.

6198{
6199 HW_INITIALIZATION_DATA hwInitializationData;
6200 ULONG adapterCount;
6201 ULONG i;
6202 ULONG statusToReturn, newStatus;
6203
6204 DebugPrint((1,"\n\nATAPI IDE MiniPort Driver\n"));
6205
6206 statusToReturn = 0xffffffff;
6207
6208 //
6209 // Zero out structure.
6210 //
6211
6212 AtapiZeroMemory(((PUCHAR)&hwInitializationData), sizeof(HW_INITIALIZATION_DATA));
6213
6214 //
6215 // Set size of hwInitializationData.
6216 //
6217
6218 hwInitializationData.HwInitializationDataSize =
6219 sizeof(HW_INITIALIZATION_DATA);
6220
6221 //
6222 // Set entry points.
6223 //
6224
6225 hwInitializationData.HwInitialize = AtapiHwInitialize;
6226 hwInitializationData.HwResetBus = AtapiResetController;
6227 hwInitializationData.HwStartIo = AtapiStartIo;
6228 hwInitializationData.HwInterrupt = AtapiInterrupt;
6229
6230 //
6231 // Specify size of extensions.
6232 //
6233
6234 hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
6235 hwInitializationData.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
6236
6237 //
6238 // Indicate PIO device.
6239 //
6240
6241 hwInitializationData.MapBuffers = TRUE;
6242
6243 //
6244 // Native Mode Devices
6245 //
6246 for (i=0; i <NUM_NATIVE_MODE_ADAPTERS; i++) {
6247 hwInitializationData.HwFindAdapter = AtapiFindNativeModeController;
6248 hwInitializationData.NumberOfAccessRanges = 4;
6249 hwInitializationData.AdapterInterfaceType = PCIBus;
6250
6251 hwInitializationData.VendorId = NativeModeAdapters[i].VendorId;
6252 hwInitializationData.VendorIdLength = (USHORT) NativeModeAdapters[i].VendorIdLength;
6253 hwInitializationData.DeviceId = NativeModeAdapters[i].DeviceId;
6254 hwInitializationData.DeviceIdLength = (USHORT) NativeModeAdapters[i].DeviceIdLength;
6255
6256 newStatus = ScsiPortInitialize(DriverObject,
6257 Argument2,
6258 &hwInitializationData,
6259 (PVOID)(ULONG_PTR)i);
6260 if (newStatus < statusToReturn)
6261 statusToReturn = newStatus;
6262 }
6263
6264 hwInitializationData.VendorId = 0;
6265 hwInitializationData.VendorIdLength = 0;
6266 hwInitializationData.DeviceId = 0;
6267 hwInitializationData.DeviceIdLength = 0;
6268
6269 //
6270 // The adapter count is used by the find adapter routine to track how
6271 // which adapter addresses have been tested.
6272 //
6273
6274 adapterCount = 0;
6275
6276 hwInitializationData.HwFindAdapter = AtapiFindPCIController;
6277 hwInitializationData.NumberOfAccessRanges = 4;
6278 hwInitializationData.AdapterInterfaceType = Isa;
6279
6280 newStatus = ScsiPortInitialize(DriverObject,
6281 Argument2,
6282 &hwInitializationData,
6283 &adapterCount);
6284 if (newStatus < statusToReturn)
6285 statusToReturn = newStatus;
6286
6287 //
6288 // Indicate 2 access ranges and reset FindAdapter.
6289 //
6290
6291 hwInitializationData.NumberOfAccessRanges = 2;
6292 hwInitializationData.HwFindAdapter = AtapiFindController;
6293
6294 //
6295 // Indicate ISA bustype.
6296 //
6297
6298 hwInitializationData.AdapterInterfaceType = Isa;
6299
6300 //
6301 // Call initialization for ISA bustype.
6302 //
6303
6304 newStatus = ScsiPortInitialize(DriverObject,
6305 Argument2,
6306 &hwInitializationData,
6307 &adapterCount);
6308 if (newStatus < statusToReturn)
6309 statusToReturn = newStatus;
6310
6311 //
6312 // Set up for MCA
6313 //
6314
6315 hwInitializationData.AdapterInterfaceType = MicroChannel;
6316 adapterCount = 0;
6317
6318 newStatus = ScsiPortInitialize(DriverObject,
6319 Argument2,
6320 &hwInitializationData,
6321 &adapterCount);
6322 if (newStatus < statusToReturn)
6323 statusToReturn = newStatus;
6324
6325 return statusToReturn;
6326
6327} // end DriverEntry()
#define NUM_NATIVE_MODE_ADAPTERS
Definition: atapi.h:322
ULONG NTAPI AtapiFindPCIController(IN PVOID HwDeviceExtension, IN PVOID Context, IN PVOID BusInformation, IN PCHAR ArgumentString, IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, OUT PBOOLEAN Again)
Definition: atapi.c:3014
struct _HW_LU_EXTENSION HW_LU_EXTENSION
BOOLEAN NTAPI AtapiStartIo(IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
Definition: atapi.c:5811
struct _HW_DEVICE_EXTENSION HW_DEVICE_EXTENSION
ULONG NTAPI AtapiFindNativeModeController(IN PVOID HwDeviceExtension, IN PVOID Context, IN PVOID BusInformation, IN PCHAR ArgumentString, IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, OUT PBOOLEAN Again)
Definition: atapi.c:2712
ULONG NTAPI ScsiPortInitialize(IN PVOID Argument1, IN PVOID Argument2, IN PHW_INITIALIZATION_DATA HwInitializationData, IN PVOID HwContext OPTIONAL)
Definition: scsiport.c:1133
_In_ PVOID Argument2
Definition: classpnp.h:721
struct _HW_INITIALIZATION_DATA HW_INITIALIZATION_DATA
@ PCIBus
Definition: hwresource.cpp:142
@ Isa
Definition: hwresource.cpp:138
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213

◆ FindBrokenController()

BOOLEAN NTAPI FindBrokenController ( IN PVOID  DeviceExtension,
IN PUCHAR  VendorID,
IN ULONG  VendorIDLength,
IN PUCHAR  DeviceID,
IN ULONG  DeviceIDLength,
IN OUT PULONG  FunctionNumber,
IN OUT PULONG  SlotNumber,
IN ULONG  BusNumber,
OUT PBOOLEAN  LastSlot 
)

Definition at line 2575 of file atapi.c.

2600{
2602 ULONG slotNumber;
2603 ULONG functionNumber;
2604 PCI_SLOT_NUMBER slotData;
2605 PPCI_COMMON_CONFIG pciData;
2606 UCHAR vendorString[5];
2607 UCHAR deviceString[5];
2608 PUCHAR vendorStrPtr;
2609 PUCHAR deviceStrPtr;
2610
2611 pciData = (PPCI_COMMON_CONFIG)&pciBuffer;
2612
2613 slotData.u.AsULONG = 0;
2614
2615 //
2616 // Look at each device.
2617 //
2618
2619 for (slotNumber = *SlotNumber;
2620 slotNumber < 32;
2621 slotNumber++) {
2622
2623 slotData.u.bits.DeviceNumber = slotNumber;
2624
2625 //
2626 // Look at each function.
2627 //
2628
2629 for (functionNumber= *FunctionNumber;
2630 functionNumber < 8;
2631 functionNumber++) {
2632
2633 slotData.u.bits.FunctionNumber = functionNumber;
2634
2635 if (!ScsiPortGetBusData(DeviceExtension,
2637 BusNumber,
2638 slotData.u.AsULONG,
2639 pciData,
2640 sizeof(ULONG))) {
2641
2642 //
2643 // Out of PCI data.
2644 //
2645
2646 *LastSlot = TRUE;
2647 return FALSE;
2648 }
2649
2650 if (pciData->VendorID == PCI_INVALID_VENDORID) {
2651
2652 //
2653 // No PCI device, or no more functions on device
2654 // move to next PCI device.
2655 //
2656
2657 break;
2658 }
2659
2660 //
2661 // Translate hex ids to strings.
2662 //
2663
2664 vendorStrPtr = vendorString;
2665 deviceStrPtr = deviceString;
2666 AtapiHexToString(pciData->VendorID, (PCHAR*)&vendorStrPtr);
2667 AtapiHexToString(pciData->DeviceID, (PCHAR*)&deviceStrPtr);
2668
2669 DebugPrint((2,
2670 "FindBrokenController: Bus %x Slot %x Function %x Vendor %s Product %s\n",
2671 BusNumber,
2672 slotNumber,
2673 functionNumber,
2674 vendorString,
2675 deviceString));
2676
2677 //
2678 // Compare strings.
2679 //
2680
2681 if (AtapiStringCmp((PCHAR)vendorString,
2682 (PCHAR)VendorID,
2683 VendorIDLength) ||
2684 AtapiStringCmp((PCHAR)deviceString,
2685 (PCHAR)DeviceID,
2686 DeviceIDLength)) {
2687
2688 //
2689 // Not our PCI device. Try next device/function
2690 //
2691
2692 continue;
2693 }
2694
2695 *FunctionNumber = functionNumber;
2696 *SlotNumber = slotNumber;
2697 return TRUE;
2698
2699 } // next PCI function
2700
2701 *FunctionNumber = 0;
2702
2703 } // next PCI slot
2704
2705 *LastSlot = TRUE;
2706 return FALSE;
2707} // end FindBrokenController
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING DeviceID
Definition: wdfpdo.h:278
_In_ WDFIORESREQLIST _In_ ULONG SlotNumber
Definition: wdfresource.h:68
_In_opt_ PUNICODE_STRING _In_ PDRIVER_OBJECT _In_ PDEVICE_OBJECT _In_ INTERFACE_TYPE _In_ ULONG BusNumber
Definition: halfuncs.h:160

Referenced by AtapiFindPCIController().

◆ FindDevices()

BOOLEAN NTAPI FindDevices ( IN PVOID  HwDeviceExtension,
IN BOOLEAN  AtapiOnly,
IN ULONG  Channel 
)

Definition at line 1489 of file atapi.c.

1514{
1515 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
1516 PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Channel];
1517 PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Channel];
1518 BOOLEAN deviceResponded = FALSE,
1519 skipSetParameters = FALSE;
1520 ULONG waitCount = 10000;
1521 ULONG deviceNumber;
1522 ULONG i;
1523 UCHAR signatureLow,
1524 signatureHigh;
1525 UCHAR statusByte;
1526
1527 //
1528 // Clear expecting interrupt flag and current SRB field.
1529 //
1530
1531 deviceExtension->ExpectingInterrupt = FALSE;
1532 deviceExtension->CurrentSrb = NULL;
1533
1534 //
1535 // Search for devices.
1536 //
1537
1538 for (deviceNumber = 0; deviceNumber < 2; deviceNumber++) {
1539
1540 //
1541 // Select the device.
1542 //
1543
1544 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
1545 (UCHAR)((deviceNumber << 4) | 0xA0));
1546
1547 //
1548 // Check here for some SCSI adapters that incorporate IDE emulation.
1549 //
1550
1551 GetStatus(baseIoAddress2, statusByte);
1552 if (statusByte == 0xFF) {
1553 continue;
1554 }
1555
1556 AtapiSoftReset(baseIoAddress1,deviceNumber);
1557 WaitOnBusy(baseIoAddress2,statusByte);
1558
1559 signatureLow = ScsiPortReadPortUchar(&baseIoAddress1->CylinderLow);
1560 signatureHigh = ScsiPortReadPortUchar(&baseIoAddress1->CylinderHigh);
1561
1562 if (signatureLow == 0x14 && signatureHigh == 0xEB) {
1563
1564 //
1565 // ATAPI signature found.
1566 // Issue the ATAPI identify command if this
1567 // is not for the crash dump utility.
1568 //
1569
1570atapiIssueId:
1571
1572 if (!deviceExtension->DriverMustPoll) {
1573
1574 //
1575 // Issue ATAPI packet identify command.
1576 //
1577
1578 if (IssueIdentify(HwDeviceExtension,
1579 deviceNumber,
1580 Channel,
1582
1583 //
1584 // Indicate ATAPI device.
1585 //
1586
1587 DebugPrint((1,
1588 "FindDevices: Device %x is ATAPI\n",
1589 deviceNumber));
1590
1591 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] |= DFLAGS_ATAPI_DEVICE;
1592 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] |= DFLAGS_DEVICE_PRESENT;
1593
1594 deviceResponded = TRUE;
1595
1596 GetStatus(baseIoAddress2, statusByte);
1597 if (statusByte & IDE_STATUS_ERROR) {
1598 AtapiSoftReset(baseIoAddress1, deviceNumber);
1599 }
1600
1601
1602 } else {
1603
1604 //
1605 // Indicate no working device.
1606 //
1607
1608 DebugPrint((1,
1609 "FindDevices: Device %x not responding\n",
1610 deviceNumber));
1611
1612 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] &= ~DFLAGS_DEVICE_PRESENT;
1613 }
1614
1615 }
1616
1617 } else {
1618
1619 //
1620 // Issue IDE Identify. If an Atapi device is actually present, the signature
1621 // will be asserted, and the drive will be recognized as such.
1622 //
1623
1624 if (IssueIdentify(HwDeviceExtension,
1625 deviceNumber,
1626 Channel,
1628
1629 //
1630 // IDE drive found.
1631 //
1632
1633
1634 DebugPrint((1,
1635 "FindDevices: Device %x is IDE\n",
1636 deviceNumber));
1637
1638 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] |= DFLAGS_DEVICE_PRESENT;
1639
1640 if (!AtapiOnly) {
1641 deviceResponded = TRUE;
1642 }
1643
1644 //
1645 // Indicate IDE - not ATAPI device.
1646 //
1647
1648 deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] &= ~DFLAGS_ATAPI_DEVICE;
1649
1650
1651 } else {
1652
1653 //
1654 // Look to see if an Atapi device is present.
1655 //
1656
1657 AtapiSoftReset(baseIoAddress1,deviceNumber);
1658
1659 WaitOnBusy(baseIoAddress2,statusByte);
1660
1661 signatureLow = ScsiPortReadPortUchar(&baseIoAddress1->CylinderLow);
1662 signatureHigh = ScsiPortReadPortUchar(&baseIoAddress1->CylinderHigh);
1663
1664 if (signatureLow == 0x14 && signatureHigh == 0xEB) {
1665 goto atapiIssueId;
1666 }
1667 }
1668 }
1669 }
1670
1671 for (i = 0; i < 2; i++) {
1672 if ((deviceExtension->DeviceFlags[i + (Channel * 2)] & DFLAGS_DEVICE_PRESENT) &&
1673 (!(deviceExtension->DeviceFlags[i + (Channel * 2)] & DFLAGS_ATAPI_DEVICE)) && deviceResponded) {
1674
1675 //
1676 // This hideous hack is to deal with ESDI devices that return
1677 // garbage geometry in the IDENTIFY data.
1678 // This is ONLY for the crashdump environment as
1679 // these are ESDI devices.
1680 //
1681
1682 if (deviceExtension->IdentifyData[i].SectorsPerTrack ==
1683 0x35 &&
1684 deviceExtension->IdentifyData[i].NumberOfHeads ==
1685 0x07) {
1686
1687 DebugPrint((1,
1688 "FindDevices: Found nasty Compaq ESDI!\n"));
1689
1690 //
1691 // Change these values to something reasonable.
1692 //
1693
1694 deviceExtension->IdentifyData[i].SectorsPerTrack =
1695 0x34;
1696 deviceExtension->IdentifyData[i].NumberOfHeads =
1697 0x0E;
1698 }
1699
1700 if (deviceExtension->IdentifyData[i].SectorsPerTrack ==
1701 0x35 &&
1702 deviceExtension->IdentifyData[i].NumberOfHeads ==
1703 0x0F) {
1704
1705 DebugPrint((1,
1706 "FindDevices: Found nasty Compaq ESDI!\n"));
1707
1708 //
1709 // Change these values to something reasonable.
1710 //
1711
1712 deviceExtension->IdentifyData[i].SectorsPerTrack =
1713 0x34;
1714 deviceExtension->IdentifyData[i].NumberOfHeads =
1715 0x0F;
1716 }
1717
1718
1719 if (deviceExtension->IdentifyData[i].SectorsPerTrack ==
1720 0x36 &&
1721 deviceExtension->IdentifyData[i].NumberOfHeads ==
1722 0x07) {
1723
1724 DebugPrint((1,
1725 "FindDevices: Found nasty UltraStor ESDI!\n"));
1726
1727 //
1728 // Change these values to something reasonable.
1729 //
1730
1731 deviceExtension->IdentifyData[i].SectorsPerTrack =
1732 0x3F;
1733 deviceExtension->IdentifyData[i].NumberOfHeads =
1734 0x10;
1735 skipSetParameters = TRUE;
1736 }
1737
1738
1739 if (!skipSetParameters) {
1740
1741 WaitOnBusy(baseIoAddress2,statusByte);
1742
1743 //
1744 // Select the device.
1745 //
1746
1747 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
1748 (UCHAR)((i << 4) | 0xA0));
1749
1750 GetStatus(baseIoAddress2, statusByte);
1751
1752 if (statusByte & IDE_STATUS_ERROR) {
1753
1754 //
1755 // Reset the device.
1756 //
1757
1758 DebugPrint((2,
1759 "FindDevices: Resetting controller before SetDriveParameters.\n"));
1760
1762 ScsiPortStallExecution(500 * 1000);
1764 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
1765 (UCHAR)((i << 4) | 0xA0));
1766
1767 do {
1768
1769 //
1770 // Wait for Busy to drop.
1771 //
1772
1774 GetStatus(baseIoAddress2, statusByte);
1775
1776 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
1777 }
1778
1779 WaitOnBusy(baseIoAddress2,statusByte);
1780 DebugPrint((2,
1781 "FindDevices: Status before SetDriveParameters: (%x) (%x)\n",
1782 statusByte,
1783 ScsiPortReadPortUchar(&baseIoAddress1->DriveSelect)));
1784
1785 //
1786 // Use the IDENTIFY data to set drive parameters.
1787 //
1788
1789 if (!SetDriveParameters(HwDeviceExtension,i,Channel)) {
1790
1791 DebugPrint((0,
1792 "AtapHwInitialize: Set drive parameters for device %d failed\n",
1793 i));
1794
1795 //
1796 // Don't use this device as writes could cause corruption.
1797 //
1798
1799 deviceExtension->DeviceFlags[i + Channel] = 0;
1800 continue;
1801
1802 }
1803 if (deviceExtension->DeviceFlags[deviceNumber + (Channel * 2)] & DFLAGS_REMOVABLE_DRIVE) {
1804
1805 //
1806 // Pick up ALL IDE removable drives that conform to Yosemite V0.2...
1807 //
1808
1809 AtapiOnly = FALSE;
1810 }
1811
1812
1813 //
1814 // Indicate that a device was found.
1815 //
1816
1817 if (!AtapiOnly) {
1818 deviceResponded = TRUE;
1819 }
1820 }
1821 }
1822 }
1823
1824 //
1825 // Make sure master device is selected on exit.
1826 //
1827
1828 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect, 0xA0);
1829
1830 //
1831 // Reset the controller. This is a feeble attempt to leave the ESDI
1832 // controllers in a state that ATDISK driver will recognize them.
1833 // The problem in ATDISK has to do with timings as it is not reproducible
1834 // in debug. The reset should restore the controller to its poweron state
1835 // and give the system enough time to settle.
1836 //
1837
1838 if (!deviceResponded) {
1839
1841 ScsiPortStallExecution(50 * 1000);
1843 }
1844
1845 return deviceResponded;
1846
1847} // end FindDevices()
#define IDE_COMMAND_IDENTIFY
Definition: atapi.h:118
#define DFLAGS_REMOVABLE_DRIVE
Definition: atapi.h:45
#define IDE_DC_RESET_CONTROLLER
Definition: hwide.h:139
#define IDE_DC_REENABLE_CONTROLLER
Definition: hwide.h:142
USHORT NumberOfHeads
Definition: atapi.h:252
USHORT SectorsPerTrack
Definition: atapi.h:255
UCHAR CylinderHigh
Definition: atapi.h:21
UCHAR CylinderLow
Definition: atapi.h:20
UCHAR AlternateStatus
Definition: atapi.h:27

◆ IdeBuildSenseBuffer()

ULONG NTAPI IdeBuildSenseBuffer ( IN PVOID  HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 5737 of file atapi.c.

5759{
5760 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
5761 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->DataBuffer;
5762
5763
5764 if (senseBuffer){
5765
5766
5767 if(deviceExtension->ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) {
5768
5769 senseBuffer->ErrorCode = 0x70;
5770 senseBuffer->Valid = 1;
5771 senseBuffer->AdditionalSenseLength = 0xb;
5772 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
5774 senseBuffer->AdditionalSenseCodeQualifier = 0;
5775 } else if(deviceExtension->ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) {
5776
5777 senseBuffer->ErrorCode = 0x70;
5778 senseBuffer->Valid = 1;
5779 senseBuffer->AdditionalSenseLength = 0xb;
5780 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
5782 senseBuffer->AdditionalSenseCodeQualifier = 0;
5783 } else if(deviceExtension->ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) {
5784
5785 senseBuffer->ErrorCode = 0x70;
5786 senseBuffer->Valid = 1;
5787 senseBuffer->AdditionalSenseLength = 0xb;
5788 senseBuffer->SenseKey = SCSI_SENSE_NOT_READY;
5790 senseBuffer->AdditionalSenseCodeQualifier = 0;
5791 } else if(deviceExtension->ReturningMediaStatus & IDE_ERROR_DATA_ERROR) {
5792
5793 senseBuffer->ErrorCode = 0x70;
5794 senseBuffer->Valid = 1;
5795 senseBuffer->AdditionalSenseLength = 0xb;
5796 senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT;
5797 senseBuffer->AdditionalSenseCode = 0;
5798 senseBuffer->AdditionalSenseCodeQualifier = 0;
5799 }
5800 return SRB_STATUS_SUCCESS;
5801 }
5802 return SRB_STATUS_ERROR;
5803
5804}// End of IdeBuildSenseBuffer
#define SCSI_SENSE_DATA_PROTECT
Definition: cdrw_hw.h:1194
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
Definition: cdrw_hw.h:1221
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define IDE_ERROR_END_OF_MEDIA
Definition: hwide.h:154
#define IDE_ERROR_MEDIA_CHANGE
Definition: hwide.h:150
#define IDE_ERROR_MEDIA_CHANGE_REQ
Definition: hwide.h:152
#define IDE_ERROR_DATA_ERROR
Definition: hwide.h:149
UCHAR ReturningMediaStatus
Definition: atapi.c:137
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
UCHAR ErrorCode
Definition: cdrw_hw.h:1164
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
UCHAR Valid
Definition: cdrw_hw.h:1165

Referenced by IdeSendCommand().

◆ IdeMediaStatus() [1/2]

VOID NTAPI IdeMediaStatus ( BOOLEAN  EnableMSN,
IN PVOID  HwDeviceExtension,
ULONG  Channel 
)

Definition at line 5655 of file atapi.c.

5672{
5673 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
5674 PIDE_REGISTERS_1 baseIoAddress = deviceExtension->BaseIoAddress1[Channel >> 1];
5675 UCHAR statusByte,errorByte;
5676
5677
5678 if (EnableMSN != FALSE){
5679
5680 //
5681 // If supported enable Media Status Notification support
5682 //
5683
5684 if ((deviceExtension->DeviceFlags[Channel] & DFLAGS_REMOVABLE_DRIVE)) {
5685
5686 //
5687 // enable
5688 //
5689 ScsiPortWritePortUchar((PUCHAR)baseIoAddress + 1,(UCHAR) (0x95));
5690 ScsiPortWritePortUchar(&baseIoAddress->Command,
5692
5693 WaitOnBaseBusy(baseIoAddress,statusByte);
5694
5695 if (statusByte & IDE_STATUS_ERROR) {
5696 //
5697 // Read the error register.
5698 //
5699 errorByte = ScsiPortReadPortUchar((PUCHAR)baseIoAddress + 1);
5700
5701 DebugPrint((1,
5702 "IdeMediaStatus: Error enabling media status. Status %x, error byte %x\n",
5703 statusByte,
5704 errorByte));
5705 } else {
5706 deviceExtension->DeviceFlags[Channel] |= DFLAGS_MEDIA_STATUS_ENABLED;
5707 DebugPrint((1,"IdeMediaStatus: Media Status Notification Supported\n"));
5708 deviceExtension->ReturningMediaStatus = 0;
5709
5710 }
5711
5712 }
5713 } else { // end if EnableMSN != FALSE
5714
5715 //
5716 // disable if previously enabled
5717 //
5718 if ((deviceExtension->DeviceFlags[Channel] & DFLAGS_MEDIA_STATUS_ENABLED)) {
5719
5720 ScsiPortWritePortUchar((PUCHAR)baseIoAddress + 1,(UCHAR) (0x31));
5721 ScsiPortWritePortUchar(&baseIoAddress->Command,
5723
5724 WaitOnBaseBusy(baseIoAddress,statusByte);
5725 deviceExtension->DeviceFlags[Channel] &= ~DFLAGS_MEDIA_STATUS_ENABLED;
5726 }
5727
5728
5729 }
5730
5731
5732
5733}
#define IDE_COMMAND_ENABLE_MEDIA_STATUS
Definition: atapi.h:117
#define DFLAGS_MEDIA_STATUS_ENABLED
Definition: atapi.h:47

◆ IdeMediaStatus() [2/2]

VOID NTAPI IdeMediaStatus ( IN BOOLEAN  EnableMSN,
IN PVOID  HwDeviceExtension,
IN ULONG  Channel 
)

Referenced by AtapiHwInitialize().

◆ IdeReadWrite()

ULONG NTAPI IdeReadWrite ( IN PVOID  HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 4499 of file atapi.c.

4521{
4522 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
4523 PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Srb->TargetId >> 1];
4524 PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Srb->TargetId >> 1];
4525 ULONG startingSector,i;
4526 ULONG wordCount;
4527 UCHAR statusByte,statusByte2;
4528 UCHAR cylinderHigh,cylinderLow,drvSelect,sectorNumber;
4529
4530 //
4531 // Select device 0 or 1.
4532 //
4533
4534 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
4535 (UCHAR)(((Srb->TargetId & 0x1) << 4) | 0xA0));
4536
4537 WaitOnBusy(baseIoAddress2,statusByte2);
4538
4539 if (statusByte2 & IDE_STATUS_BUSY) {
4540 DebugPrint((1,
4541 "IdeReadWrite: Returning BUSY status\n"));
4542 return SRB_STATUS_BUSY;
4543 }
4544
4545 //
4546 // Set data buffer pointer and words left.
4547 //
4548
4549 deviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer;
4550 deviceExtension->WordsLeft = Srb->DataTransferLength / 2;
4551
4552 //
4553 // Indicate expecting an interrupt.
4554 //
4555
4556 deviceExtension->ExpectingInterrupt = TRUE;
4557
4558 //
4559 // Set up sector count register. Round up to next block.
4560 //
4561
4562 ScsiPortWritePortUchar(&baseIoAddress1->BlockCount,
4563 (UCHAR)((Srb->DataTransferLength + 0x1FF) / 0x200));
4564
4565 //
4566 // Get starting sector number from CDB.
4567 //
4568
4569 startingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 |
4570 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 |
4571 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 |
4572 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24;
4573
4574 DebugPrint((2,
4575 "IdeReadWrite: Starting sector is %x, Number of bytes %x\n",
4576 startingSector,
4578
4579 //
4580 // Set up sector number register.
4581 //
4582
4583 sectorNumber = (UCHAR)((startingSector % deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) + 1);
4584 ScsiPortWritePortUchar(&baseIoAddress1->BlockNumber,sectorNumber);
4585
4586 //
4587 // Set up cylinder low register.
4588 //
4589
4590 cylinderLow = (UCHAR)(startingSector / (deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack *
4591 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads));
4592 ScsiPortWritePortUchar(&baseIoAddress1->CylinderLow,cylinderLow);
4593
4594 //
4595 // Set up cylinder high register.
4596 //
4597
4598 cylinderHigh = (UCHAR)((startingSector / (deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack *
4599 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads)) >> 8);
4600 ScsiPortWritePortUchar(&baseIoAddress1->CylinderHigh,cylinderHigh);
4601
4602 //
4603 // Set up head and drive select register.
4604 //
4605
4606 drvSelect = (UCHAR)(((startingSector / deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) %
4607 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads) |((Srb->TargetId & 0x1) << 4) | 0xA0);
4608 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,drvSelect);
4609
4610 DebugPrint((2,
4611 "IdeReadWrite: Cylinder %x Head %x Sector %x\n",
4612 startingSector /
4613 (deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack *
4614 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads),
4615 (startingSector /
4616 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) %
4617 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads,
4618 startingSector %
4619 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack + 1));
4620
4621 //
4622 // Check if write request.
4623 //
4624
4626
4627 //
4628 // Send read command.
4629 //
4630
4631 if (deviceExtension->MaximumBlockXfer[Srb->TargetId]) {
4632 ScsiPortWritePortUchar(&baseIoAddress1->Command,
4634
4635 } else {
4636 ScsiPortWritePortUchar(&baseIoAddress1->Command,
4638 }
4639 } else {
4640
4641
4642 //
4643 // Send write command.
4644 //
4645
4646 if (deviceExtension->MaximumBlockXfer[Srb->TargetId]) {
4647 wordCount = 256 * deviceExtension->MaximumBlockXfer[Srb->TargetId];
4648
4649 if (deviceExtension->WordsLeft < wordCount) {
4650
4651 //
4652 // Transfer only words requested.
4653 //
4654
4655 wordCount = deviceExtension->WordsLeft;
4656
4657 }
4658 ScsiPortWritePortUchar(&baseIoAddress1->Command,
4660
4661 } else {
4662 wordCount = 256;
4663 ScsiPortWritePortUchar(&baseIoAddress1->Command,
4665 }
4666
4667 //
4668 // Wait for BSY and DRQ.
4669 //
4670
4671 WaitOnBaseBusy(baseIoAddress1,statusByte);
4672
4673 if (statusByte & IDE_STATUS_BUSY) {
4674
4675 DebugPrint((1,
4676 "IdeReadWrite 2: Returning BUSY status %x\n",
4677 statusByte));
4678 return SRB_STATUS_BUSY;
4679 }
4680
4681 for (i = 0; i < 1000; i++) {
4682 GetBaseStatus(baseIoAddress1, statusByte);
4683 if (statusByte & IDE_STATUS_DRQ) {
4684 break;
4685 }
4687
4688 }
4689
4690 if (!(statusByte & IDE_STATUS_DRQ)) {
4691
4692 DebugPrint((1,
4693 "IdeReadWrite: DRQ never asserted (%x) original status (%x)\n",
4694 statusByte,
4695 statusByte2));
4696
4697 deviceExtension->WordsLeft = 0;
4698
4699 //
4700 // Clear interrupt expecting flag.
4701 //
4702
4703 deviceExtension->ExpectingInterrupt = FALSE;
4704
4705 //
4706 // Clear current SRB.
4707 //
4708
4709 deviceExtension->CurrentSrb = NULL;
4710
4711 return SRB_STATUS_TIMEOUT;
4712 }
4713
4714 //
4715 // Write next 256 words.
4716 //
4717
4718 WriteBuffer(baseIoAddress1,
4719 deviceExtension->DataBuffer,
4720 wordCount);
4721
4722 //
4723 // Adjust buffer address and words left count.
4724 //
4725
4726 deviceExtension->WordsLeft -= wordCount;
4727 deviceExtension->DataBuffer += wordCount;
4728
4729 }
4730
4731 //
4732 // Wait for interrupt.
4733 //
4734
4735 return SRB_STATUS_PENDING;
4736
4737} // end IdeReadWrite()
#define IDE_COMMAND_WRITE_MULTIPLE
Definition: atapi.h:112
#define IDE_COMMAND_WRITE
Definition: atapi.h:105
#define IDE_COMMAND_READ_MULTIPLE
Definition: atapi.h:111
#define IDE_COMMAND_READ
Definition: atapi.h:104
#define SRB_STATUS_TIMEOUT
Definition: srb.h:349
UCHAR BlockNumber
Definition: atapi.h:19

Referenced by IdeSendCommand().

◆ IdeSendCommand()

ULONG NTAPI IdeSendCommand ( IN PVOID  HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 5336 of file atapi.c.

5358{
5359 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
5360 PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Srb->TargetId >> 1];
5361 PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Srb->TargetId >> 1];
5362 PCDB cdb;
5363
5364 UCHAR statusByte,errorByte;
5365 ULONG status;
5366 ULONG i;
5367 PMODE_PARAMETER_HEADER modeData;
5368
5369 DebugPrint((2,
5370 "IdeSendCommand: Command %x to device %d\n",
5371 Srb->Cdb[0],
5372 Srb->TargetId));
5373
5374
5375
5376 switch (Srb->Cdb[0]) {
5377 case SCSIOP_INQUIRY:
5378
5379 //
5380 // Filter out all TIDs but 0 and 1 since this is an IDE interface
5381 // which support up to two devices.
5382 //
5383
5384 if ((Srb->Lun != 0) ||
5385 (!(deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_DEVICE_PRESENT))) {
5386
5387 //
5388 // Indicate no device found at this address.
5389 //
5390
5392 break;
5393
5394 } else {
5395
5396 PINQUIRYDATA inquiryData = Srb->DataBuffer;
5397 PIDENTIFY_DATA2 identifyData = &deviceExtension->IdentifyData[Srb->TargetId];
5398
5399 //
5400 // Zero INQUIRY data structure.
5401 //
5402
5403 for (i = 0; i < Srb->DataTransferLength; i++) {
5404 ((PUCHAR)Srb->DataBuffer)[i] = 0;
5405 }
5406
5407 //
5408 // Standard IDE interface only supports disks.
5409 //
5410
5411 inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
5412
5413 //
5414 // Set the removable bit, if applicable.
5415 //
5416
5417 if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_REMOVABLE_DRIVE) {
5418 inquiryData->RemovableMedia = 1;
5419 }
5420
5421 //
5422 // Fill in vendor identification fields.
5423 //
5424
5425 for (i = 0; i < 8; i += 2) {
5426 inquiryData->VendorId[i] =
5427 ((PUCHAR)identifyData->ModelNumber)[i + 1];
5428 inquiryData->VendorId[i+1] =
5429 ((PUCHAR)identifyData->ModelNumber)[i];
5430 }
5431
5432 for (i = 0; i < 12; i += 2) {
5433 inquiryData->ProductId[i] =
5434 ((PUCHAR)identifyData->ModelNumber)[i + 8 + 1];
5435 inquiryData->ProductId[i+1] =
5436 ((PUCHAR)identifyData->ModelNumber)[i + 8];
5437 }
5438
5439 //
5440 // Initialize unused portion of product id.
5441 //
5442
5443 for (i = 0; i < 4; i++) {
5444 inquiryData->ProductId[12+i] = ' ';
5445 }
5446
5447 //
5448 // Move firmware revision from IDENTIFY data to
5449 // product revision in INQUIRY data.
5450 //
5451
5452 for (i = 0; i < 4; i += 2) {
5453 inquiryData->ProductRevisionLevel[i] =
5454 ((PUCHAR)identifyData->FirmwareRevision)[i+1];
5455 inquiryData->ProductRevisionLevel[i+1] =
5456 ((PUCHAR)identifyData->FirmwareRevision)[i];
5457 }
5458
5460 }
5461
5462 break;
5463
5464 case SCSIOP_MODE_SENSE:
5465
5466 //
5467 // This is used to determine of the media is write-protected.
5468 // Since IDE does not support mode sense then we will modify just the portion we need
5469 // so the higher level driver can determine if media is protected.
5470 //
5471
5472 if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_MEDIA_STATUS_ENABLED) {
5473
5474 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
5475 (UCHAR)(((Srb->TargetId & 0x1) << 4) | 0xA0));
5477 WaitOnBusy(baseIoAddress2,statusByte);
5478
5479 if (!(statusByte & IDE_STATUS_ERROR)){
5480
5481 //
5482 // no error occured return success, media is not protected
5483 //
5484
5485 deviceExtension->ExpectingInterrupt = FALSE;
5486
5487 } else {
5488
5489 //
5490 // error occured, handle it locally, clear interrupt
5491 //
5492
5493 errorByte = ScsiPortReadPortUchar((PUCHAR)baseIoAddress1 + 1);
5494
5495 GetBaseStatus(baseIoAddress1, statusByte);
5496 deviceExtension->ExpectingInterrupt = FALSE;
5497
5498 if (errorByte & IDE_ERROR_DATA_ERROR) {
5499
5500 //
5501 //media is write-protected, set bit in mode sense buffer
5502 //
5503
5505
5508 }
5509 }
5511 } else {
5513 }
5514 break;
5515
5517
5518 if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_MEDIA_STATUS_ENABLED) {
5519
5520 //
5521 // Select device 0 or 1.
5522 //
5523
5524 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
5525 (UCHAR)(((Srb->TargetId & 0x1) << 4) | 0xA0));
5527
5528 //
5529 // Wait for busy. If media has not changed, return success
5530 //
5531
5532 WaitOnBusy(baseIoAddress2,statusByte);
5533
5534 if (!(statusByte & IDE_STATUS_ERROR)){
5535 deviceExtension->ExpectingInterrupt = FALSE;
5537 } else {
5538 errorByte = ScsiPortReadPortUchar((PUCHAR)baseIoAddress1 + 1);
5539 if (errorByte == IDE_ERROR_DATA_ERROR){
5540
5541 //
5542 // Special case: If current media is write-protected,
5543 // the 0xDA command will always fail since the write-protect bit
5544 // is sticky,so we can ignore this error
5545 //
5546
5547 GetBaseStatus(baseIoAddress1, statusByte);
5548 deviceExtension->ExpectingInterrupt = FALSE;
5550
5551 } else {
5552
5553 //
5554 // Request sense buffer to be build
5555 //
5556 deviceExtension->ExpectingInterrupt = TRUE;
5558 }
5559 }
5560 } else {
5562 }
5563
5564 break;
5565
5567
5568 //
5569 // Claim 512 byte blocks (big-endian).
5570 //
5571
5572 ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
5573
5574 //
5575 // Calculate last sector.
5576 //
5577
5578
5579 i = (deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads *
5580 deviceExtension->IdentifyData[Srb->TargetId].NumberOfCylinders *
5581 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) - 1;
5582
5583 ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
5584 (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
5585 (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
5586
5587 DebugPrint((1,
5588 "IDE disk %x - #sectors %x, #heads %x, #cylinders %x\n",
5589 Srb->TargetId,
5590 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack,
5591 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads,
5592 deviceExtension->IdentifyData[Srb->TargetId].NumberOfCylinders));
5593
5594
5596 break;
5597
5598 case SCSIOP_VERIFY:
5599 status = IdeVerify(HwDeviceExtension,Srb);
5600
5601 break;
5602
5603 case SCSIOP_READ:
5604 case SCSIOP_WRITE:
5605
5606 status = IdeReadWrite(HwDeviceExtension,
5607 Srb);
5608 break;
5609
5611
5612 //
5613 //Determine what type of operation we should perform
5614 //
5615 cdb = (PCDB)Srb->Cdb;
5616
5617 if (cdb->START_STOP.LoadEject == 1){
5618
5619 //
5620 // Eject media,
5621 // first select device 0 or 1.
5622 //
5623 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
5624 (UCHAR)(((Srb->TargetId & 0x1) << 4) | 0xA0));
5626 }
5628 break;
5629
5631 // this function makes sense buffers to report the results
5632 // of the original GET_MEDIA_STATUS command
5633
5634 if (deviceExtension->DeviceFlags[Srb->TargetId] & DFLAGS_MEDIA_STATUS_ENABLED) {
5635 status = IdeBuildSenseBuffer(HwDeviceExtension,Srb);
5636 break;
5637 }
5638
5639 default:
5640
5641 DebugPrint((1,
5642 "IdeSendCommand: Unsupported command %x\n",
5643 Srb->Cdb[0]));
5644
5646
5647 } // end switch
5648
5649 return status;
5650
5651} // end IdeSendCommand()
#define IDE_COMMAND_GET_MEDIA_STATUS
Definition: atapi.h:116
#define IDE_COMMAND_MEDIA_EJECT
Definition: atapi.h:119
ULONG NTAPI IdeReadWrite(IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
Definition: atapi.c:4499
ULONG NTAPI IdeBuildSenseBuffer(IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
Definition: atapi.c:5737
ULONG NTAPI IdeVerify(IN PVOID HwDeviceExtension, IN PSCSI_REQUEST_BLOCK Srb)
Definition: atapi.c:4743
struct _READ_CAPACITY_DATA * PREAD_CAPACITY_DATA
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
#define DIRECT_ACCESS_DEVICE
Definition: cdrw_hw.h:1144
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
#define SCSIOP_VERIFY
Definition: cdrw_hw.h:912
#define MODE_DSP_WRITE_PROTECT
Definition: cdrw_hw.h:2523
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
#define SCSIOP_READ
Definition: cdrw_hw.h:905
USHORT NumberOfCylinders
Definition: atapi.h:250
USHORT FirmwareRevision[4]
Definition: atapi.h:261
UCHAR RemovableMedia
Definition: cdrw_hw.h:1119
UCHAR ProductId[16]
Definition: cdrw_hw.h:1133
UCHAR ProductRevisionLevel[4]
Definition: cdrw_hw.h:1134
UCHAR VendorId[8]
Definition: cdrw_hw.h:1132
UCHAR DeviceType
Definition: cdrw_hw.h:1116
UCHAR DeviceSpecificParameter
Definition: cdrw_hw.h:2507
struct _CDB::_START_STOP START_STOP

Referenced by AtapiStartIo().

◆ IdeSendSmartCommand()

ULONG NTAPI IdeSendSmartCommand ( IN PVOID  HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 4343 of file atapi.c.

4365{
4366 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
4367 PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Srb->TargetId >> 1];
4368 PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Srb->TargetId >> 1];
4369 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
4370 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
4371 PIDEREGS regs = &cmdInParameters.irDriveRegs;
4372 ULONG i;
4373 UCHAR statusByte,targetId;
4374
4375
4376 if (cmdInParameters.irDriveRegs.bCommandReg == SMART_CMD) {
4377
4378 targetId = cmdInParameters.bDriveNumber;
4379
4380 //TODO optimize this check
4381
4382 if ((!(deviceExtension->DeviceFlags[targetId] & DFLAGS_DEVICE_PRESENT)) ||
4383 (deviceExtension->DeviceFlags[targetId] & DFLAGS_ATAPI_DEVICE)) {
4384
4386 }
4387
4388 deviceExtension->SmartCommand = cmdInParameters.irDriveRegs.bFeaturesReg;
4389
4390 //
4391 // Determine which of the commands to carry out.
4392 //
4393
4394 if ((cmdInParameters.irDriveRegs.bFeaturesReg == READ_ATTRIBUTES) ||
4395 (cmdInParameters.irDriveRegs.bFeaturesReg == READ_THRESHOLDS)) {
4396
4397 WaitOnBusy(baseIoAddress2,statusByte);
4398
4399 if (statusByte & IDE_STATUS_BUSY) {
4400 DebugPrint((1,
4401 "IdeSendSmartCommand: Returning BUSY status\n"));
4402 return SRB_STATUS_BUSY;
4403 }
4404
4405 //
4406 // Zero the output buffer as the input buffer info. has been saved off locally (the buffers are the same).
4407 //
4408
4409 for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1); i++) {
4410 ((PUCHAR)cmdOutParameters)[i] = 0;
4411 }
4412
4413 //
4414 // Set data buffer pointer and words left.
4415 //
4416
4417 deviceExtension->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
4418 deviceExtension->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
4419
4420 //
4421 // Indicate expecting an interrupt.
4422 //
4423
4424 deviceExtension->ExpectingInterrupt = TRUE;
4425
4426 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,(UCHAR)(((targetId & 0x1) << 4) | 0xA0));
4427 ScsiPortWritePortUchar((PUCHAR)baseIoAddress1 + 1,regs->bFeaturesReg);
4428 ScsiPortWritePortUchar(&baseIoAddress1->BlockCount,regs->bSectorCountReg);
4429 ScsiPortWritePortUchar(&baseIoAddress1->BlockNumber,regs->bSectorNumberReg);
4430 ScsiPortWritePortUchar(&baseIoAddress1->CylinderLow,regs->bCylLowReg);
4431 ScsiPortWritePortUchar(&baseIoAddress1->CylinderHigh,regs->bCylHighReg);
4432 ScsiPortWritePortUchar(&baseIoAddress1->Command,regs->bCommandReg);
4433
4434 //
4435 // Wait for interrupt.
4436 //
4437
4438 return SRB_STATUS_PENDING;
4439
4440 } else if ((cmdInParameters.irDriveRegs.bFeaturesReg == ENABLE_SMART) ||
4441 (cmdInParameters.irDriveRegs.bFeaturesReg == DISABLE_SMART) ||
4442 (cmdInParameters.irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS) ||
4443 (cmdInParameters.irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTOSAVE) ||
4444 (cmdInParameters.irDriveRegs.bFeaturesReg == EXECUTE_OFFLINE_DIAGS) ||
4445 (cmdInParameters.irDriveRegs.bFeaturesReg == SAVE_ATTRIBUTE_VALUES)) {
4446
4447 WaitOnBusy(baseIoAddress2,statusByte);
4448
4449 if (statusByte & IDE_STATUS_BUSY) {
4450 DebugPrint((1,
4451 "IdeSendSmartCommand: Returning BUSY status\n"));
4452 return SRB_STATUS_BUSY;
4453 }
4454
4455 //
4456 // Zero the output buffer as the input buffer info. has been saved off locally (the buffers are the same).
4457 //
4458
4459 for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) - 1); i++) {
4460 ((PUCHAR)cmdOutParameters)[i] = 0;
4461 }
4462
4463 //
4464 // Set data buffer pointer and indicate no data transfer.
4465 //
4466
4467 deviceExtension->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
4468 deviceExtension->WordsLeft = 0;
4469
4470 //
4471 // Indicate expecting an interrupt.
4472 //
4473
4474 deviceExtension->ExpectingInterrupt = TRUE;
4475
4476 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,(UCHAR)(((targetId & 0x1) << 4) | 0xA0));
4477 ScsiPortWritePortUchar((PUCHAR)baseIoAddress1 + 1,regs->bFeaturesReg);
4478 ScsiPortWritePortUchar(&baseIoAddress1->BlockCount,regs->bSectorCountReg);
4479 ScsiPortWritePortUchar(&baseIoAddress1->BlockNumber,regs->bSectorNumberReg);
4480 ScsiPortWritePortUchar(&baseIoAddress1->CylinderLow,regs->bCylLowReg);
4481 ScsiPortWritePortUchar(&baseIoAddress1->CylinderHigh,regs->bCylHighReg);
4482 ScsiPortWritePortUchar(&baseIoAddress1->Command,regs->bCommandReg);
4483
4484 //
4485 // Wait for interrupt.
4486 //
4487
4488 return SRB_STATUS_PENDING;
4489 }
4490 }
4491
4493
4494} // end IdeSendSmartCommand()
#define EXECUTE_OFFLINE_DIAGS
Definition: ntdddisk.h:748
#define READ_ATTRIBUTE_BUFFER_SIZE
Definition: ntdddisk.h:731
#define ENABLE_SMART
Definition: ntdddisk.h:751
#define SAVE_ATTRIBUTE_VALUES
Definition: ntdddisk.h:747
#define READ_THRESHOLDS
Definition: ntdddisk.h:745
#define DISABLE_SMART
Definition: ntdddisk.h:752
#define READ_ATTRIBUTES
Definition: ntdddisk.h:744
#define ENABLE_DISABLE_AUTOSAVE
Definition: ntdddisk.h:746
struct @5029 regs[]
Definition: helper.h:8
UCHAR bFeaturesReg
Definition: helper.h:9

Referenced by AtapiStartIo().

◆ IdeVerify()

ULONG NTAPI IdeVerify ( IN PVOID  HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 4743 of file atapi.c.

4765{
4766 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
4767 PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Srb->TargetId >> 1];
4768 //PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Srb->TargetId >> 1];
4769 ULONG startingSector;
4770 ULONG sectors;
4771 ULONG endSector;
4773
4774 //
4775 // Drive has these number sectors.
4776 //
4777
4778 sectors = deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack *
4779 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads *
4780 deviceExtension->IdentifyData[Srb->TargetId].NumberOfCylinders;
4781
4782 DebugPrint((3,
4783 "IdeVerify: Total sectors %x\n",
4784 sectors));
4785
4786 //
4787 // Get starting sector number from CDB.
4788 //
4789
4790 startingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 |
4791 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 |
4792 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 |
4793 ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24;
4794
4795 DebugPrint((3,
4796 "IdeVerify: Starting sector %x. Number of blocks %x\n",
4797 startingSector,
4798 ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb));
4799
4800 sectorCount = (USHORT)(((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8 |
4801 ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb );
4802 endSector = startingSector + sectorCount;
4803
4804 DebugPrint((3,
4805 "IdeVerify: Ending sector %x\n",
4806 endSector));
4807
4808 if (endSector > sectors) {
4809
4810 //
4811 // Too big, round down.
4812 //
4813
4814 DebugPrint((1,
4815 "IdeVerify: Truncating request to %x blocks\n",
4816 sectors - startingSector - 1));
4817
4818 ScsiPortWritePortUchar(&baseIoAddress1->BlockCount,
4819 (UCHAR)(sectors - startingSector - 1));
4820
4821 } else {
4822
4823 //
4824 // Set up sector count register. Round up to next block.
4825 //
4826
4827 if (sectorCount > 0xFF) {
4828 sectorCount = (USHORT)0xFF;
4829 }
4830
4832 }
4833
4834 //
4835 // Set data buffer pointer and words left.
4836 //
4837
4838 deviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer;
4839 deviceExtension->WordsLeft = Srb->DataTransferLength / 2;
4840
4841 //
4842 // Indicate expecting an interrupt.
4843 //
4844
4845 deviceExtension->ExpectingInterrupt = TRUE;
4846
4847 //
4848 // Set up sector number register.
4849 //
4850
4851 ScsiPortWritePortUchar(&baseIoAddress1->BlockNumber,
4852 (UCHAR)((startingSector %
4853 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) + 1));
4854
4855 //
4856 // Set up cylinder low register.
4857 //
4858
4859 ScsiPortWritePortUchar(&baseIoAddress1->CylinderLow,
4860 (UCHAR)(startingSector /
4861 (deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack *
4862 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads)));
4863
4864 //
4865 // Set up cylinder high register.
4866 //
4867
4868 ScsiPortWritePortUchar(&baseIoAddress1->CylinderHigh,
4869 (UCHAR)((startingSector /
4870 (deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack *
4871 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads)) >> 8));
4872
4873 //
4874 // Set up head and drive select register.
4875 //
4876
4877 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
4878 (UCHAR)(((startingSector /
4879 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) %
4880 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads) |
4881 ((Srb->TargetId & 0x1) << 4) | 0xA0));
4882
4883 DebugPrint((2,
4884 "IdeVerify: Cylinder %x Head %x Sector %x\n",
4885 startingSector /
4886 (deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack *
4887 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads),
4888 (startingSector /
4889 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack) %
4890 deviceExtension->IdentifyData[Srb->TargetId].NumberOfHeads,
4891 startingSector %
4892 deviceExtension->IdentifyData[Srb->TargetId].SectorsPerTrack + 1));
4893
4894
4895 //
4896 // Send verify command.
4897 //
4898
4899 ScsiPortWritePortUchar(&baseIoAddress1->Command,
4901
4902 //
4903 // Wait for interrupt.
4904 //
4905
4906 return SRB_STATUS_PENDING;
4907
4908} // end IdeVerify()
#define IDE_COMMAND_VERIFY
Definition: atapi.h:106
UINT sectorCount[1]
Definition: diskio.c:16
__u8 sectors[2]
Definition: mkdosfs.c:8

Referenced by IdeSendCommand().

◆ IssueIdentify()

BOOLEAN NTAPI IssueIdentify ( IN PVOID  HwDeviceExtension,
IN ULONG  DeviceNumber,
IN ULONG  Channel,
IN UCHAR  Command 
)

Definition at line 251 of file atapi.c.

276{
277 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
278 PIDE_REGISTERS_1 baseIoAddress1 = deviceExtension->BaseIoAddress1[Channel] ;
279 PIDE_REGISTERS_2 baseIoAddress2 = deviceExtension->BaseIoAddress2[Channel];
280 ULONG waitCount = 20000;
281 ULONG i,j;
282 UCHAR statusByte;
283 UCHAR signatureLow,
284 signatureHigh;
285
286 //
287 // Select device 0 or 1.
288 //
289
290 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
291 (UCHAR)((DeviceNumber << 4) | 0xA0));
292
293 //
294 // Check that the status register makes sense.
295 //
296
297 GetBaseStatus(baseIoAddress1, statusByte);
298
300
301 //
302 // Mask status byte ERROR bits.
303 //
304
305 statusByte &= ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX);
306
307 DebugPrint((1,
308 "IssueIdentify: Checking for IDE. Status (%x)\n",
309 statusByte));
310
311 //
312 // Check if register value is reasonable.
313 //
314
315 if (statusByte != IDE_STATUS_IDLE) {
316
317 //
318 // Reset the controller.
319 //
320
321 AtapiSoftReset(baseIoAddress1,DeviceNumber);
322
323 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
324 (UCHAR)((DeviceNumber << 4) | 0xA0));
325
326 WaitOnBusy(baseIoAddress2,statusByte);
327
328 signatureLow = ScsiPortReadPortUchar(&baseIoAddress1->CylinderLow);
329 signatureHigh = ScsiPortReadPortUchar(&baseIoAddress1->CylinderHigh);
330
331 if (signatureLow == 0x14 && signatureHigh == 0xEB) {
332
333 //
334 // Device is Atapi.
335 //
336
337 return FALSE;
338 }
339
340 DebugPrint((1,
341 "IssueIdentify: Resetting controller.\n"));
342
344 ScsiPortStallExecution(500 * 1000);
346
347
348 // We really should wait up to 31 seconds
349 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
350 // (30 seconds for device 1)
351 do {
352
353 //
354 // Wait for Busy to drop.
355 //
356
358 GetStatus(baseIoAddress2, statusByte);
359
360 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
361
362 ScsiPortWritePortUchar(&baseIoAddress1->DriveSelect,
363 (UCHAR)((DeviceNumber << 4) | 0xA0));
364
365 //
366 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
367 // a soft reset.
368 //
369
370 signatureLow = ScsiPortReadPortUchar(&baseIoAddress1->CylinderLow);
371 signatureHigh = ScsiPortReadPortUchar(&baseIoAddress1->CylinderHigh);
372
373 if (signatureLow == 0x14 && signatureHigh == 0xEB) {
374
375 //
376 // Device is Atapi.
377 //
378
379 return FALSE;
380 }
381
382 statusByte &= ~IDE_STATUS_INDEX;
383
384 if (statusByte != IDE_STATUS_IDLE) {
385
386 //
387 // Give up on this.
388 //
389
390 return FALSE;
391 }
392
393 }
394
395 } else {
396
397 DebugPrint((1,
398 "IssueIdentify: Checking for ATAPI. Status (%x)\n",
399 statusByte));
400
401 }
402
403 //
404 // Load CylinderHigh and CylinderLow with number bytes to transfer.
405 //
406
407 ScsiPortWritePortUchar(&baseIoAddress1->