Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Jan 2006 00:39:03 +0100
From:      =?ISO-8859-1?Q?S=F8ren_Schmidt?= <sos@FreeBSD.org>
To:        current@FreeBSD.org
Subject:   PATCH: DMA enabled dump for ATA please test
Message-ID:  <43C59717.7000203@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------020809040703060107040900
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit


Evening!

Originally I wanted to finally add dump functionality to ata-raid, but 
quickly discovered that it would be a pain todo the old way.
So I decided to reuse strategy for dumping by implementing polled mode 
in ATA, and have dump simply call strategy.
(This could be generalised for all drivers, and would make driver 
writing easier).
Now this also gave me the chance to use DMA on dumps, and that does do 
wonders for dump speed.
There is a few chipsets (ICH6+7 in AHCI mode and Marvell) that wont do 
dumps yet not even PIO but they didn't work before either.

Anyhow this needs a bit testing on various HW out there before it hits 
the tree, so please give it a go and let me know...

-Søren

--------------020809040703060107040900
Content-Type: text/plain;
 name="dmadump-p1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="dmadump-p1"

Index: ata-all.c
===================================================================
RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-all.c,v
retrieving revision 1.261
diff -u -r1.261 ata-all.c
--- ata-all.c	5 Jan 2006 21:27:18 -0000	1.261
+++ ata-all.c	11 Jan 2006 23:00:53 -0000
@@ -63,7 +63,6 @@
 };
 
 /* prototypes */
-static void ata_interrupt(void *);
 static void ata_boot_attach(void);
 static device_t ata_add_child(device_t, struct ata_device *, int);
 static int ata_getparam(struct ata_device *, int);
@@ -139,7 +138,7 @@
 	return ENXIO;
     }
     if ((error = bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS,
-				ata_interrupt, ch, &ch->ih))) {
+				(driver_intr_t *)ata_interrupt, ch, &ch->ih))) {
 	device_printf(dev, "unable to setup interrupt\n");
 	return error;
     }
@@ -317,7 +316,7 @@
     return error;
 }
 
-static void
+int
 ata_interrupt(void *data)
 {
     struct ata_channel *ch = (struct ata_channel *)data;
@@ -325,20 +324,17 @@
 
     mtx_lock(&ch->state_mtx);
     do {
+	/* ignore interrupt if its not for us */
+	if (ch->hw.status && !ch->hw.status(ch->dev))
+	    break;
+
 	/* do we have a running request */
 	if (!(request = ch->running))
 	    break;
 
 	ATA_DEBUG_RQ(request, "interrupt");
 
-	/* ignore interrupt if device is busy */
-	if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) {
-	    DELAY(100);
-	    if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY)
-		break;
-	}
-
-	/* check for the right state */
+	/* safetycheck for the right state */
 	if (ch->state != ATA_ACTIVE && ch->state != ATA_STALL_QUEUE) {
 	    device_printf(request->dev, "interrupt on idle channel ignored\n");
 	    break;
@@ -355,10 +351,11 @@
 	    mtx_unlock(&ch->state_mtx);
 	    ATA_LOCKING(ch->dev, ATA_LF_UNLOCK);
 	    ata_finish(request);
-	    return;
+	    return 1;
 	}
     } while (0);
     mtx_unlock(&ch->state_mtx);
