MONO.C 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header$ */
  19. /***********************************************************************************************
  20. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : MONO.C *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : 01/04/97 *
  30. * *
  31. * Last Update : January 5, 1997 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * Mono_Clear_Screen -- Clears the monochrome screen & homes cursor. *
  36. * Mono_Print -- Prints text (with formatting) to mono screen. *
  37. * Mono_Print_Raw -- Print text (without processing) to mono screen. *
  38. * Mono_Printf -- Print formatted text to the mono device. *
  39. * Mono_Scroll -- Scroll the mono screen up one line. *
  40. * Mono_Set_View_Pos -- Set the mono display ram view offset. *
  41. * Mono_Pan -- Pan the mono screen over one column. *
  42. * Mono_Detect_MGA_Adapter -- Try to detec the MGA adapter. *
  43. * Mono_Get_Address_Ptr -- Converts a physical address into a usable pointer. *
  44. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  45. #include "ntddk.h"
  46. #include "stdarg.h"
  47. #include "stdio.h"
  48. #include "monopub.h"
  49. //
  50. // Indices into & count of the above array
  51. //
  52. #define MONO_VIDEO_BUFFER 0
  53. #define MONO_CRTC_REG 1
  54. #define MONO_MODE_CTL_REG 2
  55. #define MONO_NUMBER_RESOURCE_ENTRIES 2
  56. //#define MONO_NUMBER_RESOURCE_ENTRIES 3
  57. //
  58. // Our user mode app will pass an initialized structure like this
  59. // down to the kernel mode driver
  60. //
  61. //typedef struct
  62. //{
  63. // INTERFACE_TYPE InterfaceType; // Isa, Eisa, etc....
  64. // ULONG BusNumber; // Bus number
  65. // PHYSICAL_ADDRESS BusAddress; // Bus-relative address
  66. // ULONG AddressSpace; // 0 is memory, 1 is I/O
  67. // ULONG Length; // Length of section to map
  68. //
  69. //} PHYSICAL_MEMORY_INFO, *PPHYSICAL_MEMORY_INFO;
  70. #define DEVICE_NAME L"\\Device\\Mono"
  71. #define A_DEVICE_NAME "\\Device\\Mono"
  72. #define SYMBOLIC_NAME L"\\DosDevices\\MONO"
  73. #define A_SYMBOLIC_NAME "\\DosDevices\\MONO"
  74. #define CRTC_REGISTER 0x3B4
  75. #define MONO_MEMORY 0xB0000
  76. #define MONO_MEM_LENGTH (0x10000-1)
  77. #define MAX_PAGES 16
  78. #define MONO_WIDTH 80
  79. #define MONO_HEIGHT 25
  80. #define SIZE_OF_SCREEN (MONO_WIDTH * MONO_HEIGHT * sizeof(unsigned short))
  81. #define BUILD_CHAR(c, a) ((unsigned short)(((a) << 8) | ((c) & 0xFF)))
  82. #define PINDEX_TO_CELL(index) ((index) * MONO_WIDTH * MONO_HEIGHT)
  83. /*
  84. ** This controls the state information for each of the
  85. ** display pages.
  86. */
  87. typedef struct BuffControl
  88. {
  89. int XPos;
  90. int YPos;
  91. /*
  92. ** This is the default attribute to use when displaying text.
  93. */
  94. int Attribute;
  95. /*
  96. ** This is the logical address of the display page that this
  97. ** buffer represents. This pointer is in the address space
  98. ** of this driver, NOT of the owner of the file object.
  99. */
  100. unsigned short * Buffer;
  101. /*
  102. ** This is a copy of a pointer to the page memory that is
  103. ** in mapped to the owning file object's address space.
  104. */
  105. void * LockPtr;
  106. /*
  107. ** If this page has been allocated, then this flag will
  108. ** be true.
  109. */
  110. int Allocated;
  111. } BuffControl;
  112. /*
  113. ** This stores the global information for the monochrome driver.
  114. */
  115. typedef struct MonoGlobals
  116. {
  117. /*
  118. ** Syncronizing object so that access to this device is
  119. ** serialized.
  120. */
  121. KEVENT SyncEvent;
  122. /*
  123. ** Logical pointer to the CRTC registers.
  124. */
  125. unsigned char * CRTCRegisters;
  126. /*
  127. ** Points to the first character of the MGA display
  128. ** memory.
  129. */
  130. unsigned short * DisplayMemory;
  131. /*
  132. ** Each of the display pages is managed by this buffer
  133. ** control array.
  134. */
  135. BuffControl Control[MAX_PAGES];
  136. /*
  137. ** This is the index of the currently visible display page.
  138. */
  139. int CurrentVisible;
  140. } MonoGlobals;
  141. //
  142. // A structure decribing a particular device resource
  143. //
  144. typedef struct _MONO_RESOURCE
  145. {
  146. PHYSICAL_ADDRESS PhysicalAddress;
  147. unsigned long Length;
  148. unsigned long AddressSpace;
  149. unsigned long RangeSharable;
  150. } MONO_RESOURCE, *PMONO_RESOURCE;
  151. //
  152. // A global that we keep around for use by the MonoDbgPrint function
  153. // (when other drivers call MonoDbgPrint we need to be able to access
  154. // the info stored in the device extension).
  155. //
  156. MonoGlobals * GlobalDeviceExtension = NULL;
  157. //
  158. // A variable which determines the verboseness of the messages printed by
  159. // MonoDbgPrint.
  160. //
  161. unsigned long MonoDbgLevel = 3;
  162. //
  163. // Resources used by the monochrome video adapter
  164. //
  165. MONO_RESOURCE MonoResources[] =
  166. {
  167. { MONO_MEMORY, 0x00000000, // the video buffer
  168. MONO_MEM_LENGTH, // length
  169. 0, // in memory space
  170. 1 }, // shared with other drivers/devices (vga)
  171. { CRTC_REGISTER, 0x00000000, // the 6845 index & data regs
  172. 0x00000002, // length
  173. 1, // in I/O space
  174. 1 }, // shared with other drivers/devices (vga)
  175. { 0x000b03b8, 0x00000000, // mode control register
  176. 0x00000001, // length
  177. 1, // in I/O space
  178. 1 } // shared with other drivers/devices (vga)
  179. };
  180. /*
  181. ** Each cell is constructed of the actual character that is displayed and the
  182. ** attribute to use. This character pair is located at every position on the
  183. ** display (80 x 25). Since this cell pair can be represented by a "short"
  184. ** integer, certain speed optimizations are taken in the monochrome drawing
  185. ** code.
  186. */
  187. typedef struct CellType {
  188. unsigned char Character; // Character to display.
  189. unsigned char Attribute; // Attribute.
  190. } CellType;
  191. NTSTATUS MonoDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp);
  192. void MonoUnload(PDRIVER_OBJECT DriverObject);
  193. BOOLEAN pMonoReportResourceUsage(PDRIVER_OBJECT DriverObject, PMONO_RESOURCE MonoResources, unsigned long NumberOfResources);
  194. //NTSTATUS MapMemMapTheMemory(PDEVICE_OBJECT DeviceObject,PVOID IoBuffer, ULONG OutputBufferLength);
  195. void * Mono_Get_Address_Ptr(PHYSICAL_ADDRESS PhysicalAddress, unsigned long AddressSpace, unsigned long NumberOfBytes);
  196. void Mono_Set_View_Pos(MonoGlobals * device, int pos);
  197. NTSTATUS Mono_Detect_MGA_Adapter(void);
  198. void * Mono_Fetch_Ptr(PDEVICE_OBJECT DeviceObject);
  199. void Mono_Printf(BuffControl * control, char const * DbgMessage, ...);
  200. void Mono_Clear_Screen(BuffControl * control);
  201. void Mono_Print_Raw(BuffControl * control, unsigned char * string, unsigned long length);
  202. void Mono_Scroll(BuffControl * control);
  203. void Mono_Print(BuffControl * control, unsigned char * string, unsigned long length);
  204. void Mono_Bring_To_Top(MonoGlobals * device, int index);
  205. void Mono_Pan(BuffControl * control);
  206. void Display_Signon_Banner(BuffControl * control);
  207. void Mono_Update_Cursor(MonoGlobals * device);
  208. /*++
  209. Routine Description:
  210. Installable driver initialization entry point.
  211. This entry point is called directly by the I/O system.
  212. Arguments:
  213. DriverObject - pointer to the driver object
  214. RegistryPath - pointer to a unicode string representing the path
  215. to driver-specific key in the registry
  216. Return Value:
  217. STATUS_SUCCESS if successful,
  218. STATUS_UNSUCCESSFUL otherwise
  219. --*/
  220. NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  221. {
  222. PDEVICE_OBJECT deviceObject = NULL;
  223. NTSTATUS ntStatus;
  224. UNICODE_STRING deviceNameUnicodeString;
  225. MonoGlobals * deviceExtension;
  226. BOOLEAN symbolicLinkCreated = FALSE;
  227. UNICODE_STRING deviceLinkUnicodeString;
  228. int j;
  229. //
  230. // Check to see if anybody else has claim the resources we want to
  231. // used. We don't want to be partying on someone else's hardware,
  232. // even when trying to locate our devicc.
  233. //
  234. if (!pMonoReportResourceUsage(DriverObject, MonoResources, MONO_NUMBER_RESOURCE_ENTRIES)) {
  235. return STATUS_UNSUCCESSFUL;
  236. }
  237. //
  238. // Try to locate a monochrome display adapter (MDA)
  239. //
  240. ntStatus = Mono_Detect_MGA_Adapter();
  241. if (!NT_SUCCESS(ntStatus)) {
  242. ntStatus = STATUS_UNSUCCESSFUL;
  243. goto done_DriverEntry;
  244. }
  245. //
  246. // OK, we've claimed our resources & found our h/w, so create
  247. // a device and initialize stuff...
  248. //
  249. RtlInitUnicodeString(&deviceNameUnicodeString, DEVICE_NAME);
  250. // RtlInitUnicodeString(&deviceNameUnicodeString, L"\\Device\\Mono");
  251. //
  252. // Create an EXCLUSIVE device, i.e. only 1 thread at a time can send
  253. // i/o requests. If opened as non-exclusive, then we would need to
  254. // implement a more robust synchronization scheme than the event
  255. // mechanism we utilize below.
  256. //
  257. ntStatus = IoCreateDevice(DriverObject, sizeof(MonoGlobals), &deviceNameUnicodeString, FILE_DEVICE_MONO, 0, FALSE, &deviceObject);
  258. if (NT_SUCCESS(ntStatus)) {
  259. deviceObject->Flags |= DO_BUFFERED_IO;
  260. GlobalDeviceExtension = deviceExtension = (MonoGlobals *) deviceObject->DeviceExtension;
  261. //
  262. // Initialize the dispatch event object. This allows us to
  263. // synchronize access to the h/w registers...
  264. //
  265. KeInitializeEvent(&deviceExtension->SyncEvent, SynchronizationEvent, TRUE);
  266. //
  267. // Map all the required resources, save the addresses
  268. //
  269. deviceExtension->DisplayMemory =
  270. (PUSHORT) Mono_Get_Address_Ptr(MonoResources[MONO_VIDEO_BUFFER].PhysicalAddress,
  271. MonoResources[MONO_VIDEO_BUFFER].AddressSpace,
  272. MonoResources[MONO_VIDEO_BUFFER].Length
  273. );
  274. deviceExtension->CRTCRegisters =
  275. (unsigned char *) Mono_Get_Address_Ptr(MonoResources[MONO_CRTC_REG].PhysicalAddress,
  276. MonoResources[MONO_CRTC_REG].AddressSpace,
  277. MonoResources[MONO_CRTC_REG].Length
  278. );
  279. // deviceExtension->ModeControlRegister =
  280. // (unsigned char *) Mono_Get_Address_Ptr (MonoResources[MONO_MODE_CTL_REG].PhysicalAddress,
  281. // MonoResources[MONO_MODE_CTL_REG].AddressSpace,
  282. // MonoResources[MONO_MODE_CTL_REG].Length
  283. // );
  284. if (deviceExtension->DisplayMemory == NULL || deviceExtension->CRTCRegisters == NULL) {
  285. ntStatus = STATUS_UNSUCCESSFUL;
  286. goto done_DriverEntry;
  287. }
  288. //
  289. // Create a symbolic link that Win32 apps can specify to gain access
  290. // to this driver/device
  291. //
  292. RtlInitUnicodeString(&deviceLinkUnicodeString, SYMBOLIC_NAME);
  293. // RtlInitUnicodeString(&deviceLinkUnicodeString, L"\\DosDevices\\MONO");
  294. ntStatus = IoCreateSymbolicLink(&deviceLinkUnicodeString, &deviceNameUnicodeString);
  295. if (!NT_SUCCESS(ntStatus)) {
  296. } else {
  297. symbolicLinkCreated = TRUE;
  298. }
  299. //
  300. // Create dispatch points for device control, create, close.
  301. //
  302. DriverObject->MajorFunction[IRP_MJ_CREATE] = MonoDispatch;
  303. DriverObject->MajorFunction[IRP_MJ_CLOSE] = MonoDispatch;
  304. DriverObject->MajorFunction[IRP_MJ_READ] = MonoDispatch;
  305. DriverObject->MajorFunction[IRP_MJ_WRITE] = MonoDispatch;
  306. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MonoDispatch;
  307. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MonoDispatch;
  308. DriverObject->DriverUnload = MonoUnload;
  309. //
  310. // Set the Start Address registers (indicate which part of
  311. // video buffer is displayed) to 0
  312. //
  313. Mono_Set_View_Pos(deviceExtension, 0);
  314. deviceExtension->CurrentVisible = 0;
  315. for (j = 0; j < MAX_PAGES; j++) {
  316. deviceExtension->Control[j].Buffer = &deviceExtension->DisplayMemory[PINDEX_TO_CELL(j)];
  317. deviceExtension->Control[j].XPos = 0;
  318. deviceExtension->Control[j].YPos = 0;
  319. deviceExtension->Control[j].Attribute = 0x07;
  320. deviceExtension->Control[j].LockPtr = NULL;
  321. deviceExtension->Control[j].Allocated = FALSE;
  322. }
  323. /*
  324. ** Display the signon banner.
  325. */
  326. Display_Signon_Banner(&deviceExtension->Control[deviceExtension->CurrentVisible]);
  327. Mono_Update_Cursor(deviceExtension);
  328. }
  329. done_DriverEntry:
  330. if (!NT_SUCCESS(ntStatus)) {
  331. //
  332. // Something went wrong, so clean up
  333. //
  334. pMonoReportResourceUsage(DriverObject, NULL, 0);
  335. if (symbolicLinkCreated) {
  336. IoDeleteSymbolicLink(&deviceLinkUnicodeString);
  337. }
  338. if (deviceObject) {
  339. IoDeleteDevice(deviceObject);
  340. }
  341. GlobalDeviceExtension = NULL;
  342. }
  343. return ntStatus;
  344. }
  345. /*++
  346. Routine Description:
  347. Process the IRPs sent to this device.
  348. Arguments:
  349. DeviceObject - pointer to a device object
  350. Irp - pointer to an I/O Request Packet
  351. Return Value:
  352. --*/
  353. NTSTATUS MonoDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
  354. {
  355. PIO_STACK_LOCATION irpStack;
  356. MonoGlobals * deviceExtension;
  357. void * ioBuffer;
  358. unsigned long inputBufferLength;
  359. unsigned long outputBufferLength;
  360. unsigned long ioControlCode;
  361. NTSTATUS ntStatus;
  362. FILE_OBJECT * fileobject = NULL;
  363. BuffControl * control = NULL;
  364. int currentindex = -1;
  365. /*
  366. ** Presume success in the command processing.
  367. */
  368. Irp->IoStatus.Status = STATUS_SUCCESS;
  369. Irp->IoStatus.Information = 0; // Bytes read/written or other return value.
  370. /*
  371. ** Get a pointer to the current location in the Irp. This is where
  372. ** the function codes and parameters are located.
  373. */
  374. irpStack = IoGetCurrentIrpStackLocation(Irp);
  375. /*
  376. ** Get a pointer to the device extension
  377. */
  378. deviceExtension = DeviceObject->DeviceExtension;
  379. /*
  380. ** Fetch the file object for this I/O request.
  381. */
  382. fileobject = irpStack->FileObject;
  383. if (fileobject != NULL) {
  384. currentindex = (long)fileobject->FsContext;
  385. }
  386. /*
  387. ** Get the pointer to the input/output buffer and it's length
  388. */
  389. ioBuffer = Irp->AssociatedIrp.SystemBuffer;
  390. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  391. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  392. /*
  393. ** Synchronize execution of the dispatch routine by acquiring the device
  394. ** event object. This ensures all request are serialized.
  395. */
  396. KeWaitForSingleObject(&deviceExtension->SyncEvent, Executive, KernelMode, FALSE, NULL);
  397. /*
  398. ** Get a working pointer to the display page.
  399. */
  400. if (currentindex == -1) {
  401. currentindex == deviceExtension->CurrentVisible;
  402. }
  403. control = &deviceExtension->Control[currentindex];
  404. switch (irpStack->MajorFunction) {
  405. case IRP_MJ_READ:
  406. break;
  407. /*
  408. ** Process WriteFile request to display text.
  409. */
  410. case IRP_MJ_WRITE:
  411. if (ioBuffer != NULL && irpStack->Parameters.Write.Length > 0) {
  412. Mono_Print(control, ioBuffer, irpStack->Parameters.Write.Length);
  413. Irp->IoStatus.Information = irpStack->Parameters.Write.Length;
  414. }
  415. break;
  416. /*
  417. ** The create event is called when a file object is first created. At that
  418. ** time, designate a context buffer and inialize it.
  419. */
  420. case IRP_MJ_CREATE: {
  421. int j;
  422. int avail = -1;
  423. /*
  424. ** Search for a free page to use.
  425. */
  426. for (j = 0; j < MAX_PAGES; j++) {
  427. if (!deviceExtension->Control[j].Allocated) {
  428. avail = j;
  429. break;
  430. }
  431. }
  432. /*
  433. ** If one is not found, then return with error.
  434. */
  435. if (avail == -1) {
  436. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  437. } else {
  438. BuffControl * newcon = &deviceExtension->Control[avail];
  439. newcon->XPos = 0;
  440. newcon->YPos = 0;
  441. newcon->Attribute = 0x07;
  442. newcon->Allocated = TRUE;
  443. Mono_Bring_To_Top(deviceExtension, avail);
  444. fileobject->FsContext = (void*)avail;
  445. }
  446. }
  447. break;
  448. /*
  449. ** Closing the file occurs when the last reference to the object has been
  450. ** severed.
  451. */
  452. case IRP_MJ_CLOSE:
  453. if (currentindex != -1) {
  454. deviceExtension->Control[currentindex].Allocated = FALSE;
  455. fileobject->FsContext = NULL;
  456. }
  457. break;
  458. case IRP_MJ_CLEANUP:
  459. break;
  460. case IRP_MJ_DEVICE_CONTROL:
  461. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  462. switch (ioControlCode) {
  463. case IOCTL_MONO_BRING_TO_TOP:
  464. Mono_Bring_To_Top(deviceExtension, currentindex);
  465. break;
  466. case IOCTL_MONO_SCROLL:
  467. Mono_Scroll(control);
  468. break;
  469. case IOCTL_MONO_PAN:
  470. Mono_Pan(control);
  471. break;
  472. case IOCTL_MONO_SET_CURSOR:
  473. if (inputBufferLength == sizeof(int)*2) {
  474. control->XPos = *(int*)ioBuffer;
  475. control->YPos = *(((int*)ioBuffer) + 1);
  476. }
  477. break;
  478. case IOCTL_MONO_PRINT_RAW:
  479. Mono_Print_Raw(control, ioBuffer, inputBufferLength);
  480. break;
  481. case IOCTL_MONO_SET_POS:
  482. if (inputBufferLength == sizeof(int)) {
  483. Mono_Set_View_Pos(deviceExtension, *(int*)ioBuffer);
  484. }
  485. break;
  486. case IOCTL_MONO_CLEAR_SCREEN:
  487. Mono_Clear_Screen(control);
  488. break;
  489. case IOCTL_MONO_SET_ATTRIBUTE:
  490. control->Attribute = *(char *)ioBuffer;
  491. break;
  492. #ifdef NEVER
  493. case IOCTL_MONO_LOCK:
  494. if (deviceExtension->LockPtr != NULL) {
  495. *(void**)ioBuffer = deviceExtension->LockPtr;
  496. deviceExtension->LockCount++;
  497. } else {
  498. *(void**)ioBuffer = Mono_Fetch_Ptr(DeviceObject);
  499. if (*(void**)ioBuffer != NULL) {
  500. deviceExtension->LockPtr = *(void**)ioBuffer;
  501. deviceExtension->LockCount++;
  502. Irp->IoStatus.Information = sizeof(PVOID);
  503. } else {
  504. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  505. }
  506. }
  507. break;
  508. case IOCTL_MONO_UNLOCK:
  509. if (deviceExtension->LockCount > 0) {
  510. deviceExtension->LockCount--;
  511. if (deviceExtension->LockCount == 0) {
  512. Irp->IoStatus.Status = ZwUnmapViewOfSection((HANDLE) -1, deviceExtension->LockPtr);
  513. deviceExtension->LockPtr = NULL;
  514. }
  515. }
  516. break;
  517. #endif
  518. default:
  519. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  520. break;
  521. }
  522. break;
  523. }
  524. /*
  525. ** Only if the context drawn to is the currently visible one, will the
  526. ** cursor position be updated.
  527. */
  528. if (currentindex == deviceExtension->CurrentVisible) {
  529. Mono_Update_Cursor(deviceExtension);
  530. }
  531. KeSetEvent(&deviceExtension->SyncEvent, 0, FALSE);
  532. ntStatus = Irp->IoStatus.Status;
  533. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  534. return(ntStatus);
  535. }
  536. /*++
  537. Routine Description:
  538. Free all the allocated resources, etc.
  539. Arguments:
  540. DriverObject - pointer to a driver object
  541. Return Value:
  542. --*/
  543. void MonoUnload(PDRIVER_OBJECT DriverObject)
  544. {
  545. // WCHAR deviceLinkBuffer[] = L"\\DosDevices\\MONO";
  546. UNICODE_STRING deviceLinkUnicodeString;
  547. //
  548. // Unreport the resources
  549. //
  550. pMonoReportResourceUsage(DriverObject, NULL, 0);
  551. //
  552. // Delete the symbolic link
  553. //
  554. RtlInitUnicodeString(&deviceLinkUnicodeString, L"\\DosDevices\\MONO");
  555. IoDeleteSymbolicLink(&deviceLinkUnicodeString);
  556. //
  557. // Delete the device object
  558. //
  559. IoDeleteDevice(DriverObject->DeviceObject);
  560. }
  561. /***********************************************************************************************
  562. * Mono_Detect_MGA_Adapter -- Try to detec the MGA adapter. *
  563. * *
  564. * Tries to find the MGA adaptor by writing a few bytes to the CRTC register and checking *
  565. * if they return a corresponding value. *
  566. * *
  567. * INPUT: none *
  568. * *
  569. * OUTPUT: Returns with the NT status code of the check. STATUS_SUCCESS if the MGA adapter *
  570. * was found. *
  571. * *
  572. * WARNINGS: none *
  573. * *
  574. * HISTORY: *
  575. * 01/05/1997 JLB : Created. *
  576. *=============================================================================================*/
  577. NTSTATUS Mono_Detect_MGA_Adapter(void)
  578. {
  579. PHYSICAL_ADDRESS physicalAddress;
  580. unsigned char * crtcRegisters;
  581. /*
  582. ** Get address to the CRTC registers.
  583. */
  584. physicalAddress.LowPart = CRTC_REGISTER;
  585. physicalAddress.HighPart = 0;
  586. if ((crtcRegisters = Mono_Get_Address_Ptr(physicalAddress, 1, 2))) {
  587. /*
  588. ** Set the mono cursor position and see if it changed. If so, then
  589. ** presume that the MGA adapter is present.
  590. */
  591. WRITE_PORT_UCHAR(crtcRegisters, 0x0F);
  592. WRITE_PORT_UCHAR(crtcRegisters+1, 0x55);
  593. if (READ_PORT_UCHAR(crtcRegisters+1) != 0x55) {
  594. return(STATUS_UNSUCCESSFUL);
  595. }
  596. WRITE_PORT_UCHAR(crtcRegisters+1, 0xAA);
  597. if (READ_PORT_UCHAR(crtcRegisters+1) != 0xAA) {
  598. return(STATUS_UNSUCCESSFUL);
  599. }
  600. WRITE_PORT_UCHAR(crtcRegisters+1, 0x00);
  601. } else {
  602. return(STATUS_UNSUCCESSFUL);
  603. }
  604. return(STATUS_SUCCESS);
  605. }
  606. /***********************************************************************************************
  607. * Mono_Get_Address_Ptr -- Converts a physical address into a usable pointer. *
  608. * *
  609. * This routine will take the physical address specified and convert it into a pointer that *
  610. * can be used to reference the address specified. *
  611. * *
  612. * INPUT: address -- The physical address to convert. *
  613. * *
  614. * space -- The address space that the specified address is in. 0 means memory, *
  615. * 1 means I/O space (ports). *
  616. * *
  617. * length -- The length of the memory that will be referenced. *
  618. * *
  619. * OUTPUT: Returns with a usable pointer to the memory specified or NULL if it could not be *
  620. * processed. *
  621. * *
  622. * WARNINGS: none *
  623. * *
  624. * HISTORY: *
  625. * 01/05/1997 JLB : Created. *
  626. *=============================================================================================*/
  627. void * Mono_Get_Address_Ptr(PHYSICAL_ADDRESS address, unsigned long space, unsigned long length)
  628. {
  629. PHYSICAL_ADDRESS translatedAddress;
  630. void * usable_ptr = NULL;
  631. /*
  632. ** Translate a bus specific address into a logical system address.
  633. */
  634. if (HalTranslateBusAddress(Isa, 0, address, &space, &translatedAddress)) {
  635. /*
  636. ** If the space value is zero, then this idicates that a call to
  637. ** MmMapIoSpace is required. This is usually required for port addresses.
  638. */
  639. if (space == 0) {
  640. usable_ptr = MmMapIoSpace(translatedAddress, length, FALSE);
  641. } else {
  642. usable_ptr = (void *)translatedAddress.LowPart;
  643. }
  644. }
  645. return(usable_ptr);
  646. }
  647. //
  648. // NOTE: The following is commented out because some of the video miniport
  649. // drivers provided with the system (and in the NT DDK) regsister
  650. // their resources as exclusive; if these resources overlap with
  651. // the resources used by the mono driver, then this driver will fail
  652. // to load. This can be solved in one of two ways: by commenting
  653. // out the code below, and using the resources without reporting them
  654. // (not safe to do, but the easiest for this simple example); or, by
  655. // editing the source file(s) of the appropriate miniport driver
  656. // such that the VIDEO_ACCESS_RANGE.RangeSharable element is set to
  657. // TRUE, and rebuilding the driver.
  658. //
  659. // A real driver should *always* report it's resources.
  660. //
  661. /*++
  662. Routine Description:
  663. Reports the resources used by a device.
  664. Arguments:
  665. DriverObject - pointer to a driver object
  666. MonoResources - pointer to an array of resource information, or
  667. NULL is unreporting resources for this driver
  668. NumberOfResources - number of entries in the resource array, or
  669. 0 if unreporting resources for this driver
  670. Return Value:
  671. TRUE if resources successfully report (and no conflicts),
  672. FALSE otherwise.
  673. --*/
  674. BOOLEAN pMonoReportResourceUsage(PDRIVER_OBJECT DriverObject, PMONO_RESOURCE MonoResources, unsigned long NumberOfResources)
  675. {
  676. unsigned long sizeOfResourceList = 0;
  677. PCM_RESOURCE_LIST resourceList = NULL;
  678. PCM_PARTIAL_RESOURCE_DESCRIPTOR partial;
  679. unsigned long i;
  680. UNICODE_STRING className;
  681. BOOLEAN conflictDetected;
  682. if (NumberOfResources > 0) {
  683. //
  684. // Alloc enough memory to build a resource list & zero it out
  685. //
  686. sizeOfResourceList = sizeof(CM_RESOURCE_LIST) + (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)*(NumberOfResources - 1));
  687. resourceList = ExAllocatePool(PagedPool, sizeOfResourceList);
  688. if (!resourceList) {
  689. return FALSE;
  690. }
  691. RtlZeroMemory(resourceList, sizeOfResourceList);
  692. //
  693. // Fill in the reosurce list
  694. //
  695. // NOTE: Assume Isa, bus # 0
  696. //
  697. resourceList->Count = 1;
  698. resourceList->List[0].InterfaceType = Isa;
  699. resourceList->List[0].BusNumber = 0;
  700. resourceList->List[0].PartialResourceList.Count = NumberOfResources;
  701. partial = &resourceList->List[0].PartialResourceList.PartialDescriptors[0];
  702. //
  703. // Account for the space used by the controller.
  704. //
  705. for (i = 0; i < NumberOfResources; i++) {
  706. if (MonoResources[i].AddressSpace) {
  707. partial->Type = CmResourceTypePort;
  708. partial->Flags = CM_RESOURCE_PORT_IO;
  709. partial->u.Port.Start = MonoResources[i].PhysicalAddress;
  710. partial->u.Port.Length = MonoResources[i].Length;
  711. } else {
  712. partial->Type = CmResourceTypeMemory;
  713. partial->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  714. partial->u.Memory.Start = MonoResources[i].PhysicalAddress;
  715. partial->u.Memory.Length = MonoResources[i].Length;
  716. }
  717. if (MonoResources[i].RangeSharable) {
  718. partial->ShareDisposition = CmResourceShareShared;
  719. } else {
  720. partial->ShareDisposition = CmResourceShareDeviceExclusive;
  721. }
  722. partial++;
  723. }
  724. }
  725. RtlInitUnicodeString(&className, L"LOADED MONO DRIVER RESOURCES");
  726. IoReportResourceUsage(&className, DriverObject, resourceList, sizeOfResourceList, NULL, NULL, 0, FALSE, &conflictDetected);
  727. if (resourceList) {
  728. ExFreePool(resourceList);
  729. if (conflictDetected) {
  730. return FALSE;
  731. } else {
  732. return TRUE;
  733. }
  734. }
  735. return TRUE;
  736. }
  737. void Mono_Update_Cursor(MonoGlobals * device)
  738. {
  739. int pos;
  740. pos = device->Control[device->CurrentVisible].XPos + (device->Control[device->CurrentVisible].YPos * MONO_WIDTH);
  741. WRITE_PORT_UCHAR(device->CRTCRegisters, 0x0E);
  742. WRITE_PORT_UCHAR(device->CRTCRegisters+1, (unsigned char)(pos>>8));
  743. WRITE_PORT_UCHAR(device->CRTCRegisters, 0x0F);
  744. WRITE_PORT_UCHAR(device->CRTCRegisters+1, (unsigned char)(pos & 0xFF));
  745. }
  746. /***********************************************************************************************
  747. * Mono_Print -- Prints text (with formatting) to mono screen. *
  748. * *
  749. * This routine will take the text specified and print it to the monochrome screen. If *
  750. * there are any formatting characters present, then they will be processed accordingly. *
  751. * *
  752. * INPUT: control -- Poitner to the buffer to print to. *
  753. * *
  754. * string -- Pointer to the string to print. *
  755. * *
  756. * length -- The length of the string to print. *
  757. * *
  758. * OUTPUT: none *
  759. * *
  760. * WARNINGS: none *
  761. * *
  762. * HISTORY: *
  763. * 01/04/1997 JLB : Created. *
  764. *=============================================================================================*/
  765. void Mono_Print(BuffControl * control, unsigned char * string, unsigned long length)
  766. {
  767. if (control != NULL) {
  768. int x,y;
  769. unsigned char space = ' ';
  770. x = control->XPos;
  771. y = control->YPos;
  772. while (length > 0) {
  773. unsigned char * blockstart;
  774. int blocklen;
  775. unsigned char bchar; // Breaking character.
  776. /*
  777. ** Scan for a block of contiguous non-formatting characters to print.
  778. */
  779. blockstart = string;
  780. blocklen = 0;
  781. bchar = '\0';
  782. while (length > 0 && bchar == '\0') {
  783. bchar = *string++;
  784. length--;
  785. switch (bchar) {
  786. case '\b': // Backspace
  787. case '\a': // Audible bell
  788. case '\t': // Horizontal tab
  789. case '\f': // Formfeed
  790. case '\n': // Linefeed
  791. case '\v': // Vertical tab
  792. break;
  793. /*
  794. ** If not a valid formatting character, then clear out the break
  795. ** character variable so that processing will continue.
  796. */
  797. default:
  798. blocklen++;
  799. bchar = '\0';
  800. break;
  801. }
  802. }
  803. /*
  804. ** If a block has been scanned, then print it at this time.
  805. */
  806. if (blocklen > 0) {
  807. Mono_Print_Raw(control, blockstart, blocklen);
  808. }
  809. /*
  810. ** Conveniently get the cursor position into working variables.
  811. ** This helps because many of the formatting characters change
  812. ** the cursor position.
  813. */
  814. x = control->XPos;
  815. y = control->YPos;
  816. /*
  817. ** If a formatting character was found, then process it at this
  818. ** time.
  819. */
  820. switch (bchar) {
  821. /*
  822. ** Backspace moves the cursor back one space (erasing what was there).
  823. */
  824. case '\b':
  825. if (x > 0) {
  826. x--;
  827. control->XPos = x;
  828. Mono_Print_Raw(control, &space, 1);
  829. control->XPos = x;
  830. }
  831. break;
  832. /*
  833. ** Formfeed -- clears the screen.
  834. */
  835. case '\f':
  836. Mono_Clear_Screen(control);
  837. break;
  838. /*
  839. ** Linefeed -- in the tradition of C, this actually translates
  840. ** into a functional <CR><LF> pair.
  841. */
  842. case '\n':
  843. x = 0;
  844. y++;
  845. if (y >= MONO_HEIGHT) {
  846. Mono_Scroll(control);
  847. y--;
  848. }
  849. control->XPos = x;
  850. control->YPos = y;
  851. break;
  852. /*
  853. ** Horizontal tab
  854. */
  855. case '\t':
  856. Mono_Print_Raw(control, &space, 1);
  857. break;
  858. /*
  859. ** Unrecognized formatting character.
  860. */
  861. default:
  862. break;
  863. }
  864. }
  865. }
  866. }
  867. /***********************************************************************************************
  868. * Mono_Scroll -- Scroll the mono screen up one line. *
  869. * *
  870. * Use this routine to scroll the mono screen up one line. The bottom line will be filled *
  871. * with blanks. The cursor position is moved up one line as well. *
  872. * *
  873. * INPUT: control -- Pointer to the buffer to scroll. *
  874. * *
  875. * OUTPUT: none *
  876. * *
  877. * WARNINGS: none *
  878. * *
  879. * HISTORY: *
  880. * 01/04/1997 JLB : Created. *
  881. *=============================================================================================*/
  882. void Mono_Scroll(BuffControl * control)
  883. {
  884. if (control != NULL) {
  885. int j;
  886. unsigned short * vidmem;
  887. unsigned short blank = BUILD_CHAR(' ', control->Attribute);
  888. vidmem = control->Buffer;
  889. RtlMoveMemory(vidmem, vidmem+MONO_WIDTH, (MONO_HEIGHT-1) * MONO_WIDTH * sizeof(unsigned short));
  890. /*
  891. ** Fill the bottom row with blanks.
  892. */
  893. for (j = 0; j < MONO_WIDTH; j++) {
  894. *(vidmem + j + ((MONO_HEIGHT-1) * MONO_WIDTH)) = blank;
  895. }
  896. control->YPos -= 1;
  897. if (control->YPos < 0) {
  898. control->YPos = 0;
  899. }
  900. }
  901. }
  902. /***********************************************************************************************
  903. * Mono_Pan -- Pan the mono screen over one column. *
  904. * *
  905. * This will scroll (horizontally) the monochrome screen. The new column will be filled *
  906. * with blank spaces. *
  907. * *
  908. * INPUT: control -- Pointer to the buffer to pan. *
  909. * *
  910. * OUTPUT: none *
  911. * *
  912. * WARNINGS: none *
  913. * *
  914. * HISTORY: *
  915. * 01/04/1997 JLB : Created. *
  916. *=============================================================================================*/
  917. void Mono_Pan(BuffControl * control)
  918. {
  919. if (control != NULL) {
  920. int j;
  921. unsigned short * vidmem;
  922. unsigned short blank = BUILD_CHAR(' ', control->Attribute);
  923. vidmem = control->Buffer;
  924. for (j = 0; j < MONO_HEIGHT; j++) {
  925. RtlMoveMemory(vidmem+j*MONO_WIDTH, vidmem+j*MONO_WIDTH+1, (MONO_WIDTH-1) * sizeof(unsigned short));
  926. *(vidmem + j*MONO_WIDTH + MONO_WIDTH-1) = blank;
  927. }
  928. control->XPos -= 1;
  929. if (control->XPos < 0) {
  930. control->XPos = 0;
  931. }
  932. }
  933. }
  934. /***********************************************************************************************
  935. * Mono_Print_Raw -- Print text (without processing) to mono screen. *
  936. * *
  937. * This is a low level routine that will not process the characters submitted, but merely *
  938. * draw them to the monochrome screen. The output will not wrap at right margin nor will *
  939. * it scroll the screen when it tries to print past the bottom right character position. *
  940. * This routine can be used to output characters that have a visual image even though they *
  941. * line up with formatting control characters. *
  942. * *
  943. * INPUT: control -- Pointer to the buffer to print to. *
  944. * *
  945. * string -- Pointer to the string to output. *
  946. * *
  947. * length -- The length of the string in characters. *
  948. * *
  949. * OUTPUT: none *
  950. * *
  951. * WARNINGS: none *
  952. * *
  953. * HISTORY: *
  954. * 01/04/1997 JLB : Created. *
  955. *=============================================================================================*/
  956. void Mono_Print_Raw(BuffControl * control, unsigned char * string, unsigned long length)
  957. {
  958. if (control != NULL) {
  959. unsigned short * vidmem;
  960. int x,y;
  961. unsigned long i;
  962. vidmem = control->Buffer;
  963. x = control->XPos;
  964. y = control->YPos;
  965. for (i = 0; i < length; i++) {
  966. unsigned char letter;
  967. letter = *string++;
  968. *(vidmem + x + (y * MONO_WIDTH)) = BUILD_CHAR(letter, control->Attribute);
  969. x++;
  970. /*
  971. ** Don't allow the cursor to extend past the right margin.
  972. */
  973. if (x >= MONO_WIDTH) {
  974. x = MONO_WIDTH-1;
  975. }
  976. }
  977. control->XPos = x;
  978. control->YPos = y;
  979. }
  980. }
  981. /***********************************************************************************************
  982. * Mono_Clear_Screen -- Clears the monochrome screen & homes cursor. *
  983. * *
  984. * This will erase the monochrome screen and move the output cursor to the upper left *
  985. * corner. *
  986. * *
  987. * INPUT: control -- Pointer to the buffer to clear. *
  988. * *
  989. * OUTPUT: none *
  990. * *
  991. * WARNINGS: none *
  992. * *
  993. * HISTORY: *
  994. * 01/04/1997 JLB : Created. *
  995. *=============================================================================================*/
  996. void Mono_Clear_Screen(BuffControl * control)
  997. {
  998. if (control != NULL) {
  999. int i;
  1000. unsigned short * vidptr = control->Buffer;
  1001. unsigned short blank = BUILD_CHAR(' ', control->Attribute);
  1002. for (i = 0; i < MONO_HEIGHT*MONO_WIDTH; i++) {
  1003. *vidptr++ = blank;
  1004. }
  1005. control->XPos = 0;
  1006. control->YPos = 0;
  1007. }
  1008. }
  1009. /***********************************************************************************************
  1010. * Mono_Printf -- Print formatted text to the mono device. *
  1011. * *
  1012. * Prints formatted text to the monochrome device specified. *
  1013. * *
  1014. * INPUT: control -- Pointer to the buffer to print to. *
  1015. * *
  1016. * text -- Pointer to the text to display. *
  1017. * *
  1018. * ... -- Any optional parameters needed by the string. *
  1019. * *
  1020. * OUTPUT: none *
  1021. * *
  1022. * WARNINGS: The final formatted string is limited to 1024 characters long. *
  1023. * *
  1024. * HISTORY: *
  1025. * 01/04/1997 JLB : Created. *
  1026. *=============================================================================================*/
  1027. void Mono_Printf(BuffControl * control, char const * text, ...)
  1028. {
  1029. if (control != NULL) {
  1030. char buf[1024];
  1031. va_list ap;
  1032. va_start(ap, text);
  1033. vsprintf(buf, text, ap);
  1034. Mono_Print(control, buf, strlen(buf));
  1035. va_end(ap);
  1036. }
  1037. }
  1038. /***********************************************************************************************
  1039. * Mono_Set_View_Pos -- Set the mono display ram view offset. *
  1040. * *
  1041. * Set the CRTC register for the monochrome display to the offset specified. The card *
  1042. * defaults to viewing offset 0 (i.e. $B0000 absolute RAM address). *
  1043. * *
  1044. * INPUT: device -- The monochrome device global data. *
  1045. * *
  1046. * pos -- The offset position to set the view to. *
  1047. * *
  1048. * OUTPUT: none *
  1049. * *
  1050. * WARNINGS: none *
  1051. * *
  1052. * HISTORY: *
  1053. * 01/04/1997 JLB : Created. *
  1054. *=============================================================================================*/
  1055. void Mono_Set_View_Pos(MonoGlobals * device, int pos)
  1056. {
  1057. if (device != NULL) {
  1058. WRITE_PORT_UCHAR(device->CRTCRegisters, 0x0C);
  1059. WRITE_PORT_UCHAR(device->CRTCRegisters+1, (unsigned char)(pos >> 8));
  1060. WRITE_PORT_UCHAR(device->CRTCRegisters, 0x0D);
  1061. WRITE_PORT_UCHAR(device->CRTCRegisters+1, (unsigned char)(pos & 0xFF));
  1062. }
  1063. }
  1064. void Mono_Bring_To_Top(MonoGlobals * device, int index)
  1065. {
  1066. if (index == -1 || index == device->CurrentVisible) return;
  1067. Mono_Set_View_Pos(device, index * 100);
  1068. // Mono_Set_View_Pos(device, index * MONO_WIDTH * MONO_HEIGHT);
  1069. device->CurrentVisible = index;
  1070. Mono_Update_Cursor(device);
  1071. }
  1072. void Display_Signon_Banner(BuffControl * control)
  1073. {
  1074. Mono_Printf(control,
  1075. "\fMono Display Driver [mono.sys] -- NT Kernel Mode Device Driver\n"
  1076. "Version: 1.0 -- (" __DATE__ " " __TIME__ ")\n"
  1077. "Device Name: " A_DEVICE_NAME "\n"
  1078. "Symbolic Link: " A_SYMBOLIC_NAME " (\"\\\\.\\MONO\")\n\n");
  1079. Mono_Printf(control, "Supporting IOCTL Services:\n");
  1080. Mono_Printf(control, "--------------------------\n");
  1081. Mono_Printf(control, " [%08X] IOCTL_MONO_PRINT_RAW(char * text, int length)\n", IOCTL_MONO_PRINT_RAW);
  1082. Mono_Printf(control, " [%08X] IOCTL_MONO_CLEAR_SCREEN(void)\n", IOCTL_MONO_CLEAR_SCREEN);
  1083. Mono_Printf(control, " [%08X] IOCTL_MONO_SET_CURSOR(int x, int y)\n", IOCTL_MONO_SET_CURSOR);
  1084. Mono_Printf(control, " [%08X] IOCTL_MONO_SCROLL(void)\n", IOCTL_MONO_SCROLL);
  1085. Mono_Printf(control, " [%08X] IOCTL_MONO_BRING_TO_TOP(void)\n", IOCTL_MONO_BRING_TO_TOP);
  1086. Mono_Printf(control, " [%08X] IOCTL_MONO_SET_ATTRIBUTE(char attrib)\n", IOCTL_MONO_SET_ATTRIBUTE);
  1087. Mono_Printf(control, " [%08X] IOCTL_MONO_PAN(void)\n", IOCTL_MONO_PAN);
  1088. Mono_Printf(control, " [%08X] IOCTL_MONO_LOCK(void) [returns mono memory address]\n", IOCTL_MONO_LOCK);
  1089. Mono_Printf(control, " [%08X] IOCTL_MONO_UNLOCK(void)\n", IOCTL_MONO_UNLOCK);
  1090. }
  1091. /*++
  1092. Routine Description:
  1093. Given a physical address, maps this address into a user mode process's
  1094. address space
  1095. Arguments:
  1096. DeviceObject - pointer to a device object
  1097. IoBuffer - pointer to the I/O buffer
  1098. InputBufferLength - input buffer length
  1099. OutputBufferLength - output buffer length
  1100. Return Value:
  1101. STATUS_SUCCESS if sucessful, otherwise
  1102. STATUS_UNSUCCESSFUL,
  1103. STATUS_INSUFFICIENT_RESOURCES,
  1104. (other STATUS_* as returned by kernel APIs)
  1105. --*/
  1106. void * Mono_Fetch_Ptr(PDEVICE_OBJECT DeviceObject)
  1107. {
  1108. UNICODE_STRING memory_unicode_string;
  1109. OBJECT_ATTRIBUTES object_attribute;
  1110. HANDLE section_handle = NULL;
  1111. NTSTATUS error;
  1112. void * retval = NULL;
  1113. /*
  1114. ** Try to open the PhysicalMemory section. This will be needed when mapping the
  1115. ** physical memory 'file' to an accessable address range. First create a physical
  1116. ** memory object and then convert that object into a handle value.
  1117. */
  1118. RtlInitUnicodeString(&memory_unicode_string, L"\\Device\\PhysicalMemory");
  1119. InitializeObjectAttributes(&object_attribute, &memory_unicode_string, OBJ_CASE_INSENSITIVE, (HANDLE)NULL, (PSECURITY_DESCRIPTOR)NULL);
  1120. error = ZwOpenSection(&section_handle, SECTION_ALL_ACCESS, &object_attribute);
  1121. if (NT_SUCCESS(error)) {
  1122. PHYSICAL_ADDRESS logical_base_address;
  1123. PHYSICAL_ADDRESS physical_address;
  1124. ULONG in_io_space = 0;
  1125. physical_address.HighPart = 0;
  1126. physical_address.LowPart = MONO_MEMORY;
  1127. //
  1128. // Translate the physical addresses.
  1129. //
  1130. if (HalTranslateBusAddress(Isa, 0, physical_address, &in_io_space, &logical_base_address)) {
  1131. PVOID virtual_address = NULL;
  1132. ULONG viewlength = MONO_MEM_LENGTH;
  1133. PHYSICAL_ADDRESS view_base = logical_base_address;
  1134. //
  1135. // Map the section
  1136. //
  1137. error = ZwMapViewOfSection(section_handle, (HANDLE) -1, &virtual_address, 0L, viewlength, &view_base, &viewlength, ViewShare, 0, PAGE_READWRITE | PAGE_NOCACHE);
  1138. if (NT_SUCCESS(error)) {
  1139. //
  1140. // Mapping the section above rounded the physical address down to the
  1141. // nearest 64 K boundary. Now return a virtual address that sits where
  1142. // we want by adding in the offset from the beginning of the section.
  1143. //
  1144. (ULONG) virtual_address += (ULONG)logical_base_address.LowPart - (ULONG)view_base.LowPart;
  1145. retval = virtual_address;
  1146. }
  1147. }
  1148. /*
  1149. ** Close the zone handle before exiting.
  1150. */
  1151. ZwClose(section_handle);
  1152. }
  1153. return(retval);
  1154. }