diff options
| author | kiyohara <kiyohara@NetBSD.org> | 2010-03-29 03:05:27 +0000 |
|---|---|---|
| committer | kiyohara <kiyohara@NetBSD.org> | 2010-03-29 03:05:27 +0000 |
| commit | af09db112bcc2edf9000478840d7969acbb47de6 (patch) | |
| tree | c9d7967429348bdcbca8ed447d3f15e9eb45cc92 /sys/dev | |
| parent | 3fa2c4cfe9c9e11c2344b14ea5fd00695d97811a (diff) | |
Bye-bye fw_port.h.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/cardbus/fwohci_cardbus.c | 11 | ||||
| -rw-r--r-- | sys/dev/ieee1394/firewire.c | 2564 | ||||
| -rw-r--r-- | sys/dev/ieee1394/firewire.h | 105 | ||||
| -rw-r--r-- | sys/dev/ieee1394/firewire_phy.h | 8 | ||||
| -rw-r--r-- | sys/dev/ieee1394/firewirereg.h | 103 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fw_port.h | 809 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwcrom.c | 163 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwdev.c | 842 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwdma.c | 212 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwdma.h | 69 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwmem.c | 497 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwmem.h | 45 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwohci.c | 3341 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwohcireg.h | 93 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwohcivar.h | 55 | ||||
| -rw-r--r-- | sys/dev/ieee1394/fwphyreg.h | 27 | ||||
| -rw-r--r-- | sys/dev/ieee1394/iec13213.h | 17 | ||||
| -rw-r--r-- | sys/dev/ieee1394/iec68113.h | 9 | ||||
| -rw-r--r-- | sys/dev/ieee1394/if_fwip.c | 826 | ||||
| -rw-r--r-- | sys/dev/ieee1394/if_fwipvar.h | 52 | ||||
| -rw-r--r-- | sys/dev/ieee1394/sbp.c | 2546 | ||||
| -rw-r--r-- | sys/dev/ieee1394/sbp.h | 12 | ||||
| -rw-r--r-- | sys/dev/pci/fwohci_pci.c | 26 |
23 files changed, 5167 insertions, 7265 deletions
diff --git a/sys/dev/cardbus/fwohci_cardbus.c b/sys/dev/cardbus/fwohci_cardbus.c index 61fffce5784..5065167ab83 100644 --- a/sys/dev/cardbus/fwohci_cardbus.c +++ b/sys/dev/cardbus/fwohci_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwohci_cardbus.c,v 1.31 2010/03/05 00:36:06 dyoung Exp $ */ +/* $NetBSD: fwohci_cardbus.c,v 1.32 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fwohci_cardbus.c,v 1.31 2010/03/05 00:36:06 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fwohci_cardbus.c,v 1.32 2010/03/29 03:05:27 kiyohara Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -47,7 +47,6 @@ __KERNEL_RCSID(0, "$NetBSD: fwohci_cardbus.c,v 1.31 2010/03/05 00:36:06 dyoung E #include <dev/cardbus/cardbusvar.h> #include <dev/pci/pcidevs.h> -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/firewirereg.h> #include <dev/ieee1394/fwdma.h> @@ -116,7 +115,7 @@ fwohci_cardbus_attach(device_t parent, device_t self, void *aux) sc->sc_ct = ct; /* Disable interrupts, so we don't get any spurious ones. */ - OHCI_CSR_WRITE(&sc->sc_sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); + OWRITE(&sc->sc_sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); /* Enable the device. */ csr = Cardbus_conf_read(ct, ca->ca_tag, PCI_COMMAND_STATUS_REG); @@ -124,14 +123,14 @@ fwohci_cardbus_attach(device_t parent, device_t self, void *aux) csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE); sc->sc_ih = Cardbus_intr_establish(ct, ca->ca_intrline, - IPL_BIO, fwohci_filt, sc); + IPL_BIO, fwohci_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt\n"); return; } /* XXX NULL should be replaced by some call to Cardbus coed */ - if (fwohci_init(&sc->sc_sc, sc->sc_sc.fc.dev) != 0) { + if (fwohci_init(&sc->sc_sc) != 0) { Cardbus_intr_disestablish(ct, sc->sc_ih); sc->sc_ih = NULL; } diff --git a/sys/dev/ieee1394/firewire.c b/sys/dev/ieee1394/firewire.c index a33355f3feb..8a41023864f 100644 --- a/sys/dev/ieee1394/firewire.c +++ b/sys/dev/ieee1394/firewire.c @@ -1,4 +1,4 @@ -/* $NetBSD: firewire.c,v 1.26 2010/03/11 04:00:36 mrg Exp $ */ +/* $NetBSD: firewire.c,v 1.27 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -31,55 +31,21 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/firewire/firewire.c,v 1.101 2007/10/20 23:23:14 julian Exp $ + * + * $FreeBSD: src/sys/dev/firewire/firewire.c,v 1.110 2009/04/07 02:33:46 sbruno Exp $ * */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: firewire.c,v 1.26 2010/03/11 04:00:36 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: firewire.c,v 1.27 2010/03/29 03:05:27 kiyohara Exp $"); -#if defined(__FreeBSD__) #include <sys/param.h> -#include <sys/systm.h> -#include <sys/types.h> - -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/malloc.h> -#include <sys/conf.h> -#include <sys/sysctl.h> -#include <sys/kthread.h> - -#include <sys/kdb.h> - -#if defined(__DragonFly__) || __FreeBSD_version < 500000 -#include <machine/clock.h> /* for DELAY() */ -#endif - -#include <sys/bus.h> /* used by smbus and newbus */ #include <sys/bus.h> - -#ifdef __DragonFly__ -#include "fw_port.h" -#include "firewire.h" -#include "firewirereg.h" -#include "fwmem.h" -#include "iec13213.h" -#include "iec68113.h" -#else -#include <dev/firewire/fw_port.h> -#include <dev/firewire/firewire.h> -#include <dev/firewire/firewirereg.h> -#include <dev/firewire/fwmem.h> -#include <dev/firewire/iec13213.h> -#include <dev/firewire/iec68113.h> -#endif -#elif defined(__NetBSD__) -#include <sys/param.h> +#include <sys/callout.h> +#include <sys/condvar.h> +#include <sys/conf.h> #include <sys/device.h> #include <sys/errno.h> -#include <sys/conf.h> #include <sys/kernel.h> #include <sys/kthread.h> #include <sys/malloc.h> @@ -87,9 +53,6 @@ __KERNEL_RCSID(0, "$NetBSD: firewire.c,v 1.26 2010/03/11 04:00:36 mrg Exp $"); #include <sys/sysctl.h> #include <sys/systm.h> -#include <sys/bus.h> - -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/firewirereg.h> #include <dev/ieee1394/fwmem.h> @@ -97,7 +60,6 @@ __KERNEL_RCSID(0, "$NetBSD: firewire.c,v 1.26 2010/03/11 04:00:36 mrg Exp $"); #include <dev/ieee1394/iec68113.h> #include "locators.h" -#endif struct crom_src_buf { struct crom_src src; @@ -106,19 +68,7 @@ struct crom_src_buf { struct crom_chunk hw; }; -int firewire_debug=0, try_bmr=1, hold_count=3; -#if defined(__FreeBSD__) -SYSCTL_INT(_debug, OID_AUTO, firewire_debug, CTLFLAG_RW, &firewire_debug, 0, - "FireWire driver debug flag"); -SYSCTL_NODE(_hw, OID_AUTO, firewire, CTLFLAG_RD, 0, "FireWire Subsystem"); -SYSCTL_INT(_hw_firewire, OID_AUTO, try_bmr, CTLFLAG_RW, &try_bmr, 0, - "Try to be a bus manager"); -SYSCTL_INT(_hw_firewire, OID_AUTO, hold_count, CTLFLAG_RW, &hold_count, 0, - "Number of count of bus resets for removing lost device information"); - -MALLOC_DEFINE(M_FW, "firewire", "FireWire"); -MALLOC_DEFINE(M_FWXFER, "fw_xfer", "XFER/FireWire"); -#elif defined(__NetBSD__) +int firewire_debug = 0, try_bmr = 1, hold_count = 0; /* * Setup sysctl(3) MIB, hw.ieee1394if.* * @@ -174,69 +124,54 @@ SYSCTL_SETUP(sysctl_ieee1394if, "sysctl ieee1394if(4) subtree setup") return; err: - printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); + aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); } MALLOC_DEFINE(M_FW, "ieee1394", "IEEE1394"); MALLOC_DEFINE(M_FWXFER, "fw_xfer", "XFER/IEEE1394"); -#endif #define FW_MAXASYRTY 4 -#if defined(__FreeBSD__) -devclass_t firewire_devclass; +#define FW_GENERATION_CHANGEABLE 2 + +static int firewirematch (device_t, cfdata_t, void *); +static void firewireattach (device_t, device_t, void *); +static int firewiredetach (device_t, int); +static int firewire_print (void *, const char *); -static void firewire_identify (driver_t *, device_t); -static int firewire_probe (device_t); -static int firewire_attach (device_t); -static int firewire_detach (device_t); -static int firewire_resume (device_t); -#if 0 -static int firewire_shutdown (device_t); -#endif -static device_t firewire_add_child (device_t, int, const char *, int); -#elif defined(__NetBSD__) -int firewirematch (device_t, cfdata_t, void *); -void firewireattach (device_t, device_t, void *); -int firewiredetach (device_t, int); -int firewire_print (void *, const char *); int firewire_resume (struct firewire_comm *); -#endif -static void firewire_xfer_timeout(void *, int); -static void fw_try_bmr (void *); -static void fw_try_bmr_callback (struct fw_xfer *); -static void fw_asystart (struct fw_xfer *); -static int fw_get_tlabel (struct firewire_comm *, struct fw_xfer *); -static void fw_bus_probe (struct firewire_comm *); -static void fw_attach_dev (struct firewire_comm *); -static void fw_bus_probe_thread(void *); -#ifdef FW_VMACCESS -static void fw_vmaccess (struct fw_xfer *); -#endif -static int fw_bmr (struct firewire_comm *); + +static void fw_asystart(struct fw_xfer *); +static void firewire_xfer_timeout(struct firewire_comm *); +static void firewire_watchdog(void *); +static void fw_xferq_drain(struct fw_xferq *); +static void fw_reset_csr(struct firewire_comm *); +static void fw_init_crom(struct firewire_comm *); +static void fw_reset_crom(struct firewire_comm *); static void fw_dump_hdr(struct fw_pkt *, const char *); +static void fw_tl_free(struct firewire_comm *, struct fw_xfer *); +static struct fw_xfer *fw_tl2xfer(struct firewire_comm *, int, int, int); +static void fw_phy_config(struct firewire_comm *, int, int); +static void fw_print_sid(uint32_t); +static void fw_bus_probe(struct firewire_comm *); +static int fw_explore_read_quads(struct fw_device *, int, uint32_t *, int); +static int fw_explore_csrblock(struct fw_device *, int, int); +static int fw_explore_node(struct fw_device *); +static union fw_self_id *fw_find_self_id(struct firewire_comm *, int); +static void fw_explore(struct firewire_comm *); +static void fw_bus_probe_thread(void *); +static void fw_attach_dev(struct firewire_comm *); +static int fw_get_tlabel(struct firewire_comm *, struct fw_xfer *); +static void fw_rcv_copy(struct fw_rcv_buf *); +static void fw_try_bmr_callback(struct fw_xfer *); +static void fw_try_bmr(void *); +static int fw_bmr(struct firewire_comm *); + -#if defined(__FreeBSD__) -static device_method_t firewire_methods[] = { - /* Device interface */ - DEVMETHOD(device_identify, firewire_identify), - DEVMETHOD(device_probe, firewire_probe), - DEVMETHOD(device_attach, firewire_attach), - DEVMETHOD(device_detach, firewire_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, firewire_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - /* Bus interface */ - DEVMETHOD(bus_add_child, firewire_add_child), - DEVMETHOD(bus_print_child, bus_generic_print_child), - - { 0, 0 } -}; -#elif defined(__NetBSD__) CFATTACH_DECL_NEW(ieee1394if, sizeof(struct firewire_softc), firewirematch, firewireattach, firewiredetach, NULL); -#endif + + const char *fw_linkspeed[] = { "S100", "S200", "S400", "S800", "S1600", "S3200", "undef", "undef" @@ -254,13 +189,175 @@ static const char *tcode_str[] = { u_int gap_cnt[] = { 5, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40}; -#if defined(__FreeBSD__) -static driver_t firewire_driver = { - "firewire", - firewire_methods, - sizeof(struct firewire_softc), -}; -#endif + +static int +firewirematch(device_t parent, cfdata_t cf, void *aux) +{ + + return 1; /* always match */ +} + +static void +firewireattach(device_t parent, device_t self, void *aux) +{ + struct firewire_softc *sc = device_private(self); + struct firewire_comm *fc = device_private(parent); + struct fw_attach_args faa; + struct firewire_dev_list *devlist; + + aprint_naive("\n"); + aprint_normal(": IEEE1394 bus\n"); + + fc->bdev = sc->dev = self; + sc->fc = fc; + SLIST_INIT(&sc->devlist); + + fc->status = FWBUSNOTREADY; + + if (fc->nisodma > FWMAXNDMA) + fc->nisodma = FWMAXNDMA; + + fc->crom_src_buf = + (struct crom_src_buf *)malloc(sizeof(struct crom_src_buf), + M_FW, M_NOWAIT | M_ZERO); + if (fc->crom_src_buf == NULL) { + aprint_error_dev(fc->bdev, "Malloc Failure crom src buff\n"); + return; + } + fc->topology_map = + (struct fw_topology_map *)malloc(sizeof(struct fw_topology_map), + M_FW, M_NOWAIT | M_ZERO); + if (fc->topology_map == NULL) { + aprint_error_dev(fc->dev, "Malloc Failure topology map\n"); + free(fc->crom_src_buf, M_FW); + return; + } + fc->speed_map = + (struct fw_speed_map *)malloc(sizeof(struct fw_speed_map), + M_FW, M_NOWAIT | M_ZERO); + if (fc->speed_map == NULL) { + aprint_error_dev(fc->dev, "Malloc Failure speed map\n"); + free(fc->crom_src_buf, M_FW); + free(fc->topology_map, M_FW); + return; + } + + mutex_init(&fc->tlabel_lock, MUTEX_DEFAULT, IPL_VM); + mutex_init(&fc->fc_mtx, MUTEX_DEFAULT, IPL_VM); + mutex_init(&fc->wait_lock, MUTEX_DEFAULT, IPL_VM); + cv_init(&fc->fc_cv, "ieee1394"); + + callout_init(&fc->timeout_callout, CALLOUT_MPSAFE); + callout_setfunc(&fc->timeout_callout, firewire_watchdog, fc); + callout_init(&fc->bmr_callout, CALLOUT_MPSAFE); + callout_setfunc(&fc->bmr_callout, fw_try_bmr, fc); + callout_init(&fc->busprobe_callout, CALLOUT_MPSAFE); + callout_setfunc(&fc->busprobe_callout, (void *)fw_bus_probe, fc); + + callout_schedule(&fc->timeout_callout, hz); + + /* create thread */ + if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, fw_bus_probe_thread, + fc, &fc->probe_thread, "fw%dprobe", device_unit(fc->bdev))) + aprint_error_dev(self, "kthread_create failed\n"); + config_pending_incr(); + + devlist = malloc(sizeof(struct firewire_dev_list), M_DEVBUF, M_NOWAIT); + if (devlist == NULL) { + aprint_error_dev(self, "device list allocation failed\n"); + return; + } + + faa.name = "fwip"; + faa.fc = fc; + faa.fwdev = NULL; + devlist->dev = config_found(sc->dev, &faa, firewire_print); + if (devlist->dev == NULL) + free(devlist, M_DEVBUF); + else + SLIST_INSERT_HEAD(&sc->devlist, devlist, link); + + /* bus_reset */ + fw_busreset(fc, FWBUSNOTREADY); + fc->ibr(fc); + + if (!pmf_device_register(self, NULL, NULL)) + aprint_error_dev(self, "couldn't establish power handler\n"); + + return; +} + +static int +firewiredetach(device_t self, int flags) +{ + struct firewire_softc *sc = device_private(self); + struct firewire_comm *fc; + struct fw_device *fwdev, *fwdev_next; + struct firewire_dev_list *devlist; + int err; + + fc = sc->fc; + mutex_enter(&fc->wait_lock); + fc->status = FWBUSDETACH; + cv_signal(&fc->fc_cv); + while (fc->status != FWBUSDETACHOK) { + err = cv_timedwait_sig(&fc->fc_cv, &fc->wait_lock, hz * 60); + if (err == EWOULDBLOCK) { + aprint_error_dev(self, + "firewire probe thread didn't die\n"); + break; + } + } + mutex_exit(&fc->wait_lock); + + + while ((devlist = SLIST_FIRST(&sc->devlist)) != NULL) { + if ((err = config_detach(devlist->dev, flags)) != 0) + return err; + SLIST_REMOVE(&sc->devlist, devlist, firewire_dev_list, link); + free(devlist, M_DEVBUF); + } + + callout_stop(&fc->timeout_callout); + callout_stop(&fc->bmr_callout); + callout_stop(&fc->busprobe_callout); + + /* XXX xfer_free and untimeout on all xfers */ + for (fwdev = STAILQ_FIRST(&fc->devices); fwdev != NULL; + fwdev = fwdev_next) { + fwdev_next = STAILQ_NEXT(fwdev, link); + free(fwdev, M_FW); + } + free(fc->topology_map, M_FW); + free(fc->speed_map, M_FW); + free(fc->crom_src_buf, M_FW); + + cv_destroy(&fc->fc_cv); + mutex_destroy(&fc->wait_lock); + mutex_destroy(&fc->fc_mtx); + mutex_destroy(&fc->tlabel_lock); + return 0; +} + +static int +firewire_print(void *aux, const char *pnp) +{ + struct fw_attach_args *fwa = (struct fw_attach_args *)aux; + + if (pnp) + aprint_normal("%s at %s", fwa->name, pnp); + + return UNCONF; +} + +int +firewire_resume(struct firewire_comm *fc) +{ + + fc->status = FWBUSNOTREADY; + return 0; +} + /* * Lookup fwdev by node id. @@ -269,15 +366,12 @@ struct fw_device * fw_noderesolve_nodeid(struct firewire_comm *fc, int dst) { struct fw_device *fwdev; - int s; - s = splfw(); - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); STAILQ_FOREACH(fwdev, &fc->devices, link) if (fwdev->dst == dst && fwdev->status != FWDEVINVAL) break; - FW_GUNLOCK(fc); - splx(s); + mutex_exit(&fc->fc_mtx); return fwdev; } @@ -289,16 +383,17 @@ struct fw_device * fw_noderesolve_eui64(struct firewire_comm *fc, struct fw_eui64 *eui) { struct fw_device *fwdev; - int s; - s = splfw(); + mutex_enter(&fc->fc_mtx); STAILQ_FOREACH(fwdev, &fc->devices, link) if (FW_EUI64_EQUAL(fwdev->eui, *eui)) break; - splx(s); + mutex_exit(&fc->fc_mtx); - if(fwdev == NULL) return NULL; - if(fwdev->status == FWDEVINVAL) return NULL; + if (fwdev == NULL) + return NULL; + if (fwdev->status == FWDEVINVAL) + return NULL; return fwdev; } @@ -308,16 +403,16 @@ fw_noderesolve_eui64(struct firewire_comm *fc, struct fw_eui64 *eui) int fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) { - int err = 0; struct fw_xferq *xferq; int len; struct fw_pkt *fp; int tcode; const struct tcode_info *info; - if(xfer == NULL) return EINVAL; - if(xfer->hand == NULL){ - printf("hand == NULL\n"); + if (xfer == NULL) + return EINVAL; + if (xfer->hand == NULL) { + aprint_error_dev(fc->bdev, "hand == NULL\n"); return EINVAL; } fp = &xfer->send.hdr; @@ -325,18 +420,18 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) tcode = fp->mode.common.tcode & 0xf; info = &fc->tcode[tcode]; if (info->flag == 0) { - printf("invalid tcode=%x\n", tcode); + aprint_error_dev(fc->bdev, "invalid tcode=%x\n", tcode); return EINVAL; } /* XXX allow bus explore packets only after bus rest */ if ((fc->status < FWBUSEXPLORE) && ((tcode != FWTCODE_RREQQ) || (fp->mode.rreqq.dest_hi != 0xffff) || - (fp->mode.rreqq.dest_lo < 0xf0000000) || + (fp->mode.rreqq.dest_lo < 0xf0000000) || (fp->mode.rreqq.dest_lo >= 0xf0001000))) { xfer->resp = EAGAIN; xfer->flag = FWXF_BUSY; - return (EAGAIN); + return EAGAIN; } if (info->flag & FWTI_REQ) @@ -345,7 +440,7 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) xferq = fc->ats; len = info->hdr_len; if (xfer->send.pay_len > MAXREC(fc->maxrec)) { - printf("send.pay_len > maxrec\n"); + aprint_error_dev(fc->bdev, "send.pay_len > maxrec\n"); return EINVAL; } if (info->flag & FWTI_BLOCK_STR) @@ -354,369 +449,85 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) len = fp->mode.rresb.len; else len = 0; - if (len != xfer->send.pay_len){ - printf("len(%d) != send.pay_len(%d) %s(%x)\n", + if (len != xfer->send.pay_len) { + aprint_error_dev(fc->bdev, + "len(%d) != send.pay_len(%d) %s(%x)\n", len, xfer->send.pay_len, tcode_str[tcode], tcode); - return EINVAL; + return EINVAL; } - if(xferq->start == NULL){ - printf("xferq->start == NULL\n"); + if (xferq->start == NULL) { + aprint_error_dev(fc->bdev, "xferq->start == NULL\n"); return EINVAL; } - if(!(xferq->queued < xferq->maxq)){ - fw_printf(fc->bdev, "Discard a packet (queued=%d)\n", + if (!(xferq->queued < xferq->maxq)) { + aprint_error_dev(fc->bdev, "Discard a packet (queued=%d)\n", xferq->queued); return EAGAIN; } xfer->tl = -1; - if (info->flag & FWTI_TLABEL) { + if (info->flag & FWTI_TLABEL) if (fw_get_tlabel(fc, xfer) < 0) return EAGAIN; - } xfer->resp = 0; xfer->fc = fc; xfer->q = xferq; fw_asystart(xfer); - return err; + return 0; } + /* * Wakeup blocked process. */ void fw_xferwake(struct fw_xfer *xfer) { - fw_mtx_t lock = &xfer->fc->wait_lock; - fw_mtx_lock(lock); + mutex_enter(&xfer->fc->wait_lock); xfer->flag |= FWXF_WAKE; - fw_mtx_unlock(lock); + cv_signal(&xfer->cv); + mutex_exit(&xfer->fc->wait_lock); - wakeup(xfer); return; } int fw_xferwait(struct fw_xfer *xfer) { - fw_mtx_t lock = &xfer->fc->wait_lock; - int err = 0; - - fw_mtx_lock(lock); - if ((xfer->flag & FWXF_WAKE) == 0) - err = fw_msleep((void *)xfer, lock, PWAIT|PCATCH, "fw_xferwait", 0); - fw_mtx_unlock(lock); - - return (err); -} - -/* - * Async. request with given xfer structure. - */ -static void -fw_asystart(struct fw_xfer *xfer) -{ struct firewire_comm *fc = xfer->fc; - int s; - s = splfw(); - /* Protect from interrupt/timeout */ - FW_GLOCK(fc); - xfer->flag = FWXF_INQ; - STAILQ_INSERT_TAIL(&xfer->q->q, xfer, link); -#if 0 - xfer->q->queued ++; -#endif - FW_GUNLOCK(fc); - splx(s); - /* XXX just queue for mbuf */ - if (xfer->mbuf == NULL) - xfer->q->start(fc); - return; -} - -#if defined(__FreeBSD__) -static void -firewire_identify(driver_t *driver, device_t parent) -{ - BUS_ADD_CHILD(parent, 0, "firewire", -1); -} - -static int -firewire_probe(device_t dev) -{ - device_set_desc(dev, "IEEE1394(FireWire) bus"); - return (0); -} -#elif defined(__NetBSD__) -int -firewirematch(device_t parent, cfdata_t cf, void *aux) -{ - struct fwbus_attach_args *faa = (struct fwbus_attach_args *)aux; - - if (strcmp(faa->name, "ieee1394if") == 0) - return (1); - return (0); -} -#endif - -static void -firewire_xfer_timeout(void *arg, int pending) -{ - struct firewire_comm *fc = (struct firewire_comm *)arg; - struct fw_xfer *xfer, *txfer; - struct timeval tv; - struct timeval split_timeout; - STAILQ_HEAD(, fw_xfer) xfer_timeout; - int i, s; - - split_timeout.tv_sec = 0; - split_timeout.tv_usec = 200 * 1000; /* 200 msec */ - - microtime(&tv); - fw_timevalsub(&tv, &split_timeout); - STAILQ_INIT(&xfer_timeout); - - s = splfw(); - fw_mtx_lock(&fc->tlabel_lock); - for (i = 0; i < 0x40; i ++) { - while ((xfer = STAILQ_FIRST(&fc->tlabels[i])) != NULL) { - if ((xfer->flag & FWXF_SENT) == 0) - /* not sent yet */ - break; - if (fw_timevalcmp(&xfer->tv, &tv, >)) - /* the rests are newer than this */ - break; - fw_printf(fc->bdev, - "split transaction timeout: " - "tl=0x%x flag=0x%02x\n", i, xfer->flag); - fw_dump_hdr(&xfer->send.hdr, "send"); - xfer->resp = ETIMEDOUT; - STAILQ_REMOVE_HEAD(&fc->tlabels[i], tlabel); - STAILQ_INSERT_TAIL(&xfer_timeout, xfer, tlabel); - } - } - fw_mtx_unlock(&fc->tlabel_lock); - splx(s); - fc->timeout(fc); - - STAILQ_FOREACH_SAFE(xfer, &xfer_timeout, tlabel, txfer) - xfer->hand(xfer); -} - -#define WATCHDOG_HZ 10 -static void -firewire_watchdog(void *arg) -{ - struct firewire_comm *fc; - static int watchdog_clock = 0; - - fc = (struct firewire_comm *)arg; - - /* - * At boot stage, the device interrupt is disabled and - * We encounter a timeout easily. To avoid this, - * ignore clock interrupt for a while. - */ - if (watchdog_clock > WATCHDOG_HZ * 15) - fw_taskqueue_enqueue(fc->taskqueue, &fc->task_timeout); - else - watchdog_clock ++; - - fw_callout_reset(&fc->timeout_callout, hz / WATCHDOG_HZ, - (void *)firewire_watchdog, (void *)fc); -} - -/* - * The attach routine. - */ -FW_ATTACH(firewire) -{ - FW_ATTACH_START(firewire, sc, fwa); - FIREWIRE_ATTACH_START; - -#ifdef __NetBSD__ - aprint_naive("\n"); -#endif - - sc->fc = fc; - fc->status = FWBUSNOTREADY; - - if( fc->nisodma > FWMAXNDMA) fc->nisodma = FWMAXNDMA; - - FWDEV_MAKEDEV(sc); - - fw_mtx_init(&fc->wait_lock, "fwwait", NULL, MTX_DEF); - fw_mtx_init(&fc->tlabel_lock, "fwtlabel", NULL, MTX_DEF); - fw_callout_init(&fc->timeout_callout); - fw_callout_init(&fc->bmr_callout); - fw_callout_init(&fc->busprobe_callout); - FW_TASK_INIT(&fc->task_timeout, 0, firewire_xfer_timeout, (void *)fc); - - fw_callout_reset(&sc->fc->timeout_callout, hz, - (void *)firewire_watchdog, (void *)sc->fc); - - /* create thread */ - fw_kthread_create(fw_bus_probe_thread, (void *)fc, &fc->probe_thread, - "fw%d_probe", fw_get_unit(fc->bdev)); - fw_config_pending_incr(); - - FIREWIRE_GENERIC_ATTACH; - - /* bus_reset */ - fw_busreset(fc, FWBUSNOTREADY); - fc->ibr(fc); - -#ifdef __NetBSD__ - if (!pmf_device_register(self, NULL, NULL)) - aprint_error_dev(self, "couldn't establish power handler\n"); -#endif - - FW_ATTACH_RETURN(0); -} - -#if defined(__FreeBSD__) -/* - * Attach it as child. - */ -static device_t -firewire_add_child(device_t dev, int order, const char *name, int unit) -{ - device_t child; - struct firewire_softc *sc; - struct fw_attach_args fwa; - - sc = (struct firewire_softc *)device_get_softc(dev); - child = device_add_child(dev, name, unit); - if (child) { - fwa.name = name; - fwa.fc = sc->fc; - fwa.fwdev = NULL; - device_set_ivars(child, &fwa); - device_probe_and_attach(child); - } - - return child; -} - -static int -firewire_resume(device_t dev) -{ - struct firewire_softc *sc; - - sc = (struct firewire_softc *)device_get_softc(dev); - sc->fc->status = FWBUSNOTREADY; - - bus_generic_resume(dev); - - return(0); -} -#endif - -/* - * Dettach it. - */ -FW_DETACH(firewire) -{ - FW_DETACH_START(firewire, sc); - struct firewire_comm *fc; - struct fw_device *fwdev, *fwdev_next; - - fc = sc->fc; - fw_mtx_lock(&fc->wait_lock); - fc->status = FWBUSDETACH; - wakeup(fc); - if (fw_msleep(fc->probe_thread, - &fc->wait_lock, PWAIT, "fwthr", hz * 60)) - printf("firewire probe thread didn't die\n"); - fw_mtx_unlock(&fc->wait_lock); - - FWDEV_DESTROYDEV(sc); - FIREWIRE_GENERIC_DETACH; - - fw_callout_stop(&fc->timeout_callout); - fw_callout_stop(&fc->bmr_callout); - fw_callout_stop(&fc->busprobe_callout); - - /* XXX xfree_free and untimeout on all xfers */ - for (fwdev = STAILQ_FIRST(&fc->devices); fwdev != NULL; - fwdev = fwdev_next) { - fwdev_next = STAILQ_NEXT(fwdev, link); - free(fwdev, M_FW); - } - free(fc->topology_map, M_FW); - free(fc->speed_map, M_FW); - free(fc->crom_src_buf, M_FW); - - fw_mtx_destroy(&fc->wait_lock); - fw_mtx_destroy(&fc->tlabel_lock); - return(0); -} -#if defined(__FreeBSD__) -#if 0 -static int -firewire_shutdown( device_t dev ) -{ - return 0; -} -#endif -#elif defined(__NetBSD__) -int -firewire_print(void *aux, const char *pnp) -{ - struct fw_attach_args *fwa = (struct fw_attach_args *)aux; - - if (pnp) - aprint_normal("%s at %s", fwa->name, pnp); - - return UNCONF; -} - -int -firewire_resume(struct firewire_comm *fc) -{ - - fc->status = FWBUSNOTREADY; - return 0; -} -#endif + int err = 0; -static void -fw_xferq_drain(struct fw_xferq *xferq) -{ - struct fw_xfer *xfer; + mutex_enter(&fc->wait_lock); + while (!(xfer->flag & FWXF_WAKE)) + err = cv_wait_sig(&xfer->cv, &fc->wait_lock); + mutex_exit(&fc->wait_lock); - while ((xfer = STAILQ_FIRST(&xferq->q)) != NULL) { - STAILQ_REMOVE_HEAD(&xferq->q, link); -#if 0 - xferq->queued --; -#endif - xfer->resp = EAGAIN; - xfer->flag = FWXF_SENTERR; - fw_xfer_done(xfer); - } + return err; } void fw_drain_txq(struct firewire_comm *fc) { - struct fw_xfer *xfer, *txfer; + struct fw_xfer *xfer; STAILQ_HEAD(, fw_xfer) xfer_drain; int i; STAILQ_INIT(&xfer_drain); - FW_GLOCK(fc); + mutex_enter(&fc->atq->q_mtx); fw_xferq_drain(fc->atq); + mutex_exit(&fc->atq->q_mtx); + mutex_enter(&fc->ats->q_mtx); fw_xferq_drain(fc->ats); - for(i = 0; i < fc->nisodma; i++) + mutex_exit(&fc->ats->q_mtx); + for (i = 0; i < fc->nisodma; i++) fw_xferq_drain(fc->it[i]); - FW_GUNLOCK(fc); - fw_mtx_lock(&fc->tlabel_lock); - for (i = 0; i < 0x40; i ++) + mutex_enter(&fc->tlabel_lock); + for (i = 0; i < 0x40; i++) while ((xfer = STAILQ_FIRST(&fc->tlabels[i])) != NULL) { if (firewire_debug) printf("tl=%d flag=%d\n", i, xfer->flag); @@ -724,167 +535,73 @@ fw_drain_txq(struct firewire_comm *fc) STAILQ_REMOVE_HEAD(&fc->tlabels[i], tlabel); STAILQ_INSERT_TAIL(&xfer_drain, xfer, tlabel); } - fw_mtx_unlock(&fc->tlabel_lock); + mutex_exit(&fc->tlabel_lock); - STAILQ_FOREACH_SAFE(xfer, &xfer_drain, tlabel, txfer) + STAILQ_FOREACH(xfer, &xfer_drain, tlabel) xfer->hand(xfer); } -static void -fw_reset_csr(struct firewire_comm *fc) -{ - int i; - - CSRARC(fc, STATE_CLEAR) - = 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ; - CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); - CSRARC(fc, NODE_IDS) = 0x3f; - - CSRARC(fc, TOPO_MAP + 8) = 0; - fc->irm = -1; - - fc->max_node = -1; - - for(i = 2; i < 0x100/4 - 2 ; i++){ - CSRARC(fc, SPED_MAP + i * 4) = 0; - } - CSRARC(fc, STATE_CLEAR) = 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ; - CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); - CSRARC(fc, RESET_START) = 0; - CSRARC(fc, SPLIT_TIMEOUT_HI) = 0; - CSRARC(fc, SPLIT_TIMEOUT_LO) = 800 << 19; - CSRARC(fc, CYCLE_TIME) = 0x0; - CSRARC(fc, BUS_TIME) = 0x0; - CSRARC(fc, BUS_MGR_ID) = 0x3f; - CSRARC(fc, BANDWIDTH_AV) = 4915; - CSRARC(fc, CHANNELS_AV_HI) = 0xffffffff; - CSRARC(fc, CHANNELS_AV_LO) = 0xffffffff; - CSRARC(fc, IP_CHANNELS) = (1 << 31); - - CSRARC(fc, CONF_ROM) = 0x04 << 24; - CSRARC(fc, CONF_ROM + 4) = 0x31333934; /* means strings 1394 */ - CSRARC(fc, CONF_ROM + 8) = 1 << 31 | 1 << 30 | 1 << 29 | - 1 << 28 | 0xff << 16 | 0x09 << 8; - CSRARC(fc, CONF_ROM + 0xc) = 0; - -/* DV depend CSRs see blue book */ - CSRARC(fc, oPCR) &= ~DV_BROADCAST_ON; - CSRARC(fc, iPCR) &= ~DV_BROADCAST_ON; - - CSRARC(fc, STATE_CLEAR) &= ~(1 << 23 | 1 << 15 | 1 << 14 ); - CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); -} - -static void -fw_init_crom(struct firewire_comm *fc) -{ - struct crom_src *src; - - fc->crom_src_buf = (struct crom_src_buf *) - malloc(sizeof(struct crom_src_buf), M_FW, M_WAITOK | M_ZERO); - if (fc->crom_src_buf == NULL) - return; - - src = &fc->crom_src_buf->src; - memset(src, 0, sizeof(struct crom_src)); - - /* BUS info sample */ - src->hdr.info_len = 4; - - src->businfo.bus_name = CSR_BUS_NAME_IEEE1394; - - src->businfo.irmc = 1; - src->businfo.cmc = 1; - src->businfo.isc = 1; - src->businfo.bmc = 1; - src->businfo.pmc = 0; - src->businfo.cyc_clk_acc = 100; - src->businfo.max_rec = fc->maxrec; - src->businfo.max_rom = MAXROM_4; - src->businfo.generation = 1; - src->businfo.link_spd = fc->speed; - - src->businfo.eui64.hi = fc->eui.hi; - src->businfo.eui64.lo = fc->eui.lo; - - STAILQ_INIT(&src->chunk_list); - - fc->crom_src = src; - fc->crom_root = &fc->crom_src_buf->root; -} - -static void -fw_reset_crom(struct firewire_comm *fc) -{ - struct crom_src_buf *buf; - struct crom_src *src; - struct crom_chunk *root; - - if (fc->crom_src_buf == NULL) - fw_init_crom(fc); - - buf = fc->crom_src_buf; - src = fc->crom_src; - root = fc->crom_root; - - STAILQ_INIT(&src->chunk_list); - - memset(root, 0, sizeof(struct crom_chunk)); - crom_add_chunk(src, NULL, root, 0); - crom_add_entry(root, CSRKEY_NCAP, 0x0083c0); /* XXX */ - /* private company_id */ - crom_add_entry(root, CSRKEY_VENDOR, CSRVAL_VENDOR_PRIVATE); - crom_add_simple_text(src, root, &buf->vendor, PROJECT_STR); - crom_add_entry(root, CSRKEY_HW, OS_VER); - crom_add_simple_text(src, root, &buf->hw, hostname); -} - /* * Called after bus reset. */ void fw_busreset(struct firewire_comm *fc, uint32_t new_status) { + struct firewire_softc *sc = device_private(fc->bdev); + struct firewire_dev_list *devlist; struct firewire_dev_comm *fdc; struct crom_src *src; - void *newrom; + uint32_t *newrom; + + if (fc->status == FWBUSMGRELECT) + callout_stop(&fc->bmr_callout); - switch(fc->status){ - case FWBUSMGRELECT: - fw_callout_stop(&fc->bmr_callout); - break; - default: - break; - } fc->status = new_status; fw_reset_csr(fc); + + if (fc->status == FWBUSNOTREADY) + fw_init_crom(fc); + fw_reset_crom(fc); - FIREWIRE_CHILDREN_FOREACH_FUNC(post_busreset, fdc); + /* How many safe this access? */ + SLIST_FOREACH(devlist, &sc->devlist, link) { + fdc = device_private(devlist->dev); + if (fdc->post_busreset != NULL) + fdc->post_busreset(fdc); + } + /* + * If the old config rom needs to be overwritten, + * bump the businfo.generation indicator to + * indicate that we need to be reprobed + * See 1394a-2000 8.3.2.5.4 for more details. + * generation starts at 2 and rolls over at 0xF + * back to 2. + * + * A generation of 0 indicates a device + * that is not 1394a-2000 compliant. + * A generation of 1 indicates a device that + * does not change it's Bus Info Block or + * Configuration ROM. + */ +#define FW_MAX_GENERATION 0xF newrom = malloc(CROMSIZE, M_FW, M_NOWAIT | M_ZERO); src = &fc->crom_src_buf->src; - crom_load(src, (uint32_t *)newrom, CROMSIZE); + crom_load(src, newrom, CROMSIZE); if (memcmp(newrom, fc->config_rom, CROMSIZE) != 0) { - /* bump generation and reload */ - src->businfo.generation ++; - /* generation must be between 0x2 and 0xF */ - if (src->businfo.generation < 2) - src->businfo.generation ++; - crom_load(src, (uint32_t *)newrom, CROMSIZE); - bcopy(newrom, (void *)fc->config_rom, CROMSIZE); + if (src->businfo.generation++ > FW_MAX_GENERATION) + src->businfo.generation = FW_GENERATION_CHANGEABLE; + memcpy((void *)fc->config_rom, newrom, CROMSIZE); } free(newrom, M_FW); } /* Call once after reboot */ -void fw_init(struct firewire_comm *fc) +void +fw_init(struct firewire_comm *fc) { int i; -#ifdef FW_VMACCESS - struct fw_xfer *xfer; - struct fw_bind *fwb; -#endif fc->arq->queued = 0; fc->ars->queued = 0; @@ -903,8 +620,12 @@ void fw_init(struct firewire_comm *fc) STAILQ_INIT(&fc->atq->q); STAILQ_INIT(&fc->ats->q); + mutex_init(&fc->arq->q_mtx, MUTEX_DEFAULT, IPL_VM); + mutex_init(&fc->ars->q_mtx, MUTEX_DEFAULT, IPL_VM); + mutex_init(&fc->atq->q_mtx, MUTEX_DEFAULT, IPL_VM); + mutex_init(&fc->ats->q_mtx, MUTEX_DEFAULT, IPL_VM); - for( i = 0 ; i < fc->nisodma ; i ++ ){ + for (i = 0; i < fc->nisodma; i++) { fc->it[i]->queued = 0; fc->ir[i]->queued = 0; @@ -926,17 +647,11 @@ void fw_init(struct firewire_comm *fc) fc->atq->maxq = FWMAXQUEUE; fc->ats->maxq = FWMAXQUEUE; - for( i = 0 ; i < fc->nisodma ; i++){ + for (i = 0; i < fc->nisodma; i++) { fc->ir[i]->maxq = FWMAXQUEUE; fc->it[i]->maxq = FWMAXQUEUE; } -/* Initialize csr registers */ - fc->topology_map = (struct fw_topology_map *)malloc( - sizeof(struct fw_topology_map), - M_FW, M_NOWAIT | M_ZERO); - fc->speed_map = (struct fw_speed_map *)malloc( - sizeof(struct fw_speed_map), - M_FW, M_NOWAIT | M_ZERO); + CSRARC(fc, TOPO_MAP) = 0x3f1 << 16; CSRARC(fc, TOPO_MAP + 4) = 1; CSRARC(fc, SPED_MAP) = 0x3f1 << 16; @@ -946,50 +661,27 @@ void fw_init(struct firewire_comm *fc) /* Initialize Async handlers */ STAILQ_INIT(&fc->binds); - for( i = 0 ; i < 0x40 ; i++){ + for (i = 0; i < 0x40; i++) STAILQ_INIT(&fc->tlabels[i]); - } /* DV depend CSRs see blue book */ #if 0 CSRARC(fc, oMPR) = 0x3fff0001; /* # output channel = 1 */ CSRARC(fc, oPCR) = 0x8000007a; - for(i = 4 ; i < 0x7c/4 ; i+=4){ - CSRARC(fc, i + oPCR) = 0x8000007a; - } - + for (i = 4; i < 0x7c/4; i+=4) + CSRARC(fc, i + oPCR) = 0x8000007a; + CSRARC(fc, iMPR) = 0x00ff0001; /* # input channel = 1 */ CSRARC(fc, iPCR) = 0x803f0000; - for(i = 4 ; i < 0x7c/4 ; i+=4){ - CSRARC(fc, i + iPCR) = 0x0; - } + for (i = 4; i < 0x7c/4; i+=4) + CSRARC(fc, i + iPCR) = 0x0; #endif fc->crom_src_buf = NULL; - -#ifdef FW_VMACCESS - xfer = fw_xfer_alloc(); - if(xfer == NULL) return; - - fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT); - if(fwb == NULL){ - fw_xfer_free(xfer); - return; - } - xfer->hand = fw_vmaccess; - xfer->fc = fc; - xfer->sc = NULL; - - fwb->start_hi = 0x2; - fwb->start_lo = 0; - fwb->addrlen = 0xffffffff; - fwb->xfer = xfer; - fw_bindadd(fc, fwb); -#endif } -#define BIND_CMP(addr, fwb) (((addr) < (fwb)->start)?-1:\ - ((fwb)->end < (addr))?1:0) +#define BIND_CMP(addr, fwb) \ + (((addr) < (fwb)->start) ? -1 : ((fwb)->end < (addr)) ? 1 : 0) /* * To lookup bound process from IEEE1394 address. @@ -1001,14 +693,14 @@ fw_bindlookup(struct firewire_comm *fc, uint16_t dest_hi, uint32_t dest_lo) struct fw_bind *tfw, *r = NULL; addr = ((u_int64_t)dest_hi << 32) | dest_lo; - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); STAILQ_FOREACH(tfw, &fc->binds, fclist) if (BIND_CMP(addr, tfw) == 0) { r = tfw; break; } - FW_GUNLOCK(fc); - return(r); + mutex_exit(&fc->fc_mtx); + return r; } /* @@ -1021,11 +713,11 @@ fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb) int r = 0; if (fwb->start > fwb->end) { - printf("%s: invalid range\n", __func__); + aprint_error_dev(fc->bdev, "invalid range\n"); return EINVAL; } - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); STAILQ_FOREACH(tfw, &fc->binds, fclist) { if (fwb->end < tfw->start) break; @@ -1036,11 +728,11 @@ fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb) else if (prev->end < fwb->start) STAILQ_INSERT_AFTER(&fc->binds, prev, fwb, fclist); else { - printf("%s: bind failed\n", __func__); + aprint_error_dev(fc->bdev, "bind failed\n"); r = EBUSY; } - FW_GUNLOCK(fc); - return (r); + mutex_exit(&fc->fc_mtx); + return r; } /* @@ -1053,20 +745,18 @@ fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb) struct fw_xfer *xfer, *next; #endif struct fw_bind *tfw; - int s; - s = splfw(); - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); STAILQ_FOREACH(tfw, &fc->binds, fclist) if (tfw == fwb) { STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist); + mutex_exit(&fc->fc_mtx); goto found; } - printf("%s: no such binding\n", __func__); - FW_GUNLOCK(fc); - splx(s); - return (1); + mutex_exit(&fc->fc_mtx); + aprint_error_dev(fc->bdev, "no such binding\n"); + return 1; found: #if 0 /* shall we do this? */ @@ -1076,32 +766,28 @@ found: } STAILQ_INIT(&fwb->xferlist); #endif - FW_GUNLOCK(fc); - splx(s); return 0; } int -fw_xferlist_add(struct fw_xferlist *q, struct malloc_type *type, - int slen, int rlen, int n, - struct firewire_comm *fc, void *sc, void (*hand)(struct fw_xfer *)) +fw_xferlist_add(struct fw_xferlist *q, struct malloc_type *type, int slen, + int rlen, int n, struct firewire_comm *fc, void *sc, + void (*hand)(struct fw_xfer *)) { - int i, s; struct fw_xfer *xfer; + int i; for (i = 0; i < n; i++) { xfer = fw_xfer_alloc_buf(type, slen, rlen); if (xfer == NULL) - return (n); + return n; xfer->fc = fc; xfer->sc = sc; xfer->hand = hand; - s = splfw(); STAILQ_INSERT_TAIL(q, xfer, link); - splx(s); } - return (n); + return n; } void @@ -1117,94 +803,6 @@ fw_xferlist_remove(struct fw_xferlist *q) } /* - * dump packet header - */ -static void -fw_dump_hdr(struct fw_pkt *fp, const char *prefix) -{ - printf("%s: dst=0x%02x tl=0x%02x rt=%d tcode=0x%x pri=0x%x " - "src=0x%03x\n", prefix, - fp->mode.hdr.dst & 0x3f, - fp->mode.hdr.tlrt >> 2, fp->mode.hdr.tlrt & 3, - fp->mode.hdr.tcode, fp->mode.hdr.pri, - fp->mode.hdr.src); -} - -/* - * To free transaction label. - */ -static void -fw_tl_free(struct firewire_comm *fc, struct fw_xfer *xfer) -{ - struct fw_xfer *txfer; - int s; - - if (xfer->tl < 0) - return; - - s = splfw(); - fw_mtx_lock(&fc->tlabel_lock); -#if 1 /* make sure the label is allocated */ - STAILQ_FOREACH(txfer, &fc->tlabels[xfer->tl], tlabel) - if(txfer == xfer) - break; - if (txfer == NULL) { - printf("%s: the xfer is not in the queue " - "(tlabel=%d, flag=0x%x)\n", - __func__, xfer->tl, xfer->flag); - fw_dump_hdr(&xfer->send.hdr, "send"); - fw_dump_hdr(&xfer->recv.hdr, "recv"); - kdb_backtrace(); - fw_mtx_unlock(&fc->tlabel_lock); - splx(s); - return; - } -#endif - - STAILQ_REMOVE(&fc->tlabels[xfer->tl], xfer, fw_xfer, tlabel); - fw_mtx_unlock(&fc->tlabel_lock); - splx(s); - return; -} - -/* - * To obtain XFER structure by transaction label. - */ -static struct fw_xfer * -fw_tl2xfer(struct firewire_comm *fc, int node, int tlabel, int tcode) -{ - struct fw_xfer *xfer; - int s = splfw(); - int req; - - fw_mtx_lock(&fc->tlabel_lock); - STAILQ_FOREACH(xfer, &fc->tlabels[tlabel], tlabel) - if(xfer->send.hdr.mode.hdr.dst == node) { - fw_mtx_unlock(&fc->tlabel_lock); - splx(s); - FW_KASSERT(xfer->tl == tlabel, - ("xfer->tl 0x%x != 0x%x", xfer->tl, tlabel)); - /* extra sanity check */ - req = xfer->send.hdr.mode.hdr.tcode; - if (xfer->fc->tcode[req].valid_res != tcode) { - printf("%s: invalid response tcode " - "(0x%x for 0x%x)\n", __func__, - tcode, req); - return(NULL); - } - - if (firewire_debug > 2) - printf("fw_tl2xfer: found tl=%d\n", tlabel); - return(xfer); - } - fw_mtx_unlock(&fc->tlabel_lock); - if (firewire_debug > 1) - printf("fw_tl2xfer: not found tl=%d\n", tlabel); - splx(s); - return(NULL); -} - -/* * To allocate IEEE1394 XFER structure. */ struct fw_xfer * @@ -1217,6 +815,7 @@ fw_xfer_alloc(struct malloc_type *type) return xfer; xfer->malloc = type; + cv_init(&xfer->cv, "fwxfer"); return xfer; } @@ -1228,14 +827,14 @@ fw_xfer_alloc_buf(struct malloc_type *type, int send_len, int recv_len) xfer = fw_xfer_alloc(type); if (xfer == NULL) - return(NULL); + return NULL; xfer->send.pay_len = send_len; xfer->recv.pay_len = recv_len; if (send_len > 0) { xfer->send.payload = malloc(send_len, type, M_NOWAIT | M_ZERO); if (xfer->send.payload == NULL) { fw_xfer_free(xfer); - return(NULL); + return NULL; } } if (recv_len > 0) { @@ -1244,10 +843,10 @@ fw_xfer_alloc_buf(struct malloc_type *type, int send_len, int recv_len) if (xfer->send.payload != NULL) free(xfer->send.payload, type); fw_xfer_free(xfer); - return(NULL); + return NULL; } } - return(xfer); + return xfer; } /* @@ -1256,8 +855,9 @@ fw_xfer_alloc_buf(struct malloc_type *type, int send_len, int recv_len) void fw_xfer_done(struct fw_xfer *xfer) { + if (xfer->hand == NULL) { - printf("hand == NULL\n"); + aprint_error_dev(xfer->fc->bdev, "hand == NULL\n"); return; } @@ -1271,202 +871,147 @@ fw_xfer_done(struct fw_xfer *xfer) void fw_xfer_unload(struct fw_xfer* xfer) { - int s; - if(xfer == NULL ) return; - if(xfer->flag & FWXF_INQ){ - printf("fw_xfer_free FWXF_INQ\n"); - s = splfw(); - FW_GLOCK(xfer->fc); + if (xfer == NULL) + return; + if (xfer->flag & FWXF_INQ) { + aprint_error_dev(xfer->fc->bdev, "fw_xfer_free FWXF_INQ\n"); + mutex_enter(&xfer->q->q_mtx); STAILQ_REMOVE(&xfer->q->q, xfer, fw_xfer, link); #if 0 - xfer->q->queued --; + xfer->q->queued--; #endif - FW_GUNLOCK(xfer->fc); - splx(s); + mutex_exit(&xfer->q->q_mtx); } if (xfer->fc != NULL) { #if 1 - if(xfer->flag == FWXF_START) + if (xfer->flag == FWXF_START) /* * This could happen if: * 1. We call fwohci_arcv() before fwohci_txd(). * 2. firewire_watch() is called. */ - printf("fw_xfer_free FWXF_START\n"); + aprint_error_dev(xfer->fc->bdev, + "fw_xfer_free FWXF_START\n"); #endif } xfer->flag = FWXF_INIT; xfer->resp = 0; } + /* - * To free IEEE1394 XFER structure. + * To free IEEE1394 XFER structure. */ void -fw_xfer_free_buf( struct fw_xfer* xfer) +fw_xfer_free(struct fw_xfer* xfer) { + if (xfer == NULL) { - printf("%s: xfer == NULL\n", __func__); + aprint_error_dev(xfer->fc->bdev, "xfer == NULL\n"); return; } fw_xfer_unload(xfer); - if(xfer->send.payload != NULL){ - free(xfer->send.payload, xfer->malloc); - } - if(xfer->recv.payload != NULL){ - free(xfer->recv.payload, xfer->malloc); - } + cv_destroy(&xfer->cv); free(xfer, xfer->malloc); } void -fw_xfer_free( struct fw_xfer* xfer) +fw_xfer_free_buf(struct fw_xfer* xfer) { + if (xfer == NULL) { - printf("%s: xfer == NULL\n", __func__); + aprint_error_dev(xfer->fc->bdev, "xfer == NULL\n"); return; } fw_xfer_unload(xfer); + if (xfer->send.payload != NULL) { + free(xfer->send.payload, xfer->malloc); + } + if (xfer->recv.payload != NULL) { + free(xfer->recv.payload, xfer->malloc); + } + cv_destroy(&xfer->cv); free(xfer, xfer->malloc); } void fw_asy_callback_free(struct fw_xfer *xfer) { + #if 0 - printf("asyreq done flag=%d resp=%d\n", - xfer->flag, xfer->resp); + printf("asyreq done flag=%d resp=%d\n", xfer->flag, xfer->resp); #endif fw_xfer_free(xfer); } /* - * To configure PHY. + * To receive self ID. */ -static void -fw_phy_config(struct firewire_comm *fc, int root_node, int gap_count) -{ - struct fw_xfer *xfer; - struct fw_pkt *fp; - - fc->status = FWBUSPHYCONF; - - xfer = fw_xfer_alloc(M_FWXFER); - if (xfer == NULL) - return; - xfer->fc = fc; - xfer->hand = fw_asy_callback_free; - - fp = &xfer->send.hdr; - fp->mode.ld[1] = 0; - if (root_node >= 0) - fp->mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23; - if (gap_count >= 0) - fp->mode.ld[1] |= 1 << 22 | (gap_count & 0x3f) << 16; - fp->mode.ld[2] = ~fp->mode.ld[1]; -/* XXX Dangerous, how to pass PHY packet to device driver */ - fp->mode.common.tcode |= FWTCODE_PHY; - - if (firewire_debug) - printf("send phy_config root_node=%d gap_count=%d\n", - root_node, gap_count); - fw_asyreq(fc, -1, xfer); -} - -#if 0 -/* - * Dump self ID. - */ -static void -fw_print_sid(uint32_t sid) -{ - union fw_self_id *s; - s = (union fw_self_id *) &sid; - printf("node:%d link:%d gap:%d spd:%d del:%d con:%d pwr:%d" - " p0:%d p1:%d p2:%d i:%d m:%d\n", - s->p0.phy_id, s->p0.link_active, s->p0.gap_count, - s->p0.phy_speed, s->p0.phy_delay, s->p0.contender, - s->p0.power_class, s->p0.port0, s->p0.port1, - s->p0.port2, s->p0.initiated_reset, s->p0.more_packets); -} -#endif - -/* - * To receive self ID. - */ -void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) +void +fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) { uint32_t *p; union fw_self_id *self_id; u_int i, j, node, c_port = 0, i_branch = 0; - fc->sid_cnt = len /(sizeof(uint32_t) * 2); + fc->sid_cnt = len / (sizeof(uint32_t) * 2); fc->max_node = fc->nodeid & 0x3f; CSRARC(fc, NODE_IDS) = ((uint32_t)fc->nodeid) << 16; fc->status = FWBUSCYMELECT; fc->topology_map->crc_len = 2; - fc->topology_map->generation ++; + fc->topology_map->generation++; fc->topology_map->self_id_count = 0; fc->topology_map->node_count = 0; - fc->speed_map->generation ++; + fc->speed_map->generation++; fc->speed_map->crc_len = 1 + (64*64 + 3) / 4; - self_id = &fc->topology_map->self_id[0]; - for(i = 0; i < fc->sid_cnt; i ++){ + self_id = fc->topology_map->self_id; + for (i = 0; i < fc->sid_cnt; i++) { if (sid[1] != ~sid[0]) { - printf("fw_sidrcv: invalid self-id packet\n"); + aprint_error_dev(fc->bdev, + "ERROR invalid self-id packet\n"); sid += 2; continue; } *self_id = *((union fw_self_id *)sid); fc->topology_map->crc_len++; - if(self_id->p0.sequel == 0){ - fc->topology_map->node_count ++; + if (self_id->p0.sequel == 0) { + fc->topology_map->node_count++; c_port = 0; -#if 0 - fw_print_sid(sid[0]); -#endif + if (firewire_debug) + fw_print_sid(sid[0]); node = self_id->p0.phy_id; - if(fc->max_node < node){ + if (fc->max_node < node) fc->max_node = self_id->p0.phy_id; - } /* XXX I'm not sure this is the right speed_map */ - fc->speed_map->speed[node][node] - = self_id->p0.phy_speed; - for (j = 0; j < node; j ++) { - fc->speed_map->speed[j][node] - = fc->speed_map->speed[node][j] - = min(fc->speed_map->speed[j][j], + fc->speed_map->speed[node][node] = + self_id->p0.phy_speed; + for (j = 0; j < node; j++) + fc->speed_map->speed[j][node] = + fc->speed_map->speed[node][j] = + min(fc->speed_map->speed[j][j], self_id->p0.phy_speed); - } if ((fc->irm == -1 || self_id->p0.phy_id > fc->irm) && - (self_id->p0.link_active && self_id->p0.contender)) { + (self_id->p0.link_active && self_id->p0.contender)) fc->irm = self_id->p0.phy_id; - } - if(self_id->p0.port0 >= 0x2){ + if (self_id->p0.port0 >= 0x2) c_port++; - } - if(self_id->p0.port1 >= 0x2){ + if (self_id->p0.port1 >= 0x2) c_port++; - } - if(self_id->p0.port2 >= 0x2){ + if (self_id->p0.port2 >= 0x2) c_port++; - } } - if(c_port > 2){ + if (c_port > 2) i_branch += (c_port - 2); - } sid += 2; self_id++; - fc->topology_map->self_id_count ++; + fc->topology_map->self_id_count++; } - fw_printf(fc->bdev, "%d nodes", fc->max_node + 1); /* CRC */ - fc->topology_map->crc = fw_crc16( - (uint32_t *)&fc->topology_map->generation, - fc->topology_map->crc_len * 4); - fc->speed_map->crc = fw_crc16( - (uint32_t *)&fc->speed_map->generation, - fc->speed_map->crc_len * 4); + fc->topology_map->crc = + fw_crc16((uint32_t *)&fc->topology_map->generation, + fc->topology_map->crc_len * 4); + fc->speed_map->crc = fw_crc16((uint32_t *)&fc->speed_map->generation, + fc->speed_map->crc_len * 4); /* byteswap and copy to CSR */ p = (uint32_t *)fc->topology_map; for (i = 0; i <= fc->topology_map->crc_len; i++) @@ -1475,19 +1020,14 @@ void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) CSRARC(fc, SPED_MAP) = htonl(*p++); CSRARC(fc, SPED_MAP + 4) = htonl(*p++); /* don't byte-swap uint8_t array */ - bcopy(p, &CSRARC(fc, SPED_MAP + 8), (fc->speed_map->crc_len - 1)*4); + memcpy(&CSRARC(fc, SPED_MAP + 8), p, (fc->speed_map->crc_len - 1) * 4); fc->max_hop = fc->max_node - i_branch; - aprint_normal(", maxhop <= %d", fc->max_hop); - - if(fc->irm == -1 ){ - aprint_normal(", Not found IRM capable node"); - }else{ - aprint_normal(", cable IRM = %d", fc->irm); - if (fc->irm == fc->nodeid) - aprint_normal(" (me)"); - } - aprint_normal("\n"); + aprint_normal_dev(fc->bdev, "%d nodes, maxhop <= %d %s irm(%d)%s\n", + fc->max_node + 1, fc->max_hop, + (fc->irm == -1) ? "Not IRM capable" : "cable IRM", + fc->irm, + (fc->irm == fc->nodeid) ? " (me)" : ""); if (try_bmr && (fc->irm != -1) && (CSRARC(fc, BUS_MGR_ID) == 0x3f)) { if (fc->irm == fc->nodeid) { @@ -1496,54 +1036,617 @@ void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) fw_bmr(fc); } else { fc->status = FWBUSMGRELECT; - fw_callout_reset(&fc->bmr_callout, hz/8, - (void *)fw_try_bmr, (void *)fc); + callout_schedule(&fc->bmr_callout, hz/8); } } else fc->status = FWBUSMGRDONE; - fw_callout_reset(&fc->busprobe_callout, hz/4, - (void *)fw_bus_probe, (void *)fc); + callout_schedule(&fc->busprobe_callout, hz/4); } /* - * To probe devices on the IEEE1394 bus. + * Generic packet receiving process. + */ +#if 0 +int dbgflg = 0; +#endif +void +fw_rcv(struct fw_rcv_buf *rb) +{ + struct fw_pkt *fp, *resfp; + struct fw_bind *bind; + int tcode; + int i, len, oldstate; +#if 0 + { + uint32_t *qld; + int i; + qld = (uint32_t *)buf; + printf("spd %d len:%d\n", spd, len); + for (i = 0; i <= len && i < 32; i+= 4) { + printf("0x%08x ", ntohl(qld[i/4])); + if ((i % 16) == 15) printf("\n"); + } + if ((i % 16) != 15) printf("\n"); + } +#endif + fp = (struct fw_pkt *)rb->vec[0].iov_base; + tcode = fp->mode.common.tcode; + switch (tcode) { + case FWTCODE_WRES: + case FWTCODE_RRESQ: + case FWTCODE_RRESB: + case FWTCODE_LRES: + rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src, + fp->mode.hdr.tlrt >> 2, tcode); + if (rb->xfer == NULL) { + aprint_error_dev(rb->fc->bdev, "unknown response" + " %s(%x) src=0x%x tl=0x%x rt=%d data=0x%x\n", + tcode_str[tcode], tcode, + fp->mode.hdr.src, + fp->mode.hdr.tlrt >> 2, + fp->mode.hdr.tlrt & 3, + fp->mode.rresq.data); +#if 0 +dbgflg=8; +#endif +#if 0 + printf("try ad-hoc work around!!\n"); + rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src, + (fp->mode.hdr.tlrt >> 2) ^ 3); + if (rb->xfer == NULL) { + printf("no use...\n"); + return; + } +#else + return; +#endif + } + fw_rcv_copy(rb); + if (rb->xfer->recv.hdr.mode.wres.rtcode != RESP_CMP) + rb->xfer->resp = EIO; + else + rb->xfer->resp = 0; + /* make sure the packet is drained in AT queue */ + oldstate = rb->xfer->flag; + rb->xfer->flag = FWXF_RCVD; + switch (oldstate) { + case FWXF_SENT: + fw_xfer_done(rb->xfer); + break; + case FWXF_START: +#if 0 + if (firewire_debug) + printf("not sent yet tl=%x\n", rb->xfer->tl); +#endif + break; + default: + aprint_error_dev(rb->fc->bdev, + "unexpected flag 0x%02x\n", rb->xfer->flag); + } + return; + case FWTCODE_WREQQ: + case FWTCODE_WREQB: + case FWTCODE_RREQQ: + case FWTCODE_RREQB: + case FWTCODE_LREQ: + bind = fw_bindlookup(rb->fc, fp->mode.rreqq.dest_hi, + fp->mode.rreqq.dest_lo); + if (bind == NULL) { +#if 1 + aprint_error_dev(rb->fc->bdev, "Unknown service addr" + " 0x%04x:0x%08x %s(%x) src=0x%x data=%x\n", + fp->mode.wreqq.dest_hi, fp->mode.wreqq.dest_lo, + tcode_str[tcode], tcode, + fp->mode.hdr.src, ntohl(fp->mode.wreqq.data)); +#endif + if (rb->fc->status == FWBUSINIT) { + aprint_error_dev(rb->fc->bdev, + "cannot respond(bus reset)!\n"); + return; + } + rb->xfer = fw_xfer_alloc(M_FWXFER); + if (rb->xfer == NULL) + return; + rb->xfer->send.spd = rb->spd; + rb->xfer->send.pay_len = 0; + resfp = &rb->xfer->send.hdr; + switch (tcode) { + case FWTCODE_WREQQ: + case FWTCODE_WREQB: + resfp->mode.hdr.tcode = FWTCODE_WRES; + break; + case FWTCODE_RREQQ: + resfp->mode.hdr.tcode = FWTCODE_RRESQ; + break; + case FWTCODE_RREQB: + resfp->mode.hdr.tcode = FWTCODE_RRESB; + break; + case FWTCODE_LREQ: + resfp->mode.hdr.tcode = FWTCODE_LRES; + break; + } + resfp->mode.hdr.dst = fp->mode.hdr.src; + resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt; + resfp->mode.hdr.pri = fp->mode.hdr.pri; + resfp->mode.rresb.rtcode = RESP_ADDRESS_ERROR; + resfp->mode.rresb.extcode = 0; + resfp->mode.rresb.len = 0; +/* + rb->xfer->hand = fw_xferwake; +*/ + rb->xfer->hand = fw_xfer_free; + if (fw_asyreq(rb->fc, -1, rb->xfer)) { + fw_xfer_free(rb->xfer); + return; + } + return; + } + len = 0; + for (i = 0; i < rb->nvec; i++) + len += rb->vec[i].iov_len; + mutex_enter(&bind->fwb_mtx); + rb->xfer = STAILQ_FIRST(&bind->xferlist); + if (rb->xfer == NULL) { + mutex_exit(&bind->fwb_mtx); +#if 1 + aprint_error_dev(rb->fc->bdev, + "Discard a packet for this bind.\n"); +#endif + return; + } + STAILQ_REMOVE_HEAD(&bind->xferlist, link); + mutex_exit(&bind->fwb_mtx); + fw_rcv_copy(rb); + rb->xfer->hand(rb->xfer); + return; + + default: + aprint_error_dev(rb->fc->bdev, "unknow tcode %d\n", tcode); + break; + } +} + +/* + * CRC16 check-sum for IEEE1394 register blocks. + */ +uint16_t +fw_crc16(uint32_t *ptr, uint32_t len) +{ + uint32_t i, sum, crc = 0; + int shift; + + len = (len + 3) & ~3; + for (i = 0; i < len; i+= 4) { + for (shift = 28; shift >= 0; shift -= 4) { + sum = ((crc >> 12) ^ (ptr[i/4] >> shift)) & 0xf; + crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; + } + crc &= 0xffff; + } + return (uint16_t)crc; +} + +int +fw_open_isodma(struct firewire_comm *fc, int tx) +{ + struct fw_xferq **xferqa; + struct fw_xferq *xferq; + int i; + + if (tx) + xferqa = fc->it; + else + xferqa = fc->ir; + + mutex_enter(&fc->fc_mtx); + for (i = 0; i < fc->nisodma; i++) { + xferq = xferqa[i]; + if (!(xferq->flag & FWXFERQ_OPEN)) { + xferq->flag |= FWXFERQ_OPEN; + break; + } + } + if (i == fc->nisodma) { + aprint_error_dev(fc->bdev, "no free dma channel (tx=%d)\n", tx); + i = -1; + } + mutex_exit(&fc->fc_mtx); + return i; +} + +/* + * Async. request with given xfer structure. + */ +static void +fw_asystart(struct fw_xfer *xfer) +{ + struct firewire_comm *fc = xfer->fc; + + /* Protect from interrupt/timeout */ + mutex_enter(&xfer->q->q_mtx); + xfer->flag = FWXF_INQ; + STAILQ_INSERT_TAIL(&xfer->q->q, xfer, link); +#if 0 + xfer->q->queued++; +#endif + mutex_exit(&xfer->q->q_mtx); + /* XXX just queue for mbuf */ + if (xfer->mbuf == NULL) + xfer->q->start(fc); + return; +} + +static void +firewire_xfer_timeout(struct firewire_comm *fc) +{ + struct fw_xfer *xfer; + struct timeval tv; + struct timeval split_timeout; + STAILQ_HEAD(, fw_xfer) xfer_timeout; + int i; + + split_timeout.tv_sec = 0; + split_timeout.tv_usec = 200 * 1000; /* 200 msec */ + + microtime(&tv); + timersub(&tv, &split_timeout, &tv); + STAILQ_INIT(&xfer_timeout); + + mutex_enter(&fc->tlabel_lock); + for (i = 0; i < 0x40; i++) { + while ((xfer = STAILQ_FIRST(&fc->tlabels[i])) != NULL) { + if ((xfer->flag & FWXF_SENT) == 0) + /* not sent yet */ + break; + if (timercmp(&xfer->tv, &tv, >)) + /* the rests are newer than this */ + break; + aprint_error_dev(fc->bdev, + "split transaction timeout: tl=0x%x flag=0x%02x\n", + i, xfer->flag); + fw_dump_hdr(&xfer->send.hdr, "send"); + xfer->resp = ETIMEDOUT; + STAILQ_REMOVE_HEAD(&fc->tlabels[i], tlabel); + STAILQ_INSERT_TAIL(&xfer_timeout, xfer, tlabel); + } + } + mutex_exit(&fc->tlabel_lock); + fc->timeout(fc); + + STAILQ_FOREACH(xfer, &xfer_timeout, tlabel) + xfer->hand(xfer); +} + +#define WATCHDOG_HZ 10 +static void +firewire_watchdog(void *arg) +{ + struct firewire_comm *fc; + static int watchdog_clock = 0; + + fc = (struct firewire_comm *)arg; + + /* + * At boot stage, the device interrupt is disabled and + * We encounter a timeout easily. To avoid this, + * ignore clock interrupt for a while. + */ + if (watchdog_clock > WATCHDOG_HZ * 15) + firewire_xfer_timeout(fc); + else + watchdog_clock++; + + callout_schedule(&fc->timeout_callout, hz / WATCHDOG_HZ); +} + +static void +fw_xferq_drain(struct fw_xferq *xferq) +{ + struct fw_xfer *xfer; + + while ((xfer = STAILQ_FIRST(&xferq->q)) != NULL) { + STAILQ_REMOVE_HEAD(&xferq->q, link); +#if 0 + xferq->queued--; +#endif + xfer->resp = EAGAIN; + xfer->flag = FWXF_SENTERR; + fw_xfer_done(xfer); + } +} + +static void +fw_reset_csr(struct firewire_comm *fc) +{ + int i; + + CSRARC(fc, STATE_CLEAR) = + 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14; + CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); + CSRARC(fc, NODE_IDS) = 0x3f; + + CSRARC(fc, TOPO_MAP + 8) = 0; + fc->irm = -1; + + fc->max_node = -1; + + for (i = 2; i < 0x100/4 - 2; i++) + CSRARC(fc, SPED_MAP + i * 4) = 0; + CSRARC(fc, STATE_CLEAR) = + 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14; + CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); + CSRARC(fc, RESET_START) = 0; + CSRARC(fc, SPLIT_TIMEOUT_HI) = 0; + CSRARC(fc, SPLIT_TIMEOUT_LO) = 800 << 19; + CSRARC(fc, CYCLE_TIME) = 0x0; + CSRARC(fc, BUS_TIME) = 0x0; + CSRARC(fc, BUS_MGR_ID) = 0x3f; + CSRARC(fc, BANDWIDTH_AV) = 4915; + CSRARC(fc, CHANNELS_AV_HI) = 0xffffffff; + CSRARC(fc, CHANNELS_AV_LO) = 0xffffffff; + CSRARC(fc, IP_CHANNELS) = (1 << 31); + + CSRARC(fc, CONF_ROM) = 0x04 << 24; + CSRARC(fc, CONF_ROM + 4) = 0x31333934; /* means strings 1394 */ + CSRARC(fc, CONF_ROM + 8) = + 1 << 31 | 1 << 30 | 1 << 29 | 1 << 28 | 0xff << 16 | 0x09 << 8; + CSRARC(fc, CONF_ROM + 0xc) = 0; + +/* DV depend CSRs see blue book */ + CSRARC(fc, oPCR) &= ~DV_BROADCAST_ON; + CSRARC(fc, iPCR) &= ~DV_BROADCAST_ON; + + CSRARC(fc, STATE_CLEAR) &= ~(1 << 23 | 1 << 15 | 1 << 14); + CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR); +} + +static void +fw_init_crom(struct firewire_comm *fc) +{ + struct crom_src *src; + + src = &fc->crom_src_buf->src; + memset(src, 0, sizeof(struct crom_src)); + + /* BUS info sample */ + src->hdr.info_len = 4; + + src->businfo.bus_name = CSR_BUS_NAME_IEEE1394; + + src->businfo.irmc = 1; + src->businfo.cmc = 1; + src->businfo.isc = 1; + src->businfo.bmc = 1; + src->businfo.pmc = 0; + src->businfo.cyc_clk_acc = 100; + src->businfo.max_rec = fc->maxrec; + src->businfo.max_rom = MAXROM_4; + src->businfo.generation = FW_GENERATION_CHANGEABLE; + src->businfo.link_spd = fc->speed; + + src->businfo.eui64.hi = fc->eui.hi; + src->businfo.eui64.lo = fc->eui.lo; + + STAILQ_INIT(&src->chunk_list); + + fc->crom_src = src; + fc->crom_root = &fc->crom_src_buf->root; +} + +static void +fw_reset_crom(struct firewire_comm *fc) +{ + struct crom_src_buf *buf; + struct crom_src *src; + struct crom_chunk *root; + + buf = fc->crom_src_buf; + src = fc->crom_src; + root = fc->crom_root; + + STAILQ_INIT(&src->chunk_list); + + memset(root, 0, sizeof(struct crom_chunk)); + crom_add_chunk(src, NULL, root, 0); + crom_add_entry(root, CSRKEY_NCAP, 0x0083c0); /* XXX */ + /* private company_id */ + crom_add_entry(root, CSRKEY_VENDOR, CSRVAL_VENDOR_PRIVATE); + crom_add_simple_text(src, root, &buf->vendor, PROJECT_STR); + crom_add_entry(root, CSRKEY_HW, __NetBSD_Version__); + crom_add_simple_text(src, root, &buf->hw, hostname); +} + +/* + * dump packet header + */ +static void +fw_dump_hdr(struct fw_pkt *fp, const char *prefix) +{ + + printf("%s: dst=0x%02x tl=0x%02x rt=%d tcode=0x%x pri=0x%x " + "src=0x%03x\n", prefix, + fp->mode.hdr.dst & 0x3f, + fp->mode.hdr.tlrt >> 2, fp->mode.hdr.tlrt & 3, + fp->mode.hdr.tcode, fp->mode.hdr.pri, + fp->mode.hdr.src); +} + +/* + * To free transaction label. + */ +static void +fw_tl_free(struct firewire_comm *fc, struct fw_xfer *xfer) +{ + struct fw_xfer *txfer; + + if (xfer->tl < 0) + return; + + mutex_enter(&fc->tlabel_lock); +#if 1 /* make sure the label is allocated */ + STAILQ_FOREACH(txfer, &fc->tlabels[xfer->tl], tlabel) + if (txfer == xfer) + break; + if (txfer == NULL) { + mutex_exit(&fc->tlabel_lock); + aprint_error_dev(fc->bdev, + "the xfer is not in the queue (tlabel=%d, flag=0x%x)\n", + xfer->tl, xfer->flag); + fw_dump_hdr(&xfer->send.hdr, "send"); + fw_dump_hdr(&xfer->recv.hdr, "recv"); + cpu_Debugger(); + return; + } +#endif + + STAILQ_REMOVE(&fc->tlabels[xfer->tl], xfer, fw_xfer, tlabel); + mutex_exit(&fc->tlabel_lock); + return; +} + +/* + * To obtain XFER structure by transaction label. + */ +static struct fw_xfer * +fw_tl2xfer(struct firewire_comm *fc, int node, int tlabel, int tcode) +{ + struct fw_xfer *xfer; + int req; + + mutex_enter(&fc->tlabel_lock); + STAILQ_FOREACH(xfer, &fc->tlabels[tlabel], tlabel) + if (xfer->send.hdr.mode.hdr.dst == node) { + mutex_exit(&fc->tlabel_lock); + KASSERT(xfer->tl == tlabel); + /* extra sanity check */ + req = xfer->send.hdr.mode.hdr.tcode; + if (xfer->fc->tcode[req].valid_res != tcode) { + aprint_error_dev(fc->bdev, + "invalid response tcode (0x%x for 0x%x)\n", + tcode, req); + return NULL; + } + + if (firewire_debug > 2) + printf("fw_tl2xfer: found tl=%d\n", tlabel); + return xfer; + } + mutex_exit(&fc->tlabel_lock); + if (firewire_debug > 1) + printf("fw_tl2xfer: not found tl=%d\n", tlabel); + return NULL; +} + +/* + * To configure PHY. + */ +static void +fw_phy_config(struct firewire_comm *fc, int root_node, int gap_count) +{ + struct fw_xfer *xfer; + struct fw_pkt *fp; + + fc->status = FWBUSPHYCONF; + + xfer = fw_xfer_alloc(M_FWXFER); + if (xfer == NULL) + return; + xfer->fc = fc; + xfer->hand = fw_asy_callback_free; + + fp = &xfer->send.hdr; + fp->mode.ld[1] = 0; + if (root_node >= 0) + fp->mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23; + if (gap_count >= 0) + fp->mode.ld[1] |= 1 << 22 | (gap_count & 0x3f) << 16; + fp->mode.ld[2] = ~fp->mode.ld[1]; +/* XXX Dangerous, how to pass PHY packet to device driver */ + fp->mode.common.tcode |= FWTCODE_PHY; + + if (firewire_debug) + printf("root_node=%d gap_count=%d\n", root_node, gap_count); + fw_asyreq(fc, -1, xfer); +} + +/* + * Dump self ID. + */ +static void +fw_print_sid(uint32_t sid) +{ + union fw_self_id *s; + + s = (union fw_self_id *) &sid; + if (s->p0.sequel) { + if (s->p1.sequence_num == FW_SELF_ID_PAGE0) + printf("node:%d p3:%d p4:%d p5:%d p6:%d p7:%d" + "p8:%d p9:%d p10:%d\n", + s->p1.phy_id, s->p1.port3, s->p1.port4, + s->p1.port5, s->p1.port6, s->p1.port7, + s->p1.port8, s->p1.port9, s->p1.port10); + else if (s->p2.sequence_num == FW_SELF_ID_PAGE1) + printf("node:%d p11:%d p12:%d p13:%d p14:%d p15:%d\n", + s->p2.phy_id, s->p2.port11, s->p2.port12, + s->p2.port13, s->p2.port14, s->p2.port15); + else + printf("node:%d Unknown Self ID Page number %d\n", + s->p1.phy_id, s->p1.sequence_num); + } else + printf("node:%d link:%d gap:%d spd:%d con:%d pwr:%d" + " p0:%d p1:%d p2:%d i:%d m:%d\n", + s->p0.phy_id, s->p0.link_active, s->p0.gap_count, + s->p0.phy_speed, s->p0.contender, + s->p0.power_class, s->p0.port0, s->p0.port1, + s->p0.port2, s->p0.initiated_reset, s->p0.more_packets); +} + +/* + * To probe devices on the IEEE1394 bus. */ static void fw_bus_probe(struct firewire_comm *fc) { - int s; struct fw_device *fwdev; - s = splfw(); + mutex_enter(&fc->wait_lock); fc->status = FWBUSEXPLORE; /* Invalidate all devices, just after bus reset. */ + if (firewire_debug) + printf("iterate and invalidate all nodes\n"); + mutex_enter(&fc->fc_mtx); STAILQ_FOREACH(fwdev, &fc->devices, link) if (fwdev->status != FWDEVINVAL) { fwdev->status = FWDEVINVAL; fwdev->rcnt = 0; - } - splx(s); + if (firewire_debug) + printf("Invalidate Dev ID: %08x%08x\n", + fwdev->eui.hi, fwdev->eui.lo); + } else + if (firewire_debug) + printf("Dev ID: %08x%08x already invalid\n", + fwdev->eui.hi, fwdev->eui.lo); + mutex_exit(&fc->fc_mtx); - wakeup((void *)fc); + cv_signal(&fc->fc_cv); + mutex_exit(&fc->wait_lock); } static int -fw_explore_read_quads(struct fw_device *fwdev, int offset, - uint32_t *quad, int n) +fw_explore_read_quads(struct fw_device *fwdev, int offset, uint32_t *quad, + int length) { struct fw_xfer *xfer; uint32_t tmp; int i, error; - - for (i = 0; i < n; i ++, offset += sizeof(uint32_t)) { - xfer = fwmem_read_quad(fwdev, NULL, -1, - 0xffff, 0xf0000000 | offset, (void *)&tmp, - fw_xferwake); + for (i = 0; i < length; i++, offset += sizeof(uint32_t)) { + xfer = fwmem_read_quad(fwdev, NULL, -1, 0xffff, + 0xf0000000 | offset, (void *)&tmp, fw_xferwake); if (xfer == NULL) - return (-1); + return -1; fw_xferwait(xfer); if (xfer->resp == 0) @@ -1552,9 +1655,9 @@ fw_explore_read_quads(struct fw_device *fwdev, int offset, error = xfer->resp; fw_xfer_free(xfer); if (error) - return (error); + return error; } - return (0); + return 0; } @@ -1567,17 +1670,17 @@ fw_explore_csrblock(struct fw_device *fwdev, int offset, int recur) dir = (struct csrdirectory *)&fwdev->csrrom[offset/sizeof(uint32_t)]; - err = fw_explore_read_quads(fwdev, CSRROMOFF + offset, - (uint32_t *)dir, 1); + err = fw_explore_read_quads(fwdev, CSRROMOFF + offset, (uint32_t *)dir, + 1); if (err) - return (-1); + return -1; offset += sizeof(uint32_t); - reg = (struct csrreg *)&fwdev->csrrom[offset/sizeof(uint32_t)]; - err = fw_explore_read_quads(fwdev, CSRROMOFF + offset, - (uint32_t *)reg, dir->crc_len); + reg = (struct csrreg *)&fwdev->csrrom[offset / sizeof(uint32_t)]; + err = fw_explore_read_quads(fwdev, CSRROMOFF + offset, (uint32_t *)reg, + dir->crc_len); if (err) - return (-1); + return -1; /* XXX check CRC */ @@ -1586,9 +1689,9 @@ fw_explore_csrblock(struct fw_device *fwdev, int offset, int recur) fwdev->rommax = off; if (recur == 0) - return (0); + return 0; - for (i = 0; i < dir->crc_len; i ++, offset += sizeof(uint32_t)) { + for (i = 0; i < dir->crc_len; i++, offset += sizeof(uint32_t)) { if ((reg[i].key & CSRTYPE_MASK) == CSRTYPE_D) recur = 1; else if ((reg[i].key & CSRTYPE_MASK) == CSRTYPE_L) @@ -1598,14 +1701,15 @@ fw_explore_csrblock(struct fw_device *fwdev, int offset, int recur) off = offset + reg[i].val * sizeof(uint32_t); if (off > CROMSIZE) { - printf("%s: invalid offset %d\n", __func__, off); - return(-1); + aprint_error_dev(fwdev->fc->bdev, "invalid offset %d\n", + off); + return -1; } err = fw_explore_csrblock(fwdev, off, recur); if (err) - return (-1); + return -1; } - return (0); + return 0; } static int @@ -1613,60 +1717,126 @@ fw_explore_node(struct fw_device *dfwdev) { struct firewire_comm *fc; struct fw_device *fwdev, *pfwdev, *tfwdev; - uint32_t *csr; struct csrhdr *hdr; struct bus_info *binfo; - int err, node, spd; + uint32_t *csr, speed_test = 0; + int err, node; fc = dfwdev->fc; csr = dfwdev->csrrom; node = dfwdev->dst; /* First quad */ - err = fw_explore_read_quads(dfwdev, CSRROMOFF, &csr[0], 1); - if (err) - return (-1); - hdr = (struct csrhdr *)&csr[0]; +#if 0 +printf("%s: speed=0x%x(0x%x)\n", __func__, dfwdev->speed, fc->speed_map->speed[fc->nodeid][node]); +if (dfwdev->speed == 0) + dfwdev->speed = fc->speed_map->speed[fc->nodeid][node]; +else if (dfwdev->speed == 2) + dfwdev->speed = 1; +else + dfwdev->speed = 0; +printf("%s: Re: speed=0x%x\n", __func__, dfwdev->speed); +#endif + err = fw_explore_read_quads(dfwdev, CSRROMOFF, csr, 1); + if (err) { + aprint_error_dev(fc->bdev, + "node%d: explore_read_quads failure\n", node); +printf("err=%d\n", err); + dfwdev->status = FWDEVINVAL; + return -1; + } + hdr = (struct csrhdr *)csr; if (hdr->info_len != 4) { if (firewire_debug) printf("node%d: wrong bus info len(%d)\n", node, hdr->info_len); - return (-1); + dfwdev->status = FWDEVINVAL; + return -1; } /* bus info */ err = fw_explore_read_quads(dfwdev, CSRROMOFF + 0x04, &csr[1], 4); - if (err) - return (-1); + if (err) { + aprint_error_dev(fc->bdev, "node%d: error reading 0x04\n", + node); + dfwdev->status = FWDEVINVAL; + return -1; + } binfo = (struct bus_info *)&csr[1]; if (binfo->bus_name != CSR_BUS_NAME_IEEE1394) { - if (firewire_debug) - printf("node%d: invalid bus name 0x%08x\n", - node, binfo->bus_name); - return (-1); + aprint_error_dev(fc->bdev, "node%d: invalid bus name 0x%08x\n", + node, binfo->bus_name); + dfwdev->status = FWDEVINVAL; + return -1; } - spd = fc->speed_map->speed[fc->nodeid][node]; + if (firewire_debug) + printf("node(%d) BUS INFO BLOCK:\n" + "irmc(%d) cmc(%d) isc(%d) bmc(%d) pmc(%d) " + "cyc_clk_acc(%d) max_rec(%d) max_rom(%d) " + "generation(%d) link_spd(%d)\n", + node, binfo->irmc, binfo->cmc, binfo->isc, + binfo->bmc, binfo->pmc, binfo->cyc_clk_acc, + binfo->max_rec, binfo->max_rom, + binfo->generation, binfo->link_spd); + + mutex_enter(&fc->fc_mtx); STAILQ_FOREACH(fwdev, &fc->devices, link) if (FW_EUI64_EQUAL(fwdev->eui, binfo->eui64)) break; + mutex_exit(&fc->fc_mtx); if (fwdev == NULL) { /* new device */ - fwdev = malloc(sizeof(struct fw_device), M_FW, - M_NOWAIT | M_ZERO); + fwdev = + malloc(sizeof(struct fw_device), M_FW, M_NOWAIT | M_ZERO); if (fwdev == NULL) { if (firewire_debug) printf("node%d: no memory\n", node); - return (-1); + return -1; } fwdev->fc = fc; fwdev->eui = binfo->eui64; + fwdev->dst = dfwdev->dst; + fwdev->maxrec = dfwdev->maxrec; fwdev->status = FWDEVNEW; - /* insert into sorted fwdev list */ + /* + * Pre-1394a-2000 didn't have link_spd in + * the Bus Info block, so try and use the + * speed map value. + * 1394a-2000 compliant devices only use + * the Bus Info Block link spd value, so + * ignore the speed map alltogether. SWB + */ + if (binfo->link_spd == FWSPD_S100 /* 0 */) { + aprint_normal_dev(fc->bdev, + "Pre 1394a-2000 detected\n"); + fwdev->speed = fc->speed_map->speed[fc->nodeid][node]; + } else + fwdev->speed = binfo->link_spd; + /* + * Test this speed with a read to the CSRROM. + * If it fails, slow down the speed and retry. + */ + while (fwdev->speed > FWSPD_S100 /* 0 */) { + err = fw_explore_read_quads(fwdev, CSRROMOFF, + &speed_test, 1); + if (err) { + aprint_error_dev(fc->bdev, "fwdev->speed(%s)" + " decremented due to negotiation\n", + fw_linkspeed[fwdev->speed]); + fwdev->speed--; + } else + break; + } + /* + * If the fwdev is not found in the + * fc->devices TAILQ, then we will add it. + */ pfwdev = NULL; + mutex_enter(&fc->fc_mtx); STAILQ_FOREACH(tfwdev, &fc->devices, link) { if (tfwdev->eui.hi > fwdev->eui.hi || - (tfwdev->eui.hi == fwdev->eui.hi && - tfwdev->eui.lo > fwdev->eui.lo)) + (tfwdev->eui.hi == fwdev->eui.hi && + tfwdev->eui.lo > fwdev->eui.lo)) break; pfwdev = tfwdev; } @@ -1674,37 +1844,36 @@ fw_explore_node(struct fw_device *dfwdev) STAILQ_INSERT_HEAD(&fc->devices, fwdev, link); else STAILQ_INSERT_AFTER(&fc->devices, pfwdev, fwdev, link); + mutex_exit(&fc->fc_mtx); - fw_printf(fc->bdev, "New %s device ID:%08x%08x\n", - fw_linkspeed[spd], - fwdev->eui.hi, fwdev->eui.lo); - - } else + aprint_normal_dev(fc->bdev, "New %s device ID:%08x%08x\n", + fw_linkspeed[fwdev->speed], fwdev->eui.hi, fwdev->eui.lo); + } else { + fwdev->dst = node; fwdev->status = FWDEVINIT; - fwdev->dst = node; - fwdev->speed = spd; - - /* unchanged ? */ - if (memcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) { - if (firewire_debug) - printf("node%d: crom unchanged\n", node); - return (0); + /* unchanged ? */ + if (memcmp(csr, fwdev->csrrom, sizeof(uint32_t) * 5) == 0) { + if (firewire_debug) + printf("node%d: crom unchanged\n", node); + return 0; + } } - memset(&fwdev->csrrom[0], 0, CROMSIZE); + memset(fwdev->csrrom, 0, CROMSIZE); /* copy first quad and bus info block */ - bcopy(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5); + memcpy(fwdev->csrrom, csr, sizeof(uint32_t) * 5); fwdev->rommax = CSRROMOFF + sizeof(uint32_t) * 4; err = fw_explore_csrblock(fwdev, 0x14, 1); /* root directory */ if (err) { + if (firewire_debug) + printf("explore csrblock failed err(%d)\n", err); fwdev->status = FWDEVINVAL; fwdev->csrrom[0] = 0; } - return (err); - + return err; } /* @@ -1715,7 +1884,7 @@ fw_find_self_id(struct firewire_comm *fc, int node) { uint32_t i; union fw_self_id *s; - + for (i = 0; i < fc->topology_map->self_id_count; i++) { s = &fc->topology_map->self_id[i]; if (s->p0.sequel) @@ -1729,10 +1898,10 @@ fw_find_self_id(struct firewire_comm *fc, int node) static void fw_explore(struct firewire_comm *fc) { - int node, err, s, i, todo, todo2, trys; - char nodes[63]; struct fw_device *dfwdev; union fw_self_id *fwsid; + int node, err, i, todo, todo2, trys; + char nodes[63]; todo = 0; dfwdev = malloc(sizeof(*dfwdev), M_TEMP, M_NOWAIT); @@ -1744,10 +1913,17 @@ fw_explore(struct firewire_comm *fc) dfwdev->maxrec = 8; /* 512 */ dfwdev->status = FWDEVINIT; - for (node = 0; node <= fc->max_node; node ++) { + for (node = 0; node <= fc->max_node; node++) { /* We don't probe myself and linkdown nodes */ - if (node == fc->nodeid) + if (node == fc->nodeid) { + if (firewire_debug) + printf("found myself node(%d) fc->nodeid(%d)" + " fc->max_node(%d)\n", + node, fc->nodeid, fc->max_node); continue; + } else if (firewire_debug) + printf("node(%d) fc->max_node(%d) found\n", + node, fc->max_node); fwsid = fw_find_self_id(fc, node); if (!fwsid || !fwsid->p0.link_active) { if (firewire_debug) @@ -1757,48 +1933,47 @@ fw_explore(struct firewire_comm *fc) nodes[todo++] = node; } - s = splfw(); - for (trys = 0; todo > 0 && trys < 3; trys ++) { + for (trys = 0; todo > 0 && trys < 3; trys++) { todo2 = 0; - for (i = 0; i < todo; i ++) { + for (i = 0; i < todo; i++) { dfwdev->dst = nodes[i]; err = fw_explore_node(dfwdev); if (err) nodes[todo2++] = nodes[i]; if (firewire_debug) - printf("%s: node %d, err = %d\n", - __func__, node, err); + printf("node %d, err = %d\n", nodes[i], err); } todo = todo2; } - splx(s); free(dfwdev, M_TEMP); } static void fw_bus_probe_thread(void *arg) { - struct firewire_comm *fc; - - fc = (struct firewire_comm *)arg; + struct firewire_comm *fc = (struct firewire_comm *)arg; - fw_config_pending_decr(); + config_pending_decr(); - fw_mtx_lock(&fc->wait_lock); + mutex_enter(&fc->wait_lock); while (fc->status != FWBUSDETACH) { if (fc->status == FWBUSEXPLORE) { - fw_mtx_unlock(&fc->wait_lock); + mutex_exit(&fc->wait_lock); fw_explore(fc); fc->status = FWBUSEXPDONE; if (firewire_debug) printf("bus_explore done\n"); fw_attach_dev(fc); - fw_mtx_lock(&fc->wait_lock); + mutex_enter(&fc->wait_lock); } - fw_msleep((void *)fc, &fc->wait_lock, PWAIT|PCATCH, "-", 0); + cv_wait_sig(&fc->fc_cv, &fc->wait_lock); } - fw_mtx_unlock(&fc->wait_lock); - fw_kthread_exit(0); + fc->status = FWBUSDETACHOK; + cv_signal(&fc->fc_cv); + mutex_exit(&fc->wait_lock); + kthread_exit(0); + + /* NOTREACHED */ } @@ -1808,18 +1983,56 @@ fw_bus_probe_thread(void *arg) static void fw_attach_dev(struct firewire_comm *fc) { + struct firewire_softc *sc = device_private(fc->bdev); + struct firewire_dev_list *devlist, *elm; struct fw_device *fwdev, *next; struct firewire_dev_comm *fdc; struct fw_attach_args fwa; + int locs[IEEE1394IFCF_NLOCS]; fwa.name = "sbp"; fwa.fc = fc; + mutex_enter(&fc->fc_mtx); for (fwdev = STAILQ_FIRST(&fc->devices); fwdev != NULL; fwdev = next) { next = STAILQ_NEXT(fwdev, link); + mutex_exit(&fc->fc_mtx); switch (fwdev->status) { case FWDEVNEW: - FIREWIRE_SBP_ATTACH; + devlist = malloc(sizeof(struct firewire_dev_list), + M_DEVBUF, M_NOWAIT); + if (devlist == NULL) { + aprint_error_dev(fc->bdev, + "memory allocation failed\n"); + break; + } + + locs[IEEE1394IFCF_EUIHI] = fwdev->eui.hi; + locs[IEEE1394IFCF_EUILO] = fwdev->eui.lo; + + fwa.fwdev = fwdev; + fwdev->sbp = config_found_sm_loc(sc->dev, "ieee1394if", + locs, &fwa, firewire_print, config_stdsubmatch); + if (fwdev->sbp == NULL) { + free(devlist, M_DEVBUF); + break; + } + + devlist->fwdev = fwdev; + devlist->dev = fwdev->sbp; + + mutex_enter(&fc->fc_mtx); + if (SLIST_EMPTY(&sc->devlist)) + SLIST_INSERT_HEAD(&sc->devlist, devlist, link); + else { + for (elm = SLIST_FIRST(&sc->devlist); + SLIST_NEXT(elm, link) != NULL; + elm = SLIST_NEXT(elm, link)); + SLIST_INSERT_AFTER(elm, devlist, link); + } + mutex_exit(&fc->fc_mtx); + + /* FALLTHROUGH */ case FWDEVINIT: case FWDEVATTACHED: @@ -1827,16 +2040,25 @@ fw_attach_dev(struct firewire_comm *fc) break; case FWDEVINVAL: - fwdev->rcnt ++; + fwdev->rcnt++; + if (firewire_debug) + printf("fwdev->rcnt(%d), hold_count(%d)\n", + fwdev->rcnt, hold_count); break; default: /* XXX */ break; } + mutex_enter(&fc->fc_mtx); } + mutex_exit(&fc->fc_mtx); - FIREWIRE_CHILDREN_FOREACH_FUNC(post_explore, fdc); + SLIST_FOREACH(devlist, &sc->devlist, link) { + fdc = device_private(devlist->dev); + if (fdc->post_explore != NULL) + fdc->post_explore(fdc); + } for (fwdev = STAILQ_FIRST(&fc->devices); fwdev != NULL; fwdev = next) { next = STAILQ_NEXT(fwdev, link); @@ -1845,7 +2067,19 @@ fw_attach_dev(struct firewire_comm *fc) * Remove devices which have not been seen * for a while. */ - FIREWIRE_SBP_DETACH; + SLIST_FOREACH(devlist, &sc->devlist, link) + if (devlist->fwdev == fwdev) + break; + if (devlist->fwdev != fwdev) + panic("already detached"); + + SLIST_REMOVE(&sc->devlist, devlist, firewire_dev_list, + link); + free(devlist, M_DEVBUF); + + if (config_detach(fwdev->sbp, DETACH_FORCE) != 0) + return; + STAILQ_REMOVE(&fc->devices, fwdev, fw_device, link); free(fwdev, M_FW); } @@ -1862,32 +2096,29 @@ fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer) { u_int dst, new_tlabel; struct fw_xfer *txfer; - int s; dst = xfer->send.hdr.mode.hdr.dst & 0x3f; - s = splfw(); - fw_mtx_lock(&fc->tlabel_lock); + mutex_enter(&fc->tlabel_lock); new_tlabel = (fc->last_tlabel[dst] + 1) & 0x3f; STAILQ_FOREACH(txfer, &fc->tlabels[new_tlabel], tlabel) if ((txfer->send.hdr.mode.hdr.dst & 0x3f) == dst) break; - if(txfer == NULL) { + if (txfer == NULL) { fc->last_tlabel[dst] = new_tlabel; STAILQ_INSERT_TAIL(&fc->tlabels[new_tlabel], xfer, tlabel); - fw_mtx_unlock(&fc->tlabel_lock); - splx(s); + mutex_exit(&fc->tlabel_lock); xfer->tl = new_tlabel; xfer->send.hdr.mode.hdr.tlrt = new_tlabel << 2; if (firewire_debug > 1) - printf("fw_get_tlabel: dst=%d tl=%d\n", dst, new_tlabel); - return (new_tlabel); + printf("fw_get_tlabel: dst=%d tl=%d\n", + dst, new_tlabel); + return new_tlabel; } - fw_mtx_unlock(&fc->tlabel_lock); - splx(s); + mutex_exit(&fc->tlabel_lock); if (firewire_debug > 1) printf("fw_get_tlabel: no free tlabel\n"); - return (-1); + return -1; } static void @@ -1903,9 +2134,9 @@ fw_rcv_copy(struct fw_rcv_buf *rb) pkt = (struct fw_pkt *)rb->vec->iov_base; tinfo = &rb->fc->tcode[pkt->mode.hdr.tcode]; - /* Copy header */ + /* Copy header */ p = (u_char *)&rb->xfer->recv.hdr; - bcopy(rb->vec->iov_base, p, tinfo->hdr_len); + memcpy(p, rb->vec->iov_base, tinfo->hdr_len); rb->vec->iov_base = (u_char *)rb->vec->iov_base + tinfo->hdr_len; rb->vec->iov_len -= tinfo->hdr_len; @@ -1929,12 +2160,13 @@ fw_rcv_copy(struct fw_rcv_buf *rb) for (i = 0; i < rb->nvec; i++, rb->vec++) { len = MIN(rb->vec->iov_len, plen); if (res < len) { - printf("rcv buffer(%d) is %d bytes short.\n", + aprint_error_dev(rb->fc->bdev, + "rcv buffer(%d) is %d bytes short.\n", rb->xfer->recv.pay_len, len - res); len = res; } if (p) { - bcopy(rb->vec->iov_base, p, len); + memcpy(p, rb->vec->iov_base, len); p += len; } res -= len; @@ -1947,206 +2179,6 @@ fw_rcv_copy(struct fw_rcv_buf *rb) } /* - * Generic packet receiving process. - */ -void -fw_rcv(struct fw_rcv_buf *rb) -{ - struct fw_pkt *fp, *resfp; - struct fw_bind *bind; - int tcode; - int i, len, oldstate; -#if 0 - { - uint32_t *qld; - int i; - qld = (uint32_t *)buf; - printf("spd %d len:%d\n", spd, len); - for( i = 0 ; i <= len && i < 32; i+= 4){ - printf("0x%08x ", ntohl(qld[i/4])); - if((i % 16) == 15) printf("\n"); - } - if((i % 16) != 15) printf("\n"); - } -#endif - fp = (struct fw_pkt *)rb->vec[0].iov_base; - tcode = fp->mode.common.tcode; - switch (tcode) { - case FWTCODE_WRES: - case FWTCODE_RRESQ: - case FWTCODE_RRESB: - case FWTCODE_LRES: - rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src, - fp->mode.hdr.tlrt >> 2, fp->mode.hdr.tcode); - if(rb->xfer == NULL) { - printf("fw_rcv: unknown response " - "%s(%x) src=0x%x tl=0x%x rt=%d data=0x%x\n", - tcode_str[tcode], tcode, - fp->mode.hdr.src, - fp->mode.hdr.tlrt >> 2, - fp->mode.hdr.tlrt & 3, - fp->mode.rresq.data); -#if 0 - printf("try ad-hoc work around!!\n"); - rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src, - (fp->mode.hdr.tlrt >> 2)^3); - if (rb->xfer == NULL) { - printf("no use...\n"); - return; - } -#else - return; -#endif - } - fw_rcv_copy(rb); - if (rb->xfer->recv.hdr.mode.wres.rtcode != RESP_CMP) - rb->xfer->resp = EIO; - else - rb->xfer->resp = 0; - /* make sure the packet is drained in AT queue */ - oldstate = rb->xfer->flag; - rb->xfer->flag = FWXF_RCVD; - switch (oldstate) { - case FWXF_SENT: - fw_xfer_done(rb->xfer); - break; - case FWXF_START: -#if 0 - if (firewire_debug) - printf("not sent yet tl=%x\n", rb->xfer->tl); -#endif - break; - default: - printf("unexpected flag 0x%02x\n", rb->xfer->flag); - } - return; - case FWTCODE_WREQQ: - case FWTCODE_WREQB: - case FWTCODE_RREQQ: - case FWTCODE_RREQB: - case FWTCODE_LREQ: - bind = fw_bindlookup(rb->fc, fp->mode.rreqq.dest_hi, - fp->mode.rreqq.dest_lo); - if(bind == NULL){ -#if 1 - printf("Unknown service addr 0x%04x:0x%08x %s(%x)" -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - " src=0x%x data=%lx\n", -#else - " src=0x%x data=%x\n", -#endif - fp->mode.wreqq.dest_hi, fp->mode.wreqq.dest_lo, - tcode_str[tcode], tcode, - fp->mode.hdr.src, ntohl(fp->mode.wreqq.data)); -#endif - if (rb->fc->status == FWBUSINIT) { - printf("fw_rcv: cannot respond(bus reset)!\n"); - return; - } - rb->xfer = fw_xfer_alloc(M_FWXFER); - if(rb->xfer == NULL){ - return; - } - rb->xfer->send.spd = rb->spd; - rb->xfer->send.pay_len = 0; - resfp = &rb->xfer->send.hdr; - switch (tcode) { - case FWTCODE_WREQQ: - case FWTCODE_WREQB: - resfp->mode.hdr.tcode = FWTCODE_WRES; - break; - case FWTCODE_RREQQ: - resfp->mode.hdr.tcode = FWTCODE_RRESQ; - break; - case FWTCODE_RREQB: - resfp->mode.hdr.tcode = FWTCODE_RRESB; - break; - case FWTCODE_LREQ: - resfp->mode.hdr.tcode = FWTCODE_LRES; - break; - } - resfp->mode.hdr.dst = fp->mode.hdr.src; - resfp->mode.hdr.tlrt = fp->mode.hdr.tlrt; - resfp->mode.hdr.pri = fp->mode.hdr.pri; - resfp->mode.rresb.rtcode = RESP_ADDRESS_ERROR; - resfp->mode.rresb.extcode = 0; - resfp->mode.rresb.len = 0; -/* - rb->xfer->hand = fw_xferwake; -*/ - rb->xfer->hand = fw_xfer_free; - if(fw_asyreq(rb->fc, -1, rb->xfer)){ - fw_xfer_free(rb->xfer); - return; - } - return; - } - len = 0; - for (i = 0; i < rb->nvec; i ++) - len += rb->vec[i].iov_len; - rb->xfer = STAILQ_FIRST(&bind->xferlist); - if (rb->xfer == NULL) { -#if 1 - printf("Discard a packet for this bind.\n"); -#endif - return; - } - STAILQ_REMOVE_HEAD(&bind->xferlist, link); - fw_rcv_copy(rb); - rb->xfer->hand(rb->xfer); - return; -#if 0 /* shouldn't happen ?? or for GASP */ - case FWTCODE_STREAM: - { - struct fw_xferq *xferq; - - xferq = rb->fc->ir[sub]; -#if 0 - printf("stream rcv dma %d len %d off %d spd %d\n", - sub, len, off, spd); -#endif - if(xferq->queued >= xferq->maxq) { - printf("receive queue is full\n"); - return; - } - /* XXX get xfer from xfer queue, we don't need copy for - per packet mode */ - rb->xfer = fw_xfer_alloc_buf(M_FWXFER, 0, /* XXX */ - vec[0].iov_len); - if (rb->xfer == NULL) - return; - fw_rcv_copy(rb) - s = splfw(); - xferq->queued++; - STAILQ_INSERT_TAIL(&xferq->q, rb->xfer, link); - splx(s); - sc = device_get_softc(rb->fc->bdev); -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - if (&xferq->rsel.si_pid != 0) -#else - if (SEL_WAITING(&xferq->rsel)) -#endif - selwakeuppri(&xferq->rsel, FWPRI); - if (xferq->flag & FWXFERQ_WAKEUP) { - xferq->flag &= ~FWXFERQ_WAKEUP; - wakeup((void *)xferq); - } - if (xferq->flag & FWXFERQ_HANDLER) { - xferq->hand(xferq); - } - return; - break; - } -#endif - default: - printf("fw_rcv: unknow tcode %d\n", tcode); - break; - } -} - -/* * Post process for Bus Manager election process. */ static void @@ -2175,7 +2207,7 @@ fw_try_bmr_callback(struct fw_xfer *xfer) return; error: - fw_printf(fc->bdev, "bus manager election failed\n"); + aprint_error_dev(fc->bdev, "bus manager election failed\n"); fw_xfer_free_buf(xfer); } @@ -2192,9 +2224,8 @@ fw_try_bmr(void *arg) int err = 0; xfer = fw_xfer_alloc_buf(M_FWXFER, 8, 4); - if(xfer == NULL){ + if (xfer == NULL) return; - } xfer->send.spd = 0; fc->status = FWBUSMGRELECT; @@ -2213,107 +2244,19 @@ fw_try_bmr(void *arg) xfer->hand = fw_try_bmr_callback; err = fw_asyreq(fc, -1, xfer); - if(err){ + if (err) { fw_xfer_free_buf(xfer); return; } return; } -#ifdef FW_VMACCESS /* - * Software implementation for physical memory block access. - * XXX:Too slow, usef for debug purpose only. + * Find the root node, if it is not + * Cycle Master Capable, then we should + * override this and become the Cycle + * Master */ -static void -fw_vmaccess(struct fw_xfer *xfer){ - struct fw_pkt *rfp, *sfp = NULL; - uint32_t *ld = (uint32_t *)xfer->recv.buf; - - printf("vmaccess spd:%2x len:%03x data:%08x %08x %08x %08x\n", - xfer->spd, xfer->recv.len, ntohl(ld[0]), ntohl(ld[1]), ntohl(ld[2]), ntohl(ld[3])); - printf("vmaccess data:%08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7])); - if(xfer->resp != 0){ - fw_xfer_free( xfer); - return; - } - if(xfer->recv.buf == NULL){ - fw_xfer_free( xfer); - return; - } - rfp = (struct fw_pkt *)xfer->recv.buf; - switch(rfp->mode.hdr.tcode){ - /* XXX need fix for 64bit arch */ - case FWTCODE_WREQB: - xfer->send.buf = malloc(12, M_FW, M_NOWAIT); - xfer->send.len = 12; - sfp = (struct fw_pkt *)xfer->send.buf; - bcopy(rfp->mode.wreqb.payload, - (void *)ntohl(rfp->mode.wreqb.dest_lo), ntohs(rfp->mode.wreqb.len)); - sfp->mode.wres.tcode = FWTCODE_WRES; - sfp->mode.wres.rtcode = 0; - break; - case FWTCODE_WREQQ: - xfer->send.buf = malloc(12, M_FW, M_NOWAIT); - xfer->send.len = 12; - sfp->mode.wres.tcode = FWTCODE_WRES; - *((uint32_t *)(ntohl(rfp->mode.wreqb.dest_lo))) = rfp->mode.wreqq.data; - sfp->mode.wres.rtcode = 0; - break; - case FWTCODE_RREQB: - xfer->send.buf = malloc(16 + rfp->mode.rreqb.len, M_FW, M_NOWAIT); - xfer->send.len = 16 + ntohs(rfp->mode.rreqb.len); - sfp = (struct fw_pkt *)xfer->send.buf; - bcopy((void *)ntohl(rfp->mode.rreqb.dest_lo), - sfp->mode.rresb.payload, (uint16_t)ntohs(rfp->mode.rreqb.len)); - sfp->mode.rresb.tcode = FWTCODE_RRESB; - sfp->mode.rresb.len = rfp->mode.rreqb.len; - sfp->mode.rresb.rtcode = 0; - sfp->mode.rresb.extcode = 0; - break; - case FWTCODE_RREQQ: - xfer->send.buf = malloc(16, M_FW, M_NOWAIT); - xfer->send.len = 16; - sfp = (struct fw_pkt *)xfer->send.buf; - sfp->mode.rresq.data = *(uint32_t *)(ntohl(rfp->mode.rreqq.dest_lo)); - sfp->mode.wres.tcode = FWTCODE_RRESQ; - sfp->mode.rresb.rtcode = 0; - break; - default: - fw_xfer_free( xfer); - return; - } - sfp->mode.hdr.dst = rfp->mode.hdr.src; - xfer->dst = ntohs(rfp->mode.hdr.src); - xfer->hand = fw_xfer_free; - - sfp->mode.hdr.tlrt = rfp->mode.hdr.tlrt; - sfp->mode.hdr.pri = 0; - - fw_asyreq(xfer->fc, -1, xfer); -/**/ - return; -} -#endif - -/* - * CRC16 check-sum for IEEE1394 register blocks. - */ -uint16_t -fw_crc16(uint32_t *ptr, uint32_t len){ - uint32_t i, sum, crc = 0; - int shift; - len = (len + 3) & ~3; - for(i = 0 ; i < len ; i+= 4){ - for( shift = 28 ; shift >= 0 ; shift -= 4){ - sum = ((crc >> 12) ^ (ptr[i/4] >> shift)) & 0xf; - crc = (crc << 4) ^ ( sum << 12 ) ^ ( sum << 5) ^ sum; - } - crc &= 0xffff; - } - return((uint16_t) crc); -} - static int fw_bmr(struct firewire_comm *fc) { @@ -2329,7 +2272,7 @@ fw_bmr(struct firewire_comm *fc) if (self_id->p0.link_active && self_id->p0.contender) cmstr = fc->max_node; else { - fw_printf(fc->bdev, + aprint_normal_dev(fc->bdev, "root node is not cycle master capable\n"); /* XXX shall we be the cycle master? */ cmstr = fc->nodeid; @@ -2338,16 +2281,15 @@ fw_bmr(struct firewire_comm *fc) } else cmstr = -1; - fw_printf(fc->bdev, "bus manager %d ", CSRARC(fc, BUS_MGR_ID)); - if(CSRARC(fc, BUS_MGR_ID) != fc->nodeid) { + aprint_normal_dev(fc->bdev, "bus manager %d%s\n", + CSRARC(fc, BUS_MGR_ID), + (CSRARC(fc, BUS_MGR_ID) != fc->nodeid) ? " (me)" : ""); + if (CSRARC(fc, BUS_MGR_ID) != fc->nodeid) /* We are not the bus manager */ - aprint_normal("\n"); - return(0); - } - aprint_normal("(me)\n"); + return 0; /* Optimize gapcount */ - if(fc->max_hop <= MAX_GAPHOP ) + if (fc->max_hop <= MAX_GAPHOP) fw_phy_config(fc, cmstr, gap_cnt[fc->max_hop]); /* If we are the cycle master, nothing to do */ if (cmstr == fc->nodeid || cmstr == -1) @@ -2361,74 +2303,8 @@ fw_bmr(struct firewire_comm *fc) fwdev.status = FWDEVINIT; /* Set cmstr bit on the cycle master */ quad = htonl(1 << 8); - fwmem_write_quad(&fwdev, NULL, 0/*spd*/, - 0xffff, 0xf0000000 | STATE_SET, &quad, fw_asy_callback_free); + fwmem_write_quad(&fwdev, NULL, 0/*spd*/, 0xffff, 0xf0000000 | STATE_SET, + &quad, fw_asy_callback_free); return 0; } - -int -fw_open_isodma(struct firewire_comm *fc, int tx) -{ - struct fw_xferq **xferqa; - struct fw_xferq *xferq; - int i; - - if (tx) - xferqa = &fc->it[0]; - else - xferqa = &fc->ir[0]; - - FW_GLOCK(fc); - for (i = 0; i < fc->nisodma; i ++) { - xferq = xferqa[i]; - if ((xferq->flag & FWXFERQ_OPEN) == 0) { - xferq->flag |= FWXFERQ_OPEN; - break; - } - } - if (i == fc->nisodma) { - printf("no free dma channel (tx=%d)\n", tx); - i = -1; - } - FW_GUNLOCK(fc); - return (i); -} - -#if defined(__FreeBSD__) -static int -fw_modevent(module_t mode, int type, void *data) -{ - int err = 0; -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - static eventhandler_tag fwdev_ehtag = NULL; -#endif - - switch (type) { - case MOD_LOAD: -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - fwdev_ehtag = EVENTHANDLER_REGISTER(dev_clone, - fwdev_clone, 0, 1000); -#endif - break; - case MOD_UNLOAD: -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - if (fwdev_ehtag != NULL) - EVENTHANDLER_DEREGISTER(dev_clone, fwdev_ehtag); -#endif - break; - case MOD_SHUTDOWN: - break; - default: - return (EOPNOTSUPP); - } - return (err); -} - - -#ifdef __DragonFly__ -DECLARE_DUMMY_MODULE(firewire); -#endif -DRIVER_MODULE(firewire,fwohci,firewire_driver,firewire_devclass,fw_modevent,0); -MODULE_VERSION(firewire, 1); -#endif diff --git a/sys/dev/ieee1394/firewire.h b/sys/dev/ieee1394/firewire.h index f59c55b6528..dc0c835b755 100644 --- a/sys/dev/ieee1394/firewire.h +++ b/sys/dev/ieee1394/firewire.h @@ -1,4 +1,4 @@ -/* $NetBSD: firewire.h,v 1.4 2007/11/05 19:08:56 kiyohara Exp $ */ +/* $NetBSD: firewire.h,v 1.5 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -31,13 +31,13 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/firewire/firewire.h,v 1.21 2007/04/24 12:15:05 simokawa Exp $ + * + * $FreeBSD: src/sys/dev/firewire/firewire.h,v 1.25 2009/02/17 19:37:04 sbruno Exp $ * */ -#ifndef _FIREWIRE_H -#define _FIREWIRE_H 1 +#ifndef _FIREWIRE_H_ +#define _FIREWIRE_H_ #define DEV_DEF 0 #define DEV_DV 2 @@ -100,9 +100,16 @@ struct fw_reg_req_t { #define FWRCODE_ER_TYPE 6 #define FWRCODE_ER_ADDR 7 +/* + * Defined 1394a-2000 + * Table 5B-1 + */ #define FWSPD_S100 0 #define FWSPD_S200 1 #define FWSPD_S400 2 +#define FWSPD_S800 3 +#define FWSPD_S1600 4 +#define FWSPD_S3200 5 #define FWP_TL_VALID (1 << 7) @@ -278,10 +285,18 @@ struct fw_devlstreq { struct fw_devinfo dev[FW_MAX_DEVLST]; }; +/* + * Defined in IEEE 1394a-2000 + * 4.3.4.1 + */ #define FW_SELF_ID_PORT_CONNECTED_TO_CHILD 3 #define FW_SELF_ID_PORT_CONNECTED_TO_PARENT 2 #define FW_SELF_ID_PORT_NOT_CONNECTED 1 #define FW_SELF_ID_PORT_NOT_EXISTS 0 + +#define FW_SELF_ID_PAGE0 0 +#define FW_SELF_ID_PAGE1 1 + #if BYTE_ORDER == BIG_ENDIAN union fw_self_id { struct { @@ -291,7 +306,7 @@ union fw_self_id { link_active:1, gap_count:6, phy_speed:2, - phy_delay:2, + reserved:2, contender:1, power_class:3, port0:2, @@ -306,18 +321,32 @@ union fw_self_id { phy_id:6, sequel:1, sequence_num:3, - :2, - porta:2, - portb:2, - portc:2, - portd:2, - porte:2, - portf:2, - portg:2, - porth:2, - :1, + reserved2:2, + port3:2, + port4:2, + port5:2, + port6:2, + port7:2, + port8:2, + port9:2, + port10:2, + reserved1:1, more_packets:1; } p1; + struct { + uint32_t + id:2, + phy_id:6, + sequel:1, + sequence_num:3, + :2, + port11:2, + port12:2, + port13:2, + port14:2, + port15:2, + :8; + } p2; }; #else union fw_self_id { @@ -329,7 +358,7 @@ union fw_self_id { port0:2, power_class:3, contender:1, - phy_delay:2, + reserved:2, phy_speed:2, gap_count:6, link_active:1, @@ -340,20 +369,34 @@ union fw_self_id { struct { uint32_t more_packets:1, reserved1:1, - porth:2, - portg:2, - portf:2, - porte:2, - portd:2, - portc:2, - portb:2, - porta:2, + port10:2, + port9:2, + port8:2, + port7:2, + port6:2, + port5:2, + port4:2, + port3:2, reserved2:2, sequence_num:3, sequel:1, phy_id:6, id:2; } p1; + struct { + uint32_t + reserved3:8, + port15:2, + port14:2, + port13:2, + port12:2, + port11:2, + reserved4:2, + sequence_num:3, + sequel:1, + phy_id:6, + id:2; + } p2; }; #endif @@ -412,15 +455,15 @@ struct fw_crom_buf { #define FWMAXNDMA 0x100 /* 8 bits DMA channel id. in device No. */ -#define MAKEMINOR(f, u, s) \ - fw_unit2minor((f) | (((u) & 0xff) << 8) | (s & 0xff)) -#define DEV2UNIT(x) ((fw_dev2unit(x) & 0xff00) >> 8) -#define DEV2SUB(x) (fw_dev2unit(x) & 0xff) +#define unit2minor(x) (((x) & 0xff) | (((x) << 12) & ~0xfffff)) +#define MAKEMINOR(f, u, s) ((f) | (((u) & 0xff) << 8) | ((s) & 0xff)) +#define DEV2UNIT(x) ((minor(x) & 0xff00) >> 8) +#define DEV2SUB(x) (minor(x) & 0xff) #define FW_UNITMASK MAKEMINOR(0, -1, 0) #define FW_UNIT(unit) MAKEMINOR(0, unit, 0) #define FWMEM_FLAG 0x10000 -#define DEV_FWMEM(x) (fw_dev2unit(x) & FWMEM_FLAG) +#define DEV_FWMEM(x) (minor(x) & FWMEM_FLAG) struct fw_attach_args { const char *name; @@ -429,4 +472,4 @@ struct fw_attach_args { }; #endif -#endif +#endif /* _FIREWIRE_H_ */ diff --git a/sys/dev/ieee1394/firewire_phy.h b/sys/dev/ieee1394/firewire_phy.h index d2c7412d2fd..b4a0f805080 100644 --- a/sys/dev/ieee1394/firewire_phy.h +++ b/sys/dev/ieee1394/firewire_phy.h @@ -1,4 +1,4 @@ -/* $NetBSD: firewire_phy.h,v 1.2 2005/12/11 12:22:02 christos Exp $ */ +/* $NetBSD: firewire_phy.h,v 1.3 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa * All rights reserved. @@ -30,10 +30,12 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/firewire_phy.h,v 1.3 2005/01/06 01:42:41 imp Exp $ * */ +#ifndef _FIREWIRE_PHY_H_ +#define _FIREWIRE_PHY_H_ #define FW_PHY_PHYSID_REG 0x00 #define FW_PHY_PHYSID (63<<2) @@ -84,3 +86,5 @@ #define FW_PHY_EDEL_REG 0x03 #define FW_PHY_EDEL 15<<0 + +#endif /* _FIREWIRE_PHY_H_ */ diff --git a/sys/dev/ieee1394/firewirereg.h b/sys/dev/ieee1394/firewirereg.h index f513a97b289..8b748e25cf6 100644 --- a/sys/dev/ieee1394/firewirereg.h +++ b/sys/dev/ieee1394/firewirereg.h @@ -1,4 +1,4 @@ -/* $NetBSD: firewirereg.h,v 1.10 2009/06/20 20:18:32 dyoung Exp $ */ +/* $NetBSD: firewirereg.h,v 1.11 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -31,16 +31,20 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * $FreeBSD: src/sys/dev/firewire/firewirereg.h,v 1.50 2007/07/20 03:42:57 simokawa Exp $ * */ +#ifndef _FIREWIREREG_H_ +#define _FIREWIREREG_H_ #include <sys/uio.h> +#define PROJECT_STR "The NetBSD Project" + STAILQ_HEAD(fw_xferlist, fw_xfer); -struct fw_device{ +struct fw_device { uint16_t dst; struct fw_eui64 eui; uint8_t speed; @@ -66,9 +70,9 @@ struct firewire_softc { device_t dev; SLIST_HEAD(, firewire_dev_list) devlist; void *si_drv1; - int si_iosize_max; struct firewire_comm *fc; }; + struct firewire_dev_list { SLIST_ENTRY(firewire_dev_list) link; device_t dev; @@ -97,7 +101,7 @@ struct tcode_info { u_char valid_res; }; -struct firewire_comm{ +struct firewire_comm { device_t dev; device_t bdev; uint16_t busid:10, @@ -111,6 +115,7 @@ struct firewire_comm{ u_int max_hop; #define FWPHYASYST (1 << 0) uint32_t status; +#define FWBUSDETACHOK (-3) #define FWBUSDETACH (-2) #define FWBUSNOTREADY (-1) #define FWBUSRESET 0 @@ -128,7 +133,7 @@ struct firewire_comm{ *arq, *atq, *ars, *ats, *it[FW_MAX_DMACH],*ir[FW_MAX_DMACH]; struct fw_xferlist tlabels[0x40]; u_char last_tlabel[0x40]; - fw_mtx_t tlabel_lock; + kmutex_t tlabel_lock; STAILQ_HEAD(, fw_bind) binds; STAILQ_HEAD(, fw_device) devices; u_int sid_cnt; @@ -144,33 +149,27 @@ struct firewire_comm{ struct callout busprobe_callout; struct callout bmr_callout; struct callout timeout_callout; - fw_task_t task_timeout; uint32_t (*cyctimer) (struct firewire_comm *); void (*ibr) (struct firewire_comm *); uint32_t (*set_bmr) (struct firewire_comm *, uint32_t); - int (*ioctl) (fw_dev_t, u_long, void *, int, fw_proc_t); + int (*ioctl) (dev_t, u_long, void *, int, struct lwp *); int (*irx_enable) (struct firewire_comm *, int); int (*irx_disable) (struct firewire_comm *, int); int (*itx_enable) (struct firewire_comm *, int); int (*itx_disable) (struct firewire_comm *, int); - void (*timeout) (void *); - void (*poll) (struct firewire_comm *, int, int); + void (*timeout) (struct firewire_comm *); void (*set_intr) (struct firewire_comm *, int); void (*irx_post) (struct firewire_comm *, uint32_t *); void (*itx_post) (struct firewire_comm *, uint32_t *); const struct tcode_info *tcode; bus_dma_tag_t dmat; - fw_mtx_t mtx; - fw_mtx_t wait_lock; - struct taskqueue *taskqueue; - fw_proc_t probe_thread; + kmutex_t fc_mtx; + kmutex_t wait_lock; + kcondvar_t fc_cv; + struct lwp *probe_thread; }; #define CSRARC(sc, offset) ((sc)->csr_arc[(offset)/4]) -#define FW_GMTX(fc) (&(fc)->mtx) -#define FW_GLOCK(fc) fw_mtx_lock(FW_GMTX(fc)) -#define FW_GUNLOCK(fc) fw_mtx_unlock(FW_GMTX(fc)) -#define FW_GLOCK_ASSERT(fc) fw_mtx_assert(FW_GMTX(fc), MA_OWNED) struct fw_xferq { int flag; @@ -203,9 +202,15 @@ struct fw_xferq { struct selinfo rsel; void *sc; void (*hand) (struct fw_xferq *); + kmutex_t q_mtx; }; -struct fw_bulkxfer{ +#define FW_GMTX(fc) (&(fc)->fc_mtx) +#define FW_GLOCK(fc) fw_mtx_lock(FW_GMTX(fc)) +#define FW_GUNLOCK(fc) fw_mtx_unlock(FW_GMTX(fc)) +#define FW_GLOCK_ASSERT(fc) fw_mtx_assert(FW_GMTX(fc), MA_OWNED) + +struct fw_bulkxfer { int poffset; struct mbuf *mbuf; STAILQ_ENTRY(fw_bulkxfer) link; @@ -214,16 +219,17 @@ struct fw_bulkxfer{ int resp; }; -struct fw_bind{ +struct fw_bind { u_int64_t start; u_int64_t end; struct fw_xferlist xferlist; STAILQ_ENTRY(fw_bind) fclist; STAILQ_ENTRY(fw_bind) chlist; void *sc; + kmutex_t fwb_mtx; }; -struct fw_xfer{ +struct fw_xfer { void *sc; struct firewire_comm *fc; struct fw_xferq *q; @@ -251,6 +257,7 @@ struct fw_xfer{ STAILQ_ENTRY(fw_xfer) link; STAILQ_ENTRY(fw_xfer) tlabel; struct malloc_type *malloc; + kcondvar_t cv; }; struct fw_rcv_buf { @@ -261,39 +268,39 @@ struct fw_rcv_buf { uint8_t spd; }; -void fw_sidrcv (struct firewire_comm *, uint32_t *, u_int); -void fw_rcv (struct fw_rcv_buf *); -void fw_xfer_unload ( struct fw_xfer*); -void fw_xfer_free_buf ( struct fw_xfer*); -void fw_xfer_free ( struct fw_xfer*); -struct fw_xfer *fw_xfer_alloc (struct malloc_type *); -struct fw_xfer *fw_xfer_alloc_buf (struct malloc_type *, int, int); -void fw_init (struct firewire_comm *); int fw_tbuf_update (struct firewire_comm *, int, int); int fw_rbuf_update (struct firewire_comm *, int, int); -int fw_bindadd (struct firewire_comm *, struct fw_bind *); -int fw_bindremove (struct firewire_comm *, struct fw_bind *); -int fw_xferlist_add (struct fw_xferlist *, struct malloc_type *, int, int, int, - struct firewire_comm *, void *, void (*)(struct fw_xfer *)); -void fw_xferlist_remove (struct fw_xferlist *); -int fw_asyreq (struct firewire_comm *, int, struct fw_xfer*); -void fw_busreset (struct firewire_comm *, uint32_t); -uint16_t fw_crc16 (uint32_t *, uint32_t); -void fw_xfer_timeout (void *); -void fw_xfer_done (struct fw_xfer *); -void fw_xferwake (struct fw_xfer *); -int fw_xferwait (struct fw_xfer *); -void fw_asy_callback_free (struct fw_xfer *); -struct fw_device *fw_noderesolve_nodeid (struct firewire_comm *, int); -struct fw_device *fw_noderesolve_eui64 (struct firewire_comm *, struct fw_eui64 *); -struct fw_bind *fw_bindlookup (struct firewire_comm *, uint16_t, uint32_t); -void fw_drain_txq (struct firewire_comm *); int fwdev_makedev (struct firewire_softc *); int fwdev_destroydev (struct firewire_softc *); + +struct fw_device *fw_noderesolve_nodeid(struct firewire_comm *, int); +struct fw_device *fw_noderesolve_eui64(struct firewire_comm *, + struct fw_eui64 *); +int fw_asyreq(struct firewire_comm *, int, struct fw_xfer*); +void fw_xferwake(struct fw_xfer *); +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 *); +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 *); +int fw_xferlist_add(struct fw_xferlist *, struct malloc_type *, int, int, int, + struct firewire_comm *, void *, void (*)(struct fw_xfer *)); +void fw_xferlist_remove(struct fw_xferlist *); +struct fw_xfer *fw_xfer_alloc(struct malloc_type *); +struct fw_xfer *fw_xfer_alloc_buf(struct malloc_type *, int, int); +void fw_xfer_done(struct fw_xfer *); +void fw_xfer_unload(struct fw_xfer*); +void fw_xfer_free(struct fw_xfer*); +void fw_xfer_free_buf(struct fw_xfer*); +void fw_asy_callback_free(struct fw_xfer *); +void fw_sidrcv(struct firewire_comm *, uint32_t *, u_int); +void fw_rcv(struct fw_rcv_buf *); +uint16_t fw_crc16(uint32_t *, uint32_t); int fw_open_isodma(struct firewire_comm *, int); extern int firewire_debug; -extern struct cfdriver ieee1394if_cd; extern int firewire_phydma_enable; #define FWPRI ((PZERO+8)|PCATCH) @@ -314,3 +321,5 @@ extern int firewire_phydma_enable; MALLOC_DECLARE(M_FW); MALLOC_DECLARE(M_FWXFER); + +#endif /* _FIREWIREREG_H_ */ diff --git a/sys/dev/ieee1394/fw_port.h b/sys/dev/ieee1394/fw_port.h deleted file mode 100644 index 1d3c82343a6..00000000000 --- a/sys/dev/ieee1394/fw_port.h +++ /dev/null @@ -1,809 +0,0 @@ -/* $NetBSD: fw_port.h,v 1.33 2009/08/07 00:10:53 dyoung Exp $ */ -/* - * Copyright (c) 2004 KIYOHARA Takashi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef _FW_PORT_H -#define _FW_PORT_H - -#ifdef _KERNEL - -#define OS_STR "NetBSD" -#define OS_VER __NetBSD_Version__ -#define OS_VER_STR "NetBSD-2" -#define PROJECT_STR "NetBSD Project" - -#define fw_dev_t dev_t - -struct fwbus_attach_args { - const char *name; -}; - -struct fw_hwaddr { - uint32_t sender_unique_ID_hi; - uint32_t sender_unique_ID_lo; - uint8_t sender_max_rec; - uint8_t sspd; - uint16_t sender_unicast_FIFO_hi; - uint32_t sender_unicast_FIFO_lo; -}; - - -#define fw_dev2unit(x) minor(x) -#define fw_unit2minor(x) (((x) & 0xff) | (((x) << 12) & ~0xfffff)) - -#define fw_timevalcmp(tv1, tv2, op) timercmp((tv1), (tv2), op) -#define fw_timevalsub(tv1, tv2) timersub((tv1), (tv2), (tv1)) - -#define fw_get_nameunit(dev) device_xname(dev) -#define fw_get_unit(dev) device_unit((dev)) - -#define fw_printf(dev, ...) aprint_normal_dev((dev), __VA_ARGS__) - -/* atomic macros */ -/* XXXX: unsafe... */ -#define fw_atomic_set_int(P, V) (*(u_int *)(P) |= (V)) -static __inline int -fw_atomic_readandclear_int(int *p) -{ - int _p = *p; - - *p = 0; - return _p; -} - -/* mutex macros */ -/* XXXX: unsafe... */ -typedef void *fw_mtx_t; -#define fw_mtx_init(mutex, name, type, opts) -#define fw_mtx_lock(mutex) (void)(mutex) /* XXXX */ -#define fw_mtx_unlock(mutex) (void)(mutex) /* XXXX */ -#define fw_mtx_destroy(mutex) -#define fw_mtx_assert(mutex, what) - -#define fw_msleep(ident, mtx, priority, wmesg, timo) \ - tsleep((ident), (priority), (wmesg), (timo)) - -/* taskqueue macros */ -/* XXXX: unsafe... */ -typedef void (*task_fn_t)(void *context, int pending); -typedef struct { - STAILQ_ENTRY(task) ta_link; /* link for queue */ - u_short ta_pending; /* count times queued */ - u_short ta_priority; /* priority of task in queue */ - task_fn_t ta_func; /* task handler */ - void *ta_context; /* argument for handler */ -} fw_task_t; -#define fw_taskqueue_enqueue(queue, task) \ - (task)->ta_func((task)->ta_context, 0) -#define FW_TASK_INIT(task, priority, func, context) \ - do { \ - (task)->ta_priority = (priority); \ - (task)->ta_func = (func); \ - (task)->ta_context = (context); \ - } while (/*CONSTCOND*/0) -#define fw_taskqueue_create_fast(name, mflags, enqueue, taskqueue) \ - NULL -#define fw_taskqueue_start_threads(taskqueue, n, x, fmt, ...) - -/* kthread macros */ -typedef struct proc fw_thread_t; -typedef struct lwp *fw_proc_t; -#define fw_kthread_create(func, arg, newpp, fmt, ...) \ - kthread_create(PRI_NONE, 0, NULL, \ - (func), (arg), (newpp), (fmt), __VA_ARGS__) -#define fw_kthread_exit(ecode) kthread_exit((ecode)) - -/* callout macros */ -#define fw_callout_init(c) callout_init((c), 0) -#define fw_callout_reset(c, ticks, func, arg) \ - callout_reset((c), (ticks), (func), (arg)) -#define fw_callout_stop(c) callout_stop((c)) - -/* bus_dma macros */ -#include <sys/malloc.h> -#include <sys/bus.h> -struct fw_bus_dma_tag { - bus_dma_tag_t tag; - bus_size_t alignment; - bus_size_t boundary; - bus_size_t size; - int nsegments; - bus_size_t maxsegsz; - int flags; -}; -typedef struct fw_bus_dma_tag *fw_bus_dma_tag_t; -typedef int bus_dmasync_op_t; -typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); -typedef void - bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int); - -#define fw_bus_dma_tag_create( \ - p, a, b, la, ha, ffunc, farg, maxsz, \ - nseg, maxsegsz, f, lfunc, larg, dmat) \ - \ - _fw_bus_dma_tag_create((p), (a), (b), (la), (ha), \ - (ffunc), (farg), (maxsz), (nseg), (maxsegsz), (f), (dmat)) - -static __inline int -_fw_bus_dma_tag_create(bus_dma_tag_t parent, - bus_size_t alignment, bus_size_t boundary, - bus_addr_t lowaddr, bus_addr_t highaddr, - void *filtfunc, void *filtfuncarg, - bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, - int flags, fw_bus_dma_tag_t *fwdmat) -{ - fw_bus_dma_tag_t tag; - - tag = malloc(sizeof(struct fw_bus_dma_tag), M_DEVBUF, M_NOWAIT); - if (tag == NULL) - return ENOMEM; - -/* XXXX */ -#define BUS_SPACE_MAXADDR_32BIT 0 -#define BUS_SPACE_MAXADDR 0 - - tag->tag = parent; - tag->alignment = alignment; - tag->boundary = boundary; - tag->size = maxsize; - tag->nsegments = nsegments; - tag->maxsegsz = maxsegsz; - tag->flags = flags; - - *fwdmat = tag; - - return 0; -} -#define fw_bus_dma_tag_destroy(ft) \ - free(ft, M_DEVBUF) -#define fw_bus_dmamap_create(ft, f, mp) \ - bus_dmamap_create((ft)->tag, (ft)->size,\ - (ft)->nsegments, (ft)->maxsegsz, (ft)->boundary, (f), (mp)) -#define fw_bus_dmamap_destroy(ft, m) \ - bus_dmamap_destroy((ft)->tag, (m)) -static __inline int -fw_bus_dmamap_load(fw_bus_dma_tag_t ft, bus_dmamap_t m, - void *b, bus_size_t l, bus_dmamap_callback_t *func, void *a, int f) -{ - int lf = f & (BUS_DMA_WAITOK | BUS_DMA_NOWAIT | BUS_DMA_STREAMING | - BUS_DMA_READ | BUS_DMA_WRITE | - BUS_DMA_BUS1 | BUS_DMA_BUS2 | BUS_DMA_BUS3 | BUS_DMA_BUS4); - int err = bus_dmamap_load(ft->tag, m, b, l, NULL, lf); - (func)(a, m->dm_segs, m->dm_nsegs, err); - return err; -} -static __inline int -fw_bus_dmamap_load_mbuf(fw_bus_dma_tag_t ft, bus_dmamap_t m, - struct mbuf *b, bus_dmamap_callback2_t *func, void *a, int f) -{ - int lf = f & (BUS_DMA_WAITOK | BUS_DMA_NOWAIT | BUS_DMA_STREAMING | - BUS_DMA_READ | BUS_DMA_WRITE | - BUS_DMA_BUS1 | BUS_DMA_BUS2 | BUS_DMA_BUS3 | BUS_DMA_BUS4); - int err = bus_dmamap_load_mbuf(ft->tag, m, b, lf); - (func)(a, m->dm_segs, m->dm_nsegs, m->dm_mapsize, err); - return err; -} -#define fw_bus_dmamap_unload(ft, m) \ - bus_dmamap_unload((ft)->tag, (m)) -#define fw_bus_dmamap_sync(ft, m, op) \ - bus_dmamap_sync((ft)->tag, (m), 0, (m)->dm_mapsize, (op)) -static __inline int -fw_bus_dmamem_alloc(fw_bus_dma_tag_t ft, void **vp, int f, bus_dmamap_t *mp) -{ - bus_dma_segment_t segs; - int nsegs, err; - int af, mf, cf; - - af = f & (BUS_DMA_WAITOK | BUS_DMA_NOWAIT | BUS_DMA_STREAMING | - BUS_DMA_BUS1 | BUS_DMA_BUS2 | BUS_DMA_BUS3 | BUS_DMA_BUS4); - err = bus_dmamem_alloc(ft->tag, ft->size, - ft->alignment, ft->boundary, &segs, ft->nsegments, &nsegs, af); - if (err) { - printf("fw_bus_dmamem_alloc: failed(1)\n"); - return err; - } - - mf = f & (BUS_DMA_WAITOK | BUS_DMA_NOWAIT | - BUS_DMA_BUS1 | BUS_DMA_BUS2 | BUS_DMA_BUS3 | BUS_DMA_BUS4 | - BUS_DMA_COHERENT | BUS_DMA_NOCACHE); - err = bus_dmamem_map(ft->tag, - &segs, nsegs, ft->size, (void **)vp, mf); - if (err) { - printf("fw_bus_dmamem_alloc: failed(2)\n"); - bus_dmamem_free(ft->tag, &segs, nsegs); - return err; - } - - if (*mp != NULL) - return err; - - cf = f & (BUS_DMA_WAITOK | BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW | - BUS_DMA_BUS1 | BUS_DMA_BUS2 | BUS_DMA_BUS3 | BUS_DMA_BUS4); - err = bus_dmamap_create(ft->tag, - ft->size, nsegs, ft->maxsegsz, ft->boundary, cf, mp); - if (err) { - printf("fw_bus_dmamem_alloc: failed(3)\n"); - bus_dmamem_unmap(ft->tag, (void *)*vp, ft->size); - bus_dmamem_free(ft->tag, &segs, nsegs);\ - } - - return err; -} -#define fw_bus_dmamem_free(ft, v, m) \ - do { \ - bus_dmamem_unmap((ft)->tag, (v), (ft)->size); \ - bus_dmamem_free((ft)->tag, (m)->dm_segs, (m)->dm_nsegs);\ - bus_dmamap_destroy((ft)->tag, (m)); \ - } while (/*CONSTCOND*/0) - -#define fw_config_pending_incr() config_pending_incr() -#define fw_config_pending_decr() config_pending_decr() - -#define splfw() splvm() -#define splfwnet() splnet() -#define splfwsbp() splbio() -#define splsoftvm() splbio() - -#include <sys/select.h> - -#define FW_KASSERT(expression, str) \ - KASSERT(expression) - -/* - * fw attach macro for NetBSD - */ -#define FW_ATTACH(dname) \ - void \ - __CONCAT(dname,attach) \ - (device_t parent, device_t self, void *aux) -#define FW_ATTACH_START(dname, sc, fwa) \ - struct __CONCAT(dname,_softc) *sc = device_private(self); \ - __unused struct fw_attach_args *fwa = (struct fw_attach_args *)aux -#define FW_ATTACH_RETURN(r) return - -/* - * fw detach macro for NetBSD - */ -#define FW_DETACH(dname) \ - int \ - __CONCAT(dname,detach)(device_t self, int flags) -#define FW_DETACH_START(dname, sc) \ - struct __CONCAT(dname,_softc) *sc = device_private(self) - -/* - * fw open macro for NetBSD - */ -#define FW_OPEN(dname) \ - int \ - __CONCAT(dname,_open)(dev_t _dev, int flags, int fmt, fw_proc_t td) -#define FW_OPEN_START \ - struct firewire_softc *sc, *dev; \ - \ - sc = dev = device_lookup_private(&ieee1394if_cd, DEV2UNIT(_dev));\ - if (dev == NULL) \ - return ENXIO - -/* - * fw close macro for NetBSD - */ -#define FW_CLOSE(dname) \ - int \ - __CONCAT(dname,_close)(dev_t _dev, int flags, int fmt, fw_proc_t td) -#define FW_CLOSE_START \ - int unit = DEV2UNIT(_dev); \ - struct firewire_softc *dev; \ - \ - dev = device_lookup_private(&ieee1394if_cd, unit); \ - if (dev == NULL) \ - return ENXIO - -/* - * fw read macro for NetBSD - */ -#define FW_READ(dname) \ - int \ - __CONCAT(dname,_read)(dev_t _dev, struct uio *uio, int ioflag) -#define FW_READ_START \ - int unit = DEV2UNIT(_dev); \ - struct firewire_softc *dev; \ - \ - dev = device_lookup_private(&ieee1394if_cd, unit); \ - if (dev == NULL) \ - return ENXIO - -/* - * fw write macro for NetBSD - */ -#define FW_WRITE(dname) \ - int \ - __CONCAT(dname,_write)(dev_t _dev, struct uio *uio, int ioflag) -#define FW_WRITE_START \ - int unit = DEV2UNIT(_dev); \ - struct firewire_softc *dev; \ - \ - dev = device_lookup_private(&ieee1394if_cd, unit); \ - if (dev == NULL) \ - return ENXIO - -/* - * fw ioctl macro for NetBSD - */ -#define FW_IOCTL(dname) \ - int \ - __CONCAT(dname,_ioctl) \ - (dev_t _dev, u_long cmd, void *data, int flag, fw_proc_t td) -#define FW_IOCTL_START \ - int unit = DEV2UNIT(_dev); \ - struct firewire_softc *sc, *dev; \ - \ - sc = dev = device_lookup_private(&ieee1394if_cd, unit); \ - if (dev == NULL) \ - return ENXIO - -/* - * fw poll macro for NetBSD - */ -#define FW_POLL(dname) \ - int \ - __CONCAT(dname,_poll)(dev_t _dev, int events, fw_proc_t td) -#define FW_POLL_START \ - int unit = DEV2UNIT(_dev); \ - struct firewire_softc *dev; \ - \ - dev = device_lookup_private(&ieee1394if_cd, unit); \ - if (dev == NULL) \ - return ENXIO - -/* - * fw mmap macro for NetBSD - */ -#define FW_MMAP(dname) \ - paddr_t \ - __CONCAT(dname,_mmap)(dev_t _dev, off_t offset, int nproto) -#define FW_MMAP_START \ - int unit = DEV2UNIT(_dev); \ - struct firewire_softc *dev; \ - \ - dev = device_lookup_private(&ieee1394if_cd, unit); \ - if (dev == NULL) \ - return ENXIO - -/* - * fw strategy macro for NetBSD - */ -#define FW_STRATEGY_START \ - dev_t _dev = bp->bio_dev; \ - int unit = DEV2UNIT(_dev); \ - struct firewire_softc *sc, *dev; \ - \ - sc = dev = device_lookup_private(&ieee1394if_cd, unit); \ - if (dev == NULL) \ - return - -/* - * if macro for NetBSD - */ -#define IF_DETACH_START(dname, sc) \ - struct __CONCAT(dname,_softc) *sc = device_private(self) -#define IF_IOCTL_START(dname, sc) \ - struct __CONCAT(dname,_softc) *sc = \ - ((struct fwip_eth_softc *)ifp->if_softc)->fwip -#define IF_INIT(dname) \ - int \ - __CONCAT(dname,_init)(struct ifnet *ifp) -#define IF_INIT_START(dname, sc, ifp) \ - struct __CONCAT(dname,_softc) *sc = \ - ((struct fwip_eth_softc *)(ifp)->if_softc)->fwip -#define IF_INIT_RETURN(r) return (r) -#define IF_STOP(dname) \ - void \ - __CONCAT(dname,_stop)(struct ifnet *ifp, int disable) -#define IF_STOP_START(dname, ifp, sc) \ - struct __CONCAT(dname,_softc) *sc = \ - ((struct fwip_eth_softc *)(ifp)->if_softc)->fwip - -/* - * fwohci macro for NetBSD - */ -#define FWOHCI_DETACH() \ - int \ - fwohci_detach(struct fwohci_softc *sc, int flags) -#define FWOHCI_DETACH_START \ - if (sc->fc.bdev != NULL) \ - config_detach(sc->fc.bdev, flags) -#define FWOHCI_DETACH_END -#define FWOHCI_INIT_END \ - do { \ - struct fwbus_attach_args faa; \ - faa.name = "ieee1394if"; \ - sc->fc.bdev = config_found(sc->fc.dev, &faa, fwohci_print); \ - } while (/*CONSTCOND*/0) - -/* - * firewire macro for NetBSD - */ -#define FIREWIRE_ATTACH_START \ - struct firewire_comm *fc = device_private(parent); \ - \ - aprint_normal(": IEEE1394 bus\n"); \ - \ - fc->bdev = sc->dev = self; \ - SLIST_INIT(&sc->devlist) -#define FWDEV_DESTROYDEV(sc) -#define FIREWIRE_GENERIC_ATTACH \ - do { \ - struct fw_attach_args faa; \ - struct firewire_dev_list *devlist, *elm; \ - \ - devlist = malloc( \ - sizeof(struct firewire_dev_list), M_DEVBUF, M_NOWAIT); \ - if (devlist == NULL) \ - break; \ - \ - faa.name = "fwip"; \ - faa.fc = fc; \ - faa.fwdev = NULL; \ - devlist->dev = config_found(sc->dev, &faa, firewire_print); \ - if (devlist->dev == NULL) { \ - free(devlist, M_DEVBUF); \ - break; \ - } \ - \ - if (SLIST_EMPTY(&sc->devlist)) \ - SLIST_INSERT_HEAD(&sc->devlist, devlist, link); \ - else { \ - for (elm = SLIST_FIRST(&sc->devlist); \ - SLIST_NEXT(elm, link) != NULL; \ - elm = SLIST_NEXT(elm, link)); \ - SLIST_INSERT_AFTER(elm, devlist, link); \ - } \ - } while (/*CONSTCOND*/0) -#define FIREWIRE_GENERIC_DETACH \ - do { \ - struct firewire_dev_list *devlist; \ - int err; \ - \ - while ((devlist = SLIST_FIRST(&sc->devlist)) != NULL) { \ - if ((err = config_detach(devlist->dev, flags)) != 0) \ - return err; \ - SLIST_REMOVE( \ - &sc->devlist, devlist, firewire_dev_list, link); \ - free(devlist, M_DEVBUF); \ - } \ - } while (/*CONSTCOND*/0) -#define FIREWIRE_SBP_ATTACH \ - do { \ - struct firewire_softc *sc = device_private(fc->bdev); \ - struct firewire_dev_list *devlist, *elm; \ - int locs[IEEE1394IFCF_NLOCS]; \ - \ - devlist = malloc( \ - sizeof(struct firewire_dev_list), M_DEVBUF, M_NOWAIT); \ - if (devlist == NULL) { \ - printf("memory allocation failed\n"); \ - break; \ - } \ - \ - locs[IEEE1394IFCF_EUIHI] = fwdev->eui.hi; \ - locs[IEEE1394IFCF_EUILO] = fwdev->eui.lo; \ - \ - fwa.fwdev = fwdev; \ - fwdev->sbp = config_found_sm_loc(sc->dev, "ieee1394if", \ - locs, &fwa, firewire_print, config_stdsubmatch); \ - if (fwdev->sbp == NULL) { \ - free(devlist, M_DEVBUF); \ - break; \ - } \ - \ - devlist->fwdev = fwdev; \ - devlist->dev = fwdev->sbp; \ - \ - if (SLIST_EMPTY(&sc->devlist)) \ - SLIST_INSERT_HEAD(&sc->devlist, devlist, link); \ - else { \ - for (elm = SLIST_FIRST(&sc->devlist); \ - SLIST_NEXT(elm, link) != NULL; \ - elm = SLIST_NEXT(elm, link)); \ - SLIST_INSERT_AFTER(elm, devlist, link); \ - } \ - } while (/*CONSTCOND*/0) -#define FIREWIRE_SBP_DETACH \ - do { \ - struct firewire_softc *sc = device_private(fc->bdev); \ - struct firewire_dev_list *devlist; \ - \ - SLIST_FOREACH(devlist, &sc->devlist, link) { \ - if (devlist->fwdev != fwdev) \ - continue; \ - SLIST_REMOVE( \ - &sc->devlist, devlist, firewire_dev_list, link); \ - free(devlist, M_DEVBUF); \ - \ - if (config_detach(fwdev->sbp, DETACH_FORCE) != 0) \ - return; \ - } \ - } while (/*CONSTCOND*/0) -#define FIREWIRE_CHILDREN_FOREACH_FUNC(func, fdc) \ - do { \ - struct firewire_dev_list *devlist; \ - struct firewire_softc *sc = device_private(fc->bdev); \ - \ - if (!SLIST_EMPTY(&sc->devlist)) { \ - SLIST_FOREACH(devlist, &sc->devlist, link) { \ - (fdc) = device_private(devlist->dev); \ - if ((fdc)->func != NULL) \ - (fdc)->func((fdc)); \ - } \ - } \ - } while (/*CONSTCOND*/0) - -/* - * sbp macro for NetBSD - */ -#define SBP_ATTACH_START \ - do { \ - aprint_normal(": SBP-2/SCSI over IEEE1394\n"); \ - \ - sbp->fd.dev = self; \ - } while (/*CONSTCOND*/0) -#define SBP_SCSIBUS_ATTACH \ - do { \ - struct scsipi_adapter *sc_adapter = &sbp->sc_adapter; \ - struct scsipi_channel *sc_channel = &sbp->sc_channel; \ - struct sbp_target *target = &sbp->target; \ - \ - sc_adapter->adapt_dev = sbp->fd.dev; \ - sc_adapter->adapt_nchannels = 1; \ - sc_adapter->adapt_max_periph = 1; \ - sc_adapter->adapt_request = sbp_scsipi_request; \ - sc_adapter->adapt_minphys = sbp_minphys; \ - sc_adapter->adapt_openings = 8; \ - /*Start with some. Grow as needed.*/\ - \ - sc_channel->chan_adapter = sc_adapter; \ - sc_channel->chan_bustype = &scsi_bustype; \ - sc_channel->chan_defquirks = PQUIRK_ONLYBIG; \ - sc_channel->chan_channel = 0; \ - sc_channel->chan_flags = \ - SCSIPI_CHAN_CANGROW | SCSIPI_CHAN_NOSETTLE; \ - \ - /* We set nluns 0 now */ \ - sc_channel->chan_ntargets = 1; \ - sc_channel->chan_nluns = target->num_lun; \ - sc_channel->chan_id = 1; \ - \ - if ((sbp->sc_bus = \ - config_found(sbp->fd.dev, sc_channel, scsiprint)) == \ - NULL) { \ - fw_printf(sbp->fd.dev, "attach failed\n"); \ - return; \ - } \ - } while (/*CONSTCOND*/0) -#define SBP_DEVICE(d) ((d)->periph) -#define SBP_DEVICE_FREEZE(d, x) scsipi_periph_freeze((d)->periph, (x)); -#define SBP_DEVICE_THAW(d, x) \ - do { \ - if ((d)->periph) \ - scsipi_periph_thaw((d)->periph, (x)); \ - /* XXXX */ \ - scsipi_channel_thaw(&(d)->target->sbp->sc_channel, 0); \ - } while (/*CONSTCOND*/0) -#define SBP_BUS_FREEZE(b) scsipi_channel_freeze(&(b)->sc_channel, 1) -#define SBP_BUS_THAW(b) scsipi_channel_thaw(&(b)->sc_channel, 1) -#define SBP_DEVICE_PREATTACH() \ - do { \ - if (!sbp->lwp) { \ - /* create thread */ \ - if (kthread_create(PRI_NONE, 0, NULL, \ - sbp_scsipi_scan_target, &sbp->target, \ - &sbp->lwp, "sbp%d_attach", \ - device_unit(sbp->fd.dev))) { \ - fw_printf(sbp->fd.dev, \ - "unable to create thread"); \ - panic("fw_kthread_create"); \ - } \ - } \ - } while (/*CONSTCOND*/0) - -/* - * fwip macro for NetBSD - */ -#define FWIP_ATTACH_START \ - device_t dev = self; \ - struct fw_hwaddr *hwaddr; -#define FWIP_ATTACH_SETUP \ - do { \ - aprint_normal(": IP over IEEE1394\n"); \ - fwip->fd.dev = self; \ - fwip->fw_softc.fwip_ifp = &fwip->fw_softc.fwcom.fc_if; \ - hwaddr = (struct fw_hwaddr *)&fwip->fw_softc.fwcom.ic_hwaddr; \ - } while (/*CONSTCOND*/0) - -#define FWDEV_MAKEDEV(sc) -#define FIREWIRE_IFATTACH(ifp, ha) \ - do { \ - if_attach((ifp)); \ - ieee1394_ifattach((ifp), (const struct ieee1394_hwaddr *)(ha));\ - } while (/*CONSTCOND*/0) -#define FIREWIRE_IFDETACH(ifp) \ - do { \ - ieee1394_ifdetach(ifp); \ - if_detach(ifp); \ - } while (/*CONSTCOND*/0) -#define FIREWIRE_BUSRESET(ifp) ieee1394_drain((ifp)) -#define FIREWIRE_INPUT(ifp, m, src) \ - ieee1394_input((ifp), (m), (src)) -#define FWIP_INIT(sc) fwip_init((sc)->fw_softc.fwip_ifp) -#define FWIP_STOP(sc) fwip_stop((sc)->fw_softc.fwip_ifp, 1) -#define FIREWIRE_IOCTL(ifp, cmd, data) \ - ieee1394_ioctl((ifp), (cmd), (data)) -#define IF_INITNAME(ifp, dev, unit) \ - strlcpy((ifp)->if_xname, device_xname(dev), IFNAMSIZ); -#define SET_IFFUNC(ifp, start, ioctl, init, stop) \ - do { \ - (ifp)->if_start = (start); \ - (ifp)->if_ioctl = (ioctl); \ - (ifp)->if_init = (init); \ - (ifp)->if_stop = (stop); \ - } while (/*CONSTCOND*/0) - -/* - * fwdev macro for NetBSD - */ -#define FWDEV_OPEN_START \ - if (DEV_FWMEM(_dev)) \ - return fwmem_open(_dev, flags, fmt, td) -#define FWDEV_CLOSE_START \ - if (DEV_FWMEM(_dev)) \ - return fwmem_close(_dev, flags, fmt, td) -#define FWDEV_READ_START \ - if (DEV_FWMEM(_dev)) \ - return physio(fw_strategy, NULL, _dev, ioflag, minphys, uio) -#define FWDEV_WRITE_START \ - if (DEV_FWMEM(_dev)) \ - return physio(fw_strategy, NULL, _dev, ioflag, minphys, uio) -#define FWDEV_IOCTL_START \ - if (DEV_FWMEM(_dev)) \ - return fwmem_ioctl(_dev, cmd, data, flag, td) -#define FWDEV_IOCTL_REDIRECT fc->ioctl(_dev, cmd, data, flag, td) -#define FWDEV_POLL_START \ - if (DEV_FWMEM(_dev)) \ - return fwmem_poll(_dev, events, td) -#define FWDEV_MMAP_START \ - if (DEV_FWMEM(_dev)) \ - return fwmem_mmap(_dev, offset, nproto) -#define FWDEV_STRATEGY_START \ - if (DEV_FWMEM(_dev)) { \ - fwmem_strategy(bp); \ - return; \ - } - -#define XS_REQ_INVALID XS_DRIVER_STUFFUP -#define XS_SCSI_BUS_RESET XS_RESET -#define XS_BDR_SENT XS_RESET -#define XS_DEV_NOT_THERE XS_DRIVER_STUFFUP -#define XS_CMD_TIMEOUT XS_TIMEOUT -#define XS_REQUEUE_REQ XS_REQUEUE -#define XS_REQ_CMP XS_NOERROR -#define XS_REQ_CMP_ERR XS_DRIVER_STUFFUP -#define XS_UA_ABORT XS_DRIVER_STUFFUP - -typedef struct scsipi_xfer sbp_scsi_xfer; -typedef struct scsipi_inquiry_data sbp_scsi_inquiry_data; - -#define SCSI_XFER_TARGET(x) ((x)->xs_periph->periph_target) -#define SCSI_XFER_LUN(x) ((x)->xs_periph->periph_lun) -#define SCSI_XFER_ERROR(x) ((x)->error) -#define SCSI_XFER_DIR(x) \ - ((x)->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) -#define SCSI_XFER_DATA_IN XS_CTL_DATA_IN -#define SCSI_XFER_CALLOUT(x) ((x)->xs_callout) -#define SCSI_XFER_TIMEOUT(x) ((x)->timeout) -#define SCSI_XFER_OPECODE(x) ((x)->cmd->opcode) -#define SCSI_XFER_STATUS(x) ((x)->xs_status) -#define SCSI_XFER_EVPD(x) ((x)->cmd->bytes[0] & SI_EVPD) -#define SI_EVPD 0x01 -#define SCSI_XFER_CMDLEN(x) ((x)->cmdlen) -#define SCSI_XFER_CMD(x) ((x)->cmd) -#define SCSI_XFER_DATALEN(x) ((x)->datalen) -#define SCSI_XFER_DATA(x) ((x)->data) -#define SCSI_XFER_SENSELEN(x) (0 /* XXXXX */) -#define SCSI_SENSE_DATA(x) (&(x)->sense.scsi_sense) -#define SCSI_INQUIRY_DATA(x) ((x)->data) -#define SCSI_XFER_FUNCCODE(x) XPT_SCSI_IO -#define SCSI_XFER_10BCMD_DUMP(x)\ - ((x)->cmd->opcode), \ - ((x)->cmd->bytes[0]), \ - ((x)->cmd->bytes[1]), \ - ((x)->cmd->bytes[2]), \ - ((x)->cmd->bytes[3]), \ - ((x)->cmd->bytes[4]), \ - ((x)->cmd->bytes[5]), \ - ((x)->cmd->bytes[6]), \ - ((x)->cmd->bytes[7]), \ - ((x)->cmd->bytes[8]) -#define SCSI_XFER_REQUEST_COMPLETE(x) \ - ((x)->resid = 0) -#define SCSI_TRANSFER_DONE(x) scsipi_done((x)) - -#define NOT_LUN_WILDCARD(l) (1) -#define CAM_XFER_FLAGS(x) (0) /* XXX */ -#define CAM_SCATTER_VALID (0) /* XXX */ -#define CAM_DATA_PHYS (0) /* XXX */ -#define XPT_SCSI_IO (1) /* XXX */ - -#ifndef rounddown -#define rounddown(x, y) ((x) / (y) * (y)) -#endif - -/* - * additional mbuf macros for NetBSD - */ -#include <sys/mbuf.h> -#define M_TRYWAIT M_WAITOK - -#define MTAG_FIREWIRE 1394 -#define MTAG_FIREWIRE_HWADDR 0 -#define MTAG_FIREWIRE_SENDER_EUID 1 - -#define m_tag_alloc(cookie, type, len, wait) \ - m_tag_get((type), (len), (wait)) -#define m_tag_locate(m, cookie, type, t) \ - m_tag_find((m), (type), (t)) - -/* additional bpf macros */ -#define bpf_peers_present(if_bpf) (if_bpf) - - -#define CTR0(m, format) -#define CTR1(m, format, p1) - -#define OHCI_CSR_WRITE(sc, reg, val) \ - bus_space_write_4((sc)->bst, (sc)->bsh, reg, val) - -#define FILTER_STRAY 0 -#define FILTER_HANDLED 1 - -#define SSD_CURRENT_ERROR 0x70 -#define SSD_DEFERRED_ERROR 0x71 - -#define T_RBC T_SIMPLE_DIRECT - -#define SCSI_STATUS_CHECK_COND SCSI_CHECK -#define SCSI_STATUS_BUSY SCSI_BUSY -#define SCSI_STATUS_CMD_TERMINATED SCSI_TERMINATED - -#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF - -#define DFLTPHYS (64 * 1024) /* fake */ - -#define kdb_backtrace() -#define kdb_active 0 - -#endif -#define vm_offset_t void * -#endif diff --git a/sys/dev/ieee1394/fwcrom.c b/sys/dev/ieee1394/fwcrom.c index 9f7fa18abcb..1a4e90f3bf6 100644 --- a/sys/dev/ieee1394/fwcrom.c +++ b/sys/dev/ieee1394/fwcrom.c @@ -1,8 +1,8 @@ -/* $NetBSD: fwcrom.c,v 1.10 2009/04/18 14:58:02 tsutsui Exp $ */ +/* $NetBSD: fwcrom.c,v 1.11 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2002-2003 * Hidetoshi Shimokawa. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -34,44 +34,8 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fwcrom.c,v 1.10 2009/04/18 14:58:02 tsutsui Exp $"); -#ifdef __FreeBSD__ -__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/fwcrom.c,v 1.14 2006/02/04 21:37:39 imp Exp $"); -#endif +__KERNEL_RCSID(0, "$NetBSD: fwcrom.c,v 1.11 2010/03/29 03:05:27 kiyohara Exp $"); -#if defined(__FreeBSD__) -#include <sys/param.h> - -#ifdef _BOOT -#include <stand.h> -#include <bootstrap.h> -#else -#if defined(_KERNEL) || defined(TEST) -#include <sys/queue.h> -#endif -#ifdef _KERNEL -#include <sys/systm.h> -#include <sys/kernel.h> -#else -#include <netinet/in.h> -#include <fcntl.h> -#include <stdio.h> -#include <err.h> -#include <stdlib.h> -#include <string.h> -#endif -#endif - -#ifdef __DragonFly__ -#include "fw_port.h" -#include "firewire.h" -#include "iec13213.h" -#else -#include <dev/firewire/fw_port.h> -#include <dev/firewire/firewire.h> -#include <dev/firewire/iec13213.h> -#endif -#elif defined(__NetBSD__) #include <sys/param.h> #ifdef _KERNEL #include <sys/device.h> @@ -81,10 +45,8 @@ __FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/fwcrom.c,v 1.14 2006/02 #include <stdio.h> #include <string.h> #endif -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/iec13213.h> -#endif #define MAX_ROM (1024 - sizeof(uint32_t) * 5) #define CROM_END(cc) ((char *)(cc)->stack[0].dir + MAX_ROM - 1) @@ -118,7 +80,7 @@ crom_get(struct crom_context *cc) struct crom_ptr *ptr; ptr = &cc->stack[cc->depth]; - return (&ptr->dir->entry[ptr->index]); + return &ptr->dir->entry[ptr->index]; } void @@ -135,19 +97,19 @@ crom_next(struct crom_context *cc) printf("crom_next: too deep\n"); goto again; } - cc->depth ++; + cc->depth++; ptr = &cc->stack[cc->depth]; - ptr->dir = (struct csrdirectory *) (reg + reg->val); + ptr->dir = (struct csrdirectory *)(reg + reg->val); ptr->index = 0; goto check; } again: ptr = &cc->stack[cc->depth]; - ptr->index ++; + ptr->index++; check: if (ptr->index < ptr->dir->crc_len && - (char *)crom_get(cc) <= CROM_END(cc)) + (char *)crom_get(cc) <= CROM_END(cc)) return; if (ptr->index < ptr->dir->crc_len) @@ -167,7 +129,7 @@ crom_search_key(struct crom_context *cc, uint8_t key) { struct csrreg *reg; - while(cc->depth >= 0) { + while (cc->depth >= 0) { reg = crom_get(cc); if (reg->key == key) return reg; @@ -185,7 +147,7 @@ crom_has_specver(uint32_t *p, uint32_t spec, uint32_t ver) cc = &c; crom_init_context(cc, p); - while(cc->depth >= 0) { + while (cc->depth >= 0) { reg = crom_get(cc); if (state == 0) { if (reg->key == CSRKEY_SPEC && reg->val == spec) @@ -217,7 +179,7 @@ crom_parse_text(struct crom_context *cc, char *buf, int len) reg = crom_get(cc); if (reg->key != CROM_TEXTLEAF || - (char *)(reg + reg->val) > CROM_END(cc)) { + (char *)(reg + reg->val) > CROM_END(cc)) { strncpy(buf, nullstr, len); return; } @@ -230,11 +192,11 @@ crom_parse_text(struct crom_context *cc, char *buf, int len) /* XXX should check spec and type */ - bp = (uint32_t *)&buf[0]; + bp = (uint32_t *)buf; qlen = textleaf->crc_len - 2; if (len < qlen * 4) qlen = len/4; - for (i = 0; i < qlen; i ++) + for (i = 0; i < qlen; i++) *bp++ = ntohl(textleaf->text[i]); /* make sure to terminate the string */ if (len <= qlen * 4) @@ -257,7 +219,7 @@ crom_crc(uint32_t *ptr, int len) } crc &= 0xffff; } - return((uint16_t) crc); + return (uint16_t)crc; } #if !defined(_KERNEL) && !defined(_BOOT) @@ -333,18 +295,17 @@ crom_desc(struct crom_context *cc, char *buf, int len) #endif break; case CSRTYPE_C: - len -= snprintf(buf, len, "offset=0x%04x(%d)", - reg->val, reg->val); + len -= + snprintf(buf, len, "offset=0x%04x(%d)", reg->val, reg->val); buf += strlen(buf); break; case CSRTYPE_L: /* XXX fall through */ case CSRTYPE_D: dir = (struct csrdirectory *) (reg + reg->val); - crc = crom_crc((uint32_t *)&dir->entry[0], dir->crc_len); + crc = crom_crc((uint32_t *)dir->entry, dir->crc_len); len -= snprintf(buf, len, "len=%d crc=0x%04x(%s) ", - dir->crc_len, dir->crc, - (crc == dir->crc) ? "OK" : "NG"); + dir->crc_len, dir->crc, (crc == dir->crc) ? "OK" : "NG"); buf += strlen(buf); } switch (reg->key) { @@ -418,11 +379,11 @@ crom_add_quad(struct crom_chunk *chunk, uint32_t entry) index = chunk->data.crc_len; if (index >= CROM_MAX_CHUNK_LEN - 1) { printf("too large chunk %d\n", index); - return(-1); + return -1; } chunk->data.buf[index] = entry; chunk->data.crc_len++; - return(index); + return index; } int @@ -432,42 +393,37 @@ crom_add_entry(struct crom_chunk *chunk, int key, int val) struct csrreg reg; uint32_t i; } foo; - + foo.reg.key = key; foo.reg.val = val; - return(crom_add_quad(chunk, foo.i)); + return crom_add_quad(chunk, foo.i); } int crom_add_chunk(struct crom_src *src, struct crom_chunk *parent, - struct crom_chunk *child, int key) + struct crom_chunk *child, int key) { int index; if (parent == NULL) { STAILQ_INSERT_TAIL(&src->chunk_list, child, link); - return(0); + return 0; } index = crom_add_entry(parent, key, 0); - if (index < 0) { - return(-1); - } + if (index < 0) + return -1; child->ref_chunk = parent; child->ref_index = index; STAILQ_INSERT_TAIL(&src->chunk_list, child, link); - return(index); + return index; } -#if defined(__FreeBSD__) -#define MAX_TEXT ((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext)) -#elif defined(__NetBSD__) #define MAX_TEXT (int)((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext)) -#endif int crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent, - struct crom_chunk *chunk, const char *buf) + struct crom_chunk *chunk, const char *buf) { struct csrtext *tl; uint32_t *p; @@ -476,11 +432,7 @@ crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent, len = strlen(buf); if (len > MAX_TEXT) { -#if defined(__DragonFly__) || __FreeBSD_version < 500000 || defined(__NetBSD__) printf("text(%d) trancated to %d.\n", len, MAX_TEXT); -#else - printf("text(%d) trancated to %td.\n", len, MAX_TEXT); -#endif len = MAX_TEXT; } @@ -489,24 +441,25 @@ crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent, tl->spec_id = 0; tl->spec_type = 0; tl->lang_id = 0; - memset(&t[0], 0, roundup2(len, sizeof(uint32_t))); - memcpy(&t[0], buf, len); - p = (uint32_t *)&t[0]; - for (i = 0; i < howmany(len, sizeof(uint32_t)); i ++) + memset(t, 0, roundup2(len, sizeof(uint32_t))); + memcpy(t, buf, len); + p = (uint32_t *)t; + for (i = 0; i < howmany(len, sizeof(uint32_t)); i++) tl->text[i] = ntohl(*p++); - return (crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF)); + return crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF); } static int crom_copy(uint32_t *src, uint32_t *dst, int *offset, int len, int maxlen) { + if (*offset + len > maxlen) { printf("Config. ROM is too large for the buffer\n"); - return(-1); + return -1; } memcpy((char *)(dst + *offset), src, len * sizeof(uint32_t)); *offset += len; - return(0); + return 0; } int @@ -529,27 +482,28 @@ crom_load(struct crom_src *src, uint32_t *buf, int maxlen) parent = chunk->ref_chunk; if (parent != NULL) { struct csrreg *reg; - reg = (struct csrreg *) - &parent->data.buf[chunk->ref_index]; - reg->val = offset - - (parent->offset + 1 + chunk->ref_index); + const int ref_index = chunk->ref_index; + + reg = (struct csrreg *)&parent->data.buf[ref_index]; + reg->val = + offset - (parent->offset + 1 + chunk->ref_index); } - offset += 1 + chunk->data.crc_len; + offset += (1 + chunk->data.crc_len); } /* Calculate CRC and dump to the buffer */ len = 1 + src->hdr.info_len; count = 0; if (crom_copy((uint32_t *)&src->hdr, buf, &count, len, maxlen) < 0) - return(-1); + return -1; STAILQ_FOREACH(chunk, &src->chunk_list, link) { chunk->data.crc = - crom_crc(&chunk->data.buf[0], chunk->data.crc_len); + crom_crc(chunk->data.buf, chunk->data.crc_len); len = 1 + chunk->data.crc_len; - if (crom_copy((uint32_t *)&chunk->data, buf, - &count, len, maxlen) < 0) - return(-1); + if (crom_copy((uint32_t *)&chunk->data, buf, &count, len, + maxlen) < 0) + return -1; } hdr = (struct csrhdr *)buf; hdr->crc_len = count - 1; @@ -558,13 +512,13 @@ crom_load(struct crom_src *src, uint32_t *buf, int maxlen) #if defined(_KERNEL) || defined(_BOOT) /* byte swap */ ptr = buf; - for (i = 0; i < count; i ++) { + for (i = 0; i < count; i++) { *ptr = htonl(*ptr); ptr++; } #endif - return(count); + return count; } #endif @@ -572,10 +526,11 @@ crom_load(struct crom_src *src, uint32_t *buf, int maxlen) int main () { struct crom_src src; - struct crom_chunk root,unit1,unit2,unit3; - struct crom_chunk text1,text2,text3,text4,text5,text6,text7; + struct crom_chunk root, unit1, unit2, unit3; + struct crom_chunk text1, text2, text3, text4, text5, text6, text7; uint32_t buf[256], *p; int i; + extern const char ostype[]; memset(&src, 0, sizeof(src)); memset(&root, 0, sizeof(root)); @@ -614,8 +569,8 @@ main () { /* private company_id */ crom_add_entry(&root, CSRKEY_VENDOR, 0xacde48); - crom_add_simple_text(&src, &root, &text1, OS_STR); - crom_add_entry(&root, CSRKEY_HW, OS_VER); + crom_add_simple_text(&src, &root, &text1, ostype); + crom_add_entry(&root, CSRKEY_HW, __NetBSD_Version__); crom_add_simple_text(&src, &root, &text2, OS_VER_STR); /* SBP unit directory */ @@ -648,12 +603,12 @@ main () { crom_load(&src, buf, 256); p = buf; -#define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n" - for (i = 0; i < 256/8; i ++) { +#define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n" + for (i = 0; i < 256 / 8; i++) { printf(DUMP_FORMAT, - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); p += 8; } - return(0); + return 0; } #endif diff --git a/sys/dev/ieee1394/fwdev.c b/sys/dev/ieee1394/fwdev.c index d082d83b0e5..b49aa6f1165 100644 --- a/sys/dev/ieee1394/fwdev.c +++ b/sys/dev/ieee1394/fwdev.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwdev.c,v 1.17 2009/04/18 14:58:02 tsutsui Exp $ */ +/* $NetBSD: fwdev.c,v 1.18 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -31,111 +31,37 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * $FreeBSD: src/sys/dev/firewire/fwdev.c,v 1.52 2007/06/06 14:31:36 simokawa Exp $ * */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fwdev.c,v 1.17 2009/04/18 14:58:02 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fwdev.c,v 1.18 2010/03/29 03:05:27 kiyohara Exp $"); -#if defined(__FreeBSD__) -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/types.h> -#include <sys/mbuf.h> -#if defined(__DragonFly__) || __FreeBSD_version < 500000 -#include <sys/buf.h> -#else -#include <sys/bio.h> -#endif - -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/conf.h> -#include <sys/poll.h> - -#include <sys/bus.h> -#include <sys/ctype.h> -#include <sys/bus.h> - -#include <sys/ioccom.h> - -#ifdef __DragonFly__ -#include "fw_port.h" -#include "firewire.h" -#include "firewirereg.h" -#include "fwdma.h" -#include "fwmem.h" -#include "iec68113.h" -#else -#include <dev/firewire/fw_port.h> -#include <dev/firewire/firewire.h> -#include <dev/firewire/firewirereg.h> -#include <dev/firewire/fwdma.h> -#include <dev/firewire/fwmem.h> -#include <dev/firewire/iec68113.h> -#endif -#elif defined(__NetBSD__) #include <sys/param.h> #include <sys/device.h> #include <sys/errno.h> #include <sys/buf.h> +#include <sys/bus.h> #include <sys/conf.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/poll.h> #include <sys/proc.h> +#include <sys/select.h> -#include <sys/bus.h> - -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/firewirereg.h> #include <dev/ieee1394/fwdma.h> #include <dev/ieee1394/fwmem.h> #include <dev/ieee1394/iec68113.h> -#endif + +#include "ioconf.h" #define FWNODE_INVAL 0xffff -#if defined(__FreeBSD__) -static d_open_t fw_open; -static d_close_t fw_close; -static d_ioctl_t fw_ioctl; -static d_poll_t fw_poll; -static d_read_t fw_read; /* for Isochronous packet */ -static d_write_t fw_write; -static d_mmap_t fw_mmap; -static d_strategy_t fw_strategy; - -struct cdevsw firewire_cdevsw = { -#ifdef __DragonFly__ -#define CDEV_MAJOR 127 - "fw", CDEV_MAJOR, D_MEM, NULL, 0, - fw_open, fw_close, fw_read, fw_write, fw_ioctl, - fw_poll, fw_mmap, fw_strategy, nodump, nopsize, -#elif __FreeBSD_version >= 500104 - .d_version = D_VERSION, - .d_open = fw_open, - .d_close = fw_close, - .d_read = fw_read, - .d_write = fw_write, - .d_ioctl = fw_ioctl, - .d_poll = fw_poll, - .d_mmap = fw_mmap, - .d_strategy = fw_strategy, - .d_name = "fw", - .d_flags = D_MEM -#else -#define CDEV_MAJOR 127 - fw_open, fw_close, fw_read, fw_write, fw_ioctl, - fw_poll, fw_mmap, fw_strategy, "fw", CDEV_MAJOR, - nodump, nopsize, D_MEM, -1 -#endif -}; -#elif defined(__NetBSD__) dev_type_open(fw_open); dev_type_close(fw_close); dev_type_read(fw_read); @@ -153,7 +79,6 @@ const struct cdevsw fw_cdevsw = { fw_open, fw_close, fw_read, fw_write, fw_ioctl, nostop, notty, fw_poll, fw_mmap, nokqfilter, D_OTHER, }; -#endif struct fw_drv1 { struct firewire_comm *fc; @@ -164,103 +89,42 @@ struct fw_drv1 { STAILQ_HEAD(, fw_xfer) rq; }; -static int -fwdev_allocbuf(struct firewire_comm *fc, struct fw_xferq *q, - struct fw_bufspec *b) -{ - int i; - - if (q->flag & (FWXFERQ_RUNNING | FWXFERQ_EXTBUF)) - return(EBUSY); - - q->bulkxfer = (struct fw_bulkxfer *) malloc( - sizeof(struct fw_bulkxfer) * b->nchunk, - M_FW, M_WAITOK); - if (q->bulkxfer == NULL) - return(ENOMEM); - - b->psize = roundup2(b->psize, sizeof(uint32_t)); - q->buf = fwdma_malloc_multiseg(fc, sizeof(uint32_t), - b->psize, b->nchunk * b->npacket, BUS_DMA_WAITOK); - - if (q->buf == NULL) { - free(q->bulkxfer, M_FW); - q->bulkxfer = NULL; - return(ENOMEM); - } - q->bnchunk = b->nchunk; - q->bnpacket = b->npacket; - q->psize = (b->psize + 3) & ~3; - q->queued = 0; +static int fwdev_allocbuf(struct firewire_comm *, struct fw_xferq *, + struct fw_bufspec *); +static int fwdev_freebuf(struct fw_xferq *); +static int fw_read_async(struct fw_drv1 *, struct uio *, int); +static int fw_write_async(struct fw_drv1 *, struct uio *, int); +static void fw_hand(struct fw_xfer *); - STAILQ_INIT(&q->stvalid); - STAILQ_INIT(&q->stfree); - STAILQ_INIT(&q->stdma); - q->stproc = NULL; - for(i = 0 ; i < q->bnchunk; i++){ - q->bulkxfer[i].poffset = i * q->bnpacket; - q->bulkxfer[i].mbuf = NULL; - STAILQ_INSERT_TAIL(&q->stfree, &q->bulkxfer[i], link); - } - - q->flag &= ~FWXFERQ_MODEMASK; - q->flag |= FWXFERQ_STREAM; - q->flag |= FWXFERQ_EXTBUF; - - return (0); -} - -static int -fwdev_freebuf(struct fw_xferq *q) -{ - if (q->flag & FWXFERQ_EXTBUF) { - if (q->buf != NULL) - fwdma_free_multiseg(q->buf); - q->buf = NULL; - free(q->bulkxfer, M_FW); - q->bulkxfer = NULL; - q->flag &= ~FWXFERQ_EXTBUF; - q->psize = 0; - q->maxq = FWMAXQUEUE; - } - return (0); -} - - -FW_OPEN(fw) +int +fw_open(dev_t dev, int flags, int fmt, struct lwp *td) { - int err = 0; + struct firewire_softc *sc; struct fw_drv1 *d; - FW_OPEN_START; + int err = 0; - FWDEV_OPEN_START; + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; + + if (DEV_FWMEM(dev)) + return fwmem_open(dev, flags, fmt, td); - FW_GLOCK(sc->fc); - if (dev->si_drv1 != NULL) { - FW_GUNLOCK(sc->fc); - return (EBUSY); + mutex_enter(&sc->fc->fc_mtx); + if (sc->si_drv1 != NULL) { + mutex_exit(&sc->fc->fc_mtx); + return EBUSY; } /* set dummy value for allocation */ - dev->si_drv1 = (void *)-1; - FW_GUNLOCK(sc->fc); - - dev->si_drv1 = malloc(sizeof(struct fw_drv1), M_FW, M_WAITOK | M_ZERO); - if (dev->si_drv1 == NULL) - return (ENOMEM); + sc->si_drv1 = (void *)-1; + mutex_exit(&sc->fc->fc_mtx); -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - if ((dev->si_flags & SI_NAMED) == 0) { - int unit = DEV2UNIT(dev); - int sub = DEV2SUB(dev); - - make_dev(&firewire_cdevsw, minor(dev), - UID_ROOT, GID_OPERATOR, 0660, - "fw%d.%d", unit, sub); - } -#endif + sc->si_drv1 = malloc(sizeof(struct fw_drv1), M_FW, M_WAITOK | M_ZERO); + if (sc->si_drv1 == NULL) + return ENOMEM; - d = (struct fw_drv1 *)dev->si_drv1; + d = (struct fw_drv1 *)sc->si_drv1; d->fc = sc->fc; STAILQ_INIT(&d->binds); STAILQ_INIT(&d->rq); @@ -268,23 +132,29 @@ FW_OPEN(fw) return err; } -FW_CLOSE(fw) +int +fw_close(dev_t dev, int flags, int fmt, struct lwp *td) { + struct firewire_softc *sc; struct firewire_comm *fc; struct fw_drv1 *d; struct fw_xfer *xfer; struct fw_bind *fwb; - int err = 0; - FW_CLOSE_START; + int err = 0; - FWDEV_CLOSE_START; + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; + + if (DEV_FWMEM(dev)) + return fwmem_close(dev, flags, fmt, td); - d = (struct fw_drv1 *)dev->si_drv1; + d = (struct fw_drv1 *)sc->si_drv1; fc = d->fc; /* remove binding */ for (fwb = STAILQ_FIRST(&d->binds); fwb != NULL; - fwb = STAILQ_FIRST(&d->binds)) { + fwb = STAILQ_FIRST(&d->binds)) { fw_bindremove(fc, fwb); STAILQ_REMOVE_HEAD(&d->binds, chlist); fw_xferlist_remove(&fwb->xferlist); @@ -294,7 +164,7 @@ FW_CLOSE(fw) struct fw_xferq *ir = d->ir; if ((ir->flag & FWXFERQ_OPEN) == 0) - return (EINVAL); + return EINVAL; if (ir->flag & FWXFERQ_RUNNING) { ir->flag &= ~FWXFERQ_RUNNING; fc->irx_disable(fc, ir->dmach); @@ -302,16 +172,16 @@ FW_CLOSE(fw) /* free extbuf */ fwdev_freebuf(ir); /* drain receiving buffer */ - for (xfer = STAILQ_FIRST(&ir->q); - xfer != NULL; xfer = STAILQ_FIRST(&ir->q)) { - ir->queued --; + for (xfer = STAILQ_FIRST(&ir->q); xfer != NULL; + xfer = STAILQ_FIRST(&ir->q)) { + ir->queued--; STAILQ_REMOVE_HEAD(&ir->q, link); xfer->resp = 0; fw_xfer_done(xfer); } - ir->flag &= ~(FWXFERQ_OPEN | - FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); + ir->flag &= + ~(FWXFERQ_OPEN | FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); d->ir = NULL; } @@ -319,100 +189,57 @@ FW_CLOSE(fw) struct fw_xferq *it = d->it; if ((it->flag & FWXFERQ_OPEN) == 0) - return (EINVAL); + return EINVAL; if (it->flag & FWXFERQ_RUNNING) { it->flag &= ~FWXFERQ_RUNNING; fc->itx_disable(fc, it->dmach); } /* free extbuf */ fwdev_freebuf(it); - it->flag &= ~(FWXFERQ_OPEN | - FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); + it->flag &= + ~(FWXFERQ_OPEN | FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK); d->it = NULL; } - free(dev->si_drv1, M_FW); - dev->si_drv1 = NULL; + free(sc->si_drv1, M_FW); + sc->si_drv1 = NULL; return err; } -static int -fw_read_async(struct fw_drv1 *d, struct uio *uio, int ioflag) -{ - int err = 0, s; - struct fw_xfer *xfer; - struct fw_bind *fwb; - struct fw_pkt *fp; - const struct tcode_info *tinfo; - - FW_GLOCK(d->fc); - while ((xfer = STAILQ_FIRST(&d->rq)) == NULL && err == 0) - err = fw_msleep(&d->rq, FW_GMTX(d->fc), FWPRI, "fwra", 0); - - if (err != 0) { - FW_GUNLOCK(d->fc); - return (err); - } - - s = splfw(); - STAILQ_REMOVE_HEAD(&d->rq, link); - FW_GUNLOCK(xfer->fc); - splx(s); - fp = &xfer->recv.hdr; -#if 0 /* for GASP ?? */ - if (fc->irx_post != NULL) - fc->irx_post(fc, fp->mode.ld); -#endif - tinfo = &xfer->fc->tcode[fp->mode.hdr.tcode]; - err = uiomove((void *)fp, tinfo->hdr_len, uio); - if (err) - goto out; - err = uiomove((void *)xfer->recv.payload, xfer->recv.pay_len, uio); - -out: - /* recycle this xfer */ - fwb = (struct fw_bind *)xfer->sc; - fw_xfer_unload(xfer); - xfer->recv.pay_len = PAGE_SIZE; - FW_GLOCK(xfer->fc); - STAILQ_INSERT_TAIL(&fwb->xferlist, xfer, link); - FW_GUNLOCK(xfer->fc); - return (err); -} - -/* - * read request. - */ -FW_READ(fw) +int +fw_read(dev_t dev, struct uio *uio, int ioflag) { - FW_READ_START; + struct firewire_softc *sc; + struct firewire_comm *fc; struct fw_drv1 *d; struct fw_xferq *ir; - struct firewire_comm *fc; - int err = 0, s, slept = 0; struct fw_pkt *fp; + int err = 0, slept = 0; - FWDEV_READ_START; + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; + + if (DEV_FWMEM(dev)) + return physio(fw_strategy, NULL, dev, ioflag, minphys, uio); - d = (struct fw_drv1 *)dev->si_drv1; + d = (struct fw_drv1 *)sc->si_drv1; fc = d->fc; ir = d->ir; if (ir == NULL) - return (fw_read_async(d, uio, ioflag)); + return fw_read_async(d, uio, ioflag); if (ir->buf == NULL) - return (EIO); + return EIO; - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); readloop: if (ir->stproc == NULL) { /* iso bulkxfer */ ir->stproc = STAILQ_FIRST(&ir->stvalid); if (ir->stproc != NULL) { - s = splfw(); STAILQ_REMOVE_HEAD(&ir->stvalid, link); - splx(s); ir->queued = 0; } } @@ -421,129 +248,74 @@ readloop: if (slept == 0) { slept = 1; ir->flag |= FWXFERQ_WAKEUP; - err = fw_msleep(ir, FW_GMTX(fc), FWPRI, "fw_read", hz); + err = tsleep(ir, FWPRI, "fw_read", hz); ir->flag &= ~FWXFERQ_WAKEUP; if (err == 0) goto readloop; } else if (slept == 1) err = EIO; - FW_GUNLOCK(fc); + mutex_exit(&fc->fc_mtx); return err; - } else if(ir->stproc != NULL) { + } else if (ir->stproc != NULL) { /* iso bulkxfer */ - FW_GUNLOCK(fc); - fp = (struct fw_pkt *)fwdma_v_addr(ir->buf, - ir->stproc->poffset + ir->queued); - if(fc->irx_post != NULL) + mutex_exit(&fc->fc_mtx); + fp = (struct fw_pkt *)fwdma_v_addr(ir->buf, + ir->stproc->poffset + ir->queued); + if (fc->irx_post != NULL) fc->irx_post(fc, fp->mode.ld); - if(fp->mode.stream.len == 0){ - err = EIO; - return err; - } + if (fp->mode.stream.len == 0) + return EIO; err = uiomove((void *)fp, - fp->mode.stream.len + sizeof(uint32_t), uio); - ir->queued ++; - if(ir->queued >= ir->bnpacket){ - s = splfw(); + fp->mode.stream.len + sizeof(uint32_t), uio); + ir->queued++; + if (ir->queued >= ir->bnpacket) { STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link); - splx(s); fc->irx_enable(fc, ir->dmach); ir->stproc = NULL; } if (uio->uio_resid >= ir->psize) { slept = -1; - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); goto readloop; } - } + } else + mutex_exit(&fc->fc_mtx); return err; } -static int -fw_write_async(struct fw_drv1 *d, struct uio *uio, int ioflag) -{ - struct fw_xfer *xfer; - struct fw_pkt pkt; - const struct tcode_info *tinfo; - int err; - - memset(&pkt, 0, sizeof(struct fw_pkt)); - if ((err = uiomove((void *)&pkt, sizeof(uint32_t), uio))) - return (err); - tinfo = &d->fc->tcode[pkt.mode.hdr.tcode]; - if ((err = uiomove((char *)&pkt + sizeof(uint32_t), - tinfo->hdr_len - sizeof(uint32_t), uio))) - return (err); - - if ((xfer = fw_xfer_alloc_buf(M_FWXFER, uio->uio_resid, - PAGE_SIZE/*XXX*/)) == NULL) - return (ENOMEM); - - memcpy(&xfer->send.hdr, &pkt, sizeof(struct fw_pkt)); - xfer->send.pay_len = uio->uio_resid; - if (uio->uio_resid > 0) { - if ((err = uiomove((void *)&xfer->send.payload[0], - uio->uio_resid, uio))) - goto out; - } - - xfer->fc = d->fc; - xfer->sc = NULL; - xfer->hand = fw_xferwake; - xfer->send.spd = 2 /* XXX */; - - if ((err = fw_asyreq(xfer->fc, -1, xfer))) - goto out; - - if ((err = fw_xferwait(xfer))) - goto out; - - if (xfer->resp != 0) { - err = xfer->resp; - goto out; - } - - if (xfer->flag == FWXF_RCVD) { - FW_GLOCK(xfer->fc); - STAILQ_INSERT_TAIL(&d->rq, xfer, link); - FW_GUNLOCK(xfer->fc); - return (0); - } - -out: - fw_xfer_free(xfer); - return (err); -} - -FW_WRITE(fw) +int +fw_write(dev_t dev, struct uio *uio, int ioflag) { - FW_WRITE_START; - int err = 0; - int s, slept = 0; + struct firewire_softc *sc; + struct firewire_comm *fc; struct fw_drv1 *d; struct fw_pkt *fp; - struct firewire_comm *fc; struct fw_xferq *it; + int slept = 0, err = 0; + + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; + + if (DEV_FWMEM(dev)) + return physio(fw_strategy, NULL, dev, ioflag, minphys, uio); - FWDEV_WRITE_START; - d = (struct fw_drv1 *)dev->si_drv1; + d = (struct fw_drv1 *)sc->si_drv1; fc = d->fc; it = d->it; if (it == NULL) - return (fw_write_async(d, uio, ioflag)); + return fw_write_async(d, uio, ioflag); if (it->buf == NULL) - return (EIO); + return EIO; - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); isoloop: if (it->stproc == NULL) { it->stproc = STAILQ_FIRST(&it->stfree); if (it->stproc != NULL) { - s = splfw(); STAILQ_REMOVE_HEAD(&it->stfree, link); - splx(s); it->queued = 0; } else if (slept == 0) { slept = 1; @@ -552,7 +324,7 @@ isoloop: if (err) goto out; #endif - err = fw_msleep(it, FW_GMTX(fc), FWPRI, "fw_write", hz); + err = tsleep(it, FWPRI, "fw_write", hz); if (err) goto out; goto isoloop; @@ -561,76 +333,64 @@ isoloop: goto out; } } - FW_GUNLOCK(fc); + mutex_exit(&fc->fc_mtx); fp = (struct fw_pkt *)fwdma_v_addr(it->buf, - it->stproc->poffset + it->queued); + it->stproc->poffset + it->queued); err = uiomove((void *)fp, sizeof(struct fw_isohdr), uio); - err = uiomove((void *)fp->mode.stream.payload, - fp->mode.stream.len, uio); - it->queued ++; + if (err != 0) + return err; + err = + uiomove((void *)fp->mode.stream.payload, fp->mode.stream.len, uio); + it->queued++; if (it->queued >= it->bnpacket) { - s = splfw(); STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link); - splx(s); it->stproc = NULL; err = fc->itx_enable(fc, it->dmach); } if (uio->uio_resid >= sizeof(struct fw_isohdr)) { slept = 0; - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); goto isoloop; } return err; out: - FW_GUNLOCK(fc); + mutex_exit(&fc->fc_mtx); return err; } -static void -fw_hand(struct fw_xfer *xfer) -{ - struct fw_bind *fwb; - struct fw_drv1 *d; - - fwb = (struct fw_bind *)xfer->sc; - d = (struct fw_drv1 *)fwb->sc; - FW_GLOCK(xfer->fc); - STAILQ_INSERT_TAIL(&d->rq, xfer, link); - FW_GUNLOCK(xfer->fc); - wakeup(&d->rq); -} - -/* - * ioctl support. - */ -FW_IOCTL(fw) +int +fw_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *td) { - FW_IOCTL_START; + struct firewire_softc *sc; struct firewire_comm *fc; struct fw_drv1 *d; - int i, len, err = 0; struct fw_device *fwdev; struct fw_bind *fwb; struct fw_xferq *ir, *it; struct fw_xfer *xfer; struct fw_pkt *fp; struct fw_devinfo *devinfo; - void *ptr; - struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data; struct fw_asyreq *asyreq = (struct fw_asyreq *)data; struct fw_isochreq *ichreq = (struct fw_isochreq *)data; struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data; struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data; struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data; + int i, len, err = 0; + void *ptr; + + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; - FWDEV_IOCTL_START; + if (DEV_FWMEM(dev)) + return fwmem_ioctl(dev, cmd, data, flag, td); if (!data) - return(EINVAL); + return EINVAL; - d = (struct fw_drv1 *)dev->si_drv1; + d = (struct fw_drv1 *)sc->si_drv1; fc = d->fc; ir = d->ir; it = d->it; @@ -655,6 +415,7 @@ FW_IOCTL(fw) it->flag |= ((0x3 & ichreq->tag) << 6); d->it = it; break; + case FW_GTSTREAM: if (it != NULL) { ichreq->ch = it->flag & 0x3f; @@ -662,6 +423,7 @@ FW_IOCTL(fw) } else err = EINVAL; break; + case FW_SRSTREAM: if (ir == NULL) { i = fw_open_isodma(fc, /* tx */0); @@ -682,6 +444,7 @@ FW_IOCTL(fw) d->ir = ir; err = fc->irx_enable(fc, ir->dmach); break; + case FW_GRSTREAM: if (d->ir != NULL) { ichreq->ch = ir->flag & 0x3f; @@ -689,9 +452,11 @@ FW_IOCTL(fw) } else err = EINVAL; break; + case FW_SSTBUF: memcpy(&d->bufreq, ibufreq, sizeof(d->bufreq)); break; + case FW_GSTBUF: memset(&ibufreq->rx, 0, sizeof(ibufreq->rx)); if (ir != NULL) { @@ -706,6 +471,7 @@ FW_IOCTL(fw) ibufreq->tx.psize = it->psize; } break; + case FW_ASYREQ: { const struct tcode_info *tinfo; @@ -719,24 +485,27 @@ FW_IOCTL(fw) xfer = fw_xfer_alloc_buf(M_FWXFER, pay_len, PAGE_SIZE/*XXX*/); if (xfer == NULL) - return (ENOMEM); + return ENOMEM; switch (asyreq->req.type) { case FWASREQNODE: break; + case FWASREQEUI: - fwdev = fw_noderesolve_eui64(fc, - &asyreq->req.dst.eui); + fwdev = fw_noderesolve_eui64(fc, &asyreq->req.dst.eui); if (fwdev == NULL) { - fw_printf(fc->bdev, "cannot find node\n"); + aprint_error_dev(fc->bdev, + "cannot find node\n"); err = EINVAL; goto out; } fp->mode.hdr.dst = FWLOCALBUS | fwdev->dst; break; + case FWASRESTL: /* XXX what's this? */ break; + case FWASREQSTREAM: /* nothing to do */ break; @@ -744,8 +513,8 @@ FW_IOCTL(fw) memcpy((void *)&xfer->send.hdr, fp, tinfo->hdr_len); if (pay_len > 0) - bcopy((char *)fp + tinfo->hdr_len, - (void *)xfer->send.payload, pay_len); + memcpy((void *)xfer->send.payload, + (char *)fp + tinfo->hdr_len, pay_len); xfer->send.spd = asyreq->req.sped; xfer->hand = fw_xferwake; @@ -765,29 +534,31 @@ FW_IOCTL(fw) if (xfer->recv.hdr.mode.hdr.tcode == FWTCODE_RRESB || xfer->recv.hdr.mode.hdr.tcode == FWTCODE_LRES) { pay_len = xfer->recv.pay_len; - if (asyreq->req.len >= xfer->recv.pay_len + tinfo->hdr_len) { - asyreq->req.len = xfer->recv.pay_len + - tinfo->hdr_len; - } else { + if (asyreq->req.len >= + xfer->recv.pay_len + tinfo->hdr_len) + asyreq->req.len = + xfer->recv.pay_len + tinfo->hdr_len; + else { err = EINVAL; pay_len = 0; } - } else { + } else pay_len = 0; - } memcpy(fp, &xfer->recv.hdr, tinfo->hdr_len); - memcpy((char *)fp + tinfo->hdr_len, xfer->recv.payload, pay_len); + memcpy((char *)fp + tinfo->hdr_len, xfer->recv.payload, + pay_len); out: fw_xfer_free_buf(xfer); break; } + case FW_IBUSRST: fc->ibr(fc); break; + case FW_CBINDADDR: - fwb = fw_bindlookup(fc, - bindreq->start.hi, bindreq->start.lo); - if(fwb == NULL){ + fwb = fw_bindlookup(fc, bindreq->start.hi, bindreq->start.lo); + if (fwb == NULL) { err = EINVAL; break; } @@ -796,17 +567,19 @@ out: fw_xferlist_remove(&fwb->xferlist); free(fwb, M_FW); break; + case FW_SBINDADDR: - if(bindreq->len <= 0 ){ + if (bindreq->len <= 0 ) { err = EINVAL; break; } - if(bindreq->start.hi > 0xffff ){ + if (bindreq->start.hi > 0xffff ) { err = EINVAL; break; } - fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_WAITOK); - if(fwb == NULL){ + fwb = (struct fw_bind *)malloc(sizeof(struct fw_bind), + M_FW, M_WAITOK); + if (fwb == NULL) { err = ENOMEM; break; } @@ -819,25 +592,25 @@ out: if (err == 0) { fw_xferlist_add(&fwb->xferlist, M_FWXFER, /* XXX */ - PAGE_SIZE, PAGE_SIZE, 5, - fc, (void *)fwb, fw_hand); + PAGE_SIZE, PAGE_SIZE, 5, fc, (void *)fwb, fw_hand); STAILQ_INSERT_TAIL(&d->binds, fwb, chlist); } break; + case FW_GDEVLST: i = len = 1; /* myself */ - devinfo = &fwdevlst->dev[0]; + devinfo = fwdevlst->dev; devinfo->dst = fc->nodeid; devinfo->status = 0; /* XXX */ devinfo->eui.hi = fc->eui.hi; devinfo->eui.lo = fc->eui.lo; STAILQ_FOREACH(fwdev, &fc->devices, link) { - if(len < FW_MAX_DEVLST){ + if (len < FW_MAX_DEVLST) { devinfo = &fwdevlst->dev[len++]; devinfo->dst = fwdev->dst; - devinfo->status = - (fwdev->status == FWDEVINVAL)?0:1; + devinfo->status = + (fwdev->status == FWDEVINVAL) ? 0 : 1; devinfo->eui.hi = fwdev->eui.hi; devinfo->eui.lo = fwdev->eui.lo; } @@ -846,10 +619,12 @@ out: fwdevlst->n = i; fwdevlst->info_len = len; break; + case FW_GTPMAP: memcpy(data, fc->topology_map, - (fc->topology_map->crc_len + 1) * 4); + (fc->topology_map->crc_len + 1) * 4); break; + case FW_GCROM: STAILQ_FOREACH(fwdev, &fc->devices, link) if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui)) @@ -863,11 +638,10 @@ out: ptr = malloc(CROMSIZE, M_FW, M_WAITOK); len = CROMSIZE; for (i = 0; i < CROMSIZE/4; i++) - ((uint32_t *)ptr)[i] - = ntohl(fc->config_rom[i]); + ((uint32_t *)ptr)[i] = ntohl(fc->config_rom[i]); } else { /* found */ - ptr = (void *)&fwdev->csrrom[0]; + ptr = (void *)fwdev->csrrom; if (fwdev->rommax < CSRROMOFF) len = 0; else @@ -882,23 +656,26 @@ out: /* myself */ free(ptr, M_FW); break; + default: - FWDEV_IOCTL_REDIRECT; + fc->ioctl(dev, cmd, data, flag, td); break; } return err; } -FW_POLL(fw) +int +fw_poll(dev_t dev, int events, struct lwp *td) { - FW_POLL_START; + struct firewire_softc *sc; struct fw_xferq *ir; - int revents; - int tmp; + int revents, tmp; - FWDEV_POLL_START; + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; - ir = ((struct fw_drv1 *)dev->si_drv1)->ir; + ir = ((struct fw_drv1 *)sc->si_drv1)->ir; revents = 0; tmp = POLLIN | POLLRDNORM; if (events & tmp) { @@ -908,19 +685,21 @@ FW_POLL(fw) selrecord(td, &ir->rsel); } tmp = POLLOUT | POLLWRNORM; - if (events & tmp) { - /* XXX should be fixed */ + if (events & tmp) + /* XXX should be fixed */ revents |= tmp; - } return revents; } -FW_MMAP(fw) -{ - FW_MMAP_START; +paddr_t +fw_mmap(dev_t dev, off_t offset, int nproto) +{ + struct firewire_softc *sc; - FWDEV_MMAP_START; + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; return EINVAL; } @@ -928,109 +707,196 @@ FW_MMAP(fw) void fw_strategy(struct bio *bp) { - FW_STRATEGY_START; + struct firewire_softc *sc; + dev_t dev = bp->bio_dev; - FWDEV_STRATEGY_START; + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return; + + if (DEV_FWMEM(dev)) { + fwmem_strategy(bp); + return; + } bp->bio_error = EOPNOTSUPP; bp->bio_resid = bp->bio_bcount; biodone(bp); } -#if defined(__FreeBSD__) -int -fwdev_makedev(struct firewire_softc *sc) + +static int +fwdev_allocbuf(struct firewire_comm *fc, struct fw_xferq *q, + struct fw_bufspec *b) { - int err = 0; + int i; -#if defined(__DragonFly__) - int unit; - - unit = fw_get_unit(sc->fc->bdev); - cdevsw_add(&firewire_cdevsw, FW_UNITMASK, FW_UNIT(unit)); -#elif __FreeBSD_version < 500000 - cdevsw_add(&firewire_cdevsw); -#else - fw_dev_t d; - int unit; - - unit = fw_get_unit(sc->fc->bdev); - sc->dev = make_dev(&firewire_cdevsw, MAKEMINOR(0, unit, 0), - UID_ROOT, GID_OPERATOR, 0660, - "fw%d.%d", unit, 0); - d = make_dev(&firewire_cdevsw, - MAKEMINOR(FWMEM_FLAG, unit, 0), - UID_ROOT, GID_OPERATOR, 0660, - "fwmem%d.%d", unit, 0); - dev_depends(sc->dev, d); - make_dev_alias(sc->dev, "fw%d", unit); - make_dev_alias(d, "fwmem%d", unit); -#endif + if (q->flag & (FWXFERQ_RUNNING | FWXFERQ_EXTBUF)) + return EBUSY; + + q->bulkxfer = + (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * b->nchunk, + M_FW, M_WAITOK); + if (q->bulkxfer == NULL) + return ENOMEM; + + b->psize = roundup2(b->psize, sizeof(uint32_t)); + q->buf = fwdma_malloc_multiseg(fc, sizeof(uint32_t), b->psize, + b->nchunk * b->npacket, BUS_DMA_WAITOK); + + if (q->buf == NULL) { + free(q->bulkxfer, M_FW); + q->bulkxfer = NULL; + return ENOMEM; + } + q->bnchunk = b->nchunk; + q->bnpacket = b->npacket; + q->psize = (b->psize + 3) & ~3; + q->queued = 0; + + STAILQ_INIT(&q->stvalid); + STAILQ_INIT(&q->stfree); + STAILQ_INIT(&q->stdma); + q->stproc = NULL; + + for (i = 0 ; i < q->bnchunk; i++) { + q->bulkxfer[i].poffset = i * q->bnpacket; + q->bulkxfer[i].mbuf = NULL; + STAILQ_INSERT_TAIL(&q->stfree, &q->bulkxfer[i], link); + } + + q->flag &= ~FWXFERQ_MODEMASK; + q->flag |= FWXFERQ_STREAM; + q->flag |= FWXFERQ_EXTBUF; - return (err); + return 0; } -int -fwdev_destroydev(struct firewire_softc *sc) +static int +fwdev_freebuf(struct fw_xferq *q) { + + if (q->flag & FWXFERQ_EXTBUF) { + if (q->buf != NULL) + fwdma_free_multiseg(q->buf); + q->buf = NULL; + free(q->bulkxfer, M_FW); + q->bulkxfer = NULL; + q->flag &= ~FWXFERQ_EXTBUF; + q->psize = 0; + q->maxq = FWMAXQUEUE; + } + return 0; +} + +static int +fw_read_async(struct fw_drv1 *d, struct uio *uio, int ioflag) +{ + struct fw_xfer *xfer; + struct fw_bind *fwb; + struct fw_pkt *fp; + const struct tcode_info *tinfo; int err = 0; -#if defined(__DragonFly__) - int unit; + mutex_enter(&d->fc->fc_mtx); + while ((xfer = STAILQ_FIRST(&d->rq)) == NULL && err == 0) + err = tsleep(&d->rq, FWPRI, "fwra", 0); + + if (err != 0) { + mutex_exit(&d->fc->fc_mtx); + return err; + } - unit = fw_get_unit(sc->fc->bdev); - cdevsw_remove(&firewire_cdevsw, FW_UNITMASK, FW_UNIT(unit)); -#elif __FreeBSD_version < 500000 - cdevsw_remove(&firewire_cdevsw); -#else - destroy_dev(sc->dev); + STAILQ_REMOVE_HEAD(&d->rq, link); + mutex_exit(&d->fc->fc_mtx); + fp = &xfer->recv.hdr; +#if 0 /* for GASP ?? */ + if (fc->irx_post != NULL) + fc->irx_post(fc, fp->mode.ld); #endif - return (err); + tinfo = &xfer->fc->tcode[fp->mode.hdr.tcode]; + err = uiomove((void *)fp, tinfo->hdr_len, uio); + if (err) + goto out; + err = uiomove((void *)xfer->recv.payload, xfer->recv.pay_len, uio); + +out: + /* recycle this xfer */ + fwb = (struct fw_bind *)xfer->sc; + fw_xfer_unload(xfer); + xfer->recv.pay_len = PAGE_SIZE; + mutex_enter(&d->fc->fc_mtx); + STAILQ_INSERT_TAIL(&fwb->xferlist, xfer, link); + mutex_exit(&d->fc->fc_mtx); + return err; } -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 -#define NDEVTYPE 2 -void -fwdev_clone(void *arg, struct ucred *cred, char *name, int namelen, - struct cdev **dev) +static int +fw_write_async(struct fw_drv1 *d, struct uio *uio, int ioflag) { - struct firewire_softc *sc; - char *devnames[NDEVTYPE] = {"fw", "fwmem"}; - char *subp = NULL; - int devflag[NDEVTYPE] = {0, FWMEM_FLAG}; - int i, unit = 0, sub = 0; + struct fw_xfer *xfer; + struct fw_pkt pkt; + const struct tcode_info *tinfo; + int err; - if (*dev != NULL) - return; + memset(&pkt, 0, sizeof(struct fw_pkt)); + if ((err = uiomove((void *)&pkt, sizeof(uint32_t), uio))) + return err; + tinfo = &d->fc->tcode[pkt.mode.hdr.tcode]; + if ((err = uiomove((char *)&pkt + sizeof(uint32_t), + tinfo->hdr_len - sizeof(uint32_t), uio))) + return err; - for (i = 0; i < NDEVTYPE; i++) - if (dev_stdclone(name, &subp, devnames[i], &unit) == 2) - goto found; - /* not match */ - return; -found: + if ((xfer = fw_xfer_alloc_buf(M_FWXFER, uio->uio_resid, + PAGE_SIZE/*XXX*/)) == NULL) + return ENOMEM; - if (subp == NULL || *subp++ != '.') - return; + memcpy(&xfer->send.hdr, &pkt, sizeof(struct fw_pkt)); + xfer->send.pay_len = uio->uio_resid; + if (uio->uio_resid > 0) { + if ((err = + uiomove((void *)xfer->send.payload, uio->uio_resid, uio))) + goto out; + } + + xfer->fc = d->fc; + xfer->sc = NULL; + xfer->hand = fw_xferwake; + xfer->send.spd = 2 /* XXX */; + + if ((err = fw_asyreq(xfer->fc, -1, xfer))) + goto out; + + if ((err = fw_xferwait(xfer))) + goto out; + + if (xfer->resp != 0) { + err = xfer->resp; + goto out; + } - /* /dev/fwU.S */ - while (isdigit(*subp)) { - sub *= 10; - sub += *subp++ - '0'; + if (xfer->flag == FWXF_RCVD) { + mutex_enter(&xfer->fc->fc_mtx); + STAILQ_INSERT_TAIL(&d->rq, xfer, link); + mutex_exit(&xfer->fc->fc_mtx); + return 0; } - if (*subp != '\0') - return; - sc = devclass_get_softc(firewire_devclass, unit); - if (sc == NULL) - return; - *dev = make_dev(&firewire_cdevsw, MAKEMINOR(devflag[i], unit, sub), - UID_ROOT, GID_OPERATOR, 0660, - "%s%d.%d", devnames[i], unit, sub); - dev_ref(*dev); - (*dev)->si_flags |= SI_CHEAPCLONE; - dev_depends(sc->dev, *dev); - return; +out: + fw_xfer_free(xfer); + return err; +} + +static void +fw_hand(struct fw_xfer *xfer) +{ + struct fw_bind *fwb; + struct fw_drv1 *d; + + fwb = (struct fw_bind *)xfer->sc; + d = (struct fw_drv1 *)fwb->sc; + mutex_enter(&xfer->fc->fc_mtx); + STAILQ_INSERT_TAIL(&d->rq, xfer, link); + mutex_exit(&xfer->fc->fc_mtx); + wakeup(&d->rq); } -#endif -#endif diff --git a/sys/dev/ieee1394/fwdma.c b/sys/dev/ieee1394/fwdma.c index dac1598db2e..7357d6f2d34 100644 --- a/sys/dev/ieee1394/fwdma.c +++ b/sys/dev/ieee1394/fwdma.c @@ -1,8 +1,8 @@ -/* $NetBSD: fwdma.c,v 1.12 2008/01/04 21:17:59 ad Exp $ */ +/* $NetBSD: fwdma.c,v 1.13 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2003 * Hidetoshi Shimokawa. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,156 +31,112 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fwdma.c,v 1.12 2008/01/04 21:17:59 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fwdma.c,v 1.13 2010/03/29 03:05:27 kiyohara Exp $"); #if defined(__FreeBSD__) __FBSDID("$FreeBSD: src/sys/dev/firewire/fwdma.c,v 1.9 2007/06/06 14:31:36 simokawa Exp $"); #endif -#if defined(__FreeBSD__) #include <sys/param.h> -#include <sys/systm.h> -#include <sys/types.h> -#include <sys/kernel.h> -#include <sys/conf.h> -#include <sys/malloc.h> -#if defined(__FreeBSD__) && __FreeBSD_version >= 501102 -#include <sys/mutex.h> -#endif - #include <sys/bus.h> -#include <sys/bus.h> - -#ifdef __DragonFly__ -#include <bus/firewire/fw_port.h> -#include <bus/firewire/firewire.h> -#include <bus/firewire/firewirereg.h> -#include <bus/firewire/fwdma.h> -#else -#include <dev/firewire/fw_port.h> -#include <dev/firewire/firewire.h> -#include <dev/firewire/firewirereg.h> -#include <dev/firewire/fwdma.h> -#endif -#elif defined(__NetBSD__) -#include <sys/param.h> #include <sys/device.h> #include <sys/systm.h> #include <sys/types.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/select.h> -#include <sys/bus.h> +#include <machine/vmparam.h> -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/firewirereg.h> #include <dev/ieee1394/fwdma.h> -#endif -static void -fwdma_map_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - bus_addr_t *baddr; +#define BUS_SPACE_MAXSIZE_32BIT 0xffffffff - if (error) - printf("fwdma_map_cb: error=%d\n", error); - baddr = (bus_addr_t *)arg; - *baddr = segs->ds_addr; -} void * -fwdma_malloc(struct firewire_comm *fc, int alignment, bus_size_t size, - struct fwdma_alloc *dma, int flag) +fwdma_malloc(device_t dev, bus_dma_tag_t dmat, bus_dmamap_t *dmamap, + bus_size_t size, int alignment, int flags) { + bus_dma_segment_t segs; + int nsegs; int err; + void *v_addr; - dma->v_addr = NULL; - err = fw_bus_dma_tag_create( - /*parent*/ fc->dmat, - /*alignment*/ alignment, - /*boundary*/ 0, - /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/ BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/ size, - /*nsegments*/ 1, - /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, - /*flags*/ BUS_DMA_ALLOCNOW, - /*lockfunc*/busdma_lock_mutex, - /*lockarg*/FW_GMTX(fc), - &dma->fw_dma_tag); + err = bus_dmamem_alloc(dmat, size, alignment, 0, &segs, 1, + &nsegs, flags); if (err) { - printf("fwdma_malloc: failed(1)\n"); - return(NULL); + aprint_error_dev(dev, "DMA memory allocation failed %d\n", err); + return NULL; } - err = fw_bus_dmamem_alloc(dma->fw_dma_tag, &dma->v_addr, - flag, &dma->dma_map); + err = bus_dmamem_map(dmat, &segs, nsegs, size, &v_addr, flags); if (err) { - printf("fwdma_malloc: failed(2)\n"); - fw_bus_dma_tag_destroy(dma->fw_dma_tag); - return(NULL); + aprint_error_dev(dev, "DMA memory map failed %d\n", err); + bus_dmamem_free(dmat, &segs, nsegs); + return NULL; + } + + if (*dmamap == NULL) { + err = bus_dmamap_create(dmat, size, nsegs, + BUS_SPACE_MAXSIZE_32BIT, 0, flags, dmamap); + if (err) { + aprint_error_dev(dev, + "DMA map create failed %d\n", err); + bus_dmamem_unmap(dmat, v_addr, size); + bus_dmamem_free(dmat, &segs, nsegs); + return NULL; + } } - err = fw_bus_dmamap_load(dma->fw_dma_tag, dma->dma_map, dma->v_addr, - size, fwdma_map_cb, &dma->bus_addr, flag); + err = bus_dmamap_load(dmat, *dmamap, v_addr, size, NULL, flags); if (err != 0) { - printf("fwdma_malloc: failed(3)\n"); - fw_bus_dmamem_free(dma->fw_dma_tag, dma->v_addr, dma->dma_map); - fw_bus_dma_tag_destroy(dma->fw_dma_tag); - return(NULL); + aprint_error_dev(dev, "DMA map load failed %d\n", err); + bus_dmamap_destroy(dmat, *dmamap); + bus_dmamem_unmap(dmat, v_addr, size); + bus_dmamem_free(dmat, &segs, nsegs); + return NULL; } - return(dma->v_addr); + return v_addr; } void -fwdma_free(struct firewire_comm *fc, struct fwdma_alloc *dma) +fwdma_free(bus_dma_tag_t dmat, bus_dmamap_t dmamap, void *vaddr) { - fw_bus_dmamap_unload(dma->fw_dma_tag, dma->dma_map); - fw_bus_dmamem_free(dma->fw_dma_tag, dma->v_addr, dma->dma_map); - fw_bus_dma_tag_destroy(dma->fw_dma_tag); + + bus_dmamap_unload(dmat, dmamap); + bus_dmamem_unmap(dmat, vaddr, dmamap->dm_mapsize); + bus_dmamem_free(dmat, dmamap->dm_segs, dmamap->dm_nsegs); + bus_dmamap_destroy(dmat, dmamap); } void * -fwdma_malloc_size(fw_bus_dma_tag_t dmat, bus_dmamap_t *dmamap, - bus_size_t size, bus_addr_t *bus_addr, int flag) +fwdma_alloc_setup(device_t dev, bus_dma_tag_t dmat, bus_size_t size, + struct fwdma_alloc *dma, int alignment, int flags) { - void *v_addr; - if (fw_bus_dmamem_alloc(dmat, &v_addr, flag, dmamap)) { - printf("fwdma_malloc_size: failed(1)\n"); - return(NULL); + dma->v_addr = + fwdma_malloc(dev, dmat, &dma->dma_map, size, alignment, flags); + if (dma->v_addr != NULL) { + dma->dma_tag = dmat; + dma->bus_addr = dma->dma_map->dm_segs[0].ds_addr; } - if (fw_bus_dmamap_load(dmat, *dmamap, v_addr, size, - fwdma_map_cb, bus_addr, flag)) { - printf("fwdma_malloc_size: failed(2)\n"); - fw_bus_dmamem_free(dmat, v_addr, *dmamap); - return(NULL); - } - return(v_addr); + return dma->v_addr; } -void -fwdma_free_size(fw_bus_dma_tag_t dmat, bus_dmamap_t dmamap, void *vaddr, - bus_size_t size) -{ - fw_bus_dmamap_unload(dmat, dmamap); - fw_bus_dmamem_free(dmat, vaddr, dmamap); -} - /* * Allocate multisegment dma buffers * each segment size is eqaul to ssize except last segment. */ struct fwdma_alloc_multi * -fwdma_malloc_multiseg(struct firewire_comm *fc, int alignment, - int esize, int n, int flag) +fwdma_malloc_multiseg(struct firewire_comm *fc, int alignment, int esize, int n, + int flags) { struct fwdma_alloc_multi *am; struct fwdma_seg *seg; @@ -196,55 +152,32 @@ fwdma_malloc_multiseg(struct firewire_comm *fc, int alignment, ssize = rounddown(PAGE_SIZE, esize); nseg = howmany(n, ssize / esize); } - size = sizeof (struct fwdma_alloc_multi) + - sizeof (struct fwdma_seg) * nseg; + size = sizeof(struct fwdma_alloc_multi) + + sizeof(struct fwdma_seg) * nseg; am = (struct fwdma_alloc_multi *)malloc(size, M_FW, M_WAITOK); if (am == NULL) { - printf("fwdma_malloc_multiseg: malloc failed\n"); - return(NULL); + aprint_error_dev(fc->dev, "malloc failed\n"); + return NULL; } memset(am, 0, size); am->ssize = ssize; am->esize = esize; am->nseg = 0; - if (fw_bus_dma_tag_create( - /*parent*/ fc->dmat, - /*alignment*/ alignment, - /*boundary*/ 0, - /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/ BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/ ssize, - /*nsegments*/ 1, - /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, - /*flags*/ BUS_DMA_ALLOCNOW, - /*lockfunc*/busdma_lock_mutex, - /*lockarg*/FW_GMTX(fc), - &am->fw_dma_tag)) { - printf("fwdma_malloc_multiseg: tag_create failed\n"); - free(am, M_FW); - return(NULL); - } + am->dma_tag = fc->dmat; -#if 0 -#if defined(__DragonFly__) || __FreeBSD_version < 500000 - printf("malloc_multi: ssize=%d nseg=%d\n", ssize, nseg); -#else - printf("malloc_multi: ssize=%td nseg=%d\n", ssize, nseg); -#endif -#endif - for (seg = &am->seg[0]; nseg --; seg ++) { - seg->v_addr = fwdma_malloc_size(am->fw_dma_tag, &seg->dma_map, - ssize, &seg->bus_addr, flag); + for (seg = am->seg; nseg--; seg++) { + seg->v_addr = fwdma_malloc(fc->dev, am->dma_tag, &seg->dma_map, + ssize, alignment, flags); if (seg->v_addr == NULL) { - printf("fwdma_malloc_multi: malloc_size failed %d\n", - am->nseg); + aprint_error_dev(fc->dev, "malloc_size failed %d\n", + am->nseg); fwdma_free_multiseg(am); - return(NULL); + return NULL; } + seg->bus_addr = seg->dma_map->dm_segs[0].ds_addr; am->nseg++; } - return(am); + return am; } void @@ -252,10 +185,7 @@ fwdma_free_multiseg(struct fwdma_alloc_multi *am) { struct fwdma_seg *seg; - for (seg = &am->seg[0]; am->nseg --; seg ++) { - fwdma_free_size(am->fw_dma_tag, seg->dma_map, - seg->v_addr, am->ssize); - } - fw_bus_dma_tag_destroy(am->fw_dma_tag); + for (seg = am->seg; am->nseg--; seg++) + fwdma_free(am->dma_tag, seg->dma_map, seg->v_addr); free(am, M_FW); } diff --git a/sys/dev/ieee1394/fwdma.h b/sys/dev/ieee1394/fwdma.h index e349db4b420..c558fea3256 100644 --- a/sys/dev/ieee1394/fwdma.h +++ b/sys/dev/ieee1394/fwdma.h @@ -1,8 +1,8 @@ -/* $NetBSD: fwdma.h,v 1.5 2007/03/04 06:02:05 christos Exp $ */ +/* $NetBSD: fwdma.h,v 1.6 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (C) 2003 * Hidetoshi Shimokawa. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,12 +31,15 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/fwdma.h,v 1.3 2005/01/06 01:42:41 imp Exp $ */ +#ifndef _FWDMA_H_ +#define _FWDMA_H_ + struct fwdma_alloc { - fw_bus_dma_tag_t fw_dma_tag; + bus_dma_tag_t dma_tag; bus_dmamap_t dma_map; void * v_addr; bus_addr_t bus_addr; @@ -52,7 +55,7 @@ struct fwdma_alloc_multi { bus_size_t ssize; bus_size_t esize; int nseg; - fw_bus_dma_tag_t fw_dma_tag; + bus_dma_tag_t dma_tag; struct fwdma_seg seg[0]; }; @@ -62,7 +65,7 @@ fwdma_v_addr(struct fwdma_alloc_multi *am, int index) bus_size_t ssize = am->ssize; int offset = am->esize * index; - return ((char *)am->seg[offset / ssize].v_addr + (offset % ssize)); + return (char *)am->seg[offset / ssize].v_addr + (offset % ssize); } static __inline bus_addr_t @@ -71,44 +74,56 @@ fwdma_bus_addr(struct fwdma_alloc_multi *am, int index) bus_size_t ssize = am->ssize; int offset = am->esize * index; - return (am->seg[offset / ssize].bus_addr + (offset % ssize)); + return am->seg[offset / ssize].bus_addr + (offset % ssize); } static __inline void -fwdma_sync(struct fwdma_alloc *dma, bus_dmasync_op_t op) -{ - fw_bus_dmamap_sync(dma->fw_dma_tag, dma->dma_map, op); -} - -static __inline void -fwdma_sync_multiseg(struct fwdma_alloc_multi *am, - int start, int end, bus_dmasync_op_t op) +fwdma_sync_multiseg(struct fwdma_alloc_multi *am, int start, int end, int op) { struct fwdma_seg *seg, *eseg; + bus_addr_t off, eoff; + off = (am->esize * start) % am->ssize; + eoff = (am->esize * end) % am->ssize; seg = &am->seg[am->esize * start / am->ssize]; eseg = &am->seg[am->esize * end / am->ssize]; - for (; seg <= eseg; seg ++) - fw_bus_dmamap_sync(am->fw_dma_tag, seg->dma_map, op); + + if (start > end) { + for (; seg < &am->seg[am->nseg]; seg++) { + bus_dmamap_sync(am->dma_tag, seg->dma_map, + off, seg->dma_map->dm_mapsize - off, op); + off = 0; + } + seg = am->seg; + } + for (; seg < eseg; seg++) { + bus_dmamap_sync(am->dma_tag, seg->dma_map, + off, seg->dma_map->dm_mapsize - off, op); + off = 0; + } + bus_dmamap_sync(am->dma_tag, seg->dma_map, + off, eoff - off + am->esize, op); } static __inline void -fwdma_sync_multiseg_all(struct fwdma_alloc_multi *am, bus_dmasync_op_t op) +fwdma_sync_multiseg_all(struct fwdma_alloc_multi *am, int op) { struct fwdma_seg *seg; int i; - seg = &am->seg[0]; + seg = am->seg; for (i = 0; i < am->nseg; i++, seg++) - fw_bus_dmamap_sync(am->fw_dma_tag, seg->dma_map, op); + bus_dmamap_sync(am->dma_tag, seg->dma_map, + 0, seg->dma_map->dm_mapsize, op); } -void *fwdma_malloc(struct firewire_comm *, int, bus_size_t, struct fwdma_alloc *, int); -void fwdma_free(struct firewire_comm *, struct fwdma_alloc *); -void *fwdma_malloc_size( - fw_bus_dma_tag_t, bus_dmamap_t *, bus_size_t, bus_addr_t *, int); -void fwdma_free_size(fw_bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t); +void *fwdma_malloc(device_t, bus_dma_tag_t, bus_dmamap_t *, bus_size_t, int, + int); +void fwdma_free(bus_dma_tag_t, bus_dmamap_t, void *); +void *fwdma_alloc_setup(device_t, bus_dma_tag_t, bus_size_t, + struct fwdma_alloc *, int, int); struct fwdma_alloc_multi *fwdma_malloc_multiseg(struct firewire_comm *, - int, int, int, int); + int, int, int, int); void fwdma_free_multiseg(struct fwdma_alloc_multi *); +#endif /* _FWDMA_H_ */ diff --git a/sys/dev/ieee1394/fwmem.c b/sys/dev/ieee1394/fwmem.c index 74c691d881f..2bd9955945e 100644 --- a/sys/dev/ieee1394/fwmem.c +++ b/sys/dev/ieee1394/fwmem.c @@ -1,8 +1,8 @@ -/* $NetBSD: fwmem.c,v 1.11 2009/04/18 14:58:02 tsutsui Exp $ */ +/* $NetBSD: fwmem.c,v 1.12 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2002-2003 * Hidetoshi Shimokawa. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,87 +31,38 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fwmem.c,v 1.11 2009/04/18 14:58:02 tsutsui Exp $"); -#if defined(__FreeBSD__) -__FBSDID("$FreeBSD: src/sys/dev/firewire/fwmem.c,v 1.34 2007/06/06 14:31:36 simokawa Exp $"); -#endif +__KERNEL_RCSID(0, "$NetBSD: fwmem.c,v 1.12 2010/03/29 03:05:27 kiyohara Exp $"); -#if defined(__FreeBSD__) -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/types.h> - -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/conf.h> -#include <sys/sysctl.h> -#if defined(__DragonFly__) || __FreeBSD_version < 500000 -#include <sys/buf.h> -#else -#include <sys/bio.h> -#endif - -#include <sys/bus.h> -#include <sys/bus.h> - -#include <sys/signal.h> -#include <sys/mman.h> -#include <sys/ioccom.h> -#include <sys/fcntl.h> -#include <sys/ktr.h> - -#ifdef __DragonFly__ -#include "fw_port.h" -#include "firewire.h" -#include "firewirereg.h" -#include "fwmem.h" -#else -#include <dev/firewire/fw_port.h> -#include <dev/firewire/firewire.h> -#include <dev/firewire/firewirereg.h> -#include <dev/firewire/fwmem.h> -#endif -#elif defined(__NetBSD__) #include <sys/param.h> #include <sys/device.h> #include <sys/errno.h> #include <sys/buf.h> +#include <sys/bus.h> #include <sys/conf.h> #include <sys/fcntl.h> #include <sys/malloc.h> #include <sys/sysctl.h> -#include <sys/bus.h> - -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/firewirereg.h> #include <dev/ieee1394/fwmem.h> -#endif + +#include "ioconf.h" static int fwmem_speed=2, fwmem_debug=0; static struct fw_eui64 fwmem_eui64; -#if defined(__FreeBSD__) -SYSCTL_DECL(_hw_firewire); -SYSCTL_NODE(_hw_firewire, OID_AUTO, fwmem, CTLFLAG_RD, 0, - "FireWire Memory Access"); -SYSCTL_UINT(_hw_firewire_fwmem, OID_AUTO, eui64_hi, CTLFLAG_RW, - &fwmem_eui64.hi, 0, "Fwmem target EUI64 high"); -SYSCTL_UINT(_hw_firewire_fwmem, OID_AUTO, eui64_lo, CTLFLAG_RW, - &fwmem_eui64.lo, 0, "Fwmem target EUI64 low"); -SYSCTL_INT(_hw_firewire_fwmem, OID_AUTO, speed, CTLFLAG_RW, &fwmem_speed, 0, - "Fwmem link speed"); -SYSCTL_INT(_debug, OID_AUTO, fwmem_debug, CTLFLAG_RW, &fwmem_debug, 0, - "Fwmem driver debug flag"); -MALLOC_DEFINE(M_FWMEM, "fwmem", "fwmem/FireWire"); -#elif defined(__NetBSD__) + static int sysctl_fwmem_verify(SYSCTLFN_PROTO, int, int); static int sysctl_fwmem_verify_speed(SYSCTLFN_PROTO); +static struct fw_xfer *fwmem_xfer_req(struct fw_device *, void *, int, int, + int, void *); +static void fwmem_biodone(struct fw_xfer *); + /* * Setup sysctl(3) MIB, hw.fwmem.* * @@ -187,24 +138,24 @@ sysctl_fwmem_verify(SYSCTLFN_ARGS, int lower, int upper) node.sysctl_data = &t; error = sysctl_lookup(SYSCTLFN_CALL(&node)); if (error || newp == NULL) - return (error); + return error; if (t < lower || t > upper) - return (EINVAL); + return EINVAL; *(int*)rnode->sysctl_data = t; - return (0); + return 0; } -static int +static int sysctl_fwmem_verify_speed(SYSCTLFN_ARGS) { - return (sysctl_fwmem_verify(SYSCTLFN_CALL(rnode), 0, FWSPD_S400)); + + return sysctl_fwmem_verify(SYSCTLFN_CALL(rnode), 0, FWSPD_S400); } MALLOC_DEFINE(M_FWMEM, "fwmem", "fwmem/IEEE1394"); -#endif #define MAXLEN (512 << fwmem_speed) @@ -215,52 +166,175 @@ struct fwmem_softc { STAILQ_HEAD(, fw_xfer) xferlist; }; -static struct fw_xfer * -fwmem_xfer_req( - struct fw_device *fwdev, - void *sc, - int spd, - int slen, - int rlen, - void *hand) + +int +fwmem_open(dev_t dev, int flags, int fmt, struct lwp *td) { + struct firewire_softc *sc; + struct fwmem_softc *fms; struct fw_xfer *xfer; - xfer = fw_xfer_alloc(M_FWMEM); - if (xfer == NULL) - return NULL; + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; - xfer->fc = fwdev->fc; - xfer->send.hdr.mode.hdr.dst = FWLOCALBUS | fwdev->dst; - if (spd < 0) - xfer->send.spd = fwdev->speed; - else - xfer->send.spd = min(spd, fwdev->speed); - xfer->hand = hand; - xfer->sc = sc; - xfer->send.pay_len = slen; - xfer->recv.pay_len = rlen; + if (sc->si_drv1 != NULL) { + if ((flags & FWRITE) != 0) { + return EBUSY; + } + fms = (struct fwmem_softc *)sc->si_drv1; + fms->refcount++; + } else { + sc->si_drv1 = (void *)-1; + sc->si_drv1 = malloc(sizeof(struct fwmem_softc), + M_FWMEM, M_WAITOK); + if (sc->si_drv1 == NULL) + return ENOMEM; + fms = (struct fwmem_softc *)sc->si_drv1; + memcpy(&fms->eui, &fwmem_eui64, sizeof(struct fw_eui64)); + fms->sc = sc; + fms->refcount = 1; + STAILQ_INIT(&fms->xferlist); + xfer = fw_xfer_alloc(M_FWMEM); + STAILQ_INSERT_TAIL(&fms->xferlist, xfer, link); + } + if (fwmem_debug) + printf("%s: refcount=%d\n", __func__, fms->refcount); - return xfer; + return 0; +} + +int +fwmem_close(dev_t dev, int flags, int fmt, struct lwp *td) +{ + struct firewire_softc *sc; + struct fwmem_softc *fms; + struct fw_xfer *xfer; + + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; + + fms = (struct fwmem_softc *)sc->si_drv1; + + fms->refcount--; + if (fwmem_debug) + printf("%s: refcount=%d\n", __func__, fms->refcount); + if (fms->refcount < 1) { + while ((xfer = STAILQ_FIRST(&fms->xferlist)) != NULL) { + STAILQ_REMOVE_HEAD(&fms->xferlist, link); + fw_xfer_free(xfer); + } + free(sc->si_drv1, M_FW); + sc->si_drv1 = NULL; + } + + return 0; +} + +void +fwmem_strategy(struct bio *bp) +{ + struct firewire_softc *sc; + struct fwmem_softc *fms; + struct fw_device *fwdev; + struct fw_xfer *xfer; + dev_t dev = bp->bio_dev; + int iolen, err = 0, s; + + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return; + + /* XXX check request length */ + + s = splvm(); + fms = (struct fwmem_softc *)sc->si_drv1; + fwdev = fw_noderesolve_eui64(fms->sc->fc, &fms->eui); + if (fwdev == NULL) { + if (fwmem_debug) + printf("fwmem: no such device ID:%08x%08x\n", + fms->eui.hi, fms->eui.lo); + err = EINVAL; + goto error; + } + + iolen = MIN(bp->bio_bcount, MAXLEN); + if ((bp->bio_cmd & BIO_READ) == BIO_READ) { + if (iolen == 4 && (bp->bio_offset & 3) == 0) + xfer = fwmem_read_quad(fwdev, (void *) bp, fwmem_speed, + bp->bio_offset >> 32, bp->bio_offset & 0xffffffff, + bp->bio_data, fwmem_biodone); + else + xfer = fwmem_read_block(fwdev, (void *) bp, fwmem_speed, + bp->bio_offset >> 32, bp->bio_offset & 0xffffffff, + iolen, bp->bio_data, fwmem_biodone); + } else { + if (iolen == 4 && (bp->bio_offset & 3) == 0) + xfer = fwmem_write_quad(fwdev, (void *)bp, fwmem_speed, + bp->bio_offset >> 32, bp->bio_offset & 0xffffffff, + bp->bio_data, fwmem_biodone); + else + xfer = fwmem_write_block(fwdev, (void *)bp, fwmem_speed, + bp->bio_offset >> 32, bp->bio_offset & 0xffffffff, + iolen, bp->bio_data, fwmem_biodone); + } + if (xfer == NULL) { + err = EIO; + goto error; + } + /* XXX */ + bp->bio_resid = bp->bio_bcount - iolen; +error: + splx(s); + if (err != 0) { + if (fwmem_debug) + printf("%s: err=%d\n", __func__, err); + bp->bio_error = err; + bp->bio_resid = bp->bio_bcount; + biodone(bp); + } +} + +int +fwmem_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *td) +{ + struct firewire_softc *sc; + struct fwmem_softc *fms; + int err = 0; + + sc = device_lookup_private(&ieee1394if_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; + + fms = (struct fwmem_softc *)sc->si_drv1; + switch (cmd) { + case FW_SDEUI64: + memcpy(&fms->eui, data, sizeof(struct fw_eui64)); + break; + + case FW_GDEUI64: + memcpy(data, &fms->eui, sizeof(struct fw_eui64)); + break; + + default: + err = EINVAL; + } + return err; } + struct fw_xfer * -fwmem_read_quad( - struct fw_device *fwdev, - void * sc, - uint8_t spd, - uint16_t dst_hi, - uint32_t dst_lo, - void *data, - void (*hand)(struct fw_xfer *)) +fwmem_read_quad(struct fw_device *fwdev, void * sc, uint8_t spd, + uint16_t dst_hi, uint32_t dst_lo, void *data, + void (*hand)(struct fw_xfer *)) { struct fw_xfer *xfer; struct fw_pkt *fp; xfer = fwmem_xfer_req(fwdev, (void *)sc, spd, 0, 4, hand); - if (xfer == NULL) { + if (xfer == NULL) return NULL; - } fp = &xfer->send.hdr; fp->mode.rreqq.tcode = FWTCODE_RREQQ; @@ -271,8 +345,8 @@ fwmem_read_quad( xfer->recv.payload = (uint32_t *)data; if (fwmem_debug) - printf("fwmem_read_quad: %d %04x:%08x\n", fwdev->dst, - dst_hi, dst_lo); + aprint_error("fwmem_read_quad: %d %04x:%08x\n", + fwdev->dst, dst_hi, dst_lo); if (fw_asyreq(xfer->fc, -1, xfer) == 0) return xfer; @@ -282,14 +356,9 @@ fwmem_read_quad( } struct fw_xfer * -fwmem_write_quad( - struct fw_device *fwdev, - void * sc, - uint8_t spd, - uint16_t dst_hi, - uint32_t dst_lo, - void *data, - void (*hand)(struct fw_xfer *)) +fwmem_write_quad(struct fw_device *fwdev, void *sc, uint8_t spd, + uint16_t dst_hi, uint32_t dst_lo, void *data, + void (*hand)(struct fw_xfer *)) { struct fw_xfer *xfer; struct fw_pkt *fp; @@ -307,8 +376,8 @@ fwmem_write_quad( xfer->send.payload = xfer->recv.payload = NULL; if (fwmem_debug) - printf("fwmem_write_quad: %d %04x:%08x %08x\n", fwdev->dst, - dst_hi, dst_lo, *(uint32_t *)data); + aprint_error("fwmem_write_quad: %d %04x:%08x %08x\n", + fwdev->dst, dst_hi, dst_lo, *(uint32_t *)data); if (fw_asyreq(xfer->fc, -1, xfer) == 0) return xfer; @@ -318,19 +387,13 @@ fwmem_write_quad( } struct fw_xfer * -fwmem_read_block( - struct fw_device *fwdev, - void * sc, - uint8_t spd, - uint16_t dst_hi, - uint32_t dst_lo, - int len, - void *data, - void (*hand)(struct fw_xfer *)) +fwmem_read_block(struct fw_device *fwdev, void *sc, uint8_t spd, + uint16_t dst_hi, uint32_t dst_lo, int len, void *data, + void (*hand)(struct fw_xfer *)) { struct fw_xfer *xfer; struct fw_pkt *fp; - + xfer = fwmem_xfer_req(fwdev, sc, spd, 0, roundup2(len, 4), hand); if (xfer == NULL) return NULL; @@ -346,8 +409,8 @@ fwmem_read_block( xfer->recv.payload = data; if (fwmem_debug) - printf("fwmem_read_block: %d %04x:%08x %d\n", fwdev->dst, - dst_hi, dst_lo, len); + aprint_error("fwmem_read_block: %d %04x:%08x %d\n", + fwdev->dst, dst_hi, dst_lo, len); if (fw_asyreq(xfer->fc, -1, xfer) == 0) return xfer; @@ -356,15 +419,9 @@ fwmem_read_block( } struct fw_xfer * -fwmem_write_block( - struct fw_device *fwdev, - void * sc, - uint8_t spd, - uint16_t dst_hi, - uint32_t dst_lo, - int len, - void *data, - void (*hand)(struct fw_xfer *)) +fwmem_write_block(struct fw_device *fwdev, void *sc, uint8_t spd, + uint16_t dst_hi, uint32_t dst_lo, int len, void *data, + void (*hand)(struct fw_xfer *)) { struct fw_xfer *xfer; struct fw_pkt *fp; @@ -384,8 +441,8 @@ fwmem_write_block( xfer->recv.payload = NULL; if (fwmem_debug) - printf("fwmem_write_block: %d %04x:%08x %d\n", fwdev->dst, - dst_hi, dst_lo, len); + aprint_error("fwmem_write_block: %d %04x:%08x %d\n", + fwdev->dst, dst_hi, dst_lo, len); if (fw_asyreq(xfer->fc, -1, xfer) == 0) return xfer; @@ -394,68 +451,30 @@ fwmem_write_block( } -FW_OPEN(fwmem) -{ - struct fwmem_softc *fms; - struct fw_xfer *xfer; - FW_OPEN_START; - - if (dev->si_drv1 != NULL) { - if ((flags & FWRITE) != 0) { - FW_GUNLOCK(sc->fc); - return (EBUSY); - } - FW_GUNLOCK(sc->fc); - fms = (struct fwmem_softc *)dev->si_drv1; - fms->refcount ++; - } else { - dev->si_drv1 = (void *)-1; - FW_GUNLOCK(sc->fc); - dev->si_drv1 = malloc(sizeof(struct fwmem_softc), - M_FWMEM, M_WAITOK); - if (dev->si_drv1 == NULL) - return ENOMEM; - dev->si_iosize_max = DFLTPHYS; - fms = (struct fwmem_softc *)dev->si_drv1; - memcpy(&fms->eui, &fwmem_eui64, sizeof(struct fw_eui64)); - fms->sc = sc; - fms->refcount = 1; - STAILQ_INIT(&fms->xferlist); - xfer = fw_xfer_alloc(M_FWMEM); - STAILQ_INSERT_TAIL(&fms->xferlist, xfer, link); - } - if (fwmem_debug) - printf("%s: refcount=%d\n", __func__, fms->refcount); - - return (0); -} - -FW_CLOSE(fwmem) +static struct fw_xfer * +fwmem_xfer_req(struct fw_device *fwdev, void *sc, int spd, int slen, int rlen, + void *hand) { - struct fwmem_softc *fms; struct fw_xfer *xfer; - FW_CLOSE_START; - fms = (struct fwmem_softc *)dev->si_drv1; + xfer = fw_xfer_alloc(M_FWMEM); + if (xfer == NULL) + return NULL; - FW_GLOCK(fms->sc->fc); - fms->refcount --; - FW_GUNLOCK(fms->sc->fc); - if (fwmem_debug) - printf("%s: refcount=%d\n", __func__, fms->refcount); - if (fms->refcount < 1) { - while ((xfer = STAILQ_FIRST(&fms->xferlist)) != NULL) { - STAILQ_REMOVE_HEAD(&fms->xferlist, link); - fw_xfer_free(xfer); - } - free(dev->si_drv1, M_FW); - dev->si_drv1 = NULL; - } + xfer->fc = fwdev->fc; + xfer->send.hdr.mode.hdr.dst = FWLOCALBUS | fwdev->dst; + if (spd < 0) + xfer->send.spd = fwdev->speed; + else + xfer->send.spd = min(spd, fwdev->speed); + xfer->hand = hand; + xfer->sc = sc; + xfer->send.pay_len = slen; + xfer->recv.pay_len = rlen; - return (0); + return xfer; } - static void fwmem_biodone(struct fw_xfer *xfer) { @@ -470,104 +489,6 @@ fwmem_biodone(struct fw_xfer *xfer) bp->bio_resid = bp->bio_bcount; } - CTR0(KTR_DEV, "biodone0"); fw_xfer_free(xfer); - CTR0(KTR_DEV, "biodone1"); biodone(bp); - CTR0(KTR_DEV, "biodone2"); -} - -void -fwmem_strategy(struct bio *bp) -{ - FW_STRATEGY_START; - struct fwmem_softc *fms; - struct fw_device *fwdev; - struct fw_xfer *xfer; - int err = 0, s, iolen; - - CTR0(KTR_DEV, "strategy"); - - /* XXX check request length */ - - s = splfw(); - fms = (struct fwmem_softc *)dev->si_drv1; - fwdev = fw_noderesolve_eui64(fms->sc->fc, &fms->eui); - if (fwdev == NULL) { - if (fwmem_debug) - printf("fwmem: no such device ID:%08x%08x\n", - fms->eui.hi, fms->eui.lo); - err = EINVAL; - goto error; - } - - iolen = MIN(bp->bio_bcount, MAXLEN); - if ((bp->bio_cmd & BIO_READ) == BIO_READ) { - if (iolen == 4 && (bp->bio_offset & 3) == 0) - xfer = fwmem_read_quad(fwdev, - (void *) bp, fwmem_speed, - bp->bio_offset >> 32, bp->bio_offset & 0xffffffff, - bp->bio_data, fwmem_biodone); - else - xfer = fwmem_read_block(fwdev, - (void *) bp, fwmem_speed, - bp->bio_offset >> 32, bp->bio_offset & 0xffffffff, - iolen, bp->bio_data, fwmem_biodone); - } else { - if (iolen == 4 && (bp->bio_offset & 3) == 0) - xfer = fwmem_write_quad(fwdev, - (void *)bp, fwmem_speed, - bp->bio_offset >> 32, bp->bio_offset & 0xffffffff, - bp->bio_data, fwmem_biodone); - else - xfer = fwmem_write_block(fwdev, - (void *)bp, fwmem_speed, - bp->bio_offset >> 32, bp->bio_offset & 0xffffffff, - iolen, bp->bio_data, fwmem_biodone); - } - if (xfer == NULL) { - err = EIO; - goto error; - } - /* XXX */ - bp->bio_resid = bp->bio_bcount - iolen; -error: - splx(s); - if (err != 0) { - if (fwmem_debug) - printf("%s: err=%d\n", __func__, err); - bp->bio_error = err; - bp->bio_resid = bp->bio_bcount; - biodone(bp); - } -} - -FW_IOCTL(fwmem) -{ - FW_IOCTL_START; - struct fwmem_softc *fms; - int err = 0; - - fms = (struct fwmem_softc *)dev->si_drv1; - switch (cmd) { - case FW_SDEUI64: - memcpy(&fms->eui, data, sizeof(struct fw_eui64)); - break; - case FW_GDEUI64: - memcpy(data, &fms->eui, sizeof(struct fw_eui64)); - break; - default: - err = EINVAL; - } - return(err); -} - -FW_POLL(fwmem) -{ - return EINVAL; -} - -FW_MMAP(fwmem) -{ - return EINVAL; } diff --git a/sys/dev/ieee1394/fwmem.h b/sys/dev/ieee1394/fwmem.h index 1bb0094e19a..ca9aee2b699 100644 --- a/sys/dev/ieee1394/fwmem.h +++ b/sys/dev/ieee1394/fwmem.h @@ -1,8 +1,8 @@ -/* $NetBSD: fwmem.h,v 1.3 2007/03/04 06:02:05 christos Exp $ */ +/* $NetBSD: fwmem.h,v 1.4 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (C) 2002-2003 * Hidetoshi Shimokawa. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,35 +31,26 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/fwmem.h,v 1.8 2005/01/06 01:42:41 imp Exp $ */ +#ifndef _FWMEM_H_ +#define _FWMEM_H_ -struct fw_xfer *fwmem_read_quad(struct fw_device *, void *, uint8_t, - uint16_t, uint32_t, void *, void (*)(struct fw_xfer *)); -struct fw_xfer *fwmem_write_quad(struct fw_device *, void *, uint8_t, - uint16_t, uint32_t, void *, void (*)(struct fw_xfer *)); -struct fw_xfer *fwmem_read_block(struct fw_device *, void *, uint8_t, - uint16_t, uint32_t, int, void *, void (*)(struct fw_xfer *)); -struct fw_xfer *fwmem_write_block(struct fw_device *, void *, uint8_t, - uint16_t, uint32_t, int, void *, void (*)(struct fw_xfer *)); +struct fw_xfer *fwmem_read_quad(struct fw_device *, void *, uint8_t, uint16_t, + uint32_t, void *, void (*)(struct fw_xfer *)); +struct fw_xfer *fwmem_write_quad(struct fw_device *, void *, uint8_t, uint16_t, + uint32_t, void *, void (*)(struct fw_xfer *)); +struct fw_xfer *fwmem_read_block(struct fw_device *, void *, uint8_t, uint16_t, + uint32_t, int, void *, + void (*)(struct fw_xfer *)); +struct fw_xfer *fwmem_write_block(struct fw_device *, void *, uint8_t, uint16_t, + uint32_t, int, void *, + void (*)(struct fw_xfer *)); -#if defined(__FreeBSD__) -d_open_t fwmem_open; -d_close_t fwmem_close; -d_ioctl_t fwmem_ioctl; -d_read_t fwmem_read; -d_write_t fwmem_write; -d_poll_t fwmem_poll; -d_mmap_t fwmem_mmap; -d_strategy_t fwmem_strategy; -#elif defined(__NetBSD__) dev_type_open(fwmem_open); dev_type_close(fwmem_close); dev_type_ioctl(fwmem_ioctl); -dev_type_read(fwmem_read); -dev_type_write(fwmem_write); -dev_type_poll(fwmem_poll); -dev_type_mmap(fwmem_mmap); dev_type_strategy(fwmem_strategy); -#endif + +#endif /* _FWMEM_H_ */ diff --git a/sys/dev/ieee1394/fwohci.c b/sys/dev/ieee1394/fwohci.c index 695d5ee1ae5..5e561951bc2 100644 --- a/sys/dev/ieee1394/fwohci.c +++ b/sys/dev/ieee1394/fwohci.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwohci.c,v 1.120 2009/04/18 14:58:02 tsutsui Exp $ */ +/* $NetBSD: fwohci.c,v 1.121 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa @@ -33,57 +33,15 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/firewire/fwohci.c,v 1.93 2007/06/08 09:04:30 simokawa Exp $ + * $FreeBSD: src/sys/dev/firewire/fwohci.c,v 1.98 2009/02/13 17:44:07 sbruno Exp $ * */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.120 2009/04/18 14:58:02 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.121 2010/03/29 03:05:27 kiyohara Exp $"); -#define ATRQ_CH 0 -#define ATRS_CH 1 -#define ARRQ_CH 2 -#define ARRS_CH 3 -#define ITX_CH 4 -#define IRX_CH 0x24 - -#if defined(__FreeBSD__) #include <sys/param.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/sockio.h> -#include <sys/sysctl.h> +#include <sys/atomic.h> #include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/conf.h> -#include <sys/endian.h> -#include <sys/kdb.h> - -#include <machine/bus.h> - -#if defined(__DragonFly__) || __FreeBSD_version < 500000 -#include <machine/clock.h> /* for DELAY() */ -#endif - -#ifdef __DragonFly__ -#include "fw_port.h" -#include "firewire.h" -#include "firewirereg.h" -#include "fwdma.h" -#include "fwohcireg.h" -#include "fwohcivar.h" -#include "firewire_phy.h" -#else -#include <dev/firewire/fw_port.h> -#include <dev/firewire/firewire.h> -#include <dev/firewire/firewirereg.h> -#include <dev/firewire/fwdma.h> -#include <dev/firewire/fwohcireg.h> -#include <dev/firewire/fwohcivar.h> -#include <dev/firewire/firewire_phy.h> -#endif -#elif defined(__NetBSD__) -#include <sys/param.h> #include <sys/device.h> #include <sys/errno.h> #include <sys/conf.h> @@ -92,12 +50,10 @@ __KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.120 2009/04/18 14:58:02 tsutsui Exp $") #include <sys/mbuf.h> #include <sys/proc.h> #include <sys/reboot.h> +#include <sys/select.h> #include <sys/sysctl.h> #include <sys/systm.h> -#include <sys/bus.h> - -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/firewirereg.h> #include <dev/ieee1394/fwdma.h> @@ -106,20 +62,11 @@ __KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.120 2009/04/18 14:58:02 tsutsui Exp $") #include <dev/ieee1394/firewire_phy.h> #include "ioconf.h" -#endif #undef OHCI_DEBUG static int nocyclemaster = 0; int firewire_phydma_enable = 1; -#if defined(__FreeBSD__) -SYSCTL_DECL(_hw_firewire); -SYSCTL_INT(_hw_firewire, OID_AUTO, nocyclemaster, CTLFLAG_RW, &nocyclemaster, 0, - "Do not send cycle start packets"); -SYSCTL_INT(_hw_firewire, OID_AUTO, phydma_enable, CTLFLAG_RW, - &firewire_phydma_enable, 1, "Allow physical request DMA from firewire"); -TUNABLE_INT("hw.firewire.phydma_enable", &firewire_phydma_enable); -#elif defined(__NetBSD__) /* * Setup sysctl(3) MIB, hw.fwohci.* * @@ -164,94 +111,113 @@ SYSCTL_SETUP(sysctl_fwohci, "sysctl fwohci(4) subtree setup") return; err: - printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); + aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); } -#endif -static const char * const dbcode[16] = {"OUTM", "OUTL","INPM","INPL", - "STOR","LOAD","NOP ","STOP", - "", "", "", "", "", "", "", ""}; +static const char * const dbcode[16] = { + "OUTM", "OUTL", "INPM", "INPL", "STOR", "LOAD", "NOP ", "STOP", + "", "", "", "", "", "", "", "" +}; -static const char * const dbkey[8] = {"ST0", "ST1","ST2","ST3", - "UNDEF","REG","SYS","DEV"}; -static const char * const dbcond[4] = {"NEV","C=1", "C=0", "ALL"}; +static const char * const dbkey[8] = { + "ST0", "ST1", "ST2", "ST3", "UNDEF", "REG", "SYS", "DEV" +}; + +static const char * const dbcond[4] = { "NEV", "C=1", "C=0", "ALL" }; static const char * const fwohcicode[32] = { - "No stat","Undef","long","miss Ack err", - "FIFO underrun","FIFO overrun","desc err", "data read err", - "data write err","bus reset","timeout","tcode err", - "Undef","Undef","unknown event","flushed", - "Undef","ack complete","ack pend","Undef", - "ack busy_X","ack busy_A","ack busy_B","Undef", - "Undef","Undef","Undef","ack tardy", - "Undef","ack data_err","ack type_err",""}; + "No stat", "Undef", "long", "miss Ack err", + "FIFO underrun","FIFO overrun", "desc err", "data read err", + "data write err","bus reset", "timeout", "tcode err", + "Undef", "Undef", "unknown event","flushed", + "Undef", "ack complete", "ack pend", "Undef", + "ack busy_X", "ack busy_A", "ack busy_B", "Undef", + "Undef", "Undef", "Undef", "ack tardy", + "Undef", "ack data_err", "ack type_err", "" +}; #define MAX_SPEED 3 extern const char *fw_linkspeed[]; -static uint32_t const tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31}; +static uint32_t const tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31 }; static const struct tcode_info tinfo[] = { -/* hdr_len block flag valid_response*/ -/* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL, FWTCODE_WRES}, -/* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_WRES}, -/* 2 WRES */ {12, FWTI_RES, 0xff}, -/* 3 XXX */ { 0, 0, 0xff}, -/* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESQ}, -/* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESB}, -/* 6 RRESQ */ {16, FWTI_RES, 0xff}, -/* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY, 0xff}, -/* 8 CYCS */ { 0, 0, 0xff}, -/* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_LRES}, -/* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR, 0xff}, -/* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY, 0xff}, -/* c XXX */ { 0, 0, 0xff}, -/* d XXX */ { 0, 0, 0xff}, -/* e PHY */ {12, FWTI_REQ, 0xff}, -/* f XXX */ { 0, 0, 0xff} +/* hdr_len block flag valid_response */ +/* 0 WREQQ */ { 16, FWTI_REQ | FWTI_TLABEL, FWTCODE_WRES }, +/* 1 WREQB */ { 16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_WRES }, +/* 2 WRES */ { 12, FWTI_RES, 0xff }, +/* 3 XXX */ { 0, 0, 0xff }, +/* 4 RREQQ */ { 12, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESQ }, +/* 5 RREQB */ { 16, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESB }, +/* 6 RRESQ */ { 16, FWTI_RES, 0xff }, +/* 7 RRESB */ { 16, FWTI_RES | FWTI_BLOCK_ASY, 0xff }, +/* 8 CYCS */ { 0, 0, 0xff }, +/* 9 LREQ */ { 16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_LRES }, +/* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR, 0xff }, +/* b LRES */ { 16, FWTI_RES | FWTI_BLOCK_ASY, 0xff }, +/* c XXX */ { 0, 0, 0xff }, +/* d XXX */ { 0, 0, 0xff }, +/* e PHY */ { 12, FWTI_REQ, 0xff }, +/* f XXX */ { 0, 0, 0xff } }; #define OHCI_WRITE_SIGMASK 0xffff0000 #define OHCI_READ_SIGMASK 0xffff0000 -#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)) - -static void fwohci_ibr (struct firewire_comm *); -static void fwohci_db_init (struct fwohci_softc *, struct fwohci_dbch *); -static void fwohci_db_free (struct fwohci_dbch *); -static void fwohci_arcv (struct fwohci_softc *, struct fwohci_dbch *, int); -static void fwohci_txd (struct fwohci_softc *, struct fwohci_dbch *); -static void fwohci_start_atq (struct firewire_comm *); -static void fwohci_start_ats (struct firewire_comm *); -static void fwohci_start (struct fwohci_softc *, struct fwohci_dbch *); -static uint32_t fwphy_wrdata ( struct fwohci_softc *, uint32_t, uint32_t); -static uint32_t fwphy_rddata ( struct fwohci_softc *, uint32_t); -static int fwohci_rx_enable (struct fwohci_softc *, struct fwohci_dbch *); -static int fwohci_tx_enable (struct fwohci_softc *, struct fwohci_dbch *); -static int fwohci_irx_enable (struct firewire_comm *, int); -static int fwohci_irx_disable (struct firewire_comm *, int); + +int fwohci_print(void *, const char *); + +static int fwohci_ioctl(dev_t, u_long, void *, int, struct lwp *); + +static uint32_t fwohci_cyctimer(struct firewire_comm *); +static uint32_t fwohci_set_bus_manager(struct firewire_comm *, u_int); +static void fwohci_ibr(struct firewire_comm *); +static int fwohci_irx_enable(struct firewire_comm *, int); +static int fwohci_irx_disable(struct firewire_comm *, int); +static int fwohci_itxbuf_enable(struct firewire_comm *, int); +static int fwohci_itx_disable(struct firewire_comm *, int); +static void fwohci_timeout(struct firewire_comm *fc); #if BYTE_ORDER == BIG_ENDIAN -static void fwohci_irx_post (struct firewire_comm *, uint32_t *); +static void fwohci_irx_post(struct firewire_comm *, uint32_t *); #endif -static int fwohci_itxbuf_enable (struct firewire_comm *, int); -static int fwohci_itx_disable (struct firewire_comm *, int); -static void fwohci_timeout (void *); -static void fwohci_set_intr (struct firewire_comm *, int); - -static int fwohci_add_rx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int, struct fwdma_alloc *); -static int fwohci_add_tx_buf (struct fwohci_dbch *, struct fwohcidb_tr *, int); -static void dump_db (struct fwohci_softc *, uint32_t); -static void print_db (struct fwohcidb_tr *, struct fwohcidb *, uint32_t , uint32_t); -static void dump_dma (struct fwohci_softc *, uint32_t); -static uint32_t fwohci_cyctimer (struct firewire_comm *); -static void fwohci_rbuf_update (struct fwohci_softc *, int); -static void fwohci_tbuf_update (struct fwohci_softc *, int); -void fwohci_txbufdb (struct fwohci_softc *, int , struct fw_bulkxfer *); -static void fwohci_task_busreset(void *, int); -static void fwohci_task_sid(void *, int); -static void fwohci_task_dma(void *, int); -#if defined(__NetBSD__) -int fwohci_print(void *, const char *); +static void fwohci_set_intr(struct firewire_comm *, int); + +static uint32_t fwphy_rddata(struct fwohci_softc *, uint32_t); +static uint32_t fwphy_wrdata(struct fwohci_softc *, uint32_t, uint32_t); +static int fwohci_probe_phy(struct fwohci_softc *); +static void fwohci_reset(struct fwohci_softc *); +static void fwohci_execute_db(struct fwohcidb_tr *, bus_dmamap_t); +static void fwohci_start(struct fwohci_softc *, struct fwohci_dbch *); +static void fwohci_start_atq(struct firewire_comm *); +static void fwohci_start_ats(struct firewire_comm *); +static void fwohci_txd(struct fwohci_softc *, struct fwohci_dbch *); +static void fwohci_db_free(struct fwohci_softc *, struct fwohci_dbch *); +static void fwohci_db_init(struct fwohci_softc *, struct fwohci_dbch *); +static int fwohci_rx_enable(struct fwohci_softc *, struct fwohci_dbch *); +static int fwohci_tx_enable(struct fwohci_softc *, struct fwohci_dbch *); +static int fwohci_next_cycle(struct fwohci_softc *, int); +#ifdef OHCI_DEBUG +static void fwohci_dump_intr(struct fwohci_softc *, uint32_t); #endif +static void fwohci_intr_core(struct fwohci_softc *, uint32_t); +static void fwohci_intr_dma(struct fwohci_softc *, uint32_t); +static void fwohci_task_sid(struct fwohci_softc *); +static void fwohci_task_dma(struct fwohci_softc *); +static void fwohci_tbuf_update(struct fwohci_softc *, int); +static void fwohci_rbuf_update(struct fwohci_softc *, int); +static void dump_dma(struct fwohci_softc *, uint32_t); +static void dump_db(struct fwohci_softc *, uint32_t); +static void print_db(struct fwohcidb_tr *, struct fwohcidb *, uint32_t, + uint32_t); +static void fwohci_txbufdb(struct fwohci_softc *, int, struct fw_bulkxfer *); +static int fwohci_add_tx_buf(struct fwohci_dbch *, struct fwohcidb_tr *, int); +static int fwohci_add_rx_buf(struct fwohci_dbch *, struct fwohcidb_tr *, int, + struct fwdma_alloc *); +static int fwohci_arcv_swap(struct fw_pkt *, int); +static int fwohci_get_plen(struct fwohci_softc *, struct fwohci_dbch *, + struct fw_pkt *); +static void fwohci_arcv_free_buf(struct fwohci_softc *, struct fwohci_dbch *, + struct fwohcidb_tr *, int); +static void fwohci_arcv(struct fwohci_softc *, struct fwohci_dbch *); + /* * memory allocated for DMA programs @@ -260,24 +226,24 @@ int fwohci_print(void *, const char *); #define NDB FWMAXQUEUE -#define OHCI_VERSION 0x00 -#define OHCI_ATRETRY 0x08 -#define OHCI_CROMHDR 0x18 -#define OHCI_BUS_OPT 0x20 +#define OHCI_VERSION 0x000 +#define OHCI_ATRETRY 0x008 +#define OHCI_CROMHDR 0x018 +#define OHCI_BUS_OPT 0x020 #define OHCI_BUSIRMC (1 << 31) #define OHCI_BUSCMC (1 << 30) #define OHCI_BUSISC (1 << 29) #define OHCI_BUSBMC (1 << 28) #define OHCI_BUSPMC (1 << 27) -#define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\ - OHCI_BUSBMC | OHCI_BUSPMC +#define OHCI_BUSFNC \ + (OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC | OHCI_BUSBMC | OHCI_BUSPMC) -#define OHCI_EUID_HI 0x24 -#define OHCI_EUID_LO 0x28 +#define OHCI_EUID_HI 0x024 +#define OHCI_EUID_LO 0x028 -#define OHCI_CROMPTR 0x34 -#define OHCI_HCCCTL 0x50 -#define OHCI_HCCCTLCLR 0x54 +#define OHCI_CROMPTR 0x034 +#define OHCI_HCCCTL 0x050 +#define OHCI_HCCCTLCLR 0x054 #define OHCI_AREQHI 0x100 #define OHCI_AREQHICLR 0x104 #define OHCI_AREQLO 0x108 @@ -288,98 +254,482 @@ int fwohci_print(void *, const char *); #define OHCI_PREQLOCLR 0x11c #define OHCI_PREQUPPER 0x120 -#define OHCI_SID_BUF 0x64 -#define OHCI_SID_CNT 0x68 +#define OHCI_SID_BUF 0x064 +#define OHCI_SID_CNT 0x068 #define OHCI_SID_ERR (1 << 31) #define OHCI_SID_CNT_MASK 0xffc -#define OHCI_IT_STAT 0x90 -#define OHCI_IT_STATCLR 0x94 -#define OHCI_IT_MASK 0x98 -#define OHCI_IT_MASKCLR 0x9c +#define OHCI_IT_STAT 0x090 +#define OHCI_IT_STATCLR 0x094 +#define OHCI_IT_MASK 0x098 +#define OHCI_IT_MASKCLR 0x09c -#define OHCI_IR_STAT 0xa0 -#define OHCI_IR_STATCLR 0xa4 -#define OHCI_IR_MASK 0xa8 -#define OHCI_IR_MASKCLR 0xac +#define OHCI_IR_STAT 0x0a0 +#define OHCI_IR_STATCLR 0x0a4 +#define OHCI_IR_MASK 0x0a8 +#define OHCI_IR_MASKCLR 0x0ac -#define OHCI_LNKCTL 0xe0 -#define OHCI_LNKCTLCLR 0xe4 +#define OHCI_LNKCTL 0x0e0 +#define OHCI_LNKCTLCLR 0x0e4 -#define OHCI_PHYACCESS 0xec -#define OHCI_CYCLETIMER 0xf0 +#define OHCI_PHYACCESS 0x0ec +#define OHCI_CYCLETIMER 0x0f0 #define OHCI_DMACTL(off) (off) -#define OHCI_DMACTLCLR(off) (off + 4) -#define OHCI_DMACMD(off) (off + 0xc) +#define OHCI_DMACTLCLR(off) (off + 0x04) +#define OHCI_DMACMD(off) (off + 0x0c) #define OHCI_DMAMATCH(off) (off + 0x10) #define OHCI_ATQOFF 0x180 #define OHCI_ATQCTL OHCI_ATQOFF -#define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4) -#define OHCI_ATQCMD (OHCI_ATQOFF + 0xc) +#define OHCI_ATQCTLCLR (OHCI_ATQOFF + 0x04) +#define OHCI_ATQCMD (OHCI_ATQOFF + 0x0c) #define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10) #define OHCI_ATSOFF 0x1a0 #define OHCI_ATSCTL OHCI_ATSOFF -#define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4) -#define OHCI_ATSCMD (OHCI_ATSOFF + 0xc) +#define OHCI_ATSCTLCLR (OHCI_ATSOFF + 0x04) +#define OHCI_ATSCMD (OHCI_ATSOFF + 0x0c) #define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10) #define OHCI_ARQOFF 0x1c0 #define OHCI_ARQCTL OHCI_ARQOFF -#define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4) -#define OHCI_ARQCMD (OHCI_ARQOFF + 0xc) +#define OHCI_ARQCTLCLR (OHCI_ARQOFF + 0x04) +#define OHCI_ARQCMD (OHCI_ARQOFF + 0x0c) #define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10) #define OHCI_ARSOFF 0x1e0 #define OHCI_ARSCTL OHCI_ARSOFF -#define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4) -#define OHCI_ARSCMD (OHCI_ARSOFF + 0xc) +#define OHCI_ARSCTLCLR (OHCI_ARSOFF + 0x04) +#define OHCI_ARSCMD (OHCI_ARSOFF + 0x0c) #define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10) #define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH)) #define OHCI_ITCTL(CH) (OHCI_ITOFF(CH)) -#define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4) -#define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc) +#define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 0x04) +#define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0x0c) #define OHCI_IROFF(CH) (0x400 + 0x20 * (CH)) #define OHCI_IRCTL(CH) (OHCI_IROFF(CH)) -#define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4) -#define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc) +#define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 0x04) +#define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0x0c) #define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10) -#if defined(__FreeBSD__) -d_ioctl_t fwohci_ioctl; -#elif defined(__NetBSD__) -dev_type_ioctl(fwohci_ioctl); +#define ATRQ_CH 0 +#define ATRS_CH 1 +#define ARRQ_CH 2 +#define ARRS_CH 3 +#define ITX_CH 4 +#define IRX_CH 36 + + +int +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; + sc->fc.ats = &sc->atrs.xferq; + + sc->arrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); + sc->arrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); + sc->atrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); + sc->atrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); + + sc->arrq.xferq.start = NULL; + sc->arrs.xferq.start = NULL; + sc->atrq.xferq.start = fwohci_start_atq; + sc->atrs.xferq.start = fwohci_start_ats; + + sc->arrq.xferq.buf = NULL; + sc->arrs.xferq.buf = NULL; + sc->atrq.xferq.buf = NULL; + sc->atrs.xferq.buf = NULL; + + sc->arrq.xferq.dmach = -1; + sc->arrs.xferq.dmach = -1; + sc->atrq.xferq.dmach = -1; + sc->atrs.xferq.dmach = -1; + + sc->arrq.ndesc = 1; + sc->arrs.ndesc = 1; + sc->atrq.ndesc = 8; /* equal to maximum of mbuf chains */ + sc->atrs.ndesc = 2; + + sc->arrq.ndb = NDB; + sc->arrs.ndb = NDB / 2; + sc->atrq.ndb = NDB; + sc->atrs.ndb = NDB / 2; + + sc->arrq.off = OHCI_ARQOFF; + sc->arrs.off = OHCI_ARSOFF; + sc->atrq.off = OHCI_ATQOFF; + sc->atrs.off = OHCI_ATSOFF; + + for (i = 0; i < sc->fc.nisodma; i++) { + sc->fc.it[i] = &sc->it[i].xferq; + sc->fc.ir[i] = &sc->ir[i].xferq; + sc->it[i].xferq.dmach = i; + sc->ir[i].xferq.dmach = i; + sc->it[i].ndb = 0; + sc->ir[i].ndb = 0; + sc->it[i].off = OHCI_ITOFF(i); + 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) { + aprint_error_dev(sc->fc.dev, "config_rom alloc failed."); + return ENOMEM; + } + +#if 0 + memset(sc->fc.config_rom, 0, CROMSIZE); + sc->fc.config_rom[1] = 0x31333934; + sc->fc.config_rom[2] = 0xf000a002; + sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI); + sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO); + sc->fc.config_rom[5] = 0; + sc->fc.config_rom[0] = (4 << 24) | (5 << 16); + + sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4); #endif -/* - * Communication with PHY device - */ -/* XXX need lock for phy access */ -static uint32_t -fwphy_wrdata( struct fwohci_softc *sc, uint32_t addr, uint32_t data) +/* SID recieve buffer must align 2^11 */ +#define OHCI_SIDSIZE (1 << 11) + sc->sid_buf = fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat, OHCI_SIDSIZE, + &sc->sid_dma, OHCI_SIDSIZE, BUS_DMA_NOWAIT); + if (sc->sid_buf == NULL) { + aprint_error_dev(sc->fc.dev, "sid_buf alloc failed."); + return ENOMEM; + } + + fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat, sizeof(uint32_t), + &sc->dummy_dma, sizeof(uint32_t), BUS_DMA_NOWAIT); + if (sc->dummy_dma.v_addr == NULL) { + aprint_error_dev(sc->fc.dev, "dummy_dma alloc failed."); + return ENOMEM; + } + + fwohci_db_init(sc, &sc->arrq); + if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; + + fwohci_db_init(sc, &sc->arrs); + if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; + + fwohci_db_init(sc, &sc->atrq); + if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; + + fwohci_db_init(sc, &sc->atrs); + if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; + + sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H); + sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L); + for (i = 0; i < 8; i++) + ui[i] = FW_EUI64_BYTE(&sc->fc.eui, i); + aprint_normal_dev(sc->fc.dev, + "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 = + config_found(sc->fc.dev, __UNCONST("ieee1394if"), fwohci_print); + + return 0; +} + +int +fwohci_detach(struct fwohci_softc *sc, int flags) { - uint32_t fun; + int i; - addr &= 0xf; - data &= 0xff; + if (sc->fc.bdev != NULL) + config_detach(sc->fc.bdev, flags); + if (sc->sid_buf != NULL) + fwdma_free(sc->sid_dma.dma_tag, sc->sid_dma.dma_map, + sc->sid_dma.v_addr); + if (sc->fc.config_rom != NULL) + fwdma_free(sc->crom_dma.dma_tag, sc->crom_dma.dma_map, + sc->crom_dma.v_addr); - fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA)); - OWRITE(sc, OHCI_PHYACCESS, fun); - DELAY(100); + fwohci_db_free(sc, &sc->arrq); + fwohci_db_free(sc, &sc->arrs); + fwohci_db_free(sc, &sc->atrq); + fwohci_db_free(sc, &sc->atrs); + for (i = 0; i < sc->fc.nisodma; i++) { + fwohci_db_free(sc, &sc->it[i]); + 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); + + return 0; +} + +int +fwohci_intr(void *arg) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)arg; + uint32_t stat, irstat, itstat; + + if (!device_is_active(sc->fc.dev)) + return 0; + + if (!(sc->intmask & OHCI_INT_EN)) + /* polling mode? */ + return 0; + + stat = OREAD(sc, FWOHCI_INTSTAT); + if (stat == 0xffffffff) { + aprint_error_dev(sc->fc.dev, "device physically ejected?\n"); + return 0; + } + if (stat) + OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R); + + stat &= sc->intmask; + if (stat == 0) + return 0; + + atomic_swap_32(&sc->intstat, stat); + if (stat & OHCI_INT_DMA_IR) { + irstat = OREAD(sc, OHCI_IR_STAT); + OWRITE(sc, OHCI_IR_STATCLR, irstat); + atomic_swap_32(&sc->irstat, irstat); + } + if (stat & OHCI_INT_DMA_IT) { + itstat = OREAD(sc, OHCI_IT_STAT); + OWRITE(sc, OHCI_IT_STATCLR, itstat); + atomic_swap_32(&sc->itstat, itstat); + } + + fwohci_intr_core(sc, stat); + return 1; +} + +int +fwohci_resume(struct fwohci_softc *sc) +{ + struct fw_xferq *ir; + struct fw_bulkxfer *chunk; + int i; + extern int firewire_resume(struct firewire_comm *); + + fwohci_reset(sc); + /* XXX resume isochronous receive automatically. (how about TX?) */ + for (i = 0; i < sc->fc.nisodma; i++) { + ir = &sc->ir[i].xferq; + if ((ir->flag & FWXFERQ_RUNNING) != 0) { + aprint_normal_dev(sc->fc.dev, + "resume iso receive ch: %d\n", i); + ir->flag &= ~FWXFERQ_RUNNING; + /* requeue stdma to stfree */ + while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) { + STAILQ_REMOVE_HEAD(&ir->stdma, link); + STAILQ_INSERT_TAIL(&ir->stfree, chunk, link); + } + sc->fc.irx_enable(&sc->fc, i); + } + } + + firewire_resume(&sc->fc); + sc->fc.ibr(&sc->fc); + return 0; +} + +int +fwohci_stop(struct fwohci_softc *sc) +{ + u_int i; + + fwohci_set_intr(&sc->fc, 0); + +/* Now stopping all DMA channel */ + OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); + + for (i = 0; i < sc->fc.nisodma; i++) { + OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); + } + +#if 0 /* Let dcons(4) be accessed */ +/* Stop interrupt */ + OWRITE(sc, FWOHCI_INTMASKCLR, + OHCI_INT_EN | + OHCI_INT_ERR | + OHCI_INT_PHY_SID | + OHCI_INT_PHY_INT | + OHCI_INT_DMA_ATRQ | + OHCI_INT_DMA_ATRS | + OHCI_INT_DMA_PRRQ | + OHCI_INT_DMA_PRRS | + OHCI_INT_DMA_ARRQ | + OHCI_INT_DMA_ARRS | + OHCI_INT_PHY_BUS_R); + +/* FLUSH FIFO and reset Transmitter/Reciever */ + OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); +#endif + +/* XXX Link down? Bus reset? */ + return 0; +} + + +static int +fwohci_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *td) +{ + struct fwohci_softc *sc; + struct fw_reg_req_t *reg = (struct fw_reg_req_t *)data; + uint32_t *dmach = (uint32_t *)data; + int err = 0; + + sc = device_lookup_private(&fwohci_cd, DEV2UNIT(dev)); + if (sc == NULL) + return ENXIO; + + if (!data) + return EINVAL; + + switch (cmd) { + case FWOHCI_WRREG: +#define OHCI_MAX_REG 0x800 + if (reg->addr <= OHCI_MAX_REG) { + OWRITE(sc, reg->addr, reg->data); + reg->data = OREAD(sc, reg->addr); + } else + err = EINVAL; + break; + + case FWOHCI_RDREG: + if (reg->addr <= OHCI_MAX_REG) + reg->data = OREAD(sc, reg->addr); + else + err = EINVAL; + break; + +/* Read DMA descriptors for debug */ + case DUMPDMA: + if (*dmach <= OHCI_MAX_DMA_CH) { + dump_dma(sc, *dmach); + dump_db(sc, *dmach); + } else + err = EINVAL; + break; + +/* Read/Write Phy registers */ +#define OHCI_MAX_PHY_REG 0xf + case FWOHCI_RDPHYREG: + if (reg->addr <= OHCI_MAX_PHY_REG) + reg->data = fwphy_rddata(sc, reg->addr); + else + err = EINVAL; + break; + + case FWOHCI_WRPHYREG: + if (reg->addr <= OHCI_MAX_PHY_REG) + reg->data = fwphy_wrdata(sc, reg->addr, reg->data); + else + err = EINVAL; + break; + + default: + err = EINVAL; + break; + } + return err; +} + +int +fwohci_print(void *aux, const char *pnp) +{ + struct fw_attach_args *fwa = (struct fw_attach_args *)aux; - return(fwphy_rddata( sc, addr)); + if (pnp) + aprint_normal("%s at %s", fwa->name, pnp); + + return UNCONF; +} + + +static uint32_t +fwohci_cyctimer(struct firewire_comm *fc) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)fc; + + return OREAD(sc, OHCI_CYCLETIMER); } static uint32_t fwohci_set_bus_manager(struct firewire_comm *fc, u_int node) { struct fwohci_softc *sc = (struct fwohci_softc *)fc; - int i; uint32_t bm; + int i; #define OHCI_CSR_DATA 0x0c #define OHCI_CSR_COMP 0x10 @@ -392,17 +742,334 @@ fwohci_set_bus_manager(struct firewire_comm *fc, u_int node) for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++) DELAY(10); bm = OREAD(sc, OHCI_CSR_DATA); - if((bm & 0x3f) == 0x3f) + if ((bm & 0x3f) == 0x3f) bm = node; if (firewire_debug) - fw_printf(sc->fc.dev, - "fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i); + printf("fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i); + + return bm; +} + +static void +fwohci_ibr(struct firewire_comm *fc) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)fc; + uint32_t fun; + + aprint_normal_dev(fc->dev, "Initiate bus reset\n"); + + /* + * Make sure our cached values from the config rom are + * initialised. + */ + OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); + OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); + + /* + * Set root hold-off bit so that non cyclemaster capable node + * shouldn't became the root node. + */ +#if 1 + fun = fwphy_rddata(sc, FW_PHY_IBR_REG); + fun |= FW_PHY_IBR | FW_PHY_RHB; + fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun); +#else /* Short bus reset */ + fun = fwphy_rddata(sc, FW_PHY_ISBR_REG); + fun |= FW_PHY_ISBR | FW_PHY_RHB; + fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun); +#endif +} + +static int +fwohci_irx_enable(struct firewire_comm *fc, int dmach) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)fc; + struct fwohci_dbch *dbch; + struct fwohcidb_tr *db_tr; + struct fw_bulkxfer *first, *prev, *chunk, *txfer; + struct fw_xferq *ir; + uint32_t stat; + unsigned short tag, ich; + int err = 0, ldesc; + + dbch = &sc->ir[dmach]; + ir = &dbch->xferq; + + if ((ir->flag & FWXFERQ_RUNNING) == 0) { + tag = (ir->flag >> 6) & 3; + ich = ir->flag & 0x3f; + OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich); + + ir->queued = 0; + dbch->ndb = ir->bnpacket * ir->bnchunk; + dbch->ndesc = 2; + fwohci_db_init(sc, dbch); + if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; + err = fwohci_rx_enable(sc, dbch); + if (err) + return err; + } + + first = STAILQ_FIRST(&ir->stfree); + if (first == NULL) { + aprint_error_dev(fc->dev, "IR DMA no free chunk\n"); + return 0; + } + + ldesc = dbch->ndesc - 1; + prev = NULL; + STAILQ_FOREACH(txfer, &ir->stdma, link) + prev = txfer; + while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) { + struct fwohcidb *db; + + if (chunk->mbuf != NULL) { + db_tr = (struct fwohcidb_tr *)(chunk->start); + db_tr->dbcnt = 1; + err = bus_dmamap_load_mbuf(fc->dmat, db_tr->dma_map, + chunk->mbuf, BUS_DMA_NOWAIT); + if (err == 0) + fwohci_execute_db(db_tr, db_tr->dma_map); + else + aprint_error_dev(fc->dev, + "mbuf load failed: %d\n", err); + FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd, + OHCI_UPDATE | + OHCI_INPUT_LAST | + OHCI_INTERRUPT_ALWAYS | + OHCI_BRANCH_ALWAYS); + } + db = ((struct fwohcidb_tr *)(chunk->end))->db; + FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0); + FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf); + if (prev != NULL) { + db = ((struct fwohcidb_tr *)(prev->end))->db; + FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc); + } + STAILQ_REMOVE_HEAD(&ir->stfree, link); + STAILQ_INSERT_TAIL(&ir->stdma, chunk, link); + prev = chunk; + } + fwdma_sync_multiseg_all(dbch->am, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + stat = OREAD(sc, OHCI_IRCTL(dmach)); + if (stat & OHCI_CNTL_DMA_ACTIVE) + return 0; + if (stat & OHCI_CNTL_DMA_RUN) { + OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); + aprint_error_dev(fc->dev, "IR DMA overrun (0x%08x)\n", stat); + } + + if (firewire_debug) + printf("start IR DMA 0x%x\n", stat); + OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); + OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); + OWRITE(sc, OHCI_IR_MASK, 1 << dmach); + OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000); + OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR); + OWRITE(sc, OHCI_IRCMD(dmach), + ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc); + OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN); + OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR); +#if 0 + dump_db(sc, IRX_CH + dmach); +#endif + return err; +} - return(bm); +static int +fwohci_irx_disable(struct firewire_comm *fc, int dmach) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)fc; + int sleepch; + + OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); + OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); + /* XXX we cannot free buffers until the DMA really stops */ + tsleep((void *)&sleepch, FWPRI, "fwirxd", hz); + fwohci_db_free(sc, &sc->ir[dmach]); + sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING; + return 0; } + +static int +fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)fc; + struct fwohci_dbch *dbch; + struct fw_bulkxfer *first, *chunk, *prev, *txfer; + struct fw_xferq *it; + uint32_t stat; + int cycle_match, cycle_now, ldesc, err = 0; + unsigned short tag, ich; + + dbch = &sc->it[dmach]; + it = &dbch->xferq; + + tag = (it->flag >> 6) & 3; + ich = it->flag & 0x3f; + if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) { + dbch->ndb = it->bnpacket * it->bnchunk; + dbch->ndesc = 3; + fwohci_db_init(sc, dbch); + if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) + return ENOMEM; + + err = fwohci_tx_enable(sc, dbch); + if (err) + return err; + } + + ldesc = dbch->ndesc - 1; + prev = NULL; + STAILQ_FOREACH(txfer, &it->stdma, link) + prev = txfer; + while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) { + struct fwohcidb *db; + + fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket, + BUS_DMASYNC_PREWRITE); + fwohci_txbufdb(sc, dmach, chunk); + if (prev != NULL) { + db = ((struct fwohcidb_tr *)(prev->end))->db; +#if 0 /* XXX necessary? */ + FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, + OHCI_BRANCH_ALWAYS); +#endif +#if 0 /* if bulkxfer->npacket changes */ + db[ldesc].db.desc.depend = db[0].db.desc.depend = + ((struct fwohcidb_tr *)(chunk->start))->bus_addr | + dbch->ndesc; +#else + FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc); + FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc); +#endif + } + STAILQ_REMOVE_HEAD(&it->stvalid, link); + STAILQ_INSERT_TAIL(&it->stdma, chunk, link); + prev = chunk; + } + fwdma_sync_multiseg_all(dbch->am, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + stat = OREAD(sc, OHCI_ITCTL(dmach)); + if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S)) + printf("stat 0x%x\n", stat); + + if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S)) + return 0; + +#if 0 + OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN); +#endif + OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); + OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); + OWRITE(sc, OHCI_IT_MASK, 1 << dmach); + OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT); + + first = STAILQ_FIRST(&it->stdma); + OWRITE(sc, OHCI_ITCMD(dmach), + ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc); + if (firewire_debug > 1) { + printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat); +#if 1 + dump_dma(sc, ITX_CH + dmach); +#endif + } + if ((stat & OHCI_CNTL_DMA_RUN) == 0) { +#if 1 + /* Don't start until all chunks are buffered */ + if (STAILQ_FIRST(&it->stfree) != NULL) + goto out; +#endif +#if 1 + /* Clear cycle match counter bits */ + OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000); + + /* 2bit second + 13bit cycle */ + cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff; + cycle_match = fwohci_next_cycle(sc, cycle_now); + + OWRITE(sc, OHCI_ITCTL(dmach), + OHCI_CNTL_CYCMATCH_S | (cycle_match << 16) | + OHCI_CNTL_DMA_RUN); +#else + OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN); +#endif + if (firewire_debug > 1) { + printf("cycle_match: 0x%04x->0x%04x\n", + cycle_now, cycle_match); + dump_dma(sc, ITX_CH + dmach); + dump_db(sc, ITX_CH + dmach); + } + } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) { + aprint_error_dev(fc->dev, "IT DMA underrun (0x%08x)\n", stat); + OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE); + } +out: + return err; +} + +static int +fwohci_itx_disable(struct firewire_comm *fc, int dmach) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)fc; + int sleepch; + + OWRITE(sc, OHCI_ITCTLCLR(dmach), + OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S); + OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); + OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); + /* XXX we cannot free buffers until the DMA really stops */ + tsleep((void *)&sleepch, FWPRI, "fwitxd", hz); + fwohci_db_free(sc, &sc->it[dmach]); + sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING; + return 0; +} + +static void +fwohci_timeout(struct firewire_comm *fc) +{ +#if 0 + struct fwohci_softc *sc = (struct fwohci_softc *)fc; +#endif + /* nothing? */ +} + +#if BYTE_ORDER == BIG_ENDIAN +static void +fwohci_irx_post (struct firewire_comm *fc, uint32_t *qld) +{ + + qld[0] = FWOHCI_DMA_READ(qld[0]); + return; +} +#endif + +static void +fwohci_set_intr(struct firewire_comm *fc, int enable) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)fc; + + if (firewire_debug) + printf("fwohci_set_intr: %d\n", enable); + if (enable) { + sc->intmask |= OHCI_INT_EN; + OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN); + } else { + sc->intmask &= ~OHCI_INT_EN; + OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); + } +} + +/* + * Communication with PHY device + */ +/* XXX need lock for phy access */ static uint32_t -fwphy_rddata(struct fwohci_softc *sc, u_int addr) +fwphy_rddata(struct fwohci_softc *sc, u_int addr) { uint32_t fun, stat; u_int i, retry = 0; @@ -413,15 +1080,15 @@ again: OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL); fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR); OWRITE(sc, OHCI_PHYACCESS, fun); - for ( i = 0 ; i < MAX_RETRY ; i ++ ){ + for (i = 0; i < MAX_RETRY; i++) { fun = OREAD(sc, OHCI_PHYACCESS); if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0) break; DELAY(100); } - if(i >= MAX_RETRY) { + if (i >= MAX_RETRY) { if (firewire_debug) - fw_printf(sc->fc.dev, "phy read failed(1).\n"); + printf("phy read failed(1).\n"); if (++retry < MAX_RETRY) { DELAY(100); goto again; @@ -430,89 +1097,44 @@ again: /* Make sure that SCLK is started */ stat = OREAD(sc, FWOHCI_INTSTAT); if ((stat & OHCI_INT_REG_FAIL) != 0 || - ((fun >> PHYDEV_REGADDR) & 0xf) != addr) { + ((fun >> PHYDEV_REGADDR) & 0xf) != addr) { if (firewire_debug) - fw_printf(sc->fc.dev, "phy read failed(2).\n"); + printf("phy read failed(2).\n"); if (++retry < MAX_RETRY) { DELAY(100); goto again; } } if (firewire_debug || retry >= MAX_RETRY) - fw_printf(sc->fc.dev, - "fwphy_rddata: 0x%x loop=%d, retry=%d\n", addr, i, retry); + aprint_error_dev(sc->fc.dev, + "fwphy_rddata: 0x%x loop=%d, retry=%d\n", + addr, i, retry); #undef MAX_RETRY - return((fun >> PHYDEV_RDDATA )& 0xff); + return (fun >> PHYDEV_RDDATA) & 0xff; } -/* Device specific ioctl. */ -FW_IOCTL(fwohci) + +static uint32_t +fwphy_wrdata(struct fwohci_softc *sc, uint32_t addr, uint32_t data) { - FW_IOCTL_START; - struct fwohci_softc *fc; - int err = 0; - struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data; - uint32_t *dmach = (uint32_t *) data; + uint32_t fun; - if(sc == NULL){ - return(EINVAL); - } - fc = (struct fwohci_softc *)sc->fc; + addr &= 0xf; + data &= 0xff; - if (!data) - return(EINVAL); + fun = + (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA)); + OWRITE(sc, OHCI_PHYACCESS, fun); + DELAY(100); - switch (cmd) { - case FWOHCI_WRREG: -#define OHCI_MAX_REG 0x800 - if(reg->addr <= OHCI_MAX_REG){ - OWRITE(fc, reg->addr, reg->data); - reg->data = OREAD(fc, reg->addr); - }else{ - err = EINVAL; - } - break; - case FWOHCI_RDREG: - if(reg->addr <= OHCI_MAX_REG){ - reg->data = OREAD(fc, reg->addr); - }else{ - err = EINVAL; - } - break; -/* Read DMA descriptors for debug */ - case DUMPDMA: - if(*dmach <= OHCI_MAX_DMA_CH ){ - dump_dma(fc, *dmach); - dump_db(fc, *dmach); - }else{ - err = EINVAL; - } - break; -/* Read/Write Phy registers */ -#define OHCI_MAX_PHY_REG 0xf - case FWOHCI_RDPHYREG: - if (reg->addr <= OHCI_MAX_PHY_REG) - reg->data = fwphy_rddata(fc, reg->addr); - else - err = EINVAL; - break; - case FWOHCI_WRPHYREG: - if (reg->addr <= OHCI_MAX_PHY_REG) - reg->data = fwphy_wrdata(fc, reg->addr, reg->data); - else - err = EINVAL; - break; - default: - err = EINVAL; - break; - } - return err; + return fwphy_rddata(sc, addr); } static int -fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) +fwohci_probe_phy(struct fwohci_softc *sc) { uint32_t reg, reg2; int e1394a = 1; + /* * probe PHY parameters * 0. to prove PHY version, whether compliance of 1394a. @@ -525,29 +1147,32 @@ fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) reg = fwphy_rddata(sc, FW_PHY_SPD_REG); - if((reg >> 5) != 7 ){ + if ((reg >> 5) != 7) { sc->fc.mode &= ~FWPHYASYST; sc->fc.nport = reg & FW_PHY_NP; sc->fc.speed = reg & FW_PHY_SPD >> 6; if (sc->fc.speed > MAX_SPEED) { - fw_printf(dev, "invalid speed %d (fixed to %d).\n", - sc->fc.speed, MAX_SPEED); + aprint_error_dev(sc->fc.dev, + "invalid speed %d (fixed to %d).\n", + sc->fc.speed, MAX_SPEED); sc->fc.speed = MAX_SPEED; } - fw_printf(dev, "Phy 1394 only %s, %d ports.\n", - fw_linkspeed[sc->fc.speed], sc->fc.nport); - }else{ + aprint_normal_dev(sc->fc.dev, "Phy 1394 only %s, %d ports.\n", + fw_linkspeed[sc->fc.speed], sc->fc.nport); + } else { reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG); sc->fc.mode |= FWPHYASYST; sc->fc.nport = reg & FW_PHY_NP; sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5; if (sc->fc.speed > MAX_SPEED) { - fw_printf(dev, "invalid speed %d (fixed to %d).\n", - sc->fc.speed, MAX_SPEED); + aprint_error_dev(sc->fc.dev, + "invalid speed %d (fixed to %d).\n", + sc->fc.speed, MAX_SPEED); sc->fc.speed = MAX_SPEED; } - fw_printf(dev, "Phy 1394a available %s, %d ports.\n", - fw_linkspeed[sc->fc.speed], sc->fc.nport); + aprint_normal_dev(sc->fc.dev, + "Phy 1394a available %s, %d ports.\n", + fw_linkspeed[sc->fc.speed], sc->fc.nport); /* check programPhyEnable */ reg2 = fwphy_rddata(sc, 5); @@ -557,7 +1182,7 @@ fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) if (e1394a) { #endif if (firewire_debug) - fw_printf(dev, "Enable 1394a Enhancements\n"); + printf("Enable 1394a Enhancements\n"); /* enable EAA EMC */ reg2 |= 0x03; /* set aPhyEnhanceEnable */ @@ -574,7 +1199,7 @@ fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) } reg = fwphy_rddata(sc, FW_PHY_SPD_REG); - if((reg >> 5) == 7 ){ + if ((reg >> 5) == 7) { reg = fwphy_rddata(sc, 4); reg |= 1 << 6; fwphy_wrdata(sc, 4, reg); @@ -583,61 +1208,61 @@ fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) return 0; } - -void -fwohci_reset(struct fwohci_softc *sc, device_t dev) +static void +fwohci_reset(struct fwohci_softc *sc) { - int i, max_rec, speed; - uint32_t reg, reg2; struct fwohcidb_tr *db_tr; + uint32_t reg, reg2; + int i, max_rec, speed; /* Disable interrupts */ OWRITE(sc, FWOHCI_INTMASKCLR, ~0); /* Now stopping all DMA channels */ - OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_IR_MASKCLR, ~0); - for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ - OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_IR_MASKCLR, ~0); + for (i = 0; i < sc->fc.nisodma; i++) { + OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); } /* FLUSH FIFO and reset Transmitter/Reciever */ OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); if (firewire_debug) - fw_printf(dev, "resetting OHCI..."); + printf("resetting OHCI..."); i = 0; - while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { - if (i++ > 100) break; + while (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { + if (i++ > 100) + break; DELAY(1000); } if (firewire_debug) printf("done (loop=%d)\n", i); /* Probe phy */ - fwohci_probe_phy(sc, dev); + fwohci_probe_phy(sc); /* Probe link */ - reg = OREAD(sc, OHCI_BUS_OPT); + reg = OREAD(sc, OHCI_BUS_OPT); reg2 = reg | OHCI_BUSFNC; max_rec = (reg & 0x0000f000) >> 12; speed = (reg & 0x00000007); - fw_printf(dev, "Link %s, max_rec %d bytes.\n", - fw_linkspeed[speed], MAXREC(max_rec)); + aprint_normal_dev(sc->fc.dev, "Link %s, max_rec %d bytes.\n", + fw_linkspeed[speed], MAXREC(max_rec)); /* XXX fix max_rec */ sc->fc.maxrec = sc->fc.speed + 8; if (max_rec != sc->fc.maxrec) { reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12); - fw_printf(dev, "max_rec %d -> %d\n", - MAXREC(max_rec), MAXREC(sc->fc.maxrec)); + aprint_normal_dev(sc->fc.dev, "max_rec %d -> %d\n", + MAXREC(max_rec), MAXREC(sc->fc.maxrec)); } if (firewire_debug) - fw_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2); - OWRITE(sc, OHCI_BUS_OPT, reg2); + printf("BUS_OPT 0x%x -> 0x%x\n", reg, reg2); + OWRITE(sc, OHCI_BUS_OPT, reg2); /* Initialize registers */ OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]); @@ -662,272 +1287,46 @@ fwohci_reset(struct fwohci_softc *sc, device_t dev) /* AT Retries */ OWRITE(sc, FWOHCI_RETRY, - /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */ - (0xffff << 16 ) | (0x0f << 8) | (0x0f << 4) | 0x0f) ; + /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */ + (0xffff << 16) | (0x0f << 8) | (0x0f << 4) | 0x0f); sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq); sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq); sc->atrq.bottom = sc->atrq.top; sc->atrs.bottom = sc->atrs.top; - for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ; - i ++, db_tr = STAILQ_NEXT(db_tr, link)){ + for (i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb; + i++, db_tr = STAILQ_NEXT(db_tr, link)) db_tr->xfer = NULL; - } - for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ; - i ++, db_tr = STAILQ_NEXT(db_tr, link)){ + for (i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb; + i++, db_tr = STAILQ_NEXT(db_tr, link)) db_tr->xfer = NULL; - } /* Enable interrupts */ - sc->intmask = (OHCI_INT_ERR | OHCI_INT_PHY_SID + sc->intmask = (OHCI_INT_ERR | OHCI_INT_PHY_SID | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR); - sc->intmask |= OHCI_INT_DMA_IR | OHCI_INT_DMA_IT; - sc->intmask |= OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT; + sc->intmask |= OHCI_INT_DMA_IR | OHCI_INT_DMA_IT; + sc->intmask |= OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT; OWRITE(sc, FWOHCI_INTMASK, sc->intmask); fwohci_set_intr(&sc->fc, 1); } -int -fwohci_init(struct fwohci_softc *sc, device_t dev) -{ - int i, mver; - uint32_t reg; - uint8_t ui[8]; - -/* OHCI version */ - reg = OREAD(sc, OHCI_VERSION); - mver = (reg >> 16) & 0xff; - fw_printf(dev, "OHCI version %x.%x (ROM=%d)\n", - mver, reg & 0xff, (reg>>24) & 1); - if (mver < 1 || mver > 9) { - fw_printf(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; - fw_printf(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; - sc->fc.ats = &sc->atrs.xferq; - - sc->arrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); - sc->arrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); - sc->atrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); - sc->atrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE); - - sc->arrq.xferq.start = NULL; - sc->arrs.xferq.start = NULL; - sc->atrq.xferq.start = fwohci_start_atq; - sc->atrs.xferq.start = fwohci_start_ats; - - sc->arrq.xferq.buf = NULL; - sc->arrs.xferq.buf = NULL; - sc->atrq.xferq.buf = NULL; - sc->atrs.xferq.buf = NULL; - - sc->arrq.xferq.dmach = -1; - sc->arrs.xferq.dmach = -1; - sc->atrq.xferq.dmach = -1; - sc->atrs.xferq.dmach = -1; - - sc->arrq.ndesc = 1; - sc->arrs.ndesc = 1; - sc->atrq.ndesc = 8; /* equal to maximum of mbuf chains */ - sc->atrs.ndesc = 2; - - sc->arrq.ndb = NDB; - sc->arrs.ndb = NDB / 2; - sc->atrq.ndb = NDB; - sc->atrs.ndb = NDB / 2; - - for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ - sc->fc.it[i] = &sc->it[i].xferq; - sc->fc.ir[i] = &sc->ir[i].xferq; - sc->it[i].xferq.dmach = i; - sc->ir[i].xferq.dmach = i; - sc->it[i].ndb = 0; - sc->ir[i].ndb = 0; - } - - sc->fc.tcode = tinfo; - sc->fc.dev = dev; - - sc->fc.config_rom = fwdma_malloc(&sc->fc, CROMSIZE, CROMSIZE, - &sc->crom_dma, BUS_DMA_WAITOK); - if(sc->fc.config_rom == NULL){ - fw_printf(dev, "config_rom alloc failed."); - return ENOMEM; - } - -#if 0 - memset(&sc->fc.config_rom[0], 0, CROMSIZE); - sc->fc.config_rom[1] = 0x31333934; - sc->fc.config_rom[2] = 0xf000a002; - sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI); - sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO); - sc->fc.config_rom[5] = 0; - sc->fc.config_rom[0] = (4 << 24) | (5 << 16); - - sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4); -#endif - -/* SID recieve buffer must align 2^11 */ -#define OHCI_SIDSIZE (1 << 11) - sc->sid_buf = fwdma_malloc(&sc->fc, OHCI_SIDSIZE, OHCI_SIDSIZE, - &sc->sid_dma, BUS_DMA_WAITOK); - if (sc->sid_buf == NULL) { - fw_printf(dev, "sid_buf alloc failed."); - return ENOMEM; - } - - fwdma_malloc(&sc->fc, sizeof(uint32_t), sizeof(uint32_t), - &sc->dummy_dma, BUS_DMA_WAITOK); - - if (sc->dummy_dma.v_addr == NULL) { - fw_printf(dev, "dummy_dma alloc failed."); - return ENOMEM; - } - - fwohci_db_init(sc, &sc->arrq); - if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0) - return ENOMEM; - - fwohci_db_init(sc, &sc->arrs); - if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0) - return ENOMEM; - - fwohci_db_init(sc, &sc->atrq); - if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0) - return ENOMEM; - - fwohci_db_init(sc, &sc->atrs); - if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0) - return ENOMEM; - - sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H); - sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L); - for( i = 0 ; i < 8 ; i ++) - ui[i] = FW_EUI64_BYTE(&sc->fc.eui,i); - fw_printf(dev, "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.ioctl = fwohci_ioctl; - sc->fc.cyctimer = fwohci_cyctimer; - sc->fc.set_bmr = fwohci_set_bus_manager; - sc->fc.ibr = fwohci_ibr; - 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; -#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->fc.timeout = fwohci_timeout; - sc->fc.poll = fwohci_poll; - sc->fc.set_intr = fwohci_set_intr; - - sc->intmask = sc->irstat = sc->itstat = 0; - - /* Init task queue */ - sc->fc.taskqueue = fw_taskqueue_create_fast("fw_taskq", M_WAITOK, - fw_taskqueue_thread_enqueue, &sc->fc.taskqueue); - fw_taskqueue_start_threads(&sc->fc.taskqueue, 1, PI_NET, "fw%d_taskq", - fw_get_unit(dev)); - FW_TASK_INIT(&sc->fwohci_task_busreset, 2, fwohci_task_busreset, sc); - FW_TASK_INIT(&sc->fwohci_task_sid, 1, fwohci_task_sid, sc); - FW_TASK_INIT(&sc->fwohci_task_dma, 0, fwohci_task_dma, sc); - - fw_init(&sc->fc); - fwohci_reset(sc, dev); - FWOHCI_INIT_END; - - return 0; -} - -void -fwohci_timeout(void *arg) -{ - struct fwohci_softc *sc; - - sc = (struct fwohci_softc *)arg; -} - -uint32_t -fwohci_cyctimer(struct firewire_comm *fc) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)fc; - return(OREAD(sc, OHCI_CYCLETIMER)); -} - -FWOHCI_DETACH() -{ - int i; - - FWOHCI_DETACH_START; - if (sc->sid_buf != NULL) - fwdma_free(&sc->fc, &sc->sid_dma); - if (sc->fc.config_rom != NULL) - fwdma_free(&sc->fc, &sc->crom_dma); - - fwohci_db_free(&sc->arrq); - fwohci_db_free(&sc->arrs); - - fwohci_db_free(&sc->atrq); - fwohci_db_free(&sc->atrs); - - for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ - fwohci_db_free(&sc->it[i]); - fwohci_db_free(&sc->ir[i]); - } - FWOHCI_DETACH_END; - - return 0; -} - -#define LAST_DB(dbtr, db) do { \ - struct fwohcidb_tr *_dbtr = (dbtr); \ - int _cnt = _dbtr->dbcnt; \ - db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \ -} while (0) +#define LAST_DB(dbtr) \ + &dbtr->db[(dbtr->dbcnt > 2) ? (dbtr->dbcnt - 1) : 0]; static void -fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error) +fwohci_execute_db(struct fwohcidb_tr *db_tr, bus_dmamap_t dmamap) { - struct fwohcidb_tr *db_tr; struct fwohcidb *db; bus_dma_segment_t *s; int i; - db_tr = (struct fwohcidb_tr *)arg; db = &db_tr->db[db_tr->dbcnt]; - if (error) { - if (firewire_debug || error != EFBIG) - printf("fwohci_execute_db: error=%d\n", error); - return; - } - for (i = 0; i < nseg; i++) { - s = &segs[i]; + for (i = 0; i < dmamap->dm_nsegs; i++) { + s = &dmamap->dm_segs[i]; FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr); FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len); FWOHCI_DMA_WRITE(db->db.desc.res, 0); @@ -937,54 +1336,43 @@ fwohci_execute_db(void *arg, bus_dma_segment_t *segs, int nseg, int error) } static void -fwohci_execute_db2(void *arg, bus_dma_segment_t *segs, int nseg, - bus_size_t size, int error) -{ - fwohci_execute_db(arg, segs, nseg, error); -} - -static void fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch) { - int i, s; - int tcode, hdr_len, pl_off; - int fsegment = -1; - uint32_t off; struct fw_xfer *xfer; struct fw_pkt *fp; struct fwohci_txpkthdr *ohcifp; - struct fwohcidb_tr *db_tr; + struct fwohcidb_tr *db_tr, *kick; struct fwohcidb *db; uint32_t *ld; + int tcode, hdr_len, pl_off, fsegment = -1, i; const struct tcode_info *info; - static int maxdesc=0; + static int maxdesc = 0; - FW_GLOCK_ASSERT(&sc->fc); + KASSERT(mutex_owned(&dbch->xferq.q_mtx)); - if(&sc->atrq == dbch){ - off = OHCI_ATQOFF; - }else if(&sc->atrs == dbch){ - off = OHCI_ATSOFF; - }else{ - return; - } +#if DIAGNOSTIC + if (dbch->off != OHCI_ATQOFF && + dbch->off != OHCI_ATSOFF) + panic("not async tx"); +#endif if (dbch->flags & FWOHCI_DBCH_FULL) return; - s = splfw(); - fwdma_sync_multiseg_all(dbch->am, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); db_tr = dbch->top; + kick = db_tr; + if (dbch->pdb_tr != NULL) { + kick = dbch->pdb_tr; + fwdma_sync_multiseg(dbch->am, kick->idx, kick->idx, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + } txloop: xfer = STAILQ_FIRST(&dbch->xferq.q); - if(xfer == NULL){ + if (xfer == NULL) goto kick; - } #if 0 - if(dbch->xferq.queued == 0 ){ - fw_printf(sc->fc.dev, "TX queue empty\n"); - } + if (dbch->xferq.queued == 0) + aprint_error_dev(sc->fc.dev, "TX queue empty\n"); #endif STAILQ_REMOVE_HEAD(&dbch->xferq.q, link); db_tr->xfer = xfer; @@ -997,13 +1385,13 @@ txloop: info = &tinfo[tcode]; hdr_len = pl_off = info->hdr_len; - ld = &ohcifp->mode.ld[0]; + ld = ohcifp->mode.ld; ld[0] = ld[1] = ld[2] = ld[3] = 0; - for( i = 0 ; i < pl_off ; i+= 4) - ld[i/4] = fp->mode.ld[i/4]; + for (i = 0; i < pl_off / 4; i++) + ld[i] = fp->mode.ld[i]; ohcifp->mode.common.spd = xfer->send.spd & 0x7; - if (tcode == FWTCODE_STREAM ){ + if (tcode == FWTCODE_STREAM) { hdr_len = 8; ohcifp->mode.stream.len = fp->mode.stream.len; } else if (tcode == FWTCODE_PHY) { @@ -1017,20 +1405,19 @@ txloop: ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS; ohcifp->mode.asycomm.tlrt |= FWRETRY_X; } - db = &db_tr->db[0]; + db = db_tr->db; FWOHCI_DMA_WRITE(db->db.desc.cmd, - OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len); + OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len); FWOHCI_DMA_WRITE(db->db.desc.addr, 0); FWOHCI_DMA_WRITE(db->db.desc.res, 0); /* Specify bound timer of asy. responce */ - if(&sc->atrs == dbch){ + if (dbch->off != OHCI_ATSOFF) FWOHCI_DMA_WRITE(db->db.desc.res, - (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13)); - } + (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13)); #if BYTE_ORDER == BIG_ENDIAN if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ) hdr_len = 12; - for (i = 0; i < hdr_len/4; i ++) + for (i = 0; i < hdr_len / 4; i++) FWOHCI_DMA_WRITE(ld[i], ld[i]); #endif @@ -1040,93 +1427,92 @@ again: if (xfer->send.pay_len > 0) { int err; /* handle payload */ - if (xfer->mbuf == NULL) { - err = fw_bus_dmamap_load(dbch->dmat, db_tr->dma_map, - &xfer->send.payload[0], xfer->send.pay_len, - fwohci_execute_db, db_tr, - BUS_DMA_WAITOK); - } else { + if (xfer->mbuf == NULL) + err = bus_dmamap_load(sc->fc.dmat, db_tr->dma_map, + xfer->send.payload, xfer->send.pay_len, NULL, + BUS_DMA_WAITOK); + else { /* XXX we can handle only 6 (=8-2) mbuf chains */ - err = fw_bus_dmamap_load_mbuf(dbch->dmat, - db_tr->dma_map, xfer->mbuf, - fwohci_execute_db2, db_tr, - BUS_DMA_WAITOK); + err = bus_dmamap_load_mbuf(sc->fc.dmat, db_tr->dma_map, + xfer->mbuf, BUS_DMA_WAITOK); if (err == EFBIG) { struct mbuf *m0; if (firewire_debug) - fw_printf(sc->fc.dev, "EFBIG.\n"); + printf("EFBIG.\n"); m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); if (m0 != NULL) { m_copydata(xfer->mbuf, 0, - xfer->mbuf->m_pkthdr.len, - mtod(m0, void *)); + xfer->mbuf->m_pkthdr.len, + mtod(m0, void *)); m0->m_len = m0->m_pkthdr.len = - xfer->mbuf->m_pkthdr.len; + xfer->mbuf->m_pkthdr.len; m_freem(xfer->mbuf); xfer->mbuf = m0; goto again; } - fw_printf(sc->fc.dev, "m_getcl failed.\n"); + aprint_error_dev(sc->fc.dev, + "m_getcl failed.\n"); } } - if (err) - printf("dmamap_load: err=%d\n", err); - fw_bus_dmamap_sync(dbch->dmat, db_tr->dma_map, - BUS_DMASYNC_PREWRITE); + if (!err) + fwohci_execute_db(db_tr, db_tr->dma_map); + else + aprint_error_dev(sc->fc.dev, + "dmamap_load: err=%d\n", err); + bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, + 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE); #if 0 /* OHCI_OUTPUT_MODE == 0 */ for (i = 2; i < db_tr->dbcnt; i++) FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd, - OHCI_OUTPUT_MORE); + OHCI_OUTPUT_MORE); #endif } if (maxdesc < db_tr->dbcnt) { maxdesc = db_tr->dbcnt; if (firewire_debug) - fw_printf(sc->fc.dev, "maxdesc: %d\n", maxdesc); + printf("maxdesc: %d\n", maxdesc); } /* last db */ - LAST_DB(db_tr, db); + db = LAST_DB(db_tr); FWOHCI_DMA_SET(db->db.desc.cmd, - OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS); + OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS); FWOHCI_DMA_WRITE(db->db.desc.depend, - STAILQ_NEXT(db_tr, link)->bus_addr); + STAILQ_NEXT(db_tr, link)->bus_addr); - if(fsegment == -1 ) + if (fsegment == -1) fsegment = db_tr->dbcnt; if (dbch->pdb_tr != NULL) { - LAST_DB(dbch->pdb_tr, db); + db = LAST_DB(dbch->pdb_tr); FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt); } - dbch->xferq.queued ++; + dbch->xferq.queued++; dbch->pdb_tr = db_tr; db_tr = STAILQ_NEXT(db_tr, link); - if(db_tr != dbch->bottom){ + if (db_tr != dbch->bottom) goto txloop; - } else { - fw_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n"); + else { + aprint_error_dev(sc->fc.dev, "fwohci_start: lack of db_trq\n"); dbch->flags |= FWOHCI_DBCH_FULL; } kick: /* kick asy q */ - fwdma_sync_multiseg_all(dbch->am, + fwdma_sync_multiseg(dbch->am, kick->idx, dbch->pdb_tr->idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - if(dbch->xferq.flag & FWXFERQ_RUNNING) { - OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); - } else { + if (dbch->xferq.flag & FWXFERQ_RUNNING) + OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE); + else { if (firewire_debug) - fw_printf(sc->fc.dev, "start AT DMA status=%x\n", - OREAD(sc, OHCI_DMACTL(off))); - OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | fsegment); - OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); + printf("start AT DMA status=%x\n", + OREAD(sc, OHCI_DMACTL(dbch->off))); + OWRITE(sc, OHCI_DMACMD(dbch->off), + dbch->top->bus_addr | fsegment); + OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN); dbch->xferq.flag |= FWXFERQ_RUNNING; } - CTR0(KTR_DEV, "start kick done"); - CTR0(KTR_DEV, "start kick done2"); dbch->top = db_tr; - splx(s); return; } @@ -1134,9 +1520,11 @@ static void fwohci_start_atq(struct firewire_comm *fc) { struct fwohci_softc *sc = (struct fwohci_softc *)fc; - FW_GLOCK(&sc->fc); - fwohci_start( sc, &(sc->atrq)); - FW_GUNLOCK(&sc->fc); + struct fwohci_dbch *dbch = &sc->atrq; + + mutex_enter(&dbch->xferq.q_mtx); + fwohci_start(sc, dbch); + mutex_exit(&dbch->xferq.q_mtx); return; } @@ -1144,84 +1532,88 @@ static void fwohci_start_ats(struct firewire_comm *fc) { struct fwohci_softc *sc = (struct fwohci_softc *)fc; - FW_GLOCK(&sc->fc); - fwohci_start( sc, &(sc->atrs)); - FW_GUNLOCK(&sc->fc); + struct fwohci_dbch *dbch = &sc->atrs; + + mutex_enter(&dbch->xferq.q_mtx); + fwohci_start(sc, dbch); + mutex_exit(&dbch->xferq.q_mtx); return; } -void +static void fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) { - int s, ch, err = 0; + struct firewire_comm *fc = &sc->fc; struct fwohcidb_tr *tr; struct fwohcidb *db; struct fw_xfer *xfer; - uint32_t off; u_int stat, status; - int packets; - struct firewire_comm *fc = (struct firewire_comm *)sc; + int packets = 0, ch, err = 0; - if(&sc->atrq == dbch){ - off = OHCI_ATQOFF; +#if DIAGNOSTIC + if (dbch->off != OHCI_ATQOFF && + dbch->off != OHCI_ATSOFF) + panic("not async tx"); +#endif + if (dbch->off == OHCI_ATQOFF) ch = ATRQ_CH; - }else if(&sc->atrs == dbch){ - off = OHCI_ATSOFF; + else /* OHCI_ATSOFF */ ch = ATRS_CH; - }else{ - return; - } - s = splfw(); + + mutex_enter(&dbch->xferq.q_mtx); tr = dbch->bottom; - packets = 0; - fwdma_sync_multiseg_all(dbch->am, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - while(dbch->xferq.queued > 0){ - LAST_DB(tr, db); + while (dbch->xferq.queued > 0) { + fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + db = LAST_DB(tr); status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT; - if(!(status & OHCI_CNTL_DMA_ACTIVE)){ - if (fc->status != FWBUSINIT) - /* maybe out of order?? */ + if (!(status & OHCI_CNTL_DMA_ACTIVE)) + if (fc->status != FWBUSINIT) goto out; - } if (tr->xfer->send.pay_len > 0) { - fw_bus_dmamap_sync(dbch->dmat, tr->dma_map, - BUS_DMASYNC_POSTWRITE); - fw_bus_dmamap_unload(dbch->dmat, tr->dma_map); + bus_dmamap_sync(fc->dmat, tr->dma_map, + 0, tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(fc->dmat, tr->dma_map); } #if 1 if (firewire_debug > 1) dump_db(sc, ch); #endif - if(status & OHCI_CNTL_DMA_DEAD) { + if (status & OHCI_CNTL_DMA_DEAD) { /* Stop DMA */ - OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); - fw_printf(sc->fc.dev, "force reset AT FIFO\n"); + OWRITE(sc, OHCI_DMACTLCLR(dbch->off), + OHCI_CNTL_DMA_RUN); + aprint_error_dev(fc->dev, "force reset AT FIFO\n"); OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN); OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN); - OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_DMACTLCLR(dbch->off), + OHCI_CNTL_DMA_RUN); } stat = status & FWOHCIEV_MASK; - switch(stat){ + switch(stat) { case FWOHCIEV_ACKPEND: - CTR0(KTR_DEV, "txd: ack pending"); - /* fall through */ + + /* FALLTHROUGH */ + case FWOHCIEV_ACKCOMPL: err = 0; break; + case FWOHCIEV_ACKBSA: case FWOHCIEV_ACKBSB: case FWOHCIEV_ACKBSX: - fw_printf(sc->fc.dev, "txd err=%2x %s\n", stat, + aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); err = EBUSY; break; + case FWOHCIEV_FLUSHED: case FWOHCIEV_ACKTARD: - fw_printf(sc->fc.dev, "txd err=%2x %s\n", stat, + aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); err = EAGAIN; break; + case FWOHCIEV_MISSACK: case FWOHCIEV_UNDRRUN: case FWOHCIEV_OVRRUN: @@ -1233,14 +1625,17 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) case FWOHCIEV_ACKDERR: case FWOHCIEV_ACKTERR: default: - fw_printf(sc->fc.dev, "txd err=%2x %s\n", - stat, fwohcicode[stat]); + aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat, + fwohcicode[stat]); err = EINVAL; break; } + dbch->xferq.queued--; + dbch->bottom = STAILQ_NEXT(tr, link); if (tr->xfer != NULL) { xfer = tr->xfer; - CTR0(KTR_DEV, "txd"); + tr->xfer = NULL; + mutex_exit(&dbch->xferq.q_mtx); if (xfer->flag & FWXF_RCVD) { #if 0 if (firewire_debug) @@ -1263,60 +1658,50 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) fw_xfer_done(xfer); } } + mutex_enter(&dbch->xferq.q_mtx); /* * The watchdog timer takes care of split * transcation timeout for ACKPEND case. */ - } else { - printf("this shouldn't happen\n"); - } - FW_GLOCK(fc); - dbch->xferq.queued --; - FW_GUNLOCK(fc); - tr->xfer = NULL; - - fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD); - packets ++; - tr = STAILQ_NEXT(tr, link); - dbch->bottom = tr; + } else + aprint_error_dev(fc->dev, "this shouldn't happen\n"); + packets++; if (dbch->bottom == dbch->top) { /* we reaches the end of context program */ if (firewire_debug && dbch->xferq.queued > 0) printf("queued > 0\n"); break; } + tr = dbch->bottom; } out: + if (dbch->xferq.queued > 0 || packets > 0) + fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) { - printf("make free slot\n"); + aprint_normal_dev(fc->dev, "make free slot\n"); dbch->flags &= ~FWOHCI_DBCH_FULL; - FW_GLOCK(fc); fwohci_start(sc, dbch); - FW_GUNLOCK(fc); } - fwdma_sync_multiseg_all( - dbch->am, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - splx(s); + mutex_exit(&dbch->xferq.q_mtx); } static void -fwohci_db_free(struct fwohci_dbch *dbch) +fwohci_db_free(struct fwohci_softc *sc, struct fwohci_dbch *dbch) { struct fwohcidb_tr *db_tr; - int idb; if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) return; - for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0; idb < dbch->ndb; - db_tr = STAILQ_NEXT(db_tr, link), idb++){ + for (db_tr = STAILQ_FIRST(&dbch->db_trq); db_tr != NULL; + db_tr = STAILQ_NEXT(db_tr, link)) { + bus_dmamap_destroy(sc->fc.dmat, db_tr->dma_map); if ((dbch->xferq.flag & FWXFERQ_EXTBUF) == 0 && - db_tr->buf != NULL) { - fwdma_free_size(dbch->dmat, db_tr->dma_map, - db_tr->buf, dbch->xferq.psize); + db_tr->buf != NULL) { + fwdma_free(sc->fc.dmat, db_tr->dma_map, db_tr->buf); db_tr->buf = NULL; - } else if (db_tr->dma_map != NULL) - fw_bus_dmamap_destroy(dbch->dmat, db_tr->dma_map); + } } dbch->ndb = 0; db_tr = STAILQ_FIRST(&dbch->db_trq); @@ -1330,74 +1715,82 @@ fwohci_db_free(struct fwohci_dbch *dbch) static void fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch) { - int idb; - struct fwohcidb_tr *db_tr; + struct firewire_comm *fc = &sc->fc; + struct fwohcidb_tr *db_tr, *lastq, *tmpq; + int idb; + const int db_tr_sz = sizeof(struct fwohcidb_tr) * dbch->ndb; if ((dbch->flags & FWOHCI_DBCH_INIT) != 0) goto out; - /* create dma_tag for buffers */ -#define MAX_REQCOUNT 0xffff - if (fw_bus_dma_tag_create(/*parent*/ sc->fc.dmat, - /*alignment*/ 1, /*boundary*/ 0, - /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/ BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/ dbch->xferq.psize, - /*nsegments*/ dbch->ndesc > 3 ? dbch->ndesc - 2 : 1, - /*maxsegsz*/ MAX_REQCOUNT, - /*flags*/ 0, - /*lockfunc*/busdma_lock_mutex, - /*lockarg*/FW_GMTX(&sc->fc), - &dbch->dmat)) - return; - /* allocate DB entries and attach one to each DMA channels */ /* DB entry must start at 16 bytes bounary. */ STAILQ_INIT(&dbch->db_trq); - db_tr = (struct fwohcidb_tr *) - malloc(sizeof(struct fwohcidb_tr) * dbch->ndb, - M_FW, M_WAITOK | M_ZERO); - if(db_tr == NULL){ - printf("fwohci_db_init: malloc(1) failed\n"); + db_tr = (struct fwohcidb_tr *)malloc(db_tr_sz, M_FW, M_WAITOK | M_ZERO); + if (db_tr == NULL) { + aprint_error_dev(fc->dev, "malloc(1) failed\n"); return; } #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc) - dbch->am = fwdma_malloc_multiseg(&sc->fc, DB_SIZE(dbch), - DB_SIZE(dbch), dbch->ndb, BUS_DMA_WAITOK | BUS_DMA_COHERENT); + dbch->am = fwdma_malloc_multiseg(fc, DB_SIZE(dbch), DB_SIZE(dbch), +#if 0 + dbch->ndb, BUS_DMA_WAITOK); +#else /* Ooops, debugging now... */ + dbch->ndb, BUS_DMA_WAITOK | + (dbch->off == OHCI_ARQOFF || dbch->off == OHCI_ARSOFF) ? + BUS_DMA_COHERENT : 0); +#endif if (dbch->am == NULL) { - printf("fwohci_db_init: fwdma_malloc_multiseg failed\n"); + aprint_error_dev(fc->dev, "fwdma_malloc_multiseg failed\n"); free(db_tr, M_FW); return; } /* Attach DB to DMA ch. */ - for(idb = 0 ; idb < dbch->ndb ; idb++){ + for (idb = 0; idb < dbch->ndb; idb++) { + db_tr->idx = idb; db_tr->dbcnt = 0; db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb); db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb); /* create dmamap for buffers */ - /* XXX do we need 4bytes alignment tag? */ - /* XXX don't alloc dma_map for AR */ - if (fw_bus_dmamap_create(dbch->dmat, 0, &db_tr->dma_map) != 0) { - printf("fw_bus_dmamap_create failed\n"); +#define MAX_REQCOUNT 0xffff + if (bus_dmamap_create(fc->dmat, dbch->xferq.psize, + dbch->ndesc > 3 ? dbch->ndesc - 2 : 1, MAX_REQCOUNT, 0, + 0, &db_tr->dma_map) != 0) { + aprint_error_dev(fc->dev, "bus_dmamap_create failed\n"); dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */ - fwohci_db_free(dbch); + fwohci_db_free(sc, dbch); return; } + if (dbch->off == OHCI_ARQOFF || + dbch->off == OHCI_ARSOFF) { + db_tr->buf = fwdma_malloc(fc->dev, fc->dmat, + &db_tr->dma_map, dbch->xferq.psize, 1, + BUS_DMA_NOWAIT); + if (db_tr->buf == NULL) { + aprint_error_dev(fc->dev, + "fwdma_malloc failed\n"); + dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */ + fwohci_db_free(sc, dbch); + return; + } + } STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link); if (dbch->xferq.flag & FWXFERQ_EXTBUF) { + struct fw_bulkxfer *bulkxfer = + &dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket]; + if (idb % dbch->xferq.bnpacket == 0) - dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket - ].start = (void *)db_tr; + bulkxfer->start = (void *)db_tr; if ((idb + 1) % dbch->xferq.bnpacket == 0) - dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket - ].end = (void *)db_tr; + bulkxfer->end = (void *)db_tr; } db_tr++; } - STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next - = STAILQ_FIRST(&dbch->db_trq); + lastq = NULL; + STAILQ_FOREACH(tmpq, &dbch->db_trq, link) + lastq = tmpq; + lastq->link.stqe_next = STAILQ_FIRST(&dbch->db_trq); out: dbch->xferq.queued = 0; dbch->pdb_tr = NULL; @@ -1408,186 +1801,115 @@ out: } static int -fwohci_itx_disable(struct firewire_comm *fc, int dmach) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)fc; - int sleepch; - - OWRITE(sc, OHCI_ITCTLCLR(dmach), - OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S); - OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); - OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); - /* XXX we cannot free buffers until the DMA really stops */ - tsleep((void *)&sleepch, FWPRI, "fwitxd", hz); - fwohci_db_free(&sc->it[dmach]); - sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING; - return 0; -} - -static int -fwohci_irx_disable(struct firewire_comm *fc, int dmach) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)fc; - int sleepch; - - OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); - OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); - /* XXX we cannot free buffers until the DMA really stops */ - tsleep((void *)&sleepch, FWPRI, "fwirxd", hz); - fwohci_db_free(&sc->ir[dmach]); - sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING; - return 0; -} - -#if BYTE_ORDER == BIG_ENDIAN -static void -fwohci_irx_post (struct firewire_comm *fc , uint32_t *qld) -{ - qld[0] = FWOHCI_DMA_READ(qld[0]); - return; -} -#endif - -static int fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) { int err = 0; int idb, z, i, dmach = 0, ldesc; - uint32_t off = 0; struct fwohcidb_tr *db_tr; struct fwohcidb *db; - if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){ + if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) { err = EINVAL; return err; } z = dbch->ndesc; - for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ - if( &sc->it[dmach] == dbch){ - off = OHCI_ITOFF(dmach); + for (dmach = 0; dmach < sc->fc.nisodma; dmach++) + if (dbch->off == sc->it[dmach].off) break; - } - } - if(off == 0){ + if (dmach == sc->fc.nisodma) { err = EINVAL; return err; } - if(dbch->xferq.flag & FWXFERQ_RUNNING) + if (dbch->xferq.flag & FWXFERQ_RUNNING) return err; dbch->xferq.flag |= FWXFERQ_RUNNING; - for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){ + for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++) dbch->bottom = STAILQ_NEXT(dbch->bottom, link); - } db_tr = dbch->top; - for (idb = 0; idb < dbch->ndb; idb ++) { + for (idb = 0; idb < dbch->ndb; idb++) { fwohci_add_tx_buf(dbch, db_tr, idb); - if(STAILQ_NEXT(db_tr, link) == NULL){ + if (STAILQ_NEXT(db_tr, link) == NULL) break; - } db = db_tr->db; ldesc = db_tr->dbcnt - 1; FWOHCI_DMA_WRITE(db[0].db.desc.depend, - STAILQ_NEXT(db_tr, link)->bus_addr | z); + STAILQ_NEXT(db_tr, link)->bus_addr | z); db[ldesc].db.desc.depend = db[0].db.desc.depend; - if(dbch->xferq.flag & FWXFERQ_EXTBUF){ - if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){ - FWOHCI_DMA_SET( - db[ldesc].db.desc.cmd, - OHCI_INTERRUPT_ALWAYS); + if (dbch->xferq.flag & FWXFERQ_EXTBUF) { + if (((idb + 1) % dbch->xferq.bnpacket) == 0) { + FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, + OHCI_INTERRUPT_ALWAYS); /* OHCI 1.1 and above */ - FWOHCI_DMA_SET( - db[0].db.desc.cmd, - OHCI_INTERRUPT_ALWAYS); + FWOHCI_DMA_SET(db[0].db.desc.cmd, + OHCI_INTERRUPT_ALWAYS); } } db_tr = STAILQ_NEXT(db_tr, link); } FWOHCI_DMA_CLEAR( - dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf); + dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf); return err; } static int fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) { - int err = 0; - int idb, z, i, dmach = 0, ldesc; - uint32_t off = 0; struct fwohcidb_tr *db_tr; struct fwohcidb *db; + int idb, z, i, ldesc, err = 0; z = dbch->ndesc; - if(&sc->arrq == dbch){ - off = OHCI_ARQOFF; - }else if(&sc->arrs == dbch){ - off = OHCI_ARSOFF; - }else{ - for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){ - if( &sc->ir[dmach] == dbch){ - off = OHCI_IROFF(dmach); - break; - } - } - } - if(off == 0){ - err = EINVAL; - return err; - } - if(dbch->xferq.flag & FWXFERQ_STREAM){ - if(dbch->xferq.flag & FWXFERQ_RUNNING) + if (dbch->xferq.flag & FWXFERQ_STREAM) { + if (dbch->xferq.flag & FWXFERQ_RUNNING) return err; - }else{ - if(dbch->xferq.flag & FWXFERQ_RUNNING){ + } else + if (dbch->xferq.flag & FWXFERQ_RUNNING) { err = EBUSY; return err; } - } dbch->xferq.flag |= FWXFERQ_RUNNING; dbch->top = STAILQ_FIRST(&dbch->db_trq); - for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){ + for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++) dbch->bottom = STAILQ_NEXT(dbch->bottom, link); - } db_tr = dbch->top; if (db_tr->dbcnt != 0) goto run; - for (idb = 0; idb < dbch->ndb; idb ++) { + for (idb = 0; idb < dbch->ndb; idb++) { + if (dbch->off == OHCI_ARQOFF || + dbch->off == OHCI_ARSOFF) + bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, + 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma); if (STAILQ_NEXT(db_tr, link) == NULL) break; db = db_tr->db; ldesc = db_tr->dbcnt - 1; FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend, - STAILQ_NEXT(db_tr, link)->bus_addr | z); - if(dbch->xferq.flag & FWXFERQ_EXTBUF){ - if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){ - FWOHCI_DMA_SET( - db[ldesc].db.desc.cmd, - OHCI_INTERRUPT_ALWAYS); - FWOHCI_DMA_CLEAR( - db[ldesc].db.desc.depend, - 0xf); + STAILQ_NEXT(db_tr, link)->bus_addr | z); + if (dbch->xferq.flag & FWXFERQ_EXTBUF) { + if (((idb + 1) % dbch->xferq.bnpacket) == 0) { + FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, + OHCI_INTERRUPT_ALWAYS); + FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf); } } db_tr = STAILQ_NEXT(db_tr, link); } - FWOHCI_DMA_CLEAR( - dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, 0xf); + FWOHCI_DMA_CLEAR(dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend, + 0xf); dbch->buf_offset = 0; run: fwdma_sync_multiseg_all(dbch->am, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - if(dbch->xferq.flag & FWXFERQ_STREAM){ - return err; - }else{ - OWRITE(sc, OHCI_DMACMD(off), dbch->top->bus_addr | z); + if (!(dbch->xferq.flag & FWXFERQ_STREAM)) { + OWRITE(sc, OHCI_DMACMD(dbch->off), dbch->top->bus_addr | z); + OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN); } - OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN); return err; } static int -fwohci_next_cycle(struct firewire_comm *fc, int cycle_now) +fwohci_next_cycle(struct fwohci_softc *sc, int cycle_now) { int sec, cycle, cycle_match; @@ -1601,12 +1923,12 @@ fwohci_next_cycle(struct firewire_comm *fc, int cycle_now) #endif cycle = cycle + CYCLE_DELAY; if (cycle >= 8000) { - sec ++; + sec++; cycle -= 8000; } cycle = roundup2(cycle, CYCLE_MOD); if (cycle >= 8000) { - sec ++; + sec++; if (cycle == 8000) cycle = 0; else @@ -1614,358 +1936,68 @@ fwohci_next_cycle(struct firewire_comm *fc, int cycle_now) } cycle_match = ((sec << 13) | cycle) & 0x7ffff; - return(cycle_match); -} - -static int -fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)fc; - int err = 0; - unsigned short tag, ich; - struct fwohci_dbch *dbch; - int cycle_match, cycle_now, s, ldesc; - uint32_t stat; - struct fw_bulkxfer *first, *chunk, *prev; - struct fw_xferq *it; - - dbch = &sc->it[dmach]; - it = &dbch->xferq; - - tag = (it->flag >> 6) & 3; - ich = it->flag & 0x3f; - if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) { - dbch->ndb = it->bnpacket * it->bnchunk; - dbch->ndesc = 3; - fwohci_db_init(sc, dbch); - if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) - return ENOMEM; - - err = fwohci_tx_enable(sc, dbch); - } - if(err) - return err; - - ldesc = dbch->ndesc - 1; - s = splfw(); - FW_GLOCK(fc); - prev = STAILQ_LAST(&it->stdma, fw_bulkxfer, link); - while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) { - struct fwohcidb *db; - - fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket, - BUS_DMASYNC_PREWRITE); - fwohci_txbufdb(sc, dmach, chunk); - if (prev != NULL) { - db = ((struct fwohcidb_tr *)(prev->end))->db; -#if 0 /* XXX necessary? */ - FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, - OHCI_BRANCH_ALWAYS); -#endif -#if 0 /* if bulkxfer->npacket changes */ - db[ldesc].db.desc.depend = db[0].db.desc.depend = - ((struct fwohcidb_tr *) - (chunk->start))->bus_addr | dbch->ndesc; -#else - FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc); - FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc); -#endif - } - STAILQ_REMOVE_HEAD(&it->stvalid, link); - STAILQ_INSERT_TAIL(&it->stdma, chunk, link); - prev = chunk; - } - FW_GUNLOCK(fc); - fwdma_sync_multiseg_all(dbch->am, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - splx(s); - stat = OREAD(sc, OHCI_ITCTL(dmach)); - if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S)) - printf("stat 0x%x\n", stat); - - if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S)) - return 0; - -#if 0 - OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN); -#endif - OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach); - OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach); - OWRITE(sc, OHCI_IT_MASK, 1 << dmach); - OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT); - - first = STAILQ_FIRST(&it->stdma); - OWRITE(sc, OHCI_ITCMD(dmach), - ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc); - if (firewire_debug > 1) { - printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat); -#if 1 - dump_dma(sc, ITX_CH + dmach); -#endif - } - if ((stat & OHCI_CNTL_DMA_RUN) == 0) { -#if 1 - /* Don't start until all chunks are buffered */ - if (STAILQ_FIRST(&it->stfree) != NULL) - goto out; -#endif -#if 1 - /* Clear cycle match counter bits */ - OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000); - - /* 2bit second + 13bit cycle */ - cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff; - cycle_match = fwohci_next_cycle(fc, cycle_now); - - OWRITE(sc, OHCI_ITCTL(dmach), - OHCI_CNTL_CYCMATCH_S | (cycle_match << 16) - | OHCI_CNTL_DMA_RUN); -#else - OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN); -#endif - if (firewire_debug > 1) { - printf("cycle_match: 0x%04x->0x%04x\n", - cycle_now, cycle_match); - dump_dma(sc, ITX_CH + dmach); - dump_db(sc, ITX_CH + dmach); - } - } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) { - fw_printf(sc->fc.dev, "IT DMA underrun (0x%08x)\n", stat); - OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE); - } -out: - return err; -} - -static int -fwohci_irx_enable(struct firewire_comm *fc, int dmach) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)fc; - int err = 0, s, ldesc; - unsigned short tag, ich; - uint32_t stat; - struct fwohci_dbch *dbch; - struct fwohcidb_tr *db_tr; - struct fw_bulkxfer *first, *prev, *chunk; - struct fw_xferq *ir; - - dbch = &sc->ir[dmach]; - ir = &dbch->xferq; - - if ((ir->flag & FWXFERQ_RUNNING) == 0) { - tag = (ir->flag >> 6) & 3; - ich = ir->flag & 0x3f; - OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich); - - ir->queued = 0; - dbch->ndb = ir->bnpacket * ir->bnchunk; - dbch->ndesc = 2; - fwohci_db_init(sc, dbch); - if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) - return ENOMEM; - err = fwohci_rx_enable(sc, dbch); - } - if(err) - return err; - - first = STAILQ_FIRST(&ir->stfree); - if (first == NULL) { - fw_printf(fc->dev, "IR DMA no free chunk\n"); - return 0; - } - - ldesc = dbch->ndesc - 1; - s = splfw(); - if ((ir->flag & FWXFERQ_HANDLER) == 0) - FW_GLOCK(fc); - prev = STAILQ_LAST(&ir->stdma, fw_bulkxfer, link); - while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) { - struct fwohcidb *db; - -#if 1 /* XXX for if_fwe */ - if (chunk->mbuf != NULL) { - db_tr = (struct fwohcidb_tr *)(chunk->start); - db_tr->dbcnt = 1; - err = fw_bus_dmamap_load_mbuf( - dbch->dmat, db_tr->dma_map, - chunk->mbuf, fwohci_execute_db2, db_tr, - BUS_DMA_WAITOK); - FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd, - OHCI_UPDATE | OHCI_INPUT_LAST | - OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS); - } -#endif - db = ((struct fwohcidb_tr *)(chunk->end))->db; - FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0); - FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf); - if (prev != NULL) { - db = ((struct fwohcidb_tr *)(prev->end))->db; - FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc); - } - STAILQ_REMOVE_HEAD(&ir->stfree, link); - STAILQ_INSERT_TAIL(&ir->stdma, chunk, link); - prev = chunk; - } - if ((ir->flag & FWXFERQ_HANDLER) == 0) - FW_GUNLOCK(fc); - fwdma_sync_multiseg_all(dbch->am, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - splx(s); - stat = OREAD(sc, OHCI_IRCTL(dmach)); - if (stat & OHCI_CNTL_DMA_ACTIVE) - return 0; - if (stat & OHCI_CNTL_DMA_RUN) { - OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); - fw_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat); - } - - if (firewire_debug) - printf("start IR DMA 0x%x\n", stat); - OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach); - OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach); - OWRITE(sc, OHCI_IR_MASK, 1 << dmach); - OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000); - OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR); - OWRITE(sc, OHCI_IRCMD(dmach), - ((struct fwohcidb_tr *)(first->start))->bus_addr - | dbch->ndesc); - OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN); - OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR); -#if 0 - dump_db(sc, IRX_CH + dmach); -#endif - return err; -} - -int -fwohci_stop(struct fwohci_softc *sc, device_t dev) -{ - u_int i; - -/* Now stopping all DMA channel */ - OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); - - for( i = 0 ; i < sc->fc.nisodma ; i ++ ){ - OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN); - OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); - } - - if (sc->fc.arq !=0 && sc->fc.arq->maxq > 0) - fw_drain_txq(&sc->fc); - -#if 0 /* Let dcons(4) be accessed */ -/* Stop interrupt */ - OWRITE(sc, FWOHCI_INTMASKCLR, - OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID - | OHCI_INT_PHY_INT - | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS - | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS - | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS - | OHCI_INT_PHY_BUS_R); - -/* FLUSH FIFO and reset Transmitter/Reciever */ - OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); -#endif - -/* XXX Link down? Bus reset? */ - return 0; -} - -int -fwohci_resume(struct fwohci_softc *sc, device_t dev) -{ - int i; - struct fw_xferq *ir; - struct fw_bulkxfer *chunk; - - fwohci_reset(sc, dev); - /* XXX resume isochronous receive automatically. (how about TX?) */ - for(i = 0; i < sc->fc.nisodma; i ++) { - ir = &sc->ir[i].xferq; - if((ir->flag & FWXFERQ_RUNNING) != 0) { - fw_printf(sc->fc.dev, - "resume iso receive ch: %d\n", i); - ir->flag &= ~FWXFERQ_RUNNING; - /* requeue stdma to stfree */ - while((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) { - STAILQ_REMOVE_HEAD(&ir->stdma, link); - STAILQ_INSERT_TAIL(&ir->stfree, chunk, link); - } - sc->fc.irx_enable(&sc->fc, i); - } - } - -#if defined(__FreeBSD__) - bus_generic_resume(dev); -#elif defined(__NetBSD__) - { - extern int firewire_resume(struct firewire_comm *); - firewire_resume(&sc->fc); - } -#endif - sc->fc.ibr(&sc->fc); - return 0; + return cycle_match; } #ifdef OHCI_DEBUG static void fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat) { - if(stat & OREAD(sc, FWOHCI_INTMASK)) - fw_printf(fc->dev, "INTERRUPT < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s> 0x%08x, 0x%08x\n", - stat & OHCI_INT_EN ? "DMA_EN ":"", - stat & OHCI_INT_PHY_REG ? "PHY_REG ":"", - stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"", - stat & OHCI_INT_ERR ? "INT_ERR ":"", - stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"", - stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"", - stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"", - stat & OHCI_INT_CYC_START ? "CYC_START ":"", - stat & OHCI_INT_PHY_INT ? "PHY_INT ":"", - stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"", - stat & OHCI_INT_PHY_SID ? "SID ":"", - stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"", - stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"", - stat & OHCI_INT_DMA_IR ? "DMA_IR ":"", - stat & OHCI_INT_DMA_IT ? "DMA_IT " :"", - stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"", - stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"", - stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"", - stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"", - stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"", - stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"", - stat, OREAD(sc, FWOHCI_INTMASK) + + if (stat & OREAD(sc, FWOHCI_INTMASK)) + print("%s: INTERRUPT" + " < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>" + " 0x%08x, 0x%08x\n", + device_xname(fc->dev), + stat & OHCI_INT_EN ? "DMA_EN ":"", + stat & OHCI_INT_PHY_REG ? "PHY_REG ":"", + stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"", + stat & OHCI_INT_ERR ? "INT_ERR ":"", + stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"", + stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"", + stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"", + stat & OHCI_INT_CYC_START ? "CYC_START ":"", + stat & OHCI_INT_PHY_INT ? "PHY_INT ":"", + stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"", + stat & OHCI_INT_PHY_SID ? "SID ":"", + stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"", + stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"", + stat & OHCI_INT_DMA_IR ? "DMA_IR ":"", + stat & OHCI_INT_DMA_IT ? "DMA_IT " :"", + stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"", + stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"", + stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"", + stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"", + stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"", + stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"", + stat, OREAD(sc, FWOHCI_INTMASK) ); } #endif + static void -fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count) +fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat) { - struct firewire_comm *fc = (struct firewire_comm *)sc; + struct firewire_comm *fc = &sc->fc; uint32_t node_id, plen; - CTR0(KTR_DEV, "fwohci_intr_core"); - if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) { fc->status = FWBUSRESET; /* Disable bus reset interrupt until sid recv. */ - OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R); + OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R); - fw_printf(fc->dev, "BUS reset\n"); - OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); + aprint_normal_dev(fc->dev, "BUS reset\n"); + OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC); - OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN); sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING; - OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); + OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING; - if (!kdb_active) - fw_taskqueue_enqueue(sc->fc.taskqueue, - &sc->fwohci_task_busreset); + fw_busreset(&sc->fc, FWBUSRESET); + OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); + OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); } if (stat & OHCI_INT_PHY_SID) { /* Enable bus reset interrupt */ @@ -1992,7 +2024,7 @@ fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count) plen = OREAD(sc, OHCI_SID_CNT); fc->nodeid = node_id & 0x3f; - fw_printf(fc->dev, "node_id=0x%08x, gen=%d, ", + aprint_normal_dev(fc->dev, "node_id=0x%08x, gen=%d, ", node_id, (plen >> 16) & 0xff); if (!(node_id & OHCI_NODE_VALID)) { aprint_error("Bus reset failure\n"); @@ -2001,7 +2033,7 @@ fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count) /* cycle timer */ sc->cycle_lost = 0; - OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST); + OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST); if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) { aprint_normal("CYCLEMASTER mode\n"); OWRITE(sc, OHCI_LNKCTL, @@ -2014,110 +2046,84 @@ fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count) fc->status = FWBUSINIT; - if (!kdb_active) - fw_taskqueue_enqueue(sc->fc.taskqueue, - &sc->fwohci_task_sid); + fwohci_task_sid(sc); } sidout: - if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active)) - fw_taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma); - - CTR0(KTR_DEV, "fwohci_intr_core done"); + if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID))) + fwohci_task_dma(sc); } static void -fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count) +fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat) { + struct firewire_comm *fc = &sc->fc; uint32_t irstat, itstat; u_int i; - struct firewire_comm *fc = (struct firewire_comm *)sc; - CTR0(KTR_DEV, "fwohci_intr_dma"); if (stat & OHCI_INT_DMA_IR) { - irstat = fw_atomic_readandclear_int(&sc->irstat); - for(i = 0; i < fc->nisodma ; i++){ - struct fwohci_dbch *dbch; + irstat = atomic_swap_32(&sc->irstat, 0); + for (i = 0; i < fc->nisodma; i++) + if ((irstat & (1 << i)) != 0) { + struct fwohci_dbch *dbch = &sc->ir[i]; - if((irstat & (1 << i)) != 0){ - dbch = &sc->ir[i]; if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) { - fw_printf(sc->fc.dev, - "dma(%d) not active\n", i); + aprint_error_dev(fc->dev, + "dma(%d) not active\n", i); continue; } fwohci_rbuf_update(sc, i); } - } } if (stat & OHCI_INT_DMA_IT) { - itstat = fw_atomic_readandclear_int(&sc->itstat); - for(i = 0; i < fc->nisodma ; i++){ - if((itstat & (1 << i)) != 0){ + itstat = atomic_swap_32(&sc->itstat, 0); + for (i = 0; i < fc->nisodma; i++) + if ((itstat & (1 << i)) != 0) fwohci_tbuf_update(sc, i); - } - } } if (stat & OHCI_INT_DMA_PRRS) { #if 0 dump_dma(sc, ARRS_CH); dump_db(sc, ARRS_CH); #endif - fwohci_arcv(sc, &sc->arrs, count); + fwohci_arcv(sc, &sc->arrs); } if (stat & OHCI_INT_DMA_PRRQ) { #if 0 dump_dma(sc, ARRQ_CH); dump_db(sc, ARRQ_CH); #endif - fwohci_arcv(sc, &sc->arrq, count); + fwohci_arcv(sc, &sc->arrq); } if (stat & OHCI_INT_CYC_LOST) { if (sc->cycle_lost >= 0) - sc->cycle_lost ++; + sc->cycle_lost++; if (sc->cycle_lost > 10) { sc->cycle_lost = -1; #if 0 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER); #endif - OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); - fw_printf(fc->dev, "too many cycle lost, " + OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); + aprint_error_dev(fc->dev, "too many cycle lost, " "no cycle master presents?\n"); } } - if (stat & OHCI_INT_DMA_ATRQ) { + if (stat & OHCI_INT_DMA_ATRQ) fwohci_txd(sc, &(sc->atrq)); - } - if (stat & OHCI_INT_DMA_ATRS) { + if (stat & OHCI_INT_DMA_ATRS) fwohci_txd(sc, &(sc->atrs)); - } - if (stat & OHCI_INT_PW_ERR) { - fw_printf(fc->dev, "posted write error\n"); - } - if (stat & OHCI_INT_ERR) { - fw_printf(fc->dev, "unrecoverable error\n"); - } - if (stat & OHCI_INT_PHY_INT) { - fw_printf(fc->dev, "phy int\n"); - } + if (stat & OHCI_INT_PW_ERR) + aprint_error_dev(fc->dev, "posted write error\n"); + if (stat & OHCI_INT_ERR) + aprint_error_dev(fc->dev, "unrecoverable error\n"); + if (stat & OHCI_INT_PHY_INT) + aprint_normal_dev(fc->dev, "phy int\n"); - CTR0(KTR_DEV, "fwohci_intr_dma done"); return; } static void -fwohci_task_busreset(void *arg, int pending) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)arg; - - fw_busreset(&sc->fc, FWBUSRESET); - OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); - OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); -} - -static void -fwohci_task_sid(void *arg, int pending) +fwohci_task_sid(struct fwohci_softc *sc) { - struct fwohci_softc *sc = (struct fwohci_softc *)arg; struct firewire_comm *fc = &sc->fc; uint32_t *buf; int i, plen; @@ -2125,28 +2131,28 @@ fwohci_task_sid(void *arg, int pending) plen = OREAD(sc, OHCI_SID_CNT); if (plen & OHCI_SID_ERR) { - fw_printf(fc->dev, "SID Error\n"); + aprint_error_dev(fc->dev, "SID Error\n"); return; } plen &= OHCI_SID_CNT_MASK; if (plen < 4 || plen > OHCI_SIDSIZE) { - fw_printf(fc->dev, "invalid SID len = %d\n", plen); + aprint_error_dev(fc->dev, "invalid SID len = %d\n", plen); return; } plen -= 4; /* chop control info */ buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT); if (buf == NULL) { - fw_printf(fc->dev, "malloc failed\n"); + aprint_error_dev(fc->dev, "malloc failed\n"); return; } - for (i = 0; i < plen / 4; i ++) - buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i+1]); + for (i = 0; i < plen / 4; i++) + buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]); #if 1 /* XXX needed?? */ /* pending all pre-bus_reset packets */ fwohci_txd(sc, &sc->atrq); fwohci_txd(sc, &sc->atrs); - fwohci_arcv(sc, &sc->arrs, -1); - fwohci_arcv(sc, &sc->arrq, -1); + fwohci_arcv(sc, &sc->arrs); + fwohci_arcv(sc, &sc->arrq); fw_drain_txq(fc); #endif fw_sidrcv(fc, buf, plen); @@ -2154,105 +2160,19 @@ fwohci_task_sid(void *arg, int pending) } static void -fwohci_task_dma(void *arg, int pending) +fwohci_task_dma(struct fwohci_softc *sc) { - struct fwohci_softc *sc = (struct fwohci_softc *)arg; uint32_t stat; again: - stat = fw_atomic_readandclear_int(&sc->intstat); + stat = atomic_swap_32(&sc->intstat, 0); if (stat) - fwohci_intr_dma(sc, stat, -1); + fwohci_intr_dma(sc, stat); else return; goto again; } -static int -fwohci_check_stat(struct fwohci_softc *sc) -{ - uint32_t stat, irstat, itstat; - - stat = OREAD(sc, FWOHCI_INTSTAT); - CTR1(KTR_DEV, "fwoch_check_stat 0x%08x", stat); - if (stat == 0xffffffff) { - fw_printf(sc->fc.dev, - "device physically ejected?\n"); - return (FILTER_STRAY); - } - if (stat) - OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R); - - stat &= sc->intmask; - if (stat == 0) - return (FILTER_STRAY); - - fw_atomic_set_int(&sc->intstat, stat); - if (stat & OHCI_INT_DMA_IR) { - irstat = OREAD(sc, OHCI_IR_STAT); - OWRITE(sc, OHCI_IR_STATCLR, irstat); - fw_atomic_set_int(&sc->irstat, irstat); - } - if (stat & OHCI_INT_DMA_IT) { - itstat = OREAD(sc, OHCI_IT_STAT); - OWRITE(sc, OHCI_IT_STATCLR, itstat); - fw_atomic_set_int(&sc->itstat, itstat); - } - - fwohci_intr_core(sc, stat, -1); - return (FILTER_HANDLED); -} - -int -fwohci_filt(void *arg) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)arg; - -#if defined(__NetBSD__) - if (!device_is_active(sc->fc.dev)) - return (FILTER_STRAY); -#endif - - if (!(sc->intmask & OHCI_INT_EN)) { - /* polling mode */ - return (FILTER_STRAY); - } - return (fwohci_check_stat(sc)); -} - -void -fwohci_intr(void *arg) -{ - - fwohci_filt(arg); - CTR0(KTR_DEV, "fwohci_intr end"); -} - -void -fwohci_poll(struct firewire_comm *fc, int quick, int count) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)fc; - - fwohci_check_stat(sc); -} - -static void -fwohci_set_intr(struct firewire_comm *fc, int enable) -{ - struct fwohci_softc *sc; - - sc = (struct fwohci_softc *)fc; - if (firewire_debug) - fw_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable); - if (enable) { - sc->intmask |= OHCI_INT_EN; - OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN); - } else { - sc->intmask &= ~OHCI_INT_EN; - OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); - } -} - static void fwohci_tbuf_update(struct fwohci_softc *sc, int dmach) { @@ -2261,42 +2181,40 @@ fwohci_tbuf_update(struct fwohci_softc *sc, int dmach) struct fw_bulkxfer *chunk; struct fw_xferq *it; uint32_t stat, count; - int s, w=0, ldesc; + int w = 0, ldesc; it = fc->it[dmach]; ldesc = sc->it[dmach].ndesc - 1; - s = splfw(); /* unnecessary ? */ - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD); if (firewire_debug) dump_db(sc, ITX_CH + dmach); while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) { db = ((struct fwohcidb_tr *)(chunk->end))->db; - stat = FWOHCI_DMA_READ(db[ldesc].db.desc.res) - >> OHCI_STATUS_SHIFT; + stat = + FWOHCI_DMA_READ(db[ldesc].db.desc.res) >> OHCI_STATUS_SHIFT; db = ((struct fwohcidb_tr *)(chunk->start))->db; /* timestamp */ - count = FWOHCI_DMA_READ(db[ldesc].db.desc.res) - & OHCI_COUNT_MASK; + count = + FWOHCI_DMA_READ(db[ldesc].db.desc.res) & OHCI_COUNT_MASK; if (stat == 0) break; STAILQ_REMOVE_HEAD(&it->stdma, link); - switch (stat & FWOHCIEV_MASK){ + switch (stat & FWOHCIEV_MASK) { case FWOHCIEV_ACKCOMPL: #if 0 - fw_printf(fc->dev, "0x%08x\n", count); + printf("0x%08x\n", count); #endif break; default: - fw_printf(fc->dev, - "Isochronous transmit err %02x(%s)\n", - stat, fwohcicode[stat & 0x1f]); + aprint_error_dev(fc->dev, + "Isochronous transmit err %02x(%s)\n", + stat, fwohcicode[stat & 0x1f]); } STAILQ_INSERT_TAIL(&it->stfree, chunk, link); w++; } - FW_GUNLOCK(fc); - splx(s); + mutex_exit(&fc->fc_mtx); if (w) wakeup(it); } @@ -2309,7 +2227,7 @@ fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) struct fw_bulkxfer *chunk; struct fw_xferq *ir; uint32_t stat; - int s, w = 0, ldesc; + int w = 0, ldesc; ir = fc->ir[dmach]; ldesc = sc->ir[dmach].ndesc - 1; @@ -2317,29 +2235,27 @@ fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) #if 0 dump_db(sc, dmach); #endif - s = splfw(); if ((ir->flag & FWXFERQ_HANDLER) == 0) - FW_GLOCK(fc); + mutex_enter(&fc->fc_mtx); fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD); while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) { db_tr = (struct fwohcidb_tr *)chunk->end; - stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res) - >> OHCI_STATUS_SHIFT; + stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res) >> + OHCI_STATUS_SHIFT; if (stat == 0) break; if (chunk->mbuf != NULL) { - fw_bus_dmamap_sync(sc->ir[dmach].dmat, db_tr->dma_map, - BUS_DMASYNC_POSTREAD); - fw_bus_dmamap_unload( - sc->ir[dmach].dmat, db_tr->dma_map); - } else if (ir->buf != NULL) { + bus_dmamap_sync(fc->dmat, db_tr->dma_map, 0, + db_tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(fc->dmat, db_tr->dma_map); + } else if (ir->buf != NULL) fwdma_sync_multiseg(ir->buf, chunk->poffset, - ir->bnpacket, BUS_DMASYNC_POSTREAD); - } else { + ir->bnpacket, BUS_DMASYNC_POSTREAD); + else /* XXX */ - printf("fwohci_rbuf_update: this shouldn't happend\n"); - } + aprint_error_dev(fc->dev, + "fwohci_rbuf_update: this shouldn't happend\n"); STAILQ_REMOVE_HEAD(&ir->stdma, link); STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link); @@ -2349,14 +2265,14 @@ fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) break; default: chunk->resp = EINVAL; - fw_printf(fc->dev, "Isochronous receive err %02x(%s)\n", - stat, fwohcicode[stat & 0x1f]); + aprint_error_dev(fc->dev, + "Isochronous receive err %02x(%s)\n", + stat, fwohcicode[stat & 0x1f]); } w++; } if ((ir->flag & FWXFERQ_HANDLER) == 0) - FW_GUNLOCK(fc); - splx(s); + mutex_exit(&fc->fc_mtx); if (w == 0) return; if (ir->flag & FWXFERQ_HANDLER) @@ -2365,251 +2281,195 @@ fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) wakeup(ir); } -void +static void dump_dma(struct fwohci_softc *sc, uint32_t ch) { - uint32_t off, cntl, stat, cmd, match; - - if(ch == 0){ - off = OHCI_ATQOFF; - }else if(ch == 1){ - off = OHCI_ATSOFF; - }else if(ch == 2){ - off = OHCI_ARQOFF; - }else if(ch == 3){ - off = OHCI_ARSOFF; - }else if(ch < IRX_CH){ - off = OHCI_ITCTL(ch - ITX_CH); - }else{ - off = OHCI_IRCTL(ch - IRX_CH); - } - cntl = stat = OREAD(sc, off); - cmd = OREAD(sc, off + 0xc); - match = OREAD(sc, off + 0x10); - - fw_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n", - ch, - cntl, - cmd, - match); - stat &= 0xffff ; - if (stat) { - fw_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n", - ch, - stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", - stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", - stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", - stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", - stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", - stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", - fwohcicode[stat & 0x1f], - stat & 0x1f + struct fwohci_dbch *dbch; + uint32_t cntl, stat, cmd, match; + + if (ch == ATRQ_CH) + dbch = &sc->atrq; + else if (ch == ATRS_CH) + dbch = &sc->atrs; + else if (ch == ARRQ_CH) + dbch = &sc->arrq; + else if (ch == ARRS_CH) + dbch = &sc->arrs; + else if (ch < IRX_CH) + dbch = &sc->it[ch - ITX_CH]; + else + dbch = &sc->ir[ch - IRX_CH]; + cntl = stat = OREAD(sc, dbch->off); + cmd = OREAD(sc, dbch->off + 0xc); + match = OREAD(sc, dbch->off + 0x10); + + aprint_normal_dev(sc->fc.dev, + "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n", + ch, + cntl, + cmd, + match); + stat &= 0xffff; + if (stat) + aprint_normal_dev(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n", + ch, + stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", + stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", + stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", + stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", + stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", + stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", + fwohcicode[stat & 0x1f], + stat & 0x1f ); - }else{ - fw_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch); - } + else + aprint_normal_dev(sc->fc.dev, "dma %d ch: Nostat\n", ch); } -void +static void dump_db(struct fwohci_softc *sc, uint32_t ch) { struct fwohci_dbch *dbch; struct fwohcidb_tr *cp = NULL, *pp, *np = NULL; struct fwohcidb *curr = NULL, *prev, *next = NULL; int idb, jdb; - uint32_t cmd, off; - if(ch == 0){ - off = OHCI_ATQOFF; + uint32_t cmd; + + if (ch == ATRQ_CH) dbch = &sc->atrq; - }else if(ch == 1){ - off = OHCI_ATSOFF; + else if (ch == ATRS_CH) dbch = &sc->atrs; - }else if(ch == 2){ - off = OHCI_ARQOFF; + else if (ch == ARRQ_CH) dbch = &sc->arrq; - }else if(ch == 3){ - off = OHCI_ARSOFF; + else if (ch == ARRS_CH) dbch = &sc->arrs; - }else if(ch < IRX_CH){ - off = OHCI_ITCTL(ch - ITX_CH); + else if (ch < IRX_CH) dbch = &sc->it[ch - ITX_CH]; - }else { - off = OHCI_IRCTL(ch - IRX_CH); + else dbch = &sc->ir[ch - IRX_CH]; - } - cmd = OREAD(sc, off + 0xc); + cmd = OREAD(sc, dbch->off + 0xc); - if( dbch->ndb == 0 ){ - fw_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch); + if (dbch->ndb == 0) { + aprint_error_dev(sc->fc.dev, "No DB is attached ch=%d\n", ch); return; } pp = dbch->top; prev = pp->db; - for(idb = 0 ; idb < dbch->ndb ; idb ++ ){ + for (idb = 0; idb < dbch->ndb; idb++) { cp = STAILQ_NEXT(pp, link); - if(cp == NULL){ + if (cp == NULL) { curr = NULL; goto outdb; } np = STAILQ_NEXT(cp, link); - for(jdb = 0 ; jdb < dbch->ndesc ; jdb ++ ){ - if ((cmd & 0xfffffff0) == cp->bus_addr) { + for (jdb = 0; jdb < dbch->ndesc; jdb++) + if ((cmd & 0xfffffff0) == cp->bus_addr) { curr = cp->db; - if(np != NULL){ + if (np != NULL) next = np->db; - }else{ + else next = NULL; - } goto outdb; } - } pp = STAILQ_NEXT(pp, link); - if(pp == NULL){ + if (pp == NULL) { curr = NULL; goto outdb; } prev = pp->db; } outdb: - if( curr != NULL){ + if (curr != NULL) { #if 0 - printf("Prev DB %d\n", ch); + aprint_normal("Prev DB %d\n", ch); print_db(pp, prev, ch, dbch->ndesc); #endif - printf("Current DB %d\n", ch); + aprint_normal("Current DB %d\n", ch); print_db(cp, curr, ch, dbch->ndesc); #if 0 - printf("Next DB %d\n", ch); + aprint_normal("Next DB %d\n", ch); print_db(np, next, ch, dbch->ndesc); #endif - }else{ - printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd); - } + } else + aprint_error("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd); return; } -void -print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db, - uint32_t ch, uint32_t hogemax) +static void +print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db, uint32_t ch, + uint32_t hogemax) { fwohcireg_t stat; int i, key; uint32_t cmd, res; - if(db == NULL){ - printf("No Descriptor is found\n"); + if (db == NULL) { + aprint_error("No Descriptor is found\n"); return; } - printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n", - ch, - "Current", - "OP ", - "KEY", - "INT", - "BR ", - "len", - "Addr", - "Depend", - "Stat", - "Cnt"); - for( i = 0 ; i <= hogemax ; i ++){ + aprint_normal("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n", + ch, + "Current", + "OP ", + "KEY", + "INT", + "BR ", + "len", + "Addr", + "Depend", + "Stat", + "Cnt"); + for (i = 0; i <= hogemax; i++) { cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd); res = FWOHCI_DMA_READ(db[i].db.desc.res); key = cmd & OHCI_KEY_MASK; stat = res >> OHCI_STATUS_SHIFT; -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - printf("%08x %s %s %s %s %5d %08x %08x %04x:%04x", - db_tr->bus_addr, -#else - printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x", - (uintmax_t)db_tr->bus_addr, -#endif - dbcode[(cmd >> 28) & 0xf], - dbkey[(cmd >> 24) & 0x7], - dbcond[(cmd >> 20) & 0x3], - dbcond[(cmd >> 18) & 0x3], - cmd & OHCI_COUNT_MASK, - FWOHCI_DMA_READ(db[i].db.desc.addr), - FWOHCI_DMA_READ(db[i].db.desc.depend), - stat, - res & OHCI_COUNT_MASK); - if(stat & 0xff00){ - printf(" %s%s%s%s%s%s %s(%x)\n", - stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", - stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", - stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", - stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", - stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", - stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", - fwohcicode[stat & 0x1f], - stat & 0x1f + aprint_normal("%08jx %s %s %s %s %5d %08x %08x %04x:%04x", + (uintmax_t)db_tr->bus_addr, + dbcode[(cmd >> 28) & 0xf], + dbkey[(cmd >> 24) & 0x7], + dbcond[(cmd >> 20) & 0x3], + dbcond[(cmd >> 18) & 0x3], + cmd & OHCI_COUNT_MASK, + FWOHCI_DMA_READ(db[i].db.desc.addr), + FWOHCI_DMA_READ(db[i].db.desc.depend), + stat, + res & OHCI_COUNT_MASK); + if (stat & 0xff00) + aprint_normal(" %s%s%s%s%s%s %s(%x)\n", + stat & OHCI_CNTL_DMA_RUN ? "RUN," : "", + stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "", + stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "", + stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "", + stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "", + stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "", + fwohcicode[stat & 0x1f], + stat & 0x1f ); - }else{ - printf(" Nostat\n"); - } - if(key == OHCI_KEY_ST2 ){ - printf("0x%08x 0x%08x 0x%08x 0x%08x\n", - FWOHCI_DMA_READ(db[i+1].db.immed[0]), - FWOHCI_DMA_READ(db[i+1].db.immed[1]), - FWOHCI_DMA_READ(db[i+1].db.immed[2]), - FWOHCI_DMA_READ(db[i+1].db.immed[3])); - } - if(key == OHCI_KEY_DEVICE){ + else + aprint_normal(" Nostat\n"); + if (key == OHCI_KEY_ST2) + aprint_normal("0x%08x 0x%08x 0x%08x 0x%08x\n", + FWOHCI_DMA_READ(db[i+1].db.immed[0]), + FWOHCI_DMA_READ(db[i+1].db.immed[1]), + FWOHCI_DMA_READ(db[i+1].db.immed[2]), + FWOHCI_DMA_READ(db[i+1].db.immed[3])); + if (key == OHCI_KEY_DEVICE) return; - } - if((cmd & OHCI_BRANCH_MASK) - == OHCI_BRANCH_ALWAYS){ + if ((cmd & OHCI_BRANCH_MASK) == OHCI_BRANCH_ALWAYS) return; - } - if((cmd & OHCI_CMD_MASK) - == OHCI_OUTPUT_LAST){ + if ((cmd & OHCI_CMD_MASK) == OHCI_OUTPUT_LAST) return; - } - if((cmd & OHCI_CMD_MASK) - == OHCI_INPUT_LAST){ + if ((cmd & OHCI_CMD_MASK) == OHCI_INPUT_LAST) return; - } - if(key == OHCI_KEY_ST2 ){ + if (key == OHCI_KEY_ST2) i++; - } } return; } -void -fwohci_ibr(struct firewire_comm *fc) -{ - struct fwohci_softc *sc; - uint32_t fun; - - fw_printf(fc->dev, "Initiate bus reset\n"); - sc = (struct fwohci_softc *)fc; - - /* - * Make sure our cached values from the config rom are - * initialised. - */ - OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); - OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); - - /* - * Set root hold-off bit so that non cyclemaster capable node - * shouldn't became the root node. - */ -#if 1 - fun = fwphy_rddata(sc, FW_PHY_IBR_REG); - fun |= FW_PHY_IBR | FW_PHY_RHB; - fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun); -#else /* Short bus reset */ - fun = fwphy_rddata(sc, FW_PHY_ISBR_REG); - fun |= FW_PHY_ISBR | FW_PHY_RHB; - fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun); -#endif -} - -void +static void fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) { struct fwohcidb_tr *db_tr, *fdb_tr; @@ -2620,7 +2480,7 @@ fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) unsigned short chtag; int idb; - FW_GLOCK_ASSERT(&sc->fc); + KASSERT(mutex_owner(&sc->fc.fc_mtx)); dbch = &sc->it[dmach]; chtag = sc->it[dmach].xferq.flag & 0xff; @@ -2628,9 +2488,9 @@ fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) db_tr = (struct fwohcidb_tr *)(bulkxfer->start); fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end); /* -fw_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr); +aprint_normal(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr); */ - for (idb = 0; idb < dbch->xferq.bnpacket; idb ++) { + for (idb = 0; idb < dbch->xferq.bnpacket; idb++) { db = db_tr->db; fp = (struct fw_pkt *)db_tr->buf; ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed; @@ -2648,12 +2508,10 @@ fw_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr-> FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len); FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); #if 0 /* if bulkxfer->npackets changes */ - db[2].db.desc.cmd = OHCI_OUTPUT_LAST - | OHCI_UPDATE - | OHCI_BRANCH_ALWAYS; - db[0].db.desc.depend = - = db[dbch->ndesc - 1].db.desc.depend - = STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc; + db[2].db.desc.cmd = + OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS; + db[0].db.desc.depend = db[dbch->ndesc - 1].db.desc.depend = + STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc; #else FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc); FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc); @@ -2672,21 +2530,21 @@ fw_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr-> /* db_tr = (struct fwohcidb_tr *)bulkxfer->start; fdb_tr = (struct fwohcidb_tr *)bulkxfer->end; -fw_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr); +aprint_normal(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr); */ return; } static int fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, - int poffset) + int poffset) { struct fwohcidb *db = db_tr->db; struct fw_xferq *it; int err = 0; it = &dbch->xferq; - if(it->buf == 0){ + if (it->buf == 0) { err = EINVAL; return err; } @@ -2694,14 +2552,14 @@ fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, db_tr->dbcnt = 3; FWOHCI_DMA_WRITE(db[0].db.desc.cmd, - OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8); + OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8); FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0); - memset((void *)&db[1].db.immed[0], 0, sizeof(db[1].db.immed)); + memset((void *)db[1].db.immed, 0, sizeof(db[1].db.immed)); FWOHCI_DMA_WRITE(db[2].db.desc.addr, fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t)); FWOHCI_DMA_WRITE(db[2].db.desc.cmd, - OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS); + OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS); #if 1 FWOHCI_DMA_WRITE(db[0].db.desc.res, 0); FWOHCI_DMA_WRITE(db[2].db.desc.res, 0); @@ -2711,51 +2569,42 @@ fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, int fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr, - int poffset, struct fwdma_alloc *dummy_dma) + int poffset, struct fwdma_alloc *dummy_dma) { struct fwohcidb *db = db_tr->db; - struct fw_xferq *ir; + struct fw_xferq *rq; int i, ldesc; bus_addr_t dbuf[2]; int dsiz[2]; - ir = &dbch->xferq; - if (ir->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) { - if (db_tr->buf == NULL) - db_tr->buf = fwdma_malloc_size( - dbch->dmat, &db_tr->dma_map, - ir->psize, &dbuf[0], BUS_DMA_NOWAIT); - if (db_tr->buf == NULL) - return(ENOMEM); + rq = &dbch->xferq; + if (rq->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) { + /* async */ db_tr->dbcnt = 1; - dsiz[0] = ir->psize; - fw_bus_dmamap_sync(dbch->dmat, db_tr->dma_map, - BUS_DMASYNC_PREREAD); + dsiz[0] = rq->psize; + dbuf[0] = db_tr->dma_map->dm_segs[0].ds_addr; } else { + /* isoc */ db_tr->dbcnt = 0; - if (dummy_dma != NULL) { - dsiz[db_tr->dbcnt] = sizeof(uint32_t); - dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr; - } - dsiz[db_tr->dbcnt] = ir->psize; - if (ir->buf != NULL) { - db_tr->buf = fwdma_v_addr(ir->buf, poffset); - dbuf[db_tr->dbcnt] = fwdma_bus_addr( ir->buf, poffset); + dsiz[db_tr->dbcnt] = sizeof(uint32_t); + dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr; + dsiz[db_tr->dbcnt] = rq->psize; + if (rq->buf != NULL) { + db_tr->buf = fwdma_v_addr(rq->buf, poffset); + dbuf[db_tr->dbcnt] = fwdma_bus_addr(rq->buf, poffset); } db_tr->dbcnt++; } - for(i = 0 ; i < db_tr->dbcnt ; i++){ + for (i = 0; i < db_tr->dbcnt; i++) { FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]); FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]); - if (ir->flag & FWXFERQ_STREAM) { + if (rq->flag & FWXFERQ_STREAM) FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE); - } FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]); } ldesc = db_tr->dbcnt - 1; - if (ir->flag & FWXFERQ_STREAM) { + if (rq->flag & FWXFERQ_STREAM) FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST); - } FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS); return 0; } @@ -2779,13 +2628,13 @@ fwohci_arcv_swap(struct fw_pkt *fp, int len) /* determine length to swap */ switch (fp0->mode.common.tcode) { case FWTCODE_WRES: - CTR0(KTR_DEV, "WRES"); case FWTCODE_RREQQ: case FWTCODE_WREQQ: case FWTCODE_RRESQ: case FWOHCITCODE_PHY: slen = 12; break; + case FWTCODE_RREQB: case FWTCODE_WREQB: case FWTCODE_LREQ: @@ -2793,44 +2642,46 @@ fwohci_arcv_swap(struct fw_pkt *fp, int len) case FWTCODE_LRES: slen = 16; break; + default: - printf("Unknown tcode %d\n", fp0->mode.common.tcode); - return(0); + aprint_error("Unknown tcode %d\n", fp0->mode.common.tcode); + return 0; } hlen = tinfo[fp0->mode.common.tcode].hdr_len; if (hlen > len) { if (firewire_debug) printf("splitted header\n"); - return(-hlen); + return len - hlen; } #if BYTE_ORDER == BIG_ENDIAN - for(i = 0; i < slen/4; i ++) + for (i = 0; i < slen / 4; i++) fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]); #endif - return(hlen); + return hlen; } static int -fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp) +fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, + struct fw_pkt *fp) { const struct tcode_info *info; int r; info = &tinfo[fp->mode.common.tcode]; r = info->hdr_len + sizeof(uint32_t); - if ((info->flag & FWTI_BLOCK_ASY) != 0) + if (info->flag & FWTI_BLOCK_ASY) r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t)); if (r == sizeof(uint32_t)) { /* XXX */ - fw_printf(sc->fc.dev, "Unknown tcode %d\n", - fp->mode.common.tcode); - return (-1); + aprint_error_dev(sc->fc.dev, "Unknown tcode %d\n", + fp->mode.common.tcode); + return -1; } if (r > dbch->xferq.psize) { - fw_printf(sc->fc.dev, "Invalid packet length %d\n", r); - return (-1); + aprint_error_dev(sc->fc.dev, "Invalid packet length %d\n", r); + return -1; /* panic ? */ } @@ -2839,103 +2690,108 @@ fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt static void fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch, - struct fwohcidb_tr *db_tr, uint32_t off, int wake) + struct fwohcidb_tr *db_tr, int wake) { - struct fwohcidb *db = &db_tr->db[0]; + struct fwohcidb *db = db_tr->db; + struct fwohcidb_tr *bdb_tr = dbch->bottom; FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf); FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize); - FWOHCI_DMA_SET(dbch->bottom->db[0].db.desc.depend, 1); - fwdma_sync_multiseg_all(dbch->am, + + fwdma_sync_multiseg(dbch->am, bdb_tr->idx, bdb_tr->idx, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + FWOHCI_DMA_SET(bdb_tr->db[0].db.desc.depend, dbch->ndesc); + + fwdma_sync_multiseg(dbch->am, bdb_tr->idx, db_tr->idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); dbch->bottom = db_tr; if (wake) - OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); + OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE); } static void -fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) +fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch) { struct fwohcidb_tr *db_tr; + struct fw_pkt pktbuf, *fp; struct iovec vec[2]; - struct fw_pkt pktbuf; - int nvec; - struct fw_pkt *fp; - uint8_t *ld; - uint32_t stat, off, status, event; + bus_addr_t m; + bus_size_t n; u_int spd; - int len, plen, hlen, pcnt, offset; - int s; - void *buf; - int resCount; - - CTR0(KTR_DEV, "fwohci_arv"); - - if(&sc->arrq == dbch){ - off = OHCI_ARQOFF; - }else if(&sc->arrs == dbch){ - off = OHCI_ARSOFF; - }else{ - return; - } + uint32_t stat, status, event; + uint8_t *ld; + int nvec, resCount, len, plen, hlen, offset; + const int psize = dbch->xferq.psize; +#if 0 +static int prev_resCounts[16], i; +#endif + +#if DIAGNOSTIC + if (dbch->off != OHCI_ARQOFF && + dbch->off != OHCI_ARSOFF) + panic("not async rx"); +#endif - s = splfw(); + mutex_enter(&dbch->xferq.q_mtx); db_tr = dbch->top; - pcnt = 0; /* XXX we cannot handle a packet which lies in more than two buf */ - fwdma_sync_multiseg_all(dbch->am, + fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT; resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK; while (status & OHCI_CNTL_DMA_ACTIVE) { #if 0 - - if (off == OHCI_ARQOFF) - printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n", +prev_resCounts[i] = resCount; +i = (i + 1) & 0xf; +#endif +#if 0 + if (dbch->off == OHCI_ARQOFF) + aprint_normal_dev(sc->fc.dev, + "buf 0x%08x, status 0x%04x, resCount 0x%04x\n", db_tr->bus_addr, status, resCount); #endif - len = dbch->xferq.psize - resCount; + n = 0; + len = psize - resCount; ld = (uint8_t *)db_tr->buf; if (dbch->pdb_tr == NULL) { len -= dbch->buf_offset; ld += dbch->buf_offset; - } + m = dbch->buf_offset; + } else + m = 0; if (len > 0) - fw_bus_dmamap_sync(dbch->dmat, db_tr->dma_map, - BUS_DMASYNC_POSTREAD); - while (len > 0 ) { - if (count >= 0 && count-- == 0) - goto out; - if(dbch->pdb_tr != NULL){ + bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, + m, len, BUS_DMASYNC_POSTREAD); + while (len > 0) { + if (dbch->pdb_tr != NULL) { /* we have a fragment in previous buffer */ - int rlen; + int rlen = 0; + void *buf; - offset = dbch->buf_offset; - if (offset < 0) - offset = - offset; - buf = (char *)dbch->pdb_tr->buf + offset; - rlen = dbch->xferq.psize - offset; - if (firewire_debug) - printf("rlen=%d, offset=%d\n", - rlen, dbch->buf_offset); if (dbch->buf_offset < 0) { /* splitted in header, pull up */ char *p; + rlen -= dbch->buf_offset; + buf = (char *)dbch->pdb_tr->buf + + psize - rlen; + + KASSERT(rlen <= sizeof(pktbuf)); + p = (char *)&pktbuf; memcpy(p, buf, rlen); p += rlen; /* this must be too long but harmless */ rlen = sizeof(pktbuf) - rlen; - if (rlen < 0) - printf("why rlen < 0\n"); memcpy(p, db_tr->buf, rlen); ld += rlen; len -= rlen; - hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf)); + hlen = fwohci_arcv_swap(&pktbuf, + sizeof(pktbuf)); if (hlen <= 0) { - printf("hlen should be positive."); + aprint_error_dev(sc->fc.dev, + "hlen should be positive."); goto err; } offset = sizeof(pktbuf); @@ -2943,24 +2799,31 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) vec[0].iov_len = offset; } else { /* splitted in payload */ + buf = (char *)dbch->pdb_tr->buf + + dbch->buf_offset; + rlen = psize - dbch->buf_offset; + if (firewire_debug) + printf("rlen=%d, offset=%d\n", + rlen, dbch->buf_offset); offset = rlen; vec[0].iov_base = buf; vec[0].iov_len = rlen; } - fp=(struct fw_pkt *)vec[0].iov_base; + fp = (struct fw_pkt *)vec[0].iov_base; nvec = 1; } else { /* no fragment in previous buffer */ - fp=(struct fw_pkt *)ld; + fp = (struct fw_pkt *)ld; hlen = fwohci_arcv_swap(fp, len); if (hlen == 0) goto err; if (hlen < 0) { dbch->pdb_tr = db_tr; - dbch->buf_offset = - dbch->buf_offset; + dbch->buf_offset -= psize; /* sanity check */ if (resCount != 0) { - printf("resCount=%d hlen=%d\n", + aprint_error_dev(sc->fc.dev, + "resCount=%d hlen=%d\n", resCount, hlen); goto err; } @@ -2971,9 +2834,12 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) } plen = fwohci_get_plen(sc, dbch, fp) - offset; if (plen < 0) { - /* minimum header size + trailer - = sizeof(fw_pkt) so this shouldn't happens */ - printf("plen(%d) is negative! offset=%d\n", + /* + * minimum header size + trailer = + * sizeof(fw_pkt) so this shouldn't happens + */ + aprint_error_dev(sc->fc.dev, + "plen(%d) is negative! offset=%d\n", plen, offset); goto err; } @@ -2984,8 +2850,9 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) if (firewire_debug) printf("splitted payload\n"); /* sanity check */ - if (resCount != 0) { - printf("resCount=%d plen=%d" + if (resCount != 0) { + aprint_error_dev(sc->fc.dev, + "resCount=%d plen=%d" " len=%d\n", resCount, plen, len); goto err; @@ -2994,33 +2861,35 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) } vec[nvec].iov_base = ld; vec[nvec].iov_len = plen; - nvec ++; + nvec++; ld += plen; } - dbch->buf_offset = ld - (uint8_t *)db_tr->buf; if (nvec == 0) - printf("nvec == 0\n"); + aprint_error_dev(sc->fc.dev, "nvec == 0\n"); /* DMA result-code will be written at the tail of packet */ - stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - sizeof(struct fwohci_trailer))); + stat = FWOHCI_DMA_READ(*(uint32_t *)(ld - + sizeof(struct fwohci_trailer))); #if 0 - printf("plen: %d, stat %x\n", - plen ,stat); + aprint_normal("plen: %d, stat %x\n", plen, stat); #endif spd = (stat >> 21) & 0x3; event = (stat >> 16) & 0x1f; switch (event) { case FWOHCIEV_ACKPEND: #if 0 - printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp->mode.common.tcode); + aprint_normal(sc->fc.dev, + "ack pending tcode=0x%x..\n", + fp->mode.common.tcode); #endif /* fall through */ case FWOHCIEV_ACKCOMPL: { struct fw_rcv_buf rb; - if ((vec[nvec-1].iov_len -= - sizeof(struct fwohci_trailer)) == 0) + vec[nvec - 1].iov_len -= + sizeof(struct fwohci_trailer); + if (vec[nvec - 1].iov_len == 0) nvec--; rb.fc = &sc->fc; rb.vec = vec; @@ -3032,97 +2901,155 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) case FWOHCIEV_BUSRST: if ((sc->fc.status != FWBUSRESET) && (sc->fc.status != FWBUSINIT)) - printf("got BUSRST packet!?\n"); + aprint_error_dev(sc->fc.dev, + "got BUSRST packet!?\n"); break; default: - fw_printf(sc->fc.dev, + aprint_error_dev(sc->fc.dev, "Async DMA Receive error err=%02x %s" " plen=%d offset=%d len=%d status=0x%08x" " tcode=0x%x, stat=0x%08x\n", event, fwohcicode[event], plen, - dbch->buf_offset, len, - OREAD(sc, OHCI_DMACTL(off)), + (int)(ld - (uint8_t *)db_tr->buf - plen), + len, OREAD(sc, OHCI_DMACTL(dbch->off)), fp->mode.common.tcode, stat); #if 1 /* XXX */ goto err; #endif break; } - pcnt ++; +#if 0 +{ +extern int dbgflg; +if (dbgflg) { + if (dbgflg == 8) { + int j; + + printf("%s: i=%d, resCount=%d", __func__, i, prev_resCounts[0]); + for (j = 1; j < 16; j++) + printf(", %d", prev_resCounts[j]); + printf("\n"); + } + printf("%s:", __func__); + if (dbch->off == OHCI_ARQOFF) + printf(" ARQ:"); + else + printf(" ARS:"); + printf(" plen=%d, offset=%d, buf_offset=%d,", plen, offset, dbch->buf_offset); + printf(" idx=%d, resCount=%d,", db_tr->idx, resCount); + if (dbch->pdb_tr != NULL) + printf(" pdb=%p", &dbch->pdb_tr->db[0].db); + printf(" db=%p\n", &db_tr->db[0].db); + dbgflg--; +} +} +#endif if (dbch->pdb_tr != NULL) { - fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, - off, 1); + if (dbch->buf_offset < 0) + bus_dmamap_sync(sc->fc.dmat, + dbch->pdb_tr->dma_map, + psize + dbch->buf_offset, + 0 - dbch->buf_offset, + BUS_DMASYNC_PREREAD); + else + bus_dmamap_sync(sc->fc.dmat, + dbch->pdb_tr->dma_map, + dbch->buf_offset, + psize - dbch->buf_offset, + BUS_DMASYNC_PREREAD); + fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 1); dbch->pdb_tr = NULL; } - + dbch->buf_offset = ld - (uint8_t *)db_tr->buf; + n += (plen + offset); } out: - if (resCount == 0) { - /* done on this buffer */ - if (dbch->pdb_tr == NULL) { - fwohci_arcv_free_buf(sc, dbch, db_tr, off, 1); - dbch->buf_offset = 0; - } else - if (dbch->pdb_tr != db_tr) - printf("pdb_tr != db_tr\n"); - db_tr = STAILQ_NEXT(db_tr, link); - fwdma_sync_multiseg_all(dbch->am, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) - >> OHCI_STATUS_SHIFT; - resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) - & OHCI_COUNT_MASK; - /* XXX check buffer overrun */ - dbch->top = db_tr; - } else { - dbch->buf_offset = dbch->xferq.psize - resCount; - fw_bus_dmamap_sync( - dbch->dmat, db_tr->dma_map, BUS_DMASYNC_PREREAD); + if (n > 0) + bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, m, n, + BUS_DMASYNC_PREREAD); + + if (resCount != 0) { + dbch->buf_offset = psize - resCount; break; } + + /* done on this buffer */ + + if (dbch->pdb_tr == NULL) { + fwohci_arcv_free_buf(sc, dbch, db_tr, 1); + dbch->buf_offset = 0; + } else + if (dbch->pdb_tr != db_tr) + aprint_error_dev(sc->fc.dev, + "pdb_tr != db_tr\n"); + dbch->top = STAILQ_NEXT(db_tr, link); + + db_tr = dbch->top; + fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> + OHCI_STATUS_SHIFT; + resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) + & OHCI_COUNT_MASK; + + /* XXX check buffer overrun */ + /* XXX make sure DMA is not dead */ } + fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); #if 0 - if (pcnt < 1) - printf("fwohci_arcv: no packets\n"); +{ +uint32_t _status; + +fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); +_status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT; +if (status != _status) +printf("Ooops status ? 0x%x : 0x%x, %p\n", status, _status, db_tr->db); +fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); +_status = FWOHCI_DMA_READ(((struct fwohcidb *)MIPS_PHYS_TO_KSEG1(MIPS_KSEG0_TO_PHYS(db_tr->db)))[0].db.desc.res) >> OHCI_STATUS_SHIFT; +if (status != _status) +printf("Ooooops status ? 0x%x : 0x%x\n", status, _status); +} +#endif + mutex_exit(&dbch->xferq.q_mtx); +#if 0 +prev_resCounts[i] = resCount; +i = (i + 1) & 0xf; #endif - fwdma_sync_multiseg_all(dbch->am, - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - splx(s); return; err: - fw_printf(sc->fc.dev, "AR DMA status=%x, ", - OREAD(sc, OHCI_DMACTL(off))); - dbch->pdb_tr = NULL; + aprint_error_dev(sc->fc.dev, "AR DMA status=%x, ", + OREAD(sc, OHCI_DMACTL(dbch->off))); + if (dbch->pdb_tr != NULL) { + if (dbch->buf_offset < 0) + bus_dmamap_sync(sc->fc.dmat, dbch->pdb_tr->dma_map, + psize + dbch->buf_offset, 0 - dbch->buf_offset, + BUS_DMASYNC_PREREAD); + else + bus_dmamap_sync(sc->fc.dmat, dbch->pdb_tr->dma_map, + dbch->buf_offset, psize - dbch->buf_offset, + BUS_DMASYNC_PREREAD); + fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 1); + dbch->pdb_tr = NULL; + } /* skip until resCount != 0 */ - printf(" skip buffer"); + aprint_error(" skip buffer"); while (resCount == 0) { - printf(" #"); - fwohci_arcv_free_buf(sc, dbch, db_tr, off, 0); + aprint_error(" #"); + fwohci_arcv_free_buf(sc, dbch, db_tr, 0); db_tr = STAILQ_NEXT(db_tr, link); resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) - & OHCI_COUNT_MASK; + & OHCI_COUNT_MASK; } - printf(" done\n"); + aprint_error(" done\n"); dbch->top = db_tr; - dbch->buf_offset = dbch->xferq.psize - resCount; - OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); - fwdma_sync_multiseg_all( - dbch->am, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - fw_bus_dmamap_sync(dbch->dmat, db_tr->dma_map, BUS_DMASYNC_PREREAD); - splx(s); -} -#if defined(__NetBSD__) - -int -fwohci_print(void *aux, const char *pnp) -{ - struct fw_attach_args *fwa = (struct fw_attach_args *)aux; - - if (pnp) - aprint_normal("%s at %s", fwa->name, pnp); - - return UNCONF; + dbch->buf_offset = psize - resCount; + OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE); + fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, + 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREREAD); + mutex_exit(&dbch->xferq.q_mtx); } -#endif diff --git a/sys/dev/ieee1394/fwohcireg.h b/sys/dev/ieee1394/fwohcireg.h index 3a468c6ed80..f1853f781ba 100644 --- a/sys/dev/ieee1394/fwohcireg.h +++ b/sys/dev/ieee1394/fwohcireg.h @@ -1,4 +1,4 @@ -/* $NetBSD: fwohcireg.h,v 1.17 2007/11/05 19:08:57 kiyohara Exp $ */ +/* $NetBSD: fwohcireg.h,v 1.18 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa @@ -32,10 +32,13 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/firewire/fwohcireg.h,v 1.23 2007/04/30 14:06:30 simokawa Exp $ + * + * $FreeBSD: src/sys/dev/firewire/fwohcireg.h,v 1.24 2009/02/12 03:05:42 sbruno Exp $ * */ +#ifndef _FWOHCIREG_H_ +#define _FWOHCIREG_H_ + #define PCI_CBMEM PCIR_BAR(0) #define FW_VENDORID_NATSEMI 0x100B @@ -83,16 +86,12 @@ #define PCI_INTERFACE_OHCI 0x10 -#if defined(__FreeBSD__) -#define FW_OHCI_BASE_REG 0x10 -#elif defined(__NetBSD__) #define PCI_OHCI_MAP_REGISTER 0x10 -#endif -#define OHCI_DMA_ITCH 0x20 -#define OHCI_DMA_IRCH 0x20 +#define OHCI_DMA_ITCH 0x20 +#define OHCI_DMA_IRCH 0x20 -#define OHCI_MAX_DMA_CH (0x4 + OHCI_DMA_ITCH + OHCI_DMA_IRCH) +#define OHCI_MAX_DMA_CH (0x4 + OHCI_DMA_ITCH + OHCI_DMA_IRCH) typedef uint32_t fwohcireg_t; @@ -190,7 +189,7 @@ struct fwohcidb { #define FWOHCIEV_MASK 0x1f -struct ohci_dma{ +struct ohci_dma { fwohcireg_t cntl; #define OHCI_CNTL_CYCMATCH_S (0x1 << 31) @@ -217,7 +216,7 @@ struct ohci_dma{ fwohcireg_t dummy3; }; -struct ohci_itdma{ +struct ohci_itdma { fwohcireg_t cntl; fwohcireg_t cntl_clr; fwohcireg_t dummy0; @@ -268,20 +267,20 @@ struct ohci_registers { #define FWOHCI_INTSTATCLR 0x84 #define FWOHCI_INTMASK 0x88 #define FWOHCI_INTMASKCLR 0x8c - fwohcireg_t int_stat; /* 0x80 */ - fwohcireg_t int_clear; /* 0x84 */ - fwohcireg_t int_mask; /* 0x88 */ - fwohcireg_t int_mask_clear; /* 0x8c */ - fwohcireg_t it_int_stat; /* 0x90 */ - fwohcireg_t it_int_clear; /* 0x94 */ - fwohcireg_t it_int_mask; /* 0x98 */ - fwohcireg_t it_mask_clear; /* 0x9c */ - fwohcireg_t ir_int_stat; /* 0xa0 */ - fwohcireg_t ir_int_clear; /* 0xa4 */ - fwohcireg_t ir_int_mask; /* 0xa8 */ - fwohcireg_t ir_mask_clear; /* 0xac */ - fwohcireg_t dummy5[11]; /* dummy 0xb0-d8 */ - fwohcireg_t fairness; /* fairness control 0xdc */ + fwohcireg_t int_stat; /* 0x80 */ + fwohcireg_t int_clear; /* 0x84 */ + fwohcireg_t int_mask; /* 0x88 */ + fwohcireg_t int_mask_clear; /* 0x8c */ + fwohcireg_t it_int_stat; /* 0x90 */ + fwohcireg_t it_int_clear; /* 0x94 */ + fwohcireg_t it_int_mask; /* 0x98 */ + fwohcireg_t it_mask_clear; /* 0x9c */ + fwohcireg_t ir_int_stat; /* 0xa0 */ + fwohcireg_t ir_int_clear; /* 0xa4 */ + fwohcireg_t ir_int_mask; /* 0xa8 */ + fwohcireg_t ir_mask_clear; /* 0xac */ + fwohcireg_t dummy5[11]; /* dummy 0xb0-d8 */ + fwohcireg_t fairness; /* fairness control 0xdc */ fwohcireg_t link_cntl; /* Chip control 0xe0*/ fwohcireg_t link_cntl_clr; /* Chip control clear 0xe4*/ #define FWOHCI_NODEID 0xe8 @@ -334,7 +333,8 @@ struct ohci_registers { struct ohci_dma dma_irch[0x20]; }; -struct fwohcidb_tr{ +struct fwohcidb_tr { + int idx; STAILQ_ENTRY(fwohcidb_tr) link; struct fw_xfer *xfer; struct fwohcidb *db; @@ -347,8 +347,8 @@ struct fwohcidb_tr{ /* * OHCI info structure. */ -struct fwohci_txpkthdr{ - union{ +struct fwohci_txpkthdr { + union { uint32_t ld[4]; struct { #if BYTE_ORDER == BIG_ENDIAN @@ -362,7 +362,7 @@ struct fwohci_txpkthdr{ :8, spd:16; /* XXX include reserved fields */ #endif - }common; + } common; struct { #if BYTE_ORDER == BIG_ENDIAN uint32_t :8, @@ -382,11 +382,11 @@ struct fwohci_txpkthdr{ :8; #endif BIT16x2(dst, ); - }asycomm; + } asycomm; struct { #if BYTE_ORDER == BIG_ENDIAN uint32_t :13, - spd:3, + spd:3, chtag:8, tcode:4, sy:4; @@ -394,14 +394,14 @@ struct fwohci_txpkthdr{ uint32_t sy:4, tcode:4, chtag:8, - spd:3, + spd:3, :13; #endif BIT16x2(len, ); - }stream; - }mode; + } stream; + } mode; }; -struct fwohci_trailer{ +struct fwohci_trailer { #if BYTE_ORDER == BIG_ENDIAN uint32_t stat:16, time:16; @@ -417,38 +417,39 @@ struct fwohci_trailer{ #define OHCI_CNTL_PHYPKT (0x1 << 10) #define OHCI_CNTL_SID (0x1 << 9) +/* + * defined in OHCI 1.1 + * chapter 6.1 + */ #define OHCI_INT_DMA_ATRQ (0x1 << 0) #define OHCI_INT_DMA_ATRS (0x1 << 1) #define OHCI_INT_DMA_ARRQ (0x1 << 2) #define OHCI_INT_DMA_ARRS (0x1 << 3) #define OHCI_INT_DMA_PRRQ (0x1 << 4) #define OHCI_INT_DMA_PRRS (0x1 << 5) -#define OHCI_INT_DMA_IT (0x1 << 6) -#define OHCI_INT_DMA_IR (0x1 << 7) -#define OHCI_INT_PW_ERR (0x1 << 8) -#define OHCI_INT_LR_ERR (0x1 << 9) - +#define OHCI_INT_DMA_IT (0x1 << 6) +#define OHCI_INT_DMA_IR (0x1 << 7) +#define OHCI_INT_PW_ERR (0x1 << 8) +#define OHCI_INT_LR_ERR (0x1 << 9) #define OHCI_INT_PHY_SID (0x1 << 16) #define OHCI_INT_PHY_BUS_R (0x1 << 17) - #define OHCI_INT_REG_FAIL (0x1 << 18) - #define OHCI_INT_PHY_INT (0x1 << 19) #define OHCI_INT_CYC_START (0x1 << 20) #define OHCI_INT_CYC_64SECOND (0x1 << 21) #define OHCI_INT_CYC_LOST (0x1 << 22) #define OHCI_INT_CYC_ERR (0x1 << 23) - #define OHCI_INT_ERR (0x1 << 24) #define OHCI_INT_CYC_LONG (0x1 << 25) #define OHCI_INT_PHY_REG (0x1 << 26) - #define OHCI_INT_EN (0x1 << 31) -#define IP_CHANNELS 0x0234 +#define IP_CHANNELS 0x0234 #define FWOHCI_MAXREC 2048 #define OHCI_ISORA 0x02 #define OHCI_ISORB 0x04 #define FWOHCITCODE_PHY 0xe + +#endif /* _FWOHCIREG_H_ */ diff --git a/sys/dev/ieee1394/fwohcivar.h b/sys/dev/ieee1394/fwohcivar.h index 0543c5d9fb2..04f0e32758f 100644 --- a/sys/dev/ieee1394/fwohcivar.h +++ b/sys/dev/ieee1394/fwohcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: fwohcivar.h,v 1.29 2007/11/06 15:24:11 kiyohara Exp $ */ +/* $NetBSD: fwohcivar.h,v 1.30 2010/03/29 03:05:28 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi SHimokawa @@ -36,31 +36,24 @@ * $FreeBSD: src/sys/dev/firewire/fwohcivar.h,v 1.16 2007/06/06 14:31:36 simokawa Exp $ * */ +#ifndef _FWOHCIVAR_H_ +#define _FWOHCIVAR_H_ -#if defined(__NetBSD__) MALLOC_DECLARE(M_FW); -#endif -typedef struct fwohci_softc { +struct fwohci_softc { struct firewire_comm fc; bus_space_tag_t bst; bus_space_handle_t bsh; -#if defined(__FreeBSD__) - void *ih; -#if defined(__DragonFly__) || __FreeBSD_version < 500000 - void *ih_cam; - void *ih_bio; -#endif - struct resource *bsr; - struct resource *irq_res; -#elif defined(__NetBSD__) bus_size_t bssize; -#endif - struct fwohci_dbch{ + struct fwohci_dbch { + int off; u_int ndb; u_int ndesc; STAILQ_HEAD(, fwohcidb_tr) db_trq; - struct fwohcidb_tr *top, *bottom, *pdb_tr; + struct fwohcidb_tr *top; + struct fwohcidb_tr *bottom; + struct fwohcidb_tr *pdb_tr; struct fw_xferq xferq; int flags; #define FWOHCI_DBCH_INIT (1<<0) @@ -70,30 +63,26 @@ typedef struct fwohci_softc { #define FWOHCI_DBCH_MAX_PAGES 32 /* Context programs buffer */ struct fwdma_alloc_multi *am; - fw_bus_dma_tag_t dmat; } arrq, arrs, atrq, atrs, it[OHCI_DMA_ITCH], ir[OHCI_DMA_IRCH]; u_int maxrec; uint32_t *sid_buf; struct fwdma_alloc sid_dma; struct fwdma_alloc crom_dma; struct fwdma_alloc dummy_dma; - uint32_t intmask, irstat, itstat; + uint32_t intmask; uint32_t intstat; - fw_task_t fwohci_task_busreset; - fw_task_t fwohci_task_sid; - fw_task_t fwohci_task_dma; + uint32_t irstat; + uint32_t itstat; int cycle_lost; -} fwohci_softc_t; +}; -void fwohci_intr (void *arg); -int fwohci_filt (void *arg); -int fwohci_init (struct fwohci_softc *, device_t); -void fwohci_poll (struct firewire_comm *, int, int); -void fwohci_reset (struct fwohci_softc *, device_t); -#if defined(__FreeBSD__) -int fwohci_detach(struct fwohci_softc *, device_t); -#elif defined(__NetBSD__) +#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 *); int fwohci_detach(struct fwohci_softc *, int); -#endif -int fwohci_resume (struct fwohci_softc *, device_t); -int fwohci_stop (struct fwohci_softc *, device_t dev); +int fwohci_intr(void *arg); +int fwohci_resume(struct fwohci_softc *); +int fwohci_stop(struct fwohci_softc *); + +#endif /* _FWOHCIVAR_H_ */ diff --git a/sys/dev/ieee1394/fwphyreg.h b/sys/dev/ieee1394/fwphyreg.h index 07bb1442957..791a2e5d3a9 100644 --- a/sys/dev/ieee1394/fwphyreg.h +++ b/sys/dev/ieee1394/fwphyreg.h @@ -1,8 +1,8 @@ -/* $NetBSD: fwphyreg.h,v 1.2 2005/12/11 12:22:02 christos Exp $ */ +/* $NetBSD: fwphyreg.h,v 1.3 2010/03/29 03:05:28 kiyohara Exp $ */ /*- * Copyright (C) 2003 * Hidetoshi Shimokawa. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -19,7 +19,7 @@ * 4. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -31,10 +31,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/fwphyreg.h,v 1.3 2005/01/06 01:42:41 imp Exp $ + * + * $FreeBSD: src/sys/dev/firewire/fwphyreg.h,v 1.4 2009/02/12 03:05:42 sbruno Exp $ */ +#ifndef _FWPHYREG_H_ +#define _FWPHYREG_H_ + +/* + * IEEE 1394a + * Figure 5B - 1 + */ struct phyreg_base { #if BYTE_ORDER == BIG_ENDIAN uint8_t phy_id:6, @@ -101,6 +108,10 @@ struct phyreg_base { #endif }; +/* + * IEEE 1394a + * Figure 5B - 2 + */ struct phyreg_page0 { #if BYTE_ORDER == BIG_ENDIAN uint8_t astat:2, @@ -161,9 +172,15 @@ struct phyreg_page0 { #endif }; +/* + * IEEE 1394a + * Figure 5B - 3 + */ struct phyreg_page1 { uint8_t compliance; uint8_t :8; uint8_t vendor_id[3]; uint8_t product_id[3]; }; + +#endif /* _FWPHYREG_H_ */ diff --git a/sys/dev/ieee1394/iec13213.h b/sys/dev/ieee1394/iec13213.h index bcae4ffdf1c..75a91588bc2 100644 --- a/sys/dev/ieee1394/iec13213.h +++ b/sys/dev/ieee1394/iec13213.h @@ -1,4 +1,4 @@ -/* $NetBSD: iec13213.h,v 1.3 2008/05/02 19:50:04 xtraeme Exp $ */ +/* $NetBSD: iec13213.h,v 1.4 2010/03/29 03:05:28 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -31,11 +31,14 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/iec13213.h,v 1.14 2005/01/06 01:42:41 imp Exp $ * */ +#ifndef _IEC13213_H_ +#define _IEC13213_H_ + #define STATE_CLEAR 0x0000 #define STATE_SET 0x0004 #define NODE_IDS 0x0008 @@ -162,7 +165,7 @@ struct csrtext { struct bus_info { #define CSR_BUS_NAME_IEEE1394 0x31333934 - uint32_t bus_name; + uint32_t bus_name; #if BYTE_ORDER == BIG_ENDIAN uint32_t irmc:1, /* iso. resource manager capable */ cmc:1, /* cycle master capable */ @@ -233,12 +236,12 @@ struct crom_src { struct crom_chunk { STAILQ_ENTRY(crom_chunk) link; - struct crom_chunk *ref_chunk; - int ref_index; + struct crom_chunk *ref_chunk; + int ref_index; int offset; struct { BIT16x2(crc_len, crc); - uint32_t buf[CROM_MAX_CHUNK_LEN]; + uint32_t buf[CROM_MAX_CHUNK_LEN]; } data; }; @@ -250,3 +253,5 @@ extern int crom_add_simple_text(struct crom_src *src, struct crom_chunk *, struct crom_chunk *, const char *); extern int crom_load(struct crom_src *, uint32_t *, int); #endif + +#endif /* _IEC13213_H_ */ diff --git a/sys/dev/ieee1394/iec68113.h b/sys/dev/ieee1394/iec68113.h index effec445d26..1396db25146 100644 --- a/sys/dev/ieee1394/iec68113.h +++ b/sys/dev/ieee1394/iec68113.h @@ -1,4 +1,4 @@ -/* $NetBSD: iec68113.h,v 1.3 2008/09/08 23:36:54 gmcgarry Exp $ */ +/* $NetBSD: iec68113.h,v 1.4 2010/03/29 03:05:28 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -31,11 +31,14 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * + * * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/iec68113.h,v 1.9 2005/01/06 01:42:41 imp Exp $ * */ +#ifndef _IEC68113_H_ +#define _IEC68113_H_ + #define DV_BROADCAST_ON (1<<30) #define oMPR 0x900 #define oPCR 0x904 @@ -126,3 +129,5 @@ struct dvdbc{ uint8_t payload[77]; #define DV_DSF_12 0x80 /* PAL: payload[0] in Header DIF */ }; + +#endif /* _IEC68113_H_ */ diff --git a/sys/dev/ieee1394/if_fwip.c b/sys/dev/ieee1394/if_fwip.c index 8d5e33506b2..88b3ceeb7d1 100644 --- a/sys/dev/ieee1394/if_fwip.c +++ b/sys/dev/ieee1394/if_fwip.c @@ -1,10 +1,10 @@ -/* $NetBSD: if_fwip.c,v 1.21 2010/03/11 04:00:37 mrg Exp $ */ +/* $NetBSD: if_fwip.c,v 1.22 2010/03/29 03:05:28 kiyohara Exp $ */ /*- * Copyright (c) 2004 * Doug Rabson * Copyright (c) 2002-2003 * Hidetoshi Shimokawa. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -21,7 +21,7 @@ * 4. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,69 +33,31 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/firewire/if_fwip.c,v 1.16 2007/06/06 14:31:36 simokawa Exp $ + * + * $FreeBSD: src/sys/dev/firewire/if_fwip.c,v 1.18 2009/02/09 16:58:18 fjoe Exp $ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_fwip.c,v 1.21 2010/03/11 04:00:37 mrg Exp $"); - -#ifdef HAVE_KERNEL_OPTION_HEADERS -#include "opt_device_polling.h" -#include "opt_inet.h" -#endif +__KERNEL_RCSID(0, "$NetBSD: if_fwip.c,v 1.22 2010/03/29 03:05:28 kiyohara Exp $"); -#if defined(__FreeBSD__) #include <sys/param.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/sockio.h> -#include <sys/sysctl.h> -#include <sys/systm.h> -#include <sys/taskqueue.h> -#include <sys/module.h> #include <sys/bus.h> -#include <sys/bus.h> - -#include <net/bpf.h> -#include <net/if.h> -#include <net/firewire.h> -#include <net/if_arp.h> -#include <net/if_types.h> -#ifdef __DragonFly__ -#include <bus/firewire/fw_port.h> -#include <bus/firewire/firewire.h> -#include <bus/firewire/firewirereg.h> -#include "if_fwipvar.h" -#else -#include <dev/firewire/fw_port.h> -#include <dev/firewire/firewire.h> -#include <dev/firewire/firewirereg.h> -#include <dev/firewire/iec13213.h> -#include <dev/firewire/if_fwipvar.h> -#endif -#elif defined(__NetBSD__) -#include <sys/param.h> #include <sys/device.h> #include <sys/errno.h> #include <sys/malloc.h> #include <sys/mbuf.h> +#include <sys/mutex.h> #include <sys/sysctl.h> -#include <sys/bus.h> - +#include <net/bpf.h> #include <net/if.h> #include <net/if_ieee1394.h> #include <net/if_types.h> -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/firewirereg.h> #include <dev/ieee1394/iec13213.h> #include <dev/ieee1394/if_fwipvar.h> -#endif /* * We really need a mechanism for allocating regions in the FIFO @@ -106,36 +68,35 @@ __KERNEL_RCSID(0, "$NetBSD: if_fwip.c,v 1.21 2010/03/11 04:00:37 mrg Exp $"); */ #define INET_FIFO 0xfffe00000000LL -#if defined(__FreeBSD__) -#define FWIPDEBUG if (fwipdebug) if_printf -#elif defined(__NetBSD__) #define FWIPDEBUG if (fwipdebug) aprint_debug_ifnet -#endif #define TX_MAX_QUEUE (FWMAXQUEUE - 1) -#if defined(__NetBSD__) -int fwipmatch (device_t, cfdata_t, void *); -void fwipattach (device_t, device_t, void *); -int fwipdetach (device_t, int); -int fwipactivate (device_t, enum devact); -#endif +struct fw_hwaddr { + uint32_t sender_unique_ID_hi; + uint32_t sender_unique_ID_lo; + uint8_t sender_max_rec; + uint8_t sspd; + uint16_t sender_unicast_FIFO_hi; + uint32_t sender_unicast_FIFO_lo; +}; + + +static int fwipmatch(device_t, cfdata_t, void *); +static void fwipattach(device_t, device_t, void *); +static int fwipdetach(device_t, int); +static int fwipactivate(device_t, enum devact); + /* network interface */ -static void fwip_start (struct ifnet *); -static int fwip_ioctl (struct ifnet *, u_long, void *); -#if defined(__FreeBSD__) -static void fwip_init(void *); -static void fwip_stop(struct fwip_softc *); -#elif defined(__NetBSD__) +static void fwip_start(struct ifnet *); +static int fwip_ioctl(struct ifnet *, u_long, void *); static int fwip_init(struct ifnet *); static void fwip_stop(struct ifnet *, int); -#endif -static void fwip_post_busreset (void *); -static void fwip_output_callback (struct fw_xfer *); -static void fwip_async_output (struct fwip_softc *, struct ifnet *); -static void fwip_start_send (void *, int); -static void fwip_stream_input (struct fw_xferq *); +static void fwip_post_busreset(void *); +static void fwip_output_callback(struct fw_xfer *); +static void fwip_async_output(struct fwip_softc *, struct ifnet *); +static void fwip_stream_input(struct fw_xferq *); static void fwip_unicast_input(struct fw_xfer *); static int fwipdebug = 0; @@ -143,17 +104,6 @@ static int broadcast_channel = 0xc0 | 0x1f; /* tag | channel(XXX) */ static int tx_speed = 2; static int rx_queue_len = FWMAXQUEUE; -#if defined(__FreeBSD__) -MALLOC_DEFINE(M_FWIP, "if_fwip", "IP over FireWire interface"); -SYSCTL_INT(_debug, OID_AUTO, if_fwip_debug, CTLFLAG_RW, &fwipdebug, 0, ""); -SYSCTL_DECL(_hw_firewire); -SYSCTL_NODE(_hw_firewire, OID_AUTO, fwip, CTLFLAG_RD, 0, - "Firewire ip subsystem"); -SYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RW, &rx_queue_len, - 0, "Length of the receive queue"); - -TUNABLE_INT("hw.firewire.fwip.rx_queue_len", &rx_queue_len); -#elif defined(__NetBSD__) MALLOC_DEFINE(M_FWIP, "if_fwip", "IP over IEEE1394 interface"); /* * Setup sysctl(3) MIB, hw.fwip.* @@ -200,222 +150,190 @@ SYSCTL_SETUP(sysctl_fwip, "sysctl fwip(4) subtree setup") return; err: - printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); + aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); } -#endif -#ifdef DEVICE_POLLING -static poll_handler_t fwip_poll; -static void -fwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) -{ - struct fwip_softc *fwip; - struct firewire_comm *fc; - - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - return; +CFATTACH_DECL_NEW(fwip, sizeof(struct fwip_softc), + fwipmatch, fwipattach, fwipdetach, fwipactivate); - fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; - fc = fwip->fd.fc; - fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count); -} -#endif /* DEVICE_POLLING */ -#if defined(__FreeBSD__) -static void -fwip_identify(driver_t *driver, device_t parent) -{ - BUS_ADD_CHILD(parent, 0, "fwip", fw_get_unit(parent)); -} static int -fwip_probe(device_t dev) -{ - device_t pa; - - pa = device_get_parent(dev); - if(fw_get_unit(dev) != fw_get_unit(pa)){ - return(ENXIO); - } - - device_set_desc(dev, "IP over FireWire"); - return (0); -} -#elif defined(__NetBSD__) -int fwipmatch(device_t parent, cfdata_t cf, void *aux) { struct fw_attach_args *fwa = aux; if (strcmp(fwa->name, "fwip") == 0) - return (1); - return (0); + return 1; + return 0; } -#endif -FW_ATTACH(fwip) +static void +fwipattach(device_t parent, device_t self, void *aux) { - FW_ATTACH_START(fwip, fwip, fwa); - FWIP_ATTACH_START; + struct fwip_softc *sc = device_private(self); + struct fw_attach_args *fwa = (struct fw_attach_args *)aux; + struct fw_hwaddr *hwaddr; struct ifnet *ifp; - int s; - FWIP_ATTACH_SETUP; + aprint_naive("\n"); + aprint_normal(": IP over IEEE1394\n"); - ifp = fwip->fw_softc.fwip_ifp; - if (ifp == NULL) - FW_ATTACH_RETURN(ENOSPC); + sc->sc_fd.dev = self; + sc->sc_eth.fwip_ifp = &sc->sc_eth.fwcom.fc_if; + hwaddr = (struct fw_hwaddr *)&sc->sc_eth.fwcom.ic_hwaddr; -#ifdef __NetBSD__ - aprint_naive("\n"); -#endif + ifp = sc->sc_eth.fwip_ifp; + + mutex_init(&sc->sc_fwb.fwb_mtx, MUTEX_DEFAULT, IPL_NET); + mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NET); - fw_mtx_init(&fwip->mtx, "fwip", NULL, MTX_DEF); /* XXX */ - fwip->dma_ch = -1; + sc->sc_dma_ch = -1; - fwip->fd.fc = fwa->fc; + sc->sc_fd.fc = fwa->fc; if (tx_speed < 0) - tx_speed = fwip->fd.fc->speed; + tx_speed = sc->sc_fd.fc->speed; - fwip->fd.post_explore = NULL; - fwip->fd.post_busreset = fwip_post_busreset; - fwip->fw_softc.fwip = fwip; - FW_TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip); + sc->sc_fd.post_explore = NULL; + sc->sc_fd.post_busreset = fwip_post_busreset; + sc->sc_eth.fwip = sc; /* * Encode our hardware the way that arp likes it. */ - hwaddr->sender_unique_ID_hi = htonl(fwip->fd.fc->eui.hi); - hwaddr->sender_unique_ID_lo = htonl(fwip->fd.fc->eui.lo); - hwaddr->sender_max_rec = fwip->fd.fc->maxrec; - hwaddr->sspd = fwip->fd.fc->speed; + hwaddr->sender_unique_ID_hi = htonl(sc->sc_fd.fc->eui.hi); + hwaddr->sender_unique_ID_lo = htonl(sc->sc_fd.fc->eui.lo); + hwaddr->sender_max_rec = sc->sc_fd.fc->maxrec; + hwaddr->sspd = sc->sc_fd.fc->speed; hwaddr->sender_unicast_FIFO_hi = htons((uint16_t)(INET_FIFO >> 32)); hwaddr->sender_unicast_FIFO_lo = htonl((uint32_t)INET_FIFO); - /* fill the rest and attach interface */ - ifp->if_softc = &fwip->fw_softc; + /* fill the rest and attach interface */ + ifp->if_softc = &sc->sc_eth; -#if __FreeBSD_version >= 501113 || defined(__DragonFly__) || defined(__NetBSD__) - IF_INITNAME(ifp, dev, unit); -#else - ifp->if_unit = unit; - ifp->if_name = "fwip"; -#endif -#if defined(__NetBSD__) - IFQ_SET_READY(&ifp->if_snd); -#endif - SET_IFFUNC(ifp, fwip_start, fwip_ioctl, fwip_init, fwip_stop); + strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); + ifp->if_start = fwip_start; + ifp->if_ioctl = fwip_ioctl; + ifp->if_init = fwip_init; + ifp->if_stop = fwip_stop; ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); - ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE; -#ifdef DEVICE_POLLING - ifp->if_capabilities |= IFCAP_POLLING; -#endif + IFQ_SET_READY(&ifp->if_snd); + IFQ_SET_MAXLEN(&ifp->if_snd, TX_MAX_QUEUE); - s = splfwnet(); - FIREWIRE_IFATTACH(ifp, hwaddr); - splx(s); + if_attach(ifp); + ieee1394_ifattach(ifp, (const struct ieee1394_hwaddr *)hwaddr); -#if defined(__NetBSD__) if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); else pmf_class_network_register(self, ifp); -#endif FWIPDEBUG(ifp, "interface created\n"); - FW_ATTACH_RETURN(0); + return; } -IF_STOP(fwip) +static int +fwipdetach(device_t self, int flags) { - IF_STOP_START(fwip, ifp, fwip); - struct firewire_comm *fc; - struct fw_xferq *xferq; - struct fw_xfer *xfer, *next; - int i; + struct fwip_softc *sc = device_private(self); + struct ifnet *ifp = sc->sc_eth.fwip_ifp; + + fwip_stop(sc->sc_eth.fwip_ifp, 1); + ieee1394_ifdetach(ifp); + if_detach(ifp); + mutex_destroy(&sc->sc_mtx); + mutex_destroy(&sc->sc_fwb.fwb_mtx); + return 0; +} - fc = fwip->fd.fc; +static int +fwipactivate(device_t self, enum devact act) +{ + struct fwip_softc *sc = device_private(self); - if (fwip->dma_ch >= 0) { - xferq = fc->ir[fwip->dma_ch]; + switch (act) { + case DVACT_DEACTIVATE: + if_deactivate(sc->sc_eth.fwip_ifp); + return 0; + default: + return EOPNOTSUPP; + } +} - if (xferq->flag & FWXFERQ_RUNNING) - fc->irx_disable(fc, fwip->dma_ch); - xferq->flag &= - ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM | - FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK); - xferq->hand = NULL; +static void +fwip_start(struct ifnet *ifp) +{ + struct fwip_softc *sc = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; - for (i = 0; i < xferq->bnchunk; i ++) - m_freem(xferq->bulkxfer[i].mbuf); - free(xferq->bulkxfer, M_FWIP); + FWIPDEBUG(ifp, "starting\n"); - fw_bindremove(fc, &fwip->fwb); - for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL; - xfer = next) { - next = STAILQ_NEXT(xfer, link); - fw_xfer_free(xfer); - } + if (sc->sc_dma_ch < 0) { + struct mbuf *m = NULL; - for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL; - xfer = next) { - next = STAILQ_NEXT(xfer, link); - fw_xfer_free(xfer); - } - STAILQ_INIT(&fwip->xferlist); + FWIPDEBUG(ifp, "not ready\n"); + + do { + IF_DEQUEUE(&ifp->if_snd, m); + if (m != NULL) + m_freem(m); + ifp->if_oerrors++; + } while (m != NULL); - xferq->bulkxfer = NULL; - fwip->dma_ch = -1; + return; } -#if defined(__FreeBSD__) - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); -#elif defined(__NetBSD__) - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); -#endif + ifp->if_flags |= IFF_OACTIVE; + + if (ifp->if_snd.ifq_len != 0) + fwip_async_output(sc, ifp); + + ifp->if_flags &= ~IFF_OACTIVE; } -FW_DETACH(fwip) +static int +fwip_ioctl(struct ifnet *ifp, u_long cmd, void *data) { - IF_DETACH_START(fwip, fwip); - struct ifnet *ifp; - int s; + int s, error = 0; - ifp = fwip->fw_softc.fwip_ifp; + s = splnet(); -#ifdef DEVICE_POLLING - if (ifp->if_capenable & IFCAP_POLLING) - ether_poll_deregister(ifp); -#endif + switch (cmd) { + case SIOCSIFFLAGS: + if ((error = ifioctl_common(ifp, cmd, data)) != 0) + break; + switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { + case IFF_RUNNING: + fwip_stop(ifp, 0); + break; + case IFF_UP: + fwip_init(ifp); + break; + default: + break; + } + break; - s = splfwnet(); + case SIOCADDMULTI: + case SIOCDELMULTI: + break; - FWIP_STOP(fwip); - FIREWIRE_IFDETACH(ifp); - fw_mtx_destroy(&fwip->mtx); + default: + error = ieee1394_ioctl(ifp, cmd, data); + if (error == ENETRESET) + error = 0; + break; + } splx(s); - return 0; -} - -int -fwipactivate(device_t self, enum devact act) -{ - struct fwip_softc *fwip = device_private(self); - switch (act) { - case DVACT_DEACTIVATE: - if_deactivate(fwip->fw_softc.fwip_ifp); - return 0; - default: - return EOPNOTSUPP; - } + return error; } -IF_INIT(fwip) +static int +fwip_init(struct ifnet *ifp) { - IF_INIT_START(fwip, fwip, ifp); + struct fwip_softc *sc = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; struct firewire_comm *fc; struct fw_xferq *xferq; struct fw_xfer *xfer; @@ -424,19 +342,18 @@ IF_INIT(fwip) FWIPDEBUG(ifp, "initializing\n"); - fc = fwip->fd.fc; -#define START 0 - if (fwip->dma_ch < 0) { - fwip->dma_ch = fw_open_isodma(fc, /* tx */0); - if (fwip->dma_ch < 0) - IF_INIT_RETURN(ENXIO); - xferq = fc->ir[fwip->dma_ch]; + fc = sc->sc_fd.fc; + if (sc->sc_dma_ch < 0) { + sc->sc_dma_ch = fw_open_isodma(fc, /* tx */0); + if (sc->sc_dma_ch < 0) + return ENXIO; + xferq = fc->ir[sc->sc_dma_ch]; xferq->flag |= FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_STREAM; xferq->flag &= ~0xff; xferq->flag |= broadcast_channel & 0xff; /* register fwip_input handler */ - xferq->sc = (void *) fwip; + xferq->sc = (void *) sc; xferq->hand = fwip_stream_input; xferq->bnchunk = rx_queue_len; xferq->bnpacket = 1; @@ -447,259 +364,179 @@ IF_INIT(fwip) sizeof(struct fw_bulkxfer) * xferq->bnchunk, M_FWIP, M_WAITOK); if (xferq->bulkxfer == NULL) { - printf("if_fwip: malloc failed\n"); - IF_INIT_RETURN(ENOMEM); + aprint_error_ifnet(ifp, "if_fwip: malloc failed\n"); + return ENOMEM; } STAILQ_INIT(&xferq->stvalid); STAILQ_INIT(&xferq->stfree); STAILQ_INIT(&xferq->stdma); xferq->stproc = NULL; - for (i = 0; i < xferq->bnchunk; i ++) { - m = -#if defined(__DragonFly__) || __FreeBSD_version < 500000 - m_getcl(M_WAIT, MT_DATA, M_PKTHDR); -#else - m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); -#endif + for (i = 0; i < xferq->bnchunk; i++) { + m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR); xferq->bulkxfer[i].mbuf = m; if (m != NULL) { m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; STAILQ_INSERT_TAIL(&xferq->stfree, &xferq->bulkxfer[i], link); } else - printf("fwip_as_input: m_getcl failed\n"); + aprint_error_ifnet(ifp, + "fwip_as_input: m_getcl failed\n"); } - fwip->fwb.start = INET_FIFO; - fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */ + sc->sc_fwb.start = INET_FIFO; + sc->sc_fwb.end = INET_FIFO + 16384; /* S3200 packet size */ /* pre-allocate xfer */ - STAILQ_INIT(&fwip->fwb.xferlist); - for (i = 0; i < rx_queue_len; i ++) { + STAILQ_INIT(&sc->sc_fwb.xferlist); + for (i = 0; i < rx_queue_len; i++) { xfer = fw_xfer_alloc(M_FWIP); if (xfer == NULL) break; - m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); + m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR); xfer->recv.payload = mtod(m, uint32_t *); xfer->recv.pay_len = MCLBYTES; xfer->hand = fwip_unicast_input; xfer->fc = fc; - xfer->sc = (void *)fwip; + xfer->sc = (void *) sc; xfer->mbuf = m; - STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); + STAILQ_INSERT_TAIL(&sc->sc_fwb.xferlist, xfer, link); } - fw_bindadd(fc, &fwip->fwb); + fw_bindadd(fc, &sc->sc_fwb); - STAILQ_INIT(&fwip->xferlist); + STAILQ_INIT(&sc->sc_xferlist); for (i = 0; i < TX_MAX_QUEUE; i++) { xfer = fw_xfer_alloc(M_FWIP); if (xfer == NULL) break; xfer->send.spd = tx_speed; - xfer->fc = fwip->fd.fc; - xfer->sc = (void *)fwip; + xfer->fc = sc->sc_fd.fc; + xfer->sc = (void *)sc; xfer->hand = fwip_output_callback; - STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); + STAILQ_INSERT_TAIL(&sc->sc_xferlist, xfer, link); } } else - xferq = fc->ir[fwip->dma_ch]; + xferq = fc->ir[sc->sc_dma_ch]; - fwip->last_dest.hi = 0; - fwip->last_dest.lo = 0; + sc->sc_last_dest.hi = 0; + sc->sc_last_dest.lo = 0; /* start dma */ if ((xferq->flag & FWXFERQ_RUNNING) == 0) - fc->irx_enable(fc, fwip->dma_ch); + fc->irx_enable(fc, sc->sc_dma_ch); -#if defined(__FreeBSD__) - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; -#elif defined(__NetBSD__) ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; -#endif #if 0 /* attempt to start output */ fwip_start(ifp); #endif - IF_INIT_RETURN(0); + return 0; } -static int -fwip_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static void +fwip_stop(struct ifnet *ifp, int disable) { - IF_IOCTL_START(fwip, fwip); - int s, error = 0; + struct fwip_softc *sc = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; + struct firewire_comm *fc = sc->sc_fd.fc; + struct fw_xferq *xferq; + struct fw_xfer *xfer, *next; + int i; - switch (cmd) { - case SIOCSIFFLAGS: - s = splfwnet(); - if ((error = ifioctl_common(ifp, cmd, data)) != 0) - ; - else if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_flags & IFF_RUNNING)) - FWIP_INIT(fwip); - } else { - if (ifp->if_flags & IFF_RUNNING) - FWIP_STOP(fwip); - } - splx(s); - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - break; - case SIOCSIFCAP: - if ((error = FIREWIRE_IOCTL(ifp, cmd, data)) != ENETRESET) - break; - error = 0; -#ifdef DEVICE_POLLING - { - struct ifreq *ifr = (struct ifreq *) data; - struct firewire_comm *fc = fc = fwip->fd.fc; - - if (ifr->ifr_reqcap & IFCAP_POLLING && - !(ifp->if_capenable & IFCAP_POLLING)) { - error = ether_poll_register(fwip_poll, ifp); - if (error) - return(error); - /* Disable interrupts */ - fc->set_intr(fc, 0); - ifp->if_capenable |= IFCAP_POLLING; - return (error); + if (sc->sc_dma_ch >= 0) { + xferq = fc->ir[sc->sc_dma_ch]; + + if (xferq->flag & FWXFERQ_RUNNING) + fc->irx_disable(fc, sc->sc_dma_ch); + xferq->flag &= + ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM | + FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK); + xferq->hand = NULL; + + for (i = 0; i < xferq->bnchunk; i++) + m_freem(xferq->bulkxfer[i].mbuf); + free(xferq->bulkxfer, M_FWIP); + fw_bindremove(fc, &sc->sc_fwb); + for (xfer = STAILQ_FIRST(&sc->sc_fwb.xferlist); xfer != NULL; + xfer = next) { + next = STAILQ_NEXT(xfer, link); + fw_xfer_free(xfer); } - if (!(ifr->ifr_reqcap & IFCAP_POLLING) && - ifp->if_capenable & IFCAP_POLLING) { - error = ether_poll_deregister(ifp); - /* Enable interrupts. */ - fc->set_intr(fc, 1); - ifp->if_capenable &= ~IFCAP_POLLING; - return (error); + + for (xfer = STAILQ_FIRST(&sc->sc_xferlist); xfer != NULL; + xfer = next) { + next = STAILQ_NEXT(xfer, link); + fw_xfer_free(xfer); } - } -#endif /* DEVICE_POLLING */ - break; - default: - s = splfwnet(); - error = FIREWIRE_IOCTL(ifp, cmd, data); - splx(s); - return (error); + xferq->bulkxfer = NULL; + sc->sc_dma_ch = -1; } - return error; + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); } static void fwip_post_busreset(void *arg) { - struct fwip_softc *fwip = arg; + struct fwip_softc *sc = arg; struct crom_src *src; struct crom_chunk *root; - src = fwip->fd.fc->crom_src; - root = fwip->fd.fc->crom_root; + src = sc->sc_fd.fc->crom_src; + root = sc->sc_fd.fc->crom_root; /* RFC2734 IPv4 over IEEE1394 */ - memset(&fwip->unit4, 0, sizeof(struct crom_chunk)); - crom_add_chunk(src, root, &fwip->unit4, CROM_UDIR); - crom_add_entry(&fwip->unit4, CSRKEY_SPEC, CSRVAL_IETF); - crom_add_simple_text(src, &fwip->unit4, &fwip->spec4, "IANA"); - crom_add_entry(&fwip->unit4, CSRKEY_VER, 1); - crom_add_simple_text(src, &fwip->unit4, &fwip->ver4, "IPv4"); + memset(&sc->sc_unit4, 0, sizeof(struct crom_chunk)); + crom_add_chunk(src, root, &sc->sc_unit4, CROM_UDIR); + crom_add_entry(&sc->sc_unit4, CSRKEY_SPEC, CSRVAL_IETF); + crom_add_simple_text(src, &sc->sc_unit4, &sc->sc_spec4, "IANA"); + crom_add_entry(&sc->sc_unit4, CSRKEY_VER, 1); + crom_add_simple_text(src, &sc->sc_unit4, &sc->sc_ver4, "IPv4"); /* RFC3146 IPv6 over IEEE1394 */ - memset(&fwip->unit6, 0, sizeof(struct crom_chunk)); - crom_add_chunk(src, root, &fwip->unit6, CROM_UDIR); - crom_add_entry(&fwip->unit6, CSRKEY_SPEC, CSRVAL_IETF); - crom_add_simple_text(src, &fwip->unit6, &fwip->spec6, "IANA"); - crom_add_entry(&fwip->unit6, CSRKEY_VER, 2); - crom_add_simple_text(src, &fwip->unit6, &fwip->ver6, "IPv6"); - - fwip->last_dest.hi = 0; - fwip->last_dest.lo = 0; - FIREWIRE_BUSRESET(fwip->fw_softc.fwip_ifp); + memset(&sc->sc_unit6, 0, sizeof(struct crom_chunk)); + crom_add_chunk(src, root, &sc->sc_unit6, CROM_UDIR); + crom_add_entry(&sc->sc_unit6, CSRKEY_SPEC, CSRVAL_IETF); + crom_add_simple_text(src, &sc->sc_unit6, &sc->sc_spec6, "IANA"); + crom_add_entry(&sc->sc_unit6, CSRKEY_VER, 2); + crom_add_simple_text(src, &sc->sc_unit6, &sc->sc_ver6, "IPv6"); + + sc->sc_last_dest.hi = 0; + sc->sc_last_dest.lo = 0; + ieee1394_drain(sc->sc_eth.fwip_ifp); } static void fwip_output_callback(struct fw_xfer *xfer) { - struct fwip_softc *fwip; + struct fwip_softc *sc = (struct fwip_softc *)xfer->sc; struct ifnet *ifp; - int s; - fwip = (struct fwip_softc *)xfer->sc; - ifp = fwip->fw_softc.fwip_ifp; + ifp = sc->sc_eth.fwip_ifp; /* XXX error check */ FWIPDEBUG(ifp, "resp = %d\n", xfer->resp); if (xfer->resp != 0) - ifp->if_oerrors ++; - + ifp->if_oerrors++; + m_freem(xfer->mbuf); fw_xfer_unload(xfer); - s = splfwnet(); - FWIP_LOCK(fwip); - STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); - FWIP_UNLOCK(fwip); - splx(s); + mutex_enter(&sc->sc_mtx); + STAILQ_INSERT_TAIL(&sc->sc_xferlist, xfer, link); + mutex_exit(&sc->sc_mtx); /* for queue full */ - if (ifp->if_snd.ifq_head != NULL) { + if (ifp->if_snd.ifq_head != NULL) fwip_start(ifp); - } -} - -static void -fwip_start(struct ifnet *ifp) -{ - struct fwip_softc *fwip = - ((struct fwip_eth_softc *)ifp->if_softc)->fwip; - int s; - - FWIPDEBUG(ifp, "starting\n"); - - if (fwip->dma_ch < 0) { - struct mbuf *m = NULL; - - FWIPDEBUG(ifp, "not ready\n"); - - s = splfwnet(); - do { - IF_DEQUEUE(&ifp->if_snd, m); - if (m != NULL) - m_freem(m); - ifp->if_oerrors ++; - } while (m != NULL); - splx(s); - - return; - } - - s = splfwnet(); -#if defined(__FreeBSD__) - ifp->if_drv_flags |= IFF_DRV_OACTIVE; -#elif defined(__NetBSD__) - ifp->if_flags |= IFF_OACTIVE; -#endif - - if (ifp->if_snd.ifq_len != 0) - fwip_async_output(fwip, ifp); - -#if defined(__FreeBSD__) - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; -#elif defined(__NetBSD__) - ifp->if_flags &= ~IFF_OACTIVE; -#endif - splx(s); } /* Async. stream output */ static void -fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) +fwip_async_output(struct fwip_softc *sc, struct ifnet *ifp) { - struct firewire_comm *fc = fwip->fd.fc; + struct firewire_comm *fc = sc->sc_fd.fc; struct mbuf *m; struct m_tag *mtag; struct fw_hwaddr *destfw; @@ -714,25 +551,22 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) xferq = fc->atq; while ((xferq->queued < xferq->maxq - 1) && (ifp->if_snd.ifq_head != NULL)) { - FWIP_LOCK(fwip); - xfer = STAILQ_FIRST(&fwip->xferlist); - if (xfer == NULL) { - FWIP_UNLOCK(fwip); + mutex_enter(&sc->sc_mtx); + if (STAILQ_EMPTY(&sc->sc_xferlist)) { + mutex_exit(&sc->sc_mtx); #if 0 - printf("if_fwip: lack of xfer\n"); + aprint_normal("if_fwip: lack of xfer\n"); #endif break; } - STAILQ_REMOVE_HEAD(&fwip->xferlist, link); - FWIP_UNLOCK(fwip); - IF_DEQUEUE(&ifp->if_snd, m); if (m == NULL) { - FWIP_LOCK(fwip); - STAILQ_INSERT_HEAD(&fwip->xferlist, xfer, link); - FWIP_UNLOCK(fwip); + mutex_exit(&sc->sc_mtx); break; } + xfer = STAILQ_FIRST(&sc->sc_xferlist); + STAILQ_REMOVE_HEAD(&sc->sc_xferlist, link); + mutex_exit(&sc->sc_mtx); /* * Dig out the link-level address which @@ -740,19 +574,13 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) * discovery. If we don't have a link-level address, * just stick the thing on the broadcast channel. */ - mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 0); + mtag = m_tag_find(m, MTAG_FIREWIRE_HWADDR, 0); if (mtag == NULL) destfw = 0; else destfw = (struct fw_hwaddr *) (mtag + 1); /* - * We don't do any bpf stuff here - the generic code - * in firewire_output gives the packet to bpf before - * it adds the link-level encapsulation. - */ - - /* * Put the mbuf in the xfer early in case we hit an * error case below - fwip_output_callback will free * the mbuf. @@ -774,7 +602,7 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) */ uint32_t *p; - M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT); + M_PREPEND(m, 2 * sizeof(uint32_t), M_DONTWAIT); p = mtod(m, uint32_t *); fp->mode.stream.len = m->m_pkthdr.len; fp->mode.stream.chtag = broadcast_channel; @@ -799,31 +627,33 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) eui.hi = ntohl(destfw->sender_unique_ID_hi); eui.lo = ntohl(destfw->sender_unique_ID_lo); - if (fwip->last_dest.hi != eui.hi || - fwip->last_dest.lo != eui.lo) { + if (sc->sc_last_dest.hi != eui.hi || + sc->sc_last_dest.lo != eui.lo) { fd = fw_noderesolve_eui64(fc, &eui); if (!fd) { /* error */ - ifp->if_oerrors ++; + ifp->if_oerrors++; /* XXX set error code */ fwip_output_callback(xfer); continue; } - fwip->last_hdr.mode.wreqb.dst = FWLOCALBUS | fd->dst; - fwip->last_hdr.mode.wreqb.tlrt = 0; - fwip->last_hdr.mode.wreqb.tcode = FWTCODE_WREQB; - fwip->last_hdr.mode.wreqb.pri = 0; - fwip->last_hdr.mode.wreqb.src = nodeid; - fwip->last_hdr.mode.wreqb.dest_hi = + sc->sc_last_hdr.mode.wreqb.dst = + FWLOCALBUS | fd->dst; + sc->sc_last_hdr.mode.wreqb.tlrt = 0; + sc->sc_last_hdr.mode.wreqb.tcode = + FWTCODE_WREQB; + sc->sc_last_hdr.mode.wreqb.pri = 0; + sc->sc_last_hdr.mode.wreqb.src = nodeid; + sc->sc_last_hdr.mode.wreqb.dest_hi = ntohs(destfw->sender_unicast_FIFO_hi); - fwip->last_hdr.mode.wreqb.dest_lo = + sc->sc_last_hdr.mode.wreqb.dest_lo = ntohl(destfw->sender_unicast_FIFO_lo); - fwip->last_hdr.mode.wreqb.extcode = 0; - fwip->last_dest = eui; + sc->sc_last_hdr.mode.wreqb.extcode = 0; + sc->sc_last_dest = eui; } - fp->mode.wreqb = fwip->last_hdr.mode.wreqb; + fp->mode.wreqb = sc->sc_last_hdr.mode.wreqb; fp->mode.wreqb.len = m->m_pkthdr.len; xfer->send.spd = min(destfw->sspd, fc->speed); } @@ -837,39 +667,31 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) * for later transmission. */ xfer->mbuf = 0; - FWIP_LOCK(fwip); - STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); - FWIP_UNLOCK(fwip); + mutex_enter(&sc->sc_mtx); + STAILQ_INSERT_TAIL(&sc->sc_xferlist, xfer, link); + mutex_exit(&sc->sc_mtx); IF_PREPEND(&ifp->if_snd, m); break; } if (error) { /* error */ - ifp->if_oerrors ++; + ifp->if_oerrors++; /* XXX set error code */ fwip_output_callback(xfer); continue; } else { - ifp->if_opackets ++; + ifp->if_opackets++; i++; } } #if 0 if (i > 1) - printf("%d queued\n", i); + aprint_normal("%d queued\n", i); #endif if (i > 0) xferq->start(fc); } -static void -fwip_start_send (void *arg, int count) -{ - struct fwip_softc *fwip = arg; - - fwip->fd.fc->atq->start(fwip->fd.fc); -} - /* Async. stream output */ static void fwip_stream_input(struct fw_xferq *xferq) @@ -877,19 +699,19 @@ fwip_stream_input(struct fw_xferq *xferq) struct mbuf *m, *m0; struct m_tag *mtag; struct ifnet *ifp; - struct fwip_softc *fwip; + struct fwip_softc *sc; struct fw_bulkxfer *sxfer; struct fw_pkt *fp; uint16_t src; uint32_t *p; - fwip = (struct fwip_softc *)xferq->sc; - ifp = fwip->fw_softc.fwip_ifp; + sc = (struct fwip_softc *)xferq->sc; + ifp = sc->sc_eth.fwip_ifp; while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) { STAILQ_REMOVE_HEAD(&xferq->stvalid, link); fp = mtod(sxfer->mbuf, struct fw_pkt *); - if (fwip->fd.fc->irx_post != NULL) - fwip->fd.fc->irx_post(fwip->fd.fc, fp->mode.ld); + if (sc->sc_fd.fc->irx_post != NULL) + sc->sc_fd.fc->irx_post(sc->sc_fd.fc, fp->mode.ld); m = sxfer->mbuf; /* insert new rbuf */ @@ -898,7 +720,8 @@ fwip_stream_input(struct fw_xferq *xferq) m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size; STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link); } else - printf("fwip_as_input: m_getcl failed\n"); + aprint_error_ifnet(ifp, + "fwip_as_input: m_getcl failed\n"); /* * We must have a GASP header - leave the @@ -907,10 +730,10 @@ fwip_stream_input(struct fw_xferq *xferq) * stream header even though that isn't accounted for * in mode.stream.len. */ - if (sxfer->resp != 0 || fp->mode.stream.len < - 2*sizeof(uint32_t)) { + if (sxfer->resp != 0 || + fp->mode.stream.len < 2 * sizeof(uint32_t)) { m_freem(m); - ifp->if_ierrors ++; + ifp->if_ierrors++; continue; } m->m_len = m->m_pkthdr.len = fp->mode.stream.len @@ -931,12 +754,13 @@ fwip_stream_input(struct fw_xferq *xferq) * version. */ p = mtod(m, uint32_t *); - if ((((ntohl(p[1]) & 0xffff) << 8) | ntohl(p[2]) >> 24) != 0x00005e - || (ntohl(p[2]) & 0xffffff) != 1) { + if ((((ntohl(p[1]) & 0xffff) << 8) | ntohl(p[2]) >> 24) != + 0x00005e || + (ntohl(p[2]) & 0xffffff) != 1) { FWIPDEBUG(ifp, "Unrecognised GASP header %#08x %#08x\n", ntohl(p[1]), ntohl(p[2])); m_freem(m); - ifp->if_ierrors ++; + ifp->if_ierrors++; continue; } @@ -944,15 +768,15 @@ fwip_stream_input(struct fw_xferq *xferq) * Record the sender ID for possible BPF usage. */ src = ntohl(p[1]) >> 16; - if (bpf_peers_present(ifp->if_bpf)) { - mtag = m_tag_alloc(MTAG_FIREWIRE, - MTAG_FIREWIRE_SENDER_EUID, - 2*sizeof(uint32_t), M_NOWAIT); + if (ifp->if_bpf) { + mtag = m_tag_get(MTAG_FIREWIRE_SENDER_EUID, + 2 * sizeof(uint32_t), M_NOWAIT); if (mtag) { /* bpf wants it in network byte order */ struct fw_device *fd; uint32_t *p2 = (uint32_t *) (mtag + 1); - fd = fw_noderesolve_nodeid(fwip->fd.fc, + + fd = fw_noderesolve_nodeid(sc->sc_fd.fc, src & 0x3f); if (fd) { p2[0] = htonl(fd->eui.hi); @@ -970,15 +794,15 @@ fwip_stream_input(struct fw_xferq *xferq) */ m_adj(m, 3*sizeof(uint32_t)); m->m_pkthdr.rcvif = ifp; - FIREWIRE_INPUT(ifp, m, src); - ifp->if_ipackets ++; + ieee1394_input(ifp, m, src); + ifp->if_ipackets++; } if (STAILQ_FIRST(&xferq->stfree) != NULL) - fwip->fd.fc->irx_enable(fwip->fd.fc, fwip->dma_ch); + sc->sc_fd.fc->irx_enable(sc->sc_fd.fc, sc->sc_dma_ch); } static inline void -fwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer) +fwip_unicast_input_recycle(struct fwip_softc *sc, struct fw_xfer *xfer) { struct mbuf *m; @@ -988,12 +812,14 @@ fwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer) */ m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); if (m == NULL) - printf("fwip_unicast_input_recycle: m_getcl failed\n"); - xfer->mbuf = m; + aprint_error_dev(sc->sc_fd.dev, + "fwip_unicast_input_recycle: m_getcl failed\n"); xfer->recv.payload = mtod(m, uint32_t *); xfer->recv.pay_len = MCLBYTES; xfer->mbuf = m; - STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); + mutex_enter(&sc->sc_fwb.fwb_mtx); + STAILQ_INSERT_TAIL(&sc->sc_fwb.xferlist, xfer, link); + mutex_exit(&sc->sc_fwb.fwb_mtx); } static void @@ -1003,13 +829,12 @@ fwip_unicast_input(struct fw_xfer *xfer) struct mbuf *m; struct m_tag *mtag; struct ifnet *ifp; - struct fwip_softc *fwip; + struct fwip_softc *sc; struct fw_pkt *fp; - //struct fw_pkt *sfp; int rtcode; - fwip = (struct fwip_softc *)xfer->sc; - ifp = fwip->fw_softc.fwip_ifp; + sc = (struct fwip_softc *)xfer->sc; + ifp = sc->sc_eth.fwip_ifp; m = xfer->mbuf; xfer->mbuf = 0; fp = &xfer->recv.hdr; @@ -1032,28 +857,29 @@ fwip_unicast_input(struct fw_xfer *xfer) * Pick up a new mbuf and stick it on the back of the receive * queue. */ - fwip_unicast_input_recycle(fwip, xfer); + fwip_unicast_input_recycle(sc, xfer); /* * If we've already rejected the packet, give up now. */ if (rtcode != FWRCODE_COMPLETE) { m_freem(m); - ifp->if_ierrors ++; + ifp->if_ierrors++; return; } - if (bpf_peers_present(ifp->if_bpf)) { + if (ifp->if_bpf) { /* * Record the sender ID for possible BPF usage. */ - mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, - 2*sizeof(uint32_t), M_NOWAIT); + mtag = m_tag_get(MTAG_FIREWIRE_SENDER_EUID, + 2 * sizeof(uint32_t), M_NOWAIT); if (mtag) { /* bpf wants it in network byte order */ struct fw_device *fd; uint32_t *p = (uint32_t *) (mtag + 1); - fd = fw_noderesolve_nodeid(fwip->fd.fc, + + fd = fw_noderesolve_nodeid(sc->sc_fd.fc, fp->mode.wreqb.src & 0x3f); if (fd) { p[0] = htonl(fd->eui.hi); @@ -1073,36 +899,6 @@ fwip_unicast_input(struct fw_xfer *xfer) */ m->m_len = m->m_pkthdr.len = fp->mode.wreqb.len; m->m_pkthdr.rcvif = ifp; - FIREWIRE_INPUT(ifp, m, fp->mode.wreqb.src); - ifp->if_ipackets ++; + ieee1394_input(ifp, m, fp->mode.wreqb.src); + ifp->if_ipackets++; } - -#if defined(__FreeBSD__) -static devclass_t fwip_devclass; - -static device_method_t fwip_methods[] = { - /* device interface */ - DEVMETHOD(device_identify, fwip_identify), - DEVMETHOD(device_probe, fwip_probe), - DEVMETHOD(device_attach, fwip_attach), - DEVMETHOD(device_detach, fwip_detach), - { 0, 0 } -}; - -static driver_t fwip_driver = { - "fwip", - fwip_methods, - sizeof(struct fwip_softc), -}; - - -#ifdef __DragonFly__ -DECLARE_DUMMY_MODULE(fwip); -#endif -DRIVER_MODULE(fwip, firewire, fwip_driver, fwip_devclass, 0, 0); -MODULE_VERSION(fwip, 1); -MODULE_DEPEND(fwip, firewire, 1, 1, 1); -#elif defined(__NetBSD__) -CFATTACH_DECL_NEW(fwip, sizeof(struct fwip_softc), - fwipmatch, fwipattach, fwipdetach, NULL); -#endif diff --git a/sys/dev/ieee1394/if_fwipvar.h b/sys/dev/ieee1394/if_fwipvar.h index c0bc90559e8..e7947c5e903 100644 --- a/sys/dev/ieee1394/if_fwipvar.h +++ b/sys/dev/ieee1394/if_fwipvar.h @@ -1,10 +1,10 @@ -/* $NetBSD: if_fwipvar.h,v 1.4 2007/11/05 19:08:57 kiyohara Exp $ */ +/* $NetBSD: if_fwipvar.h,v 1.5 2010/03/29 03:05:28 kiyohara Exp $ */ /*- * Copyright (c) 2004 * Doug Rabson * Copyright (c) 2002-2003 * Hidetoshi Shimokawa. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -21,7 +21,7 @@ * 4. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -33,39 +33,37 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * + * * $FreeBSD: src/sys/dev/firewire/if_fwipvar.h,v 1.5 2007/06/06 14:31:36 simokawa Exp $ */ -#ifndef _NET_IF_FWIPVAR_H_ -#define _NET_IF_FWIPVAR_H_ +#ifndef _IF_FWIPVAR_H_ +#define _IF_FWIPVAR_H_ + +#define MTAG_FIREWIRE_HWADDR 0 +#define MTAG_FIREWIRE_SENDER_EUID 1 + struct fwip_softc { /* XXX this must be first for fd.post_explore() */ - struct firewire_dev_comm fd; - short dma_ch; - struct fw_bind fwb; - struct fw_eui64 last_dest; - struct fw_pkt last_hdr; - fw_task_t start_send; - STAILQ_HEAD(, fw_xfer) xferlist; - struct crom_chunk unit4; /* unit directory for IPv4 */ - struct crom_chunk spec4; /* specifier description IPv4 */ - struct crom_chunk ver4; /* version description IPv4 */ - struct crom_chunk unit6; /* unit directory for IPv6 */ - struct crom_chunk spec6; /* specifier description IPv6 */ - struct crom_chunk ver6; /* version description IPv6 */ + struct firewire_dev_comm sc_fd; + short sc_dma_ch; + struct fw_bind sc_fwb; + struct fw_eui64 sc_last_dest; + struct fw_pkt sc_last_hdr; + STAILQ_HEAD(, fw_xfer) sc_xferlist; + struct crom_chunk sc_unit4; /* unit directory for IPv4 */ + struct crom_chunk sc_spec4; /* specifier description IPv4 */ + struct crom_chunk sc_ver4; /* version description IPv4 */ + struct crom_chunk sc_unit6; /* unit directory for IPv6 */ + struct crom_chunk sc_spec6; /* specifier description IPv6 */ + struct crom_chunk sc_ver6; /* version description IPv6 */ struct fwip_eth_softc { -#if defined(__NetBSD__) struct ieee1394com fwcom; -#endif struct ifnet *fwip_ifp; struct fwip_softc *fwip; - } fw_softc; - fw_mtx_t mtx; + } sc_eth; + kmutex_t sc_mtx; }; -#define FWIP_LOCK(fwip) fw_mtx_lock(&(fwip)->mtx) -#define FWIP_UNLOCK(fwip) fw_mtx_unlock(&(fwip)->mtx) - -#endif /* !_NET_IF_FWIPVAR_H_ */ +#endif /* !_IF_FWIPVAR_H_ */ diff --git a/sys/dev/ieee1394/sbp.c b/sys/dev/ieee1394/sbp.c index 704ec84f6e9..c5338dfceff 100644 --- a/sys/dev/ieee1394/sbp.c +++ b/sys/dev/ieee1394/sbp.c @@ -1,4 +1,4 @@ -/* $NetBSD: sbp.c,v 1.28 2009/05/12 12:16:55 cegger Exp $ */ +/* $NetBSD: sbp.c,v 1.29 2010/03/29 03:05:28 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -31,72 +31,25 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/firewire/sbp.c,v 1.92 2007/06/06 14:31:36 simokawa Exp $ + * + * $FreeBSD: src/sys/dev/firewire/sbp.c,v 1.100 2009/02/18 18:41:34 sbruno Exp $ * */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sbp.c,v 1.28 2009/05/12 12:16:55 cegger Exp $"); - -#if defined(__FreeBSD__) -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/bus.h> -#include <sys/malloc.h> -#if defined(__FreeBSD__) && __FreeBSD_version >= 501102 -#include <sys/lock.h> -#include <sys/mutex.h> -#endif +__KERNEL_RCSID(0, "$NetBSD: sbp.c,v 1.29 2010/03/29 03:05:28 kiyohara Exp $"); -#if defined(__DragonFly__) || __FreeBSD_version < 500106 -#include <sys/devicestat.h> /* for struct devstat */ -#endif -#ifdef __DragonFly__ -#include <bus/cam/cam.h> -#include <bus/cam/cam_ccb.h> -#include <bus/cam/cam_sim.h> -#include <bus/cam/cam_xpt_sim.h> -#include <bus/cam/cam_debug.h> -#include <bus/cam/cam_periph.h> -#include <bus/cam/scsi/scsi_all.h> - -#include <bus/firewire/fw_port.h> -#include <bus/firewire/firewire.h> -#include <bus/firewire/firewirereg.h> -#include <bus/firewire/fwdma.h> -#include <bus/firewire/iec13213.h> -#include "sbp.h" -#else -#include <cam/cam.h> -#include <cam/cam_ccb.h> -#include <cam/cam_sim.h> -#include <cam/cam_xpt_sim.h> -#include <cam/cam_debug.h> -#include <cam/cam_periph.h> -#include <cam/scsi/scsi_all.h> - -#include <dev/firewire/fw_port.h> -#include <dev/firewire/firewire.h> -#include <dev/firewire/firewirereg.h> -#include <dev/firewire/fwdma.h> -#include <dev/firewire/iec13213.h> -#include <dev/firewire/sbp.h> -#endif -#elif defined(__NetBSD__) #include <sys/param.h> #include <sys/device.h> #include <sys/errno.h> #include <sys/buf.h> +#include <sys/callout.h> +#include <sys/condvar.h> #include <sys/kernel.h> #include <sys/kthread.h> #include <sys/malloc.h> +#include <sys/mutex.h> #include <sys/proc.h> #include <sys/sysctl.h> @@ -108,7 +61,6 @@ __KERNEL_RCSID(0, "$NetBSD: sbp.c,v 1.28 2009/05/12 12:16:55 cegger Exp $"); #include <dev/scsipi/scsiconf.h> #include <dev/scsipi/scsipiconf.h> -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/firewirereg.h> #include <dev/ieee1394/fwdma.h> @@ -116,32 +68,28 @@ __KERNEL_RCSID(0, "$NetBSD: sbp.c,v 1.28 2009/05/12 12:16:55 cegger Exp $"); #include <dev/ieee1394/sbp.h> #include "locators.h" -#endif -#define ccb_sdev_ptr spriv_ptr0 -#define ccb_sbp_ptr spriv_ptr1 -#define SBP_NUM_TARGETS 8 /* MAX 64 */ -/* - * Scan_bus doesn't work for more than 8 LUNs - * because of CAM_SCSI2_MAXLUN in cam_xpt.c - */ -#define SBP_NUM_LUNS 64 -#define SBP_MAXPHYS MIN(MAXPHYS, (512*1024) /* 512KB */) -#define SBP_DMA_SIZE PAGE_SIZE -#define SBP_LOGIN_SIZE sizeof(struct sbp_login_res) +#define SBP_FWDEV_ALIVE(fwdev) (((fwdev)->status == FWDEVATTACHED) \ + && crom_has_specver((fwdev)->csrrom, CSRVAL_ANSIT10, CSRVAL_T10SBP2)) + +#define SBP_NUM_TARGETS 8 /* MAX 64 */ +#define SBP_NUM_LUNS 64 +#define SBP_MAXPHYS MIN(MAXPHYS, (512*1024) /* 512KB */) +#define SBP_DMA_SIZE PAGE_SIZE +#define SBP_LOGIN_SIZE sizeof(struct sbp_login_res) #define SBP_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb)) -#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS) +#define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS) -/* +/* * STATUS FIFO addressing * bit * ----------------------- * 0- 1( 2): 0 (alignment) * 2- 9( 8): lun * 10-31(14): unit - * 32-47(16): SBP_BIND_HI - * 48-64(16): bus_id, node_id + * 32-47(16): SBP_BIND_HI + * 48-64(16): bus_id, node_id */ #define SBP_BIND_HI 0x1 #define SBP_DEV2ADDR(u, l) \ @@ -166,34 +114,6 @@ static int scan_delay = 500; /* msec */ static int use_doorbell = 0; static int sbp_tags = 0; -#if defined(__FreeBSD__) -SYSCTL_DECL(_hw_firewire); -SYSCTL_NODE(_hw_firewire, OID_AUTO, sbp, CTLFLAG_RD, 0, "SBP-II Subsystem"); -SYSCTL_INT(_debug, OID_AUTO, sbp_debug, CTLFLAG_RW, &debug, 0, - "SBP debug flag"); -SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, auto_login, CTLFLAG_RW, &auto_login, 0, - "SBP perform login automatically"); -SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, max_speed, CTLFLAG_RW, &max_speed, 0, - "SBP transfer max speed"); -SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, exclusive_login, CTLFLAG_RW, - &ex_login, 0, "SBP enable exclusive login"); -SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, login_delay, CTLFLAG_RW, - &login_delay, 0, "SBP login delay in msec"); -SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, scan_delay, CTLFLAG_RW, - &scan_delay, 0, "SBP scan delay in msec"); -SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, use_doorbell, CTLFLAG_RW, - &use_doorbell, 0, "SBP use doorbell request"); -SYSCTL_INT(_hw_firewire_sbp, OID_AUTO, tags, CTLFLAG_RW, &sbp_tags, 0, - "SBP tagged queuing support"); - -TUNABLE_INT("hw.firewire.sbp.auto_login", &auto_login); -TUNABLE_INT("hw.firewire.sbp.max_speed", &max_speed); -TUNABLE_INT("hw.firewire.sbp.exclusive_login", &ex_login); -TUNABLE_INT("hw.firewire.sbp.login_delay", &login_delay); -TUNABLE_INT("hw.firewire.sbp.scan_delay", &scan_delay); -TUNABLE_INT("hw.firewire.sbp.use_doorbell", &use_doorbell); -TUNABLE_INT("hw.firewire.sbp.tags", &sbp_tags); -#elif defined(__NetBSD__) static int sysctl_sbp_verify(SYSCTLFN_PROTO, int lower, int upper); static int sysctl_sbp_verify_max_speed(SYSCTLFN_PROTO); static int sysctl_sbp_verify_tags(SYSCTLFN_PROTO); @@ -210,16 +130,14 @@ SYSCTL_SETUP(sysctl_sbp, "sysctl sbp(4) subtree setup") if ((rc = sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, - NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) { + NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) goto err; - } if ((rc = sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT, CTLTYPE_NODE, "sbp", SYSCTL_DESCR("sbp controls"), NULL, 0, NULL, - 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) goto err; - } sbp_node_num = node->sysctl_num; /* sbp auto login flag */ @@ -227,77 +145,69 @@ SYSCTL_SETUP(sysctl_sbp, "sysctl sbp(4) subtree setup") CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "auto_login", SYSCTL_DESCR("SBP perform login automatically"), NULL, 0, &auto_login, - 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) goto err; - } /* sbp max speed */ if ((rc = sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "max_speed", SYSCTL_DESCR("SBP transfer max speed"), sysctl_sbp_verify_max_speed, 0, &max_speed, - 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) goto err; - } /* sbp exclusive login flag */ if ((rc = sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "exclusive_login", SYSCTL_DESCR("SBP enable exclusive login"), NULL, 0, &ex_login, - 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) goto err; - } /* sbp login delay */ if ((rc = sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "login_delay", SYSCTL_DESCR("SBP login delay in msec"), NULL, 0, &login_delay, - 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) goto err; - } /* sbp scan delay */ if ((rc = sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "scan_delay", SYSCTL_DESCR("SBP scan delay in msec"), NULL, 0, &scan_delay, - 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) goto err; - } /* sbp use doorbell flag */ if ((rc = sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "use_doorbell", SYSCTL_DESCR("SBP use doorbell request"), NULL, 0, &use_doorbell, - 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) goto err; - } /* sbp force tagged queuing */ if ((rc = sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "tags", SYSCTL_DESCR("SBP tagged queuing support"), sysctl_sbp_verify_tags, 0, &sbp_tags, - 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) goto err; - } /* sbp driver debug flag */ if ((rc = sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "sbp_debug", SYSCTL_DESCR("SBP debug flag"), NULL, 0, &debug, - 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, sbp_node_num, CTL_CREATE, CTL_EOL)) != 0) goto err; - } return; err: - printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); + aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); } static int @@ -311,28 +221,29 @@ sysctl_sbp_verify(SYSCTLFN_ARGS, int lower, int upper) node.sysctl_data = &t; error = sysctl_lookup(SYSCTLFN_CALL(&node)); if (error || newp == NULL) - return (error); + return error; if (t < lower || t > upper) - return (EINVAL); + return EINVAL; *(int*)rnode->sysctl_data = t; - return (0); + return 0; } static int sysctl_sbp_verify_max_speed(SYSCTLFN_ARGS) { - return (sysctl_sbp_verify(SYSCTLFN_CALL(rnode), 0, FWSPD_S400)); + + return sysctl_sbp_verify(SYSCTLFN_CALL(rnode), 0, FWSPD_S400); } static int sysctl_sbp_verify_tags(SYSCTLFN_ARGS) { - return (sysctl_sbp_verify(SYSCTLFN_CALL(rnode), -1, 1)); + + return sysctl_sbp_verify(SYSCTLFN_CALL(rnode), -1, 1); } -#endif #define NEED_RESPONSE 0 @@ -343,17 +254,23 @@ sysctl_sbp_verify_tags(SYSCTLFN_ARGS) #define SBP_IND_MAX howmany(SBP_MAXPHYS, PAGE_SIZE) #endif struct sbp_ocb { - STAILQ_ENTRY(sbp_ocb) ocb; - sbp_scsi_xfer *sxfer; - bus_addr_t bus_addr; uint32_t orb[8]; -#define IND_PTR_OFFSET (8*sizeof(uint32_t)) - struct ind_ptr ind_ptr[SBP_IND_MAX]; +#define IND_PTR_OFFSET (sizeof(uint32_t) * 8) + struct ind_ptr ind_ptr[SBP_IND_MAX]; + struct scsipi_xfer *xs; struct sbp_dev *sdev; - int flags; /* XXX should be removed */ + uint16_t index; + uint16_t flags; /* XXX should be removed */ bus_dmamap_t dmamap; + bus_addr_t bus_addr; + STAILQ_ENTRY(sbp_ocb) ocb; }; +#define SBP_ORB_DMA_SYNC(dma, i, op) \ + bus_dmamap_sync((dma).dma_tag, (dma).dma_map, \ + sizeof(struct sbp_ocb) * (i), \ + sizeof(ocb->orb) + sizeof(ocb->ind_ptr), (op)); + #define OCB_ACT_MGM 0 #define OCB_ACT_CMD 1 #define OCB_MATCH(o,s) ((o)->bus_addr == ntohl((s)->orb_lo)) @@ -382,11 +299,7 @@ struct sbp_dev{ #define ORB_DOORBELL_NEED (1 << 5) #define ORB_SHORTAGE (1 << 6) uint16_t flags; -#if defined(__FreeBSD__) - struct cam_path *path; -#elif defined(__NetBSD__) struct scsipi_periph *periph; -#endif struct sbp_target *target; struct fwdma_alloc dma; struct sbp_login_res *login; @@ -398,6 +311,7 @@ struct sbp_dev{ char vendor[32]; char product[32]; char revision[10]; + char bustgtlun[32]; }; struct sbp_target { @@ -410,88 +324,87 @@ struct sbp_target { struct sbp_ocb *mgm_ocb_cur; STAILQ_HEAD(, sbp_ocb) mgm_ocb_queue; struct callout mgm_ocb_timeout; - struct callout scan_callout; STAILQ_HEAD(, fw_xfer) xferlist; int n_xfer; }; struct sbp_softc { - struct firewire_dev_comm fd; -#if defined(__FreeBSD__) - struct cam_sim *sim; - struct cam_path *path; -#elif defined(__NetBSD__) - struct scsipi_adapter sc_adapter; + struct firewire_dev_comm sc_fd; + struct scsipi_adapter sc_adapter; struct scsipi_channel sc_channel; device_t sc_bus; - struct lwp *lwp; -#endif - struct sbp_target target; - struct fw_bind fwb; - fw_bus_dma_tag_t dmat; - struct timeval last_busreset; -#define SIMQ_FREEZED 1 - int flags; - fw_mtx_t mtx; + struct lwp *sc_lwp; + struct sbp_target sc_target; + struct fw_bind sc_fwb; + bus_dma_tag_t sc_dmat; + struct timeval sc_last_busreset; + int sc_flags; + kmutex_t sc_mtx; + kcondvar_t sc_cv; }; -#define SBP_LOCK(sbp) fw_mtx_lock(&(sbp)->mtx) -#define SBP_UNLOCK(sbp) fw_mtx_unlock(&(sbp)->mtx) -#if defined(__NetBSD__) -int sbpmatch (device_t, cfdata_t, void *); -void sbpattach (device_t parent, device_t self, void *aux); -int sbpdetach (device_t self, int flags); -#endif -static void sbp_post_explore (void *); -static void sbp_recv (struct fw_xfer *); -static void sbp_mgm_callback (struct fw_xfer *); -#if 0 -static void sbp_cmd_callback (struct fw_xfer *); -#endif -static void sbp_orb_pointer (struct sbp_dev *, struct sbp_ocb *); -static void sbp_doorbell(struct sbp_dev *); -static void sbp_execute_ocb (void *, bus_dma_segment_t *, int, int); -static void sbp_free_ocb (struct sbp_dev *, struct sbp_ocb *); -static void sbp_abort_ocb (struct sbp_ocb *, int); -static void sbp_abort_all_ocbs (struct sbp_dev *, int); -static struct fw_xfer * sbp_write_cmd (struct sbp_dev *, int, int); -static struct sbp_ocb * sbp_get_ocb (struct sbp_dev *); -static struct sbp_ocb * sbp_enqueue_ocb (struct sbp_dev *, struct sbp_ocb *); -static struct sbp_ocb * sbp_dequeue_ocb (struct sbp_dev *, struct sbp_status *); -static void sbp_free_sdev(struct sbp_dev *); -static void sbp_free_target (struct sbp_target *); -static void sbp_mgm_timeout (void *arg); -static void sbp_timeout (void *arg); -static void sbp_mgm_orb (struct sbp_dev *, int, struct sbp_ocb *); -#if defined(__FreeBSD__) - -MALLOC_DEFINE(M_SBP, "sbp", "SBP-II/FireWire"); -#elif defined(__NetBSD__) -static void sbp_scsipi_request( - struct scsipi_channel *, scsipi_adapter_req_t, void *); +MALLOC_DEFINE(M_SBP, "sbp", "SBP-II/IEEE1394"); + + +static int sbpmatch(device_t, cfdata_t, void *); +static void sbpattach(device_t, device_t, void *); +static int sbpdetach(device_t, int); + +static void sbp_scsipi_request(struct scsipi_channel *, scsipi_adapter_req_t, + void *); static void sbp_minphys(struct buf *); -MALLOC_DEFINE(M_SBP, "sbp", "SBP-II/IEEE1394"); +static void sbp_show_sdev_info(struct sbp_dev *); +static void sbp_alloc_lun(struct sbp_target *); +static struct sbp_target *sbp_alloc_target(struct sbp_softc *, + struct fw_device *); +static void sbp_probe_lun(struct sbp_dev *); +static void sbp_login_callout(void *); +static void sbp_login(struct sbp_dev *); +static void sbp_probe_target(void *); +static void sbp_post_busreset(void *); +static void sbp_post_explore(void *); +#if NEED_RESPONSE +static void sbp_loginres_callback(struct fw_xfer *); #endif +static inline void sbp_xfer_free(struct fw_xfer *); +static void sbp_reset_start_callback(struct fw_xfer *); +static void sbp_reset_start(struct sbp_dev *); +static void sbp_mgm_callback(struct fw_xfer *); +static void sbp_scsipi_scan_target(void *); +static inline void sbp_scan_dev(struct sbp_dev *); +static void sbp_do_attach(struct fw_xfer *); +static void sbp_agent_reset_callback(struct fw_xfer *); +static void sbp_agent_reset(struct sbp_dev *); +static void sbp_busy_timeout_callback(struct fw_xfer *); +static void sbp_busy_timeout(struct sbp_dev *); +static void sbp_orb_pointer_callback(struct fw_xfer *); +static void sbp_orb_pointer(struct sbp_dev *, struct sbp_ocb *); +static void sbp_doorbell_callback(struct fw_xfer *); +static void sbp_doorbell(struct sbp_dev *); +static struct fw_xfer *sbp_write_cmd(struct sbp_dev *, int, int); +static void sbp_mgm_orb(struct sbp_dev *, int, struct sbp_ocb *); +static void sbp_print_scsi_cmd(struct sbp_ocb *); +static void sbp_scsi_status(struct sbp_status *, struct sbp_ocb *); +static void sbp_fix_inq_data(struct sbp_ocb *); +static void sbp_recv(struct fw_xfer *); +static int sbp_logout_all(struct sbp_softc *); +static void sbp_free_sdev(struct sbp_dev *); +static void sbp_free_target(struct sbp_target *); +static void sbp_scsipi_detach_sdev(struct sbp_dev *); +static void sbp_scsipi_detach_target(struct sbp_target *); +static void sbp_target_reset(struct sbp_dev *, int); +static void sbp_mgm_timeout(void *); +static void sbp_timeout(void *); +static void sbp_action1(struct sbp_softc *, struct scsipi_xfer *); +static void sbp_execute_ocb(struct sbp_ocb *, bus_dma_segment_t *, int); +static struct sbp_ocb *sbp_dequeue_ocb(struct sbp_dev *, struct sbp_status *); +static struct sbp_ocb *sbp_enqueue_ocb(struct sbp_dev *, struct sbp_ocb *); +static struct sbp_ocb *sbp_get_ocb(struct sbp_dev *); +static void sbp_free_ocb(struct sbp_dev *, struct sbp_ocb *); +static void sbp_abort_ocb(struct sbp_ocb *, int); +static void sbp_abort_all_ocbs(struct sbp_dev *, int); -#if defined(__FreeBSD__) -/* cam related functions */ -static void sbp_action(struct cam_sim *, sbp_scsi_xfer *sxfer); -static void sbp_poll(struct cam_sim *); -static void sbp_cam_scan_lun(struct cam_periph *, sbp_scsi_xfer *); -static void sbp_cam_scan_target(void *); -static void sbp_cam_detach_sdev(struct sbp_dev *); -static void sbp_cam_detach_target (struct sbp_target *); -#define SBP_DETACH_SDEV(sd) sbp_cam_detach_sdev((sd)) -#define SBP_DETACH_TARGET(st) sbp_cam_detach_target((st)) -#elif defined(__NetBSD__) -/* scsipi related functions */ -static void sbp_scsipi_scan_target(void *); -static void sbp_scsipi_detach_sdev(struct sbp_dev *); -static void sbp_scsipi_detach_target (struct sbp_target *); -#define SBP_DETACH_SDEV(sd) sbp_scsipi_detach_sdev((sd)) -#define SBP_DETACH_TARGET(st) sbp_scsipi_detach_target((st)) -#endif static const char *orb_status0[] = { /* 0 */ "No additional information to report", @@ -537,88 +450,213 @@ static const char *orb_status1_serial_bus_error[] = { /* F */ "Address error" }; -#if defined(__FreeBSD__) -#if 0 -static void -sbp_identify(driver_t *driver, device_t parent) + +CFATTACH_DECL_NEW(sbp, sizeof(struct sbp_softc), + sbpmatch, sbpattach, sbpdetach, NULL); + + +int +sbpmatch(device_t parent, cfdata_t cf, void *aux) { - device_t child; -SBP_DEBUG(0) - printf("sbp_identify\n"); -END_DEBUG + struct fw_attach_args *fwa = aux; - child = BUS_ADD_CHILD(parent, 0, "sbp", fw_get_unit(parent)); + if (strcmp(fwa->name, "sbp") == 0) + return 1; + return 0; } -#endif -/* - * sbp_probe() - */ -static int -sbp_probe(device_t dev) +static void +sbpattach(device_t parent, device_t self, void *aux) { - device_t pa; + struct sbp_softc *sc = device_private(self); + struct fw_attach_args *fwa = (struct fw_attach_args *)aux; + struct firewire_comm *fc; + struct scsipi_adapter *sc_adapter = &sc->sc_adapter; + struct scsipi_channel *sc_channel = &sc->sc_channel; + struct sbp_target *target = &sc->sc_target; + int dv_unit; -SBP_DEBUG(0) - printf("sbp_probe\n"); -END_DEBUG + aprint_naive("\n"); + aprint_normal(": SBP-2/SCSI over IEEE1394\n"); + + sc->sc_fd.dev = self; + + if (cold) + sbp_cold++; + sc->sc_fd.fc = fc = fwa->fc; + mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM); + cv_init(&sc->sc_cv, "sbp"); + + if (max_speed < 0) + max_speed = fc->speed; + + sc->sc_dmat = fc->dmat; + + sc->sc_target.fwdev = NULL; + sc->sc_target.luns = NULL; - pa = device_get_parent(dev); - if(fw_get_unit(dev) != fw_get_unit(pa)){ - return(ENXIO); + if (sbp_alloc_target(sc, fwa->fwdev) == NULL) + return; + + sc_adapter->adapt_dev = sc->sc_fd.dev; + sc_adapter->adapt_nchannels = 1; + sc_adapter->adapt_max_periph = 1; + sc_adapter->adapt_request = sbp_scsipi_request; + sc_adapter->adapt_minphys = sbp_minphys; + sc_adapter->adapt_openings = 8; + + sc_channel->chan_adapter = sc_adapter; + sc_channel->chan_bustype = &scsi_bustype; + sc_channel->chan_defquirks = PQUIRK_ONLYBIG; + sc_channel->chan_channel = 0; + sc_channel->chan_flags = SCSIPI_CHAN_CANGROW | SCSIPI_CHAN_NOSETTLE; + + sc_channel->chan_ntargets = 1; + sc_channel->chan_nluns = target->num_lun; /* We set nluns 0 now */ + sc_channel->chan_id = 1; + + sc->sc_bus = config_found(sc->sc_fd.dev, sc_channel, scsiprint); + if (sc->sc_bus == NULL) { + aprint_error_dev(self, "attach failed\n"); + return; } - device_set_desc(dev, "SBP-2/SCSI over FireWire"); + /* We reserve 16 bit space (4 bytes X 64 unit X 256 luns) */ + dv_unit = device_unit(sc->sc_fd.dev); + sc->sc_fwb.start = SBP_DEV2ADDR(dv_unit, 0); + sc->sc_fwb.end = SBP_DEV2ADDR(dv_unit, -1); + mutex_init(&sc->sc_fwb.fwb_mtx, MUTEX_DEFAULT, IPL_VM); + /* pre-allocate xfer */ + STAILQ_INIT(&sc->sc_fwb.xferlist); + fw_xferlist_add(&sc->sc_fwb.xferlist, M_SBP, + /*send*/ 0, /*recv*/ SBP_RECV_LEN, SBP_NUM_OCB / 2, + fc, (void *)sc, sbp_recv); + fw_bindadd(fc, &sc->sc_fwb); -#if 0 - if (bootverbose) - debug = bootverbose; -#endif + sc->sc_fd.post_busreset = sbp_post_busreset; + sc->sc_fd.post_explore = sbp_post_explore; - return (0); + if (fc->status != FWBUSNOTREADY) { + sbp_post_busreset((void *)sc); + sbp_post_explore((void *)sc); + } } -#elif defined(__NetBSD__) -int -sbpmatch(device_t parent, cfdata_t cf, void *aux) + +static int +sbpdetach(device_t self, int flags) { - struct fw_attach_args *fwa = aux; + struct sbp_softc *sc = device_private(self); + struct firewire_comm *fc = sc->sc_fd.fc; + + sbp_scsipi_detach_target(&sc->sc_target); + + if (SBP_FWDEV_ALIVE(sc->sc_target.fwdev)) { + sbp_logout_all(sc); + + /* XXX wait for logout completion */ + mutex_enter(&sc->sc_mtx); + cv_timedwait_sig(&sc->sc_cv, &sc->sc_mtx, hz/2); + mutex_exit(&sc->sc_mtx); + } + + sbp_free_target(&sc->sc_target); + + fw_bindremove(fc, &sc->sc_fwb); + fw_xferlist_remove(&sc->sc_fwb.xferlist); + mutex_destroy(&sc->sc_fwb.fwb_mtx); + + mutex_destroy(&sc->sc_mtx); - if (strcmp(fwa->name, "sbp") == 0) - return 1; return 0; } -#endif + static void -sbp_show_sdev_info(struct sbp_dev *sdev, int new) +sbp_scsipi_request(struct scsipi_channel *channel, scsipi_adapter_req_t req, + void *arg) { - struct fw_device *fwdev; + struct sbp_softc *sc = device_private(channel->chan_adapter->adapt_dev); + struct scsipi_xfer *xs = arg; + int i; - printf("%s:%d:%d ", - fw_get_nameunit(sdev->target->sbp->fd.dev), - sdev->target->target_id, - sdev->lun_id - ); - if (new == 2) { - return; - } - fwdev = sdev->target->fwdev; - printf("ordered:%d type:%d EUI:%08x%08x node:%d " - "speed:%d maxrec:%d", - (sdev->type & 0x40) >> 6, - (sdev->type & 0x1f), - fwdev->eui.hi, - fwdev->eui.lo, - fwdev->dst, - fwdev->speed, - fwdev->maxrec - ); - if (new) - printf(" new!\n"); - else +SBP_DEBUG(1) + printf("Called sbp_scsipi_request\n"); +END_DEBUG + + switch (req) { + case ADAPTER_REQ_RUN_XFER: +SBP_DEBUG(1) + printf("Got req_run_xfer\n"); + printf("xs control: 0x%08x, timeout: %d\n", + xs->xs_control, xs->timeout); + printf("opcode: 0x%02x\n", (int)xs->cmd->opcode); + for (i = 0; i < 15; i++) + printf("0x%02x ",(int)xs->cmd->bytes[i]); printf("\n"); - sbp_show_sdev_info(sdev, 2); - printf("'%s' '%s' '%s'\n", sdev->vendor, sdev->product, sdev->revision); +END_DEBUG + if (xs->xs_control & XS_CTL_RESET) { +SBP_DEBUG(1) + printf("XS_CTL_RESET not support\n"); +END_DEBUG + break; + } +#define SBPSCSI_SBP2_MAX_CDB 12 + if (xs->cmdlen > SBPSCSI_SBP2_MAX_CDB) { +SBP_DEBUG(0) + printf( + "sbp doesn't support cdb's larger than %d bytes\n", + SBPSCSI_SBP2_MAX_CDB); +END_DEBUG + xs->error = XS_DRIVER_STUFFUP; + scsipi_done(xs); + return; + } + sbp_action1(sc, xs); + + break; + case ADAPTER_REQ_GROW_RESOURCES: +SBP_DEBUG(1) + printf("Got req_grow_resources\n"); +END_DEBUG + break; + case ADAPTER_REQ_SET_XFER_MODE: +SBP_DEBUG(1) + printf("Got set xfer mode\n"); +END_DEBUG + break; + default: + panic("Unknown request: %d\n", (int)req); + } +} + +static void +sbp_minphys(struct buf *bp) +{ + + minphys(bp); +} + + +/* + * Display device characteristics on the console + */ +static void +sbp_show_sdev_info(struct sbp_dev *sdev) +{ + struct fw_device *fwdev = sdev->target->fwdev; + struct sbp_softc *sc = sdev->target->sbp; + + aprint_normal_dev(sc->sc_fd.dev, + "ordered:%d type:%d EUI:%08x%08x node:%d speed:%d maxrec:%d\n", + (sdev->type & 0x40) >> 6, + (sdev->type & 0x1f), + fwdev->eui.hi, + fwdev->eui.lo, + fwdev->dst, + fwdev->speed, + fwdev->maxrec); + aprint_normal_dev(sc->sc_fd.dev, "%s '%s' '%s' '%s'\n", + sdev->bustgtlun, sdev->vendor, sdev->product, sdev->revision); } static void @@ -627,10 +665,10 @@ sbp_alloc_lun(struct sbp_target *target) struct crom_context cc; struct csrreg *reg; struct sbp_dev *sdev, **newluns; - struct sbp_softc *sbp; + struct sbp_softc *sc; int maxlun, lun, i; - sbp = target->sbp; + sc = target->sbp; crom_init_context(&cc, target->fwdev->csrrom); /* XXX shoud parse appropriate unit directories only */ maxlun = -1; @@ -647,24 +685,24 @@ END_DEBUG crom_next(&cc); } if (maxlun < 0) - printf("%s:%d no LUN found\n", - fw_get_nameunit(target->sbp->fd.dev), + aprint_normal_dev(sc->sc_fd.dev, "%d: no LUN found\n", target->target_id); - maxlun ++; + maxlun++; if (maxlun >= SBP_NUM_LUNS) maxlun = SBP_NUM_LUNS; /* Invalidiate stale devices */ - for (lun = 0; lun < target->num_lun; lun ++) { + for (lun = 0; lun < target->num_lun; lun++) { sdev = target->luns[lun]; if (sdev == NULL) continue; sdev->flags &= ~VALID_LUN; if (lun >= maxlun) { /* lost device */ - SBP_DETACH_SDEV(sdev); + sbp_scsipi_detach_sdev(sdev); sbp_free_sdev(sdev); + target->luns[lun] = NULL; } } @@ -673,9 +711,9 @@ END_DEBUG newluns = (struct sbp_dev **) realloc(target->luns, sizeof(struct sbp_dev *) * maxlun, M_SBP, M_NOWAIT | M_ZERO); - + if (newluns == NULL) { - printf("%s: realloc failed\n", __func__); + aprint_error_dev(sc->sc_fd.dev, "realloc failed\n"); newluns = target->luns; maxlun = target->num_lun; } @@ -684,10 +722,12 @@ END_DEBUG * We must zero the extended region for the case * realloc() doesn't allocate new buffer. */ - if (maxlun > target->num_lun) + if (maxlun > target->num_lun) { + const int sbp_dev_p_sz = sizeof(struct sbp_dev *); + memset(&newluns[target->num_lun], 0, - sizeof(struct sbp_dev *) * - (maxlun - target->num_lun)); + sbp_dev_p_sz * (maxlun - target->num_lun)); + } target->luns = newluns; target->num_lun = maxlun; @@ -702,7 +742,8 @@ END_DEBUG break; lun = reg->val & 0xffff; if (lun >= SBP_NUM_LUNS) { - printf("too large lun %d\n", lun); + aprint_error_dev(sc->sc_fd.dev, "too large lun %d\n", + lun); goto next; } @@ -711,17 +752,31 @@ END_DEBUG sdev = malloc(sizeof(struct sbp_dev), M_SBP, M_NOWAIT | M_ZERO); if (sdev == NULL) { - printf("%s: malloc failed\n", __func__); + aprint_error_dev(sc->sc_fd.dev, + "malloc failed\n"); goto next; } target->luns[lun] = sdev; sdev->lun_id = lun; sdev->target = target; STAILQ_INIT(&sdev->ocbs); - fw_callout_init(&sdev->login_callout); + callout_init(&sdev->login_callout, CALLOUT_MPSAFE); + callout_setfunc(&sdev->login_callout, + sbp_login_callout, sdev); sdev->status = SBP_DEV_RESET; new = 1; - SBP_DEVICE_PREATTACH(); + snprintf(sdev->bustgtlun, 32, "%s:%d:%d", + device_xname(sc->sc_fd.dev), + sdev->target->target_id, + sdev->lun_id); + if (!sc->sc_lwp) + if (kthread_create( + PRI_NONE, KTHREAD_MPSAFE, NULL, + sbp_scsipi_scan_target, &sc->sc_target, + &sc->sc_lwp, + "sbp%d_attach", device_unit(sc->sc_fd.dev))) + aprint_error_dev(sc->sc_fd.dev, + "unable to create thread"); } sdev->flags |= VALID_LUN; sdev->type = (reg->val & 0xff0000) >> 16; @@ -729,45 +784,42 @@ END_DEBUG if (new == 0) goto next; - fwdma_malloc(sbp->fd.fc, - /* alignment */ sizeof(uint32_t), - SBP_DMA_SIZE, &sdev->dma, BUS_DMA_NOWAIT); + fwdma_alloc_setup(sc->sc_fd.dev, sc->sc_dmat, SBP_DMA_SIZE, + &sdev->dma, sizeof(uint32_t), BUS_DMA_NOWAIT); if (sdev->dma.v_addr == NULL) { - printf("%s: dma space allocation failed\n", - __func__); free(sdev, M_SBP); target->luns[lun] = NULL; goto next; } - sdev->login = (struct sbp_login_res *) sdev->dma.v_addr; - sdev->ocb = (struct sbp_ocb *) - ((char *)sdev->dma.v_addr + SBP_LOGIN_SIZE); + sdev->ocb = (struct sbp_ocb *)sdev->dma.v_addr; + sdev->login = (struct sbp_login_res *)&sdev->ocb[SBP_QUEUE_LEN]; memset((char *)sdev->ocb, 0, - sizeof (struct sbp_ocb) * SBP_QUEUE_LEN); + sizeof(struct sbp_ocb) * SBP_QUEUE_LEN); STAILQ_INIT(&sdev->free_ocbs); for (i = 0; i < SBP_QUEUE_LEN; i++) { - struct sbp_ocb *ocb; - ocb = &sdev->ocb[i]; - ocb->bus_addr = sdev->dma.bus_addr - + SBP_LOGIN_SIZE - + sizeof(struct sbp_ocb) * i - + offsetof(struct sbp_ocb, orb[0]); - if (fw_bus_dmamap_create(sbp->dmat, 0, &ocb->dmamap)) { - printf("sbp_attach: cannot create dmamap\n"); + struct sbp_ocb *ocb = &sdev->ocb[i]; + + ocb->index = i; + ocb->bus_addr = + sdev->dma.bus_addr + sizeof(struct sbp_ocb) * i; + if (bus_dmamap_create(sc->sc_dmat, 0x100000, + SBP_IND_MAX, SBP_SEG_MAX, 0, 0, &ocb->dmamap)) { + aprint_error_dev(sc->sc_fd.dev, + "cannot create dmamap %d\n", i); /* XXX */ goto next; } - sbp_free_ocb(sdev, ocb); + sbp_free_ocb(sdev, ocb); /* into free queue */ } next: crom_next(&cc); } - for (lun = 0; lun < target->num_lun; lun ++) { + for (lun = 0; lun < target->num_lun; lun++) { sdev = target->luns[lun]; if (sdev != NULL && (sdev->flags & VALID_LUN) == 0) { - SBP_DETACH_SDEV(sdev); + sbp_scsipi_detach_sdev(sdev); sbp_free_sdev(sdev); target->luns[lun] = NULL; } @@ -775,7 +827,7 @@ next: } static struct sbp_target * -sbp_alloc_target(struct sbp_softc *sbp, struct fw_device *fwdev) +sbp_alloc_target(struct sbp_softc *sc, struct fw_device *fwdev) { struct sbp_target *target; struct crom_context cc; @@ -785,8 +837,8 @@ SBP_DEBUG(1) printf("sbp_alloc_target\n"); END_DEBUG /* new target */ - target = &sbp->target; - target->sbp = sbp; + target = &sc->sc_target; + target->sbp = sc; target->fwdev = fwdev; target->target_id = 0; /* XXX we may want to reload mgm port after each bus reset */ @@ -794,7 +846,7 @@ END_DEBUG crom_init_context(&cc, target->fwdev->csrrom); reg = crom_search_key(&cc, CROM_MGM); if (reg == NULL || reg->val == 0) { - printf("NULL management address\n"); + aprint_error_dev(sc->sc_fd.dev, "NULL management address\n"); target->fwdev = NULL; return NULL; } @@ -807,8 +859,7 @@ END_DEBUG STAILQ_INIT(&target->xferlist); target->n_xfer = 0; STAILQ_INIT(&target->mgm_ocb_queue); - fw_callout_init(&target->mgm_ocb_timeout); - fw_callout_init(&target->scan_callout); + callout_init(&target->mgm_ocb_timeout, CALLOUT_MPSAFE); target->luns = NULL; target->num_lun = 0; @@ -840,8 +891,8 @@ sbp_probe_lun(struct sbp_dev *sdev) /* get firmware revision */ reg = crom_search_key(cc, CSRKEY_FIRM_VER); if (reg != NULL) - snprintf(sdev->revision, sizeof(sdev->revision), - "%06x", reg->val); + snprintf(sdev->revision, sizeof(sdev->revision), "%06x", + reg->val); /* get product string */ crom_search_key(cc, CSRKEY_MODEL); crom_next(cc); @@ -852,119 +903,81 @@ static void sbp_login_callout(void *arg) { struct sbp_dev *sdev = (struct sbp_dev *)arg; + sbp_mgm_orb(sdev, ORB_FUN_LGI, NULL); } static void sbp_login(struct sbp_dev *sdev) { + struct sbp_softc *sc = sdev->target->sbp; struct timeval delta; struct timeval t; int ticks = 0; microtime(&delta); - fw_timevalsub(&delta, &sdev->target->sbp->last_busreset); + timersub(&delta, &sc->sc_last_busreset, &delta); t.tv_sec = login_delay / 1000; t.tv_usec = (login_delay % 1000) * 1000; - fw_timevalsub(&t, &delta); + timersub(&t, &delta, &t); if (t.tv_sec >= 0 && t.tv_usec > 0) ticks = (t.tv_sec * 1000 + t.tv_usec / 1000) * hz / 1000; SBP_DEBUG(0) printf("%s: sec = %lld usec = %ld ticks = %d\n", __func__, (long long)t.tv_sec, (long)t.tv_usec, ticks); END_DEBUG - fw_callout_reset(&sdev->login_callout, ticks, - sbp_login_callout, (void *)(sdev)); + callout_schedule(&sdev->login_callout, ticks); } static void sbp_probe_target(void *arg) { struct sbp_target *target = (struct sbp_target *)arg; - struct sbp_softc *sbp; struct sbp_dev *sdev; - struct firewire_comm *fc; int i; SBP_DEBUG(1) printf("sbp_probe_target %d\n", target->target_id); END_DEBUG - sbp = target->sbp; - fc = target->sbp->fd.fc; sbp_alloc_lun(target); /* XXX untimeout mgm_ocb and dequeue */ - for (i=0; i < target->num_lun; i++) { + for (i = 0; i < target->num_lun; i++) { sdev = target->luns[i]; - if (sdev == NULL) + if (sdev == NULL || sdev->status == SBP_DEV_DEAD) continue; - if (sdev->status != SBP_DEV_DEAD) { - if (SBP_DEVICE(sdev) != NULL) { - SBP_LOCK(sbp); - SBP_DEVICE_FREEZE(sdev, 1); - sdev->freeze ++; - SBP_UNLOCK(sbp); - } - sbp_probe_lun(sdev); -SBP_DEBUG(0) - sbp_show_sdev_info(sdev, - (sdev->status == SBP_DEV_RESET)); -END_DEBUG - sbp_abort_all_ocbs(sdev, XS_SCSI_BUS_RESET); - switch (sdev->status) { - case SBP_DEV_RESET: - /* new or revived target */ - if (auto_login) - sbp_login(sdev); - break; - case SBP_DEV_TOATTACH: - case SBP_DEV_PROBE: - case SBP_DEV_ATTACHED: - case SBP_DEV_RETRY: - default: - sbp_mgm_orb(sdev, ORB_FUN_RCN, NULL); - break; - } - } else { - switch (sdev->status) { - case SBP_DEV_ATTACHED: -SBP_DEBUG(0) - /* the device has gone */ - sbp_show_sdev_info(sdev, 2); - printf("lost target\n"); -END_DEBUG - if (SBP_DEVICE(sdev) != NULL) { - SBP_LOCK(sbp); - SBP_DEVICE_FREEZE(sdev, 1); - sdev->freeze ++; - SBP_UNLOCK(sbp); - } - sdev->status = SBP_DEV_RETRY; - sbp_abort_all_ocbs(sdev, XS_SCSI_BUS_RESET); - break; - case SBP_DEV_PROBE: - case SBP_DEV_TOATTACH: - sdev->status = SBP_DEV_RESET; - break; - case SBP_DEV_RETRY: - case SBP_DEV_RESET: - case SBP_DEV_DEAD: - break; - } + if (sdev->periph != NULL) { + scsipi_periph_freeze(sdev->periph, 1); + sdev->freeze++; + } + sbp_probe_lun(sdev); + sbp_show_sdev_info(sdev); + + sbp_abort_all_ocbs(sdev, XS_RESET); + switch (sdev->status) { + case SBP_DEV_RESET: + /* new or revived target */ + if (auto_login) + sbp_login(sdev); + break; + case SBP_DEV_TOATTACH: + case SBP_DEV_PROBE: + case SBP_DEV_ATTACHED: + case SBP_DEV_RETRY: + default: + sbp_mgm_orb(sdev, ORB_FUN_RCN, NULL); + break; } } } -#define SBP_FWDEV_ALIVE(fwdev) (((fwdev)->status == FWDEVATTACHED) \ - && crom_has_specver((fwdev)->csrrom, CSRVAL_ANSIT10, CSRVAL_T10SBP2)) - static void sbp_post_busreset(void *arg) { - struct sbp_softc *sbp = (struct sbp_softc *)arg; - struct sbp_target *target = &sbp->target; + struct sbp_softc *sc = (struct sbp_softc *)arg; + struct sbp_target *target = &sc->sc_target; struct fw_device *fwdev = target->fwdev; int alive; @@ -974,21 +987,19 @@ SBP_DEBUG(0) if (!alive) printf("not alive\n"); END_DEBUG - microtime(&sbp->last_busreset); + microtime(&sc->sc_last_busreset); if (!alive) return; - SBP_LOCK(sbp); - SBP_BUS_FREEZE(sbp); - SBP_UNLOCK(sbp); + scsipi_channel_freeze(&sc->sc_channel, 1); } static void sbp_post_explore(void *arg) { - struct sbp_softc *sbp = (struct sbp_softc *)arg; - struct sbp_target *target = &sbp->target; + struct sbp_softc *sc = (struct sbp_softc *)arg; + struct sbp_target *target = &sc->sc_target; struct fw_device *fwdev = target->fwdev; int alive; @@ -1001,16 +1012,11 @@ END_DEBUG if (!alive) return; - if (sbp_cold > 0) - sbp_cold --; + if (!firewire_phydma_enable) + return; -#if 0 - /* - * XXX don't let CAM the bus rest. - * CAM tries to do something with freezed (DEV_RETRY) devices. - */ - xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL); -#endif + if (sbp_cold > 0) + sbp_cold--; SBP_DEBUG(0) printf("sbp_post_explore: EUI:%08x%08x ", fwdev->eui.hi, fwdev->eui.lo); @@ -1019,25 +1025,23 @@ END_DEBUG if (target->num_lun == 0) sbp_free_target(target); - SBP_LOCK(sbp); - SBP_BUS_THAW(sbp); - SBP_UNLOCK(sbp); + scsipi_channel_thaw(&sc->sc_channel, 1); } #if NEED_RESPONSE static void -sbp_loginres_callback(struct fw_xfer *xfer){ - int s; - struct sbp_dev *sdev; - sdev = (struct sbp_dev *)xfer->sc; +sbp_loginres_callback(struct fw_xfer *xfer) +{ + struct sbp_dev *sdev = (struct sbp_dev *)xfer->sc; + struct sbp_softc *sc = sdev->target->sbp; + SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); printf("sbp_loginres_callback\n"); END_DEBUG /* recycle */ - s = splfw(); - STAILQ_INSERT_TAIL(&sdev->target->sbp->fwb.xferlist, xfer, link); - splx(s); + mutex_enter(&sc->sc_fwb.fwb_mtx); + STAILQ_INSERT_TAIL(&sc->sc_fwb.xferlist, xfer, link); + mutex_exit(&sc->sc_fwb.fwb_mtx); return; } #endif @@ -1045,16 +1049,13 @@ END_DEBUG static inline void sbp_xfer_free(struct fw_xfer *xfer) { - struct sbp_dev *sdev; - int s; + struct sbp_dev *sdev = (struct sbp_dev *)xfer->sc; + struct sbp_softc *sc = sdev->target->sbp; - sdev = (struct sbp_dev *)xfer->sc; fw_xfer_unload(xfer); - s = splfw(); - SBP_LOCK(sdev->target->sbp); + mutex_enter(&sc->sc_mtx); STAILQ_INSERT_TAIL(&sdev->target->xferlist, xfer, link); - SBP_UNLOCK(sdev->target->sbp); - splx(s); + mutex_exit(&sc->sc_mtx); } static void @@ -1064,10 +1065,9 @@ sbp_reset_start_callback(struct fw_xfer *xfer) struct sbp_target *target = sdev->target; int i; - if (xfer->resp != 0) { - sbp_show_sdev_info(sdev, 2); - printf("sbp_reset_start failed: resp=%d\n", xfer->resp); - } + if (xfer->resp != 0) + aprint_error("%s: sbp_reset_start failed: resp=%d\n", + sdev->bustgtlun, xfer->resp); for (i = 0; i < target->num_lun; i++) { tsdev = target->luns[i]; @@ -1083,17 +1083,20 @@ sbp_reset_start(struct sbp_dev *sdev) struct fw_pkt *fp; SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("sbp_reset_start\n"); + printf("%s: sbp_reset_start: %s\n", + device_xname(sdev->target->sbp->sc_fd.dev), sdev->bustgtlun); END_DEBUG xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); + if (xfer == NULL) + return; xfer->hand = sbp_reset_start_callback; fp = &xfer->send.hdr; fp->mode.wreqq.dest_hi = 0xffff; fp->mode.wreqq.dest_lo = 0xf0000000 | RESET_START; fp->mode.wreqq.data = htonl(0xf); - fw_asyreq(xfer->fc, -1, xfer); + if (fw_asyreq(xfer->fc, -1, xfer) != 0) + sbp_xfer_free(xfer); } static void @@ -1105,132 +1108,36 @@ sbp_mgm_callback(struct fw_xfer *xfer) sdev = (struct sbp_dev *)xfer->sc; SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); - printf("sbp_mgm_callback\n"); + printf("%s: sbp_mgm_callback: %s\n", + device_xname(sdev->target->sbp->sc_fd.dev), sdev->bustgtlun); END_DEBUG resp = xfer->resp; sbp_xfer_free(xfer); -#if 0 - if (resp != 0) { - sbp_show_sdev_info(sdev, 2); - printf("management ORB failed(%d) ... RESET_START\n", resp); - sbp_reset_start(sdev); - } -#endif return; } -#if defined(__FreeBSD__) -static struct sbp_dev * -sbp_next_dev(struct sbp_target *target, int lun) -{ - struct sbp_dev **sdevp; - int i; - - for (i = lun, sdevp = &target->luns[lun]; i < target->num_lun; - i++, sdevp++) - if (*sdevp != NULL && (*sdevp)->status == SBP_DEV_PROBE) - return(*sdevp); - return(NULL); -} - -#define SCAN_PRI 1 -static void -sbp_cam_scan_lun(struct cam_periph *periph, sbp_scsi_xfer *sxfer) -{ - struct sbp_target *target; - struct sbp_dev *sdev; - - sdev = (struct sbp_dev *) sxfer->ccb_h.ccb_sdev_ptr; - target = sdev->target; -SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("sbp_cam_scan_lun\n"); -END_DEBUG - if ((SCSI_XFER_ERROR(sxfer) & CAM_STATUS_MASK) == XS_REQ_CMP) { - sdev->status = SBP_DEV_ATTACHED; - } else { - sbp_show_sdev_info(sdev, 2); - printf("scan failed\n"); - } - sdev = sbp_next_dev(target, sdev->lun_id + 1); - if (sdev == NULL) { - free(sxfer, M_SBP); - return; - } - /* reuse sxfer */ - xpt_setup_ccb(&sxfer->ccb_h, sdev->path, SCAN_PRI); - sxfer->ccb_h.ccb_sdev_ptr = sdev; - xpt_action(sxfer); - xpt_release_devq(sdev->path, sdev->freeze, TRUE); - sdev->freeze = 1; -} - -static void -sbp_cam_scan_target(void *arg) -{ - struct sbp_target *target = (struct sbp_target *)arg; - struct sbp_dev *sdev; - sbp_scsi_xfer *sxfer; - - sdev = sbp_next_dev(target, 0); - if (sdev == NULL) { - printf("sbp_cam_scan_target: nothing to do for target%d\n", - target->target_id); - return; - } -SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("sbp_cam_scan_target\n"); -END_DEBUG - sxfer = malloc(sizeof(sbp_scsi_xfer), M_SBP, M_NOWAIT | M_ZERO); - if (sxfer == NULL) { - printf("sbp_cam_scan_target: malloc failed\n"); - return; - } - xpt_setup_ccb(&sxfer->ccb_h, sdev->path, SCAN_PRI); - sxfer->ccb_h.func_code = XPT_SCAN_LUN; - sxfer->ccb_h.cbfcnp = sbp_cam_scan_lun; - sxfer->ccb_h.flags |= CAM_DEV_QFREEZE; - sxfer->crcn.flags = CAM_FLAG_NONE; - sxfer->ccb_h.ccb_sdev_ptr = sdev; - - /* The scan is in progress now. */ - SBP_LOCK(target->sbp); - xpt_action(sxfer); - xpt_release_devq(sdev->path, sdev->freeze, TRUE); - sdev->freeze = 1; - SBP_UNLOCK(target->sbp); -} - -static inline void -sbp_scan_dev(struct sbp_dev *sdev) -{ - sdev->status = SBP_DEV_PROBE; - fw_callout_reset(&sdev->target->scan_callout, scan_delay * hz / 1000, - sbp_cam_scan_target, (void *)sdev->target); -} -#elif defined(__NetBSD__) static void sbp_scsipi_scan_target(void *arg) { struct sbp_target *target = (struct sbp_target *)arg; - struct sbp_softc *sbp = target->sbp; + struct sbp_softc *sc = target->sbp; struct sbp_dev *sdev; - struct scsipi_channel *chan = &sbp->sc_channel; - struct scsibus_softc *sc_bus = device_private(sbp->sc_bus); + struct scsipi_channel *chan = &sc->sc_channel; + struct scsibus_softc *sc_bus = device_private(sc->sc_bus); int lun, yet; do { - tsleep(target, PWAIT|PCATCH, "-", 0); + mutex_enter(&sc->sc_mtx); + cv_wait_sig(&sc->sc_cv, &sc->sc_mtx); + mutex_exit(&sc->sc_mtx); yet = 0; - for (lun = 0; lun < target->num_lun; lun ++) { + for (lun = 0; lun < target->num_lun; lun++) { sdev = target->luns[lun]; if (sdev == NULL) continue; if (sdev->status != SBP_DEV_PROBE) { - yet ++; + yet++; continue; } @@ -1238,26 +1145,31 @@ sbp_scsipi_scan_target(void *arg) if (chan->chan_nluns < target->num_lun) chan->chan_nluns = target->num_lun; - scsi_probe_bus(sc_bus, - target->target_id, sdev->lun_id); - sdev->periph = scsipi_lookup_periph( - chan, target->target_id, lun); + scsi_probe_bus(sc_bus, target->target_id, + sdev->lun_id); + sdev->periph = scsipi_lookup_periph(chan, + target->target_id, lun); } sdev->status = SBP_DEV_ATTACHED; } } while (yet > 0); - sbp->lwp = NULL; + sc->sc_lwp = NULL; kthread_exit(0); + + /* NOTREACHED */ } static inline void sbp_scan_dev(struct sbp_dev *sdev) { + struct sbp_softc *sc = sdev->target->sbp; + sdev->status = SBP_DEV_PROBE; - wakeup(sdev->target); + mutex_enter(&sc->sc_mtx); + cv_signal(&sdev->target->sbp->sc_cv); + mutex_exit(&sc->sc_mtx); } -#endif static void @@ -1265,35 +1177,18 @@ sbp_do_attach(struct fw_xfer *xfer) { struct sbp_dev *sdev; struct sbp_target *target; - struct sbp_softc *sbp; + struct sbp_softc *sc; sdev = (struct sbp_dev *)xfer->sc; target = sdev->target; - sbp = target->sbp; + sc = target->sbp; SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("sbp_do_attach\n"); + printf("%s:%s:%s\n", device_xname(sc->sc_fd.dev), __func__, + sdev->bustgtlun); END_DEBUG sbp_xfer_free(xfer); -#if defined(__FreeBSD__) - if (sdev->path == NULL) - xpt_create_path(&sdev->path, xpt_periph, - cam_sim_path(target->sbp->sim), - target->target_id, sdev->lun_id); - - /* - * Let CAM scan the bus if we are in the boot process. - * XXX xpt_scan_bus cannot detect LUN larger than 0 - * if LUN 0 doesn't exists. - */ - if (sbp_cold > 0) { - sdev->status = SBP_DEV_ATTACHED; - return; - } -#endif - sbp_scan_dev(sdev); return; } @@ -1301,24 +1196,22 @@ END_DEBUG static void sbp_agent_reset_callback(struct fw_xfer *xfer) { - struct sbp_dev *sdev; + struct sbp_dev *sdev = (struct sbp_dev *)xfer->sc; + struct sbp_softc *sc = sdev->target->sbp; - sdev = (struct sbp_dev *)xfer->sc; SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); - printf("%s\n", __func__); + printf("%s:%s:%s\n", device_xname(sc->sc_fd.dev), __func__, + sdev->bustgtlun); END_DEBUG - if (xfer->resp != 0) { - sbp_show_sdev_info(sdev, 2); - printf("%s: resp=%d\n", __func__, xfer->resp); - } + if (xfer->resp != 0) + aprint_error_dev(sc->sc_fd.dev, "%s:%s: resp=%d\n", __func__, + sdev->bustgtlun, xfer->resp); sbp_xfer_free(xfer); - if (SBP_DEVICE(sdev)) { - SBP_LOCK(sdev->target->sbp); - SBP_DEVICE_THAW(sdev, sdev->freeze); + if (sdev->periph != NULL) { + scsipi_periph_thaw(sdev->periph, sdev->freeze); + scsipi_channel_thaw(&sc->sc_channel, 0); sdev->freeze = 0; - SBP_UNLOCK(sdev->target->sbp); } } @@ -1329,8 +1222,8 @@ sbp_agent_reset(struct sbp_dev *sdev) struct fw_pkt *fp; SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("sbp_agent_reset\n"); + printf("%s:%s:%s\n", device_xname(sdev->target->sbp->sc_fd.dev), + __func__, sdev->bustgtlun); END_DEBUG xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0x04); if (xfer == NULL) @@ -1341,19 +1234,19 @@ END_DEBUG xfer->hand = sbp_do_attach; fp = &xfer->send.hdr; fp->mode.wreqq.data = htonl(0xf); - fw_asyreq(xfer->fc, -1, xfer); - sbp_abort_all_ocbs(sdev, XS_BDR_SENT); + if (fw_asyreq(xfer->fc, -1, xfer) != 0) + sbp_xfer_free(xfer); + sbp_abort_all_ocbs(sdev, XS_RESET); } static void sbp_busy_timeout_callback(struct fw_xfer *xfer) { - struct sbp_dev *sdev; + struct sbp_dev *sdev = (struct sbp_dev *)xfer->sc; - sdev = (struct sbp_dev *)xfer->sc; SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); - printf("sbp_busy_timeout_callback\n"); + printf("%s:%s:%s\n", device_xname(sdev->target->sbp->sc_fd.dev), + __func__, sdev->bustgtlun); END_DEBUG sbp_xfer_free(xfer); sbp_agent_reset(sdev); @@ -1364,34 +1257,36 @@ sbp_busy_timeout(struct sbp_dev *sdev) { struct fw_pkt *fp; struct fw_xfer *xfer; + SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("sbp_busy_timeout\n"); + printf("%s:%s:%s\n", device_xname(sdev->target->sbp->sc_fd.dev), + __func__, sdev->bustgtlun); END_DEBUG xfer = sbp_write_cmd(sdev, FWTCODE_WREQQ, 0); - + if (xfer == NULL) + return; xfer->hand = sbp_busy_timeout_callback; fp = &xfer->send.hdr; fp->mode.wreqq.dest_hi = 0xffff; fp->mode.wreqq.dest_lo = 0xf0000000 | BUSY_TIMEOUT; fp->mode.wreqq.data = htonl((1 << (13+12)) | 0xf); - fw_asyreq(xfer->fc, -1, xfer); + if (fw_asyreq(xfer->fc, -1, xfer) != 0) + sbp_xfer_free(xfer); } static void sbp_orb_pointer_callback(struct fw_xfer *xfer) { - struct sbp_dev *sdev; - sdev = (struct sbp_dev *)xfer->sc; + struct sbp_dev *sdev = (struct sbp_dev *)xfer->sc; + struct sbp_softc *sc = sdev->target->sbp; SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); - printf("%s\n", __func__); + printf("%s:%s:%s\n", device_xname(sc->sc_fd.dev), __func__, + sdev->bustgtlun); END_DEBUG - if (xfer->resp != 0) { - /* XXX */ - printf("%s: xfer->resp = %d\n", __func__, xfer->resp); - } + if (xfer->resp != 0) + aprint_error_dev(sc->sc_fd.dev, "%s:%s: xfer->resp = %d\n", + __func__, sdev->bustgtlun, xfer->resp); sbp_xfer_free(xfer); sdev->flags &= ~ORB_POINTER_ACTIVE; @@ -1409,11 +1304,13 @@ END_DEBUG static void sbp_orb_pointer(struct sbp_dev *sdev, struct sbp_ocb *ocb) { + struct sbp_softc *sc = sdev->target->sbp; struct fw_xfer *xfer; struct fw_pkt *fp; + SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); - printf("%s: 0x%08x\n", __func__, (uint32_t)ocb->bus_addr); + printf("%s:%s:%s: 0x%08x\n", device_xname(sc->sc_fd.dev), __func__, + sdev->bustgtlun, (uint32_t)ocb->bus_addr); END_DEBUG if ((sdev->flags & ORB_POINTER_ACTIVE) != 0) { @@ -1433,30 +1330,30 @@ END_DEBUG fp = &xfer->send.hdr; fp->mode.wreqb.len = 8; fp->mode.wreqb.extcode = 0; - xfer->send.payload[0] = - htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16)); + xfer->send.payload[0] = + htonl(((sc->sc_fd.fc->nodeid | FWLOCALBUS) << 16)); xfer->send.payload[1] = htonl((uint32_t)ocb->bus_addr); - if(fw_asyreq(xfer->fc, -1, xfer) != 0){ - sbp_xfer_free(xfer); - SCSI_XFER_ERROR(ocb->sxfer) = XS_REQ_INVALID; - SCSI_TRANSFER_DONE(ocb->sxfer); + if (fw_asyreq(xfer->fc, -1, xfer) != 0) { + sbp_xfer_free(xfer); + ocb->xs->error = XS_DRIVER_STUFFUP; + scsipi_done(ocb->xs); } } static void sbp_doorbell_callback(struct fw_xfer *xfer) { - struct sbp_dev *sdev; - sdev = (struct sbp_dev *)xfer->sc; + struct sbp_dev *sdev = (struct sbp_dev *)xfer->sc; + struct sbp_softc *sc = sdev->target->sbp; SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); - printf("sbp_doorbell_callback\n"); + printf("%s:%s:%s\n", device_xname(sc->sc_fd.dev), __func__, + sdev->bustgtlun); END_DEBUG if (xfer->resp != 0) { - /* XXX */ - printf("%s: xfer->resp = %d\n", __func__, xfer->resp); + aprint_error_dev(sc->sc_fd.dev, "%s: xfer->resp = %d\n", + __func__, xfer->resp); } sbp_xfer_free(xfer); sdev->flags &= ~ORB_DOORBELL_ACTIVE; @@ -1472,9 +1369,10 @@ sbp_doorbell(struct sbp_dev *sdev) { struct fw_xfer *xfer; struct fw_pkt *fp; + SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); - printf("sbp_doorbell\n"); + printf("%s:%s:%s\n", device_xname(sdev->target->sbp->sc_fd.dev), + __func__, sdev->bustgtlun); END_DEBUG if ((sdev->flags & ORB_DOORBELL_ACTIVE) != 0) { @@ -1488,47 +1386,52 @@ END_DEBUG xfer->hand = sbp_doorbell_callback; fp = &xfer->send.hdr; fp->mode.wreqq.data = htonl(0xf); - fw_asyreq(xfer->fc, -1, xfer); + if (fw_asyreq(xfer->fc, -1, xfer) != 0) + sbp_xfer_free(xfer); } static struct fw_xfer * sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset) { + struct sbp_softc *sc; struct fw_xfer *xfer; struct fw_pkt *fp; struct sbp_target *target; - int s, new = 0; + int new = 0; target = sdev->target; - s = splfw(); + sc = target->sbp; + mutex_enter(&sc->sc_mtx); xfer = STAILQ_FIRST(&target->xferlist); if (xfer == NULL) { if (target->n_xfer > 5 /* XXX */) { - printf("sbp: no more xfer for this target\n"); - splx(s); - return(NULL); + aprint_error_dev(sc->sc_fd.dev, + "no more xfer for this target\n"); + mutex_exit(&sc->sc_mtx); + return NULL; } xfer = fw_xfer_alloc_buf(M_SBP, 8, 0); - if(xfer == NULL){ - printf("sbp: fw_xfer_alloc_buf failed\n"); - splx(s); + if (xfer == NULL) { + aprint_error_dev(sc->sc_fd.dev, + "fw_xfer_alloc_buf failed\n"); + mutex_exit(&sc->sc_mtx); return NULL; } - target->n_xfer ++; - if (debug) + target->n_xfer++; +SBP_DEBUG(0) printf("sbp: alloc %d xfer\n", target->n_xfer); +END_DEBUG new = 1; - } else { + } else STAILQ_REMOVE_HEAD(&target->xferlist, link); - } - splx(s); + mutex_exit(&sc->sc_mtx); microtime(&xfer->tv); if (new) { xfer->recv.pay_len = 0; - xfer->send.spd = min(sdev->target->fwdev->speed, max_speed); - xfer->fc = sdev->target->sbp->fd.fc; + xfer->send.spd = min(target->fwdev->speed, max_speed); + xfer->fc = target->sbp->sc_fd.fc; } if (tcode == FWTCODE_WREQB) @@ -1543,7 +1446,7 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset) fp->mode.wreqq.tlrt = 0; fp->mode.wreqq.tcode = tcode; fp->mode.wreqq.pri = 0; - fp->mode.wreqq.dst = FWLOCALBUS | sdev->target->fwdev->dst; + fp->mode.wreqq.dst = FWLOCALBUS | target->fwdev->dst; return xfer; } @@ -1555,32 +1458,29 @@ sbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb) struct fw_pkt *fp; struct sbp_ocb *ocb; struct sbp_target *target; - int s, nid, dv_unit; + int nid, dv_unit; target = sdev->target; - nid = target->sbp->fd.fc->nodeid | FWLOCALBUS; - dv_unit = fw_get_unit(target->sbp->fd.dev); + nid = target->sbp->sc_fd.fc->nodeid | FWLOCALBUS; + dv_unit = device_unit(target->sbp->sc_fd.dev); - s = splfw(); - SBP_LOCK(target->sbp); + mutex_enter(&target->sbp->sc_mtx); if (func == ORB_FUN_RUNQUEUE) { ocb = STAILQ_FIRST(&target->mgm_ocb_queue); if (target->mgm_ocb_cur != NULL || ocb == NULL) { - SBP_UNLOCK(target->sbp); - splx(s); + mutex_exit(&target->sbp->sc_mtx); return; } STAILQ_REMOVE_HEAD(&target->mgm_ocb_queue, ocb); - SBP_UNLOCK(target->sbp); + mutex_exit(&target->sbp->sc_mtx); goto start; } if ((ocb = sbp_get_ocb(sdev)) == NULL) { - SBP_UNLOCK(target->sbp); - splx(s); + mutex_exit(&target->sbp->sc_mtx); /* XXX */ return; } - SBP_UNLOCK(target->sbp); + mutex_exit(&target->sbp->sc_mtx); ocb->flags = OCB_ACT_MGM; ocb->sdev = sdev; @@ -1589,19 +1489,27 @@ sbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb) ocb->orb[7] = htonl(SBP_DEV2ADDR(dv_unit, sdev->lun_id)); SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("%s\n", orb_fun_name[(func>>16)&0xf]); + printf("%s:%s:%s: %s\n", device_xname(sdev->target->sbp->sc_fd.dev), + __func__, sdev->bustgtlun, orb_fun_name[(func>>16)&0xf]); END_DEBUG switch (func) { case ORB_FUN_LGI: + { + const off_t sbp_login_off = + sizeof(struct sbp_ocb) * SBP_QUEUE_LEN; + ocb->orb[0] = ocb->orb[1] = 0; /* password */ ocb->orb[2] = htonl(nid << 16); - ocb->orb[3] = htonl(sdev->dma.bus_addr); + ocb->orb[3] = htonl(sdev->dma.bus_addr + sbp_login_off); ocb->orb[4] = htonl(ORB_NOTIFY | sdev->lun_id); if (ex_login) ocb->orb[4] |= htonl(ORB_EXV); ocb->orb[5] = htonl(SBP_LOGIN_SIZE); + bus_dmamap_sync(sdev->dma.dma_tag, sdev->dma.dma_map, + sbp_login_off, SBP_LOGIN_SIZE, BUS_DMASYNC_PREREAD); break; + } + case ORB_FUN_ATA: ocb->orb[0] = htonl((0 << 16) | 0); ocb->orb[1] = htonl(aocb->bus_addr & 0xffffffff); @@ -1617,22 +1525,18 @@ END_DEBUG if (target->mgm_ocb_cur != NULL) { /* there is a standing ORB */ - SBP_LOCK(target->sbp); + mutex_enter(&target->sbp->sc_mtx); STAILQ_INSERT_TAIL(&sdev->target->mgm_ocb_queue, ocb, ocb); - SBP_UNLOCK(target->sbp); - splx(s); + mutex_exit(&target->sbp->sc_mtx); return; } start: target->mgm_ocb_cur = ocb; - splx(s); - fw_callout_reset(&target->mgm_ocb_timeout, 5*hz, - sbp_mgm_timeout, (void *)ocb); + callout_reset(&target->mgm_ocb_timeout, 5 * hz, sbp_mgm_timeout, ocb); xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0); - if(xfer == NULL){ + if (xfer == NULL) return; - } xfer->hand = sbp_mgm_callback; fp = &xfer->send.hdr; @@ -1642,35 +1546,33 @@ start: fp->mode.wreqb.extcode = 0; xfer->send.payload[0] = htonl(nid << 16); xfer->send.payload[1] = htonl(ocb->bus_addr & 0xffffffff); -SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("mgm orb: %08x\n", (uint32_t)ocb->bus_addr); -END_DEBUG /* cache writeback & invalidate(required ORB_FUN_LGI func) */ /* when abort_ocb, should sync POST ope ? */ - fwdma_sync(&sdev->dma, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - fw_asyreq(xfer->fc, -1, xfer); + SBP_ORB_DMA_SYNC(sdev->dma, ocb->index, BUS_DMASYNC_PREWRITE); + if (fw_asyreq(xfer->fc, -1, xfer) != 0) + sbp_xfer_free(xfer); } static void sbp_print_scsi_cmd(struct sbp_ocb *ocb) { -#if defined(__FreeBSD__) - struct ccb_scsiio *csio; + struct scsipi_xfer *xs = ocb->xs; - csio = &ocb->sxfer->csio; -#endif - printf("%s:%d:%d XPT_SCSI_IO: " - "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" - ", flags: 0x%02x, " - "%db cmd/%db data/%db sense\n", - fw_get_nameunit(ocb->sdev->target->sbp->fd.dev), - SCSI_XFER_TARGET(ocb->sxfer), SCSI_XFER_LUN(ocb->sxfer), - SCSI_XFER_10BCMD_DUMP(ocb->sxfer), - SCSI_XFER_DIR(ocb->sxfer), - SCSI_XFER_CMDLEN(ocb->sxfer), SCSI_XFER_DATALEN(ocb->sxfer), - SCSI_XFER_SENSELEN(ocb->sxfer)); + printf("%s:%d:%d:" + " cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x," + " flags: 0x%02x, %db cmd/%db data\n", + device_xname(ocb->sdev->target->sbp->sc_fd.dev), + xs->xs_periph->periph_target, + xs->xs_periph->periph_lun, + xs->cmd->opcode, + xs->cmd->bytes[0], xs->cmd->bytes[1], + xs->cmd->bytes[2], xs->cmd->bytes[3], + xs->cmd->bytes[4], xs->cmd->bytes[5], + xs->cmd->bytes[6], xs->cmd->bytes[7], + xs->cmd->bytes[8], + xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT), + xs->cmdlen, xs->datalen); } static void @@ -1678,48 +1580,47 @@ sbp_scsi_status(struct sbp_status *sbp_status, struct sbp_ocb *ocb) { struct sbp_cmd_status *sbp_cmd_status; scsi3_sense_data_t sense = - (scsi3_sense_data_t)SCSI_SENSE_DATA(ocb->sxfer); + (scsi3_sense_data_t)&ocb->xs->sense.scsi_sense; sbp_cmd_status = (struct sbp_cmd_status *)sbp_status->data; SBP_DEBUG(0) sbp_print_scsi_cmd(ocb); /* XXX need decode status */ - sbp_show_sdev_info(ocb->sdev, 2); - printf("SCSI status %x sfmt %x valid %x key %x code %x qlfr %x len %d\n", - sbp_cmd_status->status, - sbp_cmd_status->sfmt, - sbp_cmd_status->valid, - sbp_cmd_status->s_key, - sbp_cmd_status->s_code, - sbp_cmd_status->s_qlfr, - sbp_status->len - ); + printf("%s:" + " SCSI status %x sfmt %x valid %x key %x code %x qlfr %x len %d\n", + ocb->sdev->bustgtlun, + sbp_cmd_status->status, + sbp_cmd_status->sfmt, + sbp_cmd_status->valid, + sbp_cmd_status->s_key, + sbp_cmd_status->s_code, + sbp_cmd_status->s_qlfr, + sbp_status->len); END_DEBUG switch (sbp_cmd_status->status) { - case SCSI_STATUS_CHECK_COND: - case SCSI_STATUS_BUSY: - case SCSI_STATUS_CMD_TERMINATED: - if(sbp_cmd_status->sfmt == SBP_SFMT_CURR){ - sense->response_code = SSD_CURRENT_ERROR; - }else{ - sense->response_code = SSD_DEFERRED_ERROR; - } - if(sbp_cmd_status->valid) + case SCSI_CHECK: + case SCSI_BUSY: + case SCSI_TERMINATED: + if (sbp_cmd_status->sfmt == SBP_SFMT_CURR) + sense->response_code = SSD_RCODE_CURRENT; + else + sense->response_code = SSD_RCODE_DEFERRED; + if (sbp_cmd_status->valid) sense->response_code |= SSD_RESPONSE_CODE_VALID; sense->flags = sbp_cmd_status->s_key; - if(sbp_cmd_status->mark) + if (sbp_cmd_status->mark) sense->flags |= SSD_FILEMARK; - if(sbp_cmd_status->eom) + if (sbp_cmd_status->eom) sense->flags |= SSD_EOM; - if(sbp_cmd_status->ill_len) + if (sbp_cmd_status->ill_len) sense->flags |= SSD_ILI; - memcpy(&sense->information[0], &sbp_cmd_status->info, 4); + memcpy(sense->information, &sbp_cmd_status->info, 4); if (sbp_status->len <= 1) - /* XXX not scsi status. shouldn't be happened */ + /* XXX not scsi status. shouldn't be happened */ sense->asl = 0; else if (sbp_status->len <= 4) /* add_sense_code(_qual), info, cmd_spec_info */ @@ -1728,62 +1629,69 @@ END_DEBUG /* fru, sense_key_spec */ sense->asl = 10; - memcpy(&sense->csi[0], &sbp_cmd_status->cdb, 4); + memcpy(sense->csi, &sbp_cmd_status->cdb, 4); sense->asc = sbp_cmd_status->s_code; sense->ascq = sbp_cmd_status->s_qlfr; sense->fruc = sbp_cmd_status->fru; - memcpy(&sense->sks[0], &sbp_cmd_status->s_keydep[0], 3); - SCSI_XFER_ERROR(ocb->sxfer) = XS_SENSE; - SCSI_XFER_STATUS(ocb->sxfer) = sbp_cmd_status->status; + memcpy(sense->sks, sbp_cmd_status->s_keydep, 3); + ocb->xs->error = XS_SENSE; + ocb->xs->xs_status = sbp_cmd_status->status; /* { uint8_t j, *tmp; tmp = sense; - for( j = 0 ; j < 32 ; j+=8){ - printf("sense %02x%02x %02x%02x %02x%02x %02x%02x\n", - tmp[j], tmp[j+1], tmp[j+2], tmp[j+3], - tmp[j+4], tmp[j+5], tmp[j+6], tmp[j+7]); - } + for (j = 0; j < 32; j += 8) + aprint_normal( + "sense %02x%02x %02x%02x %02x%02x %02x%02x\n", + tmp[j], tmp[j+1], tmp[j+2], tmp[j+3], + tmp[j+4], tmp[j+5], tmp[j+6], tmp[j+7]); } */ break; default: - sbp_show_sdev_info(ocb->sdev, 2); - printf("sbp_scsi_status: unknown scsi status 0x%x\n", - sbp_cmd_status->status); + aprint_error_dev(ocb->sdev->target->sbp->sc_fd.dev, + "%s:%s: unknown scsi status 0x%x\n", + __func__, ocb->sdev->bustgtlun, sbp_cmd_status->status); } } static void sbp_fix_inq_data(struct sbp_ocb *ocb) { - sbp_scsi_xfer *sxfer = ocb->sxfer; + struct scsipi_xfer *xs = ocb->xs; struct sbp_dev *sdev; - scsi3_inquiry_data_t inq = - (scsi3_inquiry_data_t)SCSI_INQUIRY_DATA(sxfer); + scsi3_inquiry_data_t inq = (scsi3_inquiry_data_t)xs->data; + sdev = ocb->sdev; - if (SCSI_XFER_EVPD(sxfer)) +#if 0 +/* + * NetBSD is assuming always 0 for EVPD-bit and 'Page Code'. + */ +#define SI_EVPD 0x01 + if (xs->cmd->bytes[0] & SI_EVPD) return; +#endif SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); - printf("sbp_fix_inq_data\n"); + printf("%s:%s:%s\n", device_xname(sdev->target->sbp->sc_fd.dev), + __func__, sdev->bustgtlun); END_DEBUG switch (inq->device & SID_TYPE) { case T_DIRECT: #if 0 - /* + /* * XXX Convert Direct Access device to RBC. * I've never seen FireWire DA devices which support READ_6. */ if ((inq->device & SID_TYPE) == T_DIRECT) - inq->device |= T_RBC; /* T_DIRECT == 0 */ + inq->device |= T_SIMPLE_DIRECT; /* T_DIRECT == 0 */ #endif - /* fall through */ - case T_RBC: + /* FALLTHROUGH */ + + case T_SIMPLE_DIRECT: /* * Override vendor/product/revision information. * Some devices sometimes return strange strings. @@ -1791,7 +1699,8 @@ END_DEBUG #if 1 memcpy(inq->vendor, sdev->vendor, sizeof(inq->vendor)); memcpy(inq->product, sdev->product, sizeof(inq->product)); - memcpy(inq->revision, sdev->revision+2, sizeof(inq->revision)); + memcpy(inq->revision + 2, sdev->revision, + sizeof(inq->revision)); #endif break; } @@ -1807,13 +1716,13 @@ END_DEBUG } static void -sbp_recv1(struct fw_xfer *xfer) +sbp_recv(struct fw_xfer *xfer) { struct fw_pkt *rfp; #if NEED_RESPONSE struct fw_pkt *sfp; #endif - struct sbp_softc *sbp; + struct sbp_softc *sc; struct sbp_dev *sdev; struct sbp_ocb *ocb; struct sbp_login_res *login_res = NULL; @@ -1829,18 +1738,22 @@ printf("sbp %x %d %d %08x %08x %08x %08x\n", printf("sbp %08x %08x %08x %08x\n", ntohl(ld[4]), ntohl(ld[5]), ntohl(ld[6]), ntohl(ld[7])); printf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), ntohl(ld[11])); */ - sbp = (struct sbp_softc *)xfer->sc; - if (xfer->resp != 0){ - printf("sbp_recv: xfer->resp = %d\n", xfer->resp); + + sc = (struct sbp_softc *)xfer->sc; + if (xfer->resp != 0) { + aprint_error_dev(sc->sc_fd.dev, + "sbp_recv: xfer->resp = %d\n", xfer->resp); goto done0; } - if (xfer->recv.payload == NULL){ - printf("sbp_recv: xfer->recv.payload == NULL\n"); + if (xfer->recv.payload == NULL) { + aprint_error_dev(sc->sc_fd.dev, + "sbp_recv: xfer->recv.payload == NULL\n"); goto done0; } rfp = &xfer->recv.hdr; - if(rfp->mode.wreqb.tcode != FWTCODE_WREQB){ - printf("sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode); + if (rfp->mode.wreqb.tcode != FWTCODE_WREQB) { + aprint_error_dev(sc->sc_fd.dev, + "sbp_recv: tcode = %d\n", rfp->mode.wreqb.tcode); goto done0; } sbp_status = (struct sbp_status *)xfer->recv.payload; @@ -1848,51 +1761,44 @@ printf("sbp %08x %08x %08x %08x\n", ntohl(ld[8]), ntohl(ld[9]), ntohl(ld[10]), n SBP_DEBUG(2) printf("received address 0x%x\n", addr); END_DEBUG - target = &sbp->target; + target = &sc->sc_target; l = SBP_ADDR2LUN(addr); if (l >= target->num_lun || target->luns[l] == NULL) { - fw_printf(sbp->fd.dev, + aprint_error_dev(sc->sc_fd.dev, "sbp_recv1: invalid lun %d (target=%d)\n", l, target->target_id); goto done0; } sdev = target->luns[l]; - fwdma_sync(&sdev->dma, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - ocb = NULL; switch (sbp_status->src) { case SRC_NEXT_EXISTS: case SRC_NO_NEXT: /* check mgm_ocb_cur first */ - ocb = target->mgm_ocb_cur; - if (ocb != NULL) { + ocb = target->mgm_ocb_cur; + if (ocb != NULL) if (OCB_MATCH(ocb, sbp_status)) { - fw_callout_stop(&target->mgm_ocb_timeout); + callout_stop(&target->mgm_ocb_timeout); target->mgm_ocb_cur = NULL; break; } - } ocb = sbp_dequeue_ocb(sdev, sbp_status); - if (ocb == NULL) { - sbp_show_sdev_info(sdev, 2); -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - printf("No ocb(%lx) on the queue\n", -#else - printf("No ocb(%x) on the queue\n", -#endif - ntohl(sbp_status->orb_lo)); - } + if (ocb == NULL) + aprint_error_dev(sc->sc_fd.dev, + "%s:%s: No ocb(%x) on the queue\n", __func__, + sdev->bustgtlun, ntohl(sbp_status->orb_lo)); break; case SRC_UNSOL: /* unsolicit */ - sbp_show_sdev_info(sdev, 2); - printf("unsolicit status received\n"); + aprint_error_dev(sc->sc_fd.dev, + "%s:%s: unsolicit status received\n", + __func__, sdev->bustgtlun); break; default: - sbp_show_sdev_info(sdev, 2); - printf("unknown sbp_status->src\n"); + aprint_error_dev(sc->sc_fd.dev, + "%s:%s: unknown sbp_status->src\n", + __func__, sdev->bustgtlun); } status_valid0 = (sbp_status->src < 2 @@ -1900,22 +1806,17 @@ END_DEBUG && sbp_status->dead == 0); status_valid = (status_valid0 && sbp_status->status == 0); - if (!status_valid0 || debug > 2){ + if (!status_valid0 || debug > 2) { int status; SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("ORB status src:%x resp:%x dead:%x" -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - " len:%x stat:%x orb:%x%08lx\n", -#else - " len:%x stat:%x orb:%x%08x\n", -#endif - sbp_status->src, sbp_status->resp, sbp_status->dead, - sbp_status->len, sbp_status->status, - ntohs(sbp_status->orb_hi), ntohl(sbp_status->orb_lo)); + printf("%s:%s:%s: ORB status src:%x resp:%x dead:%x" + " len:%x stat:%x orb:%x%08x\n", + device_xname(sc->sc_fd.dev), __func__, sdev->bustgtlun, + sbp_status->src, sbp_status->resp, sbp_status->dead, + sbp_status->len, sbp_status->status, + ntohs(sbp_status->orb_hi), ntohl(sbp_status->orb_lo)); END_DEBUG - sbp_show_sdev_info(sdev, 2); + printf("%s:%s\n", device_xname(sc->sc_fd.dev), sdev->bustgtlun); status = sbp_status->status; switch(sbp_status->resp) { case SBP_REQ_CMP: @@ -1926,8 +1827,8 @@ END_DEBUG break; case SBP_TRANS_FAIL: printf("Obj: %s, Error: %s\n", - orb_status1_object[(status>>6) & 3], - orb_status1_serial_bus_error[status & 0xf]); + orb_status1_object[(status>>6) & 3], + orb_status1_serial_bus_error[status & 0xf]); break; case SBP_ILLE_REQ: printf("Illegal request\n"); @@ -1942,11 +1843,9 @@ END_DEBUG /* we have to reset the fetch agent if it's dead */ if (sbp_status->dead) { - if (SBP_DEVICE(sdev) != NULL) { - SBP_LOCK(sbp); - SBP_DEVICE_FREEZE(sdev, 1); - sdev->freeze ++; - SBP_UNLOCK(sbp); + if (sdev->periph != NULL) { + scsipi_periph_freeze(sdev->periph, 1); + sdev->freeze++; } reset_agent = 1; } @@ -1954,7 +1853,7 @@ END_DEBUG if (ocb == NULL) goto done; - switch(ntohl(ocb->orb[4]) & ORB_FMT_MSK){ + switch(ntohl(ocb->orb[4]) & ORB_FMT_MSK) { case ORB_FMT_NOP: break; case ORB_FMT_VED: @@ -1966,6 +1865,14 @@ END_DEBUG reset_agent = 0; switch(orb_fun) { case ORB_FUN_LGI: + { + const struct fwdma_alloc *dma = &sdev->dma; + const off_t sbp_login_off = + sizeof(struct sbp_ocb) * SBP_QUEUE_LEN; + + bus_dmamap_sync(dma->dma_tag, dma->dma_map, + sbp_login_off, SBP_LOGIN_SIZE, + BUS_DMASYNC_POSTREAD); login_res = sdev->login; login_res->len = ntohs(login_res->len); login_res->id = ntohs(login_res->id); @@ -1973,40 +1880,45 @@ END_DEBUG login_res->cmd_lo = ntohl(login_res->cmd_lo); if (status_valid) { SBP_DEBUG(0) -sbp_show_sdev_info(sdev, 2); -printf("login: len %d, ID %d, cmd %08x%08x, recon_hold %d\n", login_res->len, login_res->id, login_res->cmd_hi, login_res->cmd_lo, ntohs(login_res->recon_hold)); + printf("%s:%s:%s: login:" + " len %d, ID %d, cmd %08x%08x," + " recon_hold %d\n", + device_xname(sc->sc_fd.dev), + __func__, sdev->bustgtlun, + login_res->len, login_res->id, + login_res->cmd_hi, + login_res->cmd_lo, + ntohs(login_res->recon_hold)); END_DEBUG sbp_busy_timeout(sdev); } else { /* forgot logout? */ - sbp_show_sdev_info(sdev, 2); - printf("login failed\n"); + aprint_error_dev(sc->sc_fd.dev, + "%s:%s: login failed\n", + __func__, sdev->bustgtlun); sdev->status = SBP_DEV_RESET; } break; + } case ORB_FUN_RCN: login_res = sdev->login; if (status_valid) { SBP_DEBUG(0) -sbp_show_sdev_info(sdev, 2); -printf("reconnect: len %d, ID %d, cmd %08x%08x\n", login_res->len, login_res->id, login_res->cmd_hi, login_res->cmd_lo); + printf("%s:%s:%s: reconnect:" + " len %d, ID %d, cmd %08x%08x\n", + device_xname(sc->sc_fd.dev), + __func__, sdev->bustgtlun, + login_res->len, login_res->id, + login_res->cmd_hi, + login_res->cmd_lo); END_DEBUG -#if 1 -#if defined(__FreeBSD__) - if (sdev->status == SBP_DEV_ATTACHED) - sbp_scan_dev(sdev); - else -#endif - sbp_agent_reset(sdev); -#else - sdev->status = SBP_DEV_ATTACHED; - sbp_mgm_orb(sdev, ORB_FUN_ATS, NULL); -#endif + sbp_agent_reset(sdev); } else { /* reconnection hold time exceed? */ SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); - printf("reconnect failed\n"); + aprint_error_dev(sc->sc_fd.dev, + "%s:%s: reconnect failed\n", + __func__, sdev->bustgtlun); END_DEBUG sbp_login(sdev); } @@ -2023,44 +1935,31 @@ END_DEBUG sbp_agent_reset(sdev); break; default: - sbp_show_sdev_info(sdev, 2); - printf("unknown function %d\n", orb_fun); + aprint_error_dev(sc->sc_fd.dev, + "%s:%s: unknown function %d\n", + __func__, sdev->bustgtlun, orb_fun); break; } sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); break; case OCB_ACT_CMD: sdev->timeout = 0; - if(ocb->sxfer != NULL){ - sbp_scsi_xfer *sxfer = ocb->sxfer; -/* - uint32_t *ld = SCSI_XFER_DATA(ocb->sxfer); - if(ld != NULL && - SCSI_XFER_DATALEN(ocb->sxfer) != 0) - printf("ptr %08x %08x %08x %08x\n", ld[0], ld[1], ld[2], ld[3]); - else - printf("ptr NULL\n"); -printf("len %d\n", sbp_status->len); -*/ - if(sbp_status->len > 1){ + if (ocb->xs != NULL) { + struct scsipi_xfer *xs = ocb->xs; + + if (sbp_status->len > 1) sbp_scsi_status(sbp_status, ocb); - }else{ - if(sbp_status->resp != SBP_REQ_CMP){ - SCSI_XFER_ERROR(sxfer) = - XS_REQ_CMP_ERR; - }else{ - SCSI_XFER_ERROR(sxfer) = - XS_REQ_CMP; - SCSI_XFER_REQUEST_COMPLETE( - sxfer); + else + if (sbp_status->resp != SBP_REQ_CMP) + xs->error = XS_DRIVER_STUFFUP; + else { + xs->error = XS_NOERROR; + xs->resid = 0; } - } /* fix up inq data */ - if (SCSI_XFER_OPECODE(sxfer) == INQUIRY) + if (xs->cmd->opcode == INQUIRY) sbp_fix_inq_data(ocb); - SBP_LOCK(sbp); - SCSI_TRANSFER_DONE(sxfer); - SBP_UNLOCK(sbp); + scsipi_done(xs); } break; default: @@ -2080,7 +1979,7 @@ done0: * the buffer. In that case, the controller return ack_complete and * no respose is necessary. * - * XXX fwohci.c and firewire.c should inform event_code such as + * XXX fwohci.c and firewire.c should inform event_code such as * ack_complete or ack_pending to upper driver. */ #if NEED_RESPONSE @@ -2096,115 +1995,23 @@ done0: sfp->mode.wres.rtcode = 0; sfp->mode.wres.pri = 0; - fw_asyreq(xfer->fc, -1, xfer); + if (fw_asyreq(xfer->fc, -1, xfer) != 0) { + aprint_error_dev(sc->sc_fd.dev, "mgm_orb failed\n"); + mutex_enter(&sc->sc_fwb.fwb_mtx); + STAILQ_INSERT_TAIL(&sc->sc_fwb.xferlist, xfer, link); + mutex_exit(&sc->sc_fwb.fwb_mtx); + } #else /* recycle */ - STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link); + mutex_enter(&sc->sc_fwb.fwb_mtx); + STAILQ_INSERT_TAIL(&sc->sc_fwb.xferlist, xfer, link); + mutex_exit(&sc->sc_fwb.fwb_mtx); #endif return; } -static void -sbp_recv(struct fw_xfer *xfer) -{ - int s; - - s = splfwsbp(); - sbp_recv1(xfer); - splx(s); -} -/* - * sbp_attach() - */ -FW_ATTACH(sbp) -{ - FW_ATTACH_START(sbp, sbp, fwa); - int dv_unit, error, s; - struct firewire_comm *fc; - SBP_ATTACH_START; - - if (DFLTPHYS > SBP_MAXPHYS) - fw_printf(sbp->fd.dev, - "Warning, DFLTPHYS(%dKB) is larger than " - "SBP_MAXPHYS(%dKB).\n", DFLTPHYS / 1024, - SBP_MAXPHYS / 1024); -SBP_DEBUG(0) - printf("sbp_attach (cold=%d)\n", cold); -END_DEBUG - - if (cold) - sbp_cold ++; - sbp->fd.fc = fc = fwa->fc; - fw_mtx_init(&sbp->mtx, "sbp", NULL, MTX_DEF); - - if (max_speed < 0) - max_speed = fc->speed; - - error = fw_bus_dma_tag_create(/*parent*/fc->dmat, - /* XXX shoud be 4 for sane backend? */ - /*alignment*/1, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/0x100000, /*nsegments*/SBP_IND_MAX, - /*maxsegsz*/SBP_SEG_MAX, - /*flags*/BUS_DMA_ALLOCNOW, - /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&sbp->mtx, - &sbp->dmat); - if (error != 0) { - printf("sbp_attach: Could not allocate DMA tag " - "- error %d\n", error); - FW_ATTACH_RETURN(ENOMEM); - } - -#if defined(__FreeBSD__) - devq = cam_simq_alloc(/*maxopenings*/SBP_NUM_OCB); - if (devq == NULL) - return (ENXIO); -#endif - - sbp->target.fwdev = NULL; - sbp->target.luns = NULL; - - if (sbp_alloc_target(sbp, fwa->fwdev) == NULL) - FW_ATTACH_RETURN(ENXIO); - - SBP_SCSIBUS_ATTACH; - - /* We reserve 16 bit space (4 bytes X 64 unit X 256 luns) */ - dv_unit = fw_get_unit(sbp->fd.dev); - sbp->fwb.start = SBP_DEV2ADDR(dv_unit, 0); - sbp->fwb.end = SBP_DEV2ADDR(dv_unit, -1); - /* pre-allocate xfer */ - STAILQ_INIT(&sbp->fwb.xferlist); - fw_xferlist_add(&sbp->fwb.xferlist, M_SBP, - /*send*/ 0, /*recv*/ SBP_RECV_LEN, SBP_NUM_OCB/2, - fc, (void *)sbp, sbp_recv); - fw_bindadd(fc, &sbp->fwb); - - sbp->fd.post_busreset = sbp_post_busreset; - sbp->fd.post_explore = sbp_post_explore; - - if (fc->status != FWBUSNOTREADY) { - s = splfw(); - sbp_post_busreset((void *)sbp); - sbp_post_explore((void *)sbp); - splx(s); - } - - FW_ATTACH_RETURN(0); -#if defined(__FreeBSD__) -fail: - SBP_UNLOCK(sbp); - cam_sim_free(sbp->sim, /*free_devq*/TRUE); - return (ENXIO); -#endif -} - static int sbp_logout_all(struct sbp_softc *sbp) { @@ -2215,62 +2022,50 @@ sbp_logout_all(struct sbp_softc *sbp) SBP_DEBUG(0) printf("sbp_logout_all\n"); END_DEBUG - target = &sbp->target; + target = &sbp->sc_target; if (target->luns != NULL) for (i = 0; i < target->num_lun; i++) { sdev = target->luns[i]; if (sdev == NULL) continue; - fw_callout_stop(&sdev->login_callout); + callout_stop(&sdev->login_callout); if (sdev->status >= SBP_DEV_TOATTACH && - sdev->status <= SBP_DEV_ATTACHED) + sdev->status <= SBP_DEV_ATTACHED) sbp_mgm_orb(sdev, ORB_FUN_LGO, NULL); } return 0; } -#if defined(__FreeBSD__) -static int -sbp_shutdown(device_t dev) -{ - struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev)); - - sbp_logout_all(sbp); - return (0); -} -#endif - static void sbp_free_sdev(struct sbp_dev *sdev) { + struct sbp_softc *sc = sdev->target->sbp; int i; if (sdev == NULL) return; for (i = 0; i < SBP_QUEUE_LEN; i++) - fw_bus_dmamap_destroy(sdev->target->sbp->dmat, - sdev->ocb[i].dmamap); - fwdma_free(sdev->target->sbp->fd.fc, &sdev->dma); + bus_dmamap_destroy(sc->sc_dmat, sdev->ocb[i].dmamap); + fwdma_free(sdev->dma.dma_tag, sdev->dma.dma_map, sdev->dma.v_addr); free(sdev, M_SBP); + sdev = NULL; } static void sbp_free_target(struct sbp_target *target) { - struct sbp_softc *sbp; struct fw_xfer *xfer, *next; int i; if (target->luns == NULL) return; - fw_callout_stop(&target->mgm_ocb_timeout); - sbp = target->sbp; + callout_stop(&target->mgm_ocb_timeout); for (i = 0; i < target->num_lun; i++) sbp_free_sdev(target->luns[i]); for (xfer = STAILQ_FIRST(&target->xferlist); - xfer != NULL; xfer = next) { + xfer != NULL; xfer = next) { next = STAILQ_NEXT(xfer, link); fw_xfer_free_buf(xfer); } @@ -2281,80 +2076,6 @@ sbp_free_target(struct sbp_target *target) target->fwdev = NULL; } -FW_DETACH(sbp) -{ - FW_DETACH_START(sbp, sbp); - struct firewire_comm *fc = sbp->fd.fc; - int i; - -SBP_DEBUG(0) - printf("sbp_detach\n"); -END_DEBUG - - SBP_DETACH_TARGET(&sbp->target); -#if defined(__FreeBSD__) - SBP_LOCK(sbp); - xpt_async(AC_LOST_DEVICE, sbp->path, NULL); - xpt_free_path(sbp->path); - xpt_bus_deregister(cam_sim_path(sbp->sim)); - cam_sim_free(sbp->sim, /*free_devq*/ TRUE), - SBP_UNLOCK(sbp); -#endif - - sbp_logout_all(sbp); - - /* XXX wait for logout completion */ - tsleep(&i, FWPRI, "sbpdtc", hz/2); - - sbp_free_target(&sbp->target); - - fw_bindremove(fc, &sbp->fwb); - fw_xferlist_remove(&sbp->fwb.xferlist); - - fw_bus_dma_tag_destroy(sbp->dmat); - fw_mtx_destroy(&sbp->mtx); - - return (0); -} - -#if defined(__FreeBSD__) -static void -sbp_cam_detach_sdev(struct sbp_dev *sdev) -{ - if (sdev == NULL) - return; - if (sdev->status == SBP_DEV_DEAD) - return; - if (sdev->status == SBP_DEV_RESET) - return; - sbp_abort_all_ocbs(sdev, CAM_DEV_NOT_THERE); - if (sdev->path) { - SBP_LOCK(sdev->target->sbp); - xpt_release_devq(sdev->path, - sdev->freeze, TRUE); - sdev->freeze = 0; - xpt_async(AC_LOST_DEVICE, sdev->path, NULL); - xpt_free_path(sdev->path); - sdev->path = NULL; - SBP_UNLOCK(sdev->target->sbp); - } -} - -static void -sbp_cam_detach_target(struct sbp_target *target) -{ - int i; - - if (target->luns != NULL) { -SBP_DEBUG(0) - printf("sbp_detach_target %d\n", target->target_id); -END_DEBUG - fw_callout_stop(&target->scan_callout); - for (i = 0; i < target->num_lun; i++) - sbp_cam_detach_sdev(target->luns[i]); - } -} -#elif defined(__NetBSD__) static void sbp_scsipi_detach_sdev(struct sbp_dev *sdev) { @@ -2374,18 +2095,17 @@ sbp_scsipi_detach_sdev(struct sbp_dev *sdev) return; if (sdev->status == SBP_DEV_RESET) return; - if (sdev->periph) { + if (sdev->periph != NULL) { scsipi_periph_thaw(sdev->periph, sdev->freeze); scsipi_channel_thaw(&sbp->sc_channel, 0); /* XXXX */ sdev->freeze = 0; if (scsipi_target_detach(&sbp->sc_channel, target->target_id, sdev->lun_id, DETACH_FORCE) != 0) { - sbp_show_sdev_info(sdev, 2); - printf("detach failed\n"); + aprint_error_dev(sbp->sc_fd.dev, "detach failed\n"); } sdev->periph = NULL; } - sbp_abort_all_ocbs(sdev, XS_DEV_NOT_THERE); + sbp_abort_all_ocbs(sdev, XS_DRIVER_STUFFUP); } static void @@ -2398,24 +2118,24 @@ sbp_scsipi_detach_target(struct sbp_target *target) SBP_DEBUG(0) printf("sbp_detach_target %d\n", target->target_id); END_DEBUG - fw_callout_stop(&target->scan_callout); for (i = 0; i < target->num_lun; i++) sbp_scsipi_detach_sdev(target->luns[i]); if (config_detach(sbp->sc_bus, DETACH_FORCE) != 0) - fw_printf(sbp->fd.dev, "%d detach failed\n", - target->target_id); + aprint_error_dev(sbp->sc_fd.dev, "%d detach failed\n", + target->target_id); sbp->sc_bus = NULL; } } -#endif static void sbp_target_reset(struct sbp_dev *sdev, int method) { - int i; + struct sbp_softc *sc; struct sbp_target *target = sdev->target; struct sbp_dev *tsdev; + int i; + sc = target->sbp; for (i = 0; i < target->num_lun; i++) { tsdev = target->luns[i]; if (tsdev == NULL) @@ -2424,25 +2144,24 @@ sbp_target_reset(struct sbp_dev *sdev, int method) continue; if (tsdev->status == SBP_DEV_RESET) continue; - SBP_LOCK(target->sbp); - SBP_DEVICE_FREEZE(tsdev, 1); - tsdev->freeze ++; - SBP_UNLOCK(target->sbp); - sbp_abort_all_ocbs(tsdev, XS_CMD_TIMEOUT); + if (sdev->periph != NULL) { + scsipi_periph_freeze(tsdev->periph, 1); + tsdev->freeze++; + } + sbp_abort_all_ocbs(tsdev, XS_TIMEOUT); if (method == 2) tsdev->status = SBP_DEV_LOGIN; } switch(method) { case 1: - printf("target reset\n"); + aprint_error("target reset\n"); sbp_mgm_orb(sdev, ORB_FUN_RST, NULL); break; case 2: - printf("reset start\n"); + aprint_error("reset start\n"); sbp_reset_start(sdev); break; } - } static void @@ -2452,20 +2171,19 @@ sbp_mgm_timeout(void *arg) struct sbp_dev *sdev = ocb->sdev; struct sbp_target *target = sdev->target; - sbp_show_sdev_info(sdev, 2); - printf("request timeout(mgm orb:0x%08x) ... ", - (uint32_t)ocb->bus_addr); + aprint_error_dev(sdev->target->sbp->sc_fd.dev, + "%s:%s: request timeout(mgm orb:0x%08x) ... ", + __func__, sdev->bustgtlun, (uint32_t)ocb->bus_addr); target->mgm_ocb_cur = NULL; sbp_free_ocb(sdev, ocb); #if 0 /* XXX */ - printf("run next request\n"); + aprint_error("run next request\n"); sbp_mgm_orb(sdev, ORB_FUN_RUNQUEUE, NULL); #endif -#if 1 - printf("reset start\n"); + aprint_error_dev(sdev->target->sbp->sc_fd.dev, + "%s:%s: reset start\n", __func__, sdev->bustgtlun); sbp_reset_start(sdev); -#endif } static void @@ -2474,29 +2192,30 @@ sbp_timeout(void *arg) struct sbp_ocb *ocb = (struct sbp_ocb *)arg; struct sbp_dev *sdev = ocb->sdev; - sbp_show_sdev_info(sdev, 2); - printf("request timeout(cmd orb:0x%08x) ... ", - (uint32_t)ocb->bus_addr); + aprint_error_dev(sdev->target->sbp->sc_fd.dev, + "%s:%s: request timeout(cmd orb:0x%08x) ... ", + __func__, sdev->bustgtlun, (uint32_t)ocb->bus_addr); - sdev->timeout ++; + sdev->timeout++; switch(sdev->timeout) { case 1: - printf("agent reset\n"); - SBP_LOCK(sdev->target->sbp); - SBP_DEVICE_FREEZE(sdev, 1); - sdev->freeze ++; - SBP_UNLOCK(sdev->target->sbp); - sbp_abort_all_ocbs(sdev, XS_CMD_TIMEOUT); + aprint_error("agent reset\n"); + if (sdev->periph != NULL) { + scsipi_periph_freeze(sdev->periph, 1); + sdev->freeze++; + } + sbp_abort_all_ocbs(sdev, XS_TIMEOUT); sbp_agent_reset(sdev); break; case 2: case 3: sbp_target_reset(sdev, sdev->timeout - 1); break; -#if 0 default: + aprint_error("\n"); +#if 0 /* XXX give up */ - SBP_DETACH_TARGET(target); + sbp_scsipi_detach_target(target); if (target->luns != NULL) free(target->luns, M_SBP); target->num_lun = 0; @@ -2507,360 +2226,128 @@ sbp_timeout(void *arg) } static void -sbp_action1(struct sbp_softc *sbp, sbp_scsi_xfer *sxfer) +sbp_action1(struct sbp_softc *sc, struct scsipi_xfer *xs) { - - struct sbp_target *target = NULL; + struct sbp_target *target = &sc->sc_target; struct sbp_dev *sdev = NULL; + struct sbp_ocb *ocb; + int speed, flag, error; + void *cdb; /* target:lun -> sdev mapping */ - if (sbp != NULL) { - target = &sbp->target; - if (target->fwdev != NULL - && NOT_LUN_WILDCARD(SCSI_XFER_LUN(sxfer)) - && SCSI_XFER_LUN(sxfer) < target->num_lun) { - sdev = target->luns[SCSI_XFER_LUN(sxfer)]; - if (sdev != NULL && sdev->status != SBP_DEV_ATTACHED && - sdev->status != SBP_DEV_PROBE) - sdev = NULL; - } + if (target->fwdev != NULL && + xs->xs_periph->periph_lun < target->num_lun) { + sdev = target->luns[xs->xs_periph->periph_lun]; + if (sdev != NULL && sdev->status != SBP_DEV_ATTACHED && + sdev->status != SBP_DEV_PROBE) + sdev = NULL; } + if (sdev == NULL) { SBP_DEBUG(1) - if (sdev == NULL) - printf("invalid target %d lun %d\n", - SCSI_XFER_TARGET(sxfer), SCSI_XFER_LUN(sxfer)); -END_DEBUG - - switch (SCSI_XFER_FUNCCODE(sxfer)) { - case XPT_SCSI_IO: -#if defined(__FreeBSD__) - case XPT_RESET_DEV: - case XPT_GET_TRAN_SETTINGS: - case XPT_SET_TRAN_SETTINGS: - case XPT_CALC_GEOMETRY: -#endif - if (sdev == NULL) { -SBP_DEBUG(1) - printf("%s:%d:%d:func_code 0x%04x: " - "Invalid target (target needed)\n", - sbp ? fw_get_nameunit(sbp->fd.dev) : "???", - SCSI_XFER_TARGET(sxfer), SCSI_XFER_LUN(sxfer), - SCSI_XFER_FUNCCODE(sxfer)); + printf("%s:%d:%d: Invalid target (target needed)\n", + sc ? device_xname(sc->sc_fd.dev) : "???", + xs->xs_periph->periph_target, + xs->xs_periph->periph_lun); END_DEBUG - SCSI_XFER_ERROR(sxfer) = XS_DEV_NOT_THERE; - SCSI_TRANSFER_DONE(sxfer); - return; - } - break; -#if defined(__FreeBSD__) - case XPT_PATH_INQ: - case XPT_NOOP: - /* The opcodes sometimes aimed at a target (sc is valid), - * sometimes aimed at the SIM (sc is invalid and target is - * CAM_TARGET_WILDCARD) - */ - if (sbp == NULL && - sxfer->ccb_h.target_id != CAM_TARGET_WILDCARD) { -SBP_DEBUG(0) - printf("%s:%d:%d func_code 0x%04x: " - "Invalid target (no wildcard)\n", - fw_get_nameunit(sbp->fd.dev), - sxfer->ccb_h.target_id, sxfer->ccb_h.target_lun, - sxfer->ccb_h.func_code); -END_DEBUG - SCSI_XFER_ERROR(sxfer) = XS_DEV_NOT_THERE; - SCSI_TRANSFER_DONE(sxfer); - return; - } - break; -#endif - default: - /* XXX Hm, we should check the input parameters */ - break; + xs->error = XS_DRIVER_STUFFUP; + scsipi_done(xs); + return; } - switch (SCSI_XFER_FUNCCODE(sxfer)) { - case XPT_SCSI_IO: - { - struct sbp_ocb *ocb; - int speed; - void *cdb; - fw_mtx_assert(sim->mtx, MA_OWNED); - SBP_DEBUG(2) - printf("%s:%d:%d XPT_SCSI_IO: " - "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" - ", flags: 0x%02x, " - "%db cmd/%db data/%db sense\n", - fw_get_nameunit(sbp->fd.dev), - SCSI_XFER_TARGET(sxfer), SCSI_XFER_LUN(sxfer), - SCSI_XFER_10BCMD_DUMP(sxfer), - SCSI_XFER_DIR(sxfer), - SCSI_XFER_CMDLEN(sxfer), SCSI_XFER_DATALEN(sxfer), - SCSI_XFER_SENSELEN(sxfer)); + printf("%s:%d:%d:" + " cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x," + " flags: 0x%02x, %db cmd/%db data\n", + device_xname(sc->sc_fd.dev), + xs->xs_periph->periph_target, + xs->xs_periph->periph_lun, + xs->cmd->opcode, + xs->cmd->bytes[0], xs->cmd->bytes[1], + xs->cmd->bytes[2], xs->cmd->bytes[3], + xs->cmd->bytes[4], xs->cmd->bytes[5], + xs->cmd->bytes[6], xs->cmd->bytes[7], + xs->cmd->bytes[8], + xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT), + xs->cmdlen, xs->datalen); END_DEBUG - if(sdev == NULL){ - SCSI_XFER_ERROR(sxfer) = XS_DEV_NOT_THERE; - SCSI_TRANSFER_DONE(sxfer); - return; - } -#if 0 - /* if we are in probe stage, pass only probe commands */ - if (sdev->status == SBP_DEV_PROBE) { - char *name; - name = xpt_path_periph(sxfer->ccb_h.path)->periph_name; - printf("probe stage, periph name: %s\n", name); - if (strcmp(name, "probe") != 0) { - SCSI_XFER_ERROR(sxfer) = XS_REQUEUE_REQ; - SCSI_TRANSFER_DONE(sxfer); - return; - } - } -#endif - if ((ocb = sbp_get_ocb(sdev)) == NULL) { - SCSI_XFER_ERROR(sxfer) = XS_REQUEUE_REQ; - if (sdev->freeze == 0) { - SBP_LOCK(sdev->target->sbp); - SBP_DEVICE_FREEZE(sdev, 1); - sdev->freeze ++; - SBP_UNLOCK(sdev->target->sbp); - } - SCSI_TRANSFER_DONE(sxfer); - return; - } - - ocb->flags = OCB_ACT_CMD; - ocb->sdev = sdev; - ocb->sxfer = sxfer; -#if defined(__FreeBSD__) - sxfer->ccb_h.ccb_sdev_ptr = sdev; -#endif - ocb->orb[0] = htonl(1 << 31); - ocb->orb[1] = 0; - ocb->orb[2] = htonl(((sbp->fd.fc->nodeid | FWLOCALBUS )<< 16) ); - ocb->orb[3] = htonl(ocb->bus_addr + IND_PTR_OFFSET); - speed = min(target->fwdev->speed, max_speed); - ocb->orb[4] = htonl(ORB_NOTIFY | ORB_CMD_SPD(speed) - | ORB_CMD_MAXP(speed + 7)); - if(SCSI_XFER_DIR(sxfer) == SCSI_XFER_DATA_IN){ - ocb->orb[4] |= htonl(ORB_CMD_IN); + mutex_enter(&sc->sc_mtx); + ocb = sbp_get_ocb(sdev); + mutex_exit(&sc->sc_mtx); + if (ocb == NULL) { + xs->error = XS_REQUEUE; + if (sdev->freeze == 0) { + scsipi_periph_freeze(sdev->periph, 1); + sdev->freeze++; } + scsipi_done(xs); + return; + } - if (CAM_XFER_FLAGS(sxfer) & CAM_SCATTER_VALID) - printf("sbp: CAM_SCATTER_VALID\n"); - if (CAM_XFER_FLAGS(sxfer) & CAM_DATA_PHYS) - printf("sbp: CAM_DATA_PHYS\n"); - - cdb = SCSI_XFER_CMD(sxfer); - memcpy((void *)&ocb->orb[5], cdb, SCSI_XFER_CMDLEN(sxfer)); + ocb->flags = OCB_ACT_CMD; + ocb->sdev = sdev; + ocb->xs = xs; + ocb->orb[0] = htonl(1 << 31); + ocb->orb[1] = 0; + ocb->orb[2] = htonl(((sc->sc_fd.fc->nodeid | FWLOCALBUS) << 16)); + ocb->orb[3] = htonl(ocb->bus_addr + IND_PTR_OFFSET); + speed = min(target->fwdev->speed, max_speed); + ocb->orb[4] = + htonl(ORB_NOTIFY | ORB_CMD_SPD(speed) | ORB_CMD_MAXP(speed + 7)); + if ((xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) == + XS_CTL_DATA_IN) { + ocb->orb[4] |= htonl(ORB_CMD_IN); + flag = BUS_DMA_READ; + } else + flag = BUS_DMA_WRITE; + + cdb = xs->cmd; + memcpy((void *)&ocb->orb[5], cdb, xs->cmdlen); /* printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntohl(ocb->orb[2]), ntohl(ocb->orb[3])); printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7])); */ - if (SCSI_XFER_DATALEN(sxfer) > 0) { - int s, error; - - s = splsoftvm(); - error = fw_bus_dmamap_load(/*dma tag*/sbp->dmat, - /*dma map*/ocb->dmamap, - SCSI_XFER_DATA(sxfer), - SCSI_XFER_DATALEN(sxfer), - sbp_execute_ocb, - ocb, - /*flags*/0); - splx(s); - if (error) - printf("sbp: bus_dmamap_load error %d\n", error); + if (xs->datalen > 0) { + error = bus_dmamap_load(sc->sc_dmat, ocb->dmamap, + xs->data, xs->datalen, NULL, BUS_DMA_NOWAIT | flag); + if (error) { + aprint_error_dev(sc->sc_fd.dev, + "DMA map load error %d\n", error); + xs->error = XS_DRIVER_STUFFUP; + scsipi_done(xs); } else - sbp_execute_ocb(ocb, NULL, 0, 0); - break; - } -#if defined(__FreeBSD__) - case XPT_CALC_GEOMETRY: - { - struct ccb_calc_geometry *ccg; -#if defined(__DragonFly__) || __FreeBSD_version < 501100 - uint32_t size_mb; - uint32_t secs_per_cylinder; - int extended = 1; -#endif + sbp_execute_ocb(ocb, ocb->dmamap->dm_segs, + ocb->dmamap->dm_nsegs); + } else + sbp_execute_ocb(ocb, NULL, 0); - ccg = &sxfer->ccg; - if (ccg->block_size == 0) { - printf("sbp_action1: block_size is 0.\n"); - SCSI_XFER_ERROR(sxfer) = XS_REQ_INVALID; - SCSI_TRANSFER_DONE(sxfer); - break; - } -SBP_DEBUG(1) - printf("%s:%d:%d:%d:XPT_CALC_GEOMETRY: " -#if defined(__DragonFly__) || __FreeBSD_version < 500000 - "Volume size = %d\n", -#else - "Volume size = %jd\n", -#endif - fw_get_nameunit(sbp->fd.dev), - cam_sim_path(sbp->sim), - sxfer->ccb_h.target_id, sxfer->ccb_h.target_lun, -#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - (uintmax_t) -#endif - ccg->volume_size); -END_DEBUG - -#if defined(__DragonFly__) || __FreeBSD_version < 501100 - size_mb = ccg->volume_size - / ((1024L * 1024L) / ccg->block_size); - - if (size_mb > 1024 && extended) { - ccg->heads = 255; - ccg->secs_per_track = 63; - } else { - ccg->heads = 64; - ccg->secs_per_track = 32; - } - secs_per_cylinder = ccg->heads * ccg->secs_per_track; - ccg->cylinders = ccg->volume_size / secs_per_cylinder; - SCSI_XFER_ERROR(sxfer) = XS_REQ_CMP; -#else - cam_calc_geometry(ccg, /*extended*/1); -#endif - SCSI_TRANSFER_DONE(sxfer); - break; - } - case XPT_RESET_BUS: /* Reset the specified SCSI bus */ - { - -SBP_DEBUG(1) - printf("%s:%d:XPT_RESET_BUS: \n", - fw_get_nameunit(sbp->fd.dev), cam_sim_path(sbp->sim)); -END_DEBUG - - SCSI_XFER_ERROR(sxfer) = XS_REQ_INVALID; - SCSI_TRANSFER_DONE(sxfer); - break; - } - case XPT_PATH_INQ: /* Path routing inquiry */ - { - struct ccb_pathinq *cpi = &sxfer->cpi; - struct cam_sim *sim = sbp->sim; - -SBP_DEBUG(1) - printf("%s:%d:%d XPT_PATH_INQ:.\n", - fw_get_nameunit(sbp->fd.dev), - sxfer->ccb_h.target_id, sxfer->ccb_h.target_lun); -END_DEBUG - cpi->version_num = 1; /* XXX??? */ - cpi->hba_inquiry = PI_TAG_ABLE; - cpi->target_sprt = 0; - cpi->hba_misc = PIM_NOBUSRESET | PIM_NO_6_BYTE; - cpi->hba_eng_cnt = 0; - cpi->max_target = SBP_NUM_TARGETS - 1; - cpi->max_lun = SBP_NUM_LUNS - 1; - cpi->initiator_id = SBP_INITIATOR; - cpi->bus_id = sim->bus_id; - cpi->base_transfer_speed = 400 * 1000 / 8; - strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "SBP", HBA_IDLEN); - strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN); - cpi->unit_number = sim->unit_number; - cpi->transport = XPORT_SPI; /* XX should havea FireWire */ - cpi->transport_version = 2; - cpi->protocol = PROTO_SCSI; - cpi->protocol_version = SCSI_REV_2; - - SCSI_XFER_ERROR(cpi) = XS_REQ_CMP; - SCSI_TRANSFER_DONE(sxfer); - break; - } - case XPT_GET_TRAN_SETTINGS: - { - struct ccb_trans_settings *cts = &sxfer->cts; - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; - - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_SPI; /* should have a FireWire */ - cts->transport_version = 2; - spi->valid = CTS_SPI_VALID_DISC; - spi->flags = CTS_SPI_FLAGS_DISC_ENB; - scsi->valid = CTS_SCSI_VALID_TQ; - scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; -SBP_DEBUG(1) - printf("%s:%d:%d XPT_GET_TRAN_SETTINGS:.\n", - fw_get_nameunit(sbp->fd.dev), - sxfer->ccb_h.target_id, sxfer->ccb_h.target_lun); -END_DEBUG - SCSI_XFER_ERROR(cts) = XS_REQ_CMP; - SCSI_TRANSFER_DONE(sxfer); - break; - } - case XPT_ABORT: - SCSI_XFER_ERROR(sxfer) = XS_UA_ABORT; - SCSI_TRANSFER_DONE(sxfer); - break; - case XPT_SET_TRAN_SETTINGS: - /* XXX */ - default: - SCSI_XFER_ERROR(sxfer) = XS_REQ_INVALID; - SCSI_TRANSFER_DONE(sxfer); - break; -#endif - } return; } -#if defined(__FreeBSD__) static void -sbp_action(struct cam_sim *sim, sbp_scsi_xfer *sxfer) +sbp_execute_ocb(struct sbp_ocb *ocb, bus_dma_segment_t *segments, int seg) { - int s; - - s = splfw(); - sbp_action1(sim->softc, sxfer); - splx(s); -} -#endif - -static void -sbp_execute_ocb(void *arg, bus_dma_segment_t *segments, int seg, int error) -{ - int i; - struct sbp_ocb *ocb; struct sbp_ocb *prev; bus_dma_segment_t *s; - - if (error) - printf("sbp_execute_ocb: error=%d\n", error); - - ocb = (struct sbp_ocb *)arg; + int i; SBP_DEBUG(2) printf("sbp_execute_ocb: seg %d", seg); for (i = 0; i < seg; i++) -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - printf(", %x:%d", segments[i].ds_addr, segments[i].ds_len); -#else printf(", %jx:%jd", (uintmax_t)segments[i].ds_addr, - (uintmax_t)segments[i].ds_len); -#endif + (uintmax_t)segments[i].ds_len); printf("\n"); END_DEBUG if (seg == 1) { /* direct pointer */ - s = &segments[0]; + s = segments; if (s->ds_len > SBP_SEG_MAX) panic("ds_len > SBP_SEG_MAX, fix busdma code"); ocb->orb[3] = htonl(s->ds_addr); ocb->orb[4] |= htonl(s->ds_len); - } else if(seg > 1) { + } else if (seg > 1) { /* page table */ for (i = 0; i < seg; i++) { s = &segments[i]; @@ -2868,13 +2355,9 @@ SBP_DEBUG(0) /* XXX LSI Logic "< 16 byte" bug might be hit */ if (s->ds_len < 16) printf("sbp_execute_ocb: warning, " -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - "segment length(%d) is less than 16." -#else - "segment length(%jd) is less than 16." -#endif - "(seg=%d/%d)\n", (uintmax_t)s->ds_len, i+1, seg); + "segment length(%jd) is less than 16." + "(seg=%d/%d)\n", + (uintmax_t)s->ds_len, i + 1, seg); END_DEBUG if (s->ds_len > SBP_SEG_MAX) panic("ds_len > SBP_SEG_MAX, fix busdma code"); @@ -2883,170 +2366,146 @@ END_DEBUG } ocb->orb[4] |= htonl(ORB_CMD_PTBL | seg); } - - if (seg > 0) - fw_bus_dmamap_sync(ocb->sdev->target->sbp->dmat, ocb->dmamap, - (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? - BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); + + if (seg > 0) { + struct sbp_softc *sc = ocb->sdev->target->sbp; + const int flag = (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? + BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE; + + bus_dmamap_sync(sc->sc_dmat, ocb->dmamap, + 0, ocb->dmamap->dm_mapsize, flag); + } prev = sbp_enqueue_ocb(ocb->sdev, ocb); - fwdma_sync(&ocb->sdev->dma, BUS_DMASYNC_PREWRITE); + SBP_ORB_DMA_SYNC(ocb->sdev->dma, ocb->index, BUS_DMASYNC_PREWRITE); if (use_doorbell) { if (prev == NULL) { if (ocb->sdev->last_ocb != NULL) sbp_doorbell(ocb->sdev); else - sbp_orb_pointer(ocb->sdev, ocb); + sbp_orb_pointer(ocb->sdev, ocb); } - } else { + } else if (prev == NULL || (ocb->sdev->flags & ORB_LINK_DEAD) != 0) { ocb->sdev->flags &= ~ORB_LINK_DEAD; - sbp_orb_pointer(ocb->sdev, ocb); + sbp_orb_pointer(ocb->sdev, ocb); } - } -} - -#if defined(__FreeBSD__) -static void -sbp_poll(struct cam_sim *sim) -{ - struct sbp_softc *sbp; - struct firewire_comm *fc; - - sbp = (struct sbp_softc *)sim->softc; - fc = sbp->fd.fc; - - fc->poll(fc, 0, -1); - - return; } -#endif static struct sbp_ocb * sbp_dequeue_ocb(struct sbp_dev *sdev, struct sbp_status *sbp_status) { + struct sbp_softc *sc = sdev->target->sbp; struct sbp_ocb *ocb; struct sbp_ocb *next; - int s = splfw(), order = 0; + int order = 0; int flags; SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - printf("%s: 0x%08lx src %d\n", -#else - printf("%s: 0x%08x src %d\n", -#endif - __func__, ntohl(sbp_status->orb_lo), sbp_status->src); + printf("%s:%s:%s: 0x%08x src %d\n", device_xname(sc->sc_fd.dev), + __func__, sdev->bustgtlun, ntohl(sbp_status->orb_lo), + sbp_status->src); END_DEBUG - SBP_LOCK(sdev->target->sbp); + mutex_enter(&sc->sc_mtx); for (ocb = STAILQ_FIRST(&sdev->ocbs); ocb != NULL; ocb = next) { next = STAILQ_NEXT(ocb, ocb); flags = ocb->flags; if (OCB_MATCH(ocb, sbp_status)) { /* found */ + SBP_ORB_DMA_SYNC(sdev->dma, ocb->index, + BUS_DMASYNC_POSTWRITE); STAILQ_REMOVE(&sdev->ocbs, ocb, sbp_ocb, ocb); - if (ocb->sxfer != NULL) -#if defined(__DragonFly__) || defined(__NetBSD__) - fw_callout_stop(&SCSI_XFER_CALLOUT(ocb->sxfer)); -#else - untimeout(sbp_timeout, (void *)ocb, - SCSI_XFER_CALLOUT(ocb->sxfer)); -#endif + if (ocb->xs != NULL) + callout_stop(&ocb->xs->xs_callout); if (ntohl(ocb->orb[4]) & 0xffff) { - fw_bus_dmamap_sync(sdev->target->sbp->dmat, - ocb->dmamap, - (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? - BUS_DMASYNC_POSTREAD : - BUS_DMASYNC_POSTWRITE); - fw_bus_dmamap_unload(sdev->target->sbp->dmat, - ocb->dmamap); + const int flag = + (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? + BUS_DMASYNC_POSTREAD : + BUS_DMASYNC_POSTWRITE; + + bus_dmamap_sync(sc->sc_dmat, ocb->dmamap, + 0, ocb->dmamap->dm_mapsize, flag); + bus_dmamap_unload(sc->sc_dmat, ocb->dmamap); + } if (!use_doorbell) { if (sbp_status->src == SRC_NO_NEXT) { if (next != NULL) - sbp_orb_pointer(sdev, next); - else if (order > 0) { + sbp_orb_pointer(sdev, next); + else if (order > 0) /* * Unordered execution * We need to send pointer for * next ORB */ sdev->flags |= ORB_LINK_DEAD; - } } - } else { - /* - * XXX this is not correct for unordered - * execution. - */ - if (sdev->last_ocb != NULL) - sbp_free_ocb(sdev, sdev->last_ocb); - sdev->last_ocb = ocb; - if (next != NULL && - sbp_status->src == SRC_NO_NEXT) - sbp_doorbell(sdev); } break; } else - order ++; + order++; } - SBP_UNLOCK(sdev->target->sbp); - splx(s); -SBP_DEBUG(0) - if (ocb && order > 0) { - sbp_show_sdev_info(sdev, 2); - printf("unordered execution order:%d\n", order); + mutex_exit(&sc->sc_mtx); + + if (ocb && use_doorbell) { + /* + * XXX this is not correct for unordered + * execution. + */ + if (sdev->last_ocb != NULL) + sbp_free_ocb(sdev, sdev->last_ocb); + sdev->last_ocb = ocb; + if (next != NULL && + sbp_status->src == SRC_NO_NEXT) + sbp_doorbell(sdev); } + +SBP_DEBUG(0) + if (ocb && order > 0) + printf("%s:%s:%s: unordered execution order:%d\n", + device_xname(sc->sc_fd.dev), __func__, sdev->bustgtlun, + order); END_DEBUG - return (ocb); + return ocb; } static struct sbp_ocb * sbp_enqueue_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) { - int s = splfw(); - struct sbp_ocb *prev, *prev2; + struct sbp_softc *sc = sdev->target->sbp; + struct sbp_ocb *tocb, *prev, *prev2; SBP_DEBUG(1) - sbp_show_sdev_info(sdev, 2); -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - printf("%s: 0x%08x\n", __func__, ocb->bus_addr); -#else - printf("%s: 0x%08jx\n", __func__, (uintmax_t)ocb->bus_addr); -#endif + printf("%s:%s:%s: 0x%08jx\n", device_xname(sc->sc_fd.dev), + __func__, sdev->bustgtlun, (uintmax_t)ocb->bus_addr); END_DEBUG - prev2 = prev = STAILQ_LAST(&sdev->ocbs, sbp_ocb, ocb); + mutex_enter(&sc->sc_mtx); + prev = NULL; + STAILQ_FOREACH(tocb, &sdev->ocbs, ocb) + prev = tocb; + prev2 = prev; STAILQ_INSERT_TAIL(&sdev->ocbs, ocb, ocb); + mutex_exit(&sc->sc_mtx); - if (ocb->sxfer != NULL) -#if defined(__DragonFly__) || defined(__NetBSD__) - fw_callout_reset(&SCSI_XFER_CALLOUT(ocb->sxfer), - mstohz(SCSI_XFER_TIMEOUT(ocb->sxfer)), sbp_timeout, ocb); -#else - SCSI_XFER_CALLOUT(ocb->sxfer) = timeout(sbp_timeout, - (void *)ocb, mstohz(SCSI_XFER_TIMEOUT(ocb->sxfer))); -#endif + callout_reset(&ocb->xs->xs_callout, mstohz(ocb->xs->timeout), + sbp_timeout, ocb); if (use_doorbell && prev == NULL) prev2 = sdev->last_ocb; if (prev2 != NULL) { SBP_DEBUG(2) -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - printf("linking chain 0x%x -> 0x%x\n", - prev2->bus_addr, ocb->bus_addr); -#else printf("linking chain 0x%jx -> 0x%jx\n", (uintmax_t)prev2->bus_addr, (uintmax_t)ocb->bus_addr); -#endif END_DEBUG - prev2->orb[1] = htonl(ocb->bus_addr); - prev2->orb[0] = 0; + /* + * Suppress compiler optimization so that orb[1] must be + * written first. + * XXX We may need an explicit memory barrier for other + * architectures other than i386/amd64. + */ + *(volatile uint32_t *)&prev2->orb[1] = htonl(ocb->bus_addr); + *(volatile uint32_t *)&prev2->orb[0] = 0; } - splx(s); return prev; } @@ -3054,78 +2513,73 @@ END_DEBUG static struct sbp_ocb * sbp_get_ocb(struct sbp_dev *sdev) { + struct sbp_softc *sc = sdev->target->sbp; struct sbp_ocb *ocb; - int s = splfw(); - fw_mtx_assert(&sdev->target->sbp->mtx, MA_OWNED); + KASSERT(mutex_owned(&sc->sc_mtx)); + ocb = STAILQ_FIRST(&sdev->free_ocbs); if (ocb == NULL) { sdev->flags |= ORB_SHORTAGE; - printf("ocb shortage!!!\n"); - splx(s); + aprint_error_dev(sc->sc_fd.dev, + "ocb shortage!!!\n"); return NULL; } STAILQ_REMOVE_HEAD(&sdev->free_ocbs, ocb); - splx(s); - ocb->sxfer = NULL; - return (ocb); + ocb->xs = NULL; + return ocb; } static void sbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) { + struct sbp_softc *sc = sdev->target->sbp; + int count; + ocb->flags = 0; - ocb->sxfer = NULL; + ocb->xs = NULL; - SBP_LOCK(sdev->target->sbp); + mutex_enter(&sc->sc_mtx); STAILQ_INSERT_TAIL(&sdev->free_ocbs, ocb, ocb); - if ((sdev->flags & ORB_SHORTAGE) != 0) { - int count; - + mutex_exit(&sc->sc_mtx); + if (sdev->flags & ORB_SHORTAGE) { sdev->flags &= ~ORB_SHORTAGE; count = sdev->freeze; sdev->freeze = 0; - SBP_DEVICE_THAW(sdev, count); + if (sdev->periph) + scsipi_periph_thaw(sdev->periph, count); + scsipi_channel_thaw(&sc->sc_channel, 0); } - SBP_UNLOCK(sdev->target->sbp); } static void sbp_abort_ocb(struct sbp_ocb *ocb, int status) { + struct sbp_softc *sc; struct sbp_dev *sdev; sdev = ocb->sdev; + sc = sdev->target->sbp; SBP_DEBUG(0) - sbp_show_sdev_info(sdev, 2); -#if defined(__DragonFly__) || \ - (defined(__FreeBSD__) && __FreeBSD_version < 500000) - printf("sbp_abort_ocb 0x%x\n", ocb->bus_addr); -#else - printf("sbp_abort_ocb 0x%jx\n", (uintmax_t)ocb->bus_addr); -#endif + printf("%s:%s:%s: sbp_abort_ocb 0x%jx\n", device_xname(sc->sc_fd.dev), + __func__, sdev->bustgtlun, (uintmax_t)ocb->bus_addr); END_DEBUG SBP_DEBUG(1) - if (ocb->sxfer != NULL) + if (ocb->xs != NULL) sbp_print_scsi_cmd(ocb); END_DEBUG if (ntohl(ocb->orb[4]) & 0xffff) { - fw_bus_dmamap_sync(sdev->target->sbp->dmat, ocb->dmamap, - (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? - BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); - fw_bus_dmamap_unload(sdev->target->sbp->dmat, ocb->dmamap); + const int flag = (ntohl(ocb->orb[4]) & ORB_CMD_IN) ? + BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE; + + bus_dmamap_sync(sc->sc_dmat, ocb->dmamap, + 0, ocb->dmamap->dm_mapsize, flag); + bus_dmamap_unload(sc->sc_dmat, ocb->dmamap); } - if (ocb->sxfer != NULL) { -#if defined(__DragonFly__ ) || defined(__NetBSD__) - fw_callout_stop(&SCSI_XFER_CALLOUT(ocb->sxfer)); -#else - untimeout(sbp_timeout, (void *)ocb, - SCSI_XFER_CALLOUT(ocb->sxfer)); -#endif - SCSI_XFER_ERROR(ocb->sxfer) = status; - SBP_LOCK(sdev->target->sbp); - SCSI_TRANSFER_DONE(ocb->sxfer); - SBP_UNLOCK(sdev->target->sbp); + if (ocb->xs != NULL) { + callout_stop(&ocb->xs->xs_callout); + ocb->xs->error = status; + scsipi_done(ocb->xs); } sbp_free_ocb(sdev, ocb); } @@ -3133,14 +2587,16 @@ END_DEBUG static void sbp_abort_all_ocbs(struct sbp_dev *sdev, int status) { - int s; + struct sbp_softc *sc = sdev->target->sbp; struct sbp_ocb *ocb, *next; STAILQ_HEAD(, sbp_ocb) temp; - s = splfw(); - - memcpy(&temp, &sdev->ocbs, sizeof(temp)); + mutex_enter(&sc->sc_mtx); + STAILQ_INIT(&temp); + STAILQ_CONCAT(&temp, &sdev->ocbs); STAILQ_INIT(&sdev->ocbs); + mutex_exit(&sc->sc_mtx); + for (ocb = STAILQ_FIRST(&temp); ocb != NULL; ocb = next) { next = STAILQ_NEXT(ocb, ocb); sbp_abort_ocb(ocb, status); @@ -3149,98 +2605,4 @@ sbp_abort_all_ocbs(struct sbp_dev *sdev, int status) sbp_free_ocb(sdev, sdev->last_ocb); sdev->last_ocb = NULL; } - - splx(s); } - -#if defined(__FreeBSD__) -static devclass_t sbp_devclass; - -static device_method_t sbp_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, sbp_probe), - DEVMETHOD(device_attach, sbp_attach), - DEVMETHOD(device_detach, sbp_detach), - DEVMETHOD(device_shutdown, sbp_shutdown), - - { 0, 0 } -}; - -static driver_t sbp_driver = { - "sbp", - sbp_methods, - sizeof(struct sbp_softc), -}; -#ifdef __DragonFly__ -DECLARE_DUMMY_MODULE(sbp); -#endif -DRIVER_MODULE(sbp, firewire, sbp_driver, sbp_devclass, 0, 0); -MODULE_VERSION(sbp, 1); -MODULE_DEPEND(sbp, firewire, 1, 1, 1); -MODULE_DEPEND(sbp, cam, 1, 1, 1); -#elif defined(__NetBSD__) -static void -sbp_scsipi_request( - struct scsipi_channel *channel, scsipi_adapter_req_t req, void *arg) -{ - int i, s; - struct sbp_softc *sbp = - device_private(channel->chan_adapter->adapt_dev); - struct scsipi_xfer *xs = arg; - - if (debug > 1) - printf("Called sbpscsi_scsipi_request\n"); - - switch (req) { - case ADAPTER_REQ_RUN_XFER: - if (debug > 1) { - printf("Got req_run_xfer\n"); - printf("xs control: 0x%08x, timeout: %d\n", - xs->xs_control, xs->timeout); - printf("opcode: 0x%02x\n", (int)xs->cmd->opcode); - for (i = 0; i < 15; i++) - printf("0x%02x ",(int)xs->cmd->bytes[i]); - printf("\n"); - } - if (xs->xs_control & XS_CTL_RESET) { - if (debug > 1) - printf("XS_CTL_RESET not support\n"); - break; - } -#define SBPSCSI_SBP2_MAX_CDB 12 - if (xs->cmdlen > SBPSCSI_SBP2_MAX_CDB) { - if (debug > 0) - printf( - "sbp doesn't support cdb's larger than %d " - "bytes\n", SBPSCSI_SBP2_MAX_CDB); - SCSI_XFER_ERROR(xs) = XS_REQ_INVALID; - SCSI_TRANSFER_DONE(xs); - return; - } - s = splfw(); - sbp_action1(sbp, xs); - splx(s); - - break; - case ADAPTER_REQ_GROW_RESOURCES: - if (debug > 1) - printf("Got req_grow_resources\n"); - break; - case ADAPTER_REQ_SET_XFER_MODE: - if (debug > 1) - printf("Got set xfer mode\n"); - break; - default: - panic("Unknown request: %d\n", (int)req); - } -} - -static void -sbp_minphys(struct buf *bp) -{ - minphys(bp); -} - -CFATTACH_DECL_NEW(sbp, sizeof(struct sbp_softc), - sbpmatch, sbpattach, sbpdetach, NULL); -#endif diff --git a/sys/dev/ieee1394/sbp.h b/sys/dev/ieee1394/sbp.h index 34d8a0937c6..5ce279bdfbb 100644 --- a/sys/dev/ieee1394/sbp.h +++ b/sys/dev/ieee1394/sbp.h @@ -1,4 +1,4 @@ -/* $NetBSD: sbp.h,v 1.3 2006/02/25 02:28:58 wiz Exp $ */ +/* $NetBSD: sbp.h,v 1.4 2010/03/29 03:05:28 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -31,10 +31,12 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/sbp.h,v 1.5 2005/01/06 01:42:41 imp Exp $ + * + * $FreeBSD: src/sys/dev/firewire/sbp.h,v 1.6 2009/04/07 02:33:46 sbruno Exp $ * */ +#ifndef _SBP_H_ +#define _SBP_H_ #define ORB_NOTIFY (1 << 31) #define ORB_FMT_STD (0 << 29) @@ -117,7 +119,7 @@ struct sbp_status{ /* 3: Page size not supported */ /* 4: Access denied */ #define STATUS_ACCESS_DENY 4 -/* 5: Logical unit not supported */ +#define STATUS_LUR 5 /* 6: Maximum payload too small */ /* 7: Reserved for future standardization */ /* 8: Resource unavailabe */ @@ -229,3 +231,5 @@ struct scsi3_sense_data { uint8_t asb[14]; /* Additional sense bytes */ }; typedef struct scsi3_sense_data *scsi3_sense_data_t; + +#endif /* _SBP_H_ */ diff --git a/sys/dev/pci/fwohci_pci.c b/sys/dev/pci/fwohci_pci.c index 2964fd57dc5..75cf99d6c43 100644 --- a/sys/dev/pci/fwohci_pci.c +++ b/sys/dev/pci/fwohci_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwohci_pci.c,v 1.36 2010/02/24 22:38:00 dyoung Exp $ */ +/* $NetBSD: fwohci_pci.c,v 1.37 2010/03/29 03:05:27 kiyohara Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -30,21 +30,19 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fwohci_pci.c,v 1.36 2010/02/24 22:38:00 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fwohci_pci.c,v 1.37 2010/03/29 03:05:27 kiyohara Exp $"); #include <sys/param.h> -#include <sys/systm.h> -#include <sys/socket.h> -#include <sys/device.h> -#include <sys/select.h> - #include <sys/bus.h> +#include <sys/device.h> #include <sys/intr.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/systm.h> +#include <dev/pci/pcidevs.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> -#include <dev/pci/pcidevs.h> -#include <dev/ieee1394/fw_port.h> #include <dev/ieee1394/firewire.h> #include <dev/ieee1394/firewirereg.h> #include <dev/ieee1394/fwdma.h> @@ -122,7 +120,7 @@ fwohci_pci_attach(device_t parent, device_t self, void *aux) } /* Disable interrupts, so we don't get any spurious ones. */ - OHCI_CSR_WRITE(&psc->psc_sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); + OWRITE(&psc->psc_sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); /* Enable the device. */ csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); @@ -135,7 +133,7 @@ fwohci_pci_attach(device_t parent, device_t self, void *aux) goto fail; } intrstr = pci_intr_string(pa->pa_pc, ih); - psc->psc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, fwohci_filt, + psc->psc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, fwohci_intr, &psc->psc_sc); if (psc->psc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt"); @@ -149,7 +147,7 @@ fwohci_pci_attach(device_t parent, device_t self, void *aux) if (!pmf_device_register(self, fwohci_pci_suspend, fwohci_pci_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); - if (fwohci_init(&(psc->psc_sc), psc->psc_sc.fc.dev) != 0) { + if (fwohci_init(&psc->psc_sc) != 0) { pci_intr_disestablish(pa->pa_pc, psc->psc_ih); bus_space_unmap(psc->psc_sc.bst, psc->psc_sc.bsh, psc->psc_sc.bssize); @@ -172,7 +170,7 @@ fwohci_pci_suspend(device_t dv, const pmf_qual_t *qual) int s; s = splbio(); - fwohci_stop(&psc->psc_sc, psc->psc_sc.fc.dev); + fwohci_stop(&psc->psc_sc); splx(s); return true; @@ -185,7 +183,7 @@ fwohci_pci_resume(device_t dv, const pmf_qual_t *qual) int s; s = splbio(); - fwohci_resume(&psc->psc_sc, psc->psc_sc.fc.dev); + fwohci_resume(&psc->psc_sc); splx(s); return true; |
