linux/drivers/block/paride/comm.c
<<
>>
Prefs
   1/* 
   2        comm.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
   3                              Under the terms of the GNU General Public License.
   4
   5        comm.c is a low-level protocol driver for some older models
   6        of the DataStor "Commuter" parallel to IDE adapter.  Some of
   7        the parallel port devices marketed by Arista currently
   8        use this adapter.
   9*/
  10
  11/* Changes:
  12
  13        1.01    GRG 1998.05.05  init_proto, release_proto
  14
  15*/
  16
  17#define COMM_VERSION      "1.01"
  18
  19#include <linux/module.h>
  20#include <linux/init.h>
  21#include <linux/delay.h>
  22#include <linux/kernel.h>
  23#include <linux/types.h>
  24#include <linux/wait.h>
  25#include <asm/io.h>
  26
  27#include "paride.h"
  28
  29/* mode codes:  0  nybble reads, 8-bit writes
  30                1  8-bit reads and writes
  31                2  8-bit EPP mode
  32*/
  33
  34#define j44(a,b)        (((a>>3)&0x0f)|((b<<1)&0xf0))
  35
  36#define P1      w2(5);w2(0xd);w2(0xd);w2(5);w2(4);
  37#define P2      w2(5);w2(7);w2(7);w2(5);w2(4);
  38
  39/* cont = 0 - access the IDE register file 
  40   cont = 1 - access the IDE command set 
  41*/
  42
  43static int  cont_map[2] = { 0x08, 0x10 };
  44
  45static int comm_read_regr( PIA *pi, int cont, int regr )
  46
  47{       int     l, h, r;
  48
  49        r = regr + cont_map[cont];
  50
  51        switch (pi->mode)  {
  52
  53        case 0: w0(r); P1; w0(0);
  54                w2(6); l = r1(); w0(0x80); h = r1(); w2(4);
  55                return j44(l,h);
  56
  57        case 1: w0(r+0x20); P1; 
  58                w0(0); w2(0x26); h = r0(); w2(4);
  59                return h;
  60
  61        case 2:
  62        case 3:
  63        case 4: w3(r+0x20); (void)r1();
  64                w2(0x24); h = r4(); w2(4);
  65                return h;
  66
  67        }
  68        return -1;
  69}       
  70
  71static void comm_write_regr( PIA *pi, int cont, int regr, int val )
  72
  73{       int  r;
  74
  75        r = regr + cont_map[cont];
  76
  77        switch (pi->mode)  {
  78
  79        case 0:
  80        case 1: w0(r); P1; w0(val); P2;
  81                break;
  82
  83        case 2:
  84        case 3:
  85        case 4: w3(r); (void)r1(); w4(val);
  86                break;
  87        }
  88}
  89
  90static void comm_connect ( PIA *pi  )
  91
  92{       pi->saved_r0 = r0();
  93        pi->saved_r2 = r2();
  94        w2(4); w0(0xff); w2(6);
  95        w2(4); w0(0xaa); w2(6);
  96        w2(4); w0(0x00); w2(6);
  97        w2(4); w0(0x87); w2(6);
  98        w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4);
  99}
 100
 101static void comm_disconnect ( PIA *pi )
 102
 103{       w2(0); w2(0); w2(0); w2(4); 
 104        w0(pi->saved_r0);
 105        w2(pi->saved_r2);
 106} 
 107
 108static void comm_read_block( PIA *pi, char * buf, int count )
 109
 110{       int     i, l, h;
 111
 112        switch (pi->mode) {
 113        
 114        case 0: w0(0x48); P1;
 115                for(i=0;i<count;i++) {
 116                        w0(0); w2(6); l = r1();
 117                        w0(0x80); h = r1(); w2(4);
 118                        buf[i] = j44(l,h);
 119                }
 120                break;
 121
 122        case 1: w0(0x68); P1; w0(0);
 123                for(i=0;i<count;i++) {
 124                        w2(0x26); buf[i] = r0(); w2(0x24);
 125                }
 126                w2(4);
 127                break;
 128                
 129        case 2: w3(0x68); (void)r1(); w2(0x24);
 130                for (i=0;i<count;i++) buf[i] = r4();
 131                w2(4);
 132                break;
 133
 134        case 3: w3(0x68); (void)r1(); w2(0x24);
 135                for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
 136                w2(4);
 137                break;
 138
 139        case 4: w3(0x68); (void)r1(); w2(0x24);
 140                for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
 141                w2(4);
 142                break;
 143                
 144        }
 145}
 146
 147/* NB: Watch out for the byte swapped writes ! */
 148
 149static void comm_write_block( PIA *pi, char * buf, int count )
 150
 151{       int     k;
 152
 153        switch (pi->mode) {
 154
 155        case 0:
 156        case 1: w0(0x68); P1;
 157                for (k=0;k<count;k++) {
 158                        w2(5); w0(buf[k^1]); w2(7);
 159                }
 160                w2(5); w2(4);
 161                break;
 162
 163        case 2: w3(0x48); (void)r1();
 164                for (k=0;k<count;k++) w4(buf[k^1]);
 165                break;
 166
 167        case 3: w3(0x48); (void)r1();
 168                for (k=0;k<count/2;k++) w4w(pi_swab16(buf,k));
 169                break;
 170
 171        case 4: w3(0x48); (void)r1();
 172                for (k=0;k<count/4;k++) w4l(pi_swab32(buf,k));
 173                break;
 174
 175
 176        }
 177}
 178
 179static void comm_log_adapter( PIA *pi, char * scratch, int verbose )
 180
 181{       char    *mode_string[5] = {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"};
 182
 183        printk("%s: comm %s, DataStor Commuter at 0x%x, ",
 184                pi->device,COMM_VERSION,pi->port);
 185        printk("mode %d (%s), delay %d\n",pi->mode,
 186                mode_string[pi->mode],pi->delay);
 187
 188}
 189
 190static struct pi_protocol comm = {
 191        .owner          = THIS_MODULE,
 192        .name           = "comm",
 193        .max_mode       = 5,
 194        .epp_first      = 2,
 195        .default_delay  = 1,
 196        .max_units      = 1,
 197        .write_regr     = comm_write_regr,
 198        .read_regr      = comm_read_regr,
 199        .write_block    = comm_write_block,
 200        .read_block     = comm_read_block,
 201        .connect        = comm_connect,
 202        .disconnect     = comm_disconnect,
 203        .log_adapter    = comm_log_adapter,
 204};
 205
 206static int __init comm_init(void)
 207{
 208        return paride_register(&comm);
 209}
 210
 211static void __exit comm_exit(void)
 212{
 213        paride_unregister(&comm);
 214}
 215
 216MODULE_LICENSE("GPL");
 217module_init(comm_init)
 218module_exit(comm_exit)
 219