summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale S. Rahn <rahnds@cvs.openbsd.org>2000-07-28 13:09:02 +0000
committerDale S. Rahn <rahnds@cvs.openbsd.org>2000-07-28 13:09:02 +0000
commit4c4160d4300634511721ad2944ce4948dd28f5f6 (patch)
tree299e66cf9c4fa7770eced7367105372b3f8569a3
parent0136c8142f5a28a64e0bc3c9290f4936b13559b5 (diff)
First cut at supporting older bandit based machines
Adds mesh scsi, changes to interrupt controller to allow preconfiguration of interrupts. Mesh work by Andy.
-rw-r--r--sys/arch/powerpc/mac/macintr.c38
-rw-r--r--sys/arch/powerpc/mac/mesh.c1177
-rw-r--r--sys/arch/powerpc/mac/meshreg.h110
-rw-r--r--sys/arch/powerpc/mac/openpic.c5
4 files changed, 1319 insertions, 11 deletions
diff --git a/sys/arch/powerpc/mac/macintr.c b/sys/arch/powerpc/mac/macintr.c
index 099017076c3..accdc2616be 100644
--- a/sys/arch/powerpc/mac/macintr.c
+++ b/sys/arch/powerpc/mac/macintr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: macintr.c,v 1.4 2000/06/15 03:11:01 rahnds Exp $ */
+/* $OpenBSD: macintr.c,v 1.5 2000/07/28 13:09:01 rahnds Exp $ */
/*-
* Copyright (c) 1995 Per Fogelstrom
@@ -116,16 +116,14 @@ macintr_match(parent, cf, aux)
void *cf;
void *aux;
{
- char type[40];
struct confargs *ca = aux;
- bzero (type, sizeof(type));
-
+ /*
+ * Only check name, to allow legacy interrupt controllers
+ * to slip in here.
+ */
if (strcmp(ca->ca_name, "interrupt-controller") == 0 ) {
- OF_getprop(ca->ca_node, "device_type", type, sizeof(type));
- if (strcmp(type, "interrupt-controller") == 0) {
- return 1;
- }
+ return 1;
}
return 0;
}
@@ -144,6 +142,7 @@ intr_establish_t macintr_establish;
intr_disestablish_t macintr_disestablish;
extern intr_establish_t *mac_intr_establish_func;
extern intr_disestablish_t *mac_intr_disestablish_func;
+void macintr_collect_preconf_intr();
void
macintr_attach(parent, self, aux)
@@ -164,12 +163,35 @@ macintr_attach(parent, self, aux)
mac_intr_establish_func = macintr_establish;
mac_intr_disestablish_func = macintr_disestablish;
+ macintr_collect_preconf_intr();
mac_intr_establish(parent, 0x14, IST_LEVEL, IPL_HIGH,
prog_switch, (void *)0x14, "prog button");
printf("\n");
}
+void
+macintr_collect_preconf_intr()
+{
+ int i;
+ for (i = 0; i < ppc_configed_intr_cnt; i++) {
+ printf("\n\t%s irq %d level %d fun %x arg %x",
+ ppc_configed_intr[i].ih_what,
+ ppc_configed_intr[i].ih_irq,
+ ppc_configed_intr[i].ih_level,
+ ppc_configed_intr[i].ih_fun,
+ ppc_configed_intr[i].ih_arg
+ );
+ macintr_establish(NULL,
+ ppc_configed_intr[i].ih_irq,
+ IST_LEVEL,
+ ppc_configed_intr[i].ih_level,
+ ppc_configed_intr[i].ih_fun,
+ ppc_configed_intr[i].ih_arg,
+ ppc_configed_intr[i].ih_what);
+ }
+}
+
int
prog_switch (void *arg)
diff --git a/sys/arch/powerpc/mac/mesh.c b/sys/arch/powerpc/mac/mesh.c
new file mode 100644
index 00000000000..e42dd46be3d
--- /dev/null
+++ b/sys/arch/powerpc/mac/mesh.c
@@ -0,0 +1,1177 @@
+/* $NetBSD: mesh.c,v 1.1 1999/02/19 13:06:03 tsubai Exp $ */
+
+/*-
+ * Copyright (C) 1999 Internet Research Institute, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by
+ * Internet Research Institute, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include <scsi/scsi_message.h>
+/*
+#include "scsipi/scsi_all.h"
+#include "scsipi/scsipi_all.h"
+#include "scsipi/scsiconf.h"
+#include "scsipi/scsi_message.h"*/
+
+
+
+#include <dev/ofw/openfirm.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+#include <machine/pio.h>
+
+#include "dbdma.h"
+#include "meshreg.h"
+
+#define T_SYNCMODE 0x01 /* target uses sync mode */
+#define T_SYNCNEGO 0x02 /* sync negotiation done */
+
+
+
+struct mesh_tinfo {
+ int flags;
+ int period;
+ int offset;
+};
+
+/* scb flags */
+#define MESH_POLL 0x01
+#define MESH_CHECK 0x02
+#define MESH_SENSE 0x04
+#define MESH_READ 0x80
+
+struct mesh_scb {
+ TAILQ_ENTRY(mesh_scb) chain;
+ int flags;
+ struct scsi_xfer *xs;
+ struct scsi_generic cmd;
+ int cmdlen;
+ int target; /* target SCSI ID */
+ int resid;
+ vaddr_t daddr;
+ vsize_t dlen;
+ int status;
+};
+
+/* sc_flags value */
+#define MESH_DMA_ACTIVE 0x01
+
+struct mesh_softc {
+ struct device sc_dev; /* us as a device */
+ struct scsi_link sc_link;
+ struct scsi_adapter sc_adapter;
+
+ u_char *sc_reg; /* MESH base address */
+ dbdma_regmap_t *sc_dmareg; /* DMA register address */
+ dbdma_command_t *sc_dmacmd; /* DMA command area */
+
+ int sc_flags;
+ int sc_cfflags; /* copy of config flags */
+ int sc_meshid; /* MESH version */
+ int sc_minsync; /* minimum sync period */
+ int sc_irq;
+ int sc_freq; /* SCSI bus frequency in MHz */
+ int sc_id; /* our SCSI ID */
+ struct mesh_tinfo sc_tinfo[8]; /* target information */
+
+ int sc_nextstate;
+ int sc_prevphase;
+ struct mesh_scb *sc_nexus; /* current command */
+
+ int sc_msgout;
+ int sc_imsglen;
+ int sc_omsglen;
+ u_char sc_imsg[16];
+ u_char sc_omsg[16];
+
+ TAILQ_HEAD(, mesh_scb) free_scb;
+ TAILQ_HEAD(, mesh_scb) ready_scb;
+ struct mesh_scb sc_scb[16];
+};
+
+/* mesh_msgout() values */
+#define SEND_REJECT 1
+#define SEND_IDENTIFY 2
+#define SEND_SDTR 4
+
+
+#ifdef __OpenBSD__
+#define scsi_print_addr sc_print_addr
+#define scsipi_done scsi_done
+#endif
+
+static __inline int mesh_read_reg __P((struct mesh_softc *, int));
+static __inline void mesh_set_reg __P((struct mesh_softc *, int, int));
+
+int mesh_match __P((struct device *, struct cfdata *, void *));
+void mesh_attach __P((struct device *, struct device *, void *));
+void mesh_shutdownhook __P((void *));
+int mesh_intr __P((void *));
+void mesh_error __P((struct mesh_softc *, struct mesh_scb *, int, int));
+void mesh_select __P((struct mesh_softc *, struct mesh_scb *));
+void mesh_identify __P((struct mesh_softc *, struct mesh_scb *));
+void mesh_command __P((struct mesh_softc *, struct mesh_scb *));
+void mesh_dma_setup __P((struct mesh_softc *, struct mesh_scb *));
+void mesh_dataio __P((struct mesh_softc *, struct mesh_scb *));
+void mesh_status __P((struct mesh_softc *, struct mesh_scb *));
+void mesh_msgin __P((struct mesh_softc *, struct mesh_scb *));
+void mesh_msgout __P((struct mesh_softc *, int));
+void mesh_bus_reset __P((struct mesh_softc *));
+void mesh_reset __P((struct mesh_softc *));
+int mesh_stp __P((struct mesh_softc *, int));
+void mesh_setsync __P((struct mesh_softc *, struct mesh_tinfo *));
+struct mesh_scb *mesh_get_scb __P((struct mesh_softc *));
+void mesh_free_scb __P((struct mesh_softc *, struct mesh_scb *));
+int mesh_scsi_cmd __P((struct scsi_xfer *));
+void mesh_sched __P((struct mesh_softc *));
+int mesh_poll __P((struct mesh_softc *, struct scsi_xfer *));
+void mesh_done __P((struct mesh_softc *, struct mesh_scb *));
+void mesh_timeout __P((void *));
+void mesh_sense __P((struct mesh_softc *, struct mesh_scb *));
+void mesh_minphys __P((struct buf *));
+
+
+#define MESH_DATAOUT 0
+#define MESH_DATAIN MESH_STATUS0_IO
+#define MESH_COMMAND MESH_STATUS0_CD
+#define MESH_STATUS (MESH_STATUS0_CD | MESH_STATUS0_IO)
+#define MESH_MSGOUT (MESH_STATUS0_MSG | MESH_STATUS0_CD)
+#define MESH_MSGIN (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
+
+#define MESH_SELECTING 8
+#define MESH_IDENTIFY 9
+#define MESH_COMPLETE 10
+#define MESH_BUSFREE 11
+#define MESH_UNKNOWN -1
+
+#define MESH_PHASE_MASK (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
+
+struct cfattach mesh_ca = {
+ sizeof(struct mesh_softc),(cfmatch_t)mesh_match,
+ mesh_attach
+};
+
+
+struct cfdriver mesh_cd = {
+ NULL, "mesh", DV_DULL
+};
+
+struct scsi_device mesh_dev = {
+ NULL, /* Use default error handler */
+ NULL, /* have a queue, served by this */
+ NULL, /* have no async handler */
+ NULL, /* Use default 'done' routine */
+};
+
+int
+mesh_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+{
+ struct confargs *ca = aux;
+ printf("MESH_MATCH called ,ca->ca_name= %s\n",ca->ca_name);
+
+ if (strcmp(ca->ca_name, "mesh") != 0)
+ return 0;
+
+ return 1;
+}
+
+void
+mesh_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct mesh_softc *sc = (void *)self;
+ struct confargs *ca = aux;
+ int i;
+ u_int *reg;
+
+ printf("MESH_ATTACH called\n");
+
+ reg = ca->ca_reg;
+ reg[0] += ca->ca_baseaddr;
+ reg[2] += ca->ca_baseaddr;
+ sc->sc_reg = mapiodev(reg[0], reg[1]);
+ sc->sc_irq = ca->ca_intr[0];
+ sc->sc_dmareg = mapiodev(reg[2], reg[3]);
+
+ sc->sc_cfflags = self->dv_cfdata->cf_flags;
+ sc->sc_meshid = mesh_read_reg(sc, MESH_MESH_ID) & 0x1f;
+#if 0
+ if (sc->sc_meshid != (MESH_SIGNATURE & 0x1f) {
+ printf(": unknown MESH ID (0x%x)\n", sc->sc_meshid);
+ return;
+ }
+#endif
+ if (OF_getprop(ca->ca_node, "clock-frequency", &sc->sc_freq, 4) != 4) {
+ printf(": cannot get clock-frequency\n");
+ return;
+ }
+ sc->sc_freq /= 1000000; /* in MHz */
+ sc->sc_minsync = 25; /* maximum sync rate = 10MB/sec */
+ sc->sc_id = 7;
+
+ TAILQ_INIT(&sc->free_scb);
+ TAILQ_INIT(&sc->ready_scb);
+ for (i = 0; i < sizeof(sc->sc_scb)/sizeof(sc->sc_scb[0]); i++)
+ TAILQ_INSERT_TAIL(&sc->free_scb, &sc->sc_scb[i], chain);
+
+ sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20);
+
+ mesh_reset(sc);
+ mesh_bus_reset(sc);
+
+ printf(" irq %d: %dMHz, SCSI ID %d\n",
+ sc->sc_irq, sc->sc_freq, sc->sc_id);
+
+ sc->sc_adapter.scsi_cmd = mesh_scsi_cmd;
+ sc->sc_adapter.scsi_minphys = mesh_minphys;
+
+/* sc->sc_link.scsi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;*/
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = sc->sc_id;
+ sc->sc_link.adapter = &sc->sc_adapter;
+ sc->sc_link.device = &mesh_dev;
+ sc->sc_link.openings = 2;
+/* sc->sc_link.scsi_scsi.max_target = 7;
+ sc->sc_link.scsi_scsi.max_lun = 7;
+ sc->sc_link.type = BUS_SCSI;
+*/
+ config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
+
+ printf("in mesh_attach, after config_found,calling mac_intr_establish,sc->sc_irq = %d\n",sc->sc_irq);
+
+ /*intr_establish(sc->sc_irq, IST_LEVEL, IPL_BIO, mesh_intr, sc);*/
+ mac_intr_establish(parent,sc->sc_irq,IST_LEVEL, IPL_BIO, mesh_intr, sc,"mesh intr");
+ /* Reset SCSI bus when halt. */
+ shutdownhook_establish(mesh_shutdownhook, sc);
+}
+
+#define MESH_SET_XFER(sc, count) do { \
+ mesh_set_reg(sc, MESH_XFER_COUNT0, count); \
+ mesh_set_reg(sc, MESH_XFER_COUNT1, count >> 8); \
+} while (0)
+
+#define MESH_GET_XFER(sc) ((mesh_read_reg(sc, MESH_XFER_COUNT1) << 8) | \
+ mesh_read_reg(sc, MESH_XFER_COUNT0))
+
+int
+mesh_read_reg(sc, reg)
+ struct mesh_softc *sc;
+ int reg;
+{
+ return in8(sc->sc_reg + reg);
+}
+
+void
+mesh_set_reg(sc, reg, val)
+ struct mesh_softc *sc;
+ int reg, val;
+{
+ out8(sc->sc_reg + reg, val);
+}
+
+void
+mesh_shutdownhook(arg)
+ void *arg;
+{
+ struct mesh_softc *sc = arg;
+
+ /* Set to async mode. */
+ mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
+}
+
+int
+mesh_intr(arg)
+ void *arg;
+{
+ struct mesh_softc *sc = arg;
+ struct mesh_scb *scb;
+ u_char intr, exception, error, status0, status1;
+ int i;
+
+ intr = mesh_read_reg(sc, MESH_INTERRUPT);
+
+#ifdef MESH_DEBUG
+ if (intr == 0) {
+ printf("mesh: stray interrupt\n");
+ return 0;
+ }
+#endif
+
+ exception = mesh_read_reg(sc, MESH_EXCEPTION);
+ error = mesh_read_reg(sc, MESH_ERROR);
+ status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
+ status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
+
+ /* clear interrupt */
+ mesh_set_reg(sc, MESH_INTERRUPT, intr);
+
+ scb = sc->sc_nexus;
+ if (scb == NULL) {
+#ifdef MESH_DEBUG
+ printf("mesh: NULL nexus\n");
+#endif
+ return 1;
+ }
+
+ if (sc->sc_flags & MESH_DMA_ACTIVE) {
+ dbdma_stop(sc->sc_dmareg);
+
+ sc->sc_flags &= ~MESH_DMA_ACTIVE;
+ scb->resid = MESH_GET_XFER(sc);
+
+ if (mesh_read_reg(sc, MESH_FIFO_COUNT) != 0)
+ panic("mesh: FIFO != 0"); /* XXX */
+ }
+
+ if (intr & MESH_INTR_ERROR) {
+ mesh_error(sc, scb, error, 0);
+ return 1;
+ }
+
+ if (intr & MESH_INTR_EXCEPTION) {
+ /* selection timeout */
+ if (exception & MESH_EXC_SELTO) {
+ mesh_error(sc, scb, 0, exception);
+ return 1;
+ }
+
+ /* phase mismatch */
+ if (exception & MESH_EXC_PHASEMM) {
+ sc->sc_nextstate = status0 & MESH_PHASE_MASK;
+#if 0
+ printf("mesh: PHASE MISMATCH cdb =");
+ printf(" %02x", scb->cmd.opcode);
+ for (i = 0; i < 5; i++) {
+ printf(" %02x", scb->cmd.bytes[i]);
+ }
+ printf("\n");
+#endif
+ }
+ }
+
+ if (sc->sc_nextstate == MESH_UNKNOWN)
+ sc->sc_nextstate = status0 & MESH_PHASE_MASK;
+
+ switch (sc->sc_nextstate) {
+
+ case MESH_IDENTIFY:
+ mesh_identify(sc, scb);
+ break;
+ case MESH_COMMAND:
+ mesh_command(sc, scb);
+ printf("mesh_intr:case MESH_COMMAND\n");
+ break;
+ case MESH_DATAIN:
+ case MESH_DATAOUT:
+ mesh_dataio(sc, scb);
+ printf("mesh_intr:case MESH_DATAIN or MESH_DATAOUT\n");
+ break;
+ case MESH_STATUS:
+ mesh_status(sc, scb);
+ printf("mesh_intr:case MESH_STATUS\n");
+ break;
+ case MESH_MSGIN:
+ mesh_msgin(sc, scb);
+ printf("mesh_intr:case MESH_MSGIN\n");
+ break;
+ case MESH_COMPLETE:
+ printf("mesh_intr:case MESH_COMPLETE\n");
+ mesh_done(sc, scb);
+ break;
+
+ default:
+ panic("mesh: unknown state (0x%x)", sc->sc_nextstate);
+ }
+
+ return 1;
+}
+
+void
+mesh_error(sc, scb, error, exception)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+ int error, exception;
+{
+ if (error & MESH_ERR_SCSI_RESET) {
+ printf("mesh: SCSI RESET\n");
+
+ /* Wait until the RST signal is deasserted. */
+ while (mesh_read_reg(sc, MESH_BUS_STATUS1) & MESH_STATUS1_RST);
+ mesh_reset(sc);
+ return;
+ }
+
+ if (error & MESH_ERR_PARITY_ERR0) {
+ printf("mesh: parity error\n");
+ scb->xs->error = XS_DRIVER_STUFFUP;
+ }
+
+ if (error & MESH_ERR_DISCONNECT) {
+ printf("mesh: unexpected disconnect\n");
+ if (sc->sc_nextstate != MESH_COMPLETE)
+ scb->xs->error = XS_DRIVER_STUFFUP;
+ }
+
+ if (exception & MESH_EXC_SELTO) {
+ /* XXX should reset bus here? */
+ scb->xs->error = XS_DRIVER_STUFFUP;
+ }
+
+ mesh_done(sc, scb);
+}
+
+void
+mesh_select(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
+
+ mesh_setsync(sc, ti);
+ MESH_SET_XFER(sc, 0);
+
+ /* arbitration */
+
+ /*
+ * MESH mistakenly asserts TARGET ID bit along with its own ID bit
+ * in arbitration phase (like selection). So we should load
+ * initiator ID to DestID register temporarily.
+ */
+ mesh_set_reg(sc, MESH_DEST_ID, sc->sc_id);
+ mesh_set_reg(sc, MESH_INTR_MASK, 0); /* disable intr. */
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ARBITRATE);
+
+ while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
+ mesh_set_reg(sc, MESH_INTERRUPT, 1);
+ mesh_set_reg(sc, MESH_INTR_MASK, 7);
+
+ /* selection */
+ mesh_set_reg(sc, MESH_DEST_ID, scb->target);
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_SELECT | MESH_SEQ_ATN);
+
+ sc->sc_prevphase = MESH_SELECTING;
+ sc->sc_nextstate = MESH_IDENTIFY;
+
+ timeout(mesh_timeout, scb, 10*hz);
+}
+
+void
+mesh_identify(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
+ mesh_msgout(sc, SEND_IDENTIFY);
+
+ sc->sc_nextstate = MESH_COMMAND;
+ printf("mesh_identify called\n");
+}
+
+void
+mesh_command(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
+ int i;
+ char *cmdp;
+
+ if ((ti->flags & T_SYNCNEGO) == 0) {
+ ti->period = sc->sc_minsync;
+ ti->offset = 15;
+ mesh_msgout(sc, SEND_SDTR);
+ sc->sc_prevphase = MESH_COMMAND;
+ sc->sc_nextstate = MESH_MSGIN;
+ return;
+ }
+
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
+
+ MESH_SET_XFER(sc, scb->cmdlen);
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_COMMAND);
+
+ cmdp = (char *)&scb->cmd;
+ for (i = 0; i < scb->cmdlen; i++)
+ mesh_set_reg(sc, MESH_FIFO, *cmdp++);
+
+ if (scb->resid == 0)
+ sc->sc_nextstate = MESH_STATUS; /* no data xfer */
+ else
+ sc->sc_nextstate = MESH_DATAIN;
+}
+
+void
+mesh_dma_setup(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ struct scsi_xfer *xs = scb->xs;
+ int datain = scb->flags & MESH_READ;
+ dbdma_command_t *cmdp;
+ u_int cmd;
+ vaddr_t va;
+ int count, offset;
+
+ cmdp = sc->sc_dmacmd;
+ cmd = datain ? DBDMA_CMD_IN_MORE : DBDMA_CMD_OUT_MORE;
+
+ count = scb->dlen;
+
+ if (count / NBPG > 32)
+ panic("mesh: transfer size >= 128k");
+
+ va = scb->daddr;
+ offset = va & PGOFSET;
+
+ /* if va is not page-aligned, setup the first page */
+ if (offset != 0) {
+ int rest = NBPG - offset; /* the rest in the page */
+
+ if (count > rest) { /* if continues to next page */
+ DBDMA_BUILD(cmdp, cmd, 0, rest, vtophys(va),
+ DBDMA_INT_NEVER, DBDMA_WAIT_NEVER,
+ DBDMA_BRANCH_NEVER);
+ count -= rest;
+ va += rest;
+ cmdp++;
+ }
+ }
+
+ /* now va is page-aligned */
+ while (count > NBPG) {
+ DBDMA_BUILD(cmdp, cmd, 0, NBPG, vtophys(va),
+ DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
+ count -= NBPG;
+ va += NBPG;
+ cmdp++;
+ }
+
+ /* the last page (count <= NBPG here) */
+ cmd = datain ? DBDMA_CMD_IN_LAST : DBDMA_CMD_OUT_LAST;
+ DBDMA_BUILD(cmdp, cmd , 0, count, vtophys(va),
+ DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
+ cmdp++;
+
+ DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0,
+ DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
+}
+
+void
+mesh_dataio(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ mesh_dma_setup(sc, scb);
+
+ if (scb->dlen == 65536)
+ MESH_SET_XFER(sc, 0); /* TC = 0 means 64KB transfer */
+ else
+ MESH_SET_XFER(sc, scb->dlen);
+
+ if (scb->flags & MESH_READ)
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAIN | MESH_SEQ_DMA);
+ else
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAOUT | MESH_SEQ_DMA);
+ dbdma_start(sc->sc_dmareg, sc->sc_dmacmd);
+ sc->sc_flags |= MESH_DMA_ACTIVE;
+ sc->sc_nextstate = MESH_STATUS;
+}
+
+void
+mesh_status(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */
+ MESH_SET_XFER(sc, 1);
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_STATUS);
+ sc->sc_nextstate = MESH_STATUS;
+ return;
+ }
+
+ scb->status = mesh_read_reg(sc, MESH_FIFO);
+
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
+ MESH_SET_XFER(sc, 1);
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
+
+ sc->sc_nextstate = MESH_MSGIN;
+}
+
+#define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80)
+#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
+#define ISEXTMSG(m) ((m) == 1)
+
+void
+mesh_msgin(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ int i;
+
+ if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */
+ MESH_SET_XFER(sc, 1);
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
+ sc->sc_imsglen = 0;
+ sc->sc_nextstate = MESH_MSGIN;
+ return;
+ }
+
+ sc->sc_imsg[sc->sc_imsglen++] = mesh_read_reg(sc, MESH_FIFO);
+
+ if (sc->sc_imsglen == 1 && IS1BYTEMSG(sc->sc_imsg[0]))
+ goto gotit;
+ if (sc->sc_imsglen == 2 && IS2BYTEMSG(sc->sc_imsg[0]))
+ goto gotit;
+ if (sc->sc_imsglen >= 3 && ISEXTMSG(sc->sc_imsg[0]) &&
+ sc->sc_imsglen == sc->sc_imsg[1] + 2)
+ goto gotit;
+
+ sc->sc_nextstate = MESH_MSGIN;
+ MESH_SET_XFER(sc, 1);
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
+ return;
+
+gotit:
+#ifdef DEBUG
+ printf("msgin:");
+ for (i = 0; i < sc->sc_imsglen; i++)
+ printf(" 0x%02x", sc->sc_imsg[i]);
+ printf("\n");
+#endif
+
+ switch (sc->sc_imsg[0]) {
+ case MSG_CMDCOMPLETE:
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
+ sc->sc_nextstate = MESH_COMPLETE;
+ sc->sc_imsglen = 0;
+ return;
+
+ case MSG_MESSAGE_REJECT:
+ switch (sc->sc_msgout) {
+ case SEND_SDTR:
+ printf("SDTR rejected\n");
+ printf("using async mode\n");
+ sc->sc_tinfo[scb->target].period = 0;
+ sc->sc_tinfo[scb->target].offset = 0;
+ mesh_setsync(sc, &sc->sc_tinfo[scb->target]);
+ break;
+ }
+ break;
+
+ case MSG_NOOP:
+ break;
+
+ case MSG_EXTENDED:
+ goto extended_msg;
+
+ default:
+ scsi_print_addr(scb->xs->sc_link);
+ printf("unrecognized MESSAGE(0x%02x); sending REJECT\n",
+ sc->sc_imsg[0]);
+
+ reject:
+ mesh_msgout(sc, SEND_REJECT);
+ return;
+ }
+ goto done;
+
+extended_msg:
+ /* process an extended message */
+ switch (sc->sc_imsg[2]) {
+ case MSG_EXT_SDTR:
+ {
+ struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
+ int period = sc->sc_imsg[3];
+ int offset = sc->sc_imsg[4];
+ int r = 250 / period;
+ int s = (100*250) / period - 100 * r;
+
+ if (period < sc->sc_minsync) {
+ ti->period = sc->sc_minsync;
+ ti->offset = 15;
+ mesh_msgout(sc, SEND_SDTR);
+ return;
+ }
+ scsi_print_addr(scb->xs->sc_link);
+ /* XXX if (offset != 0) ... */
+ printf("max sync rate %d.%02dMb/s\n", r, s);
+ ti->period = period;
+ ti->offset = offset;
+ ti->flags |= T_SYNCNEGO;
+ ti->flags |= T_SYNCMODE;
+ mesh_setsync(sc, ti);
+ goto done;
+ }
+ default:
+ printf("%s target %d: rejecting extended message 0x%x\n",
+ sc->sc_dev.dv_xname, scb->target, sc->sc_imsg[0]);
+ goto reject;
+ }
+
+done:
+ sc->sc_imsglen = 0;
+ sc->sc_nextstate = MESH_UNKNOWN;
+
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE); /* XXX really? */
+}
+
+void
+mesh_msgout(sc, msg)
+ struct mesh_softc *sc;
+ int msg;
+{
+ struct mesh_scb *scb = sc->sc_nexus;
+ struct mesh_tinfo *ti;
+ int lun, i;
+
+ switch (msg) {
+ case SEND_REJECT:
+ sc->sc_omsglen = 1;
+ sc->sc_omsg[0] = MSG_MESSAGE_REJECT;
+ break;
+ case SEND_IDENTIFY:
+ lun = scb->xs->sc_link->lun;
+ sc->sc_omsglen = 1;
+ sc->sc_omsg[0] = MSG_IDENTIFY(lun, 0);
+ break;
+ case SEND_SDTR:
+ ti = &sc->sc_tinfo[scb->target];
+ sc->sc_omsglen = 5;
+ sc->sc_omsg[0] = MSG_EXTENDED;
+ sc->sc_omsg[1] = 3;
+ sc->sc_omsg[2] = MSG_EXT_SDTR;
+ sc->sc_omsg[3] = ti->period;
+ sc->sc_omsg[4] = ti->offset;
+ break;
+ }
+ sc->sc_msgout = msg;
+
+ MESH_SET_XFER(sc, sc->sc_omsglen);
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT | MESH_SEQ_ATN);
+
+ for (i = 0; i < sc->sc_omsglen; i++)
+ mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
+
+ sc->sc_nextstate = MESH_UNKNOWN;
+}
+
+void
+mesh_bus_reset(sc)
+ struct mesh_softc *sc;
+{
+ /* Disable interrupts. */
+ mesh_set_reg(sc, MESH_INTR_MASK, 0);
+
+ /* Assert RST line. */
+ mesh_set_reg(sc, MESH_BUS_STATUS1, MESH_STATUS1_RST);
+ delay(50);
+ mesh_set_reg(sc, MESH_BUS_STATUS1, 0);
+
+ mesh_reset(sc);
+}
+
+void
+mesh_reset(sc)
+ struct mesh_softc *sc;
+{
+ int i;
+
+ /* Reset DMA first. */
+ dbdma_reset(sc->sc_dmareg);
+
+ /* Disable interrupts. */
+ mesh_set_reg(sc, MESH_INTR_MASK, 0);
+
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_RESET_MESH);
+ delay(1);
+
+ /* Wait for reset done. */
+ while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
+
+ /* Clear interrupts */
+ mesh_set_reg(sc, MESH_INTERRUPT, 0x7);
+
+ /* Set SCSI ID */
+ mesh_set_reg(sc, MESH_SOURCE_ID, sc->sc_id);
+
+ /* Set to async mode by default. */
+ mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
+
+ /* Set selection timeout to 250ms. */
+ mesh_set_reg(sc, MESH_SEL_TIMEOUT, 250 * sc->sc_freq / 500);
+
+ /* Enable parity check. */
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ENABLE_PARITY);
+
+ /* Enable all interrupts. */
+ mesh_set_reg(sc, MESH_INTR_MASK, 0x7);
+
+ for (i = 0; i < 7; i++) {
+ struct mesh_tinfo *ti = &sc->sc_tinfo[i];
+
+ ti->flags = 0;
+ ti->period = ti->offset = 0;
+ if (sc->sc_cfflags & (1 << i)) {
+ ti->flags |= T_SYNCNEGO;
+ }
+ }
+ sc->sc_nexus = NULL;
+}
+
+int
+mesh_stp(sc, v)
+ struct mesh_softc *sc;
+ int v;
+{
+ /*
+ * stp(v) = 5 * clock_period (v == 0)
+ * = (v + 2) * 2 clock_period (v > 0)
+ */
+
+ if (v == 0)
+ return 5 * 250 / sc->sc_freq;
+ else
+ return (v + 2) * 2 * 250 / sc->sc_freq;
+}
+
+void
+mesh_setsync(sc, ti)
+ struct mesh_softc *sc;
+ struct mesh_tinfo *ti;
+{
+ int period = ti->period;
+ int offset = ti->offset;
+ int v;
+
+ if ((ti->flags & T_SYNCMODE) == 0)
+ offset = 0;
+
+ if (offset == 0) { /* async mode */
+ mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
+ return;
+ }
+
+ v = period * sc->sc_freq / 250 / 2 - 2;
+ if (v < 0)
+ v = 0;
+ if (mesh_stp(sc, v) < period)
+ v++;
+ if (v > 15)
+ v = 15;
+ mesh_set_reg(sc, MESH_SYNC_PARAM, (offset << 4) | v);
+}
+
+struct mesh_scb *
+mesh_get_scb(sc)
+ struct mesh_softc *sc;
+{
+ struct mesh_scb *scb;
+ int s;
+
+ s = splbio();
+ while ((scb = sc->free_scb.tqh_first) == NULL)
+ tsleep(&sc->free_scb, PRIBIO, "meshscb", 0);
+ TAILQ_REMOVE(&sc->free_scb, scb, chain);
+ splx(s);
+
+ return scb;
+}
+
+void
+mesh_free_scb(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ int s;
+
+ s = splbio();
+ TAILQ_INSERT_HEAD(&sc->free_scb, scb, chain);
+ if (scb->chain.tqe_next == NULL)
+ wakeup(&sc->free_scb);
+ splx(s);
+}
+
+int
+mesh_scsi_cmd(xs)
+ struct scsi_xfer *xs;
+{
+ struct scsi_link *sc_link = xs->sc_link;
+ struct mesh_softc *sc = sc_link->adapter_softc;
+ struct mesh_scb *scb;
+ u_int flags;
+ int s;
+
+ flags = xs->flags;
+
+ scb = mesh_get_scb(sc);
+ scb->xs = xs;
+ scb->flags = 0;
+ scb->status = 0;
+ scb->daddr = (vaddr_t)xs->data;
+ scb->dlen = xs->datalen;
+ scb->resid = xs->datalen;
+ bcopy(xs->cmd, &scb->cmd, xs->cmdlen);
+ scb->cmdlen = xs->cmdlen;
+
+ scb->target = sc_link->target;
+ sc->sc_imsglen = 0; /* XXX ? */
+
+ printf("messh_scsi_cmd,scb->target=%d\n",scb->target);
+
+ if (flags & SCSI_POLL){
+ printf("mesh_scsi_cmd:flags=SCSI_POLL\n");
+ scb->flags |= MESH_POLL;
+ }
+
+#if 0
+ if (flags & SCSI_DATA_OUT)
+ scb->flags &= ~MESH_READ;
+#endif
+ if (flags & SCSI_DATA_IN){
+ printf("mesh_scsi_cmd:flags=SCSI_DATA_IN\n");
+ scb->flags |= MESH_READ;
+ }
+
+ s = splbio();
+
+ TAILQ_INSERT_TAIL(&sc->ready_scb, scb, chain);
+
+ if (sc->sc_nexus == NULL){
+ printf("mesh_scsi_cmd:sc->sc_nexus == NULL,calling mesh_sched\n"); /* IDLE */
+ mesh_sched(sc);
+ }
+
+ splx(s);
+
+ if ((flags & SCSI_POLL) == 0){
+ printf("mesh_scsi_cmd: returning SUCCESSFULLY_QUEUED\n");
+ return SUCCESSFULLY_QUEUED;
+ }
+
+ if (mesh_poll(sc, xs)) {
+ printf("mesh: timeout\n");
+ if (mesh_poll(sc, xs))
+ printf("mesh: timeout again\n");
+ }
+ printf("mesh_scsi_cmd: returning COMPLETE\n");
+ return COMPLETE;
+}
+
+void
+mesh_sched(sc)
+ struct mesh_softc *sc;
+{
+ struct scsi_xfer *xs;
+ struct scsi_link *sc_link;
+ struct mesh_scb *scb;
+
+ scb = sc->ready_scb.tqh_first;
+start:
+ if (scb == NULL)
+ return;
+
+ xs = scb->xs;
+ sc_link = xs->sc_link;
+
+ if (sc->sc_nexus == NULL) {
+ TAILQ_REMOVE(&sc->ready_scb, scb, chain);
+ sc->sc_nexus = scb;
+ mesh_select(sc, scb);
+ return;
+ }
+
+ scb = scb->chain.tqe_next;
+ goto start;
+}
+
+int
+mesh_poll(sc, xs)
+ struct mesh_softc *sc;
+ struct scsi_xfer *xs;
+{
+ int count = xs->timeout;
+ printf("in mesh_poll,timeout=%d\n",xs->timeout);
+
+
+ while (count) {
+ if (mesh_read_reg(sc, MESH_INTERRUPT))
+ mesh_intr(sc);
+
+ if (xs->flags & ITSDONE)
+ return 0;
+ DELAY(1000);
+ count--;
+ };
+ return 1;
+}
+
+void
+mesh_done(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ struct scsi_xfer *xs = scb->xs;
+
+#ifdef MESH_SHOWSTATE
+ printf("mesh_done\n");
+#endif
+
+ sc->sc_nextstate = MESH_BUSFREE;
+ sc->sc_nexus = NULL;
+
+ untimeout(mesh_timeout, scb);
+
+ if (scb->status == SCSI_BUSY) {
+ xs->error = XS_BUSY;
+ printf("Target busy\n");
+ }
+
+ if (scb->status == SCSI_CHECK) {
+ if (scb->flags & MESH_SENSE)
+ panic("SCSI_CHECK && MESH_SENSE?");
+ xs->resid = scb->resid;
+ mesh_sense(sc, scb);
+ return;
+ }
+
+ if (xs->error == XS_NOERROR) {
+ xs->status = scb->status;
+ if (scb->flags & MESH_SENSE)
+ xs->error = XS_SENSE;
+ else
+ xs->resid = scb->resid;
+ }
+
+ xs->flags |= ITSDONE;
+
+ mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
+
+ if ((xs->flags & SCSI_POLL) == 0)
+ mesh_sched(sc);
+
+ scsi_done(xs);
+ mesh_free_scb(sc, scb);
+}
+
+void
+mesh_timeout(arg)
+ void *arg;
+{
+ struct mesh_scb *scb = arg;
+ struct mesh_softc *sc = scb->xs->sc_link->adapter_softc;
+ int s;
+ int status0, status1;
+ int intr, error, exception;
+
+ printf("mesh: timeout state=%x\n", sc->sc_nextstate);
+ intr = mesh_read_reg(sc, MESH_INTERRUPT);
+
+
+ exception = mesh_read_reg(sc, MESH_EXCEPTION);
+
+ error = mesh_read_reg(sc, MESH_ERROR);
+
+ status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
+
+ status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
+
+#if 1
+printf("intr 0x%02x, except 0x%02x, err 0x%02x\n", intr, exception, error);
+#endif
+
+ s = splbio();
+
+ if (sc->sc_flags & MESH_DMA_ACTIVE) {
+ printf("mesh: resetting dma\n");
+ dbdma_reset(sc->sc_dmareg);
+ }
+ scb->xs->error = XS_TIMEOUT;
+
+ mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
+
+ sc->sc_nextstate = MESH_COMPLETE;
+
+ splx(s);
+ printf("rerturning from mesh_timeout\n");
+}
+
+void
+mesh_sense(sc, scb)
+ struct mesh_softc *sc;
+ struct mesh_scb *scb;
+{
+ struct scsi_xfer *xs = scb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct scsi_sense *ss = (void *)&scb->cmd;
+
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = sc_link->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+ scb->cmdlen = sizeof(*ss);
+ scb->daddr = (vaddr_t)&xs->sense;
+ scb->dlen = sizeof(struct scsi_sense_data);
+ scb->resid = scb->dlen;
+ bzero((void *)scb->daddr, scb->dlen);
+
+ scb->flags |= MESH_SENSE | MESH_READ;
+
+ TAILQ_INSERT_HEAD(&sc->ready_scb, scb, chain);
+ if (sc->sc_nexus == NULL)
+ mesh_sched(sc);
+}
+
+void
+mesh_minphys(bp)
+ struct buf *bp;
+{
+ if (bp->b_bcount > 64*1024)
+ bp->b_bcount = 64*1024;
+
+ minphys(bp);
+}
diff --git a/sys/arch/powerpc/mac/meshreg.h b/sys/arch/powerpc/mac/meshreg.h
new file mode 100644
index 00000000000..9c6e6941ba4
--- /dev/null
+++ b/sys/arch/powerpc/mac/meshreg.h
@@ -0,0 +1,110 @@
+/* $NetBSD: meshreg.h,v 1.1 1999/02/19 13:06:03 tsubai Exp $ */
+
+/*-
+ * Copyright (C) 1999 Internet Research Institute, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by
+ * Internet Research Institute, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* MESH register offsets */
+#define MESH_XFER_COUNT0 0x00 /* transfer count (low) */
+#define MESH_XFER_COUNT1 0x10 /* transfer count (high) */
+#define MESH_FIFO 0x20 /* FIFO (16byte depth) */
+#define MESH_SEQUENCE 0x30 /* command register */
+#define MESH_BUS_STATUS0 0x40
+#define MESH_BUS_STATUS1 0x50
+#define MESH_FIFO_COUNT 0x60
+#define MESH_EXCEPTION 0x70
+#define MESH_ERROR 0x80
+#define MESH_INTR_MASK 0x90
+#define MESH_INTERRUPT 0xa0
+#define MESH_SOURCE_ID 0xb0
+#define MESH_DEST_ID 0xc0
+#define MESH_SYNC_PARAM 0xd0
+#define MESH_MESH_ID 0xe0 /* MESH version */
+#define MESH_SEL_TIMEOUT 0xf0 /* selection timeout delay */
+
+#define MESH_SIGNATURE 0xe2 /* XXX wrong! */
+
+/* MESH commands */
+#define MESH_CMD_ARBITRATE 0x01
+#define MESH_CMD_SELECT 0x02
+#define MESH_CMD_COMMAND 0x03
+#define MESH_CMD_STATUS 0x04
+#define MESH_CMD_DATAOUT 0x05
+#define MESH_CMD_DATAIN 0x06
+#define MESH_CMD_MSGOUT 0x07
+#define MESH_CMD_MSGIN 0x08
+#define MESH_CMD_BUSFREE 0x09
+#define MESH_CMD_ENABLE_PARITY 0x0A
+#define MESH_CMD_DISABLE_PARITY 0x0B
+#define MESH_CMD_ENABLE_RESEL 0x0C
+#define MESH_CMD_DISABLE_RESEL 0x0D
+#define MESH_CMD_RESET_MESH 0x0E
+#define MESH_CMD_FLUSH_FIFO 0x0F
+#define MESH_SEQ_DMA 0x80
+#define MESH_SEQ_TARGET 0x40
+#define MESH_SEQ_ATN 0x20
+#define MESH_SEQ_ACTNEG 0x10
+
+/* INTERRUPT/INTR_MASK register bits */
+#define MESH_INTR_ERROR 0x04
+#define MESH_INTR_EXCEPTION 0x02
+#define MESH_INTR_CMDDONE 0x01
+
+/* EXCEPTION register bits */
+#define MESH_EXC_SELATN 0x20 /* selected and ATN asserted (T) */
+#define MESH_EXC_SELECTED 0x10 /* selected (T) */
+#define MESH_EXC_RESEL 0x08 /* reselected */
+#define MESH_EXC_ARBLOST 0x04 /* arbitration lost */
+#define MESH_EXC_PHASEMM 0x02 /* phase mismatch */
+#define MESH_EXC_SELTO 0x01 /* selection timeout */
+
+/* ERROR register bits */
+#define MESH_ERR_DISCONNECT 0x40 /* unexpected disconnect */
+#define MESH_ERR_SCSI_RESET 0x20 /* Rst signal asserted */
+#define MESH_ERR_SEQERR 0x10 /* sequence error */
+#define MESH_ERR_PARITY_ERR3 0x08 /* parity error */
+#define MESH_ERR_PARITY_ERR2 0x04
+#define MESH_ERR_PARITY_ERR1 0x02
+#define MESH_ERR_PARITY_ERR0 0x01
+
+/* BUS_STATUS0 status bits */
+#define MESH_STATUS0_REQ32 0x80
+#define MESH_STATUS0_ACK32 0x40
+#define MESH_STATUS0_REQ 0x20
+#define MESH_STATUS0_ACK 0x10
+#define MESH_STATUS0_ATN 0x08
+#define MESH_STATUS0_MSG 0x04
+#define MESH_STATUS0_CD 0x02
+#define MESH_STATUS0_IO 0x01
+
+/* BUS_STATUS1 status bits */
+#define MESH_STATUS1_RST 0x80
+#define MESH_STATUS1_BSY 0x40
+#define MESH_STATUS1_SEL 0x20
diff --git a/sys/arch/powerpc/mac/openpic.c b/sys/arch/powerpc/mac/openpic.c
index 2ecd3a57dcd..71dc12ff0c3 100644
--- a/sys/arch/powerpc/mac/openpic.c
+++ b/sys/arch/powerpc/mac/openpic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: openpic.c,v 1.5 2000/07/08 19:53:12 rahnds Exp $ */
+/* $OpenBSD: openpic.c,v 1.6 2000/07/28 13:09:01 rahnds Exp $ */
/*-
* Copyright (c) 1995 Per Fogelstrom
@@ -188,9 +188,8 @@ void
openpic_collect_preconf_intr()
{
int i;
- printf("postconfiguring interrupts\n");
for (i = 0; i < ppc_configed_intr_cnt; i++) {
- printf("\t%s irq %d level %d fun %x arg %x\n",
+ printf("\n\t%s irq %d level %d fun %x arg %x",
ppc_configed_intr[i].ih_what,
ppc_configed_intr[i].ih_irq,
ppc_configed_intr[i].ih_level,