stepper.c
上传用户:wudi5211
上传日期:2010-01-21
资源大小:607k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

C/C++

  1. /*
  2.  * stepper.c -- char module
  3.  *
  4.  *********/
  5. #ifndef __KERNEL__
  6. #  define __KERNEL__
  7. #endif
  8. #ifndef MODULE
  9. #  define MODULE
  10. #endif
  11. #define __NO_VERSION__ /* don't define kernel_verion in module.h */
  12. #include <linux/module.h>
  13. #include <linux/version.h>
  14. char kernel_version [] = UTS_RELEASE;
  15. #include <linux/kernel.h> /* printk() */
  16. #include <linux/malloc.h> /* kmalloc() */
  17. #include <linux/fs.h>     /* everything... */
  18. #include <linux/errno.h>  /* error codes */
  19. #include <linux/types.h>  /* size_t */
  20. #include <linux/stat.h>   /* S_IFREG */
  21. #include <linux/proc_fs.h>
  22. #include <linux/ioport.h>
  23. #include <linux/tqueue.h>
  24. #include <asm/system.h>   /* cli(), *_flags */
  25. #include <asm/segment.h>
  26. #include <asm/io.h>
  27. #include "stepper.h"        /* local definitions */
  28. #include "sysdep.h"
  29. int stepper_major =   STEP_MAJOR;
  30. int step_x, step_y, step_tx, step_ty, step_speed, step_d[4], step_l;
  31. int step_unloading=0;
  32. struct tq_struct step_tq;
  33. int step_svec[]={100,75,50,25,20, 10,8,6,4,2};
  34. short digits[10]={0x7D,0x44,0x6B,0x6E,0x56,0x3E,0x3F,0x64,0x7F,0x7E};
  35. unsigned char data[4];
  36. void step_tick(void *unused)
  37. {
  38.     int doit=0;
  39.     static unsigned long lasttick;
  40. #ifdef STEP_DEBUG
  41.     if (jiffies%1000 == 0) {
  42.         PDEBUG("live: %i %i (%i %i) %i -- %c%c:%c%c L %02in",
  43.                step_x, step_y, step_tx, step_ty, step_speed,
  44.                step_d[0], step_d[1], step_d[2], step_d[3], step_l);
  45.         PDEBUG("last %li, %li agon",lasttick,jiffies-lasttick);
  46.     }
  47. #endif
  48.     if (jiffies%50 == 0) {
  49.         data[0]^=1; /* tick */
  50.         data[0]|=0x1e;
  51.         if ( (jiffies/100) & 3) { /* minutes */
  52.             data[1]=digits[step_d[2]-'0'];
  53.             data[2]=digits[step_d[3]-'0'];
  54.         } else { /* hour */
  55.             data[1]=digits[step_d[0]-'0'];
  56.             data[2]=digits[step_d[1]-'0'] | 0x80;
  57.         }
  58.         doit=1;
  59.     }
  60.     if (jiffies - lasttick > step_svec[step_speed] &&
  61.         ((step_x != step_tx) || (step_y != step_ty))) {
  62.         if (step_tx > step_x)
  63.             step_x++;
  64.         if (step_ty > step_y)
  65.             step_y++;
  66.         if (step_tx < step_x)
  67.             step_x--;
  68.         if (step_ty < step_y)
  69.             step_y--;
  70.         data[3]= (step_x&7) | ((step_y&7)*16);
  71.         lasttick=jiffies;
  72.         doit=1;
  73.     }
  74.     if (doit) {
  75.         doit=0;
  76.         outb_p(data[3],0x281);
  77.         outb_p(data[0]|0x80,0x280);
  78.         outb_p(data[2],0x281);
  79.         outb_p(data[0]|0x40,0x280);
  80.         outb_p(data[1],0x281);
  81.         outb_p(data[0]|0x20,0x280);
  82.         outb_p(data[0],0x280);
  83.     }
  84.             
  85.     if (!step_unloading)
  86.         queue_task(&step_tq,&tq_timer);
  87.     else
  88.         PDEBUG("not queueingn");
  89.     
  90. }
  91. /*
  92.  * The proc filesystem: function to read and entry
  93.  */
  94. int stepper_read_proc(char *buf, char **start, off_t offset,
  95.                    int len, int unused)
  96. {
  97.     len=sprintf(buf,"%i %i (%i %i) %i -- %c%c:%c%c L %02in",
  98.                 step_x, step_y, step_tx, step_ty, step_speed,
  99.                 step_d[0], step_d[1], step_d[2], step_d[3], step_l);
  100.     return len;
  101. }
  102. struct proc_dir_entry stepper_proc_entry = {
  103.         0,                 /* low_ino: the inode -- dynamic */
  104.         8, "stepper",     /* len of name and name */
  105.         S_IFREG | S_IRUGO, /* mode */
  106.         1, 0, 0,           /* nlinks, owner, group */
  107.         0, NULL,           /* size - unused; operations -- use default */
  108.         &stepper_read_proc,   /* function used to read data */
  109.         /* nothing more */
  110.     };
  111. /*
  112.  * Open and close -- I don't use them
  113.  */
  114. int stepper_open (struct inode *inode, struct file *filp)
  115. {
  116.     PDEBUG("openn");
  117.     MOD_INC_USE_COUNT;
  118.     return 0;          /* success */
  119. }
  120. void stepper_release (struct inode *inode, struct file *filp)
  121. {
  122.     PDEBUG("closen");
  123.     MOD_DEC_USE_COUNT;
  124. }
  125. /*
  126.  * Data management: read and write
  127.  */
  128. read_write_t stepper_read (struct inode *inode, struct file *filp,
  129.                 char *buf, count_t count)
  130. {
  131. return 0;
  132. #if 0
  133.     PDEBUG("read %i (pos is %li, size is %i)n",count,f_pos,dev->size);
  134.     if (f_pos > dev->size)
  135.         return 0;
  136.     if (f_pos + count > dev->size)
  137.         count = dev->size - f_pos;
  138.     /* find listitem, qset index and offset in the quantum */
  139.     item = f_pos / itemsize;
  140.     rest = f_pos % itemsize;
  141.     s_pos = rest / quantum; q_pos = rest % quantum;
  142.     PDEBUG("read at %i:%i:%in",item,s_pos,q_pos);
  143.     /* follow the list up to the right position (defined elsewhere) */
  144.     dev = stepper_follow(dev, item);
  145.     if (!dev->data)
  146.         return 0; /* don't fill holes */
  147.     if (!dev->data[s_pos])
  148.         return 0;
  149.     if (count > quantum - q_pos)
  150.         count = quantum - q_pos; /* read only up to the end of this quantum */
  151.     memcpy_tofs(buf, dev->data[s_pos]+q_pos, count);
  152.     filp->f_pos += count;
  153.     PDEBUG("read %i, pos is %lin",count,(unsigned long)filp->f_pos);
  154.     return count;
  155. #endif
  156. }
  157. int step_dispatch (int x, int y)
  158. {
  159.     PDEBUG("move %i %in",x,y);
  160.     step_tx+=x;
  161.     step_ty+=y;
  162.     return 0;
  163. }
  164. int step_off(void)
  165. {
  166.     PDEBUG("offn");
  167.     data[3]=0x88;
  168.     return 0;
  169. }
  170. int step_setspeed(int s)
  171. {
  172.     PDEBUG("speed is %in",s);
  173.     if (s>=0 && s<=9)
  174.         step_speed=s;
  175.     return 0;
  176. }
  177. read_write_t stepper_write (struct inode *inode, struct file *filp,
  178.                 const char *buf, count_t count)
  179. {
  180.     const char *datum = buf;
  181.     char cmd, sign;
  182.     int n, x, y;
  183.     int got=0;
  184. #define STEP_GET() ({char c; c=get_user(datum); datum++; count--; got++; c;})
  185. #define STEP_PEEK() (get_user(datum))
  186.     while (count) {
  187.         switch( cmd=STEP_GET() ) {
  188.         case 'l': case 'r': case 'u': case 'd':
  189.         case 'L': case 'R': case 'U': case 'D':
  190.         case 'x': case 'y':
  191.             n=0; sign=1;
  192.             if (STEP_PEEK()=='-') { STEP_GET(); sign=-1; }
  193.             while (count && STEP_PEEK() >= '0' && STEP_PEEK() <= '9') {
  194.                 n=n*10+(STEP_GET()-'0');
  195.             }
  196.             n*=sign;
  197.             PDEBUG("%c %in",cmd, n);
  198.             if (cmd == 'x') step_tx = n;
  199.             if (cmd == 'y') step_ty = n;
  200.             if (cmd>='A' && cmd <= 'Z') { n*=10; cmd += 'a' - 'A'; }
  201.             x=0 + (cmd=='r' ? n : 0) - (cmd=='l' ? n : 0);
  202.             y=0 + (cmd=='u' ? n : 0) - (cmd=='d' ? n : 0);
  203.             step_dispatch(x,y);
  204.             break;
  205.         case '-':
  206.             step_off(); break;
  207.         case 's': case 'S':
  208.             n=0;
  209.             if (count) n=STEP_GET()-'0';
  210.             step_setspeed(n);
  211.             break;
  212.         case '!':
  213.             step_x = step_y = step_tx = step_ty = 0;
  214.             break;
  215.         case 'T':
  216.             for (n=0; n<4; n++) {
  217.                 while(count) {
  218.                     step_d[n]=STEP_GET();
  219.                     if (step_d[n]>='0' && step_d[n]<='9')
  220.                         break;
  221.                 }
  222.                 if (!count) break;
  223.             }
  224.             PDEBUG("digits are %c%c%c%cn",
  225.                 step_d[0], step_d[1], step_d[2], step_d[3]);
  226.             break;
  227.         case 'M':
  228.             n=0;
  229.             while (count && (cmd=STEP_GET()) != 'n') {
  230.                 if (cmd>='0' && cmd <='9') 
  231.                     n=n*10+(cmd-'0');
  232.             }
  233.             PDEBUG("load is %in",n);
  234.             step_l=n/50;
  235.             break;
  236.         case ' ': case ';': case 't': case 'n': case ',':
  237.             break;
  238.         default:
  239.             PDEBUG("unknown cmd '%c'n",cmd);
  240.         }
  241.     }
  242.     PDEBUG("written %in",got);
  243.     return got;
  244. }
  245. /*
  246.  * The file operations
  247.  */
  248. struct file_operations stepper_fops = {
  249.     NULL,          /* stepper_lseek */
  250.     stepper_read,
  251.     stepper_write,
  252.     NULL,          /* stepper_readdir */
  253.     NULL,          /* stepper_select */
  254.     NULL,          /* stepper_ioctl */
  255.     NULL,          /* stepper_mmap */
  256.     stepper_open,
  257.     stepper_release,
  258.                    /* nothing more, fill with NULLs */
  259. };
  260. /*
  261.  * Finally, the module stuff
  262.  */
  263. int init_module(void)
  264. {
  265.     int result;
  266.     /*
  267.      * Register your major, and accept a dynamic number (is so asked)
  268.      */
  269.     result = register_chrdev(stepper_major, "stepper", &stepper_fops);
  270.     if (result < 0) return result;
  271.     if (stepper_major == 0) stepper_major = result; /* dynamic */
  272.     request_region(0x280,2,"stepper");
  273.     step_tq.routine = step_tick;
  274.     step_tq.data = NULL;
  275.     queue_task(&step_tq,&tq_timer);
  276. #ifdef STEP_USE_PROC
  277.     proc_register_dynamic(&proc_root, &stepper_proc_entry);
  278. #endif
  279. #ifndef STEP_DEBUG
  280.     register_symtab(NULL);
  281. #endif
  282.     return 0;
  283. }
  284. void cleanup_module(void)
  285. {
  286.     unsigned long j=jiffies;
  287.     step_unloading=1;
  288.     while (jiffies < j+10)
  289.         schedule();
  290.     unregister_chrdev(stepper_major, "stepper");
  291.     release_region(0x280,2);
  292. #ifdef STEP_USE_PROC
  293.     proc_unregister(&proc_root, stepper_proc_entry.low_ino);
  294. #endif
  295. }