Linux Device Drivers, 3rd Edition by Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman The following errata were *corrected* in the 5/07 reprint: This page was updated May 8, 2007. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ###################################### (xi) last paragraph; twelth -> twelfth ###################################### (xiii) first para, Greg's introduction; ... but whose kernel had never taken the time to look into. -> ... but whose kernel I had never taken the time to look into. ###################################### (xiv) Second-last paragraph, last sentence; In Chapters 1 and 1, however... -> In Chapters 9 and 10, however... ###################################### (xvii) 3rd paragraph under Acknowledgements; "Michael Boerner" added to the list of technical reviewers thanked. ###################################### (7) last paragraph; ...I2O drivers. -> ...I2C drivers. ###################################### (17) code output; Goodbye cruel world -> Goodbye, cruel world ###################################### (29) third line from bottom of page; executible -> executable ###################################### (32) 3rd paragraph, last sentence; ...necessary to enable to kernel... -> ...necessary to enable the kernel... ###################################### (82) Second section, first paragraph; ...associated withp the hardware... -> ...associated with the hardware... ###################################### (103) 3rd code snippet, 1st line; [0]kdb> mm cf26ac0c 0x50 -> [0]kdb> mm cf36ac0c 0x50 ###################################### (109) Last paragraph, 2nd sentence; ...any further processes... -> ...any further progress... ###################################### (114) Completions section, first paragraph, 4th line; It such cases... -> In such cases... ###################################### (125) First paragraph; But a full locking regime seems like over- head for a simple integer value. -> But a full locking regime seems like over- kill for a simple integer value. ###################################### (149) Third paragraph; dynamicly -> dynamically ###################################### (158) Last comment in code block at the top of the page; explained late in chapter 5 -> explained late in chapter 6 ###################################### (163) first paragraph, line 2; ...each allow a process... -> ...each allows a process... ###################################### (163) Last line (above footnote); void poll_wait (struct file *, wait_queue_head_t *, poll_table *); -> void poll_wait (struct file *filp, wait_queue_head_t *wait_queue, poll_table *wait); ###################################### {191} computer printout at bottom of page; phon% dd bs=20 count=5 < /proc/jitbusy 1686518 1687518 1687519 1688519 1688520 1689520 1689520 1690520 1690521 1691521 -> [note new bs= value, and alignment of columns]: phon% dd bs=22 count=5 < /proc/jitbusy 1686518 1687518 1687519 1688519 1688520 1689520 1689520 1690520 1690521 1691521 ###################################### {192} computer printout at top of page; phon% dd bs=20 count=5 < /proc/jitbusy 1911226 1912226 1913323 1914323 1919529 1920529 1925632 1926632 1931835 1932835 -> [note new bs= value, and alignment of columns]: phon% dd bs=22 count=5 < /proc/jitbusy 1911226 1912226 1913323 1914323 1919529 1920529 1925632 1926632 1931835 1932835 ###################################### {192} computer printout in middle of page; phon% dd bs=20 count=5 < /proc/jitbusy 14940680 14942777 14942778 14945430 14945431 14948491 14948492 14951960 14951961 14955840 -> [note new bs= value, and alignment of columns]: phon% dd bs=22 count=5 < /proc/jitbusy 14940680 14942777 14942778 14945430 14945431 14948491 14948492 14951960 14951961 14955840 ###################################### {193} computer printout in middle of page; phon% dd bs=20 count=5 < /proc/jitsched 1760205 1761207 1761209 1762211 1762212 1763212 1763213 1764213 1764214 1765217 -> [note new bs= value, and alignment of columns]: phon% dd bs=22 count=5 < /proc/jitsched 1760205 1761207 1761209 1762211 1762212 1763212 1763213 1764213 1764214 1765217 ###################################### {194} computer printout in middle of page; phon% dd bs=20 count=5 < /proc/jitqueue 2027024 2028024 2028025 2029025 2029026 2030026 2030027 2031027 2031028 2032028 -> [note new bs= value, and alignment of columns]: phon% dd bs=22 count=5 < /proc/jitqueue 2027024 2028024 2028025 2029025 2029026 2030026 2030027 2031027 2031028 2032028 ###################################### (196) 3rd paragraph from bottom, 1st sentence; The first two functions puts the calling process to sleep... -> The first two functions put the calling process to sleep... ###################################### (199) First paragraph, second line; iteslf -> itself ###################################### {206} paragraph near top beginning with "Either one..."; The return-value from these functions is 0 if the work was successfully added to the queue; a nonzero result means that this work_struct stucture was already waiting in the queue, and was not added a second time. -> The return-value from these functions is nonzero if the work was successfully added to the queue; a zero result means that this work_struct stucture was already waiting in the queue, and was not added a second time. ###################################### {209} 2nd code block; rdtscll(var32) -> rdtscll(var64) ###################################### (241) Last paragraph, third line down; ... I/O port or the same size -> ... I/O port of the same size ###################################### (242) Sixth line of first paragraph under section "Pausing I/O"; out b -> outb ###################################### (249) 2nd para,2nd line; When access passes though page tables... -> When access passes through page tables... ###################################### {251} First paragraph, first sentence; These functions read or write count values from the given buf to the given addr. -> The ioread functions read count values from the given addr to the given buf, while the iowrite functions write count values from the given buf to the given addr. ###################################### (251) 2nd Paragraph; perform all I/O -> all perform I/O ###################################### [254] 2nd code block; iowrite8 -> iowrite32 ###################################### (257) First ten lines; unsigned readb(address); unsigned readw(address); unsigned readl(address); void writeb(unsigned value, address); void writew(unsigned value, address); void writel(unsigned value, address); memset_io(address, value, count); memcpy_fromio(dest, source, nbytes); memcpy_toio(dest, source, nbytes); Older, type-unsafe functions for accessing I/O memory. -> unsigned readb(address); unsigned readw(address); unsigned readl(address); void writeb(unsigned value, address); void writew(unsigned value, address); void writel(unsigned value, address); Older, type-unsafe functions for accessing I/O memory. memset_io(address, value, count); memcpy_fromio(dest, source, nbytes); memcpy_toio(dest, source, nbytes); Functions that operate on a block of I/O memory. ###################################### (262) halfway down page; root@montalcino:/bike/corbet/write/ldd3/src/short# m /proc/interrupts -> root@montalcino:/bike/corbet/write/ldd3/src/short# cat /proc/interrupts ###################################### (270) 5th line from the bottom; By taking care to prevent in inconsistent value... -> By taking care to prevent an inconsistent value... ###################################### {271} Code for short_i_read() function, 7th line from end of function; count0 = short_buffer + PAGE_SIZE - short_tail; -> count0 = short_head + PAGE_SIZE - short_tail; ###################################### [274] 11th line from bottom; Note that flags is passed directly, not by pointer. -> Note that flags is passed directly, not by pointer; this is because local_irq_save() is actually implemented as a macro, not a function. ###################################### (275) 2nd Paragraph from End (Under "Top and Bottom Halves"; The alternative to tasklets is workqueues, which may have a higher latency but that are allowed to sleep. -> The alternative to tasklets is workqueues, which may have a higher latency but which are allowed to sleep. ###################################### (276) 2nd paragraph, 2nd sentence; Therefore, an interrupt handler can be secure that... -> Therefore, an interrupt handler can be sure that... ###################################### (289) Near top of page, 3rd line of computer output; i686 -> i386 ###################################### [298] Both versions of the todo_add_entry() function, last line; list_add_tail(&new->list, &todo_struct); -> list_add_tail(&new->list, &todo_list); ###################################### [309] 15th line from bottom; The class register is a 16-bit value... -> The class register is a 24-bit value... ###################################### {310} last sentence under the paragraph headed by "__u32 class_mask;" If a driver can handle any subsystem ID, the value PCI_ANY_ID should be used for these fields. -> If a driver can handle any class, the value 0 should be used for these fields. ###################################### {326} 2/3 way down page, the pci_write_config_*() function prototypes; int pci_write_config_byte (struct pci_dev *dev, int where, u8 *val); int pci_write_config_word (struct pci_dev *dev, int where, u16 *val); int pci_write_config_dword (struct pci_dev *dev, int where, u32 *val); -> int pci_write_config_byte (struct pci_dev *dev, int where, u8 val); int pci_write_config_word (struct pci_dev *dev, int where, u16 val); int pci_write_config_dword (struct pci_dev *dev, int where, u32 val); ###################################### (343) Last paragraph under "Bulk urbs"; The usb_fill_int_urb function does not set the transfer_flags... -> The usb_fill_bulk_urb function does not set the transfer_flags... ###################################### (345) 2nd line; This value should be used if the driver is in the block I/O patch. -> This value should be used if the driver is in the block I/O path. ###################################### (349) last paragraph, 2nd sentence; This is done with a call to usb_deregister_driver. -> This is done with a call to usb_deregister. ###################################### (355) last paragraph, line 3; Remember that the urb callback is running in interrupt context, so it should do any memory allocation... -> Remember that the urb callback is running in interrupt context, so it should not do any memory allocation... ###################################### {366} 2nd paragraph from bottom; A successful call to kobject_get increments the kobject's reference counter and returns a pointer to the kobject. If, however, the kobject is already in the process of being destroyed, the operation fails, and kobject_get returns NULL. This return value must always be tested, or no end of unpleasant race conditions could result. -> A call to kobject_get increments the kobject's reference counter and returns a pointer to the kobject. ###################################### {369} Last paragraph (above bullets); ...their parent's fields -> ...their parent fields ###################################### (376) 2nd Paragraph under "Hotplug Operations"; ...the kernel searchs up through... -> ...the kernel searches up through... ###################################### {383} last code example; #define to_ldd_device(dev) container_of(dev, struct ldd_device, dev) -> #define to_ldd_device(_dev) container_of(_dev, struct ldd_device, dev) ###################################### (396) 1st paragraph under "Add a Driver", 5th line; structdevice_driver -> struct device_driver ###################################### (415) 3rd paragraph, 4th line; If you discard the offset and shift the rest of an offset to the right... -> If you discard the offset and shift the rest of an address to the right... ###################################### (416) Second paragraph; ...while not breaking 32-bit application and the... -> ...while not breaking 32-bit applications and the... ###################################### (418) 2nd paragraph: kunmap; a limited number of such mappings is available, -> a limited number of such mappings are available, ###################################### (419) Paragraph starting "The memory areas"; by looking in /proc/ -> by looking in /proc//maps ###################################### [429] programming example under "Remapping Specific I/O Regions"; unsigned long physical = simple_region_start + off; -> unsigned long pfn = page_to_pfn(simple_region_start + off); ###################################### [429] same example; remap_pfn_range(vma, vma_>vm_start, physical, vsize, vma->vm_page_prot); -> remap_pfn_range(vma, vma->vm_start, pfn, vsize, vma->vm_page_prot); ###################################### (442) Third paragraph; arrises -> arises ###################################### {449} 1st paragraph after bullets, 2nd sentence from end; dma_unmap_single -> dma_map_single ###################################### (451) paragraph starting "Your driver should"; pci_map_sg -> dma_map_sg ###################################### {476} 5th line; sbull_transfer(dev, req->sector, req->current_nr_sectors, -> sbull_transfer(dev, req->sector, req->nr_sectors, ###################################### {476} 3rd Paragraph; The call to block_fs_request tells us... -> The call to blk_fs_request tells us... ###################################### (506) 1st paragraph under "Hardware Information", 2nd sentence; ...most modern drivers do make use of them... -> ...most modern drivers do not make use of them... ###################################### (516) 3rd paragraph from bottom, 2nd sentence; ...it calls the driver's hard_start_transmit method... -> ...it calls the driver's hard_start_xmit method... ###################################### {524} Code example, first line; static void snull_regular_interrupt(int irq, void *dev_id, struct pt_regs *regs) -> static irqreturn_t snull_regular_interrupt(int irq, void *dev_id, struct pt_regs *regs) ###################################### {524} Code example, last line before the closing "}"; return; -> return IRQ_HANDLED; ###################################### (539) Code example eighth line from bottom: /* If there's more addresses... -> /* If there are more addresses... ###################################### (549) Second line; paramater -> parameter ###################################### (561) Last paragraph, 1st sentence; There are a two basic types of... -> There are two basic types of... ###################################### [575] In the appendix, third paragraph; Deleted the second sentence, beginning "The program called repatch..." ######################################