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