0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #define FRPW_VERSION "1.03"
0027
0028 #include <linux/module.h>
0029 #include <linux/init.h>
0030 #include <linux/delay.h>
0031 #include <linux/kernel.h>
0032 #include <linux/types.h>
0033 #include <linux/wait.h>
0034 #include <asm/io.h>
0035
0036 #include "paride.h"
0037
0038 #define cec4 w2(0xc);w2(0xe);w2(0xe);w2(0xc);w2(4);w2(4);w2(4);
0039 #define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
0040
0041
0042
0043
0044
0045 static int cont_map[2] = { 0x08, 0x10 };
0046
0047 static int frpw_read_regr( PIA *pi, int cont, int regr )
0048
0049 { int h,l,r;
0050
0051 r = regr + cont_map[cont];
0052
0053 w2(4);
0054 w0(r); cec4;
0055 w2(6); l = r1();
0056 w2(4); h = r1();
0057 w2(4);
0058
0059 return j44(l,h);
0060
0061 }
0062
0063 static void frpw_write_regr( PIA *pi, int cont, int regr, int val)
0064
0065 { int r;
0066
0067 r = regr + cont_map[cont];
0068
0069 w2(4); w0(r); cec4;
0070 w0(val);
0071 w2(5);w2(7);w2(5);w2(4);
0072 }
0073
0074 static void frpw_read_block_int( PIA *pi, char * buf, int count, int regr )
0075
0076 { int h, l, k, ph;
0077
0078 switch(pi->mode) {
0079
0080 case 0: w2(4); w0(regr); cec4;
0081 for (k=0;k<count;k++) {
0082 w2(6); l = r1();
0083 w2(4); h = r1();
0084 buf[k] = j44(l,h);
0085 }
0086 w2(4);
0087 break;
0088
0089 case 1: ph = 2;
0090 w2(4); w0(regr + 0xc0); cec4;
0091 w0(0xff);
0092 for (k=0;k<count;k++) {
0093 w2(0xa4 + ph);
0094 buf[k] = r0();
0095 ph = 2 - ph;
0096 }
0097 w2(0xac); w2(0xa4); w2(4);
0098 break;
0099
0100 case 2: w2(4); w0(regr + 0x80); cec4;
0101 for (k=0;k<count;k++) buf[k] = r4();
0102 w2(0xac); w2(0xa4);
0103 w2(4);
0104 break;
0105
0106 case 3: w2(4); w0(regr + 0x80); cec4;
0107 for (k=0;k<count-2;k++) buf[k] = r4();
0108 w2(0xac); w2(0xa4);
0109 buf[count-2] = r4();
0110 buf[count-1] = r4();
0111 w2(4);
0112 break;
0113
0114 case 4: w2(4); w0(regr + 0x80); cec4;
0115 for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
0116 w2(0xac); w2(0xa4);
0117 buf[count-2] = r4();
0118 buf[count-1] = r4();
0119 w2(4);
0120 break;
0121
0122 case 5: w2(4); w0(regr + 0x80); cec4;
0123 for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
0124 buf[count-4] = r4();
0125 buf[count-3] = r4();
0126 w2(0xac); w2(0xa4);
0127 buf[count-2] = r4();
0128 buf[count-1] = r4();
0129 w2(4);
0130 break;
0131
0132 }
0133 }
0134
0135 static void frpw_read_block( PIA *pi, char * buf, int count)
0136
0137 { frpw_read_block_int(pi,buf,count,0x08);
0138 }
0139
0140 static void frpw_write_block( PIA *pi, char * buf, int count )
0141
0142 { int k;
0143
0144 switch(pi->mode) {
0145
0146 case 0:
0147 case 1:
0148 case 2: w2(4); w0(8); cec4; w2(5);
0149 for (k=0;k<count;k++) {
0150 w0(buf[k]);
0151 w2(7);w2(5);
0152 }
0153 w2(4);
0154 break;
0155
0156 case 3: w2(4); w0(0xc8); cec4; w2(5);
0157 for (k=0;k<count;k++) w4(buf[k]);
0158 w2(4);
0159 break;
0160
0161 case 4: w2(4); w0(0xc8); cec4; w2(5);
0162 for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
0163 w2(4);
0164 break;
0165
0166 case 5: w2(4); w0(0xc8); cec4; w2(5);
0167 for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
0168 w2(4);
0169 break;
0170 }
0171 }
0172
0173 static void frpw_connect ( PIA *pi )
0174
0175 { pi->saved_r0 = r0();
0176 pi->saved_r2 = r2();
0177 w2(4);
0178 }
0179
0180 static void frpw_disconnect ( PIA *pi )
0181
0182 { w2(4); w0(0x20); cec4;
0183 w0(pi->saved_r0);
0184 w2(pi->saved_r2);
0185 }
0186
0187
0188
0189
0190
0191 static int frpw_test_pnp ( PIA *pi )
0192
0193
0194
0195 { int olddelay, a, b;
0196
0197 #ifdef FRPW_HARD_RESET
0198 w0(0); w2(8); udelay(50); w2(0xc);
0199 mdelay(1500);
0200 #endif
0201
0202 olddelay = pi->delay;
0203 pi->delay = 10;
0204
0205 pi->saved_r0 = r0();
0206 pi->saved_r2 = r2();
0207
0208 w2(4); w0(4); w2(6); w2(7);
0209 a = r1() & 0xff; w2(4); b = r1() & 0xff;
0210 w2(0xc); w2(0xe); w2(4);
0211
0212 pi->delay = olddelay;
0213 w0(pi->saved_r0);
0214 w2(pi->saved_r2);
0215
0216 return ((~a&0x40) && (b&0x40));
0217 }
0218
0219
0220
0221
0222
0223
0224 static int frpw_test_proto( PIA *pi, char * scratch, int verbose )
0225
0226 { int j, k, r;
0227 int e[2] = {0,0};
0228
0229 if ((pi->private>>1) != pi->port)
0230 pi->private = frpw_test_pnp(pi) + 2*pi->port;
0231
0232 if (((pi->private%2) == 0) && (pi->mode > 2)) {
0233 if (verbose)
0234 printk("%s: frpw: Xilinx does not support mode %d\n",
0235 pi->device, pi->mode);
0236 return 1;
0237 }
0238
0239 if (((pi->private%2) == 1) && (pi->mode == 2)) {
0240 if (verbose)
0241 printk("%s: frpw: ASIC does not support mode 2\n",
0242 pi->device);
0243 return 1;
0244 }
0245
0246 frpw_connect(pi);
0247 for (j=0;j<2;j++) {
0248 frpw_write_regr(pi,0,6,0xa0+j*0x10);
0249 for (k=0;k<256;k++) {
0250 frpw_write_regr(pi,0,2,k^0xaa);
0251 frpw_write_regr(pi,0,3,k^0x55);
0252 if (frpw_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
0253 }
0254 }
0255 frpw_disconnect(pi);
0256
0257 frpw_connect(pi);
0258 frpw_read_block_int(pi,scratch,512,0x10);
0259 r = 0;
0260 for (k=0;k<128;k++) if (scratch[k] != k) r++;
0261 frpw_disconnect(pi);
0262
0263 if (verbose) {
0264 printk("%s: frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n",
0265 pi->device,pi->port,(pi->private%2),pi->mode,e[0],e[1],r);
0266 }
0267
0268 return (r || (e[0] && e[1]));
0269 }
0270
0271
0272 static void frpw_log_adapter( PIA *pi, char * scratch, int verbose )
0273
0274 { char *mode_string[6] = {"4-bit","8-bit","EPP",
0275 "EPP-8","EPP-16","EPP-32"};
0276
0277 printk("%s: frpw %s, Freecom (%s) adapter at 0x%x, ", pi->device,
0278 FRPW_VERSION,((pi->private%2) == 0)?"Xilinx":"ASIC",pi->port);
0279 printk("mode %d (%s), delay %d\n",pi->mode,
0280 mode_string[pi->mode],pi->delay);
0281
0282 }
0283
0284 static struct pi_protocol frpw = {
0285 .owner = THIS_MODULE,
0286 .name = "frpw",
0287 .max_mode = 6,
0288 .epp_first = 2,
0289 .default_delay = 2,
0290 .max_units = 1,
0291 .write_regr = frpw_write_regr,
0292 .read_regr = frpw_read_regr,
0293 .write_block = frpw_write_block,
0294 .read_block = frpw_read_block,
0295 .connect = frpw_connect,
0296 .disconnect = frpw_disconnect,
0297 .test_proto = frpw_test_proto,
0298 .log_adapter = frpw_log_adapter,
0299 };
0300
0301 static int __init frpw_init(void)
0302 {
0303 return paride_register(&frpw);
0304 }
0305
0306 static void __exit frpw_exit(void)
0307 {
0308 paride_unregister(&frpw);
0309 }
0310
0311 MODULE_LICENSE("GPL");
0312 module_init(frpw_init)
0313 module_exit(frpw_exit)