diff options
| author | bouyer <bouyer@NetBSD.org> | 2002-04-25 19:34:02 +0000 |
|---|---|---|
| committer | bouyer <bouyer@NetBSD.org> | 2002-04-25 19:34:02 +0000 |
| commit | f66f6c27a67c4500b80a50d607b02da81e8b274a (patch) | |
| tree | 3060e12442552f7606fb76249905f431b0767efb /sys/dev | |
| parent | f53d9a4fa78d36d069cb3d2077be9a7debe9bfcd (diff) | |
- We can't share the per-lun DSA entry for untagged and tag table DSA;
there may be tagged commands still running when we queue a request sense
command.
Solve this by using 2 DSA entry per LUN
- Now that we have the command DSA before select, we can load T/L/Q in
SCRATCHC. This makes the selection timeout handler simpler.
- Avoid a race condition when setting the free flag in the cmd ring (see
comment in the script)
- don't forget to update the ID in the head of LUN table after a sync/wide
negotiation. This fixes the command timeout at the first data command
after negotiation (the bus reset handler did update the ID properly,
so subsequent commands were OK).
- for DMA interrupts, clear fifo if it's not empty. Leaving the fifo dirty
would prevent subsequent interrupts from coming in.
- Various improvements in debug messages
- misc cleanups.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ic/esiop.c | 278 | ||||
| -rw-r--r-- | sys/dev/ic/esiopvar.h | 3 | ||||
| -rw-r--r-- | sys/dev/microcode/siop/esiop.ss | 28 |
3 files changed, 165 insertions, 144 deletions
diff --git a/sys/dev/ic/esiop.c b/sys/dev/ic/esiop.c index 7fce56b340f..1175e44e693 100644 --- a/sys/dev/ic/esiop.c +++ b/sys/dev/ic/esiop.c @@ -1,4 +1,4 @@ -/* $NetBSD: esiop.c,v 1.8 2002/04/24 09:43:14 bouyer Exp $ */ +/* $NetBSD: esiop.c,v 1.9 2002/04/25 19:34:02 bouyer Exp $ */ /* * Copyright (c) 2002 Manuel Bouyer. @@ -33,7 +33,7 @@ /* SYM53c7/8xx PCI-SCSI I/O Processors driver */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.8 2002/04/24 09:43:14 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.9 2002/04/25 19:34:02 bouyer Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -94,10 +94,10 @@ void esiop_dump_script __P((struct esiop_softc *)); void esiop_morecbd __P((struct esiop_softc *)); void esiop_moretagtbl __P((struct esiop_softc *)); void siop_add_reselsw __P((struct esiop_softc *, int)); -struct esiop_cmd * esiop_cmd_find __P((struct esiop_softc *, int, u_int32_t)); void esiop_target_register __P((struct esiop_softc *, u_int32_t)); -static int nintr = 0; +void esiop_update_scntl3 __P((struct esiop_softc *, + struct siop_common_target *)); #ifdef SIOP_STATS static int esiop_stat_intr = 0; @@ -369,32 +369,37 @@ esiop_intr(v) u_int32_t tflags; u_int32_t addr; int freetarget = 0; - int restart = 0; int slot; int retval = 0; again: istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT); if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0) { - if (istat & ISTAT_SEM) { - bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, - SIOP_ISTAT, (istat & ~ISTAT_SEM)); - esiop_checkdone(sc); - } return retval; } retval = 1; - nintr++; - if (nintr > 100) { - panic("esiop: intr loop"); - } INCSTAT(esiop_stat_intr); if (istat & ISTAT_INTF) { bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT, ISTAT_INTF); esiop_checkdone(sc); + if (sc->sc_flags & SCF_CHAN_NOSLOT) { + /* + * at last one command terminated, + * so we should have free slots now + */ + sc->sc_flags &= ~SCF_CHAN_NOSLOT; + scsipi_channel_thaw(&sc->sc_c.sc_chan, 1); + } goto again; } + + if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) == + (ISTAT_DIP | ISTAT_ABRT)) { + bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, + SIOP_ISTAT, 0); + } + /* get CMD from T/L/Q */ tflags = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHC); @@ -480,13 +485,15 @@ none: printf(" parity"); if (dstat & DSTAT_DFE) printf(" dma fifo empty"); + else + siop_clearfifo(&sc->sc_c); printf(", DSP=0x%x DSA=0x%x: ", (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr), bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA)); if (esiop_cmd) - printf("last msg_in=0x%x status=0x%x\n", - esiop_cmd->cmd_tables->msg_in[0], + printf("T/L/Q=%d/%d/%d last msg_in=0x%x status=0x%x\n", + target, lun, tag, esiop_cmd->cmd_tables->msg_in[0], le32toh(esiop_cmd->cmd_tables->status)); else printf(" current T/L/Q invalid\n"); @@ -595,21 +602,17 @@ none: goto reset; } if ((sist & (SIST1_STO << 8)) && need_reset == 0) { - /* selection time out, assume there's no device here */ /* - * SCRATCHC has not been loaded yet, we have to find - * params by ourselve. scratchE0 should point to - * the slot. + * selection time out, assume there's no device here + * We also have to update the ring pointer ourselve */ slot = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHE); esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - target = bus_space_read_1(sc->sc_c.sc_rt, - sc->sc_c.sc_rh, SIOP_SDID); - esiop_cmd = esiop_cmd_find(sc, target, - esiop_script_read(sc, - sc->sc_shedoffset + slot * CMD_SLOTSIZE) & ~0x3); +#ifdef SIOP_DEBUG_SCHED + printf("sel timeout target %d, slot %d\n", target, slot); +#endif /* * mark this slot as free, and advance to next slot */ @@ -633,12 +636,6 @@ none: esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); if (esiop_cmd) { - xs = esiop_cmd->cmd_c.xs; - esiop_target = (struct esiop_target *) - esiop_cmd->cmd_c.siop_target; - lun = xs->xs_periph->periph_lun; - tag = esiop_cmd->cmd_c.tag; - esiop_lun = esiop_target->esiop_lun[lun]; esiop_cmd->cmd_c.status = CMDST_DONE; xs->error = XS_SELTIMEOUT; freetarget = 1; @@ -899,53 +896,65 @@ scintr: if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) { switch (siop_ppr_neg(&esiop_cmd->cmd_c)) { case SIOP_NEG_MSGOUT: + esiop_update_scntl3(sc, + esiop_cmd->cmd_c.siop_target); esiop_table_sync(esiop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); CALL_SCRIPT(Ent_send_msgout); - return(1); + return 1; case SIOP_NEG_ACK: + esiop_update_scntl3(sc, + esiop_cmd->cmd_c.siop_target); CALL_SCRIPT(Ent_msgin_ack); - return(1); + return 1; default: panic("invalid retval from " "siop_wdtr_neg()"); } - return(1); + return 1; } if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) { switch (siop_wdtr_neg(&esiop_cmd->cmd_c)) { case SIOP_NEG_MSGOUT: + esiop_update_scntl3(sc, + esiop_cmd->cmd_c.siop_target); esiop_table_sync(esiop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); CALL_SCRIPT(Ent_send_msgout); - return(1); + return 1; case SIOP_NEG_ACK: + esiop_update_scntl3(sc, + esiop_cmd->cmd_c.siop_target); CALL_SCRIPT(Ent_msgin_ack); - return(1); + return 1; default: panic("invalid retval from " "siop_wdtr_neg()"); } - return(1); + return 1; } if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) { switch (siop_sdtr_neg(&esiop_cmd->cmd_c)) { case SIOP_NEG_MSGOUT: + esiop_update_scntl3(sc, + esiop_cmd->cmd_c.siop_target); esiop_table_sync(esiop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); CALL_SCRIPT(Ent_send_msgout); - return(1); + return 1; case SIOP_NEG_ACK: + esiop_update_scntl3(sc, + esiop_cmd->cmd_c.siop_target); CALL_SCRIPT(Ent_msgin_ack); - return(1); + return 1; default: panic("invalid retval from " "siop_wdtr_neg()"); } - return(1); + return 1; } /* send a message reject */ esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT; @@ -983,7 +992,7 @@ scintr: case A_int_resfail: printf("reselect failed\n"); CALL_SCRIPT(Ent_script_sched); - return 1; + return 1; case A_int_done: if (xs == NULL) { printf("%s: done without command\n", @@ -1024,10 +1033,6 @@ end: #ifdef SIOP_DEBUG_INTR printf("esiop_intr end: status %d\n", xs->status); #endif - if (xs->status == SCSI_OK) - CALL_SCRIPT(Ent_script_sched); - else - restart = 1; if (tag >= 0) esiop_lun->tactive[tag] = NULL; else @@ -1035,15 +1040,14 @@ end: esiop_scsicmd_end(esiop_cmd); if (freetarget && esiop_target->target_c.status == TARST_PROBING) esiop_del_dev(sc, target, lun); - if (restart) - CALL_SCRIPT(Ent_script_sched); + CALL_SCRIPT(Ent_script_sched); if (sc->sc_flags & SCF_CHAN_NOSLOT) { /* a command terminated, so we have free slots now */ sc->sc_flags &= ~SCF_CHAN_NOSLOT; scsipi_channel_thaw(&sc->sc_c.sc_chan, 1); } - return retval; + return 1; } void @@ -1181,22 +1185,22 @@ esiop_unqueue(sc, target, lun) for (slot = 0; slot < A_ncmd_slots; slot++) { slotdsa = esiop_script_read(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE); - if (slotdsa & A_f_cmd_free) - continue; - if ((slotdsa & ~A_f_cmd_free) == esiop_cmd->cmd_c.dsa) + /* if the slot has any flag, it won't match the DSA */ + if (slotdsa == esiop_cmd->cmd_c.dsa) { /* found it */ + /* Mark this slot as ignore */ + esiop_script_write(sc, + sc->sc_shedoffset + slot * CMD_SLOTSIZE, + esiop_cmd->cmd_c.dsa | A_f_cmd_ignore); + /* ask to requeue */ + esiop_cmd->cmd_c.xs->error = XS_REQUEUE; + esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK; + esiop_lun->tactive[tag] = NULL; + esiop_scsicmd_end(esiop_cmd); break; + } } - if (slot > ESIOP_NTAG) - continue; /* didn't find it */ - /* Mark this slot as ignore */ - esiop_script_write(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE, - esiop_cmd->cmd_c.dsa | A_f_cmd_ignore); - /* ask to requeue */ - esiop_cmd->cmd_c.xs->error = XS_REQUEUE; - esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK; - esiop_lun->tactive[tag] = NULL; - esiop_scsicmd_end(esiop_cmd); } + esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } /* @@ -1236,9 +1240,9 @@ esiop_handle_qtag_reject(esiop_cmd) esiop_cmd->cmd_c.flags &= ~CMDFL_TAG; esiop_cmd->cmd_c.tag = -1; /* update DSA table */ - esiop_script_write(sc, esiop_target->lun_table_offset + lun + 2, + esiop_script_write(sc, esiop_target->lun_table_offset + + lun * 2 + A_target_luntbl / sizeof(u_int32_t), esiop_cmd->cmd_c.dsa); - esiop_lun->lun_flags &= ~LUNF_TAGTABLE; esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); return 0; } @@ -1263,6 +1267,7 @@ esiop_handle_reset(sc) printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname); /* stop, reset and restart the chip */ esiop_reset(sc); + if (sc->sc_flags & SCF_CHAN_NOSLOT) { /* chip has been reset, all slots are free now */ sc->sc_flags &= ~SCF_CHAN_NOSLOT; @@ -1341,7 +1346,8 @@ esiop_scsipi_request(chan, req, arg) s = splbio(); #ifdef SIOP_DEBUG_SCHED - printf("starting cmd for %d:%d\n", target, lun); + printf("starting cmd for %d:%d tag %d(%d)\n", target, lun, + xs->xs_tag_type, xs->xs_tag_id); #endif esiop_cmd = TAILQ_FIRST(&sc->free_list); if (esiop_cmd == NULL) { @@ -1486,8 +1492,17 @@ esiop_scsipi_request(chan, req, arg) if (sc->sc_c.targets[xm->xm_target] == NULL) return; s = splbio(); - if (xm->xm_mode & PERIPH_CAP_TQING) + if ((xm->xm_mode & PERIPH_CAP_TQING) && + (sc->sc_c.targets[xm->xm_target]->flags & TARF_TAG) == 0) { sc->sc_c.targets[xm->xm_target]->flags |= TARF_TAG; + /* allocate tag tables for this device */ + for (lun = 0; + lun < sc->sc_c.sc_chan.chan_nluns; lun++) { + if (sc->sc_c.sc_chan.chan_periphs[ + xm->xm_target][lun]) + esiop_add_dev(sc, xm->xm_target, lun); + } + } if ((xm->xm_mode & PERIPH_CAP_WIDE16) && (sc->sc_c.features & SF_BUS_WIDE)) sc->sc_c.targets[xm->xm_target]->flags |= TARF_WIDE; @@ -1501,11 +1516,6 @@ esiop_scsipi_request(chan, req, arg) sc->sc_c.targets[xm->xm_target]->status == TARST_PROBING) sc->sc_c.targets[xm->xm_target]->status = TARST_ASYNC; - for (lun = 0; lun < sc->sc_c.sc_chan.chan_nluns; lun++) { - if (sc->sc_c.sc_chan.chan_periphs[xm->xm_target][lun]) - /* allocate a lun sw entry for this device */ - esiop_add_dev(sc, xm->xm_target, lun); - } splx(s); } } @@ -1521,8 +1531,6 @@ esiop_start(sc, esiop_cmd) int timeout; int target, lun, slot; - nintr = 0; - /* * first make sure to read valid data */ @@ -1578,15 +1586,10 @@ esiop_start(sc, esiop_cmd) esiop_cmd->cmd_c.status = CMDST_ACTIVE; else panic("esiop_start: bad status"); + /* DSA table for reselect */ if (esiop_cmd->cmd_c.flags & CMDFL_TAG) { esiop_lun->tactive[esiop_cmd->cmd_c.tag] = esiop_cmd; /* DSA table for reselect */ - if ((esiop_lun->lun_flags & LUNF_TAGTABLE) == 0) { - esiop_script_write(sc, - esiop_target->lun_table_offset + lun + 2, - esiop_lun->lun_tagtbl->tbl_dsa); - esiop_lun->lun_flags |= LUNF_TAGTABLE; - } esiop_lun->lun_tagtbl->tbl[esiop_cmd->cmd_c.tag] = htole32(esiop_cmd->cmd_c.dsa); bus_dmamap_sync(sc->sc_c.sc_dmat, @@ -1595,15 +1598,16 @@ esiop_start(sc, esiop_cmd) sizeof(u_int32_t) * ESIOP_NTAG, BUS_DMASYNC_PREWRITE); } else { esiop_lun->active = esiop_cmd; - /* DSA table for reselect */ - esiop_script_write(sc, esiop_target->lun_table_offset + lun + 2, + esiop_script_write(sc, + esiop_target->lun_table_offset + + lun * 2 + A_target_luntbl / sizeof(u_int32_t), esiop_cmd->cmd_c.dsa); - esiop_lun->lun_flags &= ~LUNF_TAGTABLE; - } /* scheduler slot: DSA */ esiop_script_write(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE, esiop_cmd->cmd_c.dsa); + /* make sure SCRIPT processor will read valid data */ + esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* handle timeout */ if ((esiop_cmd->cmd_c.xs->xs_control & XS_CTL_POLL) == 0) { /* start exire timer */ @@ -1613,8 +1617,6 @@ esiop_start(sc, esiop_cmd) callout_reset( &esiop_cmd->cmd_c.xs->xs_callout, timeout, esiop_timeout, esiop_cmd); } - /* make sure SCRIPT processor will read valid data */ - esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* Signal script it has some work to do */ bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT, ISTAT_SIGP); @@ -1633,11 +1635,34 @@ esiop_timeout(v) struct esiop_softc *sc = (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc; int s; +#ifdef SIOP_DEBUG + int slot, slotdsa; +#endif + s = splbio(); + esiop_table_sync(esiop_cmd, + BUS_DMASYNC_POSTREAD | + BUS_DMASYNC_POSTWRITE); scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph); - printf("command timeout\n"); +#ifdef SIOP_DEBUG + printf("command timeout (status %d)\n", le32toh(esiop_cmd->cmd_tables->status)); - s = splbio(); + esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + for (slot = 0; slot < A_ncmd_slots; slot++) { + slotdsa = esiop_script_read(sc, + sc->sc_shedoffset + slot * CMD_SLOTSIZE); + if ((slotdsa & 0x01) == 0) + printf("slot %d not free (0x%x)\n", slot, slotdsa); + } + printf("istat 0x%x ", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT)); + printf("DSP 0x%lx DSA 0x%x\n", + (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr), + bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA)); + bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_CTEST2); + printf("istat 0x%x\n", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT)); +#else + printf("command timeout\n"); +#endif /* reset the scsi bus */ siop_resetbus(&sc->sc_c); @@ -1892,6 +1917,16 @@ bad3: } void +esiop_update_scntl3(sc, _siop_target) + struct esiop_softc *sc; + struct siop_common_target *_siop_target; +{ + struct esiop_target *esiop_target = (struct esiop_target *)_siop_target; + esiop_script_write(sc, esiop_target->lun_table_offset, + esiop_target->target_c.id); +} + +void esiop_add_dev(sc, target, lun) struct esiop_softc *sc; int target; @@ -1901,21 +1936,23 @@ esiop_add_dev(sc, target, lun) (struct esiop_target *)sc->sc_c.targets[target]; struct esiop_lun *esiop_lun = esiop_target->esiop_lun[lun]; - if (esiop_target->target_c.flags & TARF_TAG) { - /* we need a tag DSA table */ + /* we need a tag DSA table */ + esiop_lun->lun_tagtbl= TAILQ_FIRST(&sc->free_tagtbl); + if (esiop_lun->lun_tagtbl == NULL) { + esiop_moretagtbl(sc); esiop_lun->lun_tagtbl= TAILQ_FIRST(&sc->free_tagtbl); if (esiop_lun->lun_tagtbl == NULL) { - esiop_moretagtbl(sc); - esiop_lun->lun_tagtbl= TAILQ_FIRST(&sc->free_tagtbl); - if (esiop_lun->lun_tagtbl == NULL) { - /* no resources, run untagged */ - esiop_target->target_c.flags &= ~TARF_TAG; - return; - } + /* no resources, run untagged */ + esiop_target->target_c.flags &= ~TARF_TAG; + return; } - TAILQ_REMOVE(&sc->free_tagtbl, esiop_lun->lun_tagtbl, next); - } + TAILQ_REMOVE(&sc->free_tagtbl, esiop_lun->lun_tagtbl, next); + /* Update LUN DSA table */ + esiop_script_write(sc, esiop_target->lun_table_offset + + lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t), + esiop_lun->lun_tagtbl->tbl_dsa); + esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } void @@ -1936,39 +1973,6 @@ esiop_del_dev(sc, target, lun) esiop_target->esiop_lun[lun] = NULL; } -struct esiop_cmd * -esiop_cmd_find(sc, target, dsa) - struct esiop_softc *sc; - int target; - u_int32_t dsa; -{ - int lun, tag; - struct esiop_cmd *cmd; - struct esiop_lun *esiop_lun; - struct esiop_target *esiop_target = - (struct esiop_target *)sc->sc_c.targets[target]; - - if (esiop_target == NULL) - return NULL; - - for (lun = 0; lun < sc->sc_c.sc_chan.chan_nluns; lun++) { - esiop_lun = esiop_target->esiop_lun[lun]; - if (esiop_lun == NULL) - continue; - cmd = esiop_lun->active; - if (cmd && cmd->cmd_c.dsa == dsa) - return cmd; - if (esiop_target->target_c.flags & TARF_TAG) { - for (tag = 0; tag < ESIOP_NTAG; tag++) { - cmd = esiop_lun->tactive[tag]; - if (cmd && cmd->cmd_c.dsa == dsa) - return cmd; - } - } - } - return NULL; -} - void esiop_target_register(sc, target) struct esiop_softc *sc; @@ -1976,10 +1980,12 @@ esiop_target_register(sc, target) { struct esiop_target *esiop_target = (struct esiop_target *)sc->sc_c.targets[target]; + struct esiop_lun *esiop_lun; + int lun; /* get a DSA table for this target */ esiop_target->lun_table_offset = sc->sc_free_offset; - sc->sc_free_offset += sc->sc_c.sc_chan.chan_nluns + 2; + sc->sc_free_offset += sc->sc_c.sc_chan.chan_nluns * 2 + 2; #ifdef SIOP_DEBUG printf("%s: lun table for target %d offset %d free offset %d\n", sc->sc_c.sc_dev.dv_xname, target, esiop_target->lun_table_offset, @@ -1993,6 +1999,16 @@ esiop_target_register(sc, target) sc->sc_target_table_offset + target, (esiop_target->lun_table_offset * sizeof(u_int32_t)) + sc->sc_c.sc_scriptaddr); + /* if we have a tag table, register it */ + for (lun = 0; lun < sc->sc_c.sc_chan.chan_nluns; lun++) { + esiop_lun = esiop_target->esiop_lun[lun]; + if (esiop_lun == NULL) + continue; + if (esiop_lun->lun_tagtbl) + esiop_script_write(sc, esiop_target->lun_table_offset + + lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t), + esiop_lun->lun_tagtbl->tbl_dsa); + } esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } diff --git a/sys/dev/ic/esiopvar.h b/sys/dev/ic/esiopvar.h index 87eb42c9e4e..fc0c21c8101 100644 --- a/sys/dev/ic/esiopvar.h +++ b/sys/dev/ic/esiopvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: esiopvar.h,v 1.4 2002/04/24 09:43:14 bouyer Exp $ */ +/* $NetBSD: esiopvar.h,v 1.5 2002/04/25 19:34:02 bouyer Exp $ */ /* * Copyright (c) 2002 Manuel Bouyer. @@ -105,7 +105,6 @@ struct esiop_lun { struct esiop_cmd *active; /* active non-tagged command */ struct esiop_cmd *tactive[ESIOP_NTAG]; /* active tagged commands */ int lun_flags; /* per-lun flags */ -#define LUNF_TAGTABLE 0x01 /* the LUN DSA points to the tag table */ struct esiop_dsatbl *lun_tagtbl; /* the tag DSA table */ }; diff --git a/sys/dev/microcode/siop/esiop.ss b/sys/dev/microcode/siop/esiop.ss index 629735b960b..463cbc36402 100644 --- a/sys/dev/microcode/siop/esiop.ss +++ b/sys/dev/microcode/siop/esiop.ss @@ -1,4 +1,4 @@ -; $NetBSD: esiop.ss,v 1.9 2002/04/24 09:43:14 bouyer Exp $ +; $NetBSD: esiop.ss,v 1.10 2002/04/25 19:34:02 bouyer Exp $ ; ; Copyright (c) 2002 Manuel Bouyer. @@ -46,6 +46,7 @@ ABSOLUTE t_data = 96; ; offsets in the per-target lun table ABSOLUTE target_id = 0x0; ABSOLUTE target_luntbl = 0x8; +ABSOLUTE target_luntbl_tag = 0xc; ;; interrupt codes ; interrupts that needs a valid target/lun/tag @@ -146,11 +147,13 @@ nextisn: MOVE SCRATCHC0 | f_c_lun to SCRATCHC0; save LUN CLEAR ACK and CARRY; MOVE SCRATCHC2 SHL SFBR; - MOVE SFBR SHL SFBR; lun * 4 + MOVE SFBR SHL SFBR; + MOVE SFBR SHL SFBR; lun * 8 MOVE DSA0 + SFBR TO DSA0; MOVE DSA1 + 0x0 TO DSA1 with carry; MOVE DSA2 + 0x0 TO DSA2 with carry; MOVE DSA3 + 0x0 TO DSA3 with carry; + LOAD SCRATCHB0, 4, from target_luntbl_tag; in case it's a tagged cmd LOAD DSA0, 4, from target_luntbl; load DSA for this LUN JUMP REL(waitphase), WHEN NOT MSG_IN; MOVE 1, abs_msgin2, WHEN MSG_IN; @@ -161,6 +164,7 @@ nextisn: MOVE SFBR to SCRATCHA2; MOVE SFBR to SCRATCHC3; MOVE SCRATCHC0 | f_c_tag to SCRATCHC0; save TAG + CALL REL(restoredsa); switch to tag table DSA MOVE 0x0 to SCRATCHA3; CLEAR CARRY; MOVE SCRATCHA2 SHL SCRATCHA2; @@ -194,12 +198,11 @@ script_sched: MOVE SCRATCHD3 to SFBR; MOVE SFBR to DSA3; LOAD DSA0,4, from o_cmd_dsa; get DSA and flags for this slot - MOVE DSA0 to SFBR; to avoid another load later - MOVE SFBR to SCRATCHA0; to avoid another load later MOVE DSA0 & f_cmd_free to SFBR; check flags JUMP REL(no_cmd), IF NOT 0x0; MOVE DSA0 & f_cmd_ignore to SFBR; JUMP REL(ignore_cmd), IF NOT 0x0; + LOAD SCRATCHC0, 4, FROM tlq_offset; ; this slot is busy, attempt to exec command SELECT ATN FROM t_id, REL(reselect); ; select either succeeded or timed out. @@ -207,6 +210,7 @@ script_sched: ; waiting for a valid phase, so we have to do it now. If not a MSG_OUT phase, ; this is an error anyway (we selected with ATN) INT int_err, WHEN NOT MSG_OUT; +ignore_cmd: MOVE SCRATCHD0 to SFBR; restore scheduler DSA MOVE SFBR to DSA0; MOVE SCRATCHD1 to SFBR; @@ -215,7 +219,6 @@ script_sched: MOVE SFBR to DSA2; MOVE SCRATCHD3 to SFBR; MOVE SFBR to DSA3; -ignore_cmd: MOVE SCRATCHE0 + 1 to SCRATCHE0; MOVE SCRATCHD0 + cmd_slot_size to SCRATCHD0; MOVE SCRATCHD1 + 0 to SCRATCHD1 WITH CARRY; @@ -234,20 +237,23 @@ cmdr3: MOVE 0xff to SCRATCHD3; MOVE 0x00 to SCRATCHE0; handle_cmd: - MOVE SCRATCHA0 | f_cmd_free to SCRATCHA0; mark slot as free - STORE noflush SCRATCHA0, 1, FROM o_cmd_dsa; - MOVE SCRATCHA0 & f_cmd_ignore to SFBR; +; to avoid race condition we have to load the DSA value before setting the +; free flag, so we have to use a temp register. +; use SCRATCHB0 so that we can CALL restoredsa later + LOAD SCRATCHB0, 4, FROM o_cmd_dsa; load DSA for this command in temp reg + MOVE SCRATCHB0 | f_cmd_free to SCRATCHB0; mark slot as free + STORE noflush SCRATCHB0, 4, FROM o_cmd_dsa; + MOVE SCRATCHB0 & f_cmd_ignore to SFBR; JUMP REL(script_sched), IF NOT 0x00; next command if ignore + MOVE SCRATCHB0 & 0xfc to SCRATCHB0; clear f_cmd_* + CALL REL(restoredsa); and move SCRATCHB to DSA ; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time ; option "SIOP_SYMLED" led_on1: NOP; - LOAD DSA0, 4, FROM o_cmd_dsa; reload DSA for this command - MOVE DSA0 & 0xfe to DSA0; clear f_cmd_free MOVE 0x00 TO SCRATCHA1; MOVE 0xff TO SCRATCHE1; - LOAD SCRATCHC0, 4, FROM tlq_offset; ;we can now send our identify message send_msgout: ; entry point for msgout after a msgin or status phase SET ATN; |
