Add support for the Intel 810 chipset (ICH type of chips)
Prober support for the VIA 82C686, I finally got the right datasheet. Get rid of atapi_wait, merge it into ata_wait. Avoid a couple of races by using asleep instead of tsleep. Always use 16bit transfers on ISA systems. Clear up the atapi_read/write functions.
This commit is contained in:
parent
87be6e697a
commit
46a37dbac0
@ -133,6 +133,7 @@ ata_isaprobe(device_t dev)
|
||||
if (res) {
|
||||
isa_set_portsize(dev, res);
|
||||
*(int *)device_get_softc(dev) = lun;
|
||||
atadevices[lun]->flags |= ATA_USE_16BIT;
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
@ -197,6 +198,12 @@ ata_pcimatch(device_t dev)
|
||||
case 0x71998086:
|
||||
return "Intel PIIX4 ATA-33 controller";
|
||||
|
||||
case 0x24118086:
|
||||
return "Intel ICH ATA-66 controller";
|
||||
|
||||
case 0x24218086:
|
||||
return "Intel ICH0 ATA-33 controller";
|
||||
|
||||
case 0x522910b9:
|
||||
return "AcerLabs Aladdin ATA-33 controller";
|
||||
|
||||
@ -363,7 +370,18 @@ ata_pciattach(device_t dev)
|
||||
/* set sector size */
|
||||
pci_write_config(dev, 0x60, DEV_BSIZE, 2);
|
||||
pci_write_config(dev, 0x68, DEV_BSIZE, 2);
|
||||
|
||||
/* prepare for ATA-66 on the 82C686 */
|
||||
if (ata_find_dev(dev, 0x06861106))
|
||||
pci_write_config(dev, 0x50,
|
||||
pci_read_config(dev, 0x50, 4) | 0x070f070f, 4);
|
||||
break;
|
||||
|
||||
case 0x00041103: /* HighPoint HPT366 controller */
|
||||
printf("hpt366: cache_line_size=0x%02x latency_timer=0x%02x min_grant=0x%02x max_latency=0x%02x\n",
|
||||
pci_read_config(dev, 0x0c, 1), pci_read_config(dev, 0x0d, 1),
|
||||
pci_read_config(dev, 0x3e, 1), pci_read_config(dev, 0x3f, 1));
|
||||
|
||||
}
|
||||
|
||||
/* now probe the addresse found for "real" ATA/ATAPI hardware */
|
||||
@ -809,30 +827,25 @@ ata_reinit(struct ata_softc *scp)
|
||||
int32_t
|
||||
ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask)
|
||||
{
|
||||
u_int8_t status;
|
||||
u_int32_t timeout = 0;
|
||||
|
||||
|
||||
DELAY(1);
|
||||
while (timeout <= 5000000) { /* timeout 5 secs */
|
||||
status = inb(scp->ioaddr + ATA_STATUS);
|
||||
while (timeout < 5000000) { /* timeout 5 secs */
|
||||
scp->status = inb(scp->ioaddr + ATA_STATUS);
|
||||
|
||||
/* if drive fails status, reselect the drive just to be sure */
|
||||
if (status == 0xff) {
|
||||
printf("ata%d: %s: no status, reselecting device\n",
|
||||
if (scp->status == 0xff) {
|
||||
printf("ata%d-%s: no status, reselecting device\n",
|
||||
scp->lun, device?"slave":"master");
|
||||
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device);
|
||||
DELAY(1);
|
||||
status = inb(scp->ioaddr + ATA_STATUS);
|
||||
}
|
||||
if (status == 0xff)
|
||||
return -1;
|
||||
scp->status = status;
|
||||
if (!(status & ATA_S_BUSY)) {
|
||||
if (status & ATA_S_ERROR)
|
||||
scp->error = inb(scp->ioaddr + ATA_ERROR);
|
||||
if ((status & mask) == mask)
|
||||
return (status & ATA_S_ERROR);
|
||||
scp->status = inb(scp->ioaddr + ATA_STATUS);
|
||||
}
|
||||
|
||||
/* are we done ? */
|
||||
if (!(scp->status & ATA_S_BUSY))
|
||||
break;
|
||||
|
||||
if (timeout > 1000) {
|
||||
timeout += 1000;
|
||||
DELAY(1000);
|
||||
@ -841,9 +854,27 @@ ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask)
|
||||
timeout += 10;
|
||||
DELAY(10);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (scp->status & ATA_S_ERROR)
|
||||
scp->error = inb(scp->ioaddr + ATA_ERROR);
|
||||
if (timeout >= 5000000)
|
||||
return -1;
|
||||
if (!mask)
|
||||
return (scp->status & ATA_S_ERROR);
|
||||
|
||||
/* Wait 50 msec for bits wanted. */
|
||||
timeout = 5000;
|
||||
while (timeout--) {
|
||||
scp->status = inb(scp->ioaddr + ATA_STATUS);
|
||||
if ((scp->status & mask) == mask) {
|
||||
if (scp->status & ATA_S_ERROR)
|
||||
scp->error = inb(scp->ioaddr + ATA_ERROR);
|
||||
return (scp->status & ATA_S_ERROR);
|
||||
}
|
||||
DELAY (10);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t
|
||||
ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
|
||||
@ -876,8 +907,9 @@ ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
|
||||
if (scp->active != ATA_IDLE)
|
||||
printf("WARNING: WAIT_INTR active=%s\n", active2str(scp->active));
|
||||
scp->active = ATA_WAIT_INTR;
|
||||
asleep((caddr_t)scp, PRIBIO, "atacmd", 500);
|
||||
outb(scp->ioaddr + ATA_CMD, command);
|
||||
if (tsleep((caddr_t)scp, PRIBIO, "atacmd", 500)) {
|
||||
if (await(PRIBIO, 500)) {
|
||||
printf("ata_command: timeout waiting for interrupt\n");
|
||||
scp->active = ATA_IDLE;
|
||||
return -1;
|
||||
|
@ -148,6 +148,7 @@ struct ata_softc {
|
||||
int32_t flags; /* controller flags */
|
||||
#define ATA_DMA_ACTIVE 0x01
|
||||
#define ATA_ATAPI_DMA_RO 0x02
|
||||
#define ATA_USE_16BIT 0x04
|
||||
|
||||
int32_t devices; /* what is present */
|
||||
#define ATA_ATA_MASTER 0x01
|
||||
|
@ -498,15 +498,15 @@ ad_transfer(struct ad_request *request)
|
||||
printf("ad_transfer: timeout waiting for DRQ");
|
||||
|
||||
/* output the data */
|
||||
#ifdef ATA_16BIT_ONLY
|
||||
outsw(adp->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)request->data + request->donecount),
|
||||
request->currentsize / sizeof(int16_t));
|
||||
#else
|
||||
outsl(adp->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)request->data + request->donecount),
|
||||
request->currentsize / sizeof(int32_t));
|
||||
#endif
|
||||
if (adp->controller->flags & ATA_USE_16BIT)
|
||||
outsw(adp->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)request->data + request->donecount),
|
||||
request->currentsize / sizeof(int16_t));
|
||||
else
|
||||
outsl(adp->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)request->data + request->donecount),
|
||||
request->currentsize / sizeof(int32_t));
|
||||
|
||||
request->bytecount -= request->currentsize;
|
||||
}
|
||||
|
||||
@ -589,15 +589,15 @@ ad_interrupt(struct ad_request *request)
|
||||
}
|
||||
|
||||
/* data ready, read in */
|
||||
#ifdef ATA_16BIT_ONLY
|
||||
insw(adp->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)request->data + request->donecount),
|
||||
request->currentsize / sizeof(int16_t));
|
||||
#else
|
||||
insl(adp->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)request->data + request->donecount),
|
||||
request->currentsize / sizeof(int32_t));
|
||||
#endif
|
||||
if (adp->controller->flags & ATA_USE_16BIT)
|
||||
insw(adp->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)request->data + request->donecount),
|
||||
request->currentsize / sizeof(int16_t));
|
||||
else
|
||||
insl(adp->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)request->data + request->donecount),
|
||||
request->currentsize / sizeof(int32_t));
|
||||
|
||||
request->bytecount -= request->currentsize;
|
||||
}
|
||||
|
||||
|
@ -98,16 +98,20 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
|
||||
switch (scp->chiptype) {
|
||||
|
||||
case 0x71118086: /* Intel PIIX4 */
|
||||
case 0x71998086: /* Intel PIIX4 */
|
||||
case 0x71998086: /* Intel PIIX4e */
|
||||
case 0x24118086: /* Intel ICH */
|
||||
case 0x24218086: /* Intel ICH0 */
|
||||
if (udmamode >= 2) {
|
||||
int32_t mask48, new48;
|
||||
|
||||
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
|
||||
ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
|
||||
if (bootverbose)
|
||||
printf("ata%d-%s: %s setting up UDMA2 mode on PIIX4 chip\n",
|
||||
printf("ata%d-%s: %s setting up UDMA2 mode on %s chip\n",
|
||||
scp->lun, (device == ATA_MASTER) ? "master" : "slave",
|
||||
(error) ? "failed" : "success");
|
||||
(error) ? "failed" : "success",
|
||||
(scp->chiptype == 0x24118086) ? "ICH" :
|
||||
(scp->chiptype == 0x24218086) ? "ICH0" :"PIIX4");
|
||||
if (!error) {
|
||||
mask48 = (1 << devno) + (3 << (16 + (devno << 2)));
|
||||
new48 = (1 << devno) + (2 << (16 + (devno << 2)));
|
||||
@ -143,10 +147,12 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
|
||||
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
|
||||
ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
|
||||
if (bootverbose)
|
||||
printf("ata%d-%s: %s setting up WDMA2 mode on PIIX%s chip\n",
|
||||
printf("ata%d-%s: %s setting up WDMA2 mode on %s chip\n",
|
||||
scp->lun, (device == ATA_MASTER) ? "master" : "slave",
|
||||
(error) ? "failed" : "success",
|
||||
(scp->chiptype == 0x70108086) ? "3" : "4");
|
||||
(scp->chiptype == 0x70108086) ? "PIIX3" :
|
||||
(scp->chiptype == 0x24118086) ? "ICH" :
|
||||
(scp->chiptype == 0x24218086) ? "ICH0" :"PIIX4");
|
||||
if (!error) {
|
||||
if (device == ATA_MASTER) {
|
||||
mask40 = 0x0000330f;
|
||||
@ -251,16 +257,44 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
|
||||
|
||||
case 0x05711106: /* VIA 82C571, 82C586, 82C596 & 82C686 */
|
||||
case 0x74091022: /* AMD 756 */
|
||||
/* UDMA4 mode only on 82C686 and AMD 756 */
|
||||
if ((udmamode >= 4 && ata_find_dev(scp->dev, 0x06861106)) ||
|
||||
(udmamode >= 4 && scp->chiptype == 0x74091022)) {
|
||||
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
|
||||
/* UDMA modes on 82C686 */
|
||||
if (ata_find_dev(scp->dev, 0x06861106)) {
|
||||
if (udmamode >= 4) {
|
||||
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
|
||||
ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
|
||||
if (bootverbose)
|
||||
printf("ata%d-%s: %s setting up UDMA4 mode on VIA chip\n",
|
||||
scp->lun, (device == ATA_MASTER) ? "master":"slave",
|
||||
(error) ? "failed" : "success");
|
||||
if (!error) {
|
||||
pci_write_config(scp->dev, 0x53 - devno, 0xe8, 1);
|
||||
scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA4;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (udmamode >= 2) {
|
||||
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
|
||||
ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
|
||||
if (bootverbose)
|
||||
printf("ata%d-%s: %s setting up UDMA2 mode on VIA chip\n",
|
||||
scp->lun, (device == ATA_MASTER) ? "master":"slave",
|
||||
(error) ? "failed" : "success");
|
||||
if (!error) {
|
||||
pci_write_config(scp->dev, 0x53 - devno, 0xea, 1);
|
||||
scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA2;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* UDMA4 mode on AMD 756 */
|
||||
if (udmamode >= 4 && scp->chiptype == 0x74091022) {
|
||||
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
|
||||
ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
|
||||
if (bootverbose)
|
||||
printf("ata%d-%s: %s setting up UDMA4 mode on %s chip\n",
|
||||
printf("ata%d-%s: %s setting up UDMA4 mode on AMD chip\n",
|
||||
scp->lun, (device == ATA_MASTER) ? "master":"slave",
|
||||
(error) ? "failed" : "success",
|
||||
(scp->chiptype == 0x74091022) ? "AMD" : "VIA");
|
||||
(error) ? "failed" : "success");
|
||||
if (!error) {
|
||||
pci_write_config(scp->dev, 0x53 - devno, 0xc3, 1);
|
||||
scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA4;
|
||||
@ -268,11 +302,10 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
|
||||
}
|
||||
}
|
||||
|
||||
/* UDMA2 mode only on 82C586 > rev1, 82C596, 82C686, AMD 756 */
|
||||
/* UDMA2 mode only on 82C586 > rev1, 82C596, AMD 756 */
|
||||
if ((udmamode >= 2 && ata_find_dev(scp->dev, 0x05861106) &&
|
||||
pci_read_config(scp->dev, 0x08, 1) >= 0x01) ||
|
||||
(udmamode >= 2 && ata_find_dev(scp->dev, 0x05961106)) ||
|
||||
(udmamode >= 2 && ata_find_dev(scp->dev, 0x06861106)) ||
|
||||
(udmamode >= 2 && scp->chiptype == 0x74091022)) {
|
||||
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
|
||||
ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
|
||||
@ -288,7 +321,6 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
|
||||
}
|
||||
}
|
||||
if (wdmamode >= 2 && apiomode >= 4) {
|
||||
/* set WDMA2 mode timing */
|
||||
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
|
||||
ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
|
||||
if (bootverbose)
|
||||
|
@ -56,7 +56,6 @@ static void atapi_timeout(struct atapi_request *request);
|
||||
static int8_t *atapi_type(int32_t);
|
||||
static int8_t *atapi_cmd2str(u_int8_t);
|
||||
static int8_t *atapi_skey2str(u_int8_t);
|
||||
static int32_t atapi_wait(struct atapi_softc *, u_int8_t);
|
||||
static void atapi_init(void);
|
||||
|
||||
/* extern references */
|
||||
@ -208,11 +207,11 @@ atapi_getparam(struct atapi_softc *atp)
|
||||
if (ata_command(atp->controller, atp->unit, ATA_C_ATAPI_IDENTIFY,
|
||||
0, 0, 0, 0, 0, ATA_WAIT_INTR))
|
||||
return -1;
|
||||
if (atapi_wait(atp, ATA_S_DRQ))
|
||||
if (ata_wait(atp->controller, atp->unit, ATA_S_DRQ))
|
||||
return -1;
|
||||
insw(atp->controller->ioaddr + ATA_DATA, buffer,
|
||||
sizeof(buffer)/sizeof(int16_t));
|
||||
if (atapi_wait(atp, 0))
|
||||
if (ata_wait(atp->controller, atp->unit, 0))
|
||||
return -1;
|
||||
if (!(atapi_parm = malloc(sizeof(struct atapi_params), M_ATAPI, M_NOWAIT)))
|
||||
return -1;
|
||||
@ -254,6 +253,10 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
|
||||
|
||||
/* append onto controller queue and try to start controller */
|
||||
s = splbio();
|
||||
|
||||
/* if not using callbacks, prepare to sleep for this request */
|
||||
if (!callback)
|
||||
asleep((caddr_t)request, PRIBIO, "atprq", 0);
|
||||
TAILQ_INSERT_TAIL(&atp->controller->atapi_queue, request, chain);
|
||||
if (atp->controller->active == ATA_IDLE)
|
||||
ata_start(atp->controller);
|
||||
@ -265,7 +268,7 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
|
||||
}
|
||||
|
||||
/* wait for request to complete */
|
||||
tsleep((caddr_t)request, PRIBIO, "atprq", 0);
|
||||
await(PRIBIO, 0);
|
||||
splx(s);
|
||||
error = request->error;
|
||||
free(request, M_ATAPI);
|
||||
@ -375,13 +378,16 @@ atapi_interrupt(struct atapi_request *request)
|
||||
if (atp->flags & ATAPI_F_DMA_USED)
|
||||
dma_stat = ata_dmadone(atp->controller);
|
||||
|
||||
if (atapi_wait(atp, 0) < 0) {
|
||||
/* is this needed anymore ?? SOS XXX */
|
||||
#if NOT_ANY_MORE
|
||||
if (ata_wait(atp->controller, atp->unit, 0) < 0) {
|
||||
printf("%s: timeout waiting for status", atp->devname);
|
||||
atp->flags &= ~ATAPI_F_DMA_USED;
|
||||
request->result = inb(atp->controller->ioaddr + ATA_ERROR) |
|
||||
ATAPI_SK_RESERVED;
|
||||
goto op_finished;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (atp->flags & ATAPI_F_DMA_USED) {
|
||||
atp->flags &= ~ATAPI_F_DMA_USED;
|
||||
@ -552,64 +558,58 @@ static void
|
||||
atapi_read(struct atapi_request *request, int32_t length)
|
||||
{
|
||||
int8_t **buffer = (int8_t **)&request->data;
|
||||
int32_t size = min(request->bytecount, length);
|
||||
int32_t resid;
|
||||
|
||||
if (request->ccb[0] == ATAPI_REQUEST_SENSE)
|
||||
*buffer = (int8_t *)&request->sense;
|
||||
|
||||
if (request->device->controller->flags & ATA_USE_16BIT ||
|
||||
(size % sizeof(int32_t)))
|
||||
insw(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), size / sizeof(int16_t));
|
||||
else
|
||||
insl(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), size / sizeof(int32_t));
|
||||
|
||||
if (request->bytecount < length) {
|
||||
printf("%s: read data overrun %d/%d\n",
|
||||
request->device->devname, length, request->bytecount);
|
||||
#ifdef ATA_16BIT_ONLY
|
||||
insw(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), request->bytecount/sizeof(int16_t));
|
||||
#else
|
||||
insl(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), request->bytecount/sizeof(int32_t));
|
||||
#endif
|
||||
|
||||
for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
|
||||
inw(request->device->controller->ioaddr + ATA_DATA);
|
||||
*buffer += request->bytecount;
|
||||
request->bytecount = 0;
|
||||
}
|
||||
else {
|
||||
insw(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), length / sizeof(int16_t));
|
||||
*buffer += length;
|
||||
request->bytecount -= length;
|
||||
}
|
||||
*buffer += size;
|
||||
request->bytecount -= size;
|
||||
}
|
||||
|
||||
static void
|
||||
atapi_write(struct atapi_request *request, int32_t length)
|
||||
{
|
||||
int8_t **buffer = (int8_t **)&request->data;
|
||||
int32_t size = min(request->bytecount, length);
|
||||
int32_t resid;
|
||||
|
||||
if (request->ccb[0] == ATAPI_REQUEST_SENSE)
|
||||
*buffer = (int8_t *)&request->sense;
|
||||
|
||||
if (request->device->controller->flags & ATA_USE_16BIT ||
|
||||
(size % sizeof(int32_t)))
|
||||
outsw(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), size / sizeof(int16_t));
|
||||
else
|
||||
outsl(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), size / sizeof(int32_t));
|
||||
|
||||
if (request->bytecount < length) {
|
||||
printf("%s: write data underrun %d/%d\n",
|
||||
request->device->devname, length, request->bytecount);
|
||||
#ifdef ATA_16BIT_ONLY
|
||||
outsw(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), request->bytecount/sizeof(int16_t));
|
||||
#else
|
||||
outsl(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), request->bytecount/sizeof(int32_t));
|
||||
#endif
|
||||
|
||||
for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
|
||||
outw(request->device->controller->ioaddr + ATA_DATA, 0);
|
||||
*buffer += request->bytecount;
|
||||
request->bytecount = 0;
|
||||
}
|
||||
else {
|
||||
outsw(request->device->controller->ioaddr + ATA_DATA,
|
||||
(void *)((uintptr_t)*buffer), length / sizeof(int16_t));
|
||||
*buffer += length;
|
||||
request->bytecount -= length;
|
||||
}
|
||||
*buffer += size;
|
||||
request->bytecount -= size;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -731,41 +731,6 @@ atapi_skey2str(u_int8_t skey)
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t
|
||||
atapi_wait(struct atapi_softc *atp, u_int8_t mask)
|
||||
{
|
||||
u_int32_t timeout = 0;
|
||||
|
||||
DELAY(1);
|
||||
while (timeout++ <= 500000) { /* timeout 5 secs */
|
||||
atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS);
|
||||
|
||||
/* if drive fails status, reselect the drive just to be sure */
|
||||
if (atp->controller->status == 0xff) {
|
||||
outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit);
|
||||
DELAY(1);
|
||||
atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS);
|
||||
}
|
||||
if (!(atp->controller->status & ATA_S_BUSY) &&
|
||||
(atp->controller->status & ATA_S_READY))
|
||||
break;
|
||||
DELAY (10);
|
||||
}
|
||||
if (timeout <= 0)
|
||||
return -1;
|
||||
if (!mask)
|
||||
return (atp->controller->status & ATA_S_ERROR);
|
||||
|
||||
/* Wait 50 msec for bits wanted. */
|
||||
for (timeout=5000; timeout>0; --timeout) {
|
||||
atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS);
|
||||
if ((atp->controller->status & mask) == mask)
|
||||
return (atp->controller->status & ATA_S_ERROR);
|
||||
DELAY (10);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
atapi_init(void)
|
||||
{
|
||||
|
@ -966,10 +966,13 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
break;
|
||||
|
||||
case CDRIOCCLOSEDISK:
|
||||
if (!(cdp->flags & F_WRITTEN) || !(cdp->flags & F_DISK_OPEN)) {
|
||||
if (!(cdp->flags & F_DISK_OPEN)) {
|
||||
error = EINVAL;
|
||||
printf("acd%d: sequence error (nothing to close)\n", cdp->lun);
|
||||
}
|
||||
else if (!(cdp->flags & F_WRITTEN)) {
|
||||
cdp->flags &= ~(F_DISK_OPEN | F_TRACK_OPEN);
|
||||
}
|
||||
else {
|
||||
error = acd_close_disk(cdp);
|
||||
cdp->flags &= ~(F_WRITTEN | F_DISK_OPEN | F_TRACK_OPEN);
|
||||
|
Loading…
Reference in New Issue
Block a user