]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] 2.5.15 IDE 64
authorMartin Dalecki <dalecki@evision-ventures.com>
Fri, 17 May 2002 16:49:53 +0000 (09:49 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Fri, 17 May 2002 16:49:53 +0000 (09:49 -0700)
Let's just get over with  this before queue handling will be targeted again...

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

- pdc202xxx updates from Thierry Vignaud.

- Tiny PIO fix from Tomita.

drivers/ide/Makefile
drivers/ide/ide-dma.c [deleted file]
drivers/ide/ide-taskfile.c
drivers/ide/ide.c
drivers/ide/pcidma.c [new file with mode: 0644]
drivers/ide/pcihost.h
drivers/ide/pdc202xx.c
drivers/ide/quirks.c [new file with mode: 0644]
include/linux/ide.h

index b004ba92bc4e5b95c40bc73d0ea89ae6010b2feb..8655590ea98dc95d583c5d0286b214d8c309f5d3 100644 (file)
@@ -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_HPT34X)      += hpt34x.o
 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 --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
deleted file mode 100644 (file)
index 59542ba..0000000
+++ /dev/null
@@ -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);
index cd620d6074af83f487e731810457102fe513b2df..4be7d8b00f852a3dc587c5c4fb8825be8fd6ce30 100644 (file)
@@ -562,7 +562,7 @@ static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *r
                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);
 
index 61223d6780269ad20ff4985b1e6b6fdd04f72e9e..1279afbe463d6049d1157859b0bb0c0a1fb8d407 100644 (file)
@@ -1145,7 +1145,7 @@ static unsigned long longest_sleep(struct ata_channel *channel)
 }
 
 /*
- * 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 --git a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c
new file mode 100644 (file)
index 0000000..b9a33e5
--- /dev/null
@@ -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);
index 915ae978eef9edd56e71a809ccea0352fc4ae422..c994b1b1ccc63197cefa17b015b2bfdc527d4a9c 100644 (file)
  * 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
  */
 
 /*
index b6b9b207627d9fcef57cd409953d0f93bebffdf5..8eaa7256534432a5b391de6cbb9484ea9f3ee349 100644 (file)
 #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 @@ static void decode_registers (byte registers, byte value)
 
        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 @@ static void decode_registers (byte registers, byte value)
                        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 @@ static void decode_registers (byte registers, byte value)
                        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 @@ static void decode_registers (byte registers, byte value)
 
 #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 @@ static int pdc202xx_tune_chipset(struct ata_device *drive, byte speed)
        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 @@ static int pdc202xx_new_tune_chipset(struct ata_device *drive, byte speed)
                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 @@ static int pdc202xx_new_tune_chipset(struct ata_device *drive, byte speed)
  * 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 @@ static int config_chipset_for_dma(struct ata_device *drive, byte ultra)
                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 @@ fast_ata_pio:
                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 @@ no_dma_set:
        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 @@ somebody_else:
        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 @@ static int pdc202xx_dmaproc(struct ata_device *drive)
 
 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 @@ void pdc202xx_reset(struct ata_device *drive)
        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 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
                        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 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
                         * 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 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev)
        }
 #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 unsigned int __init ata66_pdc202xx(struct ata_channel *hwif)
 
 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 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif)
                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 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif)
                        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 @@ static struct ata_pci_device chipsets[] __initdata = {
 
 int __init init_pdc202xx(void)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(chipsets); ++i) {
                ata_register_chipset(&chipsets[i]);
diff --git a/drivers/ide/quirks.c b/drivers/ide/quirks.c
new file mode 100644 (file)
index 0000000..d4cd055
--- /dev/null
@@ -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);
index 34b7b973a815a99f321c64b428591ff6b7c5d42d..a66146efd024c6b86f3cb455d26410ec9b602a95 100644 (file)
@@ -820,22 +820,55 @@ extern int ide_unregister_subdriver(struct ata_device *drive);
 
 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);