290 likes | 716 Views
Linux Device Management. Adam Dai, Krzysztof Kuzara, and Shaun Batterton Computer Science & Engineering Department The University of Connecticut 191 Auditorium Road, Box U-155 Storrs, CT 06269-3155. Device Management. Types of Devices Block, character, network Create a Device Node mknod
E N D
Linux Device Management Adam Dai, Krzysztof Kuzara, and Shaun Batterton Computer Science & Engineering Department The University of Connecticut 191 Auditorium Road, Box U-155 Storrs, CT 06269-3155
Device Management • Types of Devices • Block, character, network • Create a Device Node • mknod • Register Devices with kernel register_chrdev(unsigned int major, const char * name, struct file_operations * fops); register_blkdev(unsigned int major, const char * name, struct file_operations * fops); • Remap device functions with device driver • Open, read, write • Install the device driver as a module • insmod
Device Management • Device Node > ls –l /dev/mydev crw-rw-rw- 1 root 3, 0 Nov 30 1999 mydev Character device major number minor number
Device Management Approaches • Four Approaches • Direct I/O w/Polling to Detect I/O Completion • Interrupt Driven I/O - Software Controlled • Memory Mapped I/O • Direct Memory Access to Limit CPU Usage
Direct I/O with Polling • Device management polls device to detect operation’s completion • Linux Device -- Direct I/O with Polling • lp driver (line printer) • Code example static int lp_char_polled(char lpchar, int minor) { int status = 0, wait = 0; unsigned long count = 0; do { status = LP_S(minor); count ++; if(need_resched) schedule(); } while(!LP_READY(minor,status) && count < LP_CHAR(minor)); if (count == LP_CHAR(minor)) { return 0; /* we timed out, and the character was /not/ printed */ } outb_p(lpchar, LP_B(minor)); . .
Interrupt Driven I/O • Device management polls device to detect operation’s completion • Linux Device – Interrupt Driven I/O • lp driver (line printer) • Code example static int lp_char_interrupt(char lpchar, int minor) { int wait = 0; unsigned char status; if (!((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY) || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY) || !((status = LP_S(minor)) & LP_PACK) || (status & LP_PBUSY)) { if (!LP_CAREFUL_READY(minor, status)) return 0; outb_p(lpchar, LP_B(minor)); . .
Interrupts • Interrupt Occurs • User Process running • Stops user process • System transitions to kernel mode • Kernel responds to interrupt • Control returned to user process • User process continues where it left off • Linux Running in kernel mode • Stops own execution • Kernel responds to interrupt • Kernel continues where it left off before interrupt
Interrupt ReQuests (IRQs) • IRQ • Notification to CPU from hardware device • Responding to IRQ • CPU jumps to Interrupt Handler • aka Interrupt Service Routine (ISR) • Address in memory previously registered with the kernel • Function that kernel executes to service interrupt • Interrupt lines • Limited resourse (15 or 16) • System dependant
Interrupt ReQuests (IRQs) • Module requests interrupt channel • At device open • Releases channel when done • At initialization • Prevents any other driver from using the interrupt • Kernel keeps registry of interrupt line • Each device is associated with an IRQ number • Enables the CPU to tell which device generated the interrupt • Enable device to run correct interrupt handler
Interrupt Handler/Disabling Interrupts • Initializing the IRQ interface request_irq(unsigned int irq, void (*handler)(), unsigned long flags, const char *device, void *dev_id); free_irq(unsigned int irq, void *dev_id); These calls are used to register and unregister and interrupt handler. • Disabling Interrupts • When kernel doesn’t want to be interrupted cli(void); “CLear the Interrupts flag” – disable interrupts sti(void); “SeT the Interrupts flag” – enable interrupts
Autodetecting IRQ number • Probing • Way for driver to determine which IRQ line to be used by device • Driver tells device to generate interrupts • Only one line should be activated probe_irq_on(void); probe_irq_off(unsigned long); These functions are used by the driver when it has to probe to determine what interrupt line is being used by a device. The result of probe_irq_on must be passed back to probe_irq_off after the interrupt has been generated. The return value of probe_irq_off is the detected interrupt number.
Bottom Halves • Interrupt Handler split into two halves • “Top Half” • Routine that is scheduled immediately when an interrupt occurs • “Bottom Half” • Routine that is scheduled by the top half • Executed at a safer time (because interrupts enabled) • Not necessarily called once per interrupt. • Kernel services it when it can mark_bh(int nr); This function marks a bottom half for execution
Memory Mapped Devices • Allocating a memory mapped device • In device driver • mmap – allocates memory and returns a base address mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset); • Must also make sure that it doesn’t get swapped out as virtual memory • Restricted to vm’s PAGE_SIZE rules
Memory Mapped – Device Driver Struct file_operations my_fileops = { my_lseek, my_read, … my_mmap, … } … register_chrdev(major, ”mydev”,my_fileops); *my_lseek(…){ /* lseek redefined for this device */ } *my_read(..){ /* read redefined for this device */ } *my_mmap(…){ mmap(…); /* system call to allocate memory for the device */ }
DMA Devices • Allocating a DMA Device • Buffer allocated at runtime or boot time dma_buf = kmalloc(buffer_size,GFP_BUFFER | GFP_DMA); • Restriction for 16 bit devices • Lower 16 MB of memory, continuous page-addresses
DMA Memory Management • Linux has a advanced device memory management on used and unused blocks of pages with kmalloc(). Linux will try to join the released segment with a free neighbor segment. At the beginning of every segment, a page_descriptor information is maintained
The DMA of Interrupts: • The interrupts generated by devices using DMA are typically for the following reasons: • Send data on the character channel • Read data from the character channel • Initiate a DMA-transfer to or from the host • The transfer is done • The transfer is going to cross the boundary of the DMA page register (DMA page-register has to be incremented)
DMA transfer steps • These are the steps to be taken for a complete transfer: • a transfer start interrupt occurs. • The interrupt handler starts the transfer. • The interrupt handler returns, while the CPU starts its normal activity and the transfer is running. • A transfer finished Interrupt occurs. • The interrupt handler ends the transfer... • Request device for another transfer, etc.
DMA and PCI devices • The PCI is more elaborate at the hardware level and easier to manage, simply request control of the bus. • Steps for DMA Transfer with PCI: • Allocating a DMA buffer (no 16MB addressability limitation). • Talking to the device