fix cdrom media change

This commit is contained in:
cinap_lenrek 2011-12-06 14:49:40 +01:00
parent 2720d09737
commit 077537baeb
3 changed files with 67 additions and 48 deletions

View file

@ -1473,24 +1473,22 @@ iaonline(SDunit *unit)
c = unit->dev->ctlr; c = unit->dev->ctlr;
d = c->drive[unit->subno]; d = c->drive[unit->subno];
r = 0;
if(d->portm.feat & Datapi && d->drivechange){
r = scsionline(unit);
if(r > 0)
d->drivechange = 0;
return r;
}
ilock(d); ilock(d);
if(d->drivechange){ if(d->portm.feat & Datapi){
r = 2;
d->drivechange = 0; d->drivechange = 0;
/* devsd resets this after online is called; why? */ iunlock(d);
unit->sectors = d->sectors; return scsionline(unit);
unit->secsize = d->secsize; }
r = 0;
if(d->drivechange){
d->drivechange = 0;
r = 2;
}else if(d->state == Dready) }else if(d->state == Dready)
r = 1; r = 1;
if(r){
unit->sectors = d->sectors;
unit->secsize = d->secsize;
}
iunlock(d); iunlock(d);
return r; return r;
} }
@ -1707,7 +1705,6 @@ iariopkt(SDreq *r, Drive *d)
case SDretry: case SDretry:
continue; continue;
} }
// print("%.2ux :: %.2ux :: %.4ux\n", r->cmd[0], r->status, d->port->task);
r->rlen = d->portm.list->len; r->rlen = d->portm.list->len;
return SDok; return SDok;
} }

View file

