|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 Microsoft Corporation
4:
5: Module Name:
6:
7: mono.c
8:
9: Abstract:
10:
11: A simple kernel-mode driver sample.
12:
13: Environment:
14:
15: kernel mode only
16:
17: Notes:
18:
19: See readme.txt
20:
21: Revision History:
22:
23: 03-22-93 : created
24: 06-02-93 : #ifdef's removed from IoCreateSymbolicLink, and
25: bulk of pMonoReportResourceUsage commented out for
26: ease of use with other drivers (see note below)
27: --*/
28:
29: #include "ntddk.h"
30: #include "stdarg.h"
31: #include "stdio.h"
32: #include "monopub.h"
33: #include "monopriv.h"
34:
35:
36:
37: //
38: // NOTE: Routines prefixed with "p" are private to this module
39: //
40:
41: NTSTATUS
42: MonoDispatch(
43: IN PDEVICE_OBJECT DeviceObject,
44: IN PIRP Irp
45: );
46:
47: VOID
48: MonoUnload(
49: IN PDRIVER_OBJECT DriverObject
50: );
51:
52: NTSTATUS
53: pMonoLocateDevice(
54: void
55: );
56:
57: PVOID
58: pMonoGetMappedAddress(
59: IN PHYSICAL_ADDRESS PhysicalAddress,
60: IN ULONG AddressSpace,
61: IN ULONG NumberOfBytes
62: );
63:
64: BOOLEAN
65: pMonoReportResourceUsage(
66: IN PDRIVER_OBJECT DriverObject,
67: IN PMONO_RESOURCE MonoResources,
68: IN ULONG NumberOfResources
69: );
70:
71: VOID
72: MonoDbgPrint(
73: IN ULONG DbgPrintLevel,
74: IN PUCHAR DbgMessage,
75: IN ...
76: );
77:
78: VOID
79: pMonoPrint(
80: IN PMONO_DEVICE_EXTENSION DeviceExtension,
81: IN PUCHAR TextString,
82: IN ULONG BytesToMove
83: );
84:
85: VOID
86: pMonoClearScreen(
87: IN PMONO_DEVICE_EXTENSION DeviceExtension
88: );
89:
90:
91:
92: NTSTATUS
93: DriverEntry(
94: IN PDRIVER_OBJECT DriverObject,
95: IN PUNICODE_STRING RegistryPath
96: )
97: /*++
98:
99: Routine Description:
100:
101: Installable driver initialization entry point.
102: This entry point is called directly by the I/O system.
103:
104: Arguments:
105:
106: DriverObject - pointer to the driver object
107:
108: RegistryPath - pointer to a unicode string representing the path
109: to driver-specific key in the registry
110:
111: Return Value:
112:
113: STATUS_SUCCESS if successful,
114: STATUS_UNSUCCESSFUL otherwise
115:
116: --*/
117: {
118:
119: PDEVICE_OBJECT deviceObject = NULL;
120: NTSTATUS ntStatus;
121: WCHAR deviceNameBuffer[] = L"\\Device\\Mono";
122: UNICODE_STRING deviceNameUnicodeString;
123: PMONO_DEVICE_EXTENSION deviceExtension;
124: BOOLEAN symbolicLinkCreated = FALSE;
125: WCHAR deviceLinkBuffer[] = L"\\DosDevices\\MONO";
126: UNICODE_STRING deviceLinkUnicodeString;
127:
128:
129: pMonoKdPrint (("MONO.SYS: entering DriverEntry\n"));
130:
131:
132:
133: //
134: // Check to see if anybody else has claim the resources we want to
135: // used. We don't want to be partying on someone else's hardware,
136: // even when trying to locate our devicc.
137: //
138:
139: if (!pMonoReportResourceUsage (DriverObject,
140: MonoResources,
141: MONO_NUMBER_RESOURCE_ENTRIES
142: ))
143: {
144: //
145: // There's a resource conflict
146: //
147:
148: pMonoKdPrint (("MONO.SYS: pMonoReportResourceUsage failed\n"));
149:
150: return STATUS_UNSUCCESSFUL;
151: }
152:
153:
154:
155: //
156: // Try to locate a monochrome display adapter (MDA)
157: //
158:
159: ntStatus = pMonoLocateDevice ();
160:
161: if (!NT_SUCCESS(ntStatus))
162: {
163: pMonoKdPrint (("MONO.SYS: pMonoLocateDevice failed\n"));
164:
165: ntStatus = STATUS_UNSUCCESSFUL;
166:
167: goto done_DriverEntry;
168: }
169:
170:
171:
172: //
173: // OK, we've claimed our resources & found our h/w, so create
174: // a device and initialize stuff...
175: //
176:
177: RtlInitUnicodeString (&deviceNameUnicodeString,
178: deviceNameBuffer
179: );
180:
181:
182:
183: //
184: // Create an EXCLUSIVE device, i.e. only 1 thread at a time can send
185: // i/o requests. If opened as non-exclusive, then we would need to
186: // implement a more robust synchronization scheme than the event
187: // mechanism we utilize below.
188: //
189:
190: ntStatus = IoCreateDevice (DriverObject,
191: sizeof (MONO_DEVICE_EXTENSION),
192: &deviceNameUnicodeString,
193: FILE_DEVICE_MONO,
194: 0,
195: TRUE,
196: &deviceObject
197: );
198:
199: if (NT_SUCCESS(ntStatus))
200: {
201:
202: GlobalDeviceExtension =
203: deviceExtension = (PMONO_DEVICE_EXTENSION) deviceObject->DeviceExtension;
204:
205:
206: //
207: // Initialize the dispatch event object. This allows us to
208: // synchronize access to the h/w registers...
209: //
210:
211: KeInitializeEvent (&deviceExtension->SyncEvent,
212: SynchronizationEvent,
213: TRUE
214: );
215:
216:
217:
218: deviceExtension->InterfaceType = Isa;
219: deviceExtension->BusNumber = 0;
220:
221:
222: //
223: // Map all the required resources, save the addresses
224: //
225:
226: deviceExtension->VideoMemory =
227:
228: (PUSHORT) pMonoGetMappedAddress (MonoResources[MONO_VIDEO_BUFFER].PhysicalAddress,
229: MonoResources[MONO_VIDEO_BUFFER].AddressSpace,
230: MonoResources[MONO_VIDEO_BUFFER].Length
231: );
232:
233: deviceExtension->CRTCRegisters =
234:
235: (PUCHAR) pMonoGetMappedAddress (MonoResources[MONO_CRTC_REG].PhysicalAddress,
236: MonoResources[MONO_CRTC_REG].AddressSpace,
237: MonoResources[MONO_CRTC_REG].Length
238: );
239:
240: deviceExtension->ModeControlRegister =
241:
242: (PUCHAR) pMonoGetMappedAddress (MonoResources[MONO_MODE_CTL_REG].PhysicalAddress,
243: MonoResources[MONO_MODE_CTL_REG].AddressSpace,
244: MonoResources[MONO_MODE_CTL_REG].Length
245: );
246:
247: if (!deviceExtension->VideoMemory ||
248: !deviceExtension->CRTCRegisters ||
249: !deviceExtension->ModeControlRegister
250: )
251: {
252:
253: pMonoKdPrint (("MONO.SYS: pMonoGetMappedAddress failed\n"));
254:
255: ntStatus = STATUS_UNSUCCESSFUL;
256:
257: goto done_DriverEntry;
258:
259: }
260:
261: deviceExtension->Xpos =
262: deviceExtension->Ypos = 0;
263:
264:
265:
266: //
267: // Create a symbolic link that Win32 apps can specify to gain access
268: // to this driver/device
269: //
270:
271: RtlInitUnicodeString (&deviceLinkUnicodeString,
272: deviceLinkBuffer
273: );
274:
275: ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
276: &deviceNameUnicodeString
277: );
278:
279:
280: if (!NT_SUCCESS(ntStatus))
281: {
282: pMonoKdPrint (("MONO.SYS: IoCreateSymbolicLink failed\n"));
283: }
284: else
285: {
286: symbolicLinkCreated = TRUE;
287: }
288:
289:
290:
291: //
292: // Create dispatch points for device control, create, close.
293: //
294:
295: DriverObject->MajorFunction[IRP_MJ_CREATE] =
296: DriverObject->MajorFunction[IRP_MJ_CLOSE] =
297: DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MonoDispatch;
298: DriverObject->DriverUnload = MonoUnload;
299:
300:
301:
302: //
303: // Set the Start Address registers (indicate which part of
304: // video buffer is displayed) to 0
305: //
306:
307: WRITE_PORT_UCHAR (deviceExtension->CRTCRegisters, 0xc);
308: WRITE_PORT_UCHAR (deviceExtension->CRTCRegisters + 1, 0);
309: WRITE_PORT_UCHAR (deviceExtension->CRTCRegisters, 0xd);
310: WRITE_PORT_UCHAR (deviceExtension->CRTCRegisters + 1, 0);
311:
312:
313:
314: //
315: // Clear screen & alert world of our humble existence
316: //
317:
318: pMonoClearScreen (deviceExtension);
319:
320: #define INIT_STRING "Mono driver initialized\n"
321:
322: pMonoPrint (deviceExtension,
323: INIT_STRING,
324: sizeof (INIT_STRING)
325: );
326: }
327:
328:
329: done_DriverEntry:
330:
331: if (!NT_SUCCESS(ntStatus))
332: {
333: //
334: // Something went wrong, so clean up
335: //
336:
337: pMonoReportResourceUsage (DriverObject,
338: NULL,
339: 0
340: );
341:
342: if (symbolicLinkCreated)
343:
344: IoDeleteSymbolicLink (&deviceLinkUnicodeString);
345:
346:
347: if (deviceObject)
348:
349: IoDeleteDevice (deviceObject);
350:
351: GlobalDeviceExtension = NULL;
352: }
353:
354: return ntStatus;
355: }
356:
357:
358:
359: NTSTATUS
360: MonoDispatch(
361: IN PDEVICE_OBJECT DeviceObject,
362: IN PIRP Irp
363: )
364: /*++
365:
366: Routine Description:
367:
368: Process the IRPs sent to this device.
369:
370: Arguments:
371:
372: DeviceObject - pointer to a device object
373:
374: Irp - pointer to an I/O Request Packet
375:
376: Return Value:
377:
378:
379: --*/
380: {
381:
382: PIO_STACK_LOCATION irpStack;
383: PMONO_DEVICE_EXTENSION deviceExtension;
384: PVOID ioBuffer;
385: ULONG inputBufferLength;
386: ULONG outputBufferLength;
387: ULONG ioControlCode;
388: NTSTATUS ntStatus;
389:
390:
391:
392: Irp->IoStatus.Status = STATUS_SUCCESS;
393: Irp->IoStatus.Information = 0;
394:
395:
396: //
397: // Get a pointer to the current location in the Irp. This is where
398: // the function codes and parameters are located.
399: //
400:
401: irpStack = IoGetCurrentIrpStackLocation (Irp);
402:
403:
404:
405: //
406: // Get a pointer to the device extension
407: //
408:
409: deviceExtension = DeviceObject->DeviceExtension;
410:
411:
412:
413: //
414: // Get the pointer to the input/output buffer and it's length
415: //
416:
417: ioBuffer = Irp->AssociatedIrp.SystemBuffer;
418: inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
419: outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
420:
421:
422:
423: //
424: // Synchronize execution of the dispatch routine by acquiring the device
425: // event object. This ensures all request are serialized.
426: //
427:
428: KeWaitForSingleObject (&deviceExtension->SyncEvent,
429: Executive,
430: KernelMode,
431: FALSE,
432: (PTIME) NULL
433: );
434:
435:
436:
437: switch (irpStack->MajorFunction)
438: {
439: case IRP_MJ_CREATE:
440:
441: pMonoKdPrint (("MONO.SYS: IRP_MJ_CREATE\n"));
442:
443: break;
444:
445: case IRP_MJ_CLOSE:
446:
447: pMonoKdPrint (("MONO.SYS: IRP_MJ_CLOSE\n"));
448:
449: break;
450:
451: case IRP_MJ_DEVICE_CONTROL:
452:
453: pMonoKdPrint (("MONO.SYS: IRP_MJ_DEVICE_CONTROL\n"));
454:
455: ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
456:
457: switch (ioControlCode)
458: {
459:
460: case IOCTL_MONO_PRINT:
461: {
462: pMonoPrint (deviceExtension,
463: ioBuffer,
464: inputBufferLength
465: );
466:
467: break;
468: }
469:
470: case IOCTL_MONO_CLEAR_SCREEN:
471: {
472: pMonoClearScreen (deviceExtension);
473:
474: break;
475: }
476:
477: default:
478:
479: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
480:
481: pMonoKdPrint (("MONO.SYS: unknown IRP_MJ_DEVICE_CONTROL\n"));
482:
483: break;
484:
485: }
486:
487: break;
488: }
489:
490:
491: KeSetEvent (&deviceExtension->SyncEvent,
492: 0,
493: FALSE
494: );
495:
496: //
497: // DON'T get cute and try to use the status field of
498: // the irp in the return status. That IRP IS GONE as
499: // soon as you call IoCompleteRequest.
500: //
501:
502: ntStatus = Irp->IoStatus.Status;
503:
504: IoCompleteRequest (Irp,
505: IO_NO_INCREMENT
506: );
507:
508:
509: //
510: // We never have pending operation so always return the status code.
511: //
512:
513: return ntStatus;
514: }
515:
516:
517:
518: VOID
519: MonoUnload(
520: IN PDRIVER_OBJECT DriverObject
521: )
522: /*++
523:
524: Routine Description:
525:
526: Free all the allocated resources, etc.
527:
528: Arguments:
529:
530: DriverObject - pointer to a driver object
531:
532: Return Value:
533:
534:
535: --*/
536: {
537: WCHAR deviceLinkBuffer[] = L"\\DosDevices\\MONO";
538: UNICODE_STRING deviceLinkUnicodeString;
539:
540:
541: //
542: // Unreport the resources
543: //
544:
545: pMonoReportResourceUsage (DriverObject,
546: NULL,
547: 0
548: );
549:
550:
551:
552: //
553: // Delete the symbolic link
554: //
555:
556: RtlInitUnicodeString (&deviceLinkUnicodeString,
557: deviceLinkBuffer
558: );
559:
560: IoDeleteSymbolicLink (&deviceLinkUnicodeString);
561:
562:
563:
564:
565: //
566: // Delete the device object
567: //
568:
569: IoDeleteDevice (DriverObject->DeviceObject);
570:
571: pMonoKdPrint (("MONO.SYS: unloading\n"));
572: }
573:
574:
575:
576: NTSTATUS
577: pMonoLocateDevice(
578: )
579: /*++
580:
581: Routine Description:
582:
583: Attempts to locate an MDA
584:
585: Arguments:
586:
587:
588: Return Value:
589:
590: STATUS_SUCCESS if adapter found,
591: STATUS_UNSUCCESSFUL otherwise
592:
593: --*/
594: {
595:
596: NTSTATUS ntStatus = STATUS_SUCCESS;
597: PHYSICAL_ADDRESS physicalAddress;
598: PUCHAR crtcRegisters;
599:
600: //
601: // Our FindAdapter logic:
602: //
603: // - retrieve an address for the 6845's index register (0x3b4)
604: // - write a 0x0f to the index register (0x0f = index of Cursor
605: // Location Low register)
606: // - write a 0x55 to 0x3b5
607: // - read 0x3b5, and it should == 0x55
608: //
609:
610: physicalAddress.LowPart = 0x3b4;
611: physicalAddress.HighPart = 0;
612:
613:
614: if ((crtcRegisters = pMonoGetMappedAddress (physicalAddress,
615: 1,
616: 2
617: )))
618: {
619: WRITE_PORT_UCHAR (crtcRegisters, 0x0f);
620: WRITE_PORT_UCHAR (crtcRegisters + 1, 0x55);
621:
622: if (READ_PORT_UCHAR (crtcRegisters + 1) != 0x55)
623: {
624: pMonoKdPrint (("MONO.SYS: could not find adapter\n"));
625:
626: ntStatus = STATUS_UNSUCCESSFUL;
627:
628: goto done_LocateDevice;
629: }
630:
631: //
632: // Set current cursor location back to (0,0)
633: //
634:
635: WRITE_PORT_UCHAR (crtcRegisters + 1, 0x00);
636: }
637:
638: else
639: {
640: pMonoKdPrint (("MONO.SYS: HalTranslatedAddress(0x3b4) failed\n"));
641:
642: ntStatus = STATUS_UNSUCCESSFUL;
643: }
644:
645: done_LocateDevice:
646:
647: return ntStatus;
648: }
649:
650:
651:
652: PVOID
653: pMonoGetMappedAddress(
654: IN PHYSICAL_ADDRESS PhysicalAddress,
655: IN ULONG AddressSpace,
656: IN ULONG NumberOfBytes
657: )
658: /*++
659:
660: Routine Description:
661:
662: Given a physical address, retrieves a corresponding system address
663: that can be used by a kernel mode driver.
664:
665: Arguments:
666:
667: PhysicalAddress - physical address to map
668:
669: AddressSpace - 0 if in memory space, 1 if in I/O space
670:
671: NumberOfBytes - length of section to map
672:
673: Return Value:
674:
675: A valid system address is successful,
676: NULL otherwise.
677:
678: --*/
679: {
680: //
681: // Assume we're on Isa bus # 0
682: //
683:
684: IN INTERFACE_TYPE interfaceType = Isa;
685: IN ULONG busNumber = 0;
686: PHYSICAL_ADDRESS translatedAddress;
687: PVOID deviceBase = NULL;
688:
689: if (HalTranslateBusAddress (interfaceType,
690: busNumber,
691: PhysicalAddress,
692: &AddressSpace,
693: &translatedAddress
694: ))
695: {
696: if (!AddressSpace)
697: {
698: if (!(deviceBase = MmMapIoSpace (translatedAddress,
699: NumberOfBytes,
700: FALSE // noncached memory
701: )))
702: {
703: pMonoKdPrint (("MONO.SYS: MmMapIoSpaceFailed\n"));
704: }
705: }
706: else
707: {
708: deviceBase = (PVOID) translatedAddress.LowPart;
709: }
710: }
711:
712: else
713: {
714: pMonoKdPrint (("MONO.SYS: HalTranslateBusAddress failed\n"));
715: }
716:
717: return deviceBase;
718: }
719:
720:
721:
722: BOOLEAN
723: pMonoReportResourceUsage(
724: IN PDRIVER_OBJECT DriverObject,
725: IN PMONO_RESOURCE MonoResources,
726: IN ULONG NumberOfResources
727: )
728: /*++
729:
730: Routine Description:
731:
732: Reports the resources used by a device.
733:
734: Arguments:
735:
736: DriverObject - pointer to a driver object
737:
738: MonoResources - pointer to an array of resource information, or
739: NULL is unreporting resources for this driver
740:
741: NumberOfResources - number of entries in the resource array, or
742: 0 if unreporting resources for this driver
743:
744: Return Value:
745:
746: TRUE if resources successfully report (and no conflicts),
747: FALSE otherwise.
748:
749: --*/
750: {
751:
752:
753:
754: //
755: // NOTE: The following is commented out because some of the video miniport
756: // drivers provided with the system (and in the NT DDK) regsister
757: // their resources as exclusive; if these resources overlap with
758: // the resources used by the mono driver, then this driver will fail
759: // to load. This can be solved in one of two ways: by commenting
760: // out the code below, and using the resources without reporting them
761: // (not safe to do, but the easiest for this simple example); or, by
762: // editing the source file(s) of the appropriate miniport driver
763: // such that the VIDEO_ACCESS_RANGE.RangeSharable element is set to
764: // TRUE, and rebuilding the driver.
765: //
766: // A real driver should *always* report it's resources.
767: //
768:
769:
770: /*
771: ULONG sizeOfResourceList = 0;
772: PCM_RESOURCE_LIST resourceList = NULL;
773: PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;
774: ULONG i;
775: UNICODE_STRING className;
776: BOOLEAN conflictDetected;
777:
778:
779: if (NumberOfResources > 0)
780: {
781: //
782: // Alloc enough memory to build a resource list & zero it out
783: //
784:
785: sizeOfResourceList = sizeof(CM_RESOURCE_LIST) +
786: (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)*
787: (NumberOfResources - 1)
788: );
789:
790: resourceList = ExAllocatePool (PagedPool,
791: sizeOfResourceList
792: );
793:
794: if (!resourceList)
795: {
796: pMonoKdPrint (("MONO.SYS: ExAllocPool failed\n"));
797:
798: return FALSE;
799: }
800:
801: RtlZeroMemory (resourceList,
802: sizeOfResourceList
803: );
804:
805:
806: //
807: // Fill in the reosurce list
808: //
809: // NOTE: Assume Isa, bus # 0
810: //
811:
812: resourceList->Count = 1;
813:
814: resourceList->List[0].InterfaceType = Isa;
815: resourceList->List[0].BusNumber = 0;
816:
817: resourceList->List[0].PartialResourceList.Count = NumberOfResources;
818:
819: partial = &resourceList->List[0].PartialResourceList.PartialDescriptors[0];
820:
821: //
822: // Account for the space used by the controller.
823: //
824:
825: for (i = 0; i < NumberOfResources; i++)
826: {
827: if (MonoResources[i].AddressSpace)
828: {
829: partial->Type = CmResourceTypePort;
830: partial->Flags = CM_RESOURCE_PORT_IO;
831: partial->u.Port.Start = MonoResources[i].PhysicalAddress;
832: partial->u.Port.Length = MonoResources[i].Length;
833: }
834: else
835: {
836: partial->Type = CmResourceTypeMemory;
837: partial->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
838: partial->u.Memory.Start = MonoResources[i].PhysicalAddress;
839: partial->u.Memory.Length = MonoResources[i].Length;
840: }
841:
842: if (MonoResources[i].RangeSharable)
843: {
844: partial->ShareDisposition = CmResourceShareShared;
845: }
846:
847: else
848: {
849: partial->ShareDisposition = CmResourceShareDeviceExclusive;
850: }
851:
852: partial++;
853: }
854: }
855:
856: RtlInitUnicodeString (&className,
857: L"LOADED MONO DRIVER RESOURCES"
858: );
859:
860: IoReportResourceUsage (&className,
861: DriverObject,
862: resourceList,
863: sizeOfResourceList,
864: NULL,
865: NULL,
866: 0,
867: FALSE,
868: &conflictDetected
869: );
870:
871: if (resourceList)
872: {
873: ExFreePool (resourceList);
874:
875:
876: if (conflictDetected)
877:
878: return FALSE;
879:
880: else
881:
882: return TRUE;
883: }
884: */
885: return TRUE;
886: }
887:
888:
889:
890: VOID
891: MonoDbgPrint(
892: IN ULONG DbgPrintLevel,
893: IN PUCHAR DbgMessage,
894: IN ...
895: )
896: /*++
897:
898: Routine Description:
899:
900: Format the incoming debug message & calls pMonoPrint to write the
901: message out to the attached MDA.
902:
903: Arguments:
904:
905: DbgPrintLevel - level of message verboseness
906:
907: DbgMessage - printf-style format string, followed by appropriate
908: list of arguments
909:
910: Return Value:
911:
912:
913: --*/
914: {
915: va_list ap;
916:
917: va_start(ap, DbgMessage);
918:
919: if (DbgPrintLevel <= MonoDbgLevel)
920: {
921: char buf[256];
922:
923: vsprintf (buf,
924: DbgMessage,
925: ap
926: );
927:
928: if (GlobalDeviceExtension)
929:
930: pMonoPrint (GlobalDeviceExtension,
931: buf,
932: strlen (buf)
933: );
934: }
935:
936: va_end(ap);
937: }
938:
939:
940:
941: VOID
942: pMonoPrint(
943: IN PMONO_DEVICE_EXTENSION DeviceExtension,
944: IN PUCHAR TextString,
945: IN ULONG BytesToMove
946: )
947: /*++
948:
949: Routine Description:
950:
951: Writes a specified string to MDA memory
952:
953: Arguments:
954:
955: DeviceExtension - pointer to a device extension
956:
957: TextString - pointer to an ascii string
958:
959: BytesToMove - number of characters to write
960:
961: Return Value:
962:
963:
964: --*/
965: {
966:
967: PUSHORT VideoMemory;
968: ULONG x,y,i,j;
969: UCHAR Letter;
970:
971: VideoMemory = DeviceExtension->VideoMemory;
972: x = DeviceExtension->Xpos;
973: y = DeviceExtension->Ypos;
974:
975:
976: for (i = 0; i < BytesToMove; i++)
977: {
978: Letter = (UCHAR) *(TextString + i);
979:
980: if (Letter == '\n')
981: {
982: //
983: // Blank out the rest of the line
984: //
985:
986: for (j = x; j < 80; j++)
987: {
988: *(VideoMemory + j + (y * 80)) = 0;
989: }
990: x = 0;
991: y = y + 1;
992: }
993:
994: else
995: {
996: //
997: // Write character & attribute out to video memory
998: //
999: // 0x0700 = No blink, black background, normal intensity,
1000: // white chracter
1001: //
1002:
1003: *(VideoMemory + x + (y * 80)) = Letter | 0x0700;
1004:
1005: x++;
1006: }
1007:
1008: if (x > 79)
1009: {
1010: //
1011: // Wrap around to next line
1012: //
1013:
1014: x = 0;
1015: y++;
1016: }
1017:
1018: if (y > 24)
1019: {
1020: //
1021: // We've reached the bottom of the screen, scroll screen
1022: // up by 1 row
1023: //
1024:
1025: RtlMoveMemory (VideoMemory,
1026: VideoMemory+80,
1027: 24 * 80 * 2
1028: );
1029: y = 24;
1030:
1031:
1032: //
1033: // Zero out the bottom row
1034: //
1035:
1036: for (j = 0; j < 80; j++)
1037: {
1038: *(VideoMemory + j + (24 * 80)) = 0;
1039: }
1040: }
1041: }
1042:
1043: DeviceExtension->Xpos = x;
1044: DeviceExtension->Ypos = y;
1045: }
1046:
1047:
1048:
1049: VOID
1050: pMonoClearScreen(
1051: IN PMONO_DEVICE_EXTENSION DeviceExtension
1052: )
1053: /*++
1054:
1055: Routine Description:
1056:
1057: Clears the MDA
1058:
1059: Arguments:
1060:
1061:
1062: Return Value:
1063:
1064:
1065: --*/
1066: {
1067:
1068: ULONG i;
1069:
1070: //
1071: // Zero out the MDA memory
1072: //
1073:
1074: for (i = 0; i < 25 * 80; i++)
1075:
1076: *(DeviceExtension->VideoMemory + i) = 0;
1077:
1078: DeviceExtension->Xpos =
1079: DeviceExtension->Ypos = 0;
1080: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.