Driver Development Presentation at WalterCon 2006

Article contributed by axeld on Fri, 2006-10-27 22:00

This is a transcription of the Driver Development Presentation given by Axel Dörfler at WalterCon 2006. The slides in HTML format can be downloaded from here. A video of the presentation is also available for download.

Contents

  1. The Device File System, devfs
  2. Modules
  3. Device Types
  4. Interrupts
  5. Haiku Specials

1. Device File System

Weakly typed directory hierarchy:

  • there is no /dev/eth0, instead, all network devices are in /dev/net/
  • all drivers in a subdirectory usually follow the same API, however this is not enforced
  • drivers can support multiple APIs by publishing more than one device
  • the name of the driver does not need to have any relation to where or what is published, even though you shouldn't abuse this to avoid confusion

For development:

  • use rescan <driver name> to make sure the system reloads your driver after a recompilation
  • for the rescanning to work as expected, the driver must be located in the drivers/bin/ directory - this is the only reason why it's usually not a good idea to put the driver into drivers/dev/
  • Rescanning will only work if no device published by the driver is currently in use

System boot in BeOS:

  • The boot loader needs to load all drivers needed to let the kernel access the boot file system
  • Only the drivers found in certain well known directories are loaded:
    • drivers/dev/
    • drivers/dev/disk/
  • All other drivers are loaded on demand: an application (for example, the media server) looks for devices in /dev/audio, and the devfs will then load all of the drivers it finds in that directory.

System boot in Haiku:

  • It's yet to be determined how exactly the boot loader will do its job
  • If possible, it will use hardware detection to identify which driver need to be loaded so that the kernel can boot further

2. Modules

  • BeOS supports 3 different types of kernel add-ons:
    • drivers
    • file systems
    • modules
  • Haiku's file systems are standard modules; BeOS file systems are not supported
  • Haiku's new device system uses modules only, too, but BeOS drivers are still supported for compatibility
  • There can be several exported modules per add-on:
    	module_info *modules[] = {
    		(module_info *)&scsi_for_sim_module,
    		(module_info *)&scsi_bus_module,
    		(module_info *)&scsi_device_module,
    		(module_info *)&scsi_bus_raw_module,
    		NULL
    	};
  • The module name is determined by its path - plus an additional arbitrary identifier:
    • Name: "bus_managers/scsi/bus/v1"
    • Path: bus_managers/scsi
    • Free Identifier: bus/v1
  • To use a module, you have to get it first:
    	device_manager_info *gManager;
    	status_t status = get_module(B_DEVICE_MANAGER_MODULE_NAME,
    		(module_info **)&gManager);
    	if (status < B_OK) {
    		...
    	}
  • The gManager variable points to the requested module if the above call was successful; the module's exported functions can be used
  • After usage, you have to put the module away again using put_module() so that the system knows that it may unload the module again to save memory
  • Haiku extension: Dependencies
    	locked_pool_interface *gLockedPool;
    	device_manager_info *gManager;
     
    	module_dependency module_dependencies[] = {
    		{B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gManager},
    		{LOCKED_POOL_MODULE_NAME, (module_info **)&gLockedPool},
    		{}
    	};
  • These dependencies are automatically resolved when loading the module - the referenced modules are directly available via the provided variables
  • They will be put away after your module has been uninitialized

3. Device Types

The sub directory determines the function and API of a device:

  • network drivers are in /dev/net
  • disk drivers are in /dev/disk/
  • audio drivers are in /dev/audio/; there are further sub directories which specify the exact function and API, for example old for the R3 style sound interface, or multi for the never finished multi audio interface
  • graphics drivers are in /dev/graphics/, TV and similar drivers can be found in /dev/video/

API? What API?

  • all devices export the same C API
  • the special type depending API is completely exported via the general purpose ioctl() call

ioctl() pitfalls

  • You have to make sure the passed in arguments are valid!
  • You have to make sure any pointers are valid - and stay valid during execution
  • There is no publicly documented way to do the above in BeOS; in Haiku, you have to use user_memcpy() to copy any incoming data before use in the kernel
  • Any application can send any control codes - make extra double sure you can't cause crashes this way
  • BeOS does not preserve the optional length argument when given

