aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sata_sil24.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2005-10-05 22:43:39 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-06 05:51:24 -0400
commit6a575fa969beeddd0859f9e9d26ab16c6a0d8d6a (patch)
tree1472f5274023ca59eaff611e485ba6db2d0052bd /drivers/scsi/sata_sil24.c
parent46b93e7bce80a08ea07e250d03b0b596cbd32595 (diff)
[PATCH] sil24: implement proper TF register reading & caching
03_sil24_add-tf-reading.patch This patch implements proper TF register reading back and caching and bumps up version to 0.22. This is taken from Edward's driver. Signed-off-by: Tejun Heo <htejun@gmail.com> sata_sil24.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi/sata_sil24.c')
-rw-r--r--drivers/scsi/sata_sil24.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 032d9c093979..b65194c755f8 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -41,7 +41,7 @@
41#include <asm/io.h> 41#include <asm/io.h>
42 42
43#define DRV_NAME "sata_sil24" 43#define DRV_NAME "sata_sil24"
44#define DRV_VERSION "0.21" /* Silicon Image's preview driver was 0.10 */ 44#define DRV_VERSION "0.22" /* Silicon Image's preview driver was 0.10 */
45 45
46#define NR_PORTS 4 46#define NR_PORTS 4
47 47
@@ -216,6 +216,7 @@ struct sil24_cmd_block {
216struct sil24_port_priv { 216struct sil24_port_priv {
217 struct sil24_cmd_block *cmd_block; /* 32 cmd blocks */ 217 struct sil24_cmd_block *cmd_block; /* 32 cmd blocks */
218 dma_addr_t cmd_block_dma; /* DMA base addr for them */ 218 dma_addr_t cmd_block_dma; /* DMA base addr for them */
219 struct ata_taskfile tf; /* Cached taskfile registers */
219}; 220};
220 221
221/* ap->host_set->private_data */ 222/* ap->host_set->private_data */
@@ -322,14 +323,25 @@ static struct ata_port_info sil24_port_info[] = {
322 }, 323 },
323}; 324};
324 325
326static inline void sil24_update_tf(struct ata_port *ap)
327{
328 struct sil24_port_priv *pp = ap->private_data;
329 void *port = (void *)ap->ioaddr.cmd_addr;
330 struct sil24_prb *prb = port;
331
332 ata_tf_from_fis(prb->fis, &pp->tf);
333}
334
325static u8 sil24_check_status(struct ata_port *ap) 335static u8 sil24_check_status(struct ata_port *ap)
326{ 336{
327 return ATA_DRDY; 337 struct sil24_port_priv *pp = ap->private_data;
338 return pp->tf.command;
328} 339}
329 340
330static u8 sil24_check_err(struct ata_port *ap) 341static u8 sil24_check_err(struct ata_port *ap)
331{ 342{
332 return 0; 343 struct sil24_port_priv *pp = ap->private_data;
344 return pp->tf.feature;
333} 345}
334 346
335static int sil24_scr_map[] = { 347static int sil24_scr_map[] = {
@@ -485,6 +497,7 @@ static void sil24_eng_timeout(struct ata_port *ap)
485static void sil24_error_intr(struct ata_port *ap, u32 slot_stat) 497static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
486{ 498{
487 struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); 499 struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
500 struct sil24_port_priv *pp = ap->private_data;
488 void *port = (void *)ap->ioaddr.cmd_addr; 501 void *port = (void *)ap->ioaddr.cmd_addr;
489 u32 irq_stat, cmd_err, sstatus, serror; 502 u32 irq_stat, cmd_err, sstatus, serror;
490 503
@@ -509,8 +522,22 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
509 " stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n", 522 " stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
510 ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror); 523 ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
511 524
525 if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
526 /*
527 * Device is reporting error, tf registers are valid.
528 */
529 sil24_update_tf(ap);
530 } else {
531 /*
532 * Other errors. libata currently doesn't have any
533 * mechanism to report these errors. Just turn on
534 * ATA_ERR.
535 */
536 pp->tf.command = ATA_ERR;
537 }
538
512 if (qc) 539 if (qc)
513 ata_qc_complete(qc, ATA_ERR); 540 ata_qc_complete(qc, pp->tf.command);
514 541
515 sil24_reset_controller(ap); 542 sil24_reset_controller(ap);
516} 543}
@@ -523,8 +550,19 @@ static inline void sil24_host_intr(struct ata_port *ap)
523 550
524 slot_stat = readl(port + PORT_SLOT_STAT); 551 slot_stat = readl(port + PORT_SLOT_STAT);
525 if (!(slot_stat & HOST_SSTAT_ATTN)) { 552 if (!(slot_stat & HOST_SSTAT_ATTN)) {
553 struct sil24_port_priv *pp = ap->private_data;
554 /*
555 * !HOST_SSAT_ATTN guarantees successful completion,
556 * so reading back tf registers is unnecessary for
557 * most commands. TODO: read tf registers for
558 * commands which require these values on successful
559 * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
560 * DEVICE RESET and READ PORT MULTIPLIER (any more?).
561 */
562 sil24_update_tf(ap);
563
526 if (qc) 564 if (qc)
527 ata_qc_complete(qc, 0); 565 ata_qc_complete(qc, pp->tf.command);
528 } else 566 } else
529 sil24_error_intr(ap, slot_stat); 567 sil24_error_intr(ap, slot_stat);
530} 568}
@@ -579,6 +617,8 @@ static int sil24_port_start(struct ata_port *ap)
579 return -ENOMEM; 617 return -ENOMEM;
580 memset(pp, 0, sizeof(*pp)); 618 memset(pp, 0, sizeof(*pp));
581 619
620 pp->tf.command = ATA_DRDY;
621
582 cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL); 622 cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
583 if (!cb) { 623 if (!cb) {
584 kfree(pp); 624 kfree(pp);