diff options
author | Tejun Heo <htejun@gmail.com> | 2006-02-28 11:25:39 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-03-03 15:39:54 -0500 |
commit | d33f58b883a3f624b9362227bf73fc52a6cbd4b4 (patch) | |
tree | 13a5571a6a1f3b6bf3c97c3418eec6e962231598 /drivers | |
parent | d435804803befedbda9fdc1be088e7930b60982b (diff) |
[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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/ata_piix.c | 182 |
1 files changed, 122 insertions, 60 deletions
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 987a7ccac917..4080b8be847b 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c | |||
@@ -112,9 +112,6 @@ enum { | |||
112 | /* combined mode. if set, PATA is channel 0. | 112 | /* combined mode. if set, PATA is channel 0. |
113 | * if clear, PATA is channel 1. | 113 | * if clear, PATA is channel 1. |
114 | */ | 114 | */ |
115 | PIIX_COMB_PATA_P0 = (1 << 1), | ||
116 | PIIX_COMB = (1 << 2), /* combined mode enabled? */ | ||
117 | |||
118 | PIIX_PORT_ENABLED = (1 << 0), | 115 | PIIX_PORT_ENABLED = (1 << 0), |
119 | PIIX_PORT_PRESENT = (1 << 4), | 116 | PIIX_PORT_PRESENT = (1 << 4), |
120 | 117 | ||
@@ -130,9 +127,23 @@ enum { | |||
130 | ich6_sata_ahci = 5, | 127 | ich6_sata_ahci = 5, |
131 | ich6m_sata_ahci = 6, | 128 | ich6m_sata_ahci = 6, |
132 | 129 | ||
130 | /* constants for mapping table */ | ||
131 | P0 = 0, /* port 0 */ | ||
132 | P1 = 1, /* port 1 */ | ||
133 | P2 = 2, /* port 2 */ | ||
134 | P3 = 3, /* port 3 */ | ||
135 | IDE = -1, /* IDE */ | ||
136 | NA = -2, /* not avaliable */ | ||
137 | RV = -3, /* reserved */ | ||
138 | |||
133 | PIIX_AHCI_DEVICE = 6, | 139 | PIIX_AHCI_DEVICE = 6, |
134 | }; | 140 | }; |
135 | 141 | ||
142 | struct piix_map_db { | ||
143 | const u32 mask; | ||
144 | const int map[][4]; | ||
145 | }; | ||
146 | |||
136 | static int piix_init_one (struct pci_dev *pdev, | 147 | static int piix_init_one (struct pci_dev *pdev, |
137 | const struct pci_device_id *ent); | 148 | const struct pci_device_id *ent); |
138 | 149 | ||
@@ -272,6 +283,43 @@ static const struct ata_port_operations piix_sata_ops = { | |||
272 | .host_stop = ata_host_stop, | 283 | .host_stop = ata_host_stop, |
273 | }; | 284 | }; |
274 | 285 | ||
286 | static struct piix_map_db ich5_map_db = { | ||
287 | .mask = 0x7, | ||
288 | .map = { | ||
289 | /* PM PS SM SS MAP */ | ||
290 | { P0, NA, P1, NA }, /* 000b */ | ||
291 | { P1, NA, P0, NA }, /* 001b */ | ||
292 | { RV, RV, RV, RV }, | ||
293 | { RV, RV, RV, RV }, | ||
294 | { P0, P1, IDE, IDE }, /* 100b */ | ||
295 | { P1, P0, IDE, IDE }, /* 101b */ | ||
296 | { IDE, IDE, P0, P1 }, /* 110b */ | ||
297 | { IDE, IDE, P1, P0 }, /* 111b */ | ||
298 | }, | ||
299 | }; | ||
300 | |||
301 | static struct piix_map_db ich6_map_db = { | ||
302 | .mask = 0x3, | ||
303 | .map = { | ||
304 | /* PM PS SM SS MAP */ | ||
305 | { P0, P1, P2, P3 }, /* 00b */ | ||
306 | { IDE, IDE, P1, P3 }, /* 01b */ | ||
307 | { P0, P2, IDE, IDE }, /* 10b */ | ||
308 | { RV, RV, RV, RV }, | ||
309 | }, | ||
310 | }; | ||
311 | |||
312 | static struct piix_map_db ich6m_map_db = { | ||
313 | .mask = 0x3, | ||
314 | .map = { | ||
315 | /* PM PS SM SS MAP */ | ||
316 | { P0, P1, P2, P3 }, /* 00b */ | ||
317 | { RV, RV, RV, RV }, | ||
318 | { P0, P2, IDE, IDE }, /* 10b */ | ||
319 | { RV, RV, RV, RV }, | ||
320 | }, | ||
321 | }; | ||
322 | |||
275 | static struct ata_port_info piix_port_info[] = { | 323 | static struct ata_port_info piix_port_info[] = { |
276 | /* piix4_pata */ | 324 | /* piix4_pata */ |
277 | { | 325 | { |
@@ -310,6 +358,7 @@ static struct ata_port_info piix_port_info[] = { | |||
310 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 358 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
311 | .udma_mask = 0x7f, /* udma0-6 */ | 359 | .udma_mask = 0x7f, /* udma0-6 */ |
312 | .port_ops = &piix_sata_ops, | 360 | .port_ops = &piix_sata_ops, |
361 | .private_data = &ich5_map_db, | ||
313 | }, | 362 | }, |
314 | 363 | ||
315 | /* i6300esb_sata */ | 364 | /* i6300esb_sata */ |
@@ -321,42 +370,45 @@ static struct ata_port_info piix_port_info[] = { | |||
321 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 370 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
322 | .udma_mask = 0x7f, /* udma0-6 */ | 371 | .udma_mask = 0x7f, /* udma0-6 */ |
323 | .port_ops = &piix_sata_ops, | 372 | .port_ops = &piix_sata_ops, |
373 | .private_data = &ich5_map_db, | ||
324 | }, | 374 | }, |
325 | 375 | ||
326 | /* ich6_sata */ | 376 | /* ich6_sata */ |
327 | { | 377 | { |
328 | .sht = &piix_sht, | 378 | .sht = &piix_sht, |
329 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | | 379 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | |
330 | PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | | 380 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR, |
331 | PIIX_FLAG_SCR, | ||
332 | .pio_mask = 0x1f, /* pio0-4 */ | 381 | .pio_mask = 0x1f, /* pio0-4 */ |
333 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 382 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
334 | .udma_mask = 0x7f, /* udma0-6 */ | 383 | .udma_mask = 0x7f, /* udma0-6 */ |
335 | .port_ops = &piix_sata_ops, | 384 | .port_ops = &piix_sata_ops, |
385 | .private_data = &ich6_map_db, | ||
336 | }, | 386 | }, |
337 | 387 | ||
338 | /* ich6_sata_ahci */ | 388 | /* ich6_sata_ahci */ |
339 | { | 389 | { |
340 | .sht = &piix_sht, | 390 | .sht = &piix_sht, |
341 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | | 391 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | |
342 | PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | | 392 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | |
343 | PIIX_FLAG_SCR | PIIX_FLAG_AHCI, | 393 | PIIX_FLAG_AHCI, |
344 | .pio_mask = 0x1f, /* pio0-4 */ | 394 | .pio_mask = 0x1f, /* pio0-4 */ |
345 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 395 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
346 | .udma_mask = 0x7f, /* udma0-6 */ | 396 | .udma_mask = 0x7f, /* udma0-6 */ |
347 | .port_ops = &piix_sata_ops, | 397 | .port_ops = &piix_sata_ops, |
398 | .private_data = &ich6_map_db, | ||
348 | }, | 399 | }, |
349 | 400 | ||
350 | /* ich6m_sata_ahci */ | 401 | /* ich6m_sata_ahci */ |
351 | { | 402 | { |
352 | .sht = &piix_sht, | 403 | .sht = &piix_sht, |
353 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | | 404 | .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | |
354 | PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | | 405 | PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | |
355 | PIIX_FLAG_SCR | PIIX_FLAG_AHCI, | 406 | PIIX_FLAG_AHCI, |
356 | .pio_mask = 0x1f, /* pio0-4 */ | 407 | .pio_mask = 0x1f, /* pio0-4 */ |
357 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 408 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
358 | .udma_mask = 0x7f, /* udma0-6 */ | 409 | .udma_mask = 0x7f, /* udma0-6 */ |
359 | .port_ops = &piix_sata_ops, | 410 | .port_ops = &piix_sata_ops, |
411 | .private_data = &ich6m_map_db, | ||
360 | }, | 412 | }, |
361 | }; | 413 | }; |
362 | 414 | ||
@@ -708,6 +760,54 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) | |||
708 | return no_piix_dma; | 760 | return no_piix_dma; |
709 | } | 761 | } |
710 | 762 | ||
763 | static void __devinit piix_init_sata_map(struct pci_dev *pdev, | ||
764 | struct ata_port_info *pinfo) | ||
765 | { | ||
766 | struct piix_map_db *map_db = pinfo[0].private_data; | ||
767 | const unsigned int *map; | ||
768 | int i, invalid_map = 0; | ||
769 | u8 map_value; | ||
770 | |||
771 | pci_read_config_byte(pdev, ICH5_PMR, &map_value); | ||
772 | |||
773 | map = map_db->map[map_value & map_db->mask]; | ||
774 | |||
775 | dev_printk(KERN_INFO, &pdev->dev, "MAP ["); | ||
776 | for (i = 0; i < 4; i++) { | ||
777 | switch (map[i]) { | ||
778 | case RV: | ||
779 | invalid_map = 1; | ||
780 | printk(" XX"); | ||
781 | break; | ||
782 | |||
783 | case NA: | ||
784 | printk(" --"); | ||
785 | break; | ||
786 | |||
787 | case IDE: | ||
788 | WARN_ON((i & 1) || map[i + 1] != IDE); | ||
789 | pinfo[i / 2] = piix_port_info[ich5_pata]; | ||
790 | i++; | ||
791 | printk(" IDE IDE"); | ||
792 | break; | ||
793 | |||
794 | default: | ||
795 | printk(" P%d", map[i]); | ||
796 | if (i & 1) | ||
797 | pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS; | ||
798 | break; | ||
799 | } | ||
800 | } | ||
801 | printk(" ]\n"); | ||
802 | |||
803 | if (invalid_map) | ||
804 | dev_printk(KERN_ERR, &pdev->dev, | ||
805 | "invalid MAP value %u\n", map_value); | ||
806 | |||
807 | pinfo[0].private_data = (void *)map; | ||
808 | pinfo[1].private_data = (void *)map; | ||
809 | } | ||
810 | |||
711 | /** | 811 | /** |
712 | * piix_init_one - Register PIIX ATA PCI device with kernel services | 812 | * piix_init_one - Register PIIX ATA PCI device with kernel services |
713 | * @pdev: PCI device to register | 813 | * @pdev: PCI device to register |
@@ -726,9 +826,8 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) | |||
726 | static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | 826 | static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) |
727 | { | 827 | { |
728 | static int printed_version; | 828 | static int printed_version; |
729 | struct ata_port_info *port_info[2]; | 829 | struct ata_port_info port_info[2]; |
730 | unsigned int combined = 0; | 830 | struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] }; |
731 | unsigned int pata_chan = 0, sata_chan = 0; | ||
732 | unsigned long host_flags; | 831 | unsigned long host_flags; |
733 | 832 | ||
734 | if (!printed_version++) | 833 | if (!printed_version++) |
@@ -739,10 +838,10 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
739 | if (!in_module_init) | 838 | if (!in_module_init) |
740 | return -ENODEV; | 839 | return -ENODEV; |
741 | 840 | ||
742 | port_info[0] = &piix_port_info[ent->driver_data]; | 841 | port_info[0] = piix_port_info[ent->driver_data]; |
743 | port_info[1] = &piix_port_info[ent->driver_data]; | 842 | port_info[1] = piix_port_info[ent->driver_data]; |
744 | 843 | ||
745 | host_flags = port_info[0]->host_flags; | 844 | host_flags = port_info[0].host_flags; |
746 | 845 | ||
747 | if (host_flags & PIIX_FLAG_AHCI) { | 846 | if (host_flags & PIIX_FLAG_AHCI) { |
748 | u8 tmp; | 847 | u8 tmp; |
@@ -754,37 +853,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
754 | } | 853 | } |
755 | } | 854 | } |
756 | 855 | ||
757 | if (host_flags & PIIX_FLAG_COMBINED) { | 856 | /* Initialize SATA map */ |
758 | u8 tmp; | 857 | if (host_flags & ATA_FLAG_SATA) |
759 | pci_read_config_byte(pdev, ICH5_PMR, &tmp); | 858 | piix_init_sata_map(pdev, port_info); |
760 | |||
761 | if (host_flags & PIIX_FLAG_COMBINED_ICH6) { | ||
762 | switch (tmp & 0x3) { | ||
763 | case 0: | ||
764 | break; | ||
765 | case 1: | ||
766 | combined = 1; | ||
767 | sata_chan = 1; | ||
768 | break; | ||
769 | case 2: | ||
770 | combined = 1; | ||
771 | pata_chan = 1; | ||
772 | break; | ||
773 | case 3: | ||
774 | dev_printk(KERN_WARNING, &pdev->dev, | ||
775 | "invalid MAP value %u\n", tmp); | ||
776 | break; | ||
777 | } | ||
778 | } else { | ||
779 | if (tmp & PIIX_COMB) { | ||
780 | combined = 1; | ||
781 | if (tmp & PIIX_COMB_PATA_P0) | ||
782 | sata_chan = 1; | ||
783 | else | ||
784 | pata_chan = 1; | ||
785 | } | ||
786 | } | ||
787 | } | ||
788 | 859 | ||
789 | /* On ICH5, some BIOSen disable the interrupt using the | 860 | /* On ICH5, some BIOSen disable the interrupt using the |
790 | * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. | 861 | * 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 | if (host_flags & PIIX_FLAG_CHECKINTR) | 866 | if (host_flags & PIIX_FLAG_CHECKINTR) |
796 | pci_intx(pdev, 1); | 867 | pci_intx(pdev, 1); |
797 | 868 | ||
798 | if (combined) { | ||
799 | port_info[sata_chan] = &piix_port_info[ent->driver_data]; | ||
800 | port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS; | ||
801 | port_info[pata_chan] = &piix_port_info[ich5_pata]; | ||
802 | |||
803 | dev_printk(KERN_WARNING, &pdev->dev, | ||
804 | "combined mode detected (p=%u, s=%u)\n", | ||
805 | pata_chan, sata_chan); | ||
806 | } | ||
807 | if (piix_check_450nx_errata(pdev)) { | 869 | if (piix_check_450nx_errata(pdev)) { |
808 | /* This writes into the master table but it does not | 870 | /* This writes into the master table but it does not |
809 | really matter for this errata as we will apply it to | 871 | really matter for this errata as we will apply it to |
810 | all the PIIX devices on the board */ | 872 | all the PIIX devices on the board */ |
811 | port_info[0]->mwdma_mask = 0; | 873 | port_info[0].mwdma_mask = 0; |
812 | port_info[0]->udma_mask = 0; | 874 | port_info[0].udma_mask = 0; |
813 | port_info[1]->mwdma_mask = 0; | 875 | port_info[1].mwdma_mask = 0; |
814 | port_info[1]->udma_mask = 0; | 876 | port_info[1].udma_mask = 0; |
815 | } | 877 | } |
816 | return ata_pci_init_one(pdev, port_info, 2); | 878 | return ata_pci_init_one(pdev, ppinfo, 2); |
817 | } | 879 | } |
818 | 880 | ||
819 | static int __init piix_init(void) | 881 | static int __init piix_init(void) |