Professional Documents
Culture Documents
Device Types
Block devices
Random access devices (buffering) For example a file system
can only be mounted on a block device, because it requires
random access.
For example, disks are commonly implemented as block
devices.
Character devices
Sequential access (no buffering). Examples might include
printers, scanners, sound boards, &c.
The same device may have both block and character oriented
interfaces (In other UNIX this would actually require separate
drivers. A block device driver and a raw device driver.)
Major number
Each device driver is identified by a unique major number.
This number is assigned by the Linux Device Registrar (A
human currently Peter.Anvin@linux.org). This number is the
index into an array that contains the information about the
driver (the device_struct)
Minor number
This uniquely identifies a particular instance of a device. For
example, a system may have multiple IDE hard disks each
would have a major number of 3, but a different minor number.
The same device can have both character and block interfaces, so
it can have mappings in both arrays.
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *);
int (*fasync) (int, struct file *, int);
int (*check_media_change) (kdev_t dev);
int (*revalidate) (kdev_t dev);
int (*lock) (struct file *, int, struct file_lock *);
};
int ints[3];
(void)get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] != 0) {
BusLogic_Error("BusLogic: Obsolete Command Line Entry
"Format Ignored\n", NULL);
return 0;
}
if (str == NULL || *str == '\0')
return 0;
return BusLogic_ParseDriverOptions(str);
}
/* This is black magic checksetup() plays in ELF land! */
__setup("BusLogic=", BusLogic_Setup);
The call to the init() function for a driver is hard-coded into the
kernels bootstrap code. For example, a SCSI devices intialization
function could be called within scsi_dev_init() in
drivers/scsi/scsi.c
The init function must register the drivers character and/or block
interface. This installs the mapping between the generic API and
the drivers specific behaviors. Recall that these mappings are
maintained in arrays and were defined by the drivers
file_operation struct.
Unregister()
Nomenclature
Polling Mode
Interrupt Mode
Linux supports three different flavors of Interrupt Mode I/O:
Slow IRQs
These are the most common type of ISR. Slow interrupts can be
interrupted by other interrupts. Before returning to an interrupted
ISR(), the ret_from_sys_call() is used this macro restores the
registers, &c to their original values.
Fast IRQs
This mode is used for very brief ISRs. When fast mode is used,
other interrupts are not allowed. This reduces the overhead
required to invoke the ISR, because less state needs to be
preserved.
Interrupt Sharing
Interrupt sharing is the ability to have one IRQ service multiple
devices. Basically, a chain of ISRs, each for a different device, is
constructed for the IRQ. Each ISR is executed if the interrupt
occurs. The ISRs should be able to interrogate the device to
determine if, in fact, there is any work for them to do.
devname should be the name of the device driver (used in /proc for accounting)
Linux recognizes the fact that interrupt handlers should only take
care of actions that require immediate attention, so it has explicit
support for routines that compose the bottom half of a device
driver.