root/drivers/block/paride/friq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. friq_read_regr
  2. friq_write_regr
  3. friq_read_block_int
  4. friq_read_block
  5. friq_write_block
  6. friq_connect
  7. friq_disconnect
  8. friq_test_proto
  9. friq_log_adapter
  10. friq_release_proto
  11. friq_init
  12. friq_exit

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

/* [<][>][^][v][top][bottom][index][help] */