[BACK]Return to esiop.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / ic

Annotation of src/sys/dev/ic/esiop.c, Revision 1.39.18.1

1.39.18.1! yamt        1: /*     $NetBSD: esiop.c,v 1.39 2007/03/04 06:01:55 christos Exp $      */
1.1       bouyer      2:
                      3: /*
                      4:  * Copyright (c) 2002 Manuel Bouyer.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  * 3. All advertising materials mentioning features or use of this software
                     15:  *    must display the following acknowledgement:
1.7       bouyer     16:  *     This product includes software developed by Manuel Bouyer.
1.1       bouyer     17:  * 4. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     22:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1.11      bouyer     23:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1.1       bouyer     24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     25:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     26:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     27:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     28:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     29:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     30:  *
                     31:  */
                     32:
                     33: /* SYM53c7/8xx PCI-SCSI I/O Processors driver */
                     34:
                     35: #include <sys/cdefs.h>
1.39.18.1! yamt       36: __KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.39 2007/03/04 06:01:55 christos Exp $");
1.1       bouyer     37:
                     38: #include <sys/param.h>
                     39: #include <sys/systm.h>
                     40: #include <sys/device.h>
                     41: #include <sys/malloc.h>
                     42: #include <sys/buf.h>
                     43: #include <sys/kernel.h>
                     44:
                     45: #include <uvm/uvm_extern.h>
                     46:
                     47: #include <machine/endian.h>
                     48: #include <machine/bus.h>
                     49:
                     50: #include <dev/microcode/siop/esiop.out>
                     51:
                     52: #include <dev/scsipi/scsi_all.h>
                     53: #include <dev/scsipi/scsi_message.h>
                     54: #include <dev/scsipi/scsipi_all.h>
                     55:
                     56: #include <dev/scsipi/scsiconf.h>
                     57:
                     58: #include <dev/ic/siopreg.h>
                     59: #include <dev/ic/siopvar_common.h>
                     60: #include <dev/ic/esiopvar.h>
                     61:
                     62: #include "opt_siop.h"
                     63:
                     64: #ifndef DEBUG
1.6       bouyer     65: #undef DEBUG
1.1       bouyer     66: #endif
1.38      garbled    67: /*
                     68: #define SIOP_DEBUG
                     69: #define SIOP_DEBUG_DR
                     70: #define SIOP_DEBUG_INTR
                     71: #define SIOP_DEBUG_SCHED
                     72: #define DUMP_SCRIPT
                     73: */
1.1       bouyer     74:
                     75: #define SIOP_STATS
                     76:
                     77: #ifndef SIOP_DEFAULT_TARGET
                     78: #define SIOP_DEFAULT_TARGET 7
                     79: #endif
                     80:
                     81: /* number of cmd descriptors per block */
                     82: #define SIOP_NCMDPB (PAGE_SIZE / sizeof(struct esiop_xfer))
                     83:
1.32      perry      84: void   esiop_reset(struct esiop_softc *);
                     85: void   esiop_checkdone(struct esiop_softc *);
                     86: void   esiop_handle_reset(struct esiop_softc *);
                     87: void   esiop_scsicmd_end(struct esiop_cmd *, int);
                     88: void   esiop_unqueue(struct esiop_softc *, int, int);
                     89: int    esiop_handle_qtag_reject(struct esiop_cmd *);
                     90: static void    esiop_start(struct esiop_softc *, struct esiop_cmd *);
                     91: void   esiop_timeout(void *);
                     92: void   esiop_scsipi_request(struct scsipi_channel *,
                     93:                        scsipi_adapter_req_t, void *);
                     94: void   esiop_dump_script(struct esiop_softc *);
                     95: void   esiop_morecbd(struct esiop_softc *);
                     96: void   esiop_moretagtbl(struct esiop_softc *);
                     97: void   siop_add_reselsw(struct esiop_softc *, int);
                     98: void   esiop_target_register(struct esiop_softc *, u_int32_t);
1.1       bouyer     99:
1.32      perry     100: void    esiop_update_scntl3(struct esiop_softc *, struct siop_common_target *);
1.1       bouyer    101:
                    102: #ifdef SIOP_STATS
                    103: static int esiop_stat_intr = 0;
                    104: static int esiop_stat_intr_shortxfer = 0;
                    105: static int esiop_stat_intr_sdp = 0;
                    106: static int esiop_stat_intr_done = 0;
                    107: static int esiop_stat_intr_xferdisc = 0;
                    108: static int esiop_stat_intr_lunresel = 0;
                    109: static int esiop_stat_intr_qfull = 0;
1.32      perry     110: void esiop_printstats(void);
1.1       bouyer    111: #define INCSTAT(x) x++
                    112: #else
1.11      bouyer    113: #define INCSTAT(x)
1.1       bouyer    114: #endif
                    115:
1.35      perry     116: static inline void esiop_script_sync(struct esiop_softc *, int);
                    117: static inline void
1.1       bouyer    118: esiop_script_sync(sc, ops)
                    119:        struct esiop_softc *sc;
                    120:        int ops;
                    121: {
                    122:        if ((sc->sc_c.features & SF_CHIP_RAM) == 0)
                    123:                bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
                    124:                    PAGE_SIZE, ops);
                    125: }
                    126:
1.35      perry     127: static inline u_int32_t esiop_script_read(struct esiop_softc *, u_int);
                    128: static inline u_int32_t
1.1       bouyer    129: esiop_script_read(sc, offset)
                    130:        struct esiop_softc *sc;
                    131:        u_int offset;
                    132: {
                    133:        if (sc->sc_c.features & SF_CHIP_RAM) {
                    134:                return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
                    135:                    offset * 4);
                    136:        } else {
                    137:                return le32toh(sc->sc_c.sc_script[offset]);
                    138:        }
                    139: }
                    140:
1.35      perry     141: static inline void esiop_script_write(struct esiop_softc *, u_int,
1.32      perry     142:        u_int32_t);
1.35      perry     143: static inline void
1.1       bouyer    144: esiop_script_write(sc, offset, val)
                    145:        struct esiop_softc *sc;
                    146:        u_int offset;
                    147:        u_int32_t val;
                    148: {
                    149:        if (sc->sc_c.features & SF_CHIP_RAM) {
                    150:                bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
                    151:                    offset * 4, val);
                    152:        } else {
                    153:                sc->sc_c.sc_script[offset] = htole32(val);
                    154:        }
                    155: }
                    156:
                    157: void
                    158: esiop_attach(sc)
                    159:        struct esiop_softc *sc;
                    160: {
1.11      bouyer    161:        struct esiop_dsatbl *tagtbl_donering;
                    162:
1.6       bouyer    163:        if (siop_common_attach(&sc->sc_c) != 0 )
                    164:                return;
1.1       bouyer    165:
                    166:        TAILQ_INIT(&sc->free_list);
                    167:        TAILQ_INIT(&sc->cmds);
1.2       bouyer    168:        TAILQ_INIT(&sc->free_tagtbl);
                    169:        TAILQ_INIT(&sc->tag_tblblk);
1.1       bouyer    170:        sc->sc_currschedslot = 0;
                    171: #ifdef SIOP_DEBUG
1.18      thorpej   172:        aprint_debug("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
1.1       bouyer    173:            sc->sc_c.sc_dev.dv_xname, (int)sizeof(esiop_script),
                    174:            (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script);
                    175: #endif
                    176:
1.6       bouyer    177:        sc->sc_c.sc_adapt.adapt_max_periph = ESIOP_NTAG;
1.1       bouyer    178:        sc->sc_c.sc_adapt.adapt_request = esiop_scsipi_request;
                    179:
1.11      bouyer    180:        /*
                    181:         * get space for the CMD done slot. For this we use a tag table entry.
                    182:         * It's the same size and allows us to not waste 3/4 of a page
                    183:         */
                    184: #ifdef DIAGNOSTIC
                    185:        if (ESIOP_NTAG != A_ndone_slots) {
1.18      thorpej   186:                aprint_error("%s: size of tag DSA table different from the done"
                    187:                    " ring\n", sc->sc_c.sc_dev.dv_xname);
1.11      bouyer    188:                return;
                    189:        }
                    190: #endif
                    191:        esiop_moretagtbl(sc);
                    192:        tagtbl_donering = TAILQ_FIRST(&sc->free_tagtbl);
                    193:        if (tagtbl_donering == NULL) {
1.18      thorpej   194:                aprint_error("%s: no memory for command done ring\n",
                    195:                    sc->sc_c.sc_dev.dv_xname);
1.11      bouyer    196:                return;
                    197:        }
                    198:        TAILQ_REMOVE(&sc->free_tagtbl, tagtbl_donering, next);
                    199:        sc->sc_done_map = tagtbl_donering->tblblk->blkmap;
                    200:        sc->sc_done_offset = tagtbl_donering->tbl_offset;
                    201:        sc->sc_done_slot = &tagtbl_donering->tbl[0];
                    202:
1.1       bouyer    203:        /* Do a bus reset, so that devices fall back to narrow/async */
                    204:        siop_resetbus(&sc->sc_c);
                    205:        /*
                    206:         * siop_reset() will reset the chip, thus clearing pending interrupts
                    207:         */
                    208:        esiop_reset(sc);
                    209: #ifdef DUMP_SCRIPT
                    210:        esiop_dump_script(sc);
                    211: #endif
                    212:
                    213:        config_found((struct device*)sc, &sc->sc_c.sc_chan, scsiprint);
                    214: }
                    215:
                    216: void
                    217: esiop_reset(sc)
                    218:        struct esiop_softc *sc;
                    219: {
                    220:        int i, j;
                    221:        u_int32_t addr;
1.12      bouyer    222:        u_int32_t msgin_addr, sem_addr;
1.1       bouyer    223:
                    224:        siop_common_reset(&sc->sc_c);
                    225:
                    226:        /*
1.12      bouyer    227:         * we copy the script at the beggining of RAM. Then there is 4 bytes
                    228:         * for messages in, and 4 bytes for semaphore
1.1       bouyer    229:         */
                    230:        sc->sc_free_offset = sizeof(esiop_script) / sizeof(esiop_script[0]);
                    231:        msgin_addr =
                    232:            sc->sc_free_offset * sizeof(u_int32_t) + sc->sc_c.sc_scriptaddr;
1.12      bouyer    233:        sc->sc_free_offset += 1;
                    234:        sc->sc_semoffset = sc->sc_free_offset;
                    235:        sem_addr =
                    236:            sc->sc_semoffset * sizeof(u_int32_t) + sc->sc_c.sc_scriptaddr;
                    237:        sc->sc_free_offset += 1;
1.1       bouyer    238:        /* then we have the scheduler ring */
                    239:        sc->sc_shedoffset = sc->sc_free_offset;
1.8       bouyer    240:        sc->sc_free_offset += A_ncmd_slots * CMD_SLOTSIZE;
1.1       bouyer    241:        /* then the targets DSA table */
                    242:        sc->sc_target_table_offset = sc->sc_free_offset;
                    243:        sc->sc_free_offset += sc->sc_c.sc_chan.chan_ntargets;
                    244:        /* copy and patch the script */
                    245:        if (sc->sc_c.features & SF_CHIP_RAM) {
                    246:                bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0,
                    247:                    esiop_script,
                    248:                    sizeof(esiop_script) / sizeof(esiop_script[0]));
1.11      bouyer    249:                for (j = 0; j <
1.1       bouyer    250:                    (sizeof(E_tlq_offset_Used) / sizeof(E_tlq_offset_Used[0]));
                    251:                    j++) {
                    252:                        bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
                    253:                            E_tlq_offset_Used[j] * 4,
                    254:                            sizeof(struct siop_common_xfer));
                    255:                }
1.11      bouyer    256:                for (j = 0; j <
1.34      bouyer    257:                    (sizeof(E_saved_offset_offset_Used) /
                    258:                     sizeof(E_saved_offset_offset_Used[0]));
                    259:                    j++) {
                    260:                        bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
                    261:                            E_saved_offset_offset_Used[j] * 4,
                    262:                            sizeof(struct siop_common_xfer) + 4);
                    263:                }
                    264:                for (j = 0; j <
1.1       bouyer    265:                    (sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0]));
                    266:                    j++) {
                    267:                        bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
                    268:                            E_abs_msgin2_Used[j] * 4, msgin_addr);
                    269:                }
1.12      bouyer    270:                for (j = 0; j <
                    271:                    (sizeof(E_abs_sem_Used) / sizeof(E_abs_sem_Used[0]));
                    272:                    j++) {
                    273:                        bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
                    274:                            E_abs_sem_Used[j] * 4, sem_addr);
                    275:                }
1.1       bouyer    276:
1.4       bouyer    277:                if (sc->sc_c.features & SF_CHIP_LED0) {
                    278:                        bus_space_write_region_4(sc->sc_c.sc_ramt,
                    279:                            sc->sc_c.sc_ramh,
                    280:                            Ent_led_on1, esiop_led_on,
                    281:                            sizeof(esiop_led_on) / sizeof(esiop_led_on[0]));
                    282:                        bus_space_write_region_4(sc->sc_c.sc_ramt,
                    283:                            sc->sc_c.sc_ramh,
                    284:                            Ent_led_on2, esiop_led_on,
                    285:                            sizeof(esiop_led_on) / sizeof(esiop_led_on[0]));
                    286:                        bus_space_write_region_4(sc->sc_c.sc_ramt,
                    287:                            sc->sc_c.sc_ramh,
                    288:                            Ent_led_off, esiop_led_off,
                    289:                            sizeof(esiop_led_off) / sizeof(esiop_led_off[0]));
                    290:                }
1.1       bouyer    291:        } else {
                    292:                for (j = 0;
                    293:                    j < (sizeof(esiop_script) / sizeof(esiop_script[0])); j++) {
                    294:                        sc->sc_c.sc_script[j] = htole32(esiop_script[j]);
                    295:                }
                    296:                for (j = 0; j <
                    297:                    (sizeof(E_tlq_offset_Used) / sizeof(E_tlq_offset_Used[0]));
                    298:                    j++) {
                    299:                        sc->sc_c.sc_script[E_tlq_offset_Used[j]] =
                    300:                            htole32(sizeof(struct siop_common_xfer));
                    301:                }
                    302:                for (j = 0; j <
1.34      bouyer    303:                    (sizeof(E_saved_offset_offset_Used) /
                    304:                     sizeof(E_saved_offset_offset_Used[0]));
                    305:                    j++) {
                    306:                        sc->sc_c.sc_script[E_saved_offset_offset_Used[j]] =
                    307:                            htole32(sizeof(struct siop_common_xfer) + 4);
                    308:                }
                    309:                for (j = 0; j <
1.1       bouyer    310:                    (sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0]));
                    311:                    j++) {
                    312:                        sc->sc_c.sc_script[E_abs_msgin2_Used[j]] =
                    313:                            htole32(msgin_addr);
                    314:                }
