--- //depot/vendor/freebsd/src/sys/dev/ida/ida.c 2005-05-29 04:45:51.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/ida/ida.c 2012-08-16 18:12:35.000000000 0000 @@ -38,7 +38,9 @@ #include #include #include +#include #include +#include #include #include @@ -56,17 +58,17 @@ #include /* prototypes */ -static void ida_alloc_qcb(struct ida_softc *ida); -static void ida_construct_qcb(struct ida_softc *ida); +static int ida_alloc_qcbs(struct ida_softc *ida); +static void ida_done(struct ida_softc *ida, struct ida_qcb *qcb); static void ida_start(struct ida_softc *ida); -static void ida_done(struct ida_softc *ida, struct ida_qcb *qcb); +static void ida_startio(struct ida_softc *ida); +static void ida_startup(void *arg); +static void ida_timeout(void *arg); static int ida_wait(struct ida_softc *ida, struct ida_qcb *qcb); -static void ida_timeout (void *arg); static d_ioctl_t ida_ioctl; static struct cdevsw ida_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_ioctl = ida_ioctl, .d_name = "ida", }; @@ -76,10 +78,16 @@ { int i; + 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) { - for (i = 0; i < ida->num_qcbs; i++) + for (i = 0; i < IDA_QCB_MAX; i++) bus_dmamap_destroy(ida->buffer_dmat, ida->qcbs[i].dmamap); bus_dma_tag_destroy(ida->buffer_dmat); } @@ -96,9 +104,6 @@ if (ida->qcbs != NULL) free(ida->qcbs, M_DEVBUF); - if (ida->ih != NULL) - bus_teardown_intr(ida->dev, ida->irq, ida->ih); - if (ida->irq != NULL) bus_release_resource(ida->dev, ida->irq_res_type, 0, ida->irq); @@ -109,6 +114,8 @@ if (ida->regs != NULL) bus_release_resource(ida->dev, ida->regs_res_type, ida->regs_res_id, ida->regs); + + mtx_destroy(&ida->lock); } /* @@ -130,14 +137,21 @@ if ((qcb = SLIST_FIRST(&ida->free_qcbs)) != NULL) { SLIST_REMOVE_HEAD(&ida->free_qcbs, link.sle); - } else { - ida_alloc_qcb(ida); - if ((qcb = SLIST_FIRST(&ida->free_qcbs)) != NULL) - SLIST_REMOVE_HEAD(&ida->free_qcbs, link.sle); + bzero(qcb->hwqcb, sizeof(struct ida_hdr) + sizeof(struct ida_req)); } return (qcb); } +static __inline void +ida_free_qcb(struct ida_softc *ida, struct ida_qcb *qcb) +{ + + qcb->state = QCB_FREE; + qcb->buf = NULL; + qcb->error = 0; + SLIST_INSERT_HEAD(&ida->free_qcbs, qcb, link.sle); +} + static __inline bus_addr_t idahwqcbvtop(struct ida_softc *ida, struct ida_hardware_qcb *hwqcb) { @@ -155,42 +169,35 @@ return (hwqcb->qcb); } -/* - * XXX - * since we allocate all QCB space up front during initialization, then - * why bother with this routine? - */ -static void -ida_alloc_qcb(struct ida_softc *ida) +static int +ida_alloc_qcbs(struct ida_softc *ida) { struct ida_qcb *qcb; - int error; + int error, i; - if (ida->num_qcbs >= IDA_QCB_MAX) - return; + for (i = 0; i < IDA_QCB_MAX; i++) { + qcb = &ida->qcbs[i]; - qcb = &ida->qcbs[ida->num_qcbs]; + error = bus_dmamap_create(ida->buffer_dmat, /*flags*/0, &qcb->dmamap); + if (error != 0) + return (error); - error = bus_dmamap_create(ida->buffer_dmat, /*flags*/0, &qcb->dmamap); - if (error != 0) - return; - - qcb->flags = QCB_FREE; - qcb->hwqcb = &ida->hwqcbs[ida->num_qcbs]; - qcb->hwqcb->qcb = qcb; - qcb->hwqcb_busaddr = idahwqcbvtop(ida, qcb->hwqcb); - SLIST_INSERT_HEAD(&ida->free_qcbs, qcb, link.sle); - ida->num_qcbs++; + qcb->ida = ida; + qcb->flags = QCB_FREE; + qcb->hwqcb = &ida->hwqcbs[i]; + qcb->hwqcb->qcb = qcb; + qcb->hwqcb_busaddr = idahwqcbvtop(ida, qcb->hwqcb); + SLIST_INSERT_HEAD(&ida->free_qcbs, qcb, link.sle); + } + return (0); } int ida_init(struct ida_softc *ida) { - int error; - - ida->unit = device_get_unit(ida->dev); - ida->tag = rman_get_bustag(ida->regs); - ida->bsh = rman_get_bushandle(ida->regs); + struct ida_controller_info cinfo; + device_t child; + int error, i, unit; SLIST_INIT(&ida->free_qcbs); STAILQ_INIT(&ida->qcb_queue); @@ -219,8 +226,8 @@ /* nsegments */ 1, /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, /* flags */ 0, - /* lockfunc */ busdma_lock_mutex, - /* lockarg */ &Giant, + /* lockfunc */ NULL, + /* lockarg */ NULL, &ida->hwqcb_dmat); if (error) return (ENOMEM); @@ -258,26 +265,19 @@ bzero(ida->hwqcbs, IDA_QCB_MAX * sizeof(struct ida_hardware_qcb)); - ida_alloc_qcb(ida); /* allocate an initial qcb */ + error = ida_alloc_qcbs(ida); + if (error) + return (error); - callout_init(&ida->ch, CALLOUT_MPSAFE); - - return (0); -} - -void -ida_attach(struct ida_softc *ida) -{ - struct ida_controller_info cinfo; - int error, i; - + 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; + return (error); } device_printf(ida->dev, "drives=%d firm_rev=%c%c%c%c\n", @@ -290,33 +290,65 @@ 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; + 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->ida_dev_t = make_dev(&ida_cdevsw, ida->unit, + 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", ida->unit); + "ida%d", unit); ida->ida_dev_t->si_drv1 = ida; - ida->num_drives = 0; - for (i = 0; i < cinfo.num_drvs; i++) - device_add_child(ida->dev, /*"idad"*/NULL, -1); + return (0); +} + +static void +ida_startup(void *arg) +{ + struct ida_softc *ida; + ida = arg; + mtx_lock(&Giant); bus_generic_attach(ida->dev); - - ida->cmd.int_enable(ida, 1); + mtx_unlock(&Giant); } int ida_detach(device_t dev) { struct ida_softc *ida; - int error = 0; + int error; ida = (struct ida_softc *)device_get_softc(dev); + error = bus_generic_detach(dev); + if (error) + return (error); + error = device_delete_children(dev); + if (error) + return (error); + /* * XXX * before detaching, we must make sure that the system is @@ -335,11 +367,25 @@ } static void -ida_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) +ida_data_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error) { - struct ida_hardware_qcb *hwqcb = (struct ida_hardware_qcb *)arg; + struct ida_hardware_qcb *hwqcb; + struct ida_softc *ida; + struct ida_qcb *qcb; + bus_dmasync_op_t op; int i; + qcb = arg; + ida = qcb->ida; + if (!dumping) + mtx_assert(&ida->lock, MA_OWNED); + if (error) { + qcb->error = error; + ida_done(ida, qcb); + return; + } + + hwqcb = qcb->hwqcb; hwqcb->hdr.size = htole16((sizeof(struct ida_req) + sizeof(struct ida_sgb) * IDA_NSEG) >> 2); @@ -348,6 +394,47 @@ hwqcb->seg[i].length = htole32(segs[i].ds_len); } hwqcb->req.sgcount = nsegments; + if (qcb->flags & DMA_DATA_TRANSFER) { + switch (qcb->flags & DMA_DATA_TRANSFER) { + case DMA_DATA_TRANSFER: + op = BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE; + break; + case DMA_DATA_IN: + op = BUS_DMASYNC_PREREAD; + break; + default: + KASSERT((qcb->flags & DMA_DATA_TRANSFER) == + DMA_DATA_OUT, ("bad DMA data flags")); + op = BUS_DMASYNC_PREWRITE; + break; + } + bus_dmamap_sync(ida->buffer_dmat, qcb->dmamap, op); + } + bus_dmamap_sync(ida->hwqcb_dmat, ida->hwqcb_dmamap, + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + STAILQ_INSERT_TAIL(&ida->qcb_queue, qcb, link.stqe); + ida_start(ida); + ida->flags &= ~IDA_QFROZEN; +} + +static int +ida_map_qcb(struct ida_softc *ida, struct ida_qcb *qcb, void *data, + bus_size_t datasize) +{ + int error, flags; + + if (ida->flags & IDA_INTERRUPTS) + flags = BUS_DMA_WAITOK; + else + flags = BUS_DMA_NOWAIT; + error = bus_dmamap_load(ida->buffer_dmat, qcb->dmamap, data, datasize, + ida_data_cb, qcb, flags); + if (error == EINPROGRESS) { + ida->flags |= IDA_QFROZEN; + error = 0; + } + return (error); } int @@ -356,105 +443,96 @@ { struct ida_hardware_qcb *hwqcb; struct ida_qcb *qcb; - bus_dmasync_op_t op; - int s, error; + int error; - s = splbio(); + if (!dumping) + mtx_assert(&ida->lock, MA_OWNED); qcb = ida_get_qcb(ida); - splx(s); if (qcb == NULL) { - printf("ida_command: out of QCBs"); + device_printf(ida->dev, "out of QCBs\n"); return (EAGAIN); } + qcb->flags = flags | IDA_COMMAND; hwqcb = qcb->hwqcb; - bzero(hwqcb, sizeof(struct ida_hdr) + sizeof(struct ida_req)); - - bus_dmamap_load(ida->buffer_dmat, qcb->dmamap, - (void *)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 = htole32(pblkno); hwqcb->req.bcount = htole16(howmany(datasize, DEV_BSIZE)); hwqcb->req.command = command; - qcb->flags = flags | IDA_COMMAND; - - s = splbio(); - STAILQ_INSERT_TAIL(&ida->qcb_queue, qcb, link.stqe); - ida_start(ida); - error = ida_wait(ida, qcb); - splx(s); + 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); } void ida_submit_buf(struct ida_softc *ida, struct bio *bp) { + mtx_lock(&ida->lock); bioq_insert_tail(&ida->bio_queue, bp); - ida_construct_qcb(ida); - ida_start(ida); + ida_startio(ida); + mtx_unlock(&ida->lock); } static void -ida_construct_qcb(struct ida_softc *ida) +ida_startio(struct ida_softc *ida) { struct ida_hardware_qcb *hwqcb; struct ida_qcb *qcb; - bus_dmasync_op_t op; + struct idad_softc *drv; struct bio *bp; + int error; - bp = bioq_first(&ida->bio_queue); - if (bp == NULL) - return; /* no more buffers */ + 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 */ + 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; + 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; - bzero(hwqcb, sizeof(struct ida_hdr) + sizeof(struct ida_req)); + 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; - bus_dmamap_load(ida->buffer_dmat, qcb->dmamap, - (void *)bp->bio_data, bp->bio_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 = (struct idad_softc *)bp->bio_driver1; - hwqcb->hdr.drive = drv->drive; + error = ida_map_qcb(ida, qcb, bp->bio_data, bp->bio_bcount); + if (error) { + qcb->error = error; + ida_done(ida, qcb); + } } - - 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; - - STAILQ_INSERT_TAIL(&ida->qcb_queue, qcb, link.stqe); } -/* - * This routine will be called from ida_intr in order to queue up more - * I/O, meaning that we may be in an interrupt context. Hence, we should - * not muck around with spl() in this routine. - */ static void ida_start(struct ida_softc *ida) { struct ida_qcb *qcb; + if (!dumping) + mtx_assert(&ida->lock, MA_OWNED); while ((qcb = STAILQ_FIRST(&ida->qcb_queue)) != NULL) { if (ida->cmd.fifo_full(ida)) break; @@ -465,7 +543,7 @@ */ /* Set a timeout. */ - if (!ida->qactive) + if (!ida->qactive && !dumping) callout_reset(&ida->ch, hz * 5, ida_timeout, ida); ida->qactive++; @@ -481,17 +559,23 @@ bus_addr_t completed; int delay; + if (!dumping) + mtx_assert(&ida->lock, MA_OWNED); if (ida->flags & IDA_INTERRUPTS) { - if (tsleep(qcb, PRIBIO, "idacmd", 5 * hz)) + if (mtx_sleep(qcb, &ida->lock, PRIBIO, "idacmd", 5 * hz)) { + qcb->state = QCB_TIMEDOUT; return (ETIMEDOUT); + } return (0); } again: delay = 5 * 1000 * 100; /* 5 sec delay */ while ((completed = ida->cmd.done(ida)) == 0) { - if (delay-- == 0) + if (delay-- == 0) { + qcb->state = QCB_TIMEDOUT; return (ETIMEDOUT); + } DELAY(10); } @@ -511,8 +595,11 @@ ida = (struct ida_softc *)data; - if (ida->cmd.int_pending(ida) == 0) + mtx_lock(&ida->lock); + if (ida->cmd.int_pending(ida) == 0) { + mtx_unlock(&ida->lock); return; /* not our interrupt */ + } while ((completed = ida->cmd.done(ida)) != 0) { qcb = idahwqcbptov(ida, completed & ~3); @@ -527,7 +614,8 @@ qcb->hwqcb->req.error = CMD_REJECTED; ida_done(ida, qcb); } - ida_start(ida); + ida_startio(ida); + mtx_unlock(&ida->lock); } /* @@ -536,19 +624,35 @@ static void ida_done(struct ida_softc *ida, struct ida_qcb *qcb) { - int error = 0; + bus_dmasync_op_t op; + int active, 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; + 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) @@ -571,32 +675,37 @@ 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); - - qcb->state = QCB_FREE; - qcb->buf = NULL; - SLIST_INSERT_HEAD(&ida->free_qcbs, qcb, link.sle); - ida_construct_qcb(ida); } static void -ida_timeout (void *arg) +ida_timeout(void *arg) { struct ida_softc *ida; @@ -661,8 +770,10 @@ 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; --- //depot/vendor/freebsd/src/sys/dev/ida/ida_disk.c 2005-05-29 04:45:51.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/ida/ida_disk.c 2012-08-06 02:12:58.000000000 0000 @@ -87,7 +87,6 @@ idad_strategy(struct bio *bp) { struct idad_softc *drv; - int s; drv = bp->bio_disk->d_drv1; if (drv == NULL) { @@ -104,9 +103,7 @@ } bp->bio_driver1 = drv; - s = splbio(); ida_submit_buf(drv->controller, bp); - splx(s); return; bad: @@ -179,8 +176,7 @@ drv->dev = 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++; + drv->drive = (intptr_t)device_get_ivars(dev); error = ida_command(drv->controller, CMD_GET_LOG_DRV_INFO, &dinfo, sizeof(dinfo), drv->drive, 0, DMA_DATA_IN); @@ -213,7 +209,6 @@ drv->disk->d_drv1 = drv; drv->disk->d_maxsize = DFLTPHYS; /* XXX guess? */ drv->disk->d_unit = drv->unit; - drv->disk->d_flags = DISKFLAG_NEEDSGIANT; disk_create(drv->disk, DISK_VERSION); return (0); --- //depot/vendor/freebsd/src/sys/dev/ida/ida_eisa.c 2007-02-23 12:24:01.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/ida/ida_eisa.c 2012-08-06 00:02:19.000000000 0000 @@ -282,6 +282,8 @@ board = ida_eisa_match(eisa_get_id(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_IOPORT; ida->regs_res_id = 0; @@ -293,7 +295,7 @@ } error = bus_dma_tag_create( - /* parent */ NULL, + /* parent */ bus_get_dma_tag(dev), /* alignment */ 0, /* boundary */ 0, /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, @@ -323,7 +325,7 @@ return (ENOMEM); } - error = bus_setup_intr(dev, ida->irq, INTR_TYPE_BIO | INTR_ENTROPY, + error = bus_setup_intr(dev, ida->irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, ida_intr, ida, &ida->ih); if (error) { device_printf(dev, "can't setup interrupt\n"); @@ -337,9 +339,6 @@ return (error); } - ida_attach(ida); - ida->flags |= IDA_ATTACHED; - return (0); } --- //depot/vendor/freebsd/src/sys/dev/ida/ida_pci.c 2012-03-12 08:05:24.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/ida/ida_pci.c 2012-08-06 00:02:19.000000000 0000 @@ -236,23 +236,14 @@ struct ida_board *board = ida_pci_match(dev); u_int32_t id = pci_get_devid(dev); struct ida_softc *ida; - u_int command; int error, rid; - command = pci_read_config(dev, PCIR_COMMAND, 1); - - /* - * it appears that this board only does MEMIO access. - */ - if ((command & PCIM_CMD_MEMEN) == 0) { - device_printf(dev, "Only memory mapped I/O is supported\n"); - return (ENXIO); - } - 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; @@ -295,7 +286,7 @@ ida_free(ida); return (ENOMEM); } - error = bus_setup_intr(dev, ida->irq, INTR_TYPE_BIO | INTR_ENTROPY, + error = bus_setup_intr(dev, ida->irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, ida_intr, ida, &ida->ih); if (error) { device_printf(dev, "can't setup interrupt\n"); @@ -308,8 +299,6 @@ ida_free(ida); return (error); } - ida_attach(ida); - ida->flags |= IDA_ATTACHED; return (0); } --- //depot/vendor/freebsd/src/sys/dev/ida/idavar.h 2005-04-13 05:10:36.000000000 0000 +++ //depot/user/jhb/cleanup/sys/dev/ida/idavar.h 2012-08-06 02:12:58.000000000 0000 @@ -34,18 +34,18 @@ #define _IDAVAR_H #define ida_inb(ida, port) \ - bus_space_read_1((ida)->tag, (ida)->bsh, port) + bus_read_1((ida)->regs, port) #define ida_inw(ida, port) \ - bus_space_read_2((ida)->tag, (ida)->bsh, port) + bus_read_2((ida)->regs, port) #define ida_inl(ida, port) \ - bus_space_read_4((ida)->tag, (ida)->bsh, port) + bus_read_4((ida)->regs, port) #define ida_outb(ida, port, val) \ - bus_space_write_1((ida)->tag, (ida)->bsh, port, val) + bus_write_1((ida)->regs, port, val) #define ida_outw(ida, port, val) \ - bus_space_write_2((ida)->tag, (ida)->bsh, port, val) + bus_write_2((ida)->regs, port, val) #define ida_outl(ida, port, val) \ - bus_space_write_4((ida)->tag, (ida)->bsh, port, val) + bus_write_4((ida)->regs, port, val) struct ida_hdr { u_int8_t drive; /* logical drive */ @@ -83,6 +83,7 @@ typedef enum { QCB_FREE = 0x0000, QCB_ACTIVE = 0x0001, /* waiting for completion */ + QCB_TIMEDOUT = 0x0002, } qcb_state; #define DMA_DATA_IN 0x0001 @@ -93,8 +94,11 @@ #define IDA_QCB_MAX 256 #define IDA_CONTROLLER 0 /* drive "number" for controller */ +struct ida_softc; + struct ida_qcb { struct ida_hardware_qcb *hwqcb; + struct ida_softc *ida; qcb_state state; short flags; union { @@ -104,10 +108,9 @@ bus_dmamap_t dmamap; bus_addr_t hwqcb_busaddr; struct bio *buf; /* bio associated with qcb */ + int error; }; -struct ida_softc; - struct ida_access { int (*fifo_full)(struct ida_softc *); void (*submit)(struct ida_softc *, struct ida_qcb *); @@ -122,10 +125,10 @@ #define IDA_ATTACHED 0x01 /* attached */ #define IDA_FIRMWARE 0x02 /* firmware must be started */ #define IDA_INTERRUPTS 0x04 /* interrupts enabled */ +#define IDA_QFROZEN 0x08 /* request queue frozen */ struct ida_softc { device_t dev; - int unit; struct callout ch; struct cdev *ida_dev_t; @@ -138,8 +141,8 @@ struct resource *irq; void *ih; - bus_space_tag_t tag; - bus_space_handle_t bsh; + struct mtx lock; + struct intr_config_hook ich; /* various DMA tags */ bus_dma_tag_t parent_dmat; @@ -151,8 +154,6 @@ bus_dma_tag_t sg_dmat; - int num_drives; - int num_qcbs; int flags; int qactive; @@ -197,7 +198,6 @@ int regs_type, int regs_id, bus_dma_tag_t parent_dmat); extern void ida_free(struct ida_softc *ida); extern int ida_init(struct ida_softc *ida); -extern void ida_attach(struct ida_softc *ida); extern int ida_command(struct ida_softc *ida, int command, void *data, int datasize, int drive, u_int32_t pblkno, int flags); extern void ida_submit_buf(struct ida_softc *ida, struct bio *bp);