diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/sata_via.c | 108 |
1 files changed, 102 insertions, 6 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 038d49d0f2ab..e95acfac30b9 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c | |||
@@ -59,11 +59,14 @@ enum { | |||
59 | SATA_INT_GATE = 0x41, /* SATA interrupt gating */ | 59 | SATA_INT_GATE = 0x41, /* SATA interrupt gating */ |
60 | SATA_NATIVE_MODE = 0x42, /* Native mode enable */ | 60 | SATA_NATIVE_MODE = 0x42, /* Native mode enable */ |
61 | SATA_PATA_SHARING = 0x49, /* PATA/SATA sharing func ctrl */ | 61 | SATA_PATA_SHARING = 0x49, /* PATA/SATA sharing func ctrl */ |
62 | 62 | PATA_UDMA_TIMING = 0xB3, /* PATA timing for DMA/ cable detect */ | |
63 | PATA_PIO_TIMING = 0xAB, /* PATA timing register */ | ||
64 | |||
63 | PORT0 = (1 << 1), | 65 | PORT0 = (1 << 1), |
64 | PORT1 = (1 << 0), | 66 | PORT1 = (1 << 0), |
65 | ALL_PORTS = PORT0 | PORT1, | 67 | ALL_PORTS = PORT0 | PORT1, |
66 | N_PORTS = 2, | 68 | PATA_PORT = 2, /* PATA is port 2 */ |
69 | N_PORTS = 3, | ||
67 | 70 | ||
68 | NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), | 71 | NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), |
69 | 72 | ||
@@ -76,6 +79,11 @@ static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg); | |||
76 | static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); | 79 | static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); |
77 | static void svia_noop_freeze(struct ata_port *ap); | 80 | static void svia_noop_freeze(struct ata_port *ap); |
78 | static void vt6420_error_handler(struct ata_port *ap); | 81 | static void vt6420_error_handler(struct ata_port *ap); |
82 | static void vt6421_sata_error_handler(struct ata_port *ap); | ||
83 | static void vt6421_pata_error_handler(struct ata_port *ap); | ||
84 | static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev); | ||
85 | static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); | ||
86 | static int vt6421_port_start(struct ata_port *ap); | ||
79 | 87 | ||
80 | static const struct pci_device_id svia_pci_tbl[] = { | 88 | static const struct pci_device_id svia_pci_tbl[] = { |
81 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, | 89 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, |
@@ -142,9 +150,43 @@ static const struct ata_port_operations vt6420_sata_ops = { | |||
142 | .host_stop = ata_host_stop, | 150 | .host_stop = ata_host_stop, |
143 | }; | 151 | }; |
144 | 152 | ||
145 | static const struct ata_port_operations vt6421_sata_ops = { | 153 | static const struct ata_port_operations vt6421_pata_ops = { |
146 | .port_disable = ata_port_disable, | 154 | .port_disable = ata_port_disable, |
155 | |||
156 | .set_piomode = vt6421_set_pio_mode, | ||
157 | .set_dmamode = vt6421_set_dma_mode, | ||
158 | |||
159 | .tf_load = ata_tf_load, | ||
160 | .tf_read = ata_tf_read, | ||
161 | .check_status = ata_check_status, | ||
162 | .exec_command = ata_exec_command, | ||
163 | .dev_select = ata_std_dev_select, | ||
164 | |||
165 | .bmdma_setup = ata_bmdma_setup, | ||
166 | .bmdma_start = ata_bmdma_start, | ||
167 | .bmdma_stop = ata_bmdma_stop, | ||
168 | .bmdma_status = ata_bmdma_status, | ||
169 | |||
170 | .qc_prep = ata_qc_prep, | ||
171 | .qc_issue = ata_qc_issue_prot, | ||
172 | .data_xfer = ata_pio_data_xfer, | ||
173 | |||
174 | .freeze = ata_bmdma_freeze, | ||
175 | .thaw = ata_bmdma_thaw, | ||
176 | .error_handler = vt6421_pata_error_handler, | ||
177 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
147 | 178 | ||
179 | .irq_handler = ata_interrupt, | ||
180 | .irq_clear = ata_bmdma_irq_clear, | ||
181 | |||
182 | .port_start = vt6421_port_start, | ||
183 | .port_stop = ata_port_stop, | ||
184 | .host_stop = ata_host_stop, | ||
185 | }; | ||
186 | |||
187 | static const struct ata_port_operations vt6421_sata_ops = { | ||
188 | .port_disable = ata_port_disable, | ||
189 | |||
148 | .tf_load = ata_tf_load, | 190 | .tf_load = ata_tf_load, |
149 | .tf_read = ata_tf_read, | 191 | .tf_read = ata_tf_read, |
150 | .check_status = ata_check_status, | 192 | .check_status = ata_check_status, |
@@ -162,7 +204,7 @@ static const struct ata_port_operations vt6421_sata_ops = { | |||
162 | 204 | ||
163 | .freeze = ata_bmdma_freeze, | 205 | .freeze = ata_bmdma_freeze, |
164 | .thaw = ata_bmdma_thaw, | 206 | .thaw = ata_bmdma_thaw, |
165 | .error_handler = ata_bmdma_error_handler, | 207 | .error_handler = vt6421_sata_error_handler, |
166 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 208 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
167 | 209 | ||
168 | .irq_handler = ata_interrupt, | 210 | .irq_handler = ata_interrupt, |
@@ -171,7 +213,7 @@ static const struct ata_port_operations vt6421_sata_ops = { | |||
171 | .scr_read = svia_scr_read, | 213 | .scr_read = svia_scr_read, |
172 | .scr_write = svia_scr_write, | 214 | .scr_write = svia_scr_write, |
173 | 215 | ||
174 | .port_start = ata_port_start, | 216 | .port_start = vt6421_port_start, |
175 | .port_stop = ata_port_stop, | 217 | .port_stop = ata_port_stop, |
176 | .host_stop = ata_host_stop, | 218 | .host_stop = ata_host_stop, |
177 | }; | 219 | }; |
@@ -289,6 +331,61 @@ static void vt6420_error_handler(struct ata_port *ap) | |||
289 | NULL, ata_std_postreset); | 331 | NULL, ata_std_postreset); |
290 | } | 332 | } |
291 | 333 | ||
334 | static int vt6421_pata_prereset(struct ata_port *ap) | ||
335 | { | ||
336 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
337 | u8 tmp; | ||
338 | |||
339 | pci_read_config_byte(pdev, PATA_UDMA_TIMING, &tmp); | ||
340 | if (tmp & 0x10) | ||
341 | ap->cbl = ATA_CBL_PATA40; | ||
342 | else | ||
343 | ap->cbl = ATA_CBL_PATA80; | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static void vt6421_pata_error_handler(struct ata_port *ap) | ||
348 | { | ||
349 | return ata_bmdma_drive_eh(ap, vt6421_pata_prereset, ata_std_softreset, | ||
350 | NULL, ata_std_postreset); | ||
351 | } | ||
352 | |||
353 | static int vt6421_sata_prereset(struct ata_port *ap) | ||
354 | { | ||
355 | ap->cbl = ATA_CBL_SATA; | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static void vt6421_sata_error_handler(struct ata_port *ap) | ||
360 | { | ||
361 | return ata_bmdma_drive_eh(ap, vt6421_sata_prereset, ata_std_softreset, | ||
362 | NULL, ata_std_postreset); | ||
363 | } | ||
364 | |||
365 | static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev) | ||
366 | { | ||
367 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
368 | static const u8 pio_bits[] = { 0xA8, 0x65, 0x65, 0x31, 0x20 }; | ||
369 | pci_write_config_byte(pdev, PATA_PIO_TIMING, pio_bits[adev->pio_mode - XFER_PIO_0]); | ||
370 | } | ||
371 | |||
372 | static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev) | ||
373 | { | ||
374 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | ||
375 | static const u8 udma_bits[] = { 0xEE, 0xE8, 0xE6, 0xE4, 0xE2, 0xE1, 0xE0, 0xE0 }; | ||
376 | pci_write_config_byte(pdev, PATA_UDMA_TIMING, udma_bits[adev->pio_mode - XFER_UDMA_0]); | ||
377 | } | ||
378 | |||
379 | static int vt6421_port_start(struct ata_port *ap) | ||
380 | { | ||
381 | if (ap->port_no == PATA_PORT) { | ||
382 | ap->ops = &vt6421_pata_ops; | ||
383 | ap->mwdma_mask = 0; | ||
384 | ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST; | ||
385 | } | ||
386 | return ata_port_start(ap); | ||
387 | } | ||
388 | |||
292 | static const unsigned int svia_bar_sizes[] = { | 389 | static const unsigned int svia_bar_sizes[] = { |
293 | 8, 4, 8, 4, 16, 256 | 390 | 8, 4, 8, 4, 16, 256 |
294 | }; | 391 | }; |
@@ -511,4 +608,3 @@ static void __exit svia_exit(void) | |||
511 | 608 | ||
512 | module_init(svia_init); | 609 | module_init(svia_init); |
513 | module_exit(svia_exit); | 610 | module_exit(svia_exit); |
514 | |||