1 /* $OpenBSD: siop.c,v 1.65 2011/06/23 16:31:16 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); 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); 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 } 638 if (need_reset) { 639 reset: 640 /* fatal error, reset the bus */ 641 siop_resetbus(&sc->sc_c); 642 /* no table to flush here */ 643 return 1; 644 } 645 646 scintr: 647 if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */ 648 irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, 649 SIOP_DSPS); 650 #ifdef SIOP_DEBUG_INTR 651 printf("script interrupt 0x%x\n", irqcode); 652 #endif 653 /* 654 * no command, or an inactive command is only valid for a 655 * reselect interrupt 656 */ 657 if ((irqcode & 0x80) == 0) { 658 if (siop_cmd == NULL) { 659 printf( 660 "%s: script interrupt (0x%x) with invalid DSA !!!\n", 661 sc->sc_c.sc_dev.dv_xname, irqcode); 662 goto reset; 663 } 664 if (siop_cmd->cmd_c.status != CMDST_ACTIVE && 665 siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE) { 666 printf("%s: command with invalid status " 667 "(IRQ code 0x%x current status %d) !\n", 668 sc->sc_c.sc_dev.dv_xname, 669 irqcode, siop_cmd->cmd_c.status); 670 xs = NULL; 671 } 672 } 673 switch(irqcode) { 674 case A_int_err: 675 printf("error, DSP=0x%x\n", 676 (int)(bus_space_read_4(sc->sc_c.sc_rt, 677 sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr)); 678 if (xs) { 679 xs->error = XS_SELTIMEOUT; 680 goto end; 681 } else { 682 goto reset; 683 } 684 case A_int_reseltarg: 685 printf("%s: reselect with invalid target\n", 686 sc->sc_c.sc_dev.dv_xname); 687 goto reset; 688 case A_int_resellun: 689 INCSTAT(siop_stat_intr_lunresel); 690 target = bus_space_read_1(sc->sc_c.sc_rt, 691 sc->sc_c.sc_rh, SIOP_SCRATCHA) & 0xf; 692 lun = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, 693 SIOP_SCRATCHA + 1); 694 tag = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, 695 SIOP_SCRATCHA + 2); 696 siop_target = 697 (struct siop_target *)sc->sc_c.targets[target]; 698 if (siop_target == NULL) { 699 printf("%s: reselect with invalid target %d\n", 700 sc->sc_c.sc_dev.dv_xname, target); 701 goto reset; 702 } 703 siop_lun = siop_target->siop_lun[lun]; 704 if (siop_lun == NULL) { 705 printf("%s: target %d reselect with invalid " 706 "lun %d\n", sc->sc_c.sc_dev.dv_xname, 707 target, lun); 708 goto reset; 709 } 710 if (siop_lun->siop_tag[tag].active == NULL) { 711 printf("%s: target %d lun %d tag %d reselect " 712 "without command\n", 713 sc->sc_c.sc_dev.dv_xname, 714 target, lun, tag); 715 goto reset; 716 } 717 siop_cmd = siop_lun->siop_tag[tag].active; 718 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, 719 SIOP_DSP, siop_cmd->cmd_c.dsa + 720 sizeof(struct siop_common_xfer) + 721 Ent_ldsa_reload_dsa); 722 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE); 723 return 1; 724 case A_int_reseltag: 725 printf("%s: reselect with invalid tag\n", 726 sc->sc_c.sc_dev.dv_xname); 727 goto reset; 728 case A_int_msgin: 729 { 730 int msgin = bus_space_read_1(sc->sc_c.sc_rt, 731 sc->sc_c.sc_rh, SIOP_SFBR); 732 if (msgin == MSG_MESSAGE_REJECT) { 733 int msg, extmsg; 734 if (siop_cmd->cmd_tables->msg_out[0] & 0x80) { 735 /* 736 * message was part of a identify + 737 * something else. Identify shouldn't 738 * have been rejected. 739 */ 740 msg = 741 siop_cmd->cmd_tables->msg_out[1]; 742 extmsg = 743 siop_cmd->cmd_tables->msg_out[3]; 744 } else { 745 msg = siop_cmd->cmd_tables->msg_out[0]; 746 extmsg = 747 siop_cmd->cmd_tables->msg_out[2]; 748 } 749 if (msg == MSG_MESSAGE_REJECT) { 750 /* MSG_REJECT for a MSG_REJECT !*/ 751 if (xs) 752 sc_print_addr(xs->sc_link); 753 else 754 printf("%s: ", 755 sc->sc_c.sc_dev.dv_xname); 756 printf("our reject message was " 757 "rejected\n"); 758 goto reset; 759 } 760 if (msg == MSG_EXTENDED && 761 extmsg == MSG_EXT_WDTR) { 762 /* WDTR rejected, initiate sync */ 763 if ((siop_target->target_c.flags & 764 TARF_SYNC) == 0) { 765 siop_target->target_c.status = 766 TARST_OK; 767 siop_update_xfer_mode(&sc->sc_c, 768 target); 769 /* no table to flush here */ 770 CALL_SCRIPT(Ent_msgin_ack); 771 return 1; 772 } 773 siop_target->target_c.status = 774 TARST_SYNC_NEG; 775 siop_sdtr_msg(&siop_cmd->cmd_c, 0, 776 sc->sc_c.st_minsync, 777 sc->sc_c.maxoff); 778 siop_table_sync(siop_cmd, 779 BUS_DMASYNC_PREREAD | 780 BUS_DMASYNC_PREWRITE); 781 CALL_SCRIPT(Ent_send_msgout); 782 return 1; 783 } else if (msg == MSG_EXTENDED && 784 extmsg == MSG_EXT_SDTR) { 785 /* sync rejected */ 786 siop_target->target_c.offset = 0; 787 siop_target->target_c.period = 0; 788 siop_target->target_c.status = TARST_OK; 789 siop_update_xfer_mode(&sc->sc_c, 790 target); 791 /* no table to flush here */ 792 CALL_SCRIPT(Ent_msgin_ack); 793 return 1; 794 } else if (msg == MSG_EXTENDED && 795 extmsg == MSG_EXT_PPR) { 796 /* PPR negotiation rejected */ 797 siop_target->target_c.offset = 0; 798 siop_target->target_c.period = 0; 799 siop_target->target_c.status = TARST_ASYNC; 800 siop_target->target_c.flags &= ~(TARF_DT | TARF_ISDT); 801 CALL_SCRIPT(Ent_msgin_ack); 802 return 1; 803 } else if (msg == MSG_SIMPLE_Q_TAG || 804 msg == MSG_HEAD_OF_Q_TAG || 805 msg == MSG_ORDERED_Q_TAG) { 806 if (siop_handle_qtag_reject( 807 siop_cmd) == -1) 808 goto reset; 809 CALL_SCRIPT(Ent_msgin_ack); 810 return 1; 811 } 812 if (xs) 813 sc_print_addr(xs->sc_link); 814 else 815 printf("%s: ", 816 sc->sc_c.sc_dev.dv_xname); 817 if (msg == MSG_EXTENDED) { 818 printf("scsi message reject, extended " 819 "message sent was 0x%x\n", extmsg); 820 } else { 821 printf("scsi message reject, message " 822 "sent was 0x%x\n", msg); 823 } 824 /* no table to flush here */ 825 CALL_SCRIPT(Ent_msgin_ack); 826 return 1; 827 } 828 if (msgin == MSG_IGN_WIDE_RESIDUE) { 829 /* use the extmsgdata table to get the second byte */ 830 siop_cmd->cmd_tables->t_extmsgdata.count = 831 siop_htoc32(&sc->sc_c, 1); 832 siop_table_sync(siop_cmd, 833 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 834 CALL_SCRIPT(Ent_get_extmsgdata); 835 return 1; 836 } 837 if (xs) 838 sc_print_addr(xs->sc_link); 839 else 840 printf("%s: ", sc->sc_c.sc_dev.dv_xname); 841 printf("unhandled message 0x%x\n", 842 siop_cmd->cmd_tables->msg_in[0]); 843 siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT; 844 siop_cmd->cmd_tables->t_msgout.count = 845 siop_htoc32(&sc->sc_c, 1); 846 siop_table_sync(siop_cmd, 847 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 848 CALL_SCRIPT(Ent_send_msgout); 849 return 1; 850 } 851 case A_int_extmsgin: 852 #ifdef SIOP_DEBUG_INTR 853 printf("extended message: msg 0x%x len %d\n", 854 siop_cmd->cmd_tables->msg_in[2], 855 siop_cmd->cmd_tables->msg_in[1]); 856 #endif 857 if (siop_cmd->cmd_tables->msg_in[1] > 858 sizeof(siop_cmd->cmd_tables->msg_in) - 2) 859 printf("%s: extended message too big (%d)\n", 860 sc->sc_c.sc_dev.dv_xname, 861 siop_cmd->cmd_tables->msg_in[1]); 862 siop_cmd->cmd_tables->t_extmsgdata.count = 863 siop_htoc32(&sc->sc_c, 864 siop_cmd->cmd_tables->msg_in[1] - 1); 865 siop_table_sync(siop_cmd, 866 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 867 CALL_SCRIPT(Ent_get_extmsgdata); 868 return 1; 869 case A_int_extmsgdata: 870 #ifdef SIOP_DEBUG_INTR 871 { 872 int i; 873 printf("extended message: 0x%x, data:", 874 siop_cmd->cmd_tables->msg_in[2]); 875 for (i = 3; i < 2 + siop_cmd->cmd_tables->msg_in[1]; 876 i++) 877 printf(" 0x%x", 878 siop_cmd->cmd_tables->msg_in[i]); 879 printf("\n"); 880 } 881 #endif 882 if (siop_cmd->cmd_tables->msg_in[0] == 883 MSG_IGN_WIDE_RESIDUE) { 884 /* we got the second byte of MSG_IGN_WIDE_RESIDUE */ 885 if (siop_cmd->cmd_tables->msg_in[3] != 1) 886 printf("MSG_IGN_WIDE_RESIDUE: " 887 "bad len %d\n", 888 siop_cmd->cmd_tables->msg_in[3]); 889 switch (siop_iwr(&siop_cmd->cmd_c)) { 890 case SIOP_NEG_MSGOUT: 891 siop_table_sync(siop_cmd, 892 BUS_DMASYNC_PREREAD | 893 BUS_DMASYNC_PREWRITE); 894 CALL_SCRIPT(Ent_send_msgout); 895 return(1); 896 case SIOP_NEG_ACK: 897 CALL_SCRIPT(Ent_msgin_ack); 898 return(1); 899 default: 900 panic("invalid retval from " 901 "siop_iwr()"); 902 } 903 return(1); 904 } 905 if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) { 906 switch (siop_wdtr_neg(&siop_cmd->cmd_c)) { 907 case SIOP_NEG_MSGOUT: 908 siop_update_scntl3(sc, 909 siop_cmd->cmd_c.siop_target); 910 siop_table_sync(siop_cmd, 911 BUS_DMASYNC_PREREAD | 912 BUS_DMASYNC_PREWRITE); 913 CALL_SCRIPT(Ent_send_msgout); 914 return(1); 915 case SIOP_NEG_ACK: 916 siop_update_scntl3(sc, 917 siop_cmd->cmd_c.siop_target); 918 CALL_SCRIPT(Ent_msgin_ack); 919 return(1); 920 default: 921 panic("invalid retval from " 922 "siop_wdtr_neg()"); 923 } 924 return(1); 925 } 926 if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) { 927 switch (siop_sdtr_neg(&siop_cmd->cmd_c)) { 928 case SIOP_NEG_MSGOUT: 929 siop_update_scntl3(sc, 930 siop_cmd->cmd_c.siop_target); 931 siop_table_sync(siop_cmd, 932 BUS_DMASYNC_PREREAD | 933 BUS_DMASYNC_PREWRITE); 934 CALL_SCRIPT(Ent_send_msgout); 935 return(1); 936 case SIOP_NEG_ACK: 937 siop_update_scntl3(sc, 938 siop_cmd->cmd_c.siop_target); 939 CALL_SCRIPT(Ent_msgin_ack); 940 return(1); 941 default: 942 panic("invalid retval from " 943 "siop_sdtr_neg()"); 944 } 945 return(1); 946 } 947 if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) { 948 switch (siop_ppr_neg(&siop_cmd->cmd_c)) { 949 case SIOP_NEG_MSGOUT: 950 siop_update_scntl3(sc, 951 siop_cmd->cmd_c.siop_target); 952 siop_table_sync(siop_cmd, 953 BUS_DMASYNC_PREREAD | 954 BUS_DMASYNC_PREWRITE); 955 CALL_SCRIPT(Ent_send_msgout); 956 return(1); 957 case SIOP_NEG_ACK: 958 siop_update_scntl3(sc, 959 siop_cmd->cmd_c.siop_target); 960 CALL_SCRIPT(Ent_msgin_ack); 961 return(1); 962 default: 963 panic("invalid retval from " 964 "siop_wdtr_neg()"); 965 } 966 return(1); 967 } 968 /* send a message reject */ 969 siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT; 970 siop_cmd->cmd_tables->t_msgout.count = 971 siop_htoc32(&sc->sc_c, 1); 972 siop_table_sync(siop_cmd, 973 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 974 CALL_SCRIPT(Ent_send_msgout); 975 return 1; 976 case A_int_disc: 977 INCSTAT(siop_stat_intr_sdp); 978 offset = bus_space_read_1(sc->sc_c.sc_rt, 979 sc->sc_c.sc_rh, SIOP_SCRATCHA + 1); 980 #ifdef SIOP_DEBUG_DR 981 printf("disconnect offset %d\n", offset); 982 #endif 983 siop_sdp(&siop_cmd->cmd_c, offset); 984 /* we start again with no offset */ 985 siop_cmd->saved_offset = SIOP_NOOFFSET; 986 siop_table_sync(siop_cmd, 987 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 988 CALL_SCRIPT(Ent_script_sched); 989 return 1; 990 case A_int_saveoffset: 991 INCSTAT(siop_stat_intr_saveoffset); 992 offset = bus_space_read_1(sc->sc_c.sc_rt, 993 sc->sc_c.sc_rh, SIOP_SCRATCHA + 1); 994 #ifdef SIOP_DEBUG_DR 995 printf("saveoffset offset %d\n", offset); 996 #endif 997 siop_cmd->saved_offset = offset; 998 CALL_SCRIPT(Ent_script_sched); 999 return 1; 1000 case A_int_resfail: 1001 printf("reselect failed\n"); 1002 /* check if we can put some command in scheduler */ 1003 siop_start(sc); 1004 CALL_SCRIPT(Ent_script_sched); 1005 return 1; 1006 case A_int_done: 1007 if (xs == NULL) { 1008 printf("%s: done without command, DSA=0x%lx\n", 1009 sc->sc_c.sc_dev.dv_xname, 1010 (u_long)siop_cmd->cmd_c.dsa); 1011 siop_cmd->cmd_c.status = CMDST_FREE; 1012 siop_start(sc); 1013 CALL_SCRIPT(Ent_script_sched); 1014 return 1; 1015 } 1016 #ifdef SIOP_DEBUG_INTR 1017 printf("done, DSA=0x%lx target id 0x%x last msg " 1018 "in=0x%x status=0x%x\n", (u_long)siop_cmd->cmd_c.dsa, 1019 siop_ctoh32(&sc->sc_c, siop_cmd->cmd_tables->id), 1020 siop_cmd->cmd_tables->msg_in[0], 1021 siop_ctoh32(&sc->sc_c, 1022 siop_cmd->cmd_tables->status)); 1023 #endif 1024 INCSTAT(siop_stat_intr_done); 1025 /* update resid. */ 1026 offset = bus_space_read_1(sc->sc_c.sc_rt, 1027 sc->sc_c.sc_rh, SIOP_SCRATCHA + 1); 1028 /* 1029 * if we got a disconnect between the last data phase 1030 * and the status phase, offset will be 0. In this 1031 * case, siop_cmd->saved_offset will have the proper 1032 * value if it got updated by the controller 1033 */ 1034 if (offset == 0 && 1035 siop_cmd->saved_offset != SIOP_NOOFFSET) 1036 offset = siop_cmd->saved_offset; 1037 siop_update_resid(&siop_cmd->cmd_c, offset); 1038 if (siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE) 1039 siop_cmd->cmd_c.status = CMDST_SENSE_DONE; 1040 else 1041 siop_cmd->cmd_c.status = CMDST_DONE; 1042 goto end; 1043 default: 1044 printf("unknown irqcode %x\n", irqcode); 1045 if (xs) { 1046 xs->error = XS_SELTIMEOUT; 1047 goto end; 1048 } 1049 goto reset; 1050 } 1051 return 1; 1052 } 1053 /* We can get here if ISTAT_DIP and DSTAT_DFE are the only bits set. */ 1054 /* But that *SHOULDN'T* happen. It does on powerpc (at least). */ 1055 printf("%s: siop_intr() - we should not be here!\n" 1056 " istat = 0x%x, dstat = 0x%x, sist = 0x%x, sstat1 = 0x%x\n" 1057 " need_reset = %x, irqcode = %x, siop_cmd %s\n", 1058 sc->sc_c.sc_dev.dv_xname, 1059 istat, dstat, sist, sstat1, need_reset, irqcode, 1060 (siop_cmd == NULL) ? "== NULL" : "!= NULL"); 1061 goto reset; /* Where we should have gone in the first place! */ 1062 end: 1063 /* 1064 * restart the script now if command completed properly 1065 * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the 1066 * queue 1067 */ 1068 xs->status = siop_ctoh32(&sc->sc_c, siop_cmd->cmd_tables->status); 1069 if (xs->status == SCSI_OK) 1070 CALL_SCRIPT(Ent_script_sched); 1071 else 1072 restart = 1; 1073 siop_lun->siop_tag[tag].active = NULL; 1074 siop_scsicmd_end(siop_cmd); 1075 siop_start(sc); 1076 if (restart) 1077 CALL_SCRIPT(Ent_script_sched); 1078 return 1; 1079 } 1080 1081 void 1082 siop_scsicmd_end(siop_cmd) 1083 struct siop_cmd *siop_cmd; 1084 { 1085 struct scsi_xfer *xs = siop_cmd->cmd_c.xs; 1086 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc; 1087 struct siop_lun *siop_lun = 1088 ((struct siop_target*)sc->sc_c.targets[xs->sc_link->target])->siop_lun[xs->sc_link->lun]; 1089 1090 /* 1091 * If the command is re-queued (SENSE, QUEUE_FULL) it 1092 * must get a new timeout, so delete existing timeout now. 1093 */ 1094 timeout_del(&siop_cmd->cmd_c.xs->stimeout); 1095 1096 switch(xs->status) { 1097 case SCSI_OK: 1098 xs->error = (siop_cmd->cmd_c.status == CMDST_DONE) ? 1099 XS_NOERROR : XS_SENSE; 1100 break; 1101 case SCSI_BUSY: 1102 xs->error = XS_BUSY; 1103 break; 1104 case SCSI_CHECK: 1105 if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) { 1106 /* request sense on a request sense ? */ 1107 printf("%s: request sense failed\n", 1108 sc->sc_c.sc_dev.dv_xname); 1109 xs->error = XS_DRIVER_STUFFUP; 1110 } else { 1111 siop_cmd->cmd_c.status = CMDST_SENSE; 1112 } 1113 break; 1114 case SCSI_QUEUE_FULL: 1115 /* 1116 * Device didn't queue the command. We have to retry 1117 * it. We insert it into the urgent list, hoping to 1118 * preserve order. But unfortunately, commands already 1119 * in the scheduler may be accepted before this one. 1120 * Also remember the condition, to avoid starting new 1121 * commands for this device before one is done. 1122 */ 1123 INCSTAT(siop_stat_intr_qfull); 1124 #ifdef SIOP_DEBUG 1125 printf("%s:%d:%d: queue full (tag %d)\n", sc->sc_c.sc_dev.dv_xname, 1126 xs->sc_link->target, 1127 xs->sc_link->lun, siop_cmd->cmd_c.tag); 1128 #endif 1129 siop_lun->lun_flags |= SIOP_LUNF_FULL; 1130 siop_cmd->cmd_c.status = CMDST_READY; 1131 siop_setuptables(&siop_cmd->cmd_c); 1132 siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1133 TAILQ_INSERT_TAIL(&sc->urgent_list, siop_cmd, next); 1134 return; 1135 case SCSI_SIOP_NOCHECK: 1136 /* 1137 * don't check status, xs->error is already valid 1138 */ 1139 break; 1140 case SCSI_SIOP_NOSTATUS: 1141 /* 1142 * the status byte was not updated, cmd was 1143 * aborted 1144 */ 1145 xs->error = XS_SELTIMEOUT; 1146 break; 1147 default: 1148 xs->error = XS_DRIVER_STUFFUP; 1149 } 1150 if (siop_cmd->cmd_c.status != CMDST_SENSE_DONE && 1151 xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { 1152 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data, 0, 1153 siop_cmd->cmd_c.dmamap_data->dm_mapsize, 1154 (xs->flags & SCSI_DATA_IN) ? 1155 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 1156 bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data); 1157 } 1158 if (siop_cmd->cmd_c.status == CMDST_SENSE) { 1159 /* issue a request sense for this target */ 1160 struct scsi_sense *cmd = (struct scsi_sense *)&siop_cmd->cmd_c.siop_tables->xscmd; 1161 int error; 1162 bzero(cmd, sizeof(*cmd)); 1163 siop_cmd->cmd_c.siop_tables->cmd.count = 1164 siop_htoc32(&sc->sc_c, sizeof(struct scsi_sense)); 1165 cmd->opcode = REQUEST_SENSE; 1166 cmd->byte2 = xs->sc_link->lun << 5; 1167 cmd->unused[0] = cmd->unused[1] = 0; 1168 cmd->length = sizeof(struct scsi_sense_data); 1169 cmd->control = 0; 1170 siop_cmd->cmd_c.flags &= ~CMDFL_TAG; 1171 error = bus_dmamap_load(sc->sc_c.sc_dmat, 1172 siop_cmd->cmd_c.dmamap_data, 1173 siop_cmd->cmd_c.sense, sizeof(struct scsi_sense_data), 1174 NULL, BUS_DMA_NOWAIT); 1175 if (error) { 1176 printf("%s: unable to load data DMA map " 1177 "(for SENSE): %d\n", 1178 sc->sc_c.sc_dev.dv_xname, error); 1179 xs->error = XS_DRIVER_STUFFUP; 1180 goto out; 1181 } 1182 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data, 1183 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize, 1184 BUS_DMASYNC_PREREAD); 1185 1186 siop_setuptables(&siop_cmd->cmd_c); 1187 siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1188 /* arrange for the cmd to be handled now */ 1189 TAILQ_INSERT_HEAD(&sc->urgent_list, siop_cmd, next); 1190 return; 1191 } else if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) { 1192 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data, 1193 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize, 1194 BUS_DMASYNC_POSTREAD); 1195 bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data); 1196 bcopy(siop_cmd->cmd_c.sense, &xs->sense, sizeof(xs->sense)); 1197 } 1198 out: 1199 siop_lun->lun_flags &= ~SIOP_LUNF_FULL; 1200 #if 0 1201 if (xs->resid != 0) 1202 printf("resid %d datalen %d\n", xs->resid, xs->datalen); 1203 #endif 1204 scsi_done(xs); 1205 } 1206 1207 /* 1208 * handle a rejected queue tag message: the command will run untagged, 1209 * has to adjust the reselect script. 1210 */ 1211 int 1212 siop_handle_qtag_reject(siop_cmd) 1213 struct siop_cmd *siop_cmd; 1214 { 1215 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc; 1216 int target = siop_cmd->cmd_c.xs->sc_link->target; 1217 int lun = siop_cmd->cmd_c.xs->sc_link->lun; 1218 int tag = siop_cmd->cmd_tables->msg_out[2]; 1219 struct siop_lun *siop_lun = 1220 ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun]; 1221 1222 #ifdef SIOP_DEBUG 1223 printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n", 1224 sc->sc_c.sc_dev.dv_xname, target, lun, tag, siop_cmd->cmd_c.tag, 1225 siop_cmd->cmd_c.status); 1226 #endif 1227 1228 if (siop_lun->siop_tag[0].active != NULL) { 1229 printf("%s: untagged command already running for target %d " 1230 "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname, 1231 target, lun, siop_lun->siop_tag[0].active->cmd_c.status); 1232 return -1; 1233 } 1234 /* clear tag slot */ 1235 siop_lun->siop_tag[tag].active = NULL; 1236 /* add command to non-tagged slot */ 1237 siop_lun->siop_tag[0].active = siop_cmd; 1238 siop_cmd->cmd_c.tag = 0; 1239 /* adjust reselect script if there is one */ 1240 if (siop_lun->siop_tag[0].reseloff > 0) { 1241 siop_script_write(sc, 1242 siop_lun->siop_tag[0].reseloff + 1, 1243 siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) + 1244 Ent_ldsa_reload_dsa); 1245 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE); 1246 } 1247 return 0; 1248 } 1249 1250 /* 1251 * handle a bus reset: reset chip, unqueue all active commands, free all 1252 * target struct and report lossage to upper layer. 1253 * As the upper layer may requeue immediately we have to first store 1254 * all active commands in a temporary queue. 1255 */ 1256 void 1257 siop_handle_reset(sc) 1258 struct siop_softc *sc; 1259 { 1260 struct cmd_list reset_list; 1261 struct siop_cmd *siop_cmd, *next_siop_cmd; 1262 struct siop_lun *siop_lun; 1263 int target, lun, tag; 1264 /* 1265 * scsi bus reset. reset the chip and restart 1266 * the queue. Need to clean up all active commands 1267 */ 1268 printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname); 1269 /* stop, reset and restart the chip */ 1270 siop_reset(sc); 1271 TAILQ_INIT(&reset_list); 1272 /* 1273 * Process all commands: first commands being executed 1274 */ 1275 for (target = 0; target < sc->sc_c.sc_link.adapter_buswidth; 1276 target++) { 1277 if (sc->sc_c.targets[target] == NULL) 1278 continue; 1279 for (lun = 0; lun < 8; lun++) { 1280 struct siop_target *siop_target = 1281 (struct siop_target *)sc->sc_c.targets[target]; 1282 siop_lun = siop_target->siop_lun[lun]; 1283 if (siop_lun == NULL) 1284 continue; 1285 siop_lun->lun_flags &= ~SIOP_LUNF_FULL; 1286 for (tag = 0; tag < 1287 ((sc->sc_c.targets[target]->flags & TARF_TAG) ? 1288 SIOP_NTAG : 1); 1289 tag++) { 1290 siop_cmd = siop_lun->siop_tag[tag].active; 1291 if (siop_cmd == NULL) 1292 continue; 1293 siop_lun->siop_tag[tag].active = NULL; 1294 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next); 1295 sc_print_addr(siop_cmd->cmd_c.xs->sc_link); 1296 printf("cmd %p (tag %d) added to reset list\n", 1297 siop_cmd, tag); 1298 } 1299 } 1300 if (sc->sc_c.targets[target]->status != TARST_PROBING) { 1301 sc->sc_c.targets[target]->status = TARST_ASYNC; 1302 sc->sc_c.targets[target]->flags &= ~TARF_ISWIDE; 1303 sc->sc_c.targets[target]->period = 1304 sc->sc_c.targets[target]->offset = 0; 1305 siop_update_xfer_mode(&sc->sc_c, target); 1306 } 1307 } 1308 /* Next commands from the urgent list */ 1309 for (siop_cmd = TAILQ_FIRST(&sc->urgent_list); siop_cmd != NULL; 1310 siop_cmd = next_siop_cmd) { 1311 next_siop_cmd = TAILQ_NEXT(siop_cmd, next); 1312 TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next); 1313 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next); 1314 sc_print_addr(siop_cmd->cmd_c.xs->sc_link); 1315 printf("cmd %p added to reset list from urgent list\n", 1316 siop_cmd); 1317 } 1318 /* Then commands waiting in the input list. */ 1319 for (siop_cmd = TAILQ_FIRST(&sc->ready_list); siop_cmd != NULL; 1320 siop_cmd = next_siop_cmd) { 1321 next_siop_cmd = TAILQ_NEXT(siop_cmd, next); 1322 TAILQ_REMOVE(&sc->ready_list, siop_cmd, next); 1323 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next); 1324 sc_print_addr(siop_cmd->cmd_c.xs->sc_link); 1325 printf("cmd %p added to reset list from ready list\n", 1326 siop_cmd); 1327 } 1328 1329 for (siop_cmd = TAILQ_FIRST(&reset_list); siop_cmd != NULL; 1330 siop_cmd = next_siop_cmd) { 1331 next_siop_cmd = TAILQ_NEXT(siop_cmd, next); 1332 siop_cmd->cmd_c.flags &= ~CMDFL_TAG; 1333 siop_cmd->cmd_c.xs->error = 1334 (siop_cmd->cmd_c.flags & CMDFL_TIMEOUT) 1335 ? XS_TIMEOUT : XS_RESET; 1336 siop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK; 1337 sc_print_addr(siop_cmd->cmd_c.xs->sc_link); 1338 printf("cmd %p (status %d) reset", 1339 siop_cmd, siop_cmd->cmd_c.status); 1340 if (siop_cmd->cmd_c.status == CMDST_SENSE || 1341 siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE) 1342 siop_cmd->cmd_c.status = CMDST_SENSE_DONE; 1343 else 1344 siop_cmd->cmd_c.status = CMDST_DONE; 1345 printf(" with status %d, xs->error %d\n", 1346 siop_cmd->cmd_c.status, siop_cmd->cmd_c.xs->error); 1347 TAILQ_REMOVE(&reset_list, siop_cmd, next); 1348 siop_scsicmd_end(siop_cmd); 1349 } 1350 } 1351 1352 void * 1353 siop_cmd_get(void *cookie) 1354 { 1355 struct siop_softc *sc = cookie; 1356 struct siop_cmd *siop_cmd; 1357 int s; 1358 1359 /* Look if a ccb is available. */ 1360 s = splbio(); 1361 siop_cmd = TAILQ_FIRST(&sc->free_list); 1362 if (siop_cmd != NULL) { 1363 TAILQ_REMOVE(&sc->free_list, siop_cmd, next); 1364 #ifdef DIAGNOSTIC 1365 if (siop_cmd->cmd_c.status != CMDST_FREE) 1366 panic("siop_scsicmd: new cmd not free"); 1367 #endif 1368 siop_cmd->cmd_c.status = CMDST_READY; 1369 } 1370 splx(s); 1371 1372 return (siop_cmd); 1373 } 1374 1375 void 1376 siop_cmd_put(void *cookie, void *io) 1377 { 1378 struct siop_softc *sc = cookie; 1379 struct siop_cmd *siop_cmd = io; 1380 int s; 1381 1382 s = splbio(); 1383 siop_cmd->cmd_c.status = CMDST_FREE; 1384 TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next); 1385 splx(s); 1386 } 1387 1388 int 1389 siop_scsiprobe(struct scsi_link *link) 1390 { 1391 struct siop_softc *sc = (struct siop_softc *)link->adapter_softc; 1392 struct siop_target *siop_target; 1393 const int target = link->target; 1394 const int lun = link->lun; 1395 int i; 1396 1397 #ifdef SIOP_DEBUG 1398 printf("%s:%d:%d: probe\n", 1399 sc->sc_c.sc_dev.dv_xname, target, lun); 1400 #endif 1401 1402 /* XXX locking */ 1403 1404 siop_target = (struct siop_target*)sc->sc_c.targets[target]; 1405 if (siop_target == NULL) { 1406 siop_target = malloc(sizeof(*siop_target), M_DEVBUF, 1407 M_WAITOK | M_CANFAIL | M_ZERO); 1408 if (siop_target == NULL) { 1409 printf("%s: can't malloc memory for target %d\n", 1410 sc->sc_c.sc_dev.dv_xname, target); 1411 return (ENOMEM); 1412 } 1413 1414 siop_target->target_c.status = TARST_PROBING; 1415 siop_target->target_c.flags = 0; 1416 siop_target->target_c.id = 1417 sc->sc_c.clock_div << 24; /* scntl3 */ 1418 siop_target->target_c.id |= target << 16; /* id */ 1419 /* siop_target->target_c.id |= 0x0 << 8; scxfer is 0 */ 1420 1421 /* get a lun switch script */ 1422 siop_target->lunsw = siop_get_lunsw(sc); 1423 if (siop_target->lunsw == NULL) { 1424 printf("%s: can't alloc lunsw for target %d\n", 1425 sc->sc_c.sc_dev.dv_xname, target); 1426 free(siop_target, M_DEVBUF); 1427 return (ENOMEM); 1428 } 1429 for (i = 0; i < 8; i++) 1430 siop_target->siop_lun[i] = NULL; 1431 1432 sc->sc_c.targets[target] = 1433 (struct siop_common_target *)siop_target; 1434 1435 siop_add_reselsw(sc, target); 1436 } 1437 1438 if (siop_target->siop_lun[lun] == NULL) { 1439 siop_target->siop_lun[lun] = 1440 malloc(sizeof(struct siop_lun), M_DEVBUF, 1441 M_WAITOK | M_CANFAIL | M_ZERO); 1442 if (siop_target->siop_lun[lun] == NULL) { 1443 printf("%s: can't alloc siop_lun for " 1444 "target %d lun %d\n", 1445 sc->sc_c.sc_dev.dv_xname, target, lun); 1446 return (ENOMEM); 1447 } 1448 } 1449 1450 return (0); 1451 } 1452 1453 void 1454 siop_scsicmd(xs) 1455 struct scsi_xfer *xs; 1456 { 1457 struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc; 1458 struct siop_cmd *siop_cmd; 1459 struct siop_target *siop_target; 1460 int s, error, i, j; 1461 const int target = xs->sc_link->target; 1462 const int lun = xs->sc_link->lun; 1463 1464 #ifdef SIOP_DEBUG_SCHED 1465 printf("starting cmd for %d:%d\n", target, lun); 1466 #endif 1467 1468 siop_target = (struct siop_target*)sc->sc_c.targets[target]; 1469 siop_cmd = xs->io; 1470 1471 /* 1472 * The xs may have been restarted by the scsi layer, so ensure the ccb 1473 * starts in the proper state. 1474 */ 1475 siop_cmd->cmd_c.status = CMDST_READY; 1476 1477 /* Always reset xs->stimeout, lest we timeout_del() with trash */ 1478 timeout_set(&xs->stimeout, siop_timeout, siop_cmd); 1479 1480 siop_cmd->cmd_c.siop_target = sc->sc_c.targets[target]; 1481 siop_cmd->cmd_c.xs = xs; 1482 siop_cmd->cmd_c.flags = 0; 1483 1484 bzero(&siop_cmd->cmd_c.siop_tables->xscmd, 1485 sizeof(siop_cmd->cmd_c.siop_tables->xscmd)); 1486 bcopy(xs->cmd, &siop_cmd->cmd_c.siop_tables->xscmd, xs->cmdlen); 1487 siop_cmd->cmd_c.siop_tables->cmd.count = 1488 siop_htoc32(&sc->sc_c, xs->cmdlen); 1489 1490 /* load the DMA maps */ 1491 if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { 1492 error = bus_dmamap_load(sc->sc_c.sc_dmat, 1493 siop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen, 1494 NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING | 1495 ((xs->flags & SCSI_DATA_IN) ? 1496 BUS_DMA_READ : BUS_DMA_WRITE)); 1497 if (error) { 1498 printf("%s: unable to load data DMA map: %d\n", 1499 sc->sc_c.sc_dev.dv_xname, error); 1500 xs->error = XS_DRIVER_STUFFUP; 1501 scsi_done(xs); 1502 return; 1503 } 1504 bus_dmamap_sync(sc->sc_c.sc_dmat, 1505 siop_cmd->cmd_c.dmamap_data, 0, 1506 siop_cmd->cmd_c.dmamap_data->dm_mapsize, 1507 (xs->flags & SCSI_DATA_IN) ? 1508 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 1509 } 1510 1511 siop_setuptables(&siop_cmd->cmd_c); 1512 siop_cmd->saved_offset = SIOP_NOOFFSET; 1513 siop_table_sync(siop_cmd, 1514 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1515 1516 /* Negotiate transfer parameters on first non-polling command. */ 1517 if (((xs->flags & SCSI_POLL) == 0) && 1518 siop_target->target_c.status == TARST_PROBING) 1519 siop_target->target_c.status = TARST_ASYNC; 1520 1521 s = splbio(); 1522 TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next); 1523 siop_start(sc); 1524 if ((xs->flags & SCSI_POLL) == 0) { 1525 splx(s); 1526 return; 1527 } 1528 1529 /* Poll for command completion. */ 1530 for(i = xs->timeout; i > 0; i--) { 1531 siop_intr(sc); 1532 if ((xs->flags & ITSDONE) == 0) { 1533 delay(1000); 1534 continue; 1535 } 1536 if (xs->cmd->opcode == INQUIRY && xs->error == XS_NOERROR) { 1537 struct scsi_inquiry_data *inqbuf = 1538 (struct scsi_inquiry_data *)xs->data; 1539 if ((inqbuf->device & SID_QUAL) == SID_QUAL_BAD_LU) 1540 break; 1541 /* 1542 * Allocate cbd's to hold maximum openings worth of 1543 * commands. Do this now because doing it dynamically in 1544 * siop_startcmd may cause calls to bus_dma* functions 1545 * in interrupt context. 1546 */ 1547 for (j = 0; j < SIOP_NTAG; j += SIOP_NCMDPB) 1548 siop_morecbd(sc); 1549 1550 /* 1551 * Set TARF_DT here because if it is turned off during 1552 * PPR, it must STAY off! 1553 */ 1554 if ((lun == 0) && (sc->sc_c.features & SF_BUS_ULTRA3)) 1555 sc->sc_c.targets[target]->flags |= TARF_DT; 1556 /* 1557 * Can't do lun 0 here, because flags are not set yet. 1558 * But have to do other lun's here because they never go 1559 * through TARST_ASYNC. 1560 */ 1561 if (lun > 0) 1562 siop_add_dev(sc, target, lun); 1563 } 1564 break; 1565 } 1566 if (i == 0) { 1567 siop_timeout(siop_cmd); 1568 while ((xs->flags & ITSDONE) == 0) 1569 siop_intr(sc); 1570 } 1571 1572 splx(s); 1573 } 1574 1575 void 1576 siop_start(sc) 1577 struct siop_softc *sc; 1578 { 1579 struct siop_cmd *siop_cmd, *next_siop_cmd; 1580 struct siop_lun *siop_lun; 1581 struct siop_xfer *siop_xfer; 1582 u_int32_t dsa; 1583 int target, lun, tag, slot; 1584 int newcmd = 0; 1585 int doingready = 0; 1586 1587 /* 1588 * first make sure to read valid data 1589 */ 1590 siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1591 1592 /* 1593 * The queue management here is a bit tricky: the script always looks 1594 * at the slot from first to last, so if we always use the first 1595 * free slot commands can stay at the tail of the queue ~forever. 1596 * The algorithm used here is to restart from the head when we know 1597 * that the queue is empty, and only add commands after the last one. 1598 * When we're at the end of the queue wait for the script to clear it. 1599 * The best thing to do here would be to implement a circular queue, 1600 * but using only 53c720 features this can be "interesting". 1601 * A mid-way solution could be to implement 2 queues and swap orders. 1602 */ 1603 slot = sc->sc_currschedslot; 1604 /* 1605 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is 1606 * free. As this is the last used slot, all previous slots are free, 1607 * we can restart from 1. 1608 * slot 0 is reserved for request sense commands. 1609 */ 1610 if (siop_script_read(sc, (Ent_script_sched_slot0 / 4) + slot * 2) == 1611 0x80000000) { 1612 slot = sc->sc_currschedslot = 1; 1613 } else { 1614 slot++; 1615 } 1616 /* first handle commands from the urgent list */ 1617 siop_cmd = TAILQ_FIRST(&sc->urgent_list); 1618 again: 1619 for (; siop_cmd != NULL; siop_cmd = next_siop_cmd) { 1620 next_siop_cmd = TAILQ_NEXT(siop_cmd, next); 1621 #ifdef DIAGNOSTIC 1622 if (siop_cmd->cmd_c.status != CMDST_READY && 1623 siop_cmd->cmd_c.status != CMDST_SENSE) 1624 panic("siop: non-ready cmd in ready list"); 1625 #endif 1626 target = siop_cmd->cmd_c.xs->sc_link->target; 1627 lun = siop_cmd->cmd_c.xs->sc_link->lun; 1628 siop_lun = 1629 ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun]; 1630 /* if non-tagged command active, wait */ 1631 if (siop_lun->siop_tag[0].active != NULL) 1632 continue; 1633 /* 1634 * if we're in a queue full condition don't start a new 1635 * command, unless it's a request sense 1636 */ 1637 if ((siop_lun->lun_flags & SIOP_LUNF_FULL) && 1638 siop_cmd->cmd_c.status == CMDST_READY) 1639 continue; 1640 /* find a free tag if needed */ 1641 if (siop_cmd->cmd_c.flags & CMDFL_TAG) { 1642 for (tag = 1; tag < SIOP_NTAG; tag++) { 1643 if (siop_lun->siop_tag[tag].active == NULL) 1644 break; 1645 } 1646 if (tag == SIOP_NTAG) /* no free tag */ 1647 continue; 1648 } else { 1649 tag = 0; 1650 } 1651 siop_cmd->cmd_c.tag = tag; 1652 /* 1653 * find a free scheduler slot and load it. If it's a request 1654 * sense we need to use slot 0. 1655 */ 1656 if (siop_cmd->cmd_c.status != CMDST_SENSE) { 1657 for (; slot < SIOP_NSLOTS; slot++) { 1658 /* 1659 * If cmd if 0x80000000 the slot is free 1660 */ 1661 if (siop_script_read(sc, 1662 (Ent_script_sched_slot0 / 4) + slot * 2) == 1663 0x80000000) 1664 break; 1665 } 1666 /* no more free slots, no need to continue */ 1667 if (slot == SIOP_NSLOTS) { 1668 goto end; 1669 } 1670 } else { 1671 slot = 0; 1672 if (siop_script_read(sc, Ent_script_sched_slot0 / 4) 1673 != 0x80000000) 1674 goto end; 1675 } 1676 1677 #ifdef SIOP_DEBUG_SCHED 1678 printf("using slot %d for DSA 0x%lx\n", slot, 1679 (u_long)siop_cmd->cmd_c.dsa); 1680 #endif 1681 /* Ok, we can add the tag message */ 1682 if (tag > 0) { 1683 #ifdef DIAGNOSTIC 1684 int msgcount = siop_ctoh32(&sc->sc_c, 1685 siop_cmd->cmd_tables->t_msgout.count); 1686 if (msgcount != 1) 1687 printf("%s:%d:%d: tag %d with msgcount %d\n", 1688 sc->sc_c.sc_dev.dv_xname, target, lun, tag, 1689 msgcount); 1690 #endif 1691 siop_cmd->cmd_tables->msg_out[1] = MSG_SIMPLE_Q_TAG; 1692 siop_cmd->cmd_tables->msg_out[2] = tag; 1693 siop_cmd->cmd_tables->t_msgout.count = 1694 siop_htoc32(&sc->sc_c, 3); 1695 } 1696 /* note that we started a new command */ 1697 newcmd = 1; 1698 /* mark command as active */ 1699 if (siop_cmd->cmd_c.status == CMDST_READY) { 1700 siop_cmd->cmd_c.status = CMDST_ACTIVE; 1701 } else if (siop_cmd->cmd_c.status == CMDST_SENSE) { 1702 siop_cmd->cmd_c.status = CMDST_SENSE_ACTIVE; 1703 } else 1704 panic("siop_start: bad status"); 1705 if (doingready) 1706 TAILQ_REMOVE(&sc->ready_list, siop_cmd, next); 1707 else 1708 TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next); 1709 siop_lun->siop_tag[tag].active = siop_cmd; 1710 /* patch scripts with DSA addr */ 1711 dsa = siop_cmd->cmd_c.dsa; 1712 /* first reselect switch, if we have an entry */ 1713 if (siop_lun->siop_tag[tag].reseloff > 0) 1714 siop_script_write(sc, 1715 siop_lun->siop_tag[tag].reseloff + 1, 1716 dsa + sizeof(struct siop_common_xfer) + 1717 Ent_ldsa_reload_dsa); 1718 /* CMD script: MOVE MEMORY addr */ 1719 siop_xfer = (struct siop_xfer*)siop_cmd->cmd_tables; 1720 siop_xfer->resel[E_ldsa_abs_slot_Used[0]] = 1721 siop_htoc32(&sc->sc_c, sc->sc_c.sc_scriptaddr + 1722 Ent_script_sched_slot0 + slot * 8); 1723 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE); 1724 /* scheduler slot: JUMP ldsa_select */ 1725 siop_script_write(sc, 1726 (Ent_script_sched_slot0 / 4) + slot * 2 + 1, 1727 dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_select); 1728 /* handle timeout */ 1729 if (siop_cmd->cmd_c.status == CMDST_ACTIVE) { 1730 if ((siop_cmd->cmd_c.xs->flags & SCSI_POLL) == 0) { 1731 /* start expire timer */ 1732 timeout_add_msec(&siop_cmd->cmd_c.xs->stimeout, 1733 siop_cmd->cmd_c.xs->timeout); 1734 } 1735 } 1736 /* 1737 * Change JUMP cmd so that this slot will be handled 1738 */ 1739 siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2, 1740 0x80080000); 1741 /* if we're using the request sense slot, stop here */ 1742 if (slot == 0) 1743 goto end; 1744 sc->sc_currschedslot = slot; 1745 slot++; 1746 } 1747 if (doingready == 0) { 1748 /* now process ready list */ 1749 doingready = 1; 1750 siop_cmd = TAILQ_FIRST(&sc->ready_list); 1751 goto again; 1752 } 1753 1754 end: 1755 /* if nothing changed no need to flush cache and wakeup script */ 1756 if (newcmd == 0) 1757 return; 1758 /* make sure SCRIPT processor will read valid data */ 1759 siop_script_sync(sc,BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1760 /* Signal script it has some work to do */ 1761 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, 1762 SIOP_ISTAT, ISTAT_SIGP); 1763 /* and wait for IRQ */ 1764 return; 1765 } 1766 1767 void 1768 siop_timeout(v) 1769 void *v; 1770 { 1771 struct siop_cmd *siop_cmd = v; 1772 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc; 1773 int s; 1774 1775 /* deactivate callout */ 1776 timeout_del(&siop_cmd->cmd_c.xs->stimeout); 1777 1778 sc_print_addr(siop_cmd->cmd_c.xs->sc_link); 1779 printf("timeout on SCSI command 0x%x\n", 1780 siop_cmd->cmd_c.xs->cmd->opcode); 1781 1782 s = splbio(); 1783 /* reset the scsi bus */ 1784 siop_resetbus(&sc->sc_c); 1785 siop_cmd->cmd_c.flags |= CMDFL_TIMEOUT; 1786 siop_handle_reset(sc); 1787 splx(s); 1788 1789 return; 1790 } 1791 1792 #ifdef DUMP_SCRIPT 1793 void 1794 siop_dump_script(sc) 1795 struct siop_softc *sc; 1796 { 1797 int i; 1798 for (i = 0; i < PAGE_SIZE / 4; i += 2) { 1799 printf("0x%04x: 0x%08x 0x%08x", i * 4, 1800 siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[i]), 1801 siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[i+1])); 1802 if ((siop_ctoh32(&sc->sc_c, 1803 sc->sc_c.sc_script[i]) & 0xe0000000) == 0xc0000000) { 1804 i++; 1805 printf(" 0x%08x", siop_ctoh32(&sc->sc_c, 1806 sc->sc_c.sc_script[i+1])); 1807 } 1808 printf("\n"); 1809 } 1810 } 1811 #endif 1812 1813 void 1814 siop_morecbd(sc) 1815 struct siop_softc *sc; 1816 { 1817 int error, off, i, j, s; 1818 struct siop_cbd *newcbd; 1819 struct siop_xfer *xfers, *xfer; 1820 bus_addr_t dsa; 1821 u_int32_t *scr; 1822 size_t sense_size = roundup(sizeof(struct scsi_sense_data), 16); 1823 1824 /* allocate a new list head */ 1825 newcbd = malloc(sizeof(struct siop_cbd), M_DEVBUF, M_NOWAIT | M_ZERO); 1826 if (newcbd == NULL) { 1827 printf("%s: can't allocate memory for command descriptors " 1828 "head\n", sc->sc_c.sc_dev.dv_xname); 1829 return; 1830 } 1831 1832 /* allocate cmd list */ 1833 newcbd->cmds = malloc(sizeof(struct siop_cmd) * SIOP_NCMDPB, 1834 M_DEVBUF, M_NOWAIT | M_ZERO); 1835 if (newcbd->cmds == NULL) { 1836 printf("%s: can't allocate memory for command descriptors\n", 1837 sc->sc_c.sc_dev.dv_xname); 1838 goto bad3; 1839 } 1840 1841 newcbd->xfers = siop_dmamem_alloc(sc, PAGE_SIZE); 1842 if (newcbd->xfers == NULL) { 1843 printf("%s: unable to allocate cbd xfer DMA memory\n", 1844 sc->sc_c.sc_dev.dv_xname); 1845 goto bad2; 1846 } 1847 xfers = SIOP_DMA_KVA(newcbd->xfers); 1848 1849 newcbd->sense = siop_dmamem_alloc(sc, sense_size * SIOP_NCMDPB); 1850 if (newcbd->sense == NULL) { 1851 printf("%s: unable to allocate cbd sense DMA memory\n", 1852 sc->sc_c.sc_dev.dv_xname); 1853 goto bad1; 1854 } 1855 1856 for (i = 0; i < SIOP_NCMDPB; i++) { 1857 error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG, 1858 MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 1859 &newcbd->cmds[i].cmd_c.dmamap_data); 1860 if (error) { 1861 printf("%s: unable to create data DMA map for cbd: " 1862 "error %d\n", 1863 sc->sc_c.sc_dev.dv_xname, error); 1864 goto bad0; 1865 } 1866 } 1867 1868 /* Use two loops since bailing out above releases allocated memory */ 1869 off = (sc->sc_c.features & SF_CHIP_BE) ? 3 : 0; 1870 for (i = 0; i < SIOP_NCMDPB; i++) { 1871 newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c; 1872 newcbd->cmds[i].siop_cbdp = newcbd; 1873 xfer = &xfers[i]; 1874 newcbd->cmds[i].cmd_tables = (struct siop_common_xfer *)xfer; 1875 bzero(newcbd->cmds[i].cmd_tables, sizeof(struct siop_xfer)); 1876 dsa = SIOP_DMA_DVA(newcbd->xfers) + 1877 i * sizeof(struct siop_xfer); 1878 newcbd->cmds[i].cmd_c.dsa = dsa; 1879 newcbd->cmds[i].cmd_c.status = CMDST_FREE; 1880 newcbd->cmds[i].cmd_c.sense = (struct scsi_sense_data *)( 1881 i * sense_size + 1882 (u_int8_t *)SIOP_DMA_KVA(newcbd->sense)); 1883 xfer->siop_tables.t_msgout.count= siop_htoc32(&sc->sc_c, 1); 1884 xfer->siop_tables.t_msgout.addr = siop_htoc32(&sc->sc_c, dsa); 1885 xfer->siop_tables.t_msgin.count= siop_htoc32(&sc->sc_c, 1); 1886 xfer->siop_tables.t_msgin.addr = siop_htoc32(&sc->sc_c, 1887 dsa + offsetof(struct siop_common_xfer, msg_in)); 1888 xfer->siop_tables.t_extmsgin.count= siop_htoc32(&sc->sc_c, 2); 1889 xfer->siop_tables.t_extmsgin.addr = siop_htoc32(&sc->sc_c, 1890 dsa + offsetof(struct siop_common_xfer, msg_in) + 1); 1891 xfer->siop_tables.t_extmsgdata.addr = siop_htoc32(&sc->sc_c, 1892 dsa + offsetof(struct siop_common_xfer, msg_in) + 3); 1893 xfer->siop_tables.t_status.count= siop_htoc32(&sc->sc_c, 1); 1894 xfer->siop_tables.t_status.addr = siop_htoc32(&sc->sc_c, 1895 dsa + offsetof(struct siop_common_xfer, status) + off); 1896 xfer->siop_tables.cmd.count = siop_htoc32(&sc->sc_c, 0); 1897 xfer->siop_tables.cmd.addr = siop_htoc32(&sc->sc_c, 1898 dsa + offsetof(struct siop_common_xfer, xscmd)); 1899 /* The select/reselect script */ 1900 scr = &xfer->resel[0]; 1901 for (j = 0; j < sizeof(load_dsa) / sizeof(load_dsa[0]); j++) 1902 scr[j] = siop_htoc32(&sc->sc_c, load_dsa[j]); 1903 /* 1904 * 0x78000000 is a 'move data8 to reg'. data8 is the second 1905 * octet, reg offset is the third. 1906 */ 1907 scr[Ent_rdsa0 / 4] = siop_htoc32(&sc->sc_c, 1908 0x78100000 | ((dsa & 0x000000ff) << 8)); 1909 scr[Ent_rdsa1 / 4] = siop_htoc32(&sc->sc_c, 1910 0x78110000 | ( dsa & 0x0000ff00 )); 1911 scr[Ent_rdsa2 / 4] = siop_htoc32(&sc->sc_c, 1912 0x78120000 | ((dsa & 0x00ff0000) >> 8)); 1913 scr[Ent_rdsa3 / 4] = siop_htoc32(&sc->sc_c, 1914 0x78130000 | ((dsa & 0xff000000) >> 16)); 1915 scr[E_ldsa_abs_reselected_Used[0]] = siop_htoc32(&sc->sc_c, 1916 sc->sc_c.sc_scriptaddr + Ent_reselected); 1917 scr[E_ldsa_abs_reselect_Used[0]] = siop_htoc32(&sc->sc_c, 1918 sc->sc_c.sc_scriptaddr + Ent_reselect); 1919 scr[E_ldsa_abs_selected_Used[0]] = siop_htoc32(&sc->sc_c, 1920 sc->sc_c.sc_scriptaddr + Ent_selected); 1921 scr[E_ldsa_abs_data_Used[0]] = siop_htoc32(&sc->sc_c, 1922 dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data); 1923 /* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */ 1924 scr[Ent_ldsa_data / 4] = siop_htoc32(&sc->sc_c, 0x80000000); 1925 s = splbio(); 1926 TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next); 1927 splx(s); 1928 #ifdef SIOP_DEBUG 1929 printf("tables[%d]: in=0x%x out=0x%x status=0x%x " 1930 "offset=0x%x\n", i, 1931 siop_ctoh32(&sc->sc_c, 1932 newcbd->cmds[i].cmd_tables->t_msgin.addr), 1933 siop_ctoh32(&sc->sc_c, 1934 newcbd->cmds[i].cmd_tables->t_msgout.addr), 1935 siop_ctoh32(&sc->sc_c, 1936 newcbd->cmds[i].cmd_tables->t_status.addr)); 1937 #endif 1938 } 1939 s = splbio(); 1940 TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next); 1941 splx(s); 1942 return; 1943 bad0: 1944 while (--i >= 0) { 1945 bus_dmamap_destroy(sc->sc_c.sc_dmat, 1946 newcbd->cmds[i].cmd_c.dmamap_data); 1947 } 1948 siop_dmamem_free(sc, newcbd->sense); 1949 bad1: 1950 siop_dmamem_free(sc, newcbd->xfers); 1951 bad2: 1952 free(newcbd->cmds, M_DEVBUF); 1953 bad3: 1954 free(newcbd, M_DEVBUF); 1955 return; 1956 } 1957 1958 struct siop_lunsw * 1959 siop_get_lunsw(sc) 1960 struct siop_softc *sc; 1961 { 1962 struct siop_lunsw *lunsw; 1963 int i; 1964 1965 if (sc->script_free_lo + (sizeof(lun_switch) / sizeof(lun_switch[0])) >= 1966 sc->script_free_hi) 1967 return NULL; 1968 lunsw = TAILQ_FIRST(&sc->lunsw_list); 1969 if (lunsw != NULL) { 1970 #ifdef SIOP_DEBUG 1971 printf("siop_get_lunsw got lunsw at offset %d\n", 1972 lunsw->lunsw_off); 1973 #endif 1974 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next); 1975 return lunsw; 1976 } 1977 lunsw = malloc(sizeof(struct siop_lunsw), M_DEVBUF, M_NOWAIT | M_ZERO); 1978 if (lunsw == NULL) 1979 return NULL; 1980 #ifdef SIOP_DEBUG 1981 printf("allocating lunsw at offset %d\n", sc->script_free_lo); 1982 #endif 1983 if (sc->sc_c.features & SF_CHIP_RAM) { 1984 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 1985 sc->script_free_lo * 4, lun_switch, 1986 sizeof(lun_switch) / sizeof(lun_switch[0])); 1987 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 1988 (sc->script_free_lo + E_abs_lunsw_return_Used[0]) * 4, 1989 sc->sc_c.sc_scriptaddr + Ent_lunsw_return); 1990 } else { 1991 for (i = 0; i < sizeof(lun_switch) / sizeof(lun_switch[0]); 1992 i++) 1993 sc->sc_c.sc_script[sc->script_free_lo + i] = 1994 siop_htoc32(&sc->sc_c, lun_switch[i]); 1995 sc->sc_c.sc_script[ 1996 sc->script_free_lo + E_abs_lunsw_return_Used[0]] = 1997 siop_htoc32(&sc->sc_c, 1998 sc->sc_c.sc_scriptaddr + Ent_lunsw_return); 1999 } 2000 lunsw->lunsw_off = sc->script_free_lo; 2001 lunsw->lunsw_size = sizeof(lun_switch) / sizeof(lun_switch[0]); 2002 sc->script_free_lo += lunsw->lunsw_size; 2003 siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2004 return lunsw; 2005 } 2006 2007 void 2008 siop_add_reselsw(sc, target) 2009 struct siop_softc *sc; 2010 int target; 2011 { 2012 int i,j; 2013 struct siop_target *siop_target; 2014 struct siop_lun *siop_lun; 2015 2016 siop_target = (struct siop_target *)sc->sc_c.targets[target]; 2017 /* 2018 * add an entry to resel switch 2019 */ 2020 siop_script_sync(sc, BUS_DMASYNC_POSTWRITE); 2021 for (i = 0; i < 15; i++) { 2022 siop_target->reseloff = Ent_resel_targ0 / 4 + i * 2; 2023 if ((siop_script_read(sc, siop_target->reseloff) & 0xff) 2024 == 0xff) { /* it's free */ 2025 #ifdef SIOP_DEBUG 2026 printf("siop: target %d slot %d offset %d\n", 2027 target, i, siop_target->reseloff); 2028 #endif 2029 /* JUMP abs_foo, IF target | 0x80; */ 2030 siop_script_write(sc, siop_target->reseloff, 2031 0x800c0080 | target); 2032 siop_script_write(sc, siop_target->reseloff + 1, 2033 sc->sc_c.sc_scriptaddr + 2034 siop_target->lunsw->lunsw_off * 4 + 2035 Ent_lun_switch_entry); 2036 break; 2037 } 2038 } 2039 if (i == 15) /* no free slot, shouldn't happen */ 2040 panic("siop: resel switch full"); 2041 2042 sc->sc_ntargets++; 2043 for (i = 0; i < 8; i++) { 2044 siop_lun = siop_target->siop_lun[i]; 2045 if (siop_lun == NULL) 2046 continue; 2047 if (siop_lun->reseloff > 0) { 2048 siop_lun->reseloff = 0; 2049 for (j = 0; j < SIOP_NTAG; j++) 2050 siop_lun->siop_tag[j].reseloff = 0; 2051 siop_add_dev(sc, target, i); 2052 } 2053 } 2054 siop_update_scntl3(sc, sc->sc_c.targets[target]); 2055 siop_script_sync(sc, BUS_DMASYNC_PREWRITE); 2056 } 2057 2058 void 2059 siop_update_scntl3(sc, _siop_target) 2060 struct siop_softc *sc; 2061 struct siop_common_target *_siop_target; 2062 { 2063 struct siop_target *siop_target = (struct siop_target *)_siop_target; 2064 /* MOVE target->id >> 24 TO SCNTL3 */ 2065 siop_script_write(sc, 2066 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4), 2067 0x78030000 | ((siop_target->target_c.id >> 16) & 0x0000ff00)); 2068 /* MOVE target->id >> 8 TO SXFER */ 2069 siop_script_write(sc, 2070 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 2, 2071 0x78050000 | (siop_target->target_c.id & 0x0000ff00)); 2072 siop_script_sync(sc, BUS_DMASYNC_PREWRITE); 2073 } 2074 2075 void 2076 siop_add_dev(sc, target, lun) 2077 struct siop_softc *sc; 2078 int target; 2079 int lun; 2080 { 2081 struct siop_lunsw *lunsw; 2082 struct siop_target *siop_target = 2083 (struct siop_target *)sc->sc_c.targets[target]; 2084 struct siop_lun *siop_lun = siop_target->siop_lun[lun]; 2085 int i, ntargets; 2086 2087 if (siop_lun->reseloff > 0) 2088 return; 2089 lunsw = siop_target->lunsw; 2090 if ((lunsw->lunsw_off + lunsw->lunsw_size) < sc->script_free_lo) { 2091 /* 2092 * can't extend this slot. Probably not worth trying to deal 2093 * with this case 2094 */ 2095 #ifdef SIOP_DEBUG 2096 printf("%s:%d:%d: can't allocate a lun sw slot\n", 2097 sc->sc_c.sc_dev.dv_xname, target, lun); 2098 #endif 2099 return; 2100 } 2101 /* count how many free targets we still have to probe */ 2102 ntargets = (sc->sc_c.sc_link.adapter_buswidth - 1) - 1 - sc->sc_ntargets; 2103 2104 /* 2105 * we need 8 bytes for the lun sw additional entry, and 2106 * eventually sizeof(tag_switch) for the tag switch entry. 2107 * Keep enough free space for the free targets that could be 2108 * probed later. 2109 */ 2110 if (sc->script_free_lo + 2 + 2111 (ntargets * sizeof(lun_switch) / sizeof(lun_switch[0])) >= 2112 ((siop_target->target_c.flags & TARF_TAG) ? 2113 sc->script_free_hi - (sizeof(tag_switch) / sizeof(tag_switch[0])) : 2114 sc->script_free_hi)) { 2115 /* 2116 * not enough space, probably not worth dealing with it. 2117 * We can hold 13 tagged-queuing capable devices in the 4k RAM. 2118 */ 2119 #ifdef SIOP_DEBUG 2120 printf("%s:%d:%d: not enough memory for a lun sw slot\n", 2121 sc->sc_c.sc_dev.dv_xname, target, lun); 2122 #endif 2123 return; 2124 } 2125 #ifdef SIOP_DEBUG 2126 printf("%s:%d:%d: allocate lun sw entry\n", 2127 sc->sc_c.sc_dev.dv_xname, target, lun); 2128 #endif 2129 /* INT int_resellun */ 2130 siop_script_write(sc, sc->script_free_lo, 0x98080000); 2131 siop_script_write(sc, sc->script_free_lo + 1, A_int_resellun); 2132 /* Now the slot entry: JUMP abs_foo, IF lun */ 2133 siop_script_write(sc, sc->script_free_lo - 2, 2134 0x800c0000 | lun); 2135 siop_script_write(sc, sc->script_free_lo - 1, 0); 2136 siop_lun->reseloff = sc->script_free_lo - 2; 2137 lunsw->lunsw_size += 2; 2138 sc->script_free_lo += 2; 2139 if (siop_target->target_c.flags & TARF_TAG) { 2140 /* we need a tag switch */ 2141 sc->script_free_hi -= 2142 sizeof(tag_switch) / sizeof(tag_switch[0]); 2143 if (sc->sc_c.features & SF_CHIP_RAM) { 2144 bus_space_write_region_4(sc->sc_c.sc_ramt, 2145 sc->sc_c.sc_ramh, 2146 sc->script_free_hi * 4, tag_switch, 2147 sizeof(tag_switch) / sizeof(tag_switch[0])); 2148 } else { 2149 for(i = 0; 2150 i < sizeof(tag_switch) / sizeof(tag_switch[0]); 2151 i++) { 2152 sc->sc_c.sc_script[sc->script_free_hi + i] = 2153 siop_htoc32(&sc->sc_c, tag_switch[i]); 2154 } 2155 } 2156 siop_script_write(sc, 2157 siop_lun->reseloff + 1, 2158 sc->sc_c.sc_scriptaddr + sc->script_free_hi * 4 + 2159 Ent_tag_switch_entry); 2160 2161 for (i = 0; i < SIOP_NTAG; i++) { 2162 siop_lun->siop_tag[i].reseloff = 2163 sc->script_free_hi + (Ent_resel_tag0 / 4) + i * 2; 2164 } 2165 } else { 2166 /* non-tag case; just work with the lun switch */ 2167 siop_lun->siop_tag[0].reseloff = 2168 siop_target->siop_lun[lun]->reseloff; 2169 } 2170 siop_script_sync(sc, BUS_DMASYNC_PREWRITE); 2171 } 2172 2173 void 2174 siop_scsifree(struct scsi_link *link) 2175 { 2176 struct siop_softc *sc = link->adapter_softc; 2177 int target = link->target; 2178 int lun = link->lun; 2179 int i; 2180 struct siop_target *siop_target; 2181 2182 #ifdef SIOP_DEBUG 2183 printf("%s:%d:%d: free lun sw entry\n", 2184 sc->sc_c.sc_dev.dv_xname, target, lun); 2185 #endif 2186 2187 siop_target = (struct siop_target *)sc->sc_c.targets[target]; 2188 free(siop_target->siop_lun[lun], M_DEVBUF); 2189 siop_target->siop_lun[lun] = NULL; 2190 /* XXX compact sw entry too ? */ 2191 /* check if we can free the whole target */ 2192 for (i = 0; i < 8; i++) { 2193 if (siop_target->siop_lun[i] != NULL) 2194 return; 2195 } 2196 #ifdef SIOP_DEBUG 2197 printf("%s: free siop_target for target %d lun %d lunsw offset %d\n", 2198 sc->sc_c.sc_dev.dv_xname, target, lun, 2199 siop_target->lunsw->lunsw_off); 2200 #endif 2201 /* 2202 * nothing here, free the target struct and resel 2203 * switch entry 2204 */ 2205 siop_script_write(sc, siop_target->reseloff, 0x800c00ff); 2206 siop_script_sync(sc, BUS_DMASYNC_PREWRITE); 2207 TAILQ_INSERT_TAIL(&sc->lunsw_list, siop_target->lunsw, next); 2208 free(sc->sc_c.targets[target], M_DEVBUF); 2209 sc->sc_c.targets[target] = NULL; 2210 sc->sc_ntargets--; 2211 } 2212 2213 #ifdef SIOP_STATS 2214 void 2215 siop_printstats(void) 2216 { 2217 printf("siop_stat_intr %d\n", siop_stat_intr); 2218 printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer); 2219 printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc); 2220 printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp); 2221 printf("siop_stat_intr_saveoffset %d\n", siop_stat_intr_saveoffset); 2222 printf("siop_stat_intr_done %d\n", siop_stat_intr_done); 2223 printf("siop_stat_intr_lunresel %d\n", siop_stat_intr_lunresel); 2224 printf("siop_stat_intr_qfull %d\n", siop_stat_intr_qfull); 2225 } 2226 #endif 2227 2228 struct siop_dmamem * 2229 siop_dmamem_alloc(struct siop_softc *sc, size_t size) 2230 { 2231 struct siop_dmamem *sdm; 2232 int nsegs; 2233 2234 sdm = malloc(sizeof(*sdm), M_DEVBUF, M_NOWAIT | M_ZERO); 2235 if (sdm == NULL) 2236 return (NULL); 2237 2238 sdm->sdm_size = size; 2239 2240 if (bus_dmamap_create(sc->sc_c.sc_dmat, size, 1, size, 0, 2241 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sdm->sdm_map) != 0) 2242 goto sdmfree; 2243 2244 if (bus_dmamem_alloc(sc->sc_c.sc_dmat, size, PAGE_SIZE, 0, 2245 &sdm->sdm_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0) 2246 goto destroy; 2247 2248 if (bus_dmamem_map(sc->sc_c.sc_dmat, &sdm->sdm_seg, nsegs, size, 2249 &sdm->sdm_kva, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) 2250 goto free; 2251 2252 if (bus_dmamap_load(sc->sc_c.sc_dmat, sdm->sdm_map, sdm->sdm_kva, 2253 size, NULL, BUS_DMA_NOWAIT) != 0) 2254 goto unmap; 2255 2256 return (sdm); 2257 2258 unmap: 2259 bus_dmamem_unmap(sc->sc_c.sc_dmat, sdm->sdm_kva, size); 2260 free: 2261 bus_dmamem_free(sc->sc_c.sc_dmat, &sdm->sdm_seg, 1); 2262 destroy: 2263 bus_dmamap_destroy(sc->sc_c.sc_dmat, sdm->sdm_map); 2264 sdmfree: 2265 free(sdm, M_DEVBUF); 2266 2267 return (NULL); 2268 } 2269 2270 void 2271 siop_dmamem_free(struct siop_softc *sc, struct siop_dmamem *sdm) 2272 { 2273 bus_dmamap_unload(sc->sc_c.sc_dmat, sdm->sdm_map); 2274 bus_dmamem_unmap(sc->sc_c.sc_dmat, sdm->sdm_kva, sdm->sdm_size); 2275 bus_dmamem_free(sc->sc_c.sc_dmat, &sdm->sdm_seg, 1); 2276 bus_dmamap_destroy(sc->sc_c.sc_dmat, sdm->sdm_map); 2277 free(sdm, M_DEVBUF); 2278 } 2279 2280