Commit 65ea2fa1 authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz Committed by Jeff Garzik

[PATCH] update for pdc202xx_new driver

Many thanks to Promise for their support.
Expect more updates/fixes for Promise PATA support soon.

- fix PIO (auto-)tuning - use pdcnew_new_tune_chipset()
  and always tune PIO mode even if (U)DMA is used
- cleanup cable verification code a bit
- remove leftovers from driver split-up
- remove duplicate DISPLAY_PDC202XX_TIMINGS define
parent 585a692c
...@@ -140,108 +140,6 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) ...@@ -140,108 +140,6 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list)
return 0; return 0;
} }
static int pdcnew_tune_chipset (ide_drive_t *drive, u8 xferspeed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
u8 drive_pci = 0x60 + (drive->dn << 2);
u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed);
u32 drive_conf;
u8 AP, BP, CP, DP;
u8 TA = 0, TB = 0, TC = 0;
if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))
return -1;
pci_read_config_dword(dev, drive_pci, &drive_conf);
pci_read_config_byte(dev, (drive_pci), &AP);
pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
if (speed < XFER_SW_DMA_0) {
if ((AP & 0x0F) || (BP & 0x07)) {
/* clear PIO modes of lower 8421 bits of A Register */
pci_write_config_byte(dev, (drive_pci), AP &~0x0F);
pci_read_config_byte(dev, (drive_pci), &AP);
/* clear PIO modes of lower 421 bits of B Register */
pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0x07);
pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
pci_read_config_byte(dev, (drive_pci), &AP);
pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
}
} else {
if ((BP & 0xF0) && (CP & 0x0F)) {
/* clear DMA modes of upper 842 bits of B Register */
/* clear PIO forced mode upper 1 bit of B Register */
pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0xF0);
pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
/* clear DMA modes of lower 8421 bits of C Register */
pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F);
pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
}
}
pci_read_config_byte(dev, (drive_pci), &AP);
pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
switch(speed) {
case XFER_UDMA_6: speed = XFER_UDMA_5;
case XFER_UDMA_5:
case XFER_UDMA_4: TB = 0x20; TC = 0x01; break;
case XFER_UDMA_2: TB = 0x20; TC = 0x01; break;
case XFER_UDMA_3:
case XFER_UDMA_1: TB = 0x40; TC = 0x02; break;
case XFER_UDMA_0:
case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break;
case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break;
case XFER_MW_DMA_0:
case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break;
case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break;
case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break;
case XFER_PIO_4: TA = 0x01; TB = 0x04; break;
case XFER_PIO_3: TA = 0x02; TB = 0x06; break;
case XFER_PIO_2: TA = 0x03; TB = 0x08; break;
case XFER_PIO_1: TA = 0x05; TB = 0x0C; break;
case XFER_PIO_0:
default: TA = 0x09; TB = 0x13; break;
}
if (speed < XFER_SW_DMA_0) {
pci_write_config_byte(dev, (drive_pci), AP|TA);
pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
} else {
pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
}
#if PDC202XX_DECODE_REGISTER_INFO
pci_read_config_byte(dev, (drive_pci), &AP);
pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
decode_registers(REG_A, AP);
decode_registers(REG_B, BP);
decode_registers(REG_C, CP);
decode_registers(REG_D, DP);
#endif /* PDC202XX_DECODE_REGISTER_INFO */
#if PDC202XX_DEBUG_DRIVE_INFO
printk(KERN_DEBUG "%s: %s drive%d 0x%08x ",
drive->name, ide_xfer_verbose(speed),
drive->dn, drive_conf);
pci_read_config_dword(dev, drive_pci, &drive_conf);
printk("0x%08x\n", drive_conf);
#endif /* PDC202XX_DEBUG_DRIVE_INFO */
return (ide_config_drive_speed(drive, speed));
}
static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
...@@ -288,19 +186,14 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -288,19 +186,14 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed)
* 180, 120, 90, 90, 90, 60, 30 * 180, 120, 90, 90, 90, 60, 30
* 11, 5, 4, 3, 2, 1, 0 * 11, 5, 4, 3, 2, 1, 0
*/ */
static int config_chipset_for_pio (ide_drive_t *drive, u8 pio) static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio)
{ {
u8 speed = 0; u8 speed;
if (pio == 5) pio = 4; if (pio == 5) pio = 4;
speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
return ((int) pdcnew_tune_chipset(drive, speed)); (void)pdcnew_new_tune_chipset(drive, speed);
}
static void pdcnew_tune_drive (ide_drive_t *drive, u8 pio)
{
(void) config_chipset_for_pio(drive, pio);
} }
static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif)
...@@ -312,56 +205,15 @@ static int config_chipset_for_dma (ide_drive_t *drive) ...@@ -312,56 +205,15 @@ static int config_chipset_for_dma (ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
u8 speed = -1; u8 speed = -1;
u8 cable = 0; u8 cable;
u8 ultra_66 = ((id->dma_ultra & 0x0010) || u8 ultra_66 = ((id->dma_ultra & 0x0010) ||
(id->dma_ultra & 0x0008)) ? 1 : 0; (id->dma_ultra & 0x0008)) ? 1 : 0;
switch(dev->device) {
case PCI_DEVICE_ID_PROMISE_20277:
case PCI_DEVICE_ID_PROMISE_20276:
case PCI_DEVICE_ID_PROMISE_20275:
case PCI_DEVICE_ID_PROMISE_20271:
case PCI_DEVICE_ID_PROMISE_20269:
case PCI_DEVICE_ID_PROMISE_20270:
case PCI_DEVICE_ID_PROMISE_20268:
cable = pdcnew_new_cable_detect(hwif); cable = pdcnew_new_cable_detect(hwif);
#if PDC202_DEBUG_CABLE
printk(KERN_DEBUG "%s: %s-pin cable, %s-pin cable, %d\n",
hwif->name, hwif->udma_four ? "80" : "40",
cable ? "40" : "80", cable);
#endif /* PDC202_DEBUG_CABLE */
break;
default:
/* If it's not one we know we should never
arrive here.. */
BUG();
}
/* if (ultra_66 && cable) {
* Set the control register to use the 66Mhz system
* clock for UDMA 3/4 mode operation. If one drive on
* a channel is U66 capable but the other isn't we
* fall back to U33 mode. The BIOS INT 13 hooks turn
* the clock on then off for each read/write issued. I don't
* do that here because it would require modifying the
* kernel, separating the fop routines from the kernel or
* somehow hooking the fops calls. It may also be possible to
* leave the 66Mhz clock on and readjust the timing
* parameters.
*/
if ((ultra_66) && (cable)) {
#ifdef DEBUG
printk(KERN_DEBUG "ULTRA 66/100/133: %s channel of Ultra 66/100/133 "
"requires an 80-pin cable for Ultra66 operation.\n",
hwif->channel ? "Secondary" : "Primary");
printk(KERN_DEBUG " Switching to Ultra33 mode.\n");
#endif /* DEBUG */
/* Primary : zero out second bit */
/* Secondary : zero out fourth bit */
printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary");
printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name);
} }
...@@ -590,10 +442,7 @@ static void __init init_hwif_pdc202new (ide_hwif_t *hwif) ...@@ -590,10 +442,7 @@ static void __init init_hwif_pdc202new (ide_hwif_t *hwif)
hwif->speedproc = &pdcnew_new_tune_chipset; hwif->speedproc = &pdcnew_new_tune_chipset;
hwif->resetproc = &pdcnew_new_reset; hwif->resetproc = &pdcnew_new_reset;
if (!hwif->dma_base) {
hwif->drives[0].autotune = hwif->drives[1].autotune = 1; hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
return;
}
hwif->ultra_mask = 0x7f; hwif->ultra_mask = 0x7f;
hwif->mwdma_mask = 0x07; hwif->mwdma_mask = 0x07;
......
...@@ -5,15 +5,6 @@ ...@@ -5,15 +5,6 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/ide.h> #include <linux/ide.h>
#define DISPLAY_PDC202XX_TIMINGS
#ifndef SPLIT_BYTE
#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4)))
#endif
#define PDC202XX_DEBUG_DRIVE_INFO 0
#define PDC202XX_DECODE_REGISTER_INFO 0
const static char *pdc_quirk_drives[] = { const static char *pdc_quirk_drives[] = {
"QUANTUM FIREBALLlct08 08", "QUANTUM FIREBALLlct08 08",
"QUANTUM FIREBALLP KA6.4", "QUANTUM FIREBALLP KA6.4",
...@@ -26,116 +17,6 @@ const static char *pdc_quirk_drives[] = { ...@@ -26,116 +17,6 @@ const static char *pdc_quirk_drives[] = {
NULL NULL
}; };
/* A Register */
#define SYNC_ERRDY_EN 0xC0
#define SYNC_IN 0x80 /* control bit, different for master vs. slave drives */
#define ERRDY_EN 0x40 /* control bit, different for master vs. slave drives */
#define IORDY_EN 0x20 /* PIO: IOREADY */
#define PREFETCH_EN 0x10 /* PIO: PREFETCH */
#define PA3 0x08 /* PIO"A" timing */
#define PA2 0x04 /* PIO"A" timing */
#define PA1 0x02 /* PIO"A" timing */
#define PA0 0x01 /* PIO"A" timing */
/* B Register */
#define MB2 0x80 /* DMA"B" timing */
#define MB1 0x40 /* DMA"B" timing */
#define MB0 0x20 /* DMA"B" timing */
#define PB4 0x10 /* PIO_FORCE 1:0 */
#define PB3 0x08 /* PIO"B" timing */ /* PIO flow Control mode */
#define PB2 0x04 /* PIO"B" timing */ /* PIO 4 */
#define PB1 0x02 /* PIO"B" timing */ /* PIO 3 half */
#define PB0 0x01 /* PIO"B" timing */ /* PIO 3 other half */
/* C Register */
#define IORDYp_NO_SPEED 0x4F
#define SPEED_DIS 0x0F
#define DMARQp 0x80
#define IORDYp 0x40
#define DMAR_EN 0x20
#define DMAW_EN 0x10
#define MC3 0x08 /* DMA"C" timing */
#define MC2 0x04 /* DMA"C" timing */
#define MC1 0x02 /* DMA"C" timing */
#define MC0 0x01 /* DMA"C" timing */
#if PDC202XX_DECODE_REGISTER_INFO
#define REG_A 0x01
#define REG_B 0x02
#define REG_C 0x04
#define REG_D 0x08
static void decode_registers (u8 registers, u8 value)
{
u8 bit = 0, bit1 = 0, bit2 = 0;
switch(registers) {
case REG_A:
bit2 = 0;
printk("A Register ");
if (value & 0x80) printk("SYNC_IN ");
if (value & 0x40) printk("ERRDY_EN ");
if (value & 0x20) printk("IORDY_EN ");
if (value & 0x10) printk("PREFETCH_EN ");
if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; }
if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; }
if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; }
if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; }
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; }
if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; }
printk("DMA(B) = %d ", bit1 >> 5);
if (value & 0x10) printk("PIO_FORCED/PB4 ");
if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; }
if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; }
if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; }
if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; }
printk("PIO(B) = %d ", bit2);
break;
case REG_C:
bit2 = 0;
printk("C Register ");
if (value & 0x80) printk("DMARQp ");
if (value & 0x40) printk("IORDYp ");
if (value & 0x20) printk("DMAR_EN ");
if (value & 0x10) printk("DMAW_EN ");
if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; }
if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; }
if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; }
if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; }
printk("DMA(C) = %d ", bit2);
break;
case REG_D:
printk("D Register ");
break;
default:
return;
}
printk("\n %s ", (registers & REG_D) ? "DP" :
(registers & REG_C) ? "CP" :
(registers & REG_B) ? "BP" :
(registers & REG_A) ? "AP" : "ERROR");
for (bit=128;bit>0;bit/=2)
printk("%s", (value & bit) ? "1" : "0");
printk("\n");
}
#endif /* PDC202XX_DECODE_REGISTER_INFO */
#define set_2regs(a, b) \ #define set_2regs(a, b) \
do { \ do { \
hwif->OUTB((a + adj), indexreg); \ hwif->OUTB((a + adj), indexreg); \
......
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