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); }
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); }
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); }
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); }
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); }