DRIVER(9)

πŸ’– DRIVER(9) β€” structure describing a device driver πŸ’–

okay bestie, welcome to the DRIVER(9) page from the Kernel Developer's Manual, and no this is not about your rideshare app, this is about the little struct that tells the kernel what your device driver even is. sit down, grab a boba, we're doing kernel internals πŸ§‹βœ¨


✨ SYNOPSIS ✨

first the includes, because obviously:

#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>

then the methods, all static, all taking a device_t like it's the main character:

static int foo_probe(device_t);
static int foo_attach(device_t);
static int foo_detach(device_t);
static int foo_frob(device_t, int, int);
static int foo_twiddle(device_t, char *);

and now the method table, which is literally just a list of vibes the kernel can call:

static device_method_t foo_methods[] = {
        /* Methods from the device interface */
        DEVMETHOD(device_probe,         foo_probe),
        DEVMETHOD(device_attach,        foo_attach),
        DEVMETHOD(device_detach,        foo_detach),

        /* Methods from the bogo interface */
        DEVMETHOD(bogo_frob,            foo_frob),
        DEVMETHOD(bogo_twiddle,         foo_twiddle),

        /* Terminate method list */
        DEVMETHOD_END
};

the driver struct itself, three fields, she's simple, she's iconic:

static driver_t foo_driver = {
        "foo",
        foo_methods,
        sizeof(struct foo_softc)
};

and then the devclass, and the registration. this is the part where it becomes Real:

static devclass_t foo_devclass;

DRIVER_MODULE(foo, bogo, foo_driver, foo_devclass, NULL, NULL);

slay. 🌈


🌸 DESCRIPTION 🌸

so. every driver in the kernel gets described by a driver_t structure, periodt. that struct is holding:

  • the name of the device
  • a pointer to a list of methods
  • an indication of the kind of device which the driver implements
  • the size of the private data the driver needs to associate with a device instance

and every driver implements one or more sets of methods β€” those sets are called interfaces, iykyk. the example driver up there in the synopsis is doing two of them: the standard "driver" interface and the entirely made-up "bogo" interface. fake but functional, we love her πŸ’…


when a driver gets registered with the system β€” that's the DRIVER_MODULE macro doing the work, see DRIVER_MODULE(9) β€” it gets added to the list of drivers living in the devclass of its parent bus type. so like, all PCI drivers end up in the devclass named "pci", and all ISA drivers end up in the devclass named "isa". it's giving assigned seating πŸͺ‘

and why aren't the drivers just chilling inside the device object of the parent bus? bestie, because of multiple instances of a given type of bus. that's the whole reason. don't question it, it's correct.

the DRIVER_MODULE macro is also out here multitasking: it creates the devclass using the name of the driver, and it can optionally call extra initialisation code in the driver β€” you do that by specifying an extra module event handler and argument as the last two arguments. (see those two NULLs in the synopsis? that's the "nah, we're good" option πŸ’€)


πŸ‘€ SEE ALSO πŸ‘€

go read these next, they're all connected, it's a whole cinematic universe:


🫢 AUTHORS 🫢

this manual page was written by Doug Rabson. thank you Doug, absolute legend, king behavior πŸ‘‘


and that's the page!! this came from the Debian crew, dated November 22, 2011 β€” yes she's a Scorpio, and she's still serving DRIVER(9) realness to this very day. go forth and write drivers bestie, you've got this πŸ’–πŸ¦‹πŸŽ€

πŸ“¦ where this page comes from