+    return 0;
 }
 
 /*
Index: ata-all.h
===================================================================
RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-all.h,v
retrieving revision 1.110
diff -u -r1.110 ata-all.h
--- ata-all.h	5 Jan 2006 21:27:19 -0000	1.110
+++ ata-all.h	11 Jan 2006 23:00:53 -0000
@@ -470,6 +470,7 @@
 
 /* structure holding lowlevel functions */
 struct ata_lowlevel {
+    int (*status)(device_t dev);
     int (*begin_transaction)(struct ata_request *request);
     int (*end_transaction)(struct ata_request *request);
     int (*command)(struct ata_request *request);
@@ -495,6 +496,7 @@
 #define         ATA_USE_16BIT           0x02
 #define         ATA_ATAPI_DMA_RO        0x04
 #define         ATA_NO_48BIT_DMA        0x08
+#define		ATA_ALWAYS_DMASTAT	0x10
 
     int                         devices;        /* what is present */
 #define         ATA_ATA_MASTER          0x01
@@ -534,6 +536,7 @@
 int ata_reinit(device_t dev);
 int ata_suspend(device_t dev);
 int ata_resume(device_t dev);
+int ata_interrupt(void *data);
 int ata_device_ioctl(device_t dev, u_long cmd, caddr_t data);
 int ata_identify(device_t dev);
 void ata_default_registers(device_t dev);
Index: ata-chipset.c
===================================================================
RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-chipset.c,v
retrieving revision 1.149
diff -u -r1.149 ata-chipset.c
--- ata-chipset.c	5 Jan 2006 21:27:19 -0000	1.149
+++ ata-chipset.c	11 Jan 2006 23:00:53 -0000
@@ -82,15 +82,15 @@
 static int ata_cypress_chipinit(device_t dev);
 static void ata_cypress_setmode(device_t dev, int mode);
 static int ata_highpoint_chipinit(device_t dev);
-static void ata_highpoint_intr(void *data);
+static int ata_highpoint_allocate(device_t dev);
 static void ata_highpoint_setmode(device_t dev, int mode);
 static int ata_highpoint_check_80pin(device_t dev, int mode);
 static int ata_intel_chipinit(device_t dev);
+static int ata_intel_allocate(device_t dev);
 static int ata_intel_31244_allocate(device_t dev);
 static void ata_intel_31244_intr(void *data);
 static void ata_intel_31244_reset(device_t dev);
 static int ata_intel_31244_command(struct ata_request *request);
-static void ata_intel_intr(void *data);
 static void ata_intel_reset(device_t dev);
 static void ata_intel_old_setmode(device_t dev, int mode);
 static void ata_intel_new_setmode(device_t dev, int mode);
@@ -132,7 +132,6 @@
 static int ata_sii_allocate(device_t dev);
 static void ata_sii_intr(void *data);
 static void ata_cmd_intr(void *data);
-static void ata_cmd_old_intr(void *data);
 static void ata_sii_reset(device_t dev);
 static void ata_sii_setmode(device_t dev, int mode);
 static void ata_cmd_setmode(device_t dev, int mode);
@@ -184,18 +183,8 @@
     int unit;
 
     for (unit = 0; unit < ctlr->channels; unit++) {
-	if (!(ch = ctlr->interrupt[unit].argument))
-	    continue;
-	if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
-	    int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-	    if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
-		ATA_BMSTAT_INTERRUPT)
-		continue;
-	    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-	    DELAY(1);
-	}
-	ctlr->interrupt[unit].function(ch);
+	if ((ch = ctlr->interrupt[unit].argument))
+	    ctlr->interrupt[unit].function(ch);
     }
 }
 
@@ -748,18 +737,6 @@
 	if (ctlr->chip->cfg1 == ATPOLD &&
 	    ATA_LOCKING(ch->dev, ATA_LF_WHICH) != unit)
 	    continue;
-	if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
-	    int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-	    if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
-		ATA_BMSTAT_INTERRUPT)
-		continue;
-	    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-	    DELAY(1);
-	    ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
-			 ATA_IDX_INB(ch, ATA_BMCMD_PORT)&~ATA_BMCMD_START_STOP);
-	    DELAY(1);
-	}
 	ctlr->interrupt[unit].function(ch);
     }
 }
@@ -903,8 +880,8 @@
 	    device_printf(dev,
 			  "using PIO transfers above 137GB as workaround for "
 			  "48bit DMA access bug, expect reduced performance\n");
-	ctlr->reset = ata_ali_reset;
 	ctlr->allocate = ata_ali_allocate;
+	ctlr->reset = ata_ali_reset;
 	ctlr->setmode = ata_ali_setmode;
 	break;
 
@@ -973,7 +950,7 @@
     ch->flags |= ATA_NO_SLAVE;
 
     /* XXX SOS PHY handling awkward in ALI chip not supported yet */
-    ata_generic_hw(dev);
+    ata_pci_hw(dev);
     return 0;
 }
 
@@ -1407,18 +1384,9 @@
 ata_highpoint_chipinit(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(dev);
-    int rid = ATA_IRQ_RID;
 
-    if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-					       RF_SHAREABLE | RF_ACTIVE))) {
-	device_printf(dev, "unable to map interrupt\n");
-	return ENXIO;
-    }
-    if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
-			ata_highpoint_intr, ctlr, &ctlr->handle))) {
-	device_printf(dev, "unable to setup interrupt\n");
+    if (ata_setup_interrupt(dev))
 	return ENXIO;
-    }
 
     if (ctlr->chip->cfg2 == HPTOLD) {
 	/* disable interrupt prediction */
@@ -1439,31 +1407,22 @@
 	    pci_write_config(dev, 0x5b,
 			     (pci_read_config(dev, 0x5b, 1) & 0x01) | 0x20, 1);
     }
+    ctlr->allocate = ata_highpoint_allocate;
     ctlr->setmode = ata_highpoint_setmode;
     return 0;
 }
 
-static void
-ata_highpoint_intr(void *data)
+static int
+ata_highpoint_allocate(device_t dev)
 {
-    struct ata_pci_controller *ctlr = data;
-    struct ata_channel *ch;
-    int unit;
+    struct ata_channel *ch = device_get_softc(dev);
 
-    for (unit = 0; unit < ctlr->channels; unit++) {
-	if (!(ch = ctlr->interrupt[unit].argument))
-	    continue;
-	if (ch->dma) {
-	    int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
+    /* setup the usual register normal pci style */
+    if (ata_pci_allocate(dev))
+	return ENXIO;
 
-	    if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
-		ATA_BMSTAT_INTERRUPT)
-		continue;
-	    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-	    DELAY(1);
-	}
-	ctlr->interrupt[unit].function(ch);
-    }
+    ch->flags |= ATA_ALWAYS_DMASTAT;
+    return 0;
 }
 
 static void
@@ -1603,20 +1562,9 @@
 ata_intel_chipinit(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(dev);
-    int rid = ATA_IRQ_RID;
 
-    if (!ata_legacy(dev)) {
-	if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-						   RF_SHAREABLE | RF_ACTIVE))) {
-	    device_printf(dev, "unable to map interrupt\n");
-	    return ENXIO;
-	}
-	if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
-			    ata_intel_intr, ctlr, &ctlr->handle))) {
-	    device_printf(dev, "unable to setup interrupt\n");
-	    return ENXIO;
-	}
-    }
+    if (ata_setup_interrupt(dev))
+	return ENXIO;
 
     /* good old PIIX needs special treatment (not implemented) */
     if (ctlr->chip->chipid == ATA_I82371FB) {
@@ -1640,14 +1588,15 @@
 	        return ENXIO;
 	    }
 	    ctlr->channels = 4;
-	    ctlr->reset = ata_intel_31244_reset;
 	    ctlr->allocate = ata_intel_31244_allocate;
+	    ctlr->reset = ata_intel_31244_reset;
 	}
 	ctlr->setmode = ata_sata_setmode;
     }
 
     /* non SATA intel chips goes here */
     else if (ctlr->chip->max_dma < ATA_SA150) {
+	ctlr->allocate = ata_intel_allocate;
 	ctlr->setmode = ata_intel_new_setmode;
     }
 
@@ -1656,6 +1605,7 @@
 	/* force all ports active "the legacy way" */
 	pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f,2);
 
+	ctlr->allocate = ata_intel_allocate;
 	ctlr->reset = ata_intel_reset;
 
 	/* if we have AHCI capability and BAR(5) as a memory resource */
@@ -1685,9 +1635,9 @@
 		    ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC,
 			     ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) |
 			     ATA_AHCI_GHC_IE);
+		    ctlr->allocate = ata_ahci_allocate;
 		    ctlr->reset = ata_ahci_reset;
 		    ctlr->dmainit = ata_ahci_dmainit;
-		    ctlr->allocate = ata_ahci_allocate;
 		}
 	    }
 	}
@@ -1701,6 +1651,19 @@
 }
 
 static int
+ata_intel_allocate(device_t dev)
+{
+    struct ata_channel *ch = device_get_softc(dev);
+
+    /* setup the usual register normal pci style */
+    if (ata_pci_allocate(dev))
+	return ENXIO;
+
+    ch->flags |= ATA_ALWAYS_DMASTAT;
+    return 0;
+}
+
+static int
 ata_intel_31244_allocate(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
@@ -1732,7 +1695,7 @@
     ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x74;
 
     ch->flags |= ATA_NO_SLAVE;
-    ata_generic_hw(dev);
+    ata_pci_hw(dev);
     ch->hw.command = ata_intel_31244_command;
 
     /* enable PHY state change interrupt */
@@ -1784,14 +1747,6 @@
 	}
 
 	/* any drive action to take care of ? */
