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