Annotation of ntddk/src/video/miniport/s3/s3.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.