X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fide%2Fide-iops.c;h=95168833d0691a82c896197a7a4d01beae361479;hb=0c326331c8b107abc0a160e8899d749150b8f76a;hp=cf0678b6116183ebf14e6108154b94955a4d4862;hpb=26bcb879c03254545a19c6700fe5bcef6f21e7b1;p=linux-2.6-omap-h63xx.git diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index cf0678b6116..95168833d06 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -472,58 +472,23 @@ int drive_is_ready (ide_drive_t *drive) EXPORT_SYMBOL(drive_is_ready); -/* - * Global for All, and taken from ide-pmac.c. Can be called - * with spinlock held & IRQs disabled, so don't schedule ! - */ -int wait_for_ready (ide_drive_t *drive, int timeout) -{ - ide_hwif_t *hwif = HWIF(drive); - u8 stat = 0; - - while(--timeout) { - stat = hwif->INB(IDE_STATUS_REG); - if (!(stat & BUSY_STAT)) { - if (drive->ready_stat == 0) - break; - else if ((stat & drive->ready_stat)||(stat & ERR_STAT)) - break; - } - mdelay(1); - } - if ((stat & ERR_STAT) || timeout <= 0) { - if (stat & ERR_STAT) { - printk(KERN_ERR "%s: wait_for_ready, " - "error status: %x\n", drive->name, stat); - } - return 1; - } - return 0; -} - /* * This routine busy-waits for the drive status to be not "busy". * It then checks the status for all of the "good" bits and none * of the "bad" bits, and if all is okay it returns 0. All other - * cases return 1 after invoking ide_error() -- caller should just return. + * cases return error -- caller may then invoke ide_error(). * * This routine should get fixed to not hog the cpu during extra long waits.. * That could be done by busy-waiting for the first jiffy or two, and then * setting a timer to wake up at half second intervals thereafter, * until timeout is achieved, before timing out. */ -int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout) +static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat) { - ide_hwif_t *hwif = HWIF(drive); - u8 stat; - int i; + ide_hwif_t *hwif = drive->hwif; unsigned long flags; - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - *startstop = ide_stopped; - return 1; - } + int i; + u8 stat; udelay(1); /* spec allows drive 400ns to assert "BUSY" */ if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { @@ -541,8 +506,8 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 b break; local_irq_restore(flags); - *startstop = ide_error(drive, "status timeout", stat); - return 1; + *rstat = stat; + return -EBUSY; } } local_irq_restore(flags); @@ -556,11 +521,39 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 b */ for (i = 0; i < 10; i++) { udelay(1); - if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad)) + if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad)) { + *rstat = stat; return 0; + } } - *startstop = ide_error(drive, "status error", stat); - return 1; + *rstat = stat; + return -EFAULT; +} + +/* + * In case of error returns error value after doing "*startstop = ide_error()". + * The caller should return the updated value of "startstop" in this case, + * "startstop" is unchanged when the function returns 0. + */ +int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout) +{ + int err; + u8 stat; + + /* bail early if we've exceeded max_failures */ + if (drive->max_failures && (drive->failures > drive->max_failures)) { + *startstop = ide_stopped; + return 1; + } + + err = __ide_wait_stat(drive, good, bad, timeout, &stat); + + if (err) { + char *s = (err == -EBUSY) ? "status timeout" : "status error"; + *startstop = ide_error(drive, s, stat); + } + + return err; } EXPORT_SYMBOL(ide_wait_stat); @@ -620,15 +613,10 @@ u8 eighty_ninty_three (ide_drive_t *drive) /* * FIXME: - * - change master/slave IDENTIFY order * - force bit13 (80c cable present) check also for !ivb devices * (unless the slave device is pre-ATA3) */ -#ifndef CONFIG_IDEDMA_IVB if ((id->hw_config & 0x4000) || (ivb && (id->hw_config & 0x2000))) -#else - if (id->hw_config & 0x6000) -#endif return 1; no_80w: @@ -705,35 +693,16 @@ static u8 ide_auto_reduce_xfer (ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_IDEDMA */ -/* - * Update the - */ -int ide_driveid_update (ide_drive_t *drive) +int ide_driveid_update(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = drive->hwif; struct hd_driveid *id; -#if 0 - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); - if (!id) - return 0; - - taskfile_lib_get_identify(drive, (char *)&id); + unsigned long timeout, flags; - ide_fix_driveid(id); - if (id) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ - kfree(id); - } - return 1; -#else /* * Re-read drive->id for possible DMA mode * change (copied from ide-probe.c) */ - unsigned long timeout, flags; SELECT_MASK(drive, 1); if (IDE_CONTROL_REG) @@ -775,25 +744,19 @@ int ide_driveid_update (ide_drive_t *drive) } return 1; -#endif } -/* - * Similar to ide_wait_stat(), except it never calls ide_error internally. - * - * const char *msg == consider adding for verbose errors. - */ -int ide_config_drive_speed (ide_drive_t *drive, u8 speed) +int ide_config_drive_speed(ide_drive_t *drive, u8 speed) { - ide_hwif_t *hwif = HWIF(drive); - int i, error = 1; + ide_hwif_t *hwif = drive->hwif; + int error; u8 stat; // while (HWGROUP(drive)->busy) // msleep(50); #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->ide_dma_check) /* check if host supports DMA */ + if (hwif->ide_dma_on) /* check if host supports DMA */ hwif->dma_host_off(drive); #endif @@ -826,35 +789,10 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed) hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG); if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) hwif->OUTB(drive->ctl, IDE_CONTROL_REG); - udelay(1); - /* - * Wait for drive to become non-BUSY - */ - if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { - unsigned long flags, timeout; - local_irq_set(flags); - timeout = jiffies + WAIT_CMD; - while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { - if (time_after(jiffies, timeout)) - break; - } - local_irq_restore(flags); - } - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), drive->ready_stat, BUSY_STAT|DRQ_STAT|ERR_STAT)) { - error = 0; - break; - } - } + error = __ide_wait_stat(drive, drive->ready_stat, + BUSY_STAT|DRQ_STAT|ERR_STAT, + WAIT_CMD, &stat); SELECT_MASK(drive, 0); @@ -872,7 +810,7 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed) #ifdef CONFIG_BLK_DEV_IDEDMA if (speed >= XFER_SW_DMA_0) hwif->dma_host_on(drive); - else if (hwif->ide_dma_check) /* check if host supports DMA */ + else if (hwif->ide_dma_on) /* check if host supports DMA */ hwif->dma_off_quietly(drive); #endif @@ -899,9 +837,6 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed) return error; } -EXPORT_SYMBOL(ide_config_drive_speed); - - /* * This should get invoked any time we exit the driver to * wait for an interrupt response from a drive. handler() points