summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2004-07-20 20:32:03 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2004-07-20 20:32:03 +0000
commit0066da537c51c58d6f5acb9e239b3a3027b9f442 (patch)
tree90dc1aa48985ea3caf25f10ec08d90be749e1670 /sys
parent5ee2de3755d1cfb57f96c46d6b7a4c5207720c76 (diff)
Work in progress to support daughterboards. The driver now will attach a
second scsi bus if a SCSI daughterboard is present, and is supposed to know about this and send scsi commands to the appropriate bus. Unfortunately probing the second bus does not report any device at the moment (though you can boot off it), but I can't see the issue at the moment. Thanks to tdeval@ for lending a few boards equipped with daughterboards for testing.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/mvme88k/dev/vs.c121
-rw-r--r--sys/arch/mvme88k/dev/vsreg.h6
-rw-r--r--sys/arch/mvme88k/dev/vsvar.h6
3 files changed, 92 insertions, 41 deletions
diff --git a/sys/arch/mvme88k/dev/vs.c b/sys/arch/mvme88k/dev/vs.c
index bac621c582b..053cbd725a7 100644
--- a/sys/arch/mvme88k/dev/vs.c
+++ b/sys/arch/mvme88k/dev/vs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vs.c,v 1.48 2004/07/20 20:28:54 miod Exp $ */
+/* $OpenBSD: vs.c,v 1.49 2004/07/20 20:32:02 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
@@ -107,12 +107,12 @@ void vs_link_sg_element(sg_list_element_t *, vaddr_t, int);
void vs_link_sg_list(sg_list_element_t *, vaddr_t, int);
int vs_nintr(void *);
int vs_poll(struct vs_softc *, struct scsi_xfer *);
-void vs_reset(struct vs_softc *);
+int vs_queue_number(struct scsi_link *, struct vs_softc *);
+void vs_reset(struct vs_softc *, int);
void vs_resync(struct vs_softc *);
void vs_scsidone(struct vs_softc *, struct scsi_xfer *, int);
static __inline__ void vs_clear_return_info(struct vs_softc *);
-static __inline__ int vs_queue_number(int, int);
static __inline__ paddr_t kvtop(vaddr_t);
int
@@ -136,7 +136,8 @@ vsattach(struct device *parent, struct device *self, void *args)
{
struct vs_softc *sc = (struct vs_softc *)self;
struct confargs *ca = args;
- int evec;
+ struct scsi_link *sc_link;
+ int evec, bus;
int tmp;
/* get the next available vector for the error interrupt */
@@ -166,13 +167,6 @@ vsattach(struct device *parent, struct device *self, void *args)
if (vs_initialize(sc))
return;
- sc->sc_link.adapter_softc = sc;
- sc->sc_link.adapter_target = sc->sc_pid;
- sc->sc_link.adapter = &vs_scsiswitch;
- sc->sc_link.device = &vs_scsidev;
- sc->sc_link.luns = 1;
- sc->sc_link.openings = NUM_IOPB / 8;
-
sc->sc_ih_n.ih_fn = vs_nintr;
sc->sc_ih_n.ih_arg = sc;
sc->sc_ih_n.ih_wantframe = 0;
@@ -193,14 +187,43 @@ vsattach(struct device *parent, struct device *self, void *args)
evcount_attach(&sc->sc_intrcnt_e, sc->sc_intrname_e,
(void *)&sc->sc_ih_e.ih_ipl, &evcount_intr);
+ printf("SCSI ID");
+
+ for (bus = 0; bus < 2; bus++) {
+ if (sc->sc_id[bus] < 0)
+ continue;
+
+ sc_link = &sc->sc_link[bus];
+ sc_link->adapter = &vs_scsiswitch;
+ sc_link->adapter_buswidth = 8;
+ sc_link->adapter_softc = sc;
+ sc_link->adapter_target = sc->sc_id[bus];
+ sc_link->device = &vs_scsidev;
+ sc_link->luns = 1;
+ sc_link->openings = NUM_IOPB / 8;
+ if (bus != 0)
+ sc_link->flags = SDEV_2NDBUS;
+
+ printf("%c%d", bus == 0 ? ' ' : '/', sc->sc_id[bus]);
+ }
+
+ printf("\n");
+
/*
- * attach all scsi units on us, watching for boot device
+ * Attach all scsi units on us, watching for boot device
* (see dk_establish).
*/
tmp = bootpart;
if (sc->sc_paddr != bootaddr)
bootpart = -1; /* invalid flag to dk_establish */
- config_found(self, &sc->sc_link, scsiprint);
+
+ for (bus = 0; bus < 2; bus++) {
+ if (sc->sc_id[bus] < 0)
+ continue;
+
+ config_found(self, &sc->sc_link[bus], scsiprint);
+ }
+
bootpart = tmp; /* restore old value */
}
@@ -208,10 +231,16 @@ int
do_vspoll(struct vs_softc *sc, struct scsi_xfer *xs, int to, int canreset)
{
int i;
- int crsw;
+ int crsw, bus;
- if (to <= 0 ) to = 50000;
- /* use cmd_wait values? */
+ if (xs != NULL)
+ bus = !!(xs->sc_link->flags & SDEV_2NDBUS);
+ else
+ bus = -1;
+
+ /* XXX use cmd_wait values */
+ if (to <= 0)
+ to = 50000;
i = 10000;
while (((crsw = CRSW) & (M_CRSW_CRBV | M_CRSW_CC)) == 0) {
@@ -220,7 +249,7 @@ do_vspoll(struct vs_softc *sc, struct scsi_xfer *xs, int to, int canreset)
--to;
if (to <= 0) {
if (canreset) {
- vs_reset(sc);
+ vs_reset(sc, bus);
vs_resync(sc);
}
if (xs == NULL)
@@ -283,7 +312,7 @@ thaw_all_queues(struct vs_softc *sc)
{
int i;
- for (i = 1; i <= 7; i++)
+ for (i = 1; i < NUM_WQ ; i++)
thaw_queue(sc, i);
}
@@ -291,18 +320,18 @@ void
vs_scsidone(struct vs_softc *sc, struct scsi_xfer *xs, int stat)
{
int tgt;
+
+ tgt = vs_queue_number(xs->sc_link, sc);
xs->status = stat;
while (xs->status == SCSI_CHECK) {
vs_chksense(xs);
- tgt = vs_queue_number(xs->sc_link->target, sc->sc_pid);
thaw_queue(sc, tgt);
}
- tgt = vs_queue_number(xs->sc_link->target, sc->sc_pid);
xs->flags |= ITSDONE;
-
thaw_queue(sc, tgt);
+
scsi_done(xs);
}
@@ -336,7 +365,8 @@ vs_scsicmd(struct scsi_xfer *xs)
(u_int8_t *)xs->cmd, xs->cmdlen);
vs_write(2, iopb + IOPB_CMD, IOPB_PASSTHROUGH);
- vs_write(2, iopb + IOPB_UNIT, IOPB_UNIT_VALUE(slp->target, slp->lun));
+ vs_write(2, iopb + IOPB_UNIT,
+ IOPB_UNIT_VALUE(!!(slp->flags & SDEV_2NDBUS), slp->target, slp->lun));
vs_write(1, iopb + IOPB_NVCT, sc->sc_nvec);
vs_write(1, iopb + IOPB_EVCT, sc->sc_evec);
@@ -372,7 +402,7 @@ vs_scsicmd(struct scsi_xfer *xs)
vs_write(2, cqep + CQE_IOPB_ADDR, iopb);
vs_write(1, cqep + CQE_IOPB_LENGTH, iopb_len);
vs_write(1, cqep + CQE_WORK_QUEUE,
- flags & SCSI_POLL ? 0 : vs_queue_number(slp->target, sc->sc_pid));
+ flags & SCSI_POLL ? 0 : vs_queue_number(slp, sc));
MALLOC(m328_cmd, M328_CMD*, sizeof(M328_CMD), M_DEVBUF, M_WAITOK);
@@ -427,7 +457,8 @@ vs_chksense(struct scsi_xfer *xs)
mce_iopb_write(2, IOPB_ADDR, ADDR_MOD);
mce_iopb_write(4, IOPB_BUFF, kvtop((vaddr_t)&xs->sense));
mce_iopb_write(4, IOPB_LENGTH, sizeof(struct scsi_sense_data));
- mce_iopb_write(2, IOPB_UNIT, IOPB_UNIT_VALUE(slp->target, slp->lun));
+ mce_iopb_write(2, IOPB_UNIT,
+ IOPB_UNIT_VALUE(!!(slp->flags & SDEV_2NDBUS), slp->target, slp->lun));
vs_bzero(sh_MCE, CQE_SIZE);
mce_write(2, CQE_IOPB_ADDR, sh_MCE_IOPB);
@@ -513,13 +544,15 @@ vs_initialize(struct vs_softc *sc)
}
/* initialize channels id */
- sc->sc_pid = csb_read(1, CSB_PID);
- sc->sc_sid = -1;
+ sc->sc_id[0] = csb_read(1, CSB_PID);
+ sc->sc_id[1] = -1;
switch (dbid = csb_read(1, CSB_DBID)) {
case DBID_SCSI2:
case DBID_SCSI:
+#if 0
printf("daughter board, ");
- sc->sc_sid = csb_read(1, CSB_SID);
+#endif
+ sc->sc_id[1] = csb_read(1, CSB_SID);
break;
case DBID_PRINTER:
printf("printer port, ");
@@ -539,8 +572,8 @@ vs_initialize(struct vs_softc *sc)
cib_write(2, CIB_BURST, 0);
cib_write(2, CIB_NVECT, (sc->sc_ipl << 8) | sc->sc_nvec);
cib_write(2, CIB_EVECT, (sc->sc_ipl << 8) | sc->sc_evec);
- cib_write(2, CIB_PID, sc->sc_pid);
- cib_write(2, CIB_SID, 0); /* disable second channel */
+ cib_write(2, CIB_PID, 0x08); /* XXX default */
+ cib_write(2, CIB_SID, 0x08);
cib_write(2, CIB_CRBO, sh_CRB);
cib_write(4, CIB_SELECT, SELECTION_TIMEOUT);
cib_write(4, CIB_WQTIMO, 4);
@@ -572,7 +605,7 @@ vs_initialize(struct vs_softc *sc)
do_vspoll(sc, NULL, 0, 1);
/* initialize work queues */
- for (i = 1; i < 8; i++) {
+ for (i = 1; i < NUM_WQ; i++) {
vs_bzero(sh_MCE_IOPB, IOPB_LONG_SIZE);
mce_iopb_write(2, WQCF_CMD, CNTR_INIT_WORKQ);
mce_iopb_write(2, WQCF_OPTION, 0);
@@ -847,14 +880,30 @@ vs_clear_return_info(struct vs_softc *sc)
/*
* Choose the work queue number for a specific target.
*
- * Targets on the primary channel should be mapped to queues 1-7,
- * so we assign each target the queue matching its own number, except for
- * target zero which gets assigned to the queue matching the controller id.
+ * Targets on the primary channel are mapped to queues 1-7, while targets
+ * on the secondary channel are mapped to queues 8-14.
+ * To do so, we assign each target the queue matching its own number,
+ * plus eight on the secondary bus, except for target 0 on the first channel
+ * and 7 on the secondary channel which gets assigned to the queue matching
+ * the controller id.
*/
-static int
-vs_queue_number(int target, int host)
+int
+vs_queue_number(struct scsi_link *sl, struct vs_softc *sc)
{
- return target == 0 ? host : target;
+ int bus;
+
+ bus = !!(sl->flags & SDEV_2NDBUS);
+
+ if (sl->target == sc->sc_id[bus])
+ return 0;
+
+ if (bus == 0)
+ return sl->target == 0 ? sc->sc_id[bus] : sl->target;
+ else
+ if (sl->target > sc->sc_id[bus])
+ return 8 + sl->target - 1;
+ else
+ return 8 + sl->target;
}
/*
diff --git a/sys/arch/mvme88k/dev/vsreg.h b/sys/arch/mvme88k/dev/vsreg.h
index 0e45179e438..b5a5664882a 100644
--- a/sys/arch/mvme88k/dev/vsreg.h
+++ b/sys/arch/mvme88k/dev/vsreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vsreg.h,v 1.11 2004/07/19 20:35:37 miod Exp $ */
+/* $OpenBSD: vsreg.h,v 1.12 2004/07/20 20:32:02 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
* Copyright (c) 1999 Steve Murphree, Jr.
@@ -56,6 +56,7 @@
#define NUM_CQE 10
#define NUM_IOPB NUM_CQE
+#define NUM_WQ 15
/*
* Master Control Status Block (MCSB)
@@ -341,7 +342,8 @@
#define CNTR_ISSUE_ABORT 0x4e /* abort has been issued */
#define CNTR_DOWNLOAD_FIRMWARE 0x4f /* download firmware (COUGAR) */
-#define IOPB_UNIT_VALUE(target, lun) ((lun) << 3 | (target & 7))
+#define IOPB_UNIT_VALUE(bus, target, lun) \
+ (((bus) << 6) | ((lun) << 3) | (target & 7))
/*
* Memory types
diff --git a/sys/arch/mvme88k/dev/vsvar.h b/sys/arch/mvme88k/dev/vsvar.h
index 27b9ac7ce79..7c606636f6d 100644
--- a/sys/arch/mvme88k/dev/vsvar.h
+++ b/sys/arch/mvme88k/dev/vsvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vsvar.h,v 1.14 2004/07/02 14:00:43 miod Exp $ */
+/* $OpenBSD: vsvar.h,v 1.15 2004/07/20 20:32:02 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
* Copyright (c) 1999 Steve Murphree, Jr.
@@ -100,8 +100,8 @@ struct vs_softc {
char sc_intrname_e[16 + 4];
int sc_ipl;
int sc_evec, sc_nvec;
- int sc_pid, sc_sid;
- struct scsi_link sc_link;
+ int sc_id[2];
+ struct scsi_link sc_link[2];
};
/* Access macros */