From c33e2714c5b9d9a13142d9c0ec42b36becab2ccc Mon Sep 17 00:00:00 2001 From: kiyohara Date: Mon, 5 Nov 2007 19:08:56 +0000 Subject: [PATCH] + Sync to FreeBSD. firewire.c Rev.1.101 firewire.h Rev.1.21 firewirereg.h Rev.1.50 fwdev.c Rev.1.52 fwdma.c Rev.1.9 fwmem.c Rev.1.34 fwohci.c Rev.1.93 fwohcireg.h Rev.1.23 fwohcivar.h Rev.1.16 if_fwip.c Rev.1.16 if_fwipvar.h Rev.1.5 sbp.c Rev.1.92 + Cleanup macros in fw_port.h. + Fix the occurrence of the error at the resume. Don't set the buffer again. --- sys/dev/ieee1394/firewire.c | 423 ++++++++++------ sys/dev/ieee1394/firewire.h | 12 +- sys/dev/ieee1394/firewirereg.h | 48 +- sys/dev/ieee1394/fw_port.h | 859 ++++++++++++++++++--------------- sys/dev/ieee1394/fwdev.c | 111 +++-- sys/dev/ieee1394/fwdma.c | 8 +- sys/dev/ieee1394/fwmem.c | 30 +- sys/dev/ieee1394/fwohci.c | 730 ++++++++++++++-------------- sys/dev/ieee1394/fwohcireg.h | 4 +- sys/dev/ieee1394/fwohcivar.h | 32 +- sys/dev/ieee1394/if_fwip.c | 107 ++-- sys/dev/ieee1394/if_fwipvar.h | 13 +- sys/dev/ieee1394/sbp.c | 159 +++--- 13 files changed, 1423 insertions(+), 1113 deletions(-) diff --git a/sys/dev/ieee1394/firewire.c b/sys/dev/ieee1394/firewire.c index fc679f12ea3a..fe7c10d1b446 100644 --- a/sys/dev/ieee1394/firewire.c +++ b/sys/dev/ieee1394/firewire.c @@ -1,4 +1,4 @@ -/* $NetBSD: firewire.c,v 1.15 2007/10/19 12:00:12 ad Exp $ */ +/* $NetBSD: firewire.c,v 1.16 2007/11/05 19:08:56 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -32,7 +32,7 @@ * 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.c,v 1.86 2007/03/30 15:43:56 simokawa Exp $ + * $FreeBSD: src/sys/dev/firewire/firewire.c,v 1.101 2007/10/20 23:23:14 julian Exp $ * */ @@ -48,6 +48,8 @@ #include #include +#include + #if defined(__DragonFly__) || __FreeBSD_version < 500000 #include /* for DELAY() */ #endif @@ -195,19 +197,21 @@ int firewirematch (struct device *, struct cfdata *, void *); void firewireattach (struct device *, struct device *, void *); int firewiredetach (struct device *, 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_kthread_create0 (void *); 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_dump_hdr(struct fw_pkt *, const char *); #if defined(__FreeBSD__) static device_method_t firewire_methods[] = { @@ -265,9 +269,11 @@ fw_noderesolve_nodeid(struct firewire_comm *fc, int dst) int s; s = splfw(); + FW_GLOCK(fc); STAILQ_FOREACH(fwdev, &fc->devices, link) if (fwdev->dst == dst && fwdev->status != FWDEVINVAL) break; + FW_GUNLOCK(fc); splx(s); return fwdev; @@ -301,7 +307,7 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) { int err = 0; struct fw_xferq *xferq; - int tl = -1, len; + int len; struct fw_pkt *fp; int tcode; const struct tcode_info *info; @@ -319,6 +325,17 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) printf("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 >= 0xf0001000))) { + xfer->resp = EAGAIN; + xfer->flag = FWXF_BUSY; + return (EAGAIN); + } + if (info->flag & FWTI_REQ) xferq = fc->atq; else @@ -345,18 +362,17 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) return EINVAL; } if(!(xferq->queued < xferq->maxq)){ - device_printf(fc->bdev, "Discard a packet (queued=%d)\n", + fw_printf(fc->bdev, "Discard a packet (queued=%d)\n", xferq->queued); - return EINVAL; + return EAGAIN; } + xfer->tl = -1; if (info->flag & FWTI_TLABEL) { - if ((tl = fw_get_tlabel(fc, xfer)) == -1) + if (fw_get_tlabel(fc, xfer) < 0) return EAGAIN; - fp->mode.hdr.tlrt = tl << 2; } - xfer->tl = tl; xfer->resp = 0; xfer->fc = fc; xfer->q = xferq; @@ -368,11 +384,32 @@ fw_asyreq(struct firewire_comm *fc, int sub, struct fw_xfer *xfer) * Wakeup blocked process. */ void -fw_asy_callback(struct fw_xfer *xfer){ +fw_xferwake(struct fw_xfer *xfer) +{ + fw_mtx_t lock = &xfer->fc->wait_lock; + + fw_mtx_lock(lock); + xfer->flag |= FWXF_WAKE; + fw_mtx_unlock(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. */ @@ -381,20 +418,15 @@ fw_asystart(struct fw_xfer *xfer) { struct firewire_comm *fc = xfer->fc; int s; -#if 0 /* XXX allow bus explore packets only after bus rest */ - if (fc->status < FWBUSEXPLORE) { - xfer->resp = EAGAIN; - xfer->state = FWXF_BUSY; - if (xfer->hand != NULL) - xfer->hand(xfer); - return; - } -#endif - microtime(&xfer->tv); s = splfw(); - xfer->state = FWXF_INQ; + /* 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) @@ -429,44 +461,55 @@ firewirematch(struct device *parent, struct cfdata *cf, #endif static void -firewire_xfer_timeout(struct firewire_comm *fc) +firewire_xfer_timeout(void *arg, int pending) { - struct fw_xfer *xfer; + 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); - timevalsub(&tv, &split_timeout); + 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 (timevalcmp(&xfer->tv, &tv, >)) - /* the rests are newer than this */ - break; - if (xfer->state == FWXF_START) + if ((xfer->flag & FWXF_SENT) == 0) /* not sent yet */ break; - device_printf(fc->bdev, - "split transaction timeout dst=0x%x tl=0x%x state=%d\n", - xfer->send.hdr.mode.hdr.dst, i, xfer->state); + 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; - fw_xfer_done(xfer); + 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 WATCHDOC_HZ 10 +#define WATCHDOG_HZ 10 static void firewire_watchdog(void *arg) { struct firewire_comm *fc; - static int watchdoc_clock = 0; + static int watchdog_clock = 0; fc = (struct firewire_comm *)arg; @@ -475,13 +518,12 @@ firewire_watchdog(void *arg) * We encounter a timeout easily. To avoid this, * ignore clock interrupt for a while. */ - if (watchdoc_clock > WATCHDOC_HZ * 15) { - firewire_xfer_timeout(fc); - fc->timeout(fc); - } else - watchdoc_clock ++; + if (watchdog_clock > WATCHDOG_HZ * 15) + fw_taskqueue_enqueue(fc->taskqueue, &fc->task_timeout); + else + watchdog_clock ++; - callout_reset(&fc->timeout_callout, hz / WATCHDOC_HZ, + fw_callout_reset(&fc->timeout_callout, hz / WATCHDOG_HZ, (void *)firewire_watchdog, (void *)fc); } @@ -500,19 +542,25 @@ FW_ATTACH(firewire) FWDEV_MAKEDEV(sc); - CALLOUT_INIT(&sc->fc->timeout_callout); - CALLOUT_INIT(&sc->fc->bmr_callout); - CALLOUT_INIT(&sc->fc->busprobe_callout); + 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); - callout_reset(&sc->fc->timeout_callout, hz, + fw_callout_reset(&sc->fc->timeout_callout, hz, (void *)firewire_watchdog, (void *)sc->fc); - fw_kthread_create(fw_kthread_create0, 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); + fw_busreset(fc, FWBUSNOTREADY); fc->ibr(fc); FW_ATTACH_RETURN(0); @@ -566,14 +614,20 @@ FW_DETACH(firewire) 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; - callout_stop(&fc->timeout_callout); - callout_stop(&fc->bmr_callout); - callout_stop(&fc->busprobe_callout); + 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; @@ -585,10 +639,8 @@ FW_DETACH(firewire) free(fc->speed_map, M_FW); free(fc->crom_src_buf, M_FW); - wakeup(fc); - if (tsleep(fc, PWAIT, "fwthr", hz * 60)) - printf("firewire task thread didn't die\n"); - + fw_mtx_destroy(&fc->wait_lock); + fw_mtx_destroy(&fc->tlabel_lock); return(0); } #if defined(__FreeBSD__) @@ -610,6 +662,14 @@ firewire_print(void *aux, const char *pnp) return UNCONF; } + +int +firewire_resume(struct firewire_comm *fc) +{ + + fc->status = FWBUSNOTREADY; + return 0; +} #endif static void @@ -619,9 +679,11 @@ fw_xferq_drain(struct fw_xferq *xferq) while ((xfer = STAILQ_FIRST(&xferq->q)) != NULL) { STAILQ_REMOVE_HEAD(&xferq->q, link); +#if 0 xferq->queued --; +#endif xfer->resp = EAGAIN; - xfer->state = FWXF_SENTERR; + xfer->flag = FWXF_SENTERR; fw_xfer_done(xfer); } } @@ -629,12 +691,32 @@ fw_xferq_drain(struct fw_xferq *xferq) void fw_drain_txq(struct firewire_comm *fc) { + struct fw_xfer *xfer, *txfer; + STAILQ_HEAD(, fw_xfer) xfer_drain; int i; + STAILQ_INIT(&xfer_drain); + + FW_GLOCK(fc); fw_xferq_drain(fc->atq); fw_xferq_drain(fc->ats); 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 ++) + while ((xfer = STAILQ_FIRST(&fc->tlabels[i])) != NULL) { + if (firewire_debug) + printf("tl=%d flag=%d\n", i, xfer->flag); + xfer->resp = EAGAIN; + STAILQ_REMOVE_HEAD(&fc->tlabels[i], tlabel); + STAILQ_INSERT_TAIL(&xfer_drain, xfer, tlabel); + } + fw_mtx_unlock(&fc->tlabel_lock); + + STAILQ_FOREACH_SAFE(xfer, &xfer_drain, tlabel, txfer) + xfer->hand(xfer); } static void @@ -750,7 +832,7 @@ fw_reset_crom(struct firewire_comm *fc) * Called after bus reset. */ void -fw_busreset(struct firewire_comm *fc) +fw_busreset(struct firewire_comm *fc, uint32_t new_status) { struct firewire_dev_comm *fdc; struct crom_src *src; @@ -758,12 +840,12 @@ fw_busreset(struct firewire_comm *fc) switch(fc->status){ case FWBUSMGRELECT: - callout_stop(&fc->bmr_callout); + fw_callout_stop(&fc->bmr_callout); break; default: break; } - fc->status = FWBUSRESET; + fc->status = new_status; fw_reset_csr(fc); fw_reset_crom(fc); @@ -905,13 +987,17 @@ struct fw_bind * fw_bindlookup(struct firewire_comm *fc, uint16_t dest_hi, uint32_t dest_lo) { u_int64_t addr; - struct fw_bind *tfw; + struct fw_bind *tfw, *r = NULL; addr = ((u_int64_t)dest_hi << 32) | dest_lo; + FW_GLOCK(fc); STAILQ_FOREACH(tfw, &fc->binds, fclist) - if (BIND_CMP(addr, tfw) == 0) - return(tfw); - return(NULL); + if (BIND_CMP(addr, tfw) == 0) { + r = tfw; + break; + } + FW_GUNLOCK(fc); + return(r); } /* @@ -921,28 +1007,29 @@ int fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb) { struct fw_bind *tfw, *prev = NULL; + int r = 0; if (fwb->start > fwb->end) { printf("%s: invalid range\n", __func__); return EINVAL; } + FW_GLOCK(fc); STAILQ_FOREACH(tfw, &fc->binds, fclist) { if (fwb->end < tfw->start) break; prev = tfw; } - if (prev == NULL) { + if (prev == NULL) STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist); - return (0); - } - if (prev->end < fwb->start) { + else if (prev->end < fwb->start) STAILQ_INSERT_AFTER(&fc->binds, prev, fwb, fclist); - return (0); + else { + printf("%s: bind failed\n", __func__); + r = EBUSY; } - - printf("%s: bind failed\n", __func__); - return (EBUSY); + FW_GUNLOCK(fc); + return (r); } /* @@ -958,6 +1045,7 @@ fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb) int s; s = splfw(); + FW_GLOCK(fc); STAILQ_FOREACH(tfw, &fc->binds, fclist) if (tfw == fwb) { STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist); @@ -965,6 +1053,7 @@ fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb) } printf("%s: no such binding\n", __func__); + FW_GUNLOCK(fc); splx(s); return (1); found: @@ -976,6 +1065,7 @@ found: } STAILQ_INIT(&fwb->xferlist); #endif + FW_GUNLOCK(fc); splx(s); return 0; @@ -1015,6 +1105,20 @@ fw_xferlist_remove(struct fw_xferlist *q) STAILQ_INIT(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. */ @@ -1028,19 +1132,26 @@ fw_tl_free(struct firewire_comm *fc, struct fw_xfer *xfer) 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 tlabel(%d)\n", - __FUNCTION__, xfer->tl); + printf("%s: the xfer is not in the queue " + "(tlabel=%d, flag=0x%x)\n", + __FUNCTION__, 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; } @@ -1049,18 +1160,33 @@ fw_tl_free(struct firewire_comm *fc, struct fw_xfer *xfer) * To obtain XFER structure by transaction label. */ static struct fw_xfer * -fw_tl2xfer(struct firewire_comm *fc, int node, int tlabel) +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", __FUNCTION__, + 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); @@ -1137,16 +1263,20 @@ fw_xfer_unload(struct fw_xfer* xfer) int s; if(xfer == NULL ) return; - if(xfer->state == FWXF_INQ){ + if(xfer->flag & FWXF_INQ){ printf("fw_xfer_free FWXF_INQ\n"); s = splfw(); + FW_GLOCK(xfer->fc); STAILQ_REMOVE(&xfer->q->q, xfer, fw_xfer, link); +#if 0 xfer->q->queued --; +#endif + FW_GUNLOCK(xfer->fc); splx(s); } if (xfer->fc != NULL) { #if 1 - if(xfer->state == FWXF_START) + if(xfer->flag == FWXF_START) /* * This could happen if: * 1. We call fwohci_arcv() before fwohci_txd(). @@ -1155,7 +1285,7 @@ fw_xfer_unload(struct fw_xfer* xfer) printf("fw_xfer_free FWXF_START\n"); #endif } - xfer->state = FWXF_INIT; + xfer->flag = FWXF_INIT; xfer->resp = 0; } /* @@ -1193,8 +1323,8 @@ void fw_asy_callback_free(struct fw_xfer *xfer) { #if 0 - printf("asyreq done state=%d resp=%d\n", - xfer->state, xfer->resp); + printf("asyreq done flag=%d resp=%d\n", + xfer->flag, xfer->resp); #endif fw_xfer_free(xfer); } @@ -1260,7 +1390,6 @@ void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) u_int i, j, node, c_port = 0, i_branch = 0; fc->sid_cnt = len /(sizeof(uint32_t) * 2); - fc->status = FWBUSINIT; fc->max_node = fc->nodeid & 0x3f; CSRARC(fc, NODE_IDS) = ((uint32_t)fc->nodeid) << 16; fc->status = FWBUSCYMELECT; @@ -1319,7 +1448,7 @@ void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) self_id++; fc->topology_map->self_id_count ++; } - device_printf(fc->bdev, "%d nodes", fc->max_node + 1); + fw_printf(fc->bdev, "%d nodes", fc->max_node + 1); /* CRC */ fc->topology_map->crc = fw_crc16( (uint32_t *)&fc->topology_map->generation, @@ -1356,13 +1485,13 @@ void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) fw_bmr(fc); } else { fc->status = FWBUSMGRELECT; - callout_reset(&fc->bmr_callout, hz/8, + fw_callout_reset(&fc->bmr_callout, hz/8, (void *)fw_try_bmr, (void *)fc); } } else fc->status = FWBUSMGRDONE; - callout_reset(&fc->busprobe_callout, hz/4, + fw_callout_reset(&fc->busprobe_callout, hz/4, (void *)fw_bus_probe, (void *)fc); } @@ -1401,10 +1530,10 @@ fw_explore_read_quads(struct fw_device *fwdev, int offset, for (i = 0; i < n; i ++, offset += sizeof(uint32_t)) { xfer = fwmem_read_quad(fwdev, NULL, -1, 0xffff, 0xf0000000 | offset, (void *)&tmp, - fw_asy_callback); + fw_xferwake); if (xfer == NULL) return (-1); - tsleep((void *)xfer, FWPRI, "rquad", 0); + fw_xferwait(xfer); if (xfer->resp == 0) quad[i] = ntohl(tmp); @@ -1449,9 +1578,9 @@ fw_explore_csrblock(struct fw_device *fwdev, int offset, int recur) return (0); for (i = 0; i < dir->crc_len; i ++, offset += sizeof(uint32_t)) { - if (reg[i].key == CROM_UDIR) + if ((reg[i].key & CSRTYPE_MASK) == CSRTYPE_D) recur = 1; - else if (reg[i].key == CROM_TEXTLEAF) + else if ((reg[i].key & CSRTYPE_MASK) == CSRTYPE_L) recur = 0; else continue; @@ -1468,22 +1597,6 @@ fw_explore_csrblock(struct fw_device *fwdev, int offset, int recur) return (0); } -static void -fw_kthread_create0(void *arg) -{ - struct firewire_comm *fc = (struct firewire_comm *)arg; - - config_pending_incr(); - - /* create thread */ - if (THREAD_CREATE(fw_bus_probe_thread, - (void *)fc, NULL, "fw%d_probe", device_get_unit(fc->bdev))) { - - device_printf(fc->bdev, "unable to create thread"); - panic("fw_kthread_create"); - } -} - static int fw_explore_node(struct fw_device *dfwdev) { @@ -1551,7 +1664,7 @@ fw_explore_node(struct fw_device *dfwdev) else STAILQ_INSERT_AFTER(&fc->devices, pfwdev, fwdev, link); - device_printf(fc->bdev, "New %s device ID:%08x%08x\n", + fw_printf(fc->bdev, "New %s device ID:%08x%08x\n", fw_linkspeed[spd], fwdev->eui.hi, fwdev->eui.lo); @@ -1608,6 +1721,7 @@ 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; todo = 0; dfwdev = malloc(sizeof(*dfwdev), M_TEMP, M_NOWAIT); @@ -1623,7 +1737,8 @@ fw_explore(struct firewire_comm *fc) /* We don't probe myself and linkdown nodes */ if (node == fc->nodeid) continue; - if (!fw_find_self_id(fc, node)->p0.link_active) { + fwsid = fw_find_self_id(fc, node); + if (!fwsid || !fwsid->p0.link_active) { if (firewire_debug) printf("node%d: link down\n", node); continue; @@ -1656,23 +1771,23 @@ fw_bus_probe_thread(void *arg) fc = (struct firewire_comm *)arg; - config_pending_decr(); + fw_config_pending_decr(); - FW_LOCK; - while (1) { + fw_mtx_lock(&fc->wait_lock); + while (fc->status != FWBUSDETACH) { if (fc->status == FWBUSEXPLORE) { + fw_mtx_unlock(&fc->wait_lock); fw_explore(fc); fc->status = FWBUSEXPDONE; if (firewire_debug) printf("bus_explore done\n"); fw_attach_dev(fc); - } else if (fc->status == FWBUSDETACH) - break; - tsleep((void *)fc, FWPRI, "fwprobe", 0); + fw_mtx_lock(&fc->wait_lock); + } + fw_msleep((void *)fc, &fc->wait_lock, PWAIT|PCATCH, "-", 0); } - FW_UNLOCK; - wakeup(fc); - THREAD_EXIT(0); + fw_mtx_unlock(&fc->wait_lock); + fw_kthread_exit(0); } @@ -1734,32 +1849,34 @@ fw_attach_dev(struct firewire_comm *fc) static int fw_get_tlabel(struct firewire_comm *fc, struct fw_xfer *xfer) { - u_int i; + u_int dst, new_tlabel; struct fw_xfer *txfer; int s; - static uint32_t label = 0; + dst = xfer->send.hdr.mode.hdr.dst & 0x3f; s = splfw(); - for( i = 0 ; i < 0x40 ; i ++){ - label = (label + 1) & 0x3f; - STAILQ_FOREACH(txfer, &fc->tlabels[label], tlabel) - if (txfer->send.hdr.mode.hdr.dst == - xfer->send.hdr.mode.hdr.dst) - break; - if(txfer == NULL) { - STAILQ_INSERT_TAIL(&fc->tlabels[label], xfer, tlabel); - splx(s); - if (firewire_debug > 1) - printf("fw_get_tlabel: dst=%d tl=%d\n", - xfer->send.hdr.mode.hdr.dst, label); - return(label); - } + fw_mtx_lock(&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) { + fc->last_tlabel[dst] = new_tlabel; + STAILQ_INSERT_TAIL(&fc->tlabels[new_tlabel], xfer, tlabel); + fw_mtx_unlock(&fc->tlabel_lock); + splx(s); + 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); } + fw_mtx_unlock(&fc->tlabel_lock); splx(s); if (firewire_debug > 1) printf("fw_get_tlabel: no free tlabel\n"); - return(-1); + return (-1); } static void @@ -1849,7 +1966,7 @@ fw_rcv(struct fw_rcv_buf *rb) case FWTCODE_RRESB: case FWTCODE_LRES: rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src, - fp->mode.hdr.tlrt >> 2); + 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", @@ -1858,7 +1975,7 @@ fw_rcv(struct fw_rcv_buf *rb) fp->mode.hdr.tlrt >> 2, fp->mode.hdr.tlrt & 3, fp->mode.rresq.data); -#if 1 +#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); @@ -1876,8 +1993,8 @@ fw_rcv(struct fw_rcv_buf *rb) else rb->xfer->resp = 0; /* make sure the packet is drained in AT queue */ - oldstate = rb->xfer->state; - rb->xfer->state = FWXF_RCVD; + oldstate = rb->xfer->flag; + rb->xfer->flag = FWXF_RCVD; switch (oldstate) { case FWXF_SENT: fw_xfer_done(rb->xfer); @@ -1889,7 +2006,7 @@ fw_rcv(struct fw_rcv_buf *rb) #endif break; default: - printf("unexpected state %d\n", rb->xfer->state); + printf("unexpected flag 0x%02x\n", rb->xfer->flag); } return; case FWTCODE_WREQQ: @@ -1912,7 +2029,7 @@ fw_rcv(struct fw_rcv_buf *rb) tcode_str[tcode], tcode, fp->mode.hdr.src, ntohl(fp->mode.wreqq.data)); #endif - if (rb->fc->status == FWBUSRESET) { + if (rb->fc->status == FWBUSINIT) { printf("fw_rcv: cannot respond(bus reset)!\n"); return; } @@ -1945,7 +2062,7 @@ fw_rcv(struct fw_rcv_buf *rb) resfp->mode.rresb.extcode = 0; resfp->mode.rresb.len = 0; /* - rb->xfer->hand = fw_asy_callback; + rb->xfer->hand = fw_xferwake; */ rb->xfer->hand = fw_xfer_free; if(fw_asyreq(rb->fc, -1, rb->xfer)){ @@ -2047,7 +2164,7 @@ fw_try_bmr_callback(struct fw_xfer *xfer) return; error: - device_printf(fc->bdev, "bus manager election failed\n"); + fw_printf(fc->bdev, "bus manager election failed\n"); fw_xfer_free_buf(xfer); } @@ -2201,7 +2318,7 @@ fw_bmr(struct firewire_comm *fc) if (self_id->p0.link_active && self_id->p0.contender) cmstr = fc->max_node; else { - device_printf(fc->bdev, + fw_printf(fc->bdev, "root node is not cycle master capable\n"); /* XXX shall we be the cycle master? */ cmstr = fc->nodeid; @@ -2210,7 +2327,7 @@ fw_bmr(struct firewire_comm *fc) } else cmstr = -1; - device_printf(fc->bdev, "bus manager %d ", CSRARC(fc, BUS_MGR_ID)); + fw_printf(fc->bdev, "bus manager %d ", CSRARC(fc, BUS_MGR_ID)); if(CSRARC(fc, BUS_MGR_ID) != fc->nodeid) { /* We are not the bus manager */ printf("\n"); @@ -2239,6 +2356,34 @@ fw_bmr(struct firewire_comm *fc) 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) diff --git a/sys/dev/ieee1394/firewire.h b/sys/dev/ieee1394/firewire.h index 9181733f741c..f59c55b6528c 100644 --- a/sys/dev/ieee1394/firewire.h +++ b/sys/dev/ieee1394/firewire.h @@ -1,4 +1,4 @@ -/* $NetBSD: firewire.h,v 1.3 2006/11/16 15:59:28 jdolecek Exp $ */ +/* $NetBSD: firewire.h,v 1.4 2007/11/05 19:08:56 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -32,7 +32,7 @@ * 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.h,v 1.20 2005/01/06 01:42:41 imp Exp $ + * $FreeBSD: src/sys/dev/firewire/firewire.h,v 1.21 2007/04/24 12:15:05 simokawa Exp $ * */ @@ -413,14 +413,14 @@ struct fw_crom_buf { #define FWMAXNDMA 0x100 /* 8 bits DMA channel id. in device No. */ #define MAKEMINOR(f, u, s) \ - unit2minor((f) | (((u) & 0xff) << 8) | (s & 0xff)) -#define DEV2UNIT(x) ((dev2unit(x) & 0xff00) >> 8) -#define DEV2SUB(x) (dev2unit(x) & 0xff) + fw_unit2minor((f) | (((u) & 0xff) << 8) | (s & 0xff)) +#define DEV2UNIT(x) ((fw_dev2unit(x) & 0xff00) >> 8) +#define DEV2SUB(x) (fw_dev2unit(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) (dev2unit(x) & FWMEM_FLAG) +#define DEV_FWMEM(x) (fw_dev2unit(x) & FWMEM_FLAG) struct fw_attach_args { const char *name; diff --git a/sys/dev/ieee1394/firewirereg.h b/sys/dev/ieee1394/firewirereg.h index a2e236167f4d..314ad7cd286a 100644 --- a/sys/dev/ieee1394/firewirereg.h +++ b/sys/dev/ieee1394/firewirereg.h @@ -1,4 +1,4 @@ -/* $NetBSD: firewirereg.h,v 1.6 2007/07/29 13:31:08 ad Exp $ */ +/* $NetBSD: firewirereg.h,v 1.7 2007/11/05 19:08:56 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -32,7 +32,7 @@ * 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/firewirereg.h,v 1.41 2007/03/16 05:39:33 simokawa Exp $ + * $FreeBSD: src/sys/dev/firewire/firewirereg.h,v 1.50 2007/07/20 03:42:57 simokawa Exp $ * */ @@ -64,7 +64,7 @@ struct fw_device{ struct firewire_softc { #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 - DEV_T dev; + fw_dev_t dev; device_t sbp_dev; #elif defined(__NetBSD__) struct device _dev; @@ -105,6 +105,7 @@ struct tcode_info { #define FWTI_TLABEL (1 << 2) #define FWTI_BLOCK_STR (1 << 3) #define FWTI_BLOCK_ASY (1 << 4) + u_char valid_res; }; struct firewire_comm{ @@ -140,6 +141,8 @@ struct firewire_comm{ struct fw_xferq *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; STAILQ_HEAD(, fw_bind) binds; STAILQ_HEAD(, fw_device) devices; u_int sid_cnt; @@ -155,10 +158,11 @@ 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) (DEV_T, u_long, void *, int, fw_proc *); + int (*ioctl) (fw_dev_t, u_long, void *, int, fw_proc_t); int (*irx_enable) (struct firewire_comm *, int); int (*irx_disable) (struct firewire_comm *, int); int (*itx_enable) (struct firewire_comm *, int); @@ -170,9 +174,18 @@ struct firewire_comm{ 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; }; #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; #define FWXFERQ_CHTAGMASK 0xff @@ -230,14 +243,16 @@ struct fw_xfer{ struct fw_xferq *q; struct timeval tv; int8_t resp; -#define FWXF_INIT 0 -#define FWXF_INQ 1 -#define FWXF_START 2 -#define FWXF_SENT 3 -#define FWXF_SENTERR 4 -#define FWXF_BUSY 8 -#define FWXF_RCVD 10 - uint8_t state; +#define FWXF_INIT 0x00 +#define FWXF_INQ 0x01 +#define FWXF_START 0x02 +#define FWXF_SENT 0x04 +#define FWXF_SENTERR 0x08 +#define FWXF_BUSY 0x10 +#define FWXF_RCVD 0x20 + +#define FWXF_WAKE 0x80 + uint8_t flag; int8_t tl; void (*hand) (struct fw_xfer *); struct { @@ -276,11 +291,12 @@ 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 *); +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_asy_callback (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 *); @@ -289,8 +305,9 @@ void fw_drain_txq (struct firewire_comm *); int fwdev_makedev (struct firewire_softc *); int fwdev_destroydev (struct firewire_softc *); #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 -void fwdev_clone (void *, struct ucred *, char *, int, DEV_T *); +void fwdev_clone (void *, struct ucred *, char *, int, fw_dev_t *); #endif +int fw_open_isodma(struct firewire_comm *, int); extern int firewire_debug; #if defined(__FreeBSD__) @@ -298,6 +315,7 @@ extern devclass_t firewire_devclass; #elif defined(__NetBSD__) extern struct cfdriver ieee1394if_cd; #endif +extern int firewire_phydma_enable; #ifdef __DragonFly__ #define FWPRI PCATCH diff --git a/sys/dev/ieee1394/fw_port.h b/sys/dev/ieee1394/fw_port.h index 3755299fc363..51db61e37ae6 100644 --- a/sys/dev/ieee1394/fw_port.h +++ b/sys/dev/ieee1394/fw_port.h @@ -1,4 +1,4 @@ -/* $NetBSD: fw_port.h,v 1.25 2007/10/19 12:00:13 ad Exp $ */ +/* $NetBSD: fw_port.h,v 1.26 2007/11/05 19:08:56 kiyohara Exp $ */ /* * Copyright (c) 2004 KIYOHARA Takashi * All rights reserved. @@ -45,45 +45,163 @@ #endif #if defined(__DragonFly__) || __FreeBSD_version < 500000 -#define dev2unit(x) ((minor(x) & 0xff) | (minor(x) >> 8)) -#define unit2minor(x) (((x) & 0xff) | (((x) << 8) & ~0xffff)) -#endif - -#ifdef __DragonFly__ -typedef d_thread_t fw_proc; -typedef d_thread_t fw_thread; -#include -#define M_DONTWAIT MB_DONTWAIT -#elif __FreeBSD_version >= 500000 -typedef struct thread fw_proc; -typedef struct thread fw_thread; -#include +#define fw_dev_t dev_t #else -typedef struct proc fw_thread; -typedef struct proc fw_proc; -#include +#define fw_dev_t struct cdev * #endif - #if defined(__DragonFly__) || __FreeBSD_version < 500000 -#define CALLOUT_INIT(x) callout_init(x) -#define DEV_T dev_t -#define FW_LOCK -#define FW_UNLOCK -#define THREAD_CREATE(f, sc, p, name, arg) \ - kthread_create(f, (void *)sc, p, name, arg) -#define THREAD_EXIT(x) kthread_exit() +#define fw_dev2unit(x) ((minor(x) & 0xff) | (minor(x) >> 8)) +#define fw_unit2minor(x) (((x) & 0xff) | (((x) << 8) & ~0xffff)) #else -#define CALLOUT_INIT(x) callout_init(x, 0 /* mpsafe */) -#define DEV_T struct cdev * -#define FW_LOCK mtx_lock(&Giant) -#define FW_UNLOCK mtx_unlock(&Giant) -#define THREAD_CREATE(f, sc, p, name, arg) \ - kthread_create(f, (void *)sc, p, 0, 0, name, arg) -#define THREAD_EXIT(x) kthread_exit(x) +#define fw_dev2unit(x) dev2unit(x) +#define fw_unit2minor(x) unit2minor(x) #endif -#define fw_kthread_create(func, arg) \ - func((arg)) + +#define fw_timevalcmp(tv1, tv2, op) timevalcmp((tv1), (tv2), op) +#define fw_timevalsub(tv1, tv2) timevalsub((tv1), (tv2)) + +#define fw_get_nameunit(dev) device_get_nameunit((dev)) +#define fw_get_unit(dev) device_get_unit((dev)) + +#define fw_printf(dev, fmt, ...) \ + device_printf((dev), (fmt), __VA_ARGS__); + +/* atomic macros */ +#define fw_atomic_set_int(P, V) atomic_set_int((P), (V)) +#define fw_atomic_readandclear_int(p) atomic_readandclear_int((p)) + +/* mutex macros */ +#include +typedef struct mtx fw_mtx_t; +#define fw_mtx_init(mutex, name, type, opts) \ + mtx_init(mutex, name, type, opts) +#define fw_mtx_lock(mutex) mtx_lock(mutex) +#define fw_mtx_unlock(mutex) mtx_unlock(mutex) +#define fw_mtx_destroy(mutex) mtx_destroy(mutex) +#define fw_mtx_assert(mutex, what) \ + mtx_assert(mutex, what) + +#define fw_msleep(ident, mtx, priority, wmesg, timo) \ + msleep(ident, mtx, priority, wmesg, timo); + +/* taskqueue macros */ +#include +typedef struct task fw_task_t; +#define FW_TASK_INIT(task, priority, func, context) \ + TASK_INIT((task), (priority), (func), (context)) +#define fw_taskqueue_enqueue(queue, task) \ + taskqueue_enqueue((queue), (task)) +#define fw_taskqueue_create_fast(name, mflags, enqueue, taskqueue) \ + taskqueue_create_fast((name), (mflags), (enqueue), (taskqueue)) +#define fw_taskqueue_start_threads(taskqueue, n, x, fmt, ...) \ + taskqueue_start_threads((taskqueue), (n), (x), (fmt), ...) + +/* kthread macros */ +#ifdef __DragonFly__ +typedef d_thread_t fw_thread_t; +typedef d_thread_t fw_proc_t; +#define fw_kthread_create(func, arg, newpp, fmt, ...) \ + kthread_create(func, arg, newpp, fmt, __VA_ARGS__) +#define fw_kthread_exit(x) kthread_exit() +#elif __FreeBSD_version >= 500000 +typedef struct thread fw_thread_t; +typedef struct thread fw_proc_t; +#define fw_kthread_create(func, arg, newpp, fmt, ...) \ + kthread_create(func, arg, newpp, 0, 0, fmt, __VA_ARGS__) +#define fw_kthread_exit(ecode) kthread_exit((ecode)) +#else +typedef struct proc fw_thread_t; +typedef struct proc fw_proc_t; +#define fw_kthread_create(func, arg, newpp, fmt, ...) \ + kproc_create(func, arg, newpp, fmt, __VA_ARGS__) +#define fw_kthread_exit(ecode) kproc_exit((ecode)) +#endif + +/* callout macros */ +#if defined(__DragonFly__) || __FreeBSD_version < 500000 +#define fw_callout_init(c) callout_init((c), 0) +#else +#define fw_callout_init(c) callout_init(c, 1 /* mpsafe */) +#endif +#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 */ +typedef bus_dma_tag_t fw_bus_dma_tag_t; +#if defined(__FreeBSD__) && __FreeBSD_version >= 501102 +#define fw_bus_dma_tag_create(t, \ + a, b, laddr, haddr, ffunc, farg, s, ns, mxss, f, lfunc, larg, tp)\ + bus_dma_tag_create((t), (a), (b), (laddr), (haddr), \ + (ffunc), (farg), (s), (ns), (mxss), (f), (lfunc), (larg), (tp)) +#else +#define fw_bus_dma_tag_create(t, a, b, \ + laddr, haddr, ffunc, farg, s, ns, mxss, f, lfunc, larg, tp) \ + bus_dma_tag_create((t), (a), (b), (laddr), (haddr), \ + (ffunc), (farg), (s), (ns), (mxss), (f), (tp)) +#endif +#define fw_bus_dma_tag_destroy(t) \ + bus_dma_tag_destroy((t)) +#define fw_bus_dmamap_create(t, f, mp) \ + bus_dmamap_create((t), 0, (mp)) +#define fw_bus_dmamap_destroy((t), (m)) \ + bus_dmamap_destroy((t), (m)) +#define fw_bus_dmamap_load(t, m, b, l, func, a, f) \ + bus_dmamap_load((t), (m), (b), (l), (func), (a), 0) +#define fw_bus_dmamap_load_mbuf(t, m, b, func, a, f) \ + bus_dmamap_load((t), (m), (b), (func), (a), 0) +#define fw_bus_dmamap_unload(t, m) \ + bus_dmamap_unload((t), (m)) +#if __FreeBSD_version < 500000 +#define fw_bus_dmamap_sync(t, m, op) \ + do { \ + switch ((op)) { \ + (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE): \ + bus_dmamap_sync((t), (m), BUS_DMASYNC_PREWRITE);\ + bus_dmamap_sync((t), (m), BUS_DMASYNC_PREREAD); \ + break; \ + (BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE): \ + /* BUS_DMASYNC_POSTWRITE is probably a no-op. */\ + bus_dmamap_sync((t), (m), BUS_DMASYNC_POSTREAD);\ + break; \ + default: \ + bus_dmamap_sync((t), (m), (op)); \ + } \ + } while (/*CONSTCOND*/0) +#else +#define fw_bus_dmamap_sync(t, m, op) \ + bus_dmamap_sync((t), (m), (op)) +#endif +#define fw_bus_dmamem_alloc(t, vp, f, mp) \ + bus_dmamem_alloc((t), (vp), (f), (mp)) +#define fw_bus_dmamem_free(t, v, m) \ + bus_dmamem_free((t), (v), (m)) + + +#define fw_config_pending_incr() +#define fw_config_pending_decr() + +#define splfw() splimp() +#define splfwnet() splimp() +#define splfwsbp() splcam() + +#ifdef __DragonFly__ +#include +#elif __FreeBSD_version >= 500000 +#include +#else +#include +#endif + +#define FW_KASSERT(expression, str) \ + KASSERT(expression, str) + + +#ifdef __DragonFly__ +#define M_DONTWAIT MB_DONTWAIT +#endif + /* * fw attach macro for FreeBSD @@ -108,20 +226,12 @@ typedef struct proc fw_proc; struct __CONCAT(dname,_softc) *sc = \ ((struct __CONCAT(dname,_softc) *)device_get_softc(dev)) -/* - * fw intr macro for FreeBSD - */ -#define FW_INTR(fwohci) \ - void \ - fwohci_intr(void *arg) -#define FW_INTR_RETURN(r) return - /* * fw open macro for FreeBSD */ #define FW_OPEN(dname) \ int \ - __CONCAT(dname,_open)(DEV_T dev, int flags, int fmt, fw_proc *td) + __CONCAT(dname,_open)(fw_dev_t dev, int flags, int fmt, fw_proc_t td) #define FW_OPEN_START \ int unit = DEV2UNIT(dev); \ __attribute__((__unused__))struct firewire_softc *sc = \ @@ -132,8 +242,8 @@ typedef struct proc fw_proc; */ #define FW_CLOSE(dname) \ int \ - __CONCAT(dname,_close)(DEV_T dev, int flags, \ - int fmt, fw_proc *td) + __CONCAT(dname,_close)(fw_dev_t dev, int flags, \ + int fmt, fw_proc_t td) #define FW_CLOSE_START /* @@ -141,7 +251,7 @@ typedef struct proc fw_proc; */ #define FW_READ(dname) \ int \ - __CONCAT(dname,_read)(DEV_T dev, struct uio *uio, int ioflag) + __CONCAT(dname,_read)(fw_dev_t dev, struct uio *uio, int ioflag) #define FW_READ_START /* @@ -149,7 +259,7 @@ typedef struct proc fw_proc; */ #define FW_WRITE(dname) \ int \ - __CONCAT(dname,_write)(DEV_T dev, struct uio *uio, int ioflag) + __CONCAT(dname,_write)(fw_dev_t dev, struct uio *uio, int ioflag) #define FW_WRITE_START /* @@ -158,19 +268,18 @@ typedef struct proc fw_proc; #define FW_IOCTL(dname) \ int \ __CONCAT(dname,_ioctl) \ - (DEV_T dev, u_long cmd, void *data, int flag, fw_proc *td) + (fw_dev_t dev, u_long cmd, void *data, int flag, fw_proc_t td) #define FW_IOCTL_START \ int unit = DEV2UNIT(dev); \ __attribute__((__unused__))struct firewire_softc *sc = \ devclass_get_softc(firewire_devclass, unit) - /* * fw poll macro for FreeBSD */ #define FW_POLL(dname) \ int \ - __CONCAT(dname,_poll)(DEV_T dev, int events, fw_proc *td) + __CONCAT(dname,_poll)(fw_dev_t dev, int events, fw_proc_t td) #define FW_POLL_START /* @@ -179,12 +288,12 @@ typedef struct proc fw_proc; #if defined(__DragonFly__) || __FreeBSD_version < 500102 #define FW_MMAP(dname) \ int \ - __CONCAT(dname,_mmap)(DEV_T dev, vm_offset_t offset, int nproto) + __CONCAT(dname,_mmap)(fw_dev_t dev, vm_offset_t offset, int nproto) #else #define FW_MMAP(dname) \ int \ __CONCAT(dname,_mmap) \ - (DEV_T dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto) + (fw_dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto) #endif #define FW_MMAP_START @@ -192,7 +301,7 @@ typedef struct proc fw_proc; * fw strategy macro for FreeBSD */ #define FW_STRATEGY_START \ - DEV_T dev = bp->bio_dev; \ + fw_dev_t dev = bp->bio_dev; \ int unit = DEV2UNIT(dev); \ __attribute__((__unused__))struct firewire_softc *sc = \ devclass_get_softc(firewire_devclass, unit) @@ -200,14 +309,12 @@ typedef struct proc fw_proc; /* * if macro for FreeBSD */ -#define IF_STOP(dname) \ - static void \ - __CONCAT(dname,_stop)(struct __CONCAT(dname,_softc) *fwip) -#define IF_STOP_START(dname, ifp, sc) \ - struct ifnet *ifp = (sc)->fw_softc.fwip_ifp; #define IF_DETACH_START(dname, sc) \ struct __CONCAT(dname,_softc) *sc = \ (struct __CONCAT(dname,_softc) *)device_get_softc(dev) +#define IF_IOCTL_START(dname, sc) \ + struct __CONCAT(dname,_softc) *sc = \ + ((struct fwip_eth_softc *)ifp->if_softc)->fwip #define IF_INIT(dname) \ static void \ __CONCAT(dname,_init)(void *arg) @@ -216,24 +323,21 @@ typedef struct proc fw_proc; ((struct fwip_eth_softc *)arg)->fwip; \ struct ifnet *ifp = (sc)->fw_softc.fwip_ifp #define IF_INIT_RETURN(r) return -#define IF_IOCTL_START(dname, sc) \ - struct __CONCAT(dname,_softc) *sc = \ - ((struct fwip_eth_softc *)ifp->if_softc)->fwip +#define IF_STOP(dname) \ + static void \ + __CONCAT(dname,_stop)(struct __CONCAT(dname,_softc) *fwip) +#define IF_STOP_START(dname, ifp, sc) \ + struct ifnet *ifp = (sc)->fw_softc.fwip_ifp; /* * fwohci macro for FreeBSD */ -#define FWOHCI_INIT_END #define FWOHCI_DETACH() \ int \ fwohci_detach(struct fwohci_softc *sc, device_t dev) #define FWOHCI_DETACH_START #define FWOHCI_DETACH_END -#define FWOHCI_STOP() \ - int \ - fwohci_stop(struct fwohci_softc *sc, device_t dev) -#define FWOHCI_STOP_START -#define FWOHCI_STOP_RETURN(r) return (r) +#define FWOHCI_INIT_END /* * firewire macro for FreeBSD @@ -304,6 +408,7 @@ typedef struct proc fw_proc; do { \ sbp->sim = cam_sim_alloc(sbp_action, sbp_poll, "sbp", sbp, \ device_get_unit(dev), \ + &sbp->mtx, \ /*untagged*/ 1, \ /*tagged*/ SBP_QUEUE_LEN - 1, \ devq); \ @@ -313,6 +418,7 @@ typedef struct proc fw_proc; return ENXIO; \ } \ \ + SBP_LOCK(sbp); \ if (xpt_bus_register(sbp->sim, /*bus*/0) != CAM_SUCCESS) \ goto fail; \ \ @@ -323,6 +429,7 @@ typedef struct proc fw_proc; goto fail; \ } \ xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL); \ + SBP_UNLOCK(sbp); \ } while (/*CONSTCOND*/0) #define SBP_DEVICE(d) ((d)->path) #define SBP_DEVICE_FREEZE(d, x) xpt_freeze_devq((d)->path, (x)) @@ -389,14 +496,14 @@ typedef struct proc fw_proc; return fwmem_close(dev, flags, fmt, td) #define FWDEV_READ_START \ if (DEV_FWMEM(dev)) \ - return physio(dev, uio, ioflag) + return (physio(dev, uio, ioflag)) #define FWDEV_WRITE_START \ if (DEV_FWMEM(dev)) \ - return physio(dev, uio, ioflag) + return (physio(dev, uio, ioflag)) #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_IOCTL_REDIRECT fc->ioctl(dev, cmd, data, flag, td) #define FWDEV_POLL_START \ if (DEV_FWMEM(dev)) \ return fwmem_poll(dev, events, td) @@ -476,66 +583,6 @@ typedef struct scsi_inquiry_data sbp_scsi_inquiry_data; (((ms) + 0u) / 1000u) * hz : \ (((ms) + 0u) * hz) / 1000u) -#define config_pending_incr() -#define config_pending_decr() - -/* - * bus_dma macros for FreeBSD - */ -typedef bus_dma_tag_t fw_bus_dma_tag_t; - -#if defined(__FreeBSD__) && __FreeBSD_version >= 501102 -#define fw_bus_dma_tag_create(t, \ - a, b, laddr, haddr, ffunc, farg, s, ns, mxss, f, lfunc, larg, tp)\ - bus_dma_tag_create((t), (a), (b), (laddr), (haddr), \ - (ffunc), (farg), (s), (ns), (mxss), (f), (lfunc), (larg), (tp)) -#else -#define fw_bus_dma_tag_create(t, a, b, \ - laddr, haddr, ffunc, farg, s, ns, mxss, f, lfunc, larg, tp) \ - bus_dma_tag_create((t), (a), (b), (laddr), (haddr), \ - (ffunc), (farg), (s), (ns), (mxss), (f), (tp)) -#endif -#define fw_bus_dma_tag_destroy(t) \ - bus_dma_tag_destroy((t)) -#define fw_bus_dmamap_create(t, f, mp) \ - bus_dmamap_create((t), 0, (mp)) -#define fw_bus_dmamap_destroy((t), (m)) \ - bus_dmamap_destroy((t), (m)) -#define fw_bus_dmamap_load(t, m, b, l, func, a, f) \ - bus_dmamap_load((t), (m), (b), (l), (func), (a), 0) -#define fw_bus_dmamap_load_mbuf(t, m, b, func, a, f) \ - bus_dmamap_load((t), (m), (b), (func), (a), 0) -#define fw_bus_dmamap_unload(t, m) \ - bus_dmamap_unload((t), (m)) -#if __FreeBSD_version < 500000 -#define fw_bus_dmamap_sync(t, m, op) \ - do { \ - switch ((op)) { \ - (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE): \ - bus_dmamap_sync((t), (m), BUS_DMASYNC_PREWRITE);\ - bus_dmamap_sync((t), (m), BUS_DMASYNC_PREREAD); \ - break; \ - (BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE): \ - /* BUS_DMASYNC_POSTWRITE is probably a no-op. */\ - bus_dmamap_sync((t), (m), BUS_DMASYNC_POSTREAD);\ - break; \ - default: \ - bus_dmamap_sync((t), (m), (op)); \ - } \ - } while (/*CONSTCOND*/0) -#else -#define fw_bus_dmamap_sync(t, m, op) \ - bus_dmamap_sync((t), (m), (op)) -#endif -#define fw_bus_dmamem_alloc(t, vp, f, mp) \ - bus_dmamem_alloc((t), (vp), (f), (mp)) -#define fw_bus_dmamem_free(t, v, m) \ - bus_dmamem_free((t), (v), (m)) - -#define splfw() splimp() -#define splfwnet() splimp() -#define splfwsbp() splcam() - #elif defined(__NetBSD__) #define OS_STR "NetBSD" @@ -543,46 +590,246 @@ typedef bus_dma_tag_t fw_bus_dma_tag_t; #define OS_VER_STR "NetBSD-2" #define PROJECT_STR "NetBSD Project" -#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 GIANT_REQUIRED -#define IFF_NEEDSGIANT 0 - -#define MTAG_FIREWIRE 1394 -#define MTAG_FIREWIRE_HWADDR 0 -#define MTAG_FIREWIRE_SENDER_EUID 1 - -#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF - -#define DFLTPHYS (64 * 1024) /* fake */ - -#define dev2unit minor -#define unit2minor(x) (((x) & 0xff) | (((x) << 12) & ~0xfffff)) /* XXX */ - -typedef struct lwp fw_proc; -typedef struct proc fw_thread; -#include - -#define CALLOUT_INIT(x) callout_init(x, 0) -#define DEV_T dev_t -#define FW_LOCK -#define FW_UNLOCK -#define THREAD_CREATE(f, sc, p, name, arg) \ - kthread_create(PRI_NONE, 0, NULL, f, (void *)sc, p, name, arg) -#define THREAD_EXIT(x) kthread_exit(x) -#define fw_kthread_create(func, arg) (*(func))(arg) +#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) (dev)->dv_xname +#define fw_get_unit(dev) device_unit((dev)) + +#define fw_printf(dev, fmt, ...) \ + do { \ + printf("%s: ", (dev)->dv_xname);\ + printf((fmt), ##__VA_ARGS__); \ + } while (/*CONSTCOND*/0) + +/* 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 +#include +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 + +#define FW_KASSERT(expression, str) \ + KASSERT(expression) /* * fw attach macro for NetBSD @@ -608,21 +855,13 @@ struct fwbus_attach_args { struct __CONCAT(dname,_softc) *sc = \ (struct __CONCAT(dname,_softc) *)self -/* - * fw intr macro for NetBSD - */ -#define FW_INTR(fwohci) \ - int \ - fwohci_intr(void *arg) -#define FW_INTR_RETURN(r) return (r) - /* * fw open macro for NetBSD */ #define FW_OPEN(dname) \ int \ __CONCAT(dname,_open)(dev_t _dev, int flags, int fmt, \ - fw_proc *td) + fw_proc_t td) #define FW_OPEN_START \ struct firewire_softc *sc, *dev; \ \ @@ -636,7 +875,7 @@ struct fwbus_attach_args { #define FW_CLOSE(dname) \ int \ __CONCAT(dname,_close)(dev_t _dev, int flags, \ - int fmt, fw_proc *td) + int fmt, fw_proc_t td) #define FW_CLOSE_START \ int unit = DEV2UNIT(_dev); \ struct firewire_softc *dev = device_lookup(&ieee1394if_cd, unit); \ @@ -679,7 +918,7 @@ struct fwbus_attach_args { int \ __CONCAT(dname,_ioctl) \ (dev_t _dev, u_long cmd, void *data, \ - int flag, fw_proc *td) + int flag, fw_proc_t td) #define FW_IOCTL_START \ int unit = DEV2UNIT(_dev); \ struct firewire_softc *sc, *dev; \ @@ -694,7 +933,7 @@ struct fwbus_attach_args { #define FW_POLL(dname) \ int \ __CONCAT(dname,_poll)(dev_t _dev, int events, \ - fw_proc *td) + fw_proc_t td) #define FW_POLL_START \ int unit = DEV2UNIT(_dev); \ struct firewire_softc *dev; \ @@ -733,15 +972,12 @@ struct fwbus_attach_args { /* * if macro for NetBSD */ -#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 #define IF_DETACH_START(dname, sc) \ struct __CONCAT(dname,_softc) *sc = \ (struct __CONCAT(dname,_softc) *)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) @@ -749,38 +985,29 @@ struct fwbus_attach_args { struct __CONCAT(dname,_softc) *sc = \ ((struct fwip_eth_softc *)(ifp)->if_softc)->fwip #define IF_INIT_RETURN(r) return (r) -#define IF_IOCTL_START(dname, sc) \ +#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 + ((struct fwip_eth_softc *)(ifp)->if_softc)->fwip /* * fwohci macro for NetBSD */ -#define FWOHCI_INIT_END \ - do { \ - struct fwbus_attach_args faa; \ - faa.name = "ieee1394if"; \ - sc->sc_shutdownhook = shutdownhook_establish(fwohci_stop, sc);\ - sc->sc_powerhook = powerhook_establish(sc->fc._dev.dv_xname, \ - fwohci_power, sc); \ - sc->fc.bdev = config_found(sc->fc.dev, &faa, fwohci_print); \ - } while (/*CONSTCOND*/0) #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 \ - if (sc->sc_powerhook != NULL) \ - powerhook_disestablish(sc->sc_powerhook); \ - if (sc->sc_shutdownhook != NULL) \ - shutdownhook_disestablish(sc->sc_shutdownhook) -#define FWOHCI_STOP() \ - void \ - fwohci_stop(void *arg) -#define FWOHCI_STOP_START struct fwohci_softc *sc = arg -#define FWOHCI_STOP_RETURN(r) return +#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 @@ -940,7 +1167,7 @@ struct fwbus_attach_args { if ((sbp->sc_bus = \ config_found(sbp->fd.dev, sc_channel, scsiprint)) == \ NULL) { \ - device_printf(sbp->fd.dev, "attach failed\n"); \ + fw_printf(sbp->fd.dev, "attach failed\n"); \ return; \ } \ } while (/*CONSTCOND*/0) @@ -955,9 +1182,20 @@ struct fwbus_attach_args { } 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() \ - if (!sbp->lwp) \ - fw_kthread_create0(sbp) +#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 @@ -1018,7 +1256,7 @@ struct fwbus_attach_args { #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_IOCTL_REDIRECT fc->ioctl(_dev, cmd, data, flag, td) #define FWDEV_POLL_START \ if (DEV_FWMEM(_dev)) \ return fwmem_poll(_dev, events, td) @@ -1085,213 +1323,66 @@ typedef struct scsipi_inquiry_data sbp_scsi_inquiry_data; #define CAM_DATA_PHYS (0) /* XXX */ #define XPT_SCSI_IO (1) /* XXX */ - -#define splfw() splvm() -#define splfwnet() splnet() -#define splfwsbp() splbio() -#define splsoftvm() splbio() - #ifndef rounddown #define rounddown(x, y) ((x) / (y) * (y)) #endif -#define timevalcmp(tv1, tv2, op) timercmp((tv1), (tv2), op) -#define timevalsub(tv1, tv2) timersub((tv1), (tv2), (tv1)) - -#define device_get_nameunit(dev) (dev)->dv_xname -#define device_get_unit(dev) device_unit((dev)) /* - * queue macros for NetBSD + * additional queue macros for NetBSD */ #define STAILQ_LAST(head, type, field) \ (STAILQ_EMPTY((head)) ? NULL : \ (struct type *) \ ((char *)(head)->stqh_last - (size_t)&((struct type *)0)->field)) - -#define TASK_INIT(task, priority, func, context) - - -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 STAILQ_FOREACH_SAFE(var, head, field, _var) \ + (void)(_var); \ + STAILQ_FOREACH(var, head, field) /* - * mbuf macros for NetBSD + * additional mbuf macros for NetBSD */ #include #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)) -/* - * bus_dma macros for NetBSD - */ -#include -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 device_printf(dev, fmt, ...) \ - do { \ - aprint_normal("%s: ", (dev)->dv_xname); \ - aprint_normal((fmt) ,##__VA_ARGS__); \ - } while (/*CONSTCOND*/0) +/* 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) -/* - * XXXXXXXXXXX - */ -#define atomic_set_int(P, V) (*(u_int*)(P) |= (V)) +#define FILTER_STRAY 0 +#define FILTER_HANDLED 1 -#define bpf_peers_present(if_bpf) (if_bpf) +#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 #endif diff --git a/sys/dev/ieee1394/fwdev.c b/sys/dev/ieee1394/fwdev.c index 24f51fba82e6..fbb2fdb4de3f 100644 --- a/sys/dev/ieee1394/fwdev.c +++ b/sys/dev/ieee1394/fwdev.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwdev.c,v 1.12 2007/10/19 12:00:13 ad Exp $ */ +/* $NetBSD: fwdev.c,v 1.13 2007/11/05 19:08:56 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -32,7 +32,7 @@ * 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/fwdev.c,v 1.49 2007/03/16 05:39:33 simokawa Exp $ + * $FreeBSD: src/sys/dev/firewire/fwdev.c,v 1.52 2007/06/06 14:31:36 simokawa Exp $ * */ @@ -124,7 +124,7 @@ struct cdevsw firewire_cdevsw = { .d_mmap = fw_mmap, .d_strategy = fw_strategy, .d_name = "fw", - .d_flags = D_MEM | D_NEEDGIANT + .d_flags = D_MEM #else #define CDEV_MAJOR 127 fw_open, fw_close, fw_read, fw_write, fw_ioctl, @@ -233,8 +233,18 @@ FW_OPEN(fw) FWDEV_OPEN_START; - if (dev->si_drv1 != NULL) + FW_GLOCK(sc->fc); + if (dev->si_drv1 != NULL) { + FW_GUNLOCK(sc->fc); 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); #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 if ((dev->si_flags & SI_NAMED) == 0) { @@ -247,10 +257,6 @@ FW_OPEN(fw) } #endif - dev->si_drv1 = malloc(sizeof(struct fw_drv1), M_FW, M_WAITOK | M_ZERO); - if (dev->si_drv1 == NULL) - return (ENOMEM); - d = (struct fw_drv1 *)dev->si_drv1; d->fc = sc->fc; STAILQ_INIT(&d->binds); @@ -336,14 +342,18 @@ fw_read_async(struct fw_drv1 *d, struct uio *uio, int ioflag) struct fw_pkt *fp; const struct tcode_info *tinfo; + FW_GLOCK(d->fc); while ((xfer = STAILQ_FIRST(&d->rq)) == NULL && err == 0) - err = tsleep(&d->rq, FWPRI, "fwra", 0); + err = fw_msleep(&d->rq, FW_GMTX(d->fc), FWPRI, "fwra", 0); - if (err != 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 ?? */ @@ -361,7 +371,9 @@ out: 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); } @@ -389,6 +401,7 @@ FW_READ(fw) if (ir->buf == NULL) return (EIO); + FW_GLOCK(fc); readloop: if (ir->stproc == NULL) { /* iso bulkxfer */ @@ -405,15 +418,17 @@ readloop: if (slept == 0) { slept = 1; ir->flag |= FWXFERQ_WAKEUP; - err = tsleep(ir, FWPRI, "fw_read", hz); + err = fw_msleep(ir, FW_GMTX(fc), FWPRI, "fw_read", hz); ir->flag &= ~FWXFERQ_WAKEUP; if (err == 0) goto readloop; } else if (slept == 1) err = EIO; + FW_GUNLOCK(fc); return err; } 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) @@ -434,6 +449,7 @@ readloop: } if (uio->uio_resid >= ir->psize) { slept = -1; + FW_GLOCK(fc); goto readloop; } } @@ -470,13 +486,13 @@ fw_write_async(struct fw_drv1 *d, struct uio *uio, int ioflag) xfer->fc = d->fc; xfer->sc = NULL; - xfer->hand = fw_asy_callback; + xfer->hand = fw_xferwake; xfer->send.spd = 2 /* XXX */; if ((err = fw_asyreq(xfer->fc, -1, xfer))) goto out; - if ((err = tsleep(xfer, FWPRI, "fwwa", 0))) + if ((err = fw_xferwait(xfer))) goto out; if (xfer->resp != 0) { @@ -484,8 +500,10 @@ fw_write_async(struct fw_drv1 *d, struct uio *uio, int ioflag) goto out; } - if (xfer->state == FWXF_RCVD) { + if (xfer->flag == FWXF_RCVD) { + FW_GLOCK(xfer->fc); STAILQ_INSERT_TAIL(&d->rq, xfer, link); + FW_GUNLOCK(xfer->fc); return (0); } @@ -514,6 +532,8 @@ FW_WRITE(fw) if (it->buf == NULL) return (EIO); + + FW_GLOCK(fc); isoloop: if (it->stproc == NULL) { it->stproc = STAILQ_FIRST(&it->stfree); @@ -524,18 +544,21 @@ isoloop: it->queued = 0; } else if (slept == 0) { slept = 1; +#if 0 /* XXX to avoid lock recursion */ err = fc->itx_enable(fc, it->dmach); if (err) - return err; - err = tsleep(it, FWPRI, "fw_write", hz); + goto out; +#endif + err = fw_msleep(it, FW_GMTX(fc), FWPRI, "fw_write", hz); if (err) - return err; + goto out; goto isoloop; } else { err = EIO; - return err; + goto out; } } + FW_GUNLOCK(fc); fp = (struct fw_pkt *)fwdma_v_addr(it->buf, it->stproc->poffset + it->queued); err = uiomove((void *)fp, sizeof(struct fw_isohdr), uio); @@ -551,9 +574,14 @@ isoloop: } if (uio->uio_resid >= sizeof(struct fw_isohdr)) { slept = 0; + FW_GLOCK(fc); goto isoloop; } return err; + +out: + FW_GUNLOCK(fc); + return err; } static void @@ -564,7 +592,9 @@ fw_hand(struct fw_xfer *xfer) 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); } @@ -605,19 +635,17 @@ FW_IOCTL(fw) switch (cmd) { case FW_STSTREAM: if (it == NULL) { - for (i = 0; i < fc->nisodma; i ++) { - it = fc->it[i]; - if ((it->flag & FWXFERQ_OPEN) == 0) - break; - } - if (i >= fc->nisodma) { + i = fw_open_isodma(fc, /* tx */1); + if (i < 0) { err = EBUSY; break; } + it = fc->it[i]; err = fwdev_allocbuf(fc, it, &d->bufreq.tx); - if (err) + if (err) { + it->flag &= ~FWXFERQ_OPEN; break; - it->flag |= FWXFERQ_OPEN; + } } it->flag &= ~0xff; it->flag |= (0x3f & ichreq->ch); @@ -633,19 +661,17 @@ FW_IOCTL(fw) break; case FW_SRSTREAM: if (ir == NULL) { - for (i = 0; i < fc->nisodma; i ++) { - ir = fc->ir[i]; - if ((ir->flag & FWXFERQ_OPEN) == 0) - break; - } - if (i >= fc->nisodma) { + i = fw_open_isodma(fc, /* tx */0); + if (i < 0) { err = EBUSY; break; } + ir = fc->ir[i]; err = fwdev_allocbuf(fc, ir, &d->bufreq.rx); - if (err) + if (err) { + ir->flag &= ~FWXFERQ_OPEN; break; - ir->flag |= FWXFERQ_OPEN; + } } ir->flag &= ~0xff; ir->flag |= (0x3f & ichreq->ch); @@ -699,8 +725,7 @@ FW_IOCTL(fw) fwdev = fw_noderesolve_eui64(fc, &asyreq->req.dst.eui); if (fwdev == NULL) { - device_printf(fc->bdev, - "cannot find node\n"); + fw_printf(fc->bdev, "cannot find node\n"); err = EINVAL; goto out; } @@ -719,11 +744,11 @@ FW_IOCTL(fw) bcopy((char *)fp + tinfo->hdr_len, (void *)xfer->send.payload, pay_len); xfer->send.spd = asyreq->req.sped; - xfer->hand = fw_asy_callback; + xfer->hand = fw_xferwake; if ((err = fw_asyreq(fc, -1, xfer)) != 0) goto out; - if ((err = tsleep(xfer, FWPRI, "asyreq", hz)) != 0) + if ((err = fw_xferwait(xfer)) != 0) goto out; if (xfer->resp != 0) { err = EIO; @@ -777,7 +802,7 @@ out: err = EINVAL; break; } - fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT); + fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_WAITOK); if(fwb == NULL){ err = ENOMEM; break; @@ -918,15 +943,15 @@ fwdev_makedev(struct firewire_softc *sc) #if defined(__DragonFly__) int unit; - unit = device_get_unit(sc->fc->bdev); + 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 - DEV_T d; + fw_dev_t d; int unit; - unit = device_get_unit(sc->fc->bdev); + 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); @@ -950,7 +975,7 @@ fwdev_destroydev(struct firewire_softc *sc) #if defined(__DragonFly__) int unit; - unit = device_get_unit(sc->fc->bdev); + unit = fw_get_unit(sc->fc->bdev); cdevsw_remove(&firewire_cdevsw, FW_UNITMASK, FW_UNIT(unit)); #elif __FreeBSD_version < 500000 cdevsw_remove(&firewire_cdevsw); diff --git a/sys/dev/ieee1394/fwdma.c b/sys/dev/ieee1394/fwdma.c index d4bb8db5d5e6..b53c42c74f25 100644 --- a/sys/dev/ieee1394/fwdma.c +++ b/sys/dev/ieee1394/fwdma.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwdma.c,v 1.9 2007/10/19 12:00:13 ad Exp $ */ +/* $NetBSD: fwdma.c,v 1.10 2007/11/05 19:08:56 kiyohara Exp $ */ /*- * Copyright (c) 2003 * Hidetoshi Shimokawa. All rights reserved. @@ -36,7 +36,7 @@ #include #ifdef __FBSDID -__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/fwdma.c,v 1.7 2005/01/06 01:42:41 imp Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/firewire/fwdma.c,v 1.9 2007/06/06 14:31:36 simokawa Exp $"); #endif #if defined(__FreeBSD__) @@ -111,7 +111,7 @@ fwdma_malloc(struct firewire_comm *fc, int alignment, bus_size_t size, /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, /*flags*/ BUS_DMA_ALLOCNOW, /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, + /*lockarg*/FW_GMTX(fc), &dma->fw_dma_tag); if (err) { printf("fwdma_malloc: failed(1)\n"); @@ -219,7 +219,7 @@ fwdma_malloc_multiseg(struct firewire_comm *fc, int alignment, /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, /*flags*/ BUS_DMA_ALLOCNOW, /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, + /*lockarg*/FW_GMTX(fc), &am->fw_dma_tag)) { printf("fwdma_malloc_multiseg: tag_create failed\n"); free(am, M_FW); diff --git a/sys/dev/ieee1394/fwmem.c b/sys/dev/ieee1394/fwmem.c index aa4283ba40d8..410e568d32d9 100644 --- a/sys/dev/ieee1394/fwmem.c +++ b/sys/dev/ieee1394/fwmem.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwmem.c,v 1.6 2007/10/19 12:00:13 ad Exp $ */ +/* $NetBSD: fwmem.c,v 1.7 2007/11/05 19:08:56 kiyohara Exp $ */ /*- * Copyright (c) 2002-2003 * Hidetoshi Shimokawa. All rights reserved. @@ -36,7 +36,7 @@ #include #ifdef __FBSDID -__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/fwmem.c,v 1.32 2007/03/16 05:11:42 simokawa Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/firewire/fwmem.c,v 1.34 2007/06/06 14:31:36 simokawa Exp $"); #endif #if defined(__FreeBSD__) @@ -209,6 +209,7 @@ MALLOC_DEFINE(M_FWMEM, "fwmem", "fwmem/IEEE1394"); struct fwmem_softc { struct fw_eui64 eui; + struct firewire_softc *sc; int refcount; STAILQ_HEAD(, fw_xfer) xferlist; }; @@ -399,18 +400,24 @@ FW_OPEN(fwmem) FW_OPEN_START; if (dev->si_drv1 != NULL) { - if ((flags & FWRITE) != 0) + if ((flags & FWRITE) != 0) { + FW_GUNLOCK(sc->fc); return (EBUSY); + } + FW_GUNLOCK(sc->fc); fms = (struct fwmem_softc *)dev->si_drv1; fms->refcount ++; } else { - fms = (struct fwmem_softc *)malloc(sizeof(struct fwmem_softc), - M_FWMEM, M_WAITOK); - if (fms == NULL) + 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; - bcopy(&fwmem_eui64, &fms->eui, sizeof(struct fw_eui64)); - dev->si_drv1 = (void *)fms; dev->si_iosize_max = DFLTPHYS; + fms = (struct fwmem_softc *)dev->si_drv1; + bcopy(&fwmem_eui64, &fms->eui, sizeof(struct fw_eui64)); + fms->sc = sc; fms->refcount = 1; STAILQ_INIT(&fms->xferlist); xfer = fw_xfer_alloc(M_FWMEM); @@ -429,7 +436,10 @@ FW_CLOSE(fwmem) FW_CLOSE_START; fms = (struct fwmem_softc *)dev->si_drv1; + + 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) { @@ -473,7 +483,7 @@ fwmem_strategy(struct bio *bp) struct fwmem_softc *fms; struct fw_device *fwdev; struct fw_xfer *xfer; - int err=0, s, iolen; + int err = 0, s, iolen; CTR0(KTR_DEV, "strategy"); @@ -481,7 +491,7 @@ fwmem_strategy(struct bio *bp) s = splfw(); fms = (struct fwmem_softc *)dev->si_drv1; - fwdev = fw_noderesolve_eui64(sc->fc, &fms->eui); + fwdev = fw_noderesolve_eui64(fms->sc->fc, &fms->eui); if (fwdev == NULL) { if (fwmem_debug) printf("fwmem: no such device ID:%08x%08x\n", diff --git a/sys/dev/ieee1394/fwohci.c b/sys/dev/ieee1394/fwohci.c index 1b186f7b10df..95cec4faac40 100644 --- a/sys/dev/ieee1394/fwohci.c +++ b/sys/dev/ieee1394/fwohci.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwohci.c,v 1.109 2007/10/19 12:00:13 ad Exp $ */ +/* $NetBSD: fwohci.c,v 1.110 2007/11/05 19:08:56 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa @@ -33,7 +33,7 @@ * 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/fwohci.c,v 1.86 2007/03/19 03:35:45 simokawa Exp $ + * $FreeBSD: src/sys/dev/firewire/fwohci.c,v 1.93 2007/06/08 09:04:30 simokawa Exp $ * */ @@ -55,10 +55,18 @@ #include #include #include -#include +#include +<<<<<<< fwohci.c +#include +======= #include -__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.109 2007/10/19 12:00:13 ad Exp $"); +<<<<<<< fwohci.c +__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.110 2007/11/05 19:08:56 kiyohara Exp $"); +>>>>>>> 1.108 +======= +__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.110 2007/11/05 19:08:56 kiyohara Exp $"); +>>>>>>> 1.109 #if defined(__DragonFly__) || __FreeBSD_version < 500000 #include /* for DELAY() */ @@ -110,10 +118,14 @@ __KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.109 2007/10/19 12:00:13 ad Exp $"); #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.* @@ -122,7 +134,7 @@ SYSCTL_INT(_hw_firewire, OID_AUTO, nocyclemaster, CTLFLAG_RW, &nocyclemaster, 0, */ SYSCTL_SETUP(sysctl_fwohci, "sysctl fwohci(4) subtree setup") { - int rc; + int rc, fwohci_node_num; const struct sysctlnode *node; if ((rc = sysctl_createv(clog, 0, NULL, NULL, @@ -137,13 +149,23 @@ SYSCTL_SETUP(sysctl_fwohci, "sysctl fwohci(4) subtree setup") NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) { goto err; } + fwohci_node_num = node->sysctl_num; /* fwohci no cyclemaster flag */ if ((rc = sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "nocyclemaster", SYSCTL_DESCR("Do not send cycle start packets"), NULL, 0, &nocyclemaster, - 0, CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) != 0) { + 0, CTL_HW, fwohci_node_num, CTL_CREATE, CTL_EOL)) != 0) { + goto err; + } + + /* fwohci physical request DMA enable */ + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "phydma_enable", + SYSCTL_DESCR("Allow physical request DMA from firewire"), + NULL, 0, &firewire_phydma_enable, + 0, CTL_HW, fwohci_node_num, CTL_CREATE, CTL_EOL)) != 0) { goto err; } return; @@ -162,7 +184,7 @@ static const char * const dbkey[8] = {"ST0", "ST1","ST2","ST3", 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", - "underrun","overrun","desc err", "data read 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", @@ -175,23 +197,23 @@ extern const char *fw_linkspeed[]; static uint32_t const tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31}; static const struct tcode_info tinfo[] = { -/* hdr_len block flag*/ -/* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL}, -/* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY}, -/* 2 WRES */ {12, FWTI_RES}, -/* 3 XXX */ { 0, 0}, -/* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL}, -/* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL}, -/* 6 RRESQ */ {16, FWTI_RES}, -/* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY}, -/* 8 CYCS */ { 0, 0}, -/* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY}, -/* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR}, -/* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY}, -/* c XXX */ { 0, 0}, -/* d XXX */ { 0, 0}, -/* e PHY */ {12, FWTI_REQ}, -/* f XXX */ { 0, 0} +/* 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 @@ -231,11 +253,10 @@ 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 *); -#if FWOHCI_TASKQUEUE -static void fwohci_complete(void *, int); -#endif +static void fwohci_task_busreset(void *, int); +static void fwohci_task_sid(void *, int); +static void fwohci_task_dma(void *, int); #if defined(__NetBSD__) -static void fwohci_power(int, void *); int fwohci_print(void *, const char *); #endif @@ -344,6 +365,7 @@ dev_type_ioctl(fwohci_ioctl); /* * 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) { @@ -380,7 +402,7 @@ fwohci_set_bus_manager(struct firewire_comm *fc, u_int node) if((bm & 0x3f) == 0x3f) bm = node; if (firewire_debug) - device_printf(sc->fc.dev, + fw_printf(sc->fc.dev, "fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i); return(bm); @@ -406,7 +428,7 @@ again: } if(i >= MAX_RETRY) { if (firewire_debug) - device_printf(sc->fc.dev, "phy read failed(1).\n"); + fw_printf(sc->fc.dev, "phy read failed(1).\n"); if (++retry < MAX_RETRY) { DELAY(100); goto again; @@ -417,14 +439,14 @@ again: if ((stat & OHCI_INT_REG_FAIL) != 0 || ((fun >> PHYDEV_REGADDR) & 0xf) != addr) { if (firewire_debug) - device_printf(sc->fc.dev, "phy read failed(2).\n"); + fw_printf(sc->fc.dev, "phy read failed(2).\n"); if (++retry < MAX_RETRY) { DELAY(100); goto again; } } if (firewire_debug || retry >= MAX_RETRY) - device_printf(sc->fc.dev, + fw_printf(sc->fc.dev, "fwphy_rddata: 0x%x loop=%d, retry=%d\n", addr, i, retry); #undef MAX_RETRY return((fun >> PHYDEV_RDDATA )& 0xff); @@ -515,12 +537,11 @@ fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) sc->fc.nport = reg & FW_PHY_NP; sc->fc.speed = reg & FW_PHY_SPD >> 6; if (sc->fc.speed > MAX_SPEED) { - device_printf(dev, "invalid speed %d (fixed to %d).\n", + fw_printf(dev, "invalid speed %d (fixed to %d).\n", sc->fc.speed, MAX_SPEED); sc->fc.speed = MAX_SPEED; } - device_printf(dev, - "Phy 1394 only %s, %d ports.\n", + fw_printf(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); @@ -528,12 +549,11 @@ fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) sc->fc.nport = reg & FW_PHY_NP; sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5; if (sc->fc.speed > MAX_SPEED) { - device_printf(dev, "invalid speed %d (fixed to %d).\n", + fw_printf(dev, "invalid speed %d (fixed to %d).\n", sc->fc.speed, MAX_SPEED); sc->fc.speed = MAX_SPEED; } - device_printf(dev, - "Phy 1394a available %s, %d ports.\n", + fw_printf(dev, "Phy 1394a available %s, %d ports.\n", fw_linkspeed[sc->fc.speed], sc->fc.nport); /* check programPhyEnable */ @@ -544,8 +564,7 @@ fwohci_probe_phy(struct fwohci_softc *sc, device_t dev) if (e1394a) { #endif if (firewire_debug) - device_printf(dev, - "Enable 1394a Enhancements\n"); + fw_printf(dev, "Enable 1394a Enhancements\n"); /* enable EAA EMC */ reg2 |= 0x03; /* set aPhyEnhanceEnable */ @@ -597,7 +616,7 @@ fwohci_reset(struct fwohci_softc *sc, device_t dev) /* FLUSH FIFO and reset Transmitter/Reciever */ OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); if (firewire_debug) - device_printf(dev, "resetting OHCI..."); + fw_printf(dev, "resetting OHCI..."); i = 0; while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) { if (i++ > 100) break; @@ -614,17 +633,17 @@ fwohci_reset(struct fwohci_softc *sc, device_t dev) reg2 = reg | OHCI_BUSFNC; max_rec = (reg & 0x0000f000) >> 12; speed = (reg & 0x00000007); - device_printf(dev, "Link %s, max_rec %d bytes.\n", + fw_printf(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); - device_printf(dev, "max_rec %d -> %d\n", + fw_printf(dev, "max_rec %d -> %d\n", MAXREC(max_rec), MAXREC(sc->fc.maxrec)); } if (firewire_debug) - device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2); + fw_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2); OWRITE(sc, OHCI_BUS_OPT, reg2); /* Initialize registers */ @@ -669,13 +688,14 @@ fwohci_reset(struct fwohci_softc *sc, device_t dev) /* Enable interrupts */ - OWRITE(sc, FWOHCI_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; + OWRITE(sc, FWOHCI_INTMASK, sc->intmask); fwohci_set_intr(&sc->fc, 1); - } int @@ -685,17 +705,13 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) uint32_t reg; uint8_t ui[8]; -#if FWOHCI_TASKQUEUE - TASK_INIT(&sc->fwohci_task_complete, 0, fwohci_complete, sc); -#endif - /* OHCI version */ reg = OREAD(sc, OHCI_VERSION); mver = (reg >> 16) & 0xff; - device_printf(dev, "OHCI version %x.%x (ROM=%d)\n", + fw_printf(dev, "OHCI version %x.%x (ROM=%d)\n", mver, reg & 0xff, (reg>>24) & 1); if (mver < 1 || mver > 9) { - device_printf(dev, "invalid OHCI version\n"); + fw_printf(dev, "invalid OHCI version\n"); return (ENXIO); } @@ -709,7 +725,7 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) if ((reg & (1 << i)) == 0) break; sc->fc.nisodma = i; - device_printf(dev, "No. of Isochronous channels is %d.\n", i); + fw_printf(dev, "No. of Isochronous channels is %d.\n", i); if (i == 0) return (ENXIO); @@ -763,7 +779,7 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) sc->fc.config_rom = fwdma_malloc(&sc->fc, CROMSIZE, CROMSIZE, &sc->crom_dma, BUS_DMA_WAITOK); if(sc->fc.config_rom == NULL){ - device_printf(dev, "config_rom alloc failed."); + fw_printf(dev, "config_rom alloc failed."); return ENOMEM; } @@ -779,13 +795,12 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) 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) { - device_printf(dev, "sid_buf alloc failed."); + fw_printf(dev, "sid_buf alloc failed."); return ENOMEM; } @@ -793,7 +808,7 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) &sc->dummy_dma, BUS_DMA_WAITOK); if (sc->dummy_dma.v_addr == NULL) { - device_printf(dev, "dummy_dma alloc failed."); + fw_printf(dev, "dummy_dma alloc failed."); return ENOMEM; } @@ -817,7 +832,7 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L); for( i = 0 ; i < 8 ; i ++) ui[i] = FW_EUI64_BYTE(&sc->fc.eui,i); - device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + 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; @@ -841,6 +856,15 @@ fwohci_init(struct fwohci_softc *sc, device_t dev) 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; @@ -942,6 +966,8 @@ fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch) const struct tcode_info *info; static int maxdesc=0; + FW_GLOCK_ASSERT(&sc->fc); + if(&sc->atrq == dbch){ off = OHCI_ATQOFF; }else if(&sc->atrs == dbch){ @@ -962,12 +988,14 @@ txloop: if(xfer == NULL){ goto kick; } +#if 0 if(dbch->xferq.queued == 0 ){ - device_printf(sc->fc.dev, "TX queue empty\n"); + fw_printf(sc->fc.dev, "TX queue empty\n"); } +#endif STAILQ_REMOVE_HEAD(&dbch->xferq.q, link); db_tr->xfer = xfer; - xfer->state = FWXF_START; + xfer->flag = FWXF_START; fp = &xfer->send.hdr; tcode = fp->mode.common.tcode; @@ -1034,7 +1062,7 @@ again: struct mbuf *m0; if (firewire_debug) - device_printf(sc->fc.dev, "EFBIG.\n"); + fw_printf(sc->fc.dev, "EFBIG.\n"); m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); if (m0 != NULL) { m_copydata(xfer->mbuf, 0, @@ -1046,7 +1074,7 @@ again: xfer->mbuf = m0; goto again; } - device_printf(sc->fc.dev, "m_getcl failed.\n"); + fw_printf(sc->fc.dev, "m_getcl failed.\n"); } } if (err) @@ -1062,7 +1090,7 @@ again: if (maxdesc < db_tr->dbcnt) { maxdesc = db_tr->dbcnt; if (firewire_debug) - device_printf(sc->fc.dev, "maxdesc: %d\n", maxdesc); + fw_printf(sc->fc.dev, "maxdesc: %d\n", maxdesc); } /* last db */ LAST_DB(db_tr, db); @@ -1077,12 +1105,13 @@ again: LAST_DB(dbch->pdb_tr, db); FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt); } + dbch->xferq.queued ++; dbch->pdb_tr = db_tr; db_tr = STAILQ_NEXT(db_tr, link); if(db_tr != dbch->bottom){ goto txloop; } else { - device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n"); + fw_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n"); dbch->flags |= FWOHCI_DBCH_FULL; } kick: @@ -1094,7 +1123,7 @@ kick: OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE); } else { if (firewire_debug) - device_printf(sc->fc.dev, "start AT DMA status=%x\n", + 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); @@ -1112,7 +1141,9 @@ 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); return; } @@ -1120,7 +1151,9 @@ 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); return; } @@ -1154,7 +1187,7 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) LAST_DB(tr, db); status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT; if(!(status & OHCI_CNTL_DMA_ACTIVE)){ - if (fc->status != FWBUSRESET) + if (fc->status != FWBUSINIT) /* maybe out of order?? */ goto out; } @@ -1170,7 +1203,7 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) if(status & OHCI_CNTL_DMA_DEAD) { /* Stop DMA */ OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN); - device_printf(sc->fc.dev, "force reset AT FIFO\n"); + fw_printf(sc->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); @@ -1186,12 +1219,14 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) case FWOHCIEV_ACKBSA: case FWOHCIEV_ACKBSB: case FWOHCIEV_ACKBSX: - device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); + fw_printf(sc->fc.dev, "txd err=%2x %s\n", stat, + fwohcicode[stat]); err = EBUSY; break; case FWOHCIEV_FLUSHED: case FWOHCIEV_ACKTARD: - device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); + fw_printf(sc->fc.dev, "txd err=%2x %s\n", stat, + fwohcicode[stat]); err = EAGAIN; break; case FWOHCIEV_MISSACK: @@ -1205,7 +1240,7 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) case FWOHCIEV_ACKDERR: case FWOHCIEV_ACKTERR: default: - device_printf(sc->fc.dev, "txd err=%2x %s\n", + fw_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]); err = EINVAL; break; @@ -1213,22 +1248,23 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) if (tr->xfer != NULL) { xfer = tr->xfer; CTR0(KTR_DEV, "txd"); - if (xfer->state == FWXF_RCVD) { + if (xfer->flag & FWXF_RCVD) { #if 0 if (firewire_debug) printf("already rcvd\n"); #endif fw_xfer_done(xfer); } else { - xfer->state = FWXF_SENT; - if (err == EBUSY && fc->status != FWBUSRESET) { - xfer->state = FWXF_BUSY; + microtime(&xfer->tv); + xfer->flag = FWXF_SENT; + if (err == EBUSY) { + xfer->flag = FWXF_BUSY; xfer->resp = err; xfer->recv.pay_len = 0; fw_xfer_done(xfer); } else if (stat != FWOHCIEV_ACKPEND) { if (stat != FWOHCIEV_ACKCOMPL) - xfer->state = FWXF_SENTERR; + xfer->flag = FWXF_SENTERR; xfer->resp = err; xfer->recv.pay_len = 0; fw_xfer_done(xfer); @@ -1241,7 +1277,9 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) } 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); @@ -1259,7 +1297,9 @@ out: if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) { printf("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); @@ -1315,7 +1355,7 @@ fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch) /*maxsegsz*/ MAX_REQCOUNT, /*flags*/ 0, /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, + /*lockarg*/FW_GMTX(&sc->fc), &dbch->dmat)) return; @@ -1516,6 +1556,8 @@ fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 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 ++) { fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma); if (STAILQ_NEXT(db_tr, link) == NULL) @@ -1539,6 +1581,7 @@ fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 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){ @@ -1604,6 +1647,7 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) fwohci_db_init(sc, dbch); if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) return ENOMEM; + err = fwohci_tx_enable(sc, dbch); } if(err) @@ -1611,6 +1655,7 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) 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; @@ -1637,6 +1682,7 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) 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); @@ -1691,8 +1737,7 @@ fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach) dump_db(sc, ITX_CH + dmach); } } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) { - device_printf(sc->fc.dev, - "IT DMA underrun (0x%08x)\n", stat); + fw_printf(sc->fc.dev, "IT DMA underrun (0x%08x)\n", stat); OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE); } out: @@ -1732,12 +1777,14 @@ fwohci_irx_enable(struct firewire_comm *fc, int dmach) first = STAILQ_FIRST(&ir->stfree); if (first == NULL) { - device_printf(fc->dev, "IR DMA no free chunk\n"); + 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; @@ -1766,6 +1813,8 @@ fwohci_irx_enable(struct firewire_comm *fc, int dmach) 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); @@ -1774,7 +1823,7 @@ fwohci_irx_enable(struct firewire_comm *fc, int dmach) return 0; if (stat & OHCI_CNTL_DMA_RUN) { OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN); - device_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat); + fw_printf(sc->fc.dev, "IR DMA overrun (0x%08x)\n", stat); } if (firewire_debug) @@ -1795,9 +1844,9 @@ fwohci_irx_enable(struct firewire_comm *fc, int dmach) return err; } -FWOHCI_STOP() +int +fwohci_stop(struct fwohci_softc *sc, device_t dev) { - FWOHCI_STOP_START; u_int i; /* Now stopping all DMA channel */ @@ -1811,9 +1860,10 @@ FWOHCI_STOP() OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); } -/* FLUSH FIFO and reset Transmitter/Reciever */ - OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); + 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 @@ -1823,38 +1873,14 @@ FWOHCI_STOP() | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS | OHCI_INT_PHY_BUS_R); - if (sc->fc.arq !=0 && sc->fc.arq->maxq > 0) - fw_drain_txq(&sc->fc); +/* FLUSH FIFO and reset Transmitter/Reciever */ + OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET); +#endif /* XXX Link down? Bus reset? */ - FWOHCI_STOP_RETURN(0); + return 0; } -#if defined(__NetBSD__) -static void -fwohci_power(int why, void *arg) -{ - struct fwohci_softc *sc = arg; - int s; - - s = splbio(); - switch (why) { - case PWR_SUSPEND: - case PWR_STANDBY: - fwohci_stop(arg); - break; - case PWR_RESUME: - fwohci_resume(sc, sc->fc.dev); - break; - case PWR_SOFTSUSPEND: - case PWR_SOFTSTANDBY: - case PWR_SOFTRESUME: - break; - } - splx(s); -} -#endif - int fwohci_resume(struct fwohci_softc *sc, device_t dev) { @@ -1867,7 +1893,7 @@ fwohci_resume(struct fwohci_softc *sc, device_t dev) for(i = 0; i < sc->fc.nisodma; i ++) { ir = &sc->ir[i].xferq; if((ir->flag & FWXFERQ_RUNNING) != 0) { - device_printf(sc->fc.dev, + fw_printf(sc->fc.dev, "resume iso receive ch: %d\n", i); ir->flag &= ~FWXFERQ_RUNNING; /* requeue stdma to stfree */ @@ -1881,23 +1907,22 @@ fwohci_resume(struct fwohci_softc *sc, device_t dev) #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; } -#define ACK_ALL -static void -fwohci_intr_body(struct fwohci_softc *sc, uint32_t stat, int count) -{ - uint32_t irstat, itstat; - u_int i; - struct firewire_comm *fc = (struct firewire_comm *)sc; - - CTR0(KTR_DEV, "fwohci_intr_body"); #ifdef OHCI_DEBUG +static void +fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat) +{ if(stat & OREAD(sc, FWOHCI_INTMASK)) - device_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", + 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 ":"", @@ -1921,15 +1946,22 @@ fwohci_intr_body(struct fwohci_softc *sc, uint32_t stat, int count) stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"", stat, OREAD(sc, FWOHCI_INTMASK) ); +} #endif -/* Bus reset */ - if(stat & OHCI_INT_PHY_BUS_R ){ - if (fc->status == FWBUSRESET) - goto busresetout; +static void +fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count) +{ + struct firewire_comm *fc = (struct firewire_comm *)sc; + 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); - device_printf(fc->dev, "BUS reset\n"); + fw_printf(fc->dev, "BUS reset\n"); OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC); @@ -1938,31 +1970,85 @@ fwohci_intr_body(struct fwohci_softc *sc, uint32_t stat, int count) OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING; -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R); -#endif - fw_busreset(fc); - OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); - OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); + if (!kdb_active) + fw_taskqueue_enqueue(sc->fc.taskqueue, + &sc->fwohci_task_busreset); } -busresetout: - if((stat & OHCI_INT_DMA_IR )){ -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IR); -#endif -#if defined(__DragonFly__) || __FreeBSD_version < 500000 || defined(__NetBSD__) - irstat = sc->irstat; - sc->irstat = 0; -#else - irstat = atomic_readandclear_int(&sc->irstat); -#endif + if (stat & OHCI_INT_PHY_SID) { + /* Enable bus reset interrupt */ + OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R); + OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R); + + /* Allow async. request to us */ + OWRITE(sc, OHCI_AREQHI, 1 << 31); + if (firewire_phydma_enable) { + /* allow from all nodes */ + OWRITE(sc, OHCI_PREQHI, 0x7fffffff); + OWRITE(sc, OHCI_PREQLO, 0xffffffff); + /* 0 to 4GB regison */ + OWRITE(sc, OHCI_PREQUPPER, 0x10000); + } + /* Set ATRetries register */ + OWRITE(sc, OHCI_ATRETRY, 1<<(13+16) | 0xfff); + + /* + * Checking whether the node is root or not. If root, turn on + * cycle master. + */ + node_id = OREAD(sc, FWOHCI_NODEID); + plen = OREAD(sc, OHCI_SID_CNT); + + fc->nodeid = node_id & 0x3f; + fw_printf(fc->dev, "node_id=0x%08x, gen=%d, ", + node_id, (plen >> 16) & 0xff); + if (!(node_id & OHCI_NODE_VALID)) { + printf("Bus reset failure\n"); + goto sidout; + } + + /* cycle timer */ + sc->cycle_lost = 0; + OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST); + if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) { + printf("CYCLEMASTER mode\n"); + OWRITE(sc, OHCI_LNKCTL, + OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER); + } else { + printf("non CYCLEMASTER mode\n"); + OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR); + OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER); + } + + fc->status = FWBUSINIT; + + if (!kdb_active) + fw_taskqueue_enqueue(sc->fc.taskqueue, + &sc->fwohci_task_sid); + } +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"); +} + +static void +fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count) +{ + 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; if((irstat & (1 << i)) != 0){ dbch = &sc->ir[i]; if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) { - device_printf(sc->fc.dev, + fw_printf(sc->fc.dev, "dma(%d) not active\n", i); continue; } @@ -1970,36 +2056,22 @@ busresetout: } } } - if((stat & OHCI_INT_DMA_IT )){ -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IT); -#endif -#if defined(__DragonFly__) || __FreeBSD_version < 500000 || defined(__NetBSD__) - itstat = sc->itstat; - sc->itstat = 0; -#else - itstat = atomic_readandclear_int(&sc->itstat); -#endif + 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){ fwohci_tbuf_update(sc, i); } } } - if((stat & OHCI_INT_DMA_PRRS )){ -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRS); -#endif + 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); } - if((stat & OHCI_INT_DMA_PRRQ )){ -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRQ); -#endif + if (stat & OHCI_INT_DMA_PRRQ) { #if 0 dump_dma(sc, ARRQ_CH); dump_db(sc, ARRQ_CH); @@ -2015,240 +2087,155 @@ busresetout: OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER); #endif OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); - device_printf(fc->dev, "too many cycle lost, " + fw_printf(fc->dev, "too many cycle lost, " "no cycle master presents?\n"); } } - if(stat & OHCI_INT_PHY_SID){ - uint32_t *buf, node_id; - int plen; - -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_SID); -#endif - /* Enable bus reset interrupt */ - OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R); - /* Allow async. request to us */ - OWRITE(sc, OHCI_AREQHI, 1 << 31); - /* XXX insecure ?? */ - /* allow from all nodes */ - OWRITE(sc, OHCI_PREQHI, 0x7fffffff); - OWRITE(sc, OHCI_PREQLO, 0xffffffff); - /* 0 to 4GB regison */ - OWRITE(sc, OHCI_PREQUPPER, 0x10000); - /* Set ATRetries register */ - OWRITE(sc, OHCI_ATRETRY, 1<<(13+16) | 0xfff); -/* -** Checking whether the node is root or not. If root, turn on -** cycle master. -*/ - node_id = OREAD(sc, FWOHCI_NODEID); - plen = OREAD(sc, OHCI_SID_CNT); - - device_printf(fc->dev, "node_id=0x%08x, gen=%d, ", - node_id, (plen >> 16) & 0xff); - if (!(node_id & OHCI_NODE_VALID)) { - printf("Bus reset failure\n"); - goto sidout; - } - - /* cycle timer */ - sc->cycle_lost = 0; - OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST); - if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) { - printf("CYCLEMASTER mode\n"); - OWRITE(sc, OHCI_LNKCTL, - OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER); - } else { - printf("non CYCLEMASTER mode\n"); - OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR); - OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER); - } - - fc->nodeid = node_id & 0x3f; - - if (plen & OHCI_SID_ERR) { - device_printf(fc->dev, "SID Error\n"); - goto sidout; - } - plen &= OHCI_SID_CNT_MASK; - if (plen < 4 || plen > OHCI_SIDSIZE) { - device_printf(fc->dev, "invalid SID len = %d\n", plen); - goto sidout; - } - plen -= 4; /* chop control info */ - buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT); - if (buf == NULL) { - device_printf(fc->dev, "malloc failed\n"); - goto sidout; - } - for (i = 0; i < plen / 4; i ++) - buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i+1]); -#if defined(__NetBSD__) && defined(macppc) - /* XXX required as bootdisk for macppc. */ - delay(500000); -#endif -#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); - fw_drain_txq(fc); -#endif - fw_sidrcv(fc, buf, plen); - free(buf, M_FW); - } -sidout: - if((stat & OHCI_INT_DMA_ATRQ )){ -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRQ); -#endif + if (stat & OHCI_INT_DMA_ATRQ) { fwohci_txd(sc, &(sc->atrq)); } - if((stat & OHCI_INT_DMA_ATRS )){ -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRS); -#endif + if (stat & OHCI_INT_DMA_ATRS) { fwohci_txd(sc, &(sc->atrs)); } - if((stat & OHCI_INT_PW_ERR )){ -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PW_ERR); -#endif - device_printf(fc->dev, "posted write error\n"); + if (stat & OHCI_INT_PW_ERR) { + fw_printf(fc->dev, "posted write error\n"); } - if((stat & OHCI_INT_ERR )){ -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_ERR); -#endif - device_printf(fc->dev, "unrecoverable error\n"); + if (stat & OHCI_INT_ERR) { + fw_printf(fc->dev, "unrecoverable error\n"); } - if((stat & OHCI_INT_PHY_INT)) { -#ifndef ACK_ALL - OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_INT); -#endif - device_printf(fc->dev, "phy int\n"); + if (stat & OHCI_INT_PHY_INT) { + fw_printf(fc->dev, "phy int\n"); } - CTR0(KTR_DEV, "fwohci_intr_body done"); + CTR0(KTR_DEV, "fwohci_intr_dma done"); return; } -#if FWOHCI_TASKQUEUE static void -fwohci_complete(void *arg, int pending) +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) +{ + struct fwohci_softc *sc = (struct fwohci_softc *)arg; + struct firewire_comm *fc = &sc->fc; + uint32_t *buf; + int i, plen; + + plen = OREAD(sc, OHCI_SID_CNT); + + if (plen & OHCI_SID_ERR) { + fw_printf(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); + 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"); + return; + } + 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); + fw_drain_txq(fc); +#endif + fw_sidrcv(fc, buf, plen); + free(buf, M_FW); +} + +static void +fwohci_task_dma(void *arg, int pending) { struct fwohci_softc *sc = (struct fwohci_softc *)arg; uint32_t stat; again: - stat = atomic_readandclear_int(&sc->intstat); - if (stat) { - FW_LOCK; - fwohci_intr_body(sc, stat, -1); - FW_UNLOCK; - } else + stat = fw_atomic_readandclear_int(&sc->intstat); + if (stat) + fwohci_intr_dma(sc, stat, -1); + else return; goto again; } -#endif -static uint32_t -fwochi_check_stat(struct fwohci_softc *sc) +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) { - device_printf(sc->fc.dev, + fw_printf(sc->fc.dev, "device physically ejected?\n"); - return(stat); + return (FILTER_STRAY); } -#ifdef ACK_ALL if (stat) - OWRITE(sc, FWOHCI_INTSTATCLR, stat); -#endif + 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); - atomic_set_int(&sc->irstat, 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); - atomic_set_int(&sc->itstat, itstat); + fw_atomic_set_int(&sc->itstat, itstat); } - return(stat); + + fwohci_intr_core(sc, stat, -1); + return (FILTER_HANDLED); } -FW_INTR(fwohci) +int +fwohci_filt(void *arg) { struct fwohci_softc *sc = (struct fwohci_softc *)arg; - uint32_t stat; -#if !FWOHCI_TASKQUEUE - uint32_t bus_reset = 0; -#endif if (!(sc->intmask & OHCI_INT_EN)) { /* polling mode */ - FW_INTR_RETURN(0); + return (FILTER_STRAY); } + return (fwohci_check_stat(sc)); +} -#if !FWOHCI_TASKQUEUE -again: -#endif - CTR0(KTR_DEV, "fwohci_intr"); - stat = fwochi_check_stat(sc); - if (stat == 0 || stat == 0xffffffff) - FW_INTR_RETURN(1); -#if FWOHCI_TASKQUEUE - atomic_set_int(&sc->intstat, stat); - /* XXX mask bus reset intr. during bus reset phase */ - if (stat) -#if 1 - taskqueue_enqueue_fast(taskqueue_fast, - &sc->fwohci_task_complete); -#else - taskqueue_enqueue(taskqueue_swi, - &sc->fwohci_task_complete); -#endif -#else - /* We cannot clear bus reset event during bus reset phase */ - if ((stat & ~bus_reset) == 0) - FW_INTR_RETURN(1); - bus_reset = stat & OHCI_INT_PHY_BUS_R; - fwohci_intr_body(sc, stat, -1); - goto again; -#endif +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) { - int s; - uint32_t stat; - struct fwohci_softc *sc; + struct fwohci_softc *sc = (struct fwohci_softc *)fc; - - sc = (struct fwohci_softc *)fc; - stat = OHCI_INT_DMA_IR | OHCI_INT_DMA_IT | - OHCI_INT_DMA_PRRS | OHCI_INT_DMA_PRRQ | - OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS; -#if 0 - if (!quick) { -#else - if (1) { -#endif - stat = fwochi_check_stat(sc); - if (stat == 0 || stat == 0xffffffff) - return; - } - s = splfw(); - fwohci_intr_body(sc, stat, count); - splx(s); + fwohci_check_stat(sc); } static void @@ -2258,7 +2245,7 @@ fwohci_set_intr(struct firewire_comm *fc, int enable) sc = (struct fwohci_softc *)fc; if (firewire_debug) - device_printf(sc->fc.dev, "fwohci_set_intr: %d\n", enable); + 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); @@ -2281,6 +2268,7 @@ fwohci_tbuf_update(struct fwohci_softc *sc, int dmach) it = fc->it[dmach]; ldesc = sc->it[dmach].ndesc - 1; s = splfw(); /* unnecessary ? */ + FW_GLOCK(fc); fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD); if (firewire_debug) dump_db(sc, ITX_CH + dmach); @@ -2298,17 +2286,18 @@ fwohci_tbuf_update(struct fwohci_softc *sc, int dmach) switch (stat & FWOHCIEV_MASK){ case FWOHCIEV_ACKCOMPL: #if 0 - device_printf(fc->dev, "0x%08x\n", count); + fw_printf(fc->dev, "0x%08x\n", count); #endif break; default: - device_printf(fc->dev, + fw_printf(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); if (w) wakeup(it); @@ -2322,14 +2311,17 @@ 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 s, w = 0, ldesc; ir = fc->ir[dmach]; ldesc = sc->ir[dmach].ndesc - 1; + #if 0 dump_db(sc, dmach); #endif s = splfw(); + if ((ir->flag & FWXFERQ_HANDLER) == 0) + FW_GLOCK(fc); 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; @@ -2359,19 +2351,20 @@ fwohci_rbuf_update(struct fwohci_softc *sc, int dmach) break; default: chunk->resp = EINVAL; - device_printf(fc->dev, - "Isochronous receive err %02x(%s)\n", + fw_printf(fc->dev, "Isochronous receive err %02x(%s)\n", stat, fwohcicode[stat & 0x1f]); } w++; } + if ((ir->flag & FWXFERQ_HANDLER) == 0) + FW_GUNLOCK(fc); splx(s); - if (w) { - if (ir->flag & FWXFERQ_HANDLER) - ir->hand(ir); - else - wakeup(ir); - } + if (w == 0) + return; + if (ir->flag & FWXFERQ_HANDLER) + ir->hand(ir); + else + wakeup(ir); } void @@ -2396,14 +2389,14 @@ dump_dma(struct fwohci_softc *sc, uint32_t ch) cmd = OREAD(sc, off + 0xc); match = OREAD(sc, off + 0x10); - device_printf(sc->fc.dev, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n", + 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) { - device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n", + 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," : "", @@ -2415,7 +2408,7 @@ dump_dma(struct fwohci_softc *sc, uint32_t ch) stat & 0x1f ); }else{ - device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch); + fw_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch); } } @@ -2449,7 +2442,7 @@ dump_db(struct fwohci_softc *sc, uint32_t ch) cmd = OREAD(sc, off + 0xc); if( dbch->ndb == 0 ){ - device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch); + fw_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch); return; } pp = dbch->top; @@ -2593,7 +2586,7 @@ fwohci_ibr(struct firewire_comm *fc) struct fwohci_softc *sc; uint32_t fun; - device_printf(fc->dev, "Initiate bus reset\n"); + fw_printf(fc->dev, "Initiate bus reset\n"); sc = (struct fwohci_softc *)fc; /* @@ -2629,13 +2622,15 @@ fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer) unsigned short chtag; int idb; + FW_GLOCK_ASSERT(&sc->fc); + dbch = &sc->it[dmach]; chtag = sc->it[dmach].xferq.flag & 0xff; db_tr = (struct fwohcidb_tr *)(bulkxfer->start); fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end); /* -device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr); +fw_printf(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 ++) { db = db_tr->db; @@ -2679,7 +2674,7 @@ device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_ /* db_tr = (struct fwohcidb_tr *)bulkxfer->start; fdb_tr = (struct fwohcidb_tr *)bulkxfer->end; -device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr); +fw_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr); */ return; } @@ -2830,13 +2825,13 @@ fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt if (r == sizeof(uint32_t)) { /* XXX */ - device_printf(sc->fc.dev, "Unknown tcode %d\n", + fw_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode); return (-1); } if (r > dbch->xferq.psize) { - device_printf(sc->fc.dev, "Invalid packet length %d\n", r); + fw_printf(sc->fc.dev, "Invalid packet length %d\n", r); return (-1); /* panic ? */ } @@ -2942,7 +2937,7 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) len -= rlen; hlen = fwohci_arcv_swap(&pktbuf, sizeof(pktbuf)); if (hlen <= 0) { - printf("hlen < 0 shouldn't happen"); + printf("hlen should be positive."); goto err; } offset = sizeof(pktbuf); @@ -3037,11 +3032,12 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count) break; } case FWOHCIEV_BUSRST: - if (sc->fc.status != FWBUSRESET) + if ((sc->fc.status != FWBUSRESET) && + (sc->fc.status != FWBUSINIT)) printf("got BUSRST packet!?\n"); break; default: - device_printf(sc->fc.dev, + fw_printf(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", @@ -3098,7 +3094,7 @@ out: return; err: - device_printf(sc->fc.dev, "AR DMA status=%x, ", + fw_printf(sc->fc.dev, "AR DMA status=%x, ", OREAD(sc, OHCI_DMACTL(off))); dbch->pdb_tr = NULL; /* skip until resCount != 0 */ diff --git a/sys/dev/ieee1394/fwohcireg.h b/sys/dev/ieee1394/fwohcireg.h index 27de68ad8cb8..3a468c6ed80b 100644 --- a/sys/dev/ieee1394/fwohcireg.h +++ b/sys/dev/ieee1394/fwohcireg.h @@ -1,4 +1,4 @@ -/* $NetBSD: fwohcireg.h,v 1.16 2007/03/04 06:02:07 christos Exp $ */ +/* $NetBSD: fwohcireg.h,v 1.17 2007/11/05 19:08:57 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa @@ -33,7 +33,7 @@ * 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/fwohcireg.h,v 1.22 2005/05/20 12:37:16 marius Exp $ + * $FreeBSD: src/sys/dev/firewire/fwohcireg.h,v 1.23 2007/04/30 14:06:30 simokawa Exp $ * */ #define PCI_CBMEM PCIR_BAR(0) diff --git a/sys/dev/ieee1394/fwohcivar.h b/sys/dev/ieee1394/fwohcivar.h index 3ee4293efcae..f87973fb43b5 100644 --- a/sys/dev/ieee1394/fwohcivar.h +++ b/sys/dev/ieee1394/fwohcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: fwohcivar.h,v 1.26 2007/04/21 15:27:44 kiyohara Exp $ */ +/* $NetBSD: fwohcivar.h,v 1.27 2007/11/05 19:08:57 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi SHimokawa @@ -33,19 +33,10 @@ * 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/fwohcivar.h,v 1.15 2007/03/16 04:25:02 simokawa Exp $ + * $FreeBSD: src/sys/dev/firewire/fwohcivar.h,v 1.16 2007/06/06 14:31:36 simokawa Exp $ * */ -#if defined(__DragonFly__) || __FreeBSD_version < 500000 || defined(__NetBSD__) -#define FWOHCI_TASKQUEUE 0 -#else -#define FWOHCI_TASKQUEUE 1 -#endif -#if FWOHCI_TASKQUEUE -#include -#endif - #if defined(__NetBSD__) MALLOC_DECLARE(M_FW); #endif @@ -64,8 +55,6 @@ typedef struct fwohci_softc { struct resource *irq_res; #elif defined(__NetBSD__) bus_size_t bssize; - void *sc_shutdownhook; - void *sc_powerhook; #endif struct fwohci_dbch{ u_int ndb; @@ -89,17 +78,22 @@ typedef struct fwohci_softc { struct fwdma_alloc crom_dma; struct fwdma_alloc dummy_dma; uint32_t intmask, irstat, itstat; -#if FWOHCI_TASKQUEUE uint32_t intstat; - struct task fwohci_task_complete; -#endif + fw_task_t fwohci_task_busreset; + fw_task_t fwohci_task_sid; + fw_task_t fwohci_task_dma; int cycle_lost; } fwohci_softc_t; -FW_INTR(fwohci); +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); -FWOHCI_DETACH(); +#if defined(__FreeBSD__) +int fwohci_detach(struct fwohci_softc *, device_t); +#elif defined(__NetBSD__) +int fwohci_detach(struct fwohci_softc *, int); +#endif int fwohci_resume (struct fwohci_softc *, device_t); -FWOHCI_STOP(); +int fwohci_stop (struct fwohci_softc *, device_t dev); diff --git a/sys/dev/ieee1394/if_fwip.c b/sys/dev/ieee1394/if_fwip.c index c773501f6ad5..20e2b177f26d 100644 --- a/sys/dev/ieee1394/if_fwip.c +++ b/sys/dev/ieee1394/if_fwip.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_fwip.c,v 1.9 2007/10/19 12:00:13 ad Exp $ */ +/* $NetBSD: if_fwip.c,v 1.10 2007/11/05 19:08:57 kiyohara Exp $ */ /*- * Copyright (c) 2004 * Doug Rabson @@ -34,7 +34,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/if_fwip.c,v 1.14 2007/03/16 05:39:33 simokawa Exp $ + * $FreeBSD: src/sys/dev/firewire/if_fwip.c,v 1.16 2007/06/06 14:31:36 simokawa Exp $ */ #ifdef HAVE_KERNEL_OPTION_HEADERS @@ -106,10 +106,10 @@ #if defined(__FreeBSD__) #define FWIPDEBUG if (fwipdebug) if_printf #elif defined(__NetBSD__) -#define FWIPDEBUG(ifp, fmt, ...) \ - if (fwipdebug) {\ - aprint_normal("%s: ", (ifp)->if_xname); \ - aprint_normal((fmt) ,##__VA_ARGS__); \ +#define FWIPDEBUG(ifp, fmt, ...) \ + if (fwipdebug) { \ + printf("%s: ", (ifp)->if_xname);\ + printf((fmt) , ##__VA_ARGS__); \ } #endif #define TX_MAX_QUEUE (FWMAXQUEUE - 1) @@ -124,15 +124,18 @@ int fwipactivate (struct device *, enum devact); /* network interface */ static void fwip_start (struct ifnet *); static int fwip_ioctl (struct ifnet *, u_long, void *); -IF_INIT(fwip); -IF_STOP(fwip); +#if defined(__FreeBSD__) +static void fwip_init(void *); +static void fwip_stop(struct fwip_softc *); +#elif defined(__NetBSD__) +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 *); -#if defined(__FreeBSD__) static void fwip_start_send (void *, int); -#endif static void fwip_stream_input (struct fw_xferq *); static void fwip_unicast_input(struct fw_xfer *); @@ -223,7 +226,7 @@ fwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) static void fwip_identify(driver_t *driver, device_t parent) { - BUS_ADD_CHILD(parent, 0, "fwip", device_get_unit(parent)); + BUS_ADD_CHILD(parent, 0, "fwip", fw_get_unit(parent)); } static int @@ -232,7 +235,7 @@ fwip_probe(device_t dev) device_t pa; pa = device_get_parent(dev); - if(device_get_unit(dev) != device_get_unit(pa)){ + if(fw_get_unit(dev) != fw_get_unit(pa)){ return(ENXIO); } @@ -264,6 +267,7 @@ FW_ATTACH(fwip) if (ifp == NULL) FW_ATTACH_RETURN(ENOSPC); + fw_mtx_init(&fwip->mtx, "fwip", NULL, MTX_DEF); /* XXX */ fwip->dma_ch = -1; @@ -274,7 +278,7 @@ FW_ATTACH(fwip) fwip->fd.post_explore = NULL; fwip->fd.post_busreset = fwip_post_busreset; fwip->fw_softc.fwip = fwip; - TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip); + FW_TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip); /* * Encode our hardware the way that arp likes it. @@ -299,8 +303,7 @@ FW_ATTACH(fwip) IFQ_SET_READY(&ifp->if_snd); #endif SET_IFFUNC(ifp, fwip_start, fwip_ioctl, fwip_init, fwip_stop); - ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST| - IFF_NEEDSGIANT); + 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; @@ -380,6 +383,7 @@ FW_DETACH(fwip) FWIP_STOP(fwip); FIREWIRE_IFDETACH(ifp); + fw_mtx_destroy(&fwip->mtx); splx(s); return 0; @@ -422,18 +426,12 @@ IF_INIT(fwip) fc = fwip->fd.fc; #define START 0 if (fwip->dma_ch < 0) { - for (i = START; i < fc->nisodma; i ++) { - xferq = fc->ir[i]; - if ((xferq->flag & FWXFERQ_OPEN) == 0) - goto found; - } - printf("no free dma channel\n"); - IF_INIT_RETURN(ENXIO); -found: - fwip->dma_ch = i; - /* allocate DMA channel and init packet mode */ - xferq->flag |= FWXFERQ_OPEN | FWXFERQ_EXTBUF | - FWXFERQ_HANDLER | FWXFERQ_STREAM; + fwip->dma_ch = fw_open_isodma(fc, /* tx */0); + if (fwip->dma_ch < 0) + IF_INIT_RETURN(ENXIO); + xferq = fc->ir[fwip->dma_ch]; + xferq->flag |= + FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_STREAM; xferq->flag &= ~0xff; xferq->flag |= broadcast_channel & 0xff; /* register fwip_input handler */ @@ -644,8 +642,6 @@ fwip_output_callback(struct fw_xfer *xfer) struct ifnet *ifp; int s; - GIANT_REQUIRED; - fwip = (struct fwip_softc *)xfer->sc; ifp = fwip->fw_softc.fwip_ifp; /* XXX error check */ @@ -657,12 +653,15 @@ fwip_output_callback(struct fw_xfer *xfer) fw_xfer_unload(xfer); s = splfwnet(); + FWIP_LOCK(fwip); STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); + FWIP_UNLOCK(fwip); splx(s); /* for queue full */ - if (ifp->if_snd.ifq_head != NULL) + if (ifp->if_snd.ifq_head != NULL) { fwip_start(ifp); + } } static void @@ -672,8 +671,6 @@ fwip_start(struct ifnet *ifp) ((struct fwip_eth_softc *)ifp->if_softc)->fwip; int s; - GIANT_REQUIRED; - FWIPDEBUG(ifp, "starting\n"); if (fwip->dma_ch < 0) { @@ -726,19 +723,29 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) int error; int i = 0; - GIANT_REQUIRED; - xfer = NULL; - xferq = fwip->fd.fc->atq; - while (xferq->queued < xferq->maxq - 1) { + 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); +#if 0 printf("if_fwip: lack of xfer\n"); - return; - } - IF_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) +#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); + break; + } /* * Dig out the link-level address which @@ -752,8 +759,6 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) else destfw = (struct fw_hwaddr *) (mtag + 1); - STAILQ_REMOVE_HEAD(&fwip->xferlist, link); - /* * We don't do any bpf stuff here - the generic code * in firewire_output gives the packet to bpf before @@ -845,7 +850,9 @@ 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); IF_PREPEND(&ifp->if_snd, m); break; } @@ -864,25 +871,17 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) if (i > 1) printf("%d queued\n", i); #endif - if (i > 0) { -#if 1 + if (i > 0) xferq->start(fc); -#else - taskqueue_enqueue(taskqueue_swi_giant, &fwip->start_send); -#endif - } } -#if defined(__FreeBSD__) static void fwip_start_send (void *arg, int count) { struct fwip_softc *fwip = arg; - GIANT_REQUIRED; fwip->fd.fc->atq->start(fwip->fd.fc); } -#endif /* Async. stream output */ static void @@ -897,8 +896,6 @@ fwip_stream_input(struct fw_xferq *xferq) uint16_t src; uint32_t *p; - GIANT_REQUIRED; - fwip = (struct fwip_softc *)xferq->sc; ifp = fwip->fw_softc.fwip_ifp; while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) { @@ -998,8 +995,6 @@ fwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer) { struct mbuf *m; - GIANT_REQUIRED; - /* * We have finished with a unicast xfer. Allocate a new * cluster and stick it on the back of the input queue. @@ -1026,8 +1021,6 @@ fwip_unicast_input(struct fw_xfer *xfer) //struct fw_pkt *sfp; int rtcode; - GIANT_REQUIRED; - fwip = (struct fwip_softc *)xfer->sc; ifp = fwip->fw_softc.fwip_ifp; m = xfer->mbuf; diff --git a/sys/dev/ieee1394/if_fwipvar.h b/sys/dev/ieee1394/if_fwipvar.h index e9f7f54c2140..c0bc90559e80 100644 --- a/sys/dev/ieee1394/if_fwipvar.h +++ b/sys/dev/ieee1394/if_fwipvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_fwipvar.h,v 1.3 2007/04/21 15:27:44 kiyohara Exp $ */ +/* $NetBSD: if_fwipvar.h,v 1.4 2007/11/05 19:08:57 kiyohara Exp $ */ /*- * Copyright (c) 2004 * Doug Rabson @@ -34,7 +34,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: /repoman/r/ncvs/src/sys/dev/firewire/if_fwipvar.h,v 1.4 2005/06/10 16:49:08 brooks Exp $ + * $FreeBSD: src/sys/dev/firewire/if_fwipvar.h,v 1.5 2007/06/06 14:31:36 simokawa Exp $ */ #ifndef _NET_IF_FWIPVAR_H_ @@ -47,9 +47,7 @@ struct fwip_softc { struct fw_bind fwb; struct fw_eui64 last_dest; struct fw_pkt last_hdr; -#if defined(__FreeBSD__) - struct task start_send; -#endif + 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 */ @@ -64,5 +62,10 @@ struct fwip_softc { struct ifnet *fwip_ifp; struct fwip_softc *fwip; } fw_softc; + fw_mtx_t mtx; }; + +#define FWIP_LOCK(fwip) fw_mtx_lock(&(fwip)->mtx) +#define FWIP_UNLOCK(fwip) fw_mtx_unlock(&(fwip)->mtx) + #endif /* !_NET_IF_FWIPVAR_H_ */ diff --git a/sys/dev/ieee1394/sbp.c b/sys/dev/ieee1394/sbp.c index 3473593d47a9..94e4b99c4fd5 100644 --- a/sys/dev/ieee1394/sbp.c +++ b/sys/dev/ieee1394/sbp.c @@ -1,4 +1,4 @@ -/* $NetBSD: sbp.c,v 1.18 2007/10/19 12:00:13 ad Exp $ */ +/* $NetBSD: sbp.c,v 1.19 2007/11/05 19:08:57 kiyohara Exp $ */ /*- * Copyright (c) 2003 Hidetoshi Shimokawa * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa @@ -32,7 +32,7 @@ * 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.c,v 1.89 2007/03/16 05:39:33 simokawa Exp $ + * $FreeBSD: src/sys/dev/firewire/sbp.c,v 1.92 2007/06/06 14:31:36 simokawa Exp $ * */ @@ -429,7 +429,10 @@ struct sbp_softc { struct timeval last_busreset; #define SIMQ_FREEZED 1 int flags; + fw_mtx_t mtx; }; +#define SBP_LOCK(sbp) fw_mtx_lock(&(sbp)->mtx) +#define SBP_UNLOCK(sbp) fw_mtx_unlock(&(sbp)->mtx) #if defined(__NetBSD__) int sbpmatch (struct device *, struct cfdata *, void *); @@ -480,7 +483,6 @@ static void sbp_cam_detach_target (struct sbp_target *); #define SBP_DETACH_TARGET(st) sbp_cam_detach_target((st)) #elif defined(__NetBSD__) /* scsipi related functions */ -static void fw_kthread_create0(void *); 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 *); @@ -542,7 +544,7 @@ SBP_DEBUG(0) printf("sbp_identify\n"); END_DEBUG - child = BUS_ADD_CHILD(parent, 0, "sbp", device_get_unit(parent)); + child = BUS_ADD_CHILD(parent, 0, "sbp", fw_get_unit(parent)); } #endif @@ -559,7 +561,7 @@ SBP_DEBUG(0) END_DEBUG pa = device_get_parent(dev); - if(device_get_unit(dev) != device_get_unit(pa)){ + if(fw_get_unit(dev) != fw_get_unit(pa)){ return(ENXIO); } @@ -579,8 +581,8 @@ sbpmatch(struct device *parent, struct cfdata *cf, void *aux) struct fw_attach_args *fwa = aux; if (strcmp(fwa->name, "sbp") == 0) - return (1); - return (0); + return 1; + return 0; } #endif @@ -590,7 +592,7 @@ sbp_show_sdev_info(struct sbp_dev *sdev, int new) struct fw_device *fwdev; printf("%s:%d:%d ", - device_get_nameunit(sdev->target->sbp->fd.dev), + fw_get_nameunit(sdev->target->sbp->fd.dev), sdev->target->target_id, sdev->lun_id ); @@ -643,7 +645,7 @@ END_DEBUG } if (maxlun < 0) printf("%s:%d no LUN found\n", - device_get_nameunit(target->sbp->fd.dev), + fw_get_nameunit(target->sbp->fd.dev), target->target_id); maxlun ++; @@ -713,7 +715,7 @@ END_DEBUG sdev->lun_id = lun; sdev->target = target; STAILQ_INIT(&sdev->ocbs); - CALLOUT_INIT(&sdev->login_callout); + fw_callout_init(&sdev->login_callout); sdev->status = SBP_DEV_RESET; new = 1; SBP_DEVICE_PREATTACH(); @@ -802,8 +804,8 @@ END_DEBUG STAILQ_INIT(&target->xferlist); target->n_xfer = 0; STAILQ_INIT(&target->mgm_ocb_queue); - CALLOUT_INIT(&target->mgm_ocb_timeout); - CALLOUT_INIT(&target->scan_callout); + fw_callout_init(&target->mgm_ocb_timeout); + fw_callout_init(&target->scan_callout); target->luns = NULL; target->num_lun = 0; @@ -858,17 +860,17 @@ sbp_login(struct sbp_dev *sdev) int ticks = 0; microtime(&delta); - timevalsub(&delta, &sdev->target->sbp->last_busreset); + fw_timevalsub(&delta, &sdev->target->sbp->last_busreset); t.tv_sec = login_delay / 1000; t.tv_usec = (login_delay % 1000) * 1000; - timevalsub(&t, &delta); + fw_timevalsub(&t, &delta); 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 = %jd usec = %ld ticks = %d\n", __func__, (intmax_t)t.tv_sec, t.tv_usec, ticks); END_DEBUG - callout_reset(&sdev->login_callout, ticks, + fw_callout_reset(&sdev->login_callout, ticks, sbp_login_callout, (void *)(sdev)); } @@ -896,8 +898,10 @@ END_DEBUG 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) @@ -929,8 +933,10 @@ SBP_DEBUG(0) 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); @@ -970,7 +976,9 @@ END_DEBUG if (!alive) return; + SBP_LOCK(sbp); SBP_BUS_FREEZE(sbp); + SBP_UNLOCK(sbp); } static void @@ -1008,7 +1016,9 @@ END_DEBUG if (target->num_lun == 0) sbp_free_target(target); + SBP_LOCK(sbp); SBP_BUS_THAW(sbp); + SBP_UNLOCK(sbp); } #if NEED_RESPONSE @@ -1038,7 +1048,9 @@ sbp_xfer_free(struct fw_xfer *xfer) sdev = (struct sbp_dev *)xfer->sc; fw_xfer_unload(xfer); s = splfw(); + SBP_LOCK(sdev->target->sbp); STAILQ_INSERT_TAIL(&sdev->target->xferlist, xfer, link); + SBP_UNLOCK(sdev->target->sbp); splx(s); } @@ -1181,34 +1193,21 @@ END_DEBUG 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; - callout_reset(&sdev->target->scan_callout, scan_delay * hz / 1000, + fw_callout_reset(&sdev->target->scan_callout, scan_delay * hz / 1000, sbp_cam_scan_target, (void *)sdev->target); } #else -static void -fw_kthread_create0(void *arg) -{ - struct sbp_softc *sbp = (struct sbp_softc *)arg; - - /* 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))) { - - device_printf(sbp->fd.dev, "unable to create thread"); - panic("fw_kthread_create"); - } -} - static void sbp_scsipi_scan_target(void *arg) { @@ -1313,8 +1312,10 @@ END_DEBUG sbp_xfer_free(xfer); if (SBP_DEVICE(sdev)) { + SBP_LOCK(sdev->target->sbp); SBP_DEVICE_THAW(sdev, sdev->freeze); sdev->freeze = 0; + SBP_UNLOCK(sdev->target->sbp); } } @@ -1542,7 +1543,6 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset) fp->mode.wreqq.dst = FWLOCALBUS | sdev->target->fwdev->dst; return xfer; - } static void @@ -1556,23 +1556,28 @@ sbp_mgm_orb(struct sbp_dev *sdev, int func, struct sbp_ocb *aocb) target = sdev->target; nid = target->sbp->fd.fc->nodeid | FWLOCALBUS; - dv_unit = device_get_unit(target->sbp->fd.dev); + dv_unit = fw_get_unit(target->sbp->fd.dev); s = splfw(); + SBP_LOCK(target->sbp); 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); return; } STAILQ_REMOVE_HEAD(&target->mgm_ocb_queue, ocb); + SBP_UNLOCK(target->sbp); goto start; } if ((ocb = sbp_get_ocb(sdev)) == NULL) { + SBP_UNLOCK(target->sbp); splx(s); /* XXX */ return; } + SBP_UNLOCK(target->sbp); ocb->flags = OCB_ACT_MGM; ocb->sdev = sdev; @@ -1609,7 +1614,9 @@ END_DEBUG if (target->mgm_ocb_cur != NULL) { /* there is a standing ORB */ + SBP_LOCK(target->sbp); STAILQ_INSERT_TAIL(&sdev->target->mgm_ocb_queue, ocb, ocb); + SBP_UNLOCK(target->sbp); splx(s); return; } @@ -1617,7 +1624,7 @@ start: target->mgm_ocb_cur = ocb; splx(s); - callout_reset(&target->mgm_ocb_timeout, 5*hz, + fw_callout_reset(&target->mgm_ocb_timeout, 5*hz, sbp_mgm_timeout, (void *)ocb); xfer = sbp_write_cmd(sdev, FWTCODE_WREQB, 0); if(xfer == NULL){ @@ -1655,7 +1662,7 @@ sbp_print_scsi_cmd(struct sbp_ocb *ocb) "cmd: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" ", flags: 0x%02x, " "%db cmd/%db data/%db sense\n", - device_get_nameunit(ocb->sdev->target->sbp->fd.dev), + 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), @@ -1841,7 +1848,7 @@ END_DEBUG target = &sbp->target; l = SBP_ADDR2LUN(addr); if (l >= target->num_lun || target->luns[l] == NULL) { - device_printf(sbp->fd.dev, + fw_printf(sbp->fd.dev, "sbp_recv1: invalid lun %d (target=%d)\n", l, target->target_id); goto done0; @@ -1858,7 +1865,7 @@ END_DEBUG ocb = target->mgm_ocb_cur; if (ocb != NULL) { if (OCB_MATCH(ocb, sbp_status)) { - callout_stop(&target->mgm_ocb_timeout); + fw_callout_stop(&target->mgm_ocb_timeout); target->mgm_ocb_cur = NULL; break; } @@ -1933,8 +1940,10 @@ 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); } reset_agent = 1; } @@ -2046,7 +2055,9 @@ printf("len %d\n", sbp_status->len); /* fix up inq data */ if (SCSI_XFER_OPECODE(sxfer) == INQUIRY) sbp_fix_inq_data(ocb); + SBP_LOCK(sbp); SCSI_TRANSFER_DONE(sxfer); + SBP_UNLOCK(sbp); } break; default: @@ -2108,10 +2119,11 @@ 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) - device_printf(sbp->fd.dev, + fw_printf(sbp->fd.dev, "Warning, DFLTPHYS(%dKB) is larger than " "SBP_MAXPHYS(%dKB).\n", DFLTPHYS / 1024, SBP_MAXPHYS / 1024); @@ -2121,12 +2133,13 @@ END_DEBUG if (cold) sbp_cold ++; - sbp->fd.fc = fwa->fc; + sbp->fd.fc = fc = fwa->fc; + fw_mtx_init(&sbp->mtx, "sbp", NULL, MTX_DEF); if (max_speed < 0) - max_speed = sbp->fd.fc->speed; + max_speed = fc->speed; - error = fw_bus_dma_tag_create(/*parent*/sbp->fd.fc->dmat, + error = fw_bus_dma_tag_create(/*parent*/fc->dmat, /* XXX shoud be 4 for sane backend? */ /*alignment*/1, /*boundary*/0, @@ -2137,7 +2150,7 @@ END_DEBUG /*maxsegsz*/SBP_SEG_MAX, /*flags*/BUS_DMA_ALLOCNOW, /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, + /*lockarg*/&sbp->mtx, &sbp->dmat); if (error != 0) { printf("sbp_attach: Could not allocate DMA tag " @@ -2160,20 +2173,20 @@ END_DEBUG SBP_SCSIBUS_ATTACH; /* We reserve 16 bit space (4 bytes X 64 unit X 256 luns) */ - dv_unit = device_get_unit(sbp->fd.dev); + 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, - sbp->fd.fc, (void *)sbp, sbp_recv); - fw_bindadd(sbp->fd.fc, &sbp->fwb); + 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 (sbp->fd.fc->status != FWBUSNOTREADY) { + if (fc->status != FWBUSNOTREADY) { s = splfw(); sbp_post_busreset((void *)sbp); sbp_post_explore((void *)sbp); @@ -2183,6 +2196,7 @@ END_DEBUG FW_ATTACH_RETURN(0); #if defined(__FreeBSD__) fail: + SBP_UNLOCK(sbp); cam_sim_free(sbp->sim, /*free_devq*/TRUE); return (ENXIO); #endif @@ -2204,7 +2218,7 @@ END_DEBUG sdev = target->luns[i]; if (sdev == NULL) continue; - callout_stop(&sdev->login_callout); + fw_callout_stop(&sdev->login_callout); if (sdev->status >= SBP_DEV_TOATTACH && sdev->status <= SBP_DEV_ATTACHED) sbp_mgm_orb(sdev, ORB_FUN_LGO, NULL); @@ -2247,7 +2261,7 @@ sbp_free_target(struct sbp_target *target) if (target->luns == NULL) return; - callout_stop(&target->mgm_ocb_timeout); + fw_callout_stop(&target->mgm_ocb_timeout); sbp = target->sbp; for (i = 0; i < target->num_lun; i++) sbp_free_sdev(target->luns[i]); @@ -2276,10 +2290,12 @@ 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); @@ -2293,6 +2309,7 @@ END_DEBUG fw_xferlist_remove(&sbp->fwb.xferlist); fw_bus_dma_tag_destroy(sbp->dmat); + fw_mtx_destroy(&sbp->mtx); return (0); } @@ -2307,15 +2324,17 @@ sbp_cam_detach_sdev(struct sbp_dev *sdev) 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); } - sbp_abort_all_ocbs(sdev, XS_DEV_NOT_THERE); } static void @@ -2327,7 +2346,7 @@ sbp_cam_detach_target(struct sbp_target *target) SBP_DEBUG(0) printf("sbp_detach_target %d\n", target->target_id); END_DEBUG - callout_stop(&target->scan_callout); + fw_callout_stop(&target->scan_callout); for (i = 0; i < target->num_lun; i++) sbp_cam_detach_sdev(target->luns[i]); } @@ -2376,11 +2395,11 @@ sbp_scsipi_detach_target(struct sbp_target *target) SBP_DEBUG(0) printf("sbp_detach_target %d\n", target->target_id); END_DEBUG - callout_stop(&target->scan_callout); + 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) - device_printf(sbp->fd.dev, "%d detach failed\n", + fw_printf(sbp->fd.dev, "%d detach failed\n", target->target_id); sbp->sc_bus = NULL; } @@ -2402,8 +2421,10 @@ 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 (method == 2) tsdev->status = SBP_DEV_LOGIN; @@ -2458,8 +2479,10 @@ sbp_timeout(void *arg) 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); sbp_agent_reset(sdev); break; @@ -2518,7 +2541,7 @@ END_DEBUG SBP_DEBUG(1) printf("%s:%d:%d:func_code 0x%04x: " "Invalid target (target needed)\n", - sbp ? device_get_nameunit(sbp->fd.dev) : "???", + sbp ? fw_get_nameunit(sbp->fd.dev) : "???", SCSI_XFER_TARGET(sxfer), SCSI_XFER_LUN(sxfer), SCSI_XFER_FUNCCODE(sxfer)); END_DEBUG @@ -2540,7 +2563,7 @@ END_DEBUG SBP_DEBUG(0) printf("%s:%d:%d func_code 0x%04x: " "Invalid target (no wildcard)\n", - device_get_nameunit(sbp->fd.dev), + fw_get_nameunit(sbp->fd.dev), sxfer->ccb_h.target_id, sxfer->ccb_h.target_lun, sxfer->ccb_h.func_code); END_DEBUG @@ -2561,13 +2584,14 @@ END_DEBUG 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", - device_get_nameunit(sbp->fd.dev), + fw_get_nameunit(sbp->fd.dev), SCSI_XFER_TARGET(sxfer), SCSI_XFER_LUN(sxfer), SCSI_XFER_10BCMD_DUMP(sxfer), SCSI_XFER_DIR(sxfer), @@ -2595,8 +2619,10 @@ END_DEBUG 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; @@ -2672,7 +2698,7 @@ SBP_DEBUG(1) #else "Volume size = %jd\n", #endif - device_get_nameunit(sbp->fd.dev), + 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 @@ -2706,7 +2732,7 @@ END_DEBUG SBP_DEBUG(1) printf("%s:%d:XPT_RESET_BUS: \n", - device_get_nameunit(sbp->fd.dev), cam_sim_path(sbp->sim)); + fw_get_nameunit(sbp->fd.dev), cam_sim_path(sbp->sim)); END_DEBUG SCSI_XFER_ERROR(sxfer) = XS_REQ_INVALID; @@ -2720,7 +2746,7 @@ END_DEBUG SBP_DEBUG(1) printf("%s:%d:%d XPT_PATH_INQ:.\n", - device_get_nameunit(sbp->fd.dev), + fw_get_nameunit(sbp->fd.dev), sxfer->ccb_h.target_id, sxfer->ccb_h.target_lun); END_DEBUG cpi->version_num = 1; /* XXX??? */ @@ -2764,7 +2790,7 @@ END_DEBUG scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; SBP_DEBUG(1) printf("%s:%d:%d XPT_GET_TRAN_SETTINGS:.\n", - device_get_nameunit(sbp->fd.dev), + 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; @@ -2910,6 +2936,7 @@ SBP_DEBUG(1) #endif __func__, ntohl(sbp_status->orb_lo), sbp_status->src); END_DEBUG + SBP_LOCK(sdev->target->sbp); for (ocb = STAILQ_FIRST(&sdev->ocbs); ocb != NULL; ocb = next) { next = STAILQ_NEXT(ocb, ocb); flags = ocb->flags; @@ -2918,7 +2945,7 @@ END_DEBUG STAILQ_REMOVE(&sdev->ocbs, ocb, sbp_ocb, ocb); if (ocb->sxfer != NULL) #if defined(__DragonFly__) || defined(__NetBSD__) - callout_stop(&SCSI_XFER_CALLOUT(ocb->sxfer)); + fw_callout_stop(&SCSI_XFER_CALLOUT(ocb->sxfer)); #else untimeout(sbp_timeout, (void *)ocb, SCSI_XFER_CALLOUT(ocb->sxfer)); @@ -2961,6 +2988,7 @@ END_DEBUG } else order ++; } + SBP_UNLOCK(sdev->target->sbp); splx(s); SBP_DEBUG(0) if (ocb && order > 0) { @@ -2991,7 +3019,7 @@ END_DEBUG if (ocb->sxfer != NULL) #if defined(__DragonFly__) || defined(__NetBSD__) - callout_reset(&SCSI_XFER_CALLOUT(ocb->sxfer), + 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, @@ -3025,6 +3053,8 @@ sbp_get_ocb(struct sbp_dev *sdev) { struct sbp_ocb *ocb; int s = splfw(); + + fw_mtx_assert(&sdev->target->sbp->mtx, MA_OWNED); ocb = STAILQ_FIRST(&sdev->free_ocbs); if (ocb == NULL) { sdev->flags |= ORB_SHORTAGE; @@ -3043,6 +3073,8 @@ sbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) { ocb->flags = 0; ocb->sxfer = NULL; + + SBP_LOCK(sdev->target->sbp); STAILQ_INSERT_TAIL(&sdev->free_ocbs, ocb, ocb); if ((sdev->flags & ORB_SHORTAGE) != 0) { int count; @@ -3052,6 +3084,7 @@ sbp_free_ocb(struct sbp_dev *sdev, struct sbp_ocb *ocb) sdev->freeze = 0; SBP_DEVICE_THAW(sdev, count); } + SBP_UNLOCK(sdev->target->sbp); } static void @@ -3081,13 +3114,15 @@ END_DEBUG } if (ocb->sxfer != NULL) { #if defined(__DragonFly__ ) || defined(__NetBSD__) - callout_stop(&SCSI_XFER_CALLOUT(ocb->sxfer)); + 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); } sbp_free_ocb(sdev, ocb); }