Commit 470d15bb authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.14 IDE 56

 - Push poll_timeout down from the hwgroup to the channel. We are resetting the
   channel and not a whole hwgroup. This way using multiple pdc202xxx cards
   should magically start to work with multiple performance and resets will no
   longer lock the system.

 - Updates for PDC4030 by Peter Denison <peterd@marshadder.uklinux.net>.

 - Make ide_raw_taskfile don't care about request buffers. They where always
   NULL.

 - Port set multi mode count over from the special setting interface to
   ide_raw_taskfile. Fix errors in the corresponding interrupt handler in one go
   as well. It turned out that this is precisely the same code as in
   task_no_data_intr, so we can nuke it altogether. And finally we have found
   some problems with the set_pio_mode() command which can fail with -EBUSY -
   this is in esp. probably *very* common during boot hdparm usage those days!
   (OK it was masked by reportig too early that it finished...  Crap Crap utter
   crap it was!!!) Right now hdparm should just be extendid to properly
   sync and retry on   -EBUSY and everything should be fine.

   And now the 1 Milion EUR question for everybody who loves to put driver
   settings in to /proc:

   How the hell could echo > /proc/ide/ide0/settings blah blah blah blah handle
   properly cases like -EIO, -EBUSY and so on??? Having the possibility o do it
   does not mean that it is a good idea to use it.

   OK. After realizing the simple fact that quite a lot of low level hardware
   manipulating ioctls may require assistance in usage from proper logic which is
   *very* unlikely to be implemented in a bash (for me preferable still ksh) I
   have made my mind up.

	/proc/ide will be nuked.

 - Execute the recalibration for error recovery on precisely the same request as
   the one which failed.

 - Remove set geometry.  It's crap by means of standard specification. Because:

   1. We rely on the existence of the identify command anyway.

   2. This command was obsoleted *before* the identify command existed as far
   as I can see.

   2. I'm able to have a look at what other ATA/ATAPI drivers in the wild do:
   They don't do it.

 - Just call tuneproc in set_pio_mode() directly - we are already behind the rq
   queue there.

 - After we have uncovered the broken logics behind the whole ioctl handling we
   now just have made ide_spin_wait_hwgroup() waiting for a proper somehow
   longer timeout before giving up. This was previously just hiding the broken
   concept of setting ioctl values through /proc/ide/ideX/settings - now it just
   really helps hdparm to not to give up too early. (It shouldn't probably play
   wreck havock on the global driver spin lock as well. I will look in to this
   later.)

 - Scrap the non necessary, to say the least, disabling of interrupts for 3,
   read it again please, 3 seconds, on the local CPU inside
   ide_spin_wait_hwgroup().  Spin lock handling needs checking there badly as I
   see now as well...

