All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Dalecki <dalecki@evision-ventures.com>
To: Linus Torvalds <torvalds@transmeta.com>
Cc: Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH] 2.5.15 IDE 64
Date: Wed, 15 May 2002 14:04:24 +0200	[thread overview]
Message-ID: <3CE24EC8.3030202@evision-ventures.com> (raw)
In-Reply-To: <Pine.LNX.4.44.0205052046590.1405-100000@home.transmeta.com>

[-- Attachment #1: Type: text/plain, Size: 316 bytes --]

Tue May 14 13:35:04 CEST 2002 ide-clean-64:

Let's just get over with  this before queue handling will be targeted again...

- Implement suggestions by Russel King for improved portability and separation
   between PCI and non PCI host code.

- pdc202xxx updates from Thierry Vignaud.

- Tinny PIO fix from Tomita.


[-- Attachment #2: ide-clean-64.diff --]
[-- Type: text/plain, Size: 73906 bytes --]

diff -urN linux-2.5.15/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.5.15/drivers/ide/ide.c	2002-05-15 14:55:12.000000000 +0200
+++ linux/drivers/ide/ide.c	2002-05-15 13:34:25.000000000 +0200
@@ -1145,7 +1145,7 @@
 }
 
 /*
- * Select the next device which will be serviced.  This selects onlt between
+ * Select the next device which will be serviced.  This selects only between
  * devices on the same channel, since everything else will be scheduled on the
  * queue level.
  */
diff -urN linux-2.5.15/drivers/ide/ide-dma.c linux/drivers/ide/ide-dma.c
--- linux-2.5.15/drivers/ide/ide-dma.c	2002-05-15 14:55:05.000000000 +0200
+++ linux/drivers/ide/ide-dma.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,866 +0,0 @@
-/**** vi:set ts=8 sts=8 sw=8:************************************************
- *
- *  Copyright (c) 1999-2000  Andre Hedrick <andre@linux-ide.org>
- *  Copyright (c) 1995-1998  Mark Lord
- *
- *  May be copied or modified under the terms of the GNU General Public License
- *
- *  Special Thanks to Mark for his Six years of work.
- *
- * This module provides support for the bus-master IDE DMA functions
- * of various PCI chipsets, including the Intel PIIX (i82371FB for
- * the 430 FX chipset), the PIIX3 (i82371SB for the 430 HX/VX and
- * 440 chipsets), and the PIIX4 (i82371AB for the 430 TX chipset)
- * ("PIIX" stands for "PCI ISA IDE Xcellerator").
- *
- * Pretty much the same code works for other IDE PCI bus-mastering chipsets.
- *
- * DMA is supported for all IDE devices (disk drives, cdroms, tapes, floppies).
- *
- * By default, DMA support is prepared for use, but is currently enabled only
- * for drives which already have DMA enabled (UltraDMA or mode 2 multi/single),
- * or which are recognized as "good" (see table below).  Drives with only mode0
- * or mode1 (multi/single) DMA should also work with this chipset/driver
- * (eg. MC2112A) but are not enabled by default.
- *
- * Use "hdparm -i" to view modes supported by a given drive.
- *
- * The hdparm-3.5 (or later) utility can be used for manually enabling/disabling
- * DMA support, but must be (re-)compiled against this kernel version or later.
- *
- * To enable DMA, use "hdparm -d1 /dev/hd?" on a per-drive basis after booting.
- * If problems arise, ide.c will disable DMA operation after a few retries.
- * This error recovery mechanism works and has been extremely well exercised.
- *
- * IDE drives, depending on their vintage, may support several different modes
- * of DMA operation.  The boot-time modes are indicated with a "*" in
- * the "hdparm -i" listing, and can be changed with *knowledgeable* use of
- * the "hdparm -X" feature.  There is seldom a need to do this, as drives
- * normally power-up with their "best" PIO/DMA modes enabled.
- *
- * Testing has been done with a rather extensive number of drives,
- * with Quantum & Western Digital models generally outperforming the pack,
- * and Fujitsu & Conner (and some Seagate which are really Conner) drives
- * showing more lackluster throughput.
- *
- * Keep an eye on /var/adm/messages for "DMA disabled" messages.
- *
- * Some people have reported trouble with Intel Zappa motherboards.
- * This can be fixed by upgrading the AMI BIOS to version 1.00.04.BS0,
- * available from ftp://ftp.intel.com/pub/bios/10004bs0.exe
- * (thanks to Glen Morrell <glen@spin.Stanford.edu> for researching this).
- *
- * Thanks to "Christopher J. Reimer" <reimer@doe.carleton.ca> for
- * fixing the problem with the BIOS on some Acer motherboards.
- *
- * Thanks to "Benoit Poulot-Cazajous" <poulot@chorus.fr> for testing
- * "TX" chipset compatibility and for providing patches for the "TX" chipset.
- *
- * Thanks to Christian Brunner <chb@muc.de> for taking a good first crack
- * at generic DMA -- his patches were referred to when preparing this code.
- *
- * Most importantly, thanks to Robert Bringman <rob@mars.trion.com>
- * for supplying a Promise UDMA board & WD UDMA drive for this work!
- *
- * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports.
- *
- * ATA-66/100 and recovery functions, I forgot the rest......
- */
-
-#include <linux/config.h>
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-/*
- * Long lost data from 2.0.34 that is now in 2.0.39
- *
- * This was used in ./drivers/block/triton.c to do DMA Base address setup
- * when PnP failed.  Oh the things we forget.  I believe this was part
- * of SFF-8038i that has been withdrawn from public access... :-((
- */
-#define DEFAULT_BMIBA	0xe800	/* in case BIOS did not init it */
-#define DEFAULT_BMCRBA	0xcc00	/* VIA's default value */
-#define DEFAULT_BMALIBA	0xd400	/* ALI's default value */
-
-#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
-
-struct drive_list_entry {
-	char * id_model;
-	char * id_firmware;
-};
-
-struct drive_list_entry drive_whitelist[] = {
-	{ "Micropolis 2112A", NULL },
-	{ "CONNER CTMA 4000", NULL },
-	{ "CONNER CTT8000-A", NULL },
-	{ "ST34342A", NULL },
-	{ NULL, NULL }
-};
-
-struct drive_list_entry drive_blacklist[] = {
-
-	{ "WDC AC11000H", NULL },
-	{ "WDC AC22100H", NULL },
-	{ "WDC AC32500H", NULL },
-	{ "WDC AC33100H", NULL },
-	{ "WDC AC31600H", NULL },
-	{ "WDC AC32100H", "24.09P07" },
-	{ "WDC AC23200L", "21.10N21" },
-	{ "Compaq CRD-8241B", NULL },
-	{ "CRD-8400B", NULL },
-	{ "CRD-8480B", NULL },
-	{ "CRD-8480C", NULL },
-	{ "CRD-8482B", NULL },
-	{ "CRD-84", NULL },
-	{ "SanDisk SDP3B", NULL },
-	{ "SanDisk SDP3B-64", NULL },
-	{ "SANYO CD-ROM CRD", NULL },
-	{ "HITACHI CDR-8", NULL },
-	{ "HITACHI CDR-8335", NULL },
-	{ "HITACHI CDR-8435", NULL },
-	{ "Toshiba CD-ROM XM-6202B", NULL },
-	{ "CD-532E-A", NULL },
-	{ "E-IDE CD-ROM CR-840", NULL },
-	{ "CD-ROM Drive/F5A", NULL },
-	{ "RICOH CD-R/RW MP7083A", NULL },
-	{ "WPI CDD-820", NULL },
-	{ "SAMSUNG CD-ROM SC-148C", NULL },
-	{ "SAMSUNG CD-ROM SC-148F", NULL },
-	{ "SAMSUNG CD-ROM SC", NULL },
-	{ "SanDisk SDP3B-64", NULL },
-	{ "SAMSUNG CD-ROM SN-124", NULL },
-	{ "PLEXTOR CD-R PX-W8432T", NULL },
-	{ "ATAPI CD-ROM DRIVE 40X MAXIMUM", NULL },
-	{ "_NEC DV5800A", NULL },
-	{ NULL,	NULL }
-
-};
-
-static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
-{
-	for ( ; drive_table->id_model ; drive_table++)
-		if ((!strcmp(drive_table->id_model, id->model)) &&
-		    ((drive_table->id_firmware && !strstr(drive_table->id_firmware, id->fw_rev)) ||
-		     (!drive_table->id_firmware)))
-			return 1;
-	return 0;
-}
-
-#else
-
-/*
- * good_dma_drives() lists the model names (from "hdparm -i")
- * of drives which do not support mode2 DMA but which are
- * known to work fine with this interface under Linux.
- */
-const char *good_dma_drives[] = {"Micropolis 2112A",
-				 "CONNER CTMA 4000",
-				 "CONNER CTT8000-A",
-				 "ST34342A",	/* for Sun Ultra */
-				 NULL};
-
-/*
- * bad_dma_drives() lists the model names (from "hdparm -i")
- * of drives which supposedly support (U)DMA but which are
- * known to corrupt data with this interface under Linux.
- *
- * This is an empirical list. Its generated from bug reports. That means
- * while it reflects actual problem distributions it doesn't answer whether
- * the drive or the controller, or cabling, or software, or some combination
- * thereof is the fault. If you don't happen to agree with the kernel's
- * opinion of your drive - use hdparm to turn DMA on.
- */
-const char *bad_dma_drives[] = {"WDC AC11000H",
-				"WDC AC22100H",
-				"WDC AC32100H",
-				"WDC AC32500H",
-				"WDC AC33100H",
-				"WDC AC31600H",
-				NULL};
-
-#endif
-
-/*
- * This is the handler for disk read/write DMA interrupts.
- */
-ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq)
-{
-	u8 stat, dma_stat;
-
-	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);
-			return ide_stopped;
-		}
-		printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
-		       drive->name, dma_stat);
-	}
-	return ide_error(drive, rq, "dma_intr", stat);
-}
-
-/*
- * FIXME: taskfiles should be a map of pages, not a long virt address... /jens
- * FIXME: I agree with Jens --mdcki!
- */
-static int build_sglist(struct ata_channel *ch, struct request *rq)
-{
-	struct scatterlist *sg = ch->sg_table;
-	int nents = 0;
-
-	if (rq->flags & REQ_DRIVE_ACB) {
-		struct ata_taskfile *args = rq->special;
-#if 1
-		unsigned char *virt_addr = rq->buffer;
-		int sector_count = rq->nr_sectors;
-#else
-		nents = blk_rq_map_sg(rq->q, rq, ch->sg_table);
-
-		if (nents > rq->nr_segments)
-			printk("ide-dma: received %d segments, build %d\n", rq->nr_segments, nents);
-#endif
-
-		if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-			ch->sg_dma_direction = PCI_DMA_TODEVICE;
-		else
-			ch->sg_dma_direction = PCI_DMA_FROMDEVICE;
-
-		/*
-		 * FIXME: This depends upon a hard coded page size!
-		 */
-		if (sector_count > 128) {
-			memset(&sg[nents], 0, sizeof(*sg));
-
-			sg[nents].page = virt_to_page(virt_addr);
-			sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
-			sg[nents].length = 128  * SECTOR_SIZE;
-			++nents;
-			virt_addr = virt_addr + (128 * SECTOR_SIZE);
-			sector_count -= 128;
-		}
-		memset(&sg[nents], 0, sizeof(*sg));
-		sg[nents].page = virt_to_page(virt_addr);
-		sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
-		sg[nents].length =  sector_count  * SECTOR_SIZE;
-		++nents;
-	} else {
-		nents = blk_rq_map_sg(rq->q, rq, ch->sg_table);
-
-		if (rq->q && nents > rq->nr_phys_segments)
-			printk("ide-dma: received %d phys segments, build %d\n", rq->nr_phys_segments, nents);
-
-		if (rq_data_dir(rq) == READ)
-			ch->sg_dma_direction = PCI_DMA_FROMDEVICE;
-		else
-			ch->sg_dma_direction = PCI_DMA_TODEVICE;
-
-	}
-	return pci_map_sg(ch->pci_dev, sg, nents, ch->sg_dma_direction);
-}
-
-/*
- *  For both Blacklisted and Whitelisted drives.
- *  This is setup to be called as an extern for future support
- *  to other special driver code.
- */
-int check_drive_lists(struct ata_device *drive, int good_bad)
-{
-	struct hd_driveid *id = drive->id;
-
-#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
-	if (good_bad) {
-		return in_drive_list(id, drive_whitelist);
-	} else {
-		int blacklist = in_drive_list(id, drive_blacklist);
-		if (blacklist)
-			printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model);
-		return(blacklist);
-	}
-#else
-	const char **list;
-
-	if (good_bad) {
-		/* Consult the list of known "good" drives */
-		list = good_dma_drives;
-		while (*list) {
-			if (!strcmp(*list++,id->model))
-				return 1;
-		}
-	} else {
-		/* Consult the list of known "bad" drives */
-		list = bad_dma_drives;
-		while (*list) {
-			if (!strcmp(*list++,id->model)) {
-				printk("%s: Disabling (U)DMA for %s\n",
-					drive->name, id->model);
-				return 1;
-			}
-		}
-	}
-#endif
-	return 0;
-}
-
-static int config_drive_for_dma(struct ata_device *drive)
-{
-	int config_allows_dma = 1;
-	struct hd_driveid *id = drive->id;
-	struct ata_channel *ch = drive->channel;
-
-#ifdef CONFIG_IDEDMA_ONLYDISK
-	if (drive->type != ATA_DISK)
-		config_allows_dma = 0;
-#endif
-
-	if (id && (id->capability & 1) && ch->autodma && config_allows_dma) {
-		/* Consult the list of known "bad" drives */
-		if (udma_black_list(drive)) {
-			udma_enable(drive, 0, 1);
-
-			return 0;
-		}
-
-		/* Enable DMA on any drive that has UltraDMA (mode 6/7/?) enabled */
-		if ((id->field_valid & 4) && (eighty_ninty_three(drive)))
-			if ((id->dma_ultra & (id->dma_ultra >> 14) & 2)) {
-				udma_enable(drive, 1, 1);
-
-				return 0;
-			}
-		/* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */
-		if ((id->field_valid & 4) && (eighty_ninty_three(drive)))
-			if ((id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
-				udma_enable(drive, 1, 1);
-
-				return 0;
-			}
-		/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
-		if (id->field_valid & 4)	/* UltraDMA */
-			if ((id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
-				udma_enable(drive, 1, 1);
-
-				return 0;
-			}
-		/* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */
-		if (id->field_valid & 2)	/* regular DMA */
-			if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) {
-				udma_enable(drive, 1, 1);
-
-				return 0;
-			}
-		/* Consult the list of known "good" drives */
-		if (udma_white_list(drive)) {
-			udma_enable(drive, 1, 1);
-
-			return 0;
-		}
-	}
-	udma_enable(drive, 0, 0);
-
-	return 0;
-}
-
-/*
- * 1 dma-ing, 2 error, 4 intr
- */
-static int dma_timer_expiry(struct ata_device *drive, struct request *rq)
-{
-	/* FIXME: What's that? */
-	u8 dma_stat = inb(drive->channel->dma_base+2);
-
-#ifdef DEBUG
-	printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);
-#endif
-
-#if 0
-	drive->expiry = NULL;	/* one free ride for now */
-#endif
-
-	if (dma_stat & 2) {	/* ERROR */
-		u8 stat = GET_STAT();
-		return ide_error(drive, rq, "dma_timer_expiry", stat);
-	}
-	if (dma_stat & 1)	/* DMAing */
-		return WAIT_CMD;
-	return 0;
-}
-
-int ata_start_dma(struct ata_device *drive, struct request *rq)
-{
-	struct ata_channel *ch = drive->channel;
-	unsigned long dma_base = ch->dma_base;
-	unsigned int reading = 0;
-
-	if (rq_data_dir(rq) == READ)
-		reading = 1 << 3;
-
-	/* try PIO instead of DMA */
-	if (!udma_new_table(ch, rq))
-		return 1;
-
-	outl(ch->dmatable_dma, dma_base + 4); /* PRD table */
-	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;
-	return 0;
-}
-
-/*
- * This initiates/aborts DMA read/write operations on a drive.
- *
- * The caller is assumed to have selected the drive and programmed the drive's
- * sector address using CHS or LBA.  All that remains is to prepare for DMA
- * and then issue the actual read/write DMA/PIO command to the drive.
- *
- * 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
- * udma_start afterwards.
- *
- * Returns 0 if all went well.
- * Returns 1 if DMA read/write could not be started, in which case
- * the caller should revert to PIO for the current request.
- * May also be invoked from trm290.c
- */
-int XXX_ide_dmaproc(struct ata_device *drive)
-{
-	return config_drive_for_dma(drive);
-}
-
-/*
- * Needed for allowing full modular support of ide-driver
- */
-void ide_release_dma(struct ata_channel *ch)
-{
-	if (!ch->dma_base)
-		return;
-
-	if (ch->dmatable_cpu) {
-		pci_free_consistent(ch->pci_dev,
-				    PRD_ENTRIES * PRD_BYTES,
-				    ch->dmatable_cpu,
-				    ch->dmatable_dma);
-		ch->dmatable_cpu = NULL;
-	}
-	if (ch->sg_table) {
-		kfree(ch->sg_table);
-		ch->sg_table = NULL;
-	}
-	if ((ch->dma_extra) && (ch->unit == 0))
-		release_region((ch->dma_base + 16), ch->dma_extra);
-	release_region(ch->dma_base, 8);
-	ch->dma_base = 0;
-}
-
-/*
- * This can be called for a dynamically installed interface. Don't __init it
- */
-void ata_init_dma(struct ata_channel *ch, unsigned long dma_base)
-{
-	if (!request_region(dma_base, 8, ch->name)) {
-		printk(KERN_ERR "ATA: ERROR: BM DMA portst already in use!\n");
-
-		return;
-	}
-	printk(KERN_INFO"    %s: BM-DMA at 0x%04lx-0x%04lx", ch->name, dma_base, dma_base + 7);
-	ch->dma_base = dma_base;
-	ch->dmatable_cpu = pci_alloc_consistent(ch->pci_dev,
-						  PRD_ENTRIES * PRD_BYTES,
-						  &ch->dmatable_dma);
-	if (ch->dmatable_cpu == NULL)
-		goto dma_alloc_failure;
-
-	ch->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
-				 GFP_KERNEL);
-	if (ch->sg_table == NULL) {
-		pci_free_consistent(ch->pci_dev, PRD_ENTRIES * PRD_BYTES,
-				    ch->dmatable_cpu, ch->dmatable_dma);
-		goto dma_alloc_failure;
-	}
-
-	if (!ch->XXX_udma)
-		ch->XXX_udma = XXX_ide_dmaproc;
-
-	if (ch->chipset != ide_trm290) {
-		u8 dma_stat = inb(dma_base+2);
-		printk(", BIOS settings: %s:%s, %s:%s",
-		       ch->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
-		       ch->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
-	}
-	printk("\n");
-	return;
-
-dma_alloc_failure:
-	printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n");
-}
-
-/****************************************************************************
- * 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;
-	u64 addr;
-
-
-	/* Method overloaded by host chip specific code. */
-	if (ch->udma_enable) {
-		ch->udma_enable(drive, on, verbose);
-
-		return;
-	}
-
-	/* Fall back to the default implementation. */
-	unit = (drive->select.b.unit & 0x01);
-	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
- * otherwise.  May also be invoked from trm290.c
- */
-int udma_new_table(struct ata_channel *ch, struct request *rq)
-{
-	unsigned int *table = ch->dmatable_cpu;
-#ifdef CONFIG_BLK_DEV_TRM290
-	unsigned int is_trm290_chipset = (ch->chipset == ide_trm290);
-#else
-	const int is_trm290_chipset = 0;
-#endif
-	unsigned int count = 0;
-	int i;
-	struct scatterlist *sg;
-
-	ch->sg_nents = i = build_sglist(ch, rq);
-	if (!i)
-		return 0;
-
-	sg = ch->sg_table;
-	while (i) {
-		u32 cur_addr;
-		u32 cur_len;
-
-		cur_addr = sg_dma_address(sg);
-		cur_len = sg_dma_len(sg);
-
-		/*
-		 * Fill in the dma table, without crossing any 64kB boundaries.
-		 * Most hardware requires 16-bit alignment of all blocks,
-		 * but the trm290 requires 32-bit alignment.
-		 */
-
-		while (cur_len) {
-			u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
-
-			if (count++ >= PRD_ENTRIES) {
-				printk("ide-dma: count %d, sg_nents %d, cur_len %d, cur_addr %u\n",
-						count, ch->sg_nents, cur_len, cur_addr);
-				BUG();
-			}
-
-			if (bcount > cur_len)
-				bcount = cur_len;
-			*table++ = cpu_to_le32(cur_addr);
-			xcount = bcount & 0xffff;
-			if (is_trm290_chipset)
-				xcount = ((xcount >> 2) - 1) << 16;
-			if (xcount == 0x0000) {
-		        /*
-			 * Most chipsets correctly interpret a length of
-			 * 0x0000 as 64KB, but at least one (e.g. CS5530)
-			 * misinterprets it as zero (!). So here we break
-			 * the 64KB entry into two 32KB entries instead.
-			 */
-				if (count++ >= PRD_ENTRIES) {
-					pci_unmap_sg(ch->pci_dev, sg,
-						     ch->sg_nents,
-						     ch->sg_dma_direction);
-					return 0;
-				}
-
-				*table++ = cpu_to_le32(0x8000);
-				*table++ = cpu_to_le32(cur_addr + 0x8000);
-				xcount = 0x8000;
-			}
-			*table++ = cpu_to_le32(xcount);
-			cur_addr += bcount;
-			cur_len -= bcount;
-		}
-
-		sg++;
-		i--;
-	}
-
-	if (!count)
-		printk(KERN_ERR "%s: empty DMA table?\n", ch->name);
-	else if (!is_trm290_chipset)
-		*--table |= cpu_to_le32(0x80000000);
-
-	return count;
-}
-
-/* Teardown mappings after DMA has completed.  */
-void udma_destroy_table(struct ata_channel *ch)
-{
-	pci_unmap_sg(ch->pci_dev, ch->sg_table, ch->sg_nents, ch->sg_dma_direction);
-}
-
-void udma_print(struct ata_device *drive)
-{
-#ifdef CONFIG_ARCH_ACORN
-	printk(", DMA");
-#else
-	struct hd_driveid *id = drive->id;
-	char *str = NULL;
-
-	if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
-	    (id->dma_ultra & (id->dma_ultra >> 14) & 3)) {
-		if ((id->dma_ultra >> 15) & 1)
-			str = ", UDMA(mode 7)";	/* UDMA BIOS-enabled! */
-		else
-			str = ", UDMA(133)";	/* UDMA BIOS-enabled! */
-	} else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
-		  (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
-		if ((id->dma_ultra >> 13) & 1) {
-			str = ", UDMA(100)";	/* UDMA BIOS-enabled! */
-		} else if ((id->dma_ultra >> 12) & 1) {
-			str = ", UDMA(66)";	/* UDMA BIOS-enabled! */
-		} else {
-			str = ", UDMA(44)";	/* UDMA BIOS-enabled! */
-		}
-	} else if ((id->field_valid & 4) &&
-		   (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
-		if ((id->dma_ultra >> 10) & 1) {
-			str = ", UDMA(33)";	/* UDMA BIOS-enabled! */
-		} else if ((id->dma_ultra >> 9) & 1) {
-			str = ", UDMA(25)";	/* UDMA BIOS-enabled! */
-		} else {
-			str = ", UDMA(16)";	/* UDMA BIOS-enabled! */
-		}
-	} else if (id->field_valid & 4)
-		str = ", (U)DMA";	/* Can be BIOS-enabled! */
-	else
-		str = ", DMA";
-
-	printk(str);
-#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_irq_lost(struct ata_device *drive)
-{
-	if (drive->channel->udma_irq_lost)
-		drive->channel->udma_irq_lost(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);
diff -urN linux-2.5.15/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
--- linux-2.5.15/drivers/ide/ide-taskfile.c	2002-05-15 14:55:12.000000000 +0200
+++ linux/drivers/ide/ide-taskfile.c	2002-05-15 14:07:43.000000000 +0200
@@ -562,7 +562,7 @@
 		if (!ide_end_request(drive, rq, 1))
 			return ide_stopped;
 
-	if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
+	if ((rq->nr_sectors == 1) != (stat & DRQ_STAT)) {
 		pBuf = ide_map_rq(rq, &flags);
 		DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors);
 
diff -urN linux-2.5.15/drivers/ide/Makefile linux/drivers/ide/Makefile
--- linux-2.5.15/drivers/ide/Makefile	2002-05-15 14:55:12.000000000 +0200
+++ linux/drivers/ide/Makefile	2002-05-14 17:10:48.000000000 +0200
@@ -10,7 +10,7 @@
 
 O_TARGET := idedriver.o
 
-export-objs	:= ide-taskfile.o ide.o ide-features.o ide-probe.o ide-dma.o ataraid.o
+export-objs	:= ide-taskfile.o ide.o ide-features.o ide-probe.o quirks.o pcidma.o ataraid.o
 
 obj-y		:=
 obj-m		:=
@@ -43,7 +43,8 @@
 ide-obj-$(CONFIG_BLK_DEV_HPT366)	+= hpt366.o
 ide-obj-$(CONFIG_BLK_DEV_HT6560B)	+= ht6560b.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
-ide-obj-$(CONFIG_BLK_DEV_IDEDMA_PCI)	+= ide-dma.o
+ide-obj-$(CONFIG_BLK_DEV_IDEDMA)	+= quirks.o
+ide-obj-$(CONFIG_BLK_DEV_IDEDMA_PCI)	+= pcidma.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_TCQ)	+= tcq.o
 ide-obj-$(CONFIG_PCI)			+= ide-pci.o
 ide-obj-$(CONFIG_BLK_DEV_ISAPNP)	+= ide-pnp.o
diff -urN linux-2.5.15/drivers/ide/pcidma.c linux/drivers/ide/pcidma.c
--- linux-2.5.15/drivers/ide/pcidma.c	1970-01-01 01:00:00.000000000 +0100
+++ linux/drivers/ide/pcidma.c	2002-05-15 13:28:50.000000000 +0200
@@ -0,0 +1,555 @@
+/**** vi:set ts=8 sts=8 sw=8:************************************************
+ *
+ *  Copyright (C) 2002	     Marcin Dalecki <martin@dalecki.de>
+ *
+ *  Based on previous work by:
+ *
+ *  Copyright (c) 1999-2000  Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (c) 1995-1998  Mark Lord
+ *
+ *  May be copied or modified under the terms of the GNU General Public License
+ */
+
+/*
+ * Those are the generic BM DMA support functions for PCI bus based systems.
+ */
+
+#include <linux/config.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define DEFAULT_BMIBA	0xe800	/* in case BIOS did not init it */
+#define DEFAULT_BMCRBA	0xcc00	/* VIA's default value */
+#define DEFAULT_BMALIBA	0xd400	/* ALI's default value */
+
+/*
+ * This is the handler for disk read/write DMA interrupts.
+ */
+ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq)
+{
+	u8 stat, dma_stat;
+
+	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);
+			return ide_stopped;
+		}
+		printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
+		       drive->name, dma_stat);
+	}
+	return ide_error(drive, rq, "dma_intr", stat);
+}
+
+/*
+ * FIXME: taskfiles should be a map of pages, not a long virt address... /jens
+ * FIXME: I agree with Jens --mdcki!
+ */
+static int build_sglist(struct ata_channel *ch, struct request *rq)
+{
+	struct scatterlist *sg = ch->sg_table;
+	int nents = 0;
+
+	if (rq->flags & REQ_DRIVE_ACB) {
+		struct ata_taskfile *args = rq->special;
+#if 1
+		unsigned char *virt_addr = rq->buffer;
+		int sector_count = rq->nr_sectors;
+#else
+		nents = blk_rq_map_sg(rq->q, rq, ch->sg_table);
+
+		if (nents > rq->nr_segments)
+			printk("ide-dma: received %d segments, build %d\n", rq->nr_segments, nents);
+#endif
+
+		if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
+			ch->sg_dma_direction = PCI_DMA_TODEVICE;
+		else
+			ch->sg_dma_direction = PCI_DMA_FROMDEVICE;
+
+		/*
+		 * FIXME: This depends upon a hard coded page size!
+		 */
+		if (sector_count > 128) {
+			memset(&sg[nents], 0, sizeof(*sg));
+
+			sg[nents].page = virt_to_page(virt_addr);
+			sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
+			sg[nents].length = 128  * SECTOR_SIZE;
+			++nents;
+			virt_addr = virt_addr + (128 * SECTOR_SIZE);
+			sector_count -= 128;
+		}
+		memset(&sg[nents], 0, sizeof(*sg));
+		sg[nents].page = virt_to_page(virt_addr);
+		sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
+		sg[nents].length =  sector_count  * SECTOR_SIZE;
+		++nents;
+	} else {
+		nents = blk_rq_map_sg(rq->q, rq, ch->sg_table);
+
+		if (rq->q && nents > rq->nr_phys_segments)
+			printk("ide-dma: received %d phys segments, build %d\n", rq->nr_phys_segments, nents);
+
+		if (rq_data_dir(rq) == READ)
+			ch->sg_dma_direction = PCI_DMA_FROMDEVICE;
+		else
+			ch->sg_dma_direction = PCI_DMA_TODEVICE;
+
+	}
+
+	return pci_map_sg(ch->pci_dev, sg, nents, ch->sg_dma_direction);
+}
+
+/*
+ * 1 dma-ing, 2 error, 4 intr
+ */
+static int dma_timer_expiry(struct ata_device *drive, struct request *rq)
+{
+	/* FIXME: What's that? */
+	u8 dma_stat = inb(drive->channel->dma_base+2);
+
+#ifdef DEBUG
+	printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);
+#endif
+
+#if 0
+	drive->expiry = NULL;	/* one free ride for now */
+#endif
+
+	if (dma_stat & 2) {	/* ERROR */
+		u8 stat = GET_STAT();
+		return ide_error(drive, rq, "dma_timer_expiry", stat);
+	}
+	if (dma_stat & 1)	/* DMAing */
+		return WAIT_CMD;
+	return 0;
+}
+
+int ata_start_dma(struct ata_device *drive, struct request *rq)
+{
+	struct ata_channel *ch = drive->channel;
+	unsigned long dma_base = ch->dma_base;
+	unsigned int reading = 0;
+
+	if (rq_data_dir(rq) == READ)
+		reading = 1 << 3;
+
+	/* try PIO instead of DMA */
+	if (!udma_new_table(ch, rq))
+		return 1;
+
+	outl(ch->dmatable_dma, dma_base + 4); /* PRD table */
+	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;
+
+	return 0;
+}
+
+/*
+ * Configure a device for DMA operation.
+ */
+int XXX_ide_dmaproc(struct ata_device *drive)
+{
+	int config_allows_dma = 1;
+	struct hd_driveid *id = drive->id;
+	struct ata_channel *ch = drive->channel;
+
+#ifdef CONFIG_IDEDMA_ONLYDISK
+	if (drive->type != ATA_DISK)
+		config_allows_dma = 0;
+#endif
+
+	if (id && (id->capability & 1) && ch->autodma && config_allows_dma) {
+		/* Consult the list of known "bad" drives */
+		if (udma_black_list(drive)) {
+			udma_enable(drive, 0, 1);
+
+			return 0;
+		}
+
+		/* Enable DMA on any drive that has UltraDMA (mode 6/7/?) enabled */
+		if ((id->field_valid & 4) && (eighty_ninty_three(drive)))
+			if ((id->dma_ultra & (id->dma_ultra >> 14) & 2)) {
+				udma_enable(drive, 1, 1);
+
+				return 0;
+			}
+		/* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */
+		if ((id->field_valid & 4) && (eighty_ninty_three(drive)))
+			if ((id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
+				udma_enable(drive, 1, 1);
+
+				return 0;
+			}
+		/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
+		if (id->field_valid & 4)	/* UltraDMA */
+			if ((id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
+				udma_enable(drive, 1, 1);
+
+				return 0;
+			}
+		/* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */
+		if (id->field_valid & 2)	/* regular DMA */
+			if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) {
+				udma_enable(drive, 1, 1);
+
+				return 0;
+			}
+		/* Consult the list of known "good" drives */
+		if (udma_white_list(drive)) {
+			udma_enable(drive, 1, 1);
+
+			return 0;
+		}
+	}
+	udma_enable(drive, 0, 0);
+
+	return 0;
+}
+
+/*
+ * Needed for allowing full modular support of ide-driver
+ */
+void ide_release_dma(struct ata_channel *ch)
+{
+	if (!ch->dma_base)
+		return;
+
+	if (ch->dmatable_cpu) {
+		pci_free_consistent(ch->pci_dev,
+				    PRD_ENTRIES * PRD_BYTES,
+				    ch->dmatable_cpu,
+				    ch->dmatable_dma);
+		ch->dmatable_cpu = NULL;
+	}
+	if (ch->sg_table) {
+		kfree(ch->sg_table);
+		ch->sg_table = NULL;
+	}
+	if ((ch->dma_extra) && (ch->unit == 0))
+		release_region((ch->dma_base + 16), ch->dma_extra);
+	release_region(ch->dma_base, 8);
+	ch->dma_base = 0;
+}
+
+/****************************************************************************
+ * PCI specific UDMA channel method implementations.
+ */
+
+/*
+ * 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.
+ */
+static void udma_pci_enable(struct ata_device *drive, int on, int verbose)
+{
+	struct ata_channel *ch = drive->channel;
+	int set_high = 1;
+	u8 unit;
+	u64 addr;
+
+	/* Fall back to the default implementation. */
+	unit = (drive->select.b.unit & 0x01);
+	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
+ * otherwise.  May also be invoked from trm290.c
+ */
+int udma_new_table(struct ata_channel *ch, struct request *rq)
+{
+	unsigned int *table = ch->dmatable_cpu;
+#ifdef CONFIG_BLK_DEV_TRM290
+	unsigned int is_trm290_chipset = (ch->chipset == ide_trm290);
+#else
+	const int is_trm290_chipset = 0;
+#endif
+	unsigned int count = 0;
+	int i;
+	struct scatterlist *sg;
+
+	ch->sg_nents = i = build_sglist(ch, rq);
+	if (!i)
+		return 0;
+
+	sg = ch->sg_table;
+	while (i) {
+		u32 cur_addr;
+		u32 cur_len;
+
+		cur_addr = sg_dma_address(sg);
+		cur_len = sg_dma_len(sg);
+
+		/*
+		 * Fill in the dma table, without crossing any 64kB boundaries.
+		 * Most hardware requires 16-bit alignment of all blocks,
+		 * but the trm290 requires 32-bit alignment.
+		 */
+
+		while (cur_len) {
+			u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
+
+			if (count++ >= PRD_ENTRIES) {
+				printk("ide-dma: count %d, sg_nents %d, cur_len %d, cur_addr %u\n",
+						count, ch->sg_nents, cur_len, cur_addr);
+				BUG();
+			}
+
+			if (bcount > cur_len)
+				bcount = cur_len;
+			*table++ = cpu_to_le32(cur_addr);
+			xcount = bcount & 0xffff;
+			if (is_trm290_chipset)
+				xcount = ((xcount >> 2) - 1) << 16;
+			if (xcount == 0x0000) {
+		        /*
+			 * Most chipsets correctly interpret a length of
+			 * 0x0000 as 64KB, but at least one (e.g. CS5530)
+			 * misinterprets it as zero (!). So here we break
+			 * the 64KB entry into two 32KB entries instead.
+			 */
+				if (count++ >= PRD_ENTRIES) {
+					pci_unmap_sg(ch->pci_dev, sg,
+						     ch->sg_nents,
+						     ch->sg_dma_direction);
+					return 0;
+				}
+
+				*table++ = cpu_to_le32(0x8000);
+				*table++ = cpu_to_le32(cur_addr + 0x8000);
+				xcount = 0x8000;
+			}
+			*table++ = cpu_to_le32(xcount);
+			cur_addr += bcount;
+			cur_len -= bcount;
+		}
+
+		sg++;
+		i--;
+	}
+
+	if (!count)
+		printk(KERN_ERR "%s: empty DMA table?\n", ch->name);
+	else if (!is_trm290_chipset)
+		*--table |= cpu_to_le32(0x80000000);
+
+	return count;
+}
+
+/* Teardown mappings after DMA has completed.  */
+void udma_destroy_table(struct ata_channel *ch)
+{
+	pci_unmap_sg(ch->pci_dev, ch->sg_table, ch->sg_nents, ch->sg_dma_direction);
+}
+
+/*
+ * 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.
+ */
+
+static int udma_pci_start(struct ata_device *drive, struct request *rq)
+{
+	struct ata_channel *ch = drive->channel;
+	unsigned long dma_base = ch->dma_base;
+
+	/* 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;
+}
+
+static int udma_pci_stop(struct ata_device *drive)
+{
+	struct ata_channel *ch = drive->channel;
+	unsigned long dma_base = ch->dma_base;
+	u8 dma_stat;
+
+	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 udma_pci_read(struct ata_device *drive, struct request *rq)
+{
+	return ata_do_udma(1, drive, rq);
+}
+
+static int udma_pci_write(struct ata_device *drive, struct request *rq)
+{
+	return ata_do_udma(0, drive, rq);
+}
+
+/*
+ * FIXME: This should be attached to a channel as we can see now!
+ */
+static int udma_pci_irq_status(struct ata_device *drive)
+{
+	struct ata_channel *ch = drive->channel;
+	u8 dma_stat;
+
+	/* default action */
+	dma_stat = inb(ch->dma_base + 2);
+
+	return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
+}
+
+static void udma_pci_timeout(struct ata_device *drive)
+{
+	printk(KERN_ERR "ATA: UDMA timeout occured %s!\n", drive->name);
+}
+
+static void udma_pci_irq_lost(struct ata_device *drive)
+{
+}
+
+/*
+ * This can be called for a dynamically installed interface. Don't __init it
+ */
+void ata_init_dma(struct ata_channel *ch, unsigned long dma_base)
+{
+	if (!request_region(dma_base, 8, ch->name)) {
+		printk(KERN_ERR "ATA: ERROR: BM DMA portst already in use!\n");
+
+		return;
+	}
+	printk(KERN_INFO"    %s: BM-DMA at 0x%04lx-0x%04lx", ch->name, dma_base, dma_base + 7);
+	ch->dma_base = dma_base;
+	ch->dmatable_cpu = pci_alloc_consistent(ch->pci_dev,
+						  PRD_ENTRIES * PRD_BYTES,
+						  &ch->dmatable_dma);
+	if (ch->dmatable_cpu == NULL)
+		goto dma_alloc_failure;
+
+	ch->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
+				 GFP_KERNEL);
+	if (ch->sg_table == NULL) {
+		pci_free_consistent(ch->pci_dev, PRD_ENTRIES * PRD_BYTES,
+				    ch->dmatable_cpu, ch->dmatable_dma);
+		goto dma_alloc_failure;
+	}
+
+	/*
+	 * We could just assign them, and then leave it up to the chipset
+	 * specific code to override these after they've called this function.
+	 */
+	if (!ch->XXX_udma)
+		ch->XXX_udma = XXX_ide_dmaproc;
+	if (!ch->udma_enable)
+		ch->udma_enable = udma_pci_enable;
+	if (!ch->udma_start)
+		ch->udma_start = udma_pci_start;
+	if (!ch->udma_stop)
+		ch->udma_stop = udma_pci_stop;
+	if (!ch->udma_read)
+		ch->udma_read = udma_pci_read;
+	if (!ch->udma_write)
+		ch->udma_write = udma_pci_write;
+	if (!ch->udma_irq_status)
+		ch->udma_irq_status = udma_pci_irq_status;
+	if (!ch->udma_timeout)
+		ch->udma_timeout = udma_pci_timeout;
+	if (!ch->udma_irq_lost)
+		ch->udma_irq_lost = udma_pci_irq_lost;
+
+	if (ch->chipset != ide_trm290) {
+		u8 dma_stat = inb(dma_base+2);
+		printk(", BIOS settings: %s:%s, %s:%s",
+		       ch->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
+		       ch->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
+	}
+	printk("\n");
+	return;
+
+dma_alloc_failure:
+	printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n");
+}
+
+/*
+ * 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;
+
+		outb(args->taskfile.command, IDE_COMMAND_REG);
+	} else if (drive->addressing) {
+		outb(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
+	} else {
+		outb(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
+	}
+
+	return udma_start(drive, rq);
+}
+
+EXPORT_SYMBOL(ata_do_udma);
+EXPORT_SYMBOL(ide_dma_intr);
diff -urN linux-2.5.15/drivers/ide/pcihost.h linux/drivers/ide/pcihost.h
--- linux-2.5.15/drivers/ide/pcihost.h	2002-05-15 14:55:12.000000000 +0200
+++ linux/drivers/ide/pcihost.h	2002-05-15 13:29:10.000000000 +0200
@@ -10,10 +10,6 @@
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 /*
diff -urN linux-2.5.15/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c
--- linux-2.5.15/drivers/ide/pdc202xx.c	2002-05-15 14:55:05.000000000 +0200
+++ linux/drivers/ide/pdc202xx.c	2002-05-15 13:45:41.000000000 +0200
@@ -53,220 +53,10 @@
 #define PDC202XX_DEBUG_DRIVE_INFO		0
 #define PDC202XX_DECODE_REGISTER_INFO		0
 
-#undef DISPLAY_PDC202XX_TIMINGS
-
 #ifndef SPLIT_BYTE
 #define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
 #endif
 
-#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static int pdc202xx_get_info(char *, char **, off_t, int);
-extern int (*pdc202xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-static struct pci_dev *bmide_dev;
-
-char *pdc202xx_pio_verbose (u32 drive_pci)
-{
-	if ((drive_pci & 0x000ff000) == 0x000ff000) return("NOTSET");
-	if ((drive_pci & 0x00000401) == 0x00000401) return("PIO 4");
-	if ((drive_pci & 0x00000602) == 0x00000602) return("PIO 3");
-	if ((drive_pci & 0x00000803) == 0x00000803) return("PIO 2");
-	if ((drive_pci & 0x00000C05) == 0x00000C05) return("PIO 1");
-	if ((drive_pci & 0x00001309) == 0x00001309) return("PIO 0");
-	return("PIO ?");
-}
-
-char *pdc202xx_dma_verbose (u32 drive_pci)
-{
-	if ((drive_pci & 0x00036000) == 0x00036000) return("MWDMA 2");
-	if ((drive_pci & 0x00046000) == 0x00046000) return("MWDMA 1");
-	if ((drive_pci & 0x00056000) == 0x00056000) return("MWDMA 0");
-	if ((drive_pci & 0x00056000) == 0x00056000) return("SWDMA 2");
-	if ((drive_pci & 0x00068000) == 0x00068000) return("SWDMA 1");
-	if ((drive_pci & 0x000BC000) == 0x000BC000) return("SWDMA 0");
-	return("PIO---");
-}
-
-char *pdc202xx_ultra_verbose (u32 drive_pci, u16 slow_cable)
-{
-	if ((drive_pci & 0x000ff000) == 0x000ff000)
-		return("NOTSET");
-	if ((drive_pci & 0x00012000) == 0x00012000)
-		return((slow_cable) ? "UDMA 2" : "UDMA 4");
-	if ((drive_pci & 0x00024000) == 0x00024000)
-		return((slow_cable) ? "UDMA 1" : "UDMA 3");
-	if ((drive_pci & 0x00036000) == 0x00036000)
-		return("UDMA 0");
-	return(pdc202xx_dma_verbose(drive_pci));
-}
-
-static char * pdc202xx_info (char *buf, struct pci_dev *dev)
-{
-	char *p = buf;
-
-	u32 bibma  = pci_resource_start(dev, 4);
-	u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0;
-	u16 reg50h = 0, pmask = (1<<10), smask = (1<<11);
-	u8 hi = 0, lo = 0;
-
-        /*
-         * at that point bibma+0x2 et bibma+0xa are byte registers
-         * to investigate:
-         */
-	u8 c0	= inb_p((unsigned short)bibma + 0x02);
-	u8 c1	= inb_p((unsigned short)bibma + 0x0a);
-
-	u8 sc11	= inb_p((unsigned short)bibma + 0x11);
-	u8 sc1a	= inb_p((unsigned short)bibma + 0x1a);
-	u8 sc1b	= inb_p((unsigned short)bibma + 0x1b);
-	u8 sc1c	= inb_p((unsigned short)bibma + 0x1c); 
-	u8 sc1d	= inb_p((unsigned short)bibma + 0x1d);
-	u8 sc1e	= inb_p((unsigned short)bibma + 0x1e);
-	u8 sc1f	= inb_p((unsigned short)bibma + 0x1f);
-
-	pci_read_config_word(dev, 0x50, &reg50h);
-	pci_read_config_dword(dev, 0x60, &reg60h);
-	pci_read_config_dword(dev, 0x64, &reg64h);
-	pci_read_config_dword(dev, 0x68, &reg68h);
-	pci_read_config_dword(dev, 0x6c, &reg6ch);
-
-	switch(dev->device) {
-		case PCI_DEVICE_ID_PROMISE_20267:
-			p += sprintf(p, "\n                                PDC20267 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_PROMISE_20265:
-			p += sprintf(p, "\n                                PDC20265 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_PROMISE_20262:
-			p += sprintf(p, "\n                                PDC20262 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_PROMISE_20246:
-			p += sprintf(p, "\n                                PDC20246 Chipset.\n");
-			reg50h |= 0x0c00;
-			break;
-		default:
-			p += sprintf(p, "\n                                PDC202XX Chipset.\n");
-			break;
-	}
-
-	p += sprintf(p, "------------------------------- General Status ---------------------------------\n");
-	p += sprintf(p, "Burst Mode                           : %sabled\n", (sc1f & 0x01) ? "en" : "dis");
-	p += sprintf(p, "Host Mode                            : %s\n", (sc1f & 0x08) ? "Tri-Stated" : "Normal");
-	p += sprintf(p, "Bus Clocking                         : %s\n",
-		((sc1f & 0xC0) == 0xC0) ? "100 External" :
-		((sc1f & 0x80) == 0x80) ? "66 External" :
-		((sc1f & 0x40) == 0x40) ? "33 External" : "33 PCI Internal");
-	p += sprintf(p, "IO pad select                        : %s mA\n",
-		((sc1c & 0x03) == 0x03) ? "10" :
-		((sc1c & 0x02) == 0x02) ? "8" :
-		((sc1c & 0x01) == 0x01) ? "6" :
-		((sc1c & 0x00) == 0x00) ? "4" : "??");
-	SPLIT_BYTE(sc1e, hi, lo);
-	p += sprintf(p, "Status Polling Period                : %d\n", hi);
-	p += sprintf(p, "Interrupt Check Status Polling Delay : %d\n", lo);
-	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
-	p += sprintf(p, "                %s                         %s\n",
-		(c0&0x80)?"disabled":"enabled ",
-		(c1&0x80)?"disabled":"enabled ");
-	p += sprintf(p, "66 Clocking     %s                         %s\n",
-		(sc11&0x02)?"enabled ":"disabled",
-		(sc11&0x08)?"enabled ":"disabled");
-	p += sprintf(p, "           Mode %s                      Mode %s\n",
-		(sc1a & 0x01) ? "MASTER" : "PCI   ",
-		(sc1b & 0x01) ? "MASTER" : "PCI   ");
-	p += sprintf(p, "                %s                     %s\n",
-		(sc1d & 0x08) ? "Error       " :
-		((sc1d & 0x05) == 0x05) ? "Not My INTR " :
-		(sc1d & 0x04) ? "Interrupting" :
-		(sc1d & 0x02) ? "FIFO Full   " :
-		(sc1d & 0x01) ? "FIFO Empty  " : "????????????",
-		(sc1d & 0x80) ? "Error       " :
-		((sc1d & 0x50) == 0x50) ? "Not My INTR " :
-		(sc1d & 0x40) ? "Interrupting" :
-		(sc1d & 0x20) ? "FIFO Full   " :
-		(sc1d & 0x10) ? "FIFO Empty  " : "????????????");
-	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
-		(c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
-	p += sprintf(p, "DMA Mode:       %s           %s          %s            %s\n",
-		pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)),
-		pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)),
-		pdc202xx_ultra_verbose(reg68h, (reg50h & smask)),
-		pdc202xx_ultra_verbose(reg6ch, (reg50h & smask)));
-	p += sprintf(p, "PIO Mode:       %s            %s           %s            %s\n",
-		pdc202xx_pio_verbose(reg60h),
-		pdc202xx_pio_verbose(reg64h),
-		pdc202xx_pio_verbose(reg68h),
-		pdc202xx_pio_verbose(reg6ch));
-#if 0
-	p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n");
-#endif
-	return (char *)p;
-}
-
-static char * pdc202xx_info_new (char *buf, struct pci_dev *dev)
-{
-	char *p = buf;
-//	u32 bibma = pci_resource_start(dev, 4);
-
-//	u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0;
-//	u16 reg50h = 0, word88 = 0;
-//	int udmasel[4]={0,0,0,0}, piosel[4]={0,0,0,0}, i=0, hd=0;
-
-	switch(dev->device) {
-		case PCI_DEVICE_ID_PROMISE_20275:
-			p += sprintf(p, "\n                                PDC20275 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_PROMISE_20276:
-			p += sprintf(p, "\n                                PDC20276 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_PROMISE_20269:
-			p += sprintf(p, "\n                                PDC20269 TX2 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_PROMISE_20268:
-		case PCI_DEVICE_ID_PROMISE_20268R:
-			p += sprintf(p, "\n                                PDC20268 TX2 Chipset.\n");
-			break;
-default:
-			p += sprintf(p, "\n                                PDC202XX Chipset.\n");
-			break;
-	}
-	return (char *)p;
-}
-
-static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	switch(bmide_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_20268:
-		case PCI_DEVICE_ID_PROMISE_20268R:
-			p = pdc202xx_info_new(buffer, bmide_dev);
-			break;
-		default:
-			p = pdc202xx_info(buffer, bmide_dev);
-			break;
-	}
-	return p-buffer;	/* => must be less than 4k! */
-}
-#endif  /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-byte pdc202xx_proc = 0;
-
-const char *pdc_quirk_drives[] = {
-	"QUANTUM FIREBALLlct08 08",
-	"QUANTUM FIREBALLP KA6.4",
-	"QUANTUM FIREBALLP LM20.4",
-	"QUANTUM FIREBALLP KX20.5",
-	"QUANTUM FIREBALLP KX27.3",
-	"QUANTUM FIREBALLP LM20.5",
-	NULL
-};
-
 extern char *ide_xfer_verbose (byte xfer_rate);
 
 /* A Register */
@@ -322,7 +112,6 @@
 
 	switch(registers) {
 		case REG_A:
-			bit2 = 0;
 			printk("A Register ");
 			if (value & 0x80) printk("SYNC_IN ");
 			if (value & 0x40) printk("ERRDY_EN ");
@@ -335,7 +124,6 @@
 			printk("PIO(A) = %d ", bit2);
 			break;
 		case REG_B:
-			bit1 = 0;bit2 = 0;
 			printk("B Register ");
 			if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; }
 			if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; }
@@ -349,7 +137,6 @@
 			printk("PIO(B) = %d ", bit2);
 			break;
 		case REG_C:
-			bit2 = 0;
 			printk("C Register ");
 			if (value & 0x80) printk("DMARQp ");
 			if (value & 0x40) printk("IORDYp ");
@@ -379,23 +166,22 @@
 
 #endif /* PDC202XX_DECODE_REGISTER_INFO */
 
-static int check_in_drive_lists(struct ata_device *drive, const char **list)
-{
+int check_in_drive_lists(struct ata_device *drive) {
+	const char *pdc_quirk_drives[] = {
+		"QUANTUM FIREBALLlct08 08",
+		"QUANTUM FIREBALLP KA6.4",
+		"QUANTUM FIREBALLP LM20.4",
+		"QUANTUM FIREBALLP KX20.5",
+		"QUANTUM FIREBALLP KX27.3",
+		"QUANTUM FIREBALLP LM20.5",
+		NULL
+	};
+     const char**list = pdc_quirk_drives;
 	struct hd_driveid *id = drive->id;
 
-	if (pdc_quirk_drives == list) {
-		while (*list) {
-			if (strstr(id->model, *list++)) {
-				return 2;
-			}
-		}
-	} else {
-		while (*list) {
-			if (!strcmp(*list++,id->model)) {
-				return 1;
-			}
-		}
-	}
+	while (*list)
+		if (strstr(id->model, *list++))
+			return 2;
 	return 0;
 }
 
@@ -523,6 +309,15 @@
 	return err;
 }
 
+#define set_2regs(a, b) \
+        OUT_BYTE((a + adj), indexreg); \
+	OUT_BYTE(b, datareg);
+
+#define set_reg_and_wait(value, reg, delay) \
+	OUT_BYTE(value, reg); \
+        mdelay(delay);
+
+
 static int pdc202xx_new_tune_chipset(struct ata_device *drive, byte speed)
 {
 	struct ata_channel *hwif = drive->channel;
@@ -549,121 +344,79 @@
 		case XFER_UDMA_7:
 			speed = XFER_UDMA_6;
 		case XFER_UDMA_6:
-			OUT_BYTE((0x10 + adj), indexreg);
-			OUT_BYTE(0x1a, datareg);
-			OUT_BYTE((0x11 + adj), indexreg);
-			OUT_BYTE(0x01, datareg);
-			OUT_BYTE((0x12 + adj), indexreg);
-			OUT_BYTE(0xcb, datareg);
+			set_2regs(0x10, 0x1a);
+			set_2regs(0x11, 0x01);
+			set_2regs(0x12, 0xcb);
 			break;
 		case XFER_UDMA_5:
-			OUT_BYTE((0x10 + adj), indexreg);
-			OUT_BYTE(0x1a, datareg);
-			OUT_BYTE((0x11 + adj), indexreg);
-			OUT_BYTE(0x02, datareg);
-			OUT_BYTE((0x12 + adj), indexreg);
-			OUT_BYTE(0xcb, datareg);
+			set_2regs(0x10, 0x1a);
+			set_2regs(0x11, 0x02);
+			set_2regs(0x12, 0xcb);
 			break;
 		case XFER_UDMA_4:
-			OUT_BYTE((0x10 + adj), indexreg);
-			OUT_BYTE(0x1a, datareg);
-			OUT_BYTE((0x11 + adj), indexreg);
-			OUT_BYTE(0x03, datareg);
-			OUT_BYTE((0x12 + adj), indexreg);
-			OUT_BYTE(0xcd, datareg);
+			set_2regs(0x10, 0x1a);
+			set_2regs(0x11, 0x03);
+			set_2regs(0x12, 0xcd);
 			break;
 		case XFER_UDMA_3:
-			OUT_BYTE((0x10 + adj), indexreg);
-			OUT_BYTE(0x1a, datareg);
-			OUT_BYTE((0x11 + adj), indexreg);
-			OUT_BYTE(0x05, datareg);
-			OUT_BYTE((0x12 + adj), indexreg);
-			OUT_BYTE(0xcd, datareg);
+			set_2regs(0x10, 0x1a);
+			set_2regs(0x11, 0x05);
+			set_2regs(0x12, 0xcd);
 			break;
 		case XFER_UDMA_2:
-			OUT_BYTE((0x10 + adj), indexreg);
-			OUT_BYTE(0x2a, datareg);
-			OUT_BYTE((0x11 + adj), indexreg);
-			OUT_BYTE(0x07, datareg);
-			OUT_BYTE((0x12 + adj), indexreg);
-			OUT_BYTE(0xcd, datareg);
+			set_2regs(0x10, 0x2a);
+			set_2regs(0x11, 0x07);
+			set_2regs(0x12, 0xcd);
 			break;
 		case XFER_UDMA_1:
-			OUT_BYTE((0x10 + adj), indexreg);
-			OUT_BYTE(0x3a, datareg);
-			OUT_BYTE((0x11 + adj), indexreg);
-			OUT_BYTE(0x0a, datareg);
-			OUT_BYTE((0x12 + adj), indexreg);
-			OUT_BYTE(0xd0, datareg);
+			set_2regs(0x10, 0x3a);
+			set_2regs(0x11, 0x0a);
+			set_2regs(0x12, 0xd0);
 			break;
 		case XFER_UDMA_0:
-			OUT_BYTE((0x10 + adj), indexreg);
-			OUT_BYTE(0x4a, datareg);
-			OUT_BYTE((0x11 + adj), indexreg);
-			OUT_BYTE(0x0f, datareg);
-			OUT_BYTE((0x12 + adj), indexreg);
-			OUT_BYTE(0xd5, datareg);
+			set_2regs(0x10, 0x4a);
+			set_2regs(0x11, 0x0f);
+			set_2regs(0x12, 0xd5);
 			break;
 		case XFER_MW_DMA_2:
-			OUT_BYTE((0x0e + adj), indexreg);
-			OUT_BYTE(0x69, datareg);
-			OUT_BYTE((0x0f + adj), indexreg);
-			OUT_BYTE(0x25, datareg);
+			set_2regs(0x0e, 0x69);
+			set_2regs(0x0f, 0x25);
 			break;
 		case XFER_MW_DMA_1:
-			OUT_BYTE((0x0e + adj), indexreg);
-			OUT_BYTE(0x6b, datareg);
-			OUT_BYTE((0x0f+ adj), indexreg);
-			OUT_BYTE(0x27, datareg);
+			set_2regs(0x0e, 0x6b);
+			set_2regs(0x0f, 0x27);
 			break;
 		case XFER_MW_DMA_0:
-			OUT_BYTE((0x0e + adj), indexreg);
-			OUT_BYTE(0xdf, datareg);
-			OUT_BYTE((0x0f + adj), indexreg);
-			OUT_BYTE(0x5f, datareg);
+			set_2regs(0x0e, 0xdf);
+			set_2regs(0x0f, 0x5f);
 			break;
 #else
 	switch (speed) {
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:
-			OUT_BYTE((0x0c + adj), indexreg);
-			OUT_BYTE(0x23, datareg);
-			OUT_BYTE((0x0d + adj), indexreg);
-			OUT_BYTE(0x09, datareg);
-			OUT_BYTE((0x13 + adj), indexreg);
-			OUT_BYTE(0x25, datareg);
+			set_2regs(0x0c, 0x23);
+			set_2regs(0x0d, 0x09);
+			set_2regs(0x13, 0x25);
 			break;
 		case XFER_PIO_3:
-			OUT_BYTE((0x0c + adj), indexreg);
-			OUT_BYTE(0x27, datareg);
-			OUT_BYTE((0x0d + adj), indexreg);
-			OUT_BYTE(0x0d, datareg);
-			OUT_BYTE((0x13 + adj), indexreg);
-			OUT_BYTE(0x35, datareg);
+			set_2regs(0x0c, 0x27);
+			set_2regs(0x0d, 0x0d);
+			set_2regs(0x13, 0x35);
 			break;
 		case XFER_PIO_2:
-			OUT_BYTE((0x0c + adj), indexreg);
-			OUT_BYTE(0x23, datareg);
-			OUT_BYTE((0x0d + adj), indexreg);
-			OUT_BYTE(0x26, datareg);
-			OUT_BYTE((0x13 + adj), indexreg);
-			OUT_BYTE(0x64, datareg);
+			set_2regs(0x0c, 0x23);
+			set_2regs(0x0d, 0x26);
+			set_2regs(0x13, 0x64);
 			break;
 		case XFER_PIO_1:
-			OUT_BYTE((0x0c + adj), indexreg);
-			OUT_BYTE(0x46, datareg);
-			OUT_BYTE((0x0d + adj), indexreg);
-			OUT_BYTE(0x29, datareg);
-			OUT_BYTE((0x13 + adj), indexreg);
-			OUT_BYTE(0xa4, datareg);
+			set_2regs(0x0c, 0x46);
+			set_2regs(0x0d, 0x29);
+			set_2regs(0x13, 0xa4);
 			break;
 		case XFER_PIO_0:
-			OUT_BYTE((0x0c + adj), indexreg);
-			OUT_BYTE(0xfb, datareg);
-			OUT_BYTE((0x0d + adj), indexreg);
-			OUT_BYTE(0x2b, datareg);
-			OUT_BYTE((0x13 + adj), indexreg);
-			OUT_BYTE(0xac, datareg);
+			set_2regs(0x0c, 0xfb);
+			set_2regs(0x0d, 0x2b);
+			set_2regs(0x13, 0xac);
 			break;
 		default:
 			;
@@ -684,21 +437,15 @@
  * 180, 120,  90,  90,  90,  60,  30
  *  11,   5,   4,   3,   2,   1,   0
  */
-static int config_chipset_for_pio(struct ata_device *drive, byte pio)
+static void config_chipset_for_pio(struct ata_device *drive, byte pio)
 {
-	byte speed = 0x00;
+	byte speed;
 
 	if (pio == 255)
 		speed = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
-	else
-		speed = XFER_PIO_0 + min_t(byte, pio, 4);
+	else	speed = XFER_PIO_0 + min_t(byte, pio, 4);
 
-	return ((int) pdc202xx_tune_chipset(drive, speed));
-}
-
-static void pdc202xx_tune_drive(struct ata_device *drive, byte pio)
-{
-	(void) config_chipset_for_pio(drive, pio);
+	pdc202xx_tune_chipset(drive, speed);
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -833,8 +580,7 @@
 		if (drive->type != ATA_DISK)
 			return 0;
 		if (id->capability & 4) {	/* IORDY_EN & PREFETCH_EN */
-			OUT_BYTE((iordy + adj), indexreg);
-			OUT_BYTE((IN_BYTE(datareg)|0x03), datareg);
+			set_2regs(iordy, (IN_BYTE(datareg)|0x03));
 		}
 		goto jumpbit_is_set;
 	}
@@ -971,7 +717,7 @@
 		on = 0;
 		verbose = 0;
 no_dma_set:
-		(void) config_chipset_for_pio(drive, 5);
+		config_chipset_for_pio(drive, 5);
 	}
 
 	udma_enable(drive, on, verbose);
@@ -979,11 +725,6 @@
 	return 0;
 }
 
-int pdc202xx_quirkproc(struct ata_device *drive)
-{
-	return ((int) check_in_drive_lists(drive, pdc_quirk_drives));
-}
-
 static int pdc202xx_udma_start(struct ata_device *drive, struct request *rq)
 {
 	u8 clock		= 0;
@@ -1119,15 +860,7 @@
 	return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
 }
 
-static void pdc202xx_udma_timeout(struct ata_device *drive)
-{
-	if (!drive->channel->resetproc)
-		return;
-	/* Assume naively that resetting the drive may help. */
-	drive->channel->resetproc(drive);
-}
-
-static void pdc202xx_udma_irq_lost(struct ata_device *drive)
+static void pdc202xx_bug (struct ata_device *drive)
 {
 	if (!drive->channel->resetproc)
 		return;
@@ -1143,10 +876,8 @@
 
 void pdc202xx_new_reset(struct ata_device *drive)
 {
-	OUT_BYTE(0x04,IDE_CONTROL_REG);
-	mdelay(1000);
-	OUT_BYTE(0x00,IDE_CONTROL_REG);
-	mdelay(1000);
+	set_reg_and_wait(0x04,IDE_CONTROL_REG, 1000);
+	set_reg_and_wait(0x00,IDE_CONTROL_REG, 1000);
 	printk("PDC202XX: %s channel reset.\n",
 		drive->channel->unit ? "Secondary" : "Primary");
 }
@@ -1156,40 +887,12 @@
 	unsigned long high_16	= pci_resource_start(drive->channel->pci_dev, 4);
 	byte udma_speed_flag	= IN_BYTE(high_16 + 0x001f);
 
-	OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f);
-	mdelay(100);
-	OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f);
-	mdelay(2000);		/* 2 seconds ?! */
+	set_reg_and_wait(udma_speed_flag | 0x10, high_16 + 0x001f, 100);
+	set_reg_and_wait(udma_speed_flag & ~0x10, high_16 + 0x001f, 2000);		/* 2 seconds ?! */
 	printk("PDC202XX: %s channel reset.\n",
 		drive->channel->unit ? "Secondary" : "Primary");
 }
 
-/*
- * Since SUN Cobalt is attempting to do this operation, I should disclose
- * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
- * HOTSWAP ATA Infrastructure.
- */
-static int pdc202xx_tristate(struct ata_device * drive, int state)
-{
-#if 0
-	struct ata_channel *hwif = drive->channel;
-	unsigned long high_16	= pci_resource_start(hwif->pci_dev, 4);
-	byte sc1f		= inb(high_16 + 0x001f);
-
-	if (!hwif)
-		return -EINVAL;
-
-//	hwif->bus_state = state;
-
-	if (state) {
-		outb(sc1f | 0x08, high_16 + 0x001f);
-	} else {
-		outb(sc1f & ~0x08, high_16 + 0x001f);
-	}
-#endif
-	return 0;
-}
-
 static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
 {
 	unsigned long high_16	= pci_resource_start(dev, 4);
@@ -1213,10 +916,8 @@
 			break;
 		case PCI_DEVICE_ID_PROMISE_20267:
 		case PCI_DEVICE_ID_PROMISE_20265:
-			OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f);
-			mdelay(100);
-			OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f);
-			mdelay(2000);   /* 2 seconds ?! */
+			set_reg_and_wait(udma_speed_flag | 0x10, high_16 + 0x001f, 100);
+			set_reg_and_wait(udma_speed_flag & ~0x10, high_16 + 0x001f, 2000);   /* 2 seconds ?! */
 			break;
 		case PCI_DEVICE_ID_PROMISE_20262:
 			/*
@@ -1229,10 +930,8 @@
 			 * reset leaves the timing registers intact,
 			 * but resets the drives.
 			 */
