[root@armadillo (ttyAM0) ~]# [root@armadillo (ttyAM0) ~]# cat /mnt/dev_ht3070/ht3070.c /* * ht3070.c * * Copyright (C) 2006 saekisan */ #include #include #include #include #include #include #include "ht3070.h" #undef outb #define outb(v,p) __raw_writeb(v,__io(ISAIO8_BASE+p)) #undef inb #define inb(p) __raw_readb(__io(ISAIO8_BASE+p)) #define MAX_HT3070 4 static unsigned int ht3070_portlist[MAX_HT3070] __initdata = { 0x100, 0x110, 0x120, 0x130, }; static int ht3070_foundlist[MAX_HT3070] __initdata = { 0, 0, 0, 0, }; #define CHRDEV "ht3070" #define VERSION CHRDEV ": HT3070 driver, (C) 2006 saekisan" static ssize_t ht3070_read (struct file *file, char *buf, size_t count, loff_t *ppos) { unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); int devno = minor / 16; int portno = minor % 16; char tmp; if (MAX_HT3070 <= devno || 15 <= portno) { return -ENODEV; } if (!ht3070_foundlist[devno]) { return -ENODEV; } tmp = inb (ht3070_portlist[devno] + portno); if (put_user (tmp, buf)) { return -EFAULT; } return 1; } static ssize_t ht3070_write (struct file *file, const char *buf, size_t count, loff_t *ppos) { unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); int devno = minor / 16; int portno = minor % 16; if (MAX_HT3070 <= devno || 15 <= portno) { return -ENODEV; } if (!ht3070_foundlist[devno]) { return -ENODEV; } outb (buf[0], ht3070_portlist[devno] + portno); return 1; } static struct file_operations ht3070_fops = { owner: THIS_MODULE, read: ht3070_read, write: ht3070_write, }; static int ht3070_probe (unsigned int port) { int i=0; if (inb (port + 8) != 0xff) { printk (": port8 : not0xff\n"); return -1; } if (inb (port + 9) != 0xff) { printk (": port9 : not0xff\n"); return -1; } if (inb (port + 10) != 0xff) { printk (": port10 : not0xff\n"); return -1; } if (inb (port + 11) != 0xff) { printk (": port11 : not0xff\n"); return -1; } if (inb (port + 12) != 0xff) { printk (": port12 : not0xff\n"); return -1; } if (inb (port + 13) != 0xff) { printk (": port13 : not0xff\n"); return -1; } if (inb (port + 14) != 0xff) { printk (": port14 : not0xff\n"); return -1; } for (i = 0; i < 16; i++) { outb (0x00, port + i); } if (inb (port + 8) != 0x00) { printk (": port8- : cannot set to 0x00\n"); return -1; } printk ( ": port0-7 all set to OUTport \n"); return 0; } #ifdef MODULE static int io[MAX_HT3070]; MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HT3070) "i"); #endif int __init ht3070_init (void) { int i, count = 0; #ifdef MODULE int j; #endif #ifdef MODULE if (!io[0]) { printk (KERN_WARNING CHRDEV ": Append io=0xNNN.\n"); return -ENXIO; } #endif for (i = 0; i < MAX_HT3070; i++) { #ifdef MODULE for (j = 0; j < MAX_HT3070; j++) { if (io[j] == ht3070_portlist[i]) { break; } } if (j >= MAX_HT3070) { continue; } #endif if (!ht3070_probe (ht3070_portlist[i])) { ht3070_foundlist[i] = 1; count++; } } if (!count) { printk (KERN_WARNING CHRDEV ": HT3070 is not found.\n"); return -EIO; } for (i = 0; i < MAX_HT3070; i++) { if (ht3070_foundlist[i]) { if (!request_region (ISAIO8_BASE + ht3070_portlist[i], 16, CHRDEV)) { #ifdef MODULE printk (KERN_WARNING CHRDEV ": I/O port 0x%x-0x%x is not free.\n", ISAIO8_BASE + ht3070_portlist[i], ISAIO8_BASE + ht3070_portlist[i] + 15); #endif ht3070_foundlist[i] = 0; count--; if (!count) { for (i--; i >= 0; i--) { if (ht3070_foundlist[i]) { release_region (ISAIO16_BASE + ht3070_portlist[i], 16); release_region (ISAIO8_BASE + ht3070_portlist[i], 16); } } return -EIO; } continue; } if (!request_region (ISAIO16_BASE + ht3070_portlist[i], 16, CHRDEV)) { #ifdef MODULE printk (KERN_WARNING CHRDEV ": I/O port 0x%x-0x%x is not free.\n", ISAIO16_BASE + ht3070_portlist[i], ISAIO16_BASE + ht3070_portlist[i] + 15); #endif release_region (ISAIO8_BASE + ht3070_portlist[i], 16); ht3070_foundlist[i] = 0; count--; if (!count) { for (i--; i >= 0; i--) { if (ht3070_foundlist[i]) { release_region (ISAIO16_BASE + ht3070_portlist[i], 16); release_region (ISAIO8_BASE + ht3070_portlist[i], 16); } } return -EIO; } } } } if (register_chrdev (HT3070_MAJOR, CHRDEV, &ht3070_fops)) { printk (KERN_WARNING CHRDEV ": Unable to get major %d.\n", HT3070_MAJOR); for (i = MAX_HT3070 - 1; i >= 0; i--) { if (ht3070_foundlist[i]) { release_region (ISAIO16_BASE + ht3070_portlist[i], 16); release_region (ISAIO8_BASE + ht3070_portlist[i], 16); } } return -EIO; } printk (KERN_INFO VERSION "\n"); return 0; } void __exit ht3070_cleanup (void) { int i; unregister_chrdev (HT3070_MAJOR, CHRDEV); for (i = MAX_HT3070 - 1; i >= 0; i--) { if (ht3070_foundlist[i]) { release_region (ISAIO16_BASE + ht3070_portlist[i], 16); release_region (ISAIO8_BASE + ht3070_portlist[i], 16); } } } module_init (ht3070_init); module_exit (ht3070_cleanup); /* 参考: insmod ht3070.o io=0x110 で組み込んで下さい HT3070ボードの 占有I/O アドレスは SA[10:4] で設定します 0x110 では SA[10:4]=[0010001]というジャンパ設定です 0x110〜0x11f の 16バイト占有となります */ [root@armadillo (ttyAM0) ~]#