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