You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-next-2.6: (49 commits) drivers/ide: Fix continuation line formats ide: fixed section mismatch warning in cmd640.c ide: ide_timing_compute() fixup ide: make ide_get_best_pio_mode() static via82cxxx: use ->pio_mode value to determine pair device speed tx493xide: use ->pio_mode value to determine pair device speed siimage: use ->pio_mode value to determine pair device speed palm_bk3710: use ->pio_mode value to determine pair device speed it821x: use ->pio_mode value to determine pair device speed cs5536: use ->pio_mode value to determine pair device speed cs5535: use ->pio_mode value to determine pair device speed cmd64x: fix handling of address setup timings amd74xx: use ->pio_mode value to determine pair device speed alim15x3: fix handling of UDMA enable bit alim15x3: fix handling of DMA timings alim15x3: fix handling of command timings alim15x3: fix handling of address setup timings ide-timings: use ->pio_mode value to determine fastest PIO speed ide: change ->set_dma_mode method parameters ide: change ->set_pio_mode method parameters ...
This commit is contained in:
@@ -81,15 +81,15 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr
|
||||
return chipset_table->ultra_settings;
|
||||
}
|
||||
|
||||
static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void aec6210_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct ide_host *host = pci_get_drvdata(dev);
|
||||
struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
|
||||
u16 d_conf = 0;
|
||||
u8 ultra = 0, ultra_conf = 0;
|
||||
u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
|
||||
const u8 speed = drive->dma_mode;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
@@ -109,15 +109,15 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void aec6260_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct ide_host *host = pci_get_drvdata(dev);
|
||||
struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
|
||||
u8 unit = drive->dn & 1;
|
||||
u8 tmp1 = 0, tmp2 = 0;
|
||||
u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
|
||||
const u8 speed = drive->dma_mode;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
@@ -134,9 +134,10 @@ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void aec_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
|
||||
drive->dma_mode = drive->pio_mode;
|
||||
hwif->port_ops->set_dma_mode(hwif, drive);
|
||||
}
|
||||
|
||||
static int init_chipset_aec62xx(struct pci_dev *dev)
|
||||
|
||||
@@ -109,13 +109,14 @@ static DEFINE_SPINLOCK(ali14xx_lock);
|
||||
* This function computes timing parameters
|
||||
* and sets controller registers accordingly.
|
||||
*/
|
||||
static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void ali14xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
int driveNum;
|
||||
int time1, time2;
|
||||
u8 param1, param2, param3, param4;
|
||||
unsigned long flags;
|
||||
int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
|
||||
const u8 pio = drive->pio_mode - XFER_PIO_0;
|
||||
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
|
||||
|
||||
/* calculate timing, according to PIO mode */
|
||||
|
||||
+89
-76
@@ -8,7 +8,7 @@
|
||||
* Copyright (C) 2002 Alan Cox
|
||||
* ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
|
||||
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
|
||||
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
|
||||
* Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
|
||||
*
|
||||
* (U)DMA capable version of ali 1533/1543(C), 1535(D)
|
||||
*
|
||||
@@ -48,61 +48,84 @@ static u8 m5229_revision;
|
||||
static u8 chip_is_1543c_e;
|
||||
static struct pci_dev *isa_dev;
|
||||
|
||||
static void ali_fifo_control(ide_hwif_t *hwif, ide_drive_t *drive, int on)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(hwif->dev);
|
||||
int pio_fifo = 0x54 + hwif->channel;
|
||||
u8 fifo;
|
||||
int shift = 4 * (drive->dn & 1);
|
||||
|
||||
pci_read_config_byte(pdev, pio_fifo, &fifo);
|
||||
fifo &= ~(0x0F << shift);
|
||||
fifo |= (on << shift);
|
||||
pci_write_config_byte(pdev, pio_fifo, fifo);
|
||||
}
|
||||
|
||||
static void ali_program_timings(ide_hwif_t *hwif, ide_drive_t *drive,
|
||||
struct ide_timing *t, u8 ultra)
|
||||
{
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
int port = hwif->channel ? 0x5c : 0x58;
|
||||
int udmat = 0x56 + hwif->channel;
|
||||
u8 unit = drive->dn & 1, udma;
|
||||
int shift = 4 * unit;
|
||||
|
||||
/* Set up the UDMA */
|
||||
pci_read_config_byte(dev, udmat, &udma);
|
||||
udma &= ~(0x0F << shift);
|
||||
udma |= ultra << shift;
|
||||
pci_write_config_byte(dev, udmat, udma);
|
||||
|
||||
if (t == NULL)
|
||||
return;
|
||||
|
||||
t->setup = clamp_val(t->setup, 1, 8) & 7;
|
||||
t->act8b = clamp_val(t->act8b, 1, 8) & 7;
|
||||
t->rec8b = clamp_val(t->rec8b, 1, 16) & 15;
|
||||
t->active = clamp_val(t->active, 1, 8) & 7;
|
||||
t->recover = clamp_val(t->recover, 1, 16) & 15;
|
||||
|
||||
pci_write_config_byte(dev, port, t->setup);
|
||||
pci_write_config_byte(dev, port + 1, (t->act8b << 4) | t->rec8b);
|
||||
pci_write_config_byte(dev, port + unit + 2,
|
||||
(t->active << 4) | t->recover);
|
||||
}
|
||||
|
||||
/**
|
||||
* ali_set_pio_mode - set host controller for PIO mode
|
||||
* @hwif: port
|
||||
* @drive: drive
|
||||
* @pio: PIO mode number
|
||||
*
|
||||
* Program the controller for the given PIO mode.
|
||||
*/
|
||||
|
||||
static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void ali_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
|
||||
int s_time = t->setup, a_time = t->active, c_time = t->cycle;
|
||||
u8 s_clc, a_clc, r_clc;
|
||||
unsigned long flags;
|
||||
ide_drive_t *pair = ide_get_pair_dev(drive);
|
||||
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
|
||||
int port = hwif->channel ? 0x5c : 0x58;
|
||||
int portFIFO = hwif->channel ? 0x55 : 0x54;
|
||||
u8 cd_dma_fifo = 0, unit = drive->dn & 1;
|
||||
unsigned long T = 1000000 / bus_speed; /* PCI clock based */
|
||||
struct ide_timing t;
|
||||
|
||||
if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
|
||||
s_clc = 0;
|
||||
if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
|
||||
a_clc = 0;
|
||||
ide_timing_compute(drive, drive->pio_mode, &t, T, 1);
|
||||
if (pair) {
|
||||
struct ide_timing p;
|
||||
|
||||
if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
|
||||
r_clc = 1;
|
||||
} else {
|
||||
if (r_clc >= 16)
|
||||
r_clc = 0;
|
||||
ide_timing_compute(pair, pair->pio_mode, &p, T, 1);
|
||||
ide_timing_merge(&p, &t, &t,
|
||||
IDE_TIMING_SETUP | IDE_TIMING_8BIT);
|
||||
if (pair->dma_mode) {
|
||||
ide_timing_compute(pair, pair->dma_mode, &p, T, 1);
|
||||
ide_timing_merge(&p, &t, &t,
|
||||
IDE_TIMING_SETUP | IDE_TIMING_8BIT);
|
||||
}
|
||||
}
|
||||
local_irq_save(flags);
|
||||
|
||||
|
||||
/*
|
||||
* PIO mode => ATA FIFO on, ATAPI FIFO off
|
||||
*/
|
||||
pci_read_config_byte(dev, portFIFO, &cd_dma_fifo);
|
||||
if (drive->media==ide_disk) {
|
||||
if (unit) {
|
||||
pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50);
|
||||
} else {
|
||||
pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05);
|
||||
}
|
||||
} else {
|
||||
if (unit) {
|
||||
pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F);
|
||||
} else {
|
||||
pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0);
|
||||
}
|
||||
}
|
||||
|
||||
pci_write_config_byte(dev, port, s_clc);
|
||||
pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc);
|
||||
local_irq_restore(flags);
|
||||
ali_fifo_control(hwif, drive, (drive->media == ide_disk) ? 0x05 : 0x00);
|
||||
|
||||
ali_program_timings(hwif, drive, &t, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,44 +155,42 @@ static u8 ali_udma_filter(ide_drive_t *drive)
|
||||
|
||||
/**
|
||||
* ali_set_dma_mode - set host controller for DMA mode
|
||||
* @hwif: port
|
||||
* @drive: drive
|
||||
* @speed: DMA mode
|
||||
*
|
||||
* Configure the hardware for the desired IDE transfer mode.
|
||||
*/
|
||||
|
||||
static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void ali_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD };
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
u8 speed1 = speed;
|
||||
u8 unit = drive->dn & 1;
|
||||
ide_drive_t *pair = ide_get_pair_dev(drive);
|
||||
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
|
||||
unsigned long T = 1000000 / bus_speed; /* PCI clock based */
|
||||
const u8 speed = drive->dma_mode;
|
||||
u8 tmpbyte = 0x00;
|
||||
int m5229_udma = (hwif->channel) ? 0x57 : 0x56;
|
||||
|
||||
if (speed == XFER_UDMA_6)
|
||||
speed1 = 0x47;
|
||||
struct ide_timing t;
|
||||
|
||||
if (speed < XFER_UDMA_0) {
|
||||
u8 ultra_enable = (unit) ? 0x7f : 0xf7;
|
||||
/*
|
||||
* clear "ultra enable" bit
|
||||
*/
|
||||
pci_read_config_byte(dev, m5229_udma, &tmpbyte);
|
||||
tmpbyte &= ultra_enable;
|
||||
pci_write_config_byte(dev, m5229_udma, tmpbyte);
|
||||
ide_timing_compute(drive, drive->dma_mode, &t, T, 1);
|
||||
if (pair) {
|
||||
struct ide_timing p;
|
||||
|
||||
/*
|
||||
* FIXME: Oh, my... DMA timings are never set.
|
||||
*/
|
||||
ide_timing_compute(pair, pair->pio_mode, &p, T, 1);
|
||||
ide_timing_merge(&p, &t, &t,
|
||||
IDE_TIMING_SETUP | IDE_TIMING_8BIT);
|
||||
if (pair->dma_mode) {
|
||||
ide_timing_compute(pair, pair->dma_mode,
|
||||
&p, T, 1);
|
||||
ide_timing_merge(&p, &t, &t,
|
||||
IDE_TIMING_SETUP | IDE_TIMING_8BIT);
|
||||
}
|
||||
}
|
||||
ali_program_timings(hwif, drive, &t, 0);
|
||||
} else {
|
||||
pci_read_config_byte(dev, m5229_udma, &tmpbyte);
|
||||
tmpbyte &= (0x0f << ((1-unit) << 2));
|
||||
/*
|
||||
* enable ultra dma and set timing
|
||||
*/
|
||||
tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2));
|
||||
pci_write_config_byte(dev, m5229_udma, tmpbyte);
|
||||
ali_program_timings(hwif, drive, NULL,
|
||||
udma_timing[speed - XFER_UDMA_0]);
|
||||
if (speed >= XFER_UDMA_3) {
|
||||
pci_read_config_byte(dev, 0x4b, &tmpbyte);
|
||||
tmpbyte |= 1;
|
||||
@@ -355,19 +376,13 @@ static int ali_cable_override(struct pci_dev *pdev)
|
||||
*
|
||||
* This checks if the controller and the cable are capable
|
||||
* of UDMA66 transfers. It doesn't check the drives.
|
||||
* But see note 2 below!
|
||||
*
|
||||
* FIXME: frobs bits that are not defined on newer ALi devicea
|
||||
*/
|
||||
|
||||
static u8 ali_cable_detect(ide_hwif_t *hwif)
|
||||
{
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
unsigned long flags;
|
||||
u8 cbl = ATA_CBL_PATA40, tmpbyte;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (m5229_revision >= 0xC2) {
|
||||
/*
|
||||
* m5229 80-pin cable detection (from Host View)
|
||||
@@ -387,8 +402,6 @@ static u8 ali_cable_detect(ide_hwif_t *hwif)
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return cbl;
|
||||
}
|
||||
|
||||
@@ -584,6 +597,6 @@ static void __exit ali15x3_ide_exit(void)
|
||||
module_init(ali15x3_ide_init);
|
||||
module_exit(ali15x3_ide_exit);
|
||||
|
||||
MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
|
||||
MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox, Bartlomiej Zolnierkiewicz");
|
||||
MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
+10
-8
@@ -3,7 +3,7 @@
|
||||
* IDE driver for Linux.
|
||||
*
|
||||
* Copyright (c) 2000-2002 Vojtech Pavlik
|
||||
* Copyright (c) 2007-2008 Bartlomiej Zolnierkiewicz
|
||||
* Copyright (c) 2007-2010 Bartlomiej Zolnierkiewicz
|
||||
*
|
||||
* Based on the work of:
|
||||
* Andre Hedrick
|
||||
@@ -70,7 +70,8 @@ static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
|
||||
default: return;
|
||||
}
|
||||
|
||||
pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + (3 - dn), t);
|
||||
if (timing->udma)
|
||||
pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + 3 - dn, t);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -78,14 +79,14 @@ static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
|
||||
* to a desired transfer mode. It also can be called by upper layers.
|
||||
*/
|
||||
|
||||
static void amd_set_drive(ide_drive_t *drive, const u8 speed)
|
||||
static void amd_set_drive(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
ide_drive_t *peer = ide_get_pair_dev(drive);
|
||||
struct ide_timing t, p;
|
||||
int T, UT;
|
||||
u8 udma_mask = hwif->ultra_mask;
|
||||
const u8 speed = drive->dma_mode;
|
||||
|
||||
T = 1000000000 / amd_clock;
|
||||
UT = (udma_mask == ATA_UDMA2) ? T : (T / 2);
|
||||
@@ -93,7 +94,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
|
||||
ide_timing_compute(drive, speed, &t, T, UT);
|
||||
|
||||
if (peer) {
|
||||
ide_timing_compute(peer, peer->current_speed, &p, T, UT);
|
||||
ide_timing_compute(peer, peer->pio_mode, &p, T, UT);
|
||||
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
|
||||
}
|
||||
|
||||
@@ -107,9 +108,10 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
|
||||
* amd_set_pio_mode() is a callback from upper layers for PIO-only tuning.
|
||||
*/
|
||||
|
||||
static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void amd_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
amd_set_drive(drive, XFER_PIO_0 + pio);
|
||||
drive->dma_mode = drive->pio_mode;
|
||||
amd_set_drive(hwif, drive);
|
||||
}
|
||||
|
||||
static void amd7409_cable_detect(struct pci_dev *dev)
|
||||
@@ -340,6 +342,6 @@ static void __exit amd74xx_ide_exit(void)
|
||||
module_init(amd74xx_ide_init);
|
||||
module_exit(amd74xx_ide_exit);
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik");
|
||||
MODULE_AUTHOR("Vojtech Pavlik, Bartlomiej Zolnierkiewicz");
|
||||
MODULE_DESCRIPTION("AMD PCI IDE driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -172,11 +172,12 @@ static void at91_ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
|
||||
leave_16bit(chipselect, mode);
|
||||
}
|
||||
|
||||
static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void at91_ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
struct ide_timing *timing;
|
||||
u8 chipselect = drive->hwif->select_data;
|
||||
u8 chipselect = hwif->select_data;
|
||||
int use_iordy = 0;
|
||||
const u8 pio = drive->pio_mode - XFER_PIO_0;
|
||||
|
||||
pdbg("chipselect %u pio %u\n", chipselect, pio);
|
||||
|
||||
|
||||
@@ -42,19 +42,20 @@ static DEFINE_SPINLOCK(atiixp_lock);
|
||||
|
||||
/**
|
||||
* atiixp_set_pio_mode - set host controller for PIO mode
|
||||
* @hwif: port
|
||||
* @drive: drive
|
||||
* @pio: PIO mode number
|
||||
*
|
||||
* Set the interface PIO mode.
|
||||
*/
|
||||
|
||||
static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void atiixp_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
unsigned long flags;
|
||||
int timing_shift = (drive->dn ^ 1) * 8;
|
||||
u32 pio_timing_data;
|
||||
u16 pio_mode_data;
|
||||
const u8 pio = drive->pio_mode - XFER_PIO_0;
|
||||
|
||||
spin_lock_irqsave(&atiixp_lock, flags);
|
||||
|
||||
@@ -74,21 +75,22 @@ static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
|
||||
/**
|
||||
* atiixp_set_dma_mode - set host controller for DMA mode
|
||||
* @hwif: port
|
||||
* @drive: drive
|
||||
* @speed: DMA mode
|
||||
*
|
||||
* Set a ATIIXP host controller to the desired DMA mode. This involves
|
||||
* programming the right timing data into the PCI configuration space.
|
||||
*/
|
||||
|
||||
static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void atiixp_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
unsigned long flags;
|
||||
int timing_shift = (drive->dn ^ 1) * 8;
|
||||
u32 tmp32;
|
||||
u16 tmp16;
|
||||
u16 udma_ctl = 0;
|
||||
const u8 speed = drive->dma_mode;
|
||||
|
||||
spin_lock_irqsave(&atiixp_lock, flags);
|
||||
|
||||
|
||||
@@ -99,12 +99,11 @@ static void au1xxx_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
|
||||
}
|
||||
#endif
|
||||
|
||||
static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void au1xxx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
|
||||
|
||||
/* set pio mode! */
|
||||
switch(pio) {
|
||||
switch (drive->pio_mode - XFER_PIO_0) {
|
||||
case 0:
|
||||
mem_sttime = SBC_IDE_TIMING(PIO0);
|
||||
|
||||
@@ -161,11 +160,11 @@ static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
au_writel(mem_stcfg,MEM_STCFG2);
|
||||
}
|
||||
|
||||
static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void auide_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
|
||||
|
||||
switch(speed) {
|
||||
switch (drive->dma_mode) {
|
||||
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
|
||||
case XFER_MW_DMA_2:
|
||||
mem_sttime = SBC_IDE_TIMING(MDMA2);
|
||||
@@ -297,8 +296,8 @@ static int auide_dma_test_irq(ide_drive_t *drive)
|
||||
*/
|
||||
drive->waiting_for_dma++;
|
||||
if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
|
||||
printk(KERN_WARNING "%s: timeout waiting for ddma to \
|
||||
complete\n", drive->name);
|
||||
printk(KERN_WARNING "%s: timeout waiting for ddma to complete\n",
|
||||
drive->name);
|
||||
return 1;
|
||||
}
|
||||
udelay(10);
|
||||
|
||||
@@ -572,9 +572,10 @@ static void cmd640_set_mode(ide_drive_t *drive, unsigned int index,
|
||||
program_drive_counts(drive, index);
|
||||
}
|
||||
|
||||
static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void cmd640_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
unsigned int index = 0, cycle_time;
|
||||
const u8 pio = drive->pio_mode - XFER_PIO_0;
|
||||
u8 b;
|
||||
|
||||
switch (pio) {
|
||||
@@ -605,7 +606,7 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
|
||||
|
||||
static void cmd640_init_dev(ide_drive_t *drive)
|
||||
static void __init cmd640_init_dev(ide_drive_t *drive)
|
||||
{
|
||||
unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1);
|
||||
|
||||
|
||||
+43
-71
@@ -7,6 +7,7 @@
|
||||
* Copyright (C) 1998 David S. Miller (davem@redhat.com)
|
||||
*
|
||||
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
|
||||
* Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
|
||||
* Copyright (C) 2007,2009 MontaVista Software, Inc. <source@mvista.com>
|
||||
*/
|
||||
|
||||
@@ -50,72 +51,42 @@
|
||||
#define UDIDETCR1 0x7B
|
||||
#define DTPR1 0x7C
|
||||
|
||||
static u8 quantize_timing(int timing, int quant)
|
||||
{
|
||||
return (timing + quant - 1) / quant;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine calculates active/recovery counts and then writes them into
|
||||
* the chipset registers.
|
||||
*/
|
||||
static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
|
||||
static void cmd64x_program_timings(ide_drive_t *drive, u8 mode)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
|
||||
int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33);
|
||||
u8 cycle_count, active_count, recovery_count, drwtim;
|
||||
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
|
||||
const unsigned long T = 1000000 / bus_speed;
|
||||
static const u8 recovery_values[] =
|
||||
{15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
|
||||
static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
|
||||
static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
|
||||
static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};
|
||||
struct ide_timing t;
|
||||
u8 arttim = 0;
|
||||
|
||||
cycle_count = quantize_timing( cycle_time, clock_time);
|
||||
active_count = quantize_timing(active_time, clock_time);
|
||||
recovery_count = cycle_count - active_count;
|
||||
ide_timing_compute(drive, mode, &t, T, 0);
|
||||
|
||||
/*
|
||||
* In case we've got too long recovery phase, try to lengthen
|
||||
* the active phase
|
||||
*/
|
||||
if (recovery_count > 16) {
|
||||
active_count += recovery_count - 16;
|
||||
recovery_count = 16;
|
||||
if (t.recover > 16) {
|
||||
t.active += t.recover - 16;
|
||||
t.recover = 16;
|
||||
}
|
||||
if (active_count > 16) /* shouldn't actually happen... */
|
||||
active_count = 16;
|
||||
if (t.active > 16) /* shouldn't actually happen... */
|
||||
t.active = 16;
|
||||
|
||||
/*
|
||||
* Convert values to internal chipset representation
|
||||
*/
|
||||
recovery_count = recovery_values[recovery_count];
|
||||
active_count &= 0x0f;
|
||||
t.recover = recovery_values[t.recover];
|
||||
t.active &= 0x0f;
|
||||
|
||||
/* Program the active/recovery counts into the DRWTIM register */
|
||||
drwtim = (active_count << 4) | recovery_count;
|
||||
(void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine writes into the chipset registers
|
||||
* PIO setup/active/recovery timings.
|
||||
*/
|
||||
static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
|
||||
unsigned long setup_count;
|
||||
unsigned int cycle_time;
|
||||
u8 arttim = 0;
|
||||
|
||||
static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
|
||||
static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
|
||||
|
||||
cycle_time = ide_pio_cycle_time(drive, pio);
|
||||
|
||||
program_cycle_times(drive, cycle_time, t->active);
|
||||
|
||||
setup_count = quantize_timing(t->setup,
|
||||
1000 / (ide_pci_clk ? ide_pci_clk : 33));
|
||||
pci_write_config_byte(dev, drwtim_regs[drive->dn],
|
||||
(t.active << 4) | t.recover);
|
||||
|
||||
/*
|
||||
* The primary channel has individual address setup timing registers
|
||||
@@ -126,15 +97,21 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
|
||||
if (hwif->channel) {
|
||||
ide_drive_t *pair = ide_get_pair_dev(drive);
|
||||
|
||||
ide_set_drivedata(drive, (void *)setup_count);
|
||||
if (pair) {
|
||||
struct ide_timing tp;
|
||||
|
||||
if (pair)
|
||||
setup_count = max_t(u8, setup_count,
|
||||
(unsigned long)ide_get_drivedata(pair));
|
||||
ide_timing_compute(pair, pair->pio_mode, &tp, T, 0);
|
||||
ide_timing_merge(&t, &tp, &t, IDE_TIMING_SETUP);
|
||||
if (pair->dma_mode) {
|
||||
ide_timing_compute(pair, pair->dma_mode,
|
||||
&tp, T, 0);
|
||||
ide_timing_merge(&tp, &t, &t, IDE_TIMING_SETUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setup_count > 5) /* shouldn't actually happen... */
|
||||
setup_count = 5;
|
||||
if (t.setup > 5) /* shouldn't actually happen... */
|
||||
t.setup = 5;
|
||||
|
||||
/*
|
||||
* Program the address setup clocks into the ARTTIM registers.
|
||||
@@ -144,7 +121,7 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
|
||||
if (hwif->channel)
|
||||
arttim &= ~ARTTIM23_INTR_CH1;
|
||||
arttim &= ~0xc0;
|
||||
arttim |= setup_values[setup_count];
|
||||
arttim |= setup_values[t.setup];
|
||||
(void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
|
||||
}
|
||||
|
||||
@@ -153,8 +130,10 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
|
||||
* Special cases are 8: prefetch off, 9: prefetch on (both never worked)
|
||||
*/
|
||||
|
||||
static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void cmd64x_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
const u8 pio = drive->pio_mode - XFER_PIO_0;
|
||||
|
||||
/*
|
||||
* Filter out the prefetch control values
|
||||
* to prevent PIO5 from being programmed
|
||||
@@ -162,20 +141,18 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
if (pio == 8 || pio == 9)
|
||||
return;
|
||||
|
||||
cmd64x_tune_pio(drive, pio);
|
||||
cmd64x_program_timings(drive, XFER_PIO_0 + pio);
|
||||
}
|
||||
|
||||
static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void cmd64x_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
u8 unit = drive->dn & 0x01;
|
||||
u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0;
|
||||
const u8 speed = drive->dma_mode;
|
||||
|
||||
if (speed >= XFER_SW_DMA_0) {
|
||||
(void) pci_read_config_byte(dev, pciU, ®U);
|
||||
regU &= ~(unit ? 0xCA : 0x35);
|
||||
}
|
||||
pci_read_config_byte(dev, pciU, ®U);
|
||||
regU &= ~(unit ? 0xCA : 0x35);
|
||||
|
||||
switch(speed) {
|
||||
case XFER_UDMA_5:
|
||||
@@ -197,18 +174,13 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
regU |= unit ? 0xC2 : 0x31;
|
||||
break;
|
||||
case XFER_MW_DMA_2:
|
||||
program_cycle_times(drive, 120, 70);
|
||||
break;
|
||||
case XFER_MW_DMA_1:
|
||||
program_cycle_times(drive, 150, 80);
|
||||
break;
|
||||
case XFER_MW_DMA_0:
|
||||
program_cycle_times(drive, 480, 215);
|
||||
cmd64x_program_timings(drive, speed);
|
||||
break;
|
||||
}
|
||||
|
||||
if (speed >= XFER_SW_DMA_0)
|
||||
(void) pci_write_config_byte(dev, pciU, regU);
|
||||
pci_write_config_byte(dev, pciU, regU);
|
||||
}
|
||||
|
||||
static void cmd648_clear_irq(ide_drive_t *drive)
|
||||
@@ -471,6 +443,6 @@ static void __exit cmd64x_ide_exit(void)
|
||||
module_init(cmd64x_ide_init);
|
||||
module_exit(cmd64x_ide_exit);
|
||||
|
||||
MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");
|
||||
MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick, Bartlomiej Zolnierkiewicz");
|
||||
MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -57,11 +57,11 @@ static struct pio_clocks cs5520_pio_clocks[]={
|
||||
{1, 2, 1}
|
||||
};
|
||||
|
||||
static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void cs5520_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *pdev = to_pci_dev(hwif->dev);
|
||||
int controller = drive->dn > 1 ? 1 : 0;
|
||||
const u8 pio = drive->pio_mode - XFER_PIO_0;
|
||||
|
||||
/* 8bit CAT/CRT - 8bit command timing for channel */
|
||||
pci_write_config_byte(pdev, 0x62 + controller,
|
||||
@@ -81,11 +81,12 @@ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
(cs5520_pio_clocks[pio].assert));
|
||||
}
|
||||
|
||||
static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void cs5520_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
printk(KERN_ERR "cs55x0: bad ide timing.\n");
|
||||
|
||||
cs5520_set_pio_mode(drive, 0);
|
||||
drive->pio_mode = XFER_PIO_0 + 0;
|
||||
cs5520_set_pio_mode(hwif, drive);
|
||||
}
|
||||
|
||||
static const struct ide_port_ops cs5520_port_ops = {
|
||||
|
||||
@@ -41,8 +41,8 @@ static unsigned int cs5530_pio_timings[2][5] = {
|
||||
|
||||
/**
|
||||
* cs5530_set_pio_mode - set host controller for PIO mode
|
||||
* @hwif: port
|
||||
* @drive: drive
|
||||
* @pio: PIO mode number
|
||||
*
|
||||
* Handles setting of PIO mode for the chipset.
|
||||
*
|
||||
@@ -50,10 +50,11 @@ static unsigned int cs5530_pio_timings[2][5] = {
|
||||
* will have valid default PIO timings set up before we get here.
|
||||
*/
|
||||
|
||||
static void cs5530_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void cs5530_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
unsigned long basereg = CS5530_BASEREG(drive->hwif);
|
||||
unsigned long basereg = CS5530_BASEREG(hwif);
|
||||
unsigned int format = (inl(basereg + 4) >> 31) & 1;
|
||||
const u8 pio = drive->pio_mode - XFER_PIO_0;
|
||||
|
||||
outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
|
||||
}
|
||||
@@ -99,12 +100,12 @@ out:
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
static void cs5530_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
unsigned long basereg;
|
||||
unsigned int reg, timings = 0;
|
||||
|
||||
switch (mode) {
|
||||
switch (drive->dma_mode) {
|
||||
case XFER_UDMA_0: timings = 0x00921250; break;
|
||||
case XFER_UDMA_1: timings = 0x00911140; break;
|
||||
case XFER_UDMA_2: timings = 0x00911030; break;
|
||||
@@ -112,7 +113,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
case XFER_MW_DMA_1: timings = 0x00012121; break;
|
||||
case XFER_MW_DMA_2: timings = 0x00002020; break;
|
||||
}
|
||||
basereg = CS5530_BASEREG(drive->hwif);
|
||||
basereg = CS5530_BASEREG(hwif);
|
||||
reg = inl(basereg + 4); /* get drive0 config register */
|
||||
timings |= reg & 0x80000000; /* preserve PIO format bit */
|
||||
if ((drive-> dn & 1) == 0) { /* are we configuring drive0? */
|
||||
|
||||
@@ -86,7 +86,7 @@ static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
|
||||
cmd = pioa = speed - XFER_PIO_0;
|
||||
|
||||
if (pair) {
|
||||
u8 piob = ide_get_best_pio_mode(pair, 255, 4);
|
||||
u8 piob = pair->pio_mode - XFER_PIO_0;
|
||||
|
||||
if (piob < cmd)
|
||||
cmd = piob;
|
||||
@@ -129,28 +129,28 @@ static void cs5535_set_speed(ide_drive_t *drive, const u8 speed)
|
||||
|
||||
/**
|
||||
* cs5535_set_dma_mode - set host controller for DMA mode
|
||||
* @hwif: port
|
||||
* @drive: drive
|
||||
* @speed: DMA mode
|
||||
*
|
||||
* Programs the chipset for DMA mode.
|
||||
*/
|
||||
|
||||
static void cs5535_set_dma_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void cs5535_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
cs5535_set_speed(drive, speed);
|
||||
cs5535_set_speed(drive, drive->dma_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* cs5535_set_pio_mode - set host controller for PIO mode
|
||||
* @hwif: port
|
||||
* @drive: drive
|
||||
* @pio: PIO mode number
|
||||
*
|
||||
* A callback from the upper layers for PIO-only tuning.
|
||||
*/
|
||||
|
||||
static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void cs5535_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
cs5535_set_speed(drive, XFER_PIO_0 + pio);
|
||||
cs5535_set_speed(drive, drive->pio_mode);
|
||||
}
|
||||
|
||||
static u8 cs5535_cable_detect(ide_hwif_t *hwif)
|
||||
|
||||
@@ -125,11 +125,11 @@ static u8 cs5536_cable_detect(ide_hwif_t *hwif)
|
||||
|
||||
/**
|
||||
* cs5536_set_pio_mode - PIO timing setup
|
||||
* @hwif: ATA port
|
||||
* @drive: ATA device
|
||||
* @pio: PIO mode number
|
||||
*/
|
||||
|
||||
static void cs5536_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void cs5536_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
static const u8 drv_timings[5] = {
|
||||
0x98, 0x55, 0x32, 0x21, 0x20,
|
||||
@@ -143,15 +143,16 @@ static void cs5536_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
0x99, 0x92, 0x90, 0x22, 0x20,
|
||||
};
|
||||
|
||||
struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
|
||||
struct pci_dev *pdev = to_pci_dev(hwif->dev);
|
||||
ide_drive_t *pair = ide_get_pair_dev(drive);
|
||||
int cshift = (drive->dn & 1) ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
|
||||
unsigned long timings = (unsigned long)ide_get_drivedata(drive);
|
||||
u32 cast;
|
||||
const u8 pio = drive->pio_mode - XFER_PIO_0;
|
||||
u8 cmd_pio = pio;
|
||||
|
||||
if (pair)
|
||||
cmd_pio = min(pio, ide_get_best_pio_mode(pair, 255, 4));
|
||||
cmd_pio = min_t(u8, pio, pair->pio_mode - XFER_PIO_0);
|
||||
|
||||
timings &= (IDE_DRV_MASK << 8);
|
||||
timings |= drv_timings[pio];
|
||||
@@ -172,11 +173,11 @@ static void cs5536_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
|
||||
/**
|
||||
* cs5536_set_dma_mode - DMA timing setup
|
||||
* @hwif: ATA port
|
||||
* @drive: ATA device
|
||||
* @mode: DMA mode
|
||||
*/
|
||||
|
||||
static void cs5536_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
static void cs5536_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
static const u8 udma_timings[6] = {
|
||||
0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6,
|
||||
@@ -186,10 +187,11 @@ static void cs5536_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
0x67, 0x21, 0x20,
|
||||
};
|
||||
|
||||
struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
|
||||
struct pci_dev *pdev = to_pci_dev(hwif->dev);
|
||||
int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT;
|
||||
unsigned long timings = (unsigned long)ide_get_drivedata(drive);
|
||||
u32 etc;
|
||||
const u8 mode = drive->dma_mode;
|
||||
|
||||
cs5536_read(pdev, ETC, &etc);
|
||||
|
||||
|
||||
+23
-123
@@ -1,43 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
|
||||
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
|
||||
* Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
|
||||
*
|
||||
* CYPRESS CY82C693 chipset IDE controller
|
||||
*
|
||||
* The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
|
||||
* Writing the driver was quite simple, since most of the job is
|
||||
* done by the generic pci-ide support.
|
||||
* The hard part was finding the CY82C693's datasheet on Cypress's
|
||||
* web page :-(. But Altavista solved this problem :-).
|
||||
*
|
||||
*
|
||||
* Notes:
|
||||
* - I recently got a 16.8G IBM DTTA, so I was able to test it with
|
||||
* a large and fast disk - the results look great, so I'd say the
|
||||
* driver is working fine :-)
|
||||
* hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA
|
||||
* - this is my first linux driver, so there's probably a lot of room
|
||||
* for optimizations and bug fixing, so feel free to do it.
|
||||
* - if using PIO mode it's a good idea to set the PIO mode and
|
||||
* 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
|
||||
* - I had some problems with my IBM DHEA with PIO modes < 2
|
||||
* (lost interrupts) ?????
|
||||
* - first tests with DMA look okay, they seem to work, but there is a
|
||||
* problem with sound - the BusMaster IDE TimeOut should fixed this
|
||||
*
|
||||
* Ancient History:
|
||||
* AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693
|
||||
* ASK@1999-01-23: v0.33 made a few minor code clean ups
|
||||
* removed DMA clock speed setting by default
|
||||
* added boot message
|
||||
* ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut
|
||||
* added support to set DMA Controller Clock Speed
|
||||
* ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes
|
||||
* on some drives.
|
||||
* ASK@1998-10-29: v0.3 added support to set DMA modes
|
||||
* ASK@1998-10-28: v0.2 added support to set PIO modes
|
||||
* ASK@1998-10-27: v0.1 first version - chipset detection
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@@ -81,87 +49,13 @@
|
||||
#define CY82_INDEX_CHANNEL1 0x31
|
||||
#define CY82_INDEX_TIMEOUT 0x32
|
||||
|
||||
/* the min and max PCI bus speed in MHz - from datasheet */
|
||||
#define CY82C963_MIN_BUS_SPEED 25
|
||||
#define CY82C963_MAX_BUS_SPEED 33
|
||||
|
||||
/* the struct for the PIO mode timings */
|
||||
typedef struct pio_clocks_s {
|
||||
u8 address_time; /* Address setup (clocks) */
|
||||
u8 time_16r; /* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */
|
||||
u8 time_16w; /* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */
|
||||
u8 time_8; /* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */
|
||||
} pio_clocks_t;
|
||||
|
||||
/*
|
||||
* calc clocks using bus_speed
|
||||
* returns (rounded up) time in bus clocks for time in ns
|
||||
*/
|
||||
static int calc_clk(int time, int bus_speed)
|
||||
{
|
||||
int clocks;
|
||||
|
||||
clocks = (time*bus_speed+999)/1000 - 1;
|
||||
|
||||
if (clocks < 0)
|
||||
clocks = 0;
|
||||
|
||||
if (clocks > 0x0F)
|
||||
clocks = 0x0F;
|
||||
|
||||
return clocks;
|
||||
}
|
||||
|
||||
/*
|
||||
* compute the values for the clock registers for PIO
|
||||
* mode and pci_clk [MHz] speed
|
||||
*
|
||||
* NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
|
||||
* for mode 3 and 4 drives 8 and 16-bit timings are the same
|
||||
*
|
||||
*/
|
||||
static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
|
||||
{
|
||||
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
|
||||
int clk1, clk2;
|
||||
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
|
||||
|
||||
/* we don't check against CY82C693's min and max speed,
|
||||
* so you can play with the idebus=xx parameter
|
||||
*/
|
||||
|
||||
/* let's calc the address setup time clocks */
|
||||
p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed);
|
||||
|
||||
/* let's calc the active and recovery time clocks */
|
||||
clk1 = calc_clk(t->active, bus_speed);
|
||||
|
||||
/* calc recovery timing */
|
||||
clk2 = t->cycle - t->active - t->setup;
|
||||
|
||||
clk2 = calc_clk(clk2, bus_speed);
|
||||
|
||||
clk1 = (clk1<<4)|clk2; /* combine active and recovery clocks */
|
||||
|
||||
/* note: we use the same values for 16bit IOR and IOW
|
||||
* those are all the same, since I don't have other
|
||||
* timings than those from ide-lib.c
|
||||
*/
|
||||
|
||||
p_pclk->time_16r = (u8)clk1;
|
||||
p_pclk->time_16w = (u8)clk1;
|
||||
|
||||
/* what are good values for 8bit ?? */
|
||||
p_pclk->time_8 = (u8)clk1;
|
||||
}
|
||||
|
||||
/*
|
||||
* set DMA mode a specific channel for CY82C693
|
||||
*/
|
||||
|
||||
static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
static void cy82c693_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
const u8 mode = drive->dma_mode;
|
||||
u8 single = (mode & 0x10) >> 4, index = 0, data = 0;
|
||||
|
||||
index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
|
||||
@@ -186,12 +80,14 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
outb(data, CY82_DATA_PORT);
|
||||
}
|
||||
|
||||
static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
pio_clocks_t pclk;
|
||||
int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
|
||||
const unsigned long T = 1000000 / bus_speed;
|
||||
unsigned int addrCtrl;
|
||||
struct ide_timing t;
|
||||
u8 time_16, time_8;
|
||||
|
||||
/* select primary or secondary channel */
|
||||
if (hwif->index > 0) { /* drive is on the secondary channel */
|
||||
@@ -204,8 +100,12 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
}
|
||||
}
|
||||
|
||||
/* let's calc the values for this PIO mode */
|
||||
compute_clocks(pio, &pclk);
|
||||
ide_timing_compute(drive, drive->pio_mode, &t, T, 1);
|
||||
|
||||
time_16 = clamp_val(t.recover - 1, 0, 15) |
|
||||
(clamp_val(t.active - 1, 0, 15) << 4);
|
||||
time_8 = clamp_val(t.act8b - 1, 0, 15) |
|
||||
(clamp_val(t.rec8b - 1, 0, 15) << 4);
|
||||
|
||||
/* now let's write the clocks registers */
|
||||
if ((drive->dn & 1) == 0) {
|
||||
@@ -217,13 +117,13 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
|
||||
|
||||
addrCtrl &= (~0xF);
|
||||
addrCtrl |= (unsigned int)pclk.address_time;
|
||||
addrCtrl |= clamp_val(t.setup - 1, 0, 15);
|
||||
pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
|
||||
|
||||
/* now let's set the remaining registers */
|
||||
pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
|
||||
pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
|
||||
pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
|
||||
pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, time_16);
|
||||
pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, time_16);
|
||||
pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, time_8);
|
||||
} else {
|
||||
/*
|
||||
* set slave drive
|
||||
@@ -233,13 +133,13 @@ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
|
||||
|
||||
addrCtrl &= (~0xF0);
|
||||
addrCtrl |= ((unsigned int)pclk.address_time<<4);
|
||||
addrCtrl |= (clamp_val(t.setup - 1, 0, 15) << 4);
|
||||
pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
|
||||
|
||||
/* now let's set the remaining registers */
|
||||
pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r);
|
||||
pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w);
|
||||
pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8);
|
||||
pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, time_16);
|
||||
pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
|
||||
pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,6 +225,6 @@ static void __exit cy82c693_ide_exit(void)
|
||||
module_init(cy82c693_ide_init);
|
||||
module_exit(cy82c693_ide_exit);
|
||||
|
||||
MODULE_AUTHOR("Andreas Krebs, Andre Hedrick");
|
||||
MODULE_AUTHOR("Andreas Krebs, Andre Hedrick, Bartlomiej Zolnierkiewicz");
|
||||
MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -68,11 +68,11 @@ static void sub22 (char b, char c)
|
||||
|
||||
static DEFINE_SPINLOCK(dtc2278_lock);
|
||||
|
||||
static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void dtc2278_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (pio >= 3) {
|
||||
if (drive->pio_mode >= XFER_PIO_3) {
|
||||
spin_lock_irqsave(&dtc2278_lock, flags);
|
||||
/*
|
||||
* This enables PIO mode4 (3?) on the first interface
|
||||
|
||||
@@ -627,14 +627,14 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info)
|
||||
return info->timings->clock_table[info->clock][i];
|
||||
}
|
||||
|
||||
static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
static void hpt3xx_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
struct hpt_info *info = hpt3xx_get_info(hwif->dev);
|
||||
struct hpt_timings *t = info->timings;
|
||||
u8 itr_addr = 0x40 + (drive->dn * 4);
|
||||
u32 old_itr = 0;
|
||||
const u8 speed = drive->dma_mode;
|
||||
u32 new_itr = get_speed_setting(speed, info);
|
||||
u32 itr_mask = speed < XFER_MW_DMA_0 ? t->pio_mask :
|
||||
(speed < XFER_UDMA_0 ? t->dma_mask :
|
||||
@@ -651,9 +651,10 @@ static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
|
||||
pci_write_config_dword(dev, itr_addr, new_itr);
|
||||
}
|
||||
|
||||
static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void hpt3xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
|
||||
drive->dma_mode = drive->pio_mode;
|
||||
hpt3xx_set_mode(hwif, drive);
|
||||
}
|
||||
|
||||
static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
|
||||
|
||||
@@ -279,9 +279,10 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
static void ht6560b_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
unsigned long flags, config;
|
||||
const u8 pio = drive->pio_mode - XFER_PIO_0;
|
||||
u8 timing;
|
||||
|
||||
switch (pio) {
|
||||
|
||||
+62
-5
@@ -65,6 +65,8 @@ static struct cardinfo icside_cardinfo_v6_2 = {
|
||||
};
|
||||
|
||||
struct icside_state {
|
||||
unsigned int channel;
|
||||
unsigned int enabled;
|
||||
void __iomem *irq_port;
|
||||
void __iomem *ioc_base;
|
||||
unsigned int sel;
|
||||
@@ -114,11 +116,18 @@ static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
|
||||
struct icside_state *state = ec->irq_data;
|
||||
void __iomem *base = state->irq_port;
|
||||
|
||||
writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
readb(base + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
state->enabled = 1;
|
||||
|
||||
writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
readb(base + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
switch (state->channel) {
|
||||
case 0:
|
||||
writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
readb(base + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
break;
|
||||
case 1:
|
||||
writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
readb(base + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
|
||||
@@ -128,6 +137,8 @@ static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
|
||||
{
|
||||
struct icside_state *state = ec->irq_data;
|
||||
|
||||
state->enabled = 0;
|
||||
|
||||
readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
}
|
||||
@@ -149,6 +160,44 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = {
|
||||
.irqpending = icside_irqpending_arcin_v6,
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle routing of interrupts. This is called before
|
||||
* we write the command to the drive.
|
||||
*/
|
||||
static void icside_maskproc(ide_drive_t *drive, int mask)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct expansion_card *ec = ECARD_DEV(hwif->dev);
|
||||
struct icside_state *state = ecard_get_drvdata(ec);
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
state->channel = hwif->channel;
|
||||
|
||||
if (state->enabled && !mask) {
|
||||
switch (hwif->channel) {
|
||||
case 0:
|
||||
writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
break;
|
||||
case 1:
|
||||
writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
|
||||
readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static const struct ide_port_ops icside_v6_no_dma_port_ops = {
|
||||
.maskproc = icside_maskproc,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA_ICS
|
||||
/*
|
||||
* SG-DMA support.
|
||||
@@ -185,10 +234,11 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = {
|
||||
* MW1 80 50 50 150 C
|
||||
* MW2 70 25 25 120 C
|
||||
*/
|
||||
static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
|
||||
static void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
|
||||
{
|
||||
unsigned long cycle_time;
|
||||
int use_dma_info = 0;
|
||||
const u8 xfer_mode = drive->dma_mode;
|
||||
|
||||
switch (xfer_mode) {
|
||||
case XFER_MW_DMA_2:
|
||||
@@ -228,6 +278,7 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
|
||||
|
||||
static const struct ide_port_ops icside_v6_port_ops = {
|
||||
.set_dma_mode = icside_set_dma_mode,
|
||||
.maskproc = icside_maskproc,
|
||||
};
|
||||
|
||||
static void icside_dma_host_set(ide_drive_t *drive, int on)
|
||||
@@ -271,6 +322,11 @@ static int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
|
||||
*/
|
||||
BUG_ON(dma_channel_active(ec->dma));
|
||||
|
||||
/*
|
||||
* Ensure that we have the right interrupt routed.
|
||||
*/
|
||||
icside_maskproc(drive, 0);
|
||||
|
||||
/*
|
||||
* Route the DMA signals to the correct interface.
|
||||
*/
|
||||
@@ -399,6 +455,7 @@ err_free:
|
||||
|
||||
static const struct ide_port_info icside_v6_port_info __initdata = {
|
||||
.init_dma = icside_dma_off_init,
|
||||
.port_ops = &icside_v6_no_dma_port_ops,
|
||||
.dma_ops = &icside_v6_dma_ops,
|
||||
.host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
|
||||
+12
-13
@@ -121,19 +121,11 @@ static int ide_probe(struct pcmcia_device *link)
|
||||
static void ide_detach(struct pcmcia_device *link)
|
||||
{
|
||||
ide_info_t *info = link->priv;
|
||||
ide_hwif_t *hwif = info->host->ports[0];
|
||||
unsigned long data_addr, ctl_addr;
|
||||
|
||||
dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
|
||||
|
||||
data_addr = hwif->io_ports.data_addr;
|
||||
ctl_addr = hwif->io_ports.ctl_addr;
|
||||
|
||||
ide_release(link);
|
||||
|
||||
release_region(ctl_addr, 1);
|
||||
release_region(data_addr, 8);
|
||||
|
||||
kfree(info);
|
||||
} /* ide_detach */
|
||||
|
||||
@@ -354,12 +346,19 @@ static void ide_release(struct pcmcia_device *link)
|
||||
|
||||
dev_dbg(&link->dev, "ide_release(0x%p)\n", link);
|
||||
|
||||
if (info->ndev)
|
||||
/* FIXME: if this fails we need to queue the cleanup somehow
|
||||
-- need to investigate the required PCMCIA magic */
|
||||
ide_host_remove(host);
|
||||
if (info->ndev) {
|
||||
ide_hwif_t *hwif = host->ports[0];
|
||||
unsigned long data_addr, ctl_addr;
|
||||
|
||||
info->ndev = 0;
|
||||
data_addr = hwif->io_ports.data_addr;
|
||||
ctl_addr = hwif->io_ports.ctl_addr;
|
||||
|
||||
ide_host_remove(host);
|
||||
info->ndev = 0;
|
||||
|
||||
release_region(ctl_addr, 1);
|
||||
release_region(data_addr, 8);
|
||||
}
|
||||
|
||||
pcmcia_disable_device(link);
|
||||
} /* ide_release */
|
||||
|
||||
@@ -105,15 +105,17 @@ static int set_pio_mode(ide_drive_t *drive, int arg)
|
||||
return -ENOSYS;
|
||||
|
||||
if (set_pio_mode_abuse(drive->hwif, arg)) {
|
||||
drive->pio_mode = arg + XFER_PIO_0;
|
||||
|
||||
if (arg == 8 || arg == 9) {
|
||||
unsigned long flags;
|
||||
|
||||
/* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
|
||||
spin_lock_irqsave(&hwif->lock, flags);
|
||||
port_ops->set_pio_mode(drive, arg);
|
||||
port_ops->set_pio_mode(hwif, drive);
|
||||
spin_unlock_irqrestore(&hwif->lock, flags);
|
||||
} else
|
||||
port_ops->set_pio_mode(drive, arg);
|
||||
port_ops->set_pio_mode(hwif, drive);
|
||||
} else {
|
||||
int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user