1.12      bouyer    315:                for (j = 0; j <
                    316:                    (sizeof(E_abs_sem_Used) / sizeof(E_abs_sem_Used[0]));
                    317:                    j++) {
                    318:                        sc->sc_c.sc_script[E_abs_sem_Used[j]] =
                    319:                            htole32(sem_addr);
                    320:                }
1.1       bouyer    321:
1.4       bouyer    322:                if (sc->sc_c.features & SF_CHIP_LED0) {
                    323:                        for (j = 0; j < (sizeof(esiop_led_on) /
                    324:                            sizeof(esiop_led_on[0])); j++)
                    325:                                sc->sc_c.sc_script[
                    326:                                    Ent_led_on1 / sizeof(esiop_led_on[0]) + j
                    327:                                    ] = htole32(esiop_led_on[j]);
                    328:                        for (j = 0; j < (sizeof(esiop_led_on) /
                    329:                            sizeof(esiop_led_on[0])); j++)
                    330:                                sc->sc_c.sc_script[
                    331:                                    Ent_led_on2 / sizeof(esiop_led_on[0]) + j
                    332:                                    ] = htole32(esiop_led_on[j]);
                    333:                        for (j = 0; j < (sizeof(esiop_led_off) /
                    334:                            sizeof(esiop_led_off[0])); j++)
                    335:                                sc->sc_c.sc_script[
                    336:                                   Ent_led_off / sizeof(esiop_led_off[0]) + j
                    337:                                   ] = htole32(esiop_led_off[j]);
                    338:                }
1.1       bouyer    339:        }
                    340:        /* get base of scheduler ring */
                    341:        addr = sc->sc_c.sc_scriptaddr + sc->sc_shedoffset * sizeof(u_int32_t);
                    342:        /* init scheduler */
                    343:        for (i = 0; i < A_ncmd_slots; i++) {
1.8       bouyer    344:                esiop_script_write(sc,
                    345:                    sc->sc_shedoffset + i * CMD_SLOTSIZE, A_f_cmd_free);
1.1       bouyer    346:        }
                    347:        sc->sc_currschedslot = 0;
                    348:        bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHE, 0);
                    349:        bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHD, addr);
                    350:        /*
                    351:         * 0x78000000 is a 'move data8 to reg'. data8 is the second
                    352:         * octet, reg offset is the third.
                    353:         */
                    354:        esiop_script_write(sc, Ent_cmdr0 / 4,
                    355:            0x78640000 | ((addr & 0x000000ff) <<  8));
                    356:        esiop_script_write(sc, Ent_cmdr1 / 4,
                    357:            0x78650000 | ((addr & 0x0000ff00)      ));
                    358:        esiop_script_write(sc, Ent_cmdr2 / 4,
                    359:            0x78660000 | ((addr & 0x00ff0000) >>  8));
                    360:        esiop_script_write(sc, Ent_cmdr3 / 4,
                    361:            0x78670000 | ((addr & 0xff000000) >> 16));
1.11      bouyer    362:        /* done ring */
                    363:        for (i = 0; i < A_ndone_slots; i++)
                    364:                sc->sc_done_slot[i] = 0;
                    365:        bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map,
                    366:            sc->sc_done_offset, A_ndone_slots * sizeof(u_int32_t),
                    367:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    368:        addr = sc->sc_done_map->dm_segs[0].ds_addr + sc->sc_done_offset;
                    369:        sc->sc_currdoneslot = 0;
                    370:        bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHE + 2, 0);
                    371:        bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHF, addr);
                    372:        esiop_script_write(sc, Ent_doner0 / 4,
                    373:            0x786c0000 | ((addr & 0x000000ff) <<  8));
                    374:        esiop_script_write(sc, Ent_doner1 / 4,
                    375:            0x786d0000 | ((addr & 0x0000ff00)      ));
                    376:        esiop_script_write(sc, Ent_doner2 / 4,
                    377:            0x786e0000 | ((addr & 0x00ff0000) >>  8));
                    378:        esiop_script_write(sc, Ent_doner3 / 4,
                    379:            0x786f0000 | ((addr & 0xff000000) >> 16));
                    380:
1.1       bouyer    381:        /* set flags */
                    382:        bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHC, 0);
                    383:        /* write pointer of base of target DSA table */
                    384:        addr = (sc->sc_target_table_offset * sizeof(u_int32_t)) +
                    385:            sc->sc_c.sc_scriptaddr;
                    386:        esiop_script_write(sc, (Ent_load_targtable / 4) + 0,
                    387:            esiop_script_read(sc,(Ent_load_targtable / 4) + 0) |
                    388:            ((addr & 0x000000ff) <<  8));
                    389:        esiop_script_write(sc, (Ent_load_targtable / 4) + 2,
                    390:            esiop_script_read(sc,(Ent_load_targtable / 4) + 2) |
                    391:            ((addr & 0x0000ff00)      ));
                    392:        esiop_script_write(sc, (Ent_load_targtable / 4) + 4,
                    393:            esiop_script_read(sc,(Ent_load_targtable / 4) + 4) |
                    394:            ((addr & 0x00ff0000) >>  8));
                    395:        esiop_script_write(sc, (Ent_load_targtable / 4) + 6,
                    396:            esiop_script_read(sc,(Ent_load_targtable / 4) + 6) |
                    397:            ((addr & 0xff000000) >> 16));
                    398: #ifdef SIOP_DEBUG
                    399:        printf("%s: target table offset %d free offset %d\n",
                    400:            sc->sc_c.sc_dev.dv_xname, sc->sc_target_table_offset,
                    401:            sc->sc_free_offset);
                    402: #endif
                    403:
                    404:        /* register existing targets */
                    405:        for (i = 0; i < sc->sc_c.sc_chan.chan_ntargets; i++) {
                    406:                if (sc->sc_c.targets[i])
                    407:                        esiop_target_register(sc, i);
                    408:        }
                    409:        /* start script */
                    410:        if ((sc->sc_c.features & SF_CHIP_RAM) == 0) {
                    411:                bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
                    412:                    PAGE_SIZE, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    413:        }
                    414:        bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP,
                    415:            sc->sc_c.sc_scriptaddr + Ent_reselect);
                    416: }
                    417:
                    418: #if 0
                    419: #define CALL_SCRIPT(ent) do {\
                    420:        printf ("start script DSA 0x%lx DSP 0x%lx\n", \
                    421:            esiop_cmd->cmd_c.dsa, \
                    422:            sc->sc_c.sc_scriptaddr + ent); \
                    423: bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
                    424: } while (0)
                    425: #else
                    426: #define CALL_SCRIPT(ent) do {\
                    427: bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
                    428: } while (0)
                    429: #endif
                    430:
                    431: int
                    432: esiop_intr(v)
                    433:        void *v;
                    434: {
                    435:        struct esiop_softc *sc = v;
                    436:        struct esiop_target *esiop_target;
                    437:        struct esiop_cmd *esiop_cmd;
                    438:        struct esiop_lun *esiop_lun;
                    439:        struct scsipi_xfer *xs;
1.23      mycroft   440:        int istat, sist, sstat1, dstat = 0; /* XXX: gcc */
1.1       bouyer    441:        u_int32_t irqcode;
                    442:        int need_reset = 0;
                    443:        int offset, target, lun, tag;
                    444:        u_int32_t tflags;
1.3       bouyer    445:        u_int32_t addr;
1.1       bouyer    446:        int freetarget = 0;
                    447:        int slot;
                    448:        int retval = 0;
                    449:
                    450: again:
                    451:        istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT);
                    452:        if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0) {
                    453:                return retval;
                    454:        }
                    455:        retval = 1;
                    456:        INCSTAT(esiop_stat_intr);
1.12      bouyer    457:        esiop_checkdone(sc);
1.1       bouyer    458:        if (istat & ISTAT_INTF) {
                    459:                bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    460:                    SIOP_ISTAT, ISTAT_INTF);
                    461:                goto again;
                    462:        }
1.9       bouyer    463:
1.11      bouyer    464:        if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
1.9       bouyer    465:            (ISTAT_DIP | ISTAT_ABRT)) {
1.10      bouyer    466:                /* clear abort */
1.9       bouyer    467:                bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    468:                    SIOP_ISTAT, 0);
                    469:        }
1.11      bouyer    470:
1.1       bouyer    471:        /* get CMD from T/L/Q */
                    472:        tflags = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    473:            SIOP_SCRATCHC);
                    474: #ifdef SIOP_DEBUG_INTR
                    475:                printf("interrupt, istat=0x%x tflags=0x%x "
                    476:                    "DSA=0x%x DSP=0x%lx\n", istat, tflags,
                    477:                    bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
                    478:                    (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    479:                        SIOP_DSP) -
                    480:                    sc->sc_c.sc_scriptaddr));
                    481: #endif
                    482:        target = (tflags & A_f_c_target) ? ((tflags >> 8) & 0xff) : -1;
                    483:        if (target > sc->sc_c.sc_chan.chan_ntargets) target = -1;
                    484:        lun = (tflags & A_f_c_lun) ? ((tflags >> 16) & 0xff) : -1;
                    485:        if (lun > sc->sc_c.sc_chan.chan_nluns) lun = -1;
                    486:        tag = (tflags & A_f_c_tag) ? ((tflags >> 24) & 0xff) : -1;
                    487:
                    488:        if (target >= 0 && lun >= 0) {
                    489:                esiop_target = (struct esiop_target *)sc->sc_c.targets[target];
                    490:                if (esiop_target == NULL) {
                    491:                        printf("esiop_target (target %d) not valid\n", target);
                    492:                        goto none;
                    493:                }
                    494:                esiop_lun = esiop_target->esiop_lun[lun];
                    495:                if (esiop_lun == NULL) {
                    496:                        printf("esiop_lun (target %d lun %d) not valid\n",
                    497:                            target, lun);
                    498:                        goto none;
                    499:                }
1.2       bouyer    500:                esiop_cmd =
                    501:                    (tag >= 0) ? esiop_lun->tactive[tag] : esiop_lun->active;
1.1       bouyer    502:                if (esiop_cmd == NULL) {
1.2       bouyer    503:                        printf("esiop_cmd (target %d lun %d tag %d) not valid\n",
                    504:                            target, lun, tag);
1.1       bouyer    505:                        goto none;
                    506:                }
                    507:                xs = esiop_cmd->cmd_c.xs;
                    508: #ifdef DIAGNOSTIC
                    509:                if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) {
                    510:                        printf("esiop_cmd (target %d lun %d) "
                    511:                            "not active (%d)\n", target, lun,
                    512:                            esiop_cmd->cmd_c.status);
                    513:                        goto none;
                    514:                }
                    515: #endif
1.3       bouyer    516:                esiop_table_sync(esiop_cmd,
                    517:                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1.1       bouyer    518:        } else {
                    519: none:
                    520:                xs = NULL;
                    521:                esiop_target = NULL;
                    522:                esiop_lun = NULL;
                    523:                esiop_cmd = NULL;
                    524:        }
                    525:        if (istat & ISTAT_DIP) {
                    526:                dstat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    527:                    SIOP_DSTAT);
1.10      bouyer    528:                if (dstat & DSTAT_ABRT) {
                    529:                        /* was probably generated by a bus reset IOCTL */
                    530:                        if ((dstat & DSTAT_DFE) == 0)
                    531:                                siop_clearfifo(&sc->sc_c);
                    532:                        goto reset;
                    533:                }
1.1       bouyer    534:                if (dstat & DSTAT_SSI) {
                    535:                        printf("single step dsp 0x%08x dsa 0x08%x\n",
                    536:                            (int)(bus_space_read_4(sc->sc_c.sc_rt,
                    537:                            sc->sc_c.sc_rh, SIOP_DSP) -
                    538:                            sc->sc_c.sc_scriptaddr),
                    539:                            bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    540:                                SIOP_DSA));
                    541:                        if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
                    542:                            (istat & ISTAT_SIP) == 0) {
                    543:                                bus_space_write_1(sc->sc_c.sc_rt,
                    544:                                    sc->sc_c.sc_rh, SIOP_DCNTL,
                    545:                                    bus_space_read_1(sc->sc_c.sc_rt,
                    546:                                    sc->sc_c.sc_rh, SIOP_DCNTL) | DCNTL_STD);
                    547:                        }
                    548:                        return 1;
                    549:                }
1.10      bouyer    550:
1.1       bouyer    551:                if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
                    552:                printf("%s: DMA IRQ:", sc->sc_c.sc_dev.dv_xname);
                    553:                if (dstat & DSTAT_IID)
                    554:                        printf(" Illegal instruction");
                    555:                if (dstat & DSTAT_BF)
                    556:                        printf(" bus fault");
                    557:                if (dstat & DSTAT_MDPE)
                    558:                        printf(" parity");
                    559:                if (dstat & DSTAT_DFE)
1.19      wiz       560:                        printf(" DMA fifo empty");
1.9       bouyer    561:                else
                    562:                        siop_clearfifo(&sc->sc_c);
1.1       bouyer    563:                printf(", DSP=0x%x DSA=0x%x: ",
                    564:                    (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    565:                        SIOP_DSP) - sc->sc_c.sc_scriptaddr),
                    566:                    bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
                    567:                if (esiop_cmd)
1.9       bouyer    568:                        printf("T/L/Q=%d/%d/%d last msg_in=0x%x status=0x%x\n",
                    569:                            target, lun, tag, esiop_cmd->cmd_tables->msg_in[0],
1.1       bouyer    570:                            le32toh(esiop_cmd->cmd_tables->status));
1.11      bouyer    571:                else
1.1       bouyer    572:                        printf(" current T/L/Q invalid\n");
                    573:                need_reset = 1;
                    574:                }
                    575:        }
                    576:        if (istat & ISTAT_SIP) {
                    577:                if (istat & ISTAT_DIP)
                    578:                        delay(10);
                    579:                /*
1.24      wiz       580:                 * Can't read sist0 & sist1 independently, or we have to
1.1       bouyer    581:                 * insert delay
                    582:                 */
                    583:                sist = bus_space_read_2(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    584:                    SIOP_SIST0);
                    585:                sstat1 = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    586:                    SIOP_SSTAT1);
                    587: #ifdef SIOP_DEBUG_INTR
                    588:                printf("scsi interrupt, sist=0x%x sstat1=0x%x "
                    589:                    "DSA=0x%x DSP=0x%lx\n", sist, sstat1,
                    590:                    bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
                    591:                    (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    592:                        SIOP_DSP) -
                    593:                    sc->sc_c.sc_scriptaddr));
                    594: #endif
                    595:                if (sist & SIST0_RST) {
                    596:                        esiop_handle_reset(sc);
                    597:                        /* no table to flush here */
                    598:                        return 1;
                    599:                }
                    600:                if (sist & SIST0_SGE) {
                    601:                        if (esiop_cmd)
                    602:                                scsipi_printaddr(xs->xs_periph);
                    603:                        else
                    604:                                printf("%s:", sc->sc_c.sc_dev.dv_xname);
                    605:                        printf("scsi gross error\n");
1.6       bouyer    606:                        if (esiop_target)
                    607:                                esiop_target->target_c.flags &= ~TARF_DT;
1.13      bouyer    608: #ifdef DEBUG
                    609:                        printf("DSA=0x%x DSP=0x%lx\n",
                    610:                            bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
                    611:                            (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    612:                                SIOP_DSP) -
                    613:                            sc->sc_c.sc_scriptaddr));
1.14      bouyer    614:                        printf("SDID 0x%x SCNTL3 0x%x SXFER 0x%x SCNTL4 0x%x\n",
                    615:                            bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SDID),
                    616:                             bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCNTL3),
                    617:                             bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SXFER),
                    618:                             bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCNTL4));
                    619:
1.13      bouyer    620: #endif
1.1       bouyer    621:                        goto reset;
                    622:                }
                    623:                if ((sist & SIST0_MA) && need_reset == 0) {
1.11      bouyer    624:                        if (esiop_cmd) {
1.1       bouyer    625:                                int scratchc0;
                    626:                                dstat = bus_space_read_1(sc->sc_c.sc_rt,
                    627:                                    sc->sc_c.sc_rh, SIOP_DSTAT);
                    628:                                /*
                    629:                                 * first restore DSA, in case we were in a S/G
                    630:                                 * operation.
                    631:                                 */
                    632:                                bus_space_write_4(sc->sc_c.sc_rt,
                    633:                                    sc->sc_c.sc_rh,
                    634:                                    SIOP_DSA, esiop_cmd->cmd_c.dsa);
                    635:                                scratchc0 = bus_space_read_1(sc->sc_c.sc_rt,
                    636:                                    sc->sc_c.sc_rh, SIOP_SCRATCHC);
                    637:                                switch (sstat1 & SSTAT1_PHASE_MASK) {
                    638:                                case SSTAT1_PHASE_STATUS:
                    639:                                /*
                    640:                                 * previous phase may be aborted for any reason
                    641:                                 * ( for example, the target has less data to
1.29      bouyer    642:                                 * transfer than requested). Compute resid and
                    643:                                 * just go to status, the command should
                    644:                                 * terminate.
1.1       bouyer    645:                                 */
                    646:                                        INCSTAT(esiop_stat_intr_shortxfer);
1.28      bouyer    647:                                        if (scratchc0 & A_f_c_data)
1.29      bouyer    648:                                                siop_ma(&esiop_cmd->cmd_c);
1.28      bouyer    649:                                        else if ((dstat & DSTAT_DFE) == 0)
1.1       bouyer    650:                                                siop_clearfifo(&sc->sc_c);
                    651:                                        CALL_SCRIPT(Ent_status);
                    652:                                        return 1;
                    653:                                case SSTAT1_PHASE_MSGIN:
1.29      bouyer    654:                                /*
                    655:                                 * target may be ready to disconnect
                    656:                                 * Compute resid which would be used later
                    657:                                 * if a save data pointer is needed.
                    658:                                 */
1.1       bouyer    659:                                        INCSTAT(esiop_stat_intr_xferdisc);
                    660:                                        if (scratchc0 & A_f_c_data)
1.29      bouyer    661:                                                siop_ma(&esiop_cmd->cmd_c);
1.1       bouyer    662:                                        else if ((dstat & DSTAT_DFE) == 0)
                    663:                                                siop_clearfifo(&sc->sc_c);
                    664:                                        bus_space_write_1(sc->sc_c.sc_rt,
                    665:                                            sc->sc_c.sc_rh, SIOP_SCRATCHC,
                    666:                                            scratchc0 & ~A_f_c_data);
                    667:                                        CALL_SCRIPT(Ent_msgin);
                    668:                                        return 1;
                    669:                                }
                    670:                                printf("%s: unexpected phase mismatch %d\n",
                    671:                                    sc->sc_c.sc_dev.dv_xname,
                    672:                                    sstat1 & SSTAT1_PHASE_MASK);
                    673:                        } else {
                    674:                                printf("%s: phase mismatch without command\n",
                    675:                                    sc->sc_c.sc_dev.dv_xname);
                    676:                        }
                    677:                        need_reset = 1;
                    678:                }
                    679:                if (sist & SIST0_PAR) {
                    680:                        /* parity error, reset */
                    681:                        if (esiop_cmd)
                    682:                                scsipi_printaddr(xs->xs_periph);
                    683:                        else
                    684:                                printf("%s:", sc->sc_c.sc_dev.dv_xname);
                    685:                        printf("parity error\n");
1.6       bouyer    686:                        if (esiop_target)
                    687:                                esiop_target->target_c.flags &= ~TARF_DT;
1.1       bouyer    688:                        goto reset;
                    689:                }
                    690:                if ((sist & (SIST1_STO << 8)) && need_reset == 0) {
                    691:                        /*
1.9       bouyer    692:                         * selection time out, assume there's no device here
                    693:                         * We also have to update the ring pointer ourselve
1.1       bouyer    694:                         */
                    695:                        slot = bus_space_read_1(sc->sc_c.sc_rt,
                    696:                            sc->sc_c.sc_rh, SIOP_SCRATCHE);
                    697:                        esiop_script_sync(sc,
                    698:                            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1.9       bouyer    699: #ifdef SIOP_DEBUG_SCHED
                    700:                        printf("sel timeout target %d, slot %d\n", target, slot);
                    701: #endif
1.3       bouyer    702:                        /*
                    703:                         * mark this slot as free, and advance to next slot
                    704:                         */
1.8       bouyer    705:                        esiop_script_write(sc,
                    706:                            sc->sc_shedoffset + slot * CMD_SLOTSIZE,
1.3       bouyer    707:                            A_f_cmd_free);
                    708:                        addr = bus_space_read_4(sc->sc_c.sc_rt,
                    709:                                    sc->sc_c.sc_rh, SIOP_SCRATCHD);
                    710:                        if (slot < (A_ncmd_slots - 1)) {
                    711:                                bus_space_write_1(sc->sc_c.sc_rt,
                    712:                                    sc->sc_c.sc_rh, SIOP_SCRATCHE, slot + 1);
1.8       bouyer    713:                                addr = addr + sizeof(struct esiop_slot);
1.3       bouyer    714:                        } else {
                    715:                                bus_space_write_1(sc->sc_c.sc_rt,
                    716:                                    sc->sc_c.sc_rh, SIOP_SCRATCHE, 0);
                    717:                                addr = sc->sc_c.sc_scriptaddr +
                    718:                                    sc->sc_shedoffset * sizeof(u_int32_t);
                    719:                        }
                    720:                        bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    721:                            SIOP_SCRATCHD, addr);
                    722:                        esiop_script_sync(sc,
                    723:                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1.1       bouyer    724:                        if (esiop_cmd) {
                    725:                                esiop_cmd->cmd_c.status = CMDST_DONE;
                    726:                                xs->error = XS_SELTIMEOUT;
                    727:                                freetarget = 1;
1.29      bouyer    728:                                goto end;
1.1       bouyer    729:                        } else {
                    730:                                printf("%s: selection timeout without "
1.3       bouyer    731:                                    "command, target %d (sdid 0x%x), "
                    732:                                    "slot %d\n",
                    733:                                    sc->sc_c.sc_dev.dv_xname, target,
                    734:                                    bus_space_read_1(sc->sc_c.sc_rt,
                    735:                                    sc->sc_c.sc_rh, SIOP_SDID), slot);
1.1       bouyer    736:                                need_reset = 1;
                    737:                        }
                    738:                }
                    739:                if (sist & SIST0_UDC) {
                    740:                        /*
                    741:                         * unexpected disconnect. Usually the target signals
                    742:                         * a fatal condition this way. Attempt to get sense.
                    743:                         */
                    744:                         if (esiop_cmd) {
                    745:                                esiop_cmd->cmd_tables->status =
                    746:                                    htole32(SCSI_CHECK);
1.29      bouyer    747:                                goto end;
1.1       bouyer    748:                        }
                    749:                        printf("%s: unexpected disconnect without "
                    750:                            "command\n", sc->sc_c.sc_dev.dv_xname);
                    751:                        goto reset;
                    752:                }
                    753:                if (sist & (SIST1_SBMC << 8)) {
                    754:                        /* SCSI bus mode change */
                    755:                        if (siop_modechange(&sc->sc_c) == 0 || need_reset == 1)
                    756:                                goto reset;
                    757:                        if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
                    758:                                /*
                    759:                                 * we have a script interrupt, it will
                    760:                                 * restart the script.
                    761:                                 */
                    762:                                goto scintr;
                    763:                        }
                    764:                        /*
                    765:                         * else we have to restart it ourselve, at the
                    766:                         * interrupted instruction.
                    767:                         */
                    768:                        bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    769:                            SIOP_DSP,
                    770:                            bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    771:                            SIOP_DSP) - 8);
                    772:                        return 1;
                    773:                }
1.24      wiz       774:                /* Else it's an unhandled exception (for now). */
1.1       bouyer    775:                printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x "
                    776:                    "DSA=0x%x DSP=0x%x\n", sc->sc_c.sc_dev.dv_xname, sist,
                    777:                    bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    778:                        SIOP_SSTAT1),
                    779:                    bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
                    780:                    (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    781:                        SIOP_DSP) - sc->sc_c.sc_scriptaddr));
                    782:                if (esiop_cmd) {
                    783:                        esiop_cmd->cmd_c.status = CMDST_DONE;
                    784:                        xs->error = XS_SELTIMEOUT;
1.29      bouyer    785:                        goto end;
1.1       bouyer    786:                }
                    787:                need_reset = 1;
                    788:        }
                    789:        if (need_reset) {
                    790: reset:
                    791:                /* fatal error, reset the bus */
                    792:                siop_resetbus(&sc->sc_c);
                    793:                /* no table to flush here */
                    794:                return 1;
                    795:        }
                    796:
                    797: scintr:
                    798:        if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
                    799:                irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                    800:                    SIOP_DSPS);
                    801: #ifdef SIOP_DEBUG_INTR
                    802:                printf("script interrupt 0x%x\n", irqcode);
                    803: #endif
                    804:                /*
                    805:                 * no command, or an inactive command is only valid for a
                    806:                 * reselect interrupt
                    807:                 */
                    808:                if ((irqcode & 0x80) == 0) {
                    809:                        if (esiop_cmd == NULL) {
                    810:                                printf(
                    811:                        "%s: script interrupt (0x%x) with invalid DSA !!!\n",
                    812:                                    sc->sc_c.sc_dev.dv_xname, irqcode);
                    813:                                goto reset;
                    814:                        }
                    815:                        if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) {
                    816:                                printf("%s: command with invalid status "
                    817:                                    "(IRQ code 0x%x current status %d) !\n",
                    818:                                    sc->sc_c.sc_dev.dv_xname,
                    819:                                    irqcode, esiop_cmd->cmd_c.status);
                    820:                                xs = NULL;
                    821:                        }
                    822:                }
                    823:                switch(irqcode) {
                    824:                case A_int_err:
                    825:                        printf("error, DSP=0x%x\n",
                    826:                            (int)(bus_space_read_4(sc->sc_c.sc_rt,
                    827:                            sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
                    828:                        if (xs) {
                    829:                                xs->error = XS_SELTIMEOUT;
1.29      bouyer    830:                                goto end;
1.1       bouyer    831:                        } else {
                    832:                                goto reset;
                    833:                        }
                    834:                case A_int_msgin:
                    835:                {
                    836:                        int msgin = bus_space_read_1(sc->sc_c.sc_rt,
                    837:                            sc->sc_c.sc_rh, SIOP_SFBR);
                    838:                        if (msgin == MSG_MESSAGE_REJECT) {
                    839:                                int msg, extmsg;
                    840:                                if (esiop_cmd->cmd_tables->msg_out[0] & 0x80) {
                    841:                                        /*
                    842:                                         * message was part of a identify +
1.17      wiz       843:                                         * something else. Identify shouldn't
1.1       bouyer    844:                                         * have been rejected.
                    845:                                         */
                    846:                                        msg =
                    847:                                            esiop_cmd->cmd_tables->msg_out[1];
                    848:                                        extmsg =
                    849:                                            esiop_cmd->cmd_tables->msg_out[3];
                    850:                                } else {
                    851:                                        msg =
                    852:                                            esiop_cmd->cmd_tables->msg_out[0];
                    853:                                        extmsg =
                    854:                                            esiop_cmd->cmd_tables->msg_out[2];
                    855:                                }
                    856:                                if (msg == MSG_MESSAGE_REJECT) {
                    857:                                        /* MSG_REJECT  for a MSG_REJECT  !*/
                    858:                                        if (xs)
                    859:                                                scsipi_printaddr(xs->xs_periph);
                    860:                                        else
                    861:                                                printf("%s: ",
                    862:                                                   sc->sc_c.sc_dev.dv_xname);
                    863:                                        printf("our reject message was "
                    864:                                            "rejected\n");
                    865:                                        goto reset;
                    866:                                }
                    867:                                if (msg == MSG_EXTENDED &&
                    868:                                    extmsg == MSG_EXT_WDTR) {
                    869:                                        /* WDTR rejected, initiate sync */
                    870:                                        if ((esiop_target->target_c.flags &
                    871:                                           TARF_SYNC) == 0) {
                    872:                                                esiop_target->target_c.status =
                    873:                                                    TARST_OK;
                    874:                                                siop_update_xfer_mode(&sc->sc_c,
                    875:                                                    target);
                    876:                                                /* no table to flush here */
                    877:                                                CALL_SCRIPT(Ent_msgin_ack);
                    878:                                                return 1;
                    879:                                        }
                    880:                                        esiop_target->target_c.status =
                    881:                                            TARST_SYNC_NEG;
                    882:                                        siop_sdtr_msg(&esiop_cmd->cmd_c, 0,
1.6       bouyer    883:                                            sc->sc_c.st_minsync,
                    884:                                            sc->sc_c.maxoff);
1.1       bouyer    885:                                        esiop_table_sync(esiop_cmd,
                    886:                                            BUS_DMASYNC_PREREAD |
                    887:                                            BUS_DMASYNC_PREWRITE);
                    888:                                        CALL_SCRIPT(Ent_send_msgout);
                    889:                                        return 1;
                    890:                                } else if (msg == MSG_EXTENDED &&
                    891:                                    extmsg == MSG_EXT_SDTR) {
                    892:                                        /* sync rejected */
                    893:                                        esiop_target->target_c.offset = 0;
                    894:                                        esiop_target->target_c.period = 0;
                    895:                                        esiop_target->target_c.status =
                    896:                                            TARST_OK;
                    897:                                        siop_update_xfer_mode(&sc->sc_c,
                    898:                                            target);
                    899:                                        /* no table to flush here */
                    900:                                        CALL_SCRIPT(Ent_msgin_ack);
                    901:                                        return 1;
1.6       bouyer    902:                                } else if (msg == MSG_EXTENDED &&
                    903:                                    extmsg == MSG_EXT_PPR) {
                    904:                                        /* PPR rejected */
                    905:                                        esiop_target->target_c.offset = 0;
                    906:                                        esiop_target->target_c.period = 0;
                    907:                                        esiop_target->target_c.status =
                    908:                                            TARST_OK;
                    909:                                        siop_update_xfer_mode(&sc->sc_c,
                    910:                                            target);
                    911:                                        /* no table to flush here */
                    912:                                        CALL_SCRIPT(Ent_msgin_ack);
                    913:                                        return 1;
1.11      bouyer    914:                                } else if (msg == MSG_SIMPLE_Q_TAG ||
1.1       bouyer    915:                                    msg == MSG_HEAD_OF_Q_TAG ||
                    916:                                    msg == MSG_ORDERED_Q_TAG) {
1.2       bouyer    917:                                        if (esiop_handle_qtag_reject(
1.1       bouyer    918:                                            esiop_cmd) == -1)
                    919:                                                goto reset;
                    920:                                        CALL_SCRIPT(Ent_msgin_ack);
                    921:                                        return 1;
                    922:                                }
                    923:                                if (xs)
                    924:                                        scsipi_printaddr(xs->xs_periph);
                    925:                                else
                    926:                                        printf("%s: ",
                    927:                                            sc->sc_c.sc_dev.dv_xname);
                    928:                                if (msg == MSG_EXTENDED) {
                    929:                                        printf("scsi message reject, extended "
                    930:                                            "message sent was 0x%x\n", extmsg);
                    931:                                } else {
                    932:                                        printf("scsi message reject, message "
                    933:                                            "sent was 0x%x\n", msg);
                    934:                                }
                    935:                                /* no table to flush here */
                    936:                                CALL_SCRIPT(Ent_msgin_ack);
                    937:                                return 1;
                    938:                        }
1.30      bouyer    939:                        if (msgin == MSG_IGN_WIDE_RESIDUE) {
                    940:                        /* use the extmsgdata table to get the second byte */
                    941:                                esiop_cmd->cmd_tables->t_extmsgdata.count =
                    942:                                    htole32(1);
                    943:                                esiop_table_sync(esiop_cmd,
                    944:                                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    945:                                CALL_SCRIPT(Ent_get_extmsgdata);
                    946:                                return 1;
                    947:                        }
1.1       bouyer    948:                        if (xs)
                    949:                                scsipi_printaddr(xs->xs_periph);
                    950:                        else
                    951:                                printf("%s: ", sc->sc_c.sc_dev.dv_xname);
1.25      bouyer    952:                        printf("unhandled message 0x%x\n", msgin);
1.1       bouyer    953:                        esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
                    954:                        esiop_cmd->cmd_tables->t_msgout.count= htole32(1);
                    955:                        esiop_table_sync(esiop_cmd,
                    956:                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    957:                        CALL_SCRIPT(Ent_send_msgout);
                    958:                        return 1;
                    959:                }
                    960:                case A_int_extmsgin:
                    961: #ifdef SIOP_DEBUG_INTR
                    962:                        printf("extended message: msg 0x%x len %d\n",
1.11      bouyer    963:                            esiop_cmd->cmd_tables->msg_in[2],
1.1       bouyer    964:                            esiop_cmd->cmd_tables->msg_in[1]);
                    965: #endif
1.5       bouyer    966:                        if (esiop_cmd->cmd_tables->msg_in[1] >
                    967:                            sizeof(esiop_cmd->cmd_tables->msg_in) - 2)
1.1       bouyer    968:                                printf("%s: extended message too big (%d)\n",
                    969:                                    sc->sc_c.sc_dev.dv_xname,
                    970:                                    esiop_cmd->cmd_tables->msg_in[1]);
                    971:                        esiop_cmd->cmd_tables->t_extmsgdata.count =
                    972:                            htole32(esiop_cmd->cmd_tables->msg_in[1] - 1);
                    973:                        esiop_table_sync(esiop_cmd,
                    974:                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    975:                        CALL_SCRIPT(Ent_get_extmsgdata);
                    976:                        return 1;
                    977:                case A_int_extmsgdata:
                    978: #ifdef SIOP_DEBUG_INTR
                    979:                        {
                    980:                        int i;
                    981:                        printf("extended message: 0x%x, data:",
                    982:                            esiop_cmd->cmd_tables->msg_in[2]);
                    983:                        for (i = 3; i < 2 + esiop_cmd->cmd_tables->msg_in[1];
                    984:                            i++)
                    985:                                printf(" 0x%x",
                    986:                                    esiop_cmd->cmd_tables->msg_in[i]);
                    987:                        printf("\n");
                    988:                        }
                    989: #endif
1.30      bouyer    990:                        if (esiop_cmd->cmd_tables->msg_in[0] ==
                    991:                            MSG_IGN_WIDE_RESIDUE) {
                    992:                        /* we got the second byte of MSG_IGN_WIDE_RESIDUE */
                    993:                                if (esiop_cmd->cmd_tables->msg_in[3] != 1)
                    994:                                        printf("MSG_IGN_WIDE_RESIDUE: "
                    995:                                             "bad len %d\n",
                    996:                                             esiop_cmd->cmd_tables->msg_in[3]);
                    997:                                switch (siop_iwr(&esiop_cmd->cmd_c)) {
                    998:                                case SIOP_NEG_MSGOUT:
                    999:                                        esiop_table_sync(esiop_cmd,
                   1000:                                            BUS_DMASYNC_PREREAD |
                   1001:                                            BUS_DMASYNC_PREWRITE);
                   1002:                                        CALL_SCRIPT(Ent_send_msgout);
                   1003:                                        return 1;
                   1004:                                case SIOP_NEG_ACK:
                   1005:                                        CALL_SCRIPT(Ent_msgin_ack);
                   1006:                                        return 1;
                   1007:                                default:
                   1008:                                        panic("invalid retval from "
                   1009:                                            "siop_iwr()");
                   1010:                                }
                   1011:                                return 1;
                   1012:                        }
1.6       bouyer   1013:                        if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) {
                   1014:                                switch (siop_ppr_neg(&esiop_cmd->cmd_c)) {
                   1015:                                case SIOP_NEG_MSGOUT:
1.9       bouyer   1016:                                        esiop_update_scntl3(sc,
                   1017:                                            esiop_cmd->cmd_c.siop_target);
1.6       bouyer   1018:                                        esiop_table_sync(esiop_cmd,
                   1019:                                            BUS_DMASYNC_PREREAD |
                   1020:                                            BUS_DMASYNC_PREWRITE);
                   1021:                                        CALL_SCRIPT(Ent_send_msgout);
1.9       bouyer   1022:                                        return 1;
1.6       bouyer   1023:                                case SIOP_NEG_ACK:
1.9       bouyer   1024:                                        esiop_update_scntl3(sc,
                   1025:                                            esiop_cmd->cmd_c.siop_target);
1.6       bouyer   1026:                                        CALL_SCRIPT(Ent_msgin_ack);
1.9       bouyer   1027:                                        return 1;
1.6       bouyer   1028:                                default:
                   1029:                                        panic("invalid retval from "
                   1030:                                            "siop_wdtr_neg()");
                   1031:                                }
1.9       bouyer   1032:                                return 1;
1.6       bouyer   1033:                        }
1.1       bouyer   1034:                        if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
                   1035:                                switch (siop_wdtr_neg(&esiop_cmd->cmd_c)) {
                   1036:                                case SIOP_NEG_MSGOUT:
1.9       bouyer   1037:                                        esiop_update_scntl3(sc,
                   1038:                                            esiop_cmd->cmd_c.siop_target);
1.1       bouyer   1039:                                        esiop_table_sync(esiop_cmd,
                   1040:                                            BUS_DMASYNC_PREREAD |
                   1041:                                            BUS_DMASYNC_PREWRITE);
                   1042:                                        CALL_SCRIPT(Ent_send_msgout);
1.9       bouyer   1043:                                        return 1;
1.1       bouyer   1044:                                case SIOP_NEG_ACK:
1.9       bouyer   1045:                                        esiop_update_scntl3(sc,
                   1046:                                            esiop_cmd->cmd_c.siop_target);
1.1       bouyer   1047:                                        CALL_SCRIPT(Ent_msgin_ack);
1.9       bouyer   1048:                                        return 1;
1.1       bouyer   1049:                                default:
                   1050:                                        panic("invalid retval from "
                   1051:                                            "siop_wdtr_neg()");
                   1052:                                }
1.9       bouyer   1053:                                return 1;
1.1       bouyer   1054:                        }
                   1055:                        if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) {
                   1056:                                switch (siop_sdtr_neg(&esiop_cmd->cmd_c)) {
                   1057:                                case SIOP_NEG_MSGOUT:
1.9       bouyer   1058:                                        esiop_update_scntl3(sc,
                   1059:                                            esiop_cmd->cmd_c.siop_target);
1.1       bouyer   1060:                                        esiop_table_sync(esiop_cmd,
                   1061:                                            BUS_DMASYNC_PREREAD |
                   1062:                                            BUS_DMASYNC_PREWRITE);
                   1063:                                        CALL_SCRIPT(Ent_send_msgout);
1.9       bouyer   1064:                                        return 1;
1.1       bouyer   1065:                                case SIOP_NEG_ACK:
1.9       bouyer   1066:                                        esiop_update_scntl3(sc,
                   1067:                                            esiop_cmd->cmd_c.siop_target);
1.1       bouyer   1068:                                        CALL_SCRIPT(Ent_msgin_ack);
1.9       bouyer   1069:                                        return 1;
1.1       bouyer   1070:                                default:
                   1071:                                        panic("invalid retval from "
                   1072:                                            "siop_wdtr_neg()");
                   1073:                                }
1.9       bouyer   1074:                                return 1;
1.1       bouyer   1075:                        }
                   1076:                        /* send a message reject */
                   1077:                        esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
                   1078:                        esiop_cmd->cmd_tables->t_msgout.count = htole32(1);
                   1079:                        esiop_table_sync(esiop_cmd,
                   1080:                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1081:                        CALL_SCRIPT(Ent_send_msgout);
                   1082:                        return 1;
                   1083:                case A_int_disc:
                   1084:                        INCSTAT(esiop_stat_intr_sdp);
                   1085:                        offset = bus_space_read_1(sc->sc_c.sc_rt,
                   1086:                            sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
                   1087: #ifdef SIOP_DEBUG_DR
                   1088:                        printf("disconnect offset %d\n", offset);
                   1089: #endif
1.29      bouyer   1090:                        siop_sdp(&esiop_cmd->cmd_c, offset);
1.34      bouyer   1091:                        /* we start again with no offset */
                   1092:                        ESIOP_XFER(esiop_cmd, saved_offset) =
                   1093:                            htole32(SIOP_NOOFFSET);
1.29      bouyer   1094:                        esiop_table_sync(esiop_cmd,
                   1095:                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1.1       bouyer   1096:                        CALL_SCRIPT(Ent_script_sched);
                   1097:                        return 1;
                   1098:                case A_int_resfail:
                   1099:                        printf("reselect failed\n");
                   1100:                        CALL_SCRIPT(Ent_script_sched);
1.9       bouyer   1101:                        return 1;
1.1       bouyer   1102:                case A_int_done:
                   1103:                        if (xs == NULL) {
                   1104:                                printf("%s: done without command\n",
                   1105:                                    sc->sc_c.sc_dev.dv_xname);
                   1106:                                CALL_SCRIPT(Ent_script_sched);
                   1107:                                return 1;
                   1108:                        }
                   1109: #ifdef SIOP_DEBUG_INTR
                   1110:                        printf("done, DSA=0x%lx target id 0x%x last msg "
                   1111:                            "in=0x%x status=0x%x\n", (u_long)esiop_cmd->cmd_c.dsa,
                   1112:                            le32toh(esiop_cmd->cmd_tables->id),
                   1113:                            esiop_cmd->cmd_tables->msg_in[0],
                   1114:                            le32toh(esiop_cmd->cmd_tables->status));
                   1115: #endif
                   1116:                        INCSTAT(esiop_stat_intr_done);
                   1117:                        esiop_cmd->cmd_c.status = CMDST_DONE;
                   1118:                        goto end;
                   1119:                default:
                   1120:                        printf("unknown irqcode %x\n", irqcode);
                   1121:                        if (xs) {
                   1122:                                xs->error = XS_SELTIMEOUT;
1.29      bouyer   1123:                                goto end;
1.1       bouyer   1124:                        }
                   1125:                        goto reset;
                   1126:                }
                   1127:                return 1;
                   1128:        }
                   1129:        /* We just should't get there */
                   1130:        panic("siop_intr: I shouldn't be there !");
                   1131:
                   1132: end:
                   1133:        /*
                   1134:         * restart the script now if command completed properly
                   1135:         * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
                   1136:         * queue
                   1137:         */
                   1138:        xs->status = le32toh(esiop_cmd->cmd_tables->status);
                   1139: #ifdef SIOP_DEBUG_INTR
                   1140:        printf("esiop_intr end: status %d\n", xs->status);
                   1141: #endif
1.2       bouyer   1142:        if (tag >= 0)
                   1143:                esiop_lun->tactive[tag] = NULL;
                   1144:        else
                   1145:                esiop_lun->active = NULL;
1.29      bouyer   1146:        offset = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                   1147:            SIOP_SCRATCHA + 1);
1.34      bouyer   1148:        /*
                   1149:         * if we got a disconnect between the last data phase
                   1150:         * and the status phase, offset will be 0. In this
                   1151:         * case, cmd_tables->saved_offset will have the proper value
                   1152:         * if it got updated by the controller
                   1153:         */
                   1154:        if (offset == 0 &&
                   1155:            ESIOP_XFER(esiop_cmd, saved_offset) != htole32(SIOP_NOOFFSET))
                   1156:                offset =
                   1157:                    (le32toh(ESIOP_XFER(esiop_cmd, saved_offset)) >> 8) & 0xff;
                   1158:
1.29      bouyer   1159:        esiop_scsicmd_end(esiop_cmd, offset);
1.1       bouyer   1160:        if (freetarget && esiop_target->target_c.status == TARST_PROBING)
                   1161:                esiop_del_dev(sc, target, lun);
1.9       bouyer   1162:        CALL_SCRIPT(Ent_script_sched);
                   1163:        return 1;
1.1       bouyer   1164: }
                   1165:
                   1166: void
1.29      bouyer   1167: esiop_scsicmd_end(esiop_cmd, offset)
1.1       bouyer   1168:        struct esiop_cmd *esiop_cmd;
1.29      bouyer   1169:        int offset;
1.1       bouyer   1170: {
                   1171:        struct scsipi_xfer *xs = esiop_cmd->cmd_c.xs;
                   1172:        struct esiop_softc *sc = (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
1.28      bouyer   1173:
1.29      bouyer   1174:        siop_update_resid(&esiop_cmd->cmd_c, offset);
1.1       bouyer   1175:
                   1176:        switch(xs->status) {
                   1177:        case SCSI_OK:
                   1178:                xs->error = XS_NOERROR;
                   1179:                break;
                   1180:        case SCSI_BUSY:
                   1181:                xs->error = XS_BUSY;
                   1182:                break;
                   1183:        case SCSI_CHECK:
                   1184:                xs->error = XS_BUSY;
                   1185:                /* remove commands in the queue and scheduler */
                   1186:                esiop_unqueue(sc, xs->xs_periph->periph_target,
                   1187:                    xs->xs_periph->periph_lun);
                   1188:                break;
                   1189:        case SCSI_QUEUE_FULL:
                   1190:                INCSTAT(esiop_stat_intr_qfull);
                   1191: #ifdef SIOP_DEBUG
                   1192:                printf("%s:%d:%d: queue full (tag %d)\n",
                   1193:                    sc->sc_c.sc_dev.dv_xname,
                   1194:                    xs->xs_periph->periph_target,
                   1195:                    xs->xs_periph->periph_lun, esiop_cmd->cmd_c.tag);
                   1196: #endif
                   1197:                xs->error = XS_BUSY;
                   1198:                break;
                   1199:        case SCSI_SIOP_NOCHECK:
                   1200:                /*
                   1201:                 * don't check status, xs->error is already valid
                   1202:                 */
                   1203:                break;
                   1204:        case SCSI_SIOP_NOSTATUS:
                   1205:                /*
                   1206:                 * the status byte was not updated, cmd was
                   1207:                 * aborted
                   1208:                 */
                   1209:                xs->error = XS_SELTIMEOUT;
                   1210:                break;
                   1211:        default:
1.16      bouyer   1212:                scsipi_printaddr(xs->xs_periph);
                   1213:                printf("invalid status code %d\n", xs->status);
1.1       bouyer   1214:                xs->error = XS_DRIVER_STUFFUP;
                   1215:        }
                   1216:        if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
                   1217:                bus_dmamap_sync(sc->sc_c.sc_dmat,
                   1218:                    esiop_cmd->cmd_c.dmamap_data, 0,
                   1219:                    esiop_cmd->cmd_c.dmamap_data->dm_mapsize,
                   1220:                    (xs->xs_control & XS_CTL_DATA_IN) ?
                   1221:                    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                   1222:                bus_dmamap_unload(sc->sc_c.sc_dmat,
                   1223:                    esiop_cmd->cmd_c.dmamap_data);
                   1224:        }
                   1225:        bus_dmamap_unload(sc->sc_c.sc_dmat, esiop_cmd->cmd_c.dmamap_cmd);
1.39.18.1! yamt     1226:        if ((xs->xs_control & XS_CTL_POLL) == 0)
        !          1227:                callout_stop(&xs->xs_callout);
1.1       bouyer   1228:        esiop_cmd->cmd_c.status = CMDST_FREE;
                   1229:        TAILQ_INSERT_TAIL(&sc->free_list, esiop_cmd, next);
1.29      bouyer   1230: #if 0
                   1231:        if (xs->resid != 0)
                   1232:                printf("resid %d datalen %d\n", xs->resid, xs->datalen);
                   1233: #endif
1.1       bouyer   1234:        scsipi_done (xs);
                   1235: }
                   1236:
                   1237: void
                   1238: esiop_checkdone(sc)
                   1239:        struct esiop_softc *sc;
                   1240: {
1.2       bouyer   1241:        int target, lun, tag;
1.1       bouyer   1242:        struct esiop_target *esiop_target;
                   1243:        struct esiop_lun *esiop_lun;
                   1244:        struct esiop_cmd *esiop_cmd;
1.11      bouyer   1245:        u_int32_t slot;
                   1246:        int needsync = 0;
1.1       bouyer   1247:        int status;
1.34      bouyer   1248:        u_int32_t sem, offset;
1.12      bouyer   1249:
                   1250:        esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1251:        sem = esiop_script_read(sc, sc->sc_semoffset);
                   1252:        esiop_script_write(sc, sc->sc_semoffset, sem & ~A_sem_done);
                   1253:        if ((sc->sc_flags & SCF_CHAN_NOSLOT) && (sem & A_sem_start)) {
                   1254:                /*
                   1255:                 * at last one command have been started,
                   1256:                 * so we should have free slots now
                   1257:                 */
                   1258:                sc->sc_flags &= ~SCF_CHAN_NOSLOT;
                   1259:                scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
                   1260:        }
                   1261:        esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1262:
                   1263:        if ((sem & A_sem_done) == 0) {
                   1264:                /* no pending done command */
                   1265:                return;
                   1266:        }
1.1       bouyer   1267:
1.11      bouyer   1268:        bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map,
                   1269:            sc->sc_done_offset, A_ndone_slots * sizeof(u_int32_t),
                   1270:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1271: next:
                   1272:        if (sc->sc_done_slot[sc->sc_currdoneslot] == 0) {
                   1273:                if (needsync)
                   1274:                        bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map,
                   1275:                            sc->sc_done_offset,
                   1276:                            A_ndone_slots * sizeof(u_int32_t),
                   1277:                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1278:                return;
                   1279:        }
                   1280:
                   1281:        needsync = 1;
                   1282:
                   1283:        slot = htole32(sc->sc_done_slot[sc->sc_currdoneslot]);
                   1284:        sc->sc_done_slot[sc->sc_currdoneslot] = 0;
                   1285:        sc->sc_currdoneslot += 1;
                   1286:        if (sc->sc_currdoneslot == A_ndone_slots)
                   1287:                sc->sc_currdoneslot = 0;
                   1288:
                   1289:        target =  (slot & A_f_c_target) ? (slot >> 8) & 0xff : -1;
                   1290:        lun =  (slot & A_f_c_lun) ? (slot >> 16) & 0xff : -1;
                   1291:        tag =  (slot & A_f_c_tag) ? (slot >> 24) & 0xff : -1;
                   1292:
                   1293:        esiop_target = (target >= 0) ?
                   1294:            (struct esiop_target *)sc->sc_c.targets[target] : NULL;
                   1295:        if (esiop_target == NULL) {
                   1296:                printf("esiop_target (target %d) not valid\n", target);
                   1297:                goto next;
                   1298:        }
                   1299:        esiop_lun = (lun >= 0) ? esiop_target->esiop_lun[lun] : NULL;
                   1300:        if (esiop_lun == NULL) {
                   1301:                printf("esiop_lun (target %d lun %d) not valid\n",
                   1302:                    target, lun);
                   1303:                goto next;
                   1304:        }
                   1305:        esiop_cmd = (tag >= 0) ? esiop_lun->tactive[tag] : esiop_lun->active;
                   1306:        if (esiop_cmd == NULL) {
                   1307:                printf("esiop_cmd (target %d lun %d tag %d) not valid\n",
                   1308:                    target, lun, tag);
                   1309:                        goto next;
                   1310:        }
                   1311:
                   1312:        esiop_table_sync(esiop_cmd,
                   1313:                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1314:        status = le32toh(esiop_cmd->cmd_tables->status);
                   1315: #ifdef DIAGNOSTIC
                   1316:        if (status != SCSI_OK) {
                   1317:                printf("command for T/L/Q %d/%d/%d status %d\n",
                   1318:                    target, lun, tag, status);
                   1319:                goto next;
1.1       bouyer   1320:        }
1.11      bouyer   1321:
                   1322: #endif
                   1323:        /* Ok, this command has been handled */
                   1324:        esiop_cmd->cmd_c.xs->status = status;
                   1325:        if (tag >= 0)
                   1326:                esiop_lun->tactive[tag] = NULL;
                   1327:        else
                   1328:                esiop_lun->active = NULL;
1.34      bouyer   1329:        /*
                   1330:         * scratcha was eventually saved in saved_offset by script.
                   1331:         * fetch offset from it
                   1332:         */
                   1333:        offset = 0;
                   1334:        if (ESIOP_XFER(esiop_cmd, saved_offset) != htole32(SIOP_NOOFFSET))
                   1335:                offset =
                   1336:                    (le32toh(ESIOP_XFER(esiop_cmd, saved_offset)) >> 8) & 0xff;
                   1337:        esiop_scsicmd_end(esiop_cmd, offset);
1.11      bouyer   1338:        goto next;
1.1       bouyer   1339: }
                   1340:
                   1341: void
                   1342: esiop_unqueue(sc, target, lun)
                   1343:        struct esiop_softc *sc;
                   1344:        int target;
                   1345:        int lun;
                   1346: {
                   1347:        int slot, tag;
1.2       bouyer   1348:        u_int32_t slotdsa;
1.1       bouyer   1349:        struct esiop_cmd *esiop_cmd;
                   1350:        struct esiop_lun *esiop_lun =
                   1351:            ((struct esiop_target *)sc->sc_c.targets[target])->esiop_lun[lun];
                   1352:
                   1353:        /* first make sure to read valid data */
                   1354:        esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1355:
1.2       bouyer   1356:        for (tag = 0; tag < ESIOP_NTAG; tag++) {
1.1       bouyer   1357:                /* look for commands in the scheduler, not yet started */
1.11      bouyer   1358:                if (esiop_lun->tactive[tag] == NULL)
1.1       bouyer   1359:                        continue;
1.2       bouyer   1360:                esiop_cmd = esiop_lun->tactive[tag];
1.3       bouyer   1361:                for (slot = 0; slot < A_ncmd_slots; slot++) {
1.2       bouyer   1362:                        slotdsa = esiop_script_read(sc,
1.8       bouyer   1363:                            sc->sc_shedoffset + slot * CMD_SLOTSIZE);
1.9       bouyer   1364:                        /* if the slot has any flag, it won't match the DSA */
                   1365:                        if (slotdsa == esiop_cmd->cmd_c.dsa) { /* found it */
                   1366:                                /* Mark this slot as ignore */
                   1367:                                esiop_script_write(sc,
                   1368:                                    sc->sc_shedoffset + slot * CMD_SLOTSIZE,
                   1369:                                    esiop_cmd->cmd_c.dsa | A_f_cmd_ignore);
                   1370:                                /* ask to requeue */
                   1371:                                esiop_cmd->cmd_c.xs->error = XS_REQUEUE;
                   1372:                                esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
                   1373:                                esiop_lun->tactive[tag] = NULL;
1.29      bouyer   1374:                                esiop_scsicmd_end(esiop_cmd, 0);
1.1       bouyer   1375:                                break;
1.9       bouyer   1376:                        }
1.1       bouyer   1377:                }
                   1378:        }
1.9       bouyer   1379:        esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1.1       bouyer   1380: }
                   1381:
                   1382: /*
                   1383:  * handle a rejected queue tag message: the command will run untagged,
                   1384:  * has to adjust the reselect script.
                   1385:  */
                   1386:
1.2       bouyer   1387:
1.1       bouyer   1388: int
                   1389: esiop_handle_qtag_reject(esiop_cmd)
                   1390:        struct esiop_cmd *esiop_cmd;
                   1391: {
1.2       bouyer   1392:        struct esiop_softc *sc = (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
1.1       bouyer   1393:        int target = esiop_cmd->cmd_c.xs->xs_periph->periph_target;
                   1394:        int lun = esiop_cmd->cmd_c.xs->xs_periph->periph_lun;
                   1395:        int tag = esiop_cmd->cmd_tables->msg_out[2];
1.2       bouyer   1396:        struct esiop_target *esiop_target =
                   1397:            (struct esiop_target*)sc->sc_c.targets[target];
                   1398:        struct esiop_lun *esiop_lun = esiop_target->esiop_lun[lun];
1.1       bouyer   1399:
                   1400: #ifdef SIOP_DEBUG
                   1401:        printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",
                   1402:            sc->sc_c.sc_dev.dv_xname, target, lun, tag, esiop_cmd->cmd_c.tag,
                   1403:            esiop_cmd->cmd_c.status);
                   1404: #endif
                   1405:
1.2       bouyer   1406:        if (esiop_lun->active != NULL) {
1.1       bouyer   1407:                printf("%s: untagged command already running for target %d "
                   1408:                    "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname,
1.2       bouyer   1409:                    target, lun, esiop_lun->active->cmd_c.status);
1.1       bouyer   1410:                return -1;
                   1411:        }
                   1412:        /* clear tag slot */
1.2       bouyer   1413:        esiop_lun->tactive[tag] = NULL;
1.1       bouyer   1414:        /* add command to non-tagged slot */
1.2       bouyer   1415:        esiop_lun->active = esiop_cmd;
                   1416:        esiop_cmd->cmd_c.flags &= ~CMDFL_TAG;
                   1417:        esiop_cmd->cmd_c.tag = -1;
                   1418:        /* update DSA table */
1.9       bouyer   1419:        esiop_script_write(sc, esiop_target->lun_table_offset +
                   1420:            lun * 2 + A_target_luntbl / sizeof(u_int32_t),
1.2       bouyer   1421:            esiop_cmd->cmd_c.dsa);
                   1422:        esiop_script_sync(sc, BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);
1.1       bouyer   1423:        return 0;
                   1424: }
                   1425:
                   1426: /*
                   1427:  * handle a bus reset: reset chip, unqueue all active commands, free all
1.24      wiz      1428:  * target struct and report lossage to upper layer.
1.1       bouyer   1429:  * As the upper layer may requeue immediatly we have to first store
                   1430:  * all active commands in a temporary queue.
                   1431:  */
                   1432: void
                   1433: esiop_handle_reset(sc)
                   1434:        struct esiop_softc *sc;
                   1435: {
                   1436:        struct esiop_cmd *esiop_cmd;
                   1437:        struct esiop_lun *esiop_lun;
                   1438:        int target, lun, tag;
                   1439:        /*
                   1440:         * scsi bus reset. reset the chip and restart
                   1441:         * the queue. Need to clean up all active commands
                   1442:         */
                   1443:        printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname);
                   1444:        /* stop, reset and restart the chip */
                   1445:        esiop_reset(sc);
1.9       bouyer   1446:
1.1       bouyer   1447:        if (sc->sc_flags & SCF_CHAN_NOSLOT) {
                   1448:                /* chip has been reset, all slots are free now */
                   1449:                sc->sc_flags &= ~SCF_CHAN_NOSLOT;
                   1450:                scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
                   1451:        }
                   1452:        /*
1.24      wiz      1453:         * Process all commands: first commands completes, then commands
1.1       bouyer   1454:         * being executed
                   1455:         */
                   1456:        esiop_checkdone(sc);
                   1457:        for (target = 0; target < sc->sc_c.sc_chan.chan_ntargets;
                   1458:            target++) {
1.11      bouyer   1459:                struct esiop_target *esiop_target =
1.1       bouyer   1460:                    (struct esiop_target *)sc->sc_c.targets[target];
                   1461:                if (esiop_target == NULL)
                   1462:                        continue;
                   1463:                for (lun = 0; lun < 8; lun++) {
                   1464:                        esiop_lun = esiop_target->esiop_lun[lun];
                   1465:                        if (esiop_lun == NULL)
                   1466:                                continue;
1.2       bouyer   1467:                        for (tag = -1; tag <
1.1       bouyer   1468:                            ((sc->sc_c.targets[target]->flags & TARF_TAG) ?
1.2       bouyer   1469:                            ESIOP_NTAG : 0);
1.1       bouyer   1470:                            tag++) {
1.2       bouyer   1471:                                if (tag >= 0)
                   1472:                                        esiop_cmd = esiop_lun->tactive[tag];
                   1473:                                else
                   1474:                                        esiop_cmd = esiop_lun->active;
1.1       bouyer   1475:                                if (esiop_cmd == NULL)
                   1476:                                        continue;
                   1477:                                scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph);
                   1478:                                printf("command with tag id %d reset\n", tag);
                   1479:                                esiop_cmd->cmd_c.xs->error =
                   1480:                                    (esiop_cmd->cmd_c.flags & CMDFL_TIMEOUT) ?
                   1481:                                    XS_TIMEOUT : XS_RESET;
                   1482:                                esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
1.2       bouyer   1483:                                if (tag >= 0)
                   1484:                                        esiop_lun->tactive[tag] = NULL;
                   1485:                                else
                   1486:                                        esiop_lun->active = NULL;
1.1       bouyer   1487:                                esiop_cmd->cmd_c.status = CMDST_DONE;
1.29      bouyer   1488:                                esiop_scsicmd_end(esiop_cmd, 0);
1.1       bouyer   1489:                        }
                   1490:                }
                   1491:                sc->sc_c.targets[target]->status = TARST_ASYNC;
1.6       bouyer   1492:                sc->sc_c.targets[target]->flags &= ~(TARF_ISWIDE | TARF_ISDT);
1.1       bouyer   1493:                sc->sc_c.targets[target]->period =
                   1494:                    sc->sc_c.targets[target]->offset = 0;
                   1495:                siop_update_xfer_mode(&sc->sc_c, target);
                   1496:        }
                   1497:
                   1498:        scsipi_async_event(&sc->sc_c.sc_chan, ASYNC_EVENT_RESET, NULL);
                   1499: }
                   1500:
                   1501: void
                   1502: esiop_scsipi_request(chan, req, arg)
                   1503:        struct scsipi_channel *chan;
                   1504:        scsipi_adapter_req_t req;
                   1505:        void *arg;
                   1506: {
                   1507:        struct scsipi_xfer *xs;
                   1508:        struct scsipi_periph *periph;
                   1509:        struct esiop_softc *sc = (void *)chan->chan_adapter->adapt_dev;
                   1510:        struct esiop_cmd *esiop_cmd;
                   1511:        struct esiop_target *esiop_target;
                   1512:        int s, error, i;
                   1513:        int target;
                   1514:        int lun;
                   1515:
                   1516:        switch (req) {
                   1517:        case ADAPTER_REQ_RUN_XFER:
                   1518:                xs = arg;
                   1519:                periph = xs->xs_periph;
                   1520:                target = periph->periph_target;
                   1521:                lun = periph->periph_lun;
                   1522:
                   1523:                s = splbio();
1.12      bouyer   1524:                /*
                   1525:                 * first check if there are pending complete commands.
                   1526:                 * this can free us some resources (in the rings for example).
                   1527:                 * we have to lock it to avoid recursion.
                   1528:                 */
                   1529:                if ((sc->sc_flags & SCF_CHAN_ADAPTREQ) == 0) {
                   1530:                        sc->sc_flags |= SCF_CHAN_ADAPTREQ;
                   1531:                        esiop_checkdone(sc);
                   1532:                        sc->sc_flags &= ~SCF_CHAN_ADAPTREQ;
                   1533:                }
1.1       bouyer   1534: #ifdef SIOP_DEBUG_SCHED
1.9       bouyer   1535:                printf("starting cmd for %d:%d tag %d(%d)\n", target, lun,
                   1536:                    xs->xs_tag_type, xs->xs_tag_id);
1.1       bouyer   1537: #endif
                   1538:                esiop_cmd = TAILQ_FIRST(&sc->free_list);
                   1539:                if (esiop_cmd == NULL) {
                   1540:                        xs->error = XS_RESOURCE_SHORTAGE;
                   1541:                        scsipi_done(xs);
                   1542:                        splx(s);
                   1543:                        return;
                   1544:                }
                   1545:                TAILQ_REMOVE(&sc->free_list, esiop_cmd, next);
                   1546: #ifdef DIAGNOSTIC
                   1547:                if (esiop_cmd->cmd_c.status != CMDST_FREE)
                   1548:                        panic("siop_scsicmd: new cmd not free");
                   1549: #endif
                   1550:                esiop_target = (struct esiop_target*)sc->sc_c.targets[target];
                   1551:                if (esiop_target == NULL) {
                   1552: #ifdef SIOP_DEBUG
                   1553:                        printf("%s: alloc siop_target for target %d\n",
                   1554:                                sc->sc_c.sc_dev.dv_xname, target);
                   1555: #endif
                   1556:                        sc->sc_c.targets[target] =
                   1557:                            malloc(sizeof(struct esiop_target),
                   1558:                                M_DEVBUF, M_NOWAIT | M_ZERO);
                   1559:                        if (sc->sc_c.targets[target] == NULL) {
                   1560:                                printf("%s: can't malloc memory for "
                   1561:                                    "target %d\n", sc->sc_c.sc_dev.dv_xname,
                   1562:                                    target);
                   1563:                                xs->error = XS_RESOURCE_SHORTAGE;
                   1564:                                scsipi_done(xs);
                   1565:                                splx(s);
                   1566:                                return;
                   1567:                        }
                   1568:                        esiop_target =
                   1569:                            (struct esiop_target*)sc->sc_c.targets[target];
                   1570:                        esiop_target->target_c.status = TARST_PROBING;
                   1571:                        esiop_target->target_c.flags = 0;
                   1572:                        esiop_target->target_c.id =
                   1573:                            sc->sc_c.clock_div << 24; /* scntl3 */
                   1574:                        esiop_target->target_c.id |=  target << 16; /* id */
                   1575:                        /* esiop_target->target_c.id |= 0x0 << 8; scxfer is 0 */
                   1576:
                   1577:                        for (i=0; i < 8; i++)
                   1578:                                esiop_target->esiop_lun[i] = NULL;
                   1579:                        esiop_target_register(sc, target);
                   1580:                }
                   1581:                if (esiop_target->esiop_lun[lun] == NULL) {
                   1582:                        esiop_target->esiop_lun[lun] =
                   1583:                            malloc(sizeof(struct esiop_lun), M_DEVBUF,
                   1584:                            M_NOWAIT|M_ZERO);
                   1585:                        if (esiop_target->esiop_lun[lun] == NULL) {
                   1586:                                printf("%s: can't alloc esiop_lun for "
                   1587:                                    "target %d lun %d\n",
                   1588:                                    sc->sc_c.sc_dev.dv_xname, target, lun);
                   1589:                                xs->error = XS_RESOURCE_SHORTAGE;
                   1590:                                scsipi_done(xs);
                   1591:                                splx(s);
                   1592:                                return;
                   1593:                        }
                   1594:                }
                   1595:                esiop_cmd->cmd_c.siop_target = sc->sc_c.targets[target];
                   1596:                esiop_cmd->cmd_c.xs = xs;
                   1597:                esiop_cmd->cmd_c.flags = 0;
                   1598:                esiop_cmd->cmd_c.status = CMDST_READY;
                   1599:
                   1600:                /* load the DMA maps */
                   1601:                error = bus_dmamap_load(sc->sc_c.sc_dmat,
                   1602:                    esiop_cmd->cmd_c.dmamap_cmd,
                   1603:                    xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT);
                   1604:                if (error) {
                   1605:                        printf("%s: unable to load cmd DMA map: %d\n",
                   1606:                            sc->sc_c.sc_dev.dv_xname, error);
                   1607:                        xs->error = XS_DRIVER_STUFFUP;
                   1608:                        scsipi_done(xs);
                   1609:                        splx(s);
                   1610:                        return;
                   1611:                }
                   1612:                if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
                   1613:                        error = bus_dmamap_load(sc->sc_c.sc_dmat,
                   1614:                            esiop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen,
                   1615:                            NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
                   1616:                            ((xs->xs_control & XS_CTL_DATA_IN) ?
                   1617:                             BUS_DMA_READ : BUS_DMA_WRITE));
                   1618:                        if (error) {
                   1619:                                printf("%s: unable to load cmd DMA map: %d",
                   1620:                                    sc->sc_c.sc_dev.dv_xname, error);
                   1621:                                xs->error = XS_DRIVER_STUFFUP;
                   1622:                                scsipi_done(xs);
                   1623:                                bus_dmamap_unload(sc->sc_c.sc_dmat,
                   1624:                                    esiop_cmd->cmd_c.dmamap_cmd);
                   1625:                                splx(s);
                   1626:                                return;
                   1627:                        }
                   1628:                        bus_dmamap_sync(sc->sc_c.sc_dmat,
                   1629:                            esiop_cmd->cmd_c.dmamap_data, 0,
                   1630:                            esiop_cmd->cmd_c.dmamap_data->dm_mapsize,
                   1631:                            (xs->xs_control & XS_CTL_DATA_IN) ?
                   1632:                            BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
                   1633:                }
                   1634:                bus_dmamap_sync(sc->sc_c.sc_dmat, esiop_cmd->cmd_c.dmamap_cmd,
                   1635:                    0, esiop_cmd->cmd_c.dmamap_cmd->dm_mapsize,
                   1636:                    BUS_DMASYNC_PREWRITE);
                   1637:
1.2       bouyer   1638:                if (xs->xs_tag_type)
                   1639:                        esiop_cmd->cmd_c.tag = xs->xs_tag_id;
                   1640:                else
                   1641:                        esiop_cmd->cmd_c.tag = -1;
1.1       bouyer   1642:                siop_setuptables(&esiop_cmd->cmd_c);
1.34      bouyer   1643:                ESIOP_XFER(esiop_cmd, saved_offset) = htole32(SIOP_NOOFFSET);
                   1644:                ESIOP_XFER(esiop_cmd, tlq) = htole32(A_f_c_target | A_f_c_lun);
                   1645:                ESIOP_XFER(esiop_cmd, tlq) |=
1.2       bouyer   1646:                    htole32((target << 8) | (lun << 16));
                   1647:                if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
1.34      bouyer   1648:                        ESIOP_XFER(esiop_cmd, tlq) |= htole32(A_f_c_tag);
                   1649:                        ESIOP_XFER(esiop_cmd, tlq) |=
1.2       bouyer   1650:                            htole32(esiop_cmd->cmd_c.tag << 24);
                   1651:                }
1.1       bouyer   1652:
                   1653:                esiop_table_sync(esiop_cmd,
                   1654:                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1655:                esiop_start(sc, esiop_cmd);
                   1656:                if (xs->xs_control & XS_CTL_POLL) {
                   1657:                        /* poll for command completion */
                   1658:                        while ((xs->xs_status & XS_STS_DONE) == 0) {
                   1659:                                delay(1000);
                   1660:                                esiop_intr(sc);
                   1661:                        }
                   1662:                }
                   1663:                splx(s);
                   1664:                return;
                   1665:
                   1666:        case ADAPTER_REQ_GROW_RESOURCES:
                   1667: #ifdef SIOP_DEBUG
                   1668:                printf("%s grow resources (%d)\n", sc->sc_c.sc_dev.dv_xname,
                   1669:                    sc->sc_c.sc_adapt.adapt_openings);
                   1670: #endif
                   1671:                esiop_morecbd(sc);
                   1672:                return;
                   1673:
                   1674:        case ADAPTER_REQ_SET_XFER_MODE:
                   1675:        {
                   1676:                struct scsipi_xfer_mode *xm = arg;
                   1677:                if (sc->sc_c.targets[xm->xm_target] == NULL)
                   1678:                        return;
                   1679:                s = splbio();
1.33      bouyer   1680:                if (xm->xm_mode & PERIPH_CAP_TQING) {
1.1       bouyer   1681:                        sc->sc_c.targets[xm->xm_target]->flags |= TARF_TAG;
1.9       bouyer   1682:                        /* allocate tag tables for this device */
                   1683:                        for (lun = 0;
                   1684:                            lun < sc->sc_c.sc_chan.chan_nluns; lun++) {
1.15      thorpej  1685:                                if (scsipi_lookup_periph(chan,
                   1686:                                    xm->xm_target, lun) != NULL)
1.9       bouyer   1687:                                        esiop_add_dev(sc, xm->xm_target, lun);
                   1688:                        }
                   1689:                }
1.1       bouyer   1690:                if ((xm->xm_mode & PERIPH_CAP_WIDE16) &&
                   1691:                    (sc->sc_c.features & SF_BUS_WIDE))
                   1692:                        sc->sc_c.targets[xm->xm_target]->flags |= TARF_WIDE;
                   1693:                if (xm->xm_mode & PERIPH_CAP_SYNC)
                   1694:                        sc->sc_c.targets[xm->xm_target]->flags |= TARF_SYNC;
1.6       bouyer   1695:                if ((xm->xm_mode & PERIPH_CAP_DT) &&
                   1696:                    (sc->sc_c.features & SF_CHIP_DT))
                   1697:                        sc->sc_c.targets[xm->xm_target]->flags |= TARF_DT;
                   1698:                if ((xm->xm_mode &
                   1699:                    (PERIPH_CAP_SYNC | PERIPH_CAP_WIDE16 | PERIPH_CAP_DT)) ||
1.1       bouyer   1700:                    sc->sc_c.targets[xm->xm_target]->status == TARST_PROBING)
1.6       bouyer   1701:                        sc->sc_c.targets[xm->xm_target]->status = TARST_ASYNC;
1.1       bouyer   1702:
                   1703:                splx(s);
                   1704:        }
                   1705:        }
                   1706: }
                   1707:
                   1708: static void
                   1709: esiop_start(sc, esiop_cmd)
                   1710:        struct esiop_softc *sc;
                   1711:        struct esiop_cmd *esiop_cmd;
                   1712: {
                   1713:        struct esiop_lun *esiop_lun;
                   1714:        struct esiop_target *esiop_target;
                   1715:        int timeout;
                   1716:        int target, lun, slot;
                   1717:
                   1718:        /*
                   1719:         * first make sure to read valid data
                   1720:         */
                   1721:        esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1722:
                   1723:        /*
                   1724:         * We use a circular queue here. sc->sc_currschedslot points to a
                   1725:         * free slot, unless we have filled the queue. Check this.
                   1726:         */
                   1727:        slot = sc->sc_currschedslot;
1.8       bouyer   1728:        if ((esiop_script_read(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE) &
1.1       bouyer   1729:            A_f_cmd_free) == 0) {
                   1730:                /*
                   1731:                 * no more free slot, no need to continue. freeze the queue
                   1732:                 * and requeue this command.
                   1733:                 */
                   1734:                scsipi_channel_freeze(&sc->sc_c.sc_chan, 1);
                   1735:                sc->sc_flags |= SCF_CHAN_NOSLOT;
1.12      bouyer   1736:                esiop_script_write(sc, sc->sc_semoffset,
                   1737:                    esiop_script_read(sc, sc->sc_semoffset) & ~A_sem_start);
                   1738:                esiop_script_sync(sc,
1.31      bouyer   1739:                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1.1       bouyer   1740:                esiop_cmd->cmd_c.xs->error = XS_REQUEUE;
                   1741:                esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
1.29      bouyer   1742:                esiop_scsicmd_end(esiop_cmd, 0);
1.1       bouyer   1743:                return;
                   1744:        }
                   1745:        /* OK, we can use this slot */
                   1746:
                   1747:        target = esiop_cmd->cmd_c.xs->xs_periph->periph_target;
                   1748:        lun = esiop_cmd->cmd_c.xs->xs_periph->periph_lun;
                   1749:        esiop_target = (struct esiop_target*)sc->sc_c.targets[target];
                   1750:        esiop_lun = esiop_target->esiop_lun[lun];
                   1751:        /* if non-tagged command active, panic: this shouldn't happen */
                   1752:        if (esiop_lun->active != NULL) {
                   1753:                panic("esiop_start: tagged cmd while untagged running");
                   1754:        }
                   1755: #ifdef DIAGNOSTIC
                   1756:        /* sanity check the tag if needed */
                   1757:        if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
1.2       bouyer   1758:                if (esiop_cmd->cmd_c.tag >= ESIOP_NTAG ||
                   1759:                    esiop_cmd->cmd_c.tag < 0) {
1.1       bouyer   1760:                        scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph);
                   1761:                        printf(": tag id %d\n", esiop_cmd->cmd_c.tag);
                   1762:                        panic("esiop_start: invalid tag id");
                   1763:                }
1.36      christos 1764:                if (esiop_lun->tactive[esiop_cmd->cmd_c.tag] != NULL)
                   1765:                        panic("esiop_start: tag not free");
1.1       bouyer   1766:        }
                   1767: #endif
                   1768: #ifdef SIOP_DEBUG_SCHED
                   1769:        printf("using slot %d for DSA 0x%lx\n", slot,
                   1770:            (u_long)esiop_cmd->cmd_c.dsa);
                   1771: #endif
                   1772:        /* mark command as active */
                   1773:        if (esiop_cmd->cmd_c.status == CMDST_READY)
                   1774:                esiop_cmd->cmd_c.status = CMDST_ACTIVE;
                   1775:        else
                   1776:                panic("esiop_start: bad status");
1.9       bouyer   1777:        /* DSA table for reselect */
1.2       bouyer   1778:        if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
                   1779:                esiop_lun->tactive[esiop_cmd->cmd_c.tag] = esiop_cmd;
                   1780:                /* DSA table for reselect */
1.11      bouyer   1781:                esiop_lun->lun_tagtbl->tbl[esiop_cmd->cmd_c.tag] =
1.2       bouyer   1782:                    htole32(esiop_cmd->cmd_c.dsa);
                   1783:                bus_dmamap_sync(sc->sc_c.sc_dmat,
                   1784:                    esiop_lun->lun_tagtbl->tblblk->blkmap,
                   1785:                    esiop_lun->lun_tagtbl->tbl_offset,
                   1786:                    sizeof(u_int32_t) * ESIOP_NTAG, BUS_DMASYNC_PREWRITE);
                   1787:        } else {
                   1788:                esiop_lun->active = esiop_cmd;
1.9       bouyer   1789:                esiop_script_write(sc,
                   1790:                    esiop_target->lun_table_offset +
                   1791:                    lun * 2 + A_target_luntbl / sizeof(u_int32_t),
1.2       bouyer   1792:                    esiop_cmd->cmd_c.dsa);
                   1793:        }
1.8       bouyer   1794:        /* scheduler slot: DSA */
                   1795:        esiop_script_write(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE,
1.1       bouyer   1796:            esiop_cmd->cmd_c.dsa);
1.9       bouyer   1797:        /* make sure SCRIPT processor will read valid data */
                   1798:        esiop_script_sync(sc, BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);
1.1       bouyer   1799:        /* handle timeout */
                   1800:        if ((esiop_cmd->cmd_c.xs->xs_control & XS_CTL_POLL) == 0) {
                   1801:                /* start exire timer */
                   1802:                timeout = mstohz(esiop_cmd->cmd_c.xs->timeout);
                   1803:                if (timeout == 0)
                   1804:                        timeout = 1;
                   1805:                callout_reset( &esiop_cmd->cmd_c.xs->xs_callout,
                   1806:                    timeout, esiop_timeout, esiop_cmd);
                   1807:        }
                   1808:        /* Signal script it has some work to do */
                   1809:        bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
                   1810:            SIOP_ISTAT, ISTAT_SIGP);
                   1811:        /* update the current slot, and wait for IRQ */
                   1812:        sc->sc_currschedslot++;
                   1813:        if (sc->sc_currschedslot >= A_ncmd_slots)
                   1814:                sc->sc_currschedslot = 0;
                   1815:        return;
                   1816: }
                   1817:
                   1818: void
                   1819: esiop_timeout(v)
                   1820:        void *v;
                   1821: {
                   1822:        struct esiop_cmd *esiop_cmd = v;
                   1823:        struct esiop_softc *sc =
                   1824:            (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
                   1825:        int s;
1.9       bouyer   1826: #ifdef SIOP_DEBUG
                   1827:        int slot, slotdsa;
                   1828: #endif
1.1       bouyer   1829:
1.9       bouyer   1830:        s = splbio();
                   1831:        esiop_table_sync(esiop_cmd,
                   1832:            BUS_DMASYNC_POSTREAD |
                   1833:            BUS_DMASYNC_POSTWRITE);
1.1       bouyer   1834:        scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph);
1.9       bouyer   1835: #ifdef SIOP_DEBUG
                   1836:        printf("command timeout (status %d)\n", le32toh(esiop_cmd->cmd_tables->status));
                   1837:
                   1838:        esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1839:        for (slot = 0; slot < A_ncmd_slots; slot++) {
                   1840:                slotdsa = esiop_script_read(sc,
                   1841:                    sc->sc_shedoffset + slot * CMD_SLOTSIZE);
                   1842:                if ((slotdsa & 0x01) == 0)
                   1843:                        printf("slot %d not free (0x%x)\n", slot, slotdsa);
                   1844:        }
                   1845:        printf("istat 0x%x ", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT));
                   1846:        printf("DSP 0x%lx DSA 0x%x\n",
                   1847:            (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr),
                   1848:            bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
                   1849:        bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_CTEST2);
                   1850:        printf("istat 0x%x\n", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT));
                   1851: #else
