1 // io/console/vga.cc -- Kernel debugging console for standard VGA text mode
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
15 #include <System/IO.h>
16 #include <kern/kernel.h>
17 #include <kern/console.h>
18 #include <kern/notifier.h>
20 #include <kern/libc.h>
21 #include <kern/addrs.h>
22 #include <util/lock.h>
24 void vga_write(char *str);
28 class VGA : public Console {
32 unsigned long io_base;
38 void putc(int ch, int attr)
42 pos -= pos % line_width;
43 } else if (ch == '\r') {
44 pos -= pos % line_width;
46 // Use ll_swap_le16 rather than store_le16 in the hopes
47 // that the compiler can simply change the shifts around
48 // rather than assembling it one way and then ll_swapping.
50 // It's done as one atomic store rather than two single
51 // byte writes (which would eliminate endianness concerns)
52 // to eliminate the possibility of a race where the video
53 // card reads a character before its attribute has been
56 mem_base[pos++] = ll_swap_le16(ch | (attr << 8));
59 if (pos >= lines * line_width) {
62 // FIXME: until memcpy is more than a stupid byte-at-a-time
63 // loop, this could race with the video card.
65 memcpy(mem_base, mem_base + line_width,
66 line_width * (lines - 1) * sizeof(u16));
68 for (int i = 0; i < line_width; i++)
69 mem_base[pos + i] = ll_swap_le16(' ' | (7 << 8));
76 pos = (u16)ll_in_8(0x3d5) << 8;
78 pos |= ll_in_8(0x3d5);
84 ll_out_8(0x3d5, pos >> 8);
86 ll_out_8(0x3d5, pos & 0xff);
90 #include <servers/io/console/vga/IO/Console/VGA.h>
96 // FIXME: should be PCI mem space, not phys mem.
97 mem_base = (u16 *)Arch::phys_to_kvirt(0xb8000);
104 primary_console = this;
107 void write(Array<octet> buf, u64 *LEN)
109 if (!valid_size_t(*LEN))
110 /* throw something */
116 /* throw something */
119 Lock::AutoSpinLockRecIRQ autolock(lock);
122 for (size_t i = 0; i < len; i++)
128 void write_async(Array<octet> buf, u64 len, Notifier notifier)
131 io_notify(notifier, len, io_result::Success);
135 // Use a static constructor, so that it can be used before
136 // memory management is up and running.
142 #include <servers/io/console/vga/footer.cc>