[WATCHDOG] davinci: convert to ioremap() + io[read|write]
[safe/jmp/linux-2.6] / drivers / ata / sata_inic162x.c
index 8c1f06a..fbbd87c 100644 (file)
  * right.  Documentation is available at initio's website but it only
  * documents registers (not programming model).
  *
- * - ATA disks work.
- * - Hotplug works.
- * - ATAPI read works but burning doesn't.  This thing is really
- *   peculiar about ATAPI and I couldn't figure out how ATAPI PIO and
- *   ATAPI DMA WRITE should be programmed.  If you've got a clue, be
- *   my guest.
- * - Both STR and STD work.
+ * This driver has interesting history.  The first version was written
+ * from the documentation and a 2.4 IDE driver posted on a Taiwan
+ * company, which didn't use any IDMA features and couldn't handle
+ * LBA48.  The resulting driver couldn't handle LBA48 devices either
+ * making it pretty useless.
+ *
+ * After a while, initio picked the driver up, renamed it to
+ * sata_initio162x, updated it to use IDMA for ATA DMA commands and
+ * posted it on their website.  It only used ATA_PROT_DMA for IDMA and
+ * attaching both devices and issuing IDMA and !IDMA commands
+ * simultaneously broke it due to PIRQ masking interaction but it did
+ * show how to use the IDMA (ADMA + some initio specific twists)
+ * engine.
+ *
+ * Then, I picked up their changes again and here's the usable driver
+ * which uses IDMA for everything.  Everything works now including
+ * LBA48, CD/DVD burning, suspend/resume and hotplug.  There are some
+ * issues tho.  Result Tf is not resported properly, NCQ isn't
+ * supported yet and CD/DVD writing works with DMA assisted PIO
+ * protocol (which, for native SATA devices, shouldn't cause any
+ * noticeable difference).
+ *
+ * Anyways, so, here's finally a working driver for inic162x.  Enjoy!
+ *
+ * initio: If you guys wanna improve the driver regarding result TF
+ * access and other stuff, please feel free to contact me.  I'll be
+ * happy to assist.
  */
 
 #include <linux/kernel.h>
@@ -28,7 +48,7 @@
 #include <scsi/scsi_device.h>
 
 #define DRV_NAME       "sata_inic162x"
-#define DRV_VERSION    "0.3"
+#define DRV_VERSION    "0.4"
 
 enum {
        MMIO_BAR_PCI            = 5,
@@ -76,6 +96,7 @@ enum {
        PORT_SCR                = 0x20,
 
        /* HOST_CTL bits */
+       HCTL_LEDEN              = (1 << 3),  /* enable LED operation */
        HCTL_IRQOFF             = (1 << 8),  /* global IRQ off */
        HCTL_FTHD0              = (1 << 10), /* fifo threshold 0 */
        HCTL_FTHD1              = (1 << 11), /* fifo threshold 1*/
@@ -248,9 +269,9 @@ static void inic_reset_port(void __iomem *port_base)
        writeb(0xff, port_base + PORT_IRQ_STAT);
 }
 
-static int inic_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
+static int inic_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
 {
-       void __iomem *scr_addr = inic_port_base(ap) + PORT_SCR;
+       void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
        void __iomem *addr;
 
        if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
@@ -265,9 +286,9 @@ static int inic_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
        return 0;
 }
 
-static int inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+static int inic_scr_write(struct ata_link *link, unsigned sc_reg, u32 val)
 {
-       void __iomem *scr_addr = inic_port_base(ap) + PORT_SCR;
+       void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR;
 
        if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
                return -EINVAL;
@@ -520,7 +541,7 @@ static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
        void __iomem *port_base = inic_port_base(ap);
 
        /* fire up the ADMA engine */
-       writew(HCTL_FTHD0, port_base + HOST_CTL);
+       writew(HCTL_FTHD0 | HCTL_LEDEN, port_base + HOST_CTL);
        writew(IDMA_CTL_GO, port_base + PORT_IDMA_CTL);
        writeb(0, port_base + PORT_CPB_PTQFIFO);