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