[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:
parent
d435804803
commit
d33f58b883
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue