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