svn commit: r197634 - projects/sbruno_firewire/sys/dev/firewire
Sean Bruno
sbruno at FreeBSD.org
Wed Sep 30 02:50:10 UTC 2009
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 ***
More information about the svn-src-projects
mailing list