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