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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.         epat.c  (c) 1997-8  Grant R. Guenther <grant@torque.net>
  3.                             Under the terms of the GNU General Public License.
  4. This is the low level protocol driver for the EPAT parallel
  5.         to IDE adapter from Shuttle Technologies.  This adapter is
  6.         used in many popular parallel port disk products such as the
  7.         SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk.
  8. */
  9. /* Changes:
  10.         1.01    GRG 1998.05.06 init_proto, release_proto
  11.         1.02    Joshua b. Jore CPP(renamed), epat_connect, epat_disconnect
  12. */
  13. #define EPAT_VERSION      "1.02"
  14. #include <linux/module.h>
  15. #include <linux/delay.h>
  16. #include <linux/kernel.h>
  17. #include <linux/types.h>
  18. #include <linux/wait.h>
  19. #include <asm/io.h>
  20. #include "paride.h"
  21. #define j44(a,b) (((a>>4)&0x0f)+(b&0xf0))
  22. #define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0))
  23. /* cont =  0   IDE register file
  24.    cont =  1   IDE control registers
  25.    cont =  2   internal EPAT registers
  26. */
  27. static int cont_map[3] = { 0x18, 0x10, 0 };
  28. static void epat_write_regr( PIA *pi, int cont, int regr, int val)
  29. { int r;
  30. r = regr + cont_map[cont];
  31. switch (pi->mode) {
  32. case 0:
  33. case 1:
  34. case 2: w0(0x60+r); w2(1); w0(val); w2(4);
  35. break;
  36. case 3:
  37. case 4:
  38. case 5: w3(0x40+r); w4(val);
  39. break;
  40. }
  41. }
  42. static int epat_read_regr( PIA *pi, int cont, int regr )
  43. { int  a, b, r;
  44. r = regr + cont_map[cont];
  45. switch (pi->mode) {
  46. case 0: w0(r); w2(1); w2(3); 
  47. a = r1(); w2(4); b = r1();
  48. return j44(a,b);
  49. case 1: w0(0x40+r); w2(1); w2(4);
  50. a = r1(); b = r2(); w0(0xff);
  51. return j53(a,b);
  52. case 2: w0(0x20+r); w2(1); w2(0x25);
  53. a = r0(); w2(4);
  54. return a;
  55. case 3:
  56. case 4:
  57. case 5: w3(r); w2(0x24); a = r4(); w2(4);
  58. return a;
  59. }
  60. return -1; /* never gets here */
  61. }
  62. static void epat_read_block( PIA *pi, char * buf, int count )
  63. { int  k, ph, a, b;
  64. switch (pi->mode) {
  65. case 0: w0(7); w2(1); w2(3); w0(0xff);
  66. ph = 0;
  67. for(k=0;k<count;k++) {
  68. if (k == count-1) w0(0xfd);
  69. w2(6+ph); a = r1();
  70. if (a & 8) b = a; 
  71.   else { w2(4+ph); b = r1(); }
  72. buf[k] = j44(a,b);
  73. ph =  1 - ph;
  74. }
  75. w0(0); w2(4);
  76. break;
  77. case 1: w0(0x47); w2(1); w2(5); w0(0xff);
  78. ph = 0;
  79. for(k=0;k<count;k++) {
  80. if (k == count-1) w0(0xfd); 
  81. w2(4+ph);
  82. a = r1(); b = r2();
  83. buf[k] = j53(a,b);
  84. ph = 1 - ph;
  85. }
  86. w0(0); w2(4);
  87. break;
  88. case 2: w0(0x27); w2(1); w2(0x25); w0(0);
  89. ph = 0;
  90. for(k=0;k<count-1;k++) {
  91. w2(0x24+ph);
  92. buf[k] = r0();
  93. ph = 1 - ph;
  94. }
  95. w2(0x26); w2(0x27); buf[count-1] = r0(); 
  96. w2(0x25); w2(4);
  97. break;
  98. case 3: w3(0x80); w2(0x24);
  99. for(k=0;k<count-1;k++) buf[k] = r4();
  100. w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
  101. w2(4);
  102. break;
  103. case 4: w3(0x80); w2(0x24);
  104. for(k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
  105. buf[count-2] = r4();
  106. w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
  107. w2(4);
  108. break;
  109. case 5: w3(0x80); w2(0x24);
  110. for(k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
  111. for(k=count-4;k<count-1;k++) buf[k] = r4();
  112. w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
  113. w2(4);
  114. break;
  115. }
  116. }
  117. static void epat_write_block( PIA *pi, char * buf, int count )   
  118. { int ph, k;
  119. switch (pi->mode) {
  120. case 0:
  121. case 1:
  122. case 2: w0(0x67); w2(1); w2(5);
  123. ph = 0;
  124. for(k=0;k<count;k++) {
  125.    w0(buf[k]);
  126. w2(4+ph);
  127. ph = 1 - ph;
  128. }
  129. w2(7); w2(4);
  130. break;
  131. case 3: w3(0xc0); 
  132. for(k=0;k<count;k++) w4(buf[k]);
  133. w2(4);
  134. break;
  135. case 4: w3(0xc0); 
  136. for(k=0;k<(count/2);k++) w4w(((u16 *)buf)[k]);
  137. w2(4);
  138. break;
  139. case 5: w3(0xc0); 
  140. for(k=0;k<(count/4);k++) w4l(((u32 *)buf)[k]);
  141. w2(4);
  142. break;
  143. }
  144. }
  145. /* these macros access the EPAT registers in native addressing */
  146. #define WR(r,v) epat_write_regr(pi,2,r,v)
  147. #define RR(r) (epat_read_regr(pi,2,r))
  148. /* and these access the IDE task file */
  149. #define WRi(r,v)         epat_write_regr(pi,0,r,v)
  150. #define RRi(r)           (epat_read_regr(pi,0,r))
  151. /* FIXME:  the CPP stuff should be fixed to handle multiple EPATs on a chain */
  152. #define CPP(x)  w2(4);w0(0x22);w0(0xaa);w0(0x55);w0(0);w0(0xff);
  153.                 w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
  154. static void epat_connect ( PIA *pi )
  155. {       pi->saved_r0 = r0();
  156.         pi->saved_r2 = r2();
  157. #ifdef CONFIG_PARIDE_EPATC8
  158.   /* Initialize the chip */
  159.         CPP(0);CPP(0x40);CPP(0xe0);              
  160.         w0(0);w2(1);w2(4);
  161.         WR(0x8,0x12);WR(0xc,0x14);WR(0x12,0x10);
  162.         WR(0xe,0xf);WR(0xf,4);
  163.      /* WR(0xe,0xa);WR(0xf,4); */
  164.         WR(0xe,0xd);WR(0xf,0);
  165.      /* CPP(0x30); */
  166.         /* Connect to the chip */
  167. CPP(0xe0);
  168.         w0(0);w2(1);w2(4); /* Idle into SPP */
  169.         if (pi->mode >= 3) {
  170.           w0(0);w2(1);w2(4);w2(0xc);
  171.           /* Request EPP */
  172.           w0(0x40);w2(6);w2(7);w2(4);w2(0xc);w2(4);
  173.         }
  174. #else
  175.   CPP(0); CPP(0xe0);
  176. w0(0); w2(1); w2(4);
  177. if (pi->mode >= 3) {
  178. w0(0); w2(1); w2(4); w2(0xc);
  179. w0(0x40); w2(6); w2(7); w2(4); w2(0xc); w2(4);
  180. }
  181. WR(8,0x10); WR(0xc,0x14); WR(0xa,0x38); WR(0x12,0x10);
  182. #endif
  183. }
  184. static void epat_disconnect (PIA *pi)
  185. { CPP(0x30);
  186. w0(pi->saved_r0);
  187. w2(pi->saved_r2);
  188. }
  189. static int epat_test_proto( PIA *pi, char * scratch, int verbose )
  190. {       int     k, j, f, cc;
  191. int e[2] = {0,0};
  192.         epat_connect(pi);
  193. cc = RR(0xd);
  194. epat_disconnect(pi);
  195. epat_connect(pi);
  196. for (j=0;j<2;j++) {
  197.        WRi(6,0xa0+j*0x10);
  198.             for (k=0;k<256;k++) {
  199.                 WRi(2,k^0xaa);
  200.                 WRi(3,k^0x55);
  201.                 if (RRi(2) != (k^0xaa)) e[j]++;
  202.                 }
  203.     }
  204.         epat_disconnect(pi);
  205.         f = 0;
  206.         epat_connect(pi);
  207.         WR(0x13,1); WR(0x13,0); WR(0xa,0x11);
  208.         epat_read_block(pi,scratch,512);
  209.         for (k=0;k<256;k++) {
  210.             if ((scratch[2*k] & 0xff) != k) f++;
  211.             if ((scratch[2*k+1] & 0xff) != (0xff-k)) f++;
  212.         }
  213.         epat_disconnect(pi);
  214.         if (verbose)  {
  215.             printk("%s: epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)n",
  216.    pi->device,pi->port,pi->mode,cc,e[0],e[1],f);
  217. }
  218.         return (e[0] && e[1]) || f;
  219. }
  220. static void epat_log_adapter( PIA *pi, char * scratch, int verbose )
  221. { int ver;
  222.         char    *mode_string[6] = 
  223.    {"4-bit","5/3","8-bit","EPP-8","EPP-16","EPP-32"};
  224. epat_connect(pi);
  225. WR(0xa,0x38); /* read the version code */
  226.         ver = RR(0xb);
  227.         epat_disconnect(pi);
  228. printk("%s: epat %s, Shuttle EPAT chip %x at 0x%x, ",
  229. pi->device,EPAT_VERSION,ver,pi->port);
  230. printk("mode %d (%s), delay %dn",pi->mode,
  231. mode_string[pi->mode],pi->delay);
  232. }
  233. static void epat_init_proto( PIA *pi)
  234. {   MOD_INC_USE_COUNT;
  235. }
  236. static void epat_release_proto( PIA *pi)
  237. { MOD_DEC_USE_COUNT;
  238. }
  239. struct pi_protocol epat = {"epat",0,6,3,1,1,
  240.    epat_write_regr,
  241.    epat_read_regr,
  242.    epat_write_block,
  243.    epat_read_block,
  244.    epat_connect,
  245.    epat_disconnect,
  246.    0,
  247.    0,
  248.    epat_test_proto,
  249.    epat_log_adapter,
  250.    epat_init_proto,
  251.    epat_release_proto
  252.   };
  253. #ifdef MODULE
  254. int init_module(void)
  255. { return pi_register( &epat) - 1;
  256. }
  257. void cleanup_module(void)
  258. { pi_unregister( &epat);
  259. }
  260. #endif
  261. /* end of epat.c */
  262. MODULE_LICENSE("GPL");