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

驱动编程

开发平台:

Unix_Linux

  1. /* 
  2. friq.c (c) 1998    Grant R. Guenther <grant@torque.net>
  3.             Under the terms of the GNU General Public License
  4. friq.c is a low-level protocol driver for the Freecom "IQ"
  5. parallel port IDE adapter.   Early versions of this adapter
  6. use the 'frpw' protocol.
  7. Freecom uses this adapter in a battery powered external 
  8. CD-ROM drive.  It is also used in LS-120 drives by
  9. Maxell and Panasonic, and other devices.
  10. The battery powered drive requires software support to
  11. control the power to the drive.  This module enables the
  12. drive power when the high level driver (pcd) is loaded
  13. and disables it when the module is unloaded.  Note, if
  14. the friq module is built in to the kernel, the power
  15. will never be switched off, so other means should be
  16. used to conserve battery power.
  17. */
  18. /* Changes:
  19. 1.01 GRG 1998.12.20  Added support for soft power switch
  20. */
  21. #define FRIQ_VERSION "1.01" 
  22. #include <linux/module.h>
  23. #include <linux/init.h>
  24. #include <linux/delay.h>
  25. #include <linux/kernel.h>
  26. #include <linux/types.h>
  27. #include <linux/wait.h>
  28. #include <asm/io.h>
  29. #include "paride.h"
  30. #define CMD(x) w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);
  31. w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(x);
  32. #define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
  33. /* cont = 0 - access the IDE register file 
  34.    cont = 1 - access the IDE command set 
  35. */
  36. static int  cont_map[2] = { 0x08, 0x10 };
  37. static int friq_read_regr( PIA *pi, int cont, int regr )
  38. { int h,l,r;
  39. r = regr + cont_map[cont];
  40. CMD(r);
  41. w2(6); l = r1();
  42. w2(4); h = r1();
  43. w2(4); 
  44. return j44(l,h);
  45. }
  46. static void friq_write_regr( PIA *pi, int cont, int regr, int val)
  47. { int r;
  48.         r = regr + cont_map[cont];
  49. CMD(r);
  50. w0(val);
  51. w2(5);w2(7);w2(5);w2(4);
  52. }
  53. static void friq_read_block_int( PIA *pi, char * buf, int count, int regr )
  54. {       int     h, l, k, ph;
  55.         switch(pi->mode) {
  56.         case 0: CMD(regr); 
  57.                 for (k=0;k<count;k++) {
  58.                         w2(6); l = r1();
  59.                         w2(4); h = r1();
  60.                         buf[k] = j44(l,h);
  61.                 }
  62.                 w2(4);
  63.                 break;
  64.         case 1: ph = 2;
  65.                 CMD(regr+0xc0); 
  66.                 w0(0xff);
  67.                 for (k=0;k<count;k++) {
  68.                         w2(0xa4 + ph); 
  69.                         buf[k] = r0();
  70.                         ph = 2 - ph;
  71.                 } 
  72.                 w2(0xac); w2(0xa4); w2(4);
  73.                 break;
  74. case 2: CMD(regr+0x80);
  75. for (k=0;k<count-2;k++) buf[k] = r4();
  76. w2(0xac); w2(0xa4);
  77. buf[count-2] = r4();
  78. buf[count-1] = r4();
  79. w2(4);
  80. break;
  81. case 3: CMD(regr+0x80);
  82.                 for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
  83.                 w2(0xac); w2(0xa4);
  84.                 buf[count-2] = r4();
  85.                 buf[count-1] = r4();
  86.                 w2(4);
  87.                 break;
  88. case 4: CMD(regr+0x80);
  89.                 for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
  90.                 buf[count-4] = r4();
  91.                 buf[count-3] = r4();
  92.                 w2(0xac); w2(0xa4);
  93.                 buf[count-2] = r4();
  94.                 buf[count-1] = r4();
  95.                 w2(4);
  96.                 break;
  97.         }
  98. }
  99. static void friq_read_block( PIA *pi, char * buf, int count)
  100. { friq_read_block_int(pi,buf,count,0x08);
  101. }
  102. static void friq_write_block( PIA *pi, char * buf, int count )
  103.  
  104. { int k;
  105. switch(pi->mode) {
  106. case 0:
  107. case 1: CMD(8); w2(5);
  108.          for (k=0;k<count;k++) {
  109. w0(buf[k]);
  110. w2(7);w2(5);
  111. }
  112. w2(4);
  113. break;
  114. case 2: CMD(0xc8); w2(5);
  115. for (k=0;k<count;k++) w4(buf[k]);
  116. w2(4);
  117. break;
  118.         case 3: CMD(0xc8); w2(5);
  119.                 for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
  120.                 w2(4);
  121.                 break;
  122.         case 4: CMD(0xc8); w2(5);
  123.                 for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
  124.                 w2(4);
  125.                 break;
  126. }
  127. }
  128. static void friq_connect ( PIA *pi  )
  129. {       pi->saved_r0 = r0();
  130.         pi->saved_r2 = r2();
  131. w2(4);
  132. }
  133. static void friq_disconnect ( PIA *pi )
  134. {       CMD(0x20);
  135. w0(pi->saved_r0);
  136.         w2(pi->saved_r2);
  137. static int friq_test_proto( PIA *pi, char * scratch, int verbose )
  138. {       int     j, k, r;
  139. int e[2] = {0,0};
  140. pi->saved_r0 = r0();
  141. w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */
  142. udelay(500);
  143. w0(pi->saved_r0);
  144. friq_connect(pi);
  145. for (j=0;j<2;j++) {
  146.                 friq_write_regr(pi,0,6,0xa0+j*0x10);
  147.                 for (k=0;k<256;k++) {
  148.                         friq_write_regr(pi,0,2,k^0xaa);
  149.                         friq_write_regr(pi,0,3,k^0x55);
  150.                         if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
  151.                         }
  152.                 }
  153. friq_disconnect(pi);
  154. friq_connect(pi);
  155.         friq_read_block_int(pi,scratch,512,0x10);
  156.         r = 0;
  157.         for (k=0;k<128;k++) if (scratch[k] != k) r++;
  158. friq_disconnect(pi);
  159.         if (verbose)  {
  160.             printk("%s: friq: port 0x%x, mode %d, test=(%d,%d,%d)n",
  161.                    pi->device,pi->port,pi->mode,e[0],e[1],r);
  162.         }
  163.         return (r || (e[0] && e[1]));
  164. }
  165. static void friq_log_adapter( PIA *pi, char * scratch, int verbose )
  166. {       char    *mode_string[6] = {"4-bit","8-bit",
  167.    "EPP-8","EPP-16","EPP-32"};
  168.         printk("%s: friq %s, Freecom IQ ASIC-2 adapter at 0x%x, ", pi->device,
  169. FRIQ_VERSION,pi->port);
  170.         printk("mode %d (%s), delay %dn",pi->mode,
  171. mode_string[pi->mode],pi->delay);
  172. pi->private = 1;
  173. friq_connect(pi);
  174. CMD(0x9e);   /* disable sleep timer */
  175. friq_disconnect(pi);
  176. }
  177. static void friq_release_proto( PIA *pi)
  178. {
  179. if (pi->private) { /* turn off the power */
  180. friq_connect(pi);
  181. CMD(0x1d); CMD(0x1e);
  182. friq_disconnect(pi);
  183. pi->private = 0;
  184. }
  185. }
  186. static struct pi_protocol friq = {
  187. .owner = THIS_MODULE,
  188. .name = "friq",
  189. .max_mode = 5,
  190. .epp_first = 2,
  191. .default_delay = 1,
  192. .max_units = 1,
  193. .write_regr = friq_write_regr,
  194. .read_regr = friq_read_regr,
  195. .write_block = friq_write_block,
  196. .read_block = friq_read_block,
  197. .connect = friq_connect,
  198. .disconnect = friq_disconnect,
  199. .test_proto = friq_test_proto,
  200. .log_adapter = friq_log_adapter,
  201. .release_proto = friq_release_proto,
  202. };
  203. static int __init friq_init(void)
  204. {
  205. return pi_register(&friq)-1;
  206. }
  207. static void __exit friq_exit(void)
  208. {
  209. pi_unregister(&friq);
  210. }
  211. MODULE_LICENSE("GPL");
  212. module_init(friq_init)
  213. module_exit(friq_exit)