Partially implemented PEB
[reactos.git] / reactos / drivers / dd / blue / blue.c
1
2 #include <internal/mmhal.h>
3 #include <internal/halio.h>
4 #include <internal/hal/page.h>
5 #include <ddk/ntddk.h>
6 #include <string.h>
7 #include <internal/string.h>
8 #include <defines.h>
9 #include <ddk/ntddblue.h>
10
11 //#define NDEBUG
12 #include <internal/debug.h>
13
14 #define IDMAP_BASE (0xd0000000)
15 #define VIDMEM_BASE 0xb8000
16
17 /*
18 * Return a linear address which can be used to access the physical memory
19 * starting at x
20 */
21 extern inline unsigned int physical_to_linear(unsigned int x)
22 {
23 return(x+IDMAP_BASE);
24 }
25
26 extern inline unsigned int linear_to_physical(unsigned int x)
27 {
28 return(x-IDMAP_BASE);
29 }
30
31 #define NR_ROWS 50
32 #define NR_COLUMNS 80
33
34 #define CRTC_COMMAND 0x3d4
35 #define CRTC_DATA 0x3d5
36
37 #define CRTC_CURSORSTART 0x0a
38 #define CRTC_CURSOREND 0x0b
39 #define CRTC_CURSORPOSLO 0x0f
40 #define CRTC_CURSORPOSHI 0x0e
41
42
43
44
45 #define TAB_WIDTH 8
46
47
48 /* NOTES ******************************************************************/
49 /*
50 * [[character][attribute]][[character][attribute]]....
51 */
52
53
54 /* TYPEDEFS ***************************************************************/
55
56 typedef struct _DEVICE_EXTENSION
57 {
58 PBYTE VideoMemory;
59 SHORT CursorX;
60 SHORT CursorY;
61 DWORD CursorSize;
62 BOOL CursorVisible;
63 WORD CharAttribute;
64 DWORD Mode;
65 BYTE ScanLines; /* Height of a text line */
66
67 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
68
69
70
71
72
73 /* FUNCTIONS **************************************************************/
74
75
76 NTSTATUS ScrCreate (PDEVICE_OBJECT DeviceObject, PIRP Irp)
77 {
78 // PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
79 PDEVICE_EXTENSION DeviceExtension;
80 NTSTATUS Status;
81 unsigned int offset;
82
83 DeviceExtension = DeviceObject->DeviceExtension;
84
85 /* initialize device extension */
86 /* get pointer to video memory */
87 DeviceExtension->VideoMemory = (PBYTE)physical_to_linear (VIDMEM_BASE);
88
89 /* get current output position */
90 __asm__("cli\n\t");
91 outb_p (CRTC_COMMAND, CRTC_CURSORPOSLO);
92 offset = inb_p (CRTC_DATA);
93 outb_p (CRTC_COMMAND, CRTC_CURSORPOSHI);
94 offset += (inb_p (CRTC_DATA) << 8);
95 __asm__("sti\n\t");
96
97 DeviceExtension->CursorX = (SHORT)(offset % NR_COLUMNS);
98 DeviceExtension->CursorY = (SHORT)(offset / NR_COLUMNS);
99 DeviceExtension->CursorSize = 5; /* FIXME: value correct?? */
100 DeviceExtension->CursorVisible = TRUE;
101
102
103 DeviceExtension->ScanLines = 8; /* FIXME: read it from CRTC */
104
105
106 /* more initialization */
107 DeviceExtension->CharAttribute = 0x17; /* light grey on blue */
108 DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT |
109 ENABLE_WRAP_AT_EOL_OUTPUT;
110
111 /* FIXME: more initialization?? */
112
113
114 /* show blinking cursor */
115 /* FIXME: calculate cursor size */
116 __asm__("cli\n\t");
117 outb_p (CRTC_COMMAND, CRTC_CURSORSTART);
118 outb_p (CRTC_DATA, 0x47);
119 outb_p (CRTC_COMMAND, CRTC_CURSOREND);
120 outb_p (CRTC_DATA, 0x07);
121 __asm__("sti\n\t");
122
123
124 Status = STATUS_SUCCESS;
125
126 Irp->IoStatus.Status = Status;
127 IoCompleteRequest (Irp, IO_NO_INCREMENT);
128
129 return (Status);
130 }
131
132
133 NTSTATUS ScrWrite (PDEVICE_OBJECT DeviceObject, PIRP Irp)
134 {
135 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
136 PDEVICE_EXTENSION DeviceExtension;
137 NTSTATUS Status;
138 char *pch = Irp->UserBuffer;
139 char *vidmem;
140 int i, j, offset;
141 int cursorx, cursory;
142
143 DeviceExtension = DeviceObject->DeviceExtension;
144 vidmem = DeviceExtension->VideoMemory;
145 cursorx = DeviceExtension->CursorX;
146 cursory = DeviceExtension->CursorY;
147
148 for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
149 {
150 switch (*pch)
151 {
152 case '\b':
153 if (cursorx > 0)
154 {
155 cursorx--;
156 }
157 else if (cursory > 0)
158 {
159 cursorx = NR_COLUMNS - 1;
160 cursory--;
161 }
162 break;
163
164 case '\n':
165 cursory++;
166 cursorx = 0;
167 break;
168
169 case '\r':
170 break;
171
172 case '\t':
173 offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
174 for (j = 0; j < offset; j++)
175 {
176 vidmem[(cursorx * 2) + (cursory * NR_COLUMNS * 2)] = ' ';
177 cursorx++;
178 /*
179 if (cursorx >= NR_COLUMNS)
180 {
181 cursory++;
182 cursorx = 0;
183 }
184 */
185 }
186 break;
187
188 default:
189 vidmem[(cursorx * 2) + (cursory * NR_COLUMNS * 2)] = *pch;
190 vidmem[(cursorx * 2) + (cursory * NR_COLUMNS * 2) + 1] = (char) DeviceExtension->CharAttribute;
191 cursorx++;
192 if (cursorx >= NR_COLUMNS)
193 {
194 cursory++;
195 cursorx = 0;
196 }
197 }
198
199
200 if (cursory >= NR_ROWS)
201 {
202 unsigned short *LinePtr;
203
204 memcpy (vidmem,
205 &vidmem[NR_COLUMNS * 2],
206 NR_COLUMNS * (NR_ROWS - 1) * 2);
207
208 LinePtr = (unsigned short *) &vidmem[NR_COLUMNS * (NR_ROWS - 1) * 2];
209
210 for (j = 0; j < NR_COLUMNS; j++)
211 {
212 LinePtr[j] = DeviceExtension->CharAttribute << 8;
213 }
214 cursory = NR_ROWS - 1;
215 }
216 }
217
218
219 /* Set the cursor position */
220
221 offset = (cursory * NR_COLUMNS) + cursorx;
222
223 outb_p (CRTC_COMMAND, CRTC_CURSORPOSLO);
224 outb_p (CRTC_DATA, offset);
225 outb_p (CRTC_COMMAND, CRTC_CURSORPOSHI);
226 offset >>= 8;
227 outb_p (CRTC_DATA, offset);
228
229 DeviceExtension->CursorX = cursorx;
230 DeviceExtension->CursorY = cursory;
231
232
233 Status = STATUS_SUCCESS;
234
235 Irp->IoStatus.Status = Status;
236 IoCompleteRequest (Irp, IO_NO_INCREMENT);
237
238 return (Status);
239 }
240
241
242
243
244 NTSTATUS ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
245 {
246 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
247 PDEVICE_EXTENSION DeviceExtension;
248 NTSTATUS Status;
249
250
251 DeviceExtension = DeviceObject->DeviceExtension;
252
253 switch (stk->Parameters.DeviceIoControl.IoControlCode)
254 {
255 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
256 {
257 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
258 unsigned int offset;
259
260 __asm__("cli\n\t");
261 outb_p (CRTC_COMMAND, CRTC_CURSORPOSLO);
262 offset = inb_p (CRTC_DATA);
263 outb_p (CRTC_COMMAND, CRTC_CURSORPOSHI);
264 offset += (inb_p (CRTC_DATA) << 8);
265 __asm__("sti\n\t");
266
267 pcsbi->dwCursorPosition.X = (SHORT)(offset % NR_COLUMNS);
268 pcsbi->dwCursorPosition.Y = (SHORT)(offset / NR_COLUMNS);
269
270 pcsbi->dwSize.X = NR_ROWS;
271 pcsbi->dwSize.Y = NR_COLUMNS;
272
273 Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO);
274 Status = STATUS_SUCCESS;
275 }
276 break;
277
278 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
279 {
280 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
281 unsigned int offset;
282
283 DeviceExtension->CursorX = pcsbi->dwCursorPosition.X;
284 DeviceExtension->CursorY = pcsbi->dwCursorPosition.Y;
285
286 offset = (pcsbi->dwCursorPosition.Y * NR_COLUMNS) +
287 pcsbi->dwCursorPosition.X;
288
289 __asm__("cli\n\t");
290 outb_p (CRTC_COMMAND, CRTC_CURSORPOSLO);
291 outb_p (CRTC_DATA, offset);
292 outb_p (CRTC_COMMAND, CRTC_CURSORPOSHI);
293 outb_p (CRTC_DATA, offset>>8);
294 __asm__("sti\n\t");
295
296 Irp->IoStatus.Information = 0;
297 Status = STATUS_SUCCESS;
298 }
299 break;
300
301 case IOCTL_CONSOLE_GET_CURSOR_INFO:
302 {
303 // PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
304
305 // DPRINT("GetConsoleCursorInfo: pcci=%p\n", pcci);
306 // DPRINT("GetConsoleCursorInfo\n");
307 // pcci->dwSize = 10;
308 // pcci->bVisible = FALSE;
309
310 Irp->IoStatus.Information = 0;
311 Status = STATUS_SUCCESS;
312 }
313 break;
314
315 case IOCTL_CONSOLE_SET_CURSOR_INFO:
316 {
317 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
318 BYTE data;
319 DWORD size, height;
320
321 DeviceExtension->CursorSize = pcci->dwSize;
322 DeviceExtension->CursorVisible = pcci->bVisible;
323 height = DeviceExtension->ScanLines;
324 data = (pcci->bVisible) ? 0x40 : 0x20;
325
326 size = (pcci->dwSize * height) / 100;
327 if (size < 1)
328 size = 1;
329
330 data |= (BYTE)(height - size);
331
332 __asm__("cli\n\t");
333 outb_p (CRTC_COMMAND, CRTC_CURSORSTART);
334 outb_p (CRTC_DATA, data);
335 outb_p (CRTC_COMMAND, CRTC_CURSOREND);
336 outb_p (CRTC_DATA, height - 1);
337 __asm__("sti\n\t");
338
339 Irp->IoStatus.Information = 0;
340 Status = STATUS_SUCCESS;
341 }
342 break;
343
344
345
346 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
347 {
348 PFILL_OUTPUT_ATTRIBUTE Buf = (PFILL_OUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
349 char *vidmem;
350 int offset;
351 DWORD dwCount;
352
353 vidmem = DeviceExtension->VideoMemory;
354 offset = (DeviceExtension->CursorY * NR_COLUMNS * 2) +
355 (DeviceExtension->CursorX * 2) + 1;
356
357 CHECKPOINT
358
359 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
360 {
361 vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute;
362 }
363
364 Irp->IoStatus.Information = 0;
365 Status = STATUS_SUCCESS;
366 }
367 break;
368
369 #if 0
370 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
371 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
372 break;
373 #endif
374
375 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
376 DeviceExtension->CharAttribute = (WORD)Irp->AssociatedIrp.SystemBuffer;
377 Irp->IoStatus.Information = 0;
378 Status = STATUS_SUCCESS;
379 break;
380
381
382 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
383 {
384 PFILL_OUTPUT_CHARACTER Buf = (PFILL_OUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
385 char *vidmem;
386 int offset;
387 DWORD dwCount;
388
389 vidmem = DeviceExtension->VideoMemory;
390 offset = (DeviceExtension->CursorY * NR_COLUMNS * 2) +
391 (DeviceExtension->CursorX * 2);
392
393 CHECKPOINT
394
395 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
396 {
397 vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter;
398 }
399
400 Irp->IoStatus.Information = 0;
401 Status = STATUS_SUCCESS;
402 }
403 break;
404
405
406
407 default:
408 Status = STATUS_NOT_IMPLEMENTED;
409 }
410
411 Irp->IoStatus.Status = Status;
412 IoCompleteRequest (Irp, IO_NO_INCREMENT);
413
414 return (Status);
415 }
416
417
418
419
420
421
422 VOID ScrStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
423 {
424 // PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
425
426 }
427
428
429 NTSTATUS ScrDispatch (PDEVICE_OBJECT DeviceObject, PIRP Irp)
430 {
431 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
432 NTSTATUS Status;
433
434 switch (stk->MajorFunction)
435 {
436 case IRP_MJ_CLOSE:
437 Status = STATUS_SUCCESS;
438 break;
439
440 default:
441 Status = STATUS_NOT_IMPLEMENTED;
442 break;
443 }
444
445
446 Irp->IoStatus.Status = Status;
447 IoCompleteRequest (Irp, IO_NO_INCREMENT);
448
449 return (Status);
450 }
451
452
453 /*
454 * Module entry point
455 */
456 STDCALL NTSTATUS
457 DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
458 {
459 PDEVICE_OBJECT DeviceObject;
460 ANSI_STRING adevice_name;
461 UNICODE_STRING device_name;
462 ANSI_STRING asymlink_name;
463 UNICODE_STRING symlink_name;
464
465 DbgPrint ("Screen Driver 0.0.5\n");
466
467 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate;
468 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch;
469 DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch;
470 DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrWrite;
471 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl;
472 DriverObject->DriverStartIo = ScrStartIo;
473
474 RtlInitAnsiString (&adevice_name, "\\Device\\BlueScreen");
475 RtlAnsiStringToUnicodeString (&device_name, &adevice_name, TRUE);
476 IoCreateDevice (DriverObject,
477 sizeof(DEVICE_EXTENSION),
478 &device_name,
479 FILE_DEVICE_SCREEN,
480 0,
481 TRUE,
482 &DeviceObject);
483
484 RtlInitAnsiString (&asymlink_name, "\\??\\BlueScreen");
485 RtlAnsiStringToUnicodeString (&symlink_name, &asymlink_name, TRUE);
486 IoCreateSymbolicLink (&symlink_name, &device_name);
487
488 return (STATUS_SUCCESS);
489 }
490