{"id":411,"date":"2020-08-18T19:23:47","date_gmt":"2020-08-18T20:23:47","guid":{"rendered":"http:\/\/www.linux-tutorial.info\/?page_id=77"},"modified":"2020-08-22T19:26:00","modified_gmt":"2020-08-22T20:26:00","slug":"this-is-the-page-title-toplevel-244","status":"publish","type":"page","link":"http:\/\/www.linux-tutorial.info\/?page_id=411","title":{"rendered":"Device Drivers"},"content":{"rendered":"\n<title>Device Drivers<\/title>\n<p>\nOne of the purposes of an operating system is to hide the peculiarities\nof the system&#8217;s hardware devices from its users.\nFor example the Virtual File System presents a uniform view of the mounted\nfilesystems irrespective of the underlying physical devices.\nThis chapter describes how the Linux <glossary>kernel<\/glossary> manages the\nphysical devices in the system.\n<p>\nThe <glossary>CPU<\/glossary> is not the only intelligent device in the system,\nevery physical\ndevice has its own hardware controller.  The keyboard, mouse and serial ports\nare controlled by a SuperIO chip, the <glossary>IDE<\/glossary> disks by an\nIDE controller, <glossary>SCSI<\/glossary> disks by a SCSI\ncontroller and so on.\nEach hardware controller has its own control and status registers (CSRs)\nand these differ between devices.\nThe CSRs for an Adaptec 2940 SCSI controller are completely different from\nthose of an NCR 810 SCSI controller.\nThe CSRs are used to start and stop the device, to initialize it and to diagnose\nany problems with it.\nInstead of putting code to manage the hardware controllers\ninto every application, the code is kept in the Linux <glossary>kernel<\/glossary>.\nThe software that handles or manages a hardware controller is known as a device\ndriver.\nThe Linux kernel device drivers are, essentially, a <glossary>shared library<\/glossary> of\nprivileged,\nmemory resident, low level hardware handling routines.\nIt is Linux&#8217;s device drivers that handle the peculiarities of the devices they\nare managing.\n<p>\n<!-- REPEAT -->\n<p>\nLinux supports three types of hardware devices: character, block and network.\nCharacter devices are read and written directly without buffering, for example\nthe system&#8217;s <glossary>serial<\/glossary> ports \/dev\/cua0 and \/dev\/cua1.\nBlock devices can only be written to and read from in multiples of the block\nsize, typically 512 or 1024 bytes.\nBlock devices are accessed via the buffer cache and may be randomly accessed,\nthat is to say, any block can be read or written no matter where it is on the device.\nBlock devices can be accessed via their device special file but more commonly\nthey are accessed via the file system.\nOnly a block device can support a mounted file system.\nNetwork devices are accessed via the BSD <glossary>socket<\/glossary> interface\nand the networking subsytems described in the section on networking.\n<p>\nThere are many different device drivers in the Linux kernel (that is one of\nLinux&#8217;s strengths) but they all share some common attributes:\n<dl compact>\n<p>\n\t<dt><b>Kernel code<\/b><\/dt><dd> Device drivers are part of the kernel and, like\n\tother code within the kernel, if they go wrong they can seriously\n\tdamage the system.\n\tA badly written driver may even crash the system, possibly corrupting\n\tfile systems and losing data.\n<p>\n\t<dt><b>Kernel interfaces<\/b><\/dt><dd> Device drivers provide a standard interface\n        to the Linux kernel or to the appropriate subsystem.\n        For example, the terminal driver provides a file I\/O interface\n\tto the Linux kernel and a <glossary>SCSI<\/glossary> device driver provides a\n        SCSI device interface to the SCSI subsystem which, in turn, provides both\n\tfile I\/O and buffer cache interfaces to the kernel.\n<p>\n\t<dt><b>Kernel mechanisms and services<\/b><\/dt><dd> Device drivers make use of\n\tstandard kernel services such as memory allocation, interrupt delivery\n\tand wait queues to operate.\n<p>\n\t<dt><b>Loadable<\/b><\/dt><dd> Most of the Linux device drivers can be loaded on\n        demand as kernel modules when\n\tthey are needed and unloaded when they are no longer being used. This makes the\n\tkernel very adaptable and efficient with the system&#8217;s resources.\n<p>\n\t<dt><b>Configurable<\/b><\/dt><dd> Linux device drivers can be built into the\n        kernel. Which devices are built is configurable when the kernel is compiled.\n<p>\n\t<dt><b>Dynamic<\/b><\/dt><dd>\n        As the system boots and each device driver is initialized it looks for the\n        hardware devices that it will control. If those devices do not exist (maybe\n        are just not found), the device driver is simply redundant and causes no\n        harm apart from occupying a little of the system&#8217;s memory.\n<\/dl>\n<p>\n<h2>Memory<\/h2>\nDevice drivers have to be careful when using memory.\nAs they are part of the Linux kernel they cannot use virtual memory.\nEach time a device driver runs, maybe as an interrupt is received or as a bottom\nhalf or task queue handler is scheduled, the current  process may change.\nThe device driver cannot rely on a particular process running even if it is\ndoing work on its behalf.\nLike the rest of the kernel, device drivers use data structures to keep track of\nthe device they controll.\nThe kernel would become unnecessarily large if these data structures were\nstatically allocated, part of the device driver&#8217;s code.\nMost device drivers allocate kernel, non-paged, memory to hold their data.\n<p>\nLinux provides <glossary>kernel<\/glossary> memory allocation and deallocation routines and it is\nthese that the device drivers use.\nKernel memory is allocated in chunks that are powers of 2.\nFor example 128 or 512 bytes, even if the device driver asks for less.\nThe number of bytes that the device driver requests is rounded up to the next\nblock size boundary.\nThis makes kernel memory deallocation easier as the smaller free blocks can be\nrecombined into bigger blocks.\n<p>\nIt may be that Linux needs to do quite a lot of extra work when the\n<glossary>kernel<\/glossary>\nmemory is requested. If the amount of free memory is low, physical pages may\nneed to be discarded or written to the swap device.\nNormally, Linux would suspend the requestor, putting the process onto a wait\nqueue until there is enough physical memory.\nNot all device drivers (or indeed Linux kernel code) may want this to happen and\nso the kernel memory allocation routines can be requested to fail if they cannot\nimmediately allocate memory.\n<p>\nThe device driver can also specify that it wants to <glossary>DMA<\/glossary> to and from the memory\nit allocates. It is the Linux kernel, not the device driver, however, that takes\ncare of the details. This way it is the Linux kernel rather than the device\ndriver decides what constitutes DMA&#8217;able memory for the system.\n<p>\n<h2>Interfacing Device Drivers with the Kernel<\/h2>\nTo ensure that access is always done in the correct manner, the Linux kernel must be able\nto interact with device drivers in standard ways.\nEach class of device driver, character, block and network, provides common\ninterfaces that the kernel uses when requesting services from them. These common\ninterfaces mean that the kernel can treat often very different devices and their\ndevice drivers absolutely the same. For example, <glossary>SCSI<\/glossary> and\n<glossary>IDE<\/glossary> disks behave very differently but the Linux kernel\nuses the same interface to both of them.\n<p>\nLinux is very dynamic, every time a Linux kernel boots it may encounter\ndifferent physical devices and thus need different device drivers.\nLinux allows you to include device drivers at kernel build time via its\nconfiguration scripts. When these drivers are initialized at boot time they may\nnot discover any hardware to control.\nOther drivers can be loaded as kernel modules when they are needed.\nTo cope with this dynamic nature of device drivers, device drivers\nregister themselves with the kernel as they are initialized.\nLinux maintains tables of registered device drivers as part of its interfaces\nwith them.\nThese tables include pointers to routines and information that supports\nthe interface with the device class.\n<p>\n<h3>Character Devices<\/h3>\n<p>\nFigure: Character Devices\n<p>\nCharacter devices, the simplest of Linux&#8217;s devices, are accessed as files,\napplications use standard system calls to open them, read from them, write\nto them and close them exactly as if the device were a file.\nThis is true even if the device is a modem being used by the PPP daemon\nto connect a Linux system onto a network.\nAs a character device is initialized its device driver registers itself with\nthe Linux <glossary>kernel<\/glossary> by adding an entry into the\nchrdevs vector of device_struct data structures.\nThe device&#8217;s major device identifier (for example 4 for the tty\ndevice) is used as an index into this vector.\nThe major device identifier for a device is fixed.\n<p>\nEach entry in the chrdevs vector, a\ndevice_struct data structure contains two elements: a pointer to the\nname of the registered device driver and a pointer to a block of file\noperations.\nThis block of file operations is itself the addresses of routines within the\ncharacter device driver, each of which handles  specific file operations\nsuch as open, read, write and close.\nThe contents of <file type=\"\">\/proc\/devices<\/file> for character devices is taken from\nthe chrdevs vector.\n<p>\nWhen a character special file representing a character device (for example\n<device>\/dev\/cua0<\/device>) is opened, the kernel must set things up so that the correct\ncharacter device driver&#8217;s file operation routines will be called.\nJust like an ordinairy file or directory, each device special file is\nrepresented by a <glossary>VFS<\/glossary> <glossary>inode<\/glossary> .\nThe VFS inode for a character special file, indeed for all device special\nfiles, contains both the major and minor identifiers for the device.\nThis VFS inode was created by the underlying filesystem, for example\nEXT2, from information in the real filesystem when the device\nspecial file&#8217;s name was looked up.\n<p>\nEach <glossary>VFS<\/glossary> <glossary>inode<\/glossary> has associated with it a set of file operations and these are\ndifferent depending on the filesystem object that the inode represents.\nWhenever a VFS inode representing a character special file is created,\nits file operations are set to the default character device operations.\n<p>\nThis has only one file operation, the open file operation.\nWhen the character special file is opened by an application the generic\nopen file operation uses the device&#8217;s major identifier as an index into the\nchrdevs vector to retrieve the file\noperations block for this particular device.\nIt also sets up the file data structure describing this character\nspecial file, making its file operations pointer point to those of the\ndevice driver.\nThereafter all of the applications file operations will be mapped to\ncalls to the character devices set of file operations.\n<p>\n<h3>Block Devices<\/h3>\nBlock devices also support being accessed like files.\nThe mechanisms used to provide the correct set of file operations for\nthe opened block special file are very much the same as for character\ndevices. Linux maintains the set of registered block devices as the\nblkdevs vector. It, like the chrdevs vector, is indexed\nusing the device&#8217;s major device number.\nIts entries are also device_struct data structures.\nUnlike character devices, there are classes of block devices.\nSCSI devices are one such class and IDE devices are another.\nIt is the class that registers itself with the Linux kernel and provides\nfile operations to the kernel.\nThe device drivers for a class of block device provide class specific\ninterfaces to the class.\nSo, for example, a SCSI device driver has to provide interfaces to the\nSCSI subsystem which the SCSI subsystem uses to provide file operations\nfor this device to the kernel.\n<p>\nEvery block device driver must provide an interface to the buffer cache\nas well as the normal file operations interface.\nEach block device driver fills in its entry in the\nblk_dev vector  of blk_dev_struct data structures.\nThe index into this vector is, again, the device&#8217;s major number.\nThe blk_dev_struct data structure consists of the address of a\nrequest routine and a pointer to a list of request data structures,\neach one representing a request from the buffer cache for the driver to\nread or write a block of data.\n<p>\n<img decoding=\"async\" src=\"blk_dev.gif\"><br \/>\nFigure: Buffer Cache Block Device Requests\n<p>\nEach time the buffer cache wishes to read or write a block of data to or\nfrom a registered device it adds a request data structure onto its\nblk_dev_struct.\nThe figure above shows that each request has a\npointer to one or more\nbuffer_head data structures,\neach one a request to read or write a block of data.\nThe buffer_head structures are locked (by the buffer cache) and there\nmay be a process  waiting on the block operation to this buffer to complete.\nEach request structure is allocated from a static list, the\nall_requests\nlist.\nIf the request is being added to an empty request list, the driver&#8217;s\nrequest function is called to start processing the request queue.\nOtherwise the driver will simply process every request on the request\nlist.\n<p>\nOnce the device driver has completed a request it must remove each of the\nbuffer_head structures from the request structure, mark them\nas up to date and unlock them.\nThis unlocking of the buffer_head will wake up any process that has\nbeen sleeping waiting for the block operation to complete.\nAn example of this would be where a file name is being resolved and the\nEXT2 filesystem must read the block of data that contains the\nnext EXT2 directory entry from the block device that holds the\nfilesystem.\nThe process sleeps on the buffer_head that will contain the directory\nentry until the device driver wakes it up.\nThe request data structure is marked as free so that it can be used\nin another block request.\n<p>\n<h2>Hard Disks<\/h2>\n<!-- REPEAT -->\n<img decoding=\"async\" src=\"gendisk.gif\"><br \/>\nFigure: Linked list of disks\n<p>\nDuring initialization Linux maps the topology of the hard disks in the\nsystem.It finds out how many hard disks there are and of what type.\nAdditionally, Linux discovers how the individual disks have been partitioned.\nThis is all represented by a list of gendisk data structures pointed at\nby the gendisk_head list pointer. As each disk subsystem, for example <glossary>IDE<\/glossary>, is\ninitialized it generates gendisk data structures representing\nthe disks that it finds. It does this at the same time as it registers its file operations\nand adds its entry into the blk_dev data structure.\nEach gendisk data structure has a unique major device number and these\nmatch the major numbers of the block special devices.\nFor example, the <glossary>SCSI<\/glossary> disk subsystem creates a single gendisk entry\n(&#8220;sd&#8221;) with a major number of 8, the major number of all SCSI disk devices.\nFigure&nbsp;<a href=\"#gendisk-figure\"> 8.3<\/a> shows two gendisk entries,\nthe first one for the SCSI disk subsystem and the second for an IDE disk controller.\nThis is ide0, the primary IDE controller.\n<p>\nAlthough the disk subsystems build the gendisk entries during their\ninitialization they are only used by Linux during partition checking.\nInstead, each disk subsystem maintains its own data structures which allow it to\nmap device special major and minor device numbers to partitions within physical disks.\nWhenever a block device is read from or written to, either via the buffer cache\nor file operations, the kernel directs the operation to the appropriate device using the\nmajor device number found in its block special device file (for example \/dev\/sda2).\nIt is the individual device driver or subsystem that maps the minor device\nnumber to the real physical device.\n<p>\nDetails of the physical charactistics of hard disks can be found <site id=\"126\">here<\/site>.\n<question id=\"\" type=\"mc\" text=\"Which of the following represents the first IDE hard disk on your system?\" \/>\n<h3>IDE Disks<\/h3>\n<p>\n<!-- Is the size limitation still true? Then 180 GB are EIDE. -->\nThe most common disks used in Linux systems today are Integrated Disk Electronic\nor IDE disks. IDE is a disk interface rather than an I\/O bus like SCSI.\nEach IDE controller can support up to two disks, one the master disk and the\nother the slave disk. The master and slave functions are usually set by jumpers on the disk.\nThe first IDE controller in the system is known as the primary IDE controller,\nthe next the secondary controller and so on. IDE can manage about 3.3 Mbytes per second\nof data transfer to or from the disk and the maximum <file type=\"\">IDE<\/file> disk size is 538Mbytes.\nExtended IDE, or EIDE, has raised the disk size to a maximum of 8.6 Gbytes and\nthe data transfer rate up to 16.6 Mbytes per second. IDE and EIDE disks are cheaper than\nSCSI disks and most modern PCs contain one or more\non board IDE controllers.\n<p>\nLinux names <glossary>IDE<\/glossary> disks in the order in which it finds their controllers.\nThe master disk on the primary controller is <device>\/dev\/hda<\/device> and the slave\ndisk is <device>\/dev\/hdb<\/device>.\n\/dev\/hdc is the master disk on the secondary IDE controller.\nThe IDE subsystem registers IDE controllers and <em>not<\/em> disks with the\nLinux kernel.\nThe major identifier for the primary IDE controller is 3 and is 22 for the\nsecondary IDE controller.\nThis means that if a system has two IDE controllers there will be entries for\nthe IDE subsystem at indices at 3 and 22 in the blk_dev and blkdevs vectors.\nThe block special files for IDE disks reflect this numbering, disks\n<device>\/dev\/hda<\/device> and <device>\/dev\/hdb<\/device>,\nboth connected to the primary IDE controller, have a major identifier of 3.\nAny file or buffer cache operations for the IDE subsystem operations on these\nblock special files\nwill be directed to the IDE subsystem as the kernel uses the major identifier as\nan index.\nWhen the request is made, it is up to the IDE subsystem to work out which IDE\ndisk the request is for.\nTo do this  the IDE subsystem uses the minor device number from the device\nspecial identifier, this\ncontains information that allows it to direct the request to the correct\npartition of the correct\ndisk. The device identifier for <device>\/dev\/hdb<\/device>, the slave IDE drive on the primary\nIDE controller is <em>(3,64)<\/em>.\nThe device identifier for the first partition of that disk (<device>\/dev\/hdb1<\/device>)\nis <em>(3,65)<\/em>.\n<p>\nMore details of the physical charactistics of IDE drives can be found <site id=\"126\">here<\/site>.\n<h3>Initializing the IDE Subsystem<\/h3>\n<p>\nIDE disks have been around for much of the IBM PC&#8217;s history.\nThroughout this time the interface to these devices has changed.\nThis makes the initialization of the IDE subsystem more complex than it might at\nfirst appear.\n<p>\nThe maximum number of IDE controllers that Linux can support is 4.\nEach controller is represented by an ide_hwif_t data structure in the\nide_hwifs vector. Each ide_hwif_t data structure contains two ide_drive_t data\nstructures, one per possible supported master and slave IDE drive.\nDuring the initializing of the IDE subsystem, Linux first looks to see if there\nis information about the disks present in the system&#8217;s CMOS memory.\nThis is battery backed memory that does not lose its contents when the PC is\npowered off. This CMOS memory is actually in the system&#8217;s real time clock device which always\nruns no matter if your PC is on or off.\nThe CMOS memory locations are set up by the system&#8217;s BIOS and tell Linux what\nIDE controllers and drives have been found.\nLinux retrieves the found disk&#8217;s geometry from BIOS and uses the information to\nset up the ide_hwif_t data structure for this drive.\nMore modern PCs use PCI chipsets such as Intel&#8217;s 82430 VX chipset which includes\na PCI EIDE controller. The IDE subsystem uses PCI BIOS callbacks to locate the PCI (E)IDE\ncontrollers in the system. It then calls PCI specific interrogation routines for those chipsets\nthat are present.\n<p>\nOnce each IDE interface or controller has been discovered, its\nide_hwif_t is set up to reflect the\ncontrollers and attached disks.\nDuring operation the IDE driver writes commands to IDE command registers that\nexist in the I\/O memory space.\nThe default I\/O address for the primary IDE controller&#8217;s control and status\nregisters is <em>0x1F0<\/em> &#8211; <em>0x1F7<\/em>.\nThese addresses were set by convention in the early days of the IBM PC.\nThe IDE driver registers each controller with the Linux block buffer cache and\nVFS, adding it to the\nblk_dev and blkdevs vectors respectively.\nThe IDE drive will also request control of the appropriate interrupt.\nAgain these interrupts are set by convention to be 14 for the primary IDE\ncontroller and 15 for the secondary\nIDE controller.\nHowever, they like all IDE details, can be overridden by command  line options\nto the kernel.\nThe IDE driver also adds a gendisk entry into the list of\ngendisk&#8217;s discovered during boot for\neach IDE controller found.\nThis list will later be used to discover the partition tables of all of the hard\ndisks found at boot time.\nThe partition checking code understands that IDE controllers may each control\ntwo IDE disks.\n<p>\n<question id=\"\" type=\"mc\" text=\"Which of the following represents the first SCSI  hard disk on your system?\" \/>\n<h3>SCSI Disks<\/h3>\n<p>\nThe SCSI (Small Computer System Interface) bus is an efficient peer-to-peer\ndata bus that supports up to eight devices per bus, including one or more\nhosts. Each device has to have a unique identifier and this is usually set by\njumpers on the disks.\nData can be transfered synchronously or asynchronously between any two\ndevices on the bus and with 32 bit wide data transfers up to 40 Mbytes per\nsecond are possible.\nThe SCSI bus transfers both data and state information between devices, and\na single transaction between an <em>initiator<\/em> and a <em>target<\/em> can\ninvolve up to eight distinct phases.\nYou can tell the current phase of a SCSI bus from five signals from the\nbus.\nThe eight phases are:\n<dl compact>\n<p>\n\t<dt><b>BUS FREE<\/b><\/dt><dd>  No device has control of the bus and there are\n\t\tno transactions currently happening,\n\t<dt><b>ARBITRATION<\/b><\/dt><dd> A SCSI device has attempted to get control of\n\t\tthe SCSI bus, it does this by asserting its SCSI identifer\n\t\tonto the address pins.  The highest number SCSI identifier\n\t\twins.\n\t<dt><b>SELECTION<\/b><\/dt><dd> When a device has succeeded in getting control of\n\t\tthe SCSI bus through arbitration it must now signal the target\n\t\tof this SCSI request that it wants to send a command to it.\n\t\tIt does this by asserting the SCSI identifier of the target\n\t\ton the address pins.\n\t<dt><b>RESELECTION<\/b><\/dt><dd> SCSI devices may disconnect during the\nprocessing\n\t\tof a request.  The target may then reselect the initiator.\n\t\tNot all SCSI devices support this phase.\n\t<dt><b>COMMAND<\/b><\/dt><dd> 6,10 or 12 bytes of command can be transfered from\n\t\tthe initiator to the target,\n\t<dt><b>DATA IN, DATA OUT<\/b><\/dt><dd> During these phases data is transfered\n\t\tbetween the initiator and the target,\n\t<dt><b>STATUS<\/b><\/dt><dd> This phase is entered after completion of all\ncommands\n\t\tand allows the target to send a status byte indicating\n\t\tsuccess or failure to the initiator,\n\t<dt><b>MESSAGE IN, MESSAGE OUT<\/b><\/dt><dd> Additional information is\ntransfered\n\t\tbetween the initiator and the target.\n<\/dl>\n<p>\nThe Linux SCSI subsystem is made up of two basic elements, each of which is\nrepresented by\ndata structures:\n<dl compact>\n<p>\n\t<dt><b>host<\/b><\/dt><dd> A SCSI host is a physical piece of hardware, a SCSI\ncontroller.\n\tThe NCR810 PCI SCSI controller is an example of a SCSI host.\n\tIf a Linux system has more than one SCSI controller of the same type, each\ninstance\n\twill be represented by a separate SCSI host.\n\tThis means that a SCSI device driver may control more than one instance of its\ncontroller.\n\tSCSI hosts are almost always the <em>initiator<\/em> of SCSI commands.\n<p>\n\t<dt><b>Device<\/b><\/dt><dd> The most common set of SCSI device is a SCSI disk\nbut the SCSI standard supports\n\tseveral more types; tape, CD-ROM and also a generic SCSI device.\n\tSCSI devices are almost always the <em>targets<\/em> of SCSI commands.  These\ndevices must be\n\ttreated differently, for example with removable media such as CD-ROMs or tapes,\nLinux needs\n\tto detect if the media was removed.\n\tThe different disk types have different major device numbers, allowing Linux to\ndirect\n\tblock device requests to the appropriate SCSI type.\n<\/dl>\n<p>\nDetails of the physical charactistics of SCSI drives\ncan be found <site id=\"126\">here<\/site>.\n<p>\n<h4>Initializing the SCSI Subsystem<\/h4>\n<p>\nInitializing the SCSI subsystem is quite complex, reflecting the dynamic nature\nof SCSI buses and their\ndevices.\nLinux initializes the SCSI subsystem at boot time; it finds the SCSI controllers\n(known as SCSI hosts) in the system\nand then probes each of their SCSI buses finding all of their devices.\nIt then initializes those devices and makes them available to the rest of the\nLinux kernel via the\nnormal file and buffer cache block device operations.\nThis initialization is done in four phases:\n<p>\nFirst, Linux finds out which of the SCSI host adapters, or controllers, that\nwere built into the  kernel at kernel build time have hardware to control.\nEach built in SCSI host has a Scsi_Host_Template\nentry in the builtin_scsi_hosts vector\nThe Scsi_Host_Template data structure contains pointers to routines\nthat carry out SCSI host specific\nactions such as detecting what SCSI devices are attached to this SCSI host.\nThese routines are called by the SCSI subsystem as it configures itself and they\nare part of the SCSI device driver supporting this host type.\nEach detected SCSI host, those for which there are real SCSI devices attached,\nhas its Scsi_Host_Template data structure added to the scsi_hosts list\nof active SCSI hosts. Each instance of a detected host type is represented by a Scsi_Host\ndata structure held in the scsi_hostlist list.\nFor example a  system with two NCR810 PCI SCSI controllers would have two\nScsi_Host entries in the list, one per controller.\nEach Scsi_Host points at the Scsi_Host_Template representing its device driver.\n<p>\n<img decoding=\"async\" src=\"scsi.gif\"><br \/>\nFigure: SCSI Data Structures<\/center>\n>\n<p>\nNow that every SCSI host has been discovered, the SCSI subsystem must find\nout what SCSI devices are attached to each host&#8217;s bus.\nSCSI devices are numbered between 0 and 7 inclusively, each device&#8217;s number or\nSCSI identifier being unique on the SCSI bus to which it is attached.\nSCSI identifiers are usually set by jumpers on the device.\nThe SCSI initialization code finds each SCSI device on a SCSI bus by sending it\na TEST_UNIT_READY command. When a device responds, its identification is read by sending\nit an ENQUIRY command.\nThis gives Linux the vendor&#8217;s name and the device&#8217;s model and revision names.\nSCSI commands are represented by a Scsi_Cmnd data structure and these\nare passed to the device driver for this SCSI host by calling the device driver routines within its Scsi_Host_Template data structure. Every SCSI device that is found is represented by a Scsi_Device data structure, each of which points to its parent Scsi_Host. All of the Scsi_Device data structures are added to the scsi_devices list.\nThe figure above shows how the main data structures relate to one another.\n<p>\nThere are four SCSI device types: disk, tape, CD and generic. Each of these SCSI types are\nindividually registered with the kernel as different major block device types. However\nthey will only register themselves if one or more of a given SCSI device type has been\nfound. Each SCSI type, for example SCSI disk,  maintains its own tables of devices.\nIt uses these tables to direct kernel block operations (file or buffer cache) to\nthe correct device driver or SCSI host.\nEach SCSI type is represented by a Scsi_Device_Template data structure.\nThis contains information about this type of SCSI device and the addresses of\nroutines to perform various tasks.\nThe SCSI subsystem uses these templates to call the SCSI type routines for each\ntype of SCSI device.In other words, if the SCSI subsystem wishes to attach a SCSI\ndisk device it will call the SCSI disk type\nattach routine. The Scsi_Type_Template data structures are added to the\nscsi_devicelist\nlist if one or more <glossary>SCSI<\/glossary> devices of that type have been detected.\n<p>\nThe final phase of the SCSI subsystem initialization is to call the finish\nfunctions for each registered\nScsi_Device_Template.\nFor the SCSI disk type this spins up all of the SCSI disks that were found and\nthen records their disk geometry.\nIt also adds the gendisk data structure representing all SCSI disks to\nthe linked list of disks shown\nin the figure above.\n<p>\n<h4>Delivering Block Device Requests<\/h4>\nOnce Linux has initialized the SCSI subsystem, the SCSI devices may be used.\nEach active SCSI device type registers itself with the kernel so that Linux can\ndirect block device requests to it.\nThere can be buffer cache requests via blk_dev or file operations\nvia blkdevs. Taking a SCSI disk driver that has one or more EXT2 filesystem partitions as an\nexample, how do kernel\nbuffer requests get directed to the right SCSI disk when one of its EXT2\npartitions is mounted?\n<p>\nEach request to read or write a block of data to or from a SCSI disk partition\nresults in a new request structure being added to the SCSI disks\ncurrent_request list in the blk_dev vector.\nIf the request list is being processed, the buffer cache need not do\nanything else; otherwise\nit must nudge the SCSI disk subsystem to go and process its request queue.\nEach SCSI disk in the system is represented by a Scsi_Disk data\nstructure. These are kept in the rscsi_disks vector that is indexed using\npart of the SCSI disk partition&#8217;s minor device number.\nFor exmaple, \/dev\/sdb1 has a major number of 8 and a minor number of\n17; this generates an index of 1. Each Scsi_Disk data structure contains a pointer to the\nScsi_Device data structure representing this device.\nThat in turn points at the Scsi_Host data structure which &#8220;owns&#8221; it.\nThe request data structures from the buffer cache are translated into\nScsi_Cmd structures describing the SCSI command that needs to be sent to the SCSI device and this is queued onto the Scsi_Host structure representing this device.\nThese will be processed by the individual SCSI device driver once the\nappropriate data blocks have been read or written.\n<p>\n<h2>Network Devices<\/h2>\n<p>\nA network device is, so far as Linux&#8217;s network subsystem is concerned, an entity\nthat sends and receives packets of data.\nThis is normally a physical device such as an ethernet card.\nSome network devices though are software only such as the loopback device which\nis used for sending data to yourself.\nEach network device is represented by a device data structure.\nNetwork device drivers register the devices that they control with Linux during\nnetwork initialization at kernel boot time.\nThe device data structure contains information about the device and the\naddresses of functions that allow\nthe various supported network protocols to use the device&#8217;s services.\nThese functions are mostly concerned with transmitting data using the network\ndevice. The device uses standard networking support mechanisms to pass received data up\nto the appropriate protocol layer.\nAll network data (packets) transmitted and received are represented by\nsk_buff data structures, these are\nflexible data structures that allow network protocol headers to be easily added\nand removed. How the network protocol layers use the network devices, how they pass data back\nand forth using sk_buff data structures is described in detail in the Networks chapter\n(Chapter&nbsp;<a href=\"#networks-chapter\"> networks-chapter<\/a>).\nThis chapter concentrates on the device data structure and on how\nnetwork devices are discovered\nand initialized.\n<p>\nThe device data structure contains information about the network\ndevice:\n<dl compact>\n<p>\n\t<dt><b>Name<\/b><\/dt><dd> Unlike block and character devices which have their\ndevice special files created\n\t\tusing the <command>mknod<\/command> command, network device special\nfiles appear spontaniously as the\n\t\tsystem&#8217;s network devices are discovered and initialized.\n\t\tTheir names are standard, each name representing the type of device that it\nis.\n\t\tMultiple devices of the same type are numbered upwards from 0.  Thus the\nethernet\n\t\tdevices are known as <device>\/dev\/eth0<\/device>,<device>\/dev\/eth1<\/device>,<device>\/dev\/eth2<\/device>\nand so on. Some common network devices are:\n<p>\n<table><tr><td>\n\t\t<device>\/dev\/ethN<\/device>   \t<\/td><td>\tEthernet devices\n<tr><td>\n\t\t<device>\/dev\/slN<\/device>\t<\/td><td>\tSLIP devices\n<tr><td>\n\t\t<device>\/dev\/pppN<\/device>\t<\/td><td>\tPPP devices\n<tr><td>\n\t\t<device>\/dev\/lo<\/device> \t<\/td><td>\tLoopback devices<\/table>\n\t<dt><b>Bus Information<\/b><\/dt><dd> This is information that the device driver\nneeds in order to control\n\t\tthe device.   The <em>irq<\/em> number is the interrupt that this device is\nusing.\n\t\tThe <em>base address<\/em> is the address of any of the device&#8217;s control and\nstatus registers\n\t\tin I\/O memory.  The <em>DMA channel<\/em> is the DMA channel number that this\nnetwork device is using.\n\t\tAll of this information is set at boot time as the device is initialized.\n<p>\n\t<dt><b>Interface Flags<\/b><\/dt><dd> These describe the characteristics and\nabilities of the network device:\n<p>\n<table><tr><td>\n\t\tIFF_UP\t\t\t<\/td><td>\tInterface is up and running,\n<tr><td>\n\t\tIFF_BROADCAST\t\t<\/td><td>\tBroadcast address in device is valid\n<tr><td>\n\t\tIFF_DEBUG\t\t<\/td><td>\tDevice debugging turned on\n<tr><td>\n\t\tIFF_LOOPBACK\t\t<\/td><td>\tThis is a loopback device\n<tr><td>\n\t\tIFF_POINTTOPOINT\t<\/td><td>\tThis is point to point link (SLIP and PPP)\n<tr><td>\n\t\tIFF_NOTRAILERS\t\t<\/td><td>\tNo network trailers\n<tr><td>\n\t\tIFF_RUNNING\t\t<\/td><td>\tResources allocated\n<tr><td>\n\t\tIFF_NOARP\t\t<\/td><td> \tDoes not support ARP protocol\n<tr><td>\n\t\tIFF_PROMISC\t\t<\/td><td>\tDevice in promiscuous receive mode, it will receive\n<tr><td>\n\t\t\t\t\t<\/td><td>\tall packets no matter who they are addressed to\n<tr><td>\n\t\tIFF_ALLMULTI\t\t<\/td><td>\tReceive all IP multicast frames\n<tr><td>\n\t\tIFF_MULTICAST\t\t<\/td><td>\tCan receive IP multicast frames<\/table>\n\t<dt><b>Protocol Information<\/b><\/dt><dd> Each device describes how it may be\nused by the network protocool layers:\n<dl compact>\n\t\t\t<dt><b><glossary>mtu<\/glossary><\/b><\/dt><dd> The size of the largest packet that this network can\ntransmit not including any\n\t\t\t\tlink layer headers that it needs to add.   This maximum is used by the\nprotocol layers,\n\t\t\t\tfor example <glossary>IP<\/glossary>, to select suitable packet sizes to send.\n\t\t\t<dt><b>Family<\/b><\/dt><dd> The family indicates the protocol family that the\ndevice can support.\tThe\n\t\t\t\tfamily for all Linux network devices is AF_INET, the Internet address\nfamily.\n\t\t\t<dt><b>Type<\/b><\/dt><dd> The hardware interface type describes the media that\nthis network device is\n\t\t\t\tattached to.  There are many different types of media that Linux network\ndevices\n\t\t\t\tsupport.  These include Ethernet, X.25, Token Ring, Slip, PPP and Apple\nLocaltalk.\n\t\t\t<dt><b>Addresses<\/b><\/dt><dd> The device data structure holds a\nnumber of addresses that are relevant\n\t\t\t\tto this network device, including its IP addresses.\n\t\t<\/dl>\n\t<dt><b>Packet Queue<\/b><\/dt><dd> This is the queue of sk_buff packets\nqueued waiting to be transmitted on\n\t\tthis network device,\n\t<dt><b>Support Functions<\/b><\/dt><dd> Each device provides a standard set of\nroutines that protocol layers\n\t\tcall as part of their interface to this device&#8217;s link layer.   These include\nsetup and\n\t\tframe transmit routines as well as routines to add standard frame headers and\ncollect\n\t\tstatistics.  These statistics can be seen using the <font\nface=\"helvetica\">ifconfig<\/font> command.\n<\/dl>\n<p>\n<h3>Initializing Network Devices<\/h3>\n<p>\nNetwork device drivers can, like other Linux device drivers, be built into the\nLinux kernel.\nEach potential network device is represented by a device data structure\nwithin the\nnetwork device list pointed at by dev_base list pointer.\nThe network layers call one of a number of network device service routines whose\naddresses\nare held in the device data structure if they need device specific work\nperforming.\nInitially though, each device data structure holds only the address of\nan initialization or probe\nroutine.\n<p>\nThere are two problems to be solved for network device drivers.\nFirstly, not all of the network device drivers built into the Linux kernel will\nhave devices to control.\nSecondly, the ethernet devices in the system are always called\n<device>\/dev\/eth0<\/device>, <device>\/dev\/eth1<\/device> and so on, no\nmatter what their underlying device drivers are.\nThe problem of &#8220;missing&#8221; network devices is easily solved.\nAs the initialization routine for each network device is called, it returns a\nstatus indicating\nwhether or not it located an instance of the controller that it is driving.\nIf the driver could not find any devices, its entry in the device list\npointed at by\ndev_base is removed.\nIf the driver could find a device it fills out the rest of the device\ndata structure with information\nabout the device and the addresses of the support functions within the network\ndevice driver.\n<p>\nThe second problem, that of dynamically assigning ethernet devices to the\nstandard <device>\/dev\/ethN<\/device> device\nspecial files is solved more elegantly.\nThere are eight standard entries in the devices list; one for eth0,\neth1 and so on to eth7.\nThe initialization routine is the same for all of them, it tries each ethernet\ndevice driver built into\nthe kernel in turn until one finds a device.\nWhen the driver finds its ethernet device it fills out the ethN\ndevice data structure,\n which it now owns.\nIt is also at this time that the network device driver initializes the physical\nhardware that it\nis controlling and works out which IRQ it is using, which DMA channel (if any)\nand so on.\nA driver may find several instances of the network device that it is controlling\nand, in this case, it will take\nover several of the \/dev\/ethN device data structures.\nOnce all eight standard \/dev\/ethN have been allocated, no more ethernet\ndevices will be probed for.\n","protected":false},"excerpt":{"rendered":"<p>Device Drivers One of the purposes of an operating system is to hide the peculiarities of the system&#8217;s hardware devices from its users. For example the Virtual File System presents a uniform view of the mounted filesystems irrespective of the &hellip; <a href=\"http:\/\/www.linux-tutorial.info\/?page_id=411\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-411","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/411","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=411"}],"version-history":[{"count":1,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/411\/revisions"}],"predecessor-version":[{"id":539,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/411\/revisions\/539"}],"wp:attachment":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=411"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}