-	if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
-	    int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-	    if (!(bmstat & ATA_BMSTAT_INTERRUPT))
-		continue;
-	    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-	    DELAY(1);
-	}
 	ctlr->interrupt[unit].function(ch);
     }
 }
@@ -1833,29 +1788,6 @@
 }
 
 static void
-ata_intel_intr(void *data)
-{
-    struct ata_pci_controller *ctlr = data;
-    struct ata_channel *ch;
-    int unit;
-
-    for (unit = 0; unit < ctlr->channels; unit++) {
-	if (!(ch = ctlr->interrupt[unit].argument))
-	    continue;
-	if (ch->dma) {
-	    int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-	    if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
-		ATA_BMSTAT_INTERRUPT)
-		continue;
-	    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-	    DELAY(1);
-	}
-	ctlr->interrupt[unit].function(ch);
-    }
-}
-
-static void
 ata_intel_reset(device_t dev)
 {
     device_t parent = device_get_parent(dev);
@@ -2142,9 +2074,9 @@
     /* mask all PCI interrupts */
     ATA_OUTL(ctlr->r_res1, 0x01d5c, 0x00000000);
 
+    ctlr->allocate = ata_marvell_allocate;
     ctlr->reset = ata_marvell_reset;
     ctlr->dmainit = ata_marvell_dmainit;
-    ctlr->allocate = ata_marvell_allocate;
     ctlr->setmode = ata_sata_setmode;
     ctlr->channels = ctlr->chip->cfg1;
 
@@ -2809,15 +2741,6 @@
 
 	    /* any drive action to take care of ? */
 	    if (status & (0x01 << maskshift)) {
-		if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
-		    int bmstat = 
-			ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-		    if (!(bmstat & ATA_BMSTAT_INTERRUPT))
-			continue;
-		    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat&~ATA_BMSTAT_ERROR);
-		    DELAY(1);
-		}
 		ctlr->interrupt[unit].function(ch);
 	    }
 	}
@@ -3006,9 +2929,9 @@
 	    bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1);
 	    return ENXIO;
 	}
+	ctlr->allocate = ata_promise_mio_allocate;
 	ctlr->reset = ata_promise_mio_reset;
 	ctlr->dmainit = ata_promise_mio_dmainit;
-	ctlr->allocate = ata_promise_mio_allocate;
 
 	if (ctlr->chip->cfg2 == PRSX4X) {
 	    struct ata_promise_sx4 *hpkt;
@@ -3573,15 +3496,6 @@
 	    continue;
 	ATA_IDX_OUTB(ch, ATA_BMDEVSPEC_0, 0x0b);
 	if (ATA_IDX_INB(ch, ATA_BMDEVSPEC_1) & 0x20) {
-	    if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
-		int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-		if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
-		    ATA_BMSTAT_INTERRUPT)
-		    continue;
-		ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-		DELAY(1);
-	    }
 	    ctlr->interrupt[unit].function(ch);
 	}
     }
@@ -3598,15 +3512,6 @@
 	if (!(ch = ctlr->interrupt[unit].argument))
 	    continue;
 	if (ATA_INL(ctlr->r_res1, 0x1c) & (ch->unit ? 0x00004000 : 0x00000400)){
-	    if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
-		int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-		if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
-		    ATA_BMSTAT_INTERRUPT)
-		    continue;
-		ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-		DELAY(1);
-	    }
 	    ctlr->interrupt[unit].function(ch);
 	}
     }
@@ -3973,7 +3878,7 @@
     else {
 	if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
 			    ctlr->chip->cfg2 & SIIINTR ? 
-			    ata_cmd_intr : ata_cmd_old_intr,
+			    ata_cmd_intr : ata_generic_intr,
 			    ctlr, &ctlr->handle))) {
 	    device_printf(dev, "unable to setup interrupt\n");
 	    return ENXIO;
@@ -4036,7 +3941,7 @@
 	ch->dma->segsize = 15 * DEV_BSIZE;
     }
 
-    ata_generic_hw(dev);
+    ata_pci_hw(dev);
     return 0;
 }
 
