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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.         on26.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
  3.                               Under the terms of the GNU General Public License.
  4.         on26.c is a low-level protocol driver for the 
  5.         OnSpec 90c26 parallel to IDE adapter chip.
  6. */
  7. /* Changes:
  8.         1.01    GRG 1998.05.06 init_proto, release_proto
  9. 1.02    GRG 1998.09.23 updates for the -E rev chip
  10. 1.03    GRG 1998.12.14 fix for slave drives
  11. 1.04    GRG 1998.12.20 yet another bug fix
  12. */
  13. #define ON26_VERSION      "1.04"
  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. /* mode codes:  0  nybble reads, 8-bit writes
  22.                 1  8-bit reads and writes
  23.                 2  8-bit EPP mode
  24. 3  EPP-16
  25. 4  EPP-32
  26. */
  27. #define j44(a,b)  (((a>>4)&0x0f)|(b&0xf0))
  28. #define P1 w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4);
  29. #define P2 w2(5);w2(7);w2(5);w2(4);
  30. /* cont = 0 - access the IDE register file 
  31.    cont = 1 - access the IDE command set 
  32. */
  33. static int on26_read_regr( PIA *pi, int cont, int regr )
  34. {       int     a, b, r;
  35. r = (regr<<2) + 1 + cont;
  36.         switch (pi->mode)  {
  37.         case 0: w0(1); P1; w0(r); P2; w0(0); P1; 
  38. w2(6); a = r1(); w2(4);
  39. w2(6); b = r1(); w2(4);
  40. w2(6); w2(4); w2(6); w2(4);
  41.                 return j44(a,b);
  42.         case 1: w0(1); P1; w0(r); P2; w0(0); P1;
  43. w2(0x26); a = r0(); w2(4); w2(0x26); w2(4);
  44.                 return a;
  45. case 2:
  46. case 3:
  47.         case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
  48. w3(0); w3(0); w2(0x24); a = r4(); w2(4);
  49. w2(0x24); r4(); w2(4);
  50.                 return a;
  51.         }
  52.         return -1;
  53. }       
  54. static void on26_write_regr( PIA *pi, int cont, int regr, int val )
  55. {       int  r;
  56.         r = (regr<<2) + 1 + cont;
  57.         switch (pi->mode)  {
  58.         case 0:
  59.         case 1: w0(1); P1; w0(r); P2; w0(0); P1;
  60. w0(val); P2; w0(val); P2;
  61. break;
  62. case 2:
  63. case 3:
  64.         case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
  65. w3(0); w3(0); 
  66. w2(5); w4(val); w2(4);
  67. w2(5); w4(val); w2(4);
  68.                 break;
  69.         }
  70. }
  71. #define  CCP(x)  w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);
  72.  w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
  73. static void on26_connect ( PIA *pi )
  74. {       int x;
  75. pi->saved_r0 = r0();
  76.         pi->saved_r2 = r2();
  77.         CCP(0x20);
  78. x = 8; if (pi->mode) x = 9;
  79. w0(2); P1; w0(8); P2;
  80. w0(2); P1; w0(x); P2;
  81. }
  82. static void on26_disconnect ( PIA *pi )
  83. {       if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); }
  84.               else { w0(4); P1; w0(4); P1; }
  85. CCP(0x30);
  86.         w0(pi->saved_r0);
  87.         w2(pi->saved_r2);
  88. #define RESET_WAIT  200
  89. static int on26_test_port( PIA *pi)  /* hard reset */
  90. {       int     i, m, d, x=0, y=0;
  91.         pi->saved_r0 = r0();
  92.         pi->saved_r2 = r2();
  93.         d = pi->delay;
  94.         m = pi->mode;
  95.         pi->delay = 5;
  96.         pi->mode = 0;
  97.         w2(0xc);
  98.         CCP(0x30); CCP(0); 
  99.         w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);
  100.         i = ((r1() & 0xf0) << 4); w0(0x87);
  101.         i |= (r1() & 0xf0); w0(0x78);
  102.         w0(0x20);w2(4);w2(5);
  103.         i |= ((r1() & 0xf0) >> 4);
  104.         w2(4);w0(0xff);
  105.         if (i == 0xb5f) {
  106.             w0(2); P1; w0(0);   P2;
  107.             w0(3); P1; w0(0);   P2;
  108.             w0(2); P1; w0(8);   P2; udelay(100);
  109.             w0(2); P1; w0(0xa); P2; udelay(100);
  110.             w0(2); P1; w0(8);   P2; udelay(1000);
  111.             
  112.             on26_write_regr(pi,0,6,0xa0);
  113.             for (i=0;i<RESET_WAIT;i++) {
  114.                 on26_write_regr(pi,0,6,0xa0);
  115.                 x = on26_read_regr(pi,0,7);
  116.                 on26_write_regr(pi,0,6,0xb0);
  117.                 y = on26_read_regr(pi,0,7);
  118.                 if (!((x&0x80)||(y&0x80))) break;
  119.                 mdelay(100);
  120.             }
  121.     if (i == RESET_WAIT) 
  122. printk("on26: Device reset failed (%x,%x)n",x,y);
  123.             w0(4); P1; w0(4); P1;
  124.         }
  125.         CCP(0x30);
  126.         pi->delay = d;
  127.         pi->mode = m;
  128.         w0(pi->saved_r0);
  129.         w2(pi->saved_r2);
  130.         return 5;
  131. }
  132. static void on26_read_block( PIA *pi, char * buf, int count )
  133. {       int     k, a, b;
  134.         switch (pi->mode) {
  135.         case 0: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
  136. udelay(10);
  137. for (k=0;k<count;k++) {
  138.                         w2(6); a = r1();
  139.                         w2(4); b = r1();
  140.                         buf[k] = j44(a,b);
  141.                 }
  142. w0(2); P1; w0(8); P2; 
  143.                 break;
  144.         case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
  145. udelay(10);
  146.                 for (k=0;k<count/2;k++) {
  147.                         w2(0x26); buf[2*k] = r0();  
  148. w2(0x24); buf[2*k+1] = r0();
  149.                 }
  150.                 w0(2); P1; w0(9); P2;
  151.                 break;
  152.         case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
  153. w3(0); w3(0); w2(0x24);
  154. udelay(10);
  155.                 for (k=0;k<count;k++) buf[k] = r4();
  156.                 w2(4);
  157.                 break;
  158.         case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
  159.                 w3(0); w3(0); w2(0x24);
  160.                 udelay(10);
  161.                 for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
  162.                 w2(4);
  163.                 break;
  164.         case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
  165.                 w3(0); w3(0); w2(0x24);
  166.                 udelay(10);
  167.                 for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
  168.                 w2(4);
  169.                 break;
  170.         }
  171. }
  172. static void on26_write_block( PIA *pi, char * buf, int count )
  173. {       int k;
  174.         switch (pi->mode) {
  175.         case 0: 
  176.         case 1: w0(1); P1; w0(1); P2; 
  177. w0(2); P1; w0(0x18+pi->mode); P2; w0(0); P1;
  178. udelay(10);
  179. for (k=0;k<count/2;k++) {
  180.                         w2(5); w0(buf[2*k]); 
  181. w2(7); w0(buf[2*k+1]);
  182.                 }
  183.                 w2(5); w2(4);
  184. w0(2); P1; w0(8+pi->mode); P2;
  185.                 break;
  186.         case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
  187. w3(0); w3(0); w2(0xc5);
  188. udelay(10);
  189.                 for (k=0;k<count;k++) w4(buf[k]);
  190. w2(0xc4);
  191.                 break;
  192.         case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
  193.                 w3(0); w3(0); w2(0xc5);
  194.                 udelay(10);
  195.                 for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
  196.                 w2(0xc4);
  197.                 break;
  198.         case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
  199.                 w3(0); w3(0); w2(0xc5);
  200.                 udelay(10);
  201.                 for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
  202.                 w2(0xc4);
  203.                 break;
  204.         }
  205. }
  206. static void on26_log_adapter( PIA *pi, char * scratch, int verbose )
  207. {       char    *mode_string[5] = {"4-bit","8-bit","EPP-8",
  208.    "EPP-16","EPP-32"};
  209.         printk("%s: on26 %s, OnSpec 90c26 at 0x%x, ",
  210.                 pi->device,ON26_VERSION,pi->port);
  211.         printk("mode %d (%s), delay %dn",pi->mode,
  212. mode_string[pi->mode],pi->delay);
  213. }
  214. static void on26_init_proto( PIA *pi)
  215. {       MOD_INC_USE_COUNT;
  216. }
  217. static void on26_release_proto( PIA *pi)
  218. {       MOD_DEC_USE_COUNT;
  219. }
  220. struct pi_protocol on26 = {"on26",0,5,2,1,1,
  221.                            on26_write_regr,
  222.                            on26_read_regr,
  223.                            on26_write_block,
  224.                            on26_read_block,
  225.                            on26_connect,
  226.                            on26_disconnect,
  227.                            on26_test_port,
  228.                            0,
  229.                            0,
  230.                            on26_log_adapter,
  231.                            on26_init_proto,
  232.                            on26_release_proto
  233.                           };
  234. #ifdef MODULE
  235. int     init_module(void)
  236. {       return pi_register( &on26 ) - 1;
  237. }
  238. void    cleanup_module(void)
  239. {       pi_unregister( &on26 );
  240. }
  241. #endif
  242. /* end of on26.c */
  243. MODULE_LICENSE("GPL");