Hopefully fix the probing problems that caused lost slaves etc..

This commit is contained in:
sos 2000-11-12 20:40:05 +00:00
parent 8b434b8934
commit d17388a5b2

View File

@ -765,15 +765,6 @@ static driver_t ata_pcisub_driver = {
DRIVER_MODULE(ata, atapci, ata_pcisub_driver, ata_devclass, 0, 0);
#endif
static int
ata_testregs(struct ata_softc *scp)
{
outb(scp->ioaddr + ATA_ERROR, 0x58);
outb(scp->ioaddr + ATA_CYL_LSB, 0xa5);
return (inb(scp->ioaddr + ATA_ERROR) != 0x58 &&
inb(scp->ioaddr + ATA_CYL_LSB) == 0xa5);
}
static int
ata_probe(device_t dev)
{
@ -835,16 +826,15 @@ ata_probe(device_t dev)
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(1);
status0 = inb(scp->ioaddr + ATA_STATUS);
if ((status0 & 0xf8) != 0xf8 && status0 != 0xa5 && ata_testregs(scp))
if ((status0 & 0xf8) != 0xf8 && status0 != 0xa5)
mask |= 0x01;
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
DELAY(1);
status1 = inb(scp->ioaddr + ATA_STATUS);
if ((status1 & 0xf8) != 0xf8 && status1 != 0xa5 && ata_testregs(scp))
if ((status1 & 0xf8) != 0xf8 && status1 != 0xa5)
mask |= 0x02;
if (bootverbose)
/*if (bootverbose)*/
ata_printf(scp, -1, "mask=%02x status0=%02x status1=%02x\n",
mask, status0, status1);
if (!mask)
@ -1247,45 +1237,58 @@ void
ata_reset(struct ata_softc *scp, int *mask)
{
int timeout;
u_int8_t a, b, ostat0, ostat1;
u_int8_t status0 = ATA_S_BUSY, status1 = ATA_S_BUSY;
/* reset channel */
/* get the current status of the devices */
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
DELAY(10);
ostat1 = inb(scp->ioaddr + ATA_STATUS);
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(1);
inb(scp->ioaddr + ATA_STATUS);
outb(scp->altioaddr, ATA_A_IDS | ATA_A_RESET);
DELAY(10000);
outb(scp->altioaddr, ATA_A_IDS);
DELAY(100000);
inb(scp->ioaddr + ATA_ERROR);
DELAY(3000);
scp->devices = 0;
DELAY(10);
ostat0 = inb(scp->ioaddr + ATA_STATUS);
/* in some setups we dont want to test for a slave */
if (scp->flags & ATA_NO_SLAVE)
*mask &= ~0x02;
/*if (bootverbose)*/
ata_printf(scp, -1, "mask=%02x ostat0=%02x ostat2=%02x\n",
*mask, ostat0, ostat1);
/* reset channel */
outb(scp->altioaddr, ATA_A_IDS | ATA_A_RESET);
DELAY(10000);
outb(scp->altioaddr, ATA_A_IDS);
DELAY(100000);
inb(scp->ioaddr + ATA_ERROR);
scp->devices = 0;
/* wait for BUSY to go inactive */
for (timeout = 0; timeout < 310000; timeout++) {
if (status0 & ATA_S_BUSY) {
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(1);
DELAY(10);
status0 = inb(scp->ioaddr + ATA_STATUS);
if (!(status0 & ATA_S_BUSY)) {
/* check for ATAPI signature while its still there */
if (inb(scp->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB &&
inb(scp->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB)
a = inb(scp->ioaddr + ATA_CYL_LSB);
b = inb(scp->ioaddr + ATA_CYL_MSB);
ata_printf(scp, ATA_MASTER, "ATAPI probe a=%02x b=%02x\n", a, b);
if (a == ATAPI_MAGIC_LSB && b == ATAPI_MAGIC_MSB)
scp->devices |= ATA_ATAPI_MASTER;
}
}
if (status1 & ATA_S_BUSY) {
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
DELAY(1);
DELAY(10);
status1 = inb(scp->ioaddr + ATA_STATUS);
if (!(status1 & ATA_S_BUSY)) {
/* check for ATAPI signature while its still there */
if (inb(scp->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB &&
inb(scp->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB)
a = inb(scp->ioaddr + ATA_CYL_LSB);
b = inb(scp->ioaddr + ATA_CYL_MSB);
ata_printf(scp, ATA_SLAVE, "ATAPI probe a=%02x b=%02x\n", a, b);
if (a == ATAPI_MAGIC_LSB && b == ATAPI_MAGIC_MSB)
scp->devices |= ATA_ATAPI_SLAVE;
}
}
@ -1300,31 +1303,42 @@ ata_reset(struct ata_softc *scp, int *mask)
break;
DELAY(100);
}
DELAY(1);
DELAY(10);
outb(scp->altioaddr, ATA_A_4BIT);
if (status0 & ATA_S_BUSY)
*mask &= ~0x01;
if (status1 & ATA_S_BUSY)
*mask &= ~0x02;
if (bootverbose)
/*if (bootverbose)*/
ata_printf(scp, -1, "mask=%02x status0=%02x status1=%02x\n",
*mask, status0, status1);
if (!mask)
return;
if (status0 != 0x00 && !(scp->devices & ATA_ATAPI_MASTER)) {
outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_MASTER));
DELAY(1);
if (ata_testregs(scp))
if (*mask & 0x01 && ostat0 != 0x00 && !(scp->devices & ATA_ATAPI_MASTER)) {
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(10);
outb(scp->ioaddr + ATA_ERROR, 0x58);
outb(scp->ioaddr + ATA_CYL_LSB, 0xa5);
a = inb(scp->ioaddr + ATA_ERROR);
b = inb(scp->ioaddr + ATA_CYL_LSB);
ata_printf(scp, ATA_MASTER, "ATA probe a=%02x b=%02x\n", a, b);
if (a != 0x58 && b == 0xa5)
scp->devices |= ATA_ATA_MASTER;
}
if (status1 != 0x00 && !(scp->devices & ATA_ATAPI_SLAVE)) {
outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_SLAVE));
DELAY(1);
if (ata_testregs(scp))
if (*mask & 0x02 && ostat1 != 0x00 && !(scp->devices & ATA_ATAPI_SLAVE)) {
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
DELAY(10);
outb(scp->ioaddr + ATA_ERROR, 0x58);
outb(scp->ioaddr + ATA_CYL_LSB, 0xa5);
a = inb(scp->ioaddr + ATA_ERROR);
b = inb(scp->ioaddr + ATA_CYL_LSB);
ata_printf(scp, ATA_SLAVE, "ATA probe a=%02x b=%02x\n", a, b);
if (a != 0x58 && b == 0xa5)
scp->devices |= ATA_ATA_SLAVE;
}
ata_printf(scp, -1, "devices=%02x\n", scp->devices);
}
int