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