Date: Wed, 30 Sep 2009 02:50:10 +0000 (UTC) From: Sean Bruno <sbruno@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r197634 - projects/sbruno_firewire/sys/dev/firewire Message-ID: <200909300250.n8U2oAf6003090@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sbruno Date: Wed Sep 30 02:50:09 2009 New Revision: 197634 URL: http://svn.freebsd.org/changeset/base/197634 Log: Radical reworking of guts inside of sbp_targ. A lot of stuff going on here. sbp_targ.c -- add two new fwbind functions for the mandatory busy_timeout and reset_start CSRs(SBP-2) implement handler funcitons to handle these fwbinds -- extend the morb4 struct to be aligned with spec(SBP-2) -- define the unrestricted page table format per spec (SBP-2) -- define the agent state struct to better provide status to initiators -- enhance and implement locking and remove GIANT -- reach down into the fwohci stack and initiate a bus reset (ibr) whenever we enable/disable the lun -- align ourselves with CAM a bit better and assign status when needed -- handle transactions that require multiple CTIOs via sbp_targ_xfer_pt() and sbp_targ_fetch_pt() -- handle exclusive login capability from initiator and do the right thing. -- add sbp_targ_send_agent_state(), it doesn't do anything though. fwohci_pci.c -- remove meaningless #if 1 firewire.c -- implement config_intrhook() to allow CAM and others to initialize us more gracefully (thanks scottl, gibbs and others) -- manage node detection in an equally effective and simpler looping structure. fwohci.c -- move the bus_reset and SID interrupt handlers out of taskqueues and handle them immediately sbp.c -- implement a wrapper around xpt_done() to assist in debugging sbp hangs at boot. TBD add to debug level. fwcsr.c/h -- introduce common functions to handle CSR registration and deletion. Added: projects/sbruno_firewire/sys/dev/firewire/fwcsr.c projects/sbruno_firewire/sys/dev/firewire/fwcsr.h Modified: projects/sbruno_firewire/sys/dev/firewire/firewire.c projects/sbruno_firewire/sys/dev/firewire/firewirereg.h projects/sbruno_firewire/sys/dev/firewire/fwohci.c projects/sbruno_firewire/sys/dev/firewire/fwohci_pci.c projects/sbruno_firewire/sys/dev/firewire/sbp.c projects/sbruno_firewire/sys/dev/firewire/sbp_targ.c Modified: projects/sbruno_firewire/sys/dev/firewire/firewire.c ============================================================================== --- projects/sbruno_firewire/sys/dev/firewire/firewire.c Wed Sep 30 01:34:03 2009 (r197633) +++ projects/sbruno_firewire/sys/dev/firewire/firewire.c Wed Sep 30 02:50:09 2009 (r197634) @@ -77,7 +77,7 @@ struct crom_src_buf { struct crom_chunk hw; }; -int firewire_debug=0, try_bmr=1, hold_count=0; +int firewire_debug=1, try_bmr=1, hold_count=0; SYSCTL_INT(_debug, OID_AUTO, firewire_debug, CTLFLAG_RW, &firewire_debug, 0, "FireWire driver debug flag"); SYSCTL_NODE(_hw, OID_AUTO, firewire, CTLFLAG_RD, 0, "FireWire Subsystem"); @@ -103,13 +103,14 @@ static void firewire_xfer_timeout(void * static int firewire_shutdown (device_t); #endif static device_t firewire_add_child (device_t, int, const char *, int); -static void fw_try_bmr (void *); +static void fw_try_bmr (struct firewire_comm *); static void fw_try_bmr_callback (struct fw_xfer *); static void fw_asystart (struct fw_xfer *); static int fw_get_tlabel (struct firewire_comm *, struct fw_xfer *); static void fw_bus_probe (struct firewire_comm *); static void fw_attach_dev (struct firewire_comm *); static void fw_bus_probe_thread(void *); +static void fw_probe_init(void *); #ifdef FW_VMACCESS static void fw_vmaccess (struct fw_xfer *); #endif @@ -458,16 +459,27 @@ firewire_attach(device_t dev) mtx_init(&fc->wait_lock, "fwwait", NULL, MTX_DEF); mtx_init(&fc->tlabel_lock, "fwtlabel", NULL, MTX_DEF); CALLOUT_INIT(&fc->timeout_callout); +#if 0 CALLOUT_INIT(&fc->bmr_callout); CALLOUT_INIT(&fc->busprobe_callout); +#endif TASK_INIT(&fc->task_timeout, 0, firewire_xfer_timeout, (void *)fc); callout_reset(&sc->fc->timeout_callout, hz, (void *)firewire_watchdog, (void *)sc->fc); /* create thread */ - kproc_create(fw_bus_probe_thread, (void *)fc, &fc->probe_thread, - 0, 0, "fw%d_probe", unit); + if (kproc_create(fw_bus_probe_thread, (void *)sc, + &fc->probe_thread, 0, 0, "fw%d_probe", unit)) + panic("Could not create fw%d_probe thread\n", unit); + + sc->ich.ich_func = (void *)fw_probe_init; + sc->ich.ich_arg = (void *)sc; + if (config_intrhook_establish(&sc->ich) != 0) { + device_printf(sc->fc->dev, + "can't establish config hook\n"); + return(ENXIO); + } /* Locate our children */ bus_generic_probe(dev); @@ -475,11 +487,6 @@ firewire_attach(device_t dev) /* launch attachement of the added children */ bus_generic_attach(dev); - /* bus_reset */ - FW_GLOCK(fc); - fw_busreset(fc, FWBUSNOTREADY); - FW_GUNLOCK(fc); - fc->ibr(fc); return 0; } @@ -536,8 +543,11 @@ firewire_detach(device_t dev) printf("firewire probe thread didn't die\n"); mtx_unlock(&fc->wait_lock); - if (fc->arq !=0 && fc->arq->maxq > 0) + if (fc->arq !=0 && fc->arq->maxq > 0) { + FW_GLOCK(fc); fw_drain_txq(fc); + FW_GUNLOCK(fc); + } if ((err = fwdev_destroydev(sc)) != 0) return err; @@ -546,8 +556,10 @@ firewire_detach(device_t dev) return err; callout_stop(&fc->timeout_callout); +#if 0 callout_stop(&fc->bmr_callout); callout_stop(&fc->busprobe_callout); +#endif /* XXX xfer_free and untimeout on all xfers */ for (fwdev = STAILQ_FIRST(&fc->devices); fwdev != NULL; @@ -597,7 +609,7 @@ fw_drain_txq(struct firewire_comm *fc) STAILQ_INIT(&xfer_drain); - FW_GLOCK(fc); + FW_GLOCK_ASSERT(fc); fw_xferq_drain(fc->atq); fw_xferq_drain(fc->ats); for(i = 0; i < fc->nisodma; i++) @@ -617,6 +629,7 @@ fw_drain_txq(struct firewire_comm *fc) STAILQ_FOREACH_SAFE(xfer, &xfer_drain, tlabel, txfer) xfer->hand(xfer); + FW_GLOCK(fc); } static void @@ -741,8 +754,10 @@ fw_busreset(struct firewire_comm *fc, ui int i, devcnt; FW_GLOCK_ASSERT(fc); +#if 0 if (fc->status == FWBUSMGRELECT) callout_stop(&fc->bmr_callout); +#endif fc->status = new_status; fw_reset_csr(fc); @@ -756,8 +771,11 @@ fw_busreset(struct firewire_comm *fc, ui for( i = 0 ; i < devcnt ; i++) if (device_get_state(devlistp[i]) >= DS_ATTACHED) { fdc = device_get_softc(devlistp[i]); - if (fdc->post_busreset != NULL) + if (fdc->post_busreset != NULL) { + FW_GUNLOCK(fc); fdc->post_busreset(fdc); + FW_GLOCK(fc); + } } free(devlistp, M_TEMP); } @@ -1321,6 +1339,7 @@ void fw_sidrcv(struct firewire_comm* fc, union fw_self_id *self_id; u_int i, j, node, c_port = 0, i_branch = 0; + FW_GLOCK_ASSERT(fc); fc->sid_cnt = len /(sizeof(uint32_t) * 2); fc->max_node = fc->nodeid & 0x3f; CSRARC(fc, NODE_IDS) = ((uint32_t)fc->nodeid) << 16; @@ -1408,17 +1427,25 @@ void fw_sidrcv(struct firewire_comm* fc, if (fc->irm == fc->nodeid) { fc->status = FWBUSMGRDONE; CSRARC(fc, BUS_MGR_ID) = fc->set_bmr(fc, fc->irm); + FW_GUNLOCK(fc); fw_bmr(fc); + FW_GLOCK(fc); } else { fc->status = FWBUSMGRELECT; + fw_try_bmr(fc); +#if 0 callout_reset(&fc->bmr_callout, hz/8, (void *)fw_try_bmr, (void *)fc); +#endif } } else fc->status = FWBUSMGRDONE; +#if 0 callout_reset(&fc->busprobe_callout, hz/4, (void *)fw_bus_probe, (void *)fc); +#endif + fw_bus_probe(fc); } /* @@ -1716,79 +1743,109 @@ fw_find_self_id(struct firewire_comm *fc static void fw_explore(struct firewire_comm *fc) { - int node, err, s, i, todo, todo2, trys; - char nodes[63]; - struct fw_device dfwdev; - union fw_self_id *fwsid; - - todo = 0; - /* setup dummy fwdev */ - dfwdev.fc = fc; - dfwdev.speed = 0; - dfwdev.maxrec = 8; /* 512 */ - dfwdev.status = FWDEVINIT; - - for (node = 0; node <= fc->max_node; node ++) { - /* We don't probe myself and linkdown nodes */ - if (node == fc->nodeid) { - if (firewire_debug) - device_printf(fc->bdev, "%s:" - "found myself node(%d) fc->nodeid(%d) fc->max_node(%d)\n", - __func__, node, fc->nodeid, fc->max_node); - continue; - } else if (firewire_debug) { - device_printf(fc->bdev, "%s:" - "node(%d) fc->max_node(%d) found\n", - __func__, node, fc->max_node); - } - fwsid = fw_find_self_id(fc, node); - if (!fwsid || !fwsid->p0.link_active) { - if (firewire_debug) - device_printf(fc->bdev, "%s: node%d: link down\n", - __func__, node); - continue; - } - nodes[todo++] = node; - } - - s = splfw(); - for (trys = 0; todo > 0 && trys < 3; trys ++) { - todo2 = 0; - for (i = 0; i < todo; i ++) { - dfwdev.dst = nodes[i]; - err = fw_explore_node(&dfwdev); - if (err) - nodes[todo2++] = nodes[i]; - if (firewire_debug) - device_printf(fc->bdev, "%s: node %d, err = %d\n", - __func__, node, err); - } - todo = todo2; - } - splx(s); + int node, err, s, i; + struct fw_device dfwdev; + union fw_self_id *fwsid; + + /* setup dummy fwdev */ + dfwdev.fc = fc; + dfwdev.speed = 0; + dfwdev.maxrec = 8; /* 512 */ + dfwdev.status = FWDEVINIT; + + for (node = 0; node <= fc->max_node; node ++) { + /* We don't probe myself and linkdown nodes */ + if (node == fc->nodeid) { + if (firewire_debug) + device_printf(fc->bdev, "%s:" + "found myself node(%d) fc->nodeid(%d) fc->max_node(%d)\n", + __func__, node, fc->nodeid, fc->max_node); + continue; + } else if (firewire_debug) { + device_printf(fc->bdev, "%s:" + "node(%d) fc->max_node(%d) found\n", + __func__, node, fc->max_node); + } + + fwsid = fw_find_self_id(fc, node); + if (!fwsid || !fwsid->p0.link_active) { + if (firewire_debug) + device_printf(fc->bdev, "%s: node%d: link down\n", + __func__, node); + continue; + } + + s = splfw(); + dfwdev.dst = node; + for (i = 0; i < 3; i ++) { + err = fw_explore_node(&dfwdev); + if (firewire_debug) + device_printf(fc->bdev, "%s: node %d, err = %d\n", + __func__, node, err); + if (!err) /* If explore fails, retry else break inner loop */ + break; + } + if (firewire_debug && (i > 3) ) /* Failure to explore node */ + device_printf(fc->bdev, "%s: failure to explore node(%d) err(%d)\n", + __func__, node, err); + splx(s); + } } - +/* + * Used at system boot time to allow the bus_probe_thread + * to execute via config_intrhook + */ static void -fw_bus_probe_thread(void *arg) +fw_probe_init(void *arg) { + struct firewire_softc *sc; struct firewire_comm *fc; - fc = (struct firewire_comm *)arg; + sc = (struct firewire_softc *)arg; + fc = sc->fc; + printf("%s: started\n", __func__); mtx_lock(&fc->wait_lock); - while (fc->status != FWBUSDETACH) { - if (fc->status == FWBUSEXPLORE) { - mtx_unlock(&fc->wait_lock); - fw_explore(fc); - fc->status = FWBUSEXPDONE; - if (firewire_debug) - printf("bus_explore done\n"); - fw_attach_dev(fc); - mtx_lock(&fc->wait_lock); - } + fc->probe_init_state = 1; + /*wakeup(fc);*/ + /*msleep((void *)fw_probe_init, &fc->wait_lock, PWAIT|PCATCH, "-", 0);*/ + /* bus_reset */ + FW_GLOCK(fc); + fw_busreset(fc, FWBUSNOTREADY); + FW_GUNLOCK(fc); + mtx_unlock(&fc->wait_lock); + fc->ibr(fc); + printf("%s: finished\n", __func__); +} + +static void +fw_bus_probe_thread(void *arg) +{ + struct firewire_softc *sc = (struct firewire_softc *)arg; + struct firewire_comm *fc = sc->fc; + + mtx_lock(&fc->wait_lock); + do { + printf("%s: going to sleep\n", __func__); msleep((void *)fc, &fc->wait_lock, PWAIT|PCATCH, "-", 0); - } + printf("%s: awoke!\n", __func__); + if (fc->status != FWBUSDETACH) { + if (fc->status == FWBUSEXPLORE) { + mtx_unlock(&fc->wait_lock); + fw_explore(fc); + fc->status = FWBUSEXPDONE; + if (firewire_debug) + printf("bus_explore done\n"); + fw_attach_dev(fc); + mtx_lock(&fc->wait_lock); + } + } + if (fc->probe_init_state) { + fc->probe_init_state = 0; + config_intrhook_disestablish(&sc->ich); + } + } while (fc->status != FWBUSDETACH); mtx_unlock(&fc->wait_lock); kproc_exit(0); } @@ -2180,10 +2237,9 @@ error: * To candidate Bus Manager election process. */ static void -fw_try_bmr(void *arg) +fw_try_bmr(struct firewire_comm *fc) { struct fw_xfer *xfer; - struct firewire_comm *fc = (struct firewire_comm *)arg; struct fw_pkt *fp; int err = 0; Modified: projects/sbruno_firewire/sys/dev/firewire/firewirereg.h ============================================================================== --- projects/sbruno_firewire/sys/dev/firewire/firewirereg.h Wed Sep 30 01:34:03 2009 (r197633) +++ projects/sbruno_firewire/sys/dev/firewire/firewirereg.h Wed Sep 30 02:50:09 2009 (r197634) @@ -49,6 +49,7 @@ typedef struct proc fw_proc; #include <sys/uio.h> #include <sys/mutex.h> #include <sys/taskqueue.h> +#include <sys/kernel.h> #define splfw splimp @@ -79,6 +80,11 @@ struct firewire_softc { struct cdev *dev; #endif struct firewire_comm *fc; + struct intr_config_hook ich; + /* + * Used during initialization to wakeup + * sleeping parent thread + */ }; #define FW_MAX_DMACH 0x20 @@ -128,6 +134,7 @@ struct firewire_comm{ #define FWBUSPHYCONF 6 #define FWBUSEXPDONE 7 #define FWBUSCOMPLETION 10 + int probe_init_state; int nisodma; struct fw_eui64 eui; struct fw_xferq Added: projects/sbruno_firewire/sys/dev/firewire/fwcsr.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/sbruno_firewire/sys/dev/firewire/fwcsr.c Wed Sep 30 02:50:09 2009 (r197634) @@ -0,0 +1,89 @@ +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <sys/types.h> +#include <sys/conf.h> +#include <sys/malloc.h> + +#include <sys/bus.h> +#include <machine/bus.h> + +#include <dev/firewire/firewire.h> +#include <dev/firewire/firewirereg.h> +#include <dev/firewire/iec13213.h> +#include <dev/firewire/sbp.h> +#include <dev/firewire/fwmem.h> +#include <dev/firewire/fwcsr.h> + +/* + * Initialize callback for busy timeout + */ +void +fwcsr_busy_timeout_init(struct fw_bind *busy_timeout, + struct firewire_dev_comm *fd, + void *dev_softc, + void *callback, + struct malloc_type *dev_type, + uint32_t send_len, + uint32_t recv_len, + uint32_t max_lun) +{ + busy_timeout->start = 0xfffff0000000 | BUSY_TIMEOUT; + busy_timeout->end = 0xfffff0000000 | BUSY_TIMEOUT; + + STAILQ_INIT(&busy_timeout->xferlist); + fw_xferlist_add(&busy_timeout->xferlist, dev_type, + /*send*/ send_len, /*recv*/ recv_len, + max_lun, + fd->fc, dev_softc, callback); + fw_bindadd(fd->fc, busy_timeout); +} + +/* + * Terminate busy timeout callback + */ +void +fwcsr_busy_timeout_stop(struct fw_bind *busy_timeout, + struct firewire_dev_comm *fd) +{ + mtx_assert(&Giant, MA_OWNED); + fw_xferlist_remove(&busy_timeout->xferlist); + fw_bindremove(fd->fc, busy_timeout); +} + +/* + * Initialize the RESET START register + * handler and process the call back handler + */ +void +fwcsr_reset_start_init(struct fw_bind *reset_start, + struct firewire_dev_comm *fd, + void *dev_softc, + void *callback, + struct malloc_type *dev_type, + uint32_t send_len, + uint32_t recv_len, + uint32_t max_lun) +{ + reset_start->start = 0xfffff0000000 | RESET_START; + reset_start->end = 0xfffff0000000 | RESET_START; + + STAILQ_INIT(&reset_start->xferlist); + fw_xferlist_add(&reset_start->xferlist, dev_type, + /*send*/ send_len, /*recv*/ recv_len, + max_lun, + fd->fc, dev_softc, callback); + fw_bindadd(fd->fc, reset_start); +} + +/* + * Terminate processing of RESET_START register + */ +void +fwcsr_reset_start_stop(struct fw_bind *reset_start, + struct firewire_dev_comm *fd) +{ + fw_xferlist_remove(&reset_start->xferlist); + fw_bindremove(fd->fc, reset_start); +} Added: projects/sbruno_firewire/sys/dev/firewire/fwcsr.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/sbruno_firewire/sys/dev/firewire/fwcsr.h Wed Sep 30 02:50:09 2009 (r197634) @@ -0,0 +1,9 @@ +void fwcsr_busy_timeout_init(struct fw_bind *, struct firewire_dev_comm *, + void *, void *, struct malloc_type *, uint32_t, + uint32_t, uint32_t); +void fwcsr_busy_timeout_stop(struct fw_bind *, struct firewire_dev_comm *); + +void fwcsr_reset_start_init(struct fw_bind *, struct firewire_dev_comm *, + void *, void *, struct malloc_type *, uint32_t, + uint32_t, uint32_t); +void fwcsr_reset_start_stop(struct fw_bind *, struct firewire_dev_comm *); Modified: projects/sbruno_firewire/sys/dev/firewire/fwohci.c ============================================================================== --- projects/sbruno_firewire/sys/dev/firewire/fwohci.c Wed Sep 30 01:34:03 2009 (r197633) +++ projects/sbruno_firewire/sys/dev/firewire/fwohci.c Wed Sep 30 02:50:09 2009 (r197634) @@ -164,8 +164,7 @@ static uint32_t fwohci_cyctimer (struct static void fwohci_rbuf_update (struct fwohci_softc *, int); static void fwohci_tbuf_update (struct fwohci_softc *, int); void fwohci_txbufdb (struct fwohci_softc *, int , struct fw_bulkxfer *); -static void fwohci_task_busreset(void *, int); -static void fwohci_task_sid(void *, int); +static void fwohci_sid(struct fwohci_softc *); static void fwohci_task_dma(void *, int); /* @@ -771,8 +770,6 @@ fwohci_init(struct fwohci_softc *sc, dev taskqueue_thread_enqueue, &sc->fc.taskqueue); taskqueue_start_threads(&sc->fc.taskqueue, 1, PI_NET, "fw%d_taskq", device_get_unit(dev)); - TASK_INIT(&sc->fwohci_task_busreset, 2, fwohci_task_busreset, sc); - TASK_INIT(&sc->fwohci_task_sid, 1, fwohci_task_sid, sc); TASK_INIT(&sc->fwohci_task_dma, 0, fwohci_task_dma, sc); fw_init(&sc->fc); @@ -817,8 +814,6 @@ fwohci_detach(struct fwohci_softc *sc, d fwohci_db_free(&sc->ir[i]); } if (sc->fc.taskqueue != NULL) { - taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_busreset); - taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_sid); taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_dma); taskqueue_drain(sc->fc.taskqueue, &sc->fc.task_timeout); taskqueue_free(sc->fc.taskqueue); @@ -1843,7 +1838,7 @@ fwohci_intr_core(struct fwohci_softc *sc struct firewire_comm *fc = (struct firewire_comm *)sc; uint32_t node_id, plen; - FW_GLOCK_ASSERT(fc); + FW_GLOCK(fc); if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) { fc->status = FWBUSRESET; /* Disable bus reset interrupt until sid recv. */ @@ -1858,8 +1853,10 @@ fwohci_intr_core(struct fwohci_softc *sc OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN); sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING; - if (!kdb_active) - taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset); + fw_busreset(&sc->fc, FWBUSRESET); + + OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); + OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); } if (stat & OHCI_INT_PHY_SID) { /* Enable bus reset interrupt */ @@ -1909,12 +1906,16 @@ fwohci_intr_core(struct fwohci_softc *sc fc->status = FWBUSINIT; + fwohci_sid(sc); +#if 0 if (!kdb_active) taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid); +#endif } sidout: if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)) && (!kdb_active)) taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_dma); + FW_GUNLOCK(fc); } static void @@ -1995,26 +1996,14 @@ fwohci_intr_dma(struct fwohci_softc *sc, } static void -fwohci_task_busreset(void *arg, int pending) -{ - struct fwohci_softc *sc = (struct fwohci_softc *)arg; - - FW_GLOCK(&sc->fc); - 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])); - FW_GUNLOCK(&sc->fc); -} - -static void -fwohci_task_sid(void *arg, int pending) +fwohci_sid(struct fwohci_softc *sc) { - struct fwohci_softc *sc = (struct fwohci_softc *)arg; struct firewire_comm *fc = &sc->fc; uint32_t *buf; int i, plen; + FW_GLOCK_ASSERT(fc); /* * We really should have locking * here. Not sure why it's not @@ -2069,7 +2058,6 @@ fwohci_check_stat(struct fwohci_softc *s { uint32_t stat, irstat, itstat; - FW_GLOCK_ASSERT(&sc->fc); stat = OREAD(sc, FWOHCI_INTSTAT); if (stat == 0xffffffff) { device_printf(sc->fc.dev, @@ -2104,9 +2092,7 @@ fwohci_intr(void *arg) { struct fwohci_softc *sc = (struct fwohci_softc *)arg; - FW_GLOCK(&sc->fc); fwohci_check_stat(sc); - FW_GUNLOCK(&sc->fc); } void @@ -2114,9 +2100,7 @@ fwohci_poll(struct firewire_comm *fc, in { struct fwohci_softc *sc = (struct fwohci_softc *)fc; - FW_GLOCK(fc); fwohci_check_stat(sc); - FW_GUNLOCK(fc); } static void Modified: projects/sbruno_firewire/sys/dev/firewire/fwohci_pci.c ============================================================================== --- projects/sbruno_firewire/sys/dev/firewire/fwohci_pci.c Wed Sep 30 01:34:03 2009 (r197633) +++ projects/sbruno_firewire/sys/dev/firewire/fwohci_pci.c Wed Sep 30 02:50:09 2009 (r197634) @@ -91,7 +91,6 @@ static int fwohci_pci_detach(device_t se static int fwohci_pci_probe( device_t dev ) { -#if 1 uint32_t id; id = pci_get_devid(dev); @@ -212,7 +211,6 @@ fwohci_pci_probe( device_t dev ) device_set_desc(dev, "Sun PCIO-2"); return BUS_PROBE_DEFAULT; } -#endif if (pci_get_class(dev) == PCIC_SERIALBUS && pci_get_subclass(dev) == PCIS_SERIALBUS_FW && pci_get_progif(dev) == PCI_INTERFACE_OHCI) { Modified: projects/sbruno_firewire/sys/dev/firewire/sbp.c ============================================================================== --- projects/sbruno_firewire/sys/dev/firewire/sbp.c Wed Sep 30 01:34:03 2009 (r197633) +++ projects/sbruno_firewire/sys/dev/firewire/sbp.c Wed Sep 30 02:50:09 2009 (r197634) @@ -97,6 +97,11 @@ #define SBP_QUEUE_LEN ((SBP_DMA_SIZE - SBP_LOGIN_SIZE) / sizeof(struct sbp_ocb)) #define SBP_NUM_OCB (SBP_QUEUE_LEN * SBP_NUM_TARGETS) +#define SBP_XPT_DONE(ccb)\ + do { \ + xpt_print(ccb->ccb_h.path, "%s: func = %x, status = %x\n",\ + __func__, ccb->ccb_h.func_code, ccb->ccb_h.status); \ + } while (0) /* * STATUS FIFO addressing * bit @@ -806,12 +811,12 @@ sbp_post_busreset(void *arg) SBP_DEBUG(0) printf("sbp_post_busreset\n"); END_DEBUG + SBP_LOCK(sbp); if ((sbp->sim->flags & SIMQ_FREEZED) == 0) { - SBP_LOCK(sbp); - xpt_freeze_simq(sbp->sim, /*count*/1); sbp->sim->flags |= SIMQ_FREEZED; - SBP_UNLOCK(sbp); + xpt_freeze_simq(sbp->sim, /*count*/1); } + SBP_UNLOCK(sbp); microtime(&sbp->last_busreset); } @@ -1257,7 +1262,7 @@ END_DEBUG if(fw_asyreq(xfer->fc, -1, xfer) != 0){ sbp_xfer_free(xfer); ocb->ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ocb->ccb); + SBP_XPT_DONE(ocb->ccb); } SBP_LOCK(sdev->target->sbp); } @@ -1900,7 +1905,7 @@ END_DEBUG if (ccb->csio.cdb_io.cdb_bytes[0] == INQUIRY) sbp_fix_inq_data(ocb); SBP_LOCK(sbp); - xpt_done(ccb); + SBP_XPT_DONE(ccb); SBP_UNLOCK(sbp); } break; @@ -2370,7 +2375,7 @@ SBP_DEBUG(1) END_DEBUG ccb->ccb_h.status = CAM_DEV_NOT_THERE; - xpt_done(ccb); + SBP_XPT_DONE(ccb); return; } break; @@ -2390,7 +2395,7 @@ SBP_DEBUG(0) ccb->ccb_h.func_code); END_DEBUG ccb->ccb_h.status = CAM_DEV_NOT_THERE; - xpt_done(ccb); + SBP_XPT_DONE(ccb); return; } break; @@ -2433,7 +2438,7 @@ SBP_DEBUG(2) END_DEBUG if(sdev == NULL){ ccb->ccb_h.status = CAM_DEV_NOT_THERE; - xpt_done(ccb); + SBP_XPT_DONE(ccb); return; } #if 0 @@ -2444,7 +2449,7 @@ END_DEBUG printf("probe stage, periph name: %s\n", name); if (strcmp(name, "probe") != 0) { ccb->ccb_h.status = CAM_REQUEUE_REQ; - xpt_done(ccb); + SBP_XPT_DONE(ccb); return; } } @@ -2457,7 +2462,7 @@ END_DEBUG sdev->freeze ++; SBP_UNLOCK(sdev->target->sbp); } - xpt_done(ccb); + SBP_XPT_DONE(ccb); return; } @@ -2521,7 +2526,7 @@ printf("ORB %08x %08x %08x %08x\n", ntoh if (ccg->block_size == 0) { printf("sbp_action1: block_size is 0.\n"); ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); + SBP_XPT_DONE(ccb); break; } SBP_DEBUG(1) @@ -2557,7 +2562,7 @@ END_DEBUG #else cam_calc_geometry(ccg, /*extended*/1); #endif - xpt_done(ccb); + SBP_XPT_DONE(ccb); break; } case XPT_RESET_BUS: /* Reset the specified SCSI bus */ @@ -2569,7 +2574,7 @@ SBP_DEBUG(1) END_DEBUG ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); + SBP_XPT_DONE(ccb); break; } case XPT_PATH_INQ: /* Path routing inquiry */ @@ -2601,7 +2606,7 @@ END_DEBUG cpi->protocol_version = SCSI_REV_2; cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); + SBP_XPT_DONE(ccb); break; } case XPT_GET_TRAN_SETTINGS: @@ -2626,18 +2631,18 @@ SBP_DEBUG(1) ccb->ccb_h.target_id, ccb->ccb_h.target_lun); END_DEBUG cts->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); + SBP_XPT_DONE(ccb); break; } case XPT_ABORT: ccb->ccb_h.status = CAM_UA_ABORT; - xpt_done(ccb); + SBP_XPT_DONE(ccb); break; case XPT_SET_TRAN_SETTINGS: /* XXX */ default: ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); + SBP_XPT_DONE(ccb); break; } return; @@ -2939,7 +2944,7 @@ END_DEBUG ocb->ccb->ccb_h.timeout_ch); ocb->ccb->ccb_h.status = status; SBP_LOCK(sdev->target->sbp); - xpt_done(ocb->ccb); + SBP_XPT_DONE(ocb->ccb); SBP_UNLOCK(sdev->target->sbp); } sbp_free_ocb(sdev, ocb); Modified: projects/sbruno_firewire/sys/dev/firewire/sbp_targ.c ============================================================================== --- projects/sbruno_firewire/sys/dev/firewire/sbp_targ.c Wed Sep 30 01:34:03 2009 (r197633) +++ projects/sbruno_firewire/sys/dev/firewire/sbp_targ.c Wed Sep 30 02:50:09 2009 (r197634) @@ -41,6 +41,7 @@ #include <sys/types.h> #include <sys/conf.h> #include <sys/malloc.h> +#include <sys/mutex.h> #if __FreeBSD_version < 500000 #include <sys/devicestat.h> #endif @@ -53,6 +54,7 @@ #include <dev/firewire/iec13213.h> #include <dev/firewire/sbp.h> #include <dev/firewire/fwmem.h> +#include <dev/firewire/fwcsr.h> #include <cam/cam.h> #include <cam/cam_ccb.h> @@ -61,6 +63,7 @@ #include <cam/cam_debug.h> #include <cam/cam_periph.h> #include <cam/scsi/scsi_all.h> +#include <cam/scsi/scsi_message.h> #define SBP_TARG_RECV_LEN 8 #define MAX_INITIATORS 8 @@ -73,9 +76,10 @@ * BASE 0xffff f001 0000 management port * BASE 0xffff f001 0020 command port for login id 0 * BASE 0xffff f001 0040 command port for login id 1 + * BASE 0xffff f001 (0x20 * [login_id + 1]) for login_id * */ -#define SBP_TARG_MGM 0x10000 /* offset from 0xffff f000 000 */ +#define SBP_TARG_MGM 0x10000 /* offset from 0xffff f000 0000 */ #define SBP_TARG_BIND_HI 0xffff #define SBP_TARG_BIND_LO(l) (0xf0000000 + SBP_TARG_MGM + 0x20 * ((l) + 1)) #define SBP_TARG_BIND_START (((u_int64_t)SBP_TARG_BIND_HI << 32) | \ @@ -88,15 +92,20 @@ #define FETCH_CMD 1 #define FETCH_POINTER 2 -#define F_LINK_ACTIVE (1 << 0) -#define F_ATIO_STARVED (1 << 1) -#define F_LOGIN (1 << 2) -#define F_HOLD (1 << 3) -#define F_FREEZED (1 << 4) +#define F_LINK_ACTIVE (1 << 0) /* The F/W link is active */ +#define F_ATIO_STARVED (1 << 1) /* We are out of ATIO's */ +#define F_LOGIN (1 << 2) /* This initiator has logged in */ +#define F_HOLD (1 << 3) /* Hold on to this login */ +#define F_FREEZED (1 << 4) /* Frozen login, usually a bus reset occured */ +#define F_RECYCLE_LOGIN (1 << 5) /* This login is to be reused due */ + /* to login before SBP_TARG_HOLD_TIMEOUT */ +#define F_EXCLUSIVE (1 << 6) /* Reject all other logins. */ + +#define SBP_TARG_HOLD_TIMEOUT 1 MALLOC_DEFINE(M_SBP_TARG, "sbp_targ", "SBP-II/FireWire target mode"); -static int debug = 0; +static int debug = 1; SYSCTL_INT(_debug, OID_AUTO, sbp_targ_debug, CTLFLAG_RW, &debug, 0, "SBP target mode debug flag"); @@ -134,6 +143,8 @@ struct sbp_targ_softc { struct cam_sim *sim; struct cam_path *path; struct fw_bind fwb; + struct fw_bind busy_timeout; + struct fw_bind reset_start; int ndevs; int flags; struct crom_chunk unit; @@ -171,6 +182,10 @@ struct corb4 { struct morb4 { #if BYTE_ORDER == BIG_ENDIAN + uint16_t reserved; + uint16_t off_hi; + uint32_t off_lo; + uint64_t reserved2; uint32_t n:1, rq_fmt:2, :9, @@ -182,9 +197,26 @@ struct morb4 { :9, rq_fmt:2, n:1; + uint64_t reserved2; + uint32_t off_lo; + uint16_t off_hi; + uint16_t reserved; #endif }; +/* + * Urestricted page table format + * states that the segment length + * and high base addr are in the first + * 32 bits and the base low is in + * the second + */ +struct unrestricted_page_table_fmt { + uint16_t segment_len; + uint16_t segment_base_high; + uint32_t segment_base_low; +}; + struct orb_info { struct sbp_targ_softc *sc; struct fw_device *fwdev; @@ -207,10 +239,24 @@ struct orb_info { struct corb4 orb4; STAILQ_ENTRY(orb_info) link; uint32_t orb[8]; - uint32_t *page_table; + struct unrestricted_page_table_fmt *page_table; + struct unrestricted_page_table_fmt *cur_pte; + struct unrestricted_page_table_fmt *last_pte; + uint32_t last_block_read; struct sbp_status status; }; +struct agent_state { + uint32_t fetch_agent_state; +#define AGENT_STATE_RESET 0 +#define AGENT_STATE_ACTIVE 1 +#define AGENT_STATE_SUSPENDED 2 +#define AGENT_STATE_DEAD 3 + uint32_t bus_reset_command_reset_init_vals; + uint32_t read_vals; + uint32_t write_effects; +}; + static char *orb_fun_name[] = { ORB_FUN_NAMES }; @@ -219,6 +265,8 @@ static void sbp_targ_recv(struct fw_xfer static void sbp_targ_fetch_orb(struct sbp_targ_softc *, struct fw_device *, uint16_t, uint32_t, struct sbp_targ_login *, int); static void sbp_targ_abort(struct sbp_targ_softc *, struct orb_info *); +static void sbp_targ_xfer_pt(struct orb_info *); +static void sbp_targ_send_agent_state(struct fw_xfer *, int state); static void sbp_targ_identify(driver_t *driver, device_t parent) @@ -251,13 +299,19 @@ sbp_targ_dealloc_login(struct sbp_targ_l } for (orbi = STAILQ_FIRST(&login->orbs); orbi != NULL; orbi = next) { next = STAILQ_NEXT(orbi, link); + if (debug) + printf("%s: free orbi %p\n", __func__, orbi); free(orbi, M_SBP_TARG); + orbi = NULL; } callout_stop(&login->hold_callout); STAILQ_REMOVE(&login->lstate->logins, login, sbp_targ_login, link); login->lstate->sc->logins[login->id] = NULL; + if (debug) + printf("%s: free login %p\n", __func__, login); free((void *)login, M_SBP_TARG); + login = NULL; } static void @@ -267,12 +321,25 @@ sbp_targ_hold_expire(void *arg) login = (struct sbp_targ_login *)arg; - if (login->flags & F_HOLD) { - printf("%s: login_id=%d expired\n", __func__, login->id); - sbp_targ_dealloc_login(login); - } else { - printf("%s: login_id=%d not hold\n", __func__, login->id); - } + /* if the login has been deallocated + * prior to the login timeout, login + * should be NULL, and we should do + * nothing + */ + if (login != NULL ) { + if (login->flags & F_HOLD) { + if (debug) + printf("%s: login(%p), " + "login_id=%d expired\n", + __func__, login, login->id); + sbp_targ_dealloc_login(login); + } else if (debug) { + printf("%s: login(%p), " + "login_id=%d not hold\n", + __func__, login, login->id); + } + } else if (debug) + printf("%s: woke up and this login was NULL\n", __func__); } static void @@ -292,14 +359,15 @@ sbp_targ_post_busreset(void *arg) unit = &sc->unit; + SBP_LOCK(sc); if ((sc->flags & F_FREEZED) == 0) { - SBP_LOCK(sc); sc->flags |= F_FREEZED; + printf("%s: freezing simq\n", __func__); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909300250.n8U2oAf6003090>