1.27      bouyer   1852:        printf("command timeout, CDB: ");
                   1853:        scsipi_print_cdb(esiop_cmd->cmd_c.xs->cmd);
1.26      bouyer   1854:        printf("\n");
1.9       bouyer   1855: #endif
1.1       bouyer   1856:        /* reset the scsi bus */
                   1857:        siop_resetbus(&sc->sc_c);
                   1858:
                   1859:        /* deactivate callout */
                   1860:        callout_stop(&esiop_cmd->cmd_c.xs->xs_callout);
                   1861:        /*
                   1862:         * mark command has being timed out and just return;
                   1863:         * the bus reset will generate an interrupt,
                   1864:         * it will be handled in siop_intr()
                   1865:         */
                   1866:        esiop_cmd->cmd_c.flags |= CMDFL_TIMEOUT;
                   1867:        splx(s);
                   1868:        return;
                   1869:
                   1870: }
                   1871:
                   1872: void
                   1873: esiop_dump_script(sc)
                   1874:        struct esiop_softc *sc;
                   1875: {
                   1876:        int i;
                   1877:        for (i = 0; i < PAGE_SIZE / 4; i += 2) {
                   1878:                printf("0x%04x: 0x%08x 0x%08x", i * 4,
                   1879:                    le32toh(sc->sc_c.sc_script[i]),
                   1880:                    le32toh(sc->sc_c.sc_script[i+1]));
                   1881:                if ((le32toh(sc->sc_c.sc_script[i]) & 0xe0000000) ==
                   1882:                    0xc0000000) {
                   1883:                        i++;
                   1884:                        printf(" 0x%08x", le32toh(sc->sc_c.sc_script[i+1]));
                   1885:                }
                   1886:                printf("\n");
                   1887:        }
                   1888: }
                   1889:
                   1890: void
                   1891: esiop_morecbd(sc)
                   1892:        struct esiop_softc *sc;
                   1893: {
                   1894:        int error, i, s;
                   1895:        bus_dma_segment_t seg;
                   1896:        int rseg;
                   1897:        struct esiop_cbd *newcbd;
                   1898:        struct esiop_xfer *xfer;
                   1899:        bus_addr_t dsa;
                   1900:
                   1901:        /* allocate a new list head */
                   1902:        newcbd = malloc(sizeof(struct esiop_cbd), M_DEVBUF, M_NOWAIT|M_ZERO);
                   1903:        if (newcbd == NULL) {
                   1904:                printf("%s: can't allocate memory for command descriptors "
                   1905:                    "head\n", sc->sc_c.sc_dev.dv_xname);
                   1906:                return;
                   1907:        }
                   1908:
                   1909:        /* allocate cmd list */
                   1910:        newcbd->cmds = malloc(sizeof(struct esiop_cmd) * SIOP_NCMDPB,
                   1911:            M_DEVBUF, M_NOWAIT|M_ZERO);
                   1912:        if (newcbd->cmds == NULL) {
                   1913:                printf("%s: can't allocate memory for command descriptors\n",
                   1914:                    sc->sc_c.sc_dev.dv_xname);
                   1915:                goto bad3;
                   1916:        }
                   1917:        error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
                   1918:            &seg, 1, &rseg, BUS_DMA_NOWAIT);
                   1919:        if (error) {
                   1920:                printf("%s: unable to allocate cbd DMA memory, error = %d\n",
                   1921:                    sc->sc_c.sc_dev.dv_xname, error);
                   1922:                goto bad2;
                   1923:        }
                   1924:        error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