-			OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f);
-			mdelay(100);
-			OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f);
-			mdelay(2000);	/* 2 seconds ?! */
+			set_reg_and_wait(udma_speed_flag | 0x10, high_16 + 0x001f, 100);
+			set_reg_and_wait(udma_speed_flag & ~0x10, high_16 + 0x001f, 2000);	/* 2 seconds ?! */
 		default:
 			if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
 				byte irq = 0, irq2 = 0;
@@ -1265,31 +964,7 @@
 	}
 #endif /* CONFIG_PDC202XX_BURST */
 
-#ifdef CONFIG_PDC202XX_MASTER
-	if (!(primary_mode & 1)) {
-		printk("%s: FORCING PRIMARY MODE BIT 0x%02x -> 0x%02x ",
-			dev->name, primary_mode, (primary_mode|1));
-		OUT_BYTE(primary_mode|1, high_16 + 0x001a);
-		printk("%s\n", (IN_BYTE(high_16 + 0x001a) & 1) ? "MASTER" : "PCI");
-	}
-
-	if (!(secondary_mode & 1)) {
-		printk("%s: FORCING SECONDARY MODE BIT 0x%02x -> 0x%02x ",
-			dev->name, secondary_mode, (secondary_mode|1));
-		OUT_BYTE(secondary_mode|1, high_16 + 0x001b);
-		printk("%s\n", (IN_BYTE(high_16 + 0x001b) & 1) ? "MASTER" : "PCI");
-	}
-#endif
-
 fttk_tx_series:
