Linux Device Drivers by Alessandro Rubini Following are the changes made in the 6/99 reprint: {14} 4th line of code: root# rmmod hello.o now reads: root# rmmod hello (30) In the second paragraph, the word "ioports" now reads "ioport" (no "s"). {209} In chapter 9 ("Interrupt Handling"), in the section called "Going to Sleep Without Races", the code had a subtle bug. The correct implementation of the trick looks like the following: add_wait_queue(&short_queue, &wait); do { current->state = TASK_INTERRUPTIBLE; schedule(); } while ((short_head == short_tail) && !(current->signal & ~current->blocked) ); remove_wait_queue(&short_queue, &wait); if (current->signal & ~current->blocked) /* a signal arrived */ return -ERESTARTSYS; This is different from the version shown in the printed text as signal decoding must be performed *after* calling remove_wait_queue(). {274} the description of int (*swapout) has been replaced with the following: int (*swapout)(struct vm_area_struct *vma, unsigned long offset, pte_t *page_table); This method is called when a page is selected for swap-out. The [cw]offset[/] argument is the file offset: [cw]virt_address - vma->vm_start + vma->vm_offset[/]. A return value of 0 signals success; any other value signals an error. In case of error, the process owning the page is sent a [cw]SIGBUS[/]. In version 1.2, the function returned [cw]void[/] because it was never expected to fail. The method usually writes useful information to [cw]*page_table[/], so it can be retrieved at swap-in. Such information can be, for example, the offset in the swap device. pte_t (*swapin)(struct vm_area_struct *, unsigned long offset, unsigned long entry); This method is used to retrieve a page from swap space. The [cw]offset[/] argument is relative to the area (as above for swapout), while [cw]entry[/] is the current [cw]pte[/] for the page -- if swapout saved some information in the entry, that information can now be used to retrieve the page. ("[cw]" and "[/]" indicate that text that should appear in constant width. "" and "" indicate that text that should appear in italic.) {290} The last sentence on the page now reads: "If you use kmalloc you must specify GFP_DMA priority, ...." {394} In chapter 17, in the section called "Using the New Interface", the ioctl() implementation shown included a mistake: "retval" is not initialized. A correct implementation is: int another_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); { int retval = -EINVAL, size = _IOC_SIZE(cmd); if (_IOC_DIR(cmd) & _IOC_READ) { if (!access_ok(VERIFY_WRITE, (void *)arg, size)) retturn -EFAULT; } else if (_IOC_DIR(cmd) & _IOC_WRITE) { if (!access_ok(VERIFY_READ, (void *)arg, size)) return -EFAULT switch(cmd) { case NEW_GETVALUE: retval = __put_user(another_value,arg); break; case NEW_SETVALUE: retval = __get_user(another_value,arg); break; } return retval; }