summaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-07-28 23:18:56 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-07-28 23:18:56 +0000
commit4d657aa39d5bcae60c2c11bf8fb66692ddd1c9e7 (patch)
tree30f3b08741a4d4b98b16bd99ea2757ff715d1c11 /drivers/ide
parenteed6b7c84cc33f229f6fecd884d9a22af5bec514 (diff)
Merge with 2.4.0-test5 final.
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/cmd64x.c65
-rw-r--r--drivers/ide/hpt366.c24
-rw-r--r--drivers/ide/ide-dma.c14
-rw-r--r--drivers/ide/ide-features.c4
-rw-r--r--drivers/ide/ide-pci.c4
-rw-r--r--drivers/ide/ide-tape.c4
-rw-r--r--drivers/ide/ide.c35
-rw-r--r--drivers/ide/pdc202xx.c102
8 files changed, 220 insertions, 32 deletions
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 6e45bf0e0..80688e5a3 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -54,9 +54,9 @@
#define ARTTIM1 0x55
#define DRWTIM1 0x56
#define ARTTIM23 0x57
-#define ARTTIM23_INTR_CH1 0x04
#define ARTTIM23_DIS_RA2 0x04
#define ARTTIM23_DIS_RA3 0x08
+#define ARTTIM23_INTR_CH1 0x10
#define ARTTIM2 0x57
#define ARTTIM3 0x57
#define DRWTIM23 0x58
@@ -160,7 +160,6 @@ static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count)
((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"):"X"):"?" );
p += sprintf(p, "PIO Mode: %s %s %s %s\n",
"?", "?", "?", "?");
-
p += sprintf(p, " %s %s\n",
(reg50 & CFR_INTR_CH0) ? "interrupting" : "polling ",
(reg57 & ARTTIM23_INTR_CH1) ? "interrupting" : "polling");
@@ -589,9 +588,45 @@ no_dma_set:
static int cmd64x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
{
+ byte dma_stat = 0;
+ byte dma_alt_stat = 0;
+ byte mask = (HWIF(drive)->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0;
+ unsigned long dma_base = HWIF(drive)->dma_base;
+ struct pci_dev *dev = HWIF(drive)->pci_dev;
+ byte jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0;
+
switch (func) {
case ide_dma_check:
return cmd64x_config_drive_for_dma(drive);
+ case ide_dma_end: /* returns 1 on error, 0 otherwise */
+ drive->waiting_for_dma = 0;
+ outb(inb(dma_base)&~1, dma_base); /* stop DMA */
+ dma_stat = inb(dma_base+2); /* get DMA status */
+ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
+ if (jack_slap) {
+ byte dma_intr = 0;
+ byte dma_mask = (HWIF(drive)->channel) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
+ byte dma_reg = (HWIF(drive)->channel) ? ARTTIM2 : CFR;
+ (void) pci_read_config_byte(dev, dma_reg, &dma_intr);
+ /*
+ * DAMN BMIDE is not connected to PCI space!
+ * Have to manually jack-slap that bitch!
+ * To allow the PCI side to read incoming interrupts.
+ */
+ (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); /* clear the INTR bit */
+ }
+ ide_destroy_dmatable(drive); /* purge DMA mappings */
+ return (dma_stat & 7) != 4; /* verify good DMA status */
+ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
+ dma_stat = inb(dma_base+2);
+ (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat);
+#ifdef DEBUG
+ printk("%s: dma_stat: 0x%02x dma_alt_stat: 0x%02x mask: 0x%02x\n", drive->name, dma_stat, dma_alt_stat, mask);
+#endif
+ if (!(dma_alt_stat & mask)) {
+ return 0;
+ }
+ return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
default:
break;
}
@@ -609,17 +644,22 @@ static int cmd646_1_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
unsigned long dma_base = hwif->dma_base;
byte dma_stat;
- if (func == ide_dma_end) {
- drive->waiting_for_dma = 0;
- dma_stat = inb(dma_base+2); /* get DMA status */
- outb(inb(dma_base)&~1, dma_base); /* stop DMA */
- outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
- ide_destroy_dmatable(drive); /* and free any DMA resources */
- return (dma_stat & 7) != 4; /* verify good DMA status */
+ switch (func) {
+ case ide_dma_check:
+ return cmd64x_config_drive_for_dma(drive);
+ case ide_dma_end:
+ drive->waiting_for_dma = 0;
+ dma_stat = inb(dma_base+2); /* get DMA status */
+ outb(inb(dma_base)&~1, dma_base); /* stop DMA */
+ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
+ ide_destroy_dmatable(drive); /* and free any DMA resources */
+ return (dma_stat & 7) != 4; /* verify good DMA status */
+ default:
+ break;
}
/* Other cases are done by generic IDE-DMA code. */
- return cmd64x_dmaproc(func, drive);
+ return ide_dmaproc(func, drive);
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
@@ -671,6 +711,7 @@ unsigned int __init pci_init_cmd64x (struct pci_dev *dev, const char *name)
(void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10);
#endif
+
/* Setup interrupts. */
(void) pci_read_config_byte(dev, MRDMODE, &mrdmode);
mrdmode &= ~(0x30);
@@ -728,8 +769,8 @@ void __init ide_init_cmd64x (ide_hwif_t *hwif)
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
class_rev &= 0xff;
- hwif->tuneproc = &cmd64x_tuneproc;
- hwif->speedproc = &cmd64x_tune_chipset;
+ hwif->tuneproc = &cmd64x_tuneproc;
+ hwif->speedproc = &cmd64x_tune_chipset;
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 74d3018c5..270cacc61 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -45,6 +45,7 @@ extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
const char *quirk_drives[] = {
"QUANTUM FIREBALLlct08 08",
"QUANTUM FIREBALLP KA6.4",
+ "QUANTUM FIREBALLP LM20.4",
"QUANTUM FIREBALLP LM20.5",
NULL
};
@@ -224,6 +225,14 @@ static unsigned int pci_rev_check_hpt3xx (struct pci_dev *dev)
return ((int) (class_rev > 0x02) ? 1 : 0);
}
+static unsigned int pci_rev2_check_hpt3xx (struct pci_dev *dev)
+{
+ unsigned int class_rev;
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xff;
+ return ((int) (class_rev > 0x01) ? 1 : 0);
+}
+
static int check_in_drive_lists (ide_drive_t *drive, const char **list)
{
struct hd_driveid *id = drive->id;
@@ -469,6 +478,11 @@ int hpt3xx_quirkproc (ide_drive_t *drive)
void hpt3xx_intrproc (ide_drive_t *drive)
{
+ if (drive->quirk_list) {
+ /* drives in the quirk_list may not like intr setups/cleanups */
+ } else {
+ OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
+ }
}
void hpt3xx_maskproc (ide_drive_t *drive, int mask)
@@ -556,11 +570,15 @@ no_dma_set:
*/
int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
{
- byte reg50h = 0, reg52h = 0, reg5ah = 0;
+ byte reg50h = 0, reg52h = 0, reg5ah = 0, dma_stat = 0;
+ unsigned long dma_base = HWIF(drive)->dma_base;
switch (func) {
case ide_dma_check:
return config_drive_xfer_rate(drive);
+ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
+ dma_stat = inb(dma_base+2);
+ return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
case ide_dma_lostirq:
pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
@@ -651,6 +669,10 @@ void __init ide_init_hpt366 (ide_hwif_t *hwif)
hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
+ if (pci_rev2_check_hpt3xx(hwif->pci_dev)) {
+ /* do nothing now but will split device types */
+ }
+
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
if (pci_rev_check_hpt3xx(hwif->pci_dev)) {
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index e9a34afc1..c15e7ee38 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -423,6 +423,14 @@ static int dma_timer_expiry (ide_drive_t *drive)
printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);
#endif /* DEBUG */
+#if 1
+ HWGROUP(drive)->expiry = NULL; /* one free ride for now */
+#endif
+
+ if (dma_stat & 2) { /* ERROR */
+ byte stat = GET_STAT();
+ return ide_error(drive, "dma_timer_expiry", stat);
+ }
if (dma_stat & 1) /* DMAing */
return WAIT_CMD;
return 0;
@@ -495,6 +503,12 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
return (dma_stat & 7) != 4; /* verify good DMA status */
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
dma_stat = inb(dma_base+2);
+#if 0 /* do not set unless you know what you are doing */
+ if (dma_stat & 4) {
+ byte stat = GET_STAT();
+ outb(dma_base+2, dma_stat & 0xE4);
+ }
+#endif
return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
case ide_dma_bad_drive:
case ide_dma_good_drive:
diff --git a/drivers/ide/ide-features.c b/drivers/ide/ide-features.c
index 967b91e55..e46d16e7f 100644
--- a/drivers/ide/ide-features.c
+++ b/drivers/ide/ide-features.c
@@ -39,8 +39,6 @@
#include <asm/io.h>
#include <asm/bitops.h>
-#define SETFEATURES_CONTROL_REG (0) /* some arch's may need */
-
/*
* A Verbose noise maker for debugging on the attempted transfer rates.
*/
@@ -310,7 +308,7 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed)
OUT_BYTE(speed, IDE_NSECTOR_REG);
OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
- if ((IDE_CONTROL_REG) && (SETFEATURES_CONTROL_REG))
+ if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))
OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
udelay(1);
/*
diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c
index 8c9354394..b09b889d7 100644
--- a/drivers/ide/ide-pci.c
+++ b/drivers/ide/ide-pci.c
@@ -39,6 +39,7 @@
#define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1})
#define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246})
#define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262})
+#define DEVID_PDC20265 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265})
#define DEVID_PDC20267 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267})
#define DEVID_RZ1000 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000})
#define DEVID_RZ1001 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001})
@@ -318,6 +319,7 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
{DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 },
{DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 },
{DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 },
+ {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 },
{DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 },
{DEVID_RZ1000, "RZ1000", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_RZ1001, "RZ1001", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
@@ -362,6 +364,7 @@ static unsigned int __init ide_special_settings (struct pci_dev *dev, const char
case PCI_DEVICE_ID_TTI_HPT366:
case PCI_DEVICE_ID_PROMISE_20246:
case PCI_DEVICE_ID_PROMISE_20262:
+ case PCI_DEVICE_ID_PROMISE_20265:
case PCI_DEVICE_ID_PROMISE_20267:
case PCI_DEVICE_ID_ARTOP_ATP850UF:
case PCI_DEVICE_ID_ARTOP_ATP860:
@@ -633,6 +636,7 @@ check_if_enabled:
hwif->autodma = 1;
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) ||
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 298603394..f36dbd8ff 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -3913,10 +3913,14 @@ static int idetape_get_logical_blk (ide_drive_t *drive, int logical_blk_num, int
#endif
clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
position = idetape_read_position(drive);
+ if (position >= 3000 && position < 3080)
+ position += 32;
if (position >= 2980 && position < 3000)
position = 3000;
else
position += 60;
+ if (position >= 2980 && position < 3000)
+ position = 3000;
printk(KERN_INFO "ide-tape: %s: blank block detected, positioning tape to block %d\n", tape->name, position);
idetape_position_tape(drive, position, 0, 1);
cnt += 40;
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 6fe3f9d36..d9ef9510f 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -481,13 +481,27 @@ void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecoun
*/
static inline int drive_is_ready (ide_drive_t *drive)
{
+ byte stat = 0;
if (drive->waiting_for_dma)
return HWIF(drive)->dmaproc(ide_dma_test_irq, drive);
#if 0
udelay(1); /* need to guarantee 400ns since last command was issued */
#endif
-// if (GET_STAT() & BUSY_STAT) /* Note: this may clear a pending IRQ!! */
- if (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT)
+
+#ifdef CONFIG_IDEPCI_SHARE_IRQ
+ /*
+ * We do a passive status test under shared PCI interrupts on
+ * cards that truly share the ATA side interrupt, but may also share
+ * an interrupt with another pci card/device. We make no assumptions
+ * about possible isa-pnp and pci-pnp issues yet.
+ */
+ if (IDE_CONTROL_REG)
+ stat = GET_ALTSTAT();
+ else
+#endif /* CONFIG_IDEPCI_SHARE_IRQ */
+ stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */
+
+ if (stat & BUSY_STAT)
return 0; /* drive busy: definitely not interrupting */
return 1; /* drive ready: *might* be interrupting */
}
@@ -2635,6 +2649,22 @@ static int ide_ioctl (struct inode *inode, struct file *file,
}
drive->nice1 = (arg >> IDE_NICE_1) & 1;
return 0;
+ case HDIO_DRIVE_RESET:
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ (void) ide_do_reset(drive);
+ if (drive->suspend_reset) {
+/*
+ * APM WAKE UP todo !!
+ * int nogoodpower = 1;
+ * while(nogoodpower) {
+ * check_power1() or check_power2()
+ * nogoodpower = 0;
+ * }
+ * HWIF(drive)->multiproc(drive);
+ */
+ return ide_revalidate_disk(inode->i_rdev);
+ }
+ return 0;
case BLKROSET:
case BLKROGET:
@@ -3469,6 +3499,7 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio
drive->nice1 = 1;
}
drive->revalidate = 1;
+ drive->suspend_reset = 0;
#ifdef CONFIG_PROC_FS
ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive);
ide_add_proc_entries(drive->proc, driver->proc, drive);
diff --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c
index 66a123841..6385cd81b 100644
--- a/drivers/ide/pdc202xx.c
+++ b/drivers/ide/pdc202xx.c
@@ -101,11 +101,18 @@ char *pdc202xx_ultra_verbose (u32 drive_pci, u16 slow_cable)
return(pdc202xx_dma_verbose(drive_pci));
}
-static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count)
+char *pdc202xx_interrupt_verbose (u8 sc1d)
{
- char *p = buffer;
+ char *p = NULL;
+ p += sprintf(p,"0x%02x ", sc1d);
+ return (char *)p;
+}
+
+static char * pdc202xx_info (char *buf, struct pci_dev *dev)
+{
+ char *p = buf;
- u32 bibma = pci_resource_start(bmide_dev, 4);
+ 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;
@@ -125,16 +132,19 @@ static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count
u8 sc1e = inb_p((unsigned short)bibma + 0x1e);
u8 sc1f = inb_p((unsigned short)bibma + 0x1f);
- pci_read_config_word(bmide_dev, 0x50, &reg50h);
- pci_read_config_dword(bmide_dev, 0x60, &reg60h);
- pci_read_config_dword(bmide_dev, 0x64, &reg64h);
- pci_read_config_dword(bmide_dev, 0x68, &reg68h);
- pci_read_config_dword(bmide_dev, 0x6c, &reg6ch);
+ 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(bmide_dev->device) {
+ 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;
@@ -174,10 +184,12 @@ static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count
(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 " : "????????????");
@@ -195,13 +207,27 @@ static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count
#if 0
p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n");
#endif
-
+ return (char *)p;
+}
+
+static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+ char *p = buffer;
+ p = pdc202xx_info(buffer, bmide_dev);
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 LM20.5",
+ NULL
+};
+
extern char *ide_xfer_verbose (byte xfer_rate);
/* A Register */
@@ -314,6 +340,26 @@ static void decode_registers (byte registers, byte value)
#endif /* PDC202XX_DECODE_REGISTER_INFO */
+static int check_in_drive_lists (ide_drive_t *drive, const char **list)
+{
+ 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;
+ }
+ }
+ }
+ return 0;
+}
+
static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -473,7 +519,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
byte CLKSPD = IN_BYTE(high_16 + 0x11);
byte udma_33 = ultra ? (inb(high_16 + 0x001f) & 1) : 0;
byte udma_66 = ((eighty_ninty_three(drive)) && udma_33) ? 1 : 0;
- byte udma_100 = ((dev->device == PCI_DEVICE_ID_PROMISE_20267) && udma_66) ? 1 : 0;
+ byte udma_100 = (((dev->device == PCI_DEVICE_ID_PROMISE_20265) || (dev->device == PCI_DEVICE_ID_PROMISE_20267)) && udma_66) ? 1 : 0;
/*
* Set the control register to use the 66Mhz system
@@ -655,14 +701,37 @@ no_dma_set:
return HWIF(drive)->dmaproc(dma_func, drive);
}
+int pdc202xx_quirkproc (ide_drive_t *drive)
+{
+ return ((int) check_in_drive_lists(drive, pdc_quirk_drives));
+}
+
/*
* pdc202xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
*/
int pdc202xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
{
+ byte dma_stat = 0, sc1d = 0;
+ unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4);
+ unsigned long dma_base = HWIF(drive)->dma_base;
+
switch (func) {
case ide_dma_check:
return config_drive_xfer_rate(drive);
+ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
+ dma_stat = inb(dma_base+2);
+ sc1d = inb(high_16 + 0x001d);
+ if (HWIF(drive)->channel) {
+ if ((sc1d & 0x50) == 0x50) goto somebody_else;
+ else if ((sc1d & 0x40) == 0x40)
+ return (dma_stat & 4) == 4;
+ } else {
+ if ((sc1d & 0x05) == 0x05) goto somebody_else;
+ else if ((sc1d & 0x04) == 0x04)
+ return (dma_stat & 4) == 4;
+ }
+somebody_else:
+ return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
case ide_dma_lostirq:
case ide_dma_timeout:
if (HWIF(drive)->resetproc != NULL)
@@ -696,6 +765,7 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name)
byte secondary_mode = inb(high_16 + 0x001b);
if ((dev->device == PCI_DEVICE_ID_PROMISE_20262) ||
+ (dev->device == PCI_DEVICE_ID_PROMISE_20265) ||
(dev->device == PCI_DEVICE_ID_PROMISE_20267)) {
int i = 0;
/*
@@ -725,7 +795,7 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name)
byte irq = 0, irq2 = 0;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2); /* 0xbc */
- if ((irq != irq2) && (dev->device != PCI_DEVICE_ID_PROMISE_20267)) {
+ if ((irq != irq2) && (dev->device != PCI_DEVICE_ID_PROMISE_20265) && (dev->device != PCI_DEVICE_ID_PROMISE_20267)) {
pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq); /* 0xbc */
printk("%s: pci-config space interrupt mirror fixed.\n", name);
}
@@ -779,17 +849,21 @@ unsigned int __init ata66_pdc202xx (ide_hwif_t *hwif)
unsigned short CIS;
pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
- return ((CIS & mask) ? 0 : 1);
+ return ((CIS & mask) ? 0 : 1);
}
void __init ide_init_pdc202xx (ide_hwif_t *hwif)
{
hwif->tuneproc = &pdc202xx_tune_drive;
hwif->speedproc = &pdc202xx_tune_chipset;
+ hwif->quirkproc = &pdc202xx_quirkproc;
if ((hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20262) ||
- (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20267))
+ (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20265) ||
+ (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20267)) {
hwif->resetproc = &pdc202xx_reset;
+ hwif->tri_proc = &pdc202xx_tristate;
+ }
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {