ida
uint32_t ida = a->ioc.id;
if (ida > idb)
if (ida < idb)
uint32_t ida = a->ioc.id;
if (ida > idb)
if (ida < idb)
int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
void ida_remove(struct ida *ida, int id);
void ida_destroy(struct ida *ida);
void ida_init(struct ida *ida);
int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
void ida_simple_remove(struct ida *ida, unsigned int id);
ida_free(struct ida *ida, int id)
ida_remove(ida, id);
ida_get_new(struct ida *ida, int *p_id)
return (ida_get_new_above(ida, 0, p_id));
ida_alloc_min(struct ida *ida, unsigned int min, gfp_t gfp)
return (ida_simple_get(ida, min, UINT_MAX, gfp));
ida_alloc_max(struct ida *ida, unsigned int max, gfp_t gfp)
return (ida_simple_get(ida, 0, max, gfp));
ida_alloc_range(struct ida *ida, unsigned int min, unsigned int max, gfp_t gfp)
return (ida_simple_get(ida, min, max, gfp));
static inline int ida_alloc(struct ida *ida, gfp_t gfp)
return (ida_alloc_max(ida, ~0u, gfp));
ida_is_empty(struct ida *ida)
return (idr_is_empty(&ida->idr));
struct ida name; \
ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
return (idr_get_new_above(&ida->idr, NULL, starting_id, p_id));
ida_pre_get(struct ida *ida, gfp_t flags)
if (idr_pre_get(&ida->idr, flags) == 0)
if (ida->free_bitmap == NULL) {
ida->free_bitmap =
return (ida->free_bitmap != NULL);
ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
if (!ida_pre_get(ida, flags))
if ((ret = ida_get_new_above(ida, start, &id)) == 0) {
ida_remove(ida, id);
ida_simple_remove(struct ida *ida, unsigned int id)
idr_remove(&ida->idr, id);
ida_remove(struct ida *ida, int id)
idr_remove(&ida->idr, id);
ida_init(struct ida *ida)
idr_init(&ida->idr);
ida_destroy(struct ida *ida)
idr_destroy(&ida->idr);
free(ida->free_bitmap, M_IDR);
ida->free_bitmap = NULL;
ida->hwqcb_dmamap);
bus_dma_tag_destroy(ida->hwqcb_dmat);
if (ida->qcbs != NULL)
free(ida->qcbs, M_DEVBUF);
if (ida->irq != NULL)
bus_release_resource(ida->dev, ida->irq_res_type,
0, ida->irq);
if (ida->parent_dmat != NULL)
bus_dma_tag_destroy(ida->parent_dmat);
if (ida->regs != NULL)
bus_release_resource(ida->dev, ida->regs_res_type,
ida->regs_res_id, ida->regs);
mtx_destroy(&ida->lock);
ida_get_qcb(struct ida_softc *ida)
if ((qcb = SLIST_FIRST(&ida->free_qcbs)) != NULL) {
SLIST_REMOVE_HEAD(&ida->free_qcbs, link.sle);
ida_free_qcb(struct ida_softc *ida, struct ida_qcb *qcb)
SLIST_INSERT_HEAD(&ida->free_qcbs, qcb, link.sle);
idahwqcbvtop(struct ida_softc *ida, struct ida_hardware_qcb *hwqcb)
return (ida->hwqcb_busaddr +
((bus_addr_t)hwqcb - (bus_addr_t)ida->hwqcbs));
idahwqcbptov(struct ida_softc *ida, bus_addr_t hwqcb_addr)
((bus_addr_t)ida->hwqcbs + (hwqcb_addr - ida->hwqcb_busaddr));
ida_alloc_qcbs(struct ida_softc *ida)
qcb = &ida->qcbs[i];
error = bus_dmamap_create(ida->buffer_dmat, /*flags*/0, &qcb->dmamap);
qcb->ida = ida;
qcb->hwqcb = &ida->hwqcbs[i];
qcb->hwqcb_busaddr = idahwqcbvtop(ida, qcb->hwqcb);
SLIST_INSERT_HEAD(&ida->free_qcbs, qcb, link.sle);
ida_setup(struct ida_softc *ida)
SLIST_INIT(&ida->free_qcbs);
STAILQ_INIT(&ida->qcb_queue);
bioq_init(&ida->bio_queue);
ida->qcbs = (struct ida_qcb *)
if (ida->qcbs == NULL)
/* parent */ ida->parent_dmat,
&ida->hwqcb_dmat);
/* parent */ ida->parent_dmat,
/* lockarg */ &ida->lock,
&ida->buffer_dmat);
error = bus_dmamem_alloc(ida->hwqcb_dmat,
(void **)&ida->hwqcbs, BUS_DMA_NOWAIT, &ida->hwqcb_dmamap);
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);
mtx_lock(&ida->lock);
ida->cmd.int_enable(ida, 0);
error = ida_command(ida, CMD_GET_CTRL_INFO, &cinfo, sizeof(cinfo),
mtx_unlock(&ida->lock);
device_printf(ida->dev, "CMD_GET_CTRL_INFO failed.\n");
device_printf(ida->dev, "drives=%d firm_rev=%c%c%c%c\n",
if (ida->flags & IDA_FIRMWARE) {
error = ida_command(ida, CMD_START_FIRMWARE,
mtx_unlock(&ida->lock);
device_printf(ida->dev, "CMD_START_FIRMWARE failed.\n");
ida->cmd.int_enable(ida, 1);
ida->flags |= IDA_ATTACHED;
mtx_unlock(&ida->lock);
child = device_add_child(ida->dev, /*"idad"*/NULL, DEVICE_UNIT_ANY);
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");
unit = device_get_unit(ida->dev);
ida->ida_dev_t = make_dev(&ida_cdevsw, unit,
ida->ida_dev_t->si_drv1 = ida;
struct ida_softc *ida;
ida = arg;
config_intrhook_disestablish(&ida->ich);
bus_attach_children(ida->dev);
struct ida_softc *ida;
ida = (struct ida_softc *)device_get_softc(dev);
destroy_dev(ida->ida_dev_t);
ida_free(ida);
struct ida_softc *ida;
ida = qcb->ida;
mtx_assert(&ida->lock, MA_OWNED);
ida_done(ida, qcb);
bus_dmamap_sync(ida->buffer_dmat, qcb->dmamap, op);
bus_dmamap_sync(ida->hwqcb_dmat, ida->hwqcb_dmamap,
STAILQ_INSERT_TAIL(&ida->qcb_queue, qcb, link.stqe);
ida_start(ida);
ida->flags &= ~IDA_QFROZEN;
ida_map_qcb(struct ida_softc *ida, struct ida_qcb *qcb, void *data,
if (ida->flags & IDA_INTERRUPTS)
error = bus_dmamap_load(ida->buffer_dmat, qcb->dmamap, data, datasize,
ida->flags |= IDA_QFROZEN;
ida_command(struct ida_softc *ida, int command, void *data, int datasize,
mtx_assert(&ida->lock, MA_OWNED);
qcb = ida_get_qcb(ida);
device_printf(ida->dev, "out of QCBs\n");
error = ida_map_qcb(ida, qcb, data, datasize);
error = ida_wait(ida, qcb);
ida_free_qcb(ida, qcb);
ida_submit_buf(struct ida_softc *ida, struct bio *bp)
mtx_lock(&ida->lock);
bioq_insert_tail(&ida->bio_queue, bp);
ida_startio(ida);
mtx_unlock(&ida->lock);
ida_startio(struct ida_softc *ida)
mtx_assert(&ida->lock, MA_OWNED);
if (ida->flags & IDA_QFROZEN)
bp = bioq_first(&ida->bio_queue);
qcb = ida_get_qcb(ida);
bioq_remove(&ida->bio_queue, bp);
error = ida_map_qcb(ida, qcb, bp->bio_data, bp->bio_bcount);
ida_done(ida, qcb);
ida_start(struct ida_softc *ida)
mtx_assert(&ida->lock, MA_OWNED);
while ((qcb = STAILQ_FIRST(&ida->qcb_queue)) != NULL) {
if (ida->cmd.fifo_full(ida))
STAILQ_REMOVE_HEAD(&ida->qcb_queue, link.stqe);
if (!ida->qactive && !dumping)
callout_reset(&ida->ch, hz * 5, ida_timeout, ida);
ida->qactive++;
ida->cmd.submit(ida, qcb);
ida_wait(struct ida_softc *ida, struct ida_qcb *qcb)
mtx_assert(&ida->lock, MA_OWNED);
if (ida->flags & IDA_INTERRUPTS) {
if (mtx_sleep(qcb, &ida->lock, PRIBIO, "idacmd", 5 * hz)) {
while ((completed = ida->cmd.done(ida)) == 0) {
qcb_done = idahwqcbptov(ida, completed & ~3);
ida_done(ida, qcb);
struct ida_softc *ida;
ida = (struct ida_softc *)data;
mtx_lock(&ida->lock);
if (ida->cmd.int_pending(ida) == 0) {
mtx_unlock(&ida->lock);
while ((completed = ida->cmd.done(ida)) != 0) {
qcb = idahwqcbptov(ida, completed & ~3);
device_printf(ida->dev,
static int ida_alloc_qcbs(struct ida_softc *ida);
ida_done(ida, qcb);
ida_startio(ida);
mtx_unlock(&ida->lock);
static void ida_done(struct ida_softc *ida, struct ida_qcb *qcb);
ida_done(struct ida_softc *ida, struct ida_qcb *qcb)
static void ida_start(struct ida_softc *ida);
mtx_assert(&ida->lock, MA_OWNED);
static void ida_startio(struct ida_softc *ida);
bus_dmamap_sync(ida->buffer_dmat, qcb->dmamap, op);
bus_dmamap_unload(ida->buffer_dmat, qcb->dmamap);
bus_dmamap_sync(ida->hwqcb_dmat, ida->hwqcb_dmamap,
device_printf(ida->dev, "soft %s error\n",
device_printf(ida->dev, "soft error\n");
device_printf(ida->dev, "hard %s error\n",
static int ida_wait(struct ida_softc *ida, struct ida_qcb *qcb);
device_printf(ida->dev, "hard error\n");
device_printf(ida->dev, "invalid request\n");
device_printf(ida->dev, "request failed to map: %d\n", qcb->error);
if (ida->flags & IDA_INTERRUPTS)
ida_free_qcb(ida, qcb);
ida_free_qcb(ida, qcb);
ida->qactive--;
if (ida->qactive)
callout_reset(&ida->ch, hz * 5, ida_timeout, ida);
callout_stop(&ida->ch);
struct ida_softc *ida;
ida = (struct ida_softc *)arg;
device_printf(ida->dev, "%s() qactive %d\n", __func__, ida->qactive);
if (ida->flags & IDA_INTERRUPTS)
device_printf(ida->dev, "IDA_INTERRUPTS\n");
device_printf(ida->dev, "\t R_CMD_FIFO: %08x\n"
ida_inl(ida, R_CMD_FIFO),
ida_inl(ida, R_DONE_FIFO),
ida_inl(ida, R_INT_MASK),
ida_inl(ida, R_STATUS),
ida_inl(ida, R_INT_PENDING));
ida_free(struct ida_softc *ida)
if (ida->ih != NULL)
bus_teardown_intr(ida->dev, ida->irq, ida->ih);
mtx_lock(&ida->lock);
callout_stop(&ida->ch);
mtx_unlock(&ida->lock);
callout_drain(&ida->ch);
if (ida->buffer_dmat) {
bus_dmamap_destroy(ida->buffer_dmat, ida->qcbs[i].dmamap);
bus_dma_tag_destroy(ida->buffer_dmat);
if (ida->hwqcb_dmat) {
if (ida->hwqcb_busaddr)
bus_dmamap_unload(ida->hwqcb_dmat, ida->hwqcb_dmamap);
if (ida->hwqcbs)
bus_dmamem_free(ida->hwqcb_dmat, ida->hwqcbs,
DRIVER_MODULE(idad, ida, idad_driver, 0, 0);
ida_v4_fifo_full(struct ida_softc *ida)
return (ida_inl(ida, R_42XX_REQUEST) != 0);
ida_v4_submit(struct ida_softc *ida, struct ida_qcb *qcb)
ida_outl(ida, R_42XX_REQUEST, qcb->hwqcb_busaddr);
ida_v4_done(struct ida_softc *ida)
completed = ida_inl(ida, R_42XX_REPLY);
ida_outl(ida, R_42XX_REPLY, 0); /* confirm read */
ida_v4_int_pending(struct ida_softc *ida)
return (ida_inl(ida, R_42XX_STATUS) & STATUS_42XX_INT_PENDING);
ida_v4_int_enable(struct ida_softc *ida, int enable)
ida->flags |= IDA_INTERRUPTS;
ida->flags &= ~IDA_INTERRUPTS;
ida_outl(ida, R_42XX_INT_MASK,
struct ida_softc *ida;
ida = (struct ida_softc *)device_get_softc(dev);
ida->dev = dev;
ida->cmd = *board->accessor;
ida->flags = board->flags;
mtx_init(&ida->lock, "ida", NULL, MTX_DEF);
callout_init_mtx(&ida->ch, &ida->lock, 0);
ida->regs_res_type = SYS_RES_MEMORY;
ida->regs_res_id = IDA_PCI_MEMADDR;
ida->regs_res_id = PCIR_BAR(0);
ida->regs = bus_alloc_resource_any(dev, ida->regs_res_type,
&ida->regs_res_id, RF_ACTIVE);
if (ida->regs == NULL) {
&ida->parent_dmat);
ida_free(ida);
ida->irq_res_type = SYS_RES_IRQ;
ida->irq = bus_alloc_resource_any(dev, ida->irq_res_type, &rid,
if (ida->irq == NULL) {
ida_free(ida);
error = bus_setup_intr(dev, ida->irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE,
NULL, ida_intr, ida, &ida->ih);
ida_free(ida);
error = ida_setup(ida);
ida_free(ida);
DRIVER_MODULE(ida, pci, ida_pci_driver, 0, 0);
MODULE_PNP_INFO("W32:vendor/device;D:#", pci, ida, board_id,
ida_v3_fifo_full(struct ida_softc *ida)
return (ida_inl(ida, R_CMD_FIFO) == 0);
ida_v3_submit(struct ida_softc *ida, struct ida_qcb *qcb)
ida_outl(ida, R_CMD_FIFO, qcb->hwqcb_busaddr);
ida_v3_done(struct ida_softc *ida)
completed = ida_inl(ida, R_DONE_FIFO);
ida_v3_int_pending(struct ida_softc *ida)
return (ida_inl(ida, R_INT_PENDING));
ida_v3_int_enable(struct ida_softc *ida, int enable)
ida->flags |= IDA_INTERRUPTS;
ida->flags &= ~IDA_INTERRUPTS;
ida_outl(ida, R_INT_MASK, enable ? INT_ENABLE : INT_DISABLE);
struct ida_softc *ida;
extern void ida_free(struct ida_softc *ida);
extern int ida_setup(struct ida_softc *ida);
extern int ida_command(struct ida_softc *ida, int command, void *data,
extern void ida_submit_buf(struct ida_softc *ida, struct bio *bp);
#define ida_inb(ida, port) \
bus_read_1((ida)->regs, port)
#define ida_inw(ida, port) \
bus_read_2((ida)->regs, port)
#define ida_inl(ida, port) \
bus_read_4((ida)->regs, port)
#define ida_outb(ida, port, val) \
bus_write_1((ida)->regs, port, val)
#define ida_outw(ida, port, val) \
bus_write_2((ida)->regs, port, val)
#define ida_outl(ida, port, val) \
bus_write_4((ida)->regs, port, val)
struct ida ida;
struct ida fte_allocator;
ida_simple_remove(&dev->roce.reserved_gids.ida, gid_index);
ida_init(&dev->roce.reserved_gids.ida);
WARN_ON(!ida_is_empty(&dev->roce.reserved_gids.ida));
ida_destroy(&dev->roce.reserved_gids.ida);
index = ida_simple_get(&dev->roce.reserved_gids.ida,