cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

friq.c (6365B)


      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
     49static int  cont_map[2] = { 0x08, 0x10 };
     50
     51static 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
     66static 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
     77static 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
    132static void friq_read_block( PIA *pi, char * buf, int count)
    133
    134{	friq_read_block_int(pi,buf,count,0x08);
    135}
    136
    137static 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
    169static void friq_connect ( PIA *pi  )
    170
    171{       pi->saved_r0 = r0();
    172        pi->saved_r2 = r2();
    173	w2(4);
    174}
    175
    176static void friq_disconnect ( PIA *pi )
    177
    178{       CMD(0x20);
    179	w0(pi->saved_r0);
    180        w2(pi->saved_r2);
    181} 
    182
    183static 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
    219static 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
    236static 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
    246static 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
    264static int __init friq_init(void)
    265{
    266	return paride_register(&friq);
    267}
    268
    269static void __exit friq_exit(void)
    270{
    271	paride_unregister(&friq);
    272}
    273
    274MODULE_LICENSE("GPL");
    275module_init(friq_init)
    276module_exit(friq_exit)