Skip site navigation (1)Skip section navigation (2)
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>