From: Ben Pfaff Date: Thu, 2 Sep 2004 23:27:56 +0000 (+0000) Subject: Reorganization, comments. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pintos-anon;a=commitdiff_plain;h=7180597203a54c08582b1bb092dc465ec1d26d7c Reorganization, comments. --- diff --git a/src/devices/serial.c b/src/devices/serial.c index 8d1633f..e5b2fb7 100644 --- a/src/devices/serial.c +++ b/src/devices/serial.c @@ -4,23 +4,9 @@ #include "io.h" #include "timer.h" -static void -set_serial (int bps, int bits, enum parity_type parity, int stop) -{ - int baud_base = 1843200 / 16; /* Base rate of 16550A. */ - uint16_t divisor = baud_base / bps; /* Clock rate divisor. */ - - /* Enable DLAB. */ - outb (LCR_REG, make_lcr (bits, parity, stop, false, true)); - - /* Set baud rate. */ - outb (LS_REG, divisor & 0xff); - outb (MS_REG, divisor >> 8); - - /* Reset DLAB. */ - outb (LCR_REG, make_lcr (bits, parity, stop, false, false)); -} +static void set_serial (int bps, int bits, enum parity_type parity, int stop); +/* Initializes the serial port device. */ void serial_init (void) { @@ -30,6 +16,7 @@ serial_init (void) outb (MCR_REG, 0); /* Turn off output lines. */ } +/* Sends BYTE to the serial port. */ void serial_outb (uint8_t byte) { @@ -37,3 +24,22 @@ serial_outb (uint8_t byte) continue; outb (THR_REG, byte); } + +/* Configures the first serial port for BPS bits per second, + BITS bits per byte, the given PARITY, and STOP stop bits. */ +static void +set_serial (int bps, int bits, enum parity_type parity, int stop) +{ + int baud_base = 1843200 / 16; /* Base rate of 16550A. */ + uint16_t divisor = baud_base / bps; /* Clock rate divisor. */ + + /* Enable DLAB. */ + outb (LCR_REG, make_lcr (bits, parity, stop, false, true)); + + /* Set baud rate. */ + outb (LS_REG, divisor & 0xff); + outb (MS_REG, divisor >> 8); + + /* Reset DLAB. */ + outb (LCR_REG, make_lcr (bits, parity, stop, false, false)); +} diff --git a/src/devices/timer.c b/src/devices/timer.c index 4271c73..d23bed3 100644 --- a/src/devices/timer.c +++ b/src/devices/timer.c @@ -7,14 +7,10 @@ #error 8254 timer requires TIMER_FREQ >= 19 #endif +/* Number of timer ticks since OS booted. */ static volatile int64_t ticks; -static void -irq20_timer (struct intr_frame *args UNUSED) -{ - ticks++; - intr_yield_on_return (); -} +static intr_handler_func timer_interrupt; /* Sets up the 8254 Programmable Interrupt Timer (PIT) to interrupt PIT_FREQ times per second, and registers the @@ -30,9 +26,10 @@ timer_init (void) outb (0x40, count & 0xff); outb (0x40, count >> 8); - intr_register (0x20, 0, INTR_OFF, irq20_timer, "8254 Timer"); + intr_register (0x20, 0, INTR_OFF, timer_interrupt, "8254 Timer"); } +/* Returns the number of timer ticks since the OS booted. */ int64_t timer_ticks (void) { @@ -42,13 +39,15 @@ timer_ticks (void) return t; } +/* Returns the number of timer ticks elapsed since THEN, which + should be a value once returned by timer_ticks(). */ int64_t timer_elapsed (int64_t then) { return timer_ticks () - then; } -/* Suspends execution for approximately DURATION milliseconds. */ +/* Suspends execution for approximately MS milliseconds. */ void timer_msleep (int64_t ms) { @@ -59,14 +58,26 @@ timer_msleep (int64_t ms) continue; } +/* Suspends execution for approximately US microseconds. + Note: this is ridiculously inaccurate. */ void timer_usleep (int64_t us) { timer_msleep (us / 1000 + 1); } +/* Suspends execution for approximately NS nanoseconds. + Note: this is ridiculously inaccurate. */ void timer_nsleep (int64_t ns) { timer_msleep (ns / 1000000 + 1); } + +/* Timer interrupt handler. */ +static void +timer_interrupt (struct intr_frame *args UNUSED) +{ + ticks++; + intr_yield_on_return (); +} diff --git a/src/devices/vga.c b/src/devices/vga.c index 28235af..fdddd91 100644 --- a/src/devices/vga.c +++ b/src/devices/vga.c @@ -5,86 +5,128 @@ #include "lib.h" #include "mmu.h" -static size_t vga_cols, vga_rows; -static size_t vga_x, vga_y; -static uint16_t *vga_base; +/* VGA text screen support. See [FREEVGA] for more information. */ -void -vga_init (void) -{ - vga_cols = 80; - vga_rows = 25; - vga_base = (uint16_t *) ptov (0xb8000); - vga_cls (); -} +/* Number of columns and rows on the text display. */ +#define COL_CNT 80 +#define ROW_CNT 25 -void -vga_cls (void) -{ - size_t i; - for (i = 0; i < vga_cols * vga_rows; i++) - vga_base[i] = 0x0700; - vga_x = vga_y = 0; -} +/* Current cursor position. (0,0) is in the upper left corner of + the display. */ +static size_t cx, cy; -static void -vga_newline (void) -{ - vga_x = 0; - vga_y++; - if (vga_y >= vga_rows) - { - vga_y = vga_rows - 1; - memmove (vga_base, vga_base + vga_cols, - vga_cols * (vga_rows - 1) * 2); - memset (vga_base + vga_cols * (vga_rows - 1), - 0, vga_cols * 2); - } -} +/* Attribute value for gray text on a black background. */ +#define GRAY_ON_BLACK 0x07 -static void -move_cursor (void) +/* Framebuffer. See [FREEVGA] under "VGA Text Mode Operation". + The character at (x,y) is fb[y][x][0]. + The attribute at (x,y) is fb[y][x][1]. */ +static uint8_t (*fb)[COL_CNT][2]; + +static void clear_row (size_t y); +static void cls (void); +static void newline (void); +static void move_cursor (void); + +/* Initializes the VGA text display and clears the screen. */ +void +vga_init (void) { - uint16_t cp = (vga_x + vga_cols * vga_y); - outw (0x3d4, 0x0e | (cp & 0xff00)); - outw (0x3d4, 0x0f | (cp << 8)); + fb = ptov (0xb8000); + cls (); } +/* Writes C to the VGA text display, interpreting control + characters in the conventional ways. */ void vga_putc (int c) { switch (c) { case '\n': - vga_newline (); + newline (); break; case '\f': - vga_cls (); + cls (); break; case '\b': - if (vga_x > 0) - vga_x--; + if (cx > 0) + cx--; break; case '\r': - vga_x = 0; + cx = 0; break; case '\t': - vga_x = (vga_x + 8) / 8 * 8; - if (vga_x >= vga_cols) - vga_newline (); + cx = ROUND_UP (cx + 1, 8); + if (cx >= COL_CNT) + newline (); break; default: - vga_base[vga_x + vga_y * vga_cols] = 0x0700 | c; - vga_x++; - if (vga_x >= vga_cols) - vga_newline (); + fb[cy][cx][0] = c; + fb[cy][cx][1] = GRAY_ON_BLACK; + if (++cx >= COL_CNT) + newline (); break; } + /* Update cursor position. */ move_cursor (); } + +/* Clears the screen and moves the cursor to the upper left. */ +static void +cls (void) +{ + size_t y; + + for (y = 0; y < ROW_CNT; y++) + clear_row (y); + + cx = cy = 0; + move_cursor (); +} + +/* Clears row Y to spaces. */ +static void +clear_row (size_t y) +{ + size_t x; + + for (x = 0; x < COL_CNT; x++) + { + fb[y][x][0] = ' '; + fb[y][x][1] = GRAY_ON_BLACK; + } +} + +/* Advances the cursor to the first column in the next line on + the screen. If the cursor is already on the last line on the + screen, scrolls the screen upward one line. */ +static void +newline (void) +{ + cx = 0; + cy++; + if (cy >= ROW_CNT) + { + cy = ROW_CNT - 1; + memmove (&fb[0], &fb[1], sizeof fb[0] * (ROW_CNT - 1)); + clear_row (ROW_CNT - 1); + } +} + +/* Moves the hardware cursor to (cx,cy). */ +static void +move_cursor (void) +{ + /* See [FREEVGA] under "Manipulating the Text-mode Cursor". */ + uint16_t cp = cx + COL_CNT * cy; + outw (0x3d4, 0x0e | (cp & 0xff00)); + outw (0x3d4, 0x0f | (cp << 8)); +} + diff --git a/src/devices/vga.h b/src/devices/vga.h index a859dea..2221034 100644 --- a/src/devices/vga.h +++ b/src/devices/vga.h @@ -2,7 +2,6 @@ #define HEADER_VGA_H 1 void vga_init (void); -void vga_cls (void); void vga_putc (int); #endif /* vga.h */