1.39      christos 1925:            (void **)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1.1       bouyer   1926:        if (error) {
                   1927:                printf("%s: unable to map cbd DMA memory, error = %d\n",
                   1928:                    sc->sc_c.sc_dev.dv_xname, error);
                   1929:                goto bad2;
                   1930:        }
                   1931:        error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
                   1932:            BUS_DMA_NOWAIT, &newcbd->xferdma);
                   1933:        if (error) {
                   1934:                printf("%s: unable to create cbd DMA map, error = %d\n",
                   1935:                    sc->sc_c.sc_dev.dv_xname, error);
                   1936:                goto bad1;
                   1937:        }
                   1938:        error = bus_dmamap_load(sc->sc_c.sc_dmat, newcbd->xferdma,
                   1939:            newcbd->xfers, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
                   1940:        if (error) {
                   1941:                printf("%s: unable to load cbd DMA map, error = %d\n",
                   1942:                    sc->sc_c.sc_dev.dv_xname, error);
                   1943:                goto bad0;
                   1944:        }
                   1945: #ifdef DEBUG
                   1946:        printf("%s: alloc newcdb at PHY addr 0x%lx\n", sc->sc_c.sc_dev.dv_xname,
                   1947:            (unsigned long)newcbd->xferdma->dm_segs[0].ds_addr);
                   1948: #endif
                   1949:        for (i = 0; i < SIOP_NCMDPB; i++) {
                   1950:                error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG,
                   1951:                    MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
                   1952:                    &newcbd->cmds[i].cmd_c.dmamap_data);
                   1953:                if (error) {
                   1954:                        printf("%s: unable to create data DMA map for cbd: "
                   1955:                            "error %d\n",
                   1956:                            sc->sc_c.sc_dev.dv_xname, error);
                   1957:                        goto bad0;
                   1958:                }
                   1959:                error = bus_dmamap_create(sc->sc_c.sc_dmat,
                   1960:                    sizeof(struct scsipi_generic), 1,
                   1961:                    sizeof(struct scsipi_generic), 0,
                   1962:                    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
                   1963:                    &newcbd->cmds[i].cmd_c.dmamap_cmd);
                   1964:                if (error) {
                   1965:                        printf("%s: unable to create cmd DMA map for cbd %d\n",
                   1966:                            sc->sc_c.sc_dev.dv_xname, error);
                   1967:                        goto bad0;
                   1968:                }
                   1969:                newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c;
                   1970:                newcbd->cmds[i].esiop_cbdp = newcbd;
                   1971:                xfer = &newcbd->xfers[i];
                   1972:                newcbd->cmds[i].cmd_tables = (struct siop_common_xfer *)xfer;
                   1973:                memset(newcbd->cmds[i].cmd_tables, 0,
                   1974:                    sizeof(struct esiop_xfer));
                   1975:                dsa = newcbd->xferdma->dm_segs[0].ds_addr +
                   1976:                    i * sizeof(struct esiop_xfer);
                   1977:                newcbd->cmds[i].cmd_c.dsa = dsa;
                   1978:                newcbd->cmds[i].cmd_c.status = CMDST_FREE;
                   1979:                xfer->siop_tables.t_msgout.count= htole32(1);
                   1980:                xfer->siop_tables.t_msgout.addr = htole32(dsa);
                   1981:                xfer->siop_tables.t_msgin.count= htole32(1);
1.11      bouyer   1982:                xfer->siop_tables.t_msgin.addr = htole32(dsa +
1.5       bouyer   1983:                        offsetof(struct siop_common_xfer, msg_in));
1.1       bouyer   1984:                xfer->siop_tables.t_extmsgin.count= htole32(2);
1.5       bouyer   1985:                xfer->siop_tables.t_extmsgin.addr = htole32(dsa +
                   1986:                        offsetof(struct siop_common_xfer, msg_in) + 1);
                   1987:                xfer->siop_tables.t_extmsgdata.addr = htole32(dsa +
                   1988:                        offsetof(struct siop_common_xfer, msg_in) + 3);
1.1       bouyer   1989:                xfer->siop_tables.t_status.count= htole32(1);
1.5       bouyer   1990:                xfer->siop_tables.t_status.addr = htole32(dsa +
                   1991:                        offsetof(struct siop_common_xfer, status));
1.1       bouyer   1992:
                   1993:                s = splbio();
                   1994:                TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
                   1995:                splx(s);
                   1996: #ifdef SIOP_DEBUG
1.39      christos 1997:                printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n", i,
1.1       bouyer   1998:                    le32toh(newcbd->cmds[i].cmd_tables->t_msgin.addr),
                   1999:                    le32toh(newcbd->cmds[i].cmd_tables->t_msgout.addr),
1.37      garbled  2000:                    le32toh(newcbd->cmds[i].cmd_tables->t_status.addr));
1.1       bouyer   2001: #endif
                   2002:        }
                   2003:        s = splbio();
                   2004:        TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
                   2005:        sc->sc_c.sc_adapt.adapt_openings += SIOP_NCMDPB;
                   2006:        splx(s);
                   2007:        return;
                   2008: bad0:
                   2009:        bus_dmamap_unload(sc->sc_c.sc_dmat, newcbd->xferdma);
                   2010:        bus_dmamap_destroy(sc->sc_c.sc_dmat, newcbd->xferdma);
                   2011: bad1:
                   2012:        bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
                   2013: bad2:
                   2014:        free(newcbd->cmds, M_DEVBUF);
                   2015: bad3:
                   2016:        free(newcbd, M_DEVBUF);
                   2017:        return;
                   2018: }
                   2019:
                   2020: void
