Author: stuge Date: 2008-06-22 03:53:33 +0200 (Sun, 22 Jun 2008) New Revision: 49
Modified: trunk/filo-0.5/drivers/ide.c trunk/filo-0.5/include/pci.h trunk/filo-0.5/main/pci.c Log: FILO: find_ide_controller_compat(): Skip over PCI devices in native mode
find_ide_controller_compat() would assume that all controllers were using legacy ports, even SATA and IDE controllers in native PCI mode.
On a system with these PCI ids: pci_init: 00:0f.0 1106:3149 0101 8f /* SATA native with 2 channels */ pci_init: 00:0f.1 1106:0571 0101 8a /* PATA legacy with 2 channels */
The SATA device has io resources above 0x1000. The PATA device is without proper io resources, but is configured to listen on the first and second legacy IDE ports 0x1f0 and 0x170.
find_ide_controller_compat() would incorrectly assume that the SATA device used ports 0x1f0 and 0x170, and that the PATA device used 0x1e8 and 0x168.
This teaches find_ide_controller_compat() to skip devices in native mode.
Tested to not change anything on PATA-only boards and tested to allow SATA+PATA boards to correctly boot from PATA drives.
Signed-off-by: Peter Stuge peter@stuge.se Acked-by: Bari Ari bari@onelabs.com
Modified: trunk/filo-0.5/drivers/ide.c =================================================================== --- trunk/filo-0.5/drivers/ide.c 2008-05-03 15:03:45 UTC (rev 48) +++ trunk/filo-0.5/drivers/ide.c 2008-06-22 01:53:33 UTC (rev 49) @@ -1078,8 +1078,13 @@
static int find_ide_controller_compat(struct controller *ctrl, int index) { +#ifdef SUPPORT_PCI + int skip, i, pci_index = index / 2; + struct pci_dev *dev; +#else if (index >= IDE_MAX_CONTROLLERS) return -1; +#endif #ifdef PCMCIA_CF if (index == 2) { ctrl->cmd_base = 0x1e0; @@ -1087,6 +1092,31 @@ return 0; } #endif +#ifdef SUPPORT_PCI + /* skip any SATA and PATA PCI controllers in native mode */ + for (skip = i = 0; i < pci_index && index; i++) { + /* look for i:th ata (IDE/other storage really) device */ + dev = pci_find_ata_device(-1, -1, -1, i); + if (!dev) + break; + /* only IDE can be in compat mode so skip all others */ + if (0x0101 != dev->devclass) { + /* other storage (SATA) always has two channels */ + skip += 2; + continue; + } + /* primary in native mode? then skip it. */ + if (1 == (dev->prog_if & 1)) + skip++; + /* secondary in native mode? then skip it. */ + if (index && 4 == (dev->prog_if & 4)) + skip++; + } + index = skip <= index ? index - skip : 0; + debug("skipping %d native PCI controllers, new index=%d\n", skip, index); + if (index >= IDE_MAX_CONTROLLERS) + return -1; +#endif ctrl->cmd_base = ide_base[index]; ctrl->ctrl_base = ide_base[index] + IDE_REG_EXTENDED_OFFSET; return 0;
Modified: trunk/filo-0.5/include/pci.h =================================================================== --- trunk/filo-0.5/include/pci.h 2008-05-03 15:03:45 UTC (rev 48) +++ trunk/filo-0.5/include/pci.h 2008-06-22 01:53:33 UTC (rev 49) @@ -32,5 +32,6 @@
void pci_init(void); struct pci_dev *pci_find_device(int vendor, int device, int devclass, int prog_if, int index); +struct pci_dev *pci_find_ata_device(int vendor, int device, int prog_if, int index);
#endif /* PCI_H */
Modified: trunk/filo-0.5/main/pci.c =================================================================== --- trunk/filo-0.5/main/pci.c 2008-05-03 15:03:45 UTC (rev 48) +++ trunk/filo-0.5/main/pci.c 2008-06-22 01:53:33 UTC (rev 49) @@ -107,3 +107,20 @@ } return NULL; } + +struct pci_dev *pci_find_ata_device(int vendor, int device, int prog_if, int index) +{ + struct pci_dev *dev; + + for (dev = dev_list; dev < dev_list + n_devs; dev++) { + if (vendor < 0 || vendor==dev->vendor) + if (device < 0 || device==dev->device) + if (0x0180 == dev->devclass || 0x0101 == dev->devclass) + if (prog_if < 0 || prog_if==dev->prog_if) { + if (index == 0) + return dev; + index--; + } + } + return NULL; +}