summaryrefslogtreecommitdiff
path: root/sys/arch/powerpc
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 /sys/arch/powerpc
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.
Diffstat (limited to 'sys/arch/powerpc')
-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,