|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1990-1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: s3.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains the code that implements the S3 miniport driver. ! 12: ! 13: Environment: ! 14: ! 15: Kernel mode ! 16: ! 17: Revision History: ! 18: ! 19: --*/ ! 20: ! 21: #include "s3.h" ! 22: #include "s3data.h" ! 23: #include "s3logerr.h" ! 24: ! 25: #include <string.h> ! 26: ! 27: ! 28: #define MAX_CONTROL_HISTORY 512 ! 29: ! 30: ULONG giControlCode; ! 31: ULONG gaIOControlCode[MAX_CONTROL_HISTORY]; ! 32: ! 33: #ifdef i386 ! 34: ! 35: /************************************************************************************************* ! 36: * 801/805, 928 mode mask bit table. ! 37: ************************************************************************************************/ ! 38: UCHAR ModeMaskBits[] = {(UCHAR) ~0x00, // 640 X 480 DEFAULT ! 39: (UCHAR) ~0x03, // 640 X 480 @ 43Hz ! 40: (UCHAR) ~0x03, // 640 X 480 @ 56Hz ! 41: (UCHAR) ~0x03, // 640 X 480 @ 60Hz ! 42: (UCHAR) ~0x03, // 640 X 480 @ 72Hz ! 43: ! 44: (UCHAR) ~0x00, // 800 X 600 DEFAULT ! 45: (UCHAR) ~0x0C, // 800 X 600 @ 43Hz ! 46: (UCHAR) ~0x0C, // 800 X 600 @ 56Hz ! 47: (UCHAR) ~0x0C, // 800 X 600 @ 60Hz ! 48: (UCHAR) ~0x0C, // 800 X 600 @ 72Hz ! 49: ! 50: (UCHAR) ~0x00, // 1024 X 768 DEFAULT ! 51: (UCHAR) ~0x30, // 1024 X 768 @ 43Hz ! 52: (UCHAR) ~0x30, // 1024 X 768 @ 56Hz ! 53: (UCHAR) ~0x30, // 1024 X 768 @ 60Hz ! 54: (UCHAR) ~0x30, // 1024 X 768 @ 72Hz ! 55: ! 56: (UCHAR) ~0x00, // 1280 X 1024 DEFAULT ! 57: (UCHAR) ~0xC0, // 1280 X 1024 @ 43Hz ! 58: (UCHAR) ~0xC0, // 1280 X 1024 @ 56Hz ! 59: (UCHAR) ~0xC0, // 1280 X 1024 @ 60Hz ! 60: (UCHAR) ~0xC0 // 1280 X 1024 @ 72Hz ! 61: }; ! 62: ! 63: /************************************************************************************************* ! 64: * 801/805, 928 mode set bits table ! 65: ************************************************************************************************/ ! 66: UCHAR GenericModeBits[] = { (UCHAR) 0x00, // 640 X 480 DEFAULT ! 67: (UCHAR) 0x00, // 640 X 480 @ 43Hz ! 68: (UCHAR) 0x01, // 640 X 480 @ 56Hz ! 69: (UCHAR) 0x02, // 640 X 480 @ 60Hz ! 70: (UCHAR) 0x03, // 640 X 480 @ 72Hz ! 71: ! 72: (UCHAR) 0x00, // 800 X 600 DEFAULT ! 73: (UCHAR) 0x00, // 800 X 600 @ 43Hz ! 74: (UCHAR) 0x04, // 800 X 600 @ 56Hz ! 75: (UCHAR) 0x08, // 800 X 600 @ 60Hz ! 76: (UCHAR) 0x0C, // 800 X 600 @ 72Hz ! 77: ! 78: (UCHAR) 0x00, // 1024 X 768 DEFAULT ! 79: (UCHAR) 0x00, // 1024 X 768 @ 43Hz ! 80: (UCHAR) 0x10, // 1024 X 768 @ 56Hz ! 81: (UCHAR) 0x20, // 1024 X 768 @ 60Hz ! 82: (UCHAR) 0x30, // 1024 X 768 @ 72Hz ! 83: ! 84: (UCHAR) 0x00, // 1280 X 1024 DEFAULT ! 85: (UCHAR) 0x00, // 1280 X 1024 @ 43Hz ! 86: (UCHAR) 0x40, // 1280 X 1024 @ 56Hz ! 87: (UCHAR) 0x80, // 1280 X 1024 @ 60Hz ! 88: (UCHAR) 0xC0 // 1280 X 1024 @ 72Hz ! 89: }; ! 90: ! 91: /************************************************************************************************* ! 92: * Number Nine Computer 928 mode set bits table ! 93: * BIOS versions before 1.10.04 have the following refresh index to ! 94: * vertical refresh rate association: ! 95: * ! 96: * 0 default (56/60 depending upon mode) ! 97: * 1 70 Hz ! 98: * 2 72 Hz ! 99: * 3 76 Hz ! 100: * ! 101: * This miniport will always map down (better safe than sorry) ! 102: * The mapping is: ! 103: * ! 104: * index registry value #9 value ! 105: * 0 43 56/60 (default) ! 106: * 1 56 " ! 107: * 2 60 " ! 108: * 3 72 72 ! 109: ************************************************************************************************/ ! 110: UCHAR NumberNineModeBits[] = { (UCHAR) 0x00, // 640 X 480 DEFAULT ! 111: (UCHAR) 0x00, // 640 X 480 @ 43Hz ! 112: (UCHAR) 0x00, // 640 X 480 @ 56Hz ! 113: (UCHAR) 0x00, // 640 X 480 @ 60Hz ! 114: (UCHAR) 0x02, // 640 X 480 @ 72Hz ! 115: ! 116: (UCHAR) 0x00, // 800 X 600 DEFAULT ! 117: (UCHAR) 0x00, // 800 X 600 @ 43Hz ! 118: (UCHAR) 0x00, // 800 X 600 @ 56Hz ! 119: (UCHAR) 0x00, // 800 X 600 @ 60Hz ! 120: (UCHAR) 0x08, // 800 X 600 @ 72Hz ! 121: ! 122: (UCHAR) 0x00, // 1024 X 768 DEFAULT ! 123: (UCHAR) 0x00, // 1024 X 768 @ 43Hz ! 124: (UCHAR) 0x00, // 1024 X 768 @ 56Hz ! 125: (UCHAR) 0x00, // 1024 X 768 @ 60Hz ! 126: (UCHAR) 0x20, // 1024 X 768 @ 72Hz ! 127: ! 128: (UCHAR) 0x00, // 1280 X 1024 DEFAULT ! 129: (UCHAR) 0x00, // 1280 X 1024 @ 43Hz ! 130: (UCHAR) 0x00, // 1280 X 1024 @ 56Hz ! 131: (UCHAR) 0x00, // 1280 X 1024 @ 60Hz ! 132: (UCHAR) 0x80 // 1280 X 1024 @ 72Hz ! 133: }; ! 134: ! 135: /************************************************************************************************* ! 136: * DELL 805 mode set bits table ! 137: * ! 138: * Dell has a different mapping for each resolution. ! 139: * ! 140: * index registry 640 800 1024 1280 ! 141: * 0 43 60 56 43 43 ! 142: * 1 56 72 60 60 -- ! 143: * 2 60 -- 72 70 -- ! 144: * 3 72 56 56 72 -- ! 145: ************************************************************************************************/ ! 146: UCHAR DellModeBits[] = {(UCHAR) 0x00, // 640 X 480 DEFAULT ! 147: (UCHAR) 0x00, // 640 X 480 @ 43Hz ! 148: (UCHAR) 0x03, // 640 X 480 @ 56Hz ! 149: (UCHAR) 0x00, // 640 X 480 @ 60Hz ! 150: (UCHAR) 0x01, // 640 X 480 @ 72Hz ! 151: ! 152: (UCHAR) 0x00, // 800 X 600 DEFAULT ! 153: (UCHAR) 0x00, // 800 X 600 @ 43Hz ! 154: (UCHAR) 0x00, // 800 X 600 @ 56Hz ! 155: (UCHAR) 0x04, // 800 X 600 @ 60Hz ! 156: (UCHAR) 0x08, // 800 X 600 @ 72Hz ! 157: ! 158: (UCHAR) 0x00, // 1024 X 768 DEFAULT ! 159: (UCHAR) 0x00, // 1024 X 768 @ 43Hz ! 160: (UCHAR) 0x10, // 1024 X 768 @ 56Hz ! 161: (UCHAR) 0x10, // 1024 X 768 @ 60Hz ! 162: (UCHAR) 0x30, // 1024 X 768 @ 72Hz ! 163: ! 164: (UCHAR) 0x00, // 1280 X 1024 DEFAULT ! 165: (UCHAR) 0x00, // 1280 X 1024 @ 43Hz ! 166: (UCHAR) 0x00, // 1280 X 1024 @ 56Hz ! 167: (UCHAR) 0x00, // 1280 X 1024 @ 60Hz ! 168: (UCHAR) 0x00 // 1280 X 1024 @ 72Hz ! 169: }; ! 170: ! 171: ! 172: // This table is only used for the 801/805 and 928 chips. ! 173: // When this table was used on the Stealth or Orchid 911 boards the ! 174: // full screen had two images side by side. ! 175: ! 176: typedef struct { ! 177: UCHAR port, ! 178: val; ! 179: } REGVALS; ! 180: ! 181: REGVALS arvExtendedRegs[] = {{0x30, 0x0}, ! 182: {0x31, 0x0}, ! 183: {0x32, 0x0}, ! 184: {0x33, 0x0}, ! 185: {0x34, 0x0}, ! 186: {0x35, 0x0}, ! 187: {0x36, 0x0}, ! 188: {0x37, 0x0}, ! 189: {0x3A, 0x0}, ! 190: {0x3B, 0x0}, ! 191: {0x3C, 0x0}, ! 192: ! 193: {0x40, 0x0}, ! 194: {0x41, 0x0}, ! 195: {0x42, 0x0}, ! 196: {0x43, 0x0}, ! 197: {0x44, 0x0}, ! 198: {0x45, 0x0}, ! 199: {0x46, 0x0}, ! 200: {0x47, 0x0}, ! 201: {0x48, 0x0}, ! 202: {0x49, 0x0}, ! 203: {0x4A, 0x0}, ! 204: {0x4B, 0x0}, ! 205: {0x4C, 0x0}, ! 206: {0x4D, 0x0}, ! 207: {0x4E, 0x0}, ! 208: {0x4F, 0x0}, ! 209: ! 210: {0x50, 0x0}, ! 211: {0x51, 0x0}, ! 212: {0x52, 0x0}, ! 213: {0x53, 0x0}, ! 214: {0x54, 0x0}, ! 215: {0x55, 0x0}, ! 216: {0x56, 0x0}, ! 217: {0x57, 0x0}, ! 218: {0x58, 0x0}, ! 219: {0x59, 0x0}, ! 220: {0x5A, 0x0}, ! 221: {0x5B, 0x0}, ! 222: {0x5C, 0x0}, ! 223: {0x5D, 0x0}, ! 224: {0x5E, 0x0}, ! 225: {0x5F, 0x0}}; ! 226: ! 227: ULONG nExtendedRegs = sizeof(arvExtendedRegs) / sizeof (REGVALS); ! 228: ! 229: #endif ! 230: ! 231: ! 232: ! 233: #ifndef i386 ! 234: ! 235: long calc_clock(long, int); ! 236: VOID set_clock( ! 237: PHW_DEVICE_EXTENSION HwDeviceExtension, ! 238: LONG clock_value); ! 239: ! 240: #endif ! 241: ! 242: ! 243: // ! 244: // Function Prototypes ! 245: // ! 246: // Functions that start with 'S3' are entry points for the OS port driver. ! 247: // ! 248: ! 249: VP_STATUS ! 250: S3FindAdapter( ! 251: PVOID HwDeviceExtension, ! 252: PVOID HwContext, ! 253: PWSTR ArgumentString, ! 254: PVIDEO_PORT_CONFIG_INFO ConfigInfo, ! 255: PUCHAR Again ! 256: ); ! 257: ! 258: BOOLEAN ! 259: S3Initialize( ! 260: PVOID HwDeviceExtension ! 261: ); ! 262: ! 263: BOOLEAN ! 264: S3StartIO( ! 265: PVOID HwDeviceExtension, ! 266: PVIDEO_REQUEST_PACKET RequestPacket ! 267: ); ! 268: ! 269: VP_STATUS ! 270: S3SetColorLookup( ! 271: PHW_DEVICE_EXTENSION HwDeviceExtension, ! 272: PVIDEO_CLUT ClutBuffer, ! 273: ULONG ClutBufferSize ! 274: ); ! 275: ! 276: VOID ! 277: ZeroMemAndDac( ! 278: PHW_DEVICE_EXTENSION HwDeviceExtension ! 279: ); ! 280: ! 281: VOID ! 282: SetHWMode( ! 283: PHW_DEVICE_EXTENSION HwDeviceExtension, ! 284: PUSHORT pusCmdStream ! 285: ); ! 286: ! 287: VP_STATUS ! 288: S3RegistryCallback( ! 289: PVOID HwDeviceExtension, ! 290: PVOID Context, ! 291: PWSTR ValueName, ! 292: PVOID ValueData, ! 293: ULONG ValueLength ! 294: ); ! 295: ! 296: BOOLEAN ! 297: Reset_Bt485( ! 298: PHW_DEVICE_EXTENSION HwDeviceExtension ! 299: ); ! 300: ! 301: // ! 302: // Non-x86 platform support ! 303: // ! 304: ! 305: #ifndef i386 ! 306: ! 307: VP_STATUS ! 308: Set_Oem_Clock( ! 309: PHW_DEVICE_EXTENSION HwDeviceExtension ! 310: ); ! 311: ! 312: VP_STATUS ! 313: Wait_VSync( ! 314: PHW_DEVICE_EXTENSION HwDeviceExtension ! 315: ); ! 316: ! 317: BOOLEAN ! 318: Bus_Test( ! 319: PHW_DEVICE_EXTENSION HwDeviceExtension ! 320: ); ! 321: ! 322: #endif // i386 ! 323: ! 324: ! 325: ULONG ! 326: DriverEntry ( ! 327: PVOID Context1, ! 328: PVOID Context2 ! 329: ) ! 330: ! 331: /*++ ! 332: ! 333: Routine Description: ! 334: ! 335: Installable driver initialization entry point. ! 336: This entry point is called directly by the I/O system. ! 337: ! 338: Arguments: ! 339: ! 340: Context1 - First context value passed by the operating system. This is ! 341: the value with which the miniport driver calls VideoPortInitialize(). ! 342: ! 343: Context2 - Second context value passed by the operating system. This is ! 344: the value with which the miniport driver calls VideoPortInitialize(). ! 345: ! 346: Return Value: ! 347: ! 348: Status from VideoPortInitialize() ! 349: ! 350: --*/ ! 351: ! 352: { ! 353: ! 354: VIDEO_HW_INITIALIZATION_DATA hwInitData; ! 355: ULONG initializationStatus; ! 356: ULONG status; ! 357: ! 358: // ! 359: // Zero out structure. ! 360: // ! 361: ! 362: VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA)); ! 363: ! 364: // ! 365: // Specify sizes of structure and extension. ! 366: // ! 367: ! 368: hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); ! 369: ! 370: // ! 371: // Set entry points. ! 372: // ! 373: ! 374: hwInitData.HwFindAdapter = S3FindAdapter; ! 375: hwInitData.HwInitialize = S3Initialize; ! 376: hwInitData.HwInterrupt = NULL; ! 377: hwInitData.HwStartIO = S3StartIO; ! 378: ! 379: // ! 380: // Determine the size we require for the device extension. ! 381: // ! 382: ! 383: hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); ! 384: ! 385: // ! 386: // Always start with parameters for device0 in this case. ! 387: // ! 388: ! 389: // hwInitData.StartingDeviceNumber = 0; ! 390: ! 391: // ! 392: // This device only supports many bus types. ! 393: // ! 394: ! 395: hwInitData.AdapterInterfaceType = Isa; ! 396: ! 397: initializationStatus = VideoPortInitialize(Context1, ! 398: Context2, ! 399: &hwInitData, ! 400: NULL); ! 401: ! 402: hwInitData.AdapterInterfaceType = Eisa; ! 403: ! 404: status = VideoPortInitialize(Context1, ! 405: Context2, ! 406: &hwInitData, ! 407: NULL); ! 408: ! 409: if (initializationStatus > status) { ! 410: initializationStatus = status; ! 411: } ! 412: ! 413: hwInitData.AdapterInterfaceType = Internal; ! 414: ! 415: status = VideoPortInitialize(Context1, ! 416: Context2, ! 417: &hwInitData, ! 418: NULL); ! 419: ! 420: if (initializationStatus > status) { ! 421: initializationStatus = status; ! 422: } ! 423: ! 424: return initializationStatus; ! 425: ! 426: } // end DriverEntry() ! 427: ! 428: ! 429: VP_STATUS ! 430: S3FindAdapter( ! 431: PVOID HwDeviceExtension, ! 432: PVOID HwContext, ! 433: PWSTR ArgumentString, ! 434: PVIDEO_PORT_CONFIG_INFO ConfigInfo, ! 435: PUCHAR Again ! 436: ) ! 437: ! 438: /*++ ! 439: ! 440: Routine Description: ! 441: ! 442: This routine is called to determine if the adapter for this driver ! 443: is present in the system. ! 444: If it is present, the function fills out some information describing ! 445: the adapter. ! 446: ! 447: Arguments: ! 448: ! 449: HwDeviceExtension - Supplies the miniport driver's adapter storage. This ! 450: storage is initialized to zero before this call. ! 451: ! 452: HwContext - Supplies the context value which was passed to ! 453: VideoPortInitialize(). ! 454: ! 455: ArgumentString - Suuplies a NULL terminated ASCII string. This string ! 456: originates from the user. ! 457: ! 458: ConfigInfo - Returns the configuration information structure which is ! 459: filled by the miniport driver. This structure is initialized with ! 460: any knwon configuration information (such as SystemIoBusNumber) by ! 461: the port driver. Where possible, drivers should have one set of ! 462: defaults which do not require any supplied configuration information. ! 463: ! 464: Again - Indicates if the miniport driver wants the port driver to call ! 465: its VIDEO_HW_FIND_ADAPTER function again with a new device extension ! 466: and the same config info. This is used by the miniport drivers which ! 467: can search for several adapters on a bus. ! 468: ! 469: Return Value: ! 470: ! 471: This routine must return: ! 472: ! 473: NO_ERROR - Indicates a host adapter was found and the ! 474: configuration information was successfully determined. ! 475: ! 476: ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an ! 477: error obtaining the configuration information. If possible an error ! 478: should be logged. ! 479: ! 480: ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the ! 481: supplied configuration information. ! 482: ! 483: --*/ ! 484: ! 485: { ! 486: ! 487: // ! 488: // Size of the ROM we map in ! 489: // ! 490: ! 491: #define MAX_ROM_SCAN 512 ! 492: ! 493: PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; ! 494: ULONG i; ! 495: VP_STATUS status; ! 496: UCHAR jChipID, s3MemSizeCode; ! 497: UCHAR DataReg, IndexReg, reg38, reg39; ! 498: UCHAR reg40, reg43; ! 499: BOOLEAN useAlternateRegisters = FALSE; ! 500: ! 501: USHORT usRomSignature; ! 502: PVOID romAddress; ! 503: BOOLEAN bMatch; ! 504: UCHAR *pjBiosVersion, *pjRefString, offset; ! 505: LONG iCmpRet; ! 506: ! 507: VIDEO_ACCESS_RANGE accessRange[] = { ! 508: {0x000C0000, 0x00000000, 0x00008000, 0, 0, 0}, // 0 ROM location ! 509: {0x000A0000, 0x00000000, 0x00010000, 0, 0, 1}, // 1 Frame buf ! 510: {0x000003C0, 0x00000000, 0x00000010, 1, 1, 1}, // 2 Various VGA regs ! 511: {0x000003D4, 0x00000000, 0x00000008, 1, 1, 1}, // 3 System Control Registers ! 512: {0x000042E8, 0x00000000, 0x00000002, 1, 1, 0}, // 4 SubSys-Stat/Cntl ! 513: {0x00004AE8, 0x00000000, 0x00000002, 1, 1, 0}, // 5 AdvFunc-Cntl ! 514: {0x000082E8, 0x00000000, 0x00000002, 1, 1, 0}, // 6 Cur-Y ! 515: {0x000086E8, 0x00000000, 0x00000002, 1, 1, 0}, // 7 Cur-X ! 516: {0x00008AE8, 0x00000000, 0x00000002, 1, 1, 0}, // 8 DestY-AxStp ! 517: {0x00008EE8, 0x00000000, 0x00000002, 1, 1, 0}, // 9 DestX-SiaStp ! 518: {0x000092E8, 0x00000000, 0x00000002, 1, 1, 0}, // 10 Err-Term ! 519: {0x000096E8, 0x00000000, 0x00000002, 1, 1, 0}, // 11 Maj-Axis-Pcnt(Rec-Width) ! 520: {0x00009AE8, 0x00000000, 0x00000002, 1, 1, 0}, // 12 Gp-Stat/Cmd ! 521: {0x00009EE8, 0x00000000, 0x00000002, 1, 1, 0}, // 13 Short-Stroke ! 522: {0x0000A2E8, 0x00000000, 0x00000002, 1, 1, 0}, // 14 Bkgd-Color ! 523: {0x0000A6E8, 0x00000000, 0x00000002, 1, 1, 0}, // 15 Frgd-Color ! 524: {0x0000AAE8, 0x00000000, 0x00000002, 1, 1, 0}, // 16 Wrt_Mask ! 525: {0x0000AEE8, 0x00000000, 0x00000002, 1, 1, 0}, // 17 Rd-Mask ! 526: {0x0000B6E8, 0x00000000, 0x00000002, 1, 1, 0}, // 18 Bkgd-Mix ! 527: {0x0000BAE8, 0x00000000, 0x00000002, 1, 1, 0}, // 19 Frgd-Mix ! 528: {0x0000BEE8, 0x00000000, 0x00000002, 1, 1, 0}, // 20 Mulitfucn_Cntl ! 529: {0x0000E2E8, 0x00000000, 0x00000002, 1, 1, 0} // 21 Pix-Trans ! 530: }; ! 531: ! 532: // ! 533: // Make sure the size of the structure is at least as large as what we ! 534: // are expecting (check version of the config info structure). ! 535: // ! 536: ! 537: if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) { ! 538: ! 539: return (ERROR_INVALID_PARAMETER); ! 540: ! 541: } ! 542: ! 543: ! 544: #ifdef MIPS ! 545: ! 546: // ! 547: // For MIPS machine with an Internal Bus, adjust the access ranges. ! 548: // ! 549: ! 550: if (ConfigInfo->AdapterInterfaceType == Internal) { ! 551: ! 552: #define INTERNAL_BUS_VIDEO_MEMORY_BASE 0x40000000 ! 553: #define INTERNAL_BUS_IO_PORT_BASE 0x60000000 ! 554: ! 555: VideoDebugPrint((1, "S3: Internal Bus, get new IO bases\n")); ! 556: ! 557: // ! 558: // Adjust memory location ! 559: // ! 560: ! 561: accessRange[0].RangeStart.LowPart += INTERNAL_BUS_VIDEO_MEMORY_BASE; ! 562: accessRange[1].RangeStart.LowPart += INTERNAL_BUS_VIDEO_MEMORY_BASE; ! 563: ! 564: // ! 565: // Adjust io port locations, and change IO port from IO port to memory. ! 566: // ! 567: ! 568: for (i = 2; i < NUM_S3_ACCESS_RANGES; i++) { ! 569: ! 570: accessRange[i].RangeStart.LowPart += INTERNAL_BUS_IO_PORT_BASE; ! 571: accessRange[i].RangeInIoSpace = 0; ! 572: ! 573: } ! 574: } ! 575: ! 576: #endif ! 577: ! 578: ! 579: // ! 580: // Check to see if there is a hardware resource conflict. ! 581: // ! 582: ! 583: status = VideoPortVerifyAccessRanges(hwDeviceExtension, ! 584: NUM_S3_ACCESS_RANGES, ! 585: accessRange); ! 586: ! 587: if (status != NO_ERROR) { ! 588: ! 589: VideoDebugPrint((1, "S3: Access Range conflict\n")); ! 590: return status; ! 591: ! 592: } ! 593: ! 594: // ! 595: // Get the mapped addresses for all the registers. ! 596: // ! 597: // NOTE: the ROM is not mapped here. It will only be mapped later, if ! 598: // we really need it (non int10 initialization). ! 599: // ! 600: ! 601: for (i = 1; i < NUM_S3_ACCESS_RANGES; i++) { ! 602: ! 603: if ( (hwDeviceExtension->MappedAddress[i] = ! 604: VideoPortGetDeviceBase(hwDeviceExtension, ! 605: accessRange[i].RangeStart, ! 606: accessRange[i].RangeLength, ! 607: accessRange[i].RangeInIoSpace)) == NULL) { ! 608: ! 609: VideoDebugPrint((1, "S3: DeviceBase mapping failed\n")); ! 610: return ERROR_INVALID_PARAMETER; ! 611: ! 612: } ! 613: } ! 614: ! 615: // ! 616: // Save the initial value of the S3 lock registers. ! 617: // it's possible, a non-s3 bios may expect them in a state ! 618: // define in POST. ! 619: // ! 620: ! 621: DataReg = VideoPortReadPortUchar(CRT_DATA_REG); ! 622: IndexReg = VideoPortReadPortUchar(CRT_ADDRESS_REG); ! 623: ! 624: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x38); ! 625: reg38 = VideoPortReadPortUchar(CRT_DATA_REG); ! 626: ! 627: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x39); ! 628: reg39 = VideoPortReadPortUchar(CRT_DATA_REG); ! 629: ! 630: // ! 631: // Now unlock all the S3 registers, for use in this routine. ! 632: // ! 633: ! 634: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x4838); ! 635: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0xA039); ! 636: ! 637: // ! 638: // Make sure we're working with an S3 ! 639: // And while were at it, pickup the chip ID ! 640: // ! 641: ! 642: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x30); ! 643: jChipID = VideoPortReadPortUchar(CRT_DATA_REG); ! 644: ! 645: // ! 646: // In this driver we just care about the major chip ID, not the revision ! 647: // ! 648: ! 649: jChipID &= 0xf0; ! 650: ! 651: switch(jChipID) { ! 652: ! 653: case 0x80: // 911 or 924 ! 654: ! 655: VideoDebugPrint((2, "S3: 911 Chip Set\n")); ! 656: hwDeviceExtension->ChipID = S3_911; ! 657: break; ! 658: ! 659: ! 660: case 0x90: // 928 ! 661: ! 662: VideoDebugPrint((2, "S3: 928 Chip Set\n")); ! 663: hwDeviceExtension->ChipID = S3_928; ! 664: break; ! 665: ! 666: case 0xA0: // 801/805 ! 667: ! 668: VideoDebugPrint((2, "S3: 801/805 Chip Set\n")); ! 669: hwDeviceExtension->ChipID = S3_801; ! 670: break; ! 671: ! 672: default: ! 673: ! 674: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg38 << 8) | 0x38)); ! 675: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg39 << 8) | 0x39)); ! 676: VideoPortWritePortUchar(CRT_ADDRESS_REG, IndexReg); ! 677: VideoPortWritePortUchar(CRT_DATA_REG, DataReg); ! 678: ! 679: // ! 680: // Log an error to the event log. The unique Id of 0 is only used ! 681: // to identify which call to VideoPortLogError actually generated ! 682: // the message; a line # would also be appropriate. ! 683: // ! 684: ! 685: // ! 686: // NOTE ! 687: // This message has been removed because we hit it each time an ! 688: // S3 is not detected. ! 689: // ! 690: ! 691: // VideoPortLogError(hwDeviceExtension, ! 692: // NULL, ! 693: // S3_UNSUPPORTED_CHIP, ! 694: // __LINE__); ! 695: ! 696: VideoDebugPrint((2, "S3: unsupported chip set\n")); ! 697: return ERROR_DEV_NOT_EXIST; ! 698: break; ! 699: ! 700: } ! 701: ! 702: // ! 703: // At this point we know we have an S3 chip in the system. ! 704: // Set the defaults for the board type. ! 705: // ! 706: ! 707: hwDeviceExtension->BoardID = S3_GENERIC; ! 708: ! 709: // ! 710: // Get the Size the Video Memory. ! 711: // ! 712: ! 713: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x36); ! 714: s3MemSizeCode = VideoPortReadPortUchar(CRT_DATA_REG) >> 5; ! 715: ! 716: if (hwDeviceExtension->ChipID == S3_911) { ! 717: ! 718: // ! 719: // This is for the 911 & 924 ! 720: // ! 721: ! 722: if (s3MemSizeCode & 0x01) { ! 723: ! 724: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg38 << 8) | 0x38)); ! 725: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg39 << 8) | 0x39)); ! 726: VideoPortWritePortUchar(CRT_ADDRESS_REG, IndexReg); ! 727: ! 728: return ERROR_DEV_NOT_EXIST; ! 729: ! 730: } else { ! 731: ! 732: hwDeviceExtension->AdapterMemorySize = 0x00100000; ! 733: ! 734: } ! 735: ! 736: } else { ! 737: ! 738: // ! 739: // This is for the 801/805, and 928. ! 740: // If an invalid size or there is less than 1 meg on the card fail. ! 741: // ! 742: ! 743: switch (s3MemSizeCode) { ! 744: ! 745: case 0x0: // 4 meg ! 746: ! 747: hwDeviceExtension->AdapterMemorySize = 0x00400000; ! 748: break; ! 749: ! 750: case 0x2: // 3 meg ! 751: ! 752: hwDeviceExtension->AdapterMemorySize = 0x00300000; ! 753: break; ! 754: ! 755: case 0x4: // 2 meg ! 756: ! 757: hwDeviceExtension->AdapterMemorySize = 0x00200000; ! 758: break; ! 759: ! 760: case 0x6: // 1 meg ! 761: ! 762: hwDeviceExtension->AdapterMemorySize = 0x00100000; ! 763: break; ! 764: ! 765: case 0x1: // invalid ! 766: case 0x3: // invalid ! 767: case 0x5: // invalid ! 768: case 0x7: // 1/2 meg ! 769: default: ! 770: ! 771: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg38 << 8) | 0x38)); ! 772: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg39 << 8) | 0x39)); ! 773: VideoPortWritePortUchar(CRT_ADDRESS_REG, IndexReg); ! 774: ! 775: VideoPortLogError(hwDeviceExtension, ! 776: NULL, ! 777: S3_NOT_ENOUGH_VRAM, ! 778: __LINE__); ! 779: ! 780: return ERROR_INVALID_PARAMETER; ! 781: ! 782: } ! 783: } ! 784: ! 785: // ! 786: // From the size of video memory calculate which modes are valid. ! 787: // ! 788: ! 789: hwDeviceExtension->NumAvailableModes = 0; ! 790: ! 791: for (i=0; i < NumS3VideoModes; i++) { ! 792: ! 793: // ! 794: // Set the mode so it does not have to be hardcoded in the mode table. ! 795: // ! 796: ! 797: S3Modes[i].ModeInformation.ModeIndex = i; ! 798: ! 799: // ! 800: // Set the mode to valid if it is. ! 801: // ! 802: ! 803: if (S3Modes[i].RequiredVideoMemory <= ! 804: hwDeviceExtension->AdapterMemorySize) { ! 805: ! 806: #ifdef i386 ! 807: if (S3Modes[i].Int10ModeNumber) { ! 808: #else ! 809: if (S3Modes[i].CRTCTables[hwDeviceExtension->ChipID]) { ! 810: #endif ! 811: ! 812: S3Modes[i].ModeValid = TRUE; ! 813: hwDeviceExtension->NumAvailableModes++; ! 814: } ! 815: } ! 816: } ! 817: ! 818: // ! 819: // Check if we need to remap the registers of the S3 due to a register ! 820: // contention with the COM3 COM4. ! 821: // ! 822: // Allow allow for override to use alternate register set from the ! 823: // registry. ! 824: // ! 825: ! 826: if (NO_ERROR == VideoPortGetRegistryParameters(hwDeviceExtension, ! 827: L"UseAlternateRegisterSet", ! 828: FALSE, ! 829: S3RegistryCallback, ! 830: NULL)) { ! 831: ! 832: useAlternateRegisters = TRUE; ! 833: ! 834: } ! 835: ! 836: // ! 837: // This assumes the S3 registers are unlocked. ! 838: // ! 839: ! 840: // ! 841: // Get the original register values. ! 842: // ! 843: ! 844: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x40); ! 845: reg40 = VideoPortReadPortUchar(CRT_DATA_REG); ! 846: ! 847: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x43); ! 848: reg43 = VideoPortReadPortUchar(CRT_DATA_REG); ! 849: ! 850: // ! 851: // Using the BIOS and registers to detect conflict does appear to work *ONLY* ! 852: // on x86 based machines ! 853: // ! 854: // We will keep the manual override (above) for everyone, just in case .... ! 855: // ! 856: ! 857: #ifdef i386 ! 858: ! 859: // ! 860: // The 801/805 and 928 allow quesrying of the extended registers to ! 861: // determine if the registers should be remapped ! 862: // ! 863: ! 864: switch(hwDeviceExtension->ChipID) { ! 865: ! 866: case S3_801: ! 867: case S3_928: ! 868: ! 869: { ! 870: LONG i; ! 871: ! 872: // ! 873: // Disable the enhanced registers. ! 874: // ! 875: ! 876: VideoPortWritePortUshort(CRT_ADDRESS_REG, ! 877: ((USHORT)(((USHORT) (reg40 & ~0x01) << 8) | 0x40))); ! 878: ! 879: // ! 880: // Make sure there is no remapping. ! 881: // ! 882: ! 883: reg43 &= ~0x10; ! 884: ! 885: VideoPortWritePortUshort(CRT_ADDRESS_REG, ! 886: ((USHORT)(((USHORT) reg43 << 8) | 0x43))); ! 887: ! 888: // ! 889: // Read each of the enhanced registers. If any of them do not ! 890: // come back 0xff, then we have an I/O conflict, and we should remap ! 891: // the I/O registers, by setting bit 4 of register 0x43. ! 892: // ! 893: ! 894: for (i = S3_EXTENDED_RANGE_START; i < NUM_S3_ACCESS_RANGES; i++) { ! 895: ! 896: if (VideoPortReadPortUshort( ! 897: (PUSHORT) hwDeviceExtension->MappedAddress[i]) != 0xFFFF) { ! 898: ! 899: // ! 900: // We have detected an I/O conflict, ! 901: // So we must remap the registers. ! 902: // ! 903: ! 904: useAlternateRegisters = TRUE; ! 905: ! 906: break; ! 907: ! 908: } ! 909: } ! 910: ! 911: break; ! 912: } ! 913: ! 914: default: ! 915: ! 916: break; ! 917: ! 918: } ! 919: ! 920: #endif ! 921: ! 922: // ! 923: // If we do use the alternate, update all of our resources. ! 924: // ! 925: ! 926: if (useAlternateRegisters) { ! 927: ! 928: VideoDebugPrint((1, "S3: S3 registers relocated to support COM3 COM4\n")); ! 929: ! 930: // ! 931: // Calculate the updated value for reg 43. ! 932: // ! 933: ! 934: reg43 |= 0x10; ! 935: ! 936: for (i = 1; i < NUM_S3_ACCESS_RANGES; i++) { ! 937: ! 938: // ! 939: // First free the mapped address. ! 940: // ! 941: ! 942: VideoPortFreeDeviceBase(hwDeviceExtension, ! 943: hwDeviceExtension->MappedAddress[i]); ! 944: ! 945: // ! 946: // Get the new address (by XORing 3A0) ! 947: // ! 948: ! 949: accessRange[i].RangeStart.LowPart ^= 0x3A0; ! 950: ! 951: // ! 952: // Map the new address. ! 953: // ! 954: ! 955: if ( (hwDeviceExtension->MappedAddress[i] = ! 956: VideoPortGetDeviceBase(hwDeviceExtension, ! 957: accessRange[i].RangeStart, ! 958: accessRange[i].RangeLength, ! 959: accessRange[i].RangeInIoSpace)) == NULL) { ! 960: ! 961: return ERROR_INVALID_PARAMETER; ! 962: ! 963: } ! 964: } ! 965: } ! 966: ! 967: // ! 968: // Reset regs to the original (or modified) value. ! 969: // ! 970: ! 971: VideoPortWritePortUshort(CRT_ADDRESS_REG, ! 972: ((USHORT)(((USHORT) reg43 << 8) | 0x43))); ! 973: ! 974: VideoPortWritePortUshort(CRT_ADDRESS_REG, ! 975: ((USHORT)(((USHORT) reg40 << 8) | 0x40))); ! 976: ! 977: ! 978: // ! 979: // Were done mucking about with the S3 chip, so lock all the registers. ! 980: // ! 981: ! 982: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg38 << 8) | 0x38)); ! 983: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg39 << 8) | 0x39)); ! 984: VideoPortWritePortUchar(CRT_ADDRESS_REG, IndexReg); ! 985: ! 986: ! 987: // ! 988: // We will try to recognize a few boards. ! 989: // If this fails we must exit since we do not know how to initialize the ! 990: // board ! 991: // ! 992: ! 993: bMatch = FALSE; ! 994: ! 995: // ! 996: // Look for brand name signatures in the ROM. ! 997: // ! 998: ! 999: romAddress = VideoPortGetDeviceBase(hwDeviceExtension, ! 1000: accessRange[0].RangeStart, ! 1001: accessRange[0].RangeLength, ! 1002: accessRange[0].RangeInIoSpace); ! 1003: ! 1004: if (romAddress) { ! 1005: ! 1006: usRomSignature = VideoPortReadRegisterUshort(romAddress); ! 1007: ! 1008: if (usRomSignature == 0xAA55) { ! 1009: ! 1010: bMatch = VideoPortScanRom(hwDeviceExtension, ! 1011: romAddress, ! 1012: MAX_ROM_SCAN, ! 1013: "Number Nine Computer"); ! 1014: ! 1015: if (bMatch == TRUE) { ! 1016: ! 1017: hwDeviceExtension->BoardID = S3_NUMBER_NINE; ! 1018: ! 1019: // ! 1020: // We know (at least we think) this is number nine board. ! 1021: // there was a bios change at #9 to change the refresh rate ! 1022: // mapping. This change was made at Microsofts request. the ! 1023: // problem is that the change has not make into production at ! 1024: // the time this driver was written. For this reason, we must ! 1025: // check the bios version number, before we special case the ! 1026: // card as the number nine card. ! 1027: // ! 1028: // There is a byte in the bios at offset 0x190, that is the ! 1029: // offset from the beginning of the bios for the bios version ! 1030: // number. the bios version number is a string. all the ! 1031: // bios versions before 1.10.04 need this special translation. ! 1032: // all the other bios's use a translation closer to the s3 ! 1033: // standard. ! 1034: // ! 1035: ! 1036: // ! 1037: // We only do this on x86 because on MIPS we do not use the ! 1038: // BIOS. ! 1039: // ! 1040: ! 1041: #ifdef i386 ! 1042: ! 1043: offset = * (((PUCHAR) romAddress) + 0x190); ! 1044: pjBiosVersion = (PUCHAR) romAddress + offset; ! 1045: ! 1046: pjRefString = "1.10.04"; ! 1047: iCmpRet = strncmp(pjBiosVersion, ! 1048: pjRefString, ! 1049: strlen(pjRefString)); ! 1050: ! 1051: if (iCmpRet >= 0) { ! 1052: ! 1053: hwDeviceExtension->BoardID = S3_GENERIC; ! 1054: ! 1055: } ! 1056: ! 1057: #endif ! 1058: ! 1059: } else { ! 1060: ! 1061: // ! 1062: // Look for an Orchid board ! 1063: // ! 1064: ! 1065: bMatch = VideoPortScanRom(hwDeviceExtension, ! 1066: romAddress, ! 1067: MAX_ROM_SCAN, ! 1068: "Orchid Technology Fahrenheit 1280"); ! 1069: ! 1070: if (bMatch == TRUE) { ! 1071: ! 1072: hwDeviceExtension->BoardID = S3_ORCHID; ! 1073: ! 1074: } else { ! 1075: ! 1076: // ! 1077: // Look for the DELL trademark ! 1078: // ! 1079: ! 1080: bMatch = VideoPortScanRom(hwDeviceExtension, ! 1081: romAddress, ! 1082: MAX_ROM_SCAN, ! 1083: "DELL"); ! 1084: ! 1085: if (bMatch == TRUE) { ! 1086: ! 1087: hwDeviceExtension->BoardID = S3_DELL; ! 1088: ! 1089: } ! 1090: } ! 1091: ! 1092: } ! 1093: ! 1094: } ! 1095: ! 1096: // ! 1097: // Free the ROM address since we do not need it anymore. ! 1098: // ! 1099: ! 1100: VideoPortFreeDeviceBase(hwDeviceExtension, ! 1101: romAddress); ! 1102: ! 1103: } ! 1104: ! 1105: #ifdef i386 ! 1106: ! 1107: // ! 1108: // We use int10 on x86 ! 1109: // ! 1110: ! 1111: hwDeviceExtension->bUsingInt10 = TRUE; ! 1112: ! 1113: // ! 1114: // We have this so that the int10 will also work on the VGA also if we ! 1115: // use it in this driver. ! 1116: // ! 1117: ! 1118: ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x000A0000; ! 1119: ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000; ! 1120: ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00020000; ! 1121: ! 1122: #else ! 1123: ! 1124: // ! 1125: // On non-x86 platforms we can not use int 10. ! 1126: // ! 1127: ! 1128: hwDeviceExtension->bUsingInt10 = FALSE; ! 1129: ! 1130: ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x00000000; ! 1131: ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000; ! 1132: ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00000000; ! 1133: ! 1134: #endif // i386 ! 1135: ! 1136: // ! 1137: // Clear out the Emulator entries and the state size since this driver ! 1138: // does not support them. ! 1139: // ! 1140: ! 1141: ConfigInfo->NumEmulatorAccessEntries = 0; ! 1142: ConfigInfo->EmulatorAccessEntries = NULL; ! 1143: ConfigInfo->EmulatorAccessEntriesContext = 0; ! 1144: ! 1145: // ! 1146: // This driver does not do SAVE/RESTORE of hardware state. ! 1147: // ! 1148: ! 1149: ConfigInfo->HardwareStateSize = 0; ! 1150: ! 1151: // ! 1152: // Frame buffer information ! 1153: // ! 1154: ! 1155: hwDeviceExtension->PhysicalFrameAddress = accessRange[1].RangeStart; ! 1156: hwDeviceExtension->FrameLength = accessRange[1].RangeLength; ! 1157: ! 1158: // ! 1159: // IO Port information ! 1160: // Get the base address, starting at zero and map all registers ! 1161: // ! 1162: ! 1163: hwDeviceExtension->PhysicalRegisterAddress = accessRange[2].RangeStart; ! 1164: hwDeviceExtension->PhysicalRegisterAddress.LowPart &= 0xFFFF0000; ! 1165: ! 1166: hwDeviceExtension->RegisterLength = 0x10000; ! 1167: hwDeviceExtension->RegisterSpace = accessRange[2].RangeInIoSpace; ! 1168: ! 1169: // ! 1170: // Indicate we do not wish to be called over ! 1171: // ! 1172: ! 1173: *Again = 0; ! 1174: ! 1175: // ! 1176: // Indicate a successful completion status. ! 1177: // ! 1178: ! 1179: return NO_ERROR; ! 1180: ! 1181: } // end S3FindAdapter() ! 1182: ! 1183: ! 1184: VP_STATUS ! 1185: S3RegistryCallback( ! 1186: PVOID HwDeviceExtension, ! 1187: PVOID Context, ! 1188: PWSTR ValueName, ! 1189: PVOID ValueData, ! 1190: ULONG ValueLength ! 1191: ) ! 1192: ! 1193: /*++ ! 1194: ! 1195: Routine Description: ! 1196: ! 1197: This routine determines if the alternate register set was requested via ! 1198: the registry. ! 1199: ! 1200: Arguments: ! 1201: ! 1202: HwDeviceExtension - Supplies a pointer to the miniport's device extension. ! 1203: ! 1204: Context - Context value passed to the get registry paramters routine. ! 1205: ! 1206: ValueName - Name of the value requested. ! 1207: ! 1208: ValueData - Pointer to the requested data. ! 1209: ! 1210: ValueLength - Length of the requested data. ! 1211: ! 1212: Return Value: ! 1213: ! 1214: returns NO_ERROR if the paramter was TRUE. ! 1215: returns ERROR_INVALID_PARAMETER otherwise. ! 1216: ! 1217: --*/ ! 1218: ! 1219: { ! 1220: ! 1221: if (ValueLength && *((PULONG)ValueData)) { ! 1222: ! 1223: return NO_ERROR; ! 1224: ! 1225: } else { ! 1226: ! 1227: return ERROR_INVALID_PARAMETER; ! 1228: ! 1229: } ! 1230: ! 1231: } // end S3RegistryCallback() ! 1232: ! 1233: ! 1234: BOOLEAN ! 1235: S3Initialize( ! 1236: PVOID HwDeviceExtension ! 1237: ) ! 1238: ! 1239: /*++ ! 1240: ! 1241: Routine Description: ! 1242: ! 1243: This routine does one time initialization of the device. ! 1244: ! 1245: Arguments: ! 1246: ! 1247: HwDeviceExtension - Supplies a pointer to the miniport's device extension. ! 1248: ! 1249: Return Value: ! 1250: ! 1251: ! 1252: Always returns TRUE since this routine can never fail. ! 1253: ! 1254: --*/ ! 1255: ! 1256: { ! 1257: #if i386 ! 1258: ! 1259: UCHAR IndexReg, reg38, reg39; ! 1260: ULONG i; ! 1261: ! 1262: IndexReg = VideoPortReadPortUchar(CRT_ADDRESS_REG); ! 1263: ! 1264: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x38); ! 1265: reg38 = VideoPortReadPortUchar(CRT_DATA_REG); ! 1266: ! 1267: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x39); ! 1268: reg39 = VideoPortReadPortUchar(CRT_DATA_REG); ! 1269: ! 1270: // ! 1271: // Unlock the S3 registers. ! 1272: // ! 1273: ! 1274: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x4838); ! 1275: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0xA039); ! 1276: ! 1277: // ! 1278: // read all the extended registers. ! 1279: // ! 1280: ! 1281: for (i = 0; i < nExtendedRegs; i++) { ! 1282: ! 1283: VideoPortWritePortUchar(CRT_ADDRESS_REG, arvExtendedRegs[i].port); ! 1284: arvExtendedRegs[i].val = VideoPortReadPortUchar(CRT_DATA_REG); ! 1285: ! 1286: } ! 1287: ! 1288: // ! 1289: // restore the chip to the same state is was in when we got here. ! 1290: // ! 1291: ! 1292: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg38 << 8) | 0x38)); ! 1293: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg39 << 8) | 0x39)); ! 1294: VideoPortWritePortUchar(CRT_ADDRESS_REG, IndexReg); ! 1295: ! 1296: #endif ! 1297: ! 1298: return TRUE; ! 1299: ! 1300: UNREFERENCED_PARAMETER(HwDeviceExtension); ! 1301: ! 1302: } // end S3Initialize() ! 1303: ! 1304: BOOLEAN ! 1305: S3StartIO( ! 1306: PVOID HwDeviceExtension, ! 1307: PVIDEO_REQUEST_PACKET RequestPacket ! 1308: ) ! 1309: ! 1310: /*++ ! 1311: ! 1312: Routine Description: ! 1313: ! 1314: This routine is the main execution routine for the miniport driver. It ! 1315: acceptss a Video Request Packet, performs the request, and then returns ! 1316: with the appropriate status. ! 1317: ! 1318: Arguments: ! 1319: ! 1320: HwDeviceExtension - Supplies a pointer to the miniport's device extension. ! 1321: ! 1322: RequestPacket - Pointer to the video request packet. This structure ! 1323: contains all the parameters passed to the VideoIoControl function. ! 1324: ! 1325: Return Value: ! 1326: ! 1327: ! 1328: --*/ ! 1329: ! 1330: { ! 1331: PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; ! 1332: VP_STATUS status; ! 1333: ULONG inIoSpace; ! 1334: PVIDEO_MODE_INFORMATION modeInformation; ! 1335: PVIDEO_MEMORY_INFORMATION memoryInformation; ! 1336: PVIDEO_CLUT clutBuffer; ! 1337: ULONG i; ! 1338: UCHAR byte, ModeControlByte; ! 1339: ! 1340: VIDEO_X86_BIOS_ARGUMENTS biosArguments; ! 1341: ULONG modeNumber; ! 1342: PUCHAR pModeBits; ! 1343: ! 1344: // ! 1345: // Keep a history of the commands. ! 1346: // This will help track down the chip being in a DOS session while ! 1347: // GDI and the S3 display driver "think" it's in GUI mode. ! 1348: ! 1349: gaIOControlCode[giControlCode++] = RequestPacket->IoControlCode; ! 1350: giControlCode %= MAX_CONTROL_HISTORY; ! 1351: ! 1352: // ! 1353: // Switch on the IoContolCode in the RequestPacket. It indicates which ! 1354: // function must be performed by the driver. ! 1355: // ! 1356: ! 1357: switch (RequestPacket->IoControlCode) { ! 1358: ! 1359: ! 1360: case IOCTL_VIDEO_MAP_VIDEO_MEMORY: ! 1361: ! 1362: VideoDebugPrint((2, "S3tartIO - MapVideoMemory\n")); ! 1363: ! 1364: if ( (RequestPacket->OutputBufferLength < ! 1365: (RequestPacket->StatusBlock->Information = ! 1366: sizeof(VIDEO_MEMORY_INFORMATION))) || ! 1367: (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) { ! 1368: ! 1369: status = ERROR_INSUFFICIENT_BUFFER; ! 1370: } ! 1371: ! 1372: memoryInformation = RequestPacket->OutputBuffer; ! 1373: ! 1374: memoryInformation->VideoRamBase = ((PVIDEO_MEMORY) ! 1375: (RequestPacket->InputBuffer))->RequestedVirtualAddress; ! 1376: ! 1377: memoryInformation->VideoRamLength = ! 1378: hwDeviceExtension->FrameLength; ! 1379: ! 1380: inIoSpace = 0; ! 1381: ! 1382: status = VideoPortMapMemory(hwDeviceExtension, ! 1383: hwDeviceExtension->PhysicalFrameAddress, ! 1384: &(memoryInformation->VideoRamLength), ! 1385: &inIoSpace, ! 1386: &(memoryInformation->VideoRamBase)); ! 1387: ! 1388: // ! 1389: // The frame buffer and virtual memory and equivalent in this ! 1390: // case. ! 1391: // ! 1392: ! 1393: memoryInformation->FrameBufferBase = ! 1394: memoryInformation->VideoRamBase; ! 1395: ! 1396: memoryInformation->FrameBufferLength = ! 1397: memoryInformation->VideoRamLength; ! 1398: ! 1399: break; ! 1400: ! 1401: ! 1402: case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: ! 1403: ! 1404: VideoDebugPrint((2, "S3StartIO - UnMapVideoMemory\n")); ! 1405: ! 1406: if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) { ! 1407: ! 1408: status = ERROR_INSUFFICIENT_BUFFER; ! 1409: } ! 1410: ! 1411: status = VideoPortUnmapMemory(hwDeviceExtension, ! 1412: ((PVIDEO_MEMORY) ! 1413: (RequestPacket->InputBuffer))-> ! 1414: RequestedVirtualAddress, ! 1415: 0); ! 1416: ! 1417: break; ! 1418: ! 1419: ! 1420: case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES: ! 1421: ! 1422: VideoDebugPrint((2, "S3StartIO - QueryPublicAccessRanges\n")); ! 1423: ! 1424: { ! 1425: ! 1426: PVIDEO_PUBLIC_ACCESS_RANGES portAccess; ! 1427: ULONG physicalPortLength; ! 1428: ! 1429: if ( RequestPacket->OutputBufferLength < ! 1430: (RequestPacket->StatusBlock->Information = ! 1431: sizeof(VIDEO_PUBLIC_ACCESS_RANGES)) ) { ! 1432: ! 1433: status = ERROR_INSUFFICIENT_BUFFER; ! 1434: } ! 1435: ! 1436: portAccess = RequestPacket->OutputBuffer; ! 1437: ! 1438: portAccess->VirtualAddress = (PVOID) NULL; // Requested VA ! 1439: portAccess->InIoSpace = hwDeviceExtension->RegisterSpace; ! 1440: portAccess->MappedInIoSpace = portAccess->InIoSpace; ! 1441: ! 1442: physicalPortLength = hwDeviceExtension->RegisterLength; ! 1443: ! 1444: status = VideoPortMapMemory(hwDeviceExtension, ! 1445: hwDeviceExtension->PhysicalRegisterAddress, ! 1446: &physicalPortLength, ! 1447: &(portAccess->MappedInIoSpace), ! 1448: &(portAccess->VirtualAddress)); ! 1449: } ! 1450: ! 1451: break; ! 1452: ! 1453: ! 1454: case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES: ! 1455: ! 1456: VideoDebugPrint((2, "S3StartIO - FreePublicAccessRanges\n")); ! 1457: ! 1458: if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) { ! 1459: ! 1460: status = ERROR_INSUFFICIENT_BUFFER; ! 1461: } ! 1462: ! 1463: status = VideoPortUnmapMemory(hwDeviceExtension, ! 1464: ((PVIDEO_MEMORY) ! 1465: (RequestPacket->InputBuffer))-> ! 1466: RequestedVirtualAddress, ! 1467: 0); ! 1468: ! 1469: break; ! 1470: ! 1471: ! 1472: case IOCTL_VIDEO_QUERY_AVAIL_MODES: ! 1473: ! 1474: VideoDebugPrint((2, "S3StartIO - QueryAvailableModes\n")); ! 1475: ! 1476: if (RequestPacket->OutputBufferLength < ! 1477: (RequestPacket->StatusBlock->Information = ! 1478: hwDeviceExtension->NumAvailableModes ! 1479: * sizeof(VIDEO_MODE_INFORMATION)) ) { ! 1480: ! 1481: status = ERROR_INSUFFICIENT_BUFFER; ! 1482: ! 1483: } else { ! 1484: ! 1485: modeInformation = RequestPacket->OutputBuffer; ! 1486: ! 1487: for (i = 0; i < NumS3VideoModes; i++) { ! 1488: ! 1489: if (S3Modes[i].ModeValid) { ! 1490: ! 1491: *modeInformation = S3Modes[i].ModeInformation; ! 1492: modeInformation++; ! 1493: ! 1494: } ! 1495: } ! 1496: ! 1497: status = NO_ERROR; ! 1498: } ! 1499: ! 1500: break; ! 1501: ! 1502: ! 1503: case IOCTL_VIDEO_QUERY_CURRENT_MODE: ! 1504: ! 1505: VideoDebugPrint((2, "S3StartIO - QueryCurrentModes\n")); ! 1506: ! 1507: if (RequestPacket->OutputBufferLength < ! 1508: (RequestPacket->StatusBlock->Information = ! 1509: sizeof(VIDEO_MODE_INFORMATION)) ) { ! 1510: ! 1511: status = ERROR_INSUFFICIENT_BUFFER; ! 1512: ! 1513: } else { ! 1514: ! 1515: *((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer) = ! 1516: S3Modes[hwDeviceExtension->ModeNumber].ModeInformation; ! 1517: ! 1518: status = NO_ERROR; ! 1519: ! 1520: } ! 1521: ! 1522: break; ! 1523: ! 1524: ! 1525: ! 1526: case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: ! 1527: ! 1528: VideoDebugPrint((2, "S3StartIO - QueryNumAvailableModes\n")); ! 1529: ! 1530: // ! 1531: // Find out the size of the data to be put in the the buffer and ! 1532: // return that in the status information (whether or not the ! 1533: // information is there). If the buffer passed in is not large ! 1534: // enough return an appropriate error code. ! 1535: // ! 1536: ! 1537: if (RequestPacket->OutputBufferLength < ! 1538: (RequestPacket->StatusBlock->Information = ! 1539: sizeof(VIDEO_NUM_MODES)) ) { ! 1540: ! 1541: status = ERROR_INSUFFICIENT_BUFFER; ! 1542: ! 1543: } else { ! 1544: ! 1545: ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes = ! 1546: hwDeviceExtension->NumAvailableModes; ! 1547: ! 1548: ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->ModeInformationLength = ! 1549: sizeof(VIDEO_MODE_INFORMATION); ! 1550: ! 1551: ! 1552: status = NO_ERROR; ! 1553: } ! 1554: ! 1555: break; ! 1556: ! 1557: ! 1558: case IOCTL_VIDEO_SET_CURRENT_MODE: ! 1559: ! 1560: VideoDebugPrint((2, "S3StartIO - SetCurrentMode\n")); ! 1561: ! 1562: // ! 1563: // Check if the size of the data in the input buffer is large enough. ! 1564: // ! 1565: ! 1566: if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE)) { ! 1567: ! 1568: return ERROR_INSUFFICIENT_BUFFER; ! 1569: ! 1570: } ! 1571: ! 1572: // ! 1573: // Check to see if we are requesting a valid mode ! 1574: // ! 1575: ! 1576: modeNumber = ((PVIDEO_MODE) RequestPacket->InputBuffer)->RequestedMode; ! 1577: ! 1578: if ( (modeNumber >= NumS3VideoModes) || ! 1579: (!S3Modes[modeNumber].ModeValid) ) { ! 1580: ! 1581: return ERROR_INVALID_PARAMETER; ! 1582: ! 1583: } ! 1584: ! 1585: #ifdef i386 ! 1586: ! 1587: VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); ! 1588: ! 1589: // ! 1590: // Unlock the S3 registers. ! 1591: // ! 1592: ! 1593: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x4838); ! 1594: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0xA039); ! 1595: ! 1596: /* ! 1597: Important Note: The Actix 911 board did not boot when the low order ! 1598: bits of reg 41 were changed in the 640 X 480 or the ! 1599: 800 X 600 modes. The Stealth did not change to 60Hz ! 1600: in the 1024 X 768 mode when the low order bits were ! 1601: set, it stayed at 70Hz. And the Orchid would come up ! 1602: in interlaced in 1024 X 768 when it should have been ! 1603: 60Hz. Since the 911 is at the end of it's product ! 1604: life cycle it would be unreasonable to expect the ! 1605: board manufactures to upgrade the ROMS. And the user ! 1606: currently know how to set the board dip switches, so ! 1607: the V refresh rate control is being removed for the ! 1608: 911 and 924 based boards. ! 1609: */ ! 1610: ! 1611: // ! 1612: // If this is a 801/805 or 928 pickup the refresh control byte from ! 1613: // the chip, set the mode we want, and put the bits back in the chip. ! 1614: // ! 1615: ! 1616: // ! 1617: // A refresh rate of 1 indicates to use whatever is left in the BIOS ! 1618: // data area ... ! 1619: // ! 1620: ! 1621: if (S3Modes[modeNumber].ModeInformation.Frequency != 1) { ! 1622: ! 1623: switch(hwDeviceExtension->ChipID) { ! 1624: ! 1625: case S3_801: ! 1626: case S3_928: ! 1627: ! 1628: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x52); ! 1629: ! 1630: ModeControlByte = VideoPortReadPortUchar(CRT_DATA_REG); ! 1631: ModeControlByte &= ModeMaskBits[modeNumber]; ! 1632: ! 1633: switch(hwDeviceExtension->BoardID) { ! 1634: ! 1635: case S3_NUMBER_NINE: ! 1636: ! 1637: pModeBits = NumberNineModeBits; ! 1638: break; ! 1639: ! 1640: case S3_DELL: ! 1641: ! 1642: pModeBits = DellModeBits; ! 1643: break; ! 1644: ! 1645: // case S3_GENERIC: ! 1646: default: ! 1647: ! 1648: pModeBits = GenericModeBits; ! 1649: break; ! 1650: ! 1651: } ! 1652: ! 1653: ModeControlByte |= pModeBits[modeNumber]; ! 1654: ! 1655: VideoPortWritePortUchar(CRT_DATA_REG, ModeControlByte); ! 1656: ! 1657: break; ! 1658: ! 1659: default: ! 1660: ! 1661: break; ! 1662: ! 1663: } ! 1664: } ! 1665: ! 1666: biosArguments.Ebx = S3Modes[modeNumber].Int10ModeNumber; ! 1667: biosArguments.Eax = 0x4f02; ! 1668: ! 1669: status = VideoPortInt10(HwDeviceExtension, &biosArguments); ! 1670: ! 1671: // ! 1672: // If we get an error, return it. ! 1673: // ! 1674: ! 1675: if (status != NO_ERROR) { ! 1676: ! 1677: break; ! 1678: ! 1679: } ! 1680: ! 1681: // ! 1682: // Save the mode number since we know the rest will work. ! 1683: // ! 1684: ! 1685: hwDeviceExtension->ModeNumber = modeNumber; ! 1686: ! 1687: // ! 1688: // Unlock the S3 registers, we need to unlock the registers a second time, ! 1689: // since we do not know what state the locks were in after the Int10. ! 1690: // ! 1691: ! 1692: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x4838); ! 1693: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0xA039); ! 1694: ! 1695: // ! 1696: // If this is a 1280 mode then set to non-contiguous memory mode. ! 1697: // ! 1698: ! 1699: if (S3Modes[modeNumber].ModeInformation.VisScreenWidth == 1280) { ! 1700: ! 1701: // ! 1702: // Make sure we are not in linear address mode ! 1703: // ! 1704: ! 1705: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x58); ! 1706: byte = VideoPortReadPortUchar(CRT_DATA_REG); ! 1707: byte &= ~0x10; ! 1708: VideoPortWritePortUchar(CRT_DATA_REG, byte); ! 1709: ! 1710: // ! 1711: // Turn on the graphics engine. ! 1712: // ! 1713: ! 1714: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x40); ! 1715: byte = VideoPortReadPortUchar(CRT_DATA_REG); ! 1716: byte |= 0x01; ! 1717: VideoPortWritePortUchar(CRT_DATA_REG, byte); ! 1718: ! 1719: // ! 1720: // Set the 2K by 1K memory map. ! 1721: // ! 1722: ! 1723: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x0013); ! 1724: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x8f31); ! 1725: VideoPortWritePortUshort(ADV_FUNC_CTL, 0x0003); ! 1726: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x0050); ! 1727: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x5051); ! 1728: ! 1729: // ! 1730: // Some of the number nine boards do set the chip up correctly ! 1731: // for an external cursor. We must OR in the bits, because if we ! 1732: // don't the metheus board will not init. ! 1733: // ! 1734: ! 1735: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x45); ! 1736: byte = VideoPortReadPortUchar(CRT_DATA_REG); ! 1737: byte |= 0x20; ! 1738: VideoPortWritePortUchar(CRT_DATA_REG, byte); ! 1739: ! 1740: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x55); ! 1741: byte = VideoPortReadPortUchar(CRT_DATA_REG); ! 1742: byte |= 0x20; ! 1743: VideoPortWritePortUchar(CRT_DATA_REG, byte); ! 1744: ! 1745: } ! 1746: ! 1747: #else ! 1748: // ! 1749: // For MIPS program according to the mode tables ! 1750: // ! 1751: ! 1752: // ! 1753: // Save the mode number since we will reference it in SetHWMode. ! 1754: // ! 1755: ! 1756: hwDeviceExtension->ModeNumber = modeNumber; ! 1757: ! 1758: // ! 1759: // Select the Enhanced mode init depending upon the type of chip ! 1760: // found. ! 1761: ! 1762: if ( (hwDeviceExtension->BoardID == S3_NUMBER_NINE) && ! 1763: (S3Modes[modeNumber].ModeInformation.VisScreenWidth == 1280) ) { ! 1764: ! 1765: SetHWMode(hwDeviceExtension, S3_928_1280_Enhanced_Mode); ! 1766: ! 1767: } else { ! 1768: ! 1769: // ! 1770: // Use defaults for all other boards ! 1771: // ! 1772: ! 1773: switch(hwDeviceExtension->ChipID) { ! 1774: ! 1775: case S3_911: ! 1776: ! 1777: SetHWMode(hwDeviceExtension, S3_911_Enhanced_Mode); ! 1778: break; ! 1779: ! 1780: case S3_801: ! 1781: ! 1782: SetHWMode(hwDeviceExtension, S3_801_Enhanced_Mode); ! 1783: break; ! 1784: ! 1785: case S3_928: ! 1786: ! 1787: SetHWMode(hwDeviceExtension, S3_928_Enhanced_Mode); ! 1788: break; ! 1789: ! 1790: default: ! 1791: ! 1792: VideoDebugPrint((0, "S3: Bad chip type for these boards")); ! 1793: break; ! 1794: } ! 1795: ! 1796: } ! 1797: ! 1798: // ! 1799: // Unlock the S3 registers, we need to unlock the registers a second ! 1800: // time since the interperter has them locked when it returns to us. ! 1801: // ! 1802: ! 1803: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x4838); ! 1804: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0xA039); ! 1805: ! 1806: #endif // i386 ! 1807: ! 1808: // ! 1809: // On a certain version of the DELL BIOS reg 5A was set to 0. ! 1810: // This will ensure that the linear address window is always set ! 1811: // where I expect it to be, regardless of the bios. ! 1812: // ! 1813: ! 1814: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x0059); ! 1815: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x0A5A); ! 1816: ! 1817: // ! 1818: // Enable the Graphics engine. ! 1819: // ! 1820: ! 1821: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x40); ! 1822: byte = VideoPortReadPortUchar(CRT_DATA_REG); ! 1823: byte |= 0x01; ! 1824: VideoPortWritePortUchar(CRT_DATA_REG, byte); ! 1825: ! 1826: #ifndef i386 ! 1827: ! 1828: // ! 1829: // Zero the DAC and the Screen buffer memory. ! 1830: // ! 1831: ! 1832: ZeroMemAndDac(HwDeviceExtension); ! 1833: #endif ! 1834: ! 1835: status = NO_ERROR; ! 1836: ! 1837: break; ! 1838: ! 1839: case IOCTL_VIDEO_SET_COLOR_REGISTERS: ! 1840: ! 1841: VideoDebugPrint((2, "S3StartIO - SetColorRegs\n")); ! 1842: ! 1843: clutBuffer = RequestPacket->InputBuffer; ! 1844: ! 1845: status = S3SetColorLookup(HwDeviceExtension, ! 1846: (PVIDEO_CLUT) RequestPacket->InputBuffer, ! 1847: RequestPacket->InputBufferLength); ! 1848: break; ! 1849: ! 1850: ! 1851: #ifdef i386 ! 1852: ! 1853: case IOCTL_VIDEO_RESET_DEVICE: ! 1854: ! 1855: VideoDebugPrint((2, "S3StartIO - RESET_DEVICE\n")); ! 1856: ! 1857: // ! 1858: // Wait for the GP to become idle, ! 1859: // ! 1860: ! 1861: while (VideoPortReadPortUshort(GP_STAT) & 0x0200); ! 1862: ! 1863: // ! 1864: // Reset the board to a default mode ! 1865: // ! 1866: ! 1867: SetHWMode(HwDeviceExtension, s3_set_vga_mode); ! 1868: ! 1869: VideoDebugPrint((2, "S3 RESET_DEVICE - About to do int10\n")); ! 1870: ! 1871: // ! 1872: // Do an Int10 to mode 3 will put the board to a known state. ! 1873: // ! 1874: ! 1875: VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); ! 1876: ! 1877: biosArguments.Eax = 0x0003; ! 1878: ! 1879: VideoPortInt10(HwDeviceExtension, ! 1880: &biosArguments); ! 1881: ! 1882: VideoDebugPrint((2, "S3 RESET_DEVICE - Did int10\n")); ! 1883: ! 1884: status = NO_ERROR; ! 1885: break; ! 1886: ! 1887: #endif ! 1888: ! 1889: // ! 1890: // if we get here, an invalid IoControlCode was specified. ! 1891: // ! 1892: ! 1893: default: ! 1894: ! 1895: VideoDebugPrint((1, "Fell through S3 startIO routine - invalid command\n")); ! 1896: ! 1897: status = ERROR_INVALID_FUNCTION; ! 1898: ! 1899: break; ! 1900: ! 1901: } ! 1902: ! 1903: // ! 1904: // Keep a history of the commands. ! 1905: // This will help track down the chip being in a DOS session while ! 1906: // GDI and the S3 display driver "think" it's in GUI mode. ! 1907: ! 1908: gaIOControlCode[giControlCode++] = 0x00005555; ! 1909: giControlCode %= MAX_CONTROL_HISTORY; ! 1910: ! 1911: VideoDebugPrint((2, "Leaving S3 startIO routine\n")); ! 1912: ! 1913: RequestPacket->StatusBlock->Status = status; ! 1914: ! 1915: return TRUE; ! 1916: ! 1917: } // end S3StartIO() ! 1918: ! 1919: ! 1920: VP_STATUS ! 1921: S3SetColorLookup( ! 1922: PHW_DEVICE_EXTENSION HwDeviceExtension, ! 1923: PVIDEO_CLUT ClutBuffer, ! 1924: ULONG ClutBufferSize ! 1925: ) ! 1926: ! 1927: /*++ ! 1928: ! 1929: Routine Description: ! 1930: ! 1931: This routine sets a specified portion of the color lookup table settings. ! 1932: ! 1933: Arguments: ! 1934: ! 1935: HwDeviceExtension - Pointer to the miniport driver's device extension. ! 1936: ! 1937: ClutBufferSize - Length of the input buffer supplied by the user. ! 1938: ! 1939: ClutBuffer - Pointer to the structure containing the color lookup table. ! 1940: ! 1941: Return Value: ! 1942: ! 1943: None. ! 1944: ! 1945: --*/ ! 1946: ! 1947: { ! 1948: USHORT i; ! 1949: ! 1950: // ! 1951: // Check if the size of the data in the input buffer is large enough. ! 1952: // ! 1953: ! 1954: if ( (ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) || ! 1955: (ClutBufferSize < sizeof(VIDEO_CLUT) + ! 1956: (sizeof(ULONG) * (ClutBuffer->NumEntries - 1)) ) ) { ! 1957: ! 1958: return ERROR_INSUFFICIENT_BUFFER; ! 1959: ! 1960: } ! 1961: ! 1962: // ! 1963: // Check to see if the parameters are valid. ! 1964: // ! 1965: ! 1966: if ( (ClutBuffer->NumEntries == 0) || ! 1967: (ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) || ! 1968: (ClutBuffer->FirstEntry + ClutBuffer->NumEntries > ! 1969: VIDEO_MAX_COLOR_REGISTER + 1) ) { ! 1970: ! 1971: return ERROR_INVALID_PARAMETER; ! 1972: ! 1973: } ! 1974: ! 1975: // ! 1976: // Set CLUT registers directly on the hardware ! 1977: // ! 1978: ! 1979: for (i = 0; i < ClutBuffer->NumEntries; i++) { ! 1980: ! 1981: VideoPortWritePortUchar(DAC_ADDRESS_WRITE_PORT, (UCHAR) (ClutBuffer->FirstEntry + i)); ! 1982: VideoPortWritePortUchar(DAC_DATA_REG_PORT, (UCHAR) (((ClutBuffer->LookupTable[i].RgbArray.Red)) >> 2)); ! 1983: VideoPortWritePortUchar(DAC_DATA_REG_PORT, (UCHAR) (((ClutBuffer->LookupTable[i].RgbArray.Green)) >> 2)); ! 1984: VideoPortWritePortUchar(DAC_DATA_REG_PORT, (UCHAR) (((ClutBuffer->LookupTable[i].RgbArray.Blue)) >> 2)); ! 1985: ! 1986: } ! 1987: ! 1988: return NO_ERROR; ! 1989: ! 1990: } // end S3SetColorLookup() ! 1991: ! 1992: ! 1993: VOID ! 1994: SetHWMode( ! 1995: PHW_DEVICE_EXTENSION HwDeviceExtension, ! 1996: PUSHORT pusCmdStream ! 1997: ) ! 1998: ! 1999: /*++ ! 2000: ! 2001: Routine Description: ! 2002: ! 2003: Interprets the appropriate command array to set up VGA registers for the ! 2004: requested mode. Typically used to set the VGA into a particular mode by ! 2005: programming all of the registers ! 2006: ! 2007: Arguments: ! 2008: ! 2009: HwDeviceExtension - Pointer to the miniport driver's device extension. ! 2010: ! 2011: pusCmdStream - pointer to a command stream to execute. ! 2012: ! 2013: Return Value: ! 2014: ! 2015: The status of the operation (can only fail on a bad command); TRUE for ! 2016: success, FALSE for failure. ! 2017: ! 2018: --*/ ! 2019: ! 2020: { ! 2021: ULONG ulCmd; ! 2022: ULONG ulPort; ! 2023: UCHAR jValue; ! 2024: USHORT usValue; ! 2025: ULONG culCount; ! 2026: ULONG ulIndex, ! 2027: Microseconds; ! 2028: ULONG mappedAddressIndex; ! 2029: ULONG mappedAddressOffset; ! 2030: ! 2031: // ! 2032: // If there is no command string, just return ! 2033: // ! 2034: ! 2035: if (!pusCmdStream) { ! 2036: ! 2037: return; ! 2038: ! 2039: } ! 2040: ! 2041: while ((ulCmd = *pusCmdStream++) != EOD) { ! 2042: ! 2043: // ! 2044: // Determine major command type ! 2045: // ! 2046: ! 2047: switch (ulCmd & 0xF0) { ! 2048: ! 2049: case SELECTACCESSRANGE: ! 2050: ! 2051: // ! 2052: // Determine which address range to use for commands that follow ! 2053: // ! 2054: ! 2055: switch (ulCmd & 0x0F) { ! 2056: ! 2057: case VARIOUSVGA: ! 2058: ! 2059: // ! 2060: // Used for registers in the range 0x3c0 - 0x3cf ! 2061: // ! 2062: ! 2063: mappedAddressIndex = 2; ! 2064: mappedAddressOffset = 0x3c0; ! 2065: ! 2066: break; ! 2067: ! 2068: case SYSTEMCONTROL: ! 2069: ! 2070: // ! 2071: // Used for registers in the range 0x3d4 - 0x3df ! 2072: // ! 2073: ! 2074: mappedAddressIndex = 3; ! 2075: mappedAddressOffset = 0x3d4; ! 2076: ! 2077: break; ! 2078: ! 2079: case ADVANCEDFUNCTIONCONTROL: ! 2080: ! 2081: // ! 2082: // Used for registers in the range 0x4ae8-0x4ae9 ! 2083: // ! 2084: ! 2085: mappedAddressIndex = 5; ! 2086: mappedAddressOffset = 0x4ae8; ! 2087: ! 2088: break; ! 2089: ! 2090: } ! 2091: ! 2092: break; ! 2093: ! 2094: ! 2095: case OWM: ! 2096: ! 2097: ulPort = *pusCmdStream++; ! 2098: culCount = *pusCmdStream++; ! 2099: ! 2100: while (culCount--) { ! 2101: usValue = *pusCmdStream++; ! 2102: VideoPortWritePortUshort((PUSHORT)((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort), ! 2103: usValue); ! 2104: } ! 2105: ! 2106: break; ! 2107: ! 2108: ! 2109: // Basic input/output command ! 2110: ! 2111: case INOUT: ! 2112: ! 2113: // Determine type of inout instruction ! 2114: if (!(ulCmd & IO)) { ! 2115: ! 2116: // Out instruction ! 2117: // Single or multiple outs? ! 2118: if (!(ulCmd & MULTI)) { ! 2119: ! 2120: // Single out ! 2121: // Byte or word out? ! 2122: if (!(ulCmd & BW)) { ! 2123: ! 2124: // Single byte out ! 2125: ulPort = *pusCmdStream++; ! 2126: jValue = (UCHAR) *pusCmdStream++; ! 2127: VideoPortWritePortUchar((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort, ! 2128: jValue); ! 2129: ! 2130: } else { ! 2131: ! 2132: // Single word out ! 2133: ulPort = *pusCmdStream++; ! 2134: usValue = *pusCmdStream++; ! 2135: VideoPortWritePortUshort((PUSHORT)((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort), ! 2136: usValue); ! 2137: ! 2138: } ! 2139: ! 2140: } else { ! 2141: ! 2142: // Output a string of values ! 2143: // Byte or word outs? ! 2144: if (!(ulCmd & BW)) { ! 2145: ! 2146: // String byte outs. Do in a loop; can't use ! 2147: // VideoPortWritePortBufferUchar because the data ! 2148: // is in USHORT form ! 2149: ulPort = *pusCmdStream++; ! 2150: culCount = *pusCmdStream++; ! 2151: while (culCount--) { ! 2152: jValue = (UCHAR) *pusCmdStream++; ! 2153: VideoPortWritePortUchar((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort, ! 2154: jValue); ! 2155: ! 2156: } ! 2157: ! 2158: } else { ! 2159: ! 2160: // String word outs ! 2161: ulPort = *pusCmdStream++; ! 2162: culCount = *pusCmdStream++; ! 2163: VideoPortWritePortBufferUshort((PUSHORT)((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort), ! 2164: pusCmdStream, ! 2165: culCount); ! 2166: pusCmdStream += culCount; ! 2167: ! 2168: } ! 2169: } ! 2170: ! 2171: } else { ! 2172: ! 2173: // In instruction ! 2174: ! 2175: // Currently, string in instructions aren't supported; all ! 2176: // in instructions are handled as single-byte ins ! 2177: ! 2178: // Byte or word in? ! 2179: if (!(ulCmd & BW)) { ! 2180: ! 2181: // Single byte in ! 2182: ulPort = *pusCmdStream++; ! 2183: jValue = VideoPortReadPortUchar((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort); ! 2184: ! 2185: } else { ! 2186: ! 2187: // Single word in ! 2188: ulPort = *pusCmdStream++; ! 2189: usValue = VideoPortReadPortUshort((PUSHORT)((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort)); ! 2190: } ! 2191: ! 2192: } ! 2193: ! 2194: break; ! 2195: ! 2196: ! 2197: // Higher-level input/output commands ! 2198: ! 2199: case METAOUT: ! 2200: ! 2201: // Determine type of metaout command, based on minor command field ! 2202: switch (ulCmd & 0x0F) { ! 2203: ! 2204: // Indexed outs ! 2205: case INDXOUT: ! 2206: ! 2207: ulPort = *pusCmdStream++; ! 2208: culCount = *pusCmdStream++; ! 2209: ulIndex = *pusCmdStream++; ! 2210: ! 2211: while (culCount--) { ! 2212: ! 2213: usValue = (USHORT) (ulIndex + ! 2214: (((ULONG)(*pusCmdStream++)) << 8)); ! 2215: VideoPortWritePortUshort((PUSHORT)((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort), ! 2216: usValue); ! 2217: ! 2218: ulIndex++; ! 2219: ! 2220: } ! 2221: ! 2222: break; ! 2223: ! 2224: ! 2225: // Masked out (read, AND, XOR, write) ! 2226: case MASKOUT: ! 2227: ! 2228: ulPort = *pusCmdStream++; ! 2229: jValue = VideoPortReadPortUchar((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort); ! 2230: jValue &= *pusCmdStream++; ! 2231: jValue ^= *pusCmdStream++; ! 2232: VideoPortWritePortUchar((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort, ! 2233: jValue); ! 2234: break; ! 2235: ! 2236: ! 2237: // Attribute Controller out ! 2238: case ATCOUT: ! 2239: ! 2240: ulPort = *pusCmdStream++; ! 2241: culCount = *pusCmdStream++; ! 2242: ulIndex = *pusCmdStream++; ! 2243: ! 2244: while (culCount--) { ! 2245: ! 2246: // Write Attribute Controller index ! 2247: VideoPortWritePortUchar((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort, ! 2248: (UCHAR)ulIndex); ! 2249: ! 2250: // Write Attribute Controller data ! 2251: jValue = (UCHAR) *pusCmdStream++; ! 2252: VideoPortWritePortUchar((PUCHAR)HwDeviceExtension->MappedAddress[mappedAddressIndex] - mappedAddressOffset + ulPort, ! 2253: jValue); ! 2254: ! 2255: ulIndex++; ! 2256: ! 2257: } ! 2258: ! 2259: break; ! 2260: ! 2261: case DELAY: ! 2262: ! 2263: Microseconds = (ULONG) *pusCmdStream++; ! 2264: VideoPortStallExecution(Microseconds); ! 2265: ! 2266: break; ! 2267: ! 2268: case BT485RESET: ! 2269: ! 2270: Reset_Bt485(HwDeviceExtension); ! 2271: ! 2272: break; ! 2273: ! 2274: #ifndef i386 ! 2275: case VBLANK: ! 2276: ! 2277: Wait_VSync(HwDeviceExtension); ! 2278: ! 2279: break; ! 2280: ! 2281: case SETCLK: ! 2282: ! 2283: Set_Oem_Clock(HwDeviceExtension); ! 2284: ! 2285: break; ! 2286: ! 2287: case SETCRTC: ! 2288: ! 2289: // ! 2290: // NOTE: ! 2291: // beware: recursive call ... ! 2292: // ! 2293: ! 2294: SetHWMode(HwDeviceExtension, ! 2295: S3Modes[HwDeviceExtension->ModeNumber]. ! 2296: CRTCTables[HwDeviceExtension->ChipID]); ! 2297: ! 2298: ! 2299: break; ! 2300: ! 2301: case BUSTEST: ! 2302: ! 2303: Bus_Test(HwDeviceExtension); ! 2304: ! 2305: break; ! 2306: #endif // i386 ! 2307: ! 2308: // None of the above; error ! 2309: default: ! 2310: ! 2311: return; ! 2312: ! 2313: } ! 2314: ! 2315: break; ! 2316: ! 2317: ! 2318: // NOP ! 2319: ! 2320: case NCMD: ! 2321: ! 2322: break; ! 2323: ! 2324: ! 2325: // Unknown command; error ! 2326: ! 2327: default: ! 2328: ! 2329: return; ! 2330: ! 2331: } ! 2332: ! 2333: } ! 2334: ! 2335: return; ! 2336: ! 2337: } // end SetHWMode() ! 2338: ! 2339: ! 2340: BOOLEAN ! 2341: Reset_Bt485( ! 2342: PHW_DEVICE_EXTENSION HwDeviceExtension ! 2343: ) ! 2344: ! 2345: /*++ ! 2346: ! 2347: Routine Description: ! 2348: ! 2349: This routine detects the presence of a 928 and a Bt485 and if both are ! 2350: found it makes sure the DAC is resets all the command registers, to make ! 2351: sure the DAC will function in the VGA mode. ! 2352: ! 2353: Arguments: ! 2354: ! 2355: HwDeviceExtension - Supplies a pointer to the miniport's device extension. ! 2356: ! 2357: Return Value: ! 2358: ! 2359: TRUE - ! 2360: FALSE - ! 2361: ! 2362: --*/ ! 2363: { ! 2364: UCHAR OriginalReg55, Reg55; ! 2365: UCHAR reg38, reg39; ! 2366: ! 2367: // ! 2368: // This routine assumes we are dealing with an S3. ! 2369: // Make sure the registers are unlocked. ! 2370: // ! 2371: ! 2372: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x38); ! 2373: reg38 = VideoPortReadPortUchar(CRT_DATA_REG); ! 2374: ! 2375: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x39); ! 2376: reg39 = VideoPortReadPortUchar(CRT_DATA_REG); ! 2377: ! 2378: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x4838); ! 2379: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0xA039); ! 2380: ! 2381: // ! 2382: // First make sure this is a 928. ! 2383: // ! 2384: ! 2385: if (HwDeviceExtension->ChipID != S3_928) { ! 2386: ! 2387: return FALSE; ! 2388: ! 2389: } ! 2390: ! 2391: // ! 2392: // It's a 928 so now we have to make sure this is Bt485 ! 2393: // ! 2394: ! 2395: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x55); ! 2396: OriginalReg55 = VideoPortReadPortUchar(CRT_DATA_REG); ! 2397: OriginalReg55 &= ~0x03; ! 2398: ! 2399: // ! 2400: // BUGBUG ! 2401: // The ID for the BT485 did not work on all DACs so I'll switch off the ! 2402: // resolution. ! 2403: // This ID changed between the prototype chips and the release component, ! 2404: // at the time of this release there are too many prototype chips in the ! 2405: // field to rely on this ID. ! 2406: // ! 2407: ! 2408: if (S3Modes[HwDeviceExtension->ModeNumber].ModeInformation.VisScreenWidth ! 2409: != 1280) { ! 2410: ! 2411: return FALSE; ! 2412: ! 2413: } ! 2414: ! 2415: // ! 2416: // We know the board uses a Bt485 DAC. ! 2417: // ! 2418: ! 2419: // ! 2420: // Zero out Command register 3. ! 2421: // ! 2422: ! 2423: Reg55 = OriginalReg55 | 0x01; ! 2424: VideoPortWritePortUchar(CRT_DATA_REG, Reg55); ! 2425: VideoPortWritePortUchar((PUCHAR) 0x3C6, 0x80); ! 2426: ! 2427: Reg55 = OriginalReg55; ! 2428: VideoPortWritePortUchar(CRT_DATA_REG, Reg55); ! 2429: VideoPortWritePortUchar((PUCHAR) 0x3C8, 0x01); ! 2430: ! 2431: Reg55 = OriginalReg55 | 0x02; ! 2432: VideoPortWritePortUchar(CRT_DATA_REG, Reg55); ! 2433: VideoPortWritePortUchar((PUCHAR) 0x3C6, 0x00); ! 2434: ! 2435: // ! 2436: // Now zero out command register 2, 1, & 0 ! 2437: // ! 2438: ! 2439: VideoPortWritePortUchar((PUCHAR) 0x3C9, 0x00); ! 2440: VideoPortWritePortUchar((PUCHAR) 0x3C8, 0x00); ! 2441: ! 2442: Reg55 = OriginalReg55 | 0x01; ! 2443: VideoPortWritePortUchar(CRT_DATA_REG, Reg55); ! 2444: VideoPortWritePortUchar((PUCHAR) 0x3C6, 0x00); ! 2445: ! 2446: // ! 2447: // Now set the extended DAC control back to it's original val. ! 2448: // ! 2449: ! 2450: VideoPortWritePortUchar(CRT_DATA_REG, OriginalReg55); ! 2451: ! 2452: // ! 2453: // Were done mucking about with the S3 chip, so lock all the registers. ! 2454: // ! 2455: ! 2456: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg38 << 8) | 0x38)); ! 2457: VideoPortWritePortUshort(CRT_ADDRESS_REG, (USHORT)(((USHORT) reg39 << 8) | 0x39)); ! 2458: ! 2459: return TRUE; ! 2460: ! 2461: } ! 2462: ! 2463: #ifndef i386 ! 2464: ! 2465: ! 2466: VOID ! 2467: ZeroMemAndDac( ! 2468: PHW_DEVICE_EXTENSION HwDeviceExtension ! 2469: ) ! 2470: ! 2471: /*++ ! 2472: ! 2473: Routine Description: ! 2474: ! 2475: Initialize the DAC to 0 (black). ! 2476: ! 2477: Arguments: ! 2478: ! 2479: HwDeviceExtension - Supplies a pointer to the miniport's device extension. ! 2480: ! 2481: Return Value: ! 2482: ! 2483: None ! 2484: ! 2485: --*/ ! 2486: ! 2487: { ! 2488: ULONG i; ! 2489: USHORT Cmd; ! 2490: ! 2491: // ! 2492: // Turn off the screen at the DAC. ! 2493: // ! 2494: ! 2495: VideoPortWritePortUchar(DAC_PIXEL_MASK_REG, 0x0); ! 2496: ! 2497: for (i = 0; i < 256; i++) { ! 2498: ! 2499: VideoPortWritePortUchar(DAC_ADDRESS_WRITE_PORT, (UCHAR)i); ! 2500: VideoPortWritePortUchar(DAC_DATA_REG_PORT, 0x0); ! 2501: VideoPortWritePortUchar(DAC_DATA_REG_PORT, 0x0); ! 2502: VideoPortWritePortUchar(DAC_DATA_REG_PORT, 0x0); ! 2503: ! 2504: } ! 2505: ! 2506: // ! 2507: // Zero the memory. ! 2508: // ! 2509: // First open up the clipping. ! 2510: // ! 2511: ! 2512: FIFOWAIT(FIFO_4_EMPTY); ! 2513: ! 2514: VideoPortWritePortUshort (MULTIFUNC_CNTL, (CLIP_TOP | 0)); ! 2515: VideoPortWritePortUshort (MULTIFUNC_CNTL, (CLIP_LEFT | 0)); ! 2516: VideoPortWritePortUshort (MULTIFUNC_CNTL, (CLIP_BOTTOM | S3BM_HEIGHT)); ! 2517: VideoPortWritePortUshort (MULTIFUNC_CNTL, (CLIP_RIGHT | S3BM_WIDTH)); ! 2518: ! 2519: // ! 2520: // Now do the blit. ! 2521: // ! 2522: // Zero out coprocessor memory for the masks, color data, ! 2523: // and the save area. ! 2524: // ! 2525: ! 2526: Cmd = RECTANGLE_FILL | ! 2527: DRAW | DRAWING_DIR_TBLRXM | DIR_TYPE_XY | ! 2528: LAST_PIXEL_ON | SINGLE_PIXEL | WRITE; ! 2529: ! 2530: FIFOWAIT(FIFO_3_EMPTY); ! 2531: ! 2532: VideoPortWritePortUshort(FRGD_MIX, LOGICAL_0); ! 2533: VideoPortWritePortUshort(WRT_MASK, 0xff); ! 2534: VideoPortWritePortUshort(MULTIFUNC_CNTL, (DATA_EXTENSION | ALL_ONES)); ! 2535: ! 2536: FIFOWAIT(FIFO_5_EMPTY); ! 2537: ! 2538: VideoPortWritePortUshort(CUR_X, 0); ! 2539: VideoPortWritePortUshort(CUR_Y, 0); ! 2540: VideoPortWritePortUshort(RECT_WIDTH, S3BM_WIDTH - 1); ! 2541: VideoPortWritePortUshort(MULTIFUNC_CNTL, (RECT_HEIGHT | S3BM_HEIGHT - 1)); ! 2542: VideoPortWritePortUshort(CMD, Cmd); ! 2543: ! 2544: // ! 2545: // Turn on the screen at the DAC ! 2546: // ! 2547: ! 2548: VideoPortWritePortUchar(DAC_PIXEL_MASK_REG, 0x0ff); ! 2549: ! 2550: return; ! 2551: ! 2552: } ! 2553: ! 2554: VP_STATUS ! 2555: Set_Oem_Clock( ! 2556: PHW_DEVICE_EXTENSION HwDeviceExtension ! 2557: ) ! 2558: ! 2559: /*++ ! 2560: ! 2561: Routine Description: ! 2562: ! 2563: Set the clock chip on each of the supported cards. ! 2564: ! 2565: Arguments: ! 2566: ! 2567: HwDeviceExtension - Pointer to the miniport driver's device extension. ! 2568: ! 2569: Return Value: ! 2570: ! 2571: Always TRUE ! 2572: ! 2573: --*/ ! 2574: ! 2575: { ! 2576: ULONG ul; ! 2577: ULONG clock_numbers; ! 2578: ! 2579: switch(HwDeviceExtension->BoardID) { ! 2580: ! 2581: case S3_NUMBER_NINE: ! 2582: ! 2583: VideoPortStallExecution(1000); ! 2584: ! 2585: // Jerry said to make the M clock not multiple of the P clock ! 2586: // on the 3 meg (level 12) board. This solves the shimmy ! 2587: // problem. ! 2588: ! 2589: if (HwDeviceExtension->AdapterMemorySize == 0x00300000) { ! 2590: ! 2591: ul = 49000000; ! 2592: clock_numbers = calc_clock(ul, 3); ! 2593: set_clock(HwDeviceExtension, clock_numbers); ! 2594: VideoPortStallExecution(3000); ! 2595: ! 2596: } ! 2597: ! 2598: ul = aulNumberNineClk[HwDeviceExtension->ModeNumber]; ! 2599: clock_numbers = calc_clock(ul, 2); ! 2600: set_clock(HwDeviceExtension, clock_numbers); ! 2601: ! 2602: VideoPortStallExecution(3000); ! 2603: ! 2604: break; ! 2605: ! 2606: case S3_ORCHID: ! 2607: ! 2608: // ! 2609: // Only the 911 Orchid board needs specific init parameters. ! 2610: // Otherwise, fall through the generic function. ! 2611: // ! 2612: ! 2613: if (HwDeviceExtension->ChipID == S3_911) { ! 2614: ! 2615: ul = aulOrchidClk[HwDeviceExtension->ModeNumber]; ! 2616: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x42); ! 2617: VideoPortWritePortUchar(CRT_DATA_REG, (UCHAR) ul); ! 2618: ! 2619: break; ! 2620: ! 2621: } ! 2622: ! 2623: // ! 2624: // Genric S3 board. ! 2625: // ! 2626: ! 2627: case S3_GENERIC: ! 2628: default: ! 2629: ! 2630: ul = aulGenericClk[HwDeviceExtension->ModeNumber]; ! 2631: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x42); ! 2632: VideoPortWritePortUchar(CRT_DATA_REG, (UCHAR) ul); ! 2633: break; ! 2634: ! 2635: } ! 2636: ! 2637: return TRUE; ! 2638: } ! 2639: ! 2640: ! 2641: VP_STATUS ! 2642: Wait_VSync( ! 2643: PHW_DEVICE_EXTENSION HwDeviceExtension ! 2644: ) ! 2645: ! 2646: /*++ ! 2647: ! 2648: Routine Description: ! 2649: ! 2650: Wait for the vertical blanking interval on the chip ! 2651: ! 2652: Arguments: ! 2653: ! 2654: HwDeviceExtension - Supplies a pointer to the miniport's device extension. ! 2655: ! 2656: Return Value: ! 2657: ! 2658: Always TRUE ! 2659: ! 2660: --*/ ! 2661: ! 2662: { ! 2663: ! 2664: ULONG i; ! 2665: UCHAR byte; ! 2666: ! 2667: // It's real possible that this routine will get called ! 2668: // when the 911 is in a zombie state, meaning there is no ! 2669: // vertical sync being generated. This is why we have some long ! 2670: // time out loops here. ! 2671: // !!! What is the correct NT way to do this type of time out? ! 2672: ! 2673: // First wait for getting into vertical blanking. ! 2674: ! 2675: for (i = 0; i < 0x100000; i++) { ! 2676: ! 2677: byte = VideoPortReadPortUchar(SYSTEM_CONTROL_REG); ! 2678: if (byte & 0x08) ! 2679: break; ! 2680: ! 2681: } ! 2682: ! 2683: // ! 2684: // We are either in a vertical blaning interval or we have timmed out. ! 2685: // Wait for the Vertical display interval. ! 2686: // This is done to make sure we exit this routine at the beginning ! 2687: // of a vertical blanking interval, and not in the middle or near ! 2688: // the end of one. ! 2689: // ! 2690: ! 2691: for (i = 0; i < 0x100000; i++) { ! 2692: ! 2693: byte = VideoPortReadPortUchar(SYSTEM_CONTROL_REG); ! 2694: if (!(byte & 0x08)) ! 2695: break; ! 2696: ! 2697: } ! 2698: ! 2699: // ! 2700: // Now wait to get into the vertical blank interval again. ! 2701: // ! 2702: ! 2703: for (i = 0; i < 0x100000; i++) { ! 2704: ! 2705: byte = VideoPortReadPortUchar(SYSTEM_CONTROL_REG); ! 2706: if (byte & 0x08) ! 2707: break; ! 2708: ! 2709: } ! 2710: ! 2711: return (TRUE); ! 2712: ! 2713: } ! 2714: ! 2715: BOOLEAN ! 2716: Bus_Test( ! 2717: PHW_DEVICE_EXTENSION HwDeviceExtension ! 2718: ) ! 2719: ! 2720: /*++ ! 2721: ! 2722: Routine Description: ! 2723: ! 2724: Test the bus to determine in the ISA address latch needs to be ! 2725: enabled. ! 2726: ! 2727: Arguments: ! 2728: ! 2729: HwDeviceExtension - Supplies a pointer to the miniport's device extension. ! 2730: ! 2731: Return Value: ! 2732: ! 2733: TRUE - need to Enable the ISA Address Latch. ! 2734: And it is enabled when we return. ! 2735: ! 2736: FALSE - do not enable the ISA Address Latch. ! 2737: And it's disabled when we return. ! 2738: ! 2739: NOTE: The test #9 gave me; to set the ISA Address Latch, ! 2740: then do the test failed on a DELL 50Mhz machine ! 2741: Now, we'll try resetting the ISA Address Latch. ! 2742: The reset of the latch bit passed on the DELL, but failed on ! 2743: the OPTI chip set. Now I'll change the test to writting ! 2744: a pattern to the entire Video Memory and try to read it back, ! 2745: with a default state of the ISA latch bit being reset. ! 2746: ! 2747: 3/26/93 ! 2748: ! 2749: This routine does not seem to necessary with the later versions of the BIOS. ! 2750: The new Number Nine BIOS seems to detect the need to set or reset the ISA address ! 2751: latch. AT this point I will leave it in to cover all the older #9 boards in ! 2752: the field. ! 2753: --*/ ! 2754: { ! 2755: ! 2756: ! 2757: UCHAR reg35, reg51, reg58, reg59, reg5a; ! 2758: UCHAR *pRamAddr; ! 2759: PHYSICAL_ADDRESS memoryAddress; ! 2760: ! 2761: volatile ULONG *pulRamAddr; ! 2762: ! 2763: LONG i; ! 2764: LONG iBank; ! 2765: LONG nBanks; ! 2766: ! 2767: ULONG ulTestPat; ! 2768: ! 2769: BOOLEAN bEnbLa; ! 2770: ! 2771: // ! 2772: // Note: this routine assumes the S3 registers are unlocked ! 2773: // when it is called. ! 2774: // ! 2775: // Map in 64K of VRAM address space at 0xA000:0 ! 2776: // ! 2777: ! 2778: memoryAddress.HighPart = 0; ! 2779: memoryAddress.LowPart = 0xA0000; ! 2780: ! 2781: pRamAddr = VideoPortGetDeviceBase(HwDeviceExtension, ! 2782: memoryAddress, ! 2783: 0x10000, ! 2784: 0); ! 2785: ! 2786: // ! 2787: // Wait for the GP to be idle ! 2788: // ! 2789: ! 2790: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x40); ! 2791: ! 2792: if (VideoPortReadPortUchar(CRT_DATA_REG) & 0x1) { ! 2793: ! 2794: while (VideoPortReadPortUshort(GP_STAT) & 0x0200); ! 2795: ! 2796: } ! 2797: ! 2798: // ! 2799: // Get the original values for all the registers. ! 2800: // So we can restore them before we leave the driver. ! 2801: // ! 2802: ! 2803: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x35); ! 2804: reg35 = VideoPortReadPortUchar(CRT_DATA_REG) & 0xF0; ! 2805: ! 2806: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x51); ! 2807: reg51 = VideoPortReadPortUchar(CRT_DATA_REG) & ~0x0C; ! 2808: ! 2809: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x58); ! 2810: reg58 = VideoPortReadPortUchar(CRT_DATA_REG); ! 2811: ! 2812: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x59); ! 2813: reg59 = VideoPortReadPortUchar(CRT_DATA_REG); ! 2814: ! 2815: VideoPortWritePortUchar(CRT_ADDRESS_REG, 0x5A); ! 2816: reg5a = VideoPortReadPortUchar(CRT_DATA_REG); ! 2817: ! 2818: // ! 2819: // Set the Linear Address Window to A0000. ! 2820: // ! 2821: ! 2822: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x0059); ! 2823: VideoPortWritePortUshort(CRT_ADDRESS_REG, 0x0a5a); ! 2824: ! 2825: // ! 2826: // Do the test for enabling the ISA address latch feature on the chip. ! 2827: // ! 2828: ! 2829: bEnbLa = FALSE; ! 2830: ! 2831: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)((((reg58 & ~0x08) | 0x10) << 8) | 0x58))); ! 2832: ! 2833: // ! 2834: // Write out the test pattern to the Video memory. ! 2835: // This is a dword write. ! 2836: // ! 2837: ! 2838: ulTestPat = 0x55AA6699; ! 2839: pulRamAddr= (ULONG *) pRamAddr; ! 2840: ! 2841: nBanks = HwDeviceExtension->AdapterMemorySize >> 16; ! 2842: ! 2843: for (iBank = 0; iBank < nBanks; iBank++) { ! 2844: ! 2845: // ! 2846: // Set the bank address. ! 2847: // ! 2848: ! 2849: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)((((reg51 | ((0x30 & iBank) << 6)) << 8) | 0x51)))); ! 2850: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)((((reg35 | (0x0F & iBank)) << 8) | 0x35)))); ! 2851: ! 2852: // ! 2853: // Write 64K of pattern. ! 2854: // ! 2855: ! 2856: for (i = 0; i < 0x1000; i++) { ! 2857: ! 2858: pulRamAddr[i] = ulTestPat; ! 2859: } ! 2860: ! 2861: } ! 2862: ! 2863: // ! 2864: // Write 64 of Zeros to the first bank, this should take care of bus ! 2865: // float. ! 2866: // ! 2867: ! 2868: iBank = 0; ! 2869: ! 2870: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)((((reg51 | ((0x30 & iBank) << 6)) << 8) | 0x51)))); ! 2871: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)((((reg35 | (0x0F & iBank)) << 8) | 0x35)))); ! 2872: ! 2873: // ! 2874: // Write 64K of 0. ! 2875: // ! 2876: ! 2877: for (i = 0; i < 0x1000; i++) { ! 2878: ! 2879: pulRamAddr[i] = 0; ! 2880: } ! 2881: ! 2882: // ! 2883: // Now read back the pattern. ! 2884: // If the data is different at any point then the ISA latch addr. ! 2885: // should be enabled. ! 2886: // ! 2887: ! 2888: for (iBank = 1; iBank < nBanks; iBank++) { ! 2889: ! 2890: // ! 2891: // Set the bank address. ! 2892: // ! 2893: ! 2894: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)((((reg51 | ((0x30 & iBank) << 6)) << 8) | 0x51)))); ! 2895: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)((((reg35 | (0x0F & iBank)) << 8) | 0x35)))); ! 2896: ! 2897: // ! 2898: // Set the address for the beginning of this bank. ! 2899: // ! 2900: ! 2901: pulRamAddr= (ULONG *) pRamAddr; ! 2902: ! 2903: for (i = 0; i < 0x1000; i++) { ! 2904: ! 2905: if (pulRamAddr[i] != ulTestPat) { ! 2906: ! 2907: bEnbLa = TRUE; ! 2908: break; ! 2909: ! 2910: } ! 2911: } ! 2912: ! 2913: if (bEnbLa == TRUE) { ! 2914: ! 2915: break; ! 2916: ! 2917: } ! 2918: } ! 2919: ! 2920: // ! 2921: // Set register 5A, this includes the ISA address latch. ! 2922: // ! 2923: ! 2924: if (bEnbLa == TRUE) { ! 2925: ! 2926: VideoPortWritePortUshort(CRT_ADDRESS_REG, ! 2927: ((USHORT)(((reg58 | 0x8) << 8) | 0x58))); ! 2928: ! 2929: } else { ! 2930: ! 2931: VideoPortWritePortUshort(CRT_ADDRESS_REG, ! 2932: ((USHORT)(((reg58 & ~0x8) << 8) | 0x58))); ! 2933: ! 2934: } ! 2935: ! 2936: // ! 2937: // Restore the registers we used to test memory. ! 2938: // ! 2939: ! 2940: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)(((USHORT) reg35 << 8) | 0x35))); ! 2941: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)(((USHORT) reg51 << 8) | 0x51))); ! 2942: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)(((USHORT) reg59 << 8) | 0x59))); ! 2943: VideoPortWritePortUshort(CRT_ADDRESS_REG, ((USHORT)(((USHORT) reg5a << 8) | 0x5A))); ! 2944: ! 2945: // ! 2946: // Free the memory mapping we used for the RAM access ! 2947: // ! 2948: ! 2949: VideoPortFreeDeviceBase(HwDeviceExtension, pRamAddr); ! 2950: ! 2951: // ! 2952: // return the results. ! 2953: // ! 2954: ! 2955: return bEnbLa; ! 2956: ! 2957: } ! 2958: ! 2959: #endif // i386
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.