diff options
| author | JosephChan@via.com.tw <JosephChan@via.com.tw> | 2008-07-30 15:32:48 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2008-07-31 01:39:31 -0400 |
| commit | bfce5e0179ad059035df28558724ff60af708e09 (patch) | |
| tree | 0b00598e38e57559f48983ee22039e589278fbcb /drivers/ata | |
| parent | e8389f0c44652ee63d95bc0a7f8d565ac25dac77 (diff) | |
pata_via: add VX800 flag; add function for fixing h/w bugs
Add flag VIA_SATA_PATA for vx800, VX800 uses the same
chipset(0x0581/0x5324) as CX700, which has 1 PATA channel(Master/Slave)
and 1 SATA channel(Master/Slave) Add function <via_ata_tf_load>. This is
to fix the internal bug of VIA chipsets, which will reset the device
register after changing the IEN bit in CTL register
Signed-off-by: Joseph Chan <josephchan@via.com.tw>
Cc: Tejun Heo <tj@kernel.org>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
| -rw-r--r-- | drivers/ata/pata_via.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 708ed144ede9..57d951b11f2d 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c | |||
| @@ -98,7 +98,8 @@ static const struct via_isa_bridge { | |||
| 98 | u8 rev_max; | 98 | u8 rev_max; |
| 99 | u16 flags; | 99 | u16 flags; |
| 100 | } via_isa_bridges[] = { | 100 | } via_isa_bridges[] = { |
| 101 | { "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 101 | { "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, VIA_UDMA_133 | |
| 102 | VIA_BAD_AST | VIA_SATA_PATA }, | ||
| 102 | { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 103 | { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, |
| 103 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, | 104 | { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, |
| 104 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA }, | 105 | { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA }, |
| @@ -322,6 +323,65 @@ static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev) | |||
| 322 | via_do_set_mode(ap, adev, adev->dma_mode, tclock[mode], set_ast, udma[mode]); | 323 | via_do_set_mode(ap, adev, adev->dma_mode, tclock[mode], set_ast, udma[mode]); |
| 323 | } | 324 | } |
| 324 | 325 | ||
| 326 | /** | ||
| 327 | * via_ata_sff_tf_load - send taskfile registers to host controller | ||
| 328 | * @ap: Port to which output is sent | ||
| 329 | * @tf: ATA taskfile register set | ||
| 330 | * | ||
| 331 | * Outputs ATA taskfile to standard ATA host controller. | ||
| 332 | * | ||
| 333 | * Note: This is to fix the internal bug of via chipsets, which | ||
| 334 | * will reset the device register after changing the IEN bit on | ||
| 335 | * ctl register | ||
| 336 | */ | ||
| 337 | static void via_ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) | ||
| 338 | { | ||
| 339 | struct ata_ioports *ioaddr = &ap->ioaddr; | ||
| 340 | unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; | ||
| 341 | |||
| 342 | if (tf->ctl != ap->last_ctl) { | ||
| 343 | iowrite8(tf->ctl, ioaddr->ctl_addr); | ||
| 344 | iowrite8(tf->device, ioaddr->device_addr); | ||
| 345 | ap->last_ctl = tf->ctl; | ||
| 346 | ata_wait_idle(ap); | ||
| 347 | } | ||
| 348 | |||
| 349 | if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { | ||
| 350 | iowrite8(tf->hob_feature, ioaddr->feature_addr); | ||
| 351 | iowrite8(tf->hob_nsect, ioaddr->nsect_addr); | ||
| 352 | iowrite8(tf->hob_lbal, ioaddr->lbal_addr); | ||
| 353 | iowrite8(tf->hob_lbam, ioaddr->lbam_addr); | ||
| 354 | iowrite8(tf->hob_lbah, ioaddr->lbah_addr); | ||
| 355 | VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", | ||
| 356 | tf->hob_feature, | ||
| 357 | tf->hob_nsect, | ||
| 358 | tf->hob_lbal, | ||
| 359 | tf->hob_lbam, | ||
| 360 | tf->hob_lbah); | ||
| 361 | } | ||
| 362 | |||
| 363 | if (is_addr) { | ||
| 364 | iowrite8(tf->feature, ioaddr->feature_addr); | ||
| 365 | iowrite8(tf->nsect, ioaddr->nsect_addr); | ||
| 366 | iowrite8(tf->lbal, ioaddr->lbal_addr); | ||
| 367 | iowrite8(tf->lbam, ioaddr->lbam_addr); | ||
| 368 | iowrite8(tf->lbah, ioaddr->lbah_addr); | ||
| 369 | VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", | ||
| 370 | tf->feature, | ||
| 371 | tf->nsect, | ||
| 372 | tf->lbal, | ||
| 373 | tf->lbam, | ||
| 374 | tf->lbah); | ||
| 375 | } | ||
| 376 | |||
| 377 | if (tf->flags & ATA_TFLAG_DEVICE) { | ||
| 378 | iowrite8(tf->device, ioaddr->device_addr); | ||
| 379 | VPRINTK("device 0x%X\n", tf->device); | ||
| 380 | } | ||
| 381 | |||
| 382 | ata_wait_idle(ap); | ||
| 383 | } | ||
| 384 | |||
| 325 | static struct scsi_host_template via_sht = { | 385 | static struct scsi_host_template via_sht = { |
| 326 | ATA_BMDMA_SHT(DRV_NAME), | 386 | ATA_BMDMA_SHT(DRV_NAME), |
| 327 | }; | 387 | }; |
| @@ -332,11 +392,13 @@ static struct ata_port_operations via_port_ops = { | |||
| 332 | .set_piomode = via_set_piomode, | 392 | .set_piomode = via_set_piomode, |
| 333 | .set_dmamode = via_set_dmamode, | 393 | .set_dmamode = via_set_dmamode, |
| 334 | .prereset = via_pre_reset, | 394 | .prereset = via_pre_reset, |
| 395 | .sff_tf_load = via_ata_tf_load, | ||
| 335 | }; | 396 | }; |
| 336 | 397 | ||
| 337 | static struct ata_port_operations via_port_ops_noirq = { | 398 | static struct ata_port_operations via_port_ops_noirq = { |
| 338 | .inherits = &via_port_ops, | 399 | .inherits = &via_port_ops, |
| 339 | .sff_data_xfer = ata_sff_data_xfer_noirq, | 400 | .sff_data_xfer = ata_sff_data_xfer_noirq, |
| 401 | .sff_tf_load = via_ata_tf_load, | ||
| 340 | }; | 402 | }; |
| 341 | 403 | ||
| 342 | /** | 404 | /** |
