⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stepper.c

📁 linux driver 第二版 随书源码
💻 C
字号:
/* * stepper.c -- char module * *********/#ifndef __KERNEL__#  define __KERNEL__#endif#ifndef MODULE#  define MODULE#endif#define __NO_VERSION__ /* don't define kernel_verion in module.h */#include <linux/module.h>#include <linux/version.h>char kernel_version [] = UTS_RELEASE;#include <linux/kernel.h> /* printk() */#include <linux/malloc.h> /* kmalloc() */#include <linux/fs.h>     /* everything... */#include <linux/errno.h>  /* error codes */#include <linux/types.h>  /* size_t */#include <linux/stat.h>   /* S_IFREG */#include <linux/proc_fs.h>#include <linux/ioport.h>#include <linux/tqueue.h>#include <asm/system.h>   /* cli(), *_flags */#include <asm/segment.h>#include <asm/io.h>#include "stepper.h"        /* local definitions */#include "sysdep.h"int stepper_major =   STEP_MAJOR;int step_x, step_y, step_tx, step_ty, step_speed, step_d[4], step_l;int step_unloading=0;struct tq_struct step_tq;int step_svec[]={100,75,50,25,20, 10,8,6,4,2};short digits[10]={0x7D,0x44,0x6B,0x6E,0x56,0x3E,0x3F,0x64,0x7F,0x7E};unsigned char data[4];void step_tick(void *unused){    int doit=0;    static unsigned long lasttick;#ifdef STEP_DEBUG    if (jiffies%1000 == 0) {        PDEBUG("live: %i %i (%i %i) %i -- %c%c:%c%c L %02i\n",               step_x, step_y, step_tx, step_ty, step_speed,               step_d[0], step_d[1], step_d[2], step_d[3], step_l);        PDEBUG("last %li, %li ago\n",lasttick,jiffies-lasttick);    }#endif    if (jiffies%50 == 0) {        data[0]^=1; /* tick */        data[0]|=0x1e;        if ( (jiffies/100) & 3) { /* minutes */            data[1]=digits[step_d[2]-'0'];            data[2]=digits[step_d[3]-'0'];        } else { /* hour */            data[1]=digits[step_d[0]-'0'];            data[2]=digits[step_d[1]-'0'] | 0x80;        }        doit=1;    }    if (jiffies - lasttick > step_svec[step_speed] &&        ((step_x != step_tx) || (step_y != step_ty))) {        if (step_tx > step_x)            step_x++;        if (step_ty > step_y)            step_y++;        if (step_tx < step_x)            step_x--;        if (step_ty < step_y)            step_y--;        data[3]= (step_x&7) | ((step_y&7)*16);        lasttick=jiffies;        doit=1;    }    if (doit) {        doit=0;        outb_p(data[3],0x281);        outb_p(data[0]|0x80,0x280);        outb_p(data[2],0x281);        outb_p(data[0]|0x40,0x280);        outb_p(data[1],0x281);        outb_p(data[0]|0x20,0x280);        outb_p(data[0],0x280);    }                if (!step_unloading)        queue_task(&step_tq,&tq_timer);    else        PDEBUG("not queueing\n");    }/* * The proc filesystem: function to read and entry */int stepper_read_proc(char *buf, char **start, off_t offset,                   int len, int unused){    len=sprintf(buf,"%i %i (%i %i) %i -- %c%c:%c%c L %02i\n",                step_x, step_y, step_tx, step_ty, step_speed,                step_d[0], step_d[1], step_d[2], step_d[3], step_l);    return len;}struct proc_dir_entry stepper_proc_entry = {        0,                 /* low_ino: the inode -- dynamic */        8, "stepper",     /* len of name and name */        S_IFREG | S_IRUGO, /* mode */        1, 0, 0,           /* nlinks, owner, group */        0, NULL,           /* size - unused; operations -- use default */        &stepper_read_proc,   /* function used to read data */        /* nothing more */    };/* * Open and close -- I don't use them */int stepper_open (struct inode *inode, struct file *filp){    PDEBUG("open\n");    MOD_INC_USE_COUNT;    return 0;          /* success */}void stepper_release (struct inode *inode, struct file *filp){    PDEBUG("close\n");    MOD_DEC_USE_COUNT;}/* * Data management: read and write */read_write_t stepper_read (struct inode *inode, struct file *filp,                char *buf, count_t count){return 0;#if 0    PDEBUG("read %i (pos is %li, size is %i)\n",count,f_pos,dev->size);    if (f_pos > dev->size)        return 0;    if (f_pos + count > dev->size)        count = dev->size - f_pos;    /* find listitem, qset index and offset in the quantum */    item = f_pos / itemsize;    rest = f_pos % itemsize;    s_pos = rest / quantum; q_pos = rest % quantum;    PDEBUG("read at %i:%i:%i\n",item,s_pos,q_pos);    /* follow the list up to the right position (defined elsewhere) */    dev = stepper_follow(dev, item);    if (!dev->data)        return 0; /* don't fill holes */    if (!dev->data[s_pos])        return 0;    if (count > quantum - q_pos)        count = quantum - q_pos; /* read only up to the end of this quantum */    memcpy_tofs(buf, dev->data[s_pos]+q_pos, count);    filp->f_pos += count;    PDEBUG("read %i, pos is %li\n",count,(unsigned long)filp->f_pos);    return count;#endif}int step_dispatch (int x, int y){    PDEBUG("move %i %i\n",x,y);    step_tx+=x;    step_ty+=y;    return 0;}int step_off(void){    PDEBUG("off\n");    data[3]=0x88;    return 0;}int step_setspeed(int s){    PDEBUG("speed is %i\n",s);    if (s>=0 && s<=9)        step_speed=s;    return 0;}read_write_t stepper_write (struct inode *inode, struct file *filp,                const char *buf, count_t count){    const char *datum = buf;    char cmd, sign;    int n, x, y;    int got=0;#define STEP_GET() ({char c; c=get_user(datum); datum++; count--; got++; c;})#define STEP_PEEK() (get_user(datum))    while (count) {        switch( cmd=STEP_GET() ) {        case 'l': case 'r': case 'u': case 'd':        case 'L': case 'R': case 'U': case 'D':        case 'x': case 'y':            n=0; sign=1;            if (STEP_PEEK()=='-') { STEP_GET(); sign=-1; }            while (count && STEP_PEEK() >= '0' && STEP_PEEK() <= '9') {                n=n*10+(STEP_GET()-'0');            }            n*=sign;            PDEBUG("%c %i\n",cmd, n);            if (cmd == 'x') step_tx = n;            if (cmd == 'y') step_ty = n;            if (cmd>='A' && cmd <= 'Z') { n*=10; cmd += 'a' - 'A'; }            x=0 + (cmd=='r' ? n : 0) - (cmd=='l' ? n : 0);            y=0 + (cmd=='u' ? n : 0) - (cmd=='d' ? n : 0);            step_dispatch(x,y);            break;        case '-':            step_off(); break;        case 's': case 'S':            n=0;            if (count) n=STEP_GET()-'0';            step_setspeed(n);            break;        case '!':            step_x = step_y = step_tx = step_ty = 0;            break;        case 'T':            for (n=0; n<4; n++) {                while(count) {                    step_d[n]=STEP_GET();                    if (step_d[n]>='0' && step_d[n]<='9')                        break;                }                if (!count) break;            }            PDEBUG("digits are %c%c%c%c\n",                step_d[0], step_d[1], step_d[2], step_d[3]);            break;        case 'M':            n=0;            while (count && (cmd=STEP_GET()) != '\n') {                if (cmd>='0' && cmd <='9')                     n=n*10+(cmd-'0');            }            PDEBUG("load is %i\n",n);            step_l=n/50;            break;        case ' ': case ';': case '\t': case '\n': case ',':            break;        default:            PDEBUG("unknown cmd '%c'\n",cmd);        }    }    PDEBUG("written %i\n",got);    return got;}/* * The file operations */struct file_operations stepper_fops = {    NULL,          /* stepper_lseek */    stepper_read,    stepper_write,    NULL,          /* stepper_readdir */    NULL,          /* stepper_select */    NULL,          /* stepper_ioctl */    NULL,          /* stepper_mmap */    stepper_open,    stepper_release,                   /* nothing more, fill with NULLs */};/* * Finally, the module stuff */int init_module(void){    int result;    /*     * Register your major, and accept a dynamic number (is so asked)     */    result = register_chrdev(stepper_major, "stepper", &stepper_fops);    if (result < 0) return result;    if (stepper_major == 0) stepper_major = result; /* dynamic */    request_region(0x280,2,"stepper");    step_tq.routine = step_tick;    step_tq.data = NULL;    queue_task(&step_tq,&tq_timer);#ifdef STEP_USE_PROC    proc_register_dynamic(&proc_root, &stepper_proc_entry);#endif#ifndef STEP_DEBUG    register_symtab(NULL);#endif    return 0;}void cleanup_module(void){    unsigned long j=jiffies;    step_unloading=1;    while (jiffies < j+10)        schedule();    unregister_chrdev(stepper_major, "stepper");    release_region(0x280,2);#ifdef STEP_USE_PROC    proc_unregister(&proc_root, stepper_proc_entry.low_ino);#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -