Пример #1
0
void
ida_attach(struct ida_softc *ida)
{
	struct ida_controller_info cinfo;
	int error, i;

	ida->cmd.int_enable(ida, 0);

	error = ida_command(ida, CMD_GET_CTRL_INFO, &cinfo, sizeof(cinfo),
	    IDA_CONTROLLER, 0, DMA_DATA_IN);
	if (error) {
		device_printf(ida->dev, "CMD_GET_CTRL_INFO failed.\n");
		return;
	}

	device_printf(ida->dev, "drives=%d firm_rev=%c%c%c%c\n",
	    cinfo.num_drvs, cinfo.firm_rev[0], cinfo.firm_rev[1],
	    cinfo.firm_rev[2], cinfo.firm_rev[3]);

	if (ida->flags & IDA_FIRMWARE) {
		int data;

		error = ida_command(ida, CMD_START_FIRMWARE,
		    &data, sizeof(data), IDA_CONTROLLER, 0, DMA_DATA_IN);
		if (error) {
			device_printf(ida->dev, "CMD_START_FIRMWARE failed.\n");
			return;
		}
	}

	ida->num_drives = 0;
	for (i = 0; i < cinfo.num_drvs; i++)
		device_add_child(ida->dev, /*"idad"*/NULL, -1);

	bus_generic_attach(ida->dev);

	ida->cmd.int_enable(ida, 1);
}
Пример #2
0
static int
ida_ioctl (struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
{
	struct ida_softc *sc;
	struct ida_user_command *uc;
	struct cmd_info *ci;
	int len;
	int flags;
	int error;
	int data;
	void *daddr;

	sc = (struct ida_softc *)dev->si_drv1;
	uc = (struct ida_user_command *)addr;
	error = 0;

	switch (cmd) {
	case IDAIO_COMMAND:
		ci = ida_cmd_lookup(uc->command);
		if (ci == NULL) {
			error = EINVAL;
			break;
		}
		len = ci->len;
		flags = ci->flags;
		if (len)
			daddr = &uc->d.buf;
		else {
			daddr = &data;
			len = sizeof(data);
		}
		mtx_lock(&sc->lock);
		error = ida_command(sc, uc->command, daddr, len,
				    uc->drive, uc->blkno, flags);
		mtx_unlock(&sc->lock);
		break;
	default:
		error = ENOIOCTL;
		break;
	}
	return (error);
}
Пример #3
0
static int
idad_dump(struct dev_dump_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	struct idad_softc *drv;
	int error = 0;

	drv = idad_getsoftc(dev);
	if (drv == NULL)
		return (ENXIO);

	drv->controller->flags &= ~IDA_INTERRUPTS;

	if (ap->a_length > 0) {
		error = ida_command(drv->controller, CMD_WRITE, ap->a_virtual,
		    ap->a_length, drv->drive, ap->a_offset / DEV_BSIZE, DMA_DATA_OUT);
	}
	drv->controller->flags |= IDA_INTERRUPTS;
	return (error);

}
Пример #4
0
int
ida_init(struct ida_softc *ida)
{
	struct ida_controller_info cinfo;
	device_t child;
	int error, i, unit;

	SLIST_INIT(&ida->free_qcbs);
	STAILQ_INIT(&ida->qcb_queue);
	bioq_init(&ida->bio_queue);

	ida->qcbs = (struct ida_qcb *)
	    malloc(IDA_QCB_MAX * sizeof(struct ida_qcb), M_DEVBUF,
		M_NOWAIT | M_ZERO);
	if (ida->qcbs == NULL)
		return (ENOMEM);

	/*
	 * Create our DMA tags
	 */

	/* DMA tag for our hardware QCB structures */
	error = bus_dma_tag_create(
		/* parent	*/ ida->parent_dmat,
		/* alignment	*/ 1,
		/* boundary	*/ 0,
		/* lowaddr	*/ BUS_SPACE_MAXADDR,
		/* highaddr	*/ BUS_SPACE_MAXADDR,
		/* filter	*/ NULL,
		/* filterarg	*/ NULL,
		/* maxsize	*/ IDA_QCB_MAX * sizeof(struct ida_hardware_qcb),
		/* nsegments	*/ 1,
		/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
		/* flags	*/ 0,
		/* lockfunc	*/ NULL,
		/* lockarg	*/ NULL,
		&ida->hwqcb_dmat);
	if (error)
		return (ENOMEM);

	/* DMA tag for mapping buffers into device space */
	error = bus_dma_tag_create(
		/* parent 	*/ ida->parent_dmat,
		/* alignment	*/ 1,
		/* boundary	*/ 0,
		/* lowaddr	*/ BUS_SPACE_MAXADDR,
		/* highaddr	*/ BUS_SPACE_MAXADDR,
		/* filter	*/ NULL,
		/* filterarg	*/ NULL,
		/* maxsize	*/ MAXBSIZE,
		/* nsegments	*/ IDA_NSEG,
		/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
		/* flags	*/ 0,
		/* lockfunc	*/ busdma_lock_mutex,
		/* lockarg	*/ &Giant,
		&ida->buffer_dmat);
	if (error)
		return (ENOMEM);

	/* Allocation of hardware QCBs */
	/* XXX allocation is rounded to hardware page size */
	error = bus_dmamem_alloc(ida->hwqcb_dmat,
	    (void **)&ida->hwqcbs, BUS_DMA_NOWAIT, &ida->hwqcb_dmamap);
	if (error)
		return (ENOMEM);

	/* And permanently map them in */
	bus_dmamap_load(ida->hwqcb_dmat, ida->hwqcb_dmamap,
	    ida->hwqcbs, IDA_QCB_MAX * sizeof(struct ida_hardware_qcb),
	    ida_dma_map_cb, &ida->hwqcb_busaddr, /*flags*/0);

	bzero(ida->hwqcbs, IDA_QCB_MAX * sizeof(struct ida_hardware_qcb));

	error = ida_alloc_qcbs(ida);
	if (error)
		return (error);

	mtx_lock(&ida->lock);
	ida->cmd.int_enable(ida, 0);

	error = ida_command(ida, CMD_GET_CTRL_INFO, &cinfo, sizeof(cinfo),
	    IDA_CONTROLLER, 0, DMA_DATA_IN);
	if (error) {
		mtx_unlock(&ida->lock);
		device_printf(ida->dev, "CMD_GET_CTRL_INFO failed.\n");
		return (error);
	}

	device_printf(ida->dev, "drives=%d firm_rev=%c%c%c%c\n",
	    cinfo.num_drvs, cinfo.firm_rev[0], cinfo.firm_rev[1],
	    cinfo.firm_rev[2], cinfo.firm_rev[3]);

	if (ida->flags & IDA_FIRMWARE) {
		int data;

		error = ida_command(ida, CMD_START_FIRMWARE,
		    &data, sizeof(data), IDA_CONTROLLER, 0, DMA_DATA_IN);
		if (error) {
			mtx_unlock(&ida->lock);
			device_printf(ida->dev, "CMD_START_FIRMWARE failed.\n");
			return (error);
		}
	}
	
	ida->cmd.int_enable(ida, 1);
	ida->flags |= IDA_ATTACHED;
	mtx_unlock(&ida->lock);

	for (i = 0; i < cinfo.num_drvs; i++) {
		child = device_add_child(ida->dev, /*"idad"*/NULL, -1);
		if (child != NULL)
			device_set_ivars(child, (void *)(intptr_t)i);
	}

	ida->ich.ich_func = ida_startup;
	ida->ich.ich_arg = ida;
	if (config_intrhook_establish(&ida->ich) != 0) {
		device_delete_children(ida->dev);
		device_printf(ida->dev, "Cannot establish configuration hook\n");
		return (error);
	}

	unit = device_get_unit(ida->dev);
	ida->ida_dev_t = make_dev(&ida_cdevsw, unit,
				 UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
				 "ida%d", unit);
	ida->ida_dev_t->si_drv1 = ida;

	return (0);
}
Пример #5
0
static int
idad_attach(device_t dev)
{
	struct ida_drive_info dinfo;
	struct disk_info info;
	struct idad_softc *drv;
	device_t parent;
	cdev_t dsk;
	int error;

	drv = (struct idad_softc *)device_get_softc(dev);
	parent = device_get_parent(dev);
	drv->controller = (struct ida_softc *)device_get_softc(parent);
	drv->unit = device_get_unit(dev);
	drv->drive = drv->controller->num_drives;
	drv->controller->num_drives++;

	error = ida_command(drv->controller, CMD_GET_LOG_DRV_INFO,
	    &dinfo, sizeof(dinfo), drv->drive, 0, DMA_DATA_IN);
	if (error) {
		device_printf(dev, "CMD_GET_LOG_DRV_INFO failed\n");
		return (ENXIO);
	}

	drv->cylinders = dinfo.ncylinders;
	drv->heads = dinfo.nheads;
	drv->sectors = dinfo.nsectors;
	drv->secsize = dinfo.secsize == 0 ? 512 : dinfo.secsize;
	drv->secperunit = dinfo.secperunit;

	/* XXX
	 * other initialization
	 */
	device_printf(dev, "%uMB (%u sectors), blocksize=%d\n",
	    drv->secperunit / ((1024 * 1024) / drv->secsize),
	    drv->secperunit, drv->secsize);

	devstat_add_entry(&drv->stats, "idad", drv->unit, drv->secsize,
	    DEVSTAT_NO_ORDERED_TAGS,
	    DEVSTAT_TYPE_STORARRAY| DEVSTAT_TYPE_IF_OTHER,
	    DEVSTAT_PRIORITY_ARRAY);

	dsk = disk_create(drv->unit, &drv->disk, &id_ops);

	dsk->si_drv1 = drv;
	dsk->si_iosize_max = DFLTPHYS;		/* XXX guess? */

	/*
	 * Set disk info, as it appears that all needed data is available already.
	 * Setting the disk info will also cause the probing to start.
	 */
	bzero(&info, sizeof(info));
	info.d_media_blksize = drv->secsize;		/* mandatory */
	info.d_media_blocks = drv->secperunit;

	info.d_secpertrack = drv->sectors;		/* optional */
	info.d_type = DTYPE_SCSI;
	info.d_nheads = drv->heads;
	info.d_ncylinders = drv->cylinders;
	info.d_secpercyl = drv->sectors * drv->heads;

	disk_setdiskinfo(&drv->disk, &info);

	return (0);
}