lkml.org 
[lkml]   [2002]   [May]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH] 2.5.15 IDE 64
    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.

    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);
    \
     
     \ /
      Last update: 2005-03-22 13:26    [W:2.151 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site