XV6 Device Driver

Why we have a Driver?

A driver is the code in an operating system that manages a particular device: 1. It tells the device hardware to perform operations,. 2. Configures the device to generate interrupts when done. 3. Handles the resulting interrupts,. 4. Interacts with processes that may be waiting for I/O from the device.

Initialization

Config Hardware

Xv6’s main calls consoleinit (kernel/console.c:189) to initialize the UART hardware, and to configure the UART hardware to generate input interrupts (kernel/uart.c:34).

void
consoleinit(void)
{
  initlock(&cons.lock, “cons”);

  uartinit();

  // connect read and write system calls
  // to consoleread and consolewrite.
  devsw[CONSOLE].read = consoleread;
  devsw[CONSOLE].write = consolewrite;
}

Create console device

In init.c, create a console device:

The file path is console, type is T_DEVICE.

mknod implementation.

At this point, we have a console device. A file descriptor 0 points to this device.

How to read or write from device

Let’s look at fileread

If the file type is DEVICE, we call the special read function to perform read operation. Note: The special read is set up in consoleinit.

consoleread sleeps and wait for a line of inputs, then copy to user space. Details see flow section.

Flow

Every input char generates an interrupt

When the user types a character, the UART hardware asks the RISC-V to raise an interrupt.

Trap handler determines interrupt source

xv6’s trap handling code calls devintr (kernel/trap.c:177). devintr looks at the RISC-V scause register to discover that the interrupt is from an external device. Then it asks a hardware unit called the PLIC [1] to tell it which device interrupted (kernel/trap.c:186). If it was the UART, devintrcalls uartintr.

Accumulate inputs and Wake up

Read one char and hand over

uartintr (kernel/uart.c:84) reads any waiting input characters from the UART hardware and hands them to consoleintr.

Accumulate inputs

The job of consoleintr is to accumulate input characters in cons.buf until a whole line arrives.

Wake up when get a whole line

When a newline arrives, consoleintr wakes up a waiting consoleread (if there is one).

Copy to user space

Once woken, consoleread will observe a full line in cons.buf, copy it to user space and return to user space.

Question:

How does open(“console", O_RDWR) opens a file with DEVICE type?

Research: It seems this console string is defined somewhere. I tried to change to other string, and it does not work. Using this console string to open file, the file inode returns a file with type is DEVICE.

Answer:

OS create a console device using system call mknod. Any read or write with console is interacting with the UART hardware.

Last updated

Was this helpful?