-
-#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
-	if (!pdc202xx_proc) {
-		pdc202xx_proc = 1;
-		bmide_dev = dev;
-		pdc202xx_display_info = &pdc202xx_get_info;
-	}
-#endif
 	return dev->irq;
 }
 
@@ -1314,8 +989,8 @@
 
 static void __init ide_init_pdc202xx(struct ata_channel *hwif)
 {
-	hwif->tuneproc  = &pdc202xx_tune_drive;
-	hwif->quirkproc = &pdc202xx_quirkproc;
+	hwif->tuneproc  = &config_chipset_for_pio;
+	hwif->quirkproc = &check_in_drive_lists;
 
         switch(hwif->pci_dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
@@ -1329,7 +1004,6 @@
 		case PCI_DEVICE_ID_PROMISE_20267:
 		case PCI_DEVICE_ID_PROMISE_20265:
 		case PCI_DEVICE_ID_PROMISE_20262:
-			hwif->busproc   = &pdc202xx_tristate;
 			hwif->resetproc	= &pdc202xx_reset;
 		case PCI_DEVICE_ID_PROMISE_20246:
 			hwif->speedproc = &pdc202xx_tune_chipset;
@@ -1337,19 +1011,13 @@
 			break;
 	}
 
-#undef CONFIG_PDC202XX_32_UNMASK
-#ifdef CONFIG_PDC202XX_32_UNMASK
-	hwif->io_32bit = 1;
-	hwif->unmask = 1;
-#endif
-
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
 		hwif->udma_start = pdc202xx_udma_start;
 		hwif->udma_stop = pdc202xx_udma_stop;
 		hwif->udma_irq_status = pdc202xx_udma_irq_status;
-		hwif->udma_irq_lost = pdc202xx_udma_irq_lost;
-		hwif->udma_timeout = pdc202xx_udma_timeout;
+		hwif->udma_irq_lost = pdc202xx_bug;
+		hwif->udma_timeout = pdc202xx_bug;
 		hwif->XXX_udma = pdc202xx_dmaproc;
 		hwif->highmem = 1;
 		if (!noautodma)
@@ -1509,7 +1177,7 @@
 
 int __init init_pdc202xx(void)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(chipsets); ++i) {
 		ata_register_chipset(&chipsets[i]);
diff -urN linux-2.5.15/drivers/ide/quirks.c linux/drivers/ide/quirks.c
--- linux-2.5.15/drivers/ide/quirks.c	1970-01-01 01:00:00.000000000 +0100
+++ linux/drivers/ide/quirks.c	2002-05-15 13:26:34.000000000 +0200
@@ -0,0 +1,231 @@
+/**** vi:set ts=8 sts=8 sw=8:************************************************
+ *
+ *  Copyright (C) 2002 Marcin Dalecki <martin@dalecki.de>
+ *
+ *  Copyright (c) 1999-2000  Andre Hedrick <andre@linux-ide.org>
+ *  Copyright (c) 1995-1998  Mark Lord
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+/*
+ *  Just the black and white list handling for BM-DMA operation.
+ */
+
+#include <linux/config.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
+
+struct drive_list_entry {
+	char * id_model;
+	char * id_firmware;
+};
+
+struct drive_list_entry drive_whitelist[] = {
+	{ "Micropolis 2112A", NULL },
+	{ "CONNER CTMA 4000", NULL },
+	{ "CONNER CTT8000-A", NULL },
+	{ "ST34342A", NULL },
+	{ NULL, NULL }
+};
+
+struct drive_list_entry drive_blacklist[] = {
+
+	{ "WDC AC11000H", NULL },
+	{ "WDC AC22100H", NULL },
+	{ "WDC AC32500H", NULL },
+	{ "WDC AC33100H", NULL },
+	{ "WDC AC31600H", NULL },
+	{ "WDC AC32100H", "24.09P07" },
+	{ "WDC AC23200L", "21.10N21" },
+	{ "Compaq CRD-8241B", NULL },
+	{ "CRD-8400B", NULL },
+	{ "CRD-8480B", NULL },
+	{ "CRD-8480C", NULL },
+	{ "CRD-8482B", NULL },
+	{ "CRD-84", NULL },
+	{ "SanDisk SDP3B", NULL },
+	{ "SanDisk SDP3B-64", NULL },
+	{ "SANYO CD-ROM CRD", NULL },
+	{ "HITACHI CDR-8", NULL },
+	{ "HITACHI CDR-8335", NULL },
+	{ "HITACHI CDR-8435", NULL },
+	{ "Toshiba CD-ROM XM-6202B", NULL },
+	{ "CD-532E-A", NULL },
+	{ "E-IDE CD-ROM CR-840", NULL },
+	{ "CD-ROM Drive/F5A", NULL },
+	{ "RICOH CD-R/RW MP7083A", NULL },
+	{ "WPI CDD-820", NULL },
+	{ "SAMSUNG CD-ROM SC-148C", NULL },
+	{ "SAMSUNG CD-ROM SC-148F", NULL },
+	{ "SAMSUNG CD-ROM SC", NULL },
+	{ "SanDisk SDP3B-64", NULL },
+	{ "SAMSUNG CD-ROM SN-124", NULL },
+	{ "PLEXTOR CD-R PX-W8432T", NULL },
+	{ "ATAPI CD-ROM DRIVE 40X MAXIMUM", NULL },
+	{ "_NEC DV5800A", NULL },
+	{ NULL,	NULL }
+
+};
+
+static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
+{
+	for ( ; drive_table->id_model ; drive_table++)
+		if ((!strcmp(drive_table->id_model, id->model)) &&
+		    ((drive_table->id_firmware && !strstr(drive_table->id_firmware, id->fw_rev)) ||
+		     (!drive_table->id_firmware)))
+			return 1;
+	return 0;
+}
+
+#else
+
+/*
+ * good_dma_drives() lists the model names (from "hdparm -i")
+ * of drives which do not support mode2 DMA but which are
+ * known to work fine with this interface under Linux.
+ */
+const char *good_dma_drives[] = {"Micropolis 2112A",
+				 "CONNER CTMA 4000",
+				 "CONNER CTT8000-A",
+				 "ST34342A",	/* for Sun Ultra */
+				 NULL};
+
+/*
+ * bad_dma_drives() lists the model names (from "hdparm -i")
+ * of drives which supposedly support (U)DMA but which are
+ * known to corrupt data with this interface under Linux.
+ *
+ * This is an empirical list. Its generated from bug reports. That means
+ * while it reflects actual problem distributions it doesn't answer whether
+ * the drive or the controller, or cabling, or software, or some combination
+ * thereof is the fault. If you don't happen to agree with the kernel's
+ * opinion of your drive - use hdparm to turn DMA on.
+ */
+const char *bad_dma_drives[] = {"WDC AC11000H",
+				"WDC AC22100H",
+				"WDC AC32100H",
+				"WDC AC32500H",
+				"WDC AC33100H",
+				"WDC AC31600H",
+				NULL};
+
+#endif
+
+/*
+ *  For both Blacklisted and Whitelisted drives.
+ *  This is setup to be called as an extern for future support
+ *  to other special driver code.
+ */
+int check_drive_lists(struct ata_device *drive, int good_bad)
+{
+	struct hd_driveid *id = drive->id;
+
+#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
+	if (good_bad) {
+		return in_drive_list(id, drive_whitelist);
+	} else {
+		int blacklist = in_drive_list(id, drive_blacklist);
+		if (blacklist)
+			printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model);
+		return(blacklist);
+	}
+#else
+	const char **list;
+
+	if (good_bad) {
+		/* Consult the list of known "good" drives */
+		list = good_dma_drives;
+		while (*list) {
+			if (!strcmp(*list++,id->model))
+				return 1;
+		}
+	} else {
+		/* Consult the list of known "bad" drives */
+		list = bad_dma_drives;
+		while (*list) {
+			if (!strcmp(*list++,id->model)) {
+				printk("%s: Disabling (U)DMA for %s\n",
+					drive->name, id->model);
+				return 1;
+			}
+		}
+	}
+#endif
+	return 0;
+}
+
+void udma_print(struct ata_device *drive)
+{
+#ifdef CONFIG_ARCH_ACORN
+	printk(", DMA");
+#else
+	struct hd_driveid *id = drive->id;
+	char *str = NULL;
+
+	if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
+	    (id->dma_ultra & (id->dma_ultra >> 14) & 3)) {
+		if ((id->dma_ultra >> 15) & 1)
+			str = ", UDMA(mode 7)";	/* UDMA BIOS-enabled! */
+		else
+			str = ", UDMA(133)";	/* UDMA BIOS-enabled! */
+	} else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
+		  (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
+		if ((id->dma_ultra >> 13) & 1) {
+			str = ", UDMA(100)";	/* UDMA BIOS-enabled! */
+		} else if ((id->dma_ultra >> 12) & 1) {
+			str = ", UDMA(66)";	/* UDMA BIOS-enabled! */
+		} else {
+			str = ", UDMA(44)";	/* UDMA BIOS-enabled! */
+		}
+	} else if ((id->field_valid & 4) &&
+		   (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
+		if ((id->dma_ultra >> 10) & 1) {
+			str = ", UDMA(33)";	/* UDMA BIOS-enabled! */
+		} else if ((id->dma_ultra >> 9) & 1) {
+			str = ", UDMA(25)";	/* UDMA BIOS-enabled! */
+		} else {
+			str = ", UDMA(16)";	/* UDMA BIOS-enabled! */
+		}
+	} else if (id->field_valid & 4)
+		str = ", (U)DMA";	/* Can be BIOS-enabled! */
+	else
+		str = ", DMA";
+
+	printk(str);
+#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);
+}
+
+EXPORT_SYMBOL(udma_print);
+EXPORT_SYMBOL(udma_black_list);
+EXPORT_SYMBOL(udma_white_list);
diff -urN linux-2.5.15/include/linux/ide.h linux/include/linux/ide.h
--- linux-2.5.15/include/linux/ide.h	2002-05-15 14:55:12.000000000 +0200
+++ linux/include/linux/ide.h	2002-05-15 14:14:15.000000000 +0200
@@ -820,22 +820,55 @@
 
 void __init ide_scan_pcibus(int scan_direction);
 #endif
