diff options
-rw-r--r-- | sys/arch/mvme88k/dev/vs.c | 76 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/vsvar.h | 4 |
2 files changed, 64 insertions, 16 deletions
diff --git a/sys/arch/mvme88k/dev/vs.c b/sys/arch/mvme88k/dev/vs.c index 04eded4d60d..f1240f108ac 100644 --- a/sys/arch/mvme88k/dev/vs.c +++ b/sys/arch/mvme88k/dev/vs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vs.c,v 1.38 2004/05/22 19:34:12 miod Exp $ */ +/* $OpenBSD: vs.c,v 1.39 2004/05/22 21:02:38 miod Exp $ */ /* * Copyright (c) 2004, Miodrag Vallat. @@ -110,6 +110,7 @@ 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); int vsmatch(struct device *device, void *cf, void *args) @@ -145,21 +146,25 @@ vsattach(struct device *parent, struct device *self, void *args) if (ca->ca_ipl < 0) ca->ca_ipl = IPL_BIO; - printf(" vec 0x%x", evec); + printf(" vec 0x%x: ", evec); sc->sc_paddr = ca->ca_paddr; sc->sc_iot = ca->ca_iot; if (bus_space_map(sc->sc_iot, sc->sc_paddr, S_SHORTIO, 0, &sc->sc_ioh) != 0) { - printf(": can't map registers!\n"); + printf("can't map registers!\n"); return; } sc->sc_ipl = ca->ca_ipl; sc->sc_nvec = ca->ca_vec; sc->sc_evec = evec; + + if (vs_initialize(sc)) + return; + sc->sc_link.adapter_softc = sc; - sc->sc_link.adapter_target = 7; + 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; @@ -175,9 +180,6 @@ vsattach(struct device *parent, struct device *self, void *args) sc->sc_ih_e.ih_wantframe = 0; sc->sc_ih_e.ih_ipl = ca->ca_ipl; - if (vs_initialize(sc)) - return; - vmeintr_establish(sc->sc_nvec, &sc->sc_ih_n); vmeintr_establish(sc->sc_evec, &sc->sc_ih_e); evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt_n); @@ -273,11 +275,11 @@ vs_scsidone(struct vs_softc *sc, struct scsi_xfer *xs, int stat) while (xs->status == SCSI_CHECK) { vs_chksense(xs); - tgt = xs->sc_link->target + 1; + tgt = vs_queue_number(xs->sc_link->target, sc->sc_pid); thaw_queue(sc, tgt); } - tgt = xs->sc_link->target + 1; + tgt = vs_queue_number(xs->sc_link->target, sc->sc_pid); xs->flags |= ITSDONE; /* thaw all work queues */ @@ -351,7 +353,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 : slp->target + 1); + flags & SCSI_POLL ? 0 : vs_queue_number(slp->target, sc->sc_pid)); MALLOC(m328_cmd, M328_CMD*, sizeof(M328_CMD), M_DEVBUF, M_WAITOK); @@ -464,7 +466,35 @@ vs_getiopb(struct vs_softc *sc) int vs_initialize(struct vs_softc *sc) { - int i; + int i, msr; + + /* + * Reset the board, and wait for it to get ready. + * The reset signal is applied for 70 usec, and the board status + * is not tested until 100 usec after the reset signal has been + * cleared, per the manual (MVME328/D1) pages 4-6 and 4-9. + */ + + mcsb_write(2, MCSB_MCR, M_MCR_RES | M_MCR_SFEN); + delay(70); + mcsb_write(2, MCSB_MCR, M_MCR_SFEN); + + delay(100); + i = 0; + for (;;) { + msr = mcsb_read(2, MCSB_MSR); + if ((msr & (M_MSR_BOK | M_MSR_CNA)) == M_MSR_BOK) + break; + if (++i > 5000) { + printf("board reset failed, status %x\n", msr); + return 1; + } + delay(1000); + } + + /* initialize channels id */ + sc->sc_pid = csb_read(1, CSB_PID); + sc->sc_sid = csb_read(1, CSB_SID); CRB_CLR_DONE; mcsb_write(2, MCSB_QHDP, 0); @@ -474,8 +504,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, 7); - cib_write(2, CIB_SID, 0); + cib_write(2, CIB_PID, sc->sc_pid); + cib_write(2, CIB_SID, 0); /* disable second channel */ cib_write(2, CIB_CRBO, sh_CRB); cib_write(4, CIB_SELECT, SELECTION_TIMEOUT); cib_write(4, CIB_WQTIMO, 4); @@ -551,7 +581,7 @@ vs_initialize(struct vs_softc *sc) vs_reset(sc); /* sync all devices */ vs_resync(sc); - printf(": SCSI ID %d\n", sc->sc_link.adapter_target); + printf("SCSI ID %d\n", sc->sc_pid); return 0; } @@ -560,7 +590,10 @@ vs_resync(struct vs_softc *sc) { int i; - for (i = 0; i < 7; i++) { + for (i = 0; i < 8; i++) { + if (i == sc->sc_pid) + continue; + vs_bzero(sh_MCE_IOPB, IOPB_SHORT_SIZE); mce_iopb_write(2, DRCF_CMD, CNTR_DEV_REINIT); mce_iopb_write(2, DRCF_OPTION, 0); /* no interrupts yet */ @@ -780,6 +813,19 @@ 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. + */ +static int +vs_queue_number(int target, int host) +{ + return target == 0 ? host : target; +} + +/* * Useful functions for scatter/gather list */ diff --git a/sys/arch/mvme88k/dev/vsvar.h b/sys/arch/mvme88k/dev/vsvar.h index 6e8bde1ad05..e83d20f11cc 100644 --- a/sys/arch/mvme88k/dev/vsvar.h +++ b/sys/arch/mvme88k/dev/vsvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vsvar.h,v 1.12 2004/05/22 21:00:44 miod Exp $ */ +/* $OpenBSD: vsvar.h,v 1.13 2004/05/22 21:02:38 miod Exp $ */ /* * Copyright (c) 2004, Miodrag Vallat. * Copyright (c) 1999 Steve Murphree, Jr. @@ -98,6 +98,7 @@ struct vs_softc { struct evcnt sc_intrcnt_e, sc_intrcnt_n; int sc_ipl; int sc_evec, sc_nvec; + int sc_pid, sc_sid; struct scsi_link sc_link; }; @@ -114,6 +115,7 @@ struct vs_softc { #define cib_write(w,o,v) vs_write(w, sh_CIB + (o), (v)) #define crb_read(w,o) vs_read(w, sh_CRB + (o)) #define crb_write(w,o,v) vs_write(w, sh_CRB + (o), (v)) +#define csb_read(w,o) vs_read(w, sh_CSS + (o)) #define mce_read(w,o) vs_read(w, sh_MCE + (o)) #define mce_write(w,o,v) vs_write(w, sh_MCE + (o), (v)) #define mce_iopb_read(w,o) vs_read(w, sh_MCE_IOPB + (o)) |