Network device drivers

  • Private definitions in ether_driver.h
  • The ETHER_INIT parameters can safely be ignored (they are always 0 for Haiku)
  • The BONE extensions ETHER_GETIFTYPE, and ETHER_GETLINKSTATE will be supported by Haiku as well
  • ETHER_HASIOVECS might not be supported - in that case, a replacement for this mechanism will be implemented (important for speedy Gigabit ethernet)
  • More or less good example implementations: rtl8169 for a Gigabit driver, sis900 for a 10/100MBit driver

Audio device drivers

  • Obsolete R3 definitions in sound.h - this is not supported by Haiku yet
  • R5's multi audio interface was never completely finished or documented (for example, recording never worked)
  • Haiku's current multi audio implementation is not completely compatible, and is therefore called hmulti_audio for the time being
  • Example for the old R3 API: sonic_vibes, usb_audio, sis7018
  • Example for Be's multi audio API: ich97 - this will likely be converted to the new Haiku API, though
  • Example for Haiku's current multi audio API would be: auich

Graphics device drivers (1/2)

  • Special breed because the interface is mostly free
  • The only call is B_GET_ACCELERANT_SIGNATURE to identify the accelerant to be used by the app_server
  • The real app_server API to be implemented is defined in add-ons/graphics/Accelerant.h
  • The interface as defined in GraphicsCard.h is deprecated and won't be supported in Haiku

Graphics device drivers (2/2)

  • Haiku will extend the existing API (in a back- and upwards compatible way), but it's not yet finalized. For example, 32 bit mouse cursors with transparency will be used in Haiku
  • Example implementation to look at: intel_extreme - the exception here is the B_PROPOSE_MODE hook which should be better be used from a different driver at the time of this writing

4. Interrupts

  • An interrupt will be enabled when you install a dedicated handler:
    	status = install_io_interrupt_handler(info.pci->u.h0.interrupt_line,
    		&my_interrupt_handler, (void *)&info, 0);
  • When your driver is closed, you have to remove that handler again using remove_io_interrupt_handler()
  • You get the interrupt line either from the PCI device info structure, or (like PS/2, and other legacy devices) you have a documented fixed line that you have to use

Things to know about interrupt handlers (1/4)

  • You may need to share your interrupt line with another driver; the first thing you should do in that handler is to test that your hardware device generated the interrupt
  • Since a handler is called exclusively on one CPU, it should execute in very little time: the whole CPU is paused for other things while it's executing your code

Things to know about interrupt handlers (2/4)

  • The handler is called with interrupts turned off - no new interrupt can be generated while your handler is on it, at least that's the case for non-legacy edge-triggered interrupts
  • A direct consequence of the two items above: you must not wait in your driver

Things to know about interrupt handlers (3/4)

  • The only real API you can use while in a handler is:
    • release_sem_etc(..., B_DO_NOT_RESCHEDULE)
    • acquire_spinlock()/release_spinlock()
    • get_memory_map() can be currently used, but this may not be possible on all architectures, and may also be deprecated in the future
  • Timer handlers are very similar than interrupts in practice, and the same restrictions apply

Things to know about interrupt handlers (4/4)

  • Sometimes, your BIOS fails to assign an interrupt to your (PCI) device; this is a problem of BeOS that Haiku probably will overcome, but doesn't yet do so; if that happens the interrupt line will be 0x0 or 0xff

5. Haiku Specials

devfs extensions (not necessarily in R1):

  • driver will be able to publish attributes with their devices where, for example, the network MAC address can be shown
  • query support will be implemented as well
  • Also, device writers are encouraged to place unique (serial) identifiers into the attributes - this will allow querying for your particular USB printer (and its settings), no matter where you attached it

New device system (1/2):

  • A device tree is built after the hardware found in the computer
  • The function and device IDs can identify the driver to be used, the system can find the right driver faster
  • Therefore, the system knows which device belongs to which driver; if your sound card already has a driver, it's not needed to look for any other drivers if that's the only sound card in your computer

New device system (2/2):

  • No driver can mess with a device that already has a driver
  • Dynamic publishing and unpublishing of drivers at any time; it's not necessary to pre-publish any devices to make it available (for example, for USB mass storage devices you may put into your computer)
  • You know if your driver was called from within the kernel or from userland
  • Additional read()/write() calls that directly let you access ranges of physical memory

Extended stability and security:

  • New area flag B_USER_CLONEABLE_AREA prevents user code from cloning and inspecting kernel or driver data
  • Defined interface to access user memory:
    • user_memcpy()
    • user_strlcpy()
    • user_memset()