@ -1188,7 +1188,7 @@ atapktio0(Drive *drive, SDreq *r)
cmdport = ctlr->cmdport; cmdport = ctlr->cmdport;
ctlport = ctlr->ctlport; ctlport = ctlr->ctlport;
as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, Drdy, 107*1000); as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 107*1000);
/* used to test as&Chk as failure too, but some CD readers use that for media change */ /* used to test as&Chk as failure too, but some CD readers use that for media change */
if(as < 0) if(as < 0)
return SDnostatus; return SDnostatus;
@ -1242,12 +1242,12 @@ atapktio0(Drive *drive, SDreq *r)
iunlock(ctlr); iunlock(ctlr);
if(drive->status & Chk){ if(drive->status & Chk){
rv = SDcheck;
if(drive->pktdma){ if(drive->pktdma){
print("atapktio: disabling dma\n"); print("atapktio: disabling dma\n");
drive->dmactl = 0; drive->dmactl = 0;
rv = SDretry; rv = SDretry;
} else }
rv = SDcheck;
} }
return rv; return rv;
} }
@ -1545,7 +1545,7 @@ atagenatastart(Drive* d, SDreq *r)
ctlr = d->ctlr; ctlr = d->ctlr;
cmdport = ctlr->cmdport; cmdport = ctlr->cmdport;
ctlport = ctlr->ctlport; ctlport = ctlr->ctlport;
if(ataready(cmdport, ctlport, d->dev, Bsy|Drq, d->pkt? 0: Drdy, 101*1000) < 0) if(ataready(cmdport, ctlport, d->dev, Bsy|Drq, d->pkt ? 0 : Drdy, 101*1000) < 0)
return -1; return -1;
ilock(ctlr); ilock(ctlr);
@ -1902,7 +1902,6 @@ atainterrupt(Ureg*, void* arg)
print("Inil%2.2uX+", ctlr->command); print("Inil%2.2uX+", ctlr->command);
return; return;
} }
if(status & Err) if(status & Err)
drive->error = inb(cmdport+Error); drive->error = inb(cmdport+Error);
else switch(drive->command){ else switch(drive->command){
@ -1999,8 +1998,8 @@ badccru(Pcidev *p)
switch(p->did<<16 | p->did){ switch(p->did<<16 | p->did){
case 0x439c<<16 | 0x1002: case 0x439c<<16 | 0x1002:
case 0x438c<<16 | 0x1002: case 0x438c<<16 | 0x1002:
print("hi, anothy\n"); print("%T: allowing bad ccru %.2ux for suspected ide controller\n",
print("%T: allowing bad ccru %.2ux for suspected ide controller\n", p->tbdf, p->ccru); p->tbdf, p->ccru);
return 1; return 1;
default: default:
return 0; return 0;
@ -2411,9 +2410,8 @@ ataonline(SDunit *unit)
if((drive->flags & Online) == 0){ if((drive->flags & Online) == 0){
drive->flags |= Online; drive->flags |= Online;
atadrive(unit, drive, ctlr->cmdport, ctlr->ctlport, drive->dev); atadrive(unit, drive, ctlr->cmdport, ctlr->ctlport, drive->dev);
ret = 2;
} }
unit->sectors = drive->sectors;
unit->secsize = drive->secsize;
if(drive->feat & Datapi){ if(drive->feat & Datapi){
ulong dma; ulong dma;
@ -2421,6 +2419,9 @@ ataonline(SDunit *unit)
drive->dmactl = 0; drive->dmactl = 0;
ret = scsionline(unit); ret = scsionline(unit);
drive->dmactl = dma; drive->dmactl = dma;
} else {
unit->sectors = drive->sectors;
unit->secsize = drive->secsize;
} }
return ret; return ret;
} }

View file

@ -214,7 +214,6 @@ capreply(SDreq *r, ulong *secsize)
ulong ss; ulong ss;
uvlong s; uvlong s;
*secsize = 0;
u = r->data; u = r->data;
if(r->clen == 16){ if(r->clen == 16){
s = (uvlong)belong(u)<<32 | belong(u + 4); s = (uvlong)belong(u)<<32 | belong(u + 4);
@ -223,24 +222,8 @@ capreply(SDreq *r, ulong *secsize)
s = belong(u); s = belong(u);
ss = belong(u + 4); ss = belong(u + 4);
} }
/* if(secsize)
* Some ATAPI CD readers lie about the block size. *secsize = ss;
* Since we don't read audio via this interface
* it's okay to always fudge this.
*/
if(ss == 2352)
ss = 2048;
/*
* Devices with removable media may return 0 sectors
* when they have empty media (e.g. sata dvd writers);
* if so, keep the count zero.
*
* Read-capacity returns the LBA of the last sector,
* therefore the number of sectors must be incremented.
*/
if(s != 0)
s++;
*secsize = ss;
return s; return s;
} }
@ -249,6 +232,8 @@ scsionline(SDunit* unit)
{ {
SDreq *r; SDreq *r;
uchar *p; uchar *p;
ulong ss;
uvlong s;
int ok, retries; int ok, retries;
void (*cap)(SDreq*); void (*cap)(SDreq*);
@ -276,20 +261,51 @@ scsionline(SDunit* unit)
memset(r->cmd, 0, sizeof r->cmd); memset(r->cmd, 0, sizeof r->cmd);
cap(r); cap(r);
r->status = ~0;
switch(scsirio(r)){ switch(scsirio(r)){
default: default:
/*
* ATAPI returns error and no sense information
* on media change / no media present.
* count as retries.
*/
if(retries < 4)
continue;
break; break;
case 0: case 0:
unit->sectors = capreply(r, &unit->secsize); s = capreply(r, &ss);
if(unit->sectors == 0xffffffff && cap == cap10){ if(s == 0xffffffff && cap == cap10){
cap = cap16; cap = cap16;
continue; continue;
} }
ok = 1; if(s == 0xffffffffffffffffLL)
s = 0;
/*
* Some ATAPI CD readers lie about the block size.
* Since we don't read audio via this interface
* it's okay to always fudge this.
*/
if(ss == 2352)
ss = 2048;
/*
* Devices with removable media may return 0 sectors
* when they have empty media (e.g. sata dvd writers);
* if so, keep the count zero.
*
* Read-capacity returns the LBA of the last sector,
* therefore the number of sectors must be incremented.
*/
if(s != 0)
s++;
ok = (unit->sectors != s) ? 2 : 1;
unit->sectors = s;
unit->secsize = ss;
break; break;
case 1: case 1:
ok = 1; ok = (unit->sectors != 0) ? 2 : 1;
unit->sectors = 0;
break; break;
case 2: case 2:
continue; continue;
@ -299,6 +315,11 @@ scsionline(SDunit* unit)
free(p); free(p);
free(r); free(r);
/*
print("scsionline: %s: ok=%d retries=%d sectors=%llud secsize=%lud\n",
unit->name, ok, retries, unit->sectors, unit->secsize);
*/
if(ok) if(ok)
return ok+retries; return ok+retries;
else else