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

嵌入式Linux

开发平台:

C/C++

  1. /*
  2.  * skull.c -- sample typeless module.
  3.  *
  4.  * BUGS:
  5.  *   -it only runs on intel platforms.
  6.  *   -readb() should be used (see short.c): skull doesn't work with 2.1
  7.  *
  8.  * Tested with 1.2 and 2.0 on the x86
  9.  */
  10. #ifndef __KERNEL__
  11. #  define __KERNEL__
  12. #endif
  13. #ifndef MODULE
  14. #  define MODULE
  15. #endif
  16. #include <linux/ioport.h>
  17. #include <linux/errno.h>
  18. #define __NO_VERSION__ /* don't define kernel_version in module.h */
  19. #include <linux/module.h>
  20. #include <linux/version.h>
  21. char kernel_version [] = UTS_RELEASE;
  22. #include <asm/system.h> /* cli(), *_flags */
  23. #include <linux/kernel.h> /* printk */
  24. #include <linux/errno.h> /* error codes */
  25. /* have three symbols to export */
  26.        void skull_fn1(void){}
  27. static void skull_fn2(void){}
  28.        int  skull_variable;
  29. static int skull_register(void) /* and export them */
  30. {
  31.   static struct symbol_table skull_syms = {
  32. #include <linux/symtab_begin.h>
  33.         X(skull_fn1),
  34.         X(skull_fn2),
  35.         X(skull_variable),
  36. #include <linux/symtab_end.h>
  37. };
  38.   register_symtab(&skull_syms);
  39.   return 0;
  40. }
  41. /* perform hardware autodetection */
  42. int skull_probe_hw(unsigned int port, unsigned int range)
  43. {
  44.    /* do smart probing here */
  45.    return -1; /* not found  :-) */
  46. }
  47. /* perform hardware initalizazion */
  48. int skull_init_board(unsigned int port)
  49. {
  50.   /* do smart initalization here */
  51.   return 0; /* done :-) */
  52. }
  53. /* detect the the device if the region is still free */
  54. static int skull_detect(unsigned int port, unsigned int range)
  55. {
  56.     int err;
  57.     if ((err=check_region(port,range)) < 0) return err; /* busy */
  58.     if (skull_probe_hw(port,range) != 0) return -ENODEV;   /* not found */
  59.  
  60.     request_region(port,range,"skull"); /* always succeeds */
  61.     return 0;
  62. }
  63. /*
  64.  * port ranges: the device can reside between
  65.  * 0x280 and 0x300, in step of 0x10. It uses 0x10 ports.
  66.  */
  67. #define SKULL_PORT_FLOOR 0x280
  68. #define SKULL_PORT_CEIL  0x300
  69. #define SKULL_PORT_RANGE  0x010
  70. /*
  71.  * the following function performs autodetection, unless a specific
  72.  * value was assigned by insmod to "skull_port_base"
  73.  */
  74. static int skull_port_base=0; /* 0 forces autodetection */
  75. static int skull_find_hw(void) /* returns the # of devices */
  76. {
  77.     /* base is either the load-time value or the first trial */
  78.     int base = skull_port_base ? skull_port_base 
  79.                              : SKULL_PORT_FLOOR; 
  80.     int result = 0;
  81.     /* loop one time if value assigned, try them all if autodetecting */
  82.     do {
  83. if (skull_detect(base, SKULL_PORT_RANGE) == 0) {
  84.     skull_init_board(base);
  85.     result++;
  86. }
  87. base += SKULL_PORT_RANGE; /* prepare for next trial */
  88.     }
  89.     while (skull_port_base == 0 && base < SKULL_PORT_CEIL);
  90.     return result;
  91. }
  92. int init_module(void)
  93. {
  94.     /*
  95.      * Print the isa region map, in blocks of 2k bytes.
  96.      * This is not the best code, as it prints too many lines,
  97.      * but it deserves to remain short to be included in the book.
  98.      * Note also that read() should be used instead of pointers.
  99.      */
  100.     volatile unsigned char *ptr;  /* pointed data is volatile  */
  101.     unsigned char oldval, newval; /* values read from memory   */
  102.     unsigned long flags;          /* used to hold system flags */
  103.     unsigned long add, i;
  104.     
  105.     /* probe all the memory hole in 2k steps */
  106.     for (add = 0xA0000; add < 0x100000; add += 2048) {
  107. ptr = (unsigned char *)add;
  108. save_flags(flags);
  109. cli();
  110. oldval = *ptr;     /* read a byte */
  111. *ptr= oldval^0xff; /* change it   */
  112. newval=*ptr;       /* re-read     */
  113. *ptr=oldval;       /* restore     */
  114. restore_flags(flags);
  115. /* FIXME -- user getmem_fromio or such */
  116. if ((oldval^newval) == 0xff) {  /* we re-read our change: it's ram */
  117.     printk(KERN_INFO "%lx: RAMn", (long)ptr);
  118.     continue;
  119. }
  120. if ((oldval^newval) != 0) {  /* random bits changed: it's empty */
  121.     printk(KERN_INFO "%lx: emptyn",(long)ptr);
  122.     continue;
  123. }
  124. /*
  125.  * Expansion rom (executed at boot time by the bios)
  126.  * has a signature of 0x55, 0xaa, and the third byte tells
  127.  * the size of such rom
  128.  */
  129. if ( (*ptr == 0x55) && (*(ptr+1) == 0xaa)) {
  130.     int size = 512 * *(ptr+2);
  131.     printk(KERN_INFO "%lx: Expansion ROM, %i bytesn",
  132.                    (long)ptr, size);
  133.     add += (size & ~2048) - 2048; /* skip it */
  134.     continue;
  135. }
  136. /*
  137.  * If the tests above failed, we still don't know if it is ROM or
  138.  * empty. Since empty memory can appear as 0x00, 0xff, or the low
  139.  * address byte, we must probe multiple bytes: if at least one of
  140.  * them is different from these three values, then this is rom
  141.  * (though not boot rom).
  142.  */
  143. printk(KERN_INFO "%lx: ", (long)ptr);
  144. for (i=0; i<5; i++) {
  145.     ptr+=57; /* a "random" value */
  146.     if (*ptr && *ptr!=0xFF && *ptr!=((long)ptr&0xFF))
  147. break;
  148. }    
  149. printk("%sn", i==5 ? "empty" : "ROM");
  150.     }
  151.     /*
  152.      * Find you hardware 
  153.      */
  154.     skull_find_hw();
  155.     /*
  156.      * Always fail to load (or suceed).
  157.      */
  158.     skull_register(); /* register your symbol table */
  159.     return 0;
  160. }