--- drivers/ata/sata_sil.c.orig	2006-11-30 06:57:37.000000000 +0900
+++ drivers/ata/sata_sil.c	2006-12-16 11:48:39.000000000 +0900
@@ -71,6 +71,7 @@
 	 * Register offsets
 	 */
 	SIL_SYSCFG		= 0x48,
+	SIL_GPIO                = 0x54,
 
 	/*
 	 * Register bits
@@ -119,6 +120,9 @@
 static irqreturn_t sil_interrupt(int irq, void *dev_instance);
 static void sil_freeze(struct ata_port *ap);
 static void sil_thaw(struct ata_port *ap);
+static void sil_bmdma_start(struct ata_queued_cmd *qc);
+static void sil_bmdma_stop(struct ata_queued_cmd *qc);
+static void sil_host_stop (struct ata_host *host);
 
 
 static const struct pci_device_id sil_pci_tbl[] = {
@@ -195,8 +199,8 @@
 	.dev_select		= ata_std_dev_select,
 	.post_set_mode		= sil_post_set_mode,
 	.bmdma_setup            = ata_bmdma_setup,
-	.bmdma_start            = ata_bmdma_start,
-	.bmdma_stop		= ata_bmdma_stop,
+	.bmdma_start            = sil_bmdma_start,
+	.bmdma_stop		= sil_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
@@ -211,7 +215,7 @@
 	.scr_write		= sil_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
-	.host_stop		= ata_pci_host_stop,
+	.host_stop		= sil_host_stop,
 };
 
 static const struct ata_port_info sil_port_info[] = {
@@ -275,6 +279,10 @@
 	/* ... port 3 */
 };
 
+struct sil_host_priv {
+	u8			use_gpio;
+};
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller");
 MODULE_LICENSE("GPL");
@@ -293,6 +301,51 @@
 	return cache_line;
 }
 
+static void sil_bmdma_start(struct ata_queued_cmd *qc)
+{
+	struct sil_host_priv* hpriv = qc->ap->host->private_data;
+	if (hpriv->use_gpio) {
+		void* mmio_base = qc->ap->host->mmio_base;
+		u32 gpio = readl(mmio_base + SIL_GPIO);
+
+		/* set the lower 8 bits to activate the LED */
+		gpio |= 0xff;
+		writel(gpio, mmio_base + SIL_GPIO);
+		readl(mmio_base + SIL_GPIO);	/* flush */
+	}
+
+	ata_bmdma_start(qc);
+}
+
+static void sil_bmdma_stop(struct ata_queued_cmd *qc)
+{
+	struct sil_host_priv* hpriv = qc->ap->host->private_data;
+
+	ata_bmdma_stop(qc);
+
+	if (hpriv->use_gpio) {
+		void* mmio_base = qc->ap->host->mmio_base;
+		u32 gpio = readl(mmio_base + SIL_GPIO);
+
+		/* set bits [15:8] to disable the LED */
+		gpio |= 0xff00;
+		writel(gpio, mmio_base + SIL_GPIO);
+		readl(mmio_base + SIL_GPIO);	/* flush */
+	}
+}
+
+static void sil_host_stop (struct ata_host *host)
+{
+	struct pdc_host_priv *hp = host->private_data;
+
+	ata_pci_host_stop(host);
+
+	if (hp) {
+		kfree(hp);
+	}
+}
+
+
 static void sil_post_set_mode (struct ata_port *ap)
 {
 	struct ata_host *host = ap->host;
@@ -614,11 +667,13 @@
 {
 	static int printed_version;
 	struct ata_probe_ent *probe_ent = NULL;
+	struct sil_host_priv *hpriv = NULL;
 	unsigned long base;
 	void __iomem *mmio_base;
 	int rc;
 	unsigned int i;
 	int pci_dev_busy = 0;
+	u32 tmp;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@@ -646,6 +701,12 @@
 		goto err_out_regions;
 	}
 
+	hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL);
+	if (hpriv == NULL) {
+		rc = -ENOMEM;
+		goto err_out_free_ent;
+	}
+
 	INIT_LIST_HEAD(&probe_ent->node);
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops;
@@ -661,10 +722,18 @@
 	mmio_base = pci_iomap(pdev, 5, 0);
 	if (mmio_base == NULL) {
 		rc = -ENOMEM;
-		goto err_out_free_ent;
+		goto err_out_free_hpriv;
 	}
 
 	probe_ent->mmio_base = mmio_base;
+	probe_ent->private_data = hpriv;
+
+ 	/* check for LED GPIO on 3112 parts */
+ 	tmp = readl(mmio_base + SIL_GPIO);
+ 	if (ent->driver_data == sil_3112 && (tmp & 0xff) == 0xff) {
+ 		dev_printk(KERN_INFO, &pdev->dev, "using GPIO for LED control\n");
+ 		hpriv->use_gpio = 1;
+ 	}
 
 	base = (unsigned long) mmio_base;
 
@@ -688,6 +757,8 @@
 
 	return 0;
 
+err_out_free_hpriv:
+	kfree(hpriv);
 err_out_free_ent:
 	kfree(probe_ent);
 err_out_regions:
