PATCH: DMA enabled dump for ATA please test

From: Søren Schmidt <sos_at_FreeBSD.org>
Date: Thu, 12 Jan 2006 00:39:03 +0100
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

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
_at__at_ -63,7 +63,6 _at__at_
 };
 
 /* 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);
_at__at_ -139,7 +138,7 _at__at_
 	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;
     }
_at__at_ -317,7 +316,7 _at__at_
     return error;
 }
 
-static void
+int
 ata_interrupt(void *data)
 {
     struct ata_channel *ch = (struct ata_channel *)data;
_at__at_ -325,20 +324,17 _at__at_
 
     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;
_at__at_ -355,10 +351,11 _at__at_
 	    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
_at__at_ -470,6 +470,7 _at__at_
 
 /* 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);
_at__at_ -495,6 +496,7 _at__at_
 #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
_at__at_ -534,6 +536,7 _at__at_
 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
_at__at_ -82,15 +82,15 _at__at_
 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);
_at__at_ -132,7 +132,6 _at__at_
 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);
_at__at_ -184,18 +183,8 _at__at_
     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);
     }
 }
 
_at__at_ -748,18 +737,6 _at__at_
 	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);
     }
 }
_at__at_ -903,8 +880,8 _at__at_
 	    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;
 
_at__at_ -973,7 +950,7 _at__at_
     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;
 }
 
_at__at_ -1407,18 +1384,9 _at__at_
 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 */
_at__at_ -1439,31 +1407,22 _at__at_
 	    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
_at__at_ -1603,20 +1562,9 _at__at_
 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) {
_at__at_ -1640,14 +1588,15 _at__at_
 	        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;
     }
 
_at__at_ -1656,6 +1605,7 _at__at_
 	/* 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 */
_at__at_ -1685,9 +1635,9 _at__at_
 		    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;
 		}
 	    }
 	}
_at__at_ -1701,6 +1651,19 _at__at_
 }
 
 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));
_at__at_ -1732,7 +1695,7 _at__at_
     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 */
_at__at_ -1784,14 +1747,6 _at__at_
 	}
 
 	/* 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);
     }
 }
_at__at_ -1833,29 +1788,6 _at__at_
 }
 
 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);
_at__at_ -2142,9 +2074,9 _at__at_
     /* 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;
 
_at__at_ -2809,15 +2741,6 _at__at_
 
 	    /* 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);
 	    }
 	}
_at__at_ -3006,9 +2929,9 _at__at_
 	    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;
_at__at_ -3573,15 +3496,6 _at__at_
 	    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);
 	}
     }
_at__at_ -3598,15 +3512,6 _at__at_
 	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);
 	}
     }
_at__at_ -3973,7 +3878,7 _at__at_
     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;
_at__at_ -4036,7 +3941,7 _at__at_
 	ch->dma->segsize = 15 * DEV_BSIZE;
     }
 
-    ata_generic_hw(dev);
+    ata_pci_hw(dev);
     return 0;
 }
 
_at__at_ -4084,14 +3989,6 _at__at_
 
 	/* 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);
 	}
 
_at__at_ -4113,44 +4010,12 _at__at_
 	     (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));
_at__at_ -4661,7 +4526,7 _at__at_
 	    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
_at__at_ -289,45 +289,23 _at__at_
 
 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
_at__at_ -48,6 +48,7 _at__at_
 /* 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);
_at__at_ -62,6 +63,7 _at__at_
 
     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;
 }
 
_at__at_ -470,7 +472,7 _at__at_
     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)
 {
_at__at_ -605,6 +607,20 _at__at_
 		      "\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
_at__at_ -60,6 +60,7 _at__at_
 
 /* prototypes */
 static void ata_pci_dmainit(device_t);
+static int ata_pci_status(device_t dev);
 
 int
 ata_legacy(device_t dev)
_at__at_ -203,7 +204,8 _at__at_
 					      RF_ACTIVE);
     }
 
-    ctlr->chipinit(dev);
+    if (ctlr->chipinit(dev))
+	return ENXIO;
 
     /* attach all channels on this controller */
     for (unit = 0; unit < ctlr->channels; unit++) {
_at__at_ -420,10 +422,42 _at__at_
 	}
     }
 
-    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
_at__at_ -392,6 +392,7 _at__at_
 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
_at__at_ -94,7 +94,8 _at__at_
     /* 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));
_at__at_ -200,6 +201,13 _at__at_
 		    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);
 	}
_at__at_ -216,7 +224,8 _at__at_
      * 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
_at__at_ -111,7 +111,7 _at__at_
 
 /* 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)
_at__at_ -134,7 +134,7 _at__at_
 	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;
_at__at_ -751,6 +751,35 _at__at_
 	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)
 {
Received on Wed Jan 11 2006 - 22:39:06 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:50 UTC