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