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
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
comment 'IDE chipset support'
comment 'ATA host chipset support'
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 ' 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
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
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
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
......@@ -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 ' 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 ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 $CONFIG_BLK_DEV_IDEDMA_PCI
fi
if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
fi
fi
if [ "$CONFIG_ALL_PPC" = "y" ]; then
bool ' Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC
......
......@@ -437,7 +437,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (id && (id->capability & 1) && drive->channel->autodma) {
/* 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;
goto fast_ata_pio;
}
......@@ -459,7 +459,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on)
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) {
goto no_dma_set;
}
......
......@@ -441,7 +441,7 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) {
/* 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;
goto fast_ata_pio;
}
......@@ -463,7 +463,7 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
if (dma_func != ide_dma_on)
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) {
goto no_dma_set;
}
......@@ -483,21 +483,25 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
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)
{
switch(func) {
case ide_dma_check:
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:
break;
}
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)
{
......@@ -679,6 +683,7 @@ void __init ide_init_ali15x3(struct ata_channel *hwif)
/*
* M1543C or newer for DMAing
*/
hwif->udma_write = ali15x3_udma_write;
hwif->udma = ali15x3_dmaproc;
hwif->autodma = 1;
}
......
......@@ -783,7 +783,7 @@ static int cmd64x_config_drive_for_dma(struct ata_device *drive)
if ((id != NULL) && ((id->capability & 1) != 0) &&
hwif->autodma && (drive->type == ATA_DISK)) {
/* 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;
goto fast_ata_pio;
}
......@@ -805,7 +805,7 @@ static int cmd64x_config_drive_for_dma(struct ata_device *drive)
if (dma_func != ide_dma_on)
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) {
goto no_dma_set;
}
......@@ -837,20 +837,14 @@ static int cmd680_dmaproc(ide_dma_action_t func, struct ata_device *drive, struc
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;
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;
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;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
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
}
udma_destroy_table(ch); /* purge DMA mappings */
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 */
dma_stat = inb(dma_base+2);
(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
return ide_dmaproc(func, drive, rq);
}
/*
* 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)
static int cmd646_1_udma_stop(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
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;
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 */
udma_destroy_table(ch); /* and free any DMA resources */
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:
break;
}
......@@ -1134,19 +1145,22 @@ void __init ide_init_cmd64x(struct ata_channel *hwif)
case PCI_DEVICE_ID_CMD_649:
case PCI_DEVICE_ID_CMD_648:
case PCI_DEVICE_ID_CMD_643:
hwif->udma = &cmd64x_dmaproc;
hwif->tuneproc = &cmd64x_tuneproc;
hwif->speedproc = &cmd64x_tune_chipset;
hwif->udma_stop = cmd64x_udma_stop;
hwif->udma = cmd64x_dmaproc;
hwif->tuneproc = cmd64x_tuneproc;
hwif->speedproc = cmd64x_tune_chipset;
break;
case PCI_DEVICE_ID_CMD_646:
hwif->chipset = ide_cmd646;
if (class_rev == 0x01) {
hwif->udma_stop = &cmd646_1_udma_stop;
hwif->udma = &cmd646_1_dmaproc;
} else {
hwif->udma = &cmd64x_dmaproc;
hwif->udma_stop = cmd64x_udma_stop;
hwif->udma = cmd64x_dmaproc;
}
hwif->tuneproc = &cmd64x_tuneproc;
hwif->speedproc = &cmd64x_tune_chipset;
hwif->tuneproc = cmd64x_tuneproc;
hwif->speedproc = cmd64x_tune_chipset;
break;
default:
break;
......
......@@ -158,7 +158,7 @@ static int cs5530_config_dma (ide_drive_t *drive)
*/
if (mate->present) {
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))
udma_ok = 1;
else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
......@@ -172,7 +172,7 @@ static int cs5530_config_dma (ide_drive_t *drive)
* Now see what the current drive is capable of,
* 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 (id->dma_ultra & 4)
mode = XFER_UDMA_2;
......
......@@ -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) {
/* 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;
goto fast_ata_pio;
}
......@@ -278,7 +278,7 @@ static int config_drive_xfer_rate(struct ata_device *drive, struct request *rq)
if (dma_func != ide_dma_on)
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) {
goto no_dma_set;
}
......@@ -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);
}
/*
* 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.
*/
static int hpt34x_udma_stop(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
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;
unsigned long dma_base = ch->dma_base;
unsigned int count, reading = 0;
byte dma_stat;
unsigned int count;
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)))
return 1; /* try PIO instead of DMA */
outl(ch->dmatable_dma, dma_base + 4); /* PRD table */
reading |= 0x01;
outb(reading, dma_base); /* specify r/w */
outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK)
return 0;
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);
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 */
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 hpt34x_udma_read(struct ata_device *drive, struct request *rq)
{
return do_udma(1 << 3, drive, rq);
}
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:
break;
}
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.
......@@ -423,7 +444,10 @@ void __init ide_init_hpt34x(struct ata_channel *hwif)
else
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;
} else {
hwif->drives[0].autotune = 1;
......
......@@ -748,7 +748,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (id && (id->capability & 1) && drive->channel->autodma) {
/* 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;
goto fast_ata_pio;
}
......@@ -769,7 +769,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on)
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) {
goto no_dma_set;
}
......@@ -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 */
}
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)
{
struct ata_channel *hwif = drive->channel;
......@@ -845,18 +925,6 @@ int hpt370_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct reque
dma_stat = inb(dma_base+2);
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_lostirq:
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
outb(dma_stat | 0x6, dma_base+2); /* clear errors */
/* fallthrough */
#ifdef HPT_RESET_STATE_ENGINE
case ide_dma_begin:
#endif
pci_write_config_byte(hwif->pci_dev, regstate, 0x37);
udelay(10);
do_udma_start(drive);
break;
default:
......@@ -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 */
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
#endif
/*
* 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)
pci_read_config_byte(hwif->pci_dev, 0x5a, &reg5ah);
if (reg5ah & 0x10) /* interrupt force enable */
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;
} else {
hwif->udma = hpt366_dmaproc;
......
......@@ -737,9 +737,9 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive,
if (info->dma) {
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)
info->dma = !drive->channel->udma(ide_dma_write, drive, rq);
info->dma = !udma_write(drive, rq);
else
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,
OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
if (info->dma)
drive->channel->udma(ide_dma_begin, drive, NULL);
udma_start(drive, rq);
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
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
/* Check for errors. */
if (dma) {
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);
}
......@@ -1480,7 +1480,7 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request
/* Check for errors. */
if (dma) {
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");
drive->channel->udma(ide_dma_off, drive, NULL);
}
......
......@@ -199,7 +199,7 @@ ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq)
{
u8 stat, dma_stat;
dma_stat = drive->channel->udma(ide_dma_end, drive, rq);
dma_stat = udma_stop(drive);
if (OK_STAT(stat = GET_STAT(),DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
if (!dma_stat) {
__ide_end_request(drive, rq, 1, rq->nr_sectors);
......@@ -288,7 +288,7 @@ int check_drive_lists(struct ata_device *drive, int good_bad)
printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model);
return(blacklist);
}
#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */
#else
const char **list;
if (good_bad) {
......@@ -309,7 +309,7 @@ int check_drive_lists(struct ata_device *drive, int good_bad)
}
}
}
#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */
#endif
return 0;
}
......@@ -326,7 +326,7 @@ static int config_drive_for_dma(struct ata_device *drive)
if (id && (id->capability & 1) && ch->autodma && config_allows_dma) {
/* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive, NULL))
if (udma_black_list(drive))
return ch->udma(ide_dma_off, drive, NULL);
/* Enable DMA on any drive that has UltraDMA (mode 6/7/?) enabled */
......@@ -346,7 +346,7 @@ static int config_drive_for_dma(struct ata_device *drive)
if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)
return ch->udma(ide_dma_on, drive, NULL);
/* Consult the list of known "good" drives */
if (ide_dmaproc(ide_dma_good_drive, drive, NULL))
if (udma_white_list(drive))
return ch->udma(ide_dma_on, drive, NULL);
}
return ch->udma(ide_dma_off_quietly, drive, NULL);
......@@ -420,7 +420,7 @@ int ata_start_dma(struct ata_device *drive, struct request *rq)
*
* For ATAPI devices, we just prepare for DMA and return. The caller should
* then issue the packet command to the drive and call us again with
* ide_dma_begin afterwards.
* udma_start afterwards.
*
* Returns 0 if all went well.
* Returns 1 if DMA read/write could not be started, in which case
......@@ -432,7 +432,7 @@ int ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request
struct ata_channel *ch = drive->channel;
unsigned long dma_base = ch->dma_base;
u8 unit = (drive->select.b.unit & 0x01);
unsigned int reading = 0, set_high = 1;
unsigned int set_high = 1;
u8 dma_stat;
switch (func) {
......@@ -456,41 +456,6 @@ int ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request
return 0;
case ide_dma_check:
return config_drive_for_dma (drive);
case ide_dma_read:
reading = 1 << 3;
case ide_dma_write:
if (ata_start_dma(drive, rq))
return 1;
if (drive->type != ATA_DISK)
return 0;
ide_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */
if ((rq->flags & REQ_DRIVE_ACB) && (drive->addressing == 1)) {
struct ata_taskfile *args = rq->special;
OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
} else if (drive->addressing) {
OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
} else {
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
}
return drive->channel->udma(ide_dma_begin, drive, NULL);
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.
*/
outb(inb(dma_base)|1, dma_base); /* start DMA */
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 */
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 */
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
dma_stat = inb(dma_base+2);
#if 0 /* do not set unless you know what you are doing */
......@@ -500,13 +465,9 @@ int ide_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct request
}
#endif
return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
case ide_dma_bad_drive:
case ide_dma_good_drive:
return check_drive_lists(drive, (func == ide_dma_good_drive));
case ide_dma_timeout:
printk(KERN_ERR "%s: DMA timeout occured!\n", __FUNCTION__);
return 1;
case ide_dma_retune:
case ide_dma_lostirq:
printk(KERN_ERR "%s: chipset supported func only: %d\n", __FUNCTION__, func);
return 1;
......@@ -585,7 +546,64 @@ void ide_setup_dma(struct ata_channel *ch, unsigned long dma_base, unsigned int
/****************************************************************************
* UDMA function which should have architecture specific counterparts where
* neccessary.
*
* The intention is that at some point in time we will move this whole to
* architecture specific kernel sections. For now I would love the architecture
* maintainers to just #ifdef #endif this stuff directly here. I have for now
* tryed to update as much as I could in the architecture specific code. But
* of course I may have done mistakes, so please bear with me and update it
* here the proper way.
*
* Thank you a lot in advance!
*
* Sat May 4 20:29:46 CEST 2002 Marcin Dalecki.
*/
/*
* This is the generic part of the DMA setup used by the host chipset drivers
* in the corresponding DMA setup method.
*
* FIXME: there are some places where this gets used driectly for "error
* recovery" in the ATAPI drivers. This was just plain wrong before, in esp.
* not portable, and just got uncovered now.
*/
void udma_enable(struct ata_device *drive, int on, int verbose)
{
struct ata_channel *ch = drive->channel;
int set_high = 1;
u8 unit = (drive->select.b.unit & 0x01);
u64 addr = BLK_BOUNCE_HIGH;
if (!on) {
if (verbose)
printk("%s: DMA disabled\n", drive->name);
set_high = 0;
outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2);
#ifdef CONFIG_BLK_DEV_IDE_TCQ
udma_tcq_enable(drive, 0);
#endif
}
/* toggle bounce buffers */
if (on && drive->type == ATA_DISK && drive->channel->highmem) {
if (!PCI_DMA_BUS_IS_PHYS)
addr = BLK_BOUNCE_ANY;
else
addr = drive->channel->pci_dev->dma_mask;
}
blk_queue_bounce_limit(&drive->queue, addr);
drive->using_dma = on;
if (on) {
outb(inb(ch->dma_base + 2) | (1 << (5 + unit)), ch->dma_base + 2);
#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
udma_tcq_enable(drive, 1);
#endif
}
}
/*
* This prepares a dma request. Returns 0 if all went okay, returns 1
......@@ -718,4 +736,157 @@ void udma_print(struct ata_device *drive)
#endif
}
/*
* Drive back/white list handling for UDMA capability:
*/
int udma_black_list(struct ata_device *drive)
{
return check_drive_lists(drive, 0);
}
int udma_white_list(struct ata_device *drive)
{
return check_drive_lists(drive, 1);
}
/*
* Generic entry points for functions provided possibly by the host chip set
* drivers.
*/
/*
* Prepare the channel for a DMA startfer. Please note that only the broken
* Pacific Digital host chip needs the reques to be passed there to decide
* about addressing modes.
*/
int udma_start(struct ata_device *drive, struct request *rq)
{
struct ata_channel *ch = drive->channel;
unsigned long dma_base = ch->dma_base;
if (ch->udma_start)
return ch->udma_start(drive, rq);
/* 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(dma_base)|1, dma_base); /* start DMA */
return 0;
}
int udma_stop(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
if (ch->udma_stop)
return ch->udma_stop(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 */
}
/*
* This is the default read write function.
*
* It's exported only for host chips which use it for fallback or (too) late
* capability checking.
*/
int ata_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq)
{
if (ata_start_dma(drive, rq))
return 1;
if (drive->type != ATA_DISK)
return 0;
reading <<= 3;
ide_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */
if ((rq->flags & REQ_DRIVE_ACB) && (drive->addressing == 1)) {
struct ata_taskfile *args = rq->special;
OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
} else if (drive->addressing) {
OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
} else {
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
}
return udma_start(drive, rq);
}
int udma_read(struct ata_device *drive, struct request *rq)
{
struct ata_channel *ch = drive->channel;
if (ch->udma_read)
return ch->udma_read(drive, rq);
return ata_do_udma(1, drive, rq);
}
int udma_write(struct ata_device *drive, struct request *rq)
{
struct ata_channel *ch = drive->channel;
if (ch->udma_write)
return ch->udma_write(drive, rq);
return ata_do_udma(0, drive, rq);
}
/*
* FIXME: This should be attached to a channel as we can see now!
*/
int udma_irq_status(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
u8 dma_stat;
if (ch->udma_irq_status)
return ch->udma_irq_status(drive);
/* default action */
dma_stat = inb(ch->dma_base + 2);
return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
}
void udma_timeout(struct ata_device *drive)
{
printk(KERN_ERR "ATA: UDMA timeout occured %s!\n", drive->name);
/* Invoke the chipset specific handler now. */
if (drive->channel->udma_timeout)
drive->channel->udma_timeout(drive);
}
void udma_lost_irq(struct ata_device *drive)
{
if (drive->channel->udma_lost_irq)
drive->channel->udma_lost_irq(drive);
}
EXPORT_SYMBOL(udma_enable);
EXPORT_SYMBOL(udma_start);
EXPORT_SYMBOL(udma_stop);
EXPORT_SYMBOL(udma_read);
EXPORT_SYMBOL(udma_write);
EXPORT_SYMBOL(ata_do_udma);
EXPORT_SYMBOL(udma_irq_status);
EXPORT_SYMBOL(udma_print);
EXPORT_SYMBOL(udma_black_list);
EXPORT_SYMBOL(udma_white_list);
......@@ -901,7 +901,7 @@ static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct reques
#ifdef CONFIG_BLK_DEV_IDEDMA
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);
} else {
pc->actually_transferred=pc->request_transfer;
......@@ -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)) {
(void) drive->channel->udma(ide_dma_off, drive, NULL);
}
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_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) {
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 */
if (IDE_CONTROL_REG)
......@@ -1136,7 +1140,7 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque
#ifdef CONFIG_BLK_DEV_IDEDMA
if (dma_ok) { /* Begin DMA, if necessary */
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 */
......
......@@ -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;
}
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?
......@@ -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 skip */
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 &&
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;
}
}
......@@ -734,9 +734,10 @@ static void __init setup_pci_device(struct pci_dev *dev, struct ata_pci_device *
Suspect a fastrak and fall through */
}
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
* space, place chipset into init-mode, and/or preserve
* 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 *
else
pciirq = trust_pci_irq(d, dev);
} else if (tried_config) {
printk("%s: will probe IRQs later\n", dev->name);
printk(KERN_INFO "ATA: will probe IRQs later\n");
pciirq = 0;
} 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;
} else {
if (d->init_chipset)
d->init_chipset(dev);
#ifdef __sparc__
printk("%s: 100%% native mode on irq %s\n",
dev->name, __irq_itoa(pciirq));
printk(KERN_INFO "ATA: 100%% native mode on irq\n", __irq_itoa(pciirq));
#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
}
......@@ -889,10 +889,10 @@ static void __init scan_pcidev(struct pci_dev *dev)
pdc20270_device_order_fixup(dev, d);
else if (!(d->vendor == 0 && d->device == 0) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
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);
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);
}
}
......
......@@ -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_good_drive:
return check_drive_lists(drive, (func == ide_dma_good_drive));
case ide_dma_retune:
case ide_dma_lostirq:
case ide_dma_timeout:
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
#ifdef CONFIG_BLK_DEV_IDEDMA
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,
* 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
printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n");
(void) drive->channel->udma(ide_dma_off, drive, NULL);
}
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);
#endif /* CONFIG_BLK_DEV_IDEDMA */
if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) {
if (test_bit (PC_WRITING, &pc->flags))
dma_ok = !udma_write(drive, rq);
else
dma_ok = !udma_read(drive, rq);
}
#endif
if (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
#ifdef CONFIG_BLK_DEV_IDEDMA
if (dma_ok) { /* Begin DMA, if necessary */
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 */
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
......
......@@ -461,7 +461,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
* regular dma proc -- basically split stuff that needs to act
* on a request from things like ide_dma_check etc.
*/
ide_dma_action_t dma_act;
if (!drive->using_dma)
return ide_started;
......@@ -469,10 +468,10 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
/* for dma commands we don't set the handler */
if (args->taskfile.command == WIN_WRITEDMA
|| args->taskfile.command == WIN_WRITEDMA_EXT)
dma_act = ide_dma_write;
udma_write(drive, rq);
else if (args->taskfile.command == WIN_READDMA
|| args->taskfile.command == WIN_READDMA_EXT)
dma_act = ide_dma_read;
udma_read(drive, rq);
#ifdef CONFIG_BLK_DEV_IDE_TCQ
else if (args->taskfile.command == WIN_WRITEDMA_QUEUED
|| args->taskfile.command == WIN_WRITEDMA_QUEUED_EXT
......@@ -484,10 +483,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
printk("ata_taskfile: unknown command %x\n", args->taskfile.command);
return ide_stopped;
}
if (drive->channel->udma(dma_act, drive, rq))
return ide_stopped;
}
return ide_started;
......
......@@ -1407,7 +1407,7 @@ static void dma_timeout_retry(struct ata_device *drive, struct request *rq)
/*
* 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
......@@ -2127,6 +2127,13 @@ void ide_unregister(struct ata_channel *ch)
ch->atapi_read = old.atapi_read;
ch->atapi_write = old.atapi_write;
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->bus_state = old.bus_state;
ch->dma_base = old.dma_base;
......
......@@ -82,26 +82,50 @@ static void ns87415_selectproc (ide_drive_t *drive)
}
#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;
byte dma_stat;
struct ata_channel *ch = drive->channel;
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;
dma_stat = inb(hwif->dma_base+2);
outb(inb(hwif->dma_base)&~1, hwif->dma_base); /* stop DMA */
outb(inb(hwif->dma_base)|6, hwif->dma_base); /* from ERRATA: clear the INTR & ERROR bits */
udma_destroy_table(hwif); /* and free any DMA resources */
dma_stat = inb(ch->dma_base+2);
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
outb(inb(dma_base)|6, dma_base); /* from ERRATA: clear the INTR & ERROR bits */
udma_destroy_table(ch); /* and free any DMA resources */
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 */
if (!ide_dmaproc(func, drive, rq)) /* use standard DMA stuff */
if (!ata_do_udma(1, drive, rq)) /* use standard DMA stuff */
return 0;
ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */
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:
if (drive->type != ATA_DISK)
return ide_dmaproc(ide_dma_off_quietly, drive, rq);
......@@ -205,8 +229,12 @@ void __init ide_init_ns87415(struct ata_channel *hwif)
}
#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;
}
#endif
hwif->selectproc = &ns87415_selectproc;
......
......@@ -929,7 +929,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (id && (id->capability & 1) && hwif->autodma) {
/* 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;
goto fast_ata_pio;
}
......@@ -951,7 +951,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on)
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) {
goto no_dma_set;
}
......@@ -977,21 +977,15 @@ int pdc202xx_quirkproc (ide_drive_t *drive)
return ((int) check_in_drive_lists(drive, pdc_quirk_drives));
}
/*
* 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)
static int pdc202xx_udma_start(struct ata_device *drive, struct request *rq)
{
byte dma_stat = 0;
byte sc1d = 0;
byte newchip = 0;
byte clock = 0;
byte hardware48hack = 0;
struct ata_channel *hwif = drive->channel;
struct pci_dev *dev = hwif->pci_dev;
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 + (hwif->unit ? 0x24 : 0x00);
unsigned long dma_base = hwif->dma_base;
unsigned long atapi_reg = high_16 + (ch->unit ? 0x24 : 0x00);
switch (dev->device) {
case PCI_DEVICE_ID_PROMISE_20275:
......@@ -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_20268R:
case PCI_DEVICE_ID_PROMISE_20268:
newchip = 1;
break;
case PCI_DEVICE_ID_PROMISE_20267:
case PCI_DEVICE_ID_PROMISE_20265:
......@@ -1010,32 +1003,103 @@ int pdc202xx_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct req
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)) {
struct request *rq = HWGROUP(drive)->rq;
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_data_dir(rq) == READ) ? word_count | 0x05000000 : word_count | 0x06000000;
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;
case ide_dma_end:
}
if ((drive->addressing) && (hardware48hack)) {
outl(0, atapi_reg); /* zero out extra */
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;
}
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 */
dma_stat = IN_BYTE(dma_base+2);
if (newchip)
......@@ -1268,6 +1332,8 @@ void __init ide_init_pdc202xx(struct ata_channel *hwif)
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
hwif->udma_start = pdc202xx_udma_start;
hwif->udma_stop = pdc202xx_udma_stop;
hwif->udma = pdc202xx_dmaproc;
hwif->highmem = 1;
if (!noautodma)
......
......@@ -431,14 +431,14 @@ static int config_chipset_for_dma (ide_drive_t *drive)
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;
ide_dma_action_t dma_func = ide_dma_on;
if (id && (id->capability & 1) && drive->channel->autodma) {
/* 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;
goto fast_ata_pio;
}
......@@ -460,7 +460,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on)
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) {
goto no_dma_set;
}
......@@ -480,15 +480,11 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
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) {
case ide_dma_check:
return config_drive_xfer_rate(drive);
case ide_dma_end:
{
struct ata_channel *hwif = drive->channel;
unsigned long dma_base = hwif->dma_base;
struct ata_channel *ch = drive->channel;
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
if(inb(dma_base+0x02)&1)
{
......@@ -517,8 +513,21 @@ static int svwks_dmaproc(ide_dma_action_t func, struct ata_device *drive, struct
cpu_relax();
#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:
break;
}
......@@ -645,6 +654,7 @@ void __init ide_init_svwks(struct ata_channel *hwif)
if (!noautodma)
hwif->autodma = 1;
#endif
hwif->udma_stop = svwks_udma_stop;
hwif->udma = svwks_dmaproc;
hwif->highmem = 1;
} else {
......
......@@ -685,7 +685,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (id && (id->capability & 1) && drive->channel->autodma) {
/* 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;
goto fast_ata_pio;
}
......@@ -707,7 +707,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive)
if (dma_func != ide_dma_on)
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)) {
/* Consult the list of known "good" drives */
dma_func = config_chipset_for_dma(drive, 0);
......
......@@ -114,7 +114,7 @@ static int config_for_dma(ide_drive_t *drive)
* Check to see if the drive and
* 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;
......@@ -129,7 +129,7 @@ static int sl82c105_check_drive(ide_drive_t *drive)
break;
/* 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;
break;
}
......@@ -140,23 +140,23 @@ static int sl82c105_check_drive(ide_drive_t *drive)
break;
}
if (ide_dmaproc(ide_dma_good_drive, drive)) {
if (udma_white_list(drive)) {
dma_func = ide_dma_on;
break;
}
} 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
*/
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) {
case ide_dma_check:
return sl82c105_check_drive(drive);
return sl82c105_check_drive(drive, rq);
case ide_dma_on:
if (config_for_dma(drive))
func = ide_dma_off;
......@@ -168,7 +168,7 @@ static int sl82c105_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
default:
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)
* We support 32-bit I/O on this interface, and it
* doesn't have problems with interrupts.
*/
drive->io_32bit = 1;
drive->unmask = 1;
drive->channel->io_32bit = 1;
drive->channel->unmask = 1;
}
/*
......@@ -252,10 +252,10 @@ void __init dma_init_sl82c105(struct ata_channel *hwif, unsigned long dma_base)
}
outb(dma_state, dma_base + 2);
hwif->dmaproc = NULL;
hwif->udma = NULL;
ide_setup_dma(hwif, dma_base, 8);
if (hwif->dmaproc)
hwif->dmaproc = sl82c105_dmaproc;
if (hwif->udma)
hwif->udma = sl82c105_dmaproc;
}
/*
......
......@@ -95,7 +95,7 @@ static void tcq_invalidate_queue(struct ata_device *drive)
del_timer(&hwgroup->timer);
if (test_bit(IDE_DMA, &hwgroup->flags))
drive->channel->udma(ide_dma_end, drive, hwgroup->rq);
udma_stop(drive);
blk_queue_invalidate_tags(q);
......@@ -328,7 +328,7 @@ ide_startstop_t ide_dmaq_complete(struct ata_device *drive, struct request *rq,
/*
* 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
......@@ -531,7 +531,7 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *
return ide_stopped;
set_irq(drive, ide_dmaq_intr);
if (!ch->udma(ide_dma_begin, drive, rq))
if (!udma_start(drive, rq))
return ide_started;
return ide_stopped;
......
......@@ -173,36 +173,73 @@ static void trm290_selectproc (ide_drive_t *drive)
}
#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;
unsigned int count, reading = 2, writing = 0;
switch (func) {
case ide_dma_write:
drive->waiting_for_dma = 0;
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;
writing = 1;
#ifdef TRM290_NO_DMA_WRITES
break; /* always use PIO for writes */
trm290_prepare_drive(drive, 0); /* select PIO xfer */
return 1;
#endif
case ide_dma_read:
if (!(count = udma_new_table(ch, rq)))
break; /* try PIO instead of DMA */
} else {
reading = 2;
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 */
outl(ch->dmatable_dma|reading|writing, ch->dma_base);
drive->waiting_for_dma = 1;
outw((count * 2) - 1, ch->dma_base+2); /* start DMA */
if (drive->type != ATA_DISK)
return 0;
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
return 0;
case ide_dma_begin:
return 0;
case ide_dma_end:
drive->waiting_for_dma = 0;
udma_destroy_table(ch); /* purge DMA mappings */
return (inw(ch->dma_base + 2) != 0x00ff);
}
static int trm290_udma_read(struct ata_device *drive, struct request *rq)
{
return do_udma(1, drive, rq);
}
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:
return (inw(ch->dma_base + 2) == 0x00ff);
default:
......@@ -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);
#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;
#endif
......
......@@ -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);
#endif /* IDESCSI_DEBUG_LOG */
pc->actually_transferred=pc->request_transfer;
(void) drive->channel->udma(ide_dma_end, drive, NULL);
udma_stop(drive);
}
status = GET_STAT(); /* Clear the interrupt */
......@@ -429,8 +429,12 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request
pc->current_position=pc->buffer;
bcount = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */
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 (drive->using_dma && rq->bio) {
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);
if (IDE_CONTROL_REG)
......@@ -441,7 +445,7 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request
if (dma_ok) {
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)) {
ide_set_handler(drive, idescsi_transfer_pc, get_timeout(pc), NULL);
......
......@@ -374,15 +374,10 @@ struct ata_device {
} ide_drive_t;
typedef enum {
ide_dma_read, ide_dma_write,
ide_dma_begin, ide_dma_end,
ide_dma_check,
ide_dma_on, ide_dma_off,
ide_dma_off_quietly,
ide_dma_test_irq,
ide_dma_bad_drive,
ide_dma_good_drive,
ide_dma_retune,
ide_dma_lostirq,
ide_dma_timeout
} ide_dma_action_t;
......@@ -436,7 +431,19 @@ struct ata_channel {
void (*atapi_read)(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) */
dma_addr_t dmatable_dma; /* dma physical region descriptor table (dma view) */
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 *);
extern void udma_destroy_table(struct ata_channel *);
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 int udma_tcq_enable(struct ata_device *, int);
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 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_setup_dma(struct ata_channel *, unsigned long, unsigned int) __init;
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