Commit 3ddddcf2 authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.13 IDE 53

 - Start splitting the functions for host chip handling in to separate entities.
   This change is quite sensitive and may cause some trouble but it's for
   certain worth it anyway, because it should for example provide a much better
   infrastructure for th handling of different architectures.
parent ab08629c
...@@ -33,16 +33,16 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then ...@@ -33,16 +33,16 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI
comment 'IDE chipset support' comment 'ATA host chipset support'
dep_bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86 dep_bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86
dep_bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED $CONFIG_BLK_DEV_CMD640 dep_bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED $CONFIG_BLK_DEV_CMD640
dep_bool ' ISA-PNP EIDE support' CONFIG_BLK_DEV_ISAPNP $CONFIG_ISAPNP dep_bool ' ISA-PNP support' CONFIG_BLK_DEV_ISAPNP $CONFIG_ISAPNP
if [ "$CONFIG_PCI" = "y" ]; then if [ "$CONFIG_PCI" = "y" ]; then
dep_bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86 dep_bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86
bool ' Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI bool ' PCI host chipset support' CONFIG_BLK_DEV_IDEPCI
if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then
bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
bool ' Sharing PCI IDE interrupts support' CONFIG_IDEPCI_SHARE_IRQ bool ' Sharing PCI ATA interrupts support' CONFIG_IDEPCI_SHARE_IRQ
bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO dep_bool ' Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO
...@@ -82,11 +82,9 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then ...@@ -82,11 +82,9 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86 dep_bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
dep_bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' VIA chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' VIA chipset support' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 $CONFIG_BLK_DEV_IDEDMA_PCI
fi fi
if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
fi
fi fi
if [ "$CONFIG_ALL_PPC" = "y" ]; then if [ "$CONFIG_ALL_PPC" = "y" ]; then
bool ' Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC bool ' Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC
......
...@@ -437,7 +437,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -437,7 +437,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (id && (id->capability & 1) && drive->channel->autodma) { if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive, NULL)) { if (udma_black_list(drive)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
} }
...@@ -459,7 +459,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -459,7 +459,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on) if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if (ide_dmaproc(ide_dma_good_drive, drive, NULL)) { } else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) { if (id->eide_dma_time > 150) {
goto no_dma_set; goto no_dma_set;
} }
......
...@@ -441,7 +441,7 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive) ...@@ -441,7 +441,7 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) { if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive, NULL)) { if (udma_black_list(drive)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
} }
...@@ -463,7 +463,7 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive) ...@@ -463,7 +463,7 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
if (dma_func != ide_dma_on) if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if (ide_dmaproc(ide_dma_good_drive, drive, NULL)) { } else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) { if (id->eide_dma_time > 150) {
goto no_dma_set; goto no_dma_set;
} }
...@@ -483,21 +483,25 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive) ...@@ -483,21 +483,25 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
return hwif->udma(dma_func, drive, NULL); return hwif->udma(dma_func, drive, NULL);
} }
static int ali15x3_udma_write(struct ata_device *drive, struct request *rq)
{
if ((m5229_revision < 0xC2) && (drive->type != ATA_DISK))
return 1; /* try PIO instead of DMA */
return ata_do_udma(0, drive, rq);
}
static int ali15x3_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq) static int ali15x3_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
switch(func) { switch(func) {
case ide_dma_check: case ide_dma_check:
return ali15x3_config_drive_for_dma(drive); return ali15x3_config_drive_for_dma(drive);
case ide_dma_write:
if ((m5229_revision < 0xC2) && (drive->type != ATA_DISK))
return 1; /* try PIO instead of DMA */
break;
default: default:
break; break;
} }
return ide_dmaproc(func, drive, rq); /* use standard DMA stuff */ return ide_dmaproc(func, drive, rq); /* use standard DMA stuff */
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif
unsigned int __init pci_init_ali15x3(struct pci_dev *dev) unsigned int __init pci_init_ali15x3(struct pci_dev *dev)
{ {
...@@ -679,6 +683,7 @@ void __init ide_init_ali15x3(struct ata_channel *hwif) ...@@ -679,6 +683,7 @@ void __init ide_init_ali15x3(struct ata_channel *hwif)
/* /*
* M1543C or newer for DMAing * M1543C or newer for DMAing
*/ */
hwif->udma_write = ali15x3_udma_write;
hwif->udma = ali15x3_dmaproc; hwif->udma = ali15x3_dmaproc;
hwif->autodma = 1; hwif->autodma = 1;
} }
......
...@@ -783,7 +783,7 @@ static int cmd64x_config_drive_for_dma(struct ata_device *drive) ...@@ -783,7 +783,7 @@ static int cmd64x_config_drive_for_dma(struct ata_device *drive)
if ((id != NULL) && ((id->capability & 1) != 0) && if ((id != NULL) && ((id->capability & 1) != 0) &&
hwif->autodma && (drive->type == ATA_DISK)) { hwif->autodma && (drive->type == ATA_DISK)) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive, NULL)) { if (udma_black_list(drive)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
} }
...@@ -805,7 +805,7 @@ static int cmd64x_config_drive_for_dma(struct ata_device *drive) ...@@ -805,7 +805,7 @@ static int cmd64x_config_drive_for_dma(struct ata_device *drive)
if (dma_func != ide_dma_on) if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if (ide_dmaproc(ide_dma_good_drive, drive, NULL)) { } else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) { if (id->eide_dma_time > 150) {
goto no_dma_set; goto no_dma_set;
} }
...@@ -837,20 +837,14 @@ static int cmd680_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc ...@@ -837,20 +837,14 @@ static int cmd680_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc
return ide_dmaproc(func, drive, rq); return ide_dmaproc(func, drive, rq);
} }
static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq) static int cmd64x_udma_stop(struct ata_device *drive)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
u8 dma_stat = 0; u8 dma_stat = 0;
u8 dma_alt_stat = 0;
u8 mask = (ch->unit) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0;
unsigned long dma_base = ch->dma_base; unsigned long dma_base = ch->dma_base;
struct pci_dev *dev = ch->pci_dev; struct pci_dev *dev = ch->pci_dev;
byte jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0; u8 jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0;
switch (func) {
case ide_dma_check:
return cmd64x_config_drive_for_dma(drive);
case ide_dma_end: /* returns 1 on error, 0 otherwise */
drive->waiting_for_dma = 0; drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */ outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */ dma_stat = inb(dma_base+2); /* get DMA status */
...@@ -869,6 +863,20 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc ...@@ -869,6 +863,20 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc
} }
udma_destroy_table(ch); /* purge DMA mappings */ udma_destroy_table(ch); /* purge DMA mappings */
return (dma_stat & 7) != 4; /* verify good DMA status */ return (dma_stat & 7) != 4; /* verify good DMA status */
}
static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{
struct ata_channel *ch = drive->channel;
u8 dma_stat = 0;
u8 dma_alt_stat = 0;
u8 mask = (ch->unit) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0;
unsigned long dma_base = ch->dma_base;
struct pci_dev *dev = ch->pci_dev;
switch (func) {
case ide_dma_check:
return cmd64x_config_drive_for_dma(drive);
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
dma_stat = inb(dma_base+2); dma_stat = inb(dma_base+2);
(void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat); (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat);
...@@ -886,26 +894,29 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc ...@@ -886,26 +894,29 @@ static int cmd64x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc
return ide_dmaproc(func, drive, rq); return ide_dmaproc(func, drive, rq);
} }
/* static int cmd646_1_udma_stop(struct ata_device *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, struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
unsigned long dma_base = ch->dma_base; unsigned long dma_base = ch->dma_base;
byte dma_stat; u8 dma_stat;
switch (func) {
case ide_dma_check:
return cmd64x_config_drive_for_dma(drive);
case ide_dma_end:
drive->waiting_for_dma = 0; drive->waiting_for_dma = 0;
dma_stat = inb(dma_base+2); /* get DMA status */ dma_stat = inb(dma_base+2); /* get DMA status */
outb(inb(dma_base)&~1, dma_base); /* stop DMA */ outb(inb(dma_base)&~1, dma_base); /* stop DMA */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
udma_destroy_table(ch); /* and free any DMA resources */ udma_destroy_table(ch); /* and free any DMA resources */
return (dma_stat & 7) != 4; /* verify good DMA status */ return (dma_stat & 7) != 4; /* verify good DMA status */
}
/*
* 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, struct ata_device *drive, struct request *rq)
{
switch (func) {
case ide_dma_check:
return cmd64x_config_drive_for_dma(drive);
default: default:
break; break;
} }
...@@ -1134,19 +1145,22 @@ void __init ide_init_cmd64x(struct ata_channel *hwif) ...@@ -1134,19 +1145,22 @@ void __init ide_init_cmd64x(struct ata_channel *hwif)
case PCI_DEVICE_ID_CMD_649: case PCI_DEVICE_ID_CMD_649:
case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_648:
case PCI_DEVICE_ID_CMD_643: case PCI_DEVICE_ID_CMD_643:
hwif->udma = &cmd64x_dmaproc; hwif->udma_stop = cmd64x_udma_stop;
hwif->tuneproc = &cmd64x_tuneproc; hwif->udma = cmd64x_dmaproc;
hwif->speedproc = &cmd64x_tune_chipset; hwif->tuneproc = cmd64x_tuneproc;
hwif->speedproc = cmd64x_tune_chipset;
break; break;
case PCI_DEVICE_ID_CMD_646: case PCI_DEVICE_ID_CMD_646:
hwif->chipset = ide_cmd646; hwif->chipset = ide_cmd646;
if (class_rev == 0x01) { if (class_rev == 0x01) {
hwif->udma_stop = &cmd646_1_udma_stop;
hwif->udma = &cmd646_1_dmaproc; hwif->udma = &cmd646_1_dmaproc;
} else { } else {
hwif->udma = &cmd64x_dmaproc; hwif->udma_stop = cmd64x_udma_stop;
hwif->udma = cmd64x_dmaproc;
} }
hwif->tuneproc = &cmd64x_tuneproc; hwif->tuneproc = cmd64x_tuneproc;
hwif->speedproc = &cmd64x_tune_chipset; hwif->speedproc = cmd64x_tune_chipset;
break; break;
default: default:
break; break;
......
...@@ -158,7 +158,7 @@ static int cs5530_config_dma (ide_drive_t *drive) ...@@ -158,7 +158,7 @@ static int cs5530_config_dma (ide_drive_t *drive)
*/ */
if (mate->present) { if (mate->present) {
struct hd_driveid *mateid = mate->id; struct hd_driveid *mateid = mate->id;
if (mateid && (mateid->capability & 1) && !hwif->udma(ide_dma_bad_drive, mate, NULL)) { if (mateid && (mateid->capability & 1) && !udma_black_list(mate)) {
if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
udma_ok = 1; udma_ok = 1;
else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
...@@ -172,7 +172,7 @@ static int cs5530_config_dma (ide_drive_t *drive) ...@@ -172,7 +172,7 @@ static int cs5530_config_dma (ide_drive_t *drive)
* Now see what the current drive is capable of, * Now see what the current drive is capable of,
* selecting UDMA only if the mate said it was ok. * selecting UDMA only if the mate said it was ok.
*/ */
if (id && (id->capability & 1) && hwif->autodma && !hwif->udma(ide_dma_bad_drive, drive, NULL)) { if (id && (id->capability & 1) && hwif->autodma && !udma_black_list(drive)) {
if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
if (id->dma_ultra & 4) if (id->dma_ultra & 4)
mode = XFER_UDMA_2; mode = XFER_UDMA_2;
......
...@@ -256,7 +256,7 @@ static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq) ...@@ -256,7 +256,7 @@ static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq)
if (id && (id->capability & 1) && drive->channel->autodma) { if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive, rq)) { if (udma_black_list(drive)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
} }
...@@ -278,7 +278,7 @@ static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq) ...@@ -278,7 +278,7 @@ static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq)
if (dma_func != ide_dma_on) if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if (ide_dmaproc(ide_dma_good_drive, drive, rq)) { } else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) { if (id->eide_dma_time > 150) {
goto no_dma_set; goto no_dma_set;
} }
...@@ -304,52 +304,73 @@ static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq) ...@@ -304,52 +304,73 @@ static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq)
return drive->channel->udma(dma_func, drive, rq); return drive->channel->udma(dma_func, drive, rq);
} }
/* static int hpt34x_udma_stop(struct ata_device *drive)
* hpt34x_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. {
* struct ata_channel *ch = drive->channel;
* This is specific to the HPT343 UDMA bios-less chipset unsigned long dma_base = ch->dma_base;
* and HPT345 UDMA bios chipset (stamped HPT363) u8 dma_stat;
* by HighPoint|Triones Technologies, Inc.
*/
int hpt34x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq) drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
udma_destroy_table(ch); /* purge DMA mappings */
return (dma_stat & 7) != 4; /* verify good DMA status */
}
static int do_udma(unsigned int reading, struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
unsigned long dma_base = ch->dma_base; unsigned long dma_base = ch->dma_base;
unsigned int count, reading = 0; unsigned int count;
byte dma_stat;
switch (func) {
case ide_dma_check:
return config_drive_xfer_rate(drive, rq);
case ide_dma_read:
reading = 1 << 3;
case ide_dma_write:
if (!(count = udma_new_table(ch, rq))) if (!(count = udma_new_table(ch, rq)))
return 1; /* try PIO instead of DMA */ return 1; /* try PIO instead of DMA */
outl(ch->dmatable_dma, dma_base + 4); /* PRD table */ outl(ch->dmatable_dma, dma_base + 4); /* PRD table */
reading |= 0x01; reading |= 0x01;
outb(reading, dma_base); /* specify r/w */ outb(reading, dma_base); /* specify r/w */
outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
drive->waiting_for_dma = 1; drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK) if (drive->type != ATA_DISK)
return 0; return 0;
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */
OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
return 0; return 0;
case ide_dma_end: /* returns 1 on error, 0 otherwise */ }
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */ static int hpt34x_udma_read(struct ata_device *drive, struct request *rq)
dma_stat = inb(dma_base+2); /* get DMA status */ {
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ return do_udma(1 << 3, drive, rq);
udma_destroy_table(ch); /* purge DMA mappings */ }
return (dma_stat & 7) != 4; /* verify good DMA status */
static int hpt34x_udma_write(struct ata_device *drive, struct request *rq)
{
return do_udma(0, drive, rq);
}
/*
* hpt34x_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
*
* This is specific to the HPT343 UDMA bios-less chipset
* and HPT345 UDMA bios chipset (stamped HPT363)
* by HighPoint|Triones Technologies, Inc.
*/
int hpt34x_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{
switch (func) {
case ide_dma_check:
return config_drive_xfer_rate(drive, rq);
default: default:
break; break;
} }
return ide_dmaproc(func, drive, rq); /* use standard DMA stuff */ return ide_dmaproc(func, drive, rq); /* use standard DMA stuff */
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif
/* /*
* If the BIOS does not set the IO base addaress to XX00, 343 will fail. * If the BIOS does not set the IO base addaress to XX00, 343 will fail.
...@@ -423,7 +444,10 @@ void __init ide_init_hpt34x(struct ata_channel *hwif) ...@@ -423,7 +444,10 @@ void __init ide_init_hpt34x(struct ata_channel *hwif)
else else
hwif->autodma = 0; hwif->autodma = 0;
hwif->udma = &hpt34x_dmaproc; hwif->udma_stop = hpt34x_udma_stop;
hwif->udma_read = hpt34x_udma_read;
hwif->udma_write = hpt34x_udma_write;
hwif->udma = hpt34x_dmaproc;
hwif->highmem = 1; hwif->highmem = 1;
} else { } else {
hwif->drives[0].autotune = 1; hwif->drives[0].autotune = 1;
......
...@@ -748,7 +748,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -748,7 +748,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (id && (id->capability & 1) && drive->channel->autodma) { if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive, NULL)) { if (udma_black_list(drive)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
} }
...@@ -769,7 +769,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -769,7 +769,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on) if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if (ide_dmaproc(ide_dma_good_drive, drive, NULL)) { } else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) { if (id->eide_dma_time > 150) {
goto no_dma_set; goto no_dma_set;
} }
...@@ -830,6 +830,86 @@ int hpt366_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct reque ...@@ -830,6 +830,86 @@ int hpt366_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct reque
return ide_dmaproc(func, drive, rq); /* use standard DMA stuff */ return ide_dmaproc(func, drive, rq); /* use standard DMA stuff */
} }
static void do_udma_start(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
u8 regstate = ch->unit ? 0x54 : 0x50;
pci_write_config_byte(ch->pci_dev, regstate, 0x37);
udelay(10);
}
static int hpt370_udma_start(struct ata_device *drive, struct request *__rq)
{
struct ata_channel *ch = drive->channel;
do_udma_start(drive);
/* Note that this is done *after* the cmd has been issued to the drive,
* as per the BM-IDE spec. The Promise Ultra33 doesn't work correctly
* when we do this part before issuing the drive cmd.
*/
outb(inb(ch->dma_base) | 1, ch->dma_base); /* start DMA */
return 0;
}
static void do_timeout_irq(struct ata_device *drive)
{
u8 dma_stat;
u8 regstate = drive->channel->unit ? 0x54 : 0x50;
u8 reginfo = drive->channel->unit ? 0x56 : 0x52;
unsigned long dma_base = drive->channel->dma_base;
pci_read_config_byte(drive->channel->pci_dev, reginfo, &dma_stat);
printk(KERN_INFO "%s: %d bytes in FIFO\n", drive->name, dma_stat);
pci_write_config_byte(drive->channel->pci_dev, regstate, 0x37);
udelay(10);
dma_stat = inb(dma_base);
outb(dma_stat & ~0x1, dma_base); /* stop dma */
dma_stat = inb(dma_base + 2);
outb(dma_stat | 0x6, dma_base+2); /* clear errors */
}
static void hpt370_udma_timeout(struct ata_device *drive)
{
do_timeout_irq(drive);
do_udma_start(drive);
}
static void hpt370_udma_lost_irq(struct ata_device *drive)
{
do_timeout_irq(drive);
do_udma_start(drive);
}
static int hpt370_udma_stop(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
dma_stat = inb(dma_base + 2);
if (dma_stat & 0x01) {
udelay(20); /* wait a little */
dma_stat = inb(dma_base + 2);
}
if ((dma_stat & 0x01) != 0) {
do_timeout_irq(drive);
do_udma_start(drive);
}
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
udma_destroy_table(ch); /* purge DMA mappings */
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */
}
int hpt370_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq) int hpt370_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
...@@ -845,18 +925,6 @@ int hpt370_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct reque ...@@ -845,18 +925,6 @@ int hpt370_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct reque
dma_stat = inb(dma_base+2); dma_stat = inb(dma_base+2);
return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
case ide_dma_end:
dma_stat = inb(dma_base + 2);
if (dma_stat & 0x01) {
udelay(20); /* wait a little */
dma_stat = inb(dma_base + 2);
}
if ((dma_stat & 0x01) == 0)
break;
func = ide_dma_timeout;
/* fallthrough */
case ide_dma_timeout: case ide_dma_timeout:
case ide_dma_lostirq: case ide_dma_lostirq:
pci_read_config_byte(hwif->pci_dev, reginfo, pci_read_config_byte(hwif->pci_dev, reginfo,
...@@ -871,11 +939,7 @@ int hpt370_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct reque ...@@ -871,11 +939,7 @@ int hpt370_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct reque
outb(dma_stat | 0x6, dma_base+2); /* clear errors */ outb(dma_stat | 0x6, dma_base+2); /* clear errors */
/* fallthrough */ /* fallthrough */
#ifdef HPT_RESET_STATE_ENGINE do_udma_start(drive);
case ide_dma_begin:
#endif
pci_write_config_byte(hwif->pci_dev, regstate, 0x37);
udelay(10);
break; break;
default: default:
...@@ -883,7 +947,7 @@ int hpt370_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct reque ...@@ -883,7 +947,7 @@ int hpt370_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct reque
} }
return ide_dmaproc(func, drive, rq); /* use standard DMA stuff */ return ide_dmaproc(func, drive, rq); /* use standard DMA stuff */
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif
/* /*
* Since SUN Cobalt is attempting to do this operation, I should disclose * Since SUN Cobalt is attempting to do this operation, I should disclose
...@@ -1183,6 +1247,8 @@ void __init ide_init_hpt366(struct ata_channel *hwif) ...@@ -1183,6 +1247,8 @@ void __init ide_init_hpt366(struct ata_channel *hwif)
pci_read_config_byte(hwif->pci_dev, 0x5a, &reg5ah); pci_read_config_byte(hwif->pci_dev, 0x5a, &reg5ah);
if (reg5ah & 0x10) /* interrupt force enable */ if (reg5ah & 0x10) /* interrupt force enable */
pci_write_config_byte(hwif->pci_dev, 0x5a, reg5ah & ~0x10); pci_write_config_byte(hwif->pci_dev, 0x5a, reg5ah & ~0x10);
hwif->udma_start = hpt370_udma_start;
hwif->udma_stop = hpt370_udma_stop;
hwif->udma = hpt370_dmaproc; hwif->udma = hpt370_dmaproc;
} else { } else {
hwif->udma = hpt366_dmaproc; hwif->udma = hpt366_dmaproc;
......
...@@ -737,9 +737,9 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, ...@@ -737,9 +737,9 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive,
if (info->dma) { if (info->dma) {
if (info->cmd == READ) if (info->cmd == READ)
info->dma = !drive->channel->udma(ide_dma_read, drive, rq); info->dma = !udma_read(drive, rq);
else if (info->cmd == WRITE) else if (info->cmd == WRITE)
info->dma = !drive->channel->udma(ide_dma_write, drive, rq); info->dma = !udma_write(drive, rq);
else else
printk("ide-cd: DMA set, but not allowed\n"); printk("ide-cd: DMA set, but not allowed\n");
} }
...@@ -755,7 +755,7 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, ...@@ -755,7 +755,7 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive,
OUT_BYTE (drive->ctl, IDE_CONTROL_REG); OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
if (info->dma) if (info->dma)
drive->channel->udma(ide_dma_begin, drive, NULL); udma_start(drive, rq);
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
ide_set_handler(drive, handler, WAIT_CMD, cdrom_timer_expiry); ide_set_handler(drive, handler, WAIT_CMD, cdrom_timer_expiry);
...@@ -905,7 +905,7 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request ...@@ -905,7 +905,7 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request
/* Check for errors. */ /* Check for errors. */
if (dma) { if (dma) {
info->dma = 0; info->dma = 0;
if ((dma_error = drive->channel->udma(ide_dma_end, drive, NULL))) if ((dma_error = udma_stop(drive)))
drive->channel->udma(ide_dma_off, drive, NULL); drive->channel->udma(ide_dma_off, drive, NULL);
} }
...@@ -1480,7 +1480,7 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request ...@@ -1480,7 +1480,7 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request
/* Check for errors. */ /* Check for errors. */
if (dma) { if (dma) {
info->dma = 0; info->dma = 0;
if ((dma_error = drive->channel->udma(ide_dma_end, drive, NULL))) { if ((dma_error = udma_stop(drive))) {
printk("ide-cd: write dma error\n"); printk("ide-cd: write dma error\n");
drive->channel->udma(ide_dma_off, drive, NULL); drive->channel->udma(ide_dma_off, drive, NULL);
} }
......
This diff is collapsed.
...@@ -901,7 +901,7 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques ...@@ -901,7 +901,7 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
if (drive->channel->udma(ide_dma_end, drive, NULL)) { if (udma_stop(drive)) {
set_bit (PC_DMA_ERROR, &pc->flags); set_bit (PC_DMA_ERROR, &pc->flags);
} else { } else {
pc->actually_transferred=pc->request_transfer; pc->actually_transferred=pc->request_transfer;
...@@ -1122,8 +1122,12 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque ...@@ -1122,8 +1122,12 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque
if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) { if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
(void) drive->channel->udma(ide_dma_off, drive, NULL); (void) drive->channel->udma(ide_dma_off, drive, NULL);
} }
if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) {
dma_ok=!drive->channel->udma(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive, rq); if (test_bit (PC_WRITING, &pc->flags))
dma_ok = !udma_write(drive, rq);
else
dma_ok = !udma_read(drive, rq);
}
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif /* CONFIG_BLK_DEV_IDEDMA */
if (IDE_CONTROL_REG) if (IDE_CONTROL_REG)
...@@ -1136,7 +1140,7 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque ...@@ -1136,7 +1140,7 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (dma_ok) { /* Begin DMA, if necessary */ if (dma_ok) { /* Begin DMA, if necessary */
set_bit (PC_DMA_IN_PROGRESS, &pc->flags); set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
(void) drive->channel->udma(ide_dma_begin, drive, NULL); udma_start(drive, rq);
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif /* CONFIG_BLK_DEV_IDEDMA */
......
...@@ -709,7 +709,7 @@ static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device * ...@@ -709,7 +709,7 @@ static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device *
d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD;
} }
printk("%s: chipset revision %d\n", dev->name, class_rev); printk(KERN_INFO "ATA: chipset rev.: %d\n", class_rev);
/* /*
* Can we trust the reported IRQ? * Can we trust the reported IRQ?
...@@ -722,11 +722,11 @@ static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device * ...@@ -722,11 +722,11 @@ static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device *
to act otherwise on those. The Supertrak however we need to act otherwise on those. The Supertrak however we need
to skip */ to skip */
if (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20265) { if (d->vendor == PCI_VENDOR_ID_PROMISE && d->device == PCI_DEVICE_ID_PROMISE_20265) {
printk(KERN_INFO "ide: Found promise 20265 in RAID mode.\n"); printk(KERN_INFO "ATA: Found promise 20265 in RAID mode.\n");
if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL && if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL &&
dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960)
{ {
printk(KERN_INFO "ide: Skipping Promise PDC20265 attached to I2O RAID controller.\n"); printk(KERN_INFO "ATA: Skipping Promise PDC20265 attached to I2O RAID controller.\n");
return; return;
} }
} }
...@@ -734,9 +734,10 @@ static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device * ...@@ -734,9 +734,10 @@ static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device *
Suspect a fastrak and fall through */ Suspect a fastrak and fall through */
} }
if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
printk("%s: not 100%% native mode: will probe irqs later\n", dev->name); printk(KERN_INFO "ATA: non-legacy mode: IRQ probe delayed\n");
/* /*
* This allows off board ide-pci cards the enable a BIOS, * This allows off board ide-pci cards to enable a BIOS,
* verify interrupt settings of split-mirror pci-config * verify interrupt settings of split-mirror pci-config
* space, place chipset into init-mode, and/or preserve * space, place chipset into init-mode, and/or preserve
* an interrupt if the card is not native ide support. * an interrupt if the card is not native ide support.
...@@ -746,19 +747,18 @@ static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device * ...@@ -746,19 +747,18 @@ static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device *
else else
pciirq = trust_pci_irq(d, dev); pciirq = trust_pci_irq(d, dev);
} else if (tried_config) { } else if (tried_config) {
printk("%s: will probe IRQs later\n", dev->name); printk(KERN_INFO "ATA: will probe IRQs later\n");
pciirq = 0; pciirq = 0;
} else if (!pciirq) { } else if (!pciirq) {
printk("%s: bad IRQ (%d): will probe later\n", dev->name, pciirq); printk(KERN_INFO "ATA: invalid IRQ (%d): will probe later\n", pciirq);
pciirq = 0; pciirq = 0;
} else { } else {
if (d->init_chipset) if (d->init_chipset)
d->init_chipset(dev); d->init_chipset(dev);
#ifdef __sparc__ #ifdef __sparc__
printk("%s: 100%% native mode on irq %s\n", printk(KERN_INFO "ATA: 100%% native mode on irq\n", __irq_itoa(pciirq));
dev->name, __irq_itoa(pciirq));
#else #else
printk("%s: 100%% native mode on irq %d\n", dev->name, pciirq); printk(KERN_INFO "ATA: 100%% native mode on irq %d\n", pciirq);
#endif #endif
} }
...@@ -889,10 +889,10 @@ static void __init scan_pcidev(struct pci_dev *dev) ...@@ -889,10 +889,10 @@ static void __init scan_pcidev(struct pci_dev *dev)
pdc20270_device_order_fixup(dev, d); pdc20270_device_order_fixup(dev, d);
else if (!(d->vendor == 0 && d->device == 0) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { else if (!(d->vendor == 0 && d->device == 0) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
if (d->vendor == 0 && d->device == 0) if (d->vendor == 0 && d->device == 0)
printk(KERN_INFO "ATA: unknown ATA interface %s (%04x:%04x) on PCI slot %s\n", printk(KERN_INFO "ATA: unknown interface: %s (%04x:%04x) on PCI slot %s\n",
dev->name, vendor, device, dev->slot_name); dev->name, vendor, device, dev->slot_name);
else else
printk(KERN_INFO "ATA: interface %s on PCI slot %s\n", dev->name, dev->slot_name); printk(KERN_INFO "ATA: interface: %s, on PCI slot %s\n", dev->name, dev->slot_name);
setup_pci_device(dev, d); setup_pci_device(dev, d);
} }
} }
......
...@@ -1449,7 +1449,6 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str ...@@ -1449,7 +1449,6 @@ static int pmac_ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, str
case ide_dma_bad_drive: case ide_dma_bad_drive:
case ide_dma_good_drive: case ide_dma_good_drive:
return check_drive_lists(drive, (func == ide_dma_good_drive)); return check_drive_lists(drive, (func == ide_dma_good_drive));
case ide_dma_retune:
case ide_dma_lostirq: case ide_dma_lostirq:
case ide_dma_timeout: case ide_dma_timeout:
printk(KERN_WARNING "ide_pmac_dmaproc: chipset supported func only: %d\n", func); printk(KERN_WARNING "ide_pmac_dmaproc: chipset supported func only: %d\n", func);
......
...@@ -2058,7 +2058,7 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request ...@@ -2058,7 +2058,7 @@ static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
if (drive->channel->udma(ide_dma_end, drive, NULL)) { if (udma_stop(drive)) {
/* /*
* A DMA error is sometimes expected. For example, * A DMA error is sometimes expected. For example,
* if the tape is crossing a filemark during a * if the tape is crossing a filemark during a
...@@ -2311,9 +2311,13 @@ static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive, st ...@@ -2311,9 +2311,13 @@ static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive, st
printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n"); printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n");
(void) drive->channel->udma(ide_dma_off, drive, NULL); (void) drive->channel->udma(ide_dma_off, drive, NULL);
} }
if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) {
dma_ok = !drive->channel->udma(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive, rq); if (test_bit (PC_WRITING, &pc->flags))
#endif /* CONFIG_BLK_DEV_IDEDMA */ dma_ok = !udma_write(drive, rq);
else
dma_ok = !udma_read(drive, rq);
}
#endif
if (IDE_CONTROL_REG) if (IDE_CONTROL_REG)
OUT_BYTE (drive->ctl, IDE_CONTROL_REG); OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
...@@ -2324,7 +2328,7 @@ static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive, st ...@@ -2324,7 +2328,7 @@ static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive, st
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (dma_ok) { /* Begin DMA, if necessary */ if (dma_ok) { /* Begin DMA, if necessary */
set_bit (PC_DMA_IN_PROGRESS, &pc->flags); set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
(void) drive->channel->udma(ide_dma_begin, drive, NULL); udma_start(drive, rq);
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif /* CONFIG_BLK_DEV_IDEDMA */
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
......
...@@ -461,7 +461,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, ...@@ -461,7 +461,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
* regular dma proc -- basically split stuff that needs to act * regular dma proc -- basically split stuff that needs to act
* on a request from things like ide_dma_check etc. * on a request from things like ide_dma_check etc.
*/ */
ide_dma_action_t dma_act;
if (!drive->using_dma) if (!drive->using_dma)
return ide_started; return ide_started;
...@@ -469,10 +468,10 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, ...@@ -469,10 +468,10 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
/* for dma commands we don't set the handler */ /* for dma commands we don't set the handler */
if (args->taskfile.command == WIN_WRITEDMA if (args->taskfile.command == WIN_WRITEDMA
|| args->taskfile.command == WIN_WRITEDMA_EXT) || args->taskfile.command == WIN_WRITEDMA_EXT)
dma_act = ide_dma_write; udma_write(drive, rq);
else if (args->taskfile.command == WIN_READDMA else if (args->taskfile.command == WIN_READDMA
|| args->taskfile.command == WIN_READDMA_EXT) || args->taskfile.command == WIN_READDMA_EXT)
dma_act = ide_dma_read; udma_read(drive, rq);
#ifdef CONFIG_BLK_DEV_IDE_TCQ #ifdef CONFIG_BLK_DEV_IDE_TCQ
else if (args->taskfile.command == WIN_WRITEDMA_QUEUED else if (args->taskfile.command == WIN_WRITEDMA_QUEUED
|| args->taskfile.command == WIN_WRITEDMA_QUEUED_EXT || args->taskfile.command == WIN_WRITEDMA_QUEUED_EXT
...@@ -484,10 +483,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, ...@@ -484,10 +483,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
printk("ata_taskfile: unknown command %x\n", args->taskfile.command); printk("ata_taskfile: unknown command %x\n", args->taskfile.command);
return ide_stopped; return ide_stopped;
} }
if (drive->channel->udma(dma_act, drive, rq))
return ide_stopped;
} }
return ide_started; return ide_started;
......
...@@ -1407,7 +1407,7 @@ static void dma_timeout_retry(struct ata_device *drive, struct request *rq) ...@@ -1407,7 +1407,7 @@ static void dma_timeout_retry(struct ata_device *drive, struct request *rq)
/* /*
* end current dma transaction * end current dma transaction
*/ */
ch->udma(ide_dma_end, drive, rq); ch->udma_stop(drive);
/* /*
* complain a little, later we might remove some of this verbosity * complain a little, later we might remove some of this verbosity
...@@ -2127,6 +2127,13 @@ void ide_unregister(struct ata_channel *ch) ...@@ -2127,6 +2127,13 @@ void ide_unregister(struct ata_channel *ch)
ch->atapi_read = old.atapi_read; ch->atapi_read = old.atapi_read;
ch->atapi_write = old.atapi_write; ch->atapi_write = old.atapi_write;
ch->udma = old.udma; ch->udma = old.udma;
ch->udma_start = old.udma_start;
ch->udma_stop = old.udma_stop;
ch->udma_read = old.udma_read;
ch->udma_write = old.udma_write;
ch->udma_irq_status = old.udma_irq_status;
ch->udma_timeout = old.udma_timeout;
ch->udma_lost_irq = old.udma_lost_irq;
ch->busproc = old.busproc; ch->busproc = old.busproc;
ch->bus_state = old.bus_state; ch->bus_state = old.bus_state;
ch->dma_base = old.dma_base; ch->dma_base = old.dma_base;
......
...@@ -82,26 +82,50 @@ static void ns87415_selectproc (ide_drive_t *drive) ...@@ -82,26 +82,50 @@ static void ns87415_selectproc (ide_drive_t *drive)
} }
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
static int ns87415_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
static int ns87415_udma_stop(struct ata_device *drive)
{ {
struct ata_channel *hwif = drive->channel; struct ata_channel *ch = drive->channel;
byte dma_stat; unsigned long dma_base = ch->dma_base;
u8 dma_stat;
switch (func) {
case ide_dma_end: /* returns 1 on error, 0 otherwise */
drive->waiting_for_dma = 0; drive->waiting_for_dma = 0;
dma_stat = inb(hwif->dma_base+2); dma_stat = inb(ch->dma_base+2);
outb(inb(hwif->dma_base)&~1, hwif->dma_base); /* stop DMA */ outb(inb(dma_base)&~1, dma_base); /* stop DMA */
outb(inb(hwif->dma_base)|6, hwif->dma_base); /* from ERRATA: clear the INTR & ERROR bits */ outb(inb(dma_base)|6, dma_base); /* from ERRATA: clear the INTR & ERROR bits */
udma_destroy_table(hwif); /* and free any DMA resources */ udma_destroy_table(ch); /* and free any DMA resources */
return (dma_stat & 7) != 4; /* verify good DMA status */ return (dma_stat & 7) != 4; /* verify good DMA status */
case ide_dma_write:
case ide_dma_read: }
static int ns87415_udma_read(struct ata_device *drive, struct request *rq)
{
ns87415_prepare_drive(drive, 1); /* select DMA xfer */ ns87415_prepare_drive(drive, 1); /* select DMA xfer */
if (!ide_dmaproc(func, drive, rq)) /* use standard DMA stuff */
if (!ata_do_udma(1, drive, rq)) /* use standard DMA stuff */
return 0; return 0;
ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */
return 1; return 1;
}
static int ns87415_udma_write(struct ata_device *drive, struct request *rq)
{
ns87415_prepare_drive(drive, 1); /* select DMA xfer */
if (!ata_do_udma(0, drive, rq)) /* use standard DMA stuff */
return 0;
ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */
return 1;
}
static int ns87415_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{
switch (func) {
case ide_dma_check: case ide_dma_check:
if (drive->type != ATA_DISK) if (drive->type != ATA_DISK)
return ide_dmaproc(ide_dma_off_quietly, drive, rq); return ide_dmaproc(ide_dma_off_quietly, drive, rq);
...@@ -205,8 +229,12 @@ void __init ide_init_ns87415(struct ata_channel *hwif) ...@@ -205,8 +229,12 @@ void __init ide_init_ns87415(struct ata_channel *hwif)
} }
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) if (hwif->dma_base) {
hwif->udma_stop = ns87415_udma_stop;
hwif->udma_read = ns87415_udma_read;
hwif->udma_write = ns87415_udma_write;
hwif->udma = ns87415_dmaproc; hwif->udma = ns87415_dmaproc;
}
#endif #endif
hwif->selectproc = &ns87415_selectproc; hwif->selectproc = &ns87415_selectproc;
......
...@@ -929,7 +929,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -929,7 +929,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (id && (id->capability & 1) && hwif->autodma) { if (id && (id->capability & 1) && hwif->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive, NULL)) { if (udma_black_list(drive)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
} }
...@@ -951,7 +951,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -951,7 +951,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on) if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if (ide_dmaproc(ide_dma_good_drive, drive, NULL)) { } else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) { if (id->eide_dma_time > 150) {
goto no_dma_set; goto no_dma_set;
} }
...@@ -977,21 +977,15 @@ int pdc202xx_quirkproc (ide_drive_t *drive) ...@@ -977,21 +977,15 @@ int pdc202xx_quirkproc (ide_drive_t *drive)
return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); return ((int) check_in_drive_lists(drive, pdc_quirk_drives));
} }
/* static int pdc202xx_udma_start(struct ata_device *drive, struct request *rq)
* pdc202xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
*/
int pdc202xx_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
byte dma_stat = 0; u8 clock = 0;
byte sc1d = 0; u8 hardware48hack = 0;
byte newchip = 0; struct ata_channel *ch = drive->channel;
byte clock = 0; struct pci_dev *dev = ch->pci_dev;
byte hardware48hack = 0;
struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev;
unsigned long high_16 = pci_resource_start(dev, 4); unsigned long high_16 = pci_resource_start(dev, 4);
unsigned long atapi_reg = high_16 + (hwif->unit ? 0x24 : 0x00); unsigned long atapi_reg = high_16 + (ch->unit ? 0x24 : 0x00);
unsigned long dma_base = hwif->dma_base;
switch (dev->device) { switch (dev->device) {
case PCI_DEVICE_ID_PROMISE_20275: case PCI_DEVICE_ID_PROMISE_20275:
...@@ -999,7 +993,6 @@ int pdc202xx_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct req ...@@ -999,7 +993,6 @@ int pdc202xx_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct req
case PCI_DEVICE_ID_PROMISE_20269: case PCI_DEVICE_ID_PROMISE_20269:
case PCI_DEVICE_ID_PROMISE_20268R: case PCI_DEVICE_ID_PROMISE_20268R:
case PCI_DEVICE_ID_PROMISE_20268: case PCI_DEVICE_ID_PROMISE_20268:
newchip = 1;
break; break;
case PCI_DEVICE_ID_PROMISE_20267: case PCI_DEVICE_ID_PROMISE_20267:
case PCI_DEVICE_ID_PROMISE_20265: case PCI_DEVICE_ID_PROMISE_20265:
...@@ -1010,32 +1003,103 @@ int pdc202xx_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct req ...@@ -1010,32 +1003,103 @@ int pdc202xx_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct req
break; break;
} }
switch (func) {
case ide_dma_check:
return config_drive_xfer_rate(drive);
case ide_dma_begin:
/* Note that this is done *after* the cmd has
* been issued to the drive, as per the BM-IDE spec.
* The Promise Ultra33 doesn't work correctly when
* we do this part before issuing the drive cmd.
*/
if ((drive->addressing) && (hardware48hack)) { if ((drive->addressing) && (hardware48hack)) {
struct request *rq = HWGROUP(drive)->rq;
unsigned long word_count = 0; unsigned long word_count = 0;
outb(clock|(hwif->unit ? 0x08 : 0x02), high_16 + 0x11); outb(clock|(ch->unit ? 0x08 : 0x02), high_16 + 0x11);
word_count = (rq->nr_sectors << 8); word_count = (rq->nr_sectors << 8);
word_count = (rq_data_dir(rq) == READ) ? word_count | 0x05000000 : word_count | 0x06000000; word_count = (rq_data_dir(rq) == READ) ? word_count | 0x05000000 : word_count | 0x06000000;
outl(word_count, atapi_reg); outl(word_count, atapi_reg);
} }
/* Note that this is done *after* the cmd has been issued to the drive,
* as per the BM-IDE spec. The Promise Ultra33 doesn't work correctly
* when we do this part before issuing the drive cmd.
*/
outb(inb(ch->dma_base) | 1, ch->dma_base); /* start DMA */
return 0;
}
int pdc202xx_udma_stop(struct ata_device *drive)
{
u8 newchip = 0;
u8 clock = 0;
u8 hardware48hack = 0;
struct ata_channel *ch = drive->channel;
struct pci_dev *dev = ch->pci_dev;
unsigned long high_16 = pci_resource_start(dev, 4);
unsigned long atapi_reg = high_16 + (ch->unit ? 0x24 : 0x00);
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
switch (dev->device) {
case PCI_DEVICE_ID_PROMISE_20275:
case PCI_DEVICE_ID_PROMISE_20276:
case PCI_DEVICE_ID_PROMISE_20269:
case PCI_DEVICE_ID_PROMISE_20268R:
case PCI_DEVICE_ID_PROMISE_20268:
newchip = 1;
break;
case PCI_DEVICE_ID_PROMISE_20267:
case PCI_DEVICE_ID_PROMISE_20265:
case PCI_DEVICE_ID_PROMISE_20262:
hardware48hack = 1;
clock = IN_BYTE(high_16 + 0x11);
default:
break; break;
case ide_dma_end: }
if ((drive->addressing) && (hardware48hack)) { if ((drive->addressing) && (hardware48hack)) {
outl(0, atapi_reg); /* zero out extra */ outl(0, atapi_reg); /* zero out extra */
clock = IN_BYTE(high_16 + 0x11); clock = IN_BYTE(high_16 + 0x11);
OUT_BYTE(clock & ~(hwif->unit ? 0x08:0x02), high_16 + 0x11); OUT_BYTE(clock & ~(ch->unit ? 0x08:0x02), high_16 + 0x11);
} }
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
udma_destroy_table(ch); /* purge DMA mappings */
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */
}
/*
* pdc202xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
*/
int pdc202xx_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{
u8 dma_stat = 0;
u8 sc1d = 0;
u8 newchip = 0;
u8 clock = 0;
u8 hardware48hack = 0;
struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev;
unsigned long high_16 = pci_resource_start(dev, 4);
unsigned long dma_base = hwif->dma_base;
switch (dev->device) {
case PCI_DEVICE_ID_PROMISE_20275:
case PCI_DEVICE_ID_PROMISE_20276:
case PCI_DEVICE_ID_PROMISE_20269:
case PCI_DEVICE_ID_PROMISE_20268R:
case PCI_DEVICE_ID_PROMISE_20268:
newchip = 1;
break;
case PCI_DEVICE_ID_PROMISE_20267:
case PCI_DEVICE_ID_PROMISE_20265:
case PCI_DEVICE_ID_PROMISE_20262:
hardware48hack = 1;
clock = IN_BYTE(high_16 + 0x11);
default:
break; break;
}
switch (func) {
case ide_dma_check:
return config_drive_xfer_rate(drive);
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
dma_stat = IN_BYTE(dma_base+2); dma_stat = IN_BYTE(dma_base+2);
if (newchip) if (newchip)
...@@ -1268,6 +1332,8 @@ void __init ide_init_pdc202xx(struct ata_channel *hwif) ...@@ -1268,6 +1332,8 @@ void __init ide_init_pdc202xx(struct ata_channel *hwif)
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) { if (hwif->dma_base) {
hwif->udma_start = pdc202xx_udma_start;
hwif->udma_stop = pdc202xx_udma_stop;
hwif->udma = pdc202xx_dmaproc; hwif->udma = pdc202xx_dmaproc;
hwif->highmem = 1; hwif->highmem = 1;
if (!noautodma) if (!noautodma)
......
...@@ -431,14 +431,14 @@ static int config_chipset_for_dma (ide_drive_t *drive) ...@@ -431,14 +431,14 @@ static int config_chipset_for_dma (ide_drive_t *drive)
ide_dma_off_quietly); ide_dma_off_quietly);
} }
static int config_drive_xfer_rate (ide_drive_t *drive) static int config_drive_xfer_rate(struct ata_device *drive)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
ide_dma_action_t dma_func = ide_dma_on; ide_dma_action_t dma_func = ide_dma_on;
if (id && (id->capability & 1) && drive->channel->autodma) { if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive, NULL)) { if (udma_black_list(drive)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
} }
...@@ -460,7 +460,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -460,7 +460,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on) if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if (ide_dmaproc(ide_dma_good_drive, drive, NULL)) { } else if (udma_white_list(drive)) {
if (id->eide_dma_time > 150) { if (id->eide_dma_time > 150) {
goto no_dma_set; goto no_dma_set;
} }
...@@ -480,15 +480,11 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -480,15 +480,11 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
return drive->channel->udma(dma_func, drive, NULL); return drive->channel->udma(dma_func, drive, NULL);
} }
static int svwks_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq) static int svwks_udma_stop(struct ata_device *drive)
{ {
switch (func) { struct ata_channel *ch = drive->channel;
case ide_dma_check: unsigned long dma_base = ch->dma_base;
return config_drive_xfer_rate(drive); u8 dma_stat;
case ide_dma_end:
{
struct ata_channel *hwif = drive->channel;
unsigned long dma_base = hwif->dma_base;
if(inb(dma_base+0x02)&1) if(inb(dma_base+0x02)&1)
{ {
...@@ -517,8 +513,21 @@ static int svwks_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct ...@@ -517,8 +513,21 @@ static int svwks_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct
cpu_relax(); cpu_relax();
#endif #endif
} }
/* and drop through */
} drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
udma_destroy_table(ch); /* purge DMA mappings */
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */
}
static int svwks_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{
switch (func) {
case ide_dma_check:
return config_drive_xfer_rate(drive);
default: default:
break; break;
} }
...@@ -645,6 +654,7 @@ void __init ide_init_svwks(struct ata_channel *hwif) ...@@ -645,6 +654,7 @@ void __init ide_init_svwks(struct ata_channel *hwif)
if (!noautodma) if (!noautodma)
hwif->autodma = 1; hwif->autodma = 1;
#endif #endif
hwif->udma_stop = svwks_udma_stop;
hwif->udma = svwks_dmaproc; hwif->udma = svwks_dmaproc;
hwif->highmem = 1; hwif->highmem = 1;
} else { } else {
......
...@@ -685,7 +685,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -685,7 +685,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (id && (id->capability & 1) && drive->channel->autodma) { if (id && (id->capability & 1) && drive->channel->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive, NULL)) { if (udma_black_list(drive)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
} }
...@@ -707,7 +707,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) ...@@ -707,7 +707,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on) if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if ((ide_dmaproc(ide_dma_good_drive, drive, NULL)) && } else if ((udma_white_list(drive)) &&
(id->eide_dma_time > 150)) { (id->eide_dma_time > 150)) {
/* Consult the list of known "good" drives */ /* Consult the list of known "good" drives */
dma_func = config_chipset_for_dma(drive, 0); dma_func = config_chipset_for_dma(drive, 0);
......
...@@ -114,7 +114,7 @@ static int config_for_dma(ide_drive_t *drive) ...@@ -114,7 +114,7 @@ static int config_for_dma(ide_drive_t *drive)
* Check to see if the drive and * Check to see if the drive and
* chipset is capable of DMA mode * chipset is capable of DMA mode
*/ */
static int sl82c105_check_drive(ide_drive_t *drive) static int sl82c105_check_drive(ide_drive_t *drive, struct request *rq)
{ {
ide_dma_action_t dma_func = ide_dma_off_quietly; ide_dma_action_t dma_func = ide_dma_off_quietly;
...@@ -129,7 +129,7 @@ static int sl82c105_check_drive(ide_drive_t *drive) ...@@ -129,7 +129,7 @@ static int sl82c105_check_drive(ide_drive_t *drive)
break; break;
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive)) { if (udma_black_list(drive)) {
dma_func = ide_dma_off; dma_func = ide_dma_off;
break; break;
} }
...@@ -140,23 +140,23 @@ static int sl82c105_check_drive(ide_drive_t *drive) ...@@ -140,23 +140,23 @@ static int sl82c105_check_drive(ide_drive_t *drive)
break; break;
} }
if (ide_dmaproc(ide_dma_good_drive, drive)) { if (udma_white_list(drive)) {
dma_func = ide_dma_on; dma_func = ide_dma_on;
break; break;
} }
} while (0); } while (0);
return drive->channel->dmaproc(dma_func, drive); return drive->channel->udma(dma_func, drive, rq);
} }
/* /*
* Our own dmaproc, only to intercept ide_dma_check * Our own dmaproc, only to intercept ide_dma_check
*/ */
static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive) static int sl82c105_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{ {
switch (func) { switch (func) {
case ide_dma_check: case ide_dma_check:
return sl82c105_check_drive(drive); return sl82c105_check_drive(drive, rq);
case ide_dma_on: case ide_dma_on:
if (config_for_dma(drive)) if (config_for_dma(drive))
func = ide_dma_off; func = ide_dma_off;
...@@ -168,7 +168,7 @@ static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive) ...@@ -168,7 +168,7 @@ static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
default: default:
break; break;
} }
return ide_dmaproc(func, drive); return ide_dmaproc(func, drive, rq);
} }
/* /*
...@@ -183,8 +183,8 @@ static void tune_sl82c105(ide_drive_t *drive, byte pio) ...@@ -183,8 +183,8 @@ static void tune_sl82c105(ide_drive_t *drive, byte pio)
* We support 32-bit I/O on this interface, and it * We support 32-bit I/O on this interface, and it
* doesn't have problems with interrupts. * doesn't have problems with interrupts.
*/ */
drive->io_32bit = 1; drive->channel->io_32bit = 1;
drive->unmask = 1; drive->channel->unmask = 1;
} }
/* /*
...@@ -252,10 +252,10 @@ void __init dma_init_sl82c105(struct ata_channel *hwif, unsigned long dma_base) ...@@ -252,10 +252,10 @@ void __init dma_init_sl82c105(struct ata_channel *hwif, unsigned long dma_base)
} }
outb(dma_state, dma_base + 2); outb(dma_state, dma_base + 2);
hwif->dmaproc = NULL; hwif->udma = NULL;
ide_setup_dma(hwif, dma_base, 8); ide_setup_dma(hwif, dma_base, 8);
if (hwif->dmaproc) if (hwif->udma)
hwif->dmaproc = sl82c105_dmaproc; hwif->udma = sl82c105_dmaproc;
} }
/* /*
......
...@@ -95,7 +95,7 @@ static void tcq_invalidate_queue(struct ata_device *drive) ...@@ -95,7 +95,7 @@ static void tcq_invalidate_queue(struct ata_device *drive)
del_timer(&hwgroup->timer); del_timer(&hwgroup->timer);
if (test_bit(IDE_DMA, &hwgroup->flags)) if (test_bit(IDE_DMA, &hwgroup->flags))
drive->channel->udma(ide_dma_end, drive, hwgroup->rq); udma_stop(drive);
blk_queue_invalidate_tags(q); blk_queue_invalidate_tags(q);
...@@ -328,7 +328,7 @@ ide_startstop_t ide_dmaq_complete(struct ata_device *drive, struct request *rq, ...@@ -328,7 +328,7 @@ ide_startstop_t ide_dmaq_complete(struct ata_device *drive, struct request *rq,
/* /*
* transfer was in progress, stop DMA engine * transfer was in progress, stop DMA engine
*/ */
dma_stat = drive->channel->udma(ide_dma_end, drive, rq); dma_stat = udma_stop(drive);
/* /*
* must be end of I/O, check status and complete as necessary * must be end of I/O, check status and complete as necessary
...@@ -531,7 +531,7 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request * ...@@ -531,7 +531,7 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *
return ide_stopped; return ide_stopped;
set_irq(drive, ide_dmaq_intr); set_irq(drive, ide_dmaq_intr);
if (!ch->udma(ide_dma_begin, drive, rq)) if (!udma_start(drive, rq))
return ide_started; return ide_started;
return ide_stopped; return ide_stopped;
......
...@@ -173,36 +173,73 @@ static void trm290_selectproc (ide_drive_t *drive) ...@@ -173,36 +173,73 @@ static void trm290_selectproc (ide_drive_t *drive)
} }
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
static int trm290_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct request *rq) static int trm290_udma_start(struct ata_device *drive, struct request *__rq)
{
/* Nothing to be done here. */
return 0;
}
static int trm290_udma_stop(struct ata_device *drive)
{ {
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
unsigned int count, reading = 2, writing = 0;
switch (func) { drive->waiting_for_dma = 0;
case ide_dma_write: udma_destroy_table(ch); /* purge DMA mappings */
return (inw(ch->dma_base + 2) != 0x00ff);
}
static int do_udma(unsigned int reading, struct ata_device *drive, struct request *rq)
{
struct ata_channel *ch = drive->channel;
unsigned int count, writing;
if (!reading) {
reading = 0; reading = 0;
writing = 1; writing = 1;
#ifdef TRM290_NO_DMA_WRITES #ifdef TRM290_NO_DMA_WRITES
break; /* always use PIO for writes */ trm290_prepare_drive(drive, 0); /* select PIO xfer */
return 1;
#endif #endif
case ide_dma_read: } else {
if (!(count = udma_new_table(ch, rq))) reading = 2;
break; /* try PIO instead of DMA */ writing = 0;
}
if (!(count = udma_new_table(ch, rq))) {
trm290_prepare_drive(drive, 0); /* select PIO xfer */
return 1; /* try PIO instead of DMA */
}
trm290_prepare_drive(drive, 1); /* select DMA xfer */ trm290_prepare_drive(drive, 1); /* select DMA xfer */
outl(ch->dmatable_dma|reading|writing, ch->dma_base); outl(ch->dmatable_dma|reading|writing, ch->dma_base);
drive->waiting_for_dma = 1; drive->waiting_for_dma = 1;
outw((count * 2) - 1, ch->dma_base+2); /* start DMA */ outw((count * 2) - 1, ch->dma_base+2); /* start DMA */
if (drive->type != ATA_DISK) if (drive->type != ATA_DISK)
return 0; return 0;
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
return 0; return 0;
case ide_dma_begin: }
return 0;
case ide_dma_end: static int trm290_udma_read(struct ata_device *drive, struct request *rq)
drive->waiting_for_dma = 0; {
udma_destroy_table(ch); /* purge DMA mappings */ return do_udma(1, drive, rq);
return (inw(ch->dma_base + 2) != 0x00ff); }
static int trm290_udma_write(struct ata_device *drive, struct request *rq)
{
return do_udma(0, drive, rq);
}
static int trm290_dmaproc (ide_dma_action_t func, struct ata_device *drive, struct request *rq)
{
struct ata_channel *ch = drive->channel;
switch (func) {
case ide_dma_test_irq: case ide_dma_test_irq:
return (inw(ch->dma_base + 2) == 0x00ff); return (inw(ch->dma_base + 2) == 0x00ff);
default: default:
...@@ -263,6 +300,10 @@ void __init ide_init_trm290(struct ata_channel *hwif) ...@@ -263,6 +300,10 @@ void __init ide_init_trm290(struct ata_channel *hwif)
ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->unit ? 0x0080 : 0x0000), 3); ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->unit ? 0x0080 : 0x0000), 3);
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
hwif->udma_start = trm290_udma_start;
hwif->udma_stop = trm290_udma_stop;
hwif->udma_read = trm290_udma_read;
hwif->udma_write = trm290_udma_write;
hwif->udma = trm290_dmaproc; hwif->udma = trm290_dmaproc;
#endif #endif
......
...@@ -328,7 +328,7 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request ...@@ -328,7 +328,7 @@ static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request
printk ("ide-scsi: %s: DMA complete\n", drive->name); printk ("ide-scsi: %s: DMA complete\n", drive->name);
#endif /* IDESCSI_DEBUG_LOG */ #endif /* IDESCSI_DEBUG_LOG */
pc->actually_transferred=pc->request_transfer; pc->actually_transferred=pc->request_transfer;
(void) drive->channel->udma(ide_dma_end, drive, NULL); udma_stop(drive);
} }
status = GET_STAT(); /* Clear the interrupt */ status = GET_STAT(); /* Clear the interrupt */
...@@ -429,8 +429,12 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request ...@@ -429,8 +429,12 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request
pc->current_position=pc->buffer; pc->current_position=pc->buffer;
bcount = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */ bcount = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */
if (drive->using_dma && rq->bio) if (drive->using_dma && rq->bio) {
dma_ok = !drive->channel->udma(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive, rq); if (test_bit (PC_WRITING, &pc->flags))
dma_ok = !udma_write(drive, rq);
else
dma_ok = !udma_read(drive, rq);
}
SELECT_DRIVE(drive->channel, drive); SELECT_DRIVE(drive->channel, drive);
if (IDE_CONTROL_REG) if (IDE_CONTROL_REG)
...@@ -441,7 +445,7 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request ...@@ -441,7 +445,7 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request
if (dma_ok) { if (dma_ok) {
set_bit(PC_DMA_IN_PROGRESS, &pc->flags); set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
(void) drive->channel->udma(ide_dma_begin, drive, NULL); udma_start(drive, rq);
} }
if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
ide_set_handler(drive, idescsi_transfer_pc, get_timeout(pc), NULL); ide_set_handler(drive, idescsi_transfer_pc, get_timeout(pc), NULL);
......
...@@ -374,15 +374,10 @@ struct ata_device { ...@@ -374,15 +374,10 @@ struct ata_device {
} ide_drive_t; } ide_drive_t;
typedef enum { typedef enum {
ide_dma_read, ide_dma_write,
ide_dma_begin, ide_dma_end,
ide_dma_check, ide_dma_check,
ide_dma_on, ide_dma_off, ide_dma_on, ide_dma_off,
ide_dma_off_quietly, ide_dma_off_quietly,
ide_dma_test_irq, ide_dma_test_irq,
ide_dma_bad_drive,
ide_dma_good_drive,
ide_dma_retune,
ide_dma_lostirq, ide_dma_lostirq,
ide_dma_timeout ide_dma_timeout
} ide_dma_action_t; } ide_dma_action_t;
...@@ -436,7 +431,19 @@ struct ata_channel { ...@@ -436,7 +431,19 @@ struct ata_channel {
void (*atapi_read)(struct ata_device *, void *, unsigned int); void (*atapi_read)(struct ata_device *, void *, unsigned int);
void (*atapi_write)(struct ata_device *, void *, unsigned int); void (*atapi_write)(struct ata_device *, void *, unsigned int);
int (*udma)(ide_dma_action_t, struct ata_device *, struct request *); /* dma read/write/abort routine */ int (*udma)(ide_dma_action_t, struct ata_device *, struct request *);
int (*udma_start) (struct ata_device *, struct request *rq);
int (*udma_stop) (struct ata_device *);
int (*udma_read) (struct ata_device *, struct request *rq);
int (*udma_write) (struct ata_device *, struct request *rq);
int (*udma_irq_status) (struct ata_device *);
void (*udma_timeout) (struct ata_device *);
void (*udma_lost_irq) (struct ata_device *);
unsigned int *dmatable_cpu; /* dma physical region descriptor table (cpu view) */ unsigned int *dmatable_cpu; /* dma physical region descriptor table (cpu view) */
dma_addr_t dmatable_dma; /* dma physical region descriptor table (dma view) */ dma_addr_t dmatable_dma; /* dma physical region descriptor table (dma view) */
struct scatterlist *sg_table; /* Scatter-gather list used to build the above */ struct scatterlist *sg_table; /* Scatter-gather list used to build the above */
...@@ -873,13 +880,25 @@ extern int udma_new_table(struct ata_channel *, struct request *); ...@@ -873,13 +880,25 @@ extern int udma_new_table(struct ata_channel *, struct request *);
extern void udma_destroy_table(struct ata_channel *); extern void udma_destroy_table(struct ata_channel *);
extern void udma_print(struct ata_device *); extern void udma_print(struct ata_device *);
extern void udma_enable(struct ata_device *, int, int);
extern int udma_black_list(struct ata_device *);
extern int udma_white_list(struct ata_device *);
extern void udma_timeout(struct ata_device *);
extern void udma_lost_irq(struct ata_device *);
extern int udma_start(struct ata_device *, struct request *rq);
extern int udma_stop(struct ata_device *);
extern int udma_read(struct ata_device *, struct request *rq);
extern int udma_write(struct ata_device *, struct request *rq);
extern int udma_irq_status(struct ata_device *);
extern int ata_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq);
extern ide_startstop_t udma_tcq_taskfile(struct ata_device *, struct request *); extern ide_startstop_t udma_tcq_taskfile(struct ata_device *, struct request *);
extern int udma_tcq_enable(struct ata_device *, int); extern int udma_tcq_enable(struct ata_device *, int);
extern ide_startstop_t ide_dma_intr(struct ata_device *, struct request *); extern ide_startstop_t ide_dma_intr(struct ata_device *, struct request *);
extern int check_drive_lists(struct ata_device *, int good_bad); extern int check_drive_lists(struct ata_device *, int good_bad);
extern int ide_dmaproc(ide_dma_action_t func, struct ata_device *, struct request *); extern int ide_dmaproc(ide_dma_action_t func, struct ata_device *, struct request *);
extern ide_startstop_t ide_tcq_dmaproc(ide_dma_action_t, struct ata_device *, struct request *);
extern void ide_release_dma(struct ata_channel *); extern void ide_release_dma(struct ata_channel *);
extern void ide_setup_dma(struct ata_channel *, unsigned long, unsigned int) __init; extern void ide_setup_dma(struct ata_channel *, unsigned long, unsigned int) __init;
extern int ata_start_dma(struct ata_device *, struct request *rq); extern int ata_start_dma(struct ata_device *, struct request *rq);
......
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