patch-2.1.103 linux/drivers/block/paride/pd.c
Next file: linux/drivers/block/paride/pf.c
Previous file: linux/drivers/block/paride/pcd.c
Back to the patch index
Back to the overall index
- Lines: 442
- Date:
Thu May 14 19:11:48 1998
- Orig file:
v2.1.102/linux/drivers/block/paride/pd.c
- Orig date:
Thu May 7 22:51:48 1998
diff -u --recursive --new-file v2.1.102/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
@@ -1,6 +1,6 @@
/*
- pd.c (c) 1997 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU public license.
+ pd.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 IDE hard
drives based on chips supported by the paride module.
@@ -14,9 +14,9 @@
parameters are adjustable:
drive0 These four arguments can be arrays of
- drive1 1-7 integers as follows:
+ drive1 1-8 integers as follows:
drive2
- drive3 <prt>,<pro>,<uni>,<mod>,<geo>,<sby>,<dly>
+ drive3 <prt>,<pro>,<uni>,<mod>,<geo>,<sby>,<dly>,<slv>
Where,
@@ -54,6 +54,11 @@
set this to a small integer, the larger it is
the slower the port i/o. In some cases, setting
this to zero will speed up the device. (default -1)
+
+ <slv> IDE disks can be jumpered to master or slave.
+ Set this to 0 to choose the master drive, 1 to
+ choose the slave, -1 (the default) to choose the
+ first drive found.
major You may use this parameter to overide the
@@ -100,16 +105,18 @@
1.01 GRG 1997.01.24 Restored pd_reset()
Added eject ioctl
+ 1.02 GRG 1998.05.06 SMP spinlock changes,
+ Added slave support
*/
-#define PD_VERSION "1.01"
+#define PD_VERSION "1.02"
#define PD_MAJOR 45
#define PD_NAME "pd"
#define PD_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.
*/
@@ -121,12 +128,12 @@
static int nice = 0;
static int disable = 0;
-static int drive0[7] = {0,0,0,-1,0,1,-1};
-static int drive1[7] = {0,0,0,-1,0,1,-1};
-static int drive2[7] = {0,0,0,-1,0,1,-1};
-static int drive3[7] = {0,0,0,-1,0,1,-1};
+static int drive0[8] = {0,0,0,-1,0,1,-1,-1};
+static int drive1[8] = {0,0,0,-1,0,1,-1,-1};
+static int drive2[8] = {0,0,0,-1,0,1,-1,-1};
+static int drive3[8] = {0,0,0,-1,0,1,-1,-1};
-static int (*drives[4])[7] = {&drive0,&drive1,&drive2,&drive3};
+static int (*drives[4])[8] = {&drive0,&drive1,&drive2,&drive3};
static int pd_drive_count;
#define D_PRT 0
@@ -136,6 +143,7 @@
#define D_GEO 4
#define D_SBY 5
#define D_DLY 6
+#define D_SLV 7
#define DU (*drives[unit])
@@ -150,16 +158,17 @@
#include <linux/hdreg.h>
#include <linux/cdrom.h> /* for the eject ioctl */
+#include <asm/spinlock.h>
#include <asm/uaccess.h>
#ifndef MODULE
#include "setup.h"
-static STT pd_stt[7] = {{"drive0",7,drive0},
- {"drive1",7,drive1},
- {"drive2",7,drive2},
- {"drive3",7,drive3},
+static STT pd_stt[7] = {{"drive0",8,drive0},
+ {"drive1",8,drive1},
+ {"drive2",8,drive2},
+ {"drive3",8,drive3},
{"disable",1,&disable},
{"cluster",1,&cluster},
{"nice",1,&nice}};
@@ -176,10 +185,10 @@
MODULE_PARM(name,"s");
MODULE_PARM(cluster,"i");
MODULE_PARM(nice,"i");
-MODULE_PARM(drive0,"1-7i");
-MODULE_PARM(drive1,"1-7i");
-MODULE_PARM(drive2,"1-7i");
-MODULE_PARM(drive3,"1-7i");
+MODULE_PARM(drive0,"1-8i");
+MODULE_PARM(drive1,"1-8i");
+MODULE_PARM(drive2,"1-8i");
+MODULE_PARM(drive3,"1-8i");
#include "paride.h"
@@ -258,7 +267,9 @@
static int pd_revalidate(kdev_t dev);
static int pd_detect(void);
static void do_pd_read(void);
+static void do_pd_read_start(void);
static void do_pd_write(void);
+static void do_pd_write_start(void);
static void do_pd_read_drq( void );
static void do_pd_write_done( void );
@@ -282,6 +293,7 @@
int heads; /* physical geometry */
int sectors;
int cylinders;
+ int drive; /* master=0 slave=1 */
int changed; /* Have we seen a disk change ? */
int removable; /* removable media device ? */
int standby;
@@ -363,6 +375,7 @@
PD.access = 0;
PD.changed = 1;
PD.capacity = 0;
+ PD.drive = DU[D_SLV];
PD.present = 0;
j = 0;
while ((j < PD_NAMELEN-2) && (PD.name[j]=name[j])) j++;
@@ -646,6 +659,8 @@
#define WR(c,r,v) pi_write_regr(PI,c,r,v)
#define RR(c,r) (pi_read_regr(PI,c,r))
+#define DRIVE (0xa0+0x10*PD.drive)
+
/* ide command interface */
static void pd_print_error( int unit, char * msg, int status )
@@ -657,7 +672,7 @@
printk("\n");
}
-static void pd_reset( int unit )
+static void pd_reset( int unit ) /* called only for MASTER drive */
{ pi_connect(PI);
WR(1,6,4);
@@ -691,7 +706,7 @@
int c0, int c1, int func )
{
- WR(0,6,0xa0+h);
+ WR(0,6,DRIVE+h);
WR(0,1,0); /* the IDE task file */
WR(0,2,n);
WR(0,3,s);
@@ -793,10 +808,16 @@
{ int j;
char id[PD_ID_LEN+1];
- pd_reset(unit);
+/* WARNING: here there may be dragons. reset() applies to both drives,
+ but we call it only on probing the MASTER. This should allow most
+ common configurations to work, but be warned that a reset can clear
+ settings on the SLAVE drive.
+*/
+
+ if (PD.drive == 0) pd_reset(unit);
pi_connect(PI);
- WR(0,6,0xa0);
+ WR(0,6,DRIVE);
pd_wait_for(unit,0,DBMSG("before IDENT"));
pd_send_command(unit,1,0,0,0,0,IDE_IDENTIFY);
@@ -818,8 +839,10 @@
PD.removable = (word_val(0) & 0x80);
- printk("%s: %s, %d blocks [%dM], (%d/%d/%d), %s media\n",
- PD.name,id,PD.capacity,PD.capacity/2048,
+ printk("%s: %s, %s, %d blocks [%dM], (%d/%d/%d), %s media\n",
+ PD.name,id,
+ PD.drive?"slave":"master",
+ PD.capacity,PD.capacity/2048,
PD.cylinders,PD.heads,PD.sectors,
PD.removable?"removable":"fixed");
@@ -832,36 +855,39 @@
return 1;
}
+static int pd_probe_drive( int unit )
+
+{ if (PD.drive == -1) {
+ for (PD.drive=0;PD.drive<=1;PD.drive++)
+ if (pd_identify(unit)) return 1;
+ return 0;
+ }
+ else return pd_identify(unit);
+}
+
static int pd_detect( void )
-{ long flags;
- int k, unit;
+{ int k, unit;
k = 0;
if (pd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
unit = 0;
if (pi_init(PI,1,-1,-1,-1,-1,-1,pd_scratch,
PI_PD,verbose,PD.name)) {
- save_flags(flags);
- sti();
- if (pd_identify(unit)) {
+ if (pd_probe_drive(unit)) {
PD.present = 1;
k = 1;
} else pi_release(PI);
- restore_flags(flags);
}
} else for (unit=0;unit<PD_UNITS;unit++) if (DU[D_PRT])
if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
DU[D_PRO],DU[D_DLY],pd_scratch,
PI_PD,verbose,PD.name)) {
- save_flags(flags);
- sti();
- if (pd_identify(unit)) {
+ if (pd_probe_drive(unit)) {
PD.present = 1;
k = unit+1;
} else pi_release(PI);
- restore_flags(flags);
}
/* We lie about the number of drives found, as the generic partition
@@ -926,18 +952,24 @@
pd_buf = CURRENT->buffer;
pd_retries = 0;
+ pd_busy = 1;
if (pd_cmd == READ) pi_do_claimed(PI,do_pd_read);
else if (pd_cmd == WRITE) pi_do_claimed(PI,do_pd_write);
- else { end_request(0);
+ else { pd_busy = 0;
+ end_request(0);
goto repeat;
}
}
static void pd_next_buf( int unit )
-{ cli();
+{ long saved_flags;
+
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
- if (!pd_run) { sti(); return; }
+ if (!pd_run) { spin_unlock_irqrestore(&io_request_lock,saved_flags);
+ return;
+ }
/* paranoia */
@@ -951,29 +983,34 @@
pd_count = CURRENT->nr_sectors;
pd_buf = CURRENT->buffer;
- sti();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
static void do_pd_read( void )
+{ ps_set_intr(do_pd_read_start,0,0,nice);
+}
+
+static void do_pd_read_start( void )
+
{ int unit = pd_unit;
+ long saved_flags;
pd_busy = 1;
- sti();
-
pi_connect(PI);
if (pd_wait_for(unit,STAT_READY,"do_pd_read") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_read);
+ pi_do_claimed(PI,do_pd_read_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pd_ide_command(unit,IDE_READ,pd_block,pd_run);
@@ -983,21 +1020,21 @@
static void do_pd_read_drq( void )
{ int unit = pd_unit;
-
- sti();
+ long saved_flags;
while (1) {
if (pd_wait_for(unit,STAT_DRQ,"do_pd_read_drq") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_read);
+ pi_do_claimed(PI,do_pd_read_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_read_block(PI,pd_buf,512);
@@ -1008,32 +1045,38 @@
if (!pd_count) pd_next_buf(unit);
}
pi_disconnect(PI);
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
static void do_pd_write( void )
+{ ps_set_intr(do_pd_write_start,0,0,nice);
+}
+
+static void do_pd_write_start( void )
+
{ int unit = pd_unit;
+ long saved_flags;
pd_busy = 1;
- sti();
-
pi_connect(PI);
if (pd_wait_for(unit,STAT_READY,"do_pd_write") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_write);
+ pi_do_claimed(PI,do_pd_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pd_ide_command(unit,IDE_WRITE,pd_block,pd_run);
@@ -1042,14 +1085,15 @@
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_write);
+ pi_do_claimed(PI,do_pd_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
- return;
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
+ return;
}
pi_write_block(PI,pd_buf,512);
pd_count--; pd_run--;
@@ -1064,26 +1108,28 @@
static void do_pd_write_done( void )
{ int unit = pd_unit;
+ long saved_flags;
- sti();
if (pd_wait_for(unit,STAT_READY,"do_pd_write_done") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
- pi_do_claimed(PI,do_pd_write);
+ pi_do_claimed(PI,do_pd_write_start);
return;
}
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(0);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
return;
}
pi_disconnect(PI);
+ spin_lock_irqsave(&io_request_lock,saved_flags);
end_request(1);
pd_busy = 0;
- cli();
do_pd_request();
+ spin_unlock_irqrestore(&io_request_lock,saved_flags);
}
/* end of pd.c */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov