[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: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
Tejun Heo 2006-03-01 01:25:39 +09:00 committed by Jeff Garzik
parent d435804803
commit d33f58b883
1 changed files with 122 additions and 60 deletions

View File

@ -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)