Commit 8e273c4e authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] cleanup of pd.c

macroectomy a-la pf.c and pcd.c ones, ditto for passing pointers to
structures instead of minors.
parent 91c42c4d
...@@ -137,20 +137,10 @@ static int drive1[8] = { 0, 0, 0, -1, 0, 1, -1, -1 }; ...@@ -137,20 +137,10 @@ 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 drive2[8] = { 0, 0, 0, -1, 0, 1, -1, -1 };
static int drive3[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] = { static int (*drives[4])[8] = {&drive0, &drive1, &drive2, &drive3};
&drive0, &drive1, &drive2, &drive3};
static int pd_drive_count; static int pd_drive_count;
#define D_PRT 0 enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
#define D_PRO 1
#define D_UNI 2
#define D_MOD 3
#define D_GEO 4
#define D_SBY 5
#define D_DLY 6
#define D_SLV 7
#define DU (*drives[unit])
/* end of parameters */ /* end of parameters */
...@@ -169,13 +159,14 @@ static spinlock_t pd_lock = SPIN_LOCK_UNLOCKED; ...@@ -169,13 +159,14 @@ static spinlock_t pd_lock = SPIN_LOCK_UNLOCKED;
#include "setup.h" #include "setup.h"
static STT pd_stt[7] = { {"drive0", 8, drive0}, static STT pd_stt[7] = {
{"drive1", 8, drive1}, {"drive0", 8, drive0},
{"drive2", 8, drive2}, {"drive1", 8, drive1},
{"drive3", 8, drive3}, {"drive2", 8, drive2},
{"disable", 1, &disable}, {"drive3", 8, drive3},
{"cluster", 1, &cluster}, {"disable", 1, &disable},
{"nice", 1, &nice} {"cluster", 1, &cluster},
{"nice", 1, &nice}
}; };
void pd_setup(char *str, int *ints) void pd_setup(char *str, int *ints)
...@@ -267,12 +258,6 @@ static void do_pd_write_start(void); ...@@ -267,12 +258,6 @@ static void do_pd_write_start(void);
static void do_pd_read_drq(void); static void do_pd_read_drq(void);
static void do_pd_write_done(void); static void do_pd_write_done(void);
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);
#define PD_NAMELEN 8 #define PD_NAMELEN 8
struct pd_unit { struct pd_unit {
...@@ -296,10 +281,13 @@ struct pd_unit { ...@@ -296,10 +281,13 @@ struct pd_unit {
struct pd_unit pd[PD_UNITS]; struct pd_unit pd[PD_UNITS];
/* 'unit' must be defined in all functions - either as a local or a param */ static int pd_identify(struct pd_unit *disk);
static void pd_media_check(struct pd_unit *disk);
static void pd_doorlock(struct pd_unit *disk, int func);
static int pd_check_media(kdev_t dev);
static void pd_eject(struct pd_unit *disk);
#define PD pd[unit] /* 'unit' must be defined in all functions - either as a local or a param */
#define PI PD.pi
static char pd_scratch[512]; /* scratch block buffer */ static char pd_scratch[512]; /* scratch block buffer */
...@@ -307,14 +295,14 @@ static char pd_scratch[512]; /* scratch block buffer */ ...@@ -307,14 +295,14 @@ static char pd_scratch[512]; /* scratch block buffer */
processes only one request at a time. processes only one request at a time.
*/ */
static struct pd_unit *pd_current; /* current request's drive */
static int pd_retries = 0; /* i/o error retry count */ static int pd_retries = 0; /* i/o error retry count */
static int pd_busy = 0; /* request being processed ? */ static int pd_busy = 0; /* request being processed ? */
static struct request *pd_req; /* current request */
static int pd_block; /* address of next requested block */ static int pd_block; /* address of next requested block */
static int pd_count; /* number of blocks still to do */ static int pd_count; /* number of blocks still to do */
static int pd_run; /* sectors in current cluster */ static int pd_run; /* sectors in current cluster */
static int pd_cmd; /* current command READ/WRITE */ 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 char *pd_buf; /* buffer for request in progress */
static DECLARE_WAIT_QUEUE_HEAD(pd_wait_open); static DECLARE_WAIT_QUEUE_HEAD(pd_wait_open);
...@@ -339,24 +327,22 @@ static struct block_device_operations pd_fops = { ...@@ -339,24 +327,22 @@ static struct block_device_operations pd_fops = {
static void pd_init_units(void) static void pd_init_units(void)
{ {
int unit, j; int unit;
pd_drive_count = 0; pd_drive_count = 0;
for (unit = 0; unit < PD_UNITS; unit++) { for (unit = 0; unit < PD_UNITS; unit++) {
PD.pi = &PD.pia; int *parm = *drives[unit];
PD.access = 0; struct pd_unit *disk = pd + unit;
PD.changed = 1; disk->pi = &disk->pia;
PD.capacity = 0; disk->access = 0;
PD.drive = DU[D_SLV]; disk->changed = 1;
PD.present = 0; disk->capacity = 0;
j = 0; disk->drive = parm[D_SLV];
while ((j < PD_NAMELEN - 2) && (PD.name[j] = name[j])) disk->present = 0;
j++; snprintf(disk->name, PD_NAMELEN, "%s%c", name, 'a'+unit);
PD.name[j++] = 'a' + unit; disk->alt_geom = parm[D_GEO];
PD.name[j] = 0; disk->standby = parm[D_SBY];
PD.alt_geom = DU[D_GEO]; if (parm[D_PRT])
PD.standby = DU[D_SBY];
if (DU[D_PRT])
pd_drive_count++; pd_drive_count++;
} }
} }
...@@ -364,15 +350,16 @@ static void pd_init_units(void) ...@@ -364,15 +350,16 @@ static void pd_init_units(void)
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); int unit = DEVICE_NR(inode->i_rdev);
struct pd_unit *disk = pd + unit;
if ((unit >= PD_UNITS) || (!PD.present)) if (unit >= PD_UNITS || !disk->present)
return -ENODEV; return -ENODEV;
PD.access++; disk->access++;
if (PD.removable) { if (disk->removable) {
pd_media_check(unit); pd_media_check(disk);
pd_doorlock(unit, IDE_DOORLOCK); pd_doorlock(disk, IDE_DOORLOCK);
} }
return 0; return 0;
} }
...@@ -382,14 +369,15 @@ static int pd_ioctl(struct inode *inode, struct file *file, ...@@ -382,14 +369,15 @@ static int pd_ioctl(struct inode *inode, struct file *file,
{ {
struct hd_geometry *geo = (struct hd_geometry *) arg; struct hd_geometry *geo = (struct hd_geometry *) arg;
int err, unit = DEVICE_NR(inode->i_rdev); int err, unit = DEVICE_NR(inode->i_rdev);
struct pd_unit *disk = pd + unit;
if (!PD.present) if (!disk->present)
return -ENODEV; return -ENODEV;
switch (cmd) { switch (cmd) {
case CDROMEJECT: case CDROMEJECT:
if (PD.access == 1) if (disk->access == 1)
pd_eject(unit); pd_eject(disk);
return 0; return 0;
case HDIO_GETGEO: case HDIO_GETGEO:
if (!geo) if (!geo)
...@@ -398,15 +386,15 @@ static int pd_ioctl(struct inode *inode, struct file *file, ...@@ -398,15 +386,15 @@ static int pd_ioctl(struct inode *inode, struct file *file,
if (err) if (err)
return err; return err;
if (PD.alt_geom) { if (disk->alt_geom) {
put_user(PD.capacity / (PD_LOG_HEADS * PD_LOG_SECTS), put_user(disk->capacity / (PD_LOG_HEADS * PD_LOG_SECTS),
(short *) &geo->cylinders); (short *) &geo->cylinders);
put_user(PD_LOG_HEADS, (char *) &geo->heads); put_user(PD_LOG_HEADS, (char *) &geo->heads);
put_user(PD_LOG_SECTS, (char *) &geo->sectors); put_user(PD_LOG_SECTS, (char *) &geo->sectors);
} else { } else {
put_user(PD.cylinders, (short *) &geo->cylinders); put_user(disk->cylinders, (short *) &geo->cylinders);
put_user(PD.heads, (char *) &geo->heads); put_user(disk->heads, (char *) &geo->heads);
put_user(PD.sectors, (char *) &geo->sectors); put_user(disk->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; return 0;
...@@ -418,9 +406,10 @@ static int pd_ioctl(struct inode *inode, struct file *file, ...@@ -418,9 +406,10 @@ static int pd_ioctl(struct inode *inode, struct file *file,
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);
struct pd_unit *disk = pd + unit;
if (!--PD.access && PD.removable) if (!--disk->access && disk->removable)
pd_doorlock(unit, IDE_DOORUNLOCK); pd_doorlock(disk, IDE_DOORUNLOCK);
return 0; return 0;
} }
...@@ -428,107 +417,129 @@ static int pd_release(struct inode *inode, struct file *file) ...@@ -428,107 +417,129 @@ static int pd_release(struct inode *inode, struct file *file)
static int pd_check_media(kdev_t dev) static int pd_check_media(kdev_t dev)
{ {
int r, unit = DEVICE_NR(dev); int r, unit = DEVICE_NR(dev);
if ((unit >= PD_UNITS) || (!PD.present)) struct pd_unit *disk = pd + unit;
if (unit >= PD_UNITS || (!disk->present))
return -ENODEV; return -ENODEV;
if (!PD.removable) if (!disk->removable)
return 0; return 0;
pd_media_check(unit); pd_media_check(disk);
r = PD.changed; r = disk->changed;
PD.changed = 0; disk->changed = 0;
return r; return r;
} }
static int pd_revalidate(kdev_t dev) static int pd_revalidate(kdev_t dev)
{ {
int unit = DEVICE_NR(dev); int unit = DEVICE_NR(dev);
if ((unit >= PD_UNITS) || !PD.present) struct pd_unit *disk = pd + unit;
if (unit >= PD_UNITS || !disk->present)
return -ENODEV; return -ENODEV;
if (pd_identify(unit)) if (pd_identify(disk))
set_capacity(&PD.gd, PD.capacity); set_capacity(&disk->gd, disk->capacity);
else else
set_capacity(&PD.gd, 0); set_capacity(&disk->gd, 0);
return 0; return 0;
} }
#define WR(c,r,v) pi_write_regr(PI,c,r,v) static inline int status_reg(struct pd_unit *disk)
#define RR(c,r) (pi_read_regr(PI,c,r)) {
return pi_read_regr(disk->pi, 1, 6);
}
static inline int read_reg(struct pd_unit *disk, int reg)
{
return pi_read_regr(disk->pi, 0, reg);
}
static inline void write_status(struct pd_unit *disk, int val)
{
pi_write_regr(disk->pi, 1, 6, val);
}
static inline void write_reg(struct pd_unit *disk, int reg, int val)
{
pi_write_regr(disk->pi, 0, reg, val);
}
#define DRIVE (0xa0+0x10*PD.drive) static inline u8 DRIVE(struct pd_unit *disk)
{
return 0xa0+0x10*disk->drive;
}
/* ide command interface */ /* ide command interface */
static void pd_print_error(int unit, char *msg, int status) static void pd_print_error(struct pd_unit *disk, char *msg, int status)
{ {
int i; int i;
printk("%s: %s: status = 0x%x =", PD.name, msg, status); printk("%s: %s: status = 0x%x =", disk->name, msg, status);
for (i = 0; i < 18; i++) for (i = 0; i < 18; i++)
if (status & (1 << i)) if (status & (1 << i))
printk(" %s", pd_errs[i]); printk(" %s", pd_errs[i]);
printk("\n"); printk("\n");
} }
static void pd_reset(int unit) static void pd_reset(struct pd_unit *disk)
{ /* called only for MASTER drive */ { /* called only for MASTER drive */
pi_connect(PI); pi_connect(disk->pi);
WR(1, 6, 4); write_status(disk, 4);
udelay(50); udelay(50);
WR(1, 6, 0); write_status(disk, 0);
pi_disconnect(PI); pi_disconnect(disk->pi);
udelay(250); udelay(250);
} }
#define DBMSG(msg) ((verbose>1)?(msg):NULL) #define DBMSG(msg) ((verbose>1)?(msg):NULL)
static int pd_wait_for(int unit, int w, char *msg) static int pd_wait_for(struct pd_unit *disk, int w, char *msg)
{ /* polled wait */ { /* polled wait */
int k, r, e; int k, r, e;
k = 0; k = 0;
while (k < PD_SPIN) { while (k < PD_SPIN) {
r = RR(1, 6); r = status_reg(disk);
k++; k++;
if (((r & w) == w) && !(r & STAT_BUSY)) if (((r & w) == w) && !(r & STAT_BUSY))
break; break;
udelay(PD_SPIN_DEL); udelay(PD_SPIN_DEL);
} }
e = (RR(0, 1) << 8) + RR(0, 7); e = (read_reg(disk, 1) << 8) + read_reg(disk, 7);
if (k >= PD_SPIN) if (k >= PD_SPIN)
e |= ERR_TMO; e |= ERR_TMO;
if ((e & (STAT_ERR | ERR_TMO)) && (msg != NULL)) if ((e & (STAT_ERR | ERR_TMO)) && (msg != NULL))
pd_print_error(unit, msg, e); pd_print_error(disk, msg, e);
return 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(struct pd_unit *disk, int n, int s, int h, int c0, int c1, int func)
{ {
WR(0, 6, DRIVE + h); write_reg(disk, 6, DRIVE(disk) + h);
WR(0, 1, 0); /* the IDE task file */ write_reg(disk, 1, 0); /* the IDE task file */
WR(0, 2, n); write_reg(disk, 2, n);
WR(0, 3, s); write_reg(disk, 3, s);
WR(0, 4, c0); write_reg(disk, 4, c0);
WR(0, 5, c1); write_reg(disk, 5, c1);
WR(0, 7, func); write_reg(disk, 7, func);
udelay(1); udelay(1);
} }
static void pd_ide_command(int unit, int func, int block, int count) static void pd_ide_command(struct pd_unit *disk, int func, int block, int count)
{ {
int c1, c0, h, s; int c1, c0, h, s;
if (PD.can_lba) { if (disk->can_lba) {
s = block & 255; s = block & 255;
c0 = (block >>= 8) & 255; c0 = (block >>= 8) & 255;
c1 = (block >>= 8) & 255; c1 = (block >>= 8) & 255;
h = ((block >>= 8) & 15) + 0x40; h = ((block >>= 8) & 15) + 0x40;
} else { } else {
s = (block % PD.sectors) + 1; s = (block % disk->sectors) + 1;
h = (block /= PD.sectors) % PD.heads; h = (block /= disk->sectors) % disk->heads;
c0 = (block /= PD.heads) % 256; c0 = (block /= disk->heads) % 256;
c1 = (block >>= 8); c1 = (block >>= 8);
} }
pd_send_command(unit, count, s, h, c0, c1, func); pd_send_command(disk, count, s, h, c0, c1, func);
} }
/* According to the ATA standard, the default CHS geometry should be /* According to the ATA standard, the default CHS geometry should be
...@@ -537,75 +548,71 @@ static void pd_ide_command(int unit, int func, int block, int count) ...@@ -537,75 +548,71 @@ static void pd_ide_command(int unit, int func, int block, int count)
parameters are initialised. parameters are initialised.
*/ */
static void pd_init_dev_parms(int unit) static void pd_init_dev_parms(struct pd_unit *disk)
{ {
pi_connect(PI); pi_connect(disk->pi);
pd_wait_for(unit, 0, DBMSG("before init_dev_parms")); pd_wait_for(disk, 0, DBMSG("before init_dev_parms"));
pd_send_command(unit, PD.sectors, 0, PD.heads - 1, 0, 0, pd_send_command(disk, disk->sectors, 0, disk->heads - 1, 0, 0,
IDE_INIT_DEV_PARMS); IDE_INIT_DEV_PARMS);
udelay(300); udelay(300);
pd_wait_for(unit, 0, "Initialise device parameters"); pd_wait_for(disk, 0, "Initialise device parameters");
pi_disconnect(PI); pi_disconnect(disk->pi);
} }
static void pd_doorlock(int unit, int func) static void pd_doorlock(struct pd_unit *disk, int func)
{ {
pi_connect(PI); pi_connect(disk->pi);
if (pd_wait_for(unit, STAT_READY, "Lock") & STAT_ERR) { if (!(pd_wait_for(disk, STAT_READY, "Lock") & STAT_ERR)) {
pi_disconnect(PI); pd_send_command(disk, 1, 0, 0, 0, 0, func);
return; pd_wait_for(disk, STAT_READY, "Lock done");
} }
pd_send_command(unit, 1, 0, 0, 0, 0, func); pi_disconnect(disk->pi);
pd_wait_for(unit, STAT_READY, "Lock done");
pi_disconnect(PI);
} }
static void pd_eject(int unit) static void pd_eject(struct pd_unit *disk)
{ {
pi_connect(PI); pi_connect(disk->pi);
pd_wait_for(unit, 0, DBMSG("before unlock on eject")); pd_wait_for(disk, 0, DBMSG("before unlock on eject"));
pd_send_command(unit, 1, 0, 0, 0, 0, IDE_DOORUNLOCK); pd_send_command(disk, 1, 0, 0, 0, 0, IDE_DOORUNLOCK);
pd_wait_for(unit, 0, DBMSG("after unlock on eject")); pd_wait_for(disk, 0, DBMSG("after unlock on eject"));
pd_wait_for(unit, 0, DBMSG("before eject")); pd_wait_for(disk, 0, DBMSG("before eject"));
pd_send_command(unit, 0, 0, 0, 0, 0, IDE_EJECT); pd_send_command(disk, 0, 0, 0, 0, 0, IDE_EJECT);
pd_wait_for(unit, 0, DBMSG("after eject")); pd_wait_for(disk, 0, DBMSG("after eject"));
pi_disconnect(PI); pi_disconnect(disk->pi);
} }
static void pd_media_check(int unit) static void pd_media_check(struct pd_unit *disk)
{ {
int r; int r;
pi_connect(PI); pi_connect(disk->pi);
r = pd_wait_for(unit, STAT_READY, DBMSG("before media_check")); r = pd_wait_for(disk, STAT_READY, DBMSG("before media_check"));
if (!(r & STAT_ERR)) { if (!(r & STAT_ERR)) {
pd_send_command(unit, 1, 1, 0, 0, 0, IDE_READ_VRFY); pd_send_command(disk, 1, 1, 0, 0, 0, IDE_READ_VRFY);
r = pd_wait_for(unit, STAT_READY, DBMSG("RDY after READ_VRFY")); r = pd_wait_for(disk, STAT_READY, DBMSG("RDY after READ_VRFY"));
} else } else
PD.changed = 1; /* say changed if other error */ disk->changed = 1; /* say changed if other error */
if (r & ERR_MC) { if (r & ERR_MC) {
PD.changed = 1; disk->changed = 1;
pd_send_command(unit, 1, 0, 0, 0, 0, IDE_ACKCHANGE); pd_send_command(disk, 1, 0, 0, 0, 0, IDE_ACKCHANGE);
pd_wait_for(unit, STAT_READY, DBMSG("RDY after ACKCHANGE")); pd_wait_for(disk, STAT_READY, DBMSG("RDY after ACKCHANGE"));
pd_send_command(unit, 1, 1, 0, 0, 0, IDE_READ_VRFY); pd_send_command(disk, 1, 1, 0, 0, 0, IDE_READ_VRFY);
r = pd_wait_for(unit, STAT_READY, DBMSG("RDY after VRFY")); r = pd_wait_for(disk, STAT_READY, DBMSG("RDY after VRFY"));
} }
pi_disconnect(PI); pi_disconnect(disk->pi);
} }
static void pd_standby_off(int unit) static void pd_standby_off(struct pd_unit *disk)
{ {
pi_connect(PI); pi_connect(disk->pi);
pd_wait_for(unit, 0, DBMSG("before STANDBY")); pd_wait_for(disk, 0, DBMSG("before STANDBY"));
pd_send_command(unit, 0, 0, 0, 0, 0, IDE_STANDBY); pd_send_command(disk, 0, 0, 0, 0, 0, IDE_STANDBY);
pd_wait_for(unit, 0, DBMSG("after STANDBY")); pd_wait_for(disk, 0, DBMSG("after STANDBY"));
pi_disconnect(PI); pi_disconnect(disk->pi);
} }
#define word_val(n) ((pd_scratch[2*n]&0xff)+256*(pd_scratch[2*n+1]&0xff)) static int pd_identify(struct pd_unit *disk)
static int pd_identify(int unit)
{ {
int j; int j;
char id[PD_ID_LEN + 1]; char id[PD_ID_LEN + 1];
...@@ -616,28 +623,28 @@ static int pd_identify(int unit) ...@@ -616,28 +623,28 @@ static int pd_identify(int unit)
settings on the SLAVE drive. settings on the SLAVE drive.
*/ */
if (PD.drive == 0) if (disk->drive == 0)
pd_reset(unit); pd_reset(disk);
pi_connect(PI); pi_connect(disk->pi);
WR(0, 6, DRIVE); write_reg(disk, 6, DRIVE(disk));
pd_wait_for(unit, 0, DBMSG("before IDENT")); pd_wait_for(disk, 0, DBMSG("before IDENT"));
pd_send_command(unit, 1, 0, 0, 0, 0, IDE_IDENTIFY); pd_send_command(disk, 1, 0, 0, 0, 0, IDE_IDENTIFY);
if (pd_wait_for(unit, STAT_DRQ, DBMSG("IDENT DRQ")) & STAT_ERR) { if (pd_wait_for(disk, STAT_DRQ, DBMSG("IDENT DRQ")) & STAT_ERR) {
pi_disconnect(PI); pi_disconnect(disk->pi);
return 0; return 0;
} }
pi_read_block(PI, pd_scratch, 512); pi_read_block(disk->pi, pd_scratch, 512);
pi_disconnect(PI); pi_disconnect(disk->pi);
PD.can_lba = pd_scratch[99] & 2; disk->can_lba = pd_scratch[99] & 2;
PD.sectors = le16_to_cpu(*(u16 *) (pd_scratch + 12)); disk->sectors = le16_to_cpu(*(u16 *) (pd_scratch + 12));
PD.heads = le16_to_cpu(*(u16 *) (pd_scratch + 6)); disk->heads = le16_to_cpu(*(u16 *) (pd_scratch + 6));
PD.cylinders = le16_to_cpu(*(u16 *) (pd_scratch + 2)); disk->cylinders = le16_to_cpu(*(u16 *) (pd_scratch + 2));
if (PD.can_lba) if (disk->can_lba)
PD.capacity = le32_to_cpu(*(u32 *) (pd_scratch + 120)); disk->capacity = le32_to_cpu(*(u32 *) (pd_scratch + 120));
else else
PD.capacity = PD.sectors * PD.heads * PD.cylinders; disk->capacity = disk->sectors * disk->heads * disk->cylinders;
for (j = 0; j < PD_ID_LEN; j++) for (j = 0; j < PD_ID_LEN; j++)
id[j ^ 1] = pd_scratch[j + PD_ID_OFF]; id[j ^ 1] = pd_scratch[j + PD_ID_OFF];
...@@ -647,72 +654,76 @@ static int pd_identify(int unit) ...@@ -647,72 +654,76 @@ static int pd_identify(int unit)
j++; j++;
id[j] = 0; id[j] = 0;
PD.removable = (word_val(0) & 0x80); disk->removable = pd_scratch[0] & 0x80;
printk("%s: %s, %s, %d blocks [%dM], (%d/%d/%d), %s media\n", printk("%s: %s, %s, %d blocks [%dM], (%d/%d/%d), %s media\n",
PD.name, id, disk->name, id,
PD.drive ? "slave" : "master", disk->drive ? "slave" : "master",
PD.capacity, PD.capacity / 2048, disk->capacity, disk->capacity / 2048,
PD.cylinders, PD.heads, PD.sectors, disk->cylinders, disk->heads, disk->sectors,
PD.removable ? "removable" : "fixed"); disk->removable ? "removable" : "fixed");
if (PD.capacity) if (disk->capacity)
pd_init_dev_parms(unit); pd_init_dev_parms(disk);
if (!PD.standby) if (!disk->standby)
pd_standby_off(unit); pd_standby_off(disk);
return 1; return 1;
} }
static int pd_probe_drive(int unit) static int pd_probe_drive(struct pd_unit *disk)
{ {
if (PD.drive == -1) { if (disk->drive == -1) {
for (PD.drive = 0; PD.drive <= 1; PD.drive++) for (disk->drive = 0; disk->drive <= 1; disk->drive++)
if (pd_identify(unit)) if (pd_identify(disk))
return 1; return 1;
return 0; return 0;
} }
return pd_identify(unit); return pd_identify(disk);
} }
static int pd_detect(void) static int pd_detect(void)
{ {
int k, unit; int k, unit;
struct pd_unit *disk;
k = 0; k = 0;
if (pd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ if (pd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
unit = 0; disk = pd;
if (pi_init(PI, 1, -1, -1, -1, -1, -1, pd_scratch, if (pi_init(disk->pi, 1, -1, -1, -1, -1, -1, pd_scratch,
PI_PD, verbose, PD.name)) { PI_PD, verbose, disk->name)) {
if (pd_probe_drive(unit)) { if (pd_probe_drive(disk)) {
PD.present = 1; disk->present = 1;
k = 1; k = 1;
} else } else
pi_release(PI); pi_release(disk->pi);
} }
} else } else {
for (unit = 0; unit < PD_UNITS; unit++) for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) {
if (DU[D_PRT]) int *parm = *drives[unit];
if (pi_init if (!parm[D_PRT])
(PI, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI], continue;
DU[D_PRO], DU[D_DLY], pd_scratch, PI_PD, if (pi_init(disk->pi, 0, parm[D_PRT], parm[D_MOD],
verbose, PD.name)) { parm[D_UNI], parm[D_PRO], parm[D_DLY],
if (pd_probe_drive(unit)) { pd_scratch, PI_PD, verbose, disk->name)) {
PD.present = 1; if (pd_probe_drive(disk)) {
k = unit + 1; disk->present = 1;
} else k = unit + 1;
pi_release(PI); } else
} pi_release(disk->pi);
for (unit = 0; unit < PD_UNITS; unit++) { }
if (PD.present) { }
PD.gd.major_name = PD.name; }
PD.gd.minor_shift = PD_BITS; for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) {
PD.gd.fops = &pd_fops; if (disk->present) {
PD.gd.major = major; disk->gd.major_name = disk->name;
PD.gd.first_minor = unit << PD_BITS; disk->gd.minor_shift = PD_BITS;
set_capacity(&PD.gd, PD.capacity); disk->gd.fops = &pd_fops;
add_disk(&PD.gd); disk->gd.major = major;
disk->gd.first_minor = unit << PD_BITS;
set_capacity(&disk->gd, disk->capacity);
add_disk(&disk->gd);
} }
} }
if (k) if (k)
...@@ -725,9 +736,7 @@ static int pd_detect(void) ...@@ -725,9 +736,7 @@ static int pd_detect(void)
static int pd_ready(void) static int pd_ready(void)
{ {
int unit = pd_unit; return !(status_reg(pd_current) & 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)
...@@ -740,55 +749,66 @@ static void do_pd_request(request_queue_t * q) ...@@ -740,55 +749,66 @@ static void do_pd_request(request_queue_t * q)
if (blk_queue_empty(QUEUE)) if (blk_queue_empty(QUEUE))
return; return;
pd_dev = minor(CURRENT->rq_dev); pd_req = elv_next_request(QUEUE);
pd_unit = unit = DEVICE_NR(CURRENT->rq_dev); unit = DEVICE_NR(pd_req->rq_dev);
pd_block = CURRENT->sector; if (unit >= PD_UNITS) {
pd_run = CURRENT->nr_sectors; end_request(pd_req, 0);
pd_count = CURRENT->current_nr_sectors; goto repeat;
}
if ((pd_dev >= PD_DEVS) || pd_block = pd_req->sector;
((pd_block + pd_count) > get_capacity(&pd[unit].gd))) { pd_run = pd_req->nr_sectors;
end_request(CURRENT, 0); pd_count = pd_req->current_nr_sectors;
pd_current = pd + unit;
if (pd_block + pd_count > get_capacity(&pd_current->gd)) {
end_request(pd_req, 0);
goto repeat; goto repeat;
} }
pd_cmd = rq_data_dir(CURRENT); pd_cmd = rq_data_dir(pd_req);
pd_buf = CURRENT->buffer; pd_buf = pd_req->buffer;
pd_retries = 0; pd_retries = 0;
pd_busy = 1; pd_busy = 1;
if (pd_cmd == READ) if (pd_cmd == READ)
pi_do_claimed(PI, do_pd_read); pi_do_claimed(pd_current->pi, do_pd_read);
else if (pd_cmd == WRITE) else if (pd_cmd == WRITE)
pi_do_claimed(PI, do_pd_write); pi_do_claimed(pd_current->pi, do_pd_write);
else { else {
pd_busy = 0; pd_busy = 0;
end_request(CURRENT, 0); end_request(pd_req, 0);
goto repeat; goto repeat;
} }
} }
static void pd_next_buf(int unit) static int pd_next_buf(void)
{ {
long saved_flags; long saved_flags;
pd_count--;
pd_run--;
pd_buf += 512;
pd_block++;
if (!pd_run)
return 1;
if (pd_count)
return 0;
spin_lock_irqsave(&pd_lock, saved_flags); spin_lock_irqsave(&pd_lock, saved_flags);
end_request(CURRENT, 1); end_request(pd_req, 1);
if (!pd_run) { pd_count = pd_req->current_nr_sectors;
spin_unlock_irqrestore(&pd_lock, saved_flags); pd_buf = pd_req->buffer;
return; spin_unlock_irqrestore(&pd_lock, saved_flags);
} return 0;
}
/* paranoia */
if (blk_queue_empty(QUEUE) || static inline void next_request(int success)
(rq_data_dir(CURRENT) != pd_cmd) || {
(minor(CURRENT->rq_dev) != pd_dev) || (CURRENT->sector != pd_block)) long saved_flags;
printk("%s: OUCH: request list changed unexpectedly\n",
PD.name);
pd_count = CURRENT->current_nr_sectors; spin_lock_irqsave(&pd_lock, saved_flags);
pd_buf = CURRENT->buffer; end_request(pd_req, success);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags); spin_unlock_irqrestore(&pd_lock, saved_flags);
} }
...@@ -799,66 +819,42 @@ static void do_pd_read(void) ...@@ -799,66 +819,42 @@ static void do_pd_read(void)
static void do_pd_read_start(void) static void do_pd_read_start(void)
{ {
int unit = pd_unit;
long saved_flags;
pd_busy = 1; pd_busy = 1;
pi_connect(PI); pi_connect(pd_current->pi);
if (pd_wait_for(unit, STAT_READY, "do_pd_read") & STAT_ERR) { if (pd_wait_for(pd_current, STAT_READY, "do_pd_read") & STAT_ERR) {
pi_disconnect(PI); pi_disconnect(pd_current->pi);
if (pd_retries < PD_MAX_RETRIES) { if (pd_retries < PD_MAX_RETRIES) {
pd_retries++; pd_retries++;
pi_do_claimed(PI, do_pd_read_start); pi_do_claimed(pd_current->pi, do_pd_read_start);
return; return;
} }
spin_lock_irqsave(&pd_lock, saved_flags); next_request(0);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags);
return; return;
} }
pd_ide_command(unit, IDE_READ, pd_block, pd_run); pd_ide_command(pd_current, IDE_READ, pd_block, pd_run);
ps_set_intr(do_pd_read_drq, pd_ready, PD_TMO, nice); ps_set_intr(do_pd_read_drq, pd_ready, PD_TMO, nice);
} }
static void do_pd_read_drq(void) static void do_pd_read_drq(void)
{ {
int unit = pd_unit;
long saved_flags;
while (1) { while (1) {
if (pd_wait_for(unit, STAT_DRQ, "do_pd_read_drq") & STAT_ERR) { if (pd_wait_for(pd_current, STAT_DRQ, "do_pd_read_drq") & STAT_ERR) {
pi_disconnect(PI); pi_disconnect(pd_current->pi);
if (pd_retries < PD_MAX_RETRIES) { if (pd_retries < PD_MAX_RETRIES) {
pd_retries++; pd_retries++;
pi_do_claimed(PI, do_pd_read_start); pi_do_claimed(pd_current->pi, do_pd_read_start);
return; return;
} }
spin_lock_irqsave(&pd_lock, saved_flags); next_request(0);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags);
return; return;
} }
pi_read_block(PI, pd_buf, 512); pi_read_block(pd_current->pi, pd_buf, 512);
pd_count--; if (pd_next_buf())
pd_run--;
pd_buf += 512;
pd_block++;
if (!pd_run)
break; break;
if (!pd_count)
pd_next_buf(unit);
} }
pi_disconnect(PI); pi_disconnect(pd_current->pi);
spin_lock_irqsave(&pd_lock, saved_flags); next_request(1);
end_request(CURRENT, 1);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags);
} }
static void do_pd_write(void) static void do_pd_write(void)
...@@ -868,80 +864,52 @@ static void do_pd_write(void) ...@@ -868,80 +864,52 @@ static void do_pd_write(void)
static void do_pd_write_start(void) static void do_pd_write_start(void)
{ {
int unit = pd_unit;
long saved_flags;
pd_busy = 1; pd_busy = 1;
pi_connect(PI); pi_connect(pd_current->pi);
if (pd_wait_for(unit, STAT_READY, "do_pd_write") & STAT_ERR) { if (pd_wait_for(pd_current, STAT_READY, "do_pd_write") & STAT_ERR) {
pi_disconnect(PI); pi_disconnect(pd_current->pi);
if (pd_retries < PD_MAX_RETRIES) { if (pd_retries < PD_MAX_RETRIES) {
pd_retries++; pd_retries++;
pi_do_claimed(PI, do_pd_write_start); pi_do_claimed(pd_current->pi, do_pd_write_start);
return; return;
} }
spin_lock_irqsave(&pd_lock, saved_flags); next_request(0);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags);
return; return;
} }
pd_ide_command(unit, IDE_WRITE, pd_block, pd_run); pd_ide_command(pd_current, IDE_WRITE, pd_block, pd_run);
while (1) { while (1) {
if (pd_wait_for(unit, STAT_DRQ, "do_pd_write_drq") & STAT_ERR) { if (pd_wait_for(pd_current, STAT_DRQ, "do_pd_write_drq") & STAT_ERR) {
pi_disconnect(PI); pi_disconnect(pd_current->pi);
if (pd_retries < PD_MAX_RETRIES) { if (pd_retries < PD_MAX_RETRIES) {
pd_retries++; pd_retries++;
pi_do_claimed(PI, do_pd_write_start); pi_do_claimed(pd_current->pi, do_pd_write_start);
return; return;
} }
spin_lock_irqsave(&pd_lock, saved_flags); next_request(0);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags);
return; return;
} }
pi_write_block(PI, pd_buf, 512); pi_write_block(pd_current->pi, pd_buf, 512);
pd_count--; if (pd_next_buf())
pd_run--;
pd_buf += 512;
pd_block++;
if (!pd_run)
break; break;
if (!pd_count)
pd_next_buf(unit);
} }
ps_set_intr(do_pd_write_done, pd_ready, PD_TMO, nice); ps_set_intr(do_pd_write_done, pd_ready, PD_TMO, nice);
} }
static void do_pd_write_done(void) static void do_pd_write_done(void)
{ {
int unit = pd_unit; if (pd_wait_for(pd_current, STAT_READY, "do_pd_write_done") & STAT_ERR) {
long saved_flags; pi_disconnect(pd_current->pi);
if (pd_wait_for(unit, STAT_READY, "do_pd_write_done") & STAT_ERR) {
pi_disconnect(PI);
if (pd_retries < PD_MAX_RETRIES) { if (pd_retries < PD_MAX_RETRIES) {
pd_retries++; pd_retries++;
pi_do_claimed(PI, do_pd_write_start); pi_do_claimed(pd_current->pi, do_pd_write_start);
return; return;
} }
spin_lock_irqsave(&pd_lock, saved_flags); next_request(0);
end_request(CURRENT, 0);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags);
return; return;
} }
pi_disconnect(PI); pi_disconnect(pd_current->pi);
spin_lock_irqsave(&pd_lock, saved_flags); next_request(1);
end_request(CURRENT, 1);
pd_busy = 0;
do_pd_request(NULL);
spin_unlock_irqrestore(&pd_lock, saved_flags);
} }
static int __init pd_init(void) static int __init pd_init(void)
...@@ -969,13 +937,15 @@ static int __init pd_init(void) ...@@ -969,13 +937,15 @@ static int __init pd_init(void)
static void __exit pd_exit(void) static void __exit pd_exit(void)
{ {
struct pd_unit *disk;
int unit; int unit;
unregister_blkdev(MAJOR_NR, name); unregister_blkdev(MAJOR_NR, name);
for (unit = 0; unit < PD_UNITS; unit++) for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) {
if (PD.present) { if (disk->present) {
del_gendisk(&PD.gd); del_gendisk(&disk->gd);
pi_release(PI); pi_release(disk->pi);
} }
}
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
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