@@ -4084,14 +3989,6 @@
 
 	/* any drive action to take care of ? */
 	if (ATA_IDX_INB(ch, ATA_BMDEVSPEC_0) & 0x08) {
-	    if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
-		int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-		if (!(bmstat & ATA_BMSTAT_INTERRUPT))
-		    continue;
-		ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-		DELAY(1);
-	    }
 	    ctlr->interrupt[unit].function(ch);
 	}
 
@@ -4113,44 +4010,12 @@
 	     (ch->unit ? 0x08 : 0x04))) {
 	    pci_write_config(device_get_parent(ch->dev), 0x71,
 			     reg71 & ~(ch->unit ? 0x04 : 0x08), 1);
-	    if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
-		int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-		if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
-		    ATA_BMSTAT_INTERRUPT)
-		    continue;
-		ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-		DELAY(1);
-	    }
 	    ctlr->interrupt[unit].function(ch);
 	}
     }
 }
 
 static void
-ata_cmd_old_intr(void *data)
-{
-    struct ata_pci_controller *ctlr = data;
-    struct ata_channel *ch;
-    int unit;
-
-    for (unit = 0; unit < ctlr->channels; unit++) {
-	if (!(ch = ctlr->interrupt[unit].argument))
-	    continue;
-	if (ch->dma && (ch->dma->flags & ATA_DMA_ACTIVE)) {
-	    int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
-
-	    if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
-		ATA_BMSTAT_INTERRUPT)
-		continue;
-	    ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
-	    DELAY(1);
-	}
-	ctlr->interrupt[unit].function(ch);
-    }
-}
-
-static void
 ata_sii_reset(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
@@ -4661,7 +4526,7 @@
 	    ch->r_io[i].res = ctlr->r_res1;
 	    ch->r_io[i].offset = i - ATA_BMCMD_PORT;
 	}
-	ata_generic_hw(dev);
+	ata_pci_hw(dev);
     }
     else {
         if (ata_pci_allocate(dev))
Index: ata-disk.c
===================================================================
RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-disk.c,v
retrieving revision 1.192
diff -u -r1.192 ata-disk.c
--- ata-disk.c	5 Jan 2006 21:27:19 -0000	1.192
+++ ata-disk.c	11 Jan 2006 23:00:53 -0000
@@ -289,45 +289,23 @@
 
 static int
 ad_dump(void *arg, void *virtual, vm_offset_t physical,
-       off_t offset, size_t length)
+	off_t offset, size_t length)
 {
     struct disk *dp = arg;
-    device_t dev = dp->d_drv1;
-    struct ata_device *atadev = device_get_softc(dev);
-    struct ad_softc *adp = device_get_ivars(dev);
-    struct ata_channel *ch = device_get_softc(device_get_parent(dev));
-    struct ata_request request;
+    struct bio bp;
 
-    if (!adp)
-	return ENXIO;
-
-    bzero(&request, sizeof(struct ata_request));
-    request.dev = dev;
-
-    if (length) {
-	request.data = virtual;
-	request.bytecount = length;
-	request.transfersize = min(length, atadev->max_iosize);
-	request.flags = ATA_R_WRITE;
-	if (atadev->max_iosize > DEV_BSIZE)
-	    request.u.ata.command = ATA_WRITE_MUL;
-	else
-	    request.u.ata.command = ATA_WRITE;
-	request.u.ata.lba = offset / DEV_BSIZE;
-	request.u.ata.count = request.bytecount / DEV_BSIZE;
-    }
-    else {
-	request.u.ata.command = ATA_FLUSHCACHE;
-	request.flags = ATA_R_CONTROL;
-    }
-    if (ch->hw.begin_transaction(&request) == ATA_OP_CONTINUES) {
-	do {
-	    DELAY(20);
-	} while (ch->hw.end_transaction(&request) == ATA_OP_CONTINUES);
-    }
-    if (request.status & ATA_S_ERROR)
-	return EIO;
-    return 0;
+    /* length zero is special and really means flush buffers to media */
+    if (!length)
+	return ata_controlcmd(dp->d_drv1, ATA_FLUSHCACHE, 0, 0, 0);
+
+    bzero(&bp, sizeof(struct bio));
+    bp.bio_disk = dp;
+    bp.bio_pblkno = offset / DEV_BSIZE;
+    bp.bio_bcount = length;
+    bp.bio_data = virtual;
+    bp.bio_cmd = BIO_WRITE;
+    ad_strategy(&bp);
+    return bp.bio_error;
 }
 
 static void
