diff options
author | Tejun Heo <htejun@gmail.com> | 2005-11-18 00:16:45 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-18 13:11:39 -0500 |
commit | 69ad185fa139b8fff2442d89440e382679d51f0f (patch) | |
tree | 4ff8b81de321a10e3a4fcb3f69fb8c4855b9e241 /drivers/scsi/sata_sil24.c | |
parent | ca45160db70661a006d884df07f82c9b51d27a52 (diff) |
[PATCH] sil24: add ATAPI support
This patch implements ATAPI support for sil24 and bumps driver version
to 0.23.
Signed-off-by: Tejun Heo <htejun@gmail.com>
--
Jeff, it has been converted to use ->dev_config as pointed out.
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi/sata_sil24.c')
-rw-r--r-- | drivers/scsi/sata_sil24.c | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 59aab163bcdc..340641fa1c68 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c | |||
@@ -5,17 +5,6 @@ | |||
5 | * | 5 | * |
6 | * Based on preview driver from Silicon Image. | 6 | * Based on preview driver from Silicon Image. |
7 | * | 7 | * |
8 | * NOTE: No NCQ/ATAPI support yet. The preview driver didn't support | ||
9 | * NCQ nor ATAPI, and, unfortunately, I couldn't find out how to make | ||
10 | * those work. Enabling those shouldn't be difficult. Basic | ||
11 | * structure is all there (in libata-dev tree). If you have any | ||
12 | * information about this hardware, please contact me or linux-ide. | ||
13 | * Info is needed on... | ||
14 | * | ||
15 | * - How to issue tagged commands and turn on sactive on issue accordingly. | ||
16 | * - Where to put an ATAPI command and how to tell the device to send it. | ||
17 | * - How to enable/use 64bit. | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
20 | * under the terms of the GNU General Public License as published by the | 9 | * under the terms of the GNU General Public License as published by the |
21 | * Free Software Foundation; either version 2, or (at your option) any | 10 | * Free Software Foundation; either version 2, or (at your option) any |
@@ -42,7 +31,7 @@ | |||
42 | #include <asm/io.h> | 31 | #include <asm/io.h> |
43 | 32 | ||
44 | #define DRV_NAME "sata_sil24" | 33 | #define DRV_NAME "sata_sil24" |
45 | #define DRV_VERSION "0.22" /* Silicon Image's preview driver was 0.10 */ | 34 | #define DRV_VERSION "0.23" |
46 | 35 | ||
47 | /* | 36 | /* |
48 | * Port request block (PRB) 32 bytes | 37 | * Port request block (PRB) 32 bytes |
@@ -221,11 +210,22 @@ enum { | |||
221 | IRQ_STAT_4PORTS = 0xf, | 210 | IRQ_STAT_4PORTS = 0xf, |
222 | }; | 211 | }; |
223 | 212 | ||
224 | struct sil24_cmd_block { | 213 | struct sil24_ata_block { |
225 | struct sil24_prb prb; | 214 | struct sil24_prb prb; |
226 | struct sil24_sge sge[LIBATA_MAX_PRD]; | 215 | struct sil24_sge sge[LIBATA_MAX_PRD]; |
227 | }; | 216 | }; |
228 | 217 | ||
218 | struct sil24_atapi_block { | ||
219 | struct sil24_prb prb; | ||
220 | u8 cdb[16]; | ||
221 | struct sil24_sge sge[LIBATA_MAX_PRD - 1]; | ||
222 | }; | ||
223 | |||
224 | union sil24_cmd_block { | ||
225 | struct sil24_ata_block ata; | ||
226 | struct sil24_atapi_block atapi; | ||
227 | }; | ||
228 | |||
229 | /* | 229 | /* |
230 | * ap->private_data | 230 | * ap->private_data |
231 | * | 231 | * |
@@ -233,7 +233,7 @@ struct sil24_cmd_block { | |||
233 | * here from the previous interrupt. | 233 | * here from the previous interrupt. |
234 | */ | 234 | */ |
235 | struct sil24_port_priv { | 235 | struct sil24_port_priv { |
236 | struct sil24_cmd_block *cmd_block; /* 32 cmd blocks */ | 236 | union sil24_cmd_block *cmd_block; /* 32 cmd blocks */ |
237 | dma_addr_t cmd_block_dma; /* DMA base addr for them */ | 237 | dma_addr_t cmd_block_dma; /* DMA base addr for them */ |
238 | struct ata_taskfile tf; /* Cached taskfile registers */ | 238 | struct ata_taskfile tf; /* Cached taskfile registers */ |
239 | }; | 239 | }; |
@@ -244,6 +244,7 @@ struct sil24_host_priv { | |||
244 | void __iomem *port_base; /* port registers (4 * 8192 bytes @BAR2) */ | 244 | void __iomem *port_base; /* port registers (4 * 8192 bytes @BAR2) */ |
245 | }; | 245 | }; |
246 | 246 | ||
247 | static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev); | ||
247 | static u8 sil24_check_status(struct ata_port *ap); | 248 | static u8 sil24_check_status(struct ata_port *ap); |
248 | static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); | 249 | static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg); |
249 | static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); | 250 | static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); |
@@ -297,6 +298,8 @@ static struct scsi_host_template sil24_sht = { | |||
297 | static const struct ata_port_operations sil24_ops = { | 298 | static const struct ata_port_operations sil24_ops = { |
298 | .port_disable = ata_port_disable, | 299 | .port_disable = ata_port_disable, |
299 | 300 | ||
301 | .dev_config = sil24_dev_config, | ||
302 | |||
300 | .check_status = sil24_check_status, | 303 | .check_status = sil24_check_status, |
301 | .check_altstatus = sil24_check_status, | 304 | .check_altstatus = sil24_check_status, |
302 | .dev_select = ata_noop_dev_select, | 305 | .dev_select = ata_noop_dev_select, |
@@ -364,6 +367,16 @@ static struct ata_port_info sil24_port_info[] = { | |||
364 | }, | 367 | }, |
365 | }; | 368 | }; |
366 | 369 | ||
370 | static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev) | ||
371 | { | ||
372 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; | ||
373 | |||
374 | if (ap->cdb_len == 16) | ||
375 | writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); | ||
376 | else | ||
377 | writel(PORT_CS_CDB16, port + PORT_CTRL_CLR); | ||
378 | } | ||
379 | |||
367 | static inline void sil24_update_tf(struct ata_port *ap) | 380 | static inline void sil24_update_tf(struct ata_port *ap) |
368 | { | 381 | { |
369 | struct sil24_port_priv *pp = ap->private_data; | 382 | struct sil24_port_priv *pp = ap->private_data; |
@@ -419,7 +432,7 @@ static int sil24_issue_SRST(struct ata_port *ap) | |||
419 | { | 432 | { |
420 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; | 433 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; |
421 | struct sil24_port_priv *pp = ap->private_data; | 434 | struct sil24_port_priv *pp = ap->private_data; |
422 | struct sil24_prb *prb = &pp->cmd_block[0].prb; | 435 | struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; |
423 | dma_addr_t paddr = pp->cmd_block_dma; | 436 | dma_addr_t paddr = pp->cmd_block_dma; |
424 | u32 irq_enable, irq_stat; | 437 | u32 irq_enable, irq_stat; |
425 | int cnt; | 438 | int cnt; |
@@ -477,16 +490,11 @@ static void sil24_phy_reset(struct ata_port *ap) | |||
477 | } | 490 | } |
478 | 491 | ||
479 | ap->device->class = ata_dev_classify(&pp->tf); | 492 | ap->device->class = ata_dev_classify(&pp->tf); |
480 | |||
481 | /* No ATAPI yet */ | ||
482 | if (ap->device->class == ATA_DEV_ATAPI) | ||
483 | ap->ops->port_disable(ap); | ||
484 | } | 493 | } |
485 | 494 | ||
486 | static inline void sil24_fill_sg(struct ata_queued_cmd *qc, | 495 | static inline void sil24_fill_sg(struct ata_queued_cmd *qc, |
487 | struct sil24_cmd_block *cb) | 496 | struct sil24_sge *sge) |
488 | { | 497 | { |
489 | struct sil24_sge *sge = cb->sge; | ||
490 | struct scatterlist *sg; | 498 | struct scatterlist *sg; |
491 | unsigned int idx = 0; | 499 | unsigned int idx = 0; |
492 | 500 | ||
@@ -507,23 +515,47 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) | |||
507 | { | 515 | { |
508 | struct ata_port *ap = qc->ap; | 516 | struct ata_port *ap = qc->ap; |
509 | struct sil24_port_priv *pp = ap->private_data; | 517 | struct sil24_port_priv *pp = ap->private_data; |
510 | struct sil24_cmd_block *cb = pp->cmd_block + qc->tag; | 518 | union sil24_cmd_block *cb = pp->cmd_block + qc->tag; |
511 | struct sil24_prb *prb = &cb->prb; | 519 | struct sil24_prb *prb; |
520 | struct sil24_sge *sge; | ||
512 | 521 | ||
513 | switch (qc->tf.protocol) { | 522 | switch (qc->tf.protocol) { |
514 | case ATA_PROT_PIO: | 523 | case ATA_PROT_PIO: |
515 | case ATA_PROT_DMA: | 524 | case ATA_PROT_DMA: |
516 | case ATA_PROT_NODATA: | 525 | case ATA_PROT_NODATA: |
526 | prb = &cb->ata.prb; | ||
527 | sge = cb->ata.sge; | ||
528 | prb->ctrl = 0; | ||
517 | break; | 529 | break; |
530 | |||
531 | case ATA_PROT_ATAPI: | ||
532 | case ATA_PROT_ATAPI_DMA: | ||
533 | case ATA_PROT_ATAPI_NODATA: | ||
534 | prb = &cb->atapi.prb; | ||
535 | sge = cb->atapi.sge; | ||
536 | memset(cb->atapi.cdb, 0, 32); | ||
537 | memcpy(cb->atapi.cdb, qc->cdb, ap->cdb_len); | ||
538 | |||
539 | if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { | ||
540 | if (qc->tf.flags & ATA_TFLAG_WRITE) | ||
541 | prb->ctrl = PRB_CTRL_PACKET_WRITE; | ||
542 | else | ||
543 | prb->ctrl = PRB_CTRL_PACKET_READ; | ||
544 | } else | ||
545 | prb->ctrl = 0; | ||
546 | |||
547 | break; | ||
548 | |||
518 | default: | 549 | default: |
519 | /* ATAPI isn't supported yet */ | 550 | prb = NULL; /* shut up, gcc */ |
551 | sge = NULL; | ||
520 | BUG(); | 552 | BUG(); |
521 | } | 553 | } |
522 | 554 | ||
523 | ata_tf_to_fis(&qc->tf, prb->fis, 0); | 555 | ata_tf_to_fis(&qc->tf, prb->fis, 0); |
524 | 556 | ||
525 | if (qc->flags & ATA_QCFLAG_DMAMAP) | 557 | if (qc->flags & ATA_QCFLAG_DMAMAP) |
526 | sil24_fill_sg(qc, cb); | 558 | sil24_fill_sg(qc, sge); |
527 | } | 559 | } |
528 | 560 | ||
529 | static int sil24_qc_issue(struct ata_queued_cmd *qc) | 561 | static int sil24_qc_issue(struct ata_queued_cmd *qc) |
@@ -750,7 +782,7 @@ static int sil24_port_start(struct ata_port *ap) | |||
750 | { | 782 | { |
751 | struct device *dev = ap->host_set->dev; | 783 | struct device *dev = ap->host_set->dev; |
752 | struct sil24_port_priv *pp; | 784 | struct sil24_port_priv *pp; |
753 | struct sil24_cmd_block *cb; | 785 | union sil24_cmd_block *cb; |
754 | size_t cb_size = sizeof(*cb); | 786 | size_t cb_size = sizeof(*cb); |
755 | dma_addr_t cb_dma; | 787 | dma_addr_t cb_dma; |
756 | int rc = -ENOMEM; | 788 | int rc = -ENOMEM; |