- Add new unified VGA/VBE miniport driver. Based on NT4 DDK Cirrus Miniport Driver...
[reactos.git] / reactos / drivers / video / miniport / vga_new / vga.c
1 /*
2 * PROJECT: ReactOS VGA Miniport Driver
3 * LICENSE: Microsoft NT4 DDK Sample Code License
4 * FILE: boot/drivers/video/miniport/vga/vga.c
5 * PURPOSE: Main Standard VGA-compatible Minport Handling Code
6 * PROGRAMMERS: Copyright (c) 1992 Microsoft Corporation
7 * ReactOS Portable Systems Group
8 */
9
10 //---------------------------------------------------------------------------
11
12 #include "vga.h"
13
14 //---------------------------------------------------------------------------
15 //
16 // Function declarations
17 //
18 // Functions that start with 'VGA' are entry points for the OS port driver.
19 //
20
21 VP_STATUS
22 VgaFindAdapter(
23 PVOID HwDeviceExtension,
24 PVOID HwContext,
25 PWSTR ArgumentString,
26 PVIDEO_PORT_CONFIG_INFO ConfigInfo,
27 PUCHAR Again
28 );
29
30 BOOLEAN
31 VgaInitialize(
32 PVOID HwDeviceExtension
33 );
34
35 BOOLEAN
36 VgaStartIO(
37 PVOID HwDeviceExtension,
38 PVIDEO_REQUEST_PACKET RequestPacket
39 );
40
41 //
42 // Private function prototypes.
43 //
44
45 VP_STATUS
46 VgaQueryAvailableModes(
47 PHW_DEVICE_EXTENSION HwDeviceExtension,
48 PVIDEO_MODE_INFORMATION ModeInformation,
49 ULONG ModeInformationSize,
50 PULONG OutputSize
51 );
52
53 VP_STATUS
54 VgaQueryNumberOfAvailableModes(
55 PHW_DEVICE_EXTENSION HwDeviceExtension,
56 PVIDEO_NUM_MODES NumModes,
57 ULONG NumModesSize,
58 PULONG OutputSize
59 );
60
61 VP_STATUS
62 VgaSetMode(
63 PHW_DEVICE_EXTENSION HwDeviceExtension,
64 PVIDEO_MODE Mode,
65 ULONG ModeSize,
66 // eVb: 1.1 [SET MODE] - Add new output parameter for framebuffer update functionality
67 PULONG PhysPtrChange
68 // eVb: 1.1 [END]
69 );
70
71 BOOLEAN
72 VgaIsPresent(
73 PHW_DEVICE_EXTENSION HwDeviceExtension
74 );
75
76 VOID
77 VgaInterpretCmdStream(
78 PVOID HwDeviceExtension,
79 PUSHORT pusCmdStream
80 );
81
82 VP_STATUS
83 VgaSetColorLookup(
84 PHW_DEVICE_EXTENSION HwDeviceExtension,
85 PVIDEO_CLUT ClutBuffer,
86 ULONG ClutBufferSize
87 );
88
89 VP_STATUS
90 GetDeviceDataCallback(
91 PVOID HwDeviceExtension,
92 PVOID Context,
93 VIDEO_DEVICE_DATA_TYPE DeviceDataType,
94 PVOID Identifier,
95 ULONG IdentifierLength,
96 PVOID ConfigurationData,
97 ULONG ConfigurationDataLength,
98 PVOID ComponentInformation,
99 ULONG ComponentInformationLength
100 );
101
102 // eVb: 1.2 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
103 VP_STATUS
104 VgaAcquireResources(
105 PHW_DEVICE_EXTENSION DeviceExtension
106 );
107 // eVb: 1.2 [END]
108
109 #if defined(ALLOC_PRAGMA)
110 #pragma alloc_text(PAGE,DriverEntry)
111 #pragma alloc_text(PAGE,VgaFindAdapter)
112 #pragma alloc_text(PAGE,VgaInitialize)
113 #pragma alloc_text(PAGE,VgaStartIO)
114 #pragma alloc_text(PAGE,VgaIsPresent)
115 #pragma alloc_text(PAGE,VgaSetColorLookup)
116 #endif
117
118 \f
119 //---------------------------------------------------------------------------
120 ULONG
121 // eVb: 1.3 [GCC] - Add NTAPI for GCC support
122 NTAPI
123 // eVb: 1.3 [END]
124 DriverEntry(
125 PVOID Context1,
126 PVOID Context2
127 )
128
129 /*++
130
131 Routine Description:
132
133 Installable driver initialization entry point.
134 This entry point is called directly by the I/O system.
135
136 Arguments:
137
138 Context1 - First context value passed by the operating system. This is
139 the value with which the miniport driver calls VideoPortInitialize().
140
141 Context2 - Second context value passed by the operating system. This is
142 the value with which the miniport driver calls 3VideoPortInitialize().
143
144 Return Value:
145
146 Status from VideoPortInitialize()
147
148 --*/
149
150 {
151
152 VIDEO_HW_INITIALIZATION_DATA hwInitData;
153 ULONG status;
154 ULONG initializationStatus = (ULONG) -1;
155
156 //
157 // Zero out structure.
158 //
159
160 VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
161
162 //
163 // Specify sizes of structure and extension.
164 //
165
166 hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
167
168 //
169 // Set entry points.
170 //
171
172 hwInitData.HwFindAdapter = VgaFindAdapter;
173 hwInitData.HwInitialize = VgaInitialize;
174 hwInitData.HwInterrupt = NULL;
175 hwInitData.HwStartIO = VgaStartIO;
176
177 //
178 // Determine the size we require for the device extension.
179 //
180
181 hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
182
183 //
184 // Always start with parameters for device0 in this case.
185 // We can leave it like this since we know we will only ever find one
186 // VGA type adapter in a machine.
187 //
188
189 // hwInitData.StartingDeviceNumber = 0;
190
191 //
192 // Once all the relevant information has been stored, call the video
193 // port driver to do the initialization.
194 // For this device we will repeat this call three times, for ISA, EISA
195 // and PCI.
196 // We will return the minimum of all return values.
197 //
198
199 //
200 // We will try the PCI bus first so that our ISA detection does'nt claim
201 // PCI cards (since it is impossible to differentiate between the two
202 // by looking at the registers).
203 //
204
205 //
206 // NOTE: since this driver only supports one adapter, we will return
207 // as soon as we find a device, without going on to the following buses.
208 // Normally one would call for each bus type and return the smallest
209 // value.
210 //
211
212 #if !defined(_ALPHA_)
213
214 //
215 // Before we can enable this on ALPHA we need to find a way to map a
216 // sparse view of a 4MB region successfully.
217 //
218
219 hwInitData.AdapterInterfaceType = PCIBus;
220
221 initializationStatus = VideoPortInitialize(Context1,
222 Context2,
223 &hwInitData,
224 NULL);
225
226 if (initializationStatus == NO_ERROR)
227 {
228 return initializationStatus;
229 }
230
231 #endif
232
233 hwInitData.AdapterInterfaceType = MicroChannel;
234
235 initializationStatus = VideoPortInitialize(Context1,
236 Context2,
237 &hwInitData,
238 NULL);
239
240 //
241 // Return immediately instead of checkin for smallest return code.
242 //
243
244 if (initializationStatus == NO_ERROR)
245 {
246 return initializationStatus;
247 }
248
249
250 hwInitData.AdapterInterfaceType = Internal;
251
252 initializationStatus = VideoPortInitialize(Context1,
253 Context2,
254 &hwInitData,
255 NULL);
256
257 if (initializationStatus == NO_ERROR)
258 {
259 return initializationStatus;
260 }
261
262
263 hwInitData.AdapterInterfaceType = Isa;
264
265 initializationStatus = VideoPortInitialize(Context1,
266 Context2,
267 &hwInitData,
268 NULL);
269
270 if (initializationStatus == NO_ERROR)
271 {
272 return initializationStatus;
273 }
274
275
276
277 hwInitData.AdapterInterfaceType = Eisa;
278
279 status = VideoPortInitialize(Context1,
280 Context2,
281 &hwInitData,
282 NULL);
283
284 if (initializationStatus > status) {
285 initializationStatus = status;
286 }
287
288 return initializationStatus;
289
290 } // end DriverEntry()
291 \f
292 //---------------------------------------------------------------------------
293 VP_STATUS
294 VgaFindAdapter(
295 PVOID HwDeviceExtension,
296 PVOID HwContext,
297 PWSTR ArgumentString,
298 PVIDEO_PORT_CONFIG_INFO ConfigInfo,
299 PUCHAR Again
300 )
301
302 /*++
303
304 Routine Description:
305
306 This routine is called to determine if the adapter for this driver
307 is present in the system.
308 If it is present, the function fills out some information describing
309 the adapter.
310
311 Arguments:
312
313 HwDeviceExtension - Supplies the miniport driver's adapter storage. This
314 storage is initialized to zero before this call.
315
316 HwContext - Supplies the context value which was passed to
317 VideoPortInitialize().
318
319 ArgumentString - Supplies a NULL terminated ASCII string. This string
320 originates from the user.
321
322 ConfigInfo - Returns the configuration information structure which is
323 filled by the miniport driver. This structure is initialized with
324 any known configuration information (such as SystemIoBusNumber) by
325 the port driver. Where possible, drivers should have one set of
326 defaults which do not require any supplied configuration information.
327
328 Again - Indicates if the miniport driver wants the port driver to call
329 its VIDEO_HW_FIND_ADAPTER function again with a new device extension
330 and the same config info. This is used by the miniport drivers which
331 can search for several adapters on a bus.
332
333 Return Value:
334
335 This routine must return:
336
337 NO_ERROR - Indicates a host adapter was found and the
338 configuration information was successfully determined.
339
340 ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
341 error obtaining the configuration information. If possible an error
342 should be logged.
343
344 ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
345 supplied configuration information.
346
347 --*/
348
349 {
350
351 PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
352
353 //
354 // Make sure the size of the structure is at least as large as what we
355 // are expecting (check version of the config info structure).
356 //
357
358 if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) {
359
360 return ERROR_INVALID_PARAMETER;
361
362 }
363 // eVb: 1.4 [CIRRUS] - Remove CIRRUS-specific support
364 //
365 // Check internal VGA (MIPS and ARM systems)
366 //
367
368 if ((ConfigInfo->AdapterInterfaceType == Internal) &&
369 (VideoPortGetDeviceData(HwDeviceExtension,
370 VpControllerData,
371 &GetDeviceDataCallback,
372 VgaAccessRange) != NO_ERROR))
373 {
374 return ERROR_INVALID_PARAMETER;
375 }
376 // eVb: 1.4 [END]
377 //
378 // No interrupt information is necessary.
379 //
380
381 //
382 // Check to see if there is a hardware resource conflict.
383 //
384 // eVb: 1.5 [RESOURCE] - Use new function for acquiring VGA resources (I/O, memory)
385 if (VgaAcquireResources(hwDeviceExtension) != NO_ERROR) return ERROR_INVALID_PARAMETER;
386 // eVb: 1.5 [END]
387 //
388 // Get logical IO port addresses.
389 //
390
391 if ((hwDeviceExtension->IOAddress =
392 VideoPortGetDeviceBase(hwDeviceExtension,
393 VgaAccessRange->RangeStart,
394 VGA_MAX_IO_PORT - VGA_BASE_IO_PORT + 1,
395 VgaAccessRange->RangeInIoSpace)) == NULL)
396 {
397 VideoDebugPrint((2, "VgaFindAdapter - Fail to get io address\n"));
398
399 return ERROR_INVALID_PARAMETER;
400 }
401
402 //
403 // Determine whether a VGA is present.
404 //
405
406 if (!VgaIsPresent(hwDeviceExtension)) {
407
408 VideoDebugPrint((0, "VgaFindAdapter - VGA Failed\n"));
409 return ERROR_DEV_NOT_EXIST;
410 }
411
412 //
413 // Minimum size of the buffer required to store the hardware state
414 // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
415 //
416
417 ConfigInfo->HardwareStateSize = VGA_TOTAL_STATE_SIZE;
418
419 //
420 // Pass a pointer to the emulator range we are using.
421 //
422 // eVb: 1.6 [VDM] - Disable VDM for now
423 ConfigInfo->NumEmulatorAccessEntries = 0;
424 ConfigInfo->EmulatorAccessEntries = NULL;
425 ConfigInfo->EmulatorAccessEntriesContext = 0;
426 // eVb: 1.6 [END]
427 //
428 // BUGBUG
429 //
430 // There is really no reason to have the frame buffer mapped. On an
431 // x86 we use if for save/restore (supposedly) but even then we
432 // would only need to map a 64K window, not all 16 Meg!
433 //
434
435 #ifdef _X86_
436
437 //
438 // Map the video memory into the system virtual address space so we can
439 // clear it out and use it for save and restore.
440 //
441
442 if ( (hwDeviceExtension->VideoMemoryAddress =
443 VideoPortGetDeviceBase(hwDeviceExtension,
444 VgaAccessRange[2].RangeStart,
445 VgaAccessRange[2].RangeLength,
446 FALSE)) == NULL)
447 {
448 VideoDebugPrint((1, "VgaFindAdapter - Fail to get memory address\n"));
449
450 return ERROR_INVALID_PARAMETER;
451 }
452
453 VideoPortDebugPrint(0, "vga mapped at %x\n", hwDeviceExtension->VideoMemoryAddress);
454 #endif
455 // eVb: 1.7 [VDM] - Disable VDM for now
456 ConfigInfo->VdmPhysicalVideoMemoryAddress.QuadPart = 0;
457 ConfigInfo->VdmPhysicalVideoMemoryLength = 0;
458 // eVb: 1.7 [END]
459 //
460 // Indicate we do not wish to be called again for another initialization.
461 //
462
463 *Again = 0;
464
465 //
466 // Indicate a successful completion status.
467 //
468
469 return NO_ERROR;
470
471
472 } // VgaFindAdapter()
473 \f
474 //---------------------------------------------------------------------------
475 BOOLEAN
476 VgaInitialize(
477 PVOID HwDeviceExtension
478 )
479
480 /*++
481
482 Routine Description:
483
484 This routine does one time initialization of the device.
485
486 Arguments:
487
488 HwDeviceExtension - Pointer to the miniport driver's adapter information.
489
490 Return Value:
491
492 None.
493
494 --*/
495
496 {
497 PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
498
499 //
500 // set up the default cursor position and type.
501 //
502
503 hwDeviceExtension->CursorPosition.Column = 0;
504 hwDeviceExtension->CursorPosition.Row = 0;
505 hwDeviceExtension->CursorTopScanLine = 0;
506 hwDeviceExtension->CursorBottomScanLine = 31;
507 hwDeviceExtension->CursorEnable = TRUE;
508
509 // eVb: 1.8 [VBE] - Initialize VBE modes
510 InitializeModeTable(hwDeviceExtension);
511 // eVb: 1.8 [END]
512 return TRUE;
513
514 } // VgaInitialize()
515 \f
516 //---------------------------------------------------------------------------
517 BOOLEAN
518 VgaStartIO(
519 PVOID HwDeviceExtension,
520 PVIDEO_REQUEST_PACKET RequestPacket
521 )
522
523 /*++
524
525 Routine Description:
526
527 This routine is the main execution routine for the miniport driver. It
528 accepts a Video Request Packet, performs the request, and then returns
529 with the appropriate status.
530
531 Arguments:
532
533 HwDeviceExtension - Pointer to the miniport driver's adapter information.
534
535 RequestPacket - Pointer to the video request packet. This structure
536 contains all the parameters passed to the VideoIoControl function.
537
538 Return Value:
539
540 This routine will return error codes from the various support routines
541 and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
542 buffers and ERROR_INVALID_FUNCTION for unsupported functions.
543
544 --*/
545
546 {
547 PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
548 VP_STATUS status;
549 VIDEO_MODE videoMode;
550 PVIDEO_MEMORY_INFORMATION memoryInformation;
551 ULONG inIoSpace;
552 ULONG Result;
553
554 //
555 // Switch on the IoContolCode in the RequestPacket. It indicates which
556 // function must be performed by the driver.
557 //
558 // eVb: 1.9 [IOCTL] - Remove IOCTLs not needed yet
559 switch (RequestPacket->IoControlCode)
560 {
561 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
562
563 VideoDebugPrint((2, "VgaStartIO - ShareVideoMemory\n"));
564
565 status = ERROR_INVALID_FUNCTION;
566
567 break;
568
569 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
570
571 VideoDebugPrint((2, "VgaStartIO - UnshareVideoMemory\n"));
572
573 status = ERROR_INVALID_FUNCTION;
574
575 break;
576
577
578 case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
579
580 VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n"));
581
582 if ( (RequestPacket->OutputBufferLength <
583 (RequestPacket->StatusBlock->Information =
584 sizeof(VIDEO_MEMORY_INFORMATION))) ||
585 (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) )
586 {
587 status = ERROR_INSUFFICIENT_BUFFER;
588 }
589
590 memoryInformation = RequestPacket->OutputBuffer;
591
592 memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
593 (RequestPacket->InputBuffer))->RequestedVirtualAddress;
594
595 //
596 // We reserved 16 meg for the frame buffer, however, it makes
597 // no sense to map more memory than there is on the card. So
598 // only map the amount of memory we have on the card.
599 //
600 // eVb: 1.10 [CIRRUS] - On VGA, we have VRAM size since boot, use it
601 memoryInformation->VideoRamLength =
602 hwDeviceExtension->PhysicalVideoMemoryLength;
603 // eVb: 1.10 [END]
604 //
605 // If you change to using a dense space frame buffer, make this
606 // value a 4 for the ALPHA.
607 //
608
609 inIoSpace = 0;
610
611 status = VideoPortMapMemory(hwDeviceExtension,
612 hwDeviceExtension->PhysicalVideoMemoryBase,
613 // eVb: 1.11 [CIRRUS] - On VGA, we have VRAM size since boot, use it
614 &memoryInformation->VideoRamLength,
615 // eVb: 1.11 [END]
616 &inIoSpace,
617 &(memoryInformation->VideoRamBase));
618
619 if (status != NO_ERROR) {
620 VideoDebugPrint((0, "VgaStartIO - IOCTL_VIDEO_MAP_VIDEO_MEMORY failed VideoPortMapMemory (%x)\n", status));
621 }
622
623 memoryInformation->FrameBufferBase =
624 ((PUCHAR) (memoryInformation->VideoRamBase)) +
625 hwDeviceExtension->PhysicalFrameOffset.LowPart;
626
627 memoryInformation->FrameBufferLength =
628 hwDeviceExtension->PhysicalFrameLength ?
629 hwDeviceExtension->PhysicalFrameLength :
630 memoryInformation->VideoRamLength;
631
632
633 VideoDebugPrint((2, "physical VideoMemoryBase %08lx\n", hwDeviceExtension->PhysicalVideoMemoryBase));
634 VideoDebugPrint((2, "physical VideoMemoryLength %08lx\n", hwDeviceExtension->PhysicalVideoMemoryLength));
635 VideoDebugPrint((2, "VideoMemoryBase %08lx\n", memoryInformation->VideoRamBase));
636 VideoDebugPrint((2, "VideoMemoryLength %08lx\n", memoryInformation->VideoRamLength));
637
638 VideoDebugPrint((2, "physical framebuf offset %08lx\n", hwDeviceExtension->PhysicalFrameOffset.LowPart));
639 VideoDebugPrint((2, "framebuf base %08lx\n", memoryInformation->FrameBufferBase));
640 VideoDebugPrint((2, "physical framebuf len %08lx\n", hwDeviceExtension->PhysicalFrameLength));
641 VideoDebugPrint((2, "framebuf length %08lx\n", memoryInformation->FrameBufferLength));
642
643 break;
644
645 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
646
647 VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
648
649 status = ERROR_INVALID_FUNCTION;
650
651 break;
652
653
654 case IOCTL_VIDEO_QUERY_AVAIL_MODES:
655
656 VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
657
658 status = VgaQueryAvailableModes(HwDeviceExtension,
659 (PVIDEO_MODE_INFORMATION)
660 RequestPacket->OutputBuffer,
661 RequestPacket->OutputBufferLength,
662 &RequestPacket->StatusBlock->Information);
663
664 break;
665
666
667 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
668
669 VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
670
671 status = VgaQueryNumberOfAvailableModes(HwDeviceExtension,
672 (PVIDEO_NUM_MODES)
673 RequestPacket->OutputBuffer,
674 RequestPacket->OutputBufferLength,
675 &RequestPacket->StatusBlock->Information);
676
677 break;
678
679
680 case IOCTL_VIDEO_QUERY_CURRENT_MODE:
681
682 VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
683
684 status = ERROR_INVALID_FUNCTION;
685
686 break;
687
688
689 case IOCTL_VIDEO_SET_CURRENT_MODE:
690
691 VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
692
693 status = VgaSetMode(HwDeviceExtension,
694 (PVIDEO_MODE) RequestPacket->InputBuffer,
695 RequestPacket->InputBufferLength,
696 // eVb: 1.12 [SET MODE] - Use new output parameter for framebuffer update functionality
697 &Result);
698 // eVb: 1.12 [END]
699
700 break;
701
702
703 case IOCTL_VIDEO_RESET_DEVICE:
704
705 VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
706
707 videoMode.RequestedMode = 0;
708
709 VgaSetMode(HwDeviceExtension,
710 (PVIDEO_MODE) &videoMode,
711 sizeof(videoMode),
712 // eVb: 1.13 [SET MODE] - Use new output parameter for framebuffer update functionality
713 &Result);
714 // eVb: 1.13 [END]
715
716 //
717 // Always return succcess since settings the text mode will fail on
718 // non-x86.
719 //
720 // Also, failiure to set the text mode is not fatal in any way, since
721 // this operation must be followed by another set mode operation.
722 //
723
724 status = NO_ERROR;
725
726 break;
727
728
729 case IOCTL_VIDEO_LOAD_AND_SET_FONT:
730
731 VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
732
733 status = ERROR_INVALID_FUNCTION;
734
735 break;
736
737
738 case IOCTL_VIDEO_QUERY_CURSOR_POSITION:
739
740 VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
741
742 status = ERROR_INVALID_FUNCTION;
743
744 break;
745
746
747 case IOCTL_VIDEO_SET_CURSOR_POSITION:
748
749 VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
750
751 status = ERROR_INVALID_FUNCTION;
752
753 break;
754
755
756 case IOCTL_VIDEO_QUERY_CURSOR_ATTR:
757
758 VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
759
760 status = ERROR_INVALID_FUNCTION;
761
762 break;
763
764
765 case IOCTL_VIDEO_SET_CURSOR_ATTR:
766
767 VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
768
769 status = ERROR_INVALID_FUNCTION;
770
771 break;
772
773
774 case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
775
776 VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
777
778 status = ERROR_INVALID_FUNCTION;
779
780 break;
781
782
783 case IOCTL_VIDEO_SET_COLOR_REGISTERS:
784
785 VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
786
787 status = VgaSetColorLookup(HwDeviceExtension,
788 (PVIDEO_CLUT) RequestPacket->InputBuffer,
789 RequestPacket->InputBufferLength);
790
791 break;
792
793
794 case IOCTL_VIDEO_ENABLE_VDM:
795
796 VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
797
798 status = ERROR_INVALID_FUNCTION;
799
800 break;
801
802
803 case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
804
805 VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
806
807 status = ERROR_INVALID_FUNCTION;
808
809 break;
810
811
812 case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
813
814 VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
815
816 status = ERROR_INVALID_FUNCTION;
817
818 break;
819
820 case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
821
822 VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
823
824 status = ERROR_INVALID_FUNCTION;
825 break;
826
827 case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
828 case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
829
830 //
831 // if we get here, an invalid IoControlCode was specified.
832 //
833
834 default:
835
836 VideoDebugPrint((0, "Fell through vga startIO routine - invalid command\n"));
837
838 status = ERROR_INVALID_FUNCTION;
839
840 break;
841
842 }
843 // eVb: 1.9 [END]
844 RequestPacket->StatusBlock->Status = status;
845
846 return TRUE;
847
848 } // VgaStartIO()
849
850 \f
851 //---------------------------------------------------------------------------
852 //
853 // private routines
854 //
855
856 \f
857 //---------------------------------------------------------------------------
858 BOOLEAN
859 VgaIsPresent(
860 PHW_DEVICE_EXTENSION HwDeviceExtension
861 )
862
863 /*++
864
865 Routine Description:
866
867 This routine returns TRUE if a VGA is present. Determining whether a VGA
868 is present is a two-step process. First, this routine walks bits through
869 the Bit Mask register, to establish that there are readable indexed
870 registers (EGAs normally don't have readable registers, and other adapters
871 are unlikely to have indexed registers). This test is done first because
872 it's a non-destructive EGA rejection test (correctly rejects EGAs, but
873 doesn't potentially mess up the screen or the accessibility of display
874 memory). Normally, this would be an adequate test, but some EGAs have
875 readable registers, so next, we check for the existence of the Chain4 bit
876 in the Memory Mode register; this bit doesn't exist in EGAs. It's
877 conceivable that there are EGAs with readable registers and a register bit
878 where Chain4 is stored, although I don't know of any; if a better test yet
879 is needed, memory could be written to in Chain4 mode, and then examined
880 plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
881 supposed to do. However, the current test should be adequate to eliminate
882 just about all EGAs, and 100% of everything else.
883
884 If this function fails to find a VGA, it attempts to undo any damage it
885 may have inadvertently done while testing. The underlying assumption for
886 the damage control is that if there's any non-VGA adapter at the tested
887 ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
888 other adapters that use 3C4/5 or 3CE/F, and b), if there are other
889 adapters, I certainly don't know how to restore their original states. So
890 all error recovery is oriented toward putting an EGA back in a writable
891 state, so that error messages are visible. The EGA's state on entry is
892 assumed to be text mode, so the Memory Mode register is restored to the
893 default state for text mode.
894
895 If a VGA is found, the VGA is returned to its original state after
896 testing is finished.
897
898 Arguments:
899
900 None.
901
902 Return Value:
903
904 TRUE if a VGA is present, FALSE if not.
905
906 --*/
907
908 {
909 UCHAR originalGCAddr;
910 UCHAR originalSCAddr;
911 UCHAR originalBitMask;
912 UCHAR originalReadMap;
913 UCHAR originalMemoryMode;
914 UCHAR testMask;
915 BOOLEAN returnStatus;
916
917 //
918 // Remember the original state of the Graphics Controller Address register.
919 //
920
921 originalGCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
922 GRAPH_ADDRESS_PORT);
923
924 //
925 // Write the Read Map register with a known state so we can verify
926 // that it isn't changed after we fool with the Bit Mask. This ensures
927 // that we're dealing with indexed registers, since both the Read Map and
928 // the Bit Mask are addressed at GRAPH_DATA_PORT.
929 //
930
931 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
932 GRAPH_ADDRESS_PORT, IND_READ_MAP);
933
934 //
935 // If we can't read back the Graphics Address register setting we just
936 // performed, it's not readable and this isn't a VGA.
937 //
938
939 if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
940 GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_READ_MAP) {
941
942 return FALSE;
943 }
944
945 //
946 // Set the Read Map register to a known state.
947 //
948
949 originalReadMap = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
950 GRAPH_DATA_PORT);
951 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
952 GRAPH_DATA_PORT, READ_MAP_TEST_SETTING);
953
954 if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
955 GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
956
957 //
958 // The Read Map setting we just performed can't be read back; not a
959 // VGA. Restore the default Read Map state.
960 //
961
962 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
963 GRAPH_DATA_PORT, READ_MAP_DEFAULT);
964
965 return FALSE;
966 }
967
968 //
969 // Remember the original setting of the Bit Mask register.
970 //
971
972 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
973 GRAPH_ADDRESS_PORT, IND_BIT_MASK);
974 if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
975 GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_BIT_MASK) {
976
977 //
978 // The Graphics Address register setting we just made can't be read
979 // back; not a VGA. Restore the default Read Map state.
980 //
981
982 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
983 GRAPH_ADDRESS_PORT, IND_READ_MAP);
984 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
985 GRAPH_DATA_PORT, READ_MAP_DEFAULT);
986
987 return FALSE;
988 }
989
990 originalBitMask = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
991 GRAPH_DATA_PORT);
992
993 //
994 // Set up the initial test mask we'll write to and read from the Bit Mask.
995 //
996
997 testMask = 0xBB;
998
999 do {
1000
1001 //
1002 // Write the test mask to the Bit Mask.
1003 //
1004
1005 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1006 GRAPH_DATA_PORT, testMask);
1007
1008 //
1009 // Make sure the Bit Mask remembered the value.
1010 //
1011
1012 if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
1013 GRAPH_DATA_PORT) != testMask) {
1014
1015 //
1016 // The Bit Mask is not properly writable and readable; not a VGA.
1017 // Restore the Bit Mask and Read Map to their default states.
1018 //
1019
1020 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1021 GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
1022 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1023 GRAPH_ADDRESS_PORT, IND_READ_MAP);
1024 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1025 GRAPH_DATA_PORT, READ_MAP_DEFAULT);
1026
1027 return FALSE;
1028 }
1029
1030 //
1031 // Cycle the mask for next time.
1032 //
1033
1034 testMask >>= 1;
1035
1036 } while (testMask != 0);
1037
1038 //
1039 // There's something readable at GRAPH_DATA_PORT; now switch back and
1040 // make sure that the Read Map register hasn't changed, to verify that
1041 // we're dealing with indexed registers.
1042 //
1043
1044 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1045 GRAPH_ADDRESS_PORT, IND_READ_MAP);
1046 if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
1047 GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
1048
1049 //
1050 // The Read Map is not properly writable and readable; not a VGA.
1051 // Restore the Bit Mask and Read Map to their default states, in case
1052 // this is an EGA, so subsequent writes to the screen aren't garbled.
1053 //
1054
1055 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1056 GRAPH_DATA_PORT, READ_MAP_DEFAULT);
1057 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1058 GRAPH_ADDRESS_PORT, IND_BIT_MASK);
1059 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1060 GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
1061
1062 return FALSE;
1063 }
1064
1065 //
1066 // We've pretty surely verified the existence of the Bit Mask register.
1067 // Put the Graphics Controller back to the original state.
1068 //
1069
1070 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1071 GRAPH_DATA_PORT, originalReadMap);
1072 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1073 GRAPH_ADDRESS_PORT, IND_BIT_MASK);
1074 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1075 GRAPH_DATA_PORT, originalBitMask);
1076 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1077 GRAPH_ADDRESS_PORT, originalGCAddr);
1078
1079 //
1080 // Now, check for the existence of the Chain4 bit.
1081 //
1082
1083 //
1084 // Remember the original states of the Sequencer Address and Memory Mode
1085 // registers.
1086 //
1087
1088 originalSCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
1089 SEQ_ADDRESS_PORT);
1090 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1091 SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
1092 if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
1093 SEQ_ADDRESS_PORT) & SEQ_ADDR_MASK) != IND_MEMORY_MODE) {
1094
1095 //
1096 // Couldn't read back the Sequencer Address register setting we just
1097 // performed.
1098 //
1099
1100 return FALSE;
1101 }
1102 originalMemoryMode = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
1103 SEQ_DATA_PORT);
1104
1105 //
1106 // Toggle the Chain4 bit and read back the result. This must be done during
1107 // sync reset, since we're changing the chaining state.
1108 //
1109
1110 //
1111 // Begin sync reset.
1112 //
1113
1114 VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
1115 SEQ_ADDRESS_PORT),
1116 (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
1117
1118 //
1119 // Toggle the Chain4 bit.
1120 //
1121
1122 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1123 SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
1124 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1125 SEQ_DATA_PORT, (UCHAR)(originalMemoryMode ^ CHAIN4_MASK));
1126
1127 if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
1128 SEQ_DATA_PORT) != (UCHAR) (originalMemoryMode ^ CHAIN4_MASK)) {
1129
1130 //
1131 // Chain4 bit not there; not a VGA.
1132 // Set text mode default for Memory Mode register.
1133 //
1134
1135 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1136 SEQ_DATA_PORT, MEMORY_MODE_TEXT_DEFAULT);
1137 //
1138 // End sync reset.
1139 //
1140
1141 VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
1142 SEQ_ADDRESS_PORT),
1143 (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
1144
1145 returnStatus = FALSE;
1146
1147 } else {
1148
1149 //
1150 // It's a VGA.
1151 //
1152
1153 //
1154 // Restore the original Memory Mode setting.
1155 //
1156
1157 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1158 SEQ_DATA_PORT, originalMemoryMode);
1159
1160 //
1161 // End sync reset.
1162 //
1163
1164 VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
1165 SEQ_ADDRESS_PORT),
1166 (USHORT)(IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
1167
1168 //
1169 // Restore the original Sequencer Address setting.
1170 //
1171
1172 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1173 SEQ_ADDRESS_PORT, originalSCAddr);
1174
1175 returnStatus = TRUE;
1176 }
1177
1178 return returnStatus;
1179
1180 } // VgaIsPresent()
1181 \f
1182
1183 //---------------------------------------------------------------------------
1184 VP_STATUS
1185 VgaSetColorLookup(
1186 PHW_DEVICE_EXTENSION HwDeviceExtension,
1187 PVIDEO_CLUT ClutBuffer,
1188 ULONG ClutBufferSize
1189 )
1190
1191 /*++
1192
1193 Routine Description:
1194
1195 This routine sets a specified portion of the DAC color lookup table
1196 settings.
1197
1198 Arguments:
1199
1200 HwDeviceExtension - Pointer to the miniport driver's device extension.
1201
1202 ClutBufferSize - Length of the input buffer supplied by the user.
1203
1204 ClutBuffer - Pointer to the structure containing the color lookup table.
1205
1206 Return Value:
1207
1208 NO_ERROR - information returned successfully
1209
1210 ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
1211
1212 ERROR_INVALID_PARAMETER - invalid clut size.
1213
1214 --*/
1215
1216 {
1217 PVIDEOMODE CurrentMode = HwDeviceExtension->CurrentMode;
1218 USHORT i;
1219
1220 //
1221 // Check if the size of the data in the input buffer is large enough.
1222 //
1223
1224 if ( (ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) ||
1225 (ClutBufferSize < sizeof(VIDEO_CLUT) +
1226 (sizeof(ULONG) * (ClutBuffer->NumEntries - 1)) ) ) {
1227
1228 return ERROR_INSUFFICIENT_BUFFER;
1229
1230 }
1231
1232 //
1233 // Check to see if the parameters are valid.
1234 //
1235
1236 if ( (ClutBuffer->NumEntries == 0) ||
1237 (ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) ||
1238 (ClutBuffer->FirstEntry + ClutBuffer->NumEntries >
1239 VIDEO_MAX_COLOR_REGISTER + 1) ) {
1240
1241 return ERROR_INVALID_PARAMETER;
1242
1243 }
1244 // eVb: 1.14 [VBE] - Add VBE color support
1245 //
1246 // Check SVGA mode
1247 //
1248
1249 if (CurrentMode->bitsPerPlane >= 8) return VbeSetColorLookup(HwDeviceExtension, ClutBuffer);
1250 // eVb: 1.14 [END]
1251 //
1252 // Path for VGA mode
1253 //
1254 // eVb: 1.15 [VBE] - Add VBE support for non-VGA-compatible detected modes
1255 if (!CurrentMode->NonVgaMode)
1256 {
1257 // eVb: 1.15 [END]
1258 //
1259 // Set CLUT registers directly on the hardware
1260 //
1261
1262 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1263 DAC_ADDRESS_WRITE_PORT, (UCHAR) ClutBuffer->FirstEntry);
1264
1265 for (i = 0; i < ClutBuffer->NumEntries; i++) {
1266 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1267 DAC_ADDRESS_WRITE_PORT,
1268 (UCHAR)(i + ClutBuffer->FirstEntry));
1269
1270 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1271 DAC_DATA_REG_PORT,
1272 ClutBuffer->LookupTable[i].RgbArray.Red);
1273
1274 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1275 DAC_DATA_REG_PORT,
1276 ClutBuffer->LookupTable[i].RgbArray.Green);
1277
1278 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
1279 DAC_DATA_REG_PORT,
1280 ClutBuffer->LookupTable[i].RgbArray.Blue);
1281 }
1282 return NO_ERROR;
1283 }
1284
1285 return ERROR_INVALID_PARAMETER;
1286
1287 } // end VgaSetColorLookup()
1288 \f
1289 VP_STATUS
1290 GetDeviceDataCallback(
1291 PVOID HwDeviceExtension,
1292 PVOID Context,
1293 VIDEO_DEVICE_DATA_TYPE DeviceDataType,
1294 PVOID Identifier,
1295 ULONG IdentifierLength,
1296 PVOID ConfigurationData,
1297 ULONG ConfigurationDataLength,
1298 PVOID ComponentInformation,
1299 ULONG ComponentInformationLength
1300 )
1301
1302 /*++
1303
1304 Routine Description:
1305
1306 Callback routine for the VideoPortGetDeviceData function.
1307
1308 Arguments:
1309
1310 HwDeviceExtension - Pointer to the miniport drivers device extension.
1311
1312 Context - Context value passed to the VideoPortGetDeviceData function.
1313
1314 DeviceDataType - The type of data that was requested in
1315 VideoPortGetDeviceData.
1316
1317 Identifier - Pointer to a string that contains the name of the device,
1318 as setup by the ROM or ntdetect.
1319
1320 IdentifierLength - Length of the Identifier string.
1321
1322 ConfigurationData - Pointer to the configuration data for the device or
1323 BUS.
1324
1325 ConfigurationDataLength - Length of the data in the configurationData
1326 field.
1327
1328 ComponentInformation - Undefined.
1329
1330 ComponentInformationLength - Undefined.
1331
1332 Return Value:
1333
1334 Returns NO_ERROR if the function completed properly.
1335 Returns ERROR_DEV_NOT_EXIST if we did not find the device.
1336 Returns ERROR_INVALID_PARAMETER otherwise.
1337
1338 --*/
1339
1340 {
1341 VideoPortDebugPrint(Error, "Detected internal VGA chip on embedded board, todo\n");
1342 while (TRUE);
1343 return NO_ERROR;
1344
1345 } //end GetDeviceDataCallback()
1346
1347 // eVb: 1.16 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
1348 VP_STATUS
1349 VgaAcquireResources(
1350 PHW_DEVICE_EXTENSION DeviceExtension
1351 )
1352 {
1353 VP_STATUS Status = NO_ERROR;
1354 ULONG Ranges, i;
1355
1356 //
1357 // Try exclusive ranges (vga + ati)
1358 //
1359
1360 Ranges = NUM_VGA_ACCESS_RANGES;
1361 for (i = 0; i < Ranges; i++) VgaAccessRange[i].RangeShareable = FALSE;
1362 if (VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange) != NO_ERROR)
1363 {
1364 //
1365 // Not worked, try vga only
1366 //
1367
1368 Ranges = 3;
1369 if (VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange) != NO_ERROR)
1370 {
1371 //
1372 // Still not, try shared ranges
1373 //
1374
1375 for (i = 0; i < Ranges; i++) VgaAccessRange[i].RangeShareable = TRUE;
1376 Status = VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange);
1377 if (Status == NO_ERROR)
1378 {
1379 //
1380 // It did work
1381 //
1382
1383 VideoPortVerifyAccessRanges(DeviceExtension, 0, 0);
1384 Status = NO_ERROR;
1385 }
1386 }
1387 }
1388
1389 if (Status == NO_ERROR)
1390 {
1391 //
1392 // Worked with exclusive, also try shared
1393 //
1394
1395 for (i = 0; i < Ranges; i++) VgaAccessRange[i].RangeShareable = TRUE;
1396 Status = VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange);
1397 }
1398
1399 return Status;
1400 }
1401 // eVb: 1.16 [END]