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

on26.c (7532B)


      1/* 
      2        on26.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
      3                              Under the terms of the GNU General Public License.
      4
      5        on26.c is a low-level protocol driver for the 
      6        OnSpec 90c26 parallel to IDE adapter chip.
      7
      8*/
      9
     10/* Changes:
     11
     12        1.01    GRG 1998.05.06 init_proto, release_proto
     13	1.02    GRG 1998.09.23 updates for the -E rev chip
     14	1.03    GRG 1998.12.14 fix for slave drives
     15	1.04    GRG 1998.12.20 yet another bug fix
     16
     17*/
     18
     19#define ON26_VERSION      "1.04"
     20
     21#include <linux/module.h>
     22#include <linux/init.h>
     23#include <linux/delay.h>
     24#include <linux/kernel.h>
     25#include <linux/types.h>
     26#include <linux/wait.h>
     27#include <asm/io.h>
     28
     29#include "paride.h"
     30
     31/* mode codes:  0  nybble reads, 8-bit writes
     32                1  8-bit reads and writes
     33                2  8-bit EPP mode
     34		3  EPP-16
     35		4  EPP-32
     36*/
     37
     38#define j44(a,b)  (((a>>4)&0x0f)|(b&0xf0))
     39
     40#define P1	w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4);
     41#define P2	w2(5);w2(7);w2(5);w2(4);
     42
     43/* cont = 0 - access the IDE register file 
     44   cont = 1 - access the IDE command set 
     45*/
     46
     47static int on26_read_regr( PIA *pi, int cont, int regr )
     48
     49{       int     a, b, r;
     50
     51	r = (regr<<2) + 1 + cont;
     52
     53        switch (pi->mode)  {
     54
     55        case 0: w0(1); P1; w0(r); P2; w0(0); P1; 
     56		w2(6); a = r1(); w2(4);
     57		w2(6); b = r1(); w2(4);
     58		w2(6); w2(4); w2(6); w2(4);
     59                return j44(a,b);
     60
     61        case 1: w0(1); P1; w0(r); P2; w0(0); P1;
     62		w2(0x26); a = r0(); w2(4); w2(0x26); w2(4);
     63                return a;
     64
     65	case 2:
     66	case 3:
     67        case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
     68		w3(0); w3(0); w2(0x24); a = r4(); w2(4);
     69		w2(0x24); (void)r4(); w2(4);
     70                return a;
     71
     72        }
     73        return -1;
     74}       
     75
     76static void on26_write_regr( PIA *pi, int cont, int regr, int val )
     77
     78{       int  r;
     79
     80        r = (regr<<2) + 1 + cont;
     81
     82        switch (pi->mode)  {
     83
     84        case 0:
     85        case 1: w0(1); P1; w0(r); P2; w0(0); P1;
     86		w0(val); P2; w0(val); P2;
     87		break;
     88
     89	case 2:
     90	case 3:
     91        case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
     92		w3(0); w3(0); 
     93		w2(5); w4(val); w2(4);
     94		w2(5); w4(val); w2(4);
     95                break;
     96        }
     97}
     98
     99#define  CCP(x)  w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
    100		 w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
    101
    102static void on26_connect ( PIA *pi )
    103
    104{       int	x;
    105
    106	pi->saved_r0 = r0();
    107        pi->saved_r2 = r2();
    108
    109        CCP(0x20);
    110	x = 8; if (pi->mode) x = 9;
    111
    112	w0(2); P1; w0(8); P2;
    113	w0(2); P1; w0(x); P2;
    114}
    115
    116static void on26_disconnect ( PIA *pi )
    117
    118{       if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); }
    119	              else { w0(4); P1; w0(4); P1; }
    120	CCP(0x30);
    121        w0(pi->saved_r0);
    122        w2(pi->saved_r2);
    123} 
    124
    125#define	RESET_WAIT  200
    126
    127static int on26_test_port( PIA *pi)  /* hard reset */
    128
    129{       int     i, m, d, x=0, y=0;
    130
    131        pi->saved_r0 = r0();
    132        pi->saved_r2 = r2();
    133
    134        d = pi->delay;
    135        m = pi->mode;
    136        pi->delay = 5;
    137        pi->mode = 0;
    138
    139        w2(0xc);
    140
    141        CCP(0x30); CCP(0); 
    142
    143        w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);
    144        i = ((r1() & 0xf0) << 4); w0(0x87);
    145        i |= (r1() & 0xf0); w0(0x78);
    146        w0(0x20);w2(4);w2(5);
    147        i |= ((r1() & 0xf0) >> 4);
    148        w2(4);w0(0xff);
    149
    150        if (i == 0xb5f) {
    151
    152            w0(2); P1; w0(0);   P2;
    153            w0(3); P1; w0(0);   P2;
    154            w0(2); P1; w0(8);   P2; udelay(100);
    155            w0(2); P1; w0(0xa); P2; udelay(100);
    156            w0(2); P1; w0(8);   P2; udelay(1000);
    157            
    158            on26_write_regr(pi,0,6,0xa0);
    159
    160            for (i=0;i<RESET_WAIT;i++) {
    161                on26_write_regr(pi,0,6,0xa0);
    162                x = on26_read_regr(pi,0,7);
    163                on26_write_regr(pi,0,6,0xb0);
    164                y = on26_read_regr(pi,0,7);
    165                if (!((x&0x80)||(y&0x80))) break;
    166                mdelay(100);
    167            }
    168
    169	    if (i == RESET_WAIT) 
    170		printk("on26: Device reset failed (%x,%x)\n",x,y);
    171
    172            w0(4); P1; w0(4); P1;
    173        }
    174
    175        CCP(0x30);
    176
    177        pi->delay = d;
    178        pi->mode = m;
    179        w0(pi->saved_r0);
    180        w2(pi->saved_r2);
    181
    182        return 5;
    183}
    184
    185
    186static void on26_read_block( PIA *pi, char * buf, int count )
    187
    188{       int     k, a, b;
    189
    190        switch (pi->mode) {
    191
    192        case 0: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
    193		udelay(10);
    194		for (k=0;k<count;k++) {
    195                        w2(6); a = r1();
    196                        w2(4); b = r1();
    197                        buf[k] = j44(a,b);
    198                }
    199		w0(2); P1; w0(8); P2; 
    200                break;
    201
    202        case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
    203		udelay(10);
    204                for (k=0;k<count/2;k++) {
    205                        w2(0x26); buf[2*k] = r0();  
    206			w2(0x24); buf[2*k+1] = r0();
    207                }
    208                w0(2); P1; w0(9); P2;
    209                break;
    210
    211        case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
    212		w3(0); w3(0); w2(0x24);
    213		udelay(10);
    214                for (k=0;k<count;k++) buf[k] = r4();
    215                w2(4);
    216                break;
    217
    218        case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
    219                w3(0); w3(0); w2(0x24);
    220                udelay(10);
    221                for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
    222                w2(4);
    223                break;
    224
    225        case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
    226                w3(0); w3(0); w2(0x24);
    227                udelay(10);
    228                for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
    229                w2(4);
    230                break;
    231
    232        }
    233}
    234
    235static void on26_write_block( PIA *pi, char * buf, int count )
    236
    237{       int	k;
    238
    239        switch (pi->mode) {
    240
    241        case 0: 
    242        case 1: w0(1); P1; w0(1); P2; 
    243		w0(2); P1; w0(0x18+pi->mode); P2; w0(0); P1;
    244		udelay(10);
    245		for (k=0;k<count/2;k++) {
    246                        w2(5); w0(buf[2*k]); 
    247			w2(7); w0(buf[2*k+1]);
    248                }
    249                w2(5); w2(4);
    250		w0(2); P1; w0(8+pi->mode); P2;
    251                break;
    252
    253        case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
    254		w3(0); w3(0); w2(0xc5);
    255		udelay(10);
    256                for (k=0;k<count;k++) w4(buf[k]);
    257		w2(0xc4);
    258                break;
    259
    260        case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
    261                w3(0); w3(0); w2(0xc5);
    262                udelay(10);
    263                for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
    264                w2(0xc4);
    265                break;
    266
    267        case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
    268                w3(0); w3(0); w2(0xc5);
    269                udelay(10);
    270                for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
    271                w2(0xc4);
    272                break;
    273
    274        }
    275
    276}
    277
    278static void on26_log_adapter( PIA *pi, char * scratch, int verbose )
    279
    280{       char    *mode_string[5] = {"4-bit","8-bit","EPP-8",
    281				   "EPP-16","EPP-32"};
    282
    283        printk("%s: on26 %s, OnSpec 90c26 at 0x%x, ",
    284                pi->device,ON26_VERSION,pi->port);
    285        printk("mode %d (%s), delay %d\n",pi->mode,
    286		mode_string[pi->mode],pi->delay);
    287
    288}
    289
    290static struct pi_protocol on26 = {
    291	.owner		= THIS_MODULE,
    292	.name		= "on26",
    293	.max_mode	= 5,
    294	.epp_first	= 2,
    295	.default_delay	= 1,
    296	.max_units	= 1,
    297	.write_regr	= on26_write_regr,
    298	.read_regr	= on26_read_regr,
    299	.write_block	= on26_write_block,
    300	.read_block	= on26_read_block,
    301	.connect	= on26_connect,
    302	.disconnect	= on26_disconnect,
    303	.test_port	= on26_test_port,
    304	.log_adapter	= on26_log_adapter,
    305};
    306
    307static int __init on26_init(void)
    308{
    309	return paride_register(&on26);
    310}
    311
    312static void __exit on26_exit(void)
    313{
    314	paride_unregister(&on26);
    315}
    316
    317MODULE_LICENSE("GPL");
    318module_init(on26_init)
    319module_exit(on26_exit)