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

嵌入式Linux

开发平台:

C/C++

  1. /*
  2.  * skull.c -- sample typeless module.
  3.  *
  4.  * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
  5.  * Copyright (C) 2001 O'Reilly & Associates
  6.  *
  7.  * The source code in this file can be freely used, adapted,
  8.  * and redistributed in source or binary form, so long as an
  9.  * acknowledgment appears in derived source files.  The citation
  10.  * should list that the code comes from the book "Linux Device
  11.  * Drivers" by Alessandro Rubini and Jonathan Corbet, published
  12.  * by O'Reilly & Associates.   No warranty is attached;
  13.  * we cannot take responsibility for errors or fitness for use.
  14.  *
  15.  * BUGS:
  16.  *   -it only runs on intel platforms.
  17.  *   -readb() should be used (see short.c): skull doesn't work with 2.1
  18.  *
  19.  */
  20. #ifndef __KERNEL__
  21. #  define __KERNEL__
  22. #endif
  23. #ifndef MODULE
  24. #  define MODULE
  25. #endif
  26. #ifndef EXPORT_SYMTAB
  27. #  define EXPORT_SYMTAB
  28. #endif
  29. #include <linux/config.h>
  30. #include <linux/module.h>
  31. #include <linux/kernel.h> /* printk */
  32. #include <linux/ioport.h>
  33. #include <linux/errno.h>
  34. #include <asm/system.h> /* cli(), *_flags */
  35. #include <linux/mm.h> /* vremap (2.0) */
  36. #include <asm/io.h> /* ioremap */
  37. #include "sysdep.h"
  38. /* The region we look at. */
  39. #define ISA_REGION_BEGIN 0xA0000
  40. #define ISA_REGION_END   0x100000
  41. #define STEP 2048
  42. /* have three symbols to export */
  43.        void skull_fn1(void){}
  44. static void skull_fn2(void){}
  45.        int  skull_variable;
  46. #ifndef __USE_OLD_SYMTAB__
  47. EXPORT_SYMBOL (skull_fn1);
  48. EXPORT_SYMBOL (skull_fn2);
  49. EXPORT_SYMBOL (skull_variable);
  50. #endif
  51. static int skull_register(void) /* and export them */
  52. {
  53. #ifdef __USE_OLD_SYMTAB__
  54.   static struct symbol_table skull_syms = {
  55. #include <linux/symtab_begin.h>
  56.         X(skull_fn1),
  57.         X(skull_fn2),
  58.         X(skull_variable),
  59. #include <linux/symtab_end.h>
  60. };
  61.   register_symtab(&skull_syms);
  62. #endif   /* __USE_OLD_SYMTAB__ */
  63.   return 0;
  64. }
  65. /* perform hardware autodetection */
  66. int skull_probe_hw(unsigned int port, unsigned int range)
  67. {
  68.    /* do smart probing here */
  69.    return -1; /* not found  :-) */
  70. }
  71. /* perform hardware initalizazion */
  72. int skull_init_board(unsigned int port)
  73. {
  74.   /* do smart initalization here */
  75.   return 0; /* done :-) */
  76. }
  77. /* detect the the device if the region is still free */
  78. static int skull_detect(unsigned int port, unsigned int range)
  79. {
  80.     int err;
  81.     if ((err = check_region(port,range)) < 0) return err; /* busy */
  82.     if (skull_probe_hw(port,range) != 0) return -ENODEV;  /* not found */
  83.     request_region(port,range,"skull");                   /* "Can't fail" */
  84.     return 0;
  85. }
  86. /*
  87.  * port ranges: the device can reside between
  88.  * 0x280 and 0x300, in step of 0x10. It uses 0x10 ports.
  89.  */
  90. #define SKULL_PORT_FLOOR 0x280
  91. #define SKULL_PORT_CEIL  0x300
  92. #define SKULL_PORT_RANGE  0x010
  93. /*
  94.  * the following function performs autodetection, unless a specific
  95.  * value was assigned by insmod to "skull_port_base"
  96.  */
  97. static int skull_port_base=0; /* 0 forces autodetection */
  98. MODULE_PARM (skull_port_base, "i");
  99. MODULE_PARM_DESC (skull_port_base, "Base I/O port for skull");
  100. static int skull_find_hw(void) /* returns the # of devices */
  101. {
  102.     /* base is either the load-time value or the first trial */
  103.     int base = skull_port_base ? skull_port_base 
  104.                              : SKULL_PORT_FLOOR; 
  105.     int result = 0;
  106.     /* loop one time if value assigned, try them all if autodetecting */
  107.     do {
  108. if (skull_detect(base, SKULL_PORT_RANGE) == 0) {
  109.     skull_init_board(base);
  110.     result++;
  111. }
  112. base += SKULL_PORT_RANGE; /* prepare for next trial */
  113.     }
  114.     while (skull_port_base == 0 && base < SKULL_PORT_CEIL);
  115.     return result;
  116. }
  117. int skull_init(void)
  118. {
  119.     /*
  120.      * Print the isa region map, in blocks of 2K bytes.
  121.      * This is not the best code, as it prints too many lines,
  122.      * but it deserves to remain short to be included in the book.
  123.      * Note also that read() should be used instead of pointers.
  124.      */
  125.     unsigned char oldval, newval; /* values read from memory   */
  126.     unsigned long flags;          /* used to hold system flags */
  127.     unsigned long add, i;
  128.     void *base;
  129.     
  130.     /* Use ioremap to get a handle on our region */
  131.     base = ioremap(ISA_REGION_BEGIN, ISA_REGION_END - ISA_REGION_BEGIN);
  132.     base -= ISA_REGION_BEGIN;  /* Do the offset once */
  133.     
  134.     /* probe all the memory hole in 2KB steps */
  135.     for (add = ISA_REGION_BEGIN; add < ISA_REGION_END; add += STEP) {
  136. /*
  137.  * Check for an already allocated region.
  138.  */
  139. if (check_mem_region (add, 2048)) {
  140. printk(KERN_INFO "%lx: Allocatedn", add);
  141. continue;
  142. }
  143. /*
  144.  * Read and write the beginning of the region and see what happens.
  145.  */
  146. save_flags(flags); 
  147. cli();
  148. oldval = readb (base + add);  /* Read a byte */
  149. writeb (oldval^0xff, base + add);
  150. mb();
  151. newval = readb (base + add);
  152. writeb (oldval, base + add);
  153. restore_flags(flags);
  154. if ((oldval^newval) == 0xff) {  /* we re-read our change: it's ram */
  155.     printk(KERN_INFO "%lx: RAMn", add);
  156.     continue;
  157. }
  158. if ((oldval^newval) != 0) {  /* random bits changed: it's empty */
  159.     printk(KERN_INFO "%lx: emptyn", add);
  160.     continue;
  161. }
  162. /*
  163.  * Expansion rom (executed at boot time by the bios)
  164.  * has a signature where the first byt is 0x55, the second 0xaa,
  165.  * and the third byte indicates the size of such rom
  166.  */
  167. if ( (oldval == 0x55) && (readb (base + add + 1) == 0xaa)) {
  168.     int size = 512 * readb (base + add + 2);
  169.     printk(KERN_INFO "%lx: Expansion ROM, %i bytesn",
  170.                    add, size);
  171.     add += (size & ~2048) - 2048; /* skip it */
  172.     continue;
  173. }
  174. /*
  175.  * If the tests above failed, we still don't know if it is ROM or
  176.  * empty. Since empty memory can appear as 0x00, 0xff, or the low
  177.  * address byte, we must probe multiple bytes: if at least one of
  178.  * them is different from these three values, then this is rom
  179.  * (though not boot rom).
  180.  */
  181. printk(KERN_INFO "%lx: ", add);
  182. for (i=0; i<5; i++) {
  183.     unsigned long radd = add + 57*(i+1);  /* a "random" value */
  184.     unsigned char val = readb (base + radd);
  185.     if (val && val != 0xFF && val != ((unsigned long) radd&0xFF))
  186. break;
  187. }    
  188. printk("%sn", i==5 ? "empty" : "ROM");
  189.     }
  190.     /*
  191.      * Find you hardware 
  192.      */
  193.     skull_find_hw();
  194.     /*
  195.      * Always fail to load (or suceed).
  196.      */
  197.     skull_register(); /* register your symbol table */
  198.     return 0;
  199. }
  200. module_init(skull_init);