Try to narrow down the race window on HW that does not have ways to

poll for which channel actually pulled the irq line.
This commit is contained in:
sos 2004-08-05 21:13:41 +00:00
parent 54e7375090
commit 6016d1505d
7 changed files with 46 additions and 49 deletions

View File

@ -231,7 +231,6 @@ ata_detach(device_t dev)
int
ata_reinit(struct ata_channel *ch)
{
struct ata_request *request = ch->running;
int devices, misdev, newdev;
if (!ch->r_irq)
@ -242,10 +241,8 @@ ata_reinit(struct ata_channel *ch)
ata_printf(ch, -1, "reiniting channel ..\n");
ATA_FORCELOCK_CH(ch);
ch->flags |= ATA_IMMEDIATE_MODE;
ch->running = NULL;
devices = ch->devices;
ch->hw.reset(ch);
ATA_UNLOCK_CH(ch);
if (bootverbose)
ata_printf(ch, -1, "resetting done ..\n");
@ -254,10 +251,6 @@ ata_reinit(struct ata_channel *ch)
if ((misdev = devices & ~ch->devices)) {
if ((misdev & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) &&
ch->device[MASTER].detach) {
if (request && (request->device == &ch->device[MASTER])) {
request->result = ENXIO;
request->retries = 0;
}
ch->device[MASTER].detach(&ch->device[MASTER]);
ata_fail_requests(ch, &ch->device[MASTER]);
free(ch->device[MASTER].param, M_ATA);
@ -265,10 +258,6 @@ ata_reinit(struct ata_channel *ch)
}
if ((misdev & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) &&
ch->device[SLAVE].detach) {
if (request && (request->device == &ch->device[SLAVE])) {
request->result = ENXIO;
request->retries = 0;
}
ch->device[SLAVE].detach(&ch->device[SLAVE]);
ata_fail_requests(ch, &ch->device[SLAVE]);
free(ch->device[SLAVE].param, M_ATA);
@ -276,6 +265,9 @@ ata_reinit(struct ata_channel *ch)
}
}
ch->running = NULL;
ATA_UNLOCK_CH(ch);
/* identify what is present on the channel now */
ata_identify_devices(ch);

View File

@ -297,8 +297,9 @@ struct ata_dma {
u_int32_t max_iosize; /* DMA engine max IO size */
u_int32_t cur_iosize; /* DMA engine current IO size */
int flags;
#define ATA_DMA_ACTIVE 0x01 /* DMA transfer in progress */
#define ATA_DMA_READ 0x02 /* transaction is a read */
#define ATA_DMA_READ 0x01 /* transaction is a read */
#define ATA_DMA_LOADED 0x02 /* DMA tables etc loaded */
#define ATA_DMA_ACTIVE 0x04 /* DMA transfer in progress */
void (*alloc)(struct ata_channel *ch);
void (*free)(struct ata_channel *ch);

View File

@ -1278,16 +1278,16 @@ ata_promise_chipinit(device_t dev)
break;
case PRMIO:
if (ctlr->r_res1)
bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1);
// if (ctlr->r_res1)
// bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1,ctlr->r_res1);
ctlr->r_type1 = SYS_RES_MEMORY;
ctlr->r_rid1 = 0x20;
ctlr->r_rid1 = PCIR_BAR(4);
if (!(ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1,
&ctlr->r_rid1, RF_ACTIVE)))
return ENXIO;
ctlr->r_type2 = SYS_RES_MEMORY;
ctlr->r_rid2 = 0x1c;
ctlr->r_rid2 = PCIR_BAR(3);
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
&ctlr->r_rid2, RF_ACTIVE)))
return ENXIO;
@ -1433,12 +1433,14 @@ ata_promise_sx4_intr(void *data)
static int
ata_promise_mio_dmastart(struct ata_channel *ch)
{
ch->flags |= ATA_DMA_ACTIVE;
return 0;
}
static int
ata_promise_mio_dmastop(struct ata_channel *ch)
{
ch->flags &= ~ATA_DMA_ACTIVE;
/* get status XXX SOS */
return 0;
}
@ -1777,6 +1779,7 @@ ata_promise_new_dmastart(struct ata_channel *ch)
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) |
ATA_BMCMD_START_STOP);
ch->flags |= ATA_DMA_ACTIVE;
return 0;
}
@ -1795,6 +1798,7 @@ ata_promise_new_dmastop(struct ata_channel *ch)
error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT);
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
ch->flags &= ~ATA_DMA_ACTIVE;
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR);
return error;
}
@ -2057,7 +2061,7 @@ ata_sii_chipinit(device_t dev)
}
ctlr->r_type2 = SYS_RES_MEMORY;
ctlr->r_rid2 = 0x24;
ctlr->r_rid2 = PCIR_BAR(5);
if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
&ctlr->r_rid2, RF_ACTIVE)))
return ENXIO;

View File

@ -265,8 +265,7 @@ ata_dmaload(struct ata_device *atadev, caddr_t data, int32_t count, int dir)
dir ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
ch->dma->cur_iosize = count;
ch->dma->flags = dir ? (ATA_DMA_ACTIVE | ATA_DMA_READ) : ATA_DMA_ACTIVE;
ch->dma->flags = dir ? (ATA_DMA_LOADED | ATA_DMA_READ) : ATA_DMA_LOADED;
return 0;
}
@ -281,7 +280,6 @@ ata_dmaunload(struct ata_channel *ch)
bus_dmamap_unload(ch->dma->ddmatag, ch->dma->ddmamap);
ch->dma->cur_iosize = 0;
ch->dma->flags = 0;
ch->dma->flags &= ~ATA_DMA_LOADED;
return 0;
}

