1 /* $OpenBSD: siop.c,v 1.86 2020/09/22 19:32:52 krw Exp $ */ 2 /* $NetBSD: siop.c,v 1.79 2005/11/18 23:10:32 bouyer Exp $ */ 3 4 /* 5 * Copyright (c) 2000 Manuel Bouyer. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 29 /* SYM53c7/8xx PCI-SCSI I/O Processors driver */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/device.h> 34 #include <sys/malloc.h> 35 #include <sys/kernel.h> 36 #include <sys/endian.h> 37 38 #include <machine/bus.h> 39 40 #include <dev/microcode/siop/siop.out> 41 42 #include <scsi/scsi_all.h> 43 #include <scsi/scsi_message.h> 44 #include <scsi/scsiconf.h> 45 46 #include <dev/ic/siopreg.h> 47 #include <dev/ic/siopvar_common.h> 48 #include <dev/ic/siopvar.h> 49 50 #ifndef SIOP_DEBUG 51 #undef SIOP_DEBUG_DR 52 #undef SIOP_DEBUG_INTR 53 #undef SIOP_DEBUG_SCHED 54 #undef DUMP_SCRIPT 55 #else 56 #define SIOP_DEBUG_DR 57 #define SIOP_DEBUG_INTR 58 #define SIOP_DEBUG_SCHED 59 #define DUMP_SCRIPT 60 #endif 61 62 63 #undef SIOP_STATS 64 65 #ifndef SIOP_DEFAULT_TARGET 66 #define SIOP_DEFAULT_TARGET 7 67 #endif 68 69 /* number of cmd descriptors per block */ 70 #define SIOP_NCMDPB (PAGE_SIZE / sizeof(struct siop_xfer)) 71 72 /* Number of scheduler slot (needs to match script) */ 73 #define SIOP_NSLOTS 40 74 75 void siop_table_sync(struct siop_cmd *, int); 76 void siop_script_sync(struct siop_softc *, int); 77 u_int32_t siop_script_read(struct siop_softc *, u_int); 78 void siop_script_write(struct siop_softc *, u_int, u_int32_t); 79 void siop_reset(struct siop_softc *); 80 void siop_handle_reset(struct siop_softc *); 81 int siop_handle_qtag_reject(struct siop_cmd *); 82 void siop_scsicmd_end(struct siop_cmd *); 83 void siop_start(struct siop_softc *); 84 void siop_timeout(void *); 85 void siop_scsicmd(struct scsi_xfer *); 86 void * siop_cmd_get(void *); 87 void siop_cmd_put(void *, void *); 88 int siop_scsiprobe(struct scsi_link *); 89 void siop_scsifree(struct scsi_link *); 90 #ifdef DUMP_SCRIPT 91 void siop_dump_script(struct siop_softc *); 92 #endif 93 void siop_morecbd(struct siop_softc *); 94 struct siop_lunsw *siop_get_lunsw(struct siop_softc *); 95 void siop_add_reselsw(struct siop_softc *, int); 96 void siop_update_scntl3(struct siop_softc *, struct siop_common_target *); 97 98 struct siop_dmamem *siop_dmamem_alloc(struct siop_softc *, size_t); 99 void siop_dmamem_free(struct siop_softc *, struct siop_dmamem *); 100 101 struct cfdriver siop_cd = { 102 NULL, "siop", DV_DULL 103 }; 104 105 struct scsi_adapter siop_switch = { 106 siop_scsicmd, NULL, siop_scsiprobe, siop_scsifree, NULL 107 }; 108 109 #ifdef SIOP_STATS 110 static int siop_stat_intr = 0; 111 static int siop_stat_intr_shortxfer = 0; 112 static int siop_stat_intr_sdp = 0; 113 static int siop_stat_intr_saveoffset = 0; 114 static int siop_stat_intr_done = 0; 115 static int siop_stat_intr_xferdisc = 0; 116 static int siop_stat_intr_lunresel = 0; 117 static int siop_stat_intr_qfull = 0; 118 void siop_printstats(void); 119 #define INCSTAT(x) x++ 120 #else 121 #define INCSTAT(x) 122 #endif 123 124 void 125 siop_table_sync(siop_cmd, ops) 126 struct siop_cmd *siop_cmd; 127 int ops; 128 { 129 struct siop_common_softc *sc = siop_cmd->cmd_c.siop_sc; 130 bus_addr_t offset; 131 132 offset = siop_cmd->cmd_c.dsa - 133 SIOP_DMA_DVA(siop_cmd->siop_cbdp->xfers); 134 bus_dmamap_sync(sc->sc_dmat, 135 SIOP_DMA_MAP(siop_cmd->siop_cbdp->xfers), offset, 136 sizeof(struct siop_xfer), ops); 137 } 138 139 void 140 siop_script_sync(sc, ops) 141 struct siop_softc *sc; 142 int ops; 143 { 144 if ((sc->sc_c.features & SF_CHIP_RAM) == 0) 145 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0, 146 PAGE_SIZE, ops); 147 } 148 149 u_int32_t 150 siop_script_read(sc, offset) 151 struct siop_softc *sc; 152 u_int offset; 153 { 154 if (sc->sc_c.features & SF_CHIP_RAM) { 155 return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 156 offset * 4); 157 } else { 158 return siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[offset]); 159 } 160 } 161 162 void 163 siop_script_write(sc, offset, val) 164 struct siop_softc *sc; 165 u_int offset; 166 u_int32_t val; 167 { 168 if (sc->sc_c.features & SF_CHIP_RAM) { 169 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 170 offset * 4, val); 171 } else { 172 sc->sc_c.sc_script[offset] = siop_htoc32(&sc->sc_c, val); 173 } 174 } 175 176 void 177 siop_attach(sc) 178 struct siop_softc *sc; 179 { 180 struct scsibus_attach_args saa; 181 182 if (siop_common_attach(&sc->sc_c) != 0) 183 return; 184 185 TAILQ_INIT(&sc->free_list); 186 TAILQ_INIT(&sc->ready_list); 187 TAILQ_INIT(&sc->urgent_list); 188 TAILQ_INIT(&sc->cmds); 189 TAILQ_INIT(&sc->lunsw_list); 190 scsi_iopool_init(&sc->iopool, sc, siop_cmd_get, siop_cmd_put); 191 sc->sc_currschedslot = 0; 192 193 /* Start with one page worth of commands */ 194 siop_morecbd(sc); 195 196 #ifdef SIOP_DEBUG 197 printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n", 198 sc->sc_c.sc_dev.dv_xname, (int)sizeof(siop_script), 199 (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script); 200 #endif 201 202 /* Do a bus reset, so that devices fall back to narrow/async */ 203 siop_resetbus(&sc->sc_c); 204 /* 205 * siop_reset() will reset the chip, thus clearing pending interrupts 206 */ 207 siop_reset(sc); 208 #ifdef DUMP_SCRIPT 209 siop_dump_script(sc); 210 #endif 211 212 saa.saa_adapter_softc = sc; 213 saa.saa_adapter = &siop_switch; 214 saa.saa_adapter_target = sc->sc_c.sc_id; 215 saa.saa_adapter_buswidth = (sc->sc_c.features & SF_BUS_WIDE) ? 16 : 8; 216 saa.saa_luns = 8; 217 saa.saa_openings = SIOP_NTAG; 218 saa.saa_pool = &sc->iopool; 219 saa.saa_quirks = saa.saa_flags = 0; 220 saa.saa_wwpn = saa.saa_wwnn = 0; 221 222 config_found((struct device*)sc, &saa, scsiprint); 223 } 224 225 void 226 siop_reset(sc) 227 struct siop_softc *sc; 228 { 229 int i, j, buswidth; 230 struct siop_lunsw *lunsw; 231 232 siop_common_reset(&sc->sc_c); 233 234 /* copy and patch the script */ 235 if (sc->sc_c.features & SF_CHIP_RAM) { 236 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0, 237 siop_script, sizeof(siop_script) / sizeof(siop_script[0])); 238 for (j = 0; j < 239 (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0])); 240 j++) { 241 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 242 E_abs_msgin_Used[j] * 4, 243 sc->sc_c.sc_scriptaddr + Ent_msgin_space); 244 } 245 if (sc->sc_c.features & SF_CHIP_LED0) { 246 bus_space_write_region_4(sc->sc_c.sc_ramt, 247 sc->sc_c.sc_ramh, 248 Ent_led_on1, siop_led_on, 249 sizeof(siop_led_on) / sizeof(siop_led_on[0])); 250 bus_space_write_region_4(sc->sc_c.sc_ramt, 251 sc->sc_c.sc_ramh, 252 Ent_led_on2, siop_led_on, 253 sizeof(siop_led_on) / sizeof(siop_led_on[0])); 254 bus_space_write_region_4(sc->sc_c.sc_ramt, 255 sc->sc_c.sc_ramh, 256 Ent_led_off, siop_led_off, 257 sizeof(siop_led_off) / sizeof(siop_led_off[0])); 258 } 259 } else { 260 for (j = 0; 261 j < (sizeof(siop_script) / sizeof(siop_script[0])); j++) { 262 sc->sc_c.sc_script[j] = 263 siop_htoc32(&sc->sc_c, siop_script[j]); 264 } 265 for (j = 0; j < 266 (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0])); 267 j++) { 268 sc->sc_c.sc_script[E_abs_msgin_Used[j]] = 269 siop_htoc32(&sc->sc_c, 270 sc->sc_c.sc_scriptaddr + Ent_msgin_space); 271 } 272 if (sc->sc_c.features & SF_CHIP_LED0) { 273 for (j = 0; j < (sizeof(siop_led_on) / 274 sizeof(siop_led_on[0])); j++) 275 sc->sc_c.sc_script[ 276 Ent_led_on1 / sizeof(siop_led_on[0]) + j 277 ] = siop_htoc32(&sc->sc_c, siop_led_on[j]); 278 for (j = 0; j < (sizeof(siop_led_on) / 279 sizeof(siop_led_on[0])); j++) 280 sc->sc_c.sc_script[ 281 Ent_led_on2 / sizeof(siop_led_on[0]) + j 282 ] = siop_htoc32(&sc->sc_c, siop_led_on[j]); 283 for (j = 0; j < (sizeof(siop_led_off) / 284 sizeof(siop_led_off[0])); j++) 285 sc->sc_c.sc_script[ 286 Ent_led_off / sizeof(siop_led_off[0]) + j 287 ] = siop_htoc32(&sc->sc_c, siop_led_off[j]); 288 } 289 } 290 sc->script_free_lo = sizeof(siop_script) / sizeof(siop_script[0]); 291 sc->script_free_hi = sc->sc_c.ram_size / 4; 292 sc->sc_ntargets = 0; 293 294 /* free used and unused lun switches */ 295 while((lunsw = TAILQ_FIRST(&sc->lunsw_list)) != NULL) { 296 #ifdef SIOP_DEBUG 297 printf("%s: free lunsw at offset %d\n", 298 sc->sc_c.sc_dev.dv_xname, lunsw->lunsw_off); 299 #endif 300 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next); 301 free(lunsw, M_DEVBUF, 0); 302 } 303 TAILQ_INIT(&sc->lunsw_list); 304 /* restore reselect switch */ 305 buswidth = (sc->sc_c.features & SF_BUS_WIDE) ? 16 : 8; 306 for (i = 0; i < 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, buswidth; 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 buswidth = (sc->sc_c.features & SF_BUS_WIDE) ? 16 : 8; 1279 for (target = 0; target < buswidth; 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 = link->bus->sb_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, sizeof *siop_target); 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 = xs->sc_link->bus->sb_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 } 1768 1769 void 1770 siop_timeout(v) 1771 void *v; 1772 { 1773 struct siop_cmd *siop_cmd = v; 1774 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc; 1775 int s; 1776 1777 /* deactivate callout */ 1778 timeout_del(&siop_cmd->cmd_c.xs->stimeout); 1779 1780 sc_print_addr(siop_cmd->cmd_c.xs->sc_link); 1781 printf("timeout on SCSI command 0x%x\n", 1782 siop_cmd->cmd_c.xs->cmd.opcode); 1783 1784 s = splbio(); 1785 /* reset the scsi bus */ 1786 siop_resetbus(&sc->sc_c); 1787 siop_cmd->cmd_c.flags |= CMDFL_TIMEOUT; 1788 siop_handle_reset(sc); 1789 splx(s); 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 = mallocarray(SIOP_NCMDPB, sizeof(struct siop_cmd), 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\n", 1930 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, SIOP_NCMDPB * sizeof(struct siop_cmd)); 1953 bad3: 1954 free(newcbd, M_DEVBUF, sizeof *newcbd); 1955 } 1956 1957 struct siop_lunsw * 1958 siop_get_lunsw(sc) 1959 struct siop_softc *sc; 1960 { 1961 struct siop_lunsw *lunsw; 1962 int i; 1963 1964 if (sc->script_free_lo + (sizeof(lun_switch) / sizeof(lun_switch[0])) >= 1965 sc->script_free_hi) 1966 return NULL; 1967 lunsw = TAILQ_FIRST(&sc->lunsw_list); 1968 if (lunsw != NULL) { 1969 #ifdef SIOP_DEBUG 1970 printf("siop_get_lunsw got lunsw at offset %d\n", 1971 lunsw->lunsw_off); 1972 #endif 1973 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next); 1974 return lunsw; 1975 } 1976 lunsw = malloc(sizeof(struct siop_lunsw), M_DEVBUF, M_NOWAIT | M_ZERO); 1977 if (lunsw == NULL) 1978 return NULL; 1979 #ifdef SIOP_DEBUG 1980 printf("allocating lunsw at offset %d\n", sc->script_free_lo); 1981 #endif 1982 if (sc->sc_c.features & SF_CHIP_RAM) { 1983 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 1984 sc->script_free_lo * 4, lun_switch, 1985 sizeof(lun_switch) / sizeof(lun_switch[0])); 1986 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 1987 (sc->script_free_lo + E_abs_lunsw_return_Used[0]) * 4, 1988 sc->sc_c.sc_scriptaddr + Ent_lunsw_return); 1989 } else { 1990 for (i = 0; i < sizeof(lun_switch) / sizeof(lun_switch[0]); 1991 i++) 1992 sc->sc_c.sc_script[sc->script_free_lo + i] = 1993 siop_htoc32(&sc->sc_c, lun_switch[i]); 1994 sc->sc_c.sc_script[ 1995 sc->script_free_lo + E_abs_lunsw_return_Used[0]] = 1996 siop_htoc32(&sc->sc_c, 1997 sc->sc_c.sc_scriptaddr + Ent_lunsw_return); 1998 } 1999 lunsw->lunsw_off = sc->script_free_lo; 2000 lunsw->lunsw_size = sizeof(lun_switch) / sizeof(lun_switch[0]); 2001 sc->script_free_lo += lunsw->lunsw_size; 2002 siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2003 return lunsw; 2004 } 2005 2006 void 2007 siop_add_reselsw(sc, target) 2008 struct siop_softc *sc; 2009 int target; 2010 { 2011 int i,j; 2012 struct siop_target *siop_target; 2013 struct siop_lun *siop_lun; 2014 2015 siop_target = (struct siop_target *)sc->sc_c.targets[target]; 2016 /* 2017 * add an entry to resel switch 2018 */ 2019 siop_script_sync(sc, BUS_DMASYNC_POSTWRITE); 2020 for (i = 0; i < 15; i++) { 2021 siop_target->reseloff = Ent_resel_targ0 / 4 + i * 2; 2022 if ((siop_script_read(sc, siop_target->reseloff) & 0xff) 2023 == 0xff) { /* it's free */ 2024 #ifdef SIOP_DEBUG 2025 printf("siop: target %d slot %d offset %d\n", 2026 target, i, siop_target->reseloff); 2027 #endif 2028 /* JUMP abs_foo, IF target | 0x80; */ 2029 siop_script_write(sc, siop_target->reseloff, 2030 0x800c0080 | target); 2031 siop_script_write(sc, siop_target->reseloff + 1, 2032 sc->sc_c.sc_scriptaddr + 2033 siop_target->lunsw->lunsw_off * 4 + 2034 Ent_lun_switch_entry); 2035 break; 2036 } 2037 } 2038 if (i == 15) /* no free slot, shouldn't happen */ 2039 panic("siop: resel switch full"); 2040 2041 sc->sc_ntargets++; 2042 for (i = 0; i < 8; i++) { 2043 siop_lun = siop_target->siop_lun[i]; 2044 if (siop_lun == NULL) 2045 continue; 2046 if (siop_lun->reseloff > 0) { 2047 siop_lun->reseloff = 0; 2048 for (j = 0; j < SIOP_NTAG; j++) 2049 siop_lun->siop_tag[j].reseloff = 0; 2050 siop_add_dev(sc, target, i); 2051 } 2052 } 2053 siop_update_scntl3(sc, sc->sc_c.targets[target]); 2054 siop_script_sync(sc, BUS_DMASYNC_PREWRITE); 2055 } 2056 2057 void 2058 siop_update_scntl3(sc, _siop_target) 2059 struct siop_softc *sc; 2060 struct siop_common_target *_siop_target; 2061 { 2062 struct siop_target *siop_target = (struct siop_target *)_siop_target; 2063 /* MOVE target->id >> 24 TO SCNTL3 */ 2064 siop_script_write(sc, 2065 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4), 2066 0x78030000 | ((siop_target->target_c.id >> 16) & 0x0000ff00)); 2067 /* MOVE target->id >> 8 TO SXFER */ 2068 siop_script_write(sc, 2069 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 2, 2070 0x78050000 | (siop_target->target_c.id & 0x0000ff00)); 2071 siop_script_sync(sc, BUS_DMASYNC_PREWRITE); 2072 } 2073 2074 void 2075 siop_add_dev(sc, target, lun) 2076 struct siop_softc *sc; 2077 int target; 2078 int lun; 2079 { 2080 struct siop_lunsw *lunsw; 2081 struct siop_target *siop_target = 2082 (struct siop_target *)sc->sc_c.targets[target]; 2083 struct siop_lun *siop_lun = siop_target->siop_lun[lun]; 2084 int i, ntargets, buswidth; 2085 2086 if (siop_lun->reseloff > 0) 2087 return; 2088 lunsw = siop_target->lunsw; 2089 if ((lunsw->lunsw_off + lunsw->lunsw_size) < sc->script_free_lo) { 2090 /* 2091 * can't extend this slot. Probably not worth trying to deal 2092 * with this case 2093 */ 2094 #ifdef SIOP_DEBUG 2095 printf("%s:%d:%d: can't allocate a lun sw slot\n", 2096 sc->sc_c.sc_dev.dv_xname, target, lun); 2097 #endif 2098 return; 2099 } 2100 /* count how many free targets we still have to probe */ 2101 buswidth = (sc->sc_c.features & SF_BUS_WIDE) ? 16 : 8; 2102 ntargets = (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->bus->sb_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, 0); 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, 0); 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, sizeof *sdm); 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, sizeof *sdm); 2278 } 2279 2280