frpw.c
上传用户:ajay2009
上传日期:2009-05-22
资源大小:495k
文件大小:7k
源码类别:

驱动编程

开发平台:

Unix_Linux

  1. /* 
  2. frpw.c (c) 1996-8  Grant R. Guenther <grant@torque.net>
  3.             Under the terms of the GNU General Public License
  4. frpw.c is a low-level protocol driver for the Freecom "Power"
  5. parallel port IDE adapter.
  6. Some applications of this adapter may require a "printer" reset
  7. prior to loading the driver.  This can be done by loading and
  8. unloading the "lp" driver, or it can be done by this driver
  9. if you define FRPW_HARD_RESET.  The latter is not recommended
  10. as it may upset devices on other ports.
  11. */
  12. /* Changes:
  13.         1.01    GRG 1998.05.06 init_proto, release_proto
  14.        fix chip detect
  15.        added EPP-16 and EPP-32
  16. 1.02    GRG 1998.09.23 added hard reset to initialisation process
  17. 1.03    GRG 1998.12.14 made hard reset conditional
  18. */
  19. #define FRPW_VERSION "1.03" 
  20. #include <linux/module.h>
  21. #include <linux/init.h>
  22. #include <linux/delay.h>
  23. #include <linux/kernel.h>
  24. #include <linux/types.h>
  25. #include <linux/wait.h>
  26. #include <asm/io.h>
  27. #include "paride.h"
  28. #define cec4 w2(0xc);w2(0xe);w2(0xe);w2(0xc);w2(4);w2(4);w2(4);
  29. #define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
  30. /* cont = 0 - access the IDE register file 
  31.    cont = 1 - access the IDE command set 
  32. */
  33. static int  cont_map[2] = { 0x08, 0x10 };
  34. static int frpw_read_regr( PIA *pi, int cont, int regr )
  35. { int h,l,r;
  36. r = regr + cont_map[cont];
  37. w2(4);
  38. w0(r); cec4;
  39. w2(6); l = r1();
  40. w2(4); h = r1();
  41. w2(4); 
  42. return j44(l,h);
  43. }
  44. static void frpw_write_regr( PIA *pi, int cont, int regr, int val)
  45. { int r;
  46.         r = regr + cont_map[cont];
  47. w2(4); w0(r); cec4; 
  48. w0(val);
  49. w2(5);w2(7);w2(5);w2(4);
  50. }
  51. static void frpw_read_block_int( PIA *pi, char * buf, int count, int regr )
  52. {       int     h, l, k, ph;
  53.         switch(pi->mode) {
  54.         case 0: w2(4); w0(regr); cec4;
  55.                 for (k=0;k<count;k++) {
  56.                         w2(6); l = r1();
  57.                         w2(4); h = r1();
  58.                         buf[k] = j44(l,h);
  59.                 }
  60.                 w2(4);
  61.                 break;
  62.         case 1: ph = 2;
  63.                 w2(4); w0(regr + 0xc0); cec4;
  64.                 w0(0xff);
  65.                 for (k=0;k<count;k++) {
  66.                         w2(0xa4 + ph); 
  67.                         buf[k] = r0();
  68.                         ph = 2 - ph;
  69.                 } 
  70.                 w2(0xac); w2(0xa4); w2(4);
  71.                 break;
  72.         case 2: w2(4); w0(regr + 0x80); cec4;
  73.                 for (k=0;k<count;k++) buf[k] = r4();
  74.                 w2(0xac); w2(0xa4);
  75.                 w2(4);
  76.                 break;
  77. case 3: w2(4); w0(regr + 0x80); cec4;
  78. for (k=0;k<count-2;k++) buf[k] = r4();
  79. w2(0xac); w2(0xa4);
  80. buf[count-2] = r4();
  81. buf[count-1] = r4();
  82. w2(4);
  83. break;
  84. case 4: w2(4); w0(regr + 0x80); cec4;
  85.                 for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
  86.                 w2(0xac); w2(0xa4);
  87.                 buf[count-2] = r4();
  88.                 buf[count-1] = r4();
  89.                 w2(4);
  90.                 break;
  91. case 5: w2(4); w0(regr + 0x80); cec4;
  92.                 for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
  93.                 buf[count-4] = r4();
  94.                 buf[count-3] = r4();
  95.                 w2(0xac); w2(0xa4);
  96.                 buf[count-2] = r4();
  97.                 buf[count-1] = r4();
  98.                 w2(4);
  99.                 break;
  100.         }
  101. }
  102. static void frpw_read_block( PIA *pi, char * buf, int count)
  103. { frpw_read_block_int(pi,buf,count,0x08);
  104. }
  105. static void frpw_write_block( PIA *pi, char * buf, int count )
  106.  
  107. { int k;
  108. switch(pi->mode) {
  109. case 0:
  110. case 1:
  111. case 2: w2(4); w0(8); cec4; w2(5);
  112.          for (k=0;k<count;k++) {
  113. w0(buf[k]);
  114. w2(7);w2(5);
  115. }
  116. w2(4);
  117. break;
  118. case 3: w2(4); w0(0xc8); cec4; w2(5);
  119. for (k=0;k<count;k++) w4(buf[k]);
  120. w2(4);
  121. break;
  122.         case 4: w2(4); w0(0xc8); cec4; w2(5);
  123.                 for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
  124.                 w2(4);
  125.                 break;
  126.         case 5: w2(4); w0(0xc8); cec4; w2(5);
  127.                 for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
  128.                 w2(4);
  129.                 break;
  130. }
  131. }
  132. static void frpw_connect ( PIA *pi  )
  133. {       pi->saved_r0 = r0();
  134.         pi->saved_r2 = r2();
  135. w2(4);
  136. }
  137. static void frpw_disconnect ( PIA *pi )
  138. {       w2(4); w0(0x20); cec4;
  139. w0(pi->saved_r0);
  140.         w2(pi->saved_r2);
  141. /* Stub logic to see if PNP string is available - used to distinguish
  142.    between the Xilinx and ASIC implementations of the Freecom adapter.
  143. */
  144. static int frpw_test_pnp ( PIA *pi )
  145. /*  returns chip_type:   0 = Xilinx, 1 = ASIC   */
  146. { int olddelay, a, b;
  147. #ifdef FRPW_HARD_RESET
  148.         w0(0); w2(8); udelay(50); w2(0xc);   /* parallel bus reset */
  149.         mdelay(1500);
  150. #endif
  151. olddelay = pi->delay;
  152. pi->delay = 10;
  153. pi->saved_r0 = r0();
  154.         pi->saved_r2 = r2();
  155. w2(4); w0(4); w2(6); w2(7);
  156. a = r1() & 0xff; w2(4); b = r1() & 0xff;
  157. w2(0xc); w2(0xe); w2(4);
  158. pi->delay = olddelay;
  159.         w0(pi->saved_r0);
  160.         w2(pi->saved_r2);
  161. return ((~a&0x40) && (b&0x40));
  162. /* We use the pi->private to remember the result of the PNP test.
  163.    To make this work, private = port*2 + chip.  Yes, I know it's
  164.    a hack :-(
  165. */
  166. static int frpw_test_proto( PIA *pi, char * scratch, int verbose )
  167. {       int     j, k, r;
  168. int e[2] = {0,0};
  169. if ((pi->private>>1) != pi->port)
  170.    pi->private = frpw_test_pnp(pi) + 2*pi->port;
  171. if (((pi->private%2) == 0) && (pi->mode > 2)) {
  172.    if (verbose) 
  173. printk("%s: frpw: Xilinx does not support mode %dn",
  174. pi->device, pi->mode);
  175.    return 1;
  176. }
  177. if (((pi->private%2) == 1) && (pi->mode == 2)) {
  178.    if (verbose)
  179. printk("%s: frpw: ASIC does not support mode 2n",
  180. pi->device);
  181.    return 1;
  182. }
  183. frpw_connect(pi);
  184. for (j=0;j<2;j++) {
  185.                 frpw_write_regr(pi,0,6,0xa0+j*0x10);
  186.                 for (k=0;k<256;k++) {
  187.                         frpw_write_regr(pi,0,2,k^0xaa);
  188.                         frpw_write_regr(pi,0,3,k^0x55);
  189.                         if (frpw_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
  190.                         }
  191.                 }
  192. frpw_disconnect(pi);
  193. frpw_connect(pi);
  194.         frpw_read_block_int(pi,scratch,512,0x10);
  195.         r = 0;
  196.         for (k=0;k<128;k++) if (scratch[k] != k) r++;
  197. frpw_disconnect(pi);
  198.         if (verbose)  {
  199.             printk("%s: frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)n",
  200.                    pi->device,pi->port,(pi->private%2),pi->mode,e[0],e[1],r);
  201.         }
  202.         return (r || (e[0] && e[1]));
  203. }
  204. static void frpw_log_adapter( PIA *pi, char * scratch, int verbose )
  205. {       char    *mode_string[6] = {"4-bit","8-bit","EPP",
  206.    "EPP-8","EPP-16","EPP-32"};
  207.         printk("%s: frpw %s, Freecom (%s) adapter at 0x%x, ", pi->device,
  208. FRPW_VERSION,((pi->private%2) == 0)?"Xilinx":"ASIC",pi->port);
  209.         printk("mode %d (%s), delay %dn",pi->mode,
  210. mode_string[pi->mode],pi->delay);
  211. }
  212. static struct pi_protocol frpw = {
  213. .owner = THIS_MODULE,
  214. .name = "frpw",
  215. .max_mode = 6,
  216. .epp_first = 2,
  217. .default_delay = 2,
  218. .max_units = 1,
  219. .write_regr = frpw_write_regr,
  220. .read_regr = frpw_read_regr,
  221. .write_block = frpw_write_block,
  222. .read_block = frpw_read_block,
  223. .connect = frpw_connect,
  224. .disconnect = frpw_disconnect,
  225. .test_proto = frpw_test_proto,
  226. .log_adapter = frpw_log_adapter,
  227. };
  228. static int __init frpw_init(void)
  229. {
  230. return pi_register(&frpw)-1;
  231. }
  232. static void __exit frpw_exit(void)
  233. {
  234. pi_unregister(&frpw);
  235. }
  236. MODULE_LICENSE("GPL");
  237. module_init(frpw_init)
  238. module_exit(frpw_exit)