|
@@ -112,9 +112,6 @@ enum {
|
|
|
/* combined mode. if set, PATA is channel 0.
|
|
|
* if clear, PATA is channel 1.
|
|
|
*/
|
|
|
- PIIX_COMB_PATA_P0 = (1 << 1),
|
|
|
- PIIX_COMB = (1 << 2), /* combined mode enabled? */
|
|
|
-
|
|
|
PIIX_PORT_ENABLED = (1 << 0),
|
|
|
PIIX_PORT_PRESENT = (1 << 4),
|
|
|
|
|
@@ -130,9 +127,23 @@ enum {
|
|
|
ich6_sata_ahci = 5,
|
|
|
ich6m_sata_ahci = 6,
|
|
|
|
|
|
+ /* constants for mapping table */
|
|
|
+ P0 = 0, /* port 0 */
|
|
|
+ P1 = 1, /* port 1 */
|
|
|
+ P2 = 2, /* port 2 */
|
|
|
+ P3 = 3, /* port 3 */
|
|
|
+ IDE = -1, /* IDE */
|
|
|
+ NA = -2, /* not avaliable */
|
|
|
+ RV = -3, /* reserved */
|
|
|
+
|
|
|
PIIX_AHCI_DEVICE = 6,
|
|
|
};
|
|
|
|
|
|
+struct piix_map_db {
|
|
|
+ const u32 mask;
|
|
|
+ const int map[][4];
|
|
|
+};
|
|
|
+
|
|
|
static int piix_init_one (struct pci_dev *pdev,
|
|
|
const struct pci_device_id *ent);
|
|
|
|
|
@@ -272,6 +283,43 @@ static const struct ata_port_operations piix_sata_ops = {
|
|
|
.host_stop = ata_host_stop,
|
|
|
};
|
|
|
|
|
|
+static struct piix_map_db ich5_map_db = {
|
|
|
+ .mask = 0x7,
|
|
|
+ .map = {
|
|
|
+ /* PM PS SM SS MAP */
|
|
|
+ { P0, NA, P1, NA }, /* 000b */
|
|
|
+ { P1, NA, P0, NA }, /* 001b */
|
|
|
+ { RV, RV, RV, RV },
|
|
|
+ { RV, RV, RV, RV },
|
|
|
+ { P0, P1, IDE, IDE }, /* 100b */
|
|
|
+ { P1, P0, IDE, IDE }, /* 101b */
|
|
|
+ { IDE, IDE, P0, P1 }, /* 110b */
|
|
|
+ { IDE, IDE, P1, P0 }, /* 111b */
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+static struct piix_map_db ich6_map_db = {
|
|
|
+ .mask = 0x3,
|
|
|
+ .map = {
|
|
|
+ /* PM PS SM SS MAP */
|
|
|
+ { P0, P1, P2, P3 }, /* 00b */
|
|
|
+ { IDE, IDE, P1, P3 }, /* 01b */
|
|
|
+ { P0, P2, IDE, IDE }, /* 10b */
|
|
|
+ { RV, RV, RV, RV },
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+static struct piix_map_db ich6m_map_db = {
|
|
|
+ .mask = 0x3,
|
|
|
+ .map = {
|
|
|
+ /* PM PS SM SS MAP */
|
|
|
+ { P0, P1, P2, P3 }, /* 00b */
|
|
|
+ { RV, RV, RV, RV },
|
|
|
+ { P0, P2, IDE, IDE }, /* 10b */
|
|
|
+ { RV, RV, RV, RV },
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
static struct ata_port_info piix_port_info[] = {
|
|
|
/* piix4_pata */
|
|
|
{
|
|
@@ -310,6 +358,7 @@ static struct ata_port_info piix_port_info[] = {
|
|
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
|
|
.udma_mask = 0x7f, /* udma0-6 */
|
|
|
.port_ops = &piix_sata_ops,
|
|
|
+ .private_data = &ich5_map_db,
|
|
|
},
|
|
|
|
|
|
/* i6300esb_sata */
|
|
@@ -321,42 +370,45 @@ static struct ata_port_info piix_port_info[] = {
|
|
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
|
|
.udma_mask = 0x7f, /* udma0-6 */
|
|
|
.port_ops = &piix_sata_ops,
|
|
|
+ .private_data = &ich5_map_db,
|
|
|
},
|
|
|
|
|
|
/* ich6_sata */
|
|
|
{
|
|
|
.sht = &piix_sht,
|
|
|
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
|
|
|
- PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS |
|
|
|
- PIIX_FLAG_SCR,
|
|
|
+ PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
|
|
|
.pio_mask = 0x1f, /* pio0-4 */
|
|
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
|
|
.udma_mask = 0x7f, /* udma0-6 */
|
|
|
.port_ops = &piix_sata_ops,
|
|
|
+ .private_data = &ich6_map_db,
|
|
|
},
|
|
|
|
|
|
/* ich6_sata_ahci */
|
|
|
{
|
|
|
.sht = &piix_sht,
|
|
|
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
|
|
|
- PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS |
|
|
|
- PIIX_FLAG_SCR | PIIX_FLAG_AHCI,
|
|
|
+ PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
|
|
|
+ PIIX_FLAG_AHCI,
|
|
|
.pio_mask = 0x1f, /* pio0-4 */
|
|
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
|
|
.udma_mask = 0x7f, /* udma0-6 */
|
|
|
.port_ops = &piix_sata_ops,
|
|
|
+ .private_data = &ich6_map_db,
|
|
|
},
|
|
|
|
|
|
/* ich6m_sata_ahci */
|
|
|
{
|
|
|
.sht = &piix_sht,
|
|
|
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
|
|
|
- PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS |
|
|
|
- PIIX_FLAG_SCR | PIIX_FLAG_AHCI,
|
|
|
+ PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
|
|
|
+ PIIX_FLAG_AHCI,
|
|
|
.pio_mask = 0x1f, /* pio0-4 */
|
|
|
.mwdma_mask = 0x07, /* mwdma0-2 */
|
|
|
.udma_mask = 0x7f, /* udma0-6 */
|
|
|
.port_ops = &piix_sata_ops,
|
|
|
+ .private_data = &ich6m_map_db,
|
|
|
},
|
|
|
};
|
|
|
|
|
@@ -708,6 +760,54 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
|
|
|
return no_piix_dma;
|
|
|
}
|
|
|
|
|
|
+static void __devinit piix_init_sata_map(struct pci_dev *pdev,
|
|
|
+ struct ata_port_info *pinfo)
|
|
|
+{
|
|
|
+ struct piix_map_db *map_db = pinfo[0].private_data;
|
|
|
+ const unsigned int *map;
|
|
|
+ int i, invalid_map = 0;
|
|
|
+ u8 map_value;
|
|
|
+
|
|
|
+ pci_read_config_byte(pdev, ICH5_PMR, &map_value);
|
|
|
+
|
|
|
+ map = map_db->map[map_value & map_db->mask];
|
|
|
+
|
|
|
+ dev_printk(KERN_INFO, &pdev->dev, "MAP [");
|
|
|
+ for (i = 0; i < 4; i++) {
|
|
|
+ switch (map[i]) {
|
|
|
+ case RV:
|
|
|
+ invalid_map = 1;
|
|
|
+ printk(" XX");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case NA:
|
|
|
+ printk(" --");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case IDE:
|
|
|
+ WARN_ON((i & 1) || map[i + 1] != IDE);
|
|
|
+ pinfo[i / 2] = piix_port_info[ich5_pata];
|
|
|
+ i++;
|
|
|
+ printk(" IDE IDE");
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ printk(" P%d", map[i]);
|
|
|
+ if (i & 1)
|
|
|
+ pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ printk(" ]\n");
|
|
|
+
|
|
|
+ if (invalid_map)
|
|
|
+ dev_printk(KERN_ERR, &pdev->dev,
|
|
|
+ "invalid MAP value %u\n", map_value);
|
|
|
+
|
|
|
+ pinfo[0].private_data = (void *)map;
|
|
|
+ pinfo[1].private_data = (void *)map;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* piix_init_one - Register PIIX ATA PCI device with kernel services
|
|
|
* @pdev: PCI device to register
|
|
@@ -726,9 +826,8 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
|
|
|
static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
{
|
|
|
static int printed_version;
|
|
|
- struct ata_port_info *port_info[2];
|
|
|
- unsigned int combined = 0;
|
|
|
- unsigned int pata_chan = 0, sata_chan = 0;
|
|
|
+ struct ata_port_info port_info[2];
|
|
|
+ struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] };
|
|
|
unsigned long host_flags;
|
|
|
|
|
|
if (!printed_version++)
|
|
@@ -739,10 +838,10 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
if (!in_module_init)
|
|
|
return -ENODEV;
|
|
|
|
|
|
- port_info[0] = &piix_port_info[ent->driver_data];
|
|
|
- port_info[1] = &piix_port_info[ent->driver_data];
|
|
|
+ port_info[0] = piix_port_info[ent->driver_data];
|
|
|
+ port_info[1] = piix_port_info[ent->driver_data];
|
|
|
|
|
|
- host_flags = port_info[0]->host_flags;
|
|
|
+ host_flags = port_info[0].host_flags;
|
|
|
|
|
|
if (host_flags & PIIX_FLAG_AHCI) {
|
|
|
u8 tmp;
|
|
@@ -754,37 +853,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (host_flags & PIIX_FLAG_COMBINED) {
|
|
|
- u8 tmp;
|
|
|
- pci_read_config_byte(pdev, ICH5_PMR, &tmp);
|
|
|
-
|
|
|
- if (host_flags & PIIX_FLAG_COMBINED_ICH6) {
|
|
|
- switch (tmp & 0x3) {
|
|
|
- case 0:
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- combined = 1;
|
|
|
- sata_chan = 1;
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- combined = 1;
|
|
|
- pata_chan = 1;
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- dev_printk(KERN_WARNING, &pdev->dev,
|
|
|
- "invalid MAP value %u\n", tmp);
|
|
|
- break;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (tmp & PIIX_COMB) {
|
|
|
- combined = 1;
|
|
|
- if (tmp & PIIX_COMB_PATA_P0)
|
|
|
- sata_chan = 1;
|
|
|
- else
|
|
|
- pata_chan = 1;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ /* Initialize SATA map */
|
|
|
+ if (host_flags & ATA_FLAG_SATA)
|
|
|
+ piix_init_sata_map(pdev, port_info);
|
|
|
|
|
|
/* On ICH5, some BIOSen disable the interrupt using the
|
|
|
* PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
|
|
@@ -795,25 +866,16 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
if (host_flags & PIIX_FLAG_CHECKINTR)
|
|
|
pci_intx(pdev, 1);
|
|
|
|
|
|
- if (combined) {
|
|
|
- port_info[sata_chan] = &piix_port_info[ent->driver_data];
|
|
|
- port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS;
|
|
|
- port_info[pata_chan] = &piix_port_info[ich5_pata];
|
|
|
-
|
|
|
- dev_printk(KERN_WARNING, &pdev->dev,
|
|
|
- "combined mode detected (p=%u, s=%u)\n",
|
|
|
- pata_chan, sata_chan);
|
|
|
- }
|
|
|
if (piix_check_450nx_errata(pdev)) {
|
|
|
/* This writes into the master table but it does not
|
|
|
really matter for this errata as we will apply it to
|
|
|
all the PIIX devices on the board */
|
|
|
- port_info[0]->mwdma_mask = 0;
|
|
|
- port_info[0]->udma_mask = 0;
|
|
|
- port_info[1]->mwdma_mask = 0;
|
|
|
- port_info[1]->udma_mask = 0;
|
|
|
+ port_info[0].mwdma_mask = 0;
|
|
|
+ port_info[0].udma_mask = 0;
|
|
|
+ port_info[1].mwdma_mask = 0;
|
|
|
+ port_info[1].udma_mask = 0;
|
|
|
}
|
|
|
- return ata_pci_init_one(pdev, port_info, 2);
|
|
|
+ return ata_pci_init_one(pdev, ppinfo, 2);
|
|
|
}
|
|
|
|
|
|
static int __init piix_init(void)
|