summaryrefslogtreecommitdiffstats
path: root/drivers/block/paride
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/paride')
-rw-r--r--drivers/block/paride/Config.in1
-rw-r--r--drivers/block/paride/Makefile9
-rw-r--r--drivers/block/paride/friq.c282
-rw-r--r--drivers/block/paride/frpw.c11
-rw-r--r--drivers/block/paride/jumbo8
-rw-r--r--drivers/block/paride/on26.c23
-rw-r--r--drivers/block/paride/paride.c8
-rw-r--r--drivers/block/paride/pg.c8
-rw-r--r--drivers/block/paride/pseudo.h22
-rw-r--r--drivers/block/paride/pt.c2
10 files changed, 347 insertions, 27 deletions
diff --git a/drivers/block/paride/Config.in b/drivers/block/paride/Config.in
index 00dd9c8e4..8d4dc1742 100644
--- a/drivers/block/paride/Config.in
+++ b/drivers/block/paride/Config.in
@@ -16,6 +16,7 @@ dep_tristate ' FIT TD-2000 protocol' CONFIG_PARIDE_FIT2 $CONFIG_PARIDE
dep_tristate ' FIT TD-3000 protocol' CONFIG_PARIDE_FIT3 $CONFIG_PARIDE
dep_tristate ' Shuttle EPAT/EPEZ protocol' CONFIG_PARIDE_EPAT $CONFIG_PARIDE
dep_tristate ' Shuttle EPIA protocol' CONFIG_PARIDE_EPIA $CONFIG_PARIDE
+dep_tristate ' Freecom IQ ASIC-2 protocol' CONFIG_PARIDE_FRIQ $CONFIG_PARIDE
dep_tristate ' FreeCom power protocol' CONFIG_PARIDE_FRPW $CONFIG_PARIDE
dep_tristate ' KingByte KBIC-951A/971A protocols' CONFIG_PARIDE_KBIC $CONFIG_PARIDE
dep_tristate ' KT PHd protocol' CONFIG_PARIDE_KTTI $CONFIG_PARIDE
diff --git a/drivers/block/paride/Makefile b/drivers/block/paride/Makefile
index ae2d54dd9..32e856704 100644
--- a/drivers/block/paride/Makefile
+++ b/drivers/block/paride/Makefile
@@ -147,6 +147,15 @@ else
endif
endif
+
+ifeq ($(CONFIG_PARIDE_FRIQ),y)
+ LX_OBJS += friq.o
+else
+ ifeq ($(CONFIG_PARIDE_FRIQ),m)
+ M_OBJS += friq.o
+ endif
+endif
+
ifeq ($(CONFIG_PARIDE_ON20),y)
LX_OBJS += on20.o
else
diff --git a/drivers/block/paride/friq.c b/drivers/block/paride/friq.c
new file mode 100644
index 000000000..37ebaa047
--- /dev/null
+++ b/drivers/block/paride/friq.c
@@ -0,0 +1,282 @@
+/*
+ friq.c (c) 1998 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license
+
+ friq.c is a low-level protocol driver for the Freecom "IQ"
+ parallel port IDE adapter. Early versions of this adapter
+ use the 'frpw' protocol.
+
+ Freecom uses this adapter in a battery powered external
+ CD-ROM drive. It is also used in LS-120 drives by
+ Maxell and Panasonic, and other devices.
+
+ The battery powered drive requires software support to
+ control the power to the drive. This module enables the
+ drive power when the high level driver (pcd) is loaded
+ and disables it when the module is unloaded. Note, if
+ the friq module is built in to the kernel, the power
+ will never be switched off, so other means should be
+ used to conserve battery power.
+
+*/
+
+/* Changes:
+
+ 1.01 GRG 1998.12.20 Added support for soft power switch
+*/
+
+#define FRIQ_VERSION "1.01"
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include "paride.h"
+
+#define CMD(x) w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);\
+ w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(x);
+
+#define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
+
+/* cont = 0 - access the IDE register file
+ cont = 1 - access the IDE command set
+*/
+
+static int cont_map[2] = { 0x08, 0x10 };
+
+static int friq_read_regr( PIA *pi, int cont, int regr )
+
+{ int h,l,r;
+
+ r = regr + cont_map[cont];
+
+ CMD(r);
+ w2(6); l = r1();
+ w2(4); h = r1();
+ w2(4);
+
+ return j44(l,h);
+
+}
+
+static void friq_write_regr( PIA *pi, int cont, int regr, int val)
+
+{ int r;
+
+ r = regr + cont_map[cont];
+
+ CMD(r);
+ w0(val);
+ w2(5);w2(7);w2(5);w2(4);
+}
+
+static void friq_read_block_int( PIA *pi, char * buf, int count, int regr )
+
+{ int h, l, k, ph;
+
+ switch(pi->mode) {
+
+ case 0: CMD(regr);
+ for (k=0;k<count;k++) {
+ w2(6); l = r1();
+ w2(4); h = r1();
+ buf[k] = j44(l,h);
+ }
+ w2(4);
+ break;
+
+ case 1: ph = 2;
+ CMD(regr+0xc0);
+ w0(0xff);
+ for (k=0;k<count;k++) {
+ w2(0xa4 + ph);
+ buf[k] = r0();
+ ph = 2 - ph;
+ }
+ w2(0xac); w2(0xa4); w2(4);
+ break;
+
+ case 2: CMD(regr+0x80);
+ for (k=0;k<count-2;k++) buf[k] = r4();
+ w2(0xac); w2(0xa4);
+ buf[count-2] = r4();
+ buf[count-1] = r4();
+ w2(4);
+ break;
+
+ case 3: CMD(regr+0x80);
+ for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
+ w2(0xac); w2(0xa4);
+ buf[count-2] = r4();
+ buf[count-1] = r4();
+ w2(4);
+ break;
+
+ case 4: CMD(regr+0x80);
+ for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
+ buf[count-4] = r4();
+ buf[count-3] = r4();
+ w2(0xac); w2(0xa4);
+ buf[count-2] = r4();
+ buf[count-1] = r4();
+ w2(4);
+ break;
+
+ }
+}
+
+static void friq_read_block( PIA *pi, char * buf, int count)
+
+{ friq_read_block_int(pi,buf,count,0x08);
+}
+
+static void friq_write_block( PIA *pi, char * buf, int count )
+
+{ int k;
+
+ switch(pi->mode) {
+
+ case 0:
+ case 1: CMD(8); w2(5);
+ for (k=0;k<count;k++) {
+ w0(buf[k]);
+ w2(7);w2(5);
+ }
+ w2(4);
+ break;
+
+ case 2: CMD(0xc8); w2(5);
+ for (k=0;k<count;k++) w4(buf[k]);
+ w2(4);
+ break;
+
+ case 3: CMD(0xc8); w2(5);
+ for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
+ w2(4);
+ break;
+
+ case 4: CMD(0xc8); w2(5);
+ for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
+ w2(4);
+ break;
+ }
+}
+
+static void friq_connect ( PIA *pi )
+
+{ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(4);
+}
+
+static void friq_disconnect ( PIA *pi )
+
+{ CMD(0x20);
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
+
+static int friq_test_proto( PIA *pi, char * scratch, int verbose )
+
+{ int j, k, r;
+ int e[2] = {0,0};
+
+ pi->saved_r0 = r0();
+ w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */
+ udelay(500);
+ w0(pi->saved_r0);
+
+ friq_connect(pi);
+ for (j=0;j<2;j++) {
+ friq_write_regr(pi,0,6,0xa0+j*0x10);
+ for (k=0;k<256;k++) {
+ friq_write_regr(pi,0,2,k^0xaa);
+ friq_write_regr(pi,0,3,k^0x55);
+ if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
+ }
+ }
+ friq_disconnect(pi);
+
+ friq_connect(pi);
+ friq_read_block_int(pi,scratch,512,0x10);
+ r = 0;
+ for (k=0;k<128;k++) if (scratch[k] != k) r++;
+ friq_disconnect(pi);
+
+ if (verbose) {
+ printk("%s: friq: port 0x%x, mode %d, test=(%d,%d,%d)\n",
+ pi->device,pi->port,pi->mode,e[0],e[1],r);
+ }
+
+ return (r || (e[0] && e[1]));
+}
+
+
+static void friq_log_adapter( PIA *pi, char * scratch, int verbose )
+
+{ char *mode_string[6] = {"4-bit","8-bit",
+ "EPP-8","EPP-16","EPP-32"};
+
+ printk("%s: friq %s, Freecom IQ ASIC-2 adapter at 0x%x, ", pi->device,
+ FRIQ_VERSION,pi->port);
+ printk("mode %d (%s), delay %d\n",pi->mode,
+ mode_string[pi->mode],pi->delay);
+
+ pi->private = 1;
+ friq_connect(pi);
+ CMD(0x9e); /* disable sleep timer */
+ friq_disconnect(pi);
+
+}
+
+static void friq_init_proto( PIA *pi)
+
+{ MOD_INC_USE_COUNT;
+ pi->private = 0;
+}
+
+static void friq_release_proto( PIA *pi)
+
+{ if (pi->private) { /* turn off the power */
+ friq_connect(pi);
+ CMD(0x1d); CMD(0x1e);
+ friq_disconnect(pi);
+ pi->private = 0;
+ }
+
+ MOD_DEC_USE_COUNT;
+}
+
+struct pi_protocol friq = {"friq",0,5,2,1,1,
+ friq_write_regr,
+ friq_read_regr,
+ friq_write_block,
+ friq_read_block,
+ friq_connect,
+ friq_disconnect,
+ 0,
+ 0,
+ friq_test_proto,
+ friq_log_adapter,
+ friq_init_proto,
+ friq_release_proto
+ };
+
+
+#ifdef MODULE
+
+int init_module(void)
+
+{ return pi_register( &friq ) - 1;
+}
+
+void cleanup_module(void)
+
+{ pi_unregister( &friq );
+}
+
+#endif
+
+/* end of friq.c */
diff --git a/drivers/block/paride/frpw.c b/drivers/block/paride/frpw.c
index 680f9e592..f4c98c645 100644
--- a/drivers/block/paride/frpw.c
+++ b/drivers/block/paride/frpw.c
@@ -5,6 +5,12 @@
frpw.c is a low-level protocol driver for the Freecom "Power"
parallel port IDE adapter.
+ Some applications of this adapter may require a "printer" reset
+ prior to loading the driver. This can be done by loading and
+ unloading the "lp" driver, or it can be done by this driver
+ if you define FRPW_HARD_RESET. The latter is not recommended
+ as it may upset devices on other ports.
+
*/
/* Changes:
@@ -13,10 +19,11 @@
fix chip detect
added EPP-16 and EPP-32
1.02 GRG 1998.09.23 added hard reset to initialisation process
+ 1.03 GRG 1998.12.14 made hard reset conditional
*/
-#define FRPW_VERSION "1.02"
+#define FRPW_VERSION "1.03"
#include <linux/module.h>
#include <linux/delay.h>
@@ -185,8 +192,10 @@ static int frpw_test_pnp ( PIA *pi )
{ int olddelay, a, b;
+#ifdef FRPW_HARD_RESET
w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */
mdelay(1500);
+#endif
olddelay = pi->delay;
pi->delay = 10;
diff --git a/drivers/block/paride/jumbo b/drivers/block/paride/jumbo
index b952fde92..f4b8ebf75 100644
--- a/drivers/block/paride/jumbo
+++ b/drivers/block/paride/jumbo
@@ -53,11 +53,11 @@ FPROTO=-DCONFIG_PARIDE_`echo "$PROTO" | tr [a-z] [A-Z]`
FK="-D__KERNEL__ -I ../../../include"
FLCH=-D_LINUX_CONFIG_H
#
-echo cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
-cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
+echo cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
+cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
#
-echo cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
-cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
+echo cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
+cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
#
echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
diff --git a/drivers/block/paride/on26.c b/drivers/block/paride/on26.c
index 78477593e..91dcad101 100644
--- a/drivers/block/paride/on26.c
+++ b/drivers/block/paride/on26.c
@@ -11,10 +11,12 @@
1.01 GRG 1998.05.06 init_proto, release_proto
1.02 GRG 1998.09.23 updates for the -E rev chip
+ 1.03 GRG 1998.12.14 fix for slave drives
+ 1.04 GRG 1998.12.20 yet another bug fix
*/
-#define ON26_VERSION "1.02"
+#define ON26_VERSION "1.04"
#include <linux/module.h>
#include <linux/delay.h>
@@ -118,9 +120,11 @@ static void on26_disconnect ( PIA *pi )
w2(pi->saved_r2);
}
+#define RESET_WAIT 200
+
static int on26_test_port( PIA *pi) /* hard reset */
-{ int i, m, d;
+{ int i, m, d, x, y;
pi->saved_r0 = r0();
pi->saved_r2 = r2();
@@ -151,11 +155,18 @@ static int on26_test_port( PIA *pi) /* hard reset */
on26_write_regr(pi,0,6,0xa0);
- for (i=0;i<100;i++) {
- if (!(on26_read_regr(pi,0,7) & 0x80)) break;
- udelay(100000);
+ for (i=0;i<RESET_WAIT;i++) {
+ on26_write_regr(pi,0,6,0xa0);
+ x = on26_read_regr(pi,0,7);
+ on26_write_regr(pi,0,6,0xb0);
+ y = on26_read_regr(pi,0,7);
+ if (!((x&0x80)||(y&0x80))) break;
+ mdelay(100);
}
+ if (i == RESET_WAIT)
+ printk("on26: Device reset failed (%x,%x)\n",x,y);
+
w0(4); P1; w0(4); P1;
}
@@ -189,7 +200,7 @@ static void on26_read_block( PIA *pi, char * buf, int count )
case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
udelay(10);
for (k=0;k<count/2;k++) {
- w2(0x26); buf[2*k] = r0();
+ w2(0x26); buf[2*k] = r0();
w2(0x24); buf[2*k+1] = r0();
}
w0(2); P1; w0(9); P2;
diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
index 068deffd6..6e962d8c1 100644
--- a/drivers/block/paride/paride.c
+++ b/drivers/block/paride/paride.c
@@ -12,10 +12,11 @@
1.01 GRG 1998.05.03 Use spinlocks
1.02 GRG 1998.05.05 init_proto, release_proto, ktti
1.03 GRG 1998.08.15 eliminate compiler warning
+ 1.04 GRG 1998.11.28 added support for FRIQ
*/
-#define PI_VERSION "1.03"
+#define PI_VERSION "1.04"
#include <linux/module.h>
#include <linux/config.h>
@@ -450,6 +451,11 @@ void paride_init( void )
pi_register(&frpw);
};
#endif
+#ifdef CONFIG_PARIDE_FRIQ
+ { extern struct pi_protocol friq;
+ pi_register(&friq);
+ };
+#endif
#ifdef CONFIG_PARIDE_FIT2
{ extern struct pi_protocol fit2;
pi_register(&fit2);
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 1563a2afc..89c83db65 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -367,21 +367,21 @@ static int pg_wait( int unit, int go, int stop, int tmo, char * msg )
PG.status = 0;
j = 0;
- while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(jiffies<tmo)) {
+ while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(time_before(jiffies,tmo))) {
if (j++ < PG_SPIN) udelay(PG_SPIN_DEL);
else pg_sleep(1);
}
- if ((r&(STAT_ERR&stop))||(jiffies>=tmo)) {
+ if ((r&(STAT_ERR&stop))||time_after_eq(jiffies, tmo)) {
s = RR(0,7);
e = RR(0,1);
p = RR(0,2);
if (verbose > 1)
printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n",
- PG.name,msg,s,e,p,(jiffies>=tmo)?" timeout":"");
+ PG.name,msg,s,e,p,time_after_eq(jiffies, tmo)?" timeout":"");
- if (jiffies>=tmo) e |= 0x100;
+ if (time_after_eq(jiffies, tmo)) e |= 0x100;
PG.status = (e >> 4) & 0xff;
return -1;
}
diff --git a/drivers/block/paride/pseudo.h b/drivers/block/paride/pseudo.h
index 17615c2ca..3992f3c30 100644
--- a/drivers/block/paride/pseudo.h
+++ b/drivers/block/paride/pseudo.h
@@ -16,19 +16,21 @@
when either it returns true, or timeout jiffies have passed,
continuation() will be invoked.
- If nice is true, the test will done approximately once a
+ If nice is 1, the test will done approximately once a
jiffy. If nice is 0, the test will also be done whenever
- the scheduler runs (by adding it to a task queue).
+ the scheduler runs (by adding it to a task queue). If
+ nice is greater than 1, the test will be done once every
+ (nice-1) jiffies.
*/
/* Changes:
1.01 1998.05.03 Switched from cli()/sti() to spinlocks
-
+ 1.02 1998.12.14 Added support for nice > 1
*/
-#define PS_VERSION "1.01"
+#define PS_VERSION "1.02"
#include <linux/sched.h>
#include <linux/timer.h>
@@ -37,15 +39,15 @@
static void ps_timer_int( unsigned long data);
static void ps_tq_int( void *data);
-static int ps_use_tq = 1;
static void (* ps_continuation)(void);
static int (* ps_ready)(void);
static int ps_then;
static int ps_timeout;
static int ps_timer_active = 0;
static int ps_tq_active = 0;
+static int ps_nice = 0;
-static spinlock_t ps_spinlock = SPIN_LOCK_UNLOCKED;
+static spinlock_t ps_spinlock __attribute__((unused)) = SPIN_LOCK_UNLOCKED;
static struct timer_list ps_timer = {0,0,0,0,ps_timer_int};
static struct tq_struct ps_tq = {0,0,ps_tq_int,NULL};
@@ -62,9 +64,9 @@ static void ps_set_intr( void (*continuation)(void),
ps_ready = ready;
ps_then = jiffies;
ps_timeout = jiffies + timeout;
- ps_use_tq = !nice;
+ ps_nice = nice;
- if (ps_use_tq && !ps_tq_active) {
+ if (!ps_nice && !ps_tq_active) {
#ifdef HAVE_DISABLE_HLT
disable_hlt();
#endif
@@ -74,7 +76,7 @@ static void ps_set_intr( void (*continuation)(void),
if (!ps_timer_active) {
ps_timer_active = 1;
- ps_timer.expires = jiffies;
+ ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
add_timer(&ps_timer);
}
@@ -136,7 +138,7 @@ static void ps_timer_int( unsigned long data)
return;
}
ps_timer_active = 1;
- ps_timer.expires = jiffies;
+ ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
add_timer(&ps_timer);
spin_unlock_irqrestore(&ps_spinlock,flags);
}
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 1a09c84b0..2616319f7 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -471,7 +471,7 @@ static int pt_poll_dsc( int unit, int pause, int tmo, char *msg )
{ int k, e, s;
- k = 0;
+ k = 0; e = 0; s = 0;
while (k < tmo) {
pt_sleep(pause);
k++;