1.2       bouyer   2021: esiop_moretagtbl(sc)
                   2022:        struct esiop_softc *sc;
                   2023: {
                   2024:        int error, i, j, s;
                   2025:        bus_dma_segment_t seg;
                   2026:        int rseg;
                   2027:        struct esiop_dsatblblk *newtblblk;
                   2028:        struct esiop_dsatbl *newtbls;
                   2029:        u_int32_t *tbls;
                   2030:
                   2031:        /* allocate a new list head */
                   2032:        newtblblk = malloc(sizeof(struct esiop_dsatblblk),
                   2033:            M_DEVBUF, M_NOWAIT|M_ZERO);
                   2034:        if (newtblblk == NULL) {
                   2035:                printf("%s: can't allocate memory for tag DSA table block\n",
                   2036:                    sc->sc_c.sc_dev.dv_xname);
                   2037:                return;
                   2038:        }
                   2039:
                   2040:        /* allocate tbl list */
                   2041:        newtbls = malloc(sizeof(struct esiop_dsatbl) * ESIOP_NTPB,
                   2042:            M_DEVBUF, M_NOWAIT|M_ZERO);
                   2043:        if (newtbls == NULL) {
                   2044:                printf("%s: can't allocate memory for command descriptors\n",
                   2045:                    sc->sc_c.sc_dev.dv_xname);
                   2046:                goto bad3;
                   2047:        }
                   2048:        error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
                   2049:            &seg, 1, &rseg, BUS_DMA_NOWAIT);
                   2050:        if (error) {
                   2051:                printf("%s: unable to allocate tbl DMA memory, error = %d\n",
                   2052:                    sc->sc_c.sc_dev.dv_xname, error);
                   2053:                goto bad2;
                   2054:        }
                   2055:        error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
