Commit fd95fd27 authored by Jens Axboe's avatar Jens Axboe

piix update

parent 618cb93e
/* /*
* linux/drivers/ide/piix.c Version 0.32 June 9, 2000 * linux/drivers/ide/piix.c Version 0.40 August 18, 2002
* *
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
...@@ -66,205 +66,221 @@ ...@@ -66,205 +66,221 @@
#include <asm/io.h> #include <asm/io.h>
#include "ide_modes.h" #include "ide_modes.h"
#include "piix.h"
#define PIIX_DEBUG_DRIVE_INFO 0
#define DISPLAY_PIIX_TIMINGS
#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) #if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
static int piix_get_info(char *, char **, off_t, int); static u8 piix_proc = 0;
extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */ #define PIIX_MAX_DEVS 5
static struct pci_dev *bmide_dev; static struct pci_dev *piix_devs[PIIX_MAX_DEVS];
static int n_piix_devs;
/**
* piix_get_info - fill in /proc for PIIX ide
* @buffer: buffer to fill
* @addr: address of user start in buffer
* @offset: offset into 'file'
* @count: buffer count
*
* Walks the PIIX devices and outputs summary data on the tuning and
* anything else that will help with debugging
*/
static int piix_get_info (char *buffer, char **addr, off_t offset, int count) static int piix_get_info (char *buffer, char **addr, off_t offset, int count)
{ {
char *p = buffer; char *p = buffer;
u32 bibma = pci_resource_start(bmide_dev, 4); int i;
u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
u8 c0 = 0, c1 = 0; for (i = 0; i < n_piix_devs; i++) {
u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0; struct pci_dev *dev = piix_devs[i];
u32 bibma = pci_resource_start(dev, 4);
p += sprintf(p, "\n "); u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
switch(bmide_dev->device) { u8 c0 = 0, c1 = 0, reg54 = 0, reg55 = 0;
case PCI_DEVICE_ID_INTEL_82801BA_8: u8 reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0;
case PCI_DEVICE_ID_INTEL_82801BA_9:
case PCI_DEVICE_ID_INTEL_82801CA_10: p += sprintf(p, "\nController: %d\n", i);
case PCI_DEVICE_ID_INTEL_82801CA_11: p += sprintf(p, "\n Intel ");
case PCI_DEVICE_ID_INTEL_82801E_11: switch(dev->device) {
case PCI_DEVICE_ID_INTEL_82801DB_11: case PCI_DEVICE_ID_INTEL_82801BA_8:
p += sprintf(p, "Intel PIIX4 Ultra 100 Chipset.\n"); case PCI_DEVICE_ID_INTEL_82801BA_9:
break; case PCI_DEVICE_ID_INTEL_82801CA_10:
case PCI_DEVICE_ID_INTEL_82372FB_1: case PCI_DEVICE_ID_INTEL_82801CA_11:
case PCI_DEVICE_ID_INTEL_82801AA_1: case PCI_DEVICE_ID_INTEL_82801DB_11:
p += sprintf(p, "Intel PIIX4 Ultra 66 Chipset.\n"); case PCI_DEVICE_ID_INTEL_82801E_11:
break; p += sprintf(p, "PIIX4 Ultra 100 ");
case PCI_DEVICE_ID_INTEL_82451NX: break;
case PCI_DEVICE_ID_INTEL_82801AB_1: case PCI_DEVICE_ID_INTEL_82372FB_1:
case PCI_DEVICE_ID_INTEL_82443MX_1: case PCI_DEVICE_ID_INTEL_82801AA_1:
case PCI_DEVICE_ID_INTEL_82371AB: p += sprintf(p, "PIIX4 Ultra 66 ");
p += sprintf(p, "Intel PIIX4 Ultra 33 Chipset.\n"); break;
break; case PCI_DEVICE_ID_INTEL_82451NX:
case PCI_DEVICE_ID_INTEL_82371SB_1: case PCI_DEVICE_ID_INTEL_82801AB_1:
p += sprintf(p, "Intel PIIX3 Chipset.\n"); case PCI_DEVICE_ID_INTEL_82443MX_1:
break; case PCI_DEVICE_ID_INTEL_82371AB:
case PCI_DEVICE_ID_INTEL_82371MX: p += sprintf(p, "PIIX4 Ultra 33 ");
p += sprintf(p, "Intel MPIIX Chipset.\n"); break;
return p-buffer; /* => must be less than 4k! */ case PCI_DEVICE_ID_INTEL_82371SB_1:
case PCI_DEVICE_ID_INTEL_82371FB_1: p += sprintf(p, "PIIX3 ");
case PCI_DEVICE_ID_INTEL_82371FB_0: break;
default: case PCI_DEVICE_ID_INTEL_82371MX:
p += sprintf(p, "Intel PIIX Chipset.\n"); p += sprintf(p, "MPIIX ");
break; break;
case PCI_DEVICE_ID_INTEL_82371FB_1:
case PCI_DEVICE_ID_INTEL_82371FB_0:
default:
p += sprintf(p, "PIIX ");
break;
}
p += sprintf(p, "Chipset.\n");
if (dev->device == PCI_DEVICE_ID_INTEL_82371MX)
continue;
pci_read_config_word(dev, 0x40, &reg40);
pci_read_config_word(dev, 0x42, &reg42);
pci_read_config_byte(dev, 0x44, &reg44);
pci_read_config_byte(dev, 0x48, &reg48);
pci_read_config_byte(dev, 0x4a, &reg4a);
pci_read_config_byte(dev, 0x4b, &reg4b);
pci_read_config_byte(dev, 0x54, &reg54);
pci_read_config_byte(dev, 0x55, &reg55);
psitre = (reg40 & 0x4000) ? 1 : 0;
ssitre = (reg42 & 0x4000) ? 1 : 0;
/*
* at that point bibma+0x2 et bibma+0xa are byte registers
* to investigate:
*/
c0 = inb((unsigned short)bibma + 0x02);
c1 = inb((unsigned short)bibma + 0x0a);
p += sprintf(p, "--------------- Primary Channel "
"---------------- Secondary Channel "
"-------------\n");
p += sprintf(p, " %sabled "
" %sabled\n",
(c0&0x80) ? "dis" : " en",
(c1&0x80) ? "dis" : " en");
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, "UDMA enabled: %s %s "
" %s %s\n",
(reg48&0x01) ? "yes" : "no ",
(reg48&0x02) ? "yes" : "no ",
(reg48&0x04) ? "yes" : "no ",
(reg48&0x08) ? "yes" : "no " );
p += sprintf(p, "UDMA enabled: %s %s "
" %s %s\n",
((reg54&0x11) &&
(reg55&0x10) && (reg4a&0x01)) ? "5" :
((reg54&0x11) && (reg4a&0x02)) ? "4" :
((reg54&0x11) && (reg4a&0x01)) ? "3" :
(reg4a&0x02) ? "2" :
(reg4a&0x01) ? "1" :
(reg4a&0x00) ? "0" : "X",
((reg54&0x22) &&
(reg55&0x20) && (reg4a&0x10)) ? "5" :
((reg54&0x22) && (reg4a&0x20)) ? "4" :
((reg54&0x22) && (reg4a&0x10)) ? "3" :
(reg4a&0x20) ? "2" :
(reg4a&0x10) ? "1" :
(reg4a&0x00) ? "0" : "X",
((reg54&0x44) &&
(reg55&0x40) && (reg4b&0x03)) ? "5" :
((reg54&0x44) && (reg4b&0x02)) ? "4" :
((reg54&0x44) && (reg4b&0x01)) ? "3" :
(reg4b&0x02) ? "2" :
(reg4b&0x01) ? "1" :
(reg4b&0x00) ? "0" : "X",
((reg54&0x88) &&
(reg55&0x80) && (reg4b&0x30)) ? "5" :
((reg54&0x88) && (reg4b&0x20)) ? "4" :
((reg54&0x88) && (reg4b&0x10)) ? "3" :
(reg4b&0x20) ? "2" :
(reg4b&0x10) ? "1" :
(reg4b&0x00) ? "0" : "X");
p += sprintf(p, "UDMA\n");
p += sprintf(p, "DMA\n");
p += sprintf(p, "PIO\n");
/*
* FIXME.... Add configuration junk data....blah blah......
*/
} }
pci_read_config_word(bmide_dev, 0x40, &reg40);
pci_read_config_word(bmide_dev, 0x42, &reg42);
pci_read_config_byte(bmide_dev, 0x44, &reg44);
pci_read_config_byte(bmide_dev, 0x48, &reg48);
pci_read_config_byte(bmide_dev, 0x4a, &reg4a);
pci_read_config_byte(bmide_dev, 0x4b, &reg4b);
pci_read_config_byte(bmide_dev, 0x54, &reg54);
pci_read_config_byte(bmide_dev, 0x55, &reg55);
psitre = (reg40 & 0x4000) ? 1 : 0;
ssitre = (reg42 & 0x4000) ? 1 : 0;
/*
* at that point bibma+0x2 et bibma+0xa are byte registers
* to investigate:
*/
c0 = inb_p((unsigned short)bibma + 0x02);
c1 = inb_p((unsigned short)bibma + 0x0a);
p += sprintf(p, "--------------- Primary Channel "
"---------------- Secondary Channel "
"-------------\n");
p += sprintf(p, " %sabled "
" %sabled\n",
(c0&0x80) ? "dis" : " en",
(c1&0x80) ? "dis" : " en");
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, "UDMA enabled: %s %s "
" %s %s\n",
(reg48&0x01) ? "yes" : "no ",
(reg48&0x02) ? "yes" : "no ",
(reg48&0x04) ? "yes" : "no ",
(reg48&0x08) ? "yes" : "no " );
p += sprintf(p, "UDMA enabled: %s %s "
" %s %s\n",
((reg54&0x11) && (reg55&0x10) && (reg4a&0x01)) ? "5" :
((reg54&0x11) && (reg4a&0x02)) ? "4" :
((reg54&0x11) && (reg4a&0x01)) ? "3" :
(reg4a&0x02) ? "2" :
(reg4a&0x01) ? "1" :
(reg4a&0x00) ? "0" : "X",
((reg54&0x22) && (reg55&0x20) && (reg4a&0x10)) ? "5" :
((reg54&0x22) && (reg4a&0x20)) ? "4" :
((reg54&0x22) && (reg4a&0x10)) ? "3" :
(reg4a&0x20) ? "2" :
(reg4a&0x10) ? "1" :
(reg4a&0x00) ? "0" : "X",
((reg54&0x44) && (reg55&0x40) && (reg4b&0x03)) ? "5" :
((reg54&0x44) && (reg4b&0x02)) ? "4" :
((reg54&0x44) && (reg4b&0x01)) ? "3" :
(reg4b&0x02) ? "2" :
(reg4b&0x01) ? "1" :
(reg4b&0x00) ? "0" : "X",
((reg54&0x88) && (reg55&0x80) && (reg4b&0x30)) ? "5" :
((reg54&0x88) && (reg4b&0x20)) ? "4" :
((reg54&0x88) && (reg4b&0x10)) ? "3" :
(reg4b&0x20) ? "2" :
(reg4b&0x10) ? "1" :
(reg4b&0x00) ? "0" : "X");
p += sprintf(p, "UDMA\n");
p += sprintf(p, "DMA\n");
p += sprintf(p, "PIO\n");
/*
* FIXME.... Add configuration junk data....blah blah......
*/
return p-buffer; /* => must be less than 4k! */ return p-buffer; /* => must be less than 4k! */
} }
#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ #endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */
/* /**
* Used to set Fifo configuration via kernel command line: * piix_ratemask - compute rate mask for PIIX IDE
* @drive: IDE drive to compute for
*
* Returns the available modes for the PIIX IDE controller.
*/ */
byte piix_proc = 0; static u8 piix_ratemask (ide_drive_t *drive)
static byte piix_ratemask (ide_drive_t *drive)
{ {
struct pci_dev *dev = HWIF(drive)->pci_dev; struct pci_dev *dev = HWIF(drive)->pci_dev;
byte mode = 0x00; u8 mode;
switch(dev->device) { switch(dev->device) {
/* UDMA 100 capable */
case PCI_DEVICE_ID_INTEL_82801BA_8: case PCI_DEVICE_ID_INTEL_82801BA_8:
case PCI_DEVICE_ID_INTEL_82801BA_9: case PCI_DEVICE_ID_INTEL_82801BA_9:
case PCI_DEVICE_ID_INTEL_82801CA_10: case PCI_DEVICE_ID_INTEL_82801CA_10:
case PCI_DEVICE_ID_INTEL_82801CA_11: case PCI_DEVICE_ID_INTEL_82801CA_11:
case PCI_DEVICE_ID_INTEL_82801E_11: case PCI_DEVICE_ID_INTEL_82801E_11:
case PCI_DEVICE_ID_INTEL_82801DB_11: case PCI_DEVICE_ID_INTEL_82801DB_11:
mode |= 0x03; mode = 3;
break; break;
/* UDMA 66 capable */
case PCI_DEVICE_ID_INTEL_82801AA_1: case PCI_DEVICE_ID_INTEL_82801AA_1:
case PCI_DEVICE_ID_INTEL_82372FB_1: case PCI_DEVICE_ID_INTEL_82372FB_1:
mode |= 0x02; mode = 2;
break; break;
/* UDMA 33 capable */
case PCI_DEVICE_ID_INTEL_82371AB: case PCI_DEVICE_ID_INTEL_82371AB:
case PCI_DEVICE_ID_INTEL_82443MX_1: case PCI_DEVICE_ID_INTEL_82443MX_1:
case PCI_DEVICE_ID_INTEL_82451NX: case PCI_DEVICE_ID_INTEL_82451NX:
case PCI_DEVICE_ID_INTEL_82801AB_1: case PCI_DEVICE_ID_INTEL_82801AB_1:
mode |= 0x01; return 1;
/* Non UDMA capable (MWDMA2) */
case PCI_DEVICE_ID_INTEL_82371SB_1: case PCI_DEVICE_ID_INTEL_82371SB_1:
case PCI_DEVICE_ID_INTEL_82371FB_1: case PCI_DEVICE_ID_INTEL_82371FB_1:
case PCI_DEVICE_ID_INTEL_82371FB_0: case PCI_DEVICE_ID_INTEL_82371FB_0:
case PCI_DEVICE_ID_INTEL_82371MX: case PCI_DEVICE_ID_INTEL_82371MX:
default: default:
return (mode &= ~0xF8); return 0;
}
if (!eighty_ninty_three(drive)) {
mode &= ~0xFE;
mode |= 0x01;
}
return (mode &= ~0xF8);
}
static byte piix_ratefilter (ide_drive_t *drive, byte speed)
{
#ifdef CONFIG_BLK_DEV_IDEDMA
byte mode = piix_ratemask(drive);
switch(mode) {
case 0x04: while (speed > XFER_UDMA_6) speed--; break;
case 0x03: while (speed > XFER_UDMA_5) speed--; break;
case 0x02: while (speed > XFER_UDMA_4) speed--; break;
case 0x01: while (speed > XFER_UDMA_2) speed--; break;
case 0x00:
default: while (speed > XFER_MW_DMA_2) speed--; break;
break;
} }
#else
while (speed > XFER_PIO_4) speed--; /*
#endif /* CONFIG_BLK_DEV_IDEDMA */ * If we are UDMA66 capable fall back to UDMA33
// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); * if the drive cannot see an 80pin cable.
return speed; */
if (!eighty_ninty_three(drive))
mode = min(mode, (u8)1);
return mode;
} }
static byte piix_dma_2_pio (byte xfer_rate) { /**
* piix_dma_2_pio - return the PIO mode matching DMA
* @xfer_rate: transfer speed
*
* Returns the nearest equivalent PIO timing for the PIO or DMA
* mode requested by the controller.
*/
static u8 piix_dma_2_pio (u8 xfer_rate) {
switch(xfer_rate) { switch(xfer_rate) {
case XFER_UDMA_5: case XFER_UDMA_5:
case XFER_UDMA_4: case XFER_UDMA_4:
...@@ -292,11 +308,15 @@ static byte piix_dma_2_pio (byte xfer_rate) { ...@@ -292,11 +308,15 @@ static byte piix_dma_2_pio (byte xfer_rate) {
} }
} }
/* /**
* Based on settings done by AMI BIOS * piix_tune_drive - tune a drive attached to a PIIX
* (might be useful if drive is not registered in CMOS for any reason). * @drive: drive to tune
* @pio: desired PIO mode
*
* Set the interface PIO mode based upon the settings done by AMI BIOS
* (might be useful if drive is not registered in CMOS for any reason).
*/ */
static void piix_tune_drive (ide_drive_t *drive, byte pio) static void piix_tune_drive (ide_drive_t *drive, u8 pio)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
...@@ -305,13 +325,13 @@ static void piix_tune_drive (ide_drive_t *drive, byte pio) ...@@ -305,13 +325,13 @@ static void piix_tune_drive (ide_drive_t *drive, byte pio)
int slave_port = 0x44; int slave_port = 0x44;
unsigned long flags; unsigned long flags;
u16 master_data; u16 master_data;
byte slave_data; u8 slave_data;
/* ISP RTC */ /* ISP RTC */
byte timings[][2] = { { 0, 0 }, u8 timings[][2] = { { 0, 0 },
{ 0, 0 }, { 0, 0 },
{ 1, 0 }, { 1, 0 },
{ 2, 1 }, { 2, 1 },
{ 2, 3 }, }; { 2, 3 }, };
pio = ide_get_best_pio_mode(drive, pio, 5, NULL); pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
spin_lock_irqsave(&ide_lock, flags); spin_lock_irqsave(&ide_lock, flags);
...@@ -337,20 +357,30 @@ static void piix_tune_drive (ide_drive_t *drive, byte pio) ...@@ -337,20 +357,30 @@ static void piix_tune_drive (ide_drive_t *drive, byte pio)
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
} }
static int piix_tune_chipset (ide_drive_t *drive, byte xferspeed) /**
* piix_tune_chipset - tune a PIIX interface
* @drive: IDE drive to tune
* @xferspeed: speed to configure
*
* Set a PIIX interface channel to the desired speeds. This involves
* requires the right timing data into the PIIX configuration space
* then setting the drive parameters appropriately
*/
static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
byte maslave = hwif->channel ? 0x42 : 0x40; u8 maslave = hwif->channel ? 0x42 : 0x40;
byte speed = piix_ratefilter(drive, xferspeed); u8 speed = ide_rate_filter(piix_ratemask(drive), xferspeed);
int a_speed = 3 << (drive->dn * 4); int a_speed = 3 << (drive->dn * 4);
int u_flag = 1 << drive->dn; int u_flag = 1 << drive->dn;
int v_flag = 0x01 << drive->dn; int v_flag = 0x01 << drive->dn;
int w_flag = 0x10 << drive->dn; int w_flag = 0x10 << drive->dn;
int u_speed = 0; int u_speed = 0;
int sitre; int sitre;
short reg4042, reg44, reg48, reg4a, reg54; u16 reg4042, reg44, reg48, reg4a, reg54;
byte reg55; u8 reg55;
pci_read_config_word(dev, maslave, &reg4042); pci_read_config_word(dev, maslave, &reg4042);
sitre = (reg4042 & 0x4000) ? 1 : 0; sitre = (reg4042 & 0x4000) ? 1 : 0;
...@@ -383,9 +413,9 @@ static int piix_tune_chipset (ide_drive_t *drive, byte xferspeed) ...@@ -383,9 +413,9 @@ static int piix_tune_chipset (ide_drive_t *drive, byte xferspeed)
if (!(reg48 & u_flag)) if (!(reg48 & u_flag))
pci_write_config_word(dev, 0x48, reg48|u_flag); pci_write_config_word(dev, 0x48, reg48|u_flag);
if (speed == XFER_UDMA_5) { if (speed == XFER_UDMA_5) {
pci_write_config_byte(dev, 0x55, (byte) reg55|w_flag); pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
} else { } else {
pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
} }
if (!(reg4a & u_speed)) { if (!(reg4a & u_speed)) {
pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
...@@ -406,7 +436,7 @@ static int piix_tune_chipset (ide_drive_t *drive, byte xferspeed) ...@@ -406,7 +436,7 @@ static int piix_tune_chipset (ide_drive_t *drive, byte xferspeed)
if (reg54 & v_flag) if (reg54 & v_flag)
pci_write_config_word(dev, 0x54, reg54 & ~v_flag); pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
if (reg55 & w_flag) if (reg55 & w_flag)
pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag); pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
} }
piix_tune_drive(drive, piix_dma_2_pio(speed)); piix_tune_drive(drive, piix_dma_2_pio(speed));
...@@ -414,119 +444,91 @@ static int piix_tune_chipset (ide_drive_t *drive, byte xferspeed) ...@@ -414,119 +444,91 @@ static int piix_tune_chipset (ide_drive_t *drive, byte xferspeed)
} }
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
/**
* piix_config_drive_for_dma - configure drive for DMA
* @drive: IDE drive to configure
*
* Set up a PIIX interface channel for the best available speed.
* We prefer UDMA if it is available and then MWDMA. If DMA is
* not available we switch to PIO and return 0.
*/
static int piix_config_drive_for_dma (ide_drive_t *drive) static int piix_config_drive_for_dma (ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; u8 speed = ide_dma_speed(drive, piix_ratemask(drive));
byte mode = piix_ratemask(drive);
byte speed, tspeed, dma = 1; if (!(speed)) {
u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
switch(mode) { speed = piix_dma_2_pio(XFER_PIO_0 + tspeed);
case 0x03:
if (id->dma_ultra & 0x0040)
{ speed = XFER_UDMA_5; break; }
if (id->dma_ultra & 0x0020)
{ speed = XFER_UDMA_5; break; }
case 0x02:
if (id->dma_ultra & 0x0010)
{ speed = XFER_UDMA_4; break; }
if (id->dma_ultra & 0x0008)
{ speed = XFER_UDMA_3; break; }
case 0x01:
if (id->dma_ultra & 0x0004)
{ speed = XFER_UDMA_2; break; }
if (id->dma_ultra & 0x0002)
{ speed = XFER_UDMA_1; break; }
if (id->dma_ultra & 0x0001)
{ speed = XFER_UDMA_0; break; }
case 0x00:
if (id->dma_mword & 0x0004)
{ speed = XFER_MW_DMA_2; break; }
if (id->dma_mword & 0x0002)
{ speed = XFER_MW_DMA_1; break; }
if (id->dma_1word & 0x0004)
{ speed = XFER_SW_DMA_2; break; }
default:
tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
speed = piix_dma_2_pio(XFER_PIO_0 + tspeed);
dma = 0;
break;
} }
(void) piix_tune_chipset(drive, speed); (void) piix_tune_chipset(drive, speed);
return ide_dma_enable(drive);
// return ((int) (dma) ? ide_dma_on : ide_dma_off_quietly);
return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on :
((id->dma_ultra >> 8) & 7) ? ide_dma_on :
((id->dma_mword >> 8) & 7) ? ide_dma_on :
((id->dma_1word >> 8) & 7) ? ide_dma_on :
ide_dma_off_quietly);
} }
static int config_drive_xfer_rate (ide_drive_t *drive) /**
* piix_config_drive_xfer_rate - set up an IDE device
* @drive: IDE drive to configure
*
* Set up the PIIX interface for the best available speed on this
* interface, preferring DMA to PIO.
*/
static int piix_config_drive_xfer_rate (ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive);
ide_dma_action_t dma_func = ide_dma_on; struct hd_driveid *id = drive->id;
drive->init_speed = 0; drive->init_speed = 0;
if (id && (id->capability & 1) && HWIF(drive)->autodma) { if (id && (id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (ide_dmaproc(ide_dma_bad_drive, drive)) { if (hwif->ide_dma_bad_drive(drive))
dma_func = ide_dma_off;
goto fast_ata_pio; goto fast_ata_pio;
}
dma_func = ide_dma_off_quietly;
if (id->field_valid & 4) { if (id->field_valid & 4) {
if (id->dma_ultra & 0x007F) { if (id->dma_ultra & hwif->ultra_mask) {
/* Force if Capable UltraDMA */ /* Force if Capable UltraDMA */
dma_func = piix_config_drive_for_dma(drive);
if ((id->field_valid & 2) && if ((id->field_valid & 2) &&
(dma_func != ide_dma_on)) (!piix_config_drive_for_dma(drive)))
goto try_dma_modes; goto try_dma_modes;
} }
} else if (id->field_valid & 2) { } else if (id->field_valid & 2) {
try_dma_modes: try_dma_modes:
if ((id->dma_mword & 0x0007) || if ((id->dma_mword & hwif->mwdma_mask) ||
(id->dma_1word & 0x007)) { (id->dma_1word & hwif->swdma_mask)) {
/* Force if Capable regular DMA modes */ /* Force if Capable regular DMA modes */
dma_func = piix_config_drive_for_dma(drive); if (!piix_config_drive_for_dma(drive))
if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} }
} else if (ide_dmaproc(ide_dma_good_drive, drive)) { } else if (hwif->ide_dma_good_drive(drive) &&
if (id->eide_dma_time > 150) { (id->eide_dma_time < 150)) {
goto no_dma_set;
}
/* Consult the list of known "good" drives */ /* Consult the list of known "good" drives */
dma_func = piix_config_drive_for_dma(drive); if (!piix_config_drive_for_dma(drive))
if (dma_func != ide_dma_on)
goto no_dma_set; goto no_dma_set;
} else { } else {
goto fast_ata_pio; goto fast_ata_pio;
} }
} else if ((id->capability & 8) || (id->field_valid & 2)) { } else if ((id->capability & 8) || (id->field_valid & 2)) {
fast_ata_pio: fast_ata_pio:
dma_func = ide_dma_off_quietly;
no_dma_set: no_dma_set:
piix_tune_drive(drive, 255); hwif->tuneproc(drive, 255);
} return hwif->ide_dma_off_quietly(drive);
return HWIF(drive)->dmaproc(dma_func, drive);
}
static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
{
switch (func) {
case ide_dma_check:
return config_drive_xfer_rate(drive);
default :
break;
} }
/* Other cases are done by generic IDE-DMA code. */ return hwif->ide_dma_on(drive);
return ide_dmaproc(func, drive);
} }
#endif /* CONFIG_BLK_DEV_IDEDMA */ #endif /* CONFIG_BLK_DEV_IDEDMA */
unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) /**
* init_chipset_piix - set up the PIIX chipset
* @dev: PCI device to set up
* @name: Name of the device
*
* Initialize the PCI device as required. For the PIIX this turns
* out to be nice and simple
*/
static unsigned int __init init_chipset_piix (struct pci_dev *dev, const char *name)
{ {
switch(dev->device) { switch(dev->device) {
case PCI_DEVICE_ID_INTEL_82801AA_1: case PCI_DEVICE_ID_INTEL_82801AA_1:
...@@ -535,8 +537,8 @@ unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) ...@@ -535,8 +537,8 @@ unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name)
case PCI_DEVICE_ID_INTEL_82801BA_9: case PCI_DEVICE_ID_INTEL_82801BA_9:
case PCI_DEVICE_ID_INTEL_82801CA_10: case PCI_DEVICE_ID_INTEL_82801CA_10:
case PCI_DEVICE_ID_INTEL_82801CA_11: case PCI_DEVICE_ID_INTEL_82801CA_11:
case PCI_DEVICE_ID_INTEL_82801E_11:
case PCI_DEVICE_ID_INTEL_82801DB_11: case PCI_DEVICE_ID_INTEL_82801DB_11:
case PCI_DEVICE_ID_INTEL_82801E_11:
{ {
unsigned int extra = 0; unsigned int extra = 0;
pci_read_config_dword(dev, 0x54, &extra); pci_read_config_dword(dev, 0x54, &extra);
...@@ -547,35 +549,31 @@ unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) ...@@ -547,35 +549,31 @@ unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name)
} }
#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) #if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
piix_devs[n_piix_devs++] = dev;
if (!piix_proc) { if (!piix_proc) {
piix_proc = 1; piix_proc = 1;
bmide_dev = dev; ide_pci_register_host_proc(&piix_procs[0]);
piix_display_info = &piix_get_info;
} }
#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ #endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */
return 0; return 0;
} }
/* /**
* Sheesh, someone at Intel needs to go read the ATA-4/5 T13 standards. * init_hwif_piix - fill in the hwif for the PIIX
* It does not specify device detection, but channel!!! * @hwif: IDE interface
* You determine later if bit 13 of word93 is set... *
* Set up the ide_hwif_t for the PIIX interface according to the
* capabilities of the hardware.
*/ */
unsigned int __init ata66_piix (ide_hwif_t *hwif)
static void __init init_hwif_piix (ide_hwif_t *hwif)
{ {
byte reg54h = 0, reg55h = 0, ata66 = 0; #ifdef CONFIG_BLK_DEV_IDEDMA
byte mask = hwif->channel ? 0xc0 : 0x30; u8 reg54h = 0, reg55h = 0, ata66 = 0;
u8 mask = hwif->channel ? 0xc0 : 0x30;
pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h); #endif /* !CONFIG_BLK_DEV_IDEDMA */
pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
ata66 = (reg54h & mask) ? 1 : 0;
return ata66;
}
void __init ide_init_piix (ide_hwif_t *hwif)
{
#ifndef CONFIG_IA64 #ifndef CONFIG_IA64
if (!hwif->irq) if (!hwif->irq)
hwif->irq = hwif->channel ? 15 : 14; hwif->irq = hwif->channel ? 15 : 14;
...@@ -595,23 +593,100 @@ void __init ide_init_piix (ide_hwif_t *hwif) ...@@ -595,23 +593,100 @@ void __init ide_init_piix (ide_hwif_t *hwif)
if (!hwif->dma_base) if (!hwif->dma_base)
return; return;
hwif->atapi_dma = 1;
hwif->ultra_mask = 0x3f;
hwif->mwdma_mask = 0x06;
hwif->swdma_mask = 0x04;
#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA
hwif->dmaproc = &piix_dmaproc; switch(hwif->pci_dev->device) {
#ifdef CONFIG_IDEDMA_AUTO case PCI_DEVICE_ID_INTEL_82371MX:
hwif->mwdma_mask = 0x80;
hwif->swdma_mask = 0x80;
case PCI_DEVICE_ID_INTEL_82371FB_0:
case PCI_DEVICE_ID_INTEL_82371FB_1:
case PCI_DEVICE_ID_INTEL_82371SB_1:
hwif->ultra_mask = 0x80;
break;
case PCI_DEVICE_ID_INTEL_82371AB:
case PCI_DEVICE_ID_INTEL_82443MX_1:
case PCI_DEVICE_ID_INTEL_82451NX:
case PCI_DEVICE_ID_INTEL_82801AB_1:
hwif->ultra_mask = 0x07;
break;
default:
pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
ata66 = (reg54h & mask) ? 1 : 0;
break;
}
if (!(hwif->udma_four))
hwif->udma_four = ata66;
hwif->ide_dma_check = &piix_config_drive_xfer_rate;
if (!noautodma) if (!noautodma)
hwif->autodma = 1; hwif->autodma = 1;
#endif /* CONFIG_IDEDMA_AUTO */
hwif->drives[1].autodma = hwif->autodma;
hwif->drives[0].autodma = hwif->autodma;
#endif /* !CONFIG_BLK_DEV_IDEDMA */ #endif /* !CONFIG_BLK_DEV_IDEDMA */
} }
extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); /**
* init_dma_piix - set up the PIIX DMA
* @hwif: IDE interface
* @dmabase: DMA PCI base
*
* Set up the DMA on the PIIX controller, providing a DMA base is
* available. The PIIX follows the normal specs so we do nothing
* magical here.
*/
void __init fixup_device_piix (struct pci_dev *dev, ide_pci_device_t *d) static void __init init_dma_piix (ide_hwif_t *hwif, unsigned long dmabase)
{ {
if (dev->resource[0].start != 0x01F1) ide_setup_dma(hwif, dmabase, 8);
ide_register_xp_fix(dev); }
extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
printk("%s: IDE controller on PCI bus %02x dev %02x\n", /**
d->name, dev->bus->number, dev->devfn); * init_setup_piix - callback for IDE initialize
* @dev: PIIX PCI device
* @d: IDE pci info
*
* Enable the xp fixup for the PIIX controller and then perform
* a standard ide PCI setup
*/
static void __init init_setup_piix (struct pci_dev *dev, ide_pci_device_t *d)
{
ide_setup_pci_device(dev, d); ide_setup_pci_device(dev, d);
} }
/**
* piix_scan_pcidev - Check for and initialize PIIX IDE
* @dev: PCI device to check
*
* Checks if the passed device is an Intel PIIX device. If so the
* hardware is initialized and we return 1 to claim the device. If not
* we return 0.
*/
int __init piix_scan_pcidev (struct pci_dev *dev)
{
ide_pci_device_t *d;
if (dev->vendor != PCI_VENDOR_ID_INTEL)
return 0;
for (d = piix_chipsets; d && d->vendor && d->device; ++d) {
if (((d->vendor == dev->vendor) &&
(d->device == dev->device)) &&
(d->init_setup)) {
d->init_setup(dev, d);
return 1;
}
}
return 0;
}
#ifndef PIIX_H
#define PIIX_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define PIIX_DEBUG_DRIVE_INFO 0
#define DISPLAY_PIIX_TIMINGS
#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
#include <linux/proc_fs.h>
static u8 piix_proc;
static int piix_get_info(char *, char **, off_t, int);
static ide_pci_host_proc_t piix_procs[] __initdata = {
{
name: "piix",
set: 1,
get_info: piix_get_info,
parent: NULL,
},
};
#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */
static void init_setup_piix(struct pci_dev *, ide_pci_device_t *);
static unsigned int init_chipset_piix(struct pci_dev *, const char *);
static void init_hwif_piix(ide_hwif_t *);
static void init_dma_piix(ide_hwif_t *, unsigned long);
static ide_pci_device_t piix_chipsets[] __initdata = {
{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82371FB_0,
name: "PIIXa",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82371FB_1,
name: "PIIXb",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82371MX,
name: "MPIIX",
init_setup: init_setup_piix,
init_chipset: NULL,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: NULL,
channels: 2,
autodma: NODMA,
enablebits: {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82371SB_1,
name: "PIIX3",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82371AB,
name: "PIIX4",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82801AB_1,
name: "ICH0",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82443MX_1,
name: "PIIX4",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82801AA_1,
name: "ICH",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82372FB_1,
name: "PIIX4",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82451NX,
name: "PIIX4",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: NOAUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82801BA_9,
name: "ICH2",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82801BA_8,
name: "ICH2M",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82801CA_10,
name: "ICH3M",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82801CA_11,
name: "ICH3",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82801DB_11,
name: "ICH4",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: PCI_VENDOR_ID_INTEL,
device: PCI_DEVICE_ID_INTEL_82801E_11,
name: "C-ICH",
init_setup: init_setup_piix,
init_chipset: init_chipset_piix,
init_iops: NULL,
init_hwif: init_hwif_piix,
init_dma: init_dma_piix,
channels: 2,
autodma: AUTODMA,
enablebits: {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
bootable: ON_BOARD,
extra: 0,
},{
vendor: 0,
device: 0,
channels: 0,
init_setup: NULL,
bootable: EOL,
}
};
#endif /* PIIX_H */
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