Exemplo n.º 1
0
int
ida_command(struct ida_softc *ida, int command, void *data, int datasize,
	int drive, u_int64_t pblkno, int flags)
{
	struct ida_hardware_qcb *hwqcb;
	struct ida_qcb *qcb;
	bus_dmasync_op_t op;
	int error;

	crit_enter();
	qcb = ida_get_qcb(ida);
	crit_exit();

	if (qcb == NULL) {
		kprintf("ida_command: out of QCBs");
		return (EAGAIN);
	}

	hwqcb = qcb->hwqcb;
	bzero(hwqcb, sizeof(struct ida_hdr) + sizeof(struct ida_req));

	bus_dmamap_load(ida->buffer_dmat, qcb->dmamap,
	    data, datasize, ida_setup_dmamap, hwqcb, 0);
	op = qcb->flags & DMA_DATA_IN ?
	    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE;
	bus_dmamap_sync(ida->buffer_dmat, qcb->dmamap, op);

	hwqcb->hdr.drive = drive;
	hwqcb->req.blkno = pblkno;
	hwqcb->req.bcount = howmany(datasize, DEV_BSIZE);
	hwqcb->req.command = command;

	KKASSERT(pblkno < 0x100000000ULL);

	qcb->flags = flags | IDA_COMMAND;

	crit_enter();
	STAILQ_INSERT_TAIL(&ida->qcb_queue, qcb, link.stqe);
	ida_start(ida);
	error = ida_wait(ida, qcb);
	crit_exit();

	/* XXX should have status returned here? */
	/* XXX have "status pointer" area in QCB? */

	return (error);
}
Exemplo n.º 2
0
static void
ida_construct_qcb(struct ida_softc *ida)
{
	struct ida_hardware_qcb *hwqcb;
	struct ida_qcb *qcb;
	bus_dmasync_op_t op;
	struct buf *bp;
	struct bio *bio;

	bio = bioq_first(&ida->bio_queue);
	if (bio == NULL)
		return;				/* no more buffers */

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

	bioq_remove(&ida->bio_queue, bio);
	qcb->bio = bio;
	qcb->flags = 0;

	hwqcb = qcb->hwqcb;
	bzero(hwqcb, sizeof(struct ida_hdr) + sizeof(struct ida_req));

	bp = bio->bio_buf;
	bus_dmamap_load(ida->buffer_dmat, qcb->dmamap,
	    (void *)bp->b_data, bp->b_bcount, ida_setup_dmamap, hwqcb, 0);
	op = qcb->flags & DMA_DATA_IN ?
	    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE;
	bus_dmamap_sync(ida->buffer_dmat, qcb->dmamap, op);

	{
		struct idad_softc *drv;

		drv = (struct idad_softc *)bio->bio_driver_info;
		hwqcb->hdr.drive = drv->drive;
	}

	hwqcb->req.blkno = bio->bio_offset >> DEV_BSHIFT;
	hwqcb->req.bcount = howmany(bp->b_bcount, DEV_BSIZE);
	hwqcb->req.command = (bp->b_cmd == BUF_CMD_READ) ? CMD_READ : CMD_WRITE;

	KKASSERT(bio->bio_offset < 0x100000000ULL * DEV_BSIZE);

	STAILQ_INSERT_TAIL(&ida->qcb_queue, qcb, link.stqe);
}
Exemplo n.º 3
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);
		}
	}
}
Exemplo n.º 4
0
int
ida_command(struct ida_softc *ida, int command, void *data, int datasize,
	int drive, u_int32_t pblkno, int flags)
{
	struct ida_hardware_qcb *hwqcb;
	struct ida_qcb *qcb;
	int error;

	if (!dumping)
		mtx_assert(&ida->lock, MA_OWNED);
	qcb = ida_get_qcb(ida);

	if (qcb == NULL) {
		device_printf(ida->dev, "out of QCBs\n");
		return (EAGAIN);
	}

	qcb->flags = flags | IDA_COMMAND;
	hwqcb = qcb->hwqcb;
	hwqcb->hdr.drive = drive;
	hwqcb->req.blkno = htole32(pblkno);
	hwqcb->req.bcount = htole16(howmany(datasize, DEV_BSIZE));
	hwqcb->req.command = command;

	error = ida_map_qcb(ida, qcb, data, datasize);
	if (error == 0) {
		error = ida_wait(ida, qcb);
		/* Don't free QCB on a timeout in case it later completes. */
		if (error)
			return (error);
		error = qcb->error;
	}

	/* XXX should have status returned here? */
	/* XXX have "status pointer" area in QCB? */

	ida_free_qcb(ida, qcb);
	return (error);
}