summaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-features.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-features.c')
-rw-r--r--drivers/ide/ide-features.c66
1 files changed, 55 insertions, 11 deletions
diff --git a/drivers/ide/ide-features.c b/drivers/ide/ide-features.c
index 371f57ad8..fcf0aab63 100644
--- a/drivers/ide/ide-features.c
+++ b/drivers/ide/ide-features.c
@@ -27,6 +27,7 @@
#include <linux/malloc.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/byteorder.h>
@@ -109,6 +110,46 @@ char *ide_dmafunc_verbose (ide_dma_action_t dmafunc)
}
/*
+ *
+ */
+byte ide_auto_reduce_xfer (ide_drive_t *drive)
+{
+ switch(drive->current_speed) {
+ case XFER_UDMA_7: return XFER_UDMA_6;
+ case XFER_UDMA_6: return XFER_UDMA_5;
+ case XFER_UDMA_5: return XFER_UDMA_4;
+ case XFER_UDMA_4: return XFER_UDMA_3;
+ case XFER_UDMA_3: return XFER_UDMA_2;
+ case XFER_UDMA_2: return XFER_UDMA_1;
+ case XFER_UDMA_1: return XFER_UDMA_0;
+ case XFER_UDMA_0:
+ if (drive->id->dma_mword & 0x0004) return XFER_MW_DMA_2;
+ else if (drive->id->dma_mword & 0x0002) return XFER_MW_DMA_1;
+ else if (drive->id->dma_mword & 0x0001) return XFER_MW_DMA_0;
+ else return XFER_PIO_4;
+ case XFER_MW_DMA_2: return XFER_MW_DMA_1;
+ case XFER_MW_DMA_1: return XFER_MW_DMA_0;
+ case XFER_MW_DMA_0:
+ if (drive->id->dma_1word & 0x0004) return XFER_SW_DMA_2;
+ else if (drive->id->dma_1word & 0x0002) return XFER_SW_DMA_1;
+ else if (drive->id->dma_1word & 0x0001) return XFER_SW_DMA_0;
+ else return XFER_PIO_4;
+ case XFER_SW_DMA_2: return XFER_SW_DMA_1;
+ case XFER_SW_DMA_1: return XFER_SW_DMA_0;
+ case XFER_SW_DMA_0:
+ {
+ return XFER_PIO_4;
+ }
+ case XFER_PIO_4: return XFER_PIO_3;
+ case XFER_PIO_3: return XFER_PIO_2;
+ case XFER_PIO_2: return XFER_PIO_1;
+ case XFER_PIO_1: return XFER_PIO_0;
+ case XFER_PIO_0:
+ default: return XFER_PIO_SLOW;
+ }
+}
+
+/*
* Update the
*/
int ide_driveid_update (ide_drive_t *drive)
@@ -136,8 +177,10 @@ int ide_driveid_update (ide_drive_t *drive)
ide_delay_50ms(); /* give drive a breather */
} while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */
- if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT))
+ if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
+ printk("%s: CHECK for good STATUS\n", drive->name);
return 0;
+ }
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only; some systems need this */
id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
@@ -146,17 +189,14 @@ int ide_driveid_update (ide_drive_t *drive)
ide__sti(); /* local CPU only */
__restore_flags(flags); /* local CPU only */
ide_fix_driveid(id);
- if (id && id->cyls) {
+ 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 ? */
-#ifdef DEBUG
- printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n",
- drive->name, id->dma_ultra, id->dma_mword, id->dma_1word);
-#endif
kfree(id);
}
+
return 1;
}
@@ -167,7 +207,7 @@ int ide_driveid_update (ide_drive_t *drive)
* in combination with the device (usually a disk) properly detect
* and acknowledge each end of the ribbon.
*/
-int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature)
+int ide_ata66_check (ide_drive_t *drive, byte cmd, byte nsect, byte feature)
{
if ((cmd == WIN_SETFEATURES) &&
(nsect > XFER_UDMA_2) &&
@@ -189,15 +229,16 @@ int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature)
* 1 : Safe to update drive->id DMA registers.
* 0 : OOPs not allowed.
*/
-int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature)
+int set_transfer (ide_drive_t *drive, byte cmd, byte nsect, byte feature)
{
- struct hd_driveid *id = drive->id;
-
if ((cmd == WIN_SETFEATURES) &&
(nsect >= XFER_SW_DMA_0) &&
(feature == SETFEATURES_XFER) &&
- (id->dma_ultra || id->dma_mword || id->dma_1word))
+ (drive->id->dma_ultra ||
+ drive->id->dma_mword ||
+ drive->id->dma_1word))
return 1;
+
return 0;
}
@@ -219,6 +260,8 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed)
byte unit = (drive->select.b.unit & 0x01);
byte stat;
+ outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2);
+
/*
* Don't use ide_wait_cmd here - it will
* attempt to set_geometry and recalibrate,
@@ -307,6 +350,7 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed)
return error;
}
+EXPORT_SYMBOL(ide_auto_reduce_xfer);
EXPORT_SYMBOL(ide_driveid_update);
EXPORT_SYMBOL(ide_ata66_check);
EXPORT_SYMBOL(set_transfer);