^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) frpw.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) Under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) frpw.c is a low-level protocol driver for the Freecom "Power"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) parallel port IDE adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) Some applications of this adapter may require a "printer" reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) prior to loading the driver. This can be done by loading and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) unloading the "lp" driver, or it can be done by this driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) if you define FRPW_HARD_RESET. The latter is not recommended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) as it may upset devices on other ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) 1.01 GRG 1998.05.06 init_proto, release_proto
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) fix chip detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) added EPP-16 and EPP-32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) 1.02 GRG 1998.09.23 added hard reset to initialisation process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) 1.03 GRG 1998.12.14 made hard reset conditional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define FRPW_VERSION "1.03"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include "paride.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define cec4 w2(0xc);w2(0xe);w2(0xe);w2(0xc);w2(4);w2(4);w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* cont = 0 - access the IDE register file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) cont = 1 - access the IDE command set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int cont_map[2] = { 0x08, 0x10 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int frpw_read_regr( PIA *pi, int cont, int regr )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { int h,l,r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) r = regr + cont_map[cont];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) w0(r); cec4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) w2(6); l = r1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) w2(4); h = r1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return j44(l,h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void frpw_write_regr( PIA *pi, int cont, int regr, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) r = regr + cont_map[cont];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) w2(4); w0(r); cec4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) w0(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) w2(5);w2(7);w2(5);w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void frpw_read_block_int( PIA *pi, char * buf, int count, int regr )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { int h, l, k, ph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) switch(pi->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) case 0: w2(4); w0(regr); cec4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) for (k=0;k<count;k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) w2(6); l = r1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) w2(4); h = r1();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) buf[k] = j44(l,h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) case 1: ph = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) w2(4); w0(regr + 0xc0); cec4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) w0(0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) for (k=0;k<count;k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) w2(0xa4 + ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) buf[k] = r0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ph = 2 - ph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) w2(0xac); w2(0xa4); w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) case 2: w2(4); w0(regr + 0x80); cec4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) for (k=0;k<count;k++) buf[k] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) w2(0xac); w2(0xa4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) case 3: w2(4); w0(regr + 0x80); cec4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) for (k=0;k<count-2;k++) buf[k] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) w2(0xac); w2(0xa4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) buf[count-2] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) buf[count-1] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) case 4: w2(4); w0(regr + 0x80); cec4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) w2(0xac); w2(0xa4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) buf[count-2] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) buf[count-1] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case 5: w2(4); w0(regr + 0x80); cec4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) buf[count-4] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) buf[count-3] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) w2(0xac); w2(0xa4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) buf[count-2] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) buf[count-1] = r4();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static void frpw_read_block( PIA *pi, char * buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) { frpw_read_block_int(pi,buf,count,0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static void frpw_write_block( PIA *pi, char * buf, int count )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) { int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) switch(pi->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) case 2: w2(4); w0(8); cec4; w2(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) for (k=0;k<count;k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) w0(buf[k]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) w2(7);w2(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case 3: w2(4); w0(0xc8); cec4; w2(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) for (k=0;k<count;k++) w4(buf[k]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case 4: w2(4); w0(0xc8); cec4; w2(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) case 5: w2(4); w0(0xc8); cec4; w2(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static void frpw_connect ( PIA *pi )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) { pi->saved_r0 = r0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) pi->saved_r2 = r2();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static void frpw_disconnect ( PIA *pi )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) { w2(4); w0(0x20); cec4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) w0(pi->saved_r0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) w2(pi->saved_r2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /* Stub logic to see if PNP string is available - used to distinguish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) between the Xilinx and ASIC implementations of the Freecom adapter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int frpw_test_pnp ( PIA *pi )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* returns chip_type: 0 = Xilinx, 1 = ASIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { int olddelay, a, b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #ifdef FRPW_HARD_RESET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) mdelay(1500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) olddelay = pi->delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) pi->delay = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pi->saved_r0 = r0();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) pi->saved_r2 = r2();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) w2(4); w0(4); w2(6); w2(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) a = r1() & 0xff; w2(4); b = r1() & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) w2(0xc); w2(0xe); w2(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) pi->delay = olddelay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) w0(pi->saved_r0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) w2(pi->saved_r2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return ((~a&0x40) && (b&0x40));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* We use the pi->private to remember the result of the PNP test.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) To make this work, private = port*2 + chip. Yes, I know it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) a hack :-(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static int frpw_test_proto( PIA *pi, char * scratch, int verbose )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) { int j, k, r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int e[2] = {0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if ((pi->private>>1) != pi->port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) pi->private = frpw_test_pnp(pi) + 2*pi->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (((pi->private%2) == 0) && (pi->mode > 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) printk("%s: frpw: Xilinx does not support mode %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) pi->device, pi->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (((pi->private%2) == 1) && (pi->mode == 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) printk("%s: frpw: ASIC does not support mode 2\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) pi->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) frpw_connect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) for (j=0;j<2;j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) frpw_write_regr(pi,0,6,0xa0+j*0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) for (k=0;k<256;k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) frpw_write_regr(pi,0,2,k^0xaa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) frpw_write_regr(pi,0,3,k^0x55);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (frpw_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) frpw_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) frpw_connect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) frpw_read_block_int(pi,scratch,512,0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) for (k=0;k<128;k++) if (scratch[k] != k) r++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) frpw_disconnect(pi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (verbose) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) printk("%s: frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) pi->device,pi->port,(pi->private%2),pi->mode,e[0],e[1],r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return (r || (e[0] && e[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static void frpw_log_adapter( PIA *pi, char * scratch, int verbose )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { char *mode_string[6] = {"4-bit","8-bit","EPP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) "EPP-8","EPP-16","EPP-32"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) printk("%s: frpw %s, Freecom (%s) adapter at 0x%x, ", pi->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) FRPW_VERSION,((pi->private%2) == 0)?"Xilinx":"ASIC",pi->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) printk("mode %d (%s), delay %d\n",pi->mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mode_string[pi->mode],pi->delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static struct pi_protocol frpw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .name = "frpw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .max_mode = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .epp_first = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .default_delay = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .max_units = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .write_regr = frpw_write_regr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .read_regr = frpw_read_regr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .write_block = frpw_write_block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .read_block = frpw_read_block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .connect = frpw_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .disconnect = frpw_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .test_proto = frpw_test_proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .log_adapter = frpw_log_adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static int __init frpw_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return paride_register(&frpw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static void __exit frpw_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) paride_unregister(&frpw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) module_init(frpw_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) module_exit(frpw_exit)