Index: ata-lowlevel.c
===================================================================
RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-lowlevel.c,v
retrieving revision 1.75
diff -u -r1.75 ata-lowlevel.c
--- ata-lowlevel.c	5 Jan 2006 21:27:19 -0000	1.75
+++ ata-lowlevel.c	11 Jan 2006 23:00:53 -0000
@@ -48,6 +48,7 @@
 /* prototypes */
 static int ata_begin_transaction(struct ata_request *);
 static int ata_end_transaction(struct ata_request *);
+static int ata_generic_status(device_t dev);
 static int ata_wait(struct ata_channel *ch, struct ata_device *, u_int8_t);
 static void ata_pio_read(struct ata_request *, int);
 static void ata_pio_write(struct ata_request *, int);
@@ -62,6 +63,7 @@
 
     ch->hw.begin_transaction = ata_begin_transaction;
     ch->hw.end_transaction = ata_end_transaction;
+    ch->hw.status = ata_generic_status;
     ch->hw.command = ata_generic_command;
 }
 
@@ -470,7 +472,7 @@
     return ATA_OP_CONTINUES;
 }
 
-/* must be called with ATA channel locked */
+/* must be called with ATA channel locked and state_mtx held */
 void
 ata_generic_reset(device_t dev)
 {
@@ -605,6 +607,20 @@
 		      "\20\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
 }
 
+/* must be called with ATA channel locked and state_mtx held */
+int
+ata_generic_status(device_t dev)
+{
+    struct ata_channel *ch = device_get_softc(dev);
+
+    if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) {
+	DELAY(100);
+	if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY)
+	    return 0;
+    }
+    return 1;
+}
+
 static int
 ata_wait(struct ata_channel *ch, struct ata_device *atadev, u_int8_t mask)
 {
Index: ata-pci.c
===================================================================
RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-pci.c,v
retrieving revision 1.110
diff -u -r1.110 ata-pci.c
--- ata-pci.c	5 Jan 2006 21:27:19 -0000	1.110
+++ ata-pci.c	11 Jan 2006 23:00:54 -0000
@@ -60,6 +60,7 @@
 
 /* prototypes */
 static void ata_pci_dmainit(device_t);
+static int ata_pci_status(device_t dev);
 
 int
 ata_legacy(device_t dev)
@@ -203,7 +204,8 @@
 					      RF_ACTIVE);
     }
 
-    ctlr->chipinit(dev);
+    if (ctlr->chipinit(dev))
+	return ENXIO;
 
     /* attach all channels on this controller */
     for (unit = 0; unit < ctlr->channels; unit++) {
@@ -420,10 +422,42 @@
 	}
     }
 
-    ata_generic_hw(dev);
+    ata_pci_hw(dev);
     return 0;
 }
 
+void
+ata_pci_hw(device_t dev)
+{
+    struct ata_channel *ch = device_get_softc(dev);
+
+    ata_generic_hw(dev);
+    ch->hw.status = ata_pci_status;
+}
+
+static int
+ata_pci_status(device_t dev)
+{
+    struct ata_channel *ch = device_get_softc(dev);
+
+    if (ch->dma && ((ch->flags & ATA_ALWAYS_DMASTAT) ||
+		    (ch->dma->flags & ATA_DMA_ACTIVE))) {
+	int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
+
+       	if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) !=
+	    ATA_BMSTAT_INTERRUPT)
+	    return 0;
+	ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
+	DELAY(1);
+    }
+    if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) {
+        DELAY(100);
+        if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY)
+            return 0;
+    }
+    return 1;
+}
+
 static int
 ata_pci_dmastart(device_t dev)
 {
Index: ata-pci.h
===================================================================
RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-pci.h,v
retrieving revision 1.59
diff -u -r1.59 ata-pci.h
--- ata-pci.h	5 Jan 2006 21:27:19 -0000	1.59
+++ ata-pci.h	11 Jan 2006 23:00:54 -0000
@@ -392,6 +392,7 @@
 int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_intr_t *function, void *argument, void **cookiep);
  int ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie);
 int ata_pci_allocate(device_t dev);
