diff options
| author | bouyer <bouyer@NetBSD.org> | 2000-04-25 16:27:05 +0000 |
|---|---|---|
| committer | bouyer <bouyer@NetBSD.org> | 2000-04-25 16:27:05 +0000 |
| commit | 88be4752d04db3caaabd06cbe7b450a0dd2b6a1d (patch) | |
| tree | b0a30d91a0498094bd13337422b475ed087325e7 /sys/dev | |
| parent | 151b83e2e1453854e0170f0955d8842f0e8787a6 (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.c | 765 | ||||
| -rw-r--r-- | sys/dev/ic/siopreg.h | 3 | ||||
| -rw-r--r-- | sys/dev/ic/siopvar.h | 15 | ||||
| -rw-r--r-- | sys/dev/microcode/siop/siop.out | 291 | ||||
| -rw-r--r-- | sys/dev/microcode/siop/siop.ss | 115 |
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; |
