|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1991, 1992, 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: i386\atd_conf.c ! 8: ! 9: Abstract: ! 10: ! 11: This file includes the routine to get ix86 platform-dependent ! 12: configuration information for the AT disk (aka ST506, ISA, and ix86 ! 13: standard hard disk) driver for NT. ! 14: ! 15: If this driver is ported to a different platform, this file (and ! 16: atd_plat.h) will need to be modified extensively. The build ! 17: procedure should make sure that the proper version of this file is ! 18: available as atd_conf.h (which is included by atdisk.c) when ! 19: building for a specific platform. ! 20: ! 21: Author: ! 22: ! 23: Chad Schwitters (chads) 21-Feb-1991. ! 24: ! 25: Environment: ! 26: ! 27: Kernel mode only. ! 28: ! 29: Notes: ! 30: ! 31: Revision History: ! 32: ! 33: --*/ ! 34: ! 35: #include "ntddk.h" // various NT definitions ! 36: #include "ntdddisk.h" // disk device driver I/O control codes ! 37: #include <atd_plat.h> // this driver's platform dependent stuff ! 38: #include <atd_data.h> // this driver's data declarations ! 39: ! 40: NTSTATUS ! 41: AtConfigCallBack( ! 42: IN PVOID Context, ! 43: IN PUNICODE_STRING PathName, ! 44: IN INTERFACE_TYPE BusType, ! 45: IN ULONG BusNumber, ! 46: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 47: IN CONFIGURATION_TYPE ControllerType, ! 48: IN ULONG ControllerNumber, ! 49: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 50: IN CONFIGURATION_TYPE PeripheralType, ! 51: IN ULONG PeripheralNumber, ! 52: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 53: ); ! 54: ! 55: BOOLEAN ! 56: UpdateGeometryFromBios( ! 57: PDRIVER_OBJECT DriverObject, ! 58: DRIVE_DATA *DriveData, ! 59: ULONG DiskNumber ! 60: ); ! 61: ! 62: BOOLEAN ! 63: UpdateGeometryFromParameterTable( ! 64: DRIVE_DATA *DriveData, ! 65: CCHAR *ControlFlags, ! 66: ULONG ParameterTableOffset ! 67: ); ! 68: ! 69: BOOLEAN ! 70: GetGeometryFromIdentify( ! 71: PCONTROLLER_DATA ControllerData, ! 72: ULONG DiskNumber ! 73: ); ! 74: ! 75: BOOLEAN ! 76: IssueIdentify( ! 77: PCONTROLLER_DATA ControllerData, ! 78: PUCHAR Buffer, ! 79: ULONG DiskNumber ! 80: ); ! 81: ! 82: #ifdef ALLOC_PRAGMA ! 83: #pragma alloc_text(init,AtConfigCallBack) ! 84: #pragma alloc_text(init,AtGetConfigInfo) ! 85: #pragma alloc_text(init,UpdateGeometryFromBios) ! 86: #pragma alloc_text(init,UpdateGeometryFromParameterTable) ! 87: #endif ! 88: ! 89: ! 90: NTSTATUS ! 91: AtConfigCallBack( ! 92: IN PVOID Context, ! 93: IN PUNICODE_STRING PathName, ! 94: IN INTERFACE_TYPE BusType, ! 95: IN ULONG BusNumber, ! 96: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 97: IN CONFIGURATION_TYPE ControllerType, ! 98: IN ULONG ControllerNumber, ! 99: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 100: IN CONFIGURATION_TYPE PeripheralType, ! 101: IN ULONG PeripheralNumber, ! 102: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 103: ) ! 104: ! 105: /*++ ! 106: ! 107: Routine Description: ! 108: ! 109: This routine is used to acquire all of the configuration ! 110: information for each floppy disk controller and the ! 111: peripheral driver attached to that controller. ! 112: ! 113: Arguments: ! 114: ! 115: Context - Pointer to boolean. ! 116: ! 117: PathName - unicode registry path. Not Used. ! 118: ! 119: BusType - Internal, Isa, ... ! 120: ! 121: BusNumber - Should Always be zero. ! 122: ! 123: BusInformation - Configuration information about the bus. Not Used. ! 124: ! 125: ControllerType - Controller Type. Not Used. ! 126: ! 127: ControllerNumber - Which controller if there is more than one ! 128: controller in the system. Not Used ! 129: ! 130: ControllerInformation - Array of pointers to the three pieces of ! 131: registry information. Not Used ! 132: ! 133: PeripheralType - Peripheral Type. Not Used. ! 134: ! 135: PeripheralNumber - Which floppy if this controller is maintaining ! 136: more than one. Not Used ! 137: ! 138: PeripheralInformation - Arrya of pointers to the three pieces of ! 139: registry information. Not Used. ! 140: ! 141: Return Value: ! 142: ! 143: STATUS_SUCCESS ! 144: ! 145: --*/ ! 146: ! 147: { ! 148: ! 149: ASSERT(BusNumber == 0); ! 150: *((PBOOLEAN)Context) = TRUE; ! 151: return STATUS_SUCCESS; ! 152: ! 153: } ! 154: ! 155: NTSTATUS ! 156: AtGetConfigInfo( ! 157: IN PDRIVER_OBJECT DriverObject, ! 158: IN PUNICODE_STRING RegistryPath, ! 159: IN OUT PCONFIG_DATA ConfigData ! 160: ) ! 161: ! 162: /*++ ! 163: ! 164: Routine Description: ! 165: ! 166: This routine is called once at initialization time by ! 167: AtDiskInitialize() to get information about the disks that are to be ! 168: supported. ! 169: ! 170: Some values here are simply assumed (i.e. number of controllers, and ! 171: base address of controller). Other are determined by poking CMOS ! 172: (i.e. how many drives are on the controller) or by peering into ROM (i.e. ! 173: sectors per track for each drive). ! 174: ! 175: Arguments: ! 176: ! 177: DriverObject - The driver object for this driver. ! 178: ! 179: RegistryPath - The string that takes us to this drivers service node. ! 180: ! 181: ConfigData - a pointer to the pointer to a data structure that ! 182: describes the controllers and the disks attached to them ! 183: ! 184: Return Value: ! 185: ! 186: Returns STATUS_SUCCESS unless there is no drive 0. ! 187: ! 188: --*/ ! 189: ! 190: { ! 191: ULONG paramTable; ! 192: PUSHORT paramVector; ! 193: UCHAR *namePointer; ! 194: ULONG i, j, k; ! 195: UCHAR configuredIrq; ! 196: UCHAR writeValue; ! 197: UCHAR driveTypes; ! 198: PCONFIGURATION_INFORMATION configurationInformation; ! 199: BOOLEAN machineIsCompaq = FALSE; ! 200: BOOLEAN foundIt = FALSE; ! 201: ULONG diskCount; ! 202: INTERFACE_TYPE defaultInterfaceType; ! 203: ULONG defaultBusNumber; ! 204: KIRQL defaultIrql; ! 205: PHYSICAL_ADDRESS defaultBaseAddress; ! 206: PHYSICAL_ADDRESS defaultPortAddress; ! 207: RTL_QUERY_REGISTRY_TABLE registryTable[2] = {0}; ! 208: UNICODE_STRING ps1Data; ! 209: UNICODE_STRING ps1Value; ! 210: BOOLEAN ps1Detected; ! 211: UCHAR buffer[512]; ! 212: CCHAR badDisks[][40] = {" 94244-383"}; ! 213: ULONG numberOfBadDisks = sizeof(badDisks)/sizeof(badDisks[0]); ! 214: ! 215: // ! 216: // Get the temporary configuration manager information. ! 217: // ! 218: ! 219: configurationInformation = IoGetConfigurationInformation( ); ! 220: ConfigData->HardDiskCount = &configurationInformation->DiskCount; ! 221: ConfigData->ArcNamePrefix = TemporaryArcNamePrefix; ! 222: diskCount = configurationInformation->DiskCount; ! 223: ! 224: // ! 225: // This driver only knows how to work on the first isa ! 226: // or eisa bus in the system. Call IoQeuryDeviceDescription ! 227: // to make sure that there is such a bus on the system. ! 228: // ! 229: ! 230: foundIt = FALSE; ! 231: ! 232: // ! 233: // If it can't find the bus then just assume that it's the ! 234: // first isa bus. ! 235: // ! 236: ! 237: defaultInterfaceType = Isa; ! 238: defaultBusNumber = 0; ! 239: ! 240: IoQueryDeviceDescription( ! 241: &defaultInterfaceType, ! 242: &defaultBusNumber, ! 243: NULL, ! 244: NULL, ! 245: NULL, ! 246: NULL, ! 247: AtConfigCallBack, ! 248: &foundIt ! 249: ); ! 250: ! 251: if (!foundIt) { ! 252: ! 253: defaultInterfaceType = Eisa; ! 254: defaultBusNumber = 0; ! 255: IoQueryDeviceDescription( ! 256: &defaultInterfaceType, ! 257: &defaultBusNumber, ! 258: NULL, ! 259: NULL, ! 260: NULL, ! 261: NULL, ! 262: AtConfigCallBack, ! 263: &foundIt ! 264: ); ! 265: ! 266: if (!foundIt) { ! 267: ! 268: defaultInterfaceType = Isa; ! 269: defaultBusNumber = 0; ! 270: AtDump( ! 271: ATERRORS, ! 272: ("ATDISK: Not EISA OR ISA BY CONFIG, ASSUME ISA\n") ! 273: ); ! 274: ! 275: } ! 276: } ! 277: ! 278: // ! 279: // Check if first controller s unclaimed. ! 280: // ! 281: ! 282: if (!configurationInformation->AtDiskPrimaryAddressClaimed) { ! 283: ! 284: // ! 285: // Fill in some controller information. ! 286: // ! 287: ! 288: defaultBaseAddress.LowPart = 0x1F0; ! 289: defaultBaseAddress.HighPart = 0; ! 290: defaultPortAddress.LowPart = 0x3f6; ! 291: defaultPortAddress.HighPart = 0; ! 292: defaultIrql = 14; ! 293: AtDiskControllerInfo( ! 294: DriverObject, ! 295: RegistryPath, ! 296: 0, ! 297: &ConfigData->Controller[0], ! 298: defaultBaseAddress, ! 299: defaultPortAddress, ! 300: defaultIrql, ! 301: defaultInterfaceType, ! 302: defaultBusNumber, ! 303: TRUE ! 304: ); ! 305: ! 306: // ! 307: // Check if controller active at primary address. ! 308: // ! 309: ! 310: if (AtControllerPresent(&ConfigData->Controller[0])) { ! 311: ! 312: // ! 313: // Claim ATDISK primary IO address range. ! 314: // ! 315: ! 316: configurationInformation->AtDiskPrimaryAddressClaimed = TRUE; ! 317: ! 318: ConfigData->Controller[0].OkToUseThisController = TRUE; ! 319: ! 320: // ! 321: // Check to see if this is a ps/1 compatible. If it is ! 322: // then we have to do something different. (Don't ask ! 323: // me, ask IBM. I'm sure that they have an interesting ! 324: // answer.) If it is a ps/1 compatible, then zero out ! 325: // the cmos types. We'll look in the BIOS. ! 326: // ! 327: ! 328: ps1Data.Length = 0; ! 329: ps1Data.MaximumLength = sizeof(buffer); ! 330: ps1Data.Buffer = (PWCHAR)&buffer[0]; ! 331: RtlInitUnicodeString( ! 332: &ps1Value, ! 333: L"PS1/PS1 COMPATIBLE" ! 334: ); ! 335: registryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | ! 336: RTL_QUERY_REGISTRY_REQUIRED; ! 337: registryTable[0].Name = L"Identifier"; ! 338: registryTable[0].EntryContext = &ps1Data; ! 339: ! 340: if (!NT_SUCCESS(RtlQueryRegistryValues( ! 341: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, ! 342: L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM", ! 343: ®istryTable[0], ! 344: NULL, ! 345: NULL ! 346: ))) { ! 347: ! 348: // ! 349: // How odd, no identifer string! We'll it's probably not a ps1. ! 350: // ! 351: ! 352: ps1Detected = FALSE; ! 353: ! 354: } else { ! 355: ! 356: ps1Detected = RtlEqualUnicodeString( ! 357: &ps1Data, ! 358: &ps1Value, ! 359: FALSE ! 360: ); ! 361: ! 362: ! 363: } ! 364: ! 365: if (ps1Detected) { ! 366: ! 367: ConfigData->Controller[0].Disk[0].DriveType = 0; ! 368: ConfigData->Controller[0].Disk[1].DriveType = 0; ! 369: ! 370: } else { ! 371: ! 372: // ! 373: // Check CMOS for drive types for first and second disk. ! 374: // ! 375: ! 376: WRITE_PORT_UCHAR(CFGMEM_QUERY_PORT, CFGMEM_FIRST_CONTROLLER_DRIVE_TYPES); ! 377: ! 378: KeStallExecutionProcessor( 1L ); ! 379: ! 380: driveTypes = READ_PORT_UCHAR( CFGMEM_DATA_PORT ); ! 381: ! 382: ConfigData->Controller[0].Disk[0].DriveType = (UCHAR) ! 383: ( driveTypes & CFGMEM_DRIVES_FIRST_DRIVE_MASK ); ! 384: ! 385: if ( ConfigData->Controller[0].Disk[0].DriveType == 0xf0 ) { ! 386: ! 387: WRITE_PORT_UCHAR( CFGMEM_QUERY_PORT, CFGMEM_HARD_DRIVE_TYPE_ONE ); ! 388: ! 389: KeStallExecutionProcessor( 1L ); ! 390: ! 391: ConfigData->Controller[0].Disk[0].DriveType = ! 392: READ_PORT_UCHAR( CFGMEM_DATA_PORT ); ! 393: } ! 394: ! 395: ConfigData->Controller[0].Disk[1].DriveType = (UCHAR) ! 396: ( driveTypes & CFGMEM_DRIVES_SECOND_DRIVE_MASK ); ! 397: ! 398: if ( ConfigData->Controller[0].Disk[1].DriveType == 0x0f ) { ! 399: ! 400: WRITE_PORT_UCHAR( CFGMEM_QUERY_PORT, CFGMEM_HARD_DRIVE_TYPE_TWO ); ! 401: ! 402: KeStallExecutionProcessor( 1L ); ! 403: ! 404: ConfigData->Controller[0].Disk[1].DriveType = ! 405: READ_PORT_UCHAR( CFGMEM_DATA_PORT ); ! 406: } ! 407: ! 408: } ! 409: ! 410: if (ConfigData->Controller[0].Disk[0].DriveType) { ! 411: ! 412: // ! 413: // Bump disk count. ! 414: // ! 415: ! 416: diskCount++; ! 417: ! 418: // ! 419: // Map BIOS vector 41 for first disk. ! 420: // ! 421: ! 422: paramVector = MmMapIoSpace( ! 423: RtlConvertUlongToLargeInteger ( ! 424: PTR_TO_FDPT0_ADDRESS), ! 425: sizeof( ULONG ), ! 426: FALSE ); ! 427: ! 428: // ! 429: // Map drive parameter table for first disk. ! 430: // ! 431: ! 432: if (*paramVector) { ! 433: ! 434: UpdateGeometryFromParameterTable(&ConfigData->Controller[0].Disk[0], ! 435: &ConfigData->Controller[0].ControlFlags, ! 436: ((*(paramVector + 1)) << 4 ) + *paramVector); ! 437: ! 438: } else { ! 439: ! 440: // ! 441: // Check BIOS information passed in from NTDETECT. ! 442: // ! 443: ! 444: if (UpdateGeometryFromBios(DriverObject, ! 445: &ConfigData->Controller[0].Disk[0], ! 446: 0)) { ! 447: ConfigData->Controller[0].Disk[0].DriveType = 0xFF; ! 448: } ! 449: } ! 450: ! 451: MmUnmapIoSpace( paramVector, sizeof( ULONG ) ); ! 452: ! 453: } else { ! 454: ! 455: // ! 456: // Verify that a disk is attached to the first controller. ! 457: // ! 458: ! 459: if (IssueIdentify(&ConfigData->Controller[0], ! 460: buffer, ! 461: 0)) { ! 462: ! 463: // ! 464: // Check BIOS information passed in from NTDETECT. ! 465: // ! 466: ! 467: if (UpdateGeometryFromBios(DriverObject, ! 468: &ConfigData->Controller[0].Disk[0], ! 469: 0)) { ! 470: ! 471: diskCount++; ! 472: ConfigData->Controller[0].Disk[0].DriveType = 0xFF; ! 473: } ! 474: } ! 475: } ! 476: ! 477: if (ConfigData->Controller[0].Disk[1].DriveType) { ! 478: ! 479: // ! 480: // Bump disk count. ! 481: // ! 482: ! 483: diskCount++; ! 484: ! 485: // ! 486: // Map BIOS vector 46 for second disk. ! 487: // ! 488: ! 489: paramVector = MmMapIoSpace( ! 490: RtlConvertUlongToLargeInteger ( ! 491: PTR_TO_FDPT1_ADDRESS), ! 492: sizeof( ULONG ), ! 493: FALSE ); ! 494: ! 495: // ! 496: // Map drive parameter table for second disk. ! 497: // ! 498: ! 499: if (*paramVector) { ! 500: ! 501: if (UpdateGeometryFromParameterTable(&ConfigData->Controller[0].Disk[1], ! 502: &ConfigData->Controller[0].ControlFlags, ! 503: ((*(paramVector + 1)) << 4 ) + *paramVector)) { ! 504: ConfigData->Controller[0].Disk[1].DriveType = 0xFF; ! 505: } ! 506: ! 507: } else { ! 508: ! 509: // ! 510: // Check BIOS information passed in from NTDETECT. ! 511: // ! 512: ! 513: if (UpdateGeometryFromBios(DriverObject, ! 514: &ConfigData->Controller[0].Disk[1], ! 515: 1)) { ! 516: ConfigData->Controller[0].Disk[1].DriveType = 0xFF; ! 517: } ! 518: } ! 519: ! 520: MmUnmapIoSpace( paramVector, sizeof( ULONG ) ); ! 521: ! 522: } else { ! 523: ! 524: // ! 525: // Verify that a second disk is attached to the first controller. ! 526: // ! 527: ! 528: if (IssueIdentify(&ConfigData->Controller[0], ! 529: buffer, ! 530: 1)) { ! 531: ! 532: // ! 533: // Check BIOS information passed in from NTDETECT. ! 534: // ! 535: ! 536: if (UpdateGeometryFromBios(DriverObject, ! 537: &ConfigData->Controller[0].Disk[1], ! 538: 1)) { ! 539: ! 540: diskCount++; ! 541: ConfigData->Controller[0].Disk[1].DriveType = 0xFF; ! 542: } ! 543: } ! 544: } ! 545: } ! 546: } ! 547: ! 548: // ! 549: // Check for unclaimed second controller. ! 550: // ! 551: ! 552: if (!configurationInformation->AtDiskSecondaryAddressClaimed) { ! 553: ! 554: // ! 555: // Fill in controller description. ! 556: // ! 557: ! 558: defaultBaseAddress.LowPart = 0x170; ! 559: defaultBaseAddress.HighPart = 0; ! 560: defaultPortAddress.LowPart = 0x376; ! 561: defaultPortAddress.HighPart = 0; ! 562: ! 563: // ! 564: // If this is a compaq then the values for the ! 565: // vector may be wrong. They will get mapped ! 566: // to the correct value in a little bit. ! 567: // ! 568: ! 569: defaultIrql = 15; ! 570: AtDiskControllerInfo( ! 571: DriverObject, ! 572: RegistryPath, ! 573: 1, ! 574: &ConfigData->Controller[1], ! 575: defaultBaseAddress, ! 576: defaultPortAddress, ! 577: defaultIrql, ! 578: defaultInterfaceType, ! 579: defaultBusNumber, ! 580: TRUE ! 581: ); ! 582: ! 583: // ! 584: // Check if controller present at secondary address. ! 585: // ! 586: ! 587: if (AtControllerPresent(&ConfigData->Controller[1])) { ! 588: ! 589: // ! 590: // Claim ATDISK secondary IO address range. ! 591: // ! 592: ! 593: configurationInformation->AtDiskSecondaryAddressClaimed = TRUE; ! 594: ! 595: ConfigData->Controller[1].OkToUseThisController = TRUE; ! 596: ! 597: // ! 598: // Map BIOS vendor signature to check for Compaq. ! 599: // ! 600: ! 601: namePointer = MmMapIoSpace( RtlConvertUlongToLargeInteger ( ! 602: PTR_TO_NAME_STRING), ! 603: NAME_STRING_LENGTH, ! 604: FALSE ); ! 605: ! 606: if ( ( *namePointer == 'C' ) && ! 607: ( *( namePointer + 1 ) == 'O' ) && ! 608: ( *( namePointer + 2 ) == 'M' ) && ! 609: ( *( namePointer + 3 ) == 'P' ) && ! 610: ( *( namePointer + 4 ) == 'A' ) && ! 611: ( *( namePointer + 5 ) == 'Q' ) ) { ! 612: ! 613: machineIsCompaq = TRUE; ! 614: AtDump( ! 615: ATINIT, ! 616: ("ATDISK: Machine is a compaq!\n") ! 617: ); ! 618: ! 619: } ! 620: ! 621: MmUnmapIoSpace( namePointer, NAME_STRING_LENGTH ); ! 622: ! 623: // ! 624: // Compaq uses CMOS to store the drive type for up to two disks ! 625: // attached to their secondary controllers. ! 626: // ! 627: ! 628: if ( machineIsCompaq ) { ! 629: ! 630: // ! 631: // Query CMOS about types of drives 3 and 4. If they exist, get ! 632: // pointers to the appropriate places in our internal fixed disk ! 633: // parameter table. ! 634: // ! 635: ! 636: WRITE_PORT_UCHAR( CFGMEM_QUERY_PORT, CFGMEM_HARD_DRIVE_TYPE_THREE ); ! 637: ! 638: KeStallExecutionProcessor( 1L ); ! 639: ! 640: ConfigData->Controller[1].Disk[0].DriveType = ! 641: READ_PORT_UCHAR( CFGMEM_DATA_PORT ); ! 642: ! 643: if (ConfigData->Controller[1].Disk[0].DriveType) { ! 644: ! 645: // ! 646: // Bump disk count. ! 647: // ! 648: ! 649: diskCount++; ! 650: ! 651: // ! 652: // Use drive type as an index into the system BIOS drive parameter ! 653: // table to find a corresponding geometry entry. ! 654: // ! 655: ! 656: paramTable = DRIVE_PARAMETER_TABLE_OFFSET + ! 657: (ConfigData->Controller[1].Disk[0].DriveType -1) * ! 658: sizeof(FIXED_DISK_PARAMETER_TABLE); ! 659: ! 660: UpdateGeometryFromParameterTable(&ConfigData->Controller[1].Disk[0], ! 661: &ConfigData->Controller[1].ControlFlags, ! 662: paramTable); ! 663: } ! 664: ! 665: WRITE_PORT_UCHAR( CFGMEM_QUERY_PORT, CFGMEM_HARD_DRIVE_TYPE_FOUR ); ! 666: ! 667: KeStallExecutionProcessor( 1L ); ! 668: ! 669: ConfigData->Controller[1].Disk[1].DriveType = ! 670: READ_PORT_UCHAR( CFGMEM_DATA_PORT ); ! 671: ! 672: if (ConfigData->Controller[1].Disk[1].DriveType) { ! 673: ! 674: // ! 675: // Bump disk count. ! 676: // ! 677: ! 678: diskCount++; ! 679: ! 680: // ! 681: // Use drive type as an index into the system BIOS drive parameter ! 682: // table to find a corresponding geometry entry. ! 683: // ! 684: ! 685: paramTable = DRIVE_PARAMETER_TABLE_OFFSET + ! 686: (ConfigData->Controller[1].Disk[1].DriveType -1) * ! 687: sizeof(FIXED_DISK_PARAMETER_TABLE); ! 688: ! 689: UpdateGeometryFromParameterTable(&ConfigData->Controller[1].Disk[1], ! 690: &ConfigData->Controller[1].ControlFlags, ! 691: paramTable); ! 692: } ! 693: ! 694: // ! 695: // If disk 3 or 4 was found, set up the secondary controller. ! 696: // ! 697: ! 698: if ( ( ConfigData->Controller[1].Disk[0].DriveType != 0 ) || ! 699: ( ConfigData->Controller[1].Disk[1].DriveType != 0 ) ) { ! 700: ! 701: configuredIrq = READ_PORT_UCHAR( SECOND_CONTROLLER_IRQ_PORT ); ! 702: ! 703: if ( ( configuredIrq & IRQ_PORT_DISABLED_MASK ) == ! 704: IRQ_PORT_DISABLED ) { ! 705: ! 706: // ! 707: // NT (or OS/2) has already written to this port, which ! 708: // disables further writes. The bit set in the lower ! 709: // nibble indicates which IRQ is being used. ! 710: // ! 711: ! 712: switch ( configuredIrq ) { ! 713: ! 714: case IRQ_PORT_DISABLED + 1: { ! 715: ! 716: configuredIrq = 11; ! 717: break; ! 718: } ! 719: ! 720: case IRQ_PORT_DISABLED + 2: { ! 721: ! 722: configuredIrq = 12; ! 723: break; ! 724: } ! 725: ! 726: case IRQ_PORT_DISABLED + 4: { ! 727: ! 728: configuredIrq = 14; ! 729: break; ! 730: } ! 731: ! 732: default: { ! 733: ! 734: // ! 735: // Case 8 is IRQ 15; but in case we got garbage ! 736: // let's assume 15 and see if it works. ! 737: // ! 738: ! 739: configuredIrq = 15; ! 740: break; ! 741: } ! 742: } ! 743: ! 744: } else { ! 745: ! 746: // ! 747: // This is the first boot after a powercycle. We need ! 748: // to determine the IRQ being used by checking which bit ! 749: // *isn't* set in the *high* nibble. Then we need to ! 750: // write the IRQ_PORT_DISABLED + the proper IRQ bit in ! 751: // the lower nibble. ! 752: // ! 753: ! 754: switch ( configuredIrq ) { ! 755: ! 756: case 0xe0: { ! 757: ! 758: configuredIrq = 11; ! 759: writeValue = IRQ_PORT_DISABLED + 1; ! 760: break; ! 761: } ! 762: ! 763: case 0xd0: { ! 764: ! 765: configuredIrq = 12; ! 766: writeValue = IRQ_PORT_DISABLED + 2; ! 767: break; ! 768: } ! 769: ! 770: case 0xb0: { ! 771: ! 772: configuredIrq = 14; ! 773: writeValue = IRQ_PORT_DISABLED + 4; ! 774: break; ! 775: } ! 776: ! 777: default: { ! 778: ! 779: // ! 780: // Case 0x70 is IRQ 15, but we also want to try ! 781: // IRQ 15 if we got garbage from the register. ! 782: // ! 783: ! 784: configuredIrq = 15; ! 785: writeValue = IRQ_PORT_DISABLED + 8; ! 786: break; ! 787: } ! 788: } ! 789: ! 790: WRITE_PORT_UCHAR( SECOND_CONTROLLER_IRQ_PORT, writeValue ); ! 791: } ! 792: ! 793: ConfigData->Controller[1].OriginalControllerIrql = configuredIrq; ! 794: ConfigData->Controller[1].OriginalControllerVector = configuredIrq; ! 795: ! 796: ConfigData->Controller[1].ControllerVector = ! 797: HalGetInterruptVector( ! 798: ConfigData->Controller[1].InterfaceType, ! 799: ConfigData->Controller[1].BusNumber, ! 800: ConfigData->Controller[1].OriginalControllerIrql, ! 801: ConfigData->Controller[1].OriginalControllerVector, ! 802: &ConfigData->Controller[1].ControllerIrql, ! 803: &ConfigData->Controller[1].ProcessorNumber ); ! 804: } ! 805: ! 806: } else { ! 807: ! 808: // ! 809: // If it's not a compaq then the interrupt is already ! 810: // set up. ! 811: // ! 812: ! 813: // ! 814: // Verify a disk is attached to the second controller. ! 815: // ! 816: ! 817: if (IssueIdentify(&ConfigData->Controller[1], ! 818: buffer, ! 819: 0)) { ! 820: ! 821: // ! 822: // Check if the BIOS has information about this disk. ! 823: // ! 824: ! 825: if (UpdateGeometryFromBios(DriverObject, ! 826: &ConfigData->Controller[1].Disk[0], ! 827: diskCount)) { ! 828: ! 829: diskCount++; ! 830: ConfigData->Controller[1].Disk[0].DriveType = 0xFF; ! 831: ! 832: } else { ! 833: ! 834: // ! 835: // Get geometry information for disk 0 from IDENTIFY command. ! 836: // ! 837: ! 838: if (GetGeometryFromIdentify(&ConfigData->Controller[1], ! 839: 0)) { ! 840: ! 841: diskCount++; ! 842: ConfigData->Controller[1].Disk[0].DriveType = 0xFF; ! 843: } ! 844: } ! 845: ! 846: // ! 847: // Verify a disk is attached to the second controller. ! 848: // ! 849: ! 850: if (IssueIdentify(&ConfigData->Controller[1], ! 851: buffer, ! 852: 1)) { ! 853: ! 854: // ! 855: // Check if the BIOS has information about this disk. ! 856: // ! 857: ! 858: if (UpdateGeometryFromBios(DriverObject, ! 859: &ConfigData->Controller[1].Disk[1], ! 860: diskCount)) { ! 861: ! 862: diskCount++; ! 863: ConfigData->Controller[1].Disk[1].DriveType = 0xFF; ! 864: ! 865: } else { ! 866: ! 867: // ! 868: // Get geometry information for disk 1 from IDENTIFY command. ! 869: // ! 870: ! 871: if (GetGeometryFromIdentify(&ConfigData->Controller[1], ! 872: 1)) { ! 873: ! 874: diskCount++; ! 875: ConfigData->Controller[1].Disk[1].DriveType = 0xFF; ! 876: } ! 877: } ! 878: } ! 879: } ! 880: } ! 881: } ! 882: } ! 883: ! 884: for (i=2;i < MAXIMUM_NUMBER_OF_CONTROLLERS;i++) { ! 885: ! 886: if (AtDiskControllerInfo( ! 887: DriverObject, ! 888: RegistryPath, ! 889: i, ! 890: &ConfigData->Controller[i], ! 891: defaultBaseAddress, ! 892: defaultPortAddress, ! 893: defaultIrql, ! 894: defaultInterfaceType, ! 895: defaultBusNumber, ! 896: FALSE ! 897: )) { ! 898: ! 899: // ! 900: // Assume that if it is such a "high" controller, ! 901: // is following the ata spec, and that it's ok ! 902: // to set the control flags as we should. ! 903: // ! 904: ! 905: ConfigData->Controller[i].ControlFlags = 0x08; ! 906: ! 907: if (!AtControllerPresent(&ConfigData->Controller[i])) { ! 908: ! 909: continue; ! 910: ! 911: } ! 912: ! 913: if (!AtResetController( ! 914: ConfigData->Controller[i].ControllerBaseAddress + STATUS_REGISTER, ! 915: ConfigData->Controller[i].ControlPortAddress, ! 916: ConfigData->Controller[i].ControlFlags ! 917: )) { ! 918: ! 919: continue; ! 920: ! 921: } ! 922: ! 923: ConfigData->Controller[i].OkToUseThisController = TRUE; ! 924: ! 925: // ! 926: // Get geometry information for disk 0 from IDENTIFY command. ! 927: // ! 928: ! 929: if (GetGeometryFromIdentify(&ConfigData->Controller[i], ! 930: 0)) { ! 931: ! 932: diskCount++; ! 933: ConfigData->Controller[i].Disk[0].DriveType = 0xFF; ! 934: ! 935: // ! 936: // Get geometry information for disk 1 from IDENTIFY command. ! 937: // ! 938: ! 939: if (GetGeometryFromIdentify(&ConfigData->Controller[i], ! 940: 1)) { ! 941: ! 942: diskCount++; ! 943: ConfigData->Controller[i].Disk[1].DriveType = 0xFF; ! 944: } ! 945: } ! 946: } ! 947: } ! 948: // ! 949: // Check if any disks were found. ! 950: // ! 951: ! 952: if (!diskCount) { ! 953: return STATUS_NO_SUCH_DEVICE; ! 954: } ! 955: ! 956: // ! 957: // Update device map in registry with disk information. ! 958: // ! 959: ! 960: for (i=0; i< MAXIMUM_NUMBER_OF_CONTROLLERS; i++) { ! 961: for (j=0; j< MAXIMUM_NUMBER_OF_DISKS_PER_CONTROLLER; j++) { ! 962: ! 963: ! 964: if (!ConfigData->Controller[i].Disk[j].DriveType) { ! 965: continue; ! 966: } ! 967: ! 968: // ! 969: // Issue IDENTIFY command. ! 970: // ! 971: ! 972: if (IssueIdentify(&ConfigData->Controller[i], ! 973: buffer, ! 974: j)) { ! 975: ! 976: PUSHORT tempS; ! 977: UCHAR tempByte; ! 978: ! 979: // ! 980: // Byte flip model number, revision, and serial number string. ! 981: // ! 982: ! 983: tempS = ((PIDENTIFY_DATA)buffer)->ModelNumber; ! 984: for (k=0; k<20; k++) { ! 985: tempByte = (UCHAR)(tempS[k] & 0x00FF); ! 986: tempS[k] = tempS[k] >> 8; ! 987: tempS[k] |= tempByte << 8; ! 988: } ! 989: ! 990: tempS = ((PIDENTIFY_DATA)buffer)->FirmwareRevision; ! 991: for (k=0; k<4; k++) { ! 992: tempByte = (UCHAR)(tempS[k] & 0x00FF); ! 993: tempS[k] = tempS[k] >> 8; ! 994: tempS[k] |= tempByte << 8; ! 995: } ! 996: ! 997: tempS = ((PIDENTIFY_DATA)buffer)->SerialNumber; ! 998: for (k=0; k<10; k++) { ! 999: tempByte = (UCHAR)(tempS[k] & 0x00FF); ! 1000: tempS[k] = tempS[k] >> 8; ! 1001: tempS[k] |= tempByte << 8; ! 1002: } ! 1003: ! 1004: } else { ! 1005: ! 1006: RtlZeroMemory( ! 1007: &buffer[0], ! 1008: 512 ! 1009: ); ! 1010: ! 1011: } ! 1012: ! 1013: for (k=0;k<numberOfBadDisks;k++) { ! 1014: ! 1015: // ! 1016: // Check if we should disable the read cache. ! 1017: // ! 1018: ! 1019: if (!strncmp( ! 1020: &badDisks[k][0], ! 1021: (PUCHAR)&((PIDENTIFY_DATA)buffer)->ModelNumber[0], ! 1022: strlen(&badDisks[k][0]) ! 1023: )) { ! 1024: ! 1025: ConfigData->Controller[i].Disk[j].DisableReadCache = TRUE; ! 1026: ! 1027: } ! 1028: ! 1029: } ! 1030: ! 1031: // ! 1032: // Update device map. ! 1033: // ! 1034: ! 1035: AtBuildDeviceMap(i, ! 1036: j, ! 1037: ConfigData->Controller[i].OriginalControllerBaseAddress, ! 1038: ConfigData->Controller[i].OriginalControllerIrql, ! 1039: &ConfigData->Controller[i].Disk[j], ! 1040: (PIDENTIFY_DATA)buffer); ! 1041: ! 1042: } ! 1043: } ! 1044: ! 1045: return STATUS_SUCCESS; ! 1046: } ! 1047: ! 1048: ! 1049: BOOLEAN ! 1050: UpdateGeometryFromBios( ! 1051: PDRIVER_OBJECT DriverObject, ! 1052: DRIVE_DATA *DriveData, ! 1053: ULONG DiskNumber ! 1054: ) ! 1055: ! 1056: /*++ ! 1057: ! 1058: Routine Description: ! 1059: ! 1060: This updates geometry information in a disk extension ! 1061: from BIOS information passed in from NTDETECT. ! 1062: ! 1063: Arguments: ! 1064: ! 1065: DriverObject - Contains pointer to NTDETECT information. ! 1066: DriveData - Store geometry in this structure. ! 1067: DiskNumber - Drive 1(0) or drive 2(1). ! 1068: ! 1069: Return Value: ! 1070: ! 1071: TRUE if information for this disk exists in registry from BIOS. ! 1072: ! 1073: --*/ ! 1074: ! 1075: { ! 1076: OBJECT_ATTRIBUTES objectAttributes; ! 1077: UNICODE_STRING valueName; ! 1078: NTSTATUS status; ! 1079: PCM_FULL_RESOURCE_DESCRIPTOR resourceDescriptor; ! 1080: PKEY_VALUE_FULL_INFORMATION keyData; ! 1081: PUCHAR buffer; ! 1082: ULONG length; ! 1083: ULONG numberOfDrives; ! 1084: HANDLE biosKey; ! 1085: PCM_INT13_DRIVE_PARAMETER int13ParamTable; ! 1086: ! 1087: // ! 1088: // Initialize the object for the key. ! 1089: // ! 1090: ! 1091: InitializeObjectAttributes( &objectAttributes, ! 1092: DriverObject->HardwareDatabase, ! 1093: OBJ_CASE_INSENSITIVE, ! 1094: NULL, ! 1095: (PSECURITY_DESCRIPTOR) NULL ); ! 1096: ! 1097: // ! 1098: // Create the key. ! 1099: // ! 1100: ! 1101: status = ZwOpenKey( ! 1102: &biosKey, ! 1103: KEY_READ, ! 1104: &objectAttributes ! 1105: ); ! 1106: ! 1107: ! 1108: if (!NT_SUCCESS(status)) { ! 1109: return FALSE; ! 1110: } ! 1111: ! 1112: RtlInitUnicodeString( &valueName, L"Configuration Data" ); ! 1113: ! 1114: keyData = ExAllocatePool(PagedPool, 2048); ! 1115: ! 1116: if (keyData == NULL) { ! 1117: ZwClose(biosKey); ! 1118: return FALSE; ! 1119: } ! 1120: ! 1121: status = ZwQueryValueKey( ! 1122: biosKey, ! 1123: &valueName, ! 1124: KeyValueFullInformation, ! 1125: keyData, ! 1126: 2048, ! 1127: &length ! 1128: ); ! 1129: ! 1130: ZwClose(biosKey); ! 1131: ! 1132: if (!NT_SUCCESS(status)) { ! 1133: ExFreePool(keyData); ! 1134: return FALSE; ! 1135: } ! 1136: ! 1137: resourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR) keyData + ! 1138: keyData->DataOffset); ! 1139: ! 1140: // ! 1141: // Check that the data is long enough to hold a full resource descriptor, ! 1142: // and that the last resouce list is device-specific and long enough. ! 1143: // ! 1144: ! 1145: if (keyData->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR) || ! 1146: resourceDescriptor->PartialResourceList.Count == 0 || ! 1147: resourceDescriptor->PartialResourceList.PartialDescriptors[0].Type != ! 1148: CmResourceTypeDeviceSpecific || ! 1149: resourceDescriptor->PartialResourceList.PartialDescriptors[0] ! 1150: .u.DeviceSpecificData.DataSize < sizeof(ULONG) ! 1151: ) { ! 1152: ! 1153: ExFreePool(keyData); ! 1154: return FALSE; ! 1155: } ! 1156: ! 1157: length = resourceDescriptor->PartialResourceList.PartialDescriptors[0] ! 1158: .u.DeviceSpecificData.DataSize; ! 1159: ! 1160: // ! 1161: // Point to the BIOS data. The BIOS data is located after the first ! 1162: // partial Resource list which should be device specific data. ! 1163: // ! 1164: ! 1165: buffer = (PUCHAR) keyData + keyData->DataOffset + ! 1166: sizeof(CM_FULL_RESOURCE_DESCRIPTOR); ! 1167: ! 1168: ! 1169: numberOfDrives = length / sizeof(CM_INT13_DRIVE_PARAMETER); ! 1170: ! 1171: // ! 1172: // Use the defaults if the drive number is greater than the ! 1173: // number of drives detected by the BIOS. ! 1174: // ! 1175: ! 1176: if (numberOfDrives <= DiskNumber) { ! 1177: ExFreePool(keyData); ! 1178: return FALSE; ! 1179: } ! 1180: ! 1181: // ! 1182: // Point to the array of drive parameters. ! 1183: // ! 1184: ! 1185: int13ParamTable = (PCM_INT13_DRIVE_PARAMETER) buffer + DiskNumber; ! 1186: ! 1187: // ! 1188: // Initialize this drive. ! 1189: // ! 1190: ! 1191: DriveData->BytesPerSector = 512; ! 1192: DriveData->BytesPerInterrupt = 512; ! 1193: ! 1194: DriveData->ReadCommand = 0x20; ! 1195: DriveData->WriteCommand = 0x30; ! 1196: DriveData->VerifyCommand = 0x40; ! 1197: ! 1198: DriveData->PretendNumberOfCylinders = ! 1199: DriveData->NumberOfCylinders = ! 1200: (USHORT)(int13ParamTable->MaxCylinders + 1); ! 1201: DriveData->PretendTracksPerCylinder = ! 1202: DriveData->TracksPerCylinder = ! 1203: (int13ParamTable->MaxHeads + 1); ! 1204: DriveData->PretendSectorsPerTrack = ! 1205: DriveData->SectorsPerTrack = ! 1206: int13ParamTable->SectorsPerTrack; ! 1207: DriveData->WritePrecomp = 0; ! 1208: ! 1209: return TRUE; ! 1210: } ! 1211: ! 1212: ! 1213: BOOLEAN ! 1214: UpdateGeometryFromParameterTable( ! 1215: DRIVE_DATA *DriveData, ! 1216: CCHAR *ControlFlags, ! 1217: ULONG ParameterTableOffset ! 1218: ) ! 1219: ! 1220: /*++ ! 1221: ! 1222: Routine Description: ! 1223: ! 1224: This updates geometry information in a disk extension ! 1225: from a BIOS parameter table entry. ! 1226: ! 1227: Arguments: ! 1228: ! 1229: DriveData - Store geometry in this structure. ! 1230: ControlFlags - Points to a value to set in the controller when initializing. ! 1231: ParameterTableOffset - Raw ROM address. ! 1232: ! 1233: Return Value: ! 1234: ! 1235: Nothing. ! 1236: ! 1237: --*/ ! 1238: ! 1239: { ! 1240: PFIXED_DISK_PARAMETER_TABLE parameterTable; ! 1241: ! 1242: // ! 1243: // Map system BIOS drive parameter table. ! 1244: // ! 1245: ! 1246: parameterTable = MmMapIoSpace(RtlConvertUlongToLargeInteger( ! 1247: ParameterTableOffset), ! 1248: DRIVE_PARAMETER_TABLE_LENGTH, ! 1249: FALSE); ! 1250: ! 1251: // ! 1252: // Initialize this drive. ! 1253: // ! 1254: ! 1255: DriveData->BytesPerSector = 512; ! 1256: DriveData->BytesPerInterrupt = 512; ! 1257: ! 1258: DriveData->ReadCommand = 0x20; ! 1259: DriveData->WriteCommand = 0x30; ! 1260: DriveData->VerifyCommand = 0x40; ! 1261: ! 1262: DriveData->PretendNumberOfCylinders = ! 1263: parameterTable->MaxCylinders; ! 1264: DriveData->PretendTracksPerCylinder = ! 1265: parameterTable->MaxHeads; ! 1266: DriveData->PretendSectorsPerTrack = ! 1267: parameterTable->SectorsPerTrack; ! 1268: DriveData->WritePrecomp = ! 1269: parameterTable->StartWritePrecomp; ! 1270: *ControlFlags = parameterTable->ControlFlags; ! 1271: ! 1272: // ! 1273: // Some of these values might have been "pretend" values useful for ! 1274: // dealing with DOS. If so, determine the real values. ! 1275: // ! 1276: ! 1277: if ( ( parameterTable->Signature & 0xf0 ) == 0xa0 ) { ! 1278: ! 1279: // ! 1280: // The values obtained were fake; get the real ones. ! 1281: // ! 1282: ! 1283: DriveData->NumberOfCylinders = ! 1284: parameterTable->TranslatedMaxCylinders; ! 1285: DriveData->TracksPerCylinder = ! 1286: parameterTable->TranslatedMaxHeads; ! 1287: DriveData->SectorsPerTrack = ! 1288: parameterTable->TranslatedSectorsPerTrack; ! 1289: ! 1290: } else { ! 1291: ! 1292: // ! 1293: // The values obtained were correct (as far as it goes). ! 1294: // ! 1295: ! 1296: DriveData->NumberOfCylinders = ! 1297: parameterTable->MaxCylinders; ! 1298: DriveData->TracksPerCylinder = ! 1299: parameterTable->MaxHeads; ! 1300: DriveData->SectorsPerTrack = ! 1301: parameterTable->SectorsPerTrack; ! 1302: ! 1303: ! 1304: } ! 1305: ! 1306: MmUnmapIoSpace(parameterTable, sizeof(FIXED_DISK_PARAMETER_TABLE)); ! 1307: ! 1308: return TRUE; ! 1309: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.