+void ata_pci_hw(device_t dev);
 
 /* global prototypes ata-chipset.c */
 int ata_generic_ident(device_t);
Index: ata-queue.c
===================================================================
RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-queue.c,v
retrieving revision 1.53
diff -u -r1.53 ata-queue.c
--- ata-queue.c	5 Jan 2006 21:27:19 -0000	1.53
+++ ata-queue.c	11 Jan 2006 23:22:38 -0000
@@ -94,7 +94,8 @@
     /* if this is not a callback wait until request is completed */
     if (!request->callback) {
 	ATA_DEBUG_RQ(request, "wait for completition");
-	while (sema_timedwait(&request->done, request->timeout * hz * 4)) {
+	while (!dumping &&
+	       sema_timedwait(&request->done, request->timeout * hz * 4)) {
 	    device_printf(request->dev,
 		"req=%p %s semaphore timeout !! DANGER Will Robinson !!\n",
 		      request, ata_cmd2str(request));
@@ -200,6 +201,13 @@
 		    ata_finish(request);
 		    return;
 		}
+		if (dumping) {
+		    mtx_unlock(&ch->state_mtx);
+		    mtx_unlock(&ch->queue_mtx);
+		    while (!ata_interrupt(ch))
+	    		DELAY(10);
+		    return;
+		}	
 	    }
 	    mtx_unlock(&ch->state_mtx);
 	}
@@ -216,7 +224,8 @@
      * if in ATA_STALL_QUEUE state or request has ATA_R_DIRECT flags set
      * we need to call ata_complete() directly here (no taskqueue involvement)
      */
-    if ((ch->state & ATA_STALL_QUEUE) || (request->flags & ATA_R_DIRECT)) {
+    if (dumping ||
+	(ch->state & ATA_STALL_QUEUE) || (request->flags & ATA_R_DIRECT)) {
 	ATA_DEBUG_RQ(request, "finish directly");
 	ata_completed(request, 0);
     }
Index: ata-raid.c
===================================================================
RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-raid.c,v
retrieving revision 1.115
diff -u -r1.115 ata-raid.c
--- ata-raid.c	5 Jan 2006 21:27:19 -0000	1.115
+++ ata-raid.c	11 Jan 2006 23:28:35 -0000
@@ -111,7 +111,7 @@
 
 /* device structures */
 static disk_strategy_t ata_raid_strategy;
-//static dumper_t ata_raid_dump;
+static dumper_t ata_raid_dump;
 
 static void
 ata_raid_attach(struct ar_softc *rdp, int writeback)
@@ -134,7 +134,7 @@
 	buffer[0] = '\0';
     rdp->disk = disk_alloc();
     rdp->disk->d_strategy = ata_raid_strategy;
-    //rdp->disk->d_dump = ata_raid_dump;
+    rdp->disk->d_dump = ata_raid_dump;
     rdp->disk->d_name = "ar";
     rdp->disk->d_sectorsize = DEV_BSIZE;
     rdp->disk->d_mediasize = (off_t)rdp->total_sectors * DEV_BSIZE;
@@ -751,6 +751,35 @@
 	ata_free_request(request);
 }
 
+static int
+ata_raid_dump(void *arg, void *virtual, vm_offset_t physical,
+	      off_t offset, size_t length)
+{
+    struct disk *dp = arg;
+    struct ar_softc *rdp = dp->d_drv1;
+    struct bio bp;
+
+    /* length zero is special and really means flush buffers to media */
+    if (!length) {
+	int disk, error;
+
+	for (disk = 0, error = 0; disk < rdp->total_disks; disk++) 
+	    if (rdp->disks[disk].dev)
+		error |= ata_controlcmd(rdp->disks[disk].dev,
+					ATA_FLUSHCACHE, 0, 0, 0);
+	return (error ? EIO : 0);
+    }
+
+    bzero(&bp, sizeof(struct bio));
+    bp.bio_disk = dp;
+    bp.bio_pblkno = offset / DEV_BSIZE;
+    bp.bio_bcount = length;
+    bp.bio_data = virtual;
+    bp.bio_cmd = BIO_WRITE;
+    ata_raid_strategy(&bp);
+    return bp.bio_error;
+}
+
 static void
 ata_raid_config_changed(struct ar_softc *rdp, int writeback)
 {

--------------020809040703060107040900--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?43C59717.7000203>