summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorbouyer <bouyer@NetBSD.org>2000-04-25 16:27:05 +0000
committerbouyer <bouyer@NetBSD.org>2000-04-25 16:27:05 +0000
commit88be4752d04db3caaabd06cbe7b450a0dd2b6a1d (patch)
treeb0a30d91a0498094bd13337422b475ed087325e7 /sys/dev
parent151b83e2e1453854e0170f0955d8842f0e8787a6 (diff)
- Change the script to start new commands in an asyncronous way, using
'command slots' in which the host can put command and wait for the script to start them - Change siop.c to do full disconnect/reslelect, allowing as much as one command per target/lun to run in parallel. - Fix bug in registers init where a board without BIOS would end at ID 0 (now the driver works on alpha too). - better handling of messages, sending back a MSG_EXT_SDTR in response to an incoming MSG_EXT_SDTR, and MSG_MESSAGE_REJECT for unhandled messages. - fix use of bus_dmamap_sync() and htole32(). - supports shared interrups - change some int8 and int16 to int, for alpha and mips benefits ( suggested by Toru Nishimura)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/siop.c765
-rw-r--r--sys/dev/ic/siopreg.h3
-rw-r--r--sys/dev/ic/siopvar.h15
-rw-r--r--sys/dev/microcode/siop/siop.out291
-rw-r--r--sys/dev/microcode/siop/siop.ss115
5 files changed, 878 insertions, 311 deletions
diff --git a/sys/dev/ic/siop.c b/sys/dev/ic/siop.c
index 0060a8565b9..e1d5335ed60 100644
--- a/sys/dev/ic/siop.c
+++ b/sys/dev/ic/siop.c
@@ -1,4 +1,4 @@
-/* $NetBSD: siop.c,v 1.1 2000/04/21 17:56:58 bouyer Exp $ */
+/* $NetBSD: siop.c,v 1.2 2000/04/25 16:27:05 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -41,6 +41,7 @@
#include <sys/malloc.h>
#include <sys/buf.h>
#include <sys/kernel.h>
+#include <sys/scsiio.h>
#include <machine/endian.h>
#include <machine/bus.h>
@@ -60,12 +61,19 @@
#include <dev/ic/siopreg.h>
#include <dev/ic/siopvar.h>
+#undef DEBUG
+#undef DEBUG_INTR
+#undef DEBUG_SHED
+#undef DUMP_SCRIPT
+
+#define SIOP_STATS
+
#ifndef SIOP_DEFAULT_TARGET
#define SIOP_DEFAULT_TARGET 7
#endif
#define MEM_SIZE 8192
-#define SCRIPT_OFF 4096
+#define CMD_OFF 4096
/* tables used by SCRIPT */
typedef struct scr_table {
@@ -81,17 +89,19 @@ typedef struct scr_table {
* transfert. It lives in the same chunk of DMA-safe memory as the script.
*/
struct siop_xfer {
- u_int8_t msg_out; /* 0 */
- u_int8_t msg_in; /* 1 */
- u_int8_t status; /* 2 */
- u_int8_t pad2; /* 3 */
- u_int32_t id; /* 4 */
- u_int32_t pad1; /* 8 */
- scr_table_t t_msgin; /* 12 */
- scr_table_t t_msgout; /* 20 */
- scr_table_t cmd; /* 28 */
- scr_table_t t_status; /* 36 */
- scr_table_t data[SIOP_NSG]; /* 44 */
+ u_int8_t msg_out[8]; /* 0 */
+ u_int8_t msg_in[8]; /* 8 */
+ int status; /* 16 */
+ u_int32_t id; /* 20 */
+ u_int32_t pad1; /* 24 */
+ scr_table_t t_msgin; /* 28 */
+ scr_table_t t_extmsgin; /* 36 */
+ scr_table_t t_extmsgdata; /* 44 */
+ scr_table_t t_extmsgtag; /* 52 */
+ scr_table_t t_msgout; /* 60 */
+ scr_table_t cmd; /* 68 */
+ scr_table_t t_status; /* 76 */
+ scr_table_t data[SIOP_NSG]; /* 84 */
};
/*
@@ -104,20 +114,22 @@ struct siop_cmd {
struct siop_softc *siop_sc; /* pointer to adapter */
struct scsipi_xfer *xs; /* xfer from the upper level */
struct siop_xfer *siop_table; /* tables dealing with this xfer */
+ bus_addr_t dsa; /* DSA value to load */
bus_dmamap_t dmamap_cmd;
bus_dmamap_t dmamap_data;
struct scsipi_sense rs_cmd; /* request sense command buffer */
- u_int16_t status;
- u_int16_t flags;
+ int status;
+ int flags;
};
/* status defs */
-#define CMDST_FREE 0 /* cmd slot is free */
-#define CMDST_READY 1 /* cmd slot is waiting for processing */
-#define CMDST_ACTIVE 2 /* cmd slot is being processed */
-#define CMDST_SENSE 3 /* cmd slot is being requesting sense */
-#define CMDST_SENSE_DONE 4 /* request sense done */
-#define CMDST_DONE 5 /* cmd slot has been processed */
+#define CMDST_FREE 0 /* cmd slot is free */
+#define CMDST_READY 1 /* cmd slot is waiting for processing */
+#define CMDST_ACTIVE 2 /* cmd slot is being processed */
+#define CMDST_SENSE 3 /* cmd slot is being requesting sense */
+#define CMDST_SENSE_ACTIVE 4 /* request sense active */
+#define CMDST_SENSE_DONE 5 /* request sense done */
+#define CMDST_DONE 6 /* cmd slot has been processed */
/* flags defs */
#define CMDFL_TIMEOUT 0x0001 /* cmd timed out */
@@ -125,17 +137,23 @@ struct siop_cmd {
#define SIOP_NCMD 10
void siop_reset __P((struct siop_softc *));
+void siop_handle_reset __P((struct siop_softc *));
+void siop_scsicmd_end __P((struct siop_cmd *));
void siop_start __P((struct siop_softc *));
void siop_timeout __P((void *));
void siop_minphys __P((struct buf *));
+int siop_ioctl __P((struct scsipi_link *, u_long,
+ caddr_t, int, struct proc *));
int siop_scsicmd __P((struct scsipi_xfer *));
void siop_sdp __P((struct siop_cmd *));
void siop_ssg __P((struct siop_cmd *));
+void siop_dump_script __P((struct siop_softc *));
struct scsipi_adapter siop_adapter = {
0,
siop_scsicmd,
siop_minphys,
+ siop_ioctl,
NULL,
};
@@ -146,6 +164,42 @@ struct scsipi_device siop_dev = {
NULL,
};
+#ifdef SIOP_STATS
+static int siop_stat_intr = 0;
+static int siop_stat_intr_shortxfer = 0;
+static int siop_stat_intr_sdp = 0;
+static int siop_stat_intr_done = 0;
+static int siop_stat_intr_reselect = 0;
+static int siop_stat_intr_xferdisc = 0;
+void siop_printstats __P((void));
+#define INCSTAT(x) x++
+#else
+#define INCSTAT(x)
+#endif
+
+static __inline__ void siop_table_sync __P((struct siop_cmd *, int));
+static __inline__ void
+siop_table_sync(siop_cmd, ops)
+ struct siop_cmd *siop_cmd;
+ int ops;
+{
+ struct siop_softc *sc = siop_cmd->siop_sc;
+ bus_addr_t offset;
+
+ offset = sc->sc_scriptdma->dm_segs[0].ds_addr - siop_cmd->dsa;
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_scriptdma, offset,
+ sizeof(struct siop_xfer), ops);
+}
+
+static __inline__ void siop_script_sync __P((struct siop_softc *, int));
+static __inline__ void
+siop_script_sync(sc, ops)
+ struct siop_softc *sc;
+ int ops;
+{
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_scriptdma, 0, CMD_OFF, ops);
+}
+
void
siop_attach(sc)
struct siop_softc *sc;
@@ -153,7 +207,6 @@ siop_attach(sc)
int error, i;
bus_dma_segment_t seg;
int rseg;
- struct siop_cmd *cmds;
/*
* Allocate DMA-safe memory for the script itself and internal
@@ -191,8 +244,9 @@ siop_attach(sc)
for (i = 0; i < 16; i++)
TAILQ_INIT(&sc->active_list[i]);
/* allocate cmd list */
- cmds = malloc(sizeof(struct siop_cmd) * SIOP_NCMD, M_DEVBUF, M_NOWAIT);
- if (cmds == NULL) {
+ sc->cmds =
+ malloc(sizeof(struct siop_cmd) * SIOP_NCMD, M_DEVBUF, M_NOWAIT);
+ if (sc->cmds == NULL) {
printf("%s: can't allocate memory for command descriptors\n",
sc->sc_dev.dv_xname);
return;
@@ -200,7 +254,7 @@ siop_attach(sc)
for (i = 0; i < SIOP_NCMD; i++) {
error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, SIOP_NSG,
MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
- &cmds[i].dmamap_data);
+ &sc->cmds[i].dmamap_data);
if (error) {
printf("%s: unable to create data DMA map for cbd %d\n",
sc->sc_dev.dv_xname, error);
@@ -210,35 +264,50 @@ siop_attach(sc)
sizeof(struct scsipi_generic), 1,
sizeof(struct scsipi_generic), 0,
BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
- &cmds[i].dmamap_cmd);
+ &sc->cmds[i].dmamap_cmd);
if (error) {
printf("%s: unable to create cmd DMA map for cbd %d\n",
sc->sc_dev.dv_xname, error);
return;
}
- cmds[i].siop_sc = sc;
- cmds[i].siop_table = &((struct siop_xfer *)sc->sc_script)[i];
- cmds[i].status = CMDST_FREE;
- cmds[i].siop_table->t_msgout.count= htole32(1);
- cmds[i].siop_table->t_msgout.addr =
- htole32(sc->sc_scriptdma->dm_segs[0].ds_addr +
- i * sizeof(struct siop_xfer));
- cmds[i].siop_table->t_msgin.count= htole32(1);
- cmds[i].siop_table->t_msgin.addr =
- htole32(htole32(cmds[i].siop_table->t_msgout.addr) + 1);
- cmds[i].siop_table->t_status.count= htole32(1);
- cmds[i].siop_table->t_status.addr =
- htole32(htole32(cmds[i].siop_table->t_msgin.addr) + 1);
- TAILQ_INSERT_TAIL(&sc->free_list, &cmds[i], next);
+ sc->cmds[i].siop_sc = sc;
+ sc->cmds[i].siop_table =
+ &((struct siop_xfer *)(&sc->sc_script[CMD_OFF/4]))[i];
+ sc->cmds[i].dsa = sc->sc_scriptdma->dm_segs[0].ds_addr +
+ CMD_OFF + i * sizeof(struct siop_xfer);
+ sc->cmds[i].status = CMDST_FREE;
+ sc->cmds[i].siop_table->t_msgout.count= htole32(1);
+ sc->cmds[i].siop_table->t_msgout.addr =
+ htole32(sc->cmds[i].dsa);
+ sc->cmds[i].siop_table->t_msgin.count= htole32(1);
+ sc->cmds[i].siop_table->t_msgin.addr =
+ htole32(sc->cmds[i].dsa + 8);
+ sc->cmds[i].siop_table->t_extmsgin.count= htole32(2);
+ sc->cmds[i].siop_table->t_extmsgin.addr =
+ htole32(htole32(sc->cmds[i].siop_table->t_msgin.addr) + 1);
+ sc->cmds[i].siop_table->t_status.count= htole32(1);
+ sc->cmds[i].siop_table->t_status.addr =
+ htole32(htole32(sc->cmds[i].siop_table->t_msgin.addr) + 8);
+ TAILQ_INSERT_TAIL(&sc->free_list, &sc->cmds[i], next);
+#ifdef DEBUG
printf("tables[%d]: out=0x%x in=0x%x status=0x%x\n", i,
- cmds[i].siop_table->t_msgin.addr,
- cmds[i].siop_table->t_msgout.addr,
- cmds[i].siop_table->t_status.addr);
+ sc->cmds[i].siop_table->t_msgin.addr,
+ sc->cmds[i].siop_table->t_msgout.addr,
+ sc->cmds[i].siop_table->t_status.addr);
+#endif
}
+ /* compute number of sheduler slots */
+ sc->sc_nshedslots = (
+ CMD_OFF /* memory size allocated for scripts */
+ - sizeof(siop_script) /* memory for main script */
+ + 8 /* extra NOP at end of main script */
+ - sizeof(endslot_script) /* memory needed at end of sheduler */
+ ) / (sizeof(slot_script) - 8);
#ifdef DEBUG
- printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
- sc->sc_dev.dv_xname, sizeof(siop_script),
- (u_int)sc->sc_scriptdma->dm_segs[0].ds_addr, sc->sc_script);
+ printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p nslots %d\n",
+ sc->sc_dev.dv_xname, (int)sizeof(siop_script),
+ (u_int)sc->sc_scriptdma->dm_segs[0].ds_addr, sc->sc_script,
+ sc->sc_nshedslots);
#endif
sc->sc_link.adapter_softc = sc;
@@ -249,7 +318,8 @@ siop_attach(sc)
sc->sc_link.scsipi_scsi.max_lun = 7;
sc->sc_link.scsipi_scsi.adapter_target = bus_space_read_1(sc->sc_rt,
sc->sc_rh, SIOP_SCID);
- if (sc->sc_link.scsipi_scsi.adapter_target >
+ if (sc->sc_link.scsipi_scsi.adapter_target == 0 ||
+ sc->sc_link.scsipi_scsi.adapter_target >
sc->sc_link.scsipi_scsi.max_target)
sc->sc_link.scsipi_scsi.adapter_target = SIOP_DEFAULT_TARGET;
sc->sc_link.type = BUS_SCSI;
@@ -258,6 +328,9 @@ siop_attach(sc)
sc->sc_link.flags = 0;
siop_reset(sc);
+#ifdef DUMP_SCRIPT
+ siop_dump_script(sc);
+#endif
config_found((struct device*)sc, &sc->sc_link, scsiprint);
}
@@ -266,13 +339,43 @@ void
siop_reset(sc)
struct siop_softc *sc;
{
+ int i;
+ u_int32_t *scr;
+ bus_addr_t physaddr;
/* reset the chip */
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_SRST);
delay(1000);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, 0);
/* copy and patch the script */
- memcpy(&sc->sc_script[SCRIPT_OFF/4], siop_script, sizeof(siop_script));
+ memcpy(sc->sc_script, siop_script, sizeof(siop_script));
+ /* copy the sheduler slots script */
+ for (i = 0; i < sc->sc_nshedslots; i++) {
+ scr = &sc->sc_script[Ent_sheduler / 4 + (Ent_nextslot / 4) * i];
+ physaddr = sc->sc_scriptdma->dm_segs[0].ds_addr + Ent_sheduler
+ + Ent_nextslot * i;
+ memcpy(scr, slot_script, sizeof(slot_script));
+ /*
+ * save current jump offset and patch MOVE MEMORY operands
+ * to restore it.
+ */
+ scr[Ent_slotdata/4 + 1] = scr[Ent_slot/4 + 1];
+ scr[E_slot_nextp_Used[0]] = htole32(physaddr + Ent_slot + 4);
+ scr[E_slot_shed_addrsrc_Used[0]] = htole32(physaddr +
+ Ent_slotdata + 4);
+ /* JUMP selected, in main script */
+ scr[E_slot_abs_selected_Used[0]] =
+ htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + Ent_selected);
+ /* JUMP addr if SELECT fail */
+ scr[E_slot_abs_reselect_Used[0]] =
+ htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + Ent_reselect);
+ }
+ /* Now the final JUMP */
+ scr = &sc->sc_script[Ent_sheduler / 4 +
+ (Ent_nextslot / 4) * sc->sc_nshedslots];
+ memcpy(scr, endslot_script, sizeof(endslot_script));
+ scr[E_endslot_abs_reselect_Used[0]] =
+ htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + Ent_reselect);
/* init registers */
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL0,
@@ -292,25 +395,24 @@ siop_reset(sc)
sc->sc_link.scsipi_scsi.adapter_target | SCID_RRE);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_RESPID0,
1 << sc->sc_link.scsipi_scsi.adapter_target);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, 0);
+
+ /* start script */
+ siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
+ htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + Ent_reselect));
}
#if 0
#define CALL_SCRIPT(ent) do {\
printf ("start script DSA 0x%lx DSP 0x%lx\n", \
- htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + \
- (((caddr_t)siop_cmd->siop_table) - ((caddr_t)sc->sc_script))),\
- htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + SCRIPT_OFF + ent)); \
- bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSA, \
- htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + \
- (((caddr_t)siop_cmd->siop_table) - ((caddr_t)sc->sc_script)))); \
-bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + SCRIPT_OFF + ent)); \
+ htole32(siop_cmd->dsa), \
+ htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + ent)); \
+bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + ent)); \
} while (0)
#else
#define CALL_SCRIPT(ent) do {\
- bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSA, \
- htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + \
- (((caddr_t)siop_cmd->siop_table) - ((caddr_t)sc->sc_script)))); \
-bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + SCRIPT_OFF + ent)); \
+bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + ent)); \
} while (0)
#endif
@@ -324,22 +426,50 @@ siop_intr(v)
u_int8_t istat, sist0, sist1, sstat1, dstat, scntl1;
u_int32_t irqcode;
int need_reset = 0;
- int offset;
+ int offset, target;
+ bus_addr_t dsa;
istat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT);
+ if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
+ return 0;
+ INCSTAT(siop_stat_intr);
if (istat & ISTAT_INTF) {
printf("INTRF\n");
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_INTF);
}
+ /* use DSA to find the current siop_cmd */
+ dsa = bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA);
+ if (dsa >= sc->sc_scriptdma->dm_segs[0].ds_addr + CMD_OFF &&
+ dsa < sc->sc_scriptdma->dm_segs[0].ds_addr + CMD_OFF +
+ SIOP_NCMD * sizeof(struct siop_xfer)) {
+ dsa -= sc->sc_scriptdma->dm_segs[0].ds_addr + CMD_OFF;
+ siop_cmd = &sc->cmds[dsa / sizeof(struct siop_xfer)];
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ } else {
+ printf("%s: current DSA invalid\n",
+ sc->sc_dev.dv_xname);
+ siop_cmd = NULL;
+ }
if (istat & ISTAT_DIP) {
u_int32_t *p;
dstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DSTAT);
- if (dstat & ~(DSTAT_SIR | DSTAT_DFE)) {
+ if (dstat & DSTAT_SSI) {
+ printf("single step dsp 0x%08x dsa 0x08%x\n",
+ bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP),
+ bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
+ if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
+ (istat & ISTAT_SIP) == 0) {
+ bus_space_write_1(sc->sc_rt, sc->sc_rh,
+ SIOP_DCNTL, bus_space_read_1(sc->sc_rt,
+ sc->sc_rh, SIOP_DCNTL) | DCNTL_STD);
+ }
+ return 1;
+ }
+ if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
printf("DMA IRQ:");
if (dstat & DSTAT_IID)
printf(" Illegal instruction");
- if (dstat & DSTAT_SSI)
- printf(" single step");
if (dstat & DSTAT_ABRT)
printf(" abort");
if (dstat & DSTAT_BF)
@@ -351,18 +481,26 @@ siop_intr(v)
printf(", DSP=0x%x DSA=0x%x: ",
bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP),
bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
- p = &sc->sc_script[SCRIPT_OFF/4] +
+ p = sc->sc_script +
(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
- (sc->sc_scriptdma->dm_segs[0].ds_addr + SCRIPT_OFF)-8) / 4;
+ sc->sc_scriptdma->dm_segs[0].ds_addr - 8) / 4;
printf("0x%x 0x%x 0x%x 0x%x\n", p[0], p[1], p[2], p[3]);
- if ((siop_cmd = sc->active_list[sc->current_target].tqh_first))
+ if (siop_cmd)
printf("last msg_in=0x%x status=0x%x\n",
- siop_cmd->siop_table->msg_in,
- siop_cmd->siop_table->status);
+ siop_cmd->siop_table->msg_in[0],
+ htole32(siop_cmd->siop_table->status));
need_reset = 1;
}
}
if (istat & ISTAT_SIP) {
+ /*
+ * SCSI interrupt. If current command is not active,
+ * we don't need siop_cmd
+ */
+ if (siop_cmd->status != CMDST_ACTIVE &&
+ siop_cmd->status != CMDST_SENSE_ACTIVE) {
+ siop_cmd = NULL;
+ }
if (istat & ISTAT_DIP)
delay(1);
sist0 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST0);
@@ -376,27 +514,12 @@ siop_intr(v)
bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),
bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));
#endif
- siop_cmd = sc->active_list[sc->current_target].tqh_first;
if (siop_cmd)
xs = siop_cmd->xs;
if (sist0 & SIST0_RST) {
- /* scsi bus reset. reset the chip and restart
- * the queue.
- */
- printf("%s: scsi bus reset\n", sc->sc_dev.dv_xname);
- /* if we had a command running handle it */
- if (siop_cmd) {
- xs = siop_cmd->xs;
- if (siop_cmd->status == CMDST_ACTIVE ||
- siop_cmd->status == CMDST_SENSE)
- xs->error =
- (siop_cmd->flags & CMDFL_TIMEOUT) ?
- XS_TIMEOUT : XS_RESET;
- }
- siop_reset(sc);
- if (siop_cmd)
- goto end;
+ siop_handle_reset(sc);
siop_start(sc);
+ /* no table to flush here */
return 1;
}
if (sist0 & SIST0_SGE) {
@@ -417,14 +540,20 @@ siop_intr(v)
* transfer than requested). Just go to status
* and the command should terminate.
*/
+ INCSTAT(siop_stat_intr_shortxfer);
CALL_SCRIPT(Ent_status);
+ /* no table to flush here */
return 1;
case SSTAT1_PHASE_MSGIN:
/*
* target may be ready to disconnect
* Save data pointers just in case.
*/
+ INCSTAT(siop_stat_intr_xferdisc);
siop_sdp(siop_cmd);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
CALL_SCRIPT(Ent_msgin);
return 1;
}
@@ -467,7 +596,7 @@ siop_intr(v)
goto check_sense;
printf("%s: unexpected disconnect without "
"command\n", sc->sc_dev.dv_xname);
- need_reset = 1;
+ goto reset;
}
/* Else it's an unhandled exeption (for now). */
printf("%s: unhandled scsi interrupt, sist0=0x%x sist1=0x%x "
@@ -492,64 +621,158 @@ reset:
/* minimum 25 us, more time won't hurt */
delay(100);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, scntl1);
+ /* no table to flush here */
return 1;
}
- siop_cmd = sc->active_list[sc->current_target].tqh_first;
- if (siop_cmd == NULL) {
- printf("Aie, no command !\n");
- return(1);
- }
- xs = siop_cmd->xs;
if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
irqcode = bus_space_read_4(sc->sc_rt, sc->sc_rh,
SIOP_DSPS);
+#ifdef DEBUG_INTR
+ printf("script interrupt 0x%x\n", irqcode);
+#endif
+ /*
+ * an inactive command is only valid if it's a reselect
+ * interrupt: we'll change siop_cmd to point to the rigth one
+ * just here
+ */
+ if (irqcode != A_int_resel &&
+ siop_cmd->status != CMDST_ACTIVE &&
+ siop_cmd->status != CMDST_SENSE_ACTIVE) {
+ printf("%s: Aie, no command (IRQ code 0x%x current "
+ "status %d) !\n", sc->sc_dev.dv_xname,
+ irqcode, siop_cmd->status);
+ xs = NULL;
+ } else
+ xs = siop_cmd->xs;
switch(irqcode) {
case A_int_err:
- printf("error\n");
- xs->error = XS_SELTIMEOUT;
- goto end;
+ printf("error, DSP=0x%x\n",
+ bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));
+ if (xs) {
+ xs->error = XS_SELTIMEOUT;
+ goto end;
+ } else {
+ goto reset;
+ }
case A_int_msgin:
- scsi_print_addr(xs->sc_link);
- printf("unhandled message %d\n",
- siop_cmd->siop_table->msg_in);
- xs->error = XS_DRIVER_STUFFUP;
- goto end;
+ if (xs)
+ scsi_print_addr(xs->sc_link);
+ else
+ printf("%s: ", sc->sc_dev.dv_xname);
+ if (siop_cmd->siop_table->msg_in[0] ==
+ MSG_MESSAGE_REJECT) {
+ printf("scsi message reject, message sent "
+ "was 0x%x\n",
+ siop_cmd->siop_table->msg_out[0]);
+ if (siop_cmd->siop_table->msg_out[0] ==
+ MSG_MESSAGE_REJECT) {
+ /* MSG_REJECT for a MSG_REJECT !*/
+ goto reset;
+ }
+ /* no table to flush here */
+ CALL_SCRIPT(Ent_msgin_ack);
+ return 1;
+ }
+ printf("unhandled message 0x%x\n",
+ siop_cmd->siop_table->msg_in[0]);
+ siop_cmd->siop_table->t_msgout.count= htole32(1);
+ siop_cmd->siop_table->t_msgout.addr =
+ htole32(siop_cmd->dsa);
+ siop_cmd->siop_table->msg_out[0] = MSG_MESSAGE_REJECT;
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_send_msgout);
+ return 1;
+ case A_int_extmsgin:
+#ifdef DEBUG_INTR
+ printf("extended message: msg 0x%x len %d\n",
+ siop_cmd->siop_table->msg_in[2],
+ siop_cmd->siop_table->msg_in[1]);
+#endif
+ siop_cmd->siop_table->t_extmsgdata.count =
+ htole32(siop_cmd->siop_table->msg_in[1] - 1);
+ siop_cmd->siop_table->t_extmsgdata.addr =
+ htole32(
+ htole32(siop_cmd->siop_table->t_extmsgin.addr)
+ + 2);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_get_extmsgdata);
+ return 1;
+ case A_int_extmsgdata:
+#ifdef DEBUG_INTR
+ {
+ int i;
+ printf("extended message: 0x%x, data:",
+ siop_cmd->siop_table->msg_in[2]);
+ for (i = 3; i < 2 + siop_cmd->siop_table->msg_in[1];
+ i++)
+ printf(" 0x%x",
+ siop_cmd->siop_table->msg_in[i]);
+ printf("\n");
+ }
+#endif
+ if (siop_cmd->siop_table->msg_in[2] == MSG_EXT_SDTR) {
+ /* anserw with async for now */
+ siop_cmd->siop_table->msg_out[0] = MSG_EXTENDED;
+ siop_cmd->siop_table->msg_out[1] =
+ MSG_EXT_SDTR_LEN;
+ siop_cmd->siop_table->msg_out[2] = MSG_EXT_SDTR;
+ siop_cmd->siop_table->msg_out[3] = 0;
+ siop_cmd->siop_table->msg_out[4] = 0;
+ siop_cmd->siop_table->t_msgout.count =
+ htole32(MSG_EXT_SDTR_LEN + 2);
+ siop_cmd->siop_table->t_msgout.addr =
+ htole32(siop_cmd->dsa);
+ } else {
+ /* send a message reject */
+ siop_cmd->siop_table->t_msgout.count =
+ htole32(1);
+ siop_cmd->siop_table->t_msgout.addr =
+ htole32(siop_cmd->dsa);
+ siop_cmd->siop_table->msg_out[0] =
+ MSG_MESSAGE_REJECT;
+ }
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_send_msgout);
+ return 1;
case A_int_resel: /* reselected */
- if ((siop_cmd->siop_table->msg_in & 0x80) == 0) {
+ INCSTAT(siop_stat_intr_reselect);
+ if ((siop_cmd->siop_table->msg_in[0] & 0x80) == 0) {
printf("%s: reselect without identify (%d)\n",
sc->sc_dev.dv_xname,
- siop_cmd->siop_table->msg_in);
+ siop_cmd->siop_table->msg_in[0]);
goto reset;
}
- sc->current_target = bus_space_read_1(sc->sc_rt,
+ target = bus_space_read_1(sc->sc_rt,
sc->sc_rh, SIOP_SCRATCHA);
- if ((sc->current_target & 0x80) == 0) {
- printf("reselect without id (%d)\n",
- sc->current_target);
+ if ((target & 0x80) == 0) {
+ printf("reselect without id (%d)\n", target);
goto reset;
}
- sc->current_target &= 0x0f;
+ target &= 0x0f;
#ifdef DEBUG_DR
printf("reselected by target %d lun %d\n",
- sc->current_target,
- siop_cmd->siop_table->msg_in & 0x07);
+ target,
+ siop_cmd->siop_table->msg_in[0] & 0x07);
#endif
siop_cmd =
- sc->active_list[sc->current_target].tqh_first;
+ sc->active_list[target].tqh_first;
if (siop_cmd == NULL) {
printf("%s: reselected without cmd\n",
sc->sc_dev.dv_xname);
goto reset;
}
- bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSA,
- htole32(sc->sc_scriptdma->dm_segs[0].ds_addr +
- (((caddr_t)siop_cmd->siop_table) -
- ((caddr_t)sc->sc_script))));
- CALL_SCRIPT(Ent_reselected);
+ bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSA, \
+ htole32(siop_cmd->dsa));
+ /* no table to flush */
+ CALL_SCRIPT(Ent_selected);
return 1;
case A_int_disc:
+ INCSTAT(siop_stat_intr_sdp);
offset = bus_space_read_1(sc->sc_rt, sc->sc_rh,
SIOP_SCRATCHA + 1);
#ifdef DEBUG_DR
@@ -569,26 +792,37 @@ reset:
memmove(&siop_cmd->siop_table->data[0],
&siop_cmd->siop_table->data[offset],
(SIOP_NSG - offset) * sizeof(scr_table_t));
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
- CALL_SCRIPT(Ent_reselect);
+ CALL_SCRIPT(Ent_sheduler);
return 1;
case A_int_resfail:
printf("reselect failed\n");
- CALL_SCRIPT(Ent_reselect);
+ CALL_SCRIPT(Ent_sheduler);
return 1;
case A_int_done:
+ if (xs == NULL) {
+ printf("%s: done without command\n",
+ sc->sc_dev.dv_xname);
+ siop_cmd->status = 0;
+ CALL_SCRIPT(Ent_sheduler);
+ siop_start(sc);
+ return 1;
+ }
#if 0
printf("done, taget id 0x%x last msg in=0x%x "
"status=0x%x\n",
siop_cmd->siop_table->id,
- siop_cmd->siop_table->msg_in,
- siop_cmd->siop_table->status);
+ siop_cmd->siop_table->msg_in[0],
+ htole32(siop_cmd->siop_table->status));
#endif
- if (siop_cmd->status == CMDST_SENSE)
+ INCSTAT(siop_stat_intr_done);
+ if (siop_cmd->status == CMDST_SENSE_ACTIVE)
siop_cmd->status = CMDST_SENSE_DONE;
else
siop_cmd->status = CMDST_DONE;
- switch(siop_cmd->siop_table->status) {
+ switch(htole32(siop_cmd->siop_table->status)) {
case SCSI_OK:
xs->error = (siop_cmd->status == CMDST_DONE) ?
XS_NOERROR : XS_SENSE;
@@ -599,7 +833,8 @@ reset:
case SCSI_CHECK:
check_sense:
if (siop_cmd->status == CMDST_SENSE_DONE) {
- /* request sense on a request sense ? */ printf("request sense failed\n");
+ /* request sense on a request sense ? */
+ printf("request sense failed\n");
xs->error = XS_DRIVER_STUFFUP;
} else {
siop_cmd->status = CMDST_SENSE;
@@ -611,6 +846,7 @@ check_sense:
* aborted
*/
xs->error = XS_SELTIMEOUT;
+ break;
default:
xs->error = XS_DRIVER_STUFFUP;
}
@@ -622,10 +858,29 @@ check_sense:
}
return 1;
}
- siop_cmd->status = CMDST_DONE;
- xs->error = XS_BUSY;
- goto end;
+ /* We just should't get there */
+ panic("siop_intr: I shouldn't be there !");
+ return 1;
end:
+ siop_scsicmd_end(siop_cmd);
+ if (siop_cmd->status == CMDST_FREE) {
+ TAILQ_REMOVE(&sc->active_list[xs->sc_link->scsipi_scsi.target],
+ siop_cmd, next);
+ TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
+ }
+ bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
+ htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + Ent_reselect));
+ siop_start(sc);
+ return 1;
+}
+
+void
+siop_scsicmd_end(siop_cmd)
+ struct siop_cmd *siop_cmd;
+{
+ struct scsipi_xfer *xs = siop_cmd->xs;
+ struct siop_softc *sc = siop_cmd->siop_sc;
+
if (siop_cmd->status != CMDST_SENSE_DONE &&
xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
@@ -643,7 +898,11 @@ end:
siop_cmd->rs_cmd.unused[0] = siop_cmd->rs_cmd.unused[1] = 0;
siop_cmd->rs_cmd.length = sizeof(struct scsipi_sense_data);
siop_cmd->rs_cmd.control = 0;
- siop_cmd->siop_table->status = 0xff; /* set invalid status */
+ siop_cmd->siop_table->status = htole32(0xff); /*invalid status*/
+ siop_cmd->siop_table->t_msgout.count= htole32(1);
+ siop_cmd->siop_table->t_msgout.addr = htole32(siop_cmd->dsa);
+ siop_cmd->siop_table->msg_out[0] =
+ MSG_IDENTIFY(xs->sc_link->scsipi_scsi.lun, 1);
error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,
&siop_cmd->rs_cmd, sizeof(struct scsipi_sense),
NULL, BUS_DMA_NOWAIT);
@@ -677,10 +936,13 @@ end:
siop_cmd->dmamap_data->dm_mapsize, BUS_DMASYNC_PREREAD);
bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd, 0,
siop_cmd->dmamap_cmd->dm_mapsize, BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(sc->sc_dmat, sc->sc_scriptdma, 0,
- sc->sc_scriptdma->dm_mapsize, BUS_DMASYNC_PREWRITE);
- siop_start(sc);
- return(1);
+ siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
+#if 0
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_scriptdma, CMD_OFF,
+ sc->sc_scriptdma->dm_mapsize - CMD_OFF,
+ BUS_DMASYNC_PREWRITE);
+#endif
+ return;
} else if (siop_cmd->status == CMDST_SENSE_DONE) {
bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
siop_cmd->dmamap_data->dm_mapsize, BUS_DMASYNC_POSTREAD);
@@ -688,15 +950,56 @@ end:
}
out:
callout_stop(&siop_cmd->xs->xs_callout);
- TAILQ_REMOVE(&sc->active_list[sc->current_target], siop_cmd, next);
siop_cmd->status = CMDST_FREE;
- TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
xs->xs_status |= XS_STS_DONE;
xs->resid = 0;
scsipi_done (xs);
- /* restart any pending cmd */
- siop_start(sc);
- return 1;
+}
+
+/*
+ * handle a bus reset: reset chip, unqueue all active commands and report
+ * loosage to upper layer.
+ * As the upper layer may requeue immediatly we have to first store
+ * all active commands in a temporary queue.
+ */
+void
+siop_handle_reset(sc)
+ struct siop_softc *sc;
+{
+ struct cmd_list reset_list;
+ struct siop_cmd *siop_cmd, *next_siop_cmd;
+ int target;
+ /*
+ * scsi bus reset. reset the chip and restart
+ * the queue. Need to clean up all active commands
+ */
+ printf("%s: scsi bus reset\n", sc->sc_dev.dv_xname);
+ /* stop, reset and restart the chip */
+ siop_reset(sc);
+ TAILQ_INIT(&reset_list);
+ /* find all active commands */
+ for (target = 0; target < 16; target++) {
+ for (siop_cmd = TAILQ_FIRST(&sc->active_list[target]);
+ siop_cmd != NULL; siop_cmd = next_siop_cmd) {
+ next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
+ if (siop_cmd->status < CMDST_ACTIVE)
+ continue;
+ printf("cmd %p (target %d) in reset list\n", siop_cmd,
+ target);
+ TAILQ_REMOVE( &sc->active_list[target], siop_cmd, next);
+ TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
+ }
+ }
+ for (siop_cmd = TAILQ_FIRST(&reset_list); siop_cmd != NULL;
+ siop_cmd = next_siop_cmd) {
+ next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
+ siop_cmd->xs->error = (siop_cmd->flags & CMDFL_TIMEOUT) ?
+ XS_TIMEOUT : XS_RESET;
+ printf("cmd %p about to be processed\n", siop_cmd);
+ TAILQ_REMOVE(&reset_list, siop_cmd, next);
+ siop_scsicmd_end(siop_cmd);
+ TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
+ }
}
void
@@ -707,6 +1010,34 @@ siop_minphys(bp)
}
int
+siop_ioctl(link, cmd, arg, flag, p)
+ struct scsipi_link *link;
+ u_long cmd;
+ caddr_t arg;
+ int flag;
+ struct proc *p;
+{
+ struct siop_softc *sc = link->adapter_softc;
+ u_int8_t scntl1;
+ int s;
+
+ switch (cmd) {
+ case SCBUSIORESET:
+ s = splbio();
+ scntl1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1,
+ scntl1 | SCNTL1_RST);
+ /* minimum 25 us, more time won't hurt */
+ delay(100);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, scntl1);
+ splx(s);
+ return (0);
+ default:
+ return (ENOTTY);
+ }
+}
+
+int
siop_scsicmd(xs)
struct scsipi_xfer *xs;
{
@@ -737,9 +1068,11 @@ siop_scsicmd(xs)
id |= xs->sc_link->scsipi_scsi.target << 16; /* id */
id |= 0xe0 << 8; /* scxfer */
siop_cmd->siop_table->id = htole32(id);
- siop_cmd->siop_table->msg_out =
+ siop_cmd->siop_table->t_msgout.count= htole32(1);
+ siop_cmd->siop_table->t_msgout.addr = htole32(siop_cmd->dsa);
+ siop_cmd->siop_table->msg_out[0] =
MSG_IDENTIFY(xs->sc_link->scsipi_scsi.lun, 1);
- siop_cmd->siop_table->status = 0xff; /* set invalid status */
+ siop_cmd->siop_table->status = htole32(0xff); /* set invalid status */
/* load the DMA maps */
error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,
@@ -777,16 +1110,17 @@ siop_scsicmd(xs)
}
bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd, 0,
siop_cmd->dmamap_cmd->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+#if 0
bus_dmamap_sync(sc->sc_dmat, sc->sc_scriptdma, 0,
sc->sc_scriptdma->dm_mapsize, BUS_DMASYNC_PREWRITE);
+#endif
siop_cmd->status = CMDST_READY;
s = splbio();
TAILQ_INSERT_TAIL(&sc->active_list[xs->sc_link->scsipi_scsi.target],
siop_cmd, next);
- if ((sc->sc_flags & SC_CTRL_ACTIVE) == 0) {
- siop_start(sc);
- }
+ siop_start(sc);
splx(s);
return (SUCCESSFULLY_QUEUED);
}
@@ -796,46 +1130,99 @@ siop_start(sc)
struct siop_softc *sc;
{
struct siop_cmd *siop_cmd;
+ u_int32_t *scr;
+ u_int32_t dsa;
+ u_int8_t *dsap = (u_int8_t *)&dsa;
int timeout;
- int i;
+ int target, slot;
+ int newcmd = 0;
- for (i = 0; i < 16; i++) {
- siop_cmd = sc->active_list[i].tqh_first;
- if (siop_cmd) {
- sc->current_target = i;
+ /*
+ * first make sure to read valid data
+ */
+ siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ /*
+ * no need to restart at slot 0 each time we're looking for a free
+ * slot; init slot before the target loop.
+ */
+ slot = 0;
+ for (target = 0; target < 16; target++) {
+ siop_cmd = sc->active_list[target].tqh_first;
+ if (siop_cmd == NULL)
+ continue;
+ if (siop_cmd->status != CMDST_READY &&
+ siop_cmd->status != CMDST_SENSE)
+ continue;
+ /* mark command as active (if not reqsense) and start script */
+ if (siop_cmd->status == CMDST_READY)
+ siop_cmd->status = CMDST_ACTIVE;
+ else if (siop_cmd->status == CMDST_SENSE)
+ siop_cmd->status = CMDST_SENSE_ACTIVE;
+ else
+ panic("siop_start: bad status");
+ /* find a free sheduler slot and load it */
+ for (; slot < sc->sc_nshedslots; slot++) {
+ scr = &sc->sc_script[Ent_sheduler / 4 +
+ (Ent_nextslot / 4) * slot];
+ /*
+ * if relative addr of first jump is 0 the slot isn't
+ * free
+ */
+ if (scr[Ent_slot / 4 + 1] == 0)
+ continue;
+#ifdef DEBUG_SHED
+ printf("using slot %d\n", slot);
+#endif
+ /* record that we started at last one new comand */
+ newcmd = 1;
+ /* ok, patch script with DSA addr */
+ dsa = siop_cmd->dsa;
+ /*
+ * 0x78000000 is a 'move data8 to reg'. data8 is the
+ * second octet, reg offset is the third.
+ */
+ scr[Ent_idsa0 / 4] =
+ htole32(0x78100000 | (dsap[0] << 8));
+ scr[Ent_idsa1 / 4] =
+ htole32(0x78110000 | (dsap[1] << 8));
+ scr[Ent_idsa2 / 4] =
+ htole32(0x78120000 | (dsap[2] << 8));
+ scr[Ent_idsa3 / 4] =
+ htole32(0x78130000 | (dsap[3] << 8));
+ /* change status of cmd */
+ if (siop_cmd->status == CMDST_ACTIVE) {
+ if ((siop_cmd->xs->xs_control & XS_CTL_POLL)
+ == 0) {
+ /* start exire timer */
+ timeout =
+ siop_cmd->xs->timeout * hz / 1000;
+ if (timeout == 0)
+ timeout = 1;
+ callout_reset(&siop_cmd->xs->xs_callout,
+ timeout, siop_timeout, siop_cmd);
+ }
+ }
+ /*
+ * Change jump offset so that this slot will be
+ * handled
+ */
+ scr[Ent_slot / 4 + 1] = 0;
break;
}
+ /* if we didn't find any free slot no need to try next target */
+ if (slot == sc->sc_nshedslots)
+ break;
}
- if (siop_cmd == NULL) {
- sc->sc_flags &= ~SC_CTRL_ACTIVE;
+ /* if nothing changed no need to flush cache and wakeup script */
+ if (newcmd == 0)
return;
- }
-
- sc->sc_flags |= SC_CTRL_ACTIVE;
- if (siop_cmd->status == CMDST_READY &&
- (siop_cmd->xs->xs_control & XS_CTL_POLL) == 0) {
- /* start exire timer */
- timeout = siop_cmd->xs->timeout * hz / 1000;
- if (timeout == 0)
- timeout = 1; /* at last one tick */
- callout_reset(&siop_cmd->xs->xs_callout, timeout,
- siop_timeout, siop_cmd);
- }
- /* load DSA */
- bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSA,
- htole32(sc->sc_scriptdma->dm_segs[0].ds_addr +
- (((caddr_t)siop_cmd->siop_table) - ((caddr_t)sc->sc_script))));
- /* mark command as active (if not reqsense) and start script */
- if (siop_cmd->status == CMDST_READY)
- siop_cmd->status = CMDST_ACTIVE;
-#if 0
- printf("starting script, DSA 0x%lx\n",
- htole32(sc->sc_scriptdma->dm_segs[0].ds_addr +
- (((caddr_t)siop_cmd->siop_table) - ((caddr_t)sc->sc_script))));
-#endif
- bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
- htole32(sc->sc_scriptdma->dm_segs[0].ds_addr + SCRIPT_OFF + Ent_select));
- /* now wait for IRQ */
+ /* make sure SCRIPT processor will read valid data */
+ siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ /* Signal script it has some work to do */
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_SIGP);
+ /* and wait for IRQ */
+ return;
}
void
@@ -920,3 +1307,33 @@ siop_sdp(siop_cmd)
printf("now count=%d addr=0x%x\n", table->count, table->addr);
#endif
}
+
+void
+siop_dump_script(sc)
+ struct siop_softc *sc;
+{
+ int i;
+ siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ for (i = 0; i < CMD_OFF / 4; i += 2) {
+ printf("0x%04x: 0x%08x 0x%08x", i * 4, sc->sc_script[i],
+ sc->sc_script[i+1]);
+ if ((sc->sc_script[i] & 0xe0000000) == 0xc0000000) {
+ i++;
+ printf(" 0x%08x", sc->sc_script[i+1]);
+ }
+ printf("\n");
+ }
+}
+
+#ifdef SIOP_STATS
+void
+siop_printstats()
+{
+ printf("siop_stat_intr %d\n", siop_stat_intr);
+ printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer);
+ printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc);
+ printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp);
+ printf("siop_stat_intr_reselect %d\n", siop_stat_intr_reselect);
+ printf("siop_stat_intr_done %d\n", siop_stat_intr_done);
+}
+#endif
diff --git a/sys/dev/ic/siopreg.h b/sys/dev/ic/siopreg.h
index 480bdc147ca..429ec68ed80 100644
--- a/sys/dev/ic/siopreg.h
+++ b/sys/dev/ic/siopreg.h
@@ -1,5 +1,4 @@
-
-/* $NetBSD: siopreg.h,v 1.1 2000/04/21 17:56:59 bouyer Exp $ */
+/* $NetBSD: siopreg.h,v 1.2 2000/04/25 16:27:05 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
diff --git a/sys/dev/ic/siopvar.h b/sys/dev/ic/siopvar.h
index 84be8c697d6..81b2820469c 100644
--- a/sys/dev/ic/siopvar.h
+++ b/sys/dev/ic/siopvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: siopvar.h,v 1.1 2000/04/21 17:56:59 bouyer Exp $ */
+/* $NetBSD: siopvar.h,v 1.2 2000/04/25 16:27:05 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -41,23 +41,24 @@ TAILQ_HEAD(cmd_list, siop_cmd);
struct siop_softc {
struct device sc_dev;
struct scsipi_link sc_link; /* link to upper level */
- int features; /* chip's features */
- u_int8_t maxburst;
- u_int8_t maxoff;
- u_int8_t clock_div;
+ int features; /* chip's features */
+ int maxburst;
+ int maxoff;
+ int clock_div;
bus_space_tag_t sc_rt; /* bus_space registers tag */
bus_space_handle_t sc_rh; /* bus_space registers handle */
bus_addr_t sc_raddr; /* register adresses */
bus_dma_tag_t sc_dmat; /* bus DMA tag */
bus_dmamap_t sc_scriptdma; /* DMA map for script */
u_int32_t *sc_script; /* script location in memory */
+ int sc_nshedslots; /* number of sheduler slots */
+ struct siop_cmd *cmds; /* commands array */
struct cmd_list free_list; /* cmd descr free list */
struct cmd_list active_list[16]; /* per-target active cmds */
- int current_target; /* current target */
u_int32_t sc_flags;
};
/* defs for sc_flags */
-#define SC_CTRL_ACTIVE 0x00000001 /* controller already running */
+/* none for now */
/* features */
#define SF_BUS_WIDE 0x00000001 /* wide bus */
diff --git a/sys/dev/microcode/siop/siop.out b/sys/dev/microcode/siop/siop.out
index effe33a0b9f..67a59edbbfa 100644
--- a/sys/dev/microcode/siop/siop.out
+++ b/sys/dev/microcode/siop/siop.out
@@ -1,121 +1,194 @@
-/* $NetBSD: siop.out,v 1.1 2000/04/21 17:57:01 bouyer Exp $ */
+/* $NetBSD: siop.out,v 1.2 2000/04/25 16:27:06 bouyer Exp $ */
/*
* DO NOT EDIT - this file is automatically generated.
- * created from siop.ss on Thu Apr 20 23:36:33 2000
+ * created from siop.ss on Mon Apr 24 16:52:43 2000
*/
const u_int32_t siop_script[] = {
- 0x47000004, 0x00000048, /* 000 - 0 */
- 0x78340000, 0x00000000, /* 008 - 8 */
- 0x78350000, 0x00000000, /* 010 - 16 */
- 0x868b0000, 0x000000a0, /* 018 - 24 */
- 0x878b0000, 0x00000068, /* 020 - 32 */
- 0x808b0000, 0x00000118, /* 028 - 40 */
- 0x818b0000, 0x000000c0, /* 030 - 48 */
- 0x828b0000, 0x00000098, /* 038 - 56 */
- 0x838b0000, 0x000000a0, /* 040 - 64 */
- 0x98080000, 0x0000ffff, /* 048 - 72 */
- 0x54000000, 0x00000030, /* 050 - 80 */
- 0x740a8f00, 0x00000000, /* 058 - 88 */
- 0x6a340000, 0x00000000, /* 060 - 96 */
- 0x9f030000, 0x0000ffff, /* 068 - 104 */
- 0x1f00000c, 0x0000000c, /* 070 - 112 */
- 0x60000040, 0x00000000, /* 078 - 120 */
- 0x98080000, 0x0000ff02, /* 080 - 128 */
- 0x98080000, 0x0000ff03, /* 088 - 136 */
- 0x60000008, 0x00000000, /* 090 - 144 */
- 0x1f00000c, 0x0000000c, /* 098 - 152 */
- 0x808c0004, 0x000001a8, /* 0a0 - 160 */
- 0x808c0000, 0x000001d0, /* 0a8 - 168 */
- 0x808c0002, 0x000001d8, /* 0b0 - 176 */
- 0x98080000, 0x0000ff01, /* 0b8 - 184 */
- 0x1e000014, 0x00000014, /* 0c0 - 192 */
- 0x60000008, 0x00000000, /* 0c8 - 200 */
- 0x80880000, 0xffffff40, /* 0d0 - 208 */
- 0x1a00001c, 0x0000001c, /* 0d8 - 216 */
- 0x80880000, 0xffffff30, /* 0e0 - 224 */
- 0x1b000024, 0x00000024, /* 0e8 - 232 */
- 0x80880000, 0xffffff20, /* 0f0 - 240 */
- 0x88880000, 0x00000098, /* 0f8 - 248 */
- 0x1900002c, 0x0000002c, /* 100 - 256 */
- 0x7e350100, 0x00000000, /* 108 - 264 */
- 0x7e100800, 0x00000000, /* 110 - 272 */
- 0x7f110000, 0x00000000, /* 118 - 280 */
- 0x7f120000, 0x00000000, /* 120 - 288 */
- 0x7f130000, 0x00000000, /* 128 - 296 */
- 0x818b0000, 0xffffffc8, /* 130 - 304 */
- 0x88880000, 0x000000a0, /* 138 - 312 */
- 0x80880000, 0xfffffed0, /* 140 - 320 */
- 0x88880000, 0x00000048, /* 148 - 328 */
- 0x1800002c, 0x0000002c, /* 150 - 336 */
- 0x7e350100, 0x00000000, /* 158 - 344 */
- 0x7e100800, 0x00000000, /* 160 - 352 */
- 0x7f110000, 0x00000000, /* 168 - 360 */
- 0x7f120000, 0x00000000, /* 170 - 368 */
- 0x7f130000, 0x00000000, /* 178 - 376 */
- 0x808b0000, 0xffffffc8, /* 180 - 384 */
- 0x88880000, 0x00000050, /* 188 - 392 */
- 0x80880000, 0xfffffe80, /* 190 - 400 */
- 0x72100000, 0x00000000, /* 198 - 408 */
- 0x6a5c0000, 0x00000000, /* 1a0 - 416 */
- 0x72110000, 0x00000000, /* 1a8 - 424 */
- 0x6a5d0000, 0x00000000, /* 1b0 - 432 */
- 0x72120000, 0x00000000, /* 1b8 - 440 */
- 0x6a5e0000, 0x00000000, /* 1c0 - 448 */
- 0x72130000, 0x00000000, /* 1c8 - 456 */
- 0x6a5f0000, 0x00000000, /* 1d0 - 464 */
- 0x90080000, 0x00000000, /* 1d8 - 472 */
- 0x725c0000, 0x00000000, /* 1e0 - 480 */
- 0x6a100000, 0x00000000, /* 1e8 - 488 */
- 0x725d0000, 0x00000000, /* 1f0 - 496 */
- 0x6a110000, 0x00000000, /* 1f8 - 504 */
- 0x725e0000, 0x00000000, /* 200 - 512 */
- 0x6a120000, 0x00000000, /* 208 - 520 */
- 0x725f0000, 0x00000000, /* 210 - 528 */
- 0x6a130000, 0x00000000, /* 218 - 536 */
- 0x90080000, 0x00000000, /* 220 - 544 */
- 0x7c027f00, 0x00000000, /* 228 - 552 */
- 0x60000008, 0x00000000, /* 230 - 560 */
- 0x60000040, 0x00000000, /* 238 - 568 */
- 0x48000000, 0x00000000, /* 240 - 576 */
- 0x90080000, 0x00000000, /* 248 - 584 */
- 0x88880000, 0xffffffd0, /* 250 - 592 */
- 0x74340100, 0x00000000, /* 258 - 600 */
- 0x808c0000, 0xfffffde8, /* 260 - 608 */
- 0x72350000, 0x00000000, /* 268 - 616 */
- 0x808c0000, 0xfffffdd8, /* 270 - 624 */
- 0x98080000, 0x0000ff04, /* 278 - 632 */
- 0x88880000, 0xffffffa0, /* 280 - 640 */
- 0x98080000, 0x0000ff00, /* 288 - 648 */
- 0x60000040, 0x00000000, /* 290 - 656 */
- 0x7a340100, 0x00000000, /* 298 - 664 */
- 0x80880000, 0xfffffde8, /* 2a0 - 672 */
+ 0x78340000, 0x00000000, /* 000 - 0 */
+ 0x78350000, 0x00000000, /* 008 - 8 */
+ 0x868b0000, 0x000000d8, /* 010 - 16 */
+ 0x878b0000, 0x00000078, /* 018 - 24 */
+ 0x808b0000, 0x00000150, /* 020 - 32 */
+ 0x818b0000, 0x000000f8, /* 028 - 40 */
+ 0x828b0000, 0x000000d0, /* 030 - 48 */
+ 0x838b0000, 0x000000d8, /* 038 - 56 */
+ 0x98080000, 0x0000ffff, /* 040 - 64 */
+ 0x54000000, 0x00000030, /* 048 - 72 */
+ 0x740a8f00, 0x00000000, /* 050 - 80 */
+ 0x6a340000, 0x00000000, /* 058 - 88 */
+ 0x9f030000, 0x0000ffff, /* 060 - 96 */
+ 0x1f00001c, 0x0000001c, /* 068 - 104 */
+ 0x60000040, 0x00000000, /* 070 - 112 */
+ 0x98080000, 0x0000ff04, /* 078 - 120 */
+ 0x741a4000, 0x00000000, /* 080 - 128 */
+ 0x980c0000, 0x0000ff06, /* 088 - 136 */
+ 0x80880000, 0x00000280, /* 090 - 144 */
+ 0x60000008, 0x00000000, /* 098 - 152 */
+ 0x1f00001c, 0x0000001c, /* 0a0 - 160 */
+ 0x808c0004, 0x000001d0, /* 0a8 - 168 */
+ 0x808c0000, 0x000001f8, /* 0b0 - 176 */
+ 0x808c0002, 0x00000200, /* 0b8 - 184 */
+ 0x808c0001, 0x00000210, /* 0c0 - 192 */
+ 0x98080000, 0x0000ff01, /* 0c8 - 200 */
+ 0x60000040, 0x00000000, /* 0d0 - 208 */
+ 0x80880000, 0xffffff30, /* 0d8 - 216 */
+ 0x58000008, 0x00000000, /* 0e0 - 224 */
+ 0x60000040, 0x00000000, /* 0e8 - 232 */
+ 0x1e00003c, 0x0000003c, /* 0f0 - 240 */
+ 0x60000008, 0x00000000, /* 0f8 - 248 */
+ 0x80880000, 0xffffff08, /* 100 - 256 */
+ 0x1a000044, 0x00000044, /* 108 - 264 */
+ 0x80880000, 0xfffffef8, /* 110 - 272 */
+ 0x1b00004c, 0x0000004c, /* 118 - 280 */
+ 0x80880000, 0xfffffee8, /* 120 - 288 */
+ 0x88880000, 0x00000098, /* 128 - 296 */
+ 0x19000054, 0x00000054, /* 130 - 304 */
+ 0x7e350100, 0x00000000, /* 138 - 312 */
+ 0x7e100800, 0x00000000, /* 140 - 320 */
+ 0x7f110000, 0x00000000, /* 148 - 328 */
+ 0x7f120000, 0x00000000, /* 150 - 336 */
+ 0x7f130000, 0x00000000, /* 158 - 344 */
+ 0x818b0000, 0xffffffc8, /* 160 - 352 */
+ 0x88880000, 0x000000a0, /* 168 - 360 */
+ 0x80880000, 0xfffffe98, /* 170 - 368 */
+ 0x88880000, 0x00000048, /* 178 - 376 */
+ 0x18000054, 0x00000054, /* 180 - 384 */
+ 0x7e350100, 0x00000000, /* 188 - 392 */
+ 0x7e100800, 0x00000000, /* 190 - 400 */
+ 0x7f110000, 0x00000000, /* 198 - 408 */
+ 0x7f120000, 0x00000000, /* 1a0 - 416 */
+ 0x7f130000, 0x00000000, /* 1a8 - 424 */
+ 0x808b0000, 0xffffffc8, /* 1b0 - 432 */
+ 0x88880000, 0x00000050, /* 1b8 - 440 */
+ 0x80880000, 0xfffffe48, /* 1c0 - 448 */
+ 0x72100000, 0x00000000, /* 1c8 - 456 */
+ 0x6a5c0000, 0x00000000, /* 1d0 - 464 */
+ 0x72110000, 0x00000000, /* 1d8 - 472 */
+ 0x6a5d0000, 0x00000000, /* 1e0 - 480 */
+ 0x72120000, 0x00000000, /* 1e8 - 488 */
+ 0x6a5e0000, 0x00000000, /* 1f0 - 496 */
+ 0x72130000, 0x00000000, /* 1f8 - 504 */
+ 0x6a5f0000, 0x00000000, /* 200 - 512 */
+ 0x90080000, 0x00000000, /* 208 - 520 */
+ 0x725c0000, 0x00000000, /* 210 - 528 */
+ 0x6a100000, 0x00000000, /* 218 - 536 */
+ 0x725d0000, 0x00000000, /* 220 - 544 */
+ 0x6a110000, 0x00000000, /* 228 - 552 */
+ 0x725e0000, 0x00000000, /* 230 - 560 */
+ 0x6a120000, 0x00000000, /* 238 - 568 */
+ 0x725f0000, 0x00000000, /* 240 - 576 */
+ 0x6a130000, 0x00000000, /* 248 - 584 */
+ 0x90080000, 0x00000000, /* 250 - 592 */
+ 0x7c027f00, 0x00000000, /* 258 - 600 */
+ 0x60000008, 0x00000000, /* 260 - 608 */
+ 0x60000040, 0x00000000, /* 268 - 616 */
+ 0x48000000, 0x00000000, /* 270 - 624 */
+ 0x90080000, 0x00000000, /* 278 - 632 */
+ 0x88880000, 0xffffffd0, /* 280 - 640 */
+ 0x74340100, 0x00000000, /* 288 - 648 */
+ 0x808c0000, 0x00000080, /* 290 - 656 */
+ 0x72350000, 0x00000000, /* 298 - 664 */
+ 0x808c0000, 0x00000070, /* 2a0 - 672 */
+ 0x98080000, 0x0000ff07, /* 2a8 - 680 */
+ 0x88880000, 0xffffffa0, /* 2b0 - 688 */
+ 0x98080000, 0x0000ff00, /* 2b8 - 696 */
+ 0x60000040, 0x00000000, /* 2c0 - 704 */
+ 0x7a340100, 0x00000000, /* 2c8 - 712 */
+ 0x80880000, 0xfffffdc0, /* 2d0 - 720 */
+ 0x60000040, 0x00000000, /* 2d8 - 728 */
+ 0x9f020000, 0x0000ffff, /* 2e0 - 736 */
+ 0x1f000024, 0x00000024, /* 2e8 - 744 */
+ 0x98080000, 0x0000ff02, /* 2f0 - 752 */
+ 0x60000040, 0x00000000, /* 2f8 - 760 */
+ 0x9f020000, 0x0000ffff, /* 300 - 768 */
+ 0x1f00002c, 0x0000002c, /* 308 - 776 */
+ 0x98080000, 0x0000ff03, /* 310 - 784 */
+ 0x10000000, 0x00000000, /* 318 - 792 */
};
-#define A_t_id 0x00000004
-#define A_t_msg_in 0x0000000c
-#define A_t_msg_out 0x00000014
-#define A_t_cmd 0x0000001c
-#define A_t_status 0x00000024
-#define A_t_data 0x0000002c
+const u_int32_t slot_script[] = {
+ 0x80880000, 0x00000044, /* 000 - 0 */
+ 0x78100000, 0x00000000, /* 008 - 8 */
+ 0x78110100, 0x00000000, /* 010 - 16 */
+ 0x78120200, 0x00000000, /* 018 - 24 */
+ 0x78130300, 0x00000000, /* 020 - 32 */
+ 0x43000014, 0x00000000, /* 028 - 40 */
+ 0xc0000004, 0x00000000, 0x00000000, /* 030 - 48 */
+ 0x80080000, 0x00000000, /* 03c - 60 */
+ 0x10000000, 0x00000000, /* 044 - 68 */
+ 0x10000000, 0x00000000, /* 04c - 76 */
+};
+
+const u_int32_t endslot_script[] = {
+ 0x80080000, 0x00000000, /* 000 - 0 */
+};
+
+#define A_t_id 0x00000014
+#define A_t_msg_in 0x0000001c
+#define A_t_ext_msg_in 0x00000024
+#define A_t_ext_msg_data 0x0000002c
+#define A_t_ext_msg_tag 0x00000034
+#define A_t_msg_out 0x0000003c
+#define A_t_cmd 0x00000044
+#define A_t_status 0x0000004c
+#define A_t_data 0x00000054
#define A_int_done 0x0000ff00
#define A_int_msgin 0x0000ff01
-#define A_int_resel 0x0000ff02
-#define A_int_resfail 0x0000ff03
-#define A_int_disc 0x0000ff04
+#define A_int_extmsgin 0x0000ff02
+#define A_int_extmsgdata 0x0000ff03
+#define A_int_resel 0x0000ff04
+#define A_int_reseltag 0x0000ff05
+#define A_int_resfail 0x0000ff06
+#define A_int_disc 0x0000ff07
#define A_int_err 0x0000ffff
#define A_flag_sdp 0x00000001
-#define Ent_waitphase 0x00000018
-#define Ent_select 0x00000000
-#define Ent_msgout 0x000000c0
-#define Ent_msgin 0x00000090
-#define Ent_dataout 0x00000148
-#define Ent_datain 0x000000f8
-#define Ent_cmdout 0x000000d8
-#define Ent_status 0x000000e8
-#define Ent_disconnect 0x00000228
-#define Ent_reselect 0x00000050
-#define Ent_reselected 0x00000008
-#define Ent_handle_reselect 0x00000000
+#define Ent_waitphase 0x00000010
+#define Ent_send_msgout 0x000000e0
+#define Ent_msgout 0x000000f0
+#define Ent_msgin 0x00000098
+#define Ent_msgin_ack 0x000000d0
+#define Ent_dataout 0x00000178
+#define Ent_datain 0x00000128
+#define Ent_cmdout 0x00000108
+#define Ent_status 0x00000118
+#define Ent_disconnect 0x00000258
+#define Ent_reselect 0x00000048
+#define Ent_selected 0x00000000
+#define Ent_get_extmsgdata 0x000002f8
+#define Ent_sheduler 0x00000318
+#define Ent_slot 0x00000000
+#define Ent_idsa0 0x00000008
+#define Ent_idsa1 0x00000010
+#define Ent_idsa2 0x00000018
+#define Ent_idsa3 0x00000020
+#define Ent_slotdata 0x00000044
+#define Ent_nextslot 0x0000004c
+#define Ent_endslot 0x00000000
+#define E_slot_nextp 0x00000000
+u_int32_t E_slot_nextp_Used[] = {
+ 0x0000000e,
+};
+
+#define E_slot_shed_addrsrc 0x00000000
+u_int32_t E_slot_shed_addrsrc_Used[] = {
+ 0x0000000d,
+};
+
+#define E_slot_abs_reselect 0x00000000
+u_int32_t E_slot_abs_reselect_Used[] = {
+ 0x0000000b,
+};
+
+#define E_slot_abs_selected 0x00000000
+u_int32_t E_slot_abs_selected_Used[] = {
+ 0x00000010,
+};
+
+#define E_endslot_abs_reselect 0x00000000
+u_int32_t E_endslot_abs_reselect_Used[] = {
+ 0x00000001,
+};
+
-u_int32_t INSTRUCTIONS = 0x00000055;
+u_int32_t INSTRUCTIONS = 0x0000006f;
u_int32_t PATCHES = 0x00000000;
diff --git a/sys/dev/microcode/siop/siop.ss b/sys/dev/microcode/siop/siop.ss
index e7e6b61220f..77b9a29318a 100644
--- a/sys/dev/microcode/siop/siop.ss
+++ b/sys/dev/microcode/siop/siop.ss
@@ -1,42 +1,63 @@
ARCH 720
-; offsets of sym_xfer
-ABSOLUTE t_id = 4;
-ABSOLUTE t_msg_in = 12;
-ABSOLUTE t_msg_out = 20;
-ABSOLUTE t_cmd = 28;
-ABSOLUTE t_status = 36;
-ABSOLUTE t_data = 44;
+; offsets in sym_xfer
+ABSOLUTE t_id = 20;
+ABSOLUTE t_msg_in = 28;
+ABSOLUTE t_ext_msg_in = 36;
+ABSOLUTE t_ext_msg_data = 44;
+ABSOLUTE t_ext_msg_tag = 52;
+ABSOLUTE t_msg_out = 60;
+ABSOLUTE t_cmd = 68;
+ABSOLUTE t_status = 76;
+ABSOLUTE t_data = 84;
;; interrupt codes
ABSOLUTE int_done = 0xff00;
ABSOLUTE int_msgin = 0xff01;
-ABSOLUTE int_resel = 0xff02;
-ABSOLUTE int_resfail = 0xff03;
-ABSOLUTE int_disc = 0xff04;
+ABSOLUTE int_extmsgin = 0xff02;
+ABSOLUTE int_extmsgdata = 0xff03;
+ABSOLUTE int_resel = 0xff04;
+ABSOLUTE int_reseltag = 0xff05;
+ABSOLUTE int_resfail = 0xff06;
+ABSOLUTE int_disc = 0xff07;
ABSOLUTE int_err = 0xffff;
; flags for scratcha0
ABSOLUTE flag_sdp = 0x01 ; got save data pointer
ENTRY waitphase;
-ENTRY select;
+ENTRY send_msgout;
ENTRY msgout;
ENTRY msgin;
+ENTRY msgin_ack;
ENTRY dataout;
ENTRY datain;
ENTRY cmdout;
ENTRY status;
ENTRY disconnect;
ENTRY reselect;
-ENTRY reselected;
-ENTRY handle_reselect;
+ENTRY selected;
+ENTRY get_extmsgdata;
+ENTRY sheduler;
+ENTRY slot;
+ENTRY idsa0;
+ENTRY idsa1;
+ENTRY idsa2;
+ENTRY idsa3;
+ENTRY slotdata;
+ENTRY nextslot;
+ENTRY endslot;
+
+EXTERN slot_nextp;
+EXTERN slot_shed_addrsrc;
+EXTERN slot_abs_reselect;
+EXTERN slot_abs_selected;
+
+EXTERN endslot_abs_reselect;
PROC siop_script:
-select:
- SELECT ATN FROM t_id, REL(reselect);
-reselected:
+selected:
; starting a new session, init 'local variables'
MOVE 0 to SCRATCHA0 ; flags
MOVE 0 to SCRATCHA1 ; DSA offset (for S/G save data pointer)
@@ -60,7 +81,10 @@ reselect:
INT int_resel;
reselect_fail:
- INT int_resfail;
+ ; check that host asserted SIGP, this'll clear SIGP in ISTAT
+ MOVE CTEST2 & 0x40 TO SFBR;
+ INT int_resfail, IF 0x00;
+ JUMP REL(sheduler);
msgin:
CLEAR ATN
@@ -68,7 +92,16 @@ msgin:
JUMP REL(handle_dis), IF 0x04 ; disconnect message
JUMP REL(handle_cmpl), IF 0x00 ; command complete message
JUMP REL(handle_sdp), IF 0x02 ; save data pointer message
+ JUMP REL(handle_extin), IF 0x01 ; extended message
INT int_msgin;
+msgin_ack:
+ CLEAR ACK;
+ JUMP REL(waitphase);
+
+; entry point for msgout after a msgin or status phase
+send_msgout:
+ SET ATN;
+ CLEAR ACK;
msgout:
MOVE FROM t_msg_out, WHEN MSG_OUT;
CLEAR ATN;
@@ -138,9 +171,9 @@ handle_dis:
CALL REL(disconnect);
; if we didn't get sdp, or if offset is 0, no need to interrupt
MOVE SCRATCHA0 & flag_sdp TO SFBR;
- JUMP REL(reselect), if 0x00;
+ JUMP REL(sheduler), if 0x00;
MOVE SCRATCHA1 TO SFBR;
- JUMP REL(reselect), if 0x00;
+ JUMP REL(sheduler), if 0x00;
; Ok, we need to save data pointers
INT int_disc;
@@ -151,3 +184,47 @@ handle_sdp:
CLEAR ACK;
MOVE SCRATCHA0 | flag_sdp TO SCRATCHA0;
JUMP REL(msgin) ; should get a disconnect message now
+
+handle_extin:
+ CLEAR ACK;
+ INT int_err, IF NOT MSG_IN;
+ MOVE FROM t_ext_msg_in, WHEN MSG_IN;
+ INT int_extmsgin; /* let host fill in t_ext_msg_data */
+get_extmsgdata:
+ CLEAR ACK;
+ INT int_err, IF NOT MSG_IN;
+ MOVE FROM t_ext_msg_data, WHEN MSG_IN;
+ INT int_extmsgdata;
+
+sheduler:
+ NOP; /* will be changed by the slot scripts */
+
+; script used for the sheduler: when a slot is free the JUMP points to
+; the next slot so that instructions for this slot are not run.
+; once the CPU has set up the slot variables (DSA address) it changes
+; the JUMP address to 0 (so that it'll jump to the next instruction) and
+; this command will be processed next time the sheduler is executed.
+; When the target has been successfully selected the script changes the jump
+; addr back to the next slot, so that it's ignored the next time.
+;
+
+PROC slot_script:
+slot:
+ JUMP REL(nextslot);
+idsa0:
+ MOVE 0x00 to dsa0;
+idsa1:
+ MOVE 0x01 to dsa1;
+idsa2:
+ MOVE 0x02 to dsa2;
+idsa3:
+ MOVE 0x03 to dsa3;
+ SELECT ATN FROM t_id, slot_abs_reselect;
+ MOVE MEMORY 4, slot_shed_addrsrc, slot_nextp;
+ JUMP slot_abs_selected;
+slotdata:
+ NOP; slot variables: dsa & jumppatchp
+nextslot: NOP; /* will be changed to the next slot entry
+
+PROC endslot_script:
+ JUMP endslot_abs_reselect;