summaryrefslogtreecommitdiff
path: root/sys/arch/vax/mscp/mscp_subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/vax/mscp/mscp_subr.c')
-rw-r--r--sys/arch/vax/mscp/mscp_subr.c404
1 files changed, 227 insertions, 177 deletions
diff --git a/sys/arch/vax/mscp/mscp_subr.c b/sys/arch/vax/mscp/mscp_subr.c
index 0452ff14b3e..c94d5919563 100644
--- a/sys/arch/vax/mscp/mscp_subr.c
+++ b/sys/arch/vax/mscp/mscp_subr.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mscp_subr.c,v 1.2 1997/05/29 00:05:03 niklas Exp $ */
-/* $NetBSD: mscp_subr.c,v 1.6 1997/01/11 11:20:34 ragge Exp $ */
+/* $OpenBSD: mscp_subr.c,v 1.3 2000/04/27 03:14:46 bjc Exp $ */
+/* $NetBSD: mscp_subr.c,v 1.12 1999/06/06 19:16:18 ragge Exp $ */
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* Copyright (c) 1988 Regents of the University of California.
@@ -49,32 +49,42 @@
#include <sys/systm.h>
#include <sys/proc.h>
+#include <machine/bus.h>
#include <machine/sid.h>
-#include <vax/mscp/mscp.h>
-#include <vax/mscp/mscpreg.h>
-#include <vax/mscp/mscpvar.h>
+#include <arch/vax/mscp/mscp.h>
+#include <arch/vax/mscp/mscpreg.h>
+#include <arch/vax/mscp/mscpvar.h>
#include "ra.h"
#include "mt.h"
-#define b_forw b_hash.le_next
+#define b_forw b_hash.le_next
-int mscp_match __P((struct device *, void *, void *));
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+int mscp_match __P((struct device *, struct cfdata *, void *));
void mscp_attach __P((struct device *, struct device *, void *));
-void mscp_start __P((struct mscp_softc *));
+void mscp_start __P((struct mscp_softc *));
int mscp_init __P((struct mscp_softc *));
void mscp_initds __P((struct mscp_softc *));
int mscp_waitstep __P((struct mscp_softc *, int, int));
struct cfattach mscpbus_ca = {
- sizeof(struct mscp_softc), mscp_match, mscp_attach
+ sizeof(struct mscp_softc), (cfmatch_t)mscp_match, mscp_attach
};
struct cfdriver mscpbus_cd = {
NULL, "mscpbus", DV_DULL
};
+#define READ_SA (bus_space_read_2(mi->mi_iot, mi->mi_sah, 0))
+#define READ_IP (bus_space_read_2(mi->mi_iot, mi->mi_iph, 0))
+#define WRITE_IP(x) bus_space_write_2(mi->mi_iot, mi->mi_iph, 0, (x))
+#define WRITE_SW(x) bus_space_write_2(mi->mi_iot, mi->mi_swh, 0, (x))
+
struct mscp slavereply;
/*
@@ -91,9 +101,9 @@ mscp_waitstep(mi, mask, result)
{
int status = 1;
- if ((*mi->mi_sa & mask) != result) {
+ if ((READ_SA & mask) != result) {
volatile int count = 0;
- while ((*mi->mi_sa & mask) != result) {
+ while ((READ_SA & mask) != result) {
DELAY(10000);
count += 1;
if (count > DELAYTEN)
@@ -108,11 +118,12 @@ mscp_waitstep(mi, mask, result)
int
mscp_match(parent, match, aux)
struct device *parent;
- void *match, *aux;
+ struct cfdata *match;
+ void *aux;
{
struct mscp_attach_args *ma = aux;
-#if NRA
+#if NRA || NRX
if (ma->ma_type & MSCPBUS_DISK)
return 1;
#endif
@@ -130,18 +141,20 @@ mscp_attach(parent, self, aux)
{
struct mscp_attach_args *ma = aux;
struct mscp_softc *mi = (void *)self;
- volatile struct mscp *mp;
+ volatile struct mscp *mp;
volatile int i;
int timeout, next = 0;
mi->mi_mc = ma->ma_mc;
mi->mi_me = NULL;
mi->mi_type = ma->ma_type;
- mi->mi_uuda = ma->ma_uuda;
mi->mi_uda = ma->ma_uda;
- mi->mi_ip = ma->ma_ip;
- mi->mi_sa = ma->ma_sa;
- mi->mi_sw = ma->ma_sw;
+ mi->mi_dmat = ma->ma_dmat;
+ mi->mi_dmam = ma->ma_dmam;
+ mi->mi_iot = ma->ma_iot;
+ mi->mi_iph = ma->ma_iph;
+ mi->mi_sah = ma->ma_sah;
+ mi->mi_swh = ma->ma_swh;
mi->mi_ivec = ma->ma_ivec;
mi->mi_adapnr = ma->ma_adapnr;
mi->mi_ctlrnr = ma->ma_ctlrnr;
@@ -150,20 +163,28 @@ mscp_attach(parent, self, aux)
* Go out to init the bus, so that we can give commands
* to its devices.
*/
- mi->mi_cmd.mri_size = NCMD;
- mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc;
- mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd;
- mi->mi_rsp.mri_size = NRSP;
- mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc;
- mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp;
- mi->mi_actf = (void *)&mi->mi_actf; /* Circular wait queue */
- mi->mi_actb = (void *)&mi->mi_actf;
+ mi->mi_cmd.mri_size = NCMD;
+ mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc;
+ mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd;
+ mi->mi_rsp.mri_size = NRSP;
+ mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc;
+ mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp;
+ SIMPLEQ_INIT(&mi->mi_resq);
if (mscp_init(mi)) {
printf("%s: can't init, controller hung\n",
mi->mi_dev.dv_xname);
return;
}
+ for (i = 0; i < NCMD; i++) {
+ mi->mi_mxiuse |= (1 << i);
+ if (bus_dmamap_create(mi->mi_dmat, (64*1024), 1, (64*1024),
+ 0, BUS_DMA_NOWAIT, &mi->mi_xi[i].mxi_dmam)) {
+ printf("Couldn't alloc dmamap %d\n", i);
+ return;
+ }
+ }
+
#if NRA
if (ma->ma_type & MSCPBUS_DISK) {
@@ -193,7 +214,7 @@ findunit:
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
slavereply.mscp_opcode = 0;
- i = *mi->mi_ip; /* Kick off polling */
+ i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
mp = &slavereply;
timeout = 1000;
while (timeout-- > 0) {
@@ -210,65 +231,65 @@ gotit: /*
*/
switch (mp->mscp_status & M_ST_MASK) {
- case M_ST_SUCCESS: /* worked */
- case M_ST_AVAILABLE: /* found another drive */
- break; /* use it */
+ case M_ST_SUCCESS: /* worked */
+ case M_ST_AVAILABLE: /* found another drive */
+ break; /* use it */
case M_ST_OFFLINE:
/*
* Figure out why it is off line. It may be because
- * it is nonexistent, or because it is spun down, or
- * for some other reason.
- */
- switch (mp->mscp_status & ~M_ST_MASK) {
-
- case M_OFFLINE_UNKNOWN:
- /*
- * No such drive, and there are none with
- * higher unit numbers either, if we are
- * using M_GUM_NEXTUNIT.
- */
+ * it is nonexistent, or because it is spun down, or
+ * for some other reason.
+ */
+ switch (mp->mscp_status & ~M_ST_MASK) {
+
+ case M_OFFLINE_UNKNOWN:
+ /*
+ * No such drive, and there are none with
+ * higher unit numbers either, if we are
+ * using M_GUM_NEXTUNIT.
+ */
mi->mi_ierr = 3;
- return;
-
- case M_OFFLINE_UNMOUNTED:
- /*
- * The drive is not spun up. Use it anyway.
- *
- * N.B.: this seems to be a common occurrance
- * after a power failure. The first attempt
- * to bring it on line seems to spin it up
- * (and thus takes several minutes). Perhaps
- * we should note here that the on-line may
- * take longer than usual.
- */
- break;
-
- default:
- /*
- * In service, or something else equally unusable.
- */
- printf("%s: unit %d off line: ", mi->mi_dev.dv_xname,
- mp->mscp_unit);
- mscp_printevent((struct mscp *)mp);
+ return;
+
+ case M_OFFLINE_UNMOUNTED:
+ /*
+ * The drive is not spun up. Use it anyway.
+ *
+ * N.B.: this seems to be a common occurrance
+ * after a power failure. The first attempt
+ * to bring it on line seems to spin it up
+ * (and thus takes several minutes). Perhaps
+ * we should note here that the on-line may
+ * take longer than usual.
+ */
+ break;
+
+ default:
+ /*
+ * In service, or something else equally unusable.
+ */
+ printf("%s: unit %d off line: ", mi->mi_dev.dv_xname,
+ mp->mscp_unit);
+ mscp_printevent((struct mscp *)mp);
next++;
- goto findunit;
- }
- break;
-
- default:
- printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname);
- mscp_printevent((struct mscp *)mp);
- return;
- }
-
- /*
- * If we get a lower number, we have circulated around all
+ goto findunit;
+ }
+ break;
+
+ default:
+ printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname);
+ mscp_printevent((struct mscp *)mp);
+ return;
+ }
+
+ /*
+ * If we get a lower number, we have circulated around all
* devices and are finished, otherwise try to find next unit.
* We shouldn't ever get this, it's a workaround.
- */
- if (mp->mscp_unit < next)
- return;
+ */
+ if (mp->mscp_unit < next)
+ return;
next = mp->mscp_unit + 1;
goto findunit;
@@ -289,29 +310,29 @@ mscp_init(mi)
int status, count;
unsigned int j = 0;
- /*
- * While we are thinking about it, reset the next command
- * and response indicies.
- */
+ /*
+ * While we are thinking about it, reset the next command
+ * and response indicies.
+ */
mi->mi_cmd.mri_next = 0;
mi->mi_rsp.mri_next = 0;
mi->mi_flags |= MSC_IGNOREINTR;
if ((mi->mi_type & MSCPBUS_KDB) == 0)
- *mi->mi_ip = 0; /* Kick off */
+ WRITE_IP(0); /* Kick off */;
status = mscp_waitstep(mi, MP_STEP1, MP_STEP1);/* Wait to it wakes up */
if (status == 0)
return 1; /* Init failed */
- if (*mi->mi_sa & MP_ERR) {
+ if (READ_SA & MP_ERR) {
(*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
return 1;
}
/* step1 */
- *mi->mi_sw = MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) |
- MP_IE | (mi->mi_ivec >> 2);
+ WRITE_SW(MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) |
+ MP_IE | (mi->mi_ivec >> 2));
status = mscp_waitstep(mi, STEP1MASK, STEP1GOOD);
if (status == 0) {
(*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
@@ -319,31 +340,33 @@ mscp_init(mi)
}
/* step2 */
- *mi->mi_sw = (int)&mi->mi_uuda->mp_ca.ca_rspdsc[0] |
- (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0);
+ WRITE_SW(((mi->mi_dmam->dm_segs[0].ds_addr & 0xffff) +
+ offsetof(struct mscp_pack, mp_ca.ca_rspdsc[0])) |
+ (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0));
status = mscp_waitstep(mi, STEP2MASK, STEP2GOOD(mi->mi_ivec >> 2));
- if (status == 0) {
- (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
- return 1;
- }
+ if (status == 0) {
+ (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
+ return 1;
+ }
/* step3 */
- *mi->mi_sw = ((int)&mi->mi_uuda->mp_ca.ca_rspdsc[0]) >> 16;
+
+ WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 16));
status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD);
- if (status == 0) {
- (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
- return 1;
- }
- i = *mi->mi_sa & 0377;
+ if (status == 0) {
+ (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
+ return 1;
+ }
+ i = READ_SA & 0377;
printf(": version %d model %d\n", i & 15, i >> 4);
-#define BURST 4 /* XXX */
+#define BURST 4 /* XXX */
if (mi->mi_type & MSCPBUS_UDA) {
- *mi->mi_sw = MP_GO | (BURST - 1) << 2;
+ WRITE_SW(MP_GO | (BURST - 1) << 2);
printf("%s: DMA burst size set to %d\n",
mi->mi_dev.dv_xname, BURST);
}
- *mi->mi_sw = MP_GO;
+ WRITE_SW(MP_GO);
mscp_initds(mi);
mi->mi_flags &= ~MSC_IGNOREINTR;
@@ -363,17 +386,17 @@ mscp_init(mi)
mp->mscp_sccc.sccc_errlgfl = 0;
mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS;
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
- i = *mi->mi_ip;
+ i = READ_IP;
- count = 0;
- while (count < DELAYTEN) {
- if (((volatile)mi->mi_flags & MSC_READY) != 0)
- break;
- if ((j = *mi->mi_sa) & MP_ERR)
+ count = 0;
+ while (count < DELAYTEN) {
+ if (((volatile int)mi->mi_flags & MSC_READY) != 0)
+ break;
+ if ((j = READ_SA) & MP_ERR)
goto out;
- DELAY(10000);
- count += 1;
- }
+ DELAY(10000);
+ count += 1;
+ }
if (count == DELAYTEN) {
out:
printf("%s: couldn't set ctlr characteristics, sa=%x\n",
@@ -390,20 +413,21 @@ void
mscp_initds(mi)
struct mscp_softc *mi;
{
- struct mscp_pack *uud = mi->mi_uuda;
struct mscp_pack *ud = mi->mi_uda;
struct mscp *mp;
int i;
for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) {
ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
- (long)&uud->mp_rsp[i].mscp_cmdref;
+ (mi->mi_dmam->dm_segs[0].ds_addr +
+ offsetof(struct mscp_pack, mp_rsp[i].mscp_cmdref));
mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i];
mp->mscp_msglen = MSCP_MSGLEN;
}
for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) {
ud->mp_ca.ca_cmddsc[i] = MSCP_INT |
- (long)&uud->mp_cmd[i].mscp_cmdref;
+ (mi->mi_dmam->dm_segs[0].ds_addr +
+ offsetof(struct mscp_pack, mp_cmd[i].mscp_cmdref));
mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i];
mp->mscp_msglen = MSCP_MSGLEN;
if (mi->mi_type & MSCPBUS_TAPE)
@@ -411,6 +435,8 @@ mscp_initds(mi)
}
}
+static void mscp_kickaway(struct mscp_softc *);
+
void
mscp_intr(mi)
struct mscp_softc *mi;
@@ -419,31 +445,23 @@ mscp_intr(mi)
if (mi->mi_flags & MSC_IGNOREINTR)
return;
- /*
- * Check for response and command ring transitions.
- */
- if (ud->mp_ca.ca_rspint) {
- ud->mp_ca.ca_rspint = 0;
- mscp_dorsp(mi);
- }
- if (ud->mp_ca.ca_cmdint) {
- ud->mp_ca.ca_cmdint = 0;
- MSCP_DOCMD(mi);
- }
-
/*
- * If there are any not-yet-handled requeset, try them now.
- * XXX - We handles them (erroneous) in last-in first-handled order.
- * Must we fix this???
+ * Check for response and command ring transitions.
*/
- while (mi->mi_w) {
- struct buf *bp = mi->mi_w;
-
- mi->mi_w = (void *)bp->b_actb;
- mscp_strategy(bp, (struct device *)mi);
- if (mi->mi_w == bp)
- break;
+ if (ud->mp_ca.ca_rspint) {
+ ud->mp_ca.ca_rspint = 0;
+ mscp_dorsp(mi);
+ }
+ if (ud->mp_ca.ca_cmdint) {
+ ud->mp_ca.ca_cmdint = 0;
+ MSCP_DOCMD(mi);
}
+
+ /*
+ * If there are any not-yet-handled request, try them now.
+ */
+ if (SIMPLEQ_FIRST(&mi->mi_resq))
+ mscp_kickaway(mi);
}
int
@@ -451,12 +469,22 @@ mscp_print(aux, name)
void *aux;
const char *name;
{
+ struct drive_attach_args *da = aux;
+ struct mscp *mp = da->da_mp;
+ int type = mp->mscp_guse.guse_mediaid;
+
+ if (name) {
+ printf("%c%c", MSCP_MID_CHAR(2, type), MSCP_MID_CHAR(1, type));
+ if (MSCP_MID_ECH(0, type))
+ printf("%c", MSCP_MID_CHAR(0, type));
+ printf("%d at %s drive %d", MSCP_MID_NUM(type), name,
+ mp->mscp_unit);
+ }
return UNCONF;
}
/*
* common strategy routine for all types of MSCP devices.
- * bp is the current buf, dp is the drive queue.
*/
void
mscp_strategy(bp, usc)
@@ -464,60 +492,82 @@ mscp_strategy(bp, usc)
struct device *usc;
{
struct mscp_softc *mi = (void *)usc;
+ int s = splimp();
+
+/* SIMPLEQ_INSERT_TAIL(&mi->mi_resq, bp, xxx) */
+ bp->b_actf = NULL;
+ *mi->mi_resq.sqh_last = bp;
+ mi->mi_resq.sqh_last = &bp->b_actf;
+ mscp_kickaway(mi);
+ splx(s);
+}
+
+
+void
+mscp_kickaway(mi)
+ struct mscp_softc *mi;
+{
+ struct buf *bp;
struct mscp *mp;
- int s = spl6();
+ int next;
- /*
- * Ok; we are ready to try to start a xfer. Get a MSCP packet
- * and try to start...
- */
- if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
- if (mi->mi_credits > MSCP_MINCREDITS)
- printf("%s: command ring too small\n",
- mi->mi_dev.dv_parent->dv_xname);
+ while ((bp = SIMPLEQ_FIRST(&mi->mi_resq))) {
/*
- * By some (strange) reason we didn't get a MSCP packet.
- * Put it on queue and wait for free packets.
+ * Ok; we are ready to try to start a xfer. Get a MSCP packet
+ * and try to start...
*/
- (void *)bp->b_actb = mi->mi_w;
- mi->mi_w = bp;
- splx(s);
- return;
+ if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
+ if (mi->mi_credits > MSCP_MINCREDITS)
+ printf("%s: command ring too small\n",
+ mi->mi_dev.dv_parent->dv_xname);
+ /*
+ * By some (strange) reason we didn't get a MSCP packet.
+ * Just return and wait for free packets.
+ */
+ return;
+ }
+
+ if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0)
+ panic("no mxi buffers");
+ mi->mi_mxiuse &= ~(1 << next);
+ if (mi->mi_xi[next].mxi_inuse)
+ panic("mxi inuse");
+ /*
+ * Set up the MSCP packet and ask the ctlr to start.
+ */
+ mp->mscp_opcode =
+ (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
+ mp->mscp_cmdref = next;
+ mi->mi_xi[next].mxi_bp = bp;
+ mi->mi_xi[next].mxi_mp = mp;
+ mi->mi_xi[next].mxi_inuse = 1;
+ bp->b_resid = next;
+ (*mi->mi_me->me_fillin)(bp, mp);
+ (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, &mi->mi_xi[next]);
+ if ((mi->mi_resq.sqh_first = bp->b_actf) == NULL)
+ mi->mi_resq.sqh_last = &mi->mi_resq.sqh_first;
+#if 0
+ mi->mi_w = bp->b_actf;
+#endif
}
-
- /*
- * Set up the MSCP packet and ask the ctlr to start.
- */
- mp->mscp_opcode = (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
- (*mi->mi_me->me_fillin)(bp, mp);
- (void *)bp->b_actb = mp; /* b_actb is unused, save mscp packet here */
- (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, bp);
- splx(s);
}
void
-mscp_dgo(mi, buffer, info, bp)
+mscp_dgo(mi, mxi)
struct mscp_softc *mi;
- long buffer, info;
- struct buf *bp;
+ struct mscp_xi *mxi;
{
volatile int i;
struct mscp *mp;
- /*
- * Fill in the MSCP packet and move the buffer to the I/O wait queue.
- */
- mp = (void *)bp->b_actb;
-
- mp->mscp_seq.seq_buffer = buffer;
-
- _insque(&bp->b_actf, &mi->mi_actf);
+ /*
+ * Fill in the MSCP packet and move the buffer to the I/O wait queue.
+ */
+ mp = mxi->mxi_mp;
+ mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr;
- bp->b_resid = info;
- mp->mscp_cmdref = (long) bp;
*mp->mscp_addr |= MSCP_OWN | MSCP_INT;
-
- i = *mi->mi_ip;
+ i = READ_IP;
}
#ifdef DIAGNOSTIC
@@ -686,7 +736,7 @@ static char *drive_msgs[] = {
"lost rd/wr ready", /* 4 = Lost R/W Ready Error */
"drive clock dropout", /* 5 = Lost Drive Clock */
"lost recvr ready", /* 6 = Lost Receiver Ready */
- "drive detected error", /* 7 = Drive Error */
+ "drive detected error", /* 7 = Drive Error */
"ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
};
@@ -699,7 +749,7 @@ struct code_decode {
int cdc_nsubcodes;
char **cdc_submsgs;
} code_decode[] = {
-#define SC(m) sizeof (m) / sizeof (m[0]), m
+#define SC(m) sizeof (m) / sizeof (m[0]), m
{"success", SC(succ_msgs)},
{"invalid command", SC(icmd_msgs)},
{"command aborted", 0, 0},