diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
commit | 59223edaa18759982db0a8aced0e77457d10c68e (patch) | |
tree | 89354903b01fa0a447bffeefe00df3044495db2e /drivers/block/cmd646.c | |
parent | db7d4daea91e105e3859cf461d7e53b9b77454b2 (diff) |
Merge with Linux 2.3.6. Sorry, this isn't tested on silicon, I don't
have a MIPS box at hand.
Diffstat (limited to 'drivers/block/cmd646.c')
-rw-r--r-- | drivers/block/cmd646.c | 56 |
1 files changed, 45 insertions, 11 deletions
diff --git a/drivers/block/cmd646.c b/drivers/block/cmd646.c index 57b593131..63b4bbc09 100644 --- a/drivers/block/cmd646.c +++ b/drivers/block/cmd646.c @@ -1,4 +1,4 @@ -/* $Id: cmd646.c,v 1.11 1998/12/13 08:36:54 davem Exp $ +/* $Id: cmd646.c,v 1.13 1999/05/27 04:49:38 davem Exp $ * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines. * Note, this driver is not used at all on other systems because * there the "BIOS" has done all of the following already. @@ -12,8 +12,10 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/hdreg.h> +#include <linux/ide.h> + #include <asm/io.h> -#include "ide.h" static int cmd646_config_drive_for_dma(ide_drive_t *drive) { @@ -43,14 +45,14 @@ static int cmd646_config_drive_for_dma(ide_drive_t *drive) } /* This is fun. -DaveM */ -#define IDE_SETXFER 0x03 -#define IDE_SETFEATURE 0xef -#define IDE_DMA2_ENABLE 0x22 -#define IDE_DMA1_ENABLE 0x21 -#define IDE_DMA0_ENABLE 0x20 -#define IDE_UDMA2_ENABLE 0x42 -#define IDE_UDMA1_ENABLE 0x41 -#define IDE_UDMA0_ENABLE 0x40 +#define IDE_SETXFER SETFEATURES_XFER +#define IDE_SETFEATURE WIN_SETFEATURES +#define IDE_DMA2_ENABLE XFER_MW_DMA_2 +#define IDE_DMA1_ENABLE XFER_MW_DMA_1 +#define IDE_DMA0_ENABLE XFER_MW_DMA_0 +#define IDE_UDMA2_ENABLE XFER_UDMA_2 +#define IDE_UDMA1_ENABLE XFER_UDMA_1 +#define IDE_UDMA0_ENABLE XFER_UDMA_0 static __inline__ unsigned char dma2_bits_to_command(unsigned char bits) { @@ -212,10 +214,36 @@ static int cmd646_dmaproc(ide_dma_action_t func, ide_drive_t *drive) return ide_dmaproc(func, drive); } +/* + * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old + * event order for DMA transfers. + */ +static int cmd646_1_dmaproc(ide_dma_action_t func, ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte dma_stat; + + if (func == ide_dma_end) { + drive->waiting_for_dma = 0; + dma_stat = inb(dma_base+2); /* get DMA status */ + outb(inb(dma_base)&~1, dma_base); /* stop DMA */ + outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ + return (dma_stat & 7) != 4; /* verify good DMA status */ + } + + /* Other cases are done by generic IDE-DMA code. */ + return cmd646_dmaproc(func, drive); +} + __initfunc(void ide_init_cmd646 (ide_hwif_t *hwif)) { struct pci_dev *dev = hwif->pci_dev; unsigned char mrdmode; + unsigned int class_rev; + + pci_read_config_dword(hwif->pci_dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; hwif->chipset = ide_cmd646; @@ -247,5 +275,11 @@ __initfunc(void ide_init_cmd646 (ide_hwif_t *hwif)) (void) pci_write_config_byte(dev, 0x58, 0x3f); (void) pci_write_config_byte(dev, 0x5b, 0x3f); - hwif->dmaproc = &cmd646_dmaproc; + if (hwif->dma_base) { + if (class_rev == 0x01) { + hwif->dmaproc = &cmd646_1_dmaproc; + } else { + hwif->dmaproc = &cmd646_dmaproc; + } + } } |