📄 short.c
字号:
/* * short.c -- Simple Hardware Operations and Raw Tests *********/#define CONFIG_X86_LOCAL_APIC#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif//jca #define _LINUX_CONFIG_H//jca #define CONFIG_1GB /* added to get PAGE_OFFSET_RAW to be defined */#include <linux/config.h>#if 0// needed to get external names correct#include <linux/modsetver.h>#include <linux/modules/ksyms.ver>#else#include <linux/modversions.h>#endif#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h> /* printk() */#include <linux/fs.h> /* everything... */#include <linux/errno.h> /* error codes */#include <linux/malloc.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/tqueue.h> #include <asm/io.h>#include <asm/segment.h> #include "sysdep-2.1.h"#define DATA 0#define STATUS 1#define CONTROL 2int short_major = 0;int short_base = 0x378; /* intel: default to lp0 *//* * The devices with low minor numbers write/read burst of data to/from * specific I/O ports (by default the parallel ones). * * The device with 128 as minor number returns ascii strings telling * when interrupts have been received. Writing to the device toggles * 00/FF on the parallel data lines. If there is a loopback wire, this * generates interrupts. */int short_open (struct inode *inode, struct file *filp){ MOD_INC_USE_COUNT; printk(KERN_INFO "short: start short_open()\n"); return 0;}static int short_release(struct inode * inode, struct file * file){ MOD_DEC_USE_COUNT; return 0;}void myparport_pc_write_data( unsigned char d){ outb(d, short_base+DATA);}unsigned char myparport_pc_read_status(void){int i; i = inb(short_base+STATUS);return i;}void myparport_pc_write_status( unsigned char d){ outb(d, short_base+STATUS);}unsigned char myparport_pc_read_data(void){int i; i = inb(short_base+DATA);return i;}void myparport_pc_write_control( unsigned char d){ outb(d, short_base+CONTROL);}unsigned char myparport_pc_read_control(void){int i; i = inb(short_base+CONTROL);return i;}static int short_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int retval = 0; retval = -EINVAL; if (arg && cmd == TIOCPKT_DATA) { myparport_pc_write_data(*(unsigned char *)arg); *(unsigned char *)arg = myparport_pc_read_status(); retval = 0; } else if (arg && cmd == TIOCPKT_STOP) { *(unsigned char *)arg = myparport_pc_read_status(); retval = 0; } else if (arg && cmd == TIOCPKT_START) { myparport_pc_write_status(*(unsigned char *)arg); retval = 0; } else if (arg && cmd == TIOCPKT_FLUSHREAD) { *(unsigned char *)arg = myparport_pc_read_data(); retval = 0; } else if (arg && cmd == TIOCPKT_FLUSHWRITE) { myparport_pc_write_data(*(unsigned char *)arg); retval = 0; } else if (arg && cmd == TIOCPKT_NOSTOP) { *(unsigned char *)arg = myparport_pc_read_control(); retval = 0; } else if (arg && cmd == TIOCPKT_DOSTOP) { myparport_pc_write_control(*(unsigned char *)arg); retval = 0; } return retval;}struct file_operations short_fops = { NULL, /* owner */ NULL/*llseek*/, NULL/*read*/, NULL/*write*/, NULL/*readdir*/, NULL/*poll*/, short_ioctl, /* short_ioctl */ NULL, /* short_mmap */ short_open, NULL, /* flush */ short_release /*fsync, fasync, lock, readv, writev, writepage */};/* * The following two functions are equivalent to the previous one, * but split in top and bottom half. First, a few needed variables */static struct tq_struct short_task; /* 0 by now, filled by init_module code */void short_bottom_half(void *unused){}int init_module(void){int result = check_region(short_base,4); printk(KERN_INFO "short: start init_module()\n"); if (result) { printk(KERN_INFO "short: can't get I/O address 0x%x\n",short_base); return result; } request_region(short_base,4,"short"); result = register_chrdev(short_major, "short", &short_fops); if (result < 0) { printk(KERN_INFO "short: can't get major number\n"); release_region(short_base,4); return result; } if (short_major == 0) short_major = result; /* dynamic */ /* * Fill the short_task structure, used for the bottom half handler */ short_task.routine = short_bottom_half; short_task.data = NULL; /* unused */ myparport_pc_write_data(0xff); return 0;}void cleanup_module(void){ unregister_chrdev(short_major, "short"); release_region(short_base,4); myparport_pc_write_data(0xff);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -