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