Hey apparently any "special" requests are gone. We now have only
to deal with REQ_DEVICE_ACB and REQ_DEVICE_CMD. One of them is still too
much and will be killed.
parent 537ad07f
...@@ -34,9 +34,9 @@ ...@@ -34,9 +34,9 @@
#include <asm/io.h> #include <asm/io.h>
#ifdef CONFIG_BLK_DEV_PDC4030 #ifdef CONFIG_BLK_DEV_PDC4030
#define IS_PDC4030_DRIVE (drive->channel->chipset == ide_pdc4030) # define IS_PDC4030_DRIVE (drive->channel->chipset == ide_pdc4030)
#else #else
#define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ # define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */
#endif #endif
/* /*
...@@ -304,9 +304,9 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque ...@@ -304,9 +304,9 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
} }
if (IS_PDC4030_DRIVE) { if (IS_PDC4030_DRIVE) {
extern ide_startstop_t promise_rw_disk(struct ata_device *, struct request *, unsigned long); extern ide_startstop_t promise_do_request(struct ata_device *, struct request *, sector_t);
return promise_rw_disk(drive, rq, block); return promise_do_request(drive, rq, block);
} }
/* /*
...@@ -364,7 +364,7 @@ static int idedisk_open (struct inode *inode, struct file *filp, struct ata_devi ...@@ -364,7 +364,7 @@ static int idedisk_open (struct inode *inode, struct file *filp, struct ata_devi
* point. * point.
*/ */
if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) if (drive->doorlocking && ide_raw_taskfile(drive, &args))
drive->doorlocking = 0; drive->doorlocking = 0;
} }
return 0; return 0;
...@@ -383,10 +383,10 @@ static int idedisk_flushcache(struct ata_device *drive) ...@@ -383,10 +383,10 @@ static int idedisk_flushcache(struct ata_device *drive)
ide_cmd_type_parser(&args); ide_cmd_type_parser(&args);
return ide_raw_taskfile(drive, &args, NULL); return ide_raw_taskfile(drive, &args);
} }
static void idedisk_release (struct inode *inode, struct file *filp, struct ata_device *drive) static void idedisk_release(struct inode *inode, struct file *filp, struct ata_device *drive)
{ {
if (drive->removable && !drive->usage) { if (drive->removable && !drive->usage) {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -398,7 +398,7 @@ static void idedisk_release (struct inode *inode, struct file *filp, struct ata_ ...@@ -398,7 +398,7 @@ static void idedisk_release (struct inode *inode, struct file *filp, struct ata_
ide_cmd_type_parser(&args); ide_cmd_type_parser(&args);
if (drive->doorlocking && if (drive->doorlocking &&
ide_raw_taskfile(drive, &args, NULL)) ide_raw_taskfile(drive, &args))
drive->doorlocking = 0; drive->doorlocking = 0;
} }
if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
...@@ -419,75 +419,6 @@ static sector_t idedisk_capacity(struct ata_device *drive) ...@@ -419,75 +419,6 @@ static sector_t idedisk_capacity(struct ata_device *drive)
return drive->capacity - drive->sect0; return drive->capacity - drive->sect0;
} }
static ide_startstop_t idedisk_special(struct ata_device *drive)
{
unsigned char special_cmd = drive->special_cmd;
if (special_cmd & ATA_SPECIAL_GEOMETRY) {
struct ata_taskfile args;
drive->special_cmd &= ~ATA_SPECIAL_GEOMETRY;
memset(&args, 0, sizeof(args));
args.taskfile.sector_number = drive->sect;
args.taskfile.low_cylinder = drive->cyl;
args.taskfile.high_cylinder = drive->cyl>>8;
args.taskfile.device_head = ((drive->head-1)|drive->select.all)&0xBF;
if (!IS_PDC4030_DRIVE) {
args.taskfile.sector_count = drive->sect;
args.taskfile.command = WIN_SPECIFY;
args.handler = set_geometry_intr;;
}
ata_taskfile(drive, &args, NULL);
} else if (special_cmd & ATA_SPECIAL_RECALIBRATE) {
drive->special_cmd &= ~ATA_SPECIAL_RECALIBRATE;
if (!IS_PDC4030_DRIVE) {
struct ata_taskfile args;
memset(&args, 0, sizeof(args));
args.taskfile.sector_count = drive->sect;
args.taskfile.command = WIN_RESTORE;
args.handler = recal_intr;
ata_taskfile(drive, &args, NULL);
}
} else if (special_cmd & ATA_SPECIAL_MMODE) {
drive->special_cmd &= ~ATA_SPECIAL_MMODE;
if (drive->id && drive->mult_req > drive->id->max_multsect)
drive->mult_req = drive->id->max_multsect;
if (!IS_PDC4030_DRIVE) {
struct ata_taskfile args;
memset(&args, 0, sizeof(args));
args.taskfile.sector_count = drive->mult_req;
args.taskfile.command = WIN_SETMULT;
args.handler = set_multmode_intr;
ata_taskfile(drive, &args, NULL);
}
} else if (special_cmd) {
drive->special_cmd = 0;
printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special_cmd);
return ide_stopped;
}
return IS_PDC4030_DRIVE ? ide_stopped : ide_started;
}
static void idedisk_pre_reset(struct ata_device *drive)
{
int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
if (legacy)
drive->special_cmd = (ATA_SPECIAL_GEOMETRY | ATA_SPECIAL_RECALIBRATE);
else
drive->special_cmd = 0;
if (OK_TO_RESET_CONTROLLER)
drive->mult_count = 0;
if (drive->mult_req != drive->mult_count)
drive->special_cmd |= ATA_SPECIAL_MMODE;
}
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
#ifdef CONFIG_BLK_DEV_IDE_TCQ #ifdef CONFIG_BLK_DEV_IDE_TCQ
...@@ -556,28 +487,58 @@ static ide_proc_entry_t idedisk_proc[] = { ...@@ -556,28 +487,58 @@ static ide_proc_entry_t idedisk_proc[] = {
*/ */
static int set_multcount(struct ata_device *drive, int arg) static int set_multcount(struct ata_device *drive, int arg)
{ {
struct request rq; struct ata_taskfile args;
/* Setting multi mode count on this channel type is not supported/not
* handled.
*/
if (IS_PDC4030_DRIVE)
return -EIO;
/* Hugh, we still didn't detect the devices capabilities.
*/
if (!drive->id)
return -EIO;
if (drive->special_cmd & ATA_SPECIAL_MMODE) /* FIXME: Hmm... just bailing out my be problematic, since there *is*
* activity during boot. For now the same problem persists in
* set_pio_mode() we will have to do something about it soon.
*/
if (HWGROUP(drive)->handler)
return -EBUSY; return -EBUSY;
ide_init_drive_cmd(&rq); if (arg > drive->id->max_multsect)
arg = drive->id->max_multsect;
drive->mult_req = arg; memset(&args, 0, sizeof(args));
drive->special_cmd |= ATA_SPECIAL_MMODE; args.taskfile.sector_count = arg;
args.taskfile.command = WIN_SETMULT;
ide_cmd_type_parser(&args);
ide_do_drive_cmd(drive, &rq, ide_wait); if (!ide_raw_taskfile(drive, &args)) {
/* all went well track this setting as valid */
drive->mult_count = arg;
return (drive->mult_count == arg) ? 0 : -EIO; return 0;
} else
drive->mult_count = 0; /* reset */
return -EIO;
} }
static int set_nowerr(struct ata_device *drive, int arg) static int set_nowerr(struct ata_device *drive, int arg)
{ {
if (ide_spin_wait_hwgroup(drive)) if (HWGROUP(drive)->handler)
return -EBUSY; return -EBUSY;
drive->nowerr = arg; drive->nowerr = arg;
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
/* FIXME: I'm less then sure that we are under the global request lock here!
*/
#if 0
spin_unlock_irq(&ide_lock); spin_unlock_irq(&ide_lock);
#endif
return 0; return 0;
} }
...@@ -593,7 +554,7 @@ static int write_cache(struct ata_device *drive, int arg) ...@@ -593,7 +554,7 @@ static int write_cache(struct ata_device *drive, int arg)
args.taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; args.taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
args.taskfile.command = WIN_SETFEATURES; args.taskfile.command = WIN_SETFEATURES;
ide_cmd_type_parser(&args); ide_cmd_type_parser(&args);
ide_raw_taskfile(drive, &args, NULL); ide_raw_taskfile(drive, &args);
drive->wcache = arg; drive->wcache = arg;
...@@ -608,7 +569,7 @@ static int idedisk_standby(struct ata_device *drive) ...@@ -608,7 +569,7 @@ static int idedisk_standby(struct ata_device *drive)
args.taskfile.command = WIN_STANDBYNOW1; args.taskfile.command = WIN_STANDBYNOW1;
ide_cmd_type_parser(&args); ide_cmd_type_parser(&args);
return ide_raw_taskfile(drive, &args, NULL); return ide_raw_taskfile(drive, &args);
} }
static int set_acoustic(struct ata_device *drive, int arg) static int set_acoustic(struct ata_device *drive, int arg)
...@@ -620,7 +581,7 @@ static int set_acoustic(struct ata_device *drive, int arg) ...@@ -620,7 +581,7 @@ static int set_acoustic(struct ata_device *drive, int arg)
args.taskfile.sector_count = arg; args.taskfile.sector_count = arg;
args.taskfile.command = WIN_SETFEATURES; args.taskfile.command = WIN_SETFEATURES;
ide_cmd_type_parser(&args); ide_cmd_type_parser(&args);
ide_raw_taskfile(drive, &args, NULL); ide_raw_taskfile(drive, &args);
drive->acoustic = arg; drive->acoustic = arg;
...@@ -673,17 +634,11 @@ static void idedisk_add_settings(struct ata_device *drive) ...@@ -673,17 +634,11 @@ static void idedisk_add_settings(struct ata_device *drive)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL);
ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing);
ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount); ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount);
ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr);
ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL);
ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache);
ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic);
ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL);
ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL);
#ifdef CONFIG_BLK_DEV_IDE_TCQ #ifdef CONFIG_BLK_DEV_IDE_TCQ
ide_add_setting(drive, "using_tcq", SETTING_RW, HDIO_GET_QDMA, HDIO_SET_QDMA, TYPE_BYTE, 0, IDE_MAX_TAG, 1, 1, &drive->using_tcq, set_using_tcq); ide_add_setting(drive, "using_tcq", SETTING_RW, HDIO_GET_QDMA, HDIO_SET_QDMA, TYPE_BYTE, 0, IDE_MAX_TAG, 1, 1, &drive->using_tcq, set_using_tcq);
#endif #endif
...@@ -761,7 +716,7 @@ static unsigned long native_max_address(struct ata_device *drive) ...@@ -761,7 +716,7 @@ static unsigned long native_max_address(struct ata_device *drive)
args.handler = task_no_data_intr; args.handler = task_no_data_intr;
/* submit command request */ /* submit command request */
ide_raw_taskfile(drive, &args, NULL); ide_raw_taskfile(drive, &args);
/* if OK, compute maximum address value */ /* if OK, compute maximum address value */
if ((args.taskfile.command & 0x01) == 0) { if ((args.taskfile.command & 0x01) == 0) {
...@@ -789,7 +744,7 @@ static u64 native_max_address_ext(struct ata_device *drive) ...@@ -789,7 +744,7 @@ static u64 native_max_address_ext(struct ata_device *drive)
args.handler = task_no_data_intr; args.handler = task_no_data_intr;
/* submit command request */ /* submit command request */
ide_raw_taskfile(drive, &args, NULL); ide_raw_taskfile(drive, &args);
/* if OK, compute maximum address value */ /* if OK, compute maximum address value */
if ((args.taskfile.command & 0x01) == 0) { if ((args.taskfile.command & 0x01) == 0) {
...@@ -829,7 +784,7 @@ static sector_t set_max_address(struct ata_device *drive, sector_t addr_req) ...@@ -829,7 +784,7 @@ static sector_t set_max_address(struct ata_device *drive, sector_t addr_req)
args.taskfile.command = WIN_SET_MAX; args.taskfile.command = WIN_SET_MAX;
args.handler = task_no_data_intr; args.handler = task_no_data_intr;
/* submit command request */ /* submit command request */
ide_raw_taskfile(drive, &args, NULL); ide_raw_taskfile(drive, &args);
/* if OK, read new maximum address value */ /* if OK, read new maximum address value */
if ((args.taskfile.command & 0x01) == 0) { if ((args.taskfile.command & 0x01) == 0) {
addr_set = ((args.taskfile.device_head & 0x0f) << 24) addr_set = ((args.taskfile.device_head & 0x0f) << 24)
...@@ -865,7 +820,7 @@ static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req) ...@@ -865,7 +820,7 @@ static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req)
args.handler = task_no_data_intr; args.handler = task_no_data_intr;
/* submit command request */ /* submit command request */
ide_raw_taskfile(drive, &args, NULL); ide_raw_taskfile(drive, &args);
/* if OK, compute maximum address value */ /* if OK, compute maximum address value */
if ((args.taskfile.command & 0x01) == 0) { if ((args.taskfile.command & 0x01) == 0) {
u32 high = (args.hobfile.high_cylinder << 16) | u32 high = (args.hobfile.high_cylinder << 16) |
...@@ -1078,7 +1033,13 @@ static void idedisk_setup(struct ata_device *drive) ...@@ -1078,7 +1033,13 @@ static void idedisk_setup(struct ata_device *drive)
printk("\n"); printk("\n");
drive->mult_count = 0; drive->mult_count = 0;
#if 0
if (id->max_multsect) { if (id->max_multsect) {
/* FIXME: reenable this again after making it to use
* the same code path as the ioctl stuff.
*/
#ifdef CONFIG_IDEDISK_MULTI_MODE #ifdef CONFIG_IDEDISK_MULTI_MODE
id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0; id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
id->multsect_valid = id->multsect ? 1 : 0; id->multsect_valid = id->multsect ? 1 : 0;
...@@ -1094,6 +1055,7 @@ static void idedisk_setup(struct ata_device *drive) ...@@ -1094,6 +1055,7 @@ static void idedisk_setup(struct ata_device *drive)
drive->special_cmd |= ATA_SPECIAL_MMODE; drive->special_cmd |= ATA_SPECIAL_MMODE;
#endif #endif
} }
#endif
/* FIXME: Nowadays there are many chipsets out there which *require* 32 /* FIXME: Nowadays there are many chipsets out there which *require* 32
* bit IO. Those will most propably not work properly with drives not * bit IO. Those will most propably not work properly with drives not
...@@ -1136,9 +1098,7 @@ static struct ata_operations idedisk_driver = { ...@@ -1136,9 +1098,7 @@ static struct ata_operations idedisk_driver = {
release: idedisk_release, release: idedisk_release,
check_media_change: idedisk_check_media_change, check_media_change: idedisk_check_media_change,
revalidate: NULL, /* use default method */ revalidate: NULL, /* use default method */
pre_reset: idedisk_pre_reset,
capacity: idedisk_capacity, capacity: idedisk_capacity,
special: idedisk_special,
proc: idedisk_proc proc: idedisk_proc
}; };
......
...@@ -4272,16 +4272,6 @@ static void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_ ...@@ -4272,16 +4272,6 @@ static void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_
#endif #endif
} }
/*
* idetape_pre_reset is called before an ATAPI/ATA software reset.
*/
static void idetape_pre_reset (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
if (tape != NULL)
set_bit (IDETAPE_IGNORE_DSC, &tape->flags);
}
/* /*
* Character device interface functions * Character device interface functions
*/ */
...@@ -6164,8 +6154,6 @@ static struct ata_operations idetape_driver = { ...@@ -6164,8 +6154,6 @@ static struct ata_operations idetape_driver = {
release: idetape_blkdev_release, release: idetape_blkdev_release,
check_media_change: NULL, check_media_change: NULL,
revalidate: idetape_revalidate, revalidate: idetape_revalidate,
pre_reset: idetape_pre_reset,
capacity: NULL,
proc: idetape_proc proc: idetape_proc
}; };
......
...@@ -488,40 +488,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, ...@@ -488,40 +488,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
return ide_started; return ide_started;
} }
/*
* This is invoked on completion of a WIN_SETMULT cmd.
*/
ide_startstop_t set_multmode_intr(struct ata_device *drive, struct request *__rq)
{
u8 stat;
if (OK_STAT(stat = GET_STAT(),READY_STAT,BAD_STAT)) {
drive->mult_count = drive->mult_req;
} else {
drive->mult_req = drive->mult_count = 0;
drive->special_cmd |= ATA_SPECIAL_RECALIBRATE;
ide_dump_status(drive, "set_multmode", stat);
}
return ide_stopped;
}
/*
* This is invoked on completion of a WIN_SPECIFY cmd.
*/
ide_startstop_t set_geometry_intr(struct ata_device *drive, struct request *__rq)
{
u8 stat;
if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT))
return ide_stopped;
if (stat & (ERR_STAT|DRQ_STAT))
return ide_error(drive, "set_geometry_intr", stat);
ide_set_handler(drive, set_geometry_intr, WAIT_CMD, NULL);
return ide_started;
}
/* /*
* This is invoked on completion of a WIN_RESTORE (recalibrate) cmd. * This is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
*/ */
...@@ -729,11 +695,11 @@ void ide_cmd_type_parser(struct ata_taskfile *args) ...@@ -729,11 +695,11 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
args->command_type = IDE_DRIVE_TASK_IN; args->command_type = IDE_DRIVE_TASK_IN;
return; return;
case CFA_WRITE_SECT_WO_ERASE:
case WIN_WRITE: case WIN_WRITE:
case WIN_WRITE_EXT: case WIN_WRITE_EXT:
case WIN_WRITE_VERIFY: case WIN_WRITE_VERIFY:
case WIN_WRITE_BUFFER: case WIN_WRITE_BUFFER:
case CFA_WRITE_SECT_WO_ERASE:
case WIN_DOWNLOAD_MICROCODE: case WIN_DOWNLOAD_MICROCODE:
args->prehandler = pre_task_out_intr; args->prehandler = pre_task_out_intr;
args->handler = task_out_intr; args->handler = task_out_intr;
...@@ -832,7 +798,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args) ...@@ -832,7 +798,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
} }
case WIN_SPECIFY: case WIN_SPECIFY:
args->handler = set_geometry_intr; args->handler = task_no_data_intr;
args->command_type = IDE_DRIVE_TASK_NO_DATA; args->command_type = IDE_DRIVE_TASK_NO_DATA;
return; return;
...@@ -874,7 +840,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args) ...@@ -874,7 +840,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
return; return;
case WIN_SETMULT: case WIN_SETMULT:
args->handler = set_multmode_intr; args->handler = task_no_data_intr;
args->command_type = IDE_DRIVE_TASK_NO_DATA; args->command_type = IDE_DRIVE_TASK_NO_DATA;
return; return;
...@@ -894,19 +860,19 @@ void ide_cmd_type_parser(struct ata_taskfile *args) ...@@ -894,19 +860,19 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
} }
} }
int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *args, byte *buf) int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *args)
{ {
struct request rq; struct request rq;
memset(&rq, 0, sizeof(rq)); memset(&rq, 0, sizeof(rq));
rq.flags = REQ_DRIVE_ACB; rq.flags = REQ_DRIVE_ACB;
rq.buffer = buf;
#if 0
if (args->command_type != IDE_DRIVE_TASK_NO_DATA) if (args->command_type != IDE_DRIVE_TASK_NO_DATA)
rq.current_nr_sectors = rq.nr_sectors rq.current_nr_sectors = rq.nr_sectors
= (args->hobfile.sector_count << 8) = (args->hobfile.sector_count << 8)
| args->taskfile.sector_count; | args->taskfile.sector_count;
#endif
rq.special = args; rq.special = args;
return ide_do_drive_cmd(drive, &rq, ide_wait); return ide_do_drive_cmd(drive, &rq, ide_wait);
...@@ -996,8 +962,6 @@ EXPORT_SYMBOL(atapi_read); ...@@ -996,8 +962,6 @@ EXPORT_SYMBOL(atapi_read);
EXPORT_SYMBOL(atapi_write); EXPORT_SYMBOL(atapi_write);
EXPORT_SYMBOL(ata_taskfile); EXPORT_SYMBOL(ata_taskfile);
EXPORT_SYMBOL(recal_intr); EXPORT_SYMBOL(recal_intr);
EXPORT_SYMBOL(set_geometry_intr);
EXPORT_SYMBOL(set_multmode_intr);
EXPORT_SYMBOL(task_no_data_intr); EXPORT_SYMBOL(task_no_data_intr);
EXPORT_SYMBOL(ide_raw_taskfile); EXPORT_SYMBOL(ide_raw_taskfile);
EXPORT_SYMBOL(ide_cmd_type_parser); EXPORT_SYMBOL(ide_cmd_type_parser);
......
...@@ -193,7 +193,7 @@ static void init_hwif_data(struct ata_channel *ch, unsigned int index) ...@@ -193,7 +193,7 @@ static void init_hwif_data(struct ata_channel *ch, unsigned int index)
#ifdef CONFIG_BLK_DEV_HD #ifdef CONFIG_BLK_DEV_HD
if (ch->io_ports[IDE_DATA_OFFSET] == HD_DATA) if (ch->io_ports[IDE_DATA_OFFSET] == HD_DATA)
ch->noprobe = 1; /* may be overridden by ide_setup() */ ch->noprobe = 1; /* may be overridden by ide_setup() */
#endif /* CONFIG_BLK_DEV_HD */ #endif
ch->major = ide_major[index]; ch->major = ide_major[index];
sprintf(ch->name, "ide%d", index); sprintf(ch->name, "ide%d", index);
ch->bus_state = BUSSTATE_ON; ch->bus_state = BUSSTATE_ON;
...@@ -207,7 +207,6 @@ static void init_hwif_data(struct ata_channel *ch, unsigned int index) ...@@ -207,7 +207,6 @@ static void init_hwif_data(struct ata_channel *ch, unsigned int index)
drive->ctl = 0x08; drive->ctl = 0x08;
drive->ready_stat = READY_STAT; drive->ready_stat = READY_STAT;
drive->bad_wstat = BAD_W_STAT; drive->bad_wstat = BAD_W_STAT;
drive->special_cmd = (ATA_SPECIAL_RECALIBRATE | ATA_SPECIAL_GEOMETRY);
sprintf(drive->name, "hd%c", 'a' + (index * MAX_DRIVES) + unit); sprintf(drive->name, "hd%c", 'a' + (index * MAX_DRIVES) + unit);
drive->max_failures = IDE_DEFAULT_MAX_FAILURES; drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
...@@ -354,11 +353,8 @@ void ide_set_handler(struct ata_device *drive, ata_handler_t handler, ...@@ -354,11 +353,8 @@ void ide_set_handler(struct ata_device *drive, ata_handler_t handler,
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
} }
static void ata_pre_reset(struct ata_device *drive) static void check_crc_errors(struct ata_device *drive)
{ {
if (ata_ops(drive) && ata_ops(drive)->pre_reset)
ata_ops(drive)->pre_reset(drive);
if (!drive->using_dma) if (!drive->using_dma)
return; return;
...@@ -392,38 +388,6 @@ sector_t ata_capacity(struct ata_device *drive) ...@@ -392,38 +388,6 @@ sector_t ata_capacity(struct ata_device *drive)
return ~0UL; return ~0UL;
} }
/*
* This is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT commands to
* a drive.
*/
static ide_startstop_t ata_special(struct ata_device *drive)
{
unsigned char special_cmd = drive->special_cmd;
#ifdef DEBUG
printk("%s: ata_special: 0x%02x\n", drive->name, special_cmd);
#endif
if (special_cmd & ATA_SPECIAL_TUNE) {
drive->special_cmd &= ~ATA_SPECIAL_TUNE;
if (drive->channel->tuneproc != NULL)
drive->channel->tuneproc(drive, drive->tune_req);
} else if (drive->driver != NULL) {
if (ata_ops(drive)->special)
return ata_ops(drive)->special(drive);
else {
drive->special_cmd = 0;
drive->mult_req = 0;
return ide_stopped;
}
} else if (special_cmd) {
printk("%s: bad special flag: 0x%02x\n", drive->name, special_cmd);
drive->special_cmd = 0;
}
return ide_stopped;
}
extern struct block_device_operations ide_fops[]; extern struct block_device_operations ide_fops[];
/* /*
...@@ -460,24 +424,24 @@ static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */ ...@@ -460,24 +424,24 @@ static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */
*/ */
static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq) static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq)
{ {
ide_hwgroup_t *hwgroup = HWGROUP(drive); struct ata_channel *ch = drive->channel;
byte stat; u8 stat;
SELECT_DRIVE(drive->channel,drive); SELECT_DRIVE(ch,drive);
udelay (10); udelay (10);
if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) { if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) {
printk("%s: ATAPI reset complete\n", drive->name); printk("%s: ATAPI reset complete\n", drive->name);
} else { } else {
if (time_before(jiffies, hwgroup->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler (drive, atapi_reset_pollfunc, HZ/20, NULL); ide_set_handler (drive, atapi_reset_pollfunc, HZ/20, NULL);
return ide_started; /* continue polling */ return ide_started; /* continue polling */
} }
hwgroup->poll_timeout = 0; /* end of polling */ ch->poll_timeout = 0; /* end of polling */
printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat); printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat);
return do_reset1 (drive, 1); /* do it the old fashioned way */ return do_reset1 (drive, 1); /* do it the old fashioned way */
} }
hwgroup->poll_timeout = 0; /* done polling */ ch->poll_timeout = 0; /* done polling */
return ide_stopped; return ide_stopped;
} }
...@@ -489,19 +453,18 @@ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct req ...@@ -489,19 +453,18 @@ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct req
*/ */
static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq) static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq)
{ {
ide_hwgroup_t *hwgroup = HWGROUP(drive); struct ata_channel *ch = drive->channel;
struct ata_channel *hwif = drive->channel;
u8 stat; u8 stat;
if (!OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) { if (!OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) {
if (time_before(jiffies, hwgroup->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler(drive, reset_pollfunc, HZ/20, NULL); ide_set_handler(drive, reset_pollfunc, HZ/20, NULL);
return ide_started; /* continue polling */ return ide_started; /* continue polling */
} }
printk("%s: reset timed-out, status=0x%02x\n", hwif->name, stat); printk("%s: reset timed-out, status=0x%02x\n", ch->name, stat);
drive->failures++; drive->failures++;
} else { } else {
printk("%s: reset: ", hwif->name); printk("%s: reset: ", ch->name);
if ((stat = GET_ERR()) == 1) { if ((stat = GET_ERR()) == 1) {
printk("success\n"); printk("success\n");
drive->failures = 0; drive->failures = 0;
...@@ -531,7 +494,8 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * ...@@ -531,7 +494,8 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *
drive->failures++; drive->failures++;
} }
} }
hwgroup->poll_timeout = 0; /* done polling */ ch->poll_timeout = 0; /* done polling */
return ide_stopped; return ide_stopped;
} }
...@@ -555,21 +519,21 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) ...@@ -555,21 +519,21 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi)
{ {
unsigned int unit; unsigned int unit;
unsigned long flags; unsigned long flags;
struct ata_channel *hwif = drive->channel; struct ata_channel *ch = drive->channel;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
__save_flags(flags); /* local CPU only */ __save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */ __cli(); /* local CPU only */
/* For an ATAPI device, first try an ATAPI SRST. */ /* For an ATAPI device, first try an ATAPI SRST. */
if (drive->type != ATA_DISK && !do_not_try_atapi) { if (drive->type != ATA_DISK && !do_not_try_atapi) {
ata_pre_reset(drive); check_crc_errors(drive);
SELECT_DRIVE(hwif,drive); SELECT_DRIVE(ch, drive);
udelay (20); udelay (20);
OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL); ide_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
__restore_flags(flags); /* local CPU only */ __restore_flags(flags); /* local CPU only */
return ide_started; return ide_started;
} }
...@@ -578,11 +542,12 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) ...@@ -578,11 +542,12 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi)
* for any of the drives on this interface. * for any of the drives on this interface.
*/ */
for (unit = 0; unit < MAX_DRIVES; ++unit) for (unit = 0; unit < MAX_DRIVES; ++unit)
ata_pre_reset(&hwif->drives[unit]); check_crc_errors(&ch->drives[unit]);
#if OK_TO_RESET_CONTROLLER #if OK_TO_RESET_CONTROLLER
if (!IDE_CONTROL_REG) { if (!IDE_CONTROL_REG) {
__restore_flags(flags); __restore_flags(flags);
return ide_stopped; return ide_stopped;
} }
/* /*
...@@ -601,7 +566,7 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) ...@@ -601,7 +566,7 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi)
OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */ OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */
} }
udelay(10); /* more than enough time */ udelay(10); /* more than enough time */
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, reset_pollfunc, HZ/20, NULL); ide_set_handler(drive, reset_pollfunc, HZ/20, NULL);
/* /*
...@@ -609,9 +574,10 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) ...@@ -609,9 +574,10 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi)
* state when the disks are reset this way. At least, the Winbond * state when the disks are reset this way. At least, the Winbond
* 553 documentation says that * 553 documentation says that
*/ */
if (hwif->resetproc != NULL) if (ch->resetproc != NULL)
hwif->resetproc(drive); ch->resetproc(drive);
/* FIXME: we should handle mulit mode setting here as well ! */
#endif #endif
__restore_flags (flags); /* local CPU only */ __restore_flags (flags); /* local CPU only */
...@@ -789,6 +755,36 @@ static void try_to_flush_leftover_data(struct ata_device *drive) ...@@ -789,6 +755,36 @@ static void try_to_flush_leftover_data(struct ata_device *drive)
} }
} }
#ifdef CONFIG_BLK_DEV_PDC4030
# define IS_PDC4030_DRIVE (drive->channel->chipset == ide_pdc4030)
#else
# define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */
#endif
/*
* We are still on the old request path here so issuing the recalibrate command
* directly should just work.
*/
static int do_recalibrate(struct ata_device *drive)
{
printk(KERN_INFO "%s: recalibrating!\n", drive->name);
if (drive->type != ATA_DISK)
return ide_stopped;
if (!IS_PDC4030_DRIVE) {
struct ata_taskfile args;
memset(&args, 0, sizeof(args));
args.taskfile.sector_count = drive->sect;
args.taskfile.command = WIN_RESTORE;
args.handler = recal_intr;
ata_taskfile(drive, &args, NULL);
}
return IS_PDC4030_DRIVE ? ide_stopped : ide_started;
}
/* /*
* Take action based on the error returned by the drive. * Take action based on the error returned by the drive.
*/ */
...@@ -835,13 +831,11 @@ ide_startstop_t ide_error(struct ata_device *drive, const char *msg, byte stat) ...@@ -835,13 +831,11 @@ ide_startstop_t ide_error(struct ata_device *drive, const char *msg, byte stat)
else else
ide_end_request(drive, rq, 0); ide_end_request(drive, rq, 0);
} else { } else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors; ++rq->errors;
if ((rq->errors & ERROR_RESET) == ERROR_RESET)
return do_reset1(drive, 0); return do_reset1(drive, 0);
}
if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
drive->special_cmd |= ATA_SPECIAL_RECALIBRATE; return do_recalibrate(drive);
++rq->errors;
} }
return ide_stopped; return ide_stopped;
} }
...@@ -991,14 +985,6 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r ...@@ -991,14 +985,6 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r
} }
} }
/* FIXME: We can see nicely here that all commands should be submitted
* through the request queue and that the special field in drive should
* go as soon as possible!
*/
if (drive->special_cmd)
return ata_special(drive);
/* This issues a special drive command, usually initiated by ioctl() /* This issues a special drive command, usually initiated by ioctl()
* from the external hdparm program. * from the external hdparm program.
*/ */
...@@ -1053,6 +1039,7 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r ...@@ -1053,6 +1039,7 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r
return ata_ops(drive)->do_request(drive, rq, block); return ata_ops(drive)->do_request(drive, rq, block);
else { else {
ide_end_request(drive, rq, 0); ide_end_request(drive, rq, 0);
return ide_stopped; return ide_stopped;
} }
} }
...@@ -1499,7 +1486,7 @@ void ide_timer_expiry(unsigned long data) ...@@ -1499,7 +1486,7 @@ void ide_timer_expiry(unsigned long data)
disable_irq(ch->irq); /* disable_irq_nosync ?? */ disable_irq(ch->irq); /* disable_irq_nosync ?? */
#endif #endif
__cli(); /* local CPU only, as if we were handling an interrupt */ __cli(); /* local CPU only, as if we were handling an interrupt */
if (hwgroup->poll_timeout != 0) { if (ch->poll_timeout != 0) {
startstop = handler(drive, ch->hwgroup->rq); startstop = handler(drive, ch->hwgroup->rq);
} else if (drive_is_ready(drive)) { } else if (drive_is_ready(drive)) {
if (drive->waiting_for_dma) if (drive->waiting_for_dma)
...@@ -1598,7 +1585,7 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs) ...@@ -1598,7 +1585,7 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs)
if (!ide_ack_intr(ch)) if (!ide_ack_intr(ch))
goto out_lock; goto out_lock;
if (handler == NULL || hwgroup->poll_timeout != 0) { if (handler == NULL || ch->poll_timeout != 0) {
#if 0 #if 0
printk(KERN_INFO "ide: unexpected interrupt %d %d\n", ch->unit, irq); printk(KERN_INFO "ide: unexpected interrupt %d %d\n", ch->unit, irq);
#endif #endif
...@@ -2327,23 +2314,24 @@ int ide_read_setting(struct ata_device *drive, ide_settings_t *setting) ...@@ -2327,23 +2314,24 @@ int ide_read_setting(struct ata_device *drive, ide_settings_t *setting)
int ide_spin_wait_hwgroup(struct ata_device *drive) int ide_spin_wait_hwgroup(struct ata_device *drive)
{ {
ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned long timeout = jiffies + (3 * HZ);
/* FIXME: Wait on a proper timer. Instead of playing games on the
* spin_lock().
*/
unsigned long timeout = jiffies + (10 * HZ);
spin_lock_irq(&ide_lock); spin_lock_irq(&ide_lock);
while (test_bit(IDE_BUSY, &hwgroup->flags)) { while (test_bit(IDE_BUSY, &hwgroup->flags)) {
unsigned long lflags;
spin_unlock_irq(&ide_lock); spin_unlock_irq(&ide_lock);
__save_flags(lflags); /* local CPU only */ if (time_after(jiffies, timeout)) {
__sti(); /* local CPU only; needed for jiffies */
if (0 < (signed long)(jiffies - timeout)) {
__restore_flags(lflags); /* local CPU only */
printk("%s: channel busy\n", drive->name); printk("%s: channel busy\n", drive->name);
return -EBUSY; return -EBUSY;
} }
__restore_flags(lflags); /* local CPU only */
spin_lock_irq(&ide_lock); spin_lock_irq(&ide_lock);
} }
return 0; return 0;
} }
...@@ -2411,18 +2399,17 @@ static int set_using_dma(struct ata_device *drive, int arg) ...@@ -2411,18 +2399,17 @@ static int set_using_dma(struct ata_device *drive, int arg)
static int set_pio_mode(struct ata_device *drive, int arg) static int set_pio_mode(struct ata_device *drive, int arg)
{ {
struct request rq;
if (!drive->channel->tuneproc) if (!drive->channel->tuneproc)
return -ENOSYS; return -ENOSYS;
if (drive->special_cmd & ATA_SPECIAL_TUNE) /* FIXME: This is very much the same kind of problem as we have with
* set_mutlmode() see for a edscription there.
*/
if (HWGROUP(drive)->handler)
return -EBUSY; return -EBUSY;
ide_init_drive_cmd(&rq); if (drive->channel->tuneproc != NULL)
drive->tune_req = (u8) arg; drive->channel->tuneproc(drive, (u8) arg);
drive->special_cmd |= ATA_SPECIAL_TUNE;
ide_do_drive_cmd(drive, &rq, ide_wait);
return 0; return 0;
} }
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
* Version 0.90 Transition to BETA code. No lost/unexpected interrupts * Version 0.90 Transition to BETA code. No lost/unexpected interrupts
* Version 0.91 Bring in line with new bio code in 2.5.1 * Version 0.91 Bring in line with new bio code in 2.5.1
* Version 0.92 Update for IDE driver taskfile changes * Version 0.92 Update for IDE driver taskfile changes
* Version 0.93 Sync with 2.5.10, minor taskfile changes
*/ */
/* /*
...@@ -380,6 +381,7 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques ...@@ -380,6 +381,7 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques
} }
/* /*
* promise_complete_pollfunc()
* This is the polling function for waiting (nicely!) until drive stops * This is the polling function for waiting (nicely!) until drive stops
* being busy. It is invoked at the end of a write, after the previous poll * being busy. It is invoked at the end of a write, after the previous poll
* has finished. * has finished.
...@@ -388,20 +390,20 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques ...@@ -388,20 +390,20 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques
*/ */
static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struct request *rq) static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struct request *rq)
{ {
ide_hwgroup_t *hwgroup = HWGROUP(drive); struct ata_channel *ch = drive->channel;
if (GET_STAT() & BUSY_STAT) { if (GET_STAT() & BUSY_STAT) {
if (time_before(jiffies, hwgroup->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
return ide_started; /* continue polling... */ return ide_started; /* continue polling... */
} }
hwgroup->poll_timeout = 0; ch->poll_timeout = 0;
printk(KERN_ERR "%s: completion timeout - still busy!\n", printk(KERN_ERR "%s: completion timeout - still busy!\n",
drive->name); drive->name);
return ide_error(drive, "busy timeout", GET_STAT()); return ide_error(drive, "busy timeout", GET_STAT());
} }
hwgroup->poll_timeout = 0; ch->poll_timeout = 0;
#ifdef DEBUG_WRITE #ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
#endif #endif
...@@ -432,7 +434,7 @@ int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int ...@@ -432,7 +434,7 @@ int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int
nsect = mcount; nsect = mcount;
mcount -= nsect; mcount -= nsect;
buffer = bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq); buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq);
rq->sector += nsect; rq->sector += nsect;
rq->nr_sectors -= nsect; rq->nr_sectors -= nsect;
rq->current_nr_sectors -= nsect; rq->current_nr_sectors -= nsect;
...@@ -467,23 +469,23 @@ int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int ...@@ -467,23 +469,23 @@ int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int
*/ */
static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct request *rq) static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct request *rq)
{ {
ide_hwgroup_t *hwgroup = HWGROUP(drive); struct ata_channel *ch = drive->channel;
if (IN_BYTE(IDE_NSECTOR_REG) != 0) { if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
if (time_before(jiffies, hwgroup->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL);
return ide_started; /* continue polling... */ return ide_started; /* continue polling... */
} }
hwgroup->poll_timeout = 0; ch->poll_timeout = 0;
printk(KERN_ERR "%s: write timed-out!\n",drive->name); printk(KERN_ERR "%s: write timed-out!\n",drive->name);
return ide_error (drive, "write timeout", GET_STAT()); return ide_error(drive, "write timeout", GET_STAT());
} }
/* /*
* Now write out last 4 sectors and poll for not BUSY * Now write out last 4 sectors and poll for not BUSY
*/ */
promise_multwrite(drive, rq, 4); promise_multwrite(drive, rq, 4);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
#ifdef DEBUG_WRITE #ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
...@@ -501,7 +503,7 @@ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct r ...@@ -501,7 +503,7 @@ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct r
*/ */
static ide_startstop_t promise_write(struct ata_device *drive, struct request *rq) static ide_startstop_t promise_write(struct ata_device *drive, struct request *rq)
{ {
ide_hwgroup_t *hwgroup = HWGROUP(drive); struct ata_channel *ch = drive->channel;
#ifdef DEBUG_WRITE #ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), " printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), "
...@@ -516,7 +518,7 @@ static ide_startstop_t promise_write(struct ata_device *drive, struct request *r ...@@ -516,7 +518,7 @@ static ide_startstop_t promise_write(struct ata_device *drive, struct request *r
if (rq->nr_sectors > 4) { if (rq->nr_sectors > 4) {
if (promise_multwrite(drive, rq, rq->nr_sectors - 4)) if (promise_multwrite(drive, rq, rq->nr_sectors - 4))
return ide_stopped; return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL); ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL);
return ide_started; return ide_started;
} else { } else {
...@@ -526,7 +528,7 @@ static ide_startstop_t promise_write(struct ata_device *drive, struct request *r ...@@ -526,7 +528,7 @@ static ide_startstop_t promise_write(struct ata_device *drive, struct request *r
*/ */
if (promise_multwrite(drive, rq, rq->nr_sectors)) if (promise_multwrite(drive, rq, rq->nr_sectors))
return ide_stopped; return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL); ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
#ifdef DEBUG_WRITE #ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
...@@ -537,13 +539,13 @@ static ide_startstop_t promise_write(struct ata_device *drive, struct request *r ...@@ -537,13 +539,13 @@ static ide_startstop_t promise_write(struct ata_device *drive, struct request *r
} }
/* /*
* do_pdc4030_io() is called from do_rw_disk, having had the block number * do_pdc4030_io() is called from promise_do_request, having had the block
* already set up. It issues a READ or WRITE command to the Promise * number already set up. It issues a READ or WRITE command to the Promise
* controller, assuming LBA has been used to set up the block number. * controller, assuming LBA has been used to set up the block number.
*/ */
ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *task, struct request *rq) ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *args, struct request *rq)
{ {
struct hd_drive_task_hdr *taskfile = &task->taskfile; struct hd_drive_task_hdr *taskfile = &(args->taskfile);
unsigned long timeout; unsigned long timeout;
byte stat; byte stat;
...@@ -628,7 +630,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *tas ...@@ -628,7 +630,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *tas
} }
} }
ide_startstop_t promise_rw_disk(struct ata_device *drive, struct request *rq, sector_t block) ide_startstop_t promise_do_request(struct ata_device *drive, struct request *rq, sector_t block)
{ {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -647,12 +649,12 @@ ide_startstop_t promise_rw_disk(struct ata_device *drive, struct request *rq, se ...@@ -647,12 +649,12 @@ ide_startstop_t promise_rw_disk(struct ata_device *drive, struct request *rq, se
args.taskfile.device_head = ((block>>8)&0x0f)|drive->select.all; args.taskfile.device_head = ((block>>8)&0x0f)|drive->select.all;
args.taskfile.command = (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE; args.taskfile.command = (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE;
ide_cmd_type_parser(&args); /* We can't call ide_cmd_type_parser here, since it won't understand
/* We don't use the generic inerrupt handlers here? */ our command, but that doesn't matter, since we don't use the
args.prehandler = NULL; generic interrupt handlers either. Setup the bits of args that we
will need. */
args.handler = NULL; args.handler = NULL;
rq->special = &args; rq->special = &args;
return do_pdc4030_io(drive, &args, rq); return do_pdc4030_io(drive, &args, rq);
} }
...@@ -418,7 +418,7 @@ static int check_autopoll(struct ata_device *drive) ...@@ -418,7 +418,7 @@ static int check_autopoll(struct ata_device *drive)
* pass NOP with sub-code 0x01 to device, so the command will not * pass NOP with sub-code 0x01 to device, so the command will not
* fail there * fail there
*/ */
ide_raw_taskfile(drive, &args, NULL); ide_raw_taskfile(drive, &args);
if (args.taskfile.feature & ABRT_ERR) if (args.taskfile.feature & ABRT_ERR)
return 1; return 1;
...@@ -448,7 +448,7 @@ static int configure_tcq(struct ata_device *drive) ...@@ -448,7 +448,7 @@ static int configure_tcq(struct ata_device *drive)
args.taskfile.command = WIN_SETFEATURES; args.taskfile.command = WIN_SETFEATURES;
ide_cmd_type_parser(&args); ide_cmd_type_parser(&args);
if (ide_raw_taskfile(drive, &args, NULL)) { if (ide_raw_taskfile(drive, &args)) {
printk("%s: failed to enable write cache\n", drive->name); printk("%s: failed to enable write cache\n", drive->name);
return 1; return 1;
} }
...@@ -462,7 +462,7 @@ static int configure_tcq(struct ata_device *drive) ...@@ -462,7 +462,7 @@ static int configure_tcq(struct ata_device *drive)
args.taskfile.command = WIN_SETFEATURES; args.taskfile.command = WIN_SETFEATURES;
ide_cmd_type_parser(&args); ide_cmd_type_parser(&args);
if (ide_raw_taskfile(drive, &args, NULL)) { if (ide_raw_taskfile(drive, &args)) {
printk("%s: disabling release interrupt fail\n", drive->name); printk("%s: disabling release interrupt fail\n", drive->name);
return 1; return 1;
} }
...@@ -476,7 +476,7 @@ static int configure_tcq(struct ata_device *drive) ...@@ -476,7 +476,7 @@ static int configure_tcq(struct ata_device *drive)
args.taskfile.command = WIN_SETFEATURES; args.taskfile.command = WIN_SETFEATURES;
ide_cmd_type_parser(&args); ide_cmd_type_parser(&args);
if (ide_raw_taskfile(drive, &args, NULL)) { if (ide_raw_taskfile(drive, &args)) {
printk("%s: enabling service interrupt fail\n", drive->name); printk("%s: enabling service interrupt fail\n", drive->name);
return 1; return 1;
} }
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
# define DISK_RECOVERY_TIME 0 /* for hardware that needs it */ # define DISK_RECOVERY_TIME 0 /* for hardware that needs it */
#endif #endif
#ifndef OK_TO_RESET_CONTROLLER /* 1 needed for good error recovery */ #ifndef OK_TO_RESET_CONTROLLER /* 1 needed for good error recovery */
# define OK_TO_RESET_CONTROLLER 1 /* 0 for use with AH2372A/B interface */ # define OK_TO_RESET_CONTROLLER 0 /* 0 for use with AH2372A/B interface */
#endif #endif
#ifndef FANCY_STATUS_DUMPS /* 1 for human-readable drive errors */ #ifndef FANCY_STATUS_DUMPS /* 1 for human-readable drive errors */
# define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */ # define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */
...@@ -327,19 +327,9 @@ struct ata_device { ...@@ -327,19 +327,9 @@ struct ata_device {
*/ */
request_queue_t queue; /* per device request queue */ request_queue_t queue; /* per device request queue */
unsigned long sleep; /* sleep until this time */ unsigned long sleep; /* sleep until this time */
/* Flags requesting/indicating one of the following special commands u8 XXX_tune_req; /* requested drive tuning setting */
* executed on the request queue.
*/
#define ATA_SPECIAL_GEOMETRY 0x01
#define ATA_SPECIAL_RECALIBRATE 0x02
#define ATA_SPECIAL_MMODE 0x04
#define ATA_SPECIAL_TUNE 0x08
unsigned char special_cmd;
u8 mult_req; /* requested multiple sector setting */
u8 tune_req; /* requested drive tuning setting */
byte using_dma; /* disk is using dma for read/write */ byte using_dma; /* disk is using dma for read/write */
byte using_tcq; /* disk is using queueing */ byte using_tcq; /* disk is using queueing */
...@@ -409,6 +399,7 @@ struct ata_device { ...@@ -409,6 +399,7 @@ struct ata_device {
unsigned int failures; /* current failure count */ unsigned int failures; /* current failure count */
unsigned int max_failures; /* maximum allowed failure count */ unsigned int max_failures; /* maximum allowed failure count */
struct device device; /* global device tree handle */ struct device device; /* global device tree handle */
/* /*
* tcq statistics * tcq statistics
*/ */
...@@ -517,6 +508,8 @@ struct ata_channel { ...@@ -517,6 +508,8 @@ struct ata_channel {
/* driver soft-power interface */ /* driver soft-power interface */
int (*busproc)(struct ata_device *, int); int (*busproc)(struct ata_device *, int);
byte bus_state; /* power state of the IDE bus */ byte bus_state; /* power state of the IDE bus */
unsigned long poll_timeout; /* timeout value during polled operations */
}; };
/* /*
...@@ -565,17 +558,19 @@ static inline int ata_can_queue(struct ata_device *drive) ...@@ -565,17 +558,19 @@ static inline int ata_can_queue(struct ata_device *drive)
return 1; return 1;
} }
#else #else
#define ata_pending_commands(drive) (0) # define ata_pending_commands(drive) (0)
#define ata_can_queue(drive) (1) # define ata_can_queue(drive) (1)
#endif #endif
typedef struct hwgroup_s { typedef struct hwgroup_s {
/* FIXME: We should look for busy request queues instead of looking at
* the !NULL state of this field.
*/
ide_startstop_t (*handler)(struct ata_device *, struct request *); /* irq handler, if active */ ide_startstop_t (*handler)(struct ata_device *, struct request *); /* irq handler, if active */
unsigned long flags; /* BUSY, SLEEPING */ unsigned long flags; /* BUSY, SLEEPING */
struct ata_device *XXX_drive; /* current drive */ struct ata_device *XXX_drive; /* current drive */
struct request *rq; /* current request */ struct request *rq; /* current request */
struct timer_list timer; /* failsafe timer */ struct timer_list timer; /* failsafe timer */
unsigned long poll_timeout; /* timeout value during long polls */
int (*expiry)(struct ata_device *, struct request *); /* irq handler, if active */ int (*expiry)(struct ata_device *, struct request *); /* irq handler, if active */
} ide_hwgroup_t; } ide_hwgroup_t;
...@@ -675,9 +670,7 @@ struct ata_operations { ...@@ -675,9 +670,7 @@ struct ata_operations {
int (*check_media_change)(struct ata_device *); int (*check_media_change)(struct ata_device *);
void (*revalidate)(struct ata_device *); void (*revalidate)(struct ata_device *);
void (*pre_reset)(struct ata_device *);
sector_t (*capacity)(struct ata_device *); sector_t (*capacity)(struct ata_device *);
ide_startstop_t (*special)(struct ata_device *);
ide_proc_entry_t *proc; ide_proc_entry_t *proc;
}; };
...@@ -827,15 +820,13 @@ extern ide_startstop_t ata_taskfile(struct ata_device *, ...@@ -827,15 +820,13 @@ extern ide_startstop_t ata_taskfile(struct ata_device *,
*/ */
extern ide_startstop_t recal_intr(struct ata_device *, struct request *); extern ide_startstop_t recal_intr(struct ata_device *, struct request *);
extern ide_startstop_t set_geometry_intr(struct ata_device *, struct request *);
extern ide_startstop_t set_multmode_intr(struct ata_device *, struct request *);
extern ide_startstop_t task_no_data_intr(struct ata_device *, struct request *); extern ide_startstop_t task_no_data_intr(struct ata_device *, struct request *);
/* This is setting up all fields in args, which depend upon the command type. /* This is setting up all fields in args, which depend upon the command type.
*/ */
extern void ide_cmd_type_parser(struct ata_taskfile *args); extern void ide_cmd_type_parser(struct ata_taskfile *args);
extern int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *cmd, byte *buf); extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *);
extern int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg); extern int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg);
void ide_delay_50ms(void); void ide_delay_50ms(void);
......
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