1.20      drochner 2056:            (void *)&tbls, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1.2       bouyer   2057:        if (error) {
                   2058:                printf("%s: unable to map tbls DMA memory, error = %d\n",
                   2059:                    sc->sc_c.sc_dev.dv_xname, error);
                   2060:                goto bad2;
                   2061:        }
                   2062:        error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
                   2063:            BUS_DMA_NOWAIT, &newtblblk->blkmap);
                   2064:        if (error) {
                   2065:                printf("%s: unable to create tbl DMA map, error = %d\n",
                   2066:                    sc->sc_c.sc_dev.dv_xname, error);
                   2067:                goto bad1;
                   2068:        }
                   2069:        error = bus_dmamap_load(sc->sc_c.sc_dmat, newtblblk->blkmap,
                   2070:            tbls, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
                   2071:        if (error) {
                   2072:                printf("%s: unable to load tbl DMA map, error = %d\n",
                   2073:                    sc->sc_c.sc_dev.dv_xname, error);
                   2074:                goto bad0;
                   2075:        }
                   2076: #ifdef DEBUG
                   2077:        printf("%s: alloc new tag DSA table at PHY addr 0x%lx\n",
                   2078:            sc->sc_c.sc_dev.dv_xname,
                   2079:            (unsigned long)newtblblk->blkmap->dm_segs[0].ds_addr);
                   2080: #endif
                   2081:        for (i = 0; i < ESIOP_NTPB; i++) {
                   2082:                newtbls[i].tblblk = newtblblk;
                   2083:                newtbls[i].tbl = &tbls[i * ESIOP_NTAG];
                   2084:                newtbls[i].tbl_offset = i * ESIOP_NTAG * sizeof(u_int32_t);
                   2085:                newtbls[i].tbl_dsa = newtblblk->blkmap->dm_segs[0].ds_addr +
                   2086:                    newtbls[i].tbl_offset;
                   2087:                for (j = 0; j < ESIOP_NTAG; j++)
                   2088:                        newtbls[i].tbl[j] = j;
                   2089:                s = splbio();
                   2090:                TAILQ_INSERT_TAIL(&sc->free_tagtbl, &newtbls[i], next);
                   2091:                splx(s);
                   2092:        }
                   2093:        s = splbio();
                   2094:        TAILQ_INSERT_TAIL(&sc->tag_tblblk, newtblblk, next);
                   2095:        splx(s);
                   2096:        return;
                   2097: bad0:
                   2098:        bus_dmamap_unload(sc->sc_c.sc_dmat, newtblblk->blkmap);
                   2099:        bus_dmamap_destroy(sc->sc_c.sc_dmat, newtblblk->blkmap);
                   2100: bad1:
                   2101:        bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
                   2102: bad2:
                   2103:        free(newtbls, M_DEVBUF);
                   2104: bad3:
                   2105:        free(newtblblk, M_DEVBUF);
                   2106:        return;
1.1       bouyer   2107: }
                   2108:
                   2109: void
1.9       bouyer   2110: esiop_update_scntl3(sc, _siop_target)
                   2111:        struct esiop_softc *sc;
                   2112:        struct siop_common_target *_siop_target;
                   2113: {
                   2114:        struct esiop_target *esiop_target = (struct esiop_target *)_siop_target;
                   2115:        esiop_script_write(sc, esiop_target->lun_table_offset,
                   2116:            esiop_target->target_c.id);
1.13      bouyer   2117:        esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1.9       bouyer   2118: }
                   2119:
                   2120: void
1.1       bouyer   2121: esiop_add_dev(sc, target, lun)
                   2122:        struct esiop_softc *sc;
                   2123:        int target;
                   2124:        int lun;
                   2125: {
                   2126:        struct esiop_target *esiop_target =
                   2127:            (struct esiop_target *)sc->sc_c.targets[target];
                   2128:        struct esiop_lun *esiop_lun = esiop_target->esiop_lun[lun];
1.2       bouyer   2129:
1.33      bouyer   2130:        if (esiop_lun->lun_tagtbl != NULL)
                   2131:                return; /* already allocated */
                   2132:
1.9       bouyer   2133:        /* we need a tag DSA table */
                   2134:        esiop_lun->lun_tagtbl= TAILQ_FIRST(&sc->free_tagtbl);
                   2135:        if (esiop_lun->lun_tagtbl == NULL) {
                   2136:                esiop_moretagtbl(sc);
1.2       bouyer   2137:                esiop_lun->lun_tagtbl= TAILQ_FIRST(&sc->free_tagtbl);
                   2138:                if (esiop_lun->lun_tagtbl == NULL) {
1.9       bouyer   2139:                        /* no resources, run untagged */
                   2140:                        esiop_target->target_c.flags &= ~TARF_TAG;
                   2141:                        return;
1.1       bouyer   2142:                }
                   2143:        }
1.9       bouyer   2144:        TAILQ_REMOVE(&sc->free_tagtbl, esiop_lun->lun_tagtbl, next);
                   2145:        /* Update LUN DSA table */
                   2146:        esiop_script_write(sc, esiop_target->lun_table_offset +
                   2147:           lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t),
                   2148:            esiop_lun->lun_tagtbl->tbl_dsa);
                   2149:        esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1.1       bouyer   2150: }
                   2151:
                   2152: void
                   2153: esiop_del_dev(sc, target, lun)
                   2154:        struct esiop_softc *sc;
                   2155:        int target;
                   2156:        int lun;
                   2157: {
                   2158:        struct esiop_target *esiop_target;
                   2159: #ifdef SIOP_DEBUG
                   2160:                printf("%s:%d:%d: free lun sw entry\n",
                   2161:                    sc->sc_c.sc_dev.dv_xname, target, lun);
                   2162: #endif
                   2163:        if (sc->sc_c.targets[target] == NULL)
                   2164:                return;
                   2165:        esiop_target = (struct esiop_target *)sc->sc_c.targets[target];
                   2166:        free(esiop_target->esiop_lun[lun], M_DEVBUF);
                   2167:        esiop_target->esiop_lun[lun] = NULL;
                   2168: }
                   2169:
                   2170: void
                   2171: esiop_target_register(sc, target)
                   2172:        struct esiop_softc *sc;
                   2173:        u_int32_t target;
                   2174: {
                   2175:        struct esiop_target *esiop_target =
                   2176:            (struct esiop_target *)sc->sc_c.targets[target];
1.9       bouyer   2177:        struct esiop_lun *esiop_lun;
                   2178:        int lun;
1.1       bouyer   2179:
                   2180:        /* get a DSA table for this target */
                   2181:        esiop_target->lun_table_offset = sc->sc_free_offset;
1.9       bouyer   2182:        sc->sc_free_offset += sc->sc_c.sc_chan.chan_nluns * 2 + 2;
1.1       bouyer   2183: #ifdef SIOP_DEBUG
                   2184:        printf("%s: lun table for target %d offset %d free offset %d\n",
                   2185:            sc->sc_c.sc_dev.dv_xname, target, esiop_target->lun_table_offset,
                   2186:            sc->sc_free_offset);
                   2187: #endif
                   2188:        /* first 32 bytes are ID (for select) */
                   2189:        esiop_script_write(sc, esiop_target->lun_table_offset,
                   2190:            esiop_target->target_c.id);
                   2191:        /* Record this table in the target DSA table */
                   2192:        esiop_script_write(sc,
                   2193:            sc->sc_target_table_offset + target,
                   2194:            (esiop_target->lun_table_offset * sizeof(u_int32_t)) +
                   2195:            sc->sc_c.sc_scriptaddr);
1.9       bouyer   2196:        /* if we have a tag table, register it */
                   2197:        for (lun = 0; lun < sc->sc_c.sc_chan.chan_nluns; lun++) {
                   2198:                esiop_lun = esiop_target->esiop_lun[lun];
                   2199:                if (esiop_lun == NULL)
                   2200:                        continue;
                   2201:                if (esiop_lun->lun_tagtbl)
                   2202:                        esiop_script_write(sc, esiop_target->lun_table_offset +
                   2203:                           lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t),
                   2204:                            esiop_lun->lun_tagtbl->tbl_dsa);
                   2205:        }
1.1       bouyer   2206:        esiop_script_sync(sc,
                   2207:            BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);
                   2208: }
                   2209:
                   2210: #ifdef SIOP_STATS
                   2211: void
                   2212: esiop_printstats()
                   2213: {
                   2214:        printf("esiop_stat_intr %d\n", esiop_stat_intr);
                   2215:        printf("esiop_stat_intr_shortxfer %d\n", esiop_stat_intr_shortxfer);
                   2216:        printf("esiop_stat_intr_xferdisc %d\n", esiop_stat_intr_xferdisc);
                   2217:        printf("esiop_stat_intr_sdp %d\n", esiop_stat_intr_sdp);
                   2218:        printf("esiop_stat_intr_done %d\n", esiop_stat_intr_done);
                   2219:        printf("esiop_stat_intr_lunresel %d\n", esiop_stat_intr_lunresel);
                   2220:        printf("esiop_stat_intr_qfull %d\n", esiop_stat_intr_qfull);
                   2221: }
                   2222: #endif

CVSweb <webmaster@jp.NetBSD.org>