Lecture 16 - Writing Device Drivers

Last time we talked about device drivers.

The /dev/secret is a device that can be written a secret to. If there's a secret, it can only be read by the device owner. If there's no space then it returns ENOSPACE.

If you remember our minix structure:

Pasted image 20241030103902.png

It may be that A talks to the file system, which talks to the disk driver, which talks to the process management. For example:

echo "boo" > /dev/secret
cat /dev/secret

Rather than testing with the high level programs echo and cat, you can write a program that reads/writes directly to /dev/secret to see what the read/write is actually doing.

Every MINIX driver has a "Dev Hello" introduction to writing device drivers which just gives some started template code. For example:

init();
for(;;){
	recv(msg);
	switch(msg m_type){
		//... do something on receiving a message
	}
	send(reply);
}
cleanup();

The two users you care about here are:

  1. The m_source: the source of the message
  2. The identity of the process actually doing the IO: IO_ENDPT

In Version 3.0 it's PROC_NR, but in 3.3 it's USER_ENDPT.

Message Types

  1. DEV_OPEN: Trying to be opened. Decide if you want to be opened.
    • If the person talking to you (get via getnusercred() gives you this) is the person that made the secret, then respond okay and give the fd.
    • If not then respond with an error code.
  2. DEV_CLOSE: You want to close the given fd.

Just count the number of DEV_OPEN's that were okayed, and DEV_CLOSE's and see that they match. Look at the terminal docs in man and the header files that explain what these messages do in more detail.

To read and write:

  1. DEV_SCATTER_S
  2. DEV_GATHER_S

These take a vector of IO operations (but you can just use one if you need). You'll want to keep track of when these operations also happen.

Another type:

  1. HARD_INT: you got a hardware interrupt. This shouldn't happen since there's no hardware but it should handle it.
  2. DEV_IOCTL
  3. CANCEL: certain long systems calls can be interupted by a signal. This says to try to end a long operation. If you get this then you probably are already done so say "yeah cool".
  4. SYS_SIG

Keep in mind we'll have to copy memory to/from a process's virtual address space to our own. Now that's a high-admin process (you don't want a malicious program to change say a ra for another one), so then we'll either:

  1. Read the sys.conf page an learn every admin privilege your program needs
  2. Just use the "Hello World" driver template and hope that it's the same level (hint: it is).

Structure of the Driver

Other than the code above for handling messages, there's a System Expect Framework (SEF) that generalizes all the open(), close(),... functions that all drivers are required.

The cc is the C-compiler kit. Don't use gcc.