shithub: riscv

Download patch

ref: cb02859888c7aa4bbd5ae598563458960b5a26e2
parent: 3202d39042623467db4bf51cb583e191f3aa54d2
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Sat Jul 23 19:40:35 EDT 2011

sdide: limit max dma transfer size, make sure dma transfer is stoped in error case, set bytecount to 0 for dma

--- a/sys/src/9/pc/sdide.c
+++ b/sys/src/9/pc/sdide.c
@@ -259,7 +259,7 @@
 } Prd;
 
 enum {
-	BMspan		= 64*1024,	/* must be power of 2 <= 64*1024 */
+	BMspan		= 32*1024,	/* must be power of 2 <= 64*1024 */
 
 	Nprd		= SDmaxio/BMspan+2,
 };
@@ -272,6 +272,7 @@
 	int	bmiba;			/* bus master interface base address */
 	int	maxio;			/* sector count transfer maximum */
 	int	span;			/* don't span this boundary with dma */
+	int	maxdma;			/* don't attempt dma transfers bigger than this */
 
 	Pcidev*	pcidev;
 	void	(*ienable)(Ctlr*);
@@ -1019,6 +1020,8 @@
 	pa = PCIWADDR(drive->data);
 	if(pa & 0x03)
 		return -1;
+	if(ctlr->maxdma && len > ctlr->maxdma)
+		return -1;
 
 	/*
 	 * Sometimes drives identify themselves as being DMA capable
@@ -1047,7 +1050,7 @@
 		prd++;
 	}
 	if(i == Nprd)
-		(prd-1)->count |= PrdEOT;
+		return -1;
 
 	bmiba = ctlr->bmiba;
 	outl(bmiba+Bmidtpx, PCIWADDR(ctlr->prdt));
@@ -1134,6 +1137,8 @@
 		break;
 
 	case 0:
+		if(drive->pktdma)
+			goto Pktdma;
 		len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
 		if(drive->data+len > drive->limit){
 			atanop(drive, 0);
@@ -1144,6 +1149,8 @@
 		break;
 
 	case Io:
+		if(drive->pktdma)
+			goto Pktdma;
 		len = (inb(cmdport+Bytehi)<<8)|inb(cmdport+Bytelo);
 		if(drive->data+len > drive->limit){
 			atanop(drive, 0);
@@ -1154,9 +1161,10 @@
 		break;
 
 	case Io|Cd:
-		if(drive->pktdma)
+		if(drive->pktdma){
+	Pktdma:
 			atadmainterrupt(drive, drive->dlen);
-		else
+		} else
 			ctlr->done = 1;
 		break;
 	}
@@ -1186,18 +1194,19 @@
 		return SDnostatus;
 
 	ilock(ctlr);
-	if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen))
+	if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen)){
 		drive->pktdma = Dma;
-	else
+		len = 0;		/* bytecount should be 0 for dma */
+	}else{
 		drive->pktdma = 0;
-
+		if(drive->secsize)
+			len = 16*drive->secsize;
+		else
+			len = 0x8000;
+	}
 	outb(cmdport+Features, drive->pktdma);
 	outb(cmdport+Count, 0);
 	outb(cmdport+Sector, 0);
-	if(drive->secsize)
-		len = 16*drive->secsize;
-	else
-		len = 0x8000;
 	outb(cmdport+Bytelo, len);
 	outb(cmdport+Bytehi, len>>8);
 	outb(cmdport+Dh, drive->dev);
@@ -1204,8 +1213,6 @@
 	ctlr->done = 0;
 	ctlr->curdrive = drive;
 	ctlr->command = Cpkt;		/* debugging */
-	if(drive->pktdma)
-		atadmastart(ctlr, drive->write);
 	outb(cmdport+Command, Cpkt);
 
 	if((drive->info[Iconfig] & Mdrq) != 0x0020){
@@ -1219,23 +1226,22 @@
 		}else
 			atapktinterrupt(drive);
 	}
+	if(drive->pktdma)
+		atadmastart(ctlr, drive->write);
 	iunlock(ctlr);
 
 	if(iowait(drive, 20*1000, 1) <= 0){
 		ilock(ctlr);
-		if(!drive->error){
-			ataabort(drive, 0);
-			if(drive->pktdma){
-				atadmastop(ctlr);
-				drive->dmactl = 0;
-			}
-		}
-		if(drive->error){
-			drive->status |= Chk;
-			ctlr->curdrive = nil;
-		}
-		iunlock(ctlr);
+		ataabort(drive, 0);
+	} else
+		ilock(ctlr);
+	if(drive->error){
+		if(drive->pktdma)
+			atadmastop(ctlr);
+		drive->status |= Chk;
+		ctlr->curdrive = nil;
 	}
+	iunlock(ctlr);
 
 	if(drive->status & Chk)
 		rv = SDcheck;
@@ -2001,7 +2007,7 @@
 atapnp(void)
 {
 	char *s;
-	int channel, map, ispc87415, maxio, pi, r, span, tbdf;
+	int channel, map, ispc87415, maxio, pi, r, span, maxdma, tbdf;
 	Ctlr *ctlr;
 	Pcidev *p;
 	SDev *sdev, *head, *tail;
@@ -2034,6 +2040,7 @@
 		pi = p->ccrp;
 		map = 3;
 		ispc87415 = 0;
+		maxdma = 0;
 		maxio = 0;
 		if(s = getconf("*idemaxio"))
 			maxio = atoi(s);
@@ -2172,9 +2179,10 @@
 		case (0x2366<<16)|0x197b:	/* jmicron jmb366 */
 		case (0x2368<<16)|0x197b:	/* jmicron jmb368 */
 			break;
-		case (0x1230<<16)|0x8086:	/* 82371FB (PIIX) */
 		case (0x7010<<16)|0x8086:	/* 82371SB (PIIX3) */
+		case (0x1230<<16)|0x8086:	/* 82371FB (PIIX) */
 		case (0x7111<<16)|0x8086:	/* 82371[AE]B (PIIX4[E]) */
+			maxdma = 0x20000;
 			break;
 		case (0x2411<<16)|0x8086:	/* 82801AA (ICH) */
 		case (0x2421<<16)|0x8086:	/* 82801AB (ICH0) */
@@ -2246,6 +2254,7 @@
 			ctlr->tbdf = tbdf;
 			ctlr->pcidev = p;
 			ctlr->maxio = maxio;
+			ctlr->maxdma = maxdma;
 			ctlr->span = span;
 			ctlr->irqack = irqack;
 			if(pi & 0x80)