fix cdrom media change
This commit is contained in:
parent
2720d09737
commit
077537baeb
3 changed files with 67 additions and 48 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,23 +222,7 @@ 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.
|
|
||||||
* 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;
|
*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
|
||||||
|
|
Loading…
Reference in a new issue