+
+static inline void udma_enable(struct ata_device *drive, int on, int verbose)
+{
+	drive->channel->udma_enable(drive, on, verbose);
+}
+
+static inline int udma_start(struct ata_device *drive, struct request *rq)
+{
+	return drive->channel->udma_start(drive, rq);
+}
+
+static inline int udma_stop(struct ata_device *drive)
+{
+	return drive->channel->udma_stop(drive);
+}
+
+static inline int udma_read(struct ata_device *drive, struct request *rq)
+{
+	return drive->channel->udma_read(drive, rq);
+}
+
+static inline int udma_write(struct ata_device *drive, struct request *rq)
+{
+	return drive->channel->udma_write(drive, rq);
+}
+
+static inline int udma_irq_status(struct ata_device *drive)
+{
+	return drive->channel->udma_irq_status(drive);
+}
+
+static inline void udma_timeout(struct ata_device *drive)
+{
+	return drive->channel->udma_timeout(drive);
+}
+
+static inline void udma_irq_lost(struct ata_device *drive)
+{
+	return drive->channel->udma_irq_lost(drive);
+}
+
 #ifdef CONFIG_BLK_DEV_IDEDMA
 
 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_irq_lost(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);
 

  parent reply	other threads:[~2002-05-15 13:07 UTC|newest]

