Device Driver Implementation

33
ital UNIX Internals II Device Driver Implementatio Device Driver Implementation Chapter 14

description

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 - PowerPoint PPT Presentation

Transcript of Device Driver Implementation

Page 1: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

Device Driver Implementation

Chapter 14

Page 2: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

Topics

• Interfaces• Autoconfiguration• Structures• Device Identification• Building and Loading Drivers

Page 3: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 4: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 5: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

When a Device Driver is Called (3)

drv_open()

drv_close()

....

drv_isr()

drv_probe()

drv_slave()

....

drv_configure()

bdevsw[]

cdevsw[]

_scb

System Calls

Interrupts

bus_list[]

controller_list[]

struct driver

AutoConfiguration

device_list[]

/etc/sysconfigtabkload server

Dynamic Loading

/var/subsys/driver.mod

/subsys/driver.mth

Page 6: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 7: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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)

Page 8: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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.

Page 9: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 10: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 11: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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 */

Page 12: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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 */

};

Page 13: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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).

Page 14: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 15: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 16: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 17: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 18: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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.

Page 19: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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;

};

Page 20: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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).

Page 21: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 22: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 23: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

Building a Driver

Page 24: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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.

Page 25: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

/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

Page 26: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

/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

Page 27: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

/dev/none Configuration FilesBINARY.list

/usr/sys/io/ESA100:

Page 28: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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.

Page 29: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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.

Page 30: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 31: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 32: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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

Page 33: Device Driver Implementation

Digital UNIX Internals II Device Driver Implementation

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