patch-2.1.103 linux/drivers/block/paride/pf.c
Next file: linux/drivers/block/paride/pseudo.h
Previous file: linux/drivers/block/paride/pd.c
Back to the patch index
Back to the overall index
- Lines: 300
- Date:
Thu May 14 19:11:48 1998
- Orig file:
v2.1.102/linux/drivers/block/paride/pf.c
- Orig date:
Thu May 7 22:51:48 1998
diff -u --recursive --new-file v2.1.102/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
@@ -1,6 +1,6 @@
/*
- pf.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ pf.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license.
This is the high-level driver for parallel port ATAPI disk
drives based on chips supported by the paride module.
@@ -83,8 +83,8 @@
nice This parameter controls the driver's use of
idle CPU time, at the expense of some speed.
- If this driver is built into the kernel, you can use kernel
- the following command line parameters, with the same values
+ If this driver is built into the kernel, you can use the
+ following command line parameters, with the same values
as the corresponding module parameters listed above:
pf.drive0
@@ -99,13 +99,23 @@
*/
-#define PF_VERSION "1.0"
+/* Changes:
+
+ 1.01 GRG 1998.05.03 Changes for SMP. Eliminate sti().
+ Fix for drives that don't clear STAT_ERR
+ until after next CDB delivered.
+ Small change in pf_completion to round
+ up transfer size.
+
+*/
+
+#define PF_VERSION "1.01"
#define PF_MAJOR 47
#define PF_NAME "pf"
#define PF_UNITS 4
/* Here are things one can override from the insmod command.
- Most are autoprobed by paride unless set here. Verbose is on
+ Most are autoprobed by paride unless set here. Verbose is off
by default.
*/
@@ -146,6 +156,7 @@
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/cdrom.h>
+#include <asm/spinlock.h>
#include <asm/uaccess.h>
@@ -238,7 +249,9 @@
static int pf_detect(void);
static void do_pf_read(void);
+static void do_pf_read_start(void);
static void do_pf_write(void);
+static void do_pf_write_start(void);
static void do_pf_read_drq( void );
static void do_pf_write_done( void );
@@ -562,7 +575,7 @@
WR(0,5,dlen / 256);
WR(0,7,0xa0); /* ATAPI packet command */
- if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,fun,"command DRQ")) {
+ if (pf_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) {
pi_disconnect(PI);
return -1;
}
@@ -586,7 +599,7 @@
fun,"completion");
if ((RR(0,2)&2) && (RR(0,7)&STAT_DRQ)) {
- n = (RR(0,4)+256*RR(0,5));
+ n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
pi_read_block(PI,buf,n);
}
@@ -661,23 +674,17 @@
{ int i, k, flg;
int expect[5] = {1,1,1,0x14,0xeb};
- long flags;
pi_connect(PI);
WR(0,6,DRIVE);
WR(0,7,8);
- save_flags(flags);
- sti();
-
pf_sleep(2);
k = 0;
while ((k++ < PF_RESET_TMO) && (RR(1,6)&STAT_BUSY))
pf_sleep(10);
- restore_flags(flags);
-
flg = 1;
for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
@@ -906,19 +913,24 @@
pf_buf = CURRENT->buffer;
pf_retries = 0;
-
+ pf_busy = 1;
if (pf_cmd == READ) pi_do_claimed(PI,do_pf_read);
else if (pf_cmd == WRITE) pi_do_claimed(PI,do_pf_write);
- else { end_request(0);
+ else { pf_busy = 0;
+ end_request(0);
goto repeat;
}
}
static void pf_next_buf( int unit )
-{ cli();
+{ long saved_flags;
+
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
- if (!pf_run) { sti(); return; }
+ if (!pf_run) { spin_unlock_irqrestore(&io_request_lock,saved_flags);
+ return;
+ }
/* paranoia */
@@ -932,39 +944,46 @@
pf_count = CURRENT->nr_sectors;
pf_buf = CURRENT->buffer;
- sti();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
static void do_pf_read( void )
+/* detach from the calling context - in case the spinlock is held */
+
+{ ps_set_intr(do_pf_read_start,0,0,nice);
+}
+
+static void do_pf_read_start( void )
+
{ int unit = pf_unit;
+ long saved_flags;
pf_busy = 1;
- sti();
-
if (pf_start(unit,ATAPI_READ_10,pf_block,pf_run)) {
pi_disconnect(PI);
if (pf_retries < PF_MAX_RETRIES) {
pf_retries++;
- pi_do_claimed(PI,do_pf_read);
+ pi_do_claimed(PI,do_pf_read_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
- pf_mask=STAT_DRQ;
+ pf_mask = STAT_DRQ;
ps_set_intr(do_pf_read_drq,pf_ready,PF_TMO,nice);
}
static void do_pf_read_drq( void )
{ int unit = pf_unit;
-
- sti();
+ long saved_flags;
+
while (1) {
if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,
"read block","completion") & STAT_ERR) {
@@ -972,13 +991,14 @@
if (pf_retries < PF_MAX_RETRIES) {
pf_req_sense(unit,0);
pf_retries++;
- pi_do_claimed(PI,do_pf_read);
+ pi_do_claimed(PI,do_pf_read_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_read_block(PI,pf_buf,512);
@@ -989,31 +1009,37 @@
if (!pf_count) pf_next_buf(unit);
}
pi_disconnect(PI);
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
static void do_pf_write( void )
+{ ps_set_intr(do_pf_write_start,0,0,nice);
+}
+
+static void do_pf_write_start( void )
+
{ int unit = pf_unit;
+ long saved_flags;
pf_busy = 1;
- sti();
-
if (pf_start(unit,ATAPI_WRITE_10,pf_block,pf_run)) {
pi_disconnect(PI);
if (pf_retries < PF_MAX_RETRIES) {
pf_retries++;
- pi_do_claimed(PI,do_pf_write);
+ pi_do_claimed(PI,do_pf_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
@@ -1023,13 +1049,14 @@
pi_disconnect(PI);
if (pf_retries < PF_MAX_RETRIES) {
pf_retries++;
- pi_do_claimed(PI,do_pf_write);
+ pi_do_claimed(PI,do_pf_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_write_block(PI,pf_buf,512);
@@ -1046,26 +1073,28 @@
static void do_pf_write_done( void )
{ int unit = pf_unit;
+ long saved_flags;
- sti();
if (pf_wait(unit,STAT_BUSY,0,"write block","done") & STAT_ERR) {
pi_disconnect(PI);
if (pf_retries < PF_MAX_RETRIES) {
pf_retries++;
- pi_do_claimed(PI,do_pf_write);
+ pi_do_claimed(PI,do_pf_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_disconnect(PI);
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pf_busy = 0;
- cli();
do_pf_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
/* end of pf.c */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov