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)