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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2. bpck.c (c) 1996-8  Grant R. Guenther <grant@torque.net>
  3.             Under the terms of the GNU General Public License.
  4. bpck.c is a low-level protocol driver for the MicroSolutions 
  5. "backpack" parallel port IDE adapter.  
  6. */
  7. /* Changes:
  8. 1.01 GRG 1998.05.05 init_proto, release_proto, pi->delay 
  9. 1.02    GRG 1998.08.15 default pi->delay returned to 4
  10. */
  11. #define BPCK_VERSION "1.02" 
  12. #include <linux/module.h>
  13. #include <linux/delay.h>
  14. #include <linux/kernel.h>
  15. #include <linux/types.h>
  16. #include <linux/wait.h>
  17. #include <asm/io.h>
  18. #include "paride.h"
  19. #undef r2
  20. #undef w2
  21. #define PC pi->private
  22. #define r2() (PC=(in_p(2) & 0xff))
  23. #define w2(byte)   {out_p(2,byte); PC = byte;}
  24. #define t2(pat)    {PC ^= pat; out_p(2,PC);}
  25. #define e2() {PC &= 0xfe; out_p(2,PC);}
  26. #define o2() {PC |= 1; out_p(2,PC);}
  27. #define j44(l,h)     (((l>>3)&0x7)|((l>>4)&0x8)|((h<<1)&0x70)|(h&0x80))
  28. /* cont = 0 - access the IDE register file 
  29.    cont = 1 - access the IDE command set 
  30.    cont = 2 - use internal bpck register addressing
  31. */
  32. static int  cont_map[3] = { 0x40, 0x48, 0 };
  33. static int bpck_read_regr( PIA *pi, int cont, int regr )
  34. {       int r, l, h;
  35. r = regr + cont_map[cont];
  36. switch (pi->mode) {
  37. case 0: w0(r & 0xf); w0(r); t2(2); t2(4);
  38.         l = r1();
  39.          t2(4);
  40.          h = r1();
  41.          return j44(l,h);
  42. case 1: w0(r & 0xf); w0(r); t2(2);
  43.         e2(); t2(0x20);
  44. t2(4); h = r0();
  45.         t2(1); t2(0x20);
  46.         return h;
  47. case 2:
  48. case 3:
  49. case 4: w0(r); w2(9); w2(0); w2(0x20);
  50. h = r4();
  51. w2(0);
  52. return h;
  53. }
  54. return -1;
  55. }
  56. static void bpck_write_regr( PIA *pi, int cont, int regr, int val )
  57. { int r;
  58.         r = regr + cont_map[cont];
  59. switch (pi->mode) {
  60. case 0:
  61. case 1: w0(r);
  62. t2(2);
  63. w0(val);
  64. o2(); t2(4); t2(1);
  65. break;
  66. case 2:
  67. case 3:
  68. case 4: w0(r); w2(9); w2(0);
  69. w0(val); w2(1); w2(3); w2(0);
  70. break;
  71. }
  72. }
  73. /* These macros access the bpck registers in native addressing */
  74. #define WR(r,v) bpck_write_regr(pi,2,r,v)
  75. #define RR(r) (bpck_read_regr(pi,2,r))
  76. static void bpck_write_block( PIA *pi, char * buf, int count )
  77. { int i;
  78. switch (pi->mode) {
  79. case 0: WR(4,0x40);
  80. w0(0x40); t2(2); t2(1);
  81. for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
  82. WR(4,0);
  83. break;
  84. case 1: WR(4,0x50);
  85.                 w0(0x40); t2(2); t2(1);
  86.                 for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
  87.                 WR(4,0x10);
  88. break;
  89. case 2: WR(4,0x48);
  90. w0(0x40); w2(9); w2(0); w2(1);
  91. for (i=0;i<count;i++) w4(buf[i]);
  92. w2(0);
  93. WR(4,8);
  94. break;
  95.         case 3: WR(4,0x48);
  96.                 w0(0x40); w2(9); w2(0); w2(1);
  97.                 for (i=0;i<count/2;i++) w4w(((u16 *)buf)[i]);
  98.                 w2(0);
  99.                 WR(4,8);
  100.                 break;
  101.  
  102.         case 4: WR(4,0x48);
  103.                 w0(0x40); w2(9); w2(0); w2(1);
  104.                 for (i=0;i<count/4;i++) w4l(((u32 *)buf)[i]);
  105.                 w2(0);
  106.                 WR(4,8);
  107.                 break;
  108.   }
  109. }
  110. static void bpck_read_block( PIA *pi, char * buf, int count )
  111. { int i, l, h;
  112. switch (pi->mode) {
  113.        case 0: WR(4,0x40);
  114. w0(0x40); t2(2);
  115. for (i=0;i<count;i++) {
  116.     t2(4); l = r1();
  117.     t2(4); h = r1();
  118.     buf[i] = j44(l,h);
  119. }
  120. WR(4,0);
  121. break;
  122. case 1: WR(4,0x50);
  123. w0(0x40); t2(2); t2(0x20);
  124.                for(i=0;i<count;i++) { t2(4); buf[i] = r0(); }
  125.         t2(1); t2(0x20);
  126.         WR(4,0x10);
  127. break;
  128. case 2: WR(4,0x48);
  129. w0(0x40); w2(9); w2(0); w2(0x20);
  130. for (i=0;i<count;i++) buf[i] = r4();
  131. w2(0);
  132. WR(4,8);
  133. break;
  134.         case 3: WR(4,0x48);
  135.                 w0(0x40); w2(9); w2(0); w2(0x20);
  136.                 for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
  137.                 w2(0);
  138.                 WR(4,8);
  139.                 break;
  140.         case 4: WR(4,0x48);
  141.                 w0(0x40); w2(9); w2(0); w2(0x20);
  142.                 for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
  143.                 w2(0);
  144.                 WR(4,8);
  145.                 break;
  146. }
  147. }
  148. static int bpck_probe_unit ( PIA *pi )
  149. { int o1, o0, f7, id;
  150. int t, s;
  151. id = pi->unit;
  152. s = 0;
  153. w2(4); w2(0xe); r2(); t2(2); 
  154. o1 = r1()&0xf8;
  155. o0 = r0();
  156. w0(255-id); w2(4); w0(id);
  157. t2(8); t2(8); t2(8);
  158. t2(2); t = r1()&0xf8;
  159. f7 = ((id % 8) == 7);
  160. if ((f7) || (t != o1)) { t2(2); s = r1()&0xf8; }
  161. if ((t == o1) && ((!f7) || (s == o1)))  {
  162. w2(0x4c); w0(o0);
  163. return 0;
  164. }
  165. t2(8); w0(0); t2(2); w2(0x4c); w0(o0);
  166. return 1;
  167. }
  168. static void bpck_connect ( PIA *pi  )
  169. {       pi->saved_r0 = r0();
  170. w0(0xff-pi->unit); w2(4); w0(pi->unit);
  171. t2(8); t2(8); t2(8); 
  172. t2(2); t2(2);
  173. switch (pi->mode) {
  174. case 0: t2(8); WR(4,0);
  175. break;
  176. case 1: t2(8); WR(4,0x10);
  177. break;
  178. case 2:
  179.         case 3:
  180. case 4: w2(0); WR(4,8);
  181. break;
  182. }
  183. WR(5,8);
  184. if (pi->devtype == PI_PCD) {
  185. WR(0x46,0x10); /* fiddle with ESS logic ??? */
  186. WR(0x4c,0x38);
  187. WR(0x4d,0x88);
  188. WR(0x46,0xa0);
  189. WR(0x41,0);
  190. WR(0x4e,8);
  191. }
  192. }
  193. static void bpck_disconnect ( PIA *pi )
  194. { w0(0); 
  195. if (pi->mode >= 2) { w2(9); w2(0); } else t2(2);
  196. w2(0x4c); w0(pi->saved_r0);
  197. static void bpck_force_spp ( PIA *pi )
  198. /* This fakes the EPP protocol to turn off EPP ... */
  199. {       pi->saved_r0 = r0();
  200.         w0(0xff-pi->unit); w2(4); w0(pi->unit);
  201.         t2(8); t2(8); t2(8); 
  202.         t2(2); t2(2);
  203.         w2(0); 
  204.         w0(4); w2(9); w2(0); 
  205.         w0(0); w2(1); w2(3); w2(0);     
  206.         w0(0); w2(9); w2(0);
  207.         w2(0x4c); w0(pi->saved_r0);
  208. }
  209. #define TEST_LEN  16
  210. static int bpck_test_proto( PIA *pi, char * scratch, int verbose )
  211. { int i, e, l, h, om;
  212. char buf[TEST_LEN];
  213. bpck_force_spp(pi);
  214. switch (pi->mode) {
  215. case 0: bpck_connect(pi);
  216. WR(0x13,0x7f);
  217. w0(0x13); t2(2);
  218. for(i=0;i<TEST_LEN;i++) {
  219.                     t2(4); l = r1();
  220.                     t2(4); h = r1();
  221.                     buf[i] = j44(l,h);
  222. }
  223. bpck_disconnect(pi);
  224. break;
  225.         case 1: bpck_connect(pi);
  226. WR(0x13,0x7f);
  227.                 w0(0x13); t2(2); t2(0x20);
  228.                 for(i=0;i<TEST_LEN;i++) { t2(4); buf[i] = r0(); }
  229.                 t2(1); t2(0x20);
  230. bpck_disconnect(pi);
  231. break;
  232. case 2:
  233. case 3:
  234. case 4: om = pi->mode;
  235. pi->mode = 0;
  236. bpck_connect(pi);
  237. WR(7,3);
  238. WR(4,8);
  239. bpck_disconnect(pi);
  240. pi->mode = om;
  241. bpck_connect(pi);
  242. w0(0x13); w2(9); w2(1); w0(0); w2(3); w2(0); w2(0xe0);
  243. switch (pi->mode) {
  244.   case 2: for (i=0;i<TEST_LEN;i++) buf[i] = r4();
  245.   break;
  246.   case 3: for (i=0;i<TEST_LEN/2;i++) ((u16 *)buf)[i] = r4w();
  247.                           break;
  248.   case 4: for (i=0;i<TEST_LEN/4;i++) ((u32 *)buf)[i] = r4l();
  249.                           break;
  250. }
  251. w2(0);
  252. WR(7,0);
  253. bpck_disconnect(pi);
  254. break;
  255. }
  256. if (verbose) {
  257.     printk("%s: bpck: 0x%x unit %d mode %d: ",
  258.    pi->device,pi->port,pi->unit,pi->mode);
  259.     for (i=0;i<TEST_LEN;i++) printk("%3d",buf[i]);
  260.     printk("n");
  261. }
  262. e = 0;
  263. for (i=0;i<TEST_LEN;i++) if (buf[i] != (i+1)) e++;
  264. return e;
  265. }
  266. static void bpck_read_eeprom ( PIA *pi, char * buf )
  267. {       int i,j,k,n,p,v,f, om, od;
  268. bpck_force_spp(pi);
  269. om = pi->mode;  od = pi->delay;
  270. pi->mode = 0; pi->delay = 6;
  271. bpck_connect(pi);
  272. n = 0;
  273. WR(4,0);
  274. for (i=0;i<64;i++) {
  275.     WR(6,8);  
  276.     WR(6,0xc);
  277.     p = 0x100;
  278.     for (k=0;k<9;k++) {
  279. f = (((i + 0x180) & p) != 0) * 2;
  280. WR(6,f+0xc); 
  281. WR(6,f+0xd); 
  282. WR(6,f+0xc);
  283. p = (p >> 1);
  284.     }
  285.     for (j=0;j<2;j++) {
  286. v = 0;
  287. for (k=0;k<8;k++) {
  288.     WR(6,0xc); 
  289.     WR(6,0xd); 
  290.     WR(6,0xc); 
  291.     f = RR(0);
  292.     v = 2*v + (f == 0x84);
  293. }
  294. buf[2*i+1-j] = v;
  295.     }
  296. }
  297. WR(6,8);
  298. WR(6,0);
  299. WR(5,8);
  300. bpck_disconnect(pi);
  301.         if (om >= 2) {
  302.                 bpck_connect(pi);
  303.                 WR(7,3);
  304.                 WR(4,8);
  305.                 bpck_disconnect(pi);
  306.         }
  307. pi->mode = om; pi->delay = od;
  308. }
  309. static int bpck_test_port ( PIA *pi )  /* check for 8-bit port */
  310. { int i, r, m;
  311. w2(0x2c); i = r0(); w0(255-i); r = r0(); w0(i);
  312. m = -1;
  313. if (r == i) m = 2;
  314. if (r == (255-i)) m = 0;
  315. w2(0xc); i = r0(); w0(255-i); r = r0(); w0(i);
  316. if (r != (255-i)) m = -1;
  317. if (m == 0) { w2(6); w2(0xc); r = r0(); w0(0xaa); w0(r); w0(0xaa); }
  318. if (m == 2) { w2(0x26); w2(0xc); }
  319. if (m == -1) return 0;
  320. return 5;
  321. }
  322. static void bpck_log_adapter( PIA *pi, char * scratch, int verbose )
  323. { char *mode_string[5] = { "4-bit","8-bit","EPP-8",
  324.     "EPP-16","EPP-32" };
  325. #ifdef DUMP_EEPROM
  326. int i;
  327. #endif
  328. bpck_read_eeprom(pi,scratch);
  329. #ifdef DUMP_EEPROM
  330. if (verbose) {
  331.    for(i=0;i<128;i++)
  332. if ((scratch[i] < ' ') || (scratch[i] > '~'))
  333.     scratch[i] = '.';
  334.    printk("%s: bpck EEPROM: %64.64sn",pi->device,scratch);
  335.    printk("%s:              %64.64sn",pi->device,&scratch[64]);
  336. }
  337. #endif
  338. printk("%s: bpck %s, backpack %8.8s unit %d",
  339. pi->device,BPCK_VERSION,&scratch[110],pi->unit);
  340. printk(" at 0x%x, mode %d (%s), delay %dn",pi->port,
  341. pi->mode,mode_string[pi->mode],pi->delay);
  342. }
  343. static void bpck_init_proto( PIA *pi)
  344. { MOD_INC_USE_COUNT;
  345. }
  346. static void bpck_release_proto( PIA *pi)
  347. {       MOD_DEC_USE_COUNT;
  348. }
  349. struct pi_protocol bpck = { "bpck",0,5,2,4,256,
  350.   bpck_write_regr,
  351.   bpck_read_regr,
  352.   bpck_write_block,
  353.   bpck_read_block,
  354.   bpck_connect,
  355.   bpck_disconnect,
  356.   bpck_test_port,
  357.   bpck_probe_unit,
  358.           bpck_test_proto,
  359.   bpck_log_adapter,
  360.   bpck_init_proto,
  361.   bpck_release_proto
  362. };
  363. #ifdef MODULE
  364. int init_module(void)
  365. { return pi_register(&bpck) - 1;
  366. }
  367. void cleanup_module(void)
  368. { pi_unregister(&bpck);
  369. }
  370. #endif
  371. /* end of bpck.c */
  372. MODULE_LICENSE("GPL");