diff --git a/sys/dev/ieee1394/firewire.c b/sys/dev/ieee1394/firewire.c index 941a5d1..7f66423 100644 --- a/sys/dev/ieee1394/firewire.c +++ b/sys/dev/ieee1394/firewire.c @@ -1,4 +1,4 @@ -/* $NetBSD: firewire.c,v 1.39 2012/04/29 18:31:40 dsl Exp $ */ +/* $NetBSD: firewire.c,v 1.42 2012/08/05 02:47:52 riastradh Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: firewire.c,v 1.39 2012/04/29 18:31:40 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: firewire.c,v 1.42 2012/08/05 02:47:52 riastradh Exp $"); #include #include @@ -255,11 +255,15 @@ firewireattach(device_t parent, device_t self, void *aux) callout_schedule(&fc->timeout_callout, hz); + /* Tell config we will have started a thread to scan the bus. */ + config_pending_incr(); + /* create thread */ if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, fw_bus_probe_thread, - fc, &fc->probe_thread, "fw%dprobe", device_unit(fc->bdev))) + fc, &fc->probe_thread, "fw%dprobe", device_unit(fc->bdev))) { aprint_error_dev(self, "kthread_create failed\n"); - config_pending_incr(); + config_pending_decr(); + } devlist = malloc(sizeof(struct firewire_dev_list), M_DEVBUF, M_NOWAIT); if (devlist == NULL) { @@ -679,6 +683,15 @@ fw_init(struct firewire_comm *fc) fc->crom_src_buf = NULL; } +void +fw_destroy(struct firewire_comm *fc) +{ + mutex_destroy(&fc->arq->q_mtx); + mutex_destroy(&fc->ars->q_mtx); + mutex_destroy(&fc->atq->q_mtx); + mutex_destroy(&fc->ats->q_mtx); +} + #define BIND_CMP(addr, fwb) \ (((addr) < (fwb)->start) ? -1 : ((fwb)->end < (addr)) ? 1 : 0) @@ -1935,6 +1948,20 @@ fw_bus_probe_thread(void *arg) { struct firewire_comm *fc = (struct firewire_comm *)arg; + /* + * Tell config we've scanned the bus. + * + * XXX This is not right -- we haven't actually scanned it. We + * probably ought to call this after the first bus exploration. + * + * bool once = false; + * ... + * fw_attach_dev(fc); + * if (!once) { + * config_pending_decr(); + * once = true; + * } + */ config_pending_decr(); mutex_enter(&fc->wait_lock); diff --git a/sys/dev/ieee1394/firewirereg.h b/sys/dev/ieee1394/firewirereg.h index 2cbaf08..322d6cb 100644 --- a/sys/dev/ieee1394/firewirereg.h +++ b/sys/dev/ieee1394/firewirereg.h @@ -1,4 +1,4 @@ -/* $NetBSD: firewirereg.h,v 1.17 2012/04/29 18:31:40 dsl Exp $ */ +/* $NetBSD: firewirereg.h,v 1.18 2012/08/04 03:55:43 riastradh Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -283,6 +283,7 @@ int fw_xferwait(struct fw_xfer *); void fw_drain_txq(struct firewire_comm *); void fw_busreset(struct firewire_comm *, uint32_t); void fw_init(struct firewire_comm *); +void fw_destroy(struct firewire_comm *); struct fw_bind *fw_bindlookup(struct firewire_comm *, uint16_t, uint32_t); int fw_bindadd(struct firewire_comm *, struct fw_bind *); int fw_bindremove(struct firewire_comm *, struct fw_bind *); diff --git a/sys/dev/ieee1394/fwohci.c b/sys/dev/ieee1394/fwohci.c index 07e60b1..5cb81a9 100644 --- a/sys/dev/ieee1394/fwohci.c +++ b/sys/dev/ieee1394/fwohci.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwohci.c,v 1.132 2011/07/31 13:51:53 uebayasi Exp $ */ +/* $NetBSD: fwohci.c,v 1.133 2012/08/04 03:55:43 riastradh Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa @@ -37,7 +37,7 @@ * */ #include -__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.132 2011/07/31 13:51:53 uebayasi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.133 2012/08/04 03:55:43 riastradh Exp $"); #include #include @@ -323,38 +323,15 @@ static void fwohci_arcv(struct fwohci_softc *, struct fwohci_dbch *); #define IRX_CH 36 -int +/* + * Call fwohci_init before fwohci_attach to initialize the kernel's + * data structures well enough that fwohci_detach won't crash, even if + * fwohci_attach fails. + */ + +void fwohci_init(struct fwohci_softc *sc) { - uint32_t reg; - uint8_t ui[8]; - int i, mver; - -/* OHCI version */ - reg = OREAD(sc, OHCI_VERSION); - mver = (reg >> 16) & 0xff; - aprint_normal_dev(sc->fc.dev, "OHCI version %x.%x (ROM=%d)\n", - mver, reg & 0xff, (reg >> 24) & 1); - if (mver < 1 || mver > 9) { - aprint_error_dev(sc->fc.dev, "invalid OHCI version\n"); - return ENXIO; - } - -/* Available Isochronous DMA channel probe */ - OWRITE(sc, OHCI_IT_MASK, 0xffffffff); - OWRITE(sc, OHCI_IR_MASK, 0xffffffff); - reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK); - OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff); - OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff); - for (i = 0; i < 0x20; i++) - if ((reg & (1 << i)) == 0) - break; - sc->fc.nisodma = i; - aprint_normal_dev(sc->fc.dev, "No. of Isochronous channels is %d.\n", - i); - if (i == 0) - return ENXIO; - sc->fc.arq = &sc->arrq.xferq; sc->fc.ars = &sc->arrs.xferq; sc->fc.atq = &sc->atrq.xferq; @@ -395,6 +372,68 @@ fwohci_init(struct fwohci_softc *sc) sc->atrq.off = OHCI_ATQOFF; sc->atrs.off = OHCI_ATSOFF; + sc->fc.tcode = tinfo; + + sc->fc.cyctimer = fwohci_cyctimer; + sc->fc.ibr = fwohci_ibr; + sc->fc.set_bmr = fwohci_set_bus_manager; + sc->fc.ioctl = fwohci_ioctl; + sc->fc.irx_enable = fwohci_irx_enable; + sc->fc.irx_disable = fwohci_irx_disable; + + sc->fc.itx_enable = fwohci_itxbuf_enable; + sc->fc.itx_disable = fwohci_itx_disable; + sc->fc.timeout = fwohci_timeout; + sc->fc.set_intr = fwohci_set_intr; +#if BYTE_ORDER == BIG_ENDIAN + sc->fc.irx_post = fwohci_irx_post; +#else + sc->fc.irx_post = NULL; +#endif + sc->fc.itx_post = NULL; + + sc->intmask = sc->irstat = sc->itstat = 0; + + fw_init(&sc->fc); +} + +/* + * Call fwohci_attach after fwohci_init to initialize the hardware and + * attach children. + */ + +int +fwohci_attach(struct fwohci_softc *sc) +{ + uint32_t reg; + uint8_t ui[8]; + int i, mver; + +/* OHCI version */ + reg = OREAD(sc, OHCI_VERSION); + mver = (reg >> 16) & 0xff; + aprint_normal_dev(sc->fc.dev, "OHCI version %x.%x (ROM=%d)\n", + mver, reg & 0xff, (reg >> 24) & 1); + if (mver < 1 || mver > 9) { + aprint_error_dev(sc->fc.dev, "invalid OHCI version\n"); + return ENXIO; + } + +/* Available Isochronous DMA channel probe */ + OWRITE(sc, OHCI_IT_MASK, 0xffffffff); + OWRITE(sc, OHCI_IR_MASK, 0xffffffff); + reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK); + OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff); + OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff); + for (i = 0; i < 0x20; i++) + if ((reg & (1 << i)) == 0) + break; + sc->fc.nisodma = i; + aprint_normal_dev(sc->fc.dev, "No. of Isochronous channels is %d.\n", + i); + if (i == 0) + return ENXIO; + for (i = 0; i < sc->fc.nisodma; i++) { sc->fc.it[i] = &sc->it[i].xferq; sc->fc.ir[i] = &sc->ir[i].xferq; @@ -406,8 +445,6 @@ fwohci_init(struct fwohci_softc *sc) sc->ir[i].off = OHCI_IROFF(i); } - sc->fc.tcode = tinfo; - sc->fc.config_rom = fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat, CROMSIZE, &sc->crom_dma, CROMSIZE, BUS_DMA_NOWAIT); if (sc->fc.config_rom == NULL) { @@ -467,27 +504,6 @@ fwohci_init(struct fwohci_softc *sc) "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]); - sc->fc.cyctimer = fwohci_cyctimer; - sc->fc.ibr = fwohci_ibr; - sc->fc.set_bmr = fwohci_set_bus_manager; - sc->fc.ioctl = fwohci_ioctl; - sc->fc.irx_enable = fwohci_irx_enable; - sc->fc.irx_disable = fwohci_irx_disable; - - sc->fc.itx_enable = fwohci_itxbuf_enable; - sc->fc.itx_disable = fwohci_itx_disable; - sc->fc.timeout = fwohci_timeout; - sc->fc.set_intr = fwohci_set_intr; -#if BYTE_ORDER == BIG_ENDIAN - sc->fc.irx_post = fwohci_irx_post; -#else - sc->fc.irx_post = NULL; -#endif - sc->fc.itx_post = NULL; - - sc->intmask = sc->irstat = sc->itstat = 0; - - fw_init(&sc->fc); fwohci_reset(sc); sc->fc.bdev = @@ -499,10 +515,13 @@ fwohci_init(struct fwohci_softc *sc) int fwohci_detach(struct fwohci_softc *sc, int flags) { - int i; + int i, rv; - if (sc->fc.bdev != NULL) - config_detach(sc->fc.bdev, flags); + if (sc->fc.bdev != NULL) { + rv = config_detach(sc->fc.bdev, flags); + if (rv) + return rv; + } if (sc->sid_buf != NULL) fwdma_free(sc->sid_dma.dma_tag, sc->sid_dma.dma_map, sc->sid_dma.v_addr); @@ -519,10 +538,7 @@ fwohci_detach(struct fwohci_softc *sc, int flags) fwohci_db_free(sc, &sc->ir[i]); } - mutex_destroy(&sc->arrq.xferq.q_mtx); - mutex_destroy(&sc->arrs.xferq.q_mtx); - mutex_destroy(&sc->atrq.xferq.q_mtx); - mutex_destroy(&sc->atrs.xferq.q_mtx); + fw_destroy(&sc->fc); return 0; } diff --git a/sys/dev/ieee1394/fwohcivar.h b/sys/dev/ieee1394/fwohcivar.h index 49340cb..d8625ac 100644 --- a/sys/dev/ieee1394/fwohcivar.h +++ b/sys/dev/ieee1394/fwohcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: fwohcivar.h,v 1.33 2012/04/29 18:31:40 dsl Exp $ */ +/* $NetBSD: fwohcivar.h,v 1.34 2012/08/04 03:55:43 riastradh Exp $ */ /*- * Copyright (c) 2003 Hidetoshi SHimokawa @@ -77,7 +77,8 @@ struct fwohci_softc { #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x)) #define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r)) -int fwohci_init(struct fwohci_softc *); +void fwohci_init(struct fwohci_softc *); +int fwohci_attach(struct fwohci_softc *); int fwohci_detach(struct fwohci_softc *, int); int fwohci_intr(void *arg); int fwohci_resume(struct fwohci_softc *);