Thread overview: 220+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-05-06  3:53 Linux-2.5.14 Linus Torvalds
2002-05-06  6:30 ` Linux-2.5.14 Daniel Pittman
2002-05-06  6:51   ` Linux-2.5.14 Andrew Morton
2002-05-06 15:13   ` Linux-2.5.14 Linus Torvalds
2002-05-07  4:28     ` Linux-2.5.14 Daniel Pittman
2002-05-09  3:53     ` Linux-2.5.14 Daniel Pittman
2002-05-09  4:34       ` Linux-2.5.14 Andrew Morton
2002-05-09  6:02         ` Linux-2.5.14 Daniel Pittman
2002-05-06  6:47 ` Linux-2.5.14 bert hubert
2002-05-06  7:07   ` Linux-2.5.14 Andrew Morton
2002-05-06 14:00     ` Linux-2.5.14 Rik van Riel
2002-05-06  9:09 ` [PATCH] 2.5.14 IDE 55 Martin Dalecki
2002-05-06 17:48   ` David Lang
2002-05-06 22:40   ` Roman Zippel
2002-05-07 10:10     ` Martin Dalecki
2002-05-07 11:31       ` Roman Zippel
2002-05-07 10:31         ` Martin Dalecki
2002-05-07 10:34           ` Martin Dalecki
2002-05-07 11:48             ` Roman Zippel
2002-05-07 11:19               ` Martin Dalecki
2002-05-07 12:35                 ` Roman Zippel
2002-05-07 12:36                 ` Andrey Panin
2002-05-07 11:32                   ` Martin Dalecki
2002-05-07 12:38                 ` Dave Jones
2002-05-07  0:03   ` Roman Zippel
2002-05-07 10:12     ` Martin Dalecki
2002-05-07 11:39       ` Roman Zippel
2002-05-07 10:40         ` Martin Dalecki
2002-05-07 12:42           ` Roman Zippel
2002-05-07 11:22 ` [PATCH] 2.5.14 IDE 56 Martin Dalecki
2002-05-07 14:02   ` Padraig Brady
2002-05-07 13:15     ` Martin Dalecki
2002-05-07 14:30       ` Padraig Brady
2002-05-07 15:08       ` Anton Altaparmakov
2002-05-07 15:36         ` Linus Torvalds
2002-05-07 16:20           ` Jan Harkes
2002-05-07 15:26             ` Martin Dalecki
2002-05-07 21:36               ` Jan Harkes
2002-05-08  0:25                 ` Guest section DW
2002-05-08  3:03                   ` Jan Harkes
2002-05-08  9:03                   ` Martin Dalecki
2002-05-08 12:10                     ` Alan Cox
2002-05-08 10:51                       ` Martin Dalecki
2002-05-07 16:29           ` Padraig Brady
2002-05-07 16:51             ` Linus Torvalds
2002-05-07 18:29               ` Kai Henningsen
2002-05-08  7:48               ` Juan Quintela
2002-05-08 16:54                 ` Linus Torvalds
2002-05-07 17:08             ` Alan Cox
2002-05-07 17:00               ` Linus Torvalds
2002-05-07 17:19                 ` benh
2002-05-07 17:24                   ` Linus Torvalds
2002-05-07 17:30                     ` benh
2002-05-10  1:45                       ` Mike Fedyk
2002-05-07 17:43                     ` Richard Gooch
2002-05-07 18:05                       ` Linus Torvalds
2002-05-07 18:26                         ` Alan Cox
2002-05-07 18:16                           ` Linus Torvalds
2002-05-07 18:40                             ` Richard Gooch
2002-05-07 18:46                               ` Linus Torvalds
2002-05-07 23:54                                 ` Roman Zippel
2002-05-08  6:57                                 ` Kai Henningsen
2002-05-08  9:37                                   ` Ian Molton
2002-05-09 13:58                                 ` Pavel Machek
2002-05-08  8:21                               ` Martin Dalecki
2002-05-07 17:27                   ` Jauder Ho
2002-05-08  8:13                     ` Martin Dalecki
2002-05-07 18:29                   ` Patrick Mochel
2002-05-07 18:02                     ` Greg KH
2002-05-07 18:44                     ` Richard Gooch
2002-05-07 18:44                       ` Patrick Mochel
2002-05-07 19:21                         ` Richard Gooch
2002-05-07 19:58                           ` Patrick Mochel
2002-05-07 18:49                     ` Thunder from the hill
2002-05-07 19:47                       ` Patrick Mochel
2002-05-07 22:03                         ` Richard Gooch
2002-05-08  8:14                           ` Russell King
2002-05-08 16:07                             ` Richard Gooch
2002-05-08 17:07                               ` Russell King
2002-05-08  8:18                     ` Martin Dalecki
2002-05-08  8:07                   ` Martin Dalecki
2002-05-08  7:58                 ` Martin Dalecki
2002-05-08 12:18                   ` Alan Cox
2002-05-08 11:09                     ` Martin Dalecki
2002-05-08 12:42                       ` Alan Cox
2002-05-08 11:23                         ` Martin Dalecki
2002-05-09  2:37                         ` Lincoln Dale
2002-05-09  3:10                           ` Andrew Morton
2002-05-09 10:05                             ` Lincoln Dale
2002-05-09 18:50                               ` Andrew Morton
2002-05-10  0:33                                 ` Andi Kleen
2002-05-10  0:48                                   ` Andrew Morton
2002-05-10  1:06                                     ` Andi Kleen
2002-05-13 17:51                                       ` Pavel Machek
2002-05-14 21:44                                         ` Andi Kleen
2002-05-10  6:50                                 ` O_DIRECT performance impact on 2.4.18 (was: Re: [PATCH] 2.5.14 IDE 56) Lincoln Dale
2002-05-10  7:15                                   ` O_DIRECT performance impact on 2.4.18 (was: Re: [PATCH] 2.5.14IDE 56) Andrew Morton
2002-05-10  7:21                                     ` Jens Axboe
2002-05-10  8:12                                     ` Andrea Arcangeli
2002-05-10 10:14                                     ` Lincoln Dale
2002-05-10 12:36                                       ` Andrea Arcangeli
2002-05-11  3:23                                         ` Lincoln Dale
2002-05-13 11:19                                           ` Andrea Arcangeli
2002-05-13 23:58                                             ` Lincoln Dale
2002-05-14  0:22                                               ` Andrea Arcangeli
2002-05-14  2:43                                                 ` O_DIRECT on 2.4.19pre8aa2 md device Lincoln Dale
2002-05-21 15:51                                                   ` Andrea Arcangeli
2002-05-22  1:18                                                     ` Lincoln Dale
2002-05-22  2:51                                                       ` Andrea Arcangeli
2002-06-03  4:53                                                         ` high-end i/o performance of 2.4.19pre8aa2 (was: Re: O_DIRECT on 2.4.19pre8aa2 device) Lincoln Dale
2002-05-12 11:23                                         ` O_DIRECT performance impact on 2.4.18 (was: Re: [PATCH] 2.5.14IDE 56) Lincoln Dale
2002-05-13 11:37                                           ` Andrea Arcangeli
2002-05-10 15:55                                   ` O_DIRECT performance impact on 2.4.18 (was: Re: [PATCH] 2.5.14 IDE 56) Linus Torvalds
2002-05-11  1:01                                     ` Gerrit Huizenga
2002-05-11 18:04                                       ` Linus Torvalds
2002-05-11 18:19                                         ` Larry McVoy
2002-05-11 18:35                                           ` Linus Torvalds
2002-05-11 18:37                                             ` Larry McVoy
2002-05-11 18:56                                               ` Linus Torvalds
2002-05-11 21:42                                                 ` Gerrit Huizenga
2002-05-11 18:43                                             ` Mr. James W. Laferriere
2002-05-11 23:38                                             ` Lincoln Dale
2002-05-12  0:36                                               ` yodaiken
2002-05-12  2:40                                                 ` Andrew Morton
2002-05-11 18:26                                         ` O_DIRECT performance impact on 2.4.18 (was: Re: [PATCH] 2.5.14 Alan Cox
2002-05-11 18:09                                           ` Linus Torvalds
2002-05-11 18:45                                         ` O_DIRECT performance impact on 2.4.18 (was: Re: [PATCH] 2.5.14 IDE 56) yodaiken
2002-05-11 19:55                                         ` O_DIRECT performance impact on 2.4.18 Bernd Eckenfels
2002-05-11 14:18                                     ` O_DIRECT performance impact on 2.4.18 (was: Re: [PATCH] 2.5.14 IDE 56) Roy Sigurd Karlsbakk
2002-05-11 14:24                                       ` Jens Axboe
2002-05-11 18:25                                         ` Gerrit Huizenga
2002-05-11 20:17                                           ` Jens Axboe
2002-05-11 22:27                                             ` Gerrit Huizenga
2002-05-11 23:17                                       ` Lincoln Dale
2002-05-09  4:16                           ` [PATCH] 2.5.14 IDE 56 Andre Hedrick
2002-05-09 13:32                             ` Alan Cox
2002-05-09 14:58                           ` Alan Cox
2002-05-08 18:21                     ` Erik Andersen
2002-05-08 18:59                       ` Dave Jones
2002-05-08 19:31                       ` Alan Cox
2002-05-08 21:16                         ` Erik Andersen
2002-05-08 22:14                           ` Alan Cox
2002-05-09 13:13                   ` Pavel Machek
2002-05-09 19:22                     ` Daniel Jacobowitz
2002-05-10 12:01                   ` Padraig Brady
2002-05-09 13:18                 ` Pavel Machek
2002-05-07 17:10             ` Richard B. Johnson
2002-05-08  7:36             ` Martin Dalecki
2002-05-08 17:22               ` Greg KH
2002-05-08 18:46   ` Denis Vlasenko
2002-05-07 11:27 ` [PATCH] 2.5.14 IDE 57 Martin Dalecki
2002-05-07 13:16   ` Anton Altaparmakov
2002-05-07 12:34     ` Martin Dalecki
2002-05-07 13:56       ` Mikael Pettersson
2002-05-07 14:04         ` Dave Jones
2002-05-07 13:57       ` Anton Altaparmakov
2002-05-07 14:08         ` Dave Jones
2002-05-07 13:11           ` Martin Dalecki
2002-05-07 14:29           ` Anton Altaparmakov
2002-05-07 13:36             ` Martin Dalecki
2002-05-07 15:08               ` Anton Altaparmakov
2002-05-07 16:51             ` Dave Jones
2002-05-08  3:38               ` Anton Altaparmakov
2002-05-08 11:47                 ` Dave Jones
2002-05-07 15:07           ` Padraig Brady
2002-05-07 17:21           ` Andre Hedrick
2002-05-11 14:09   ` Aaron Lehmann
2002-05-07 15:03 ` [PATCH] IDE 58 Martin Dalecki
2002-05-08  6:42   ` Paul Mackerras
2002-05-08  8:53     ` Martin Dalecki
2002-05-08 10:37       ` Bjorn Wesen
2002-05-08 10:16         ` Martin Dalecki
2002-05-08 19:06           ` Linus Torvalds
2002-05-08 19:10             ` Benjamin Herrenschmidt
2002-05-08 20:31               ` Alan Cox
2002-05-08 19:49                 ` Benjamin Herrenschmidt
2002-05-08 20:44                   ` Alan Cox
2002-05-08 20:04                     ` Benjamin Herrenschmidt
2002-05-09 20:20                       ` Ian Molton
2002-05-08 20:36                     ` Andre Hedrick
2002-05-08 20:29                 ` Andre Hedrick
2002-05-08 20:06                   ` Benjamin Herrenschmidt
2002-05-09 12:14                   ` Martin Dalecki
2002-05-09 15:19               ` Eric W. Biederman
2002-05-09 20:20               ` Ian Molton
2002-05-08 11:00         ` Benjamin Herrenschmidt
2002-05-09 19:58 ` [PATCH] 2.5.14 IDE 59 Martin Dalecki
2002-05-11  4:16   ` William Lee Irwin III
2002-05-11 16:59 ` [PATCH] 2.5.15 IDE 60 Martin Dalecki
2002-05-11 18:47   ` Pierre Rousselet
2002-05-11 19:12     ` Andre Hedrick
2002-05-11 19:52       ` Pierre Rousselet
2002-05-11 23:48         ` Andre Hedrick
2002-05-12 19:19   ` pdc202xx.c fails to compile in 2.5.15 Zlatko Calusic
2002-05-12 19:40     ` Jurriaan on Alpha
2002-05-12 22:00     ` Petr Vandrovec
2002-05-13 12:03       ` Alan Cox
2002-05-13  9:48 ` [PATCH] 2.5.15 IDE 61 Martin Dalecki
2002-05-13 12:17 ` [PATCH] 2.5.15 IDE 62 Martin Dalecki
2002-05-13 13:48   ` Jens Axboe
2002-05-13 13:02     ` Martin Dalecki
2002-05-13 15:38       ` Jens Axboe
2002-05-13 15:45         ` Martin Dalecki
2002-05-13 16:54           ` Linus Torvalds
2002-05-13 16:55             ` Jens Axboe
2002-05-13 16:00               ` Martin Dalecki
2002-05-13 18:02             ` benh
2002-05-13 15:50         ` Martin Dalecki
2002-05-13 17:52         ` benh
2002-05-13 15:55           ` Martin Dalecki
2002-05-13 19:13             ` benh
2002-05-14  8:48               ` Martin Dalecki
2002-05-17 11:40               ` Martin Dalecki
2002-05-17  2:27                 ` Benjamin Herrenschmidt
2002-05-13 15:36   ` Tom Rini
2002-05-14 10:26 ` [PATCH] 2.5.15 IDE 62a Martin Dalecki
2002-05-14 10:28 ` [PATCH] 2.5.15 IDE 63 Martin Dalecki
2002-05-15 12:04 ` Martin Dalecki [this message]
2002-05-15 13:12   ` [PATCH] 2.5.15 IDE 64 Russell King
2002-05-15 12:14     ` Martin Dalecki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3CE24EC8.3030202@evision-ventures.com \
    --to=dalecki@evision-ventures.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@transmeta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.