frpw.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

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/delay.h>
  22. #include <linux/kernel.h>
  23. #include <linux/types.h>
  24. #include <linux/wait.h>
  25. #include <asm/io.h>
  26. #include "paride.h"
  27. #define cec4 w2(0xc);w2(0xe);w2(0xe);w2(0xc);w2(4);w2(4);w2(4);
  28. #define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
  29. /* cont = 0 - access the IDE register file 
  30.    cont = 1 - access the IDE command set 
  31. */
  32. static int  cont_map[2] = { 0x08, 0x10 };
  33. static int frpw_read_regr( PIA *pi, int cont, int regr )
  34. { int h,l,r;
  35. r = regr + cont_map[cont];
  36. w2(4);
  37. w0(r); cec4;
  38. w2(6); l = r1();
  39. w2(4); h = r1();
  40. w2(4); 
  41. return j44(l,h);
  42. }
  43. static void frpw_write_regr( PIA *pi, int cont, int regr, int val)
  44. { int r;
  45.         r = regr + cont_map[cont];
  46. w2(4); w0(r); cec4; 
  47. w0(val);
  48. w2(5);w2(7);w2(5);w2(4);
  49. }
  50. static void frpw_read_block_int( PIA *pi, char * buf, int count, int regr )
  51. {       int     h, l, k, ph;
  52.         switch(pi->mode) {
  53.         case 0: w2(4); w0(regr); cec4;
  54.                 for (k=0;k<count;k++) {
  55.                         w2(6); l = r1();
  56.                         w2(4); h = r1();
  57.                         buf[k] = j44(l,h);
  58.                 }
  59.                 w2(4);
  60.                 break;
  61.         case 1: ph = 2;
  62.                 w2(4); w0(regr + 0xc0); cec4;
  63.                 w0(0xff);
  64.                 for (k=0;k<count;k++) {
  65.                         w2(0xa4 + ph); 
  66.                         buf[k] = r0();
  67.                         ph = 2 - ph;
  68.                 } 
  69.                 w2(0xac); w2(0xa4); w2(4);
  70.                 break;
  71.         case 2: w2(4); w0(regr + 0x80); cec4;
  72.                 for (k=0;k<count;k++) buf[k] = r4();
  73.                 w2(0xac); w2(0xa4);
  74.                 w2(4);
  75.                 break;
  76. case 3: w2(4); w0(regr + 0x80); cec4;
  77. for (k=0;k<count-2;k++) buf[k] = r4();
  78. w2(0xac); w2(0xa4);
  79. buf[count-2] = r4();
  80. buf[count-1] = r4();
  81. w2(4);
  82. break;
  83. case 4: w2(4); w0(regr + 0x80); cec4;
  84.                 for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
  85.                 w2(0xac); w2(0xa4);
  86.                 buf[count-2] = r4();
  87.                 buf[count-1] = r4();
  88.                 w2(4);
  89.                 break;
  90. case 5: w2(4); w0(regr + 0x80); cec4;
  91.                 for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
  92.                 buf[count-4] = r4();
  93.                 buf[count-3] = r4();
  94.                 w2(0xac); w2(0xa4);
  95.                 buf[count-2] = r4();
  96.                 buf[count-1] = r4();
  97.                 w2(4);
  98.                 break;
  99.         }
  100. }
  101. static void frpw_read_block( PIA *pi, char * buf, int count)
  102. { frpw_read_block_int(pi,buf,count,0x08);
  103. }
  104. static void frpw_write_block( PIA *pi, char * buf, int count )
  105.  
  106. { int k;
  107. switch(pi->mode) {
  108. case 0:
  109. case 1:
  110. case 2: w2(4); w0(8); cec4; w2(5);
  111.          for (k=0;k<count;k++) {
  112. w0(buf[k]);
  113. w2(7);w2(5);
  114. }
  115. w2(4);
  116. break;
  117. case 3: w2(4); w0(0xc8); cec4; w2(5);
  118. for (k=0;k<count;k++) w4(buf[k]);
  119. w2(4);
  120. break;
  121.         case 4: w2(4); w0(0xc8); cec4; w2(5);
  122.                 for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
  123.                 w2(4);
  124.                 break;
  125.         case 5: w2(4); w0(0xc8); cec4; w2(5);
  126.                 for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
  127.                 w2(4);
  128.                 break;
  129. }
  130. }
  131. static void frpw_connect ( PIA *pi  )
  132. {       pi->saved_r0 = r0();
  133.         pi->saved_r2 = r2();
  134. w2(4);
  135. }
  136. static void frpw_disconnect ( PIA *pi )
  137. {       w2(4); w0(0x20); cec4;
  138. w0(pi->saved_r0);
  139.         w2(pi->saved_r2);
  140. /* Stub logic to see if PNP string is available - used to distinguish
  141.    between the Xilinx and ASIC implementations of the Freecom adapter.
  142. */
  143. static int frpw_test_pnp ( PIA *pi )
  144. /*  returns chip_type:   0 = Xilinx, 1 = ASIC   */
  145. { int olddelay, a, b;
  146. #ifdef FRPW_HARD_RESET
  147.         w0(0); w2(8); udelay(50); w2(0xc);   /* parallel bus reset */
  148.         mdelay(1500);
  149. #endif
  150. olddelay = pi->delay;
  151. pi->delay = 10;
  152. pi->saved_r0 = r0();
  153.         pi->saved_r2 = r2();
  154. w2(4); w0(4); w2(6); w2(7);
  155. a = r1() & 0xff; w2(4); b = r1() & 0xff;
  156. w2(0xc); w2(0xe); w2(4);
  157. pi->delay = olddelay;
  158.         w0(pi->saved_r0);
  159.         w2(pi->saved_r2);
  160. return ((~a&0x40) && (b&0x40));
  161. /* We use the pi->private to remember the result of the PNP test.
  162.    To make this work, private = port*2 + chip.  Yes, I know it's
  163.    a hack :-(
  164. */
  165. static int frpw_test_proto( PIA *pi, char * scratch, int verbose )
  166. {       int     j, k, r;
  167. int e[2] = {0,0};
  168. if ((pi->private>>1) != pi->port)
  169.    pi->private = frpw_test_pnp(pi) + 2*pi->port;
  170. if (((pi->private%2) == 0) && (pi->mode > 2)) {
  171.    if (verbose) 
  172. printk("%s: frpw: Xilinx does not support mode %dn",
  173. pi->device, pi->mode);
  174.    return 1;
  175. }
  176. if (((pi->private%2) == 1) && (pi->mode == 2)) {
  177.    if (verbose)
  178. printk("%s: frpw: ASIC does not support mode 2n",
  179. pi->device);
  180.    return 1;
  181. }
  182. frpw_connect(pi);
  183. for (j=0;j<2;j++) {
  184.                 frpw_write_regr(pi,0,6,0xa0+j*0x10);
  185.                 for (k=0;k<256;k++) {
  186.                         frpw_write_regr(pi,0,2,k^0xaa);
  187.                         frpw_write_regr(pi,0,3,k^0x55);
  188.                         if (frpw_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
  189.                         }
  190.                 }
  191. frpw_disconnect(pi);
  192. frpw_connect(pi);
  193.         frpw_read_block_int(pi,scratch,512,0x10);
  194.         r = 0;
  195.         for (k=0;k<128;k++) if (scratch[k] != k) r++;
  196. frpw_disconnect(pi);
  197.         if (verbose)  {
  198.             printk("%s: frpw: port 0x%x, chip %d, mode %d, test=(%d,%d,%d)n",
  199.                    pi->device,pi->port,(pi->private%2),pi->mode,e[0],e[1],r);
  200.         }
  201.         return (r || (e[0] && e[1]));
  202. }
  203. static void frpw_log_adapter( PIA *pi, char * scratch, int verbose )
  204. {       char    *mode_string[6] = {"4-bit","8-bit","EPP",
  205.    "EPP-8","EPP-16","EPP-32"};
  206.         printk("%s: frpw %s, Freecom (%s) adapter at 0x%x, ", pi->device,
  207. FRPW_VERSION,((pi->private%2) == 0)?"Xilinx":"ASIC",pi->port);
  208.         printk("mode %d (%s), delay %dn",pi->mode,
  209. mode_string[pi->mode],pi->delay);
  210. }
  211. static void frpw_init_proto( PIA *pi)
  212. {       MOD_INC_USE_COUNT;
  213. pi->private = 0;
  214. }
  215. static void frpw_release_proto( PIA *pi)
  216. {       MOD_DEC_USE_COUNT;
  217. }
  218. struct pi_protocol frpw = {"frpw",0,6,2,2,1,
  219.                            frpw_write_regr,
  220.                            frpw_read_regr,
  221.                            frpw_write_block,
  222.                            frpw_read_block,
  223.                            frpw_connect,
  224.                            frpw_disconnect,
  225.                            0,
  226.                            0,
  227.                            frpw_test_proto,
  228.                            frpw_log_adapter,
  229.                            frpw_init_proto,
  230.                            frpw_release_proto
  231.                           };
  232. #ifdef MODULE
  233. int     init_module(void)
  234. {       return pi_register( &frpw ) - 1;
  235. }
  236. void    cleanup_module(void)
  237. {       pi_unregister( &frpw );
  238. }
  239. #endif
  240. /* end of frpw.c */
  241. MODULE_LICENSE("GPL");