Skip to content

Serial

The serial port on an x86(_64) computer is an interface used to connect a terminal emulator to so you can get output. This might be useful before you get a full terminal working on a framebuffer.

You can setup the serial port with the following code but make sure you have functions in place for port I/O

#define SERIAL_PORT 0x3F8

volatile bool serial_works = false;

void setup_serial() {
    outb(SERIAL_PORT + 1, 0x00);
    outb(SERIAL_PORT + 3, 0x80);
    outb(SERIAL_PORT + 0, 0x01);
    outb(SERIAL_PORT + 1, 0x00);
    outb(SERIAL_PORT + 3, 0x03);
    outb(SERIAL_PORT + 2, 0xC7);
    outb(SERIAL_PORT + 4, 0x0B);
    outb(SERIAL_PORT + 4, 0x1E);
    outb(SERIAL_PORT + 0, 0xAE);

    if(inb(SERIAL_PORT + 0) != 0xAE) {
        serial_works = false;
    }

    outb(SERIAL_PORT + 4, 0x0F);
    serial_works = true;
}

This will configure the serial port to 115200 8N1 mode and then you can use the next functions to get and send data to the port

int serial_received() {
    return inb(SERIAL_PORT + 5) & 1;
}

int is_transmit_empty() {
    return inb(SERIAL_PORT + 5) & 0x20;
}

char read_serial() {
    while (serial_received() == 0);

    return inb(SERIAL_PORT);
}

int write_serial(char *string, int write_length) {
    while (is_transmit_empty() == 0);

    int i = 0;

    while (string[i] != '\0' && (i < write_length)) {
        char c = string[i];

        // qemu serial terminal and maybe others expect \r\n and not just \n while you might use just \n so convert
        if (c == '\n') {
            outb(SERIAL_PORT, '\r');
        }

        outb(SERIAL_PORT, c);
        i++;
    }

    return i;
}

Notes

  • On QEMU CRTL-ALT-3 will bring up the serial port output
  • Can you perhaps setup an interrupt handler on IRQ4 (The first serial port) to get input without polling?