Exemple #1
0
/*
 * should switch out command type; may be status, not just I/O.
 */
static void
ida_done(struct ida_softc *ida, struct ida_qcb *qcb)
{
	int error = 0;

	/*
	 * finish up command
	 */
	if (qcb->flags & DMA_DATA_TRANSFER) {
		bus_dmasync_op_t op;

		op = qcb->flags & DMA_DATA_IN ?
		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE;
		bus_dmamap_sync(ida->buffer_dmat, qcb->dmamap, op);
		bus_dmamap_unload(ida->buffer_dmat, qcb->dmamap);
	}

	if (qcb->hwqcb->req.error & SOFT_ERROR)
		device_printf(ida->dev, "soft error\n");
	if (qcb->hwqcb->req.error & HARD_ERROR) {
		error = 1;
		device_printf(ida->dev, "hard error\n");
	}
	if (qcb->hwqcb->req.error & CMD_REJECTED) {
		error = 1;
		device_printf(ida->dev, "invalid request\n");
	}

	if (qcb->flags & IDA_COMMAND) {
		if (ida->flags & IDA_INTERRUPTS)
			wakeup(qcb);
	} else {
		if (error)
			qcb->bio->bio_buf->b_flags |= B_ERROR;
		idad_intr(qcb->bio);
	}

	qcb->state = QCB_FREE;
	SLIST_INSERT_HEAD(&ida->free_qcbs, qcb, link.sle);
	ida_construct_qcb(ida);
}
Exemple #2
0
/*
 * should switch out command type; may be status, not just I/O.
 */
static void
ida_done(struct ida_softc *ida, struct ida_qcb *qcb)
{
	bus_dmasync_op_t op;
	int active, error = 0;

	/*
	 * finish up command
	 */
	if (!dumping)
		mtx_assert(&ida->lock, MA_OWNED);
	active = (qcb->state != QCB_FREE);
	if (qcb->flags & DMA_DATA_TRANSFER && active) {
		switch (qcb->flags & DMA_DATA_TRANSFER) {
		case DMA_DATA_TRANSFER:
			op = BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE;
			break;
		case DMA_DATA_IN:
			op = BUS_DMASYNC_POSTREAD;
			break;
		default:
			KASSERT((qcb->flags & DMA_DATA_TRANSFER) ==
			    DMA_DATA_OUT, ("bad DMA data flags"));
			op = BUS_DMASYNC_POSTWRITE;
			break;
		}
		bus_dmamap_sync(ida->buffer_dmat, qcb->dmamap, op);
		bus_dmamap_unload(ida->buffer_dmat, qcb->dmamap);
	}
	if (active)
		bus_dmamap_sync(ida->hwqcb_dmat, ida->hwqcb_dmamap,
		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);

	if (qcb->hwqcb->req.error & SOFT_ERROR) {
		if (qcb->buf)
			device_printf(ida->dev, "soft %s error\n",
				qcb->buf->bio_cmd == BIO_READ ?
					"read" : "write");
		else
			device_printf(ida->dev, "soft error\n");
	}
	if (qcb->hwqcb->req.error & HARD_ERROR) {
		error = 1;
		if (qcb->buf)
			device_printf(ida->dev, "hard %s error\n",
				qcb->buf->bio_cmd == BIO_READ ?
					"read" : "write");
		else
			device_printf(ida->dev, "hard error\n");
	}
	if (qcb->hwqcb->req.error & CMD_REJECTED) {
		error = 1;
		device_printf(ida->dev, "invalid request\n");
	}
	if (qcb->error) {
		error = 1;
		device_printf(ida->dev, "request failed to map: %d\n", qcb->error);
	}

	if (qcb->flags & IDA_COMMAND) {
		if (ida->flags & IDA_INTERRUPTS)
			wakeup(qcb);
		if (qcb->state == QCB_TIMEDOUT)
			ida_free_qcb(ida, qcb);
	} else {
		KASSERT(qcb->buf != NULL, ("ida_done(): qcb->buf is NULL!"));
		if (error)
			qcb->buf->bio_flags |= BIO_ERROR;
		idad_intr(qcb->buf);
		ida_free_qcb(ida, qcb);
	}

	if (!active)
		return;

	ida->qactive--;
	/* Reschedule or cancel timeout */
	if (ida->qactive)
		callout_reset(&ida->ch, hz * 5, ida_timeout, ida);
	else
		callout_stop(&ida->ch);
}