diff options
Diffstat (limited to 'drivers/block/ide-features.c')
-rw-r--r-- | drivers/block/ide-features.c | 199 |
1 files changed, 105 insertions, 94 deletions
diff --git a/drivers/block/ide-features.c b/drivers/block/ide-features.c index 87b7cacb4..3f29ed591 100644 --- a/drivers/block/ide-features.c +++ b/drivers/block/ide-features.c @@ -1,16 +1,15 @@ /* - * linux/drivers/block/ide-features.c + * linux/drivers/block/ide-features.c Version 0.03 Feb. 10, 2000 * - * Copyright (C) 1999 Linus Torvalds & authors (see below) + * Copyright (C) 1999-2000 Linus Torvalds & authors (see below) * - * Andre Hedrick <andre@suse.com> + * Copyright (C) 1999-2000 Andre Hedrick <andre@suse.com> * * Extracts if ide.c to address the evolving transfer rate code for - * the SETFEATURES_XFER callouts. Below are original authors of some or - * various parts of any given function below. + * the SETFEATURES_XFER callouts. Various parts of any given function + * are credited to previous ATA-IDE maintainers. * - * Mark Lord <mlord@pobox.com> - * Gadi Oxman <gadio@netvision.net.il> + * May be copied or modified under the terms of the GNU General Public License */ #define __NO_VERSION__ @@ -36,12 +35,15 @@ #include <asm/io.h> #include <asm/bitops.h> +#define SETFEATURES_CONTROL_REG (0) /* some arch's may need */ + /* - * + * A Verbose noise maker for debugging on the attempted transfer rates. */ char *ide_xfer_verbose (byte xfer_rate) { switch(xfer_rate) { + case XFER_UDMA_7: return("UDMA 7"); case XFER_UDMA_6: return("UDMA 6"); case XFER_UDMA_5: return("UDMA 5"); case XFER_UDMA_4: return("UDMA 4"); @@ -71,14 +73,42 @@ char *ide_xfer_verbose (byte xfer_rate) char *ide_media_verbose (ide_drive_t *drive) { switch (drive->media) { - case ide_disk: return("disk "); - case ide_cdrom: return("cdrom "); - case ide_tape: return("tape "); - case ide_floppy: return("floppy"); - default: return("??????"); + case ide_scsi: return("scsi "); + case ide_disk: return("disk "); + case ide_optical: return("optical"); + case ide_cdrom: return("cdrom "); + case ide_tape: return("tape "); + case ide_floppy: return("floppy "); + default: return("???????"); } } +/* + * A Verbose noise maker for debugging on the attempted dmaing calls. + */ +char *ide_dmafunc_verbose (ide_dma_action_t dmafunc) +{ + switch (dmafunc) { + case ide_dma_read: return("ide_dma_read"); + case ide_dma_write: return("ide_dma_write"); + case ide_dma_begin: return("ide_dma_begin"); + case ide_dma_end: return("ide_dma_end:"); + case ide_dma_check: return("ide_dma_check"); + case ide_dma_on: return("ide_dma_on"); + case ide_dma_off: return("ide_dma_off"); + case ide_dma_off_quietly: return("ide_dma_off_quietly"); + case ide_dma_test_irq: return("ide_dma_test_irq"); + case ide_dma_bad_drive: return("ide_dma_bad_drive"); + case ide_dma_good_drive: return("ide_dma_good_drive"); + case ide_dma_lostirq: return("ide_dma_lostirq"); + case ide_dma_timeout: return("ide_dma_timeout"); + default: return("unknown"); + } +} + +/* + * Update the + */ int ide_driveid_update (ide_drive_t *drive) { /* @@ -129,50 +159,6 @@ int ide_driveid_update (ide_drive_t *drive) } /* - * Similar to ide_wait_stat(), except it never calls ide_error internally. - * This is a kludge to handle the new ide_config_drive_speed() function, - * and should not otherwise be used anywhere. Eventually, the tuneproc's - * should be updated to return ide_startstop_t, in which case we can get - * rid of this abomination again. :) -ml - */ -int ide_wait_noerr (ide_drive_t *drive, byte good, byte bad, unsigned long timeout) -{ - byte stat; - int i; - unsigned long flags; - - udelay(1); /* spec allows drive 400ns to assert "BUSY" */ - if ((stat = GET_STAT()) & BUSY_STAT) { - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only */ - timeout += jiffies; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(flags); /* local CPU only */ - (void)ide_dump_status(drive, "ide_wait_noerr", stat); - return 1; - } - } - __restore_flags(flags); /* local CPU only */ - } - /* - * 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 = GET_STAT()), good, bad)) - return 0; - } - (void)ide_dump_status(drive, "ide_wait_noerr", stat); - return 1; -} - - -/* * Verify that we are doing an approved SETFEATURES_XFER with respect * to the hardware being able to support request. Since some hardware * can improperly report capabilties, we check to see if the host adapter @@ -213,70 +199,96 @@ int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature) return 0; } -#if 0 -ide_startstop_t set_drive_speed_intr (ide_drive_t *drive) -{ - byte stat; - - if (!OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) /* - * if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,BAD_STAT)) - * if (stat != DRIVE_READY) + * Similar to ide_wait_stat(), except it never calls ide_error internally. + * This is a kludge to handle the new ide_config_drive_speed() function, + * and should not otherwise be used anywhere. Eventually, the tuneproc's + * should be updated to return ide_startstop_t, in which case we can get + * rid of this abomination again. :) -ml + * + * It is gone.......... + * + * const char *msg == consider adding for verbose errors. */ - (void) ide_dump_status(drive, "set_drive_speed_status", stat); - - return ide_stopped; -} -#endif - int ide_config_drive_speed (ide_drive_t *drive, byte speed) { - unsigned long flags; - int err; + ide_hwif_t *hwif = HWIF(drive); + int i, error = 1; + byte unit = (drive->select.b.unit & 0x01); byte stat; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - /* * Don't use ide_wait_cmd here - it will * attempt to set_geometry and recalibrate, * but for some reason these don't work at * this point (lost interrupt). */ + /* + * Select the drive, and issue the SETFEATURES command + */ + disable_irq(hwif->irq); /* disable_irq_nosync ?? */ + udelay(1); SELECT_DRIVE(HWIF(drive), drive); + udelay(1); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); OUT_BYTE(speed, IDE_NSECTOR_REG); OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - - err = ide_wait_noerr(drive, DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD); - -#if 0 - if (IDE_CONTROL_REG) + if ((IDE_CONTROL_REG) && (SETFEATURES_CONTROL_REG)) OUT_BYTE(drive->ctl, IDE_CONTROL_REG); -#endif + udelay(1); + /* + * Wait for drive to become non-BUSY + */ + if ((stat = GET_STAT()) & BUSY_STAT) { + unsigned long flags, timeout; + __save_flags(flags); /* local CPU only */ + ide__sti(); /* local CPU only -- for jiffies */ + timeout = jiffies + WAIT_CMD; + while ((stat = GET_STAT()) & BUSY_STAT) { + if (0 < (signed long)(jiffies - timeout)) + break; + } + __restore_flags(flags); /* local CPU only */ + } - __restore_flags(flags); /* local CPU only */ + /* + * 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 = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { + error = 0; + break; + } + } -#if 0 - ide_set_handler(drive, &set_drive_speed_intr, WAIT_CMD, NULL); -#endif + enable_irq(hwif->irq); - stat = GET_STAT(); - if (stat != DRIVE_READY) + if (error) { (void) ide_dump_status(drive, "set_drive_speed_status", stat); + return error; + } drive->id->dma_ultra &= ~0xFF00; drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; + if (speed > XFER_PIO_4) { + outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); + } else { + outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); + } + switch(speed) { -#if 0 - case XFER_UDMA_6: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x1010; break; -#endif + case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; + case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; + case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; @@ -290,11 +302,10 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed) case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; default: break; } - return(err); + return error; } EXPORT_SYMBOL(ide_driveid_update); -EXPORT_SYMBOL(ide_wait_noerr); EXPORT_SYMBOL(ide_ata66_check); EXPORT_SYMBOL(set_transfer); EXPORT_SYMBOL(ide_config_drive_speed); |