aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/sata_sis.c82
1 files changed, 71 insertions, 11 deletions
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index 43af445b3ad2..7d1aaa99aaae 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -52,7 +52,10 @@ enum {
52 /* PCI configuration registers */ 52 /* PCI configuration registers */
53 SIS_GENCTL = 0x54, /* IDE General Control register */ 53 SIS_GENCTL = 0x54, /* IDE General Control register */
54 SIS_SCR_BASE = 0xc0, /* sata0 phy SCR registers */ 54 SIS_SCR_BASE = 0xc0, /* sata0 phy SCR registers */
55 SIS_SATA1_OFS = 0x10, /* offset from sata0->sata1 phy regs */ 55 SIS180_SATA1_OFS = 0x10, /* offset from sata0->sata1 phy regs */
56 SIS182_SATA1_OFS = 0x20, /* offset from sata0->sata1 phy regs */
57 SIS_PMR = 0x90, /* port mapping register */
58 SIS_PMR_COMBINED = 0x30,
56 59
57 /* random bits */ 60 /* random bits */
58 SIS_FLAG_CFGSCR = (1 << 30), /* host flag: SCRs via PCI cfg */ 61 SIS_FLAG_CFGSCR = (1 << 30), /* host flag: SCRs via PCI cfg */
@@ -67,6 +70,7 @@ static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
67static struct pci_device_id sis_pci_tbl[] = { 70static struct pci_device_id sis_pci_tbl[] = {
68 { PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, 71 { PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
69 { PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, 72 { PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
73 { PCI_VENDOR_ID_SI, 0x182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
70 { } /* terminate list */ 74 { } /* terminate list */
71}; 75};
72 76
@@ -139,56 +143,94 @@ MODULE_LICENSE("GPL");
139MODULE_DEVICE_TABLE(pci, sis_pci_tbl); 143MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
140MODULE_VERSION(DRV_VERSION); 144MODULE_VERSION(DRV_VERSION);
141 145
142static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg) 146static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, int device)
143{ 147{
144 unsigned int addr = SIS_SCR_BASE + (4 * sc_reg); 148 unsigned int addr = SIS_SCR_BASE + (4 * sc_reg);
145 149
146 if (port_no) 150 if (port_no)
147 addr += SIS_SATA1_OFS; 151 if (device == 0x182)
152 addr += SIS182_SATA1_OFS;
153 else
154 addr += SIS180_SATA1_OFS;
148 return addr; 155 return addr;
149} 156}
150 157
151static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) 158static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
152{ 159{
153 struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); 160 struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
154 unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg); 161 unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device);
155 u32 val; 162 u32 val, val2;
163 u8 pmr;
156 164
157 if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ 165 if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
158 return 0xffffffff; 166 return 0xffffffff;
167
168 pci_read_config_byte(pdev, SIS_PMR, &pmr);
169
159 pci_read_config_dword(pdev, cfg_addr, &val); 170 pci_read_config_dword(pdev, cfg_addr, &val);
160 return val; 171
172 if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
173 pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
174
175 return val|val2;
161} 176}
162 177
163static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) 178static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
164{ 179{
165 struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); 180 struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
166 unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr); 181 unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev->device);
182 u8 pmr;
167 183
168 if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */ 184 if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */
169 return; 185 return;
186
187 pci_read_config_byte(pdev, SIS_PMR, &pmr);
188
170 pci_write_config_dword(pdev, cfg_addr, val); 189 pci_write_config_dword(pdev, cfg_addr, val);
190
191 if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
192 pci_write_config_dword(pdev, cfg_addr+0x10, val);
171} 193}
172 194
173static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg) 195static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg)
174{ 196{
197 struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
198 u32 val,val2;
199 u8 pmr;
200
175 if (sc_reg > SCR_CONTROL) 201 if (sc_reg > SCR_CONTROL)
176 return 0xffffffffU; 202 return 0xffffffffU;
177 203
178 if (ap->flags & SIS_FLAG_CFGSCR) 204 if (ap->flags & SIS_FLAG_CFGSCR)
179 return sis_scr_cfg_read(ap, sc_reg); 205 return sis_scr_cfg_read(ap, sc_reg);
180 return inl(ap->ioaddr.scr_addr + (sc_reg * 4)); 206
207 pci_read_config_byte(pdev, SIS_PMR, &pmr);
208
209 val = inl(ap->ioaddr.scr_addr + (sc_reg * 4));
210
211 if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
212 val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
213
214 return val|val2;
181} 215}
182 216
183static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) 217static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
184{ 218{
219 struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
220 u8 pmr;
221
185 if (sc_reg > SCR_CONTROL) 222 if (sc_reg > SCR_CONTROL)
186 return; 223 return;
187 224
225 pci_read_config_byte(pdev, SIS_PMR, &pmr);
226
188 if (ap->flags & SIS_FLAG_CFGSCR) 227 if (ap->flags & SIS_FLAG_CFGSCR)
189 sis_scr_cfg_write(ap, sc_reg, val); 228 sis_scr_cfg_write(ap, sc_reg, val);
190 else 229 else {
191 outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)); 230 outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
231 if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED))
232 outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
233 }
192} 234}
193 235
194/* move to PCI layer, integrate w/ MSI stuff */ 236/* move to PCI layer, integrate w/ MSI stuff */
@@ -210,6 +252,8 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
210 u32 genctl; 252 u32 genctl;
211 struct ata_port_info *ppi; 253 struct ata_port_info *ppi;
212 int pci_dev_busy = 0; 254 int pci_dev_busy = 0;
255 u8 pmr;
256 u8 port2_start;
213 257
214 rc = pci_enable_device(pdev); 258 rc = pci_enable_device(pdev);
215 if (rc) 259 if (rc)
@@ -251,11 +295,27 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
251 probe_ent->host_flags |= SIS_FLAG_CFGSCR; 295 probe_ent->host_flags |= SIS_FLAG_CFGSCR;
252 } 296 }
253 297
298 pci_read_config_byte(pdev, SIS_PMR, &pmr);
299 if (ent->device != 0x182) {
300 if ((pmr & SIS_PMR_COMBINED) == 0) {
301 printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n");
302 port2_start=0x64;
303 }
304 else {
305 printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n");
306 port2_start=0;
307 }
308 }
309 else {
310 printk(KERN_INFO "sata_sis: Detected SiS 182 chipset\n");
311 port2_start = 0x20;
312 }
313
254 if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) { 314 if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
255 probe_ent->port[0].scr_addr = 315 probe_ent->port[0].scr_addr =
256 pci_resource_start(pdev, SIS_SCR_PCI_BAR); 316 pci_resource_start(pdev, SIS_SCR_PCI_BAR);
257 probe_ent->port[1].scr_addr = 317 probe_ent->port[1].scr_addr =
258 pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64; 318 pci_resource_start(pdev, SIS_SCR_PCI_BAR) + port2_start;
259 } 319 }
260 320
261 pci_set_master(pdev); 321 pci_set_master(pdev);