Commit 91c42c4d authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] Lindent pd.c

pd.c fed through Lindent
parent f299adc6
......@@ -125,19 +125,20 @@
*/
static int verbose = 0;
static int major = PD_MAJOR;
static char *name = PD_NAME;
static int cluster = 64;
static int nice = 0;
static int disable = 0;
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])[8] = {&drive0,&drive1,&drive2,&drive3};
static int verbose = 0;
static int major = PD_MAJOR;
static char *name = PD_NAME;
static int cluster = 64;
static int nice = 0;
static int disable = 0;
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])[8] = {
&drive0, &drive1, &drive2, &drive3};
static int pd_drive_count;
#define D_PRT 0
......@@ -168,30 +169,31 @@ static spinlock_t pd_lock = SPIN_LOCK_UNLOCKED;
#include "setup.h"
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}};
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}
};
void pd_setup( char *str, int *ints)
void pd_setup(char *str, int *ints)
{
generic_setup(pd_stt,7,str);
generic_setup(pd_stt, 7, str);
}
#endif
MODULE_PARM(verbose,"i");
MODULE_PARM(major,"i");
MODULE_PARM(name,"s");
MODULE_PARM(cluster,"i");
MODULE_PARM(nice,"i");
MODULE_PARM(drive0,"1-8i");
MODULE_PARM(drive1,"1-8i");
MODULE_PARM(drive2,"1-8i");
MODULE_PARM(drive3,"1-8i");
MODULE_PARM(verbose, "i");
MODULE_PARM(major, "i");
MODULE_PARM(name, "s");
MODULE_PARM(cluster, "i");
MODULE_PARM(nice, "i");
MODULE_PARM(drive0, "1-8i");
MODULE_PARM(drive1, "1-8i");
MODULE_PARM(drive2, "1-8i");
MODULE_PARM(drive3, "1-8i");
#include "paride.h"
......@@ -216,10 +218,10 @@ MODULE_PARM(drive3,"1-8i");
#define PD_ID_LEN 14
#define PD_MAX_RETRIES 5
#define PD_TMO 800 /* interrupt timeout in jiffies */
#define PD_SPIN_DEL 50 /* spin delay in micro-seconds */
#define PD_TMO 800 /* interrupt timeout in jiffies */
#define PD_SPIN_DEL 50 /* spin delay in micro-seconds */
#define PD_SPIN (1000000*PD_TMO)/(HZ*PD_SPIN_DEL)
#define PD_SPIN (1000000*PD_TMO)/(HZ*PD_SPIN_DEL)
#define STAT_ERR 0x00001
#define STAT_INDEX 0x00002
......@@ -250,45 +252,45 @@ MODULE_PARM(drive3,"1-8i");
#define IDE_IDENTIFY 0xec
#define IDE_EJECT 0xed
void pd_setup(char * str, int * ints);
void pd_setup(char *str, int *ints);
static int pd_open(struct inode *inode, struct file *file);
static void do_pd_request(request_queue_t * q);
static int pd_ioctl(struct inode *inode,struct file *file,
unsigned int cmd, unsigned long arg);
static int pd_release (struct inode *inode, struct file *file);
static int pd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
static int pd_release(struct inode *inode, struct file *file);
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 );
static void do_pd_read_drq(void);
static void do_pd_write_done(void);
static int pd_identify (int unit);
static int pd_identify(int unit);
static void pd_media_check(int unit);
static void pd_doorlock(int unit, int func);
static int pd_check_media(kdev_t dev);
static void pd_eject( int unit);
static void pd_eject(int unit);
#define PD_NAMELEN 8
struct pd_unit {
struct pi_adapter pia; /* interface to paride layer */
struct pi_adapter pia; /* interface to paride layer */
struct pi_adapter *pi;
int access; /* count of active opens ... */
int capacity; /* Size of this volume in sectors */
int heads; /* physical geometry */
int access; /* count of active opens ... */
int capacity; /* Size of this volume in sectors */
int heads; /* physical geometry */
int sectors;
int cylinders;
int can_lba;
int drive; /* master=0 slave=1 */
int changed; /* Have we seen a disk change ? */
int removable; /* removable media device ? */
int drive; /* master=0 slave=1 */
int changed; /* Have we seen a disk change ? */
int removable; /* removable media device ? */
int standby;
int alt_geom;
int present;
char name[PD_NAMELEN]; /* pda, pdb, etc ... */
char name[PD_NAMELEN]; /* pda, pdb, etc ... */
struct gendisk gd;
};
......@@ -299,81 +301,84 @@ struct pd_unit pd[PD_UNITS];
#define PD pd[unit]
#define PI PD.pi
static char pd_scratch[512]; /* scratch block buffer */
static char pd_scratch[512]; /* scratch block buffer */
/* the variables below are used mainly in the I/O request engine, which
processes only one request at a time.
*/
static int pd_retries = 0; /* i/o error retry count */
static int pd_busy = 0; /* request being processed ? */
static int pd_block; /* address of next requested block */
static int pd_count; /* number of blocks still to do */
static int pd_run; /* sectors in current cluster */
static int pd_cmd; /* current command READ/WRITE */
static int pd_unit; /* unit of current request */
static int pd_dev; /* minor of current request */
static char * pd_buf; /* buffer for request in progress */
static int pd_retries = 0; /* i/o error retry count */
static int pd_busy = 0; /* request being processed ? */
static int pd_block; /* address of next requested block */
static int pd_count; /* number of blocks still to do */
static int pd_run; /* sectors in current cluster */
static int pd_cmd; /* current command READ/WRITE */
static int pd_unit; /* unit of current request */
static int pd_dev; /* minor of current request */
static char *pd_buf; /* buffer for request in progress */
static DECLARE_WAIT_QUEUE_HEAD(pd_wait_open);
static char *pd_errs[17] = { "ERR","INDEX","ECC","DRQ","SEEK","WRERR",
"READY","BUSY","AMNF","TK0NF","ABRT","MCR",
"IDNF","MC","UNC","???","TMO"};
static char *pd_errs[17] = { "ERR", "INDEX", "ECC", "DRQ", "SEEK", "WRERR",
"READY", "BUSY", "AMNF", "TK0NF", "ABRT", "MCR",
"IDNF", "MC", "UNC", "???", "TMO"
};
/* kernel glue structures */
extern struct block_device_operations pd_fops;
static struct block_device_operations pd_fops = {
owner: THIS_MODULE,
open: pd_open,
release: pd_release,
ioctl: pd_ioctl,
check_media_change: pd_check_media,
revalidate: pd_revalidate
.owner = THIS_MODULE,
.open = pd_open,
.release = pd_release,
.ioctl = pd_ioctl,
.check_media_change = pd_check_media,
.revalidate = pd_revalidate
};
void pd_init_units( void )
{ int unit, j;
static void pd_init_units(void)
{
int unit, j;
pd_drive_count = 0;
for (unit=0;unit<PD_UNITS;unit++) {
PD.pi = & PD.pia;
for (unit = 0; unit < PD_UNITS; unit++) {
PD.pi = &PD.pia;
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++;
while ((j < PD_NAMELEN - 2) && (PD.name[j] = name[j]))
j++;
PD.name[j++] = 'a' + unit;
PD.name[j] = 0;
PD.alt_geom = DU[D_GEO];
PD.standby = DU[D_SBY];
if (DU[D_PRT]) pd_drive_count++;
if (DU[D_PRT])
pd_drive_count++;
}
}
static int pd_open (struct inode *inode, struct file *file)
static int pd_open(struct inode *inode, struct file *file)
{
int unit = DEVICE_NR(inode->i_rdev);
if ((unit >= PD_UNITS) || (!PD.present))
if ((unit >= PD_UNITS) || (!PD.present))
return -ENODEV;
PD.access++;
PD.access++;
if (PD.removable) {
if (PD.removable) {
pd_media_check(unit);
pd_doorlock(unit,IDE_DOORLOCK);
pd_doorlock(unit, IDE_DOORLOCK);
}
return 0;
return 0;
}
static int pd_ioctl(struct inode *inode,struct file *file,
unsigned int cmd, unsigned long arg)
static int pd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct hd_geometry *geo = (struct hd_geometry *) arg;
int err, unit = DEVICE_NR(inode->i_rdev);
......@@ -382,47 +387,50 @@ static int pd_ioctl(struct inode *inode,struct file *file,
return -ENODEV;
switch (cmd) {
case CDROMEJECT:
if (PD.access == 1) pd_eject(unit);
case CDROMEJECT:
if (PD.access == 1)
pd_eject(unit);
return 0;
case HDIO_GETGEO:
if (!geo) return -EINVAL;
err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
if (err) return err;
case HDIO_GETGEO:
if (!geo)
return -EINVAL;
err = verify_area(VERIFY_WRITE, geo, sizeof (*geo));
if (err)
return err;
if (PD.alt_geom) {
put_user(PD.capacity/(PD_LOG_HEADS*PD_LOG_SECTS),
(short *) &geo->cylinders);
put_user(PD_LOG_HEADS, (char *) &geo->heads);
put_user(PD_LOG_SECTS, (char *) &geo->sectors);
put_user(PD.capacity / (PD_LOG_HEADS * PD_LOG_SECTS),
(short *) &geo->cylinders);
put_user(PD_LOG_HEADS, (char *) &geo->heads);
put_user(PD_LOG_SECTS, (char *) &geo->sectors);
} else {
put_user(PD.cylinders, (short *) &geo->cylinders);
put_user(PD.heads, (char *) &geo->heads);
put_user(PD.sectors, (char *) &geo->sectors);
put_user(PD.cylinders, (short *) &geo->cylinders);
put_user(PD.heads, (char *) &geo->heads);
put_user(PD.sectors, (char *) &geo->sectors);
}
put_user(get_start_sect(inode->i_bdev), (long *)&geo->start);
put_user(get_start_sect(inode->i_bdev), (long *) &geo->start);
return 0;
default:
default:
return -EINVAL;
}
}
static int pd_release (struct inode *inode, struct file *file)
static int pd_release(struct inode *inode, struct file *file)
{
int unit = DEVICE_NR(inode->i_rdev);
int unit = DEVICE_NR(inode->i_rdev);
if (!--PD.access && PD.removable)
pd_doorlock(unit,IDE_DOORUNLOCK);
if (!--PD.access && PD.removable)
pd_doorlock(unit, IDE_DOORUNLOCK);
return 0;
}
static int pd_check_media( kdev_t dev)
static int pd_check_media(kdev_t dev)
{
int r, unit = DEVICE_NR(dev);
if ((unit >= PD_UNITS) || (!PD.present))
return -ENODEV;
if (!PD.removable)
if (!PD.removable)
return 0;
pd_media_check(unit);
r = PD.changed;
......@@ -439,7 +447,7 @@ static int pd_revalidate(kdev_t dev)
set_capacity(&PD.gd, PD.capacity);
else
set_capacity(&PD.gd, 0);
return 0;
return 0;
}
#define WR(c,r,v) pi_write_regr(PI,c,r,v)
......@@ -449,60 +457,63 @@ static int pd_revalidate(kdev_t dev)
/* ide command interface */
static void pd_print_error( int unit, char * msg, int status )
{ int i;
static void pd_print_error(int unit, char *msg, int status)
{
int i;
printk("%s: %s: status = 0x%x =",PD.name,msg,status);
for(i=0;i<18;i++) if (status & (1<<i)) printk(" %s",pd_errs[i]);
printk("%s: %s: status = 0x%x =", PD.name, msg, status);
for (i = 0; i < 18; i++)
if (status & (1 << i))
printk(" %s", pd_errs[i]);
printk("\n");
}
static void pd_reset( int unit ) /* called only for MASTER drive */
{ pi_connect(PI);
WR(1,6,4);
udelay(50);
WR(1,6,0);
static void pd_reset(int unit)
{ /* called only for MASTER drive */
pi_connect(PI);
WR(1, 6, 4);
udelay(50);
WR(1, 6, 0);
pi_disconnect(PI);
udelay(250);
}
#define DBMSG(msg) ((verbose>1)?(msg):NULL)
static int pd_wait_for( int unit, int w, char * msg ) /* polled wait */
{ int k, r, e;
k=0;
while(k < PD_SPIN) {
r = RR(1,6);
k++;
if (((r & w) == w) && !(r & STAT_BUSY)) break;
udelay(PD_SPIN_DEL);
}
e = (RR(0,1)<<8) + RR(0,7);
if (k >= PD_SPIN) e |= ERR_TMO;
if ((e & (STAT_ERR|ERR_TMO)) && (msg != NULL))
pd_print_error(unit,msg,e);
return e;
static int pd_wait_for(int unit, int w, char *msg)
{ /* polled wait */
int k, r, e;
k = 0;
while (k < PD_SPIN) {
r = RR(1, 6);
k++;
if (((r & w) == w) && !(r & STAT_BUSY))
break;
udelay(PD_SPIN_DEL);
}
e = (RR(0, 1) << 8) + RR(0, 7);
if (k >= PD_SPIN)
e |= ERR_TMO;
if ((e & (STAT_ERR | ERR_TMO)) && (msg != NULL))
pd_print_error(unit, msg, e);
return e;
}
static void pd_send_command( int unit, int n, int s, int h,
int c0, int c1, int func )
static void pd_send_command(int unit, int n, int s, int h, int c0, int c1, int func)
{
WR(0,6,DRIVE+h);
WR(0,1,0); /* the IDE task file */
WR(0,2,n);
WR(0,3,s);
WR(0,4,c0);
WR(0,5,c1);
WR(0,7,func);
udelay(1);
WR(0, 6, DRIVE + h);
WR(0, 1, 0); /* the IDE task file */
WR(0, 2, n);
WR(0, 3, s);
WR(0, 4, c0);
WR(0, 5, c1);
WR(0, 7, func);
udelay(1);
}
static void pd_ide_command( int unit, int func, int block, int count )
static void pd_ide_command(int unit, int func, int block, int count)
{
int c1, c0, h, s;
......@@ -512,12 +523,12 @@ static void pd_ide_command( int unit, int func, int block, int count )
c1 = (block >>= 8) & 255;
h = ((block >>= 8) & 15) + 0x40;
} else {
s = ( block % PD.sectors) + 1;
h = ( block /= PD.sectors) % PD.heads;
c0 = ( block /= PD.heads) % 256;
s = (block % PD.sectors) + 1;
h = (block /= PD.sectors) % PD.heads;
c0 = (block /= PD.heads) % 256;
c1 = (block >>= 8);
}
pd_send_command(unit,count,s,h,c0,c1,func);
pd_send_command(unit, count, s, h, c0, c1, func);
}
/* According to the ATA standard, the default CHS geometry should be
......@@ -526,129 +537,137 @@ static void pd_ide_command( int unit, int func, int block, int count )
parameters are initialised.
*/
static void pd_init_dev_parms( int unit )
{ pi_connect(PI);
pd_wait_for(unit,0,DBMSG("before init_dev_parms"));
pd_send_command(unit,PD.sectors,0,PD.heads-1,0,0,IDE_INIT_DEV_PARMS);
udelay(300);
pd_wait_for(unit,0,"Initialise device parameters");
pi_disconnect(PI);
static void pd_init_dev_parms(int unit)
{
pi_connect(PI);
pd_wait_for(unit, 0, DBMSG("before init_dev_parms"));
pd_send_command(unit, PD.sectors, 0, PD.heads - 1, 0, 0,
IDE_INIT_DEV_PARMS);
udelay(300);
pd_wait_for(unit, 0, "Initialise device parameters");
pi_disconnect(PI);
}
static void pd_doorlock( int unit, int func )
{ pi_connect(PI);
if (pd_wait_for(unit,STAT_READY,"Lock") & STAT_ERR) {
pi_disconnect(PI);
return;
}
pd_send_command(unit,1,0,0,0,0,func);
pd_wait_for(unit,STAT_READY,"Lock done");
pi_disconnect(PI);
static void pd_doorlock(int unit, int func)
{
pi_connect(PI);
if (pd_wait_for(unit, STAT_READY, "Lock") & STAT_ERR) {
pi_disconnect(PI);
return;
}
pd_send_command(unit, 1, 0, 0, 0, 0, func);
pd_wait_for(unit, STAT_READY, "Lock done");
pi_disconnect(PI);
}
static void pd_eject( int unit )
{ pi_connect(PI);
pd_wait_for(unit,0,DBMSG("before unlock on eject"));
pd_send_command(unit,1,0,0,0,0,IDE_DOORUNLOCK);
pd_wait_for(unit,0,DBMSG("after unlock on eject"));
pd_wait_for(unit,0,DBMSG("before eject"));
pd_send_command(unit,0,0,0,0,0,IDE_EJECT);
pd_wait_for(unit,0,DBMSG("after eject"));
pi_disconnect(PI);
static void pd_eject(int unit)
{
pi_connect(PI);
pd_wait_for(unit, 0, DBMSG("before unlock on eject"));
pd_send_command(unit, 1, 0, 0, 0, 0, IDE_DOORUNLOCK);
pd_wait_for(unit, 0, DBMSG("after unlock on eject"));
pd_wait_for(unit, 0, DBMSG("before eject"));
pd_send_command(unit, 0, 0, 0, 0, 0, IDE_EJECT);
pd_wait_for(unit, 0, DBMSG("after eject"));
pi_disconnect(PI);
}
static void pd_media_check( int unit )
{ int r;
pi_connect(PI);
r = pd_wait_for(unit,STAT_READY,DBMSG("before media_check"));
if (!(r & STAT_ERR)) {
pd_send_command(unit,1,1,0,0,0,IDE_READ_VRFY);
r = pd_wait_for(unit,STAT_READY,DBMSG("RDY after READ_VRFY"));
} else PD.changed = 1; /* say changed if other error */
if (r & ERR_MC) {
PD.changed = 1;
pd_send_command(unit,1,0,0,0,0,IDE_ACKCHANGE);
pd_wait_for(unit,STAT_READY,DBMSG("RDY after ACKCHANGE"));
pd_send_command(unit,1,1,0,0,0,IDE_READ_VRFY);
r = pd_wait_for(unit,STAT_READY,DBMSG("RDY after VRFY"));
}
pi_disconnect(PI);
static void pd_media_check(int unit)
{
int r;
pi_connect(PI);
r = pd_wait_for(unit, STAT_READY, DBMSG("before media_check"));
if (!(r & STAT_ERR)) {
pd_send_command(unit, 1, 1, 0, 0, 0, IDE_READ_VRFY);
r = pd_wait_for(unit, STAT_READY, DBMSG("RDY after READ_VRFY"));
} else
PD.changed = 1; /* say changed if other error */
if (r & ERR_MC) {
PD.changed = 1;
pd_send_command(unit, 1, 0, 0, 0, 0, IDE_ACKCHANGE);
pd_wait_for(unit, STAT_READY, DBMSG("RDY after ACKCHANGE"));
pd_send_command(unit, 1, 1, 0, 0, 0, IDE_READ_VRFY);
r = pd_wait_for(unit, STAT_READY, DBMSG("RDY after VRFY"));
}
pi_disconnect(PI);
}
static void pd_standby_off( int unit )
{ pi_connect(PI);
pd_wait_for(unit,0,DBMSG("before STANDBY"));
pd_send_command(unit,0,0,0,0,0,IDE_STANDBY);
pd_wait_for(unit,0,DBMSG("after STANDBY"));
pi_disconnect(PI);
static void pd_standby_off(int unit)
{
pi_connect(PI);
pd_wait_for(unit, 0, DBMSG("before STANDBY"));
pd_send_command(unit, 0, 0, 0, 0, 0, IDE_STANDBY);
pd_wait_for(unit, 0, DBMSG("after STANDBY"));
pi_disconnect(PI);
}
#define word_val(n) ((pd_scratch[2*n]&0xff)+256*(pd_scratch[2*n+1]&0xff))
static int pd_identify( int unit )
{ int j;
char id[PD_ID_LEN+1];
static int pd_identify(int unit)
{
int j;
char id[PD_ID_LEN + 1];
/* 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);
if (PD.drive == 0)
pd_reset(unit);
pi_connect(PI);
WR(0,6,DRIVE);
pd_wait_for(unit,0,DBMSG("before IDENT"));
pd_send_command(unit,1,0,0,0,0,IDE_IDENTIFY);
pi_connect(PI);
WR(0, 6, DRIVE);
pd_wait_for(unit, 0, DBMSG("before IDENT"));
pd_send_command(unit, 1, 0, 0, 0, 0, IDE_IDENTIFY);
if (pd_wait_for(unit,STAT_DRQ,DBMSG("IDENT DRQ")) & STAT_ERR) {
pi_disconnect(PI);
return 0;
}
pi_read_block(PI,pd_scratch,512);
pi_disconnect(PI);
if (pd_wait_for(unit, STAT_DRQ, DBMSG("IDENT DRQ")) & STAT_ERR) {
pi_disconnect(PI);
return 0;
}
pi_read_block(PI, pd_scratch, 512);
pi_disconnect(PI);
PD.can_lba = pd_scratch[99] & 2;
PD.sectors = le16_to_cpu(*(u16*)(pd_scratch+12));
PD.heads = le16_to_cpu(*(u16*)(pd_scratch+6));
PD.cylinders = le16_to_cpu(*(u16*)(pd_scratch+2));
PD.sectors = le16_to_cpu(*(u16 *) (pd_scratch + 12));
PD.heads = le16_to_cpu(*(u16 *) (pd_scratch + 6));
PD.cylinders = le16_to_cpu(*(u16 *) (pd_scratch + 2));
if (PD.can_lba)
PD.capacity = le32_to_cpu(*(u32*)(pd_scratch + 120));
PD.capacity = le32_to_cpu(*(u32 *) (pd_scratch + 120));
else
PD.capacity = PD.sectors*PD.heads*PD.cylinders;
for(j=0;j<PD_ID_LEN;j++) id[j^1] = pd_scratch[j+PD_ID_OFF];
j = PD_ID_LEN-1;
while ((j >= 0) && (id[j] <= 0x20)) j--;
j++; id[j] = 0;
PD.removable = (word_val(0) & 0x80);
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");
if (PD.capacity) pd_init_dev_parms(unit);
if (!PD.standby) pd_standby_off(unit);
return 1;
PD.capacity = PD.sectors * PD.heads * PD.cylinders;
for (j = 0; j < PD_ID_LEN; j++)
id[j ^ 1] = pd_scratch[j + PD_ID_OFF];
j = PD_ID_LEN - 1;
while ((j >= 0) && (id[j] <= 0x20))
j--;
j++;
id[j] = 0;
PD.removable = (word_val(0) & 0x80);
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");
if (PD.capacity)
pd_init_dev_parms(unit);
if (!PD.standby)
pd_standby_off(unit);
return 1;
}
static int pd_probe_drive( int unit )
static int pd_probe_drive(int unit)
{
if (PD.drive == -1) {
for (PD.drive=0;PD.drive<=1;PD.drive++)
for (PD.drive = 0; PD.drive <= 1; PD.drive++)
if (pd_identify(unit))
return 1;
return 0;
......@@ -656,31 +675,36 @@ static int pd_probe_drive( int unit )
return pd_identify(unit);
}
static int pd_detect( void )
static int pd_detect(void)
{
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)) {
if (pd_probe_drive(unit)) {
PD.present = 1;
k = 1;
} else pi_release(PI);
}
} 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)) {
if (pd_probe_drive(unit)) {
PD.present = 1;
k = unit+1;
} else pi_release(PI);
}
for (unit=0;unit<PD_UNITS;unit++) {
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)) {
if (pd_probe_drive(unit)) {
PD.present = 1;
k = 1;
} else
pi_release(PI);
}
} 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)) {
if (pd_probe_drive(unit)) {
PD.present = 1;
k = unit + 1;
} else
pi_release(PI);
}
for (unit = 0; unit < PD_UNITS; unit++) {
if (PD.present) {
PD.gd.major_name = PD.name;
PD.gd.minor_shift = PD_BITS;
......@@ -692,252 +716,262 @@ static int pd_detect( void )
}
}
if (k)
return 1;
printk("%s: no valid drive found\n",name);
return 0;
return 1;
printk("%s: no valid drive found\n", name);
return 0;
}
/* The i/o request engine */
static int pd_ready( void )
{ int unit = pd_unit;
static int pd_ready(void)
{
int unit = pd_unit;
return (!(RR(1,6) & STAT_BUSY)) ;
return (!(RR(1, 6) & STAT_BUSY));
}
static void do_pd_request (request_queue_t * q)
static void do_pd_request(request_queue_t * q)
{
int unit;
int unit;
if (pd_busy) return;
if (pd_busy)
return;
repeat:
if (blk_queue_empty(QUEUE))
return;
pd_dev = minor(CURRENT->rq_dev);
pd_dev = minor(CURRENT->rq_dev);
pd_unit = unit = DEVICE_NR(CURRENT->rq_dev);
pd_block = CURRENT->sector;
pd_run = CURRENT->nr_sectors;
pd_count = CURRENT->current_nr_sectors;
pd_block = CURRENT->sector;
pd_run = CURRENT->nr_sectors;
pd_count = CURRENT->current_nr_sectors;
if ((pd_dev >= PD_DEVS) ||
((pd_block+pd_count) > get_capacity(&pd[unit].gd))) {
end_request(CURRENT, 0);
goto repeat;
}
if ((pd_dev >= PD_DEVS) ||
((pd_block + pd_count) > get_capacity(&pd[unit].gd))) {
end_request(CURRENT, 0);
goto repeat;
}
pd_cmd = rq_data_dir(CURRENT);
pd_buf = CURRENT->buffer;
pd_retries = 0;
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 { pd_busy = 0;
if (pd_cmd == READ)
pi_do_claimed(PI, do_pd_read);
else if (pd_cmd == WRITE)
pi_do_claimed(PI, do_pd_write);
else {
pd_busy = 0;
end_request(CURRENT, 0);
goto repeat;
}
goto repeat;
}
}
static void pd_next_buf( int unit )
{ long saved_flags;
static void pd_next_buf(int unit)
{
long saved_flags;
spin_lock_irqsave(&pd_lock,saved_flags);
spin_lock_irqsave(&pd_lock, saved_flags);
end_request(CURRENT, 1);
if (!pd_run) { spin_unlock_irqrestore(&pd_lock,saved_flags);
return;
if (!pd_run) {
spin_unlock_irqrestore(&pd_lock, saved_flags);
return;
}
/* paranoia */
if (blk_queue_empty(QUEUE) ||
(rq_data_dir(CURRENT) != pd_cmd) ||
(minor(CURRENT->rq_dev) != pd_dev) ||
(CURRENT->sector != pd_block))
(minor(CURRENT->rq_dev) != pd_dev) || (CURRENT->sector != pd_block))
printk("%s: OUCH: request list changed unexpectedly\n",
PD.name);
PD.name);
pd_count = CURRENT->current_nr_sectors;
pd_buf = CURRENT->buffer;
spin_unlock_irqrestore(&pd_lock,saved_flags);
spin_unlock_irqrestore(&pd_lock, saved_flags);
}
static void do_pd_read( void )
{ ps_set_intr(do_pd_read_start,0,0,nice);
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;
static void do_pd_read_start(void)
{
int unit = pd_unit;
long saved_flags;
pd_busy = 1;
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_start);
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_start);
return;
}
spin_lock_irqsave(&pd_lock,saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
}
spin_lock_irqsave(&pd_lock, saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock,saved_flags);
return;
}
pd_ide_command(unit,IDE_READ,pd_block,pd_run);
ps_set_intr(do_pd_read_drq,pd_ready,PD_TMO,nice);
spin_unlock_irqrestore(&pd_lock, saved_flags);
return;
}
pd_ide_command(unit, IDE_READ, pd_block, pd_run);
ps_set_intr(do_pd_read_drq, pd_ready, PD_TMO, nice);
}
static void do_pd_read_drq( void )
{ int unit = pd_unit;
long saved_flags;
static void do_pd_read_drq(void)
{
int unit = pd_unit;
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_start);
return;
}
spin_lock_irqsave(&pd_lock,saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock,saved_flags);
return;
}
pi_read_block(PI,pd_buf,512);
pd_count--; pd_run--;
pd_buf += 512;
pd_block++;
if (!pd_run) break;
if (!pd_count) pd_next_buf(unit);
}
pi_disconnect(PI);
spin_lock_irqsave(&pd_lock,saved_flags);
end_request(CURRENT, 1);
pd_busy = 0;
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_start);
return;
}
spin_lock_irqsave(&pd_lock, saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags);
return;
}
pi_read_block(PI, pd_buf, 512);
pd_count--;
pd_run--;
pd_buf += 512;
pd_block++;
if (!pd_run)
break;
if (!pd_count)
pd_next_buf(unit);
}
pi_disconnect(PI);
spin_lock_irqsave(&pd_lock, saved_flags);
end_request(CURRENT, 1);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock,saved_flags);
spin_unlock_irqrestore(&pd_lock, saved_flags);
}
static void do_pd_write( void )
{ ps_set_intr(do_pd_write_start,0,0,nice);
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;
static void do_pd_write_start(void)
{
int unit = pd_unit;
long saved_flags;
pd_busy = 1;
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_start);
return;
}
spin_lock_irqsave(&pd_lock,saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock,saved_flags);
return;
}
pd_ide_command(unit,IDE_WRITE,pd_block,pd_run);
while (1) {
if (pd_wait_for(unit,STAT_DRQ,"do_pd_write_drq") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
pi_do_claimed(PI,do_pd_write_start);
return;
}
spin_lock_irqsave(&pd_lock,saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
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_start);
return;
}
spin_lock_irqsave(&pd_lock, saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock,saved_flags);
spin_unlock_irqrestore(&pd_lock, saved_flags);
return;
}
pi_write_block(PI,pd_buf,512);
pd_count--; pd_run--;
pd_buf += 512;
pd_block++;
if (!pd_run) break;
if (!pd_count) pd_next_buf(unit);
}
ps_set_intr(do_pd_write_done,pd_ready,PD_TMO,nice);
pd_ide_command(unit, IDE_WRITE, pd_block, pd_run);
while (1) {
if (pd_wait_for(unit, STAT_DRQ, "do_pd_write_drq") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) {
pd_retries++;
pi_do_claimed(PI, do_pd_write_start);
return;
}
spin_lock_irqsave(&pd_lock, saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags);
return;
}
pi_write_block(PI, pd_buf, 512);
pd_count--;
pd_run--;
pd_buf += 512;
pd_block++;
if (!pd_run)
break;
if (!pd_count)
pd_next_buf(unit);
}
ps_set_intr(do_pd_write_done, pd_ready, PD_TMO, nice);
}
static void do_pd_write_done( void )
{ int unit = pd_unit;
long saved_flags;
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_start);
return;
}
spin_lock_irqsave(&pd_lock,saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
static void do_pd_write_done(void)
{
int unit = pd_unit;
long saved_flags;
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_start);
return;
}
spin_lock_irqsave(&pd_lock, saved_flags);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock,saved_flags);
return;
}
pi_disconnect(PI);
spin_lock_irqsave(&pd_lock,saved_flags);
end_request(CURRENT, 1);
pd_busy = 0;
spin_unlock_irqrestore(&pd_lock, saved_flags);
return;
}
pi_disconnect(PI);
spin_lock_irqsave(&pd_lock, saved_flags);
end_request(CURRENT, 1);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock,saved_flags);
spin_unlock_irqrestore(&pd_lock, saved_flags);
}
static int __init pd_init(void)
{
request_queue_t * q;
if (disable) return -1;
if (register_blkdev(MAJOR_NR,name,&pd_fops)) {
printk("%s: unable to get major number %d\n",
name,major);
return -1;
}
request_queue_t *q;
if (disable)
return -1;
if (register_blkdev(MAJOR_NR, name, &pd_fops)) {
printk("%s: unable to get major number %d\n", name, major);
return -1;
}
q = BLK_DEFAULT_QUEUE(MAJOR_NR);
blk_init_queue(q, do_pd_request, &pd_lock);
blk_queue_max_sectors(q, cluster);
printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
name,name,PD_VERSION,major,cluster,nice);
name, name, PD_VERSION, major, cluster, nice);
pd_init_units();
if (!pd_detect()) {
if (!pd_detect()) {
unregister_blkdev(MAJOR_NR, name);
return -1;
}
return 0;
return 0;
}
static void __exit pd_exit(void)
{
int unit;
unregister_blkdev(MAJOR_NR, name);
for (unit=0; unit<PD_UNITS; unit++)
for (unit = 0; unit < PD_UNITS; unit++)
if (PD.present) {
del_gendisk(&PD.gd);
pi_release(PI);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment