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