View File

@ -80,9 +80,6 @@ ata_generic_transaction(struct ata_request *request)
return ATA_OP_FINISHED;
}
/* record the request as running */
ch->running = request;
ATA_DEBUG_RQ(request, "transaction");
/* disable ATAPI DMA writes if HW doesn't support it */
@ -120,10 +117,8 @@ ata_generic_transaction(struct ata_request *request)
else
printf("ATAPI_RESET timeout\n");
if (request->status & ATA_S_ERROR) {
if (request->status & ATA_S_ERROR)
request->error = ATA_IDX_INB(ch, ATA_ERROR);
//request->result = EIO;
}
break;
}
@ -139,7 +134,8 @@ ata_generic_transaction(struct ata_request *request)
}
}
/* return and wait for interrupt */
/* record the request as running and return for interrupt */
ch->running = request;
return ATA_OP_CONTINUES;
/* ATA DMA data transfer commands */
@ -168,7 +164,8 @@ ata_generic_transaction(struct ata_request *request)
break;
}
/* return and wait for interrupt */
/* record the request as running and return for interrupt */
ch->running = request;
return ATA_OP_CONTINUES;
/* ATAPI PIO commands */
@ -192,8 +189,10 @@ ata_generic_transaction(struct ata_request *request)
}
/* command interrupt device ? just return and wait for interrupt */
if ((request->device->param->config & ATA_DRQ_MASK) == ATA_DRQ_INTR)
if ((request->device->param->config & ATA_DRQ_MASK) == ATA_DRQ_INTR) {
ch->running = request;
return ATA_OP_CONTINUES;
}
/* wait for ready to write ATAPI command block */
{
@ -224,7 +223,8 @@ ata_generic_transaction(struct ata_request *request)
(request->device->param->config & ATA_PROTO_MASK) ==
ATA_PROTO_ATAPI_12 ? 6 : 8);
/* return and wait for interrupt */
/* record the request as running and return for interrupt */
ch->running = request;
return ATA_OP_CONTINUES;
case ATA_R_ATAPI|ATA_R_DMA:
@ -289,14 +289,14 @@ ata_generic_transaction(struct ata_request *request)
break;
}
/* return and wait for interrupt */
/* record the request as running and return for interrupt */
ch->running = request;
return ATA_OP_CONTINUES;
}
/* request finish here */
if (ch->dma->flags & ATA_DMA_ACTIVE)
if (ch->dma->flags & ATA_DMA_LOADED)
ch->dma->unload(ch);
ch->running = NULL;
return ATA_OP_FINISHED;
}

View File

@ -454,6 +454,7 @@ ata_pci_dmastart(struct ata_channel *ch)
(ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) |
((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) |
ATA_BMCMD_START_STOP);
ch->dma->flags |= ATA_DMA_ACTIVE;
return 0;
}
@ -465,6 +466,7 @@ ata_pci_dmastop(struct ata_channel *ch)
error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
ch->dma->flags &= ~ATA_DMA_ACTIVE;
ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR);
return error;
}

View File

@ -160,15 +160,8 @@ ata_start(struct ata_channel *ch)
if (ch->flags & ATA_IMMEDIATE_MODE)
return;
/* lock the ATA HW for this request */
mtx_lock(&ch->queue_mtx);
ch->locking(ch, ATA_LF_LOCK);
if (!ATA_LOCK_CH(ch)) {
mtx_unlock(&ch->queue_mtx);
return;
}
/* if we dont have any work, ask the subdriver(s) */
mtx_lock(&ch->queue_mtx);
if (TAILQ_EMPTY(&ch->ata_queue)) {
mtx_unlock(&ch->queue_mtx);
if (ch->device[MASTER].start)
@ -177,7 +170,15 @@ ata_start(struct ata_channel *ch)
ch->device[SLAVE].start(&ch->device[SLAVE]);
mtx_lock(&ch->queue_mtx);
}
/* if we have work todo, try to lock the ATA HW and start transaction */
if ((request = TAILQ_FIRST(&ch->ata_queue))) {
ch->locking(ch, ATA_LF_LOCK);
if (!ATA_LOCK_CH(ch)) {
mtx_unlock(&ch->queue_mtx);
return;
}
TAILQ_REMOVE(&ch->ata_queue, request, chain);
mtx_unlock(&ch->queue_mtx);
@ -192,15 +193,14 @@ ata_start(struct ata_channel *ch)
/* kick HW into action and wait for interrupt if it flies*/
if (ch->hw.transaction(request) == ATA_OP_CONTINUES)
return;
}
/* unlock ATA channel HW */
ATA_UNLOCK_CH(ch);
ch->locking(ch, ATA_LF_UNLOCK);
/* unlock ATA channel HW */
ATA_UNLOCK_CH(ch);
ch->locking(ch, ATA_LF_UNLOCK);
/* if we have a request here it failed and should be completed */
if (request)
/* finish up this (failed) request */
ata_finish(request);
}
else
mtx_unlock(&ch->queue_mtx);
}