Remaining SATA (and other) issues TAKE 2

Søren Schmidt sos at deepcore.dk
Sun Nov 11 02:40:23 PST 2007


Hi All

Alexander found the bug causing the data to be offset wrongly in my last 
patch, this new one should fix that so we dont get disappearing nodes 
etc, sorry about that :)

Please apply to clean releng_7 sources.

Let me know how it turns out.

-Søren
-------------- next part --------------
Index: ata-chipset.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-chipset.c,v
retrieving revision 1.202.2.2
diff -u -r1.202.2.2 ata-chipset.c
--- ata-chipset.c	31 Oct 2007 19:59:53 -0000	1.202.2.2
+++ ata-chipset.c	8 Nov 2007 20:15:48 -0000
@@ -142,6 +142,7 @@
 static int ata_promise_mio_command(struct ata_request *request);
 static void ata_promise_mio_reset(device_t dev);
 static void ata_promise_mio_dmainit(device_t dev);
+static void ata_promise_mio_setprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
 static void ata_promise_mio_setmode(device_t dev, int mode);
 static void ata_promise_sx4_intr(void *data);
 static int ata_promise_sx4_command(struct ata_request *request);
@@ -792,6 +793,7 @@
 	    prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK);
 	}
     }
+    KASSERT(nsegs <= ATA_DMA_ENTRIES, "too many DMA segment entries\n");
     args->nsegs = nsegs;
 }
 
@@ -2760,6 +2762,8 @@
 	prd[i].addrhi = htole32((u_int64_t)segs[i].ds_addr >> 32);
     }
     prd[i - 1].count |= htole32(ATA_DMA_EOT);
+    KASSERT(nsegs <= ATA_DMA_ENTRIES, "too many DMA segment entries\n");
+    args->nsegs = nsegs;
 }
 
 static void
@@ -3288,9 +3292,13 @@
 	/* prime fake interrupt register */
 	ATA_OUTL(ctlr->r_res2, fake_reg, 0xffffffff);
 
-	/* clear SATA status */
+	/* clear SATA status and unmask interrupts */
 	ATA_OUTL(ctlr->r_res2, stat_reg, 0x000000ff);
 
+	/* enable "long burst lenght" on gen2 chips */
+	if ((ctlr->chip->cfg2 == PRSATA2) || (ctlr->chip->cfg2 == PRCMBO2))
+	    ATA_OUTL(ctlr->r_res2, 0x44, ATA_INL(ctlr->r_res2, 0x44) | 0x2000);
+
 	ctlr->allocate = ata_promise_mio_allocate;
 	ctlr->reset = ata_promise_mio_reset;
 	ctlr->dmainit = ata_promise_mio_dmainit;
@@ -3778,8 +3786,41 @@
 static void
 ata_promise_mio_dmainit(device_t dev)
 {
+    struct ata_channel *ch = device_get_softc(dev);
+
     /* note start and stop are not used here */
     ata_dmainit(dev);
+    if (ch->dma) 
+	ch->dma->setprd = ata_promise_mio_setprd;
+}
+
+
+#define MAXLASTSGSIZE (32 * sizeof(u_int32_t))
+static void 
+ata_promise_mio_setprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
+{
+    struct ata_dmasetprd_args *args = xsc;
+    struct ata_dma_prdentry *prd = args->dmatab;
+    int i;
+
+    if ((args->error = error))
+	return;
+
+    for (i = 0; i < nsegs; i++) {
+	prd[i].addr = htole32(segs[i].ds_addr);
+	prd[i].count = htole32(segs[i].ds_len);
+    }
+    if (segs[i - 1].ds_len > MAXLASTSGSIZE) {
+	//printf("split last SG element of %u\n", segs[i - 1].ds_len);
+	prd[i - 1].count = htole32(segs[i - 1].ds_len - MAXLASTSGSIZE);
+	prd[i].count = htole32(MAXLASTSGSIZE);
+	prd[i].addr = htole32(segs[i - 1].ds_addr + (segs[i - 1].ds_len - MAXLASTSGSIZE));
+	nsegs++;
+	i++;
+    }
+    prd[i - 1].count |= htole32(ATA_DMA_EOT);
+    KASSERT(nsegs <= ATA_DMA_ENTRIES, "too many DMA segment entries\n");
+    args->nsegs = nsegs;
 }
 
 static void
@@ -4849,6 +4890,8 @@
 	prd[i].count = htole32(segs[i].ds_len);
     }
     prd[i - 1].control = htole32(ATA_DMA_EOT);
+    KASSERT(nsegs <= ATA_DMA_ENTRIES, "too many DMA segment entries\n");
+    args->nsegs = nsegs;
 }
 
 static void
Index: ata-dma.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-dma.c,v
retrieving revision 1.147
diff -u -r1.147 ata-dma.c
--- ata-dma.c	8 Apr 2007 21:53:52 -0000	1.147
+++ ata-dma.c	8 Nov 2007 20:15:48 -0000
@@ -213,6 +213,7 @@
 	prd[i].count = htole32(segs[i].ds_len);
     }
     prd[i - 1].count |= htole32(ATA_DMA_EOT);
+    KASSERT(nsegs <= ATA_DMA_ENTRIES, "too many DMA segment entries\n");
     args->nsegs = nsegs;
 }
 


More information about the freebsd-current mailing list