Beispiel #1
0
static int
ida_wait(struct ida_softc *ida, struct ida_qcb *qcb)
{
	struct ida_qcb *qcb_done = NULL;
	bus_addr_t completed;
	int delay;

	if (ida->flags & IDA_INTERRUPTS) {
		if (tsleep((caddr_t)qcb, 0, "idacmd", 5 * hz))
			return (ETIMEDOUT);
		return (0);
	}

again:
	delay = 5 * 1000 * 100;			/* 5 sec delay */
	while ((completed = ida->cmd.done(ida)) == 0) {
		if (delay-- == 0)
			return (ETIMEDOUT);
		DELAY(10);
	}

	qcb_done = idahwqcbptov(ida, completed & ~3);
	if (qcb_done != qcb)
		goto again;
	ida_done(ida, qcb);
	return (0);
}
Beispiel #2
0
void
ida_intr(void *data)
{
	struct ida_softc *ida;
	struct ida_qcb *qcb;
	bus_addr_t completed;

	ida = (struct ida_softc *)data;

	mtx_lock(&ida->lock);
	if (ida->cmd.int_pending(ida) == 0) {
		mtx_unlock(&ida->lock);
		return;				/* not our interrupt */
	}

	while ((completed = ida->cmd.done(ida)) != 0) {
		qcb = idahwqcbptov(ida, completed & ~3);

		if (qcb == NULL || qcb->state != QCB_ACTIVE) {
			device_printf(ida->dev,
			    "ignoring completion %jx\n", (intmax_t)completed);
			continue;
		}
		/* Handle "Bad Command List" errors. */
		if ((completed & 3) && (qcb->hwqcb->req.error == 0))
			qcb->hwqcb->req.error = CMD_REJECTED;
		ida_done(ida, qcb);
	}
	ida_startio(ida);
	mtx_unlock(&ida->lock);
}
Beispiel #3
0
static int
ida_wait(struct ida_softc *ida, struct ida_qcb *qcb)
{
	struct ida_qcb *qcb_done = NULL;
	bus_addr_t completed;
	int delay;

	if (!dumping)
		mtx_assert(&ida->lock, MA_OWNED);
	if (ida->flags & IDA_INTERRUPTS) {
		if (mtx_sleep(qcb, &ida->lock, PRIBIO, "idacmd", 5 * hz)) {
			qcb->state = QCB_TIMEDOUT;
			return (ETIMEDOUT);
		}
		return (0);
	}

again:
	delay = 5 * 1000 * 100;			/* 5 sec delay */
	while ((completed = ida->cmd.done(ida)) == 0) {
		if (delay-- == 0) {
			qcb->state = QCB_TIMEDOUT;
			return (ETIMEDOUT);
		}
		DELAY(10);
	}

	qcb_done = idahwqcbptov(ida, completed & ~3);
	if (qcb_done != qcb)
		goto again;
	ida_done(ida, qcb);
	return (0);
}
Beispiel #4
0
static void
ida_data_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
{
	struct ida_hardware_qcb *hwqcb;
	struct ida_softc *ida;
	struct ida_qcb *qcb;
	bus_dmasync_op_t op;
	int i;

	qcb = arg;
	ida = qcb->ida;
	if (!dumping)
		mtx_assert(&ida->lock, MA_OWNED);
	if (error) {
		qcb->error = error;
		ida_done(ida, qcb);
		return;
	}

	hwqcb = qcb->hwqcb;
	hwqcb->hdr.size = htole16((sizeof(struct ida_req) +
	    sizeof(struct ida_sgb) * IDA_NSEG) >> 2);

	for (i = 0; i < nsegments; i++) {
		hwqcb->seg[i].addr = htole32(segs[i].ds_addr);
		hwqcb->seg[i].length = htole32(segs[i].ds_len);
	}
	hwqcb->req.sgcount = nsegments;
	if (qcb->flags & DMA_DATA_TRANSFER) {
		switch (qcb->flags & DMA_DATA_TRANSFER) {
		case DMA_DATA_TRANSFER:
			op = BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE;
			break;
		case DMA_DATA_IN:
			op = BUS_DMASYNC_PREREAD;
			break;
		default:
			KASSERT((qcb->flags & DMA_DATA_TRANSFER) ==
			    DMA_DATA_OUT, ("bad DMA data flags"));
			op = BUS_DMASYNC_PREWRITE;
			break;
		}
		bus_dmamap_sync(ida->buffer_dmat, qcb->dmamap, op);
	}
	bus_dmamap_sync(ida->hwqcb_dmat, ida->hwqcb_dmamap,
	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);

	STAILQ_INSERT_TAIL(&ida->qcb_queue, qcb, link.stqe);
	ida_start(ida);
	ida->flags &= ~IDA_QFROZEN;
}
Beispiel #5
0
static void
ida_startio(struct ida_softc *ida)
{
	struct ida_hardware_qcb *hwqcb;
	struct ida_qcb *qcb;
	struct idad_softc *drv;
	struct bio *bp;
	int error;

	mtx_assert(&ida->lock, MA_OWNED);
	for (;;) {
		if (ida->flags & IDA_QFROZEN)
			return;
		bp = bioq_first(&ida->bio_queue);
		if (bp == NULL)
			return;				/* no more buffers */

		qcb = ida_get_qcb(ida);
		if (qcb == NULL)
			return;				/* out of resources */

		bioq_remove(&ida->bio_queue, bp);
		qcb->buf = bp;
		qcb->flags = bp->bio_cmd == BIO_READ ? DMA_DATA_IN : DMA_DATA_OUT;

		hwqcb = qcb->hwqcb;
		drv = bp->bio_driver1;
		hwqcb->hdr.drive = drv->drive;
		hwqcb->req.blkno = bp->bio_pblkno;
		hwqcb->req.bcount = howmany(bp->bio_bcount, DEV_BSIZE);
		hwqcb->req.command = bp->bio_cmd == BIO_READ ? CMD_READ : CMD_WRITE;

		error = ida_map_qcb(ida, qcb, bp->bio_data, bp->bio_bcount);
		if (error) {
			qcb->error = error;
			ida_done(ida, qcb);
		}
	}
}
Beispiel #6
0
void
ida_intr(void *data)
{
	struct ida_softc *ida;
	struct ida_qcb *qcb;
	bus_addr_t completed;

	ida = (struct ida_softc *)data;

	if (ida->cmd.int_pending(ida) == 0)
		return;				/* not our interrupt */

	while ((completed = ida->cmd.done(ida)) != 0) {
		qcb = idahwqcbptov(ida, completed & ~3);

		if (qcb == NULL || qcb->state != QCB_ACTIVE) {
			device_printf(ida->dev,
			    "ignoring completion %jx\n", (uintmax_t)completed);
			continue;
		}
		ida_done(ida, qcb);
	}
	ida_start(ida);
}