#include #include #include #include #include #include #include #include static ssize_t doc_read (struct file *filp, char *buf, size_t count, loff_t *ptr); static ssize_t doc_write (struct file *file, const char *buf, size_t count, loff_t *ppos); static int doc_release(struct inode *inode, struct file *file); static int doc_open(struct inode *inode, struct file *filp); struct file_operations doc_fops={ NULL, /* llseek */ doc_read, /* read */ doc_write, /* write */ NULL, /* readdir */ NULL, /* poll */ NULL, /* ioctl */ NULL, /* mmap */ doc_open, /* open */ NULL, /* flush */ doc_release, /* release */ NULL /* fsync */ }; struct miscdevice doc_miscdev={ 157, "doc", &doc_fops }; #define DOCLOC 0xd8000 unsigned long docptr=0; int doccheck(unsigned long potential); int init_module(void) { int status; docptr=(unsigned long)ioremap(0xd8000, 0x2000); status=doccheck(docptr); if (status) { printk("DOC found at 0x%lx\n",docptr); misc_register (&doc_miscdev); return 0; } else { printk("DOC not found at 0x%lx\n", docptr); return -ENXIO; } } void cleanup_module(void) { if (docptr) iounmap((void *)docptr); docptr = 0; misc_deregister (&doc_miscdev); } int doccheck(unsigned long potential) { unsigned long window=potential; unsigned char tmp, tmp2; /* Routine copied from the Linux DOC driver */ if (readb(window) != 0x55 || readb(window+1) != 0xaa) { printk ("Start of window not 0x55 0xaa: %2.2X %2.2X\n", (unsigned int)readb(window),(unsigned int)readb(window+1)); return 0; } tmp2 = readb(window+0x1002); writeb(0x84, window+0x1002); writeb(0x84, window+0x1002); writeb(0x85, window+0x1002); writeb(0x85, window+0x1002); if (readb(window+0x1000) != 0x20) { writeb(tmp2, window+0x1002); return 0; } tmp = readb(window+0x1007) & 4; if ((readb(window+0x1007) & 4) != tmp) { return 1; } writeb(tmp2, window+0x1002); return 0; } static ssize_t doc_read (struct file *filp, char *buf, size_t count, loff_t *ptr) { size_t di; loff_t ofs = *ptr; di = 0; for (ofs = *ptr; ofs < *ptr + count ; ofs++) { if (!(ofs & 0xf)) { writeb(0x1d, docptr+ 0x1004); // Set to 'set address' mode? writew( 1+ readw(docptr + 0x1000), docptr + 0x1000); //writeb( ofs & 0xff, docptr+ 0x100d); writeb( ofs & 0xff, docptr+ 0x1800); //writeb( (ofs >> 8) & 0xff, docptr + 0x100d); writeb( (ofs >> 8) & 0xff, docptr + 0x1800); //writeb( (ofs >> 16) & 0xff, docptr + 0x100d); writeb( (ofs >> 16) & 0xff, docptr + 0x1800); writeb ( 0x19, docptr + 0x1004); // Set to 'read' mode? writew( 1 + readw(docptr + 0x1000), docptr + 0x1000); while ( !(readb(docptr + 0x1004) & 80) ) printk("waiting...\n"); // Wait for ack? (void)readw(docptr + 0x1004); /* The while() loop above never actually seems to wait. We need this udelay() to get consistent results. */ udelay(1); } //(void)readb(docptr + 0x100d); buf[di++] = readb(docptr + 0x1800); } *ptr = ofs; return count; } static ssize_t doc_write (struct file *file, const char *buf, size_t count, loff_t *ppos) { return -EIO; } static int doc_release(struct inode *inode, struct file *file) { return 0; } static int doc_open(struct inode *inode, struct file *filp) { return 0; }