Hello Uwe, Thanks for you reply. I sent the patch to you again. Hope it is okay. Do you need a referenced board for testing ? David -------------- diff -Nura a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c --- a/drivers/scsi/sata_sis.c 2006-08-24 05:16:33.000000000 +0800 +++ b/drivers/scsi/sata_sis.c 2006-09-05 11:08:58.000000000 +0800 @@ -71,6 +71,9 @@ { PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, { PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, { PCI_VENDOR_ID_SI, 0x182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, + { PCI_VENDOR_ID_SI, 0x1180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, + { PCI_VENDOR_ID_SI, 0x1182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, + { PCI_VENDOR_ID_SI, 0x1183, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, { } /* terminate list */ }; @@ -126,7 +129,7 @@ static struct ata_port_info sis_port_info = { .sht = &sis_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | - ATA_FLAG_NO_LEGACY, + ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, .mwdma_mask = 0x7, .udma_mask = 0x7f, @@ -140,15 +143,37 @@ MODULE_DEVICE_TABLE(pci, sis_pci_tbl); MODULE_VERSION(DRV_VERSION); -static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, int device) +static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, struct pci_dev *pdev) { unsigned int addr = SIS_SCR_BASE + (4 * sc_reg); + u32 val = 0; if (port_no) { - if (device == 0x182) - addr += SIS182_SATA1_OFS; - else - addr += SIS180_SATA1_OFS; + switch (pdev->device) { + case 0x0180: + case 0x0181: + addr += SIS180_SATA1_OFS; + break; + case 0x0182: + case 0x1182: + case 0x1183: + addr += SIS182_SATA1_OFS; + break; + case 0x1180: + /* + * If hw_id == 0x1180 + * read PCI offset 64h, bit 28 to decide what the chip is. + * This is the only way to tell SiS966 from SiS966L. + * 1: 966L port0 = c0h, port1 = e0h + * 0: 966 port0 = c0h, port1 = d0h + */ + pci_read_config_dword(pdev, 0x64, &val); + if (val & (1 << 28)) + addr += SIS182_SATA1_OFS; /* SB-966L */ + else + addr += SIS180_SATA1_OFS; /* 966 */ + break; + } } return addr; @@ -157,7 +182,7 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); - unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device); + unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev); u32 val, val2 = 0; u8 pmr; @@ -168,16 +193,19 @@ pci_read_config_dword(pdev, cfg_addr, &val); - if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) + if ((pdev->device == 0x182) || (pdev->device == 0x1182) || (pdev->device == 0x1183) ||(pmr & SIS_PMR_COMBINED)) pci_read_config_dword(pdev, cfg_addr+0x10, &val2); - - return val|val2; + + /* Due to the port status is ORed with two SATA ports. + The unused SATA port might be powered down by BIOS. + We need to mask 0x3 to report the correct value */ + return (val|val2) & 3U; } static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); - unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev->device); + unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev); u8 pmr; if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */ @@ -187,7 +215,7 @@ pci_write_config_dword(pdev, cfg_addr, val); - if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) + if ((pdev->device == 0x182) || (pdev->device == 0x1182) || (pdev->device == 0x1183) ||(pmr & SIS_PMR_COMBINED)) pci_write_config_dword(pdev, cfg_addr+0x10, val); } @@ -207,10 +235,14 @@ val = inl(ap->ioaddr.scr_addr + (sc_reg * 4)); - if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) + if ((pdev->device == 0x182) || (pdev->device == 0x1182) + || (pdev->device == 0x1183) ||(pmr & SIS_PMR_COMBINED)) val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10); - - return val | val2; + + /* Due to the port status is ORed with two SATA ports. + The unused SATA port might be powered down by BIOS. + We need to mask 0x3 to report the correct value */ + return (val|val2) & 3U; } static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) @@ -227,7 +259,8 @@ sis_scr_cfg_write(ap, sc_reg, val); else { outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)); - if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) + if ((pdev->device == 0x182) || (pdev->device == 0x1182) + || (pdev->device == 0x1183) ||(pmr & SIS_PMR_COMBINED)) outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10); } } @@ -241,11 +274,29 @@ struct ata_port_info *ppi; int pci_dev_busy = 0; u8 pmr; - u8 port2_start; + u8 port2_start = 0; + u8 progintf; + u16 classCode; if (!printed_version++) dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); + /* check if the device's programming interface 09h, + is compatibility mode + */ + pci_read_config_word(pdev, 0x0A, &classCode); + if (classCode == 0x0101) { + pci_read_config_byte(pdev, 0x09, &progintf); + if ((progintf & 0x5) == 0) { + dev_printk(KERN_INFO, &pdev->dev, + "SiS-%x IDE device is compatibiltiy mode. Ignore it\n", + ent->device); + dev_printk(KERN_INFO, &pdev->dev, + "Try to change BIOS setting with native mode..\n"); + rc = -1; + return rc; + } + } rc = pci_enable_device(pdev); if (rc) return rc; @@ -275,6 +326,10 @@ if ((genctl & GENCTL_IOMAPPED_SCR) == 0) probe_ent->host_flags |= SIS_FLAG_CFGSCR; + /* 0x1180 does not provide SCRs mapping. Set the CFGSCR Flag */ + if (ent->device == 0x1180) + probe_ent->host_flags |= SIS_FLAG_CFGSCR; + /* if hardware thinks SCRs are in IO space, but there are * no IO resources assigned, change to PCI cfg space. */ @@ -287,21 +342,31 @@ } pci_read_config_byte(pdev, SIS_PMR, &pmr); - if (ent->device != 0x182) { - if ((pmr & SIS_PMR_COMBINED) == 0) { - dev_printk(KERN_INFO, &pdev->dev, + switch (ent->device) { + case 0x0180: + case 0x0181: + if ((pmr & SIS_PMR_COMBINED) == 0) { + dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 180/181 chipset in SATA mode\n"); - port2_start = 64; - } - else { - dev_printk(KERN_INFO, &pdev->dev, + port2_start = 64; + } + else { + dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 180/181 chipset in combined mode\n"); - port2_start=0; - } - } - else { - dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182 chipset\n"); - port2_start = 0x20; + port2_start = 0; + } + break; + + case 0x0182: + case 0x1182: + case 0x1183: + dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/1182/1183 SATA controller\n"); + port2_start = 0x20; + break; + + case 0x1180: + dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1180 SATA controller\n"); + break; } if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) { - To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html