File tree Expand file tree Collapse file tree 6 files changed +100
-0
lines changed
Expand file tree Collapse file tree 6 files changed +100
-0
lines changed Original file line number Diff line number Diff line change 1+ ../14-checkpoint/Makefile
Original file line number Diff line number Diff line change 1+ * Concepts you may want to Google beforehand: I/O ports*
2+
3+ ** Goal: Learn how to use the VGA card data ports**
4+
5+ We will use C to communicate with devices via I/O registers and ports.
6+
7+ Open ` drivers/ports.c ` and examine the inline C assembler syntax. It has
8+ some differences, like the order of the source and destination operands,
9+ and the funny syntax to assign variables to operands.
10+
11+ When you understand the concepts, open ` kernel/kernel.c ` for an example
12+ of use.
13+
14+ In this example we will examine the I/O ports which map the screen cursor
15+ position. Specifically, we will query port ` 0x3d4 ` with value ` 14 ` to request
16+ the cursor position high byte, and the same port with ` 15 ` for the low byte.
17+
18+ When this port is queried, it saves the result in port ` 0x3d5 `
19+
20+ Don't miss the opportunity to use ` gdb ` to inspect the value of C variables,
21+ since we still can't print them on the screen. To do so, set a breakpoint
22+ for a specific line, ` breakpoint kernel.c:21 ` and use the ` print ` command
23+ to examine variables. Aren't you glad now that we invested some time in
24+ compiling the cross-compiled gdb? ;)
25+
26+ Finally, we will use the queried cursor position to write a character
27+ at that location.
Original file line number Diff line number Diff line change 1+ ../14-checkpoint/boot
Original file line number Diff line number Diff line change 1+ /**
2+ * Read a byte from the specified port
3+ */
4+ unsigned char port_byte_in (unsigned short port ) {
5+ unsigned char result ;
6+ /* Inline assembler syntax
7+ * !! Notice how the source and destination registers are switched from NASM !!
8+ *
9+ * '"=a" (result)'; set '=' the C variable '(result)' to the value of register e'a'x
10+ * '"d" (port)': map the C variable '(port)' into e'd'x register
11+ *
12+ * Inputs and outputs are separated by colons
13+ */
14+ __asm__("in %%dx, %%al" : "=a" (result ) : "d" (port ));
15+ return result ;
16+ }
17+
18+ void port_byte_out (unsigned short port , unsigned char data ) {
19+ /* Notice how here both registers are mapped to C variables and
20+ * nothing is returned, thus, no equals '=' in the asm syntax
21+ * However we see a comma since there are two variables in the input area
22+ * and none in the 'return' area
23+ */
24+ __asm__("out %%al, %%dx" : : "a" (data ), "d" (port ));
25+ }
26+
27+ unsigned short port_word_in (unsigned short port ) {
28+ unsigned short result ;
29+ __asm__("in %%dx, %%ax" : "=a" (result ) : "d" (port ));
30+ return result ;
31+ }
32+
33+ void port_word_out (unsigned short port , unsigned short data ) {
34+ __asm__("out %%ax, %%dx" : : "a" (data ), "d" (port ));
35+ }
Original file line number Diff line number Diff line change 1+ unsigned char port_byte_in (unsigned short port );
2+ void port_byte_out (unsigned short port , unsigned char data );
3+ unsigned short port_word_in (unsigned short port );
4+ void port_word_out (unsigned short port , unsigned short data );
Original file line number Diff line number Diff line change 1+ #include "../drivers/ports.h"
2+
3+ void main () {
4+ /* Screen cursor position: ask VGA control register (0x3d4) for bytes
5+ * 14 = high byte of cursor and 15 = low byte of cursor. */
6+ port_byte_out (0x3d4 , 14 ); /* Requesting byte 14: high byte of cursor pos */
7+ /* Data is returned in VGA data register (0x3d5) */
8+ int position = port_byte_in (0x3d5 );
9+ position = position << 8 ; /* high byte */
10+
11+ port_byte_out (0x3d4 , 15 ); /* requesting low byte */
12+ position += port_byte_in (0x3d5 );
13+
14+ /* VGA 'cells' consist of the character and its control data
15+ * e.g. 'white on black background', 'red text on white bg', etc */
16+ int offset_from_vga = position * 2 ;
17+
18+ /* Now you can examine both variables using gdb, since we still
19+ * don't know how to print strings on screen. Run 'make debug' and
20+ * on the gdb console:
21+ * breakpoint kernel.c:21
22+ * continue
23+ * print position
24+ * print offset_from_vga
25+ */
26+
27+ /* Let's write on the current cursor position, we already know how
28+ * to do that */
29+ char * vga = 0xb8000 ;
30+ vga [offset_from_vga ] = 'X' ;
31+ vga [offset_from_vga + 1 ] = 0x0f ; /* White text on black background */
32+ }
You can’t perform that action at this time.
0 commit comments