Commit acff0d93 authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.15 IDE 64

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.
parent d7e09f7e
......@@ -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
......
......@@ -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);
......
......@@ -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.
*/
......
/**** 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
*
* 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......
*/
/*
* Those are the generic BM DMA support functions for PCI bus based systems.
*/
#include <linux/config.h>
......@@ -83,115 +30,10 @@
#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.
*/
......@@ -267,53 +109,60 @@ static int build_sglist(struct ata_channel *ch, struct request *rq)
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.
* 1 dma-ing, 2 error, 4 intr
*/
int check_drive_lists(struct ata_device *drive, int good_bad)
static int dma_timer_expiry(struct ata_device *drive, struct request *rq)
{
struct hd_driveid *id = drive->id;
/* FIXME: What's that? */
u8 dma_stat = inb(drive->channel->dma_base+2);
#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;
#ifdef DEBUG
printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);
#endif
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;
}
}
}
#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;
}
static int config_drive_for_dma(struct ata_device *drive)
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;
......@@ -372,72 +221,6 @@ static int config_drive_for_dma(struct ata_device *drive)
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
*/
......@@ -463,62 +246,8 @@ void ide_release_dma(struct ata_channel *ch)
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.
* PCI specific UDMA channel method implementations.
*/
/*
......@@ -529,21 +258,13 @@ void ata_init_dma(struct ata_channel *ch, unsigned long dma_base)
* 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)
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;
/* 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;
......@@ -669,80 +390,17 @@ 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)
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;
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
......@@ -752,15 +410,12 @@ int udma_start(struct ata_device *drive, struct request *rq)
return 0;
}
int udma_stop(struct ata_device *drive)
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;
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 */
......@@ -770,97 +425,131 @@ int udma_stop(struct ata_device *drive)
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)
static int udma_pci_read(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)
static int udma_pci_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)
static int udma_pci_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)
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)
{
}
/* Invoke the chipset specific handler now. */
if (drive->channel->udma_timeout)
drive->channel->udma_timeout(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");
}
void udma_irq_lost(struct ata_device *drive)
/*
* 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 (drive->channel->udma_irq_lost)
drive->channel->udma_irq_lost(drive);
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(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);
EXPORT_SYMBOL(ide_dma_intr);
......@@ -10,10 +10,6 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
......
......@@ -53,220 +53,10 @@
#define PDC202XX_DEBUG_DRIVE_INFO 0
#define PDC202XX_DECODE_REGISTER_INFO 0
#undef DISPLAY_PDC202XX_TIMINGS
#ifndef SPLIT_BYTE
#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4)))
#endif
#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
#include <linux/proc_fs.h>
static int pdc202xx_get_info(char *, char **, off_t, int);
extern int (*pdc202xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
static struct pci_dev *bmide_dev;
char *pdc202xx_pio_verbose (u32 drive_pci)
{
if ((drive_pci & 0x000ff000) == 0x000ff000) return("NOTSET");
if ((drive_pci & 0x00000401) == 0x00000401) return("PIO 4");
if ((drive_pci & 0x00000602) == 0x00000602) return("PIO 3");
if ((drive_pci & 0x00000803) == 0x00000803) return("PIO 2");
if ((drive_pci & 0x00000C05) == 0x00000C05) return("PIO 1");
if ((drive_pci & 0x00001309) == 0x00001309) return("PIO 0");
return("PIO ?");
}
char *pdc202xx_dma_verbose (u32 drive_pci)
{
if ((drive_pci & 0x00036000) == 0x00036000) return("MWDMA 2");
if ((drive_pci & 0x00046000) == 0x00046000) return("MWDMA 1");
if ((drive_pci & 0x00056000) == 0x00056000) return("MWDMA 0");
if ((drive_pci & 0x00056000) == 0x00056000) return("SWDMA 2");
if ((drive_pci & 0x00068000) == 0x00068000) return("SWDMA 1");
if ((drive_pci & 0x000BC000) == 0x000BC000) return("SWDMA 0");
return("PIO---");
}
char *pdc202xx_ultra_verbose (u32 drive_pci, u16 slow_cable)
{
if ((drive_pci & 0x000ff000) == 0x000ff000)
return("NOTSET");
if ((drive_pci & 0x00012000) == 0x00012000)
return((slow_cable) ? "UDMA 2" : "UDMA 4");
if ((drive_pci & 0x00024000) == 0x00024000)
return((slow_cable) ? "UDMA 1" : "UDMA 3");
if ((drive_pci & 0x00036000) == 0x00036000)
return("UDMA 0");
return(pdc202xx_dma_verbose(drive_pci));
}
static char * pdc202xx_info (char *buf, struct pci_dev *dev)
{
char *p = buf;
u32 bibma = pci_resource_start(dev, 4);
u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0;
u16 reg50h = 0, pmask = (1<<10), smask = (1<<11);
u8 hi = 0, lo = 0;
/*
* at that point bibma+0x2 et bibma+0xa are byte registers
* to investigate:
*/
u8 c0 = inb_p((unsigned short)bibma + 0x02);
u8 c1 = inb_p((unsigned short)bibma + 0x0a);
u8 sc11 = inb_p((unsigned short)bibma + 0x11);
u8 sc1a = inb_p((unsigned short)bibma + 0x1a);
u8 sc1b = inb_p((unsigned short)bibma + 0x1b);
u8 sc1c = inb_p((unsigned short)bibma + 0x1c);
u8 sc1d = inb_p((unsigned short)bibma + 0x1d);
u8 sc1e = inb_p((unsigned short)bibma + 0x1e);
u8 sc1f = inb_p((unsigned short)bibma + 0x1f);
pci_read_config_word(dev, 0x50, &reg50h);
pci_read_config_dword(dev, 0x60, &reg60h);
pci_read_config_dword(dev, 0x64, &reg64h);
pci_read_config_dword(dev, 0x68, &reg68h);
pci_read_config_dword(dev, 0x6c, &reg6ch);
switch(dev->device) {
case PCI_DEVICE_ID_PROMISE_20267:
p += sprintf(p, "\n PDC20267 Chipset.\n");
break;
case PCI_DEVICE_ID_PROMISE_20265:
p += sprintf(p, "\n PDC20265 Chipset.\n");
break;
case PCI_DEVICE_ID_PROMISE_20262:
p += sprintf(p, "\n PDC20262 Chipset.\n");
break;
case PCI_DEVICE_ID_PROMISE_20246:
p += sprintf(p, "\n PDC20246 Chipset.\n");
reg50h |= 0x0c00;
break;
default:
p += sprintf(p, "\n PDC202XX Chipset.\n");
break;
}
p += sprintf(p, "------------------------------- General Status ---------------------------------\n");
p += sprintf(p, "Burst Mode : %sabled\n", (sc1f & 0x01) ? "en" : "dis");
p += sprintf(p, "Host Mode : %s\n", (sc1f & 0x08) ? "Tri-Stated" : "Normal");
p += sprintf(p, "Bus Clocking : %s\n",
((sc1f & 0xC0) == 0xC0) ? "100 External" :
((sc1f & 0x80) == 0x80) ? "66 External" :
((sc1f & 0x40) == 0x40) ? "33 External" : "33 PCI Internal");
p += sprintf(p, "IO pad select : %s mA\n",
((sc1c & 0x03) == 0x03) ? "10" :
((sc1c & 0x02) == 0x02) ? "8" :
((sc1c & 0x01) == 0x01) ? "6" :
((sc1c & 0x00) == 0x00) ? "4" : "??");
SPLIT_BYTE(sc1e, hi, lo);
p += sprintf(p, "Status Polling Period : %d\n", hi);
p += sprintf(p, "Interrupt Check Status Polling Delay : %d\n", lo);
p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
p += sprintf(p, " %s %s\n",
(c0&0x80)?"disabled":"enabled ",
(c1&0x80)?"disabled":"enabled ");
p += sprintf(p, "66 Clocking %s %s\n",
(sc11&0x02)?"enabled ":"disabled",
(sc11&0x08)?"enabled ":"disabled");
p += sprintf(p, " Mode %s Mode %s\n",
(sc1a & 0x01) ? "MASTER" : "PCI ",
(sc1b & 0x01) ? "MASTER" : "PCI ");
p += sprintf(p, " %s %s\n",
(sc1d & 0x08) ? "Error " :
((sc1d & 0x05) == 0x05) ? "Not My INTR " :
(sc1d & 0x04) ? "Interrupting" :
(sc1d & 0x02) ? "FIFO Full " :
(sc1d & 0x01) ? "FIFO Empty " : "????????????",
(sc1d & 0x80) ? "Error " :
((sc1d & 0x50) == 0x50) ? "Not My INTR " :
(sc1d & 0x40) ? "Interrupting" :
(sc1d & 0x20) ? "FIFO Full " :
(sc1d & 0x10) ? "FIFO Empty " : "????????????");
p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
p += sprintf(p, "DMA enabled: %s %s %s %s\n",
(c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
p += sprintf(p, "DMA Mode: %s %s %s %s\n",
pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)),
pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)),
pdc202xx_ultra_verbose(reg68h, (reg50h & smask)),
pdc202xx_ultra_verbose(reg6ch, (reg50h & smask)));
p += sprintf(p, "PIO Mode: %s %s %s %s\n",
pdc202xx_pio_verbose(reg60h),
pdc202xx_pio_verbose(reg64h),
pdc202xx_pio_verbose(reg68h),
pdc202xx_pio_verbose(reg6ch));
#if 0
p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n");
#endif
return (char *)p;
}
static char * pdc202xx_info_new (char *buf, struct pci_dev *dev)
{
char *p = buf;
// u32 bibma = pci_resource_start(dev, 4);
// u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0;
// u16 reg50h = 0, word88 = 0;
// int udmasel[4]={0,0,0,0}, piosel[4]={0,0,0,0}, i=0, hd=0;
switch(dev->device) {
case PCI_DEVICE_ID_PROMISE_20275:
p += sprintf(p, "\n PDC20275 Chipset.\n");
break;
case PCI_DEVICE_ID_PROMISE_20276:
p += sprintf(p, "\n PDC20276 Chipset.\n");
break;
case PCI_DEVICE_ID_PROMISE_20269:
p += sprintf(p, "\n PDC20269 TX2 Chipset.\n");
break;
case PCI_DEVICE_ID_PROMISE_20268:
case PCI_DEVICE_ID_PROMISE_20268R:
p += sprintf(p, "\n PDC20268 TX2 Chipset.\n");
break;
default:
p += sprintf(p, "\n PDC202XX Chipset.\n");
break;
}
return (char *)p;
}
static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count)
{
char *p = buffer;
switch(bmide_dev->device) {
case PCI_DEVICE_ID_PROMISE_20275:
case PCI_DEVICE_ID_PROMISE_20276:
case PCI_DEVICE_ID_PROMISE_20269:
case PCI_DEVICE_ID_PROMISE_20268:
case PCI_DEVICE_ID_PROMISE_20268R:
p = pdc202xx_info_new(buffer, bmide_dev);
break;
default:
p = pdc202xx_info(buffer, bmide_dev);
break;
}
return p-buffer; /* => must be less than 4k! */
}
#endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */
byte pdc202xx_proc = 0;
const char *pdc_quirk_drives[] = {
"QUANTUM FIREBALLlct08 08",
"QUANTUM FIREBALLP KA6.4",
"QUANTUM FIREBALLP LM20.4",
"QUANTUM FIREBALLP KX20.5",
"QUANTUM FIREBALLP KX27.3",
"QUANTUM FIREBALLP LM20.5",
NULL
};
extern char *ide_xfer_verbose (byte xfer_rate);
/* A Register */
......@@ -322,7 +112,6 @@ 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 @@ static int config_drive_xfer_rate(struct ata_device *drive)
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 @@ static int config_drive_xfer_rate(struct ata_device *drive)
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 @@ static int pdc202xx_udma_irq_status(struct ata_device *drive)
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]);
......
/**** 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);
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment