1 / 33

Device Driver Implementation

Device Driver Implementation. Chapter 14. Topics. Interfaces Autoconfiguration Structures Device Identification Building and Loading Drivers. When a Device Driver is Called (1). I/O Operation kernel calls device driver on behalf of a user level application to open, read, write, or close

doris
Download Presentation

Device Driver Implementation

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Device Driver Implementation Chapter 14

  2. Topics • Interfaces • Autoconfiguration • Structures • Device Identification • Building and Loading Drivers

  3. When a Device Driver is Called (1) • I/O Operation • kernel calls device driver on behalf of a user level application to open, read, write, or close • Interrupt Handling • kernel calls a device driver’s interrupt handler when a hardware interrupt occurs • Special Requests • special requests via ioctl calls

  4. When a Device Driver is Called (2) • Autoconfiguration • kernel calls the driver’s probe, attach, and slave interfaces at system startup to determine what devices are available and to initialize them • User-level requests to the sysconfig utility • kernel calls a device driver’s configure interface • to dynamically configure, unconfigure, query and reconfigure a device • implicit during system boot or driver load • Reinitialization • called by kernel when associated bus (path from CPU) is reset

  5. bus_list[] controller_list[] device_list[] When a Device Driver is Called (3) bdevsw[] System Calls Auto Configuration drv_open() drv_close() .... drv_isr() drv_probe() drv_slave() .... drv_configure() cdevsw[] struct driver _scb /etc/sysconfigtab kload server Interrupts /var/subsys/driver.mod /subsys/driver.mth Dynamic Loading

  6. Device Driver Design Issues • There are many design issues that must be considered prior to writing a driver. • Ideally, the driver will be able to run without recompilation in as many different environments as possible. • Issues include: • System Configuration • static vs. dynamic configuration • autoconfiguration • block vs. character interfaces (or both) • Support for various Alpha buses

  7. Static vs. Dynamic Configuration • It is important to write one device driver that a system manager can statically or dynamically configure into the kernel • static - kernel is rebuilt (doconfig) • dynamic - driver is loaded and controlled via sysconfig • tools are provided to produce a single binary module (.mod)

  8. Autoconfiguration • A process that determines what hardware actually exists during the current instance of the running kernel at static configuration time. • The autoconfiguration software (the bus’s confl1 interface) calls the driver’s probe, attach, and slave interfaces to determine if the devices exist and are functional on a given system • At boot time, system software: • Configures static drivers into a configuration tree • Configures loadable drivers into a configuration tree based on /etc/sysconfigtab.

  9. Device Autoconfiguration System Configuration File bus tc0 at nexus controller fb0 at tc0 vector fbintr controller ipi0 at tc0 vector ipiintr device disk ip1 at ipi0 unit 1 device disk ip2 at ipi0 unit 2 bus vba0 at tc0 slot 2 vector vbaerrors controller sk0 at vba0 csr 0x8000 vector skintr 0xc8 bus vba1 at tc0 slot 1 controller cb0 at vba1 csr 0x80001000 vector cbintr 0x45

  10. Device Autoconfiguration (2)sysconfigtab driver fragment none: Module_Config_Name = none Device_Dir = /dev Device_Char_Major = ANY Device_Char_Minor = 0 Device_Char_Files = none Device_User = root Device_Group = 0 Device_Mode = 666 Device_Major_Req = Same TC_Option = Modname - 'NONE ', Driver_Name - none, Type - C, Adpt_Config - N

  11. The driver structure (1) struct driver { int (*probe)(); /* called during autoconfig for each controller to */ /* register interrupt routine and device switch info */ int (*slave)(); /* optionally called for each device */ int (*cattach)(); /* optionally called for each controller to initialize */ int (*dattach)(); /* optionally called for each slave() returning success */ int (*go)(); /* not currently used */ caddr_t *addr_list; /* list of optional CSR addresses */ char *dev_name /* name of device connected to this controller */ struct device **dev_list; /* indexed by logunit, list of device structs currently connected */ char *ctlr_name; /* name of controller */ struct controller **ctlr_list; /* supports multiple controllers for single driver */ short xclu; /* not currently used */

  12. The driver structure (2) int addr1_size; /* VMEbus only, size in bytes of first CSR area */ int addr1_atype; /* VMEbus only, addr space, transfer size, swap mode */ int addr2_size; /* VMEbus only, size in bytes of second CSR area */ int addr2_atype; /* VMEbus only, addr space, transfer size, swap mode */ int (*ctlr_unattach)(); /* dynamically configured drivers only, undo attach() allocations */ int (*dev_unattach)(); /* dynamically configured drivers only, undo dattach() allocations */ };

  13. Block vs. Character Devices • Historically, there are two sets of interfaces to the kernel, one for character devices and another for block devices. • Drivers defined their interface to the kernel which would load this information into either the character device (cdevsw) or block device (bdevsw) switch table. • To reduce these differences, in V4.0 the dsent structure has been introduced. Thus the differences are less formalized and a driver, indeed, can support both. • The kernel populates both character and block device switch tables with information from the dsent structure. • The device major number is the index into these tables. • Both a character and a block device file may specify the same entry (i.e. major number).

  14. The bdevsw Structure (1) Entry Point Function (*d_open)() Opens the device and fills in structures Verifies device that was identified during autoconfiguration Locks nonshared devices Sets up driver to buffer cache Logs any errors (*d_close)() Closes the device Disks - null routine (*d_strategy)() Takes address of buf structure as argument; Initiates read/write and returns immediately; I/O requests translated by system into block I/O routines bread()/bwrite() calls device strategy with pointer to buffer containing parameters for I/O request If synchronous request, caller sleeps on address of buf structure

  15. The bdevsw Structure (2) Entry Point Function (*d_dump)() Writes all physical memory to the device (*d_psize)() Returns the size of disk partitions dflags Identifies device status (*d_ioctl)() Gets or sets device control status or performs special operations d_funnel Enables or disables on a per-file system basis Enabled means uniprocessor driver support Disabled means multiprocessor/parallelized driver support

  16. The cdevsw Structure (1) Entry Point Function (*d_open)() Performs a function very similar to bdevsw d_open() (*d_close)() Closes the device Disks - null routine Tape - writes EOF marks to mark EOT and rewinds (*d_read)() Reads data from a device; raw devices, calls physio() Terminals - reads request passed to driver (*d_write)() Write data to device; parallels read() above (*d_ioctl)() Performs an operation other than read/write such as get/set device parameters (*d_stop)() Stops output on a device; only meaningful to terminal driver (*d_reset)() Specifies a pointer to an entry point for the driver's reset interface, which stops all current work and places the device connected to the controller in a known state *d_ttys Points to a table of tty structures, if a tty driver

  17. The cdevsw Structure (2) Entry Point Function (*d_select)() Checks device to see if data is available for reading/writing (*d_mmap)() Maps device contents into memory; TURBOchannel only d_funnel Enables or disables on a per-file system basis Enables means uniprocessor driver support Disabled means multiprocessor/parallelized driver support (*d_segmap)() Specifies the segmap entry point d_flags Set to C_DDIDKI if driver is SVR4 DDI/DKI- complaint

  18. The dsent Structure (1) • Instead of separate block and character structures and pointers • Drivers fill in the dsent structure and registers it during its probe() operation by calling devsw_add() • dsent structure elements are the union of the elements in both character and block device switch tables.

  19. The dsent Structure (2) struct dsent { int (*d_open)(); int (*d_close)(); int (*d_strategy)(); int (*d_read)(); int (*d_write)(); int (*d_ioctl)(); int (*d_dump)(); int (*d_psize)(); ... ... int (*d_stop)(); int (*d_reset)(); int (*d_select)(); int (*d_mmap)(); int (*d_segmap)(); struct tty *d_ttys; int d_funnel; int d_bflags; int d_cflags; };

  20. Supporting Multiple Buses • To provide device driver binary compatibility across different bus architectures, different CPU architectures, and different CPU types within the same architecture, • The kernel represents I/O bus address spaces through an I/O handle (io_handle_t). • Device drivers use this handle to reference bus address space (which may be I/O space or Memory space, sparse or dense).

  21. Device Identification • System administrators know devices as • Major number • Identifies type of device • Disk, tape, terminal • Minor number • Identifies instance of device • Disk 5, Tape 2, TTY 3 • Or identifies use of device • Tape 2 in high density • Kernel knows devices as a 32-bit dev_t • ( major_number >> 20 ) + minor_number

  22. Associating cluster and local devices • Cluster device hash +----------+ hw_hash_entry |----0-----|---> __________ |----------| | type | |----------| |----------| |----------| | count | hwc_devt_element (HWC_DEVT_ELE) . |----------| ------------- ------------- . | listptr |----->| next |---->| next |-->... . |----------| |-------------| |-------------| |----------| | hashptr | | devt | | devt | |---255----| ---------- |-------------| |-------------| +----------+ +------------|l_devnodeinfo| |l_devnodeinfo| | |-------------| |-------------| | |c_devnodeinfo|-+ |c_devnodeinfo| | ------------- | ------------- v devnode v devnode ------------- ------------- | HWC_DEVNODE | | HWC_DEVNODE | |=============| |=============| | hwc_devnode | | hwc_devnode | | info | | info | ------------- ------------- (entry in local dbase) (entry in cluster dbase) HWC_DEVNODE_INFO Hash function: ((devt>>24) + (devt>>16) + (devt>>8) + devt) % 255

  23. Building a Driver

  24. Files Related to Static and Dynamic Configuration NAME.list file - static drivers, define where the files are for this driver product (third parties) BINARY.list file - identify the build rules associated with third-party device drivers built into the BINARY Makefile when the driver writer invokes the sourceconfig utility files file fragment - for static drivers delivered in binary form, used by the config program sysconfigtab file fragment - associated with drivers written to conform to the single binary module model so the driver can be statically or dynamically configured into the kernel. Specify the device major number requirements (if any), names and minor numbers of device special files.

  25. /dev/none Configuration Filessysconfigtab fragment none: Module_Config_Name = none Device_Dir = /dev Device_Char_Major = ANY Device_Char_Minor = 0 Device_Char_Files = none Device_User = root Device_Group = 0 Device_Mode = 666 Device_Major_Req = Same TC_Option = Modname - 'NONE ', Driver_Name - none, Type - C, Adpt_Config - N

  26. /dev/none Configuration Filesfiles fragment # This is the files file fragment for the /dev/none driver # used to produce the single binary module. # MODULE/STATIC/none standard Binary io/ESA100/none.c module none

  27. /dev/none Configuration FilesBINARY.list /usr/sys/io/ESA100:

  28. System Management Tools (1) doconfig creates or modifies an existing target configuration file, copies .product.list to NAME.list, creates the device special file information for statically configured drivers, and builds a new kernel (via calling the config program). cfgmgr works with kloadsrv, the kernel load server, to manage device drivers that are dynamically configured into the kernel. device.mth works with driver products to produce the method file (.mth). kmknod uses the information from the driver’s sysconfigtab file fragment and the driver’s attribute table to dynamically create device special files at boot time for statically configured drivers.

  29. System Management Tools (2) kreg maintains the /sys/conf/.product.list system file which registers device driver products that are statically configured into the kernel. sysconfig configures a driver or handles a dynamically configured device driver. Provides a user interface to the cfgmgr framework. osfboot boots a kernel. Contains support for boot link kernels that the doconfig -b command generates. Also supports dynamic booting and foreign devices. sysconfigdb maintains the sysconfigtab database. The driver entries in the sysconfigtab file fragment are appended to this database when the user installs a kernel kit.

  30. Building the Driver (1) • Step 1: Create a directory to contain the driver product files #mkdir /usr/sys/io/ESA100 • Step 2: Copy driver product files into the above directory #cp none.c /usr/sys/io/ESA100 #cp nonereg.h /usr/sys/io/ESA100 • Step 3: Create a none files file fragment to include in the /usr/sys/conf/files file. • Step 4: Create none entry for the /sys/config/BINARY.list file and add. • Step 5: Run the sourceconfig program from /usr/sys/conf # cd /usr/sys/conf # ./sourceconfig BINARY

  31. Building the Driver (2) • Step 6: Run the make program # cd /usr/sys/BINARY # make none.mod • Step 7: Create a sysconfigtab file fragment in /usr/sys/io/ESA100. Run the sysconfigdb utility# cd /usr/sys/io/ESA100 # sysconfigdb -a -f sysconfigtab none

  32. Statically adding the none driver to a kernel • Step 1: Ensure that the none entries are in the /usr/sys/conf/NAME.list, and /usr/sys/conf/files files • Step 2: Run the doconfig program # cd /usr/sys/conf # doconfig -c NAME • Step 3: copy the new kernel to the root directory # cp vmunix /vmunix • Step 4: Shutdown and boot the system # shutdown -b now

  33. Dynamically loading the none driver • Step 1: Ensure that the none sysconfigtab entry was added to the /etc/sysconfig file • Step 2: Link to the single binary module # cd /var/subsys # ln -s /usr/sys/BINARY/none.mod none.mod • Step 3: Link to the method file # cd /var/subsys # ln -s /subsys/device.mth none.mth • Step 4: Run the sysconfig utility # sysconfig -c none

More Related