提交 d33f58b8 编写于 作者: T Tejun Heo 提交者: Jeff Garzik

[PATCH] ata_piix: implement proper port map

Replace combined mode handling via PIIX_COMB/COMB_PATA_P0 with proper
port map.  PIIX now prints port configuration during initialization.
ATA_FLAG_SLAVE_POSS is now turned on for SATA ports only when the
slave device is actually avaliable.
Signed-off-by: NTejun Heo <htejun@gmail.com>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
上级 d4358048
...@@ -112,9 +112,6 @@ enum { ...@@ -112,9 +112,6 @@ enum {
/* combined mode. if set, PATA is channel 0. /* combined mode. if set, PATA is channel 0.
* if clear, PATA is channel 1. * 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_ENABLED = (1 << 0),
PIIX_PORT_PRESENT = (1 << 4), PIIX_PORT_PRESENT = (1 << 4),
...@@ -130,9 +127,23 @@ enum { ...@@ -130,9 +127,23 @@ enum {
ich6_sata_ahci = 5, ich6_sata_ahci = 5,
ich6m_sata_ahci = 6, 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, PIIX_AHCI_DEVICE = 6,
}; };
struct piix_map_db {
const u32 mask;
const int map[][4];
};
static int piix_init_one (struct pci_dev *pdev, static int piix_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent); const struct pci_device_id *ent);
...@@ -272,6 +283,43 @@ static const struct ata_port_operations piix_sata_ops = { ...@@ -272,6 +283,43 @@ static const struct ata_port_operations piix_sata_ops = {
.host_stop = ata_host_stop, .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[] = { static struct ata_port_info piix_port_info[] = {
/* piix4_pata */ /* piix4_pata */
{ {
...@@ -310,6 +358,7 @@ static struct ata_port_info piix_port_info[] = { ...@@ -310,6 +358,7 @@ static struct ata_port_info piix_port_info[] = {
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
.private_data = &ich5_map_db,
}, },
/* i6300esb_sata */ /* i6300esb_sata */
...@@ -321,42 +370,45 @@ static struct ata_port_info piix_port_info[] = { ...@@ -321,42 +370,45 @@ static struct ata_port_info piix_port_info[] = {
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
.private_data = &ich5_map_db,
}, },
/* ich6_sata */ /* ich6_sata */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR,
PIIX_FLAG_SCR,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
.private_data = &ich6_map_db,
}, },
/* ich6_sata_ahci */ /* ich6_sata_ahci */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
PIIX_FLAG_SCR | PIIX_FLAG_AHCI, PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
.private_data = &ich6_map_db,
}, },
/* ich6m_sata_ahci */ /* ich6m_sata_ahci */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 |
PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
PIIX_FLAG_SCR | PIIX_FLAG_AHCI, PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 */ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops, .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) ...@@ -708,6 +760,54 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
return no_piix_dma; 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 * piix_init_one - Register PIIX ATA PCI device with kernel services
* @pdev: PCI device to register * @pdev: PCI device to register
...@@ -726,9 +826,8 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) ...@@ -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 piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
static int printed_version; static int printed_version;
struct ata_port_info *port_info[2]; struct ata_port_info port_info[2];
unsigned int combined = 0; struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] };
unsigned int pata_chan = 0, sata_chan = 0;
unsigned long host_flags; unsigned long host_flags;
if (!printed_version++) if (!printed_version++)
...@@ -739,10 +838,10 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -739,10 +838,10 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (!in_module_init) if (!in_module_init)
return -ENODEV; return -ENODEV;
port_info[0] = &piix_port_info[ent->driver_data]; port_info[0] = piix_port_info[ent->driver_data];
port_info[1] = &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) { if (host_flags & PIIX_FLAG_AHCI) {
u8 tmp; u8 tmp;
...@@ -754,37 +853,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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) { /* Initialize SATA map */
u8 tmp; if (host_flags & ATA_FLAG_SATA)
pci_read_config_byte(pdev, ICH5_PMR, &tmp); piix_init_sata_map(pdev, port_info);
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;
}
}
}
/* On ICH5, some BIOSen disable the interrupt using the /* On ICH5, some BIOSen disable the interrupt using the
* PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. * 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) ...@@ -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) if (host_flags & PIIX_FLAG_CHECKINTR)
pci_intx(pdev, 1); 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)) { if (piix_check_450nx_errata(pdev)) {
/* This writes into the master table but it does not /* This writes into the master table but it does not
really matter for this errata as we will apply it to really matter for this errata as we will apply it to
all the PIIX devices on the board */ all the PIIX devices on the board */
port_info[0]->mwdma_mask = 0; port_info[0].mwdma_mask = 0;
port_info[0]->udma_mask = 0; port_info[0].udma_mask = 0;
port_info[1]->mwdma_mask = 0; port_info[1].mwdma_mask = 0;
port_info[1]->udma_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) static int __init piix_init(void)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册