1 /* $NetBSD: siop2.c,v 1.25 2005/12/11 12:16:28 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Van Jacobson of Lawrence Berkeley Laboratory. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)siop.c 7.5 (Berkeley) 5/4/91 35 */ 36 37 /* 38 * Copyright (c) 1994,1998 Michael L. Hitch 39 * 40 * This code is derived from software contributed to Berkeley by 41 * Van Jacobson of Lawrence Berkeley Laboratory. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 55 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 56 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 57 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 61 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 * 63 * @(#)siop.c 7.5 (Berkeley) 5/4/91 64 */ 65 66 /* 67 * AMIGA 53C720/770 scsi adaptor driver 68 */ 69 70 #include "opt_ddb.h" 71 72 #include <sys/cdefs.h> 73 __KERNEL_RCSID(0, "$NetBSD: siop2.c,v 1.25 2005/12/11 12:16:28 christos Exp $"); 74 75 #include <sys/param.h> 76 #include <sys/systm.h> 77 #include <sys/device.h> 78 #include <sys/disklabel.h> 79 #include <sys/buf.h> 80 #include <sys/malloc.h> 81 82 #include <uvm/uvm_extern.h> 83 84 #include <dev/scsipi/scsi_all.h> 85 #include <dev/scsipi/scsipi_all.h> 86 #include <dev/scsipi/scsiconf.h> 87 #include <machine/cpu.h> 88 #ifdef __m68k__ 89 #include <m68k/include/cacheops.h> 90 #endif 91 #include <amiga/amiga/custom.h> 92 #include <amiga/amiga/isr.h> 93 94 #define ARCH_720 95 96 #include <amiga/dev/siopreg.h> 97 #include <amiga/dev/siopvar.h> 98 99 /* 100 * SCSI delays 101 * In u-seconds, primarily for state changes on the SPC. 102 */ 103 #define SCSI_CMD_WAIT 500000 /* wait per step of 'immediate' cmds */ 104 #define SCSI_DATA_WAIT 500000 /* wait per data in/out step */ 105 #define SCSI_INIT_WAIT 500000 /* wait per step (both) during init */ 106 107 void siopng_select(struct siop_softc *); 108 void siopngabort(struct siop_softc *, siop_regmap_p, const char *); 109 void siopngerror(struct siop_softc *, siop_regmap_p, u_char); 110 int siopng_checkintr(struct siop_softc *, u_char, u_char, u_short, int *); 111 void siopngreset(struct siop_softc *); 112 void siopngsetdelay(int); 113 void siopng_scsidone(struct siop_acb *, int); 114 void siopng_sched(struct siop_softc *); 115 void siopng_poll(struct siop_softc *, struct siop_acb *); 116 void siopngintr(struct siop_softc *); 117 void scsi_period_to_siopng(struct siop_softc *, int); 118 void siopng_start(struct siop_softc *, int, int, u_char *, int, u_char *, int); 119 void siopng_dump_acb(struct siop_acb *); 120 121 /* 53C720/770 script */ 122 123 #include <amiga/dev/siop2_script.out> 124 125 /* default to not inhibit sync negotiation on any drive */ 126 u_char siopng_inhibit_sync[16] = { 127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 128 }; /* initialize, so patchable */ 129 130 u_char siopng_inhibit_wide[16] = { 131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 132 }; /* initialize, so patchable */ 133 134 u_char siopng_allow_disc[16] = { 135 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 136 }; 137 138 int siopng_no_dma = 0; 139 140 int siopng_reset_delay = 250; /* delay after reset, in milleseconds */ 141 142 int siopng_cmd_wait = SCSI_CMD_WAIT; 143 int siopng_data_wait = SCSI_DATA_WAIT; 144 int siopng_init_wait = SCSI_INIT_WAIT; 145 146 #define DEBUG_SYNC 147 148 #ifdef DEBUG 149 /* 150 * 0x01 - full debug 151 * 0x02 - DMA chaining 152 * 0x04 - siopngintr 153 * 0x08 - phase mismatch 154 * 0x10 - <not used> 155 * 0x20 - panic on unhandled exceptions 156 * 0x100 - disconnect/reselect 157 */ 158 int siopng_debug = 0; 159 int siopngsync_debug = 0; 160 int siopngdma_hits = 0; 161 int siopngdma_misses = 0; 162 int siopngchain_ints = 0; 163 int siopngstarts = 0; 164 int siopngints = 0; 165 int siopngphmm = 0; 166 #define SIOP_TRACE_SIZE 128 167 #define SIOP_TRACE(a,b,c,d) \ 168 siopng_trbuf[siopng_trix] = (a); \ 169 siopng_trbuf[siopng_trix+1] = (b); \ 170 siopng_trbuf[siopng_trix+2] = (c); \ 171 siopng_trbuf[siopng_trix+3] = (d); \ 172 siopng_trix = (siopng_trix + 4) & (SIOP_TRACE_SIZE - 1); 173 u_char siopng_trbuf[SIOP_TRACE_SIZE]; 174 int siopng_trix; 175 void siopng_dump(struct siop_softc *); 176 void siopng_dump_trace(void); 177 #else 178 #define SIOP_TRACE(a,b,c,d) 179 #endif 180 181 182 static const char *siopng_chips[] = { 183 "720", "720SE", "770", "0x3", 184 "810A", "0x5", "0x6", "0x7", 185 "0x8", "0x9", "0xA", "0xB", 186 "0xC", "0xD", "0xE", "0xF", 187 }; 188 189 /* 190 * default minphys routine for siopng based controllers 191 */ 192 void 193 siopng_minphys(struct buf *bp) 194 { 195 196 /* 197 * No max transfer at this level. 198 */ 199 minphys(bp); 200 } 201 202 /* 203 * used by specific siopng controller 204 * 205 */ 206 void 207 siopng_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 208 void *arg) 209 { 210 struct scsipi_xfer *xs; 211 struct scsipi_periph *periph; 212 struct siop_acb *acb; 213 struct siop_softc *sc = (void *)chan->chan_adapter->adapt_dev; 214 int flags, s; 215 216 switch (req) { 217 case ADAPTER_REQ_RUN_XFER: 218 xs = arg; 219 periph = xs->xs_periph; 220 flags = xs->xs_control; 221 222 /* XXXX ?? */ 223 if (flags & XS_CTL_DATA_UIO) 224 panic("siopng: scsi data uio requested"); 225 226 /* XXXX ?? */ 227 if (sc->sc_nexus && flags & XS_CTL_POLL) 228 /* panic("siopng_scsicmd: busy");*/ 229 printf("siopng_scsicmd: busy\n"); 230 231 s = splbio(); 232 acb = sc->free_list.tqh_first; 233 if (acb) { 234 TAILQ_REMOVE(&sc->free_list, acb, chain); 235 } 236 splx(s); 237 238 #ifdef DIAGNOSTIC 239 /* 240 * This should never happen as we track the resources 241 * in the mid-layer. 242 */ 243 if (acb == NULL) { 244 scsipi_printaddr(periph); 245 printf("unable to allocate acb\n"); 246 panic("siopng_scsipi_request"); 247 } 248 #endif 249 acb->flags = ACB_ACTIVE; 250 acb->xs = xs; 251 bcopy(xs->cmd, &acb->cmd, xs->cmdlen); 252 acb->clen = xs->cmdlen; 253 acb->daddr = xs->data; 254 acb->dleft = xs->datalen; 255 256 s = splbio(); 257 TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain); 258 259 if (sc->sc_nexus == NULL) 260 siopng_sched(sc); 261 262 splx(s); 263 264 if (flags & XS_CTL_POLL || siopng_no_dma) 265 siopng_poll(sc, acb); 266 return; 267 268 case ADAPTER_REQ_GROW_RESOURCES: 269 return; 270 271 case ADAPTER_REQ_SET_XFER_MODE: 272 return; 273 } 274 } 275 276 void 277 siopng_poll(struct siop_softc *sc, struct siop_acb *acb) 278 { 279 siop_regmap_p rp = sc->sc_siopp; 280 struct scsipi_xfer *xs = acb->xs; 281 int i; 282 int status; 283 u_char istat; 284 u_char dstat; 285 u_short sist; 286 int s; 287 int to; 288 289 s = splbio(); 290 to = xs->timeout / 1000; 291 if (sc->nexus_list.tqh_first) 292 printf("%s: siopng_poll called with disconnected device\n", 293 sc->sc_dev.dv_xname); 294 for (;;) { 295 /* use cmd_wait values? */ 296 i = 50000; 297 /* XXX spl0(); */ 298 while (((istat = rp->siop_istat) & 299 (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) { 300 if (--i <= 0) { 301 #ifdef DEBUG 302 printf ("waiting: tgt %d cmd %02x sbcl %02x istat %02x sbdl %04x\n dsp %lx (+%lx) dcmd %lx ds %p timeout %d\n", 303 xs->xs_periph->periph_target, acb->cmd.opcode, 304 rp->siop_sbcl, istat, rp->siop_sbdl, rp->siop_dsp, 305 rp->siop_dsp - sc->sc_scriptspa, 306 *((long *)&rp->siop_dcmd), &acb->ds, acb->xs->timeout); 307 #endif 308 i = 50000; 309 --to; 310 if (to <= 0) { 311 siopngreset(sc); 312 return; 313 } 314 } 315 delay(20); 316 } 317 sist = rp->siop_sist; 318 dstat = rp->siop_dstat; 319 if (siopng_checkintr(sc, istat, dstat, sist, &status)) { 320 if (acb != sc->sc_nexus) 321 printf("%s: siopng_poll disconnected device completed\n", 322 sc->sc_dev.dv_xname); 323 else if ((sc->sc_flags & SIOP_INTDEFER) == 0) { 324 sc->sc_flags &= ~SIOP_INTSOFF; 325 rp->siop_sien = sc->sc_sien; 326 rp->siop_dien = sc->sc_dien; 327 } 328 siopng_scsidone(sc->sc_nexus, status); 329 } 330 if (xs->xs_status & XS_STS_DONE) 331 break; 332 } 333 splx(s); 334 } 335 336 /* 337 * start next command that's ready 338 */ 339 void 340 siopng_sched(struct siop_softc *sc) 341 { 342 struct scsipi_periph *periph; 343 struct siop_acb *acb; 344 int i; 345 346 #ifdef DEBUG 347 if (sc->sc_nexus) { 348 printf("%s: siopng_sched- nexus %p/%d ready %p/%d\n", 349 sc->sc_dev.dv_xname, sc->sc_nexus, 350 sc->sc_nexus->xs->xs_periph->periph_target, 351 sc->ready_list.tqh_first, 352 sc->ready_list.tqh_first->xs->xs_periph->periph_target); 353 return; 354 } 355 #endif 356 for (acb = sc->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) { 357 periph = acb->xs->xs_periph; 358 i = periph->periph_target; 359 if(!(sc->sc_tinfo[i].lubusy & (1 << periph->periph_lun))) { 360 struct siop_tinfo *ti = &sc->sc_tinfo[i]; 361 362 TAILQ_REMOVE(&sc->ready_list, acb, chain); 363 sc->sc_nexus = acb; 364 periph = acb->xs->xs_periph; 365 ti = &sc->sc_tinfo[periph->periph_target]; 366 ti->lubusy |= (1 << periph->periph_lun); 367 break; 368 } 369 } 370 371 if (acb == NULL) { 372 #ifdef DEBUGXXX 373 printf("%s: siopng_sched didn't find ready command\n", 374 sc->sc_dev.dv_xname); 375 #endif 376 return; 377 } 378 379 if (acb->xs->xs_control & XS_CTL_RESET) 380 siopngreset(sc); 381 382 #if 0 383 acb->cmd.bytes[0] |= periph->periph_lun << 5; /* XXXX */ 384 #endif 385 ++sc->sc_active; 386 siopng_select(sc); 387 } 388 389 void 390 siopng_scsidone(struct siop_acb *acb, int stat) 391 { 392 struct scsipi_xfer *xs; 393 struct scsipi_periph *periph; 394 struct siop_softc *sc; 395 int dosched = 0; 396 397 if (acb == NULL || (xs = acb->xs) == NULL) { 398 #ifdef DIAGNOSTIC 399 printf("siopng_scsidone: NULL acb or scsipi_xfer\n"); 400 #if defined(DEBUG) && defined(DDB) 401 Debugger(); 402 #endif 403 #endif 404 return; 405 } 406 periph = xs->xs_periph; 407 sc = (void *)periph->periph_channel->chan_adapter->adapt_dev; 408 409 xs->status = stat; 410 xs->resid = 0; /* XXXX */ 411 412 if (xs->error == XS_NOERROR) { 413 if (stat == SCSI_CHECK || stat == SCSI_BUSY) 414 xs->error = XS_BUSY; 415 } 416 417 /* 418 * Remove the ACB from whatever queue it's on. We have to do a bit of 419 * a hack to figure out which queue it's on. Note that it is *not* 420 * necessary to cdr down the ready queue, but we must cdr down the 421 * nexus queue and see if it's there, so we can mark the unit as no 422 * longer busy. This code is sickening, but it works. 423 */ 424 if (acb == sc->sc_nexus) { 425 sc->sc_nexus = NULL; 426 sc->sc_tinfo[periph->periph_target].lubusy &= 427 ~(1<<periph->periph_lun); 428 if (sc->ready_list.tqh_first) 429 dosched = 1; /* start next command */ 430 --sc->sc_active; 431 SIOP_TRACE('d','a',stat,0) 432 } else if (sc->ready_list.tqh_last == &acb->chain.tqe_next) { 433 TAILQ_REMOVE(&sc->ready_list, acb, chain); 434 SIOP_TRACE('d','r',stat,0) 435 } else { 436 register struct siop_acb *acb2; 437 for (acb2 = sc->nexus_list.tqh_first; acb2; 438 acb2 = acb2->chain.tqe_next) 439 if (acb2 == acb) { 440 TAILQ_REMOVE(&sc->nexus_list, acb, chain); 441 sc->sc_tinfo[periph->periph_target].lubusy 442 &= ~(1<<periph->periph_lun); 443 --sc->sc_active; 444 break; 445 } 446 if (acb2) 447 ; 448 else if (acb->chain.tqe_next) { 449 TAILQ_REMOVE(&sc->ready_list, acb, chain); 450 --sc->sc_active; 451 } else { 452 printf("%s: can't find matching acb\n", 453 sc->sc_dev.dv_xname); 454 #ifdef DDB 455 /* Debugger(); */ 456 #endif 457 } 458 SIOP_TRACE('d','n',stat,0); 459 } 460 /* Put it on the free list. */ 461 acb->flags = ACB_FREE; 462 TAILQ_INSERT_HEAD(&sc->free_list, acb, chain); 463 464 sc->sc_tinfo[periph->periph_target].cmds++; 465 466 scsipi_done(xs); 467 468 if (dosched && sc->sc_nexus == NULL) 469 siopng_sched(sc); 470 } 471 472 void 473 siopngabort(register struct siop_softc *sc, siop_regmap_p rp, const char *where) 474 { 475 #ifdef fix_this 476 int i; 477 #endif 478 479 printf ("%s: abort %s: dstat %02x, istat %02x sist %04x sien %04x sbcl %02x\n", 480 sc->sc_dev.dv_xname, 481 where, rp->siop_dstat, rp->siop_istat, rp->siop_sist, 482 rp->siop_sien, rp->siop_sbcl); 483 siopng_dump_registers(sc); 484 485 if (sc->sc_active > 0) { 486 #ifdef TODO 487 SET_SBIC_cmd (rp, SBIC_CMD_ABORT); 488 WAIT_CIP (rp); 489 490 GET_SBIC_asr (rp, asr); 491 if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) 492 { 493 /* ok, get more drastic.. */ 494 495 SET_SBIC_cmd (rp, SBIC_CMD_RESET); 496 delay(25); 497 SBIC_WAIT(rp, SBIC_ASR_INT, 0); 498 GET_SBIC_csr (rp, csr); /* clears interrupt also */ 499 500 return; 501 } 502 503 do 504 { 505 SBIC_WAIT (rp, SBIC_ASR_INT, 0); 506 GET_SBIC_csr (rp, csr); 507 } 508 while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) 509 && (csr != SBIC_CSR_CMD_INVALID)); 510 #endif 511 512 /* lets just hope it worked.. */ 513 #ifdef fix_this 514 for (i = 0; i < 2; ++i) { 515 if (sc->sc_iob[i].sc_xs && &sc->sc_iob[i] != 516 sc->sc_cur) { 517 printf ("siopngabort: cleanup!\n"); 518 sc->sc_iob[i].sc_xs = NULL; 519 } 520 } 521 #endif /* fix_this */ 522 /* sc->sc_active = 0; */ 523 } 524 } 525 526 void 527 siopnginitialize(struct siop_softc *sc) 528 { 529 int i; 530 u_int inhibit_sync; 531 extern u_long scsi_nosync; 532 extern int shift_nosync; 533 534 /* 535 * Need to check that scripts is on a long word boundary 536 * Also should verify that dev doesn't span non-contiguous 537 * physical pages. 538 */ 539 sc->sc_scriptspa = kvtop((caddr_t)__UNCONST(siopng_scripts)); 540 541 /* 542 * malloc sc_acb to ensure that DS is on a long word boundary. 543 */ 544 545 MALLOC(sc->sc_acb, struct siop_acb *, 546 sizeof(struct siop_acb) * SIOP_NACB, M_DEVBUF, M_NOWAIT); 547 if (sc->sc_acb == NULL) 548 panic("siopnginitialize: ACB malloc failed!"); 549 550 sc->sc_tcp[1] = 1000 / sc->sc_clock_freq; 551 sc->sc_tcp[2] = 1500 / sc->sc_clock_freq; 552 sc->sc_tcp[3] = 2000 / sc->sc_clock_freq; 553 sc->sc_minsync = sc->sc_tcp[1]; /* in 4ns units */ 554 if (sc->sc_minsync < 25) 555 sc->sc_minsync = 25; 556 sc->sc_minsync >>= 1; /* Using clock doubler, allow Ultra */ 557 if (sc->sc_clock_freq <= 25) { 558 sc->sc_dcntl |= 0x80; /* SCLK/1 */ 559 sc->sc_tcp[0] = sc->sc_tcp[1]; 560 } else if (sc->sc_clock_freq <= 37) { 561 sc->sc_dcntl |= 0x40; /* SCLK/1.5 */ 562 sc->sc_tcp[0] = sc->sc_tcp[2]; 563 } else if (sc->sc_clock_freq <= 50) { 564 sc->sc_dcntl |= 0x00; /* SCLK/2 */ 565 sc->sc_tcp[0] = sc->sc_tcp[3]; 566 } else { 567 sc->sc_dcntl |= 0xc0; /* SCLK/3 */ 568 sc->sc_tcp[0] = 3000 / sc->sc_clock_freq; 569 } 570 571 if (scsi_nosync) { 572 inhibit_sync = (scsi_nosync >> shift_nosync) & 0xffff; 573 shift_nosync += 16; /* XXX maxtarget */ 574 #ifdef DEBUG 575 if (inhibit_sync) 576 printf("%s: Inhibiting synchronous transfer %02x\n", 577 sc->sc_dev.dv_xname, inhibit_sync); 578 #endif 579 for (i = 0; i < 16; ++i) /* XXX maxtarget */ 580 if (inhibit_sync & (1 << i)) 581 siopng_inhibit_sync[i] = 1; 582 } 583 584 siopngreset (sc); 585 } 586 587 void 588 siopngreset(struct siop_softc *sc) 589 { 590 siop_regmap_p rp; 591 u_int i, s; 592 u_short dummy; 593 struct siop_acb *acb; 594 595 rp = sc->sc_siopp; 596 597 if (sc->sc_flags & SIOP_ALIVE) 598 siopngabort(sc, rp, "reset"); 599 600 printf("%s: ", sc->sc_dev.dv_xname); /* XXXX */ 601 602 s = splbio(); 603 604 /* 605 * Reset the chip 606 * XXX - is this really needed? 607 */ 608 rp->siop_istat |= SIOP_ISTAT_ABRT; /* abort current script */ 609 rp->siop_istat |= SIOP_ISTAT_RST; /* reset chip */ 610 rp->siop_istat &= ~SIOP_ISTAT_RST; 611 /* 612 * Reset SCSI bus (do we really want this?) 613 */ 614 rp->siop_sien = 0; 615 rp->siop_scntl1 |= SIOP_SCNTL1_RST; 616 delay(1); 617 rp->siop_scntl1 &= ~SIOP_SCNTL1_RST; 618 619 /* 620 * Set up various chip parameters 621 */ 622 rp->siop_stest1 |= SIOP_STEST1_DBLEN; /* SCLK doubler enable */ 623 delay(20); 624 rp->siop_stest3 |= SIOP_STEST3_HSC; /* Halt SCSI clock */ 625 rp->siop_scntl3 = 0x15; /* SCF/CCF*/ 626 rp->siop_stest1 |= SIOP_STEST1_DBLSEL; /* SCLK doubler select */ 627 rp->siop_stest3 &= ~SIOP_STEST3_HSC; /* Clear Halt SCSI clock */ 628 rp->siop_scntl0 = SIOP_ARB_FULL | /*SIOP_SCNTL0_EPC |*/ SIOP_SCNTL0_EPG; 629 rp->siop_dcntl = sc->sc_dcntl; 630 rp->siop_dmode = 0xc0; /* XXX burst length */ 631 rp->siop_sien = 0x00; /* don't enable interrupts yet */ 632 rp->siop_dien = 0x00; /* don't enable interrupts yet */ 633 rp->siop_scid = sc->sc_channel.chan_id | 634 SIOP_SCID_RRE | SIOP_SCID_SRE; 635 rp->siop_respid = 1 << sc->sc_channel.chan_id; 636 rp->siop_dwt = 0x00; 637 rp->siop_stime0 = 0x0c; /* XXXXX check */ 638 639 /* will need to re-negotiate sync xfers */ 640 bzero(&sc->sc_sync, sizeof (sc->sc_sync)); 641 642 i = rp->siop_istat; 643 if (i & SIOP_ISTAT_SIP) 644 dummy = rp->siop_sist; 645 if (i & SIOP_ISTAT_DIP) 646 dummy = rp->siop_dstat; 647 648 splx (s); 649 650 delay (siopng_reset_delay * 1000); 651 652 /* 653 * is lower half unterminated? 654 */ 655 if ((rp->siop_sbdl & 0x00ff) == 0x00ff) { 656 printf(" no SCSI termination, host adapter deactivated.\n"); 657 sc->sc_channel.chan_ntargets = 0; /* XXX */ 658 sc->sc_flags &= ~(SIOP_ALIVE|SIOP_INTDEFER|SIOP_INTSOFF); 659 /* disable SCSI and DMA interrupts */ 660 sc->sc_sien = 0; 661 sc->sc_dien = 0; 662 rp->siop_sien = sc->sc_sien; 663 rp->siop_dien = sc->sc_dien; 664 665 return; 666 } 667 668 /* 669 * Check if upper half of SCSI bus is unterminated, and disallow 670 * disconnections if it appears to be unterminated. 671 */ 672 if ((rp->siop_sbdl & 0xff00) == 0xff00) { 673 printf(" NO WIDE TERM"); 674 /* XXX need to restrict maximum target ID as well? */ 675 sc->sc_channel.chan_ntargets = 8; 676 for (i = 0; i < 16; ++i) { 677 siopng_allow_disc[i] = 0; 678 siopng_inhibit_wide[i] |= 0x80; 679 } 680 } 681 682 printf("siopng type %s id %d reset V%d\n", 683 siopng_chips[rp->siop_macntl>>4], 684 sc->sc_channel.chan_ntargets, 685 rp->siop_ctest3 >> 4); 686 687 if ((sc->sc_flags & SIOP_ALIVE) == 0) { 688 TAILQ_INIT(&sc->ready_list); 689 TAILQ_INIT(&sc->nexus_list); 690 TAILQ_INIT(&sc->free_list); 691 sc->sc_nexus = NULL; 692 acb = sc->sc_acb; 693 bzero(acb, sizeof(struct siop_acb) * SIOP_NACB); 694 for (i = 0; i < SIOP_NACB; i++) { 695 TAILQ_INSERT_TAIL(&sc->free_list, acb, chain); 696 acb++; 697 } 698 bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo)); 699 } else { 700 if (sc->sc_nexus != NULL) { 701 sc->sc_nexus->xs->error = XS_RESET; 702 siopng_scsidone(sc->sc_nexus, sc->sc_nexus->stat[0]); 703 } 704 while ((acb = sc->nexus_list.tqh_first) > 0) { 705 acb->xs->error = XS_RESET; 706 siopng_scsidone(acb, acb->stat[0]); 707 } 708 } 709 710 sc->sc_flags |= SIOP_ALIVE; 711 sc->sc_flags &= ~(SIOP_INTDEFER|SIOP_INTSOFF); 712 /* enable SCSI and DMA interrupts */ 713 sc->sc_sien = SIOP_SIEN_MA | SIOP_SIEN_STO | /*SIOP_SIEN_GEN |*/ 714 /*SIOP_SIEN_SEL |*/ SIOP_SIEN_SGE | SIOP_SIEN_UDC | 715 SIOP_SIEN_RST | SIOP_SIEN_PAR; 716 sc->sc_dien = SIOP_DIEN_BF | SIOP_DIEN_ABRT | SIOP_DIEN_SIR | 717 /*SIOP_DIEN_WTD |*/ SIOP_DIEN_IID; 718 rp->siop_sien = sc->sc_sien; 719 rp->siop_dien = sc->sc_dien; 720 /*siopng_dump_registers(sc);*/ 721 } 722 723 /* 724 * Setup Data Storage for 53C720/770 and start SCRIPTS processing 725 */ 726 727 void 728 siopng_start(struct siop_softc *sc, int target, int lun, u_char *cbuf, 729 int clen, u_char *buf, int len) 730 { 731 siop_regmap_p rp = sc->sc_siopp; 732 int nchain; 733 int count, tcount; 734 char *addr, *dmaend; 735 struct siop_acb *acb = sc->sc_nexus; 736 #ifdef DEBUG 737 int i; 738 #endif 739 740 #ifdef DEBUG 741 if (siopng_debug & 0x100 && rp->siop_sbcl & SIOP_BSY) { 742 printf ("ACK! siopng was busy: rp %p script %p dsa %p active %ld\n", 743 rp, &siopng_scripts, &acb->ds, sc->sc_active); 744 printf ("istat %02x sfbr %02x respid %02x sien %04x dien %02x\n", 745 rp->siop_istat, rp->siop_sfbr, rp->siop_respid, 746 rp->siop_sien, rp->siop_dien); 747 #ifdef DDB 748 /*Debugger();*/ 749 #endif 750 } 751 #endif 752 acb->msgout[0] = MSG_IDENTIFY | lun; 753 if (siopng_allow_disc[target] & 2 || 754 (siopng_allow_disc[target] && len == 0)) 755 acb->msgout[0] = MSG_IDENTIFY_DR | lun; 756 acb->status = 0; 757 acb->stat[0] = -1; 758 acb->msg[0] = -1; 759 acb->ds.scsi_addr = (target << 16) | (sc->sc_sync[target].sxfer << 8) | 760 (sc->sc_sync[target].scntl3 << 24); 761 acb->ds.idlen = 1; 762 acb->ds.idbuf = (char *) kvtop(&acb->msgout[0]); 763 acb->ds.cmdlen = clen; 764 acb->ds.cmdbuf = (char *) kvtop(cbuf); 765 acb->ds.stslen = 1; 766 acb->ds.stsbuf = (char *) kvtop(&acb->stat[0]); 767 acb->ds.msglen = 1; 768 acb->ds.msgbuf = (char *) kvtop(&acb->msg[0]); 769 acb->msg[1] = -1; 770 acb->ds.msginlen = 1; 771 acb->ds.extmsglen = 1; 772 acb->ds.synmsglen = 3; 773 acb->ds.msginbuf = acb->ds.msgbuf + 1; 774 acb->ds.extmsgbuf = acb->ds.msginbuf + 1; 775 acb->ds.synmsgbuf = acb->ds.extmsgbuf + 1; 776 bzero(&acb->ds.chain, sizeof (acb->ds.chain)); 777 778 if (sc->sc_sync[target].state == NEG_WIDE) { 779 if (siopng_inhibit_wide[target]) { 780 sc->sc_sync[target].state = NEG_SYNC; 781 sc->sc_sync[target].scntl3 &= ~SIOP_SCNTL3_EWS; 782 #ifdef DEBUG 783 if (siopngsync_debug) 784 printf ("Forcing target %d narrow\n", target); 785 #endif 786 } 787 else { 788 sc->sc_sync[target].scntl3 = 0x15 | /* XXX */ 789 (sc->sc_sync[target].scntl3 & 0x88); /* XXX */ 790 acb->msg[2] = -1; 791 acb->msgout[1] = MSG_EXT_MESSAGE; 792 acb->msgout[2] = 2; 793 acb->msgout[3] = MSG_WIDE_REQ; 794 acb->msgout[4] = 1; 795 acb->ds.idlen = 5; 796 acb->ds.synmsglen = 2; 797 sc->sc_sync[target].state = NEG_WAITW; 798 #ifdef DEBUG 799 if (siopngsync_debug) 800 printf("Sending wide request to target %d\n", target); 801 #endif 802 } 803 } 804 if (sc->sc_sync[target].state == NEG_SYNC) { 805 if (siopng_inhibit_sync[target]) { 806 sc->sc_sync[target].state = NEG_DONE; 807 sc->sc_sync[target].scntl3 = 5 | /* XXX */ 808 (sc->sc_sync[target].scntl3 & 0x88); /* XXX */ 809 sc->sc_sync[target].sxfer = 0; 810 #ifdef DEBUG 811 if (siopngsync_debug) 812 printf ("Forcing target %d asynchronous\n", target); 813 #endif 814 } 815 else { 816 sc->sc_sync[target].scntl3 = 0x15 | /* XXX */ 817 (sc->sc_sync[target].scntl3 & 0x88); /* XXX */ 818 acb->msg[2] = -1; 819 acb->msgout[1] = MSG_EXT_MESSAGE; 820 acb->msgout[2] = 3; 821 acb->msgout[3] = MSG_SYNC_REQ; 822 #ifdef MAXTOR_SYNC_KLUDGE 823 acb->msgout[4] = 50 / 4; /* ask for ridiculous period */ 824 #else 825 acb->msgout[4] = sc->sc_minsync; 826 #endif 827 acb->msgout[5] = SIOP_MAX_OFFSET; 828 acb->ds.idlen = 6; 829 sc->sc_sync[target].state = NEG_WAITS; 830 #ifdef DEBUG 831 if (siopngsync_debug) 832 printf ("Sending sync request to target %d\n", target); 833 #endif 834 } 835 } 836 837 /* 838 * Build physical DMA addresses for scatter/gather I/O 839 */ 840 acb->iob_buf = buf; 841 acb->iob_len = len; 842 acb->iob_curbuf = acb->iob_curlen = 0; 843 nchain = 0; 844 count = len; 845 addr = buf; 846 dmaend = NULL; 847 while (count > 0) { 848 acb->ds.chain[nchain].databuf = (char *) kvtop (addr); 849 if (count < (tcount = PAGE_SIZE - ((int) addr & PGOFSET))) 850 tcount = count; 851 852 #if DEBUG_ONLY_IF_DESPERATE 853 printf("chain[%d]: count %d tcount %d vaddr %p paddr %p\n", 854 nchain, count, tcount, addr, 855 acb->ds.chain[nchain].databuf); 856 #endif 857 acb->ds.chain[nchain].datalen = tcount; 858 addr += tcount; 859 count -= tcount; 860 if (acb->ds.chain[nchain].databuf == dmaend) { 861 dmaend += acb->ds.chain[nchain].datalen; 862 acb->ds.chain[nchain].datalen = 0; 863 acb->ds.chain[--nchain].datalen += tcount; 864 #ifdef DEBUG 865 ++siopngdma_hits; 866 #endif 867 } 868 else { 869 dmaend = acb->ds.chain[nchain].databuf + 870 acb->ds.chain[nchain].datalen; 871 acb->ds.chain[nchain].datalen = tcount; 872 #ifdef DEBUG 873 if (nchain) /* Don't count miss on first one */ 874 ++siopngdma_misses; 875 #endif 876 } 877 ++nchain; 878 } 879 #ifdef DEBUG 880 if (nchain != 1 && len != 0 && siopng_debug & 3) { 881 printf ("DMA chaining set: %d\n", nchain); 882 for (i = 0; i < nchain; ++i) { 883 printf (" [%d] %8p %lx\n", i, acb->ds.chain[i].databuf, 884 acb->ds.chain[i].datalen); 885 } 886 } 887 #endif 888 889 /* push data cache for all data the 53c720/770 needs to access */ 890 dma_cachectl ((caddr_t)acb, sizeof (struct siop_acb)); 891 dma_cachectl (cbuf, clen); 892 if (buf != NULL && len != 0) 893 dma_cachectl (buf, len); 894 #ifdef DEBUG 895 if (siopng_debug & 0x100 && rp->siop_sbcl & SIOP_BSY) { 896 printf ("ACK! siopng was busy at start: rp %p script %p dsa %p active %ld\n", 897 rp, &siopng_scripts, &acb->ds, sc->sc_active); 898 #ifdef DDB 899 /*Debugger();*/ 900 #endif 901 } 902 #endif 903 if (sc->nexus_list.tqh_first == NULL) { 904 if (rp->siop_istat & SIOP_ISTAT_CON) 905 printf("%s: siopng_select while connected?\n", 906 sc->sc_dev.dv_xname); 907 rp->siop_temp = 0; 908 #ifndef FIXME 909 rp->siop_scntl3 = sc->sc_sync[target].scntl3; 910 #endif 911 rp->siop_dsa = kvtop((caddr_t)&acb->ds); 912 rp->siop_dsp = sc->sc_scriptspa; 913 SIOP_TRACE('s',1,0,0) 914 } else { 915 if ((rp->siop_istat & SIOP_ISTAT_CON) == 0) { 916 rp->siop_istat = SIOP_ISTAT_SIGP; 917 SIOP_TRACE('s',2,0,0); 918 } 919 else { 920 SIOP_TRACE('s',3,rp->siop_istat,0); 921 } 922 } 923 #ifdef DEBUG 924 ++siopngstarts; 925 #endif 926 } 927 928 /* 929 * Process a DMA or SCSI interrupt from the 53C720/770 SIOP 930 */ 931 932 int 933 siopng_checkintr(struct siop_softc *sc, u_char istat, u_char dstat, 934 u_short sist, int *status) 935 { 936 siop_regmap_p rp = sc->sc_siopp; 937 struct siop_acb *acb = sc->sc_nexus; 938 int target = 0; 939 int dfifo, dbc, sstat0, sstat1, sstat2; 940 941 dfifo = rp->siop_dfifo; 942 dbc = rp->siop_dbc0; 943 sstat0 = rp->siop_sstat0; 944 sstat1 = rp->siop_sstat1; 945 sstat2 = rp->siop_sstat2; 946 rp->siop_ctest3 |= SIOP_CTEST8_CLF; 947 while ((rp->siop_ctest1 & SIOP_CTEST1_FMT) != SIOP_CTEST1_FMT) 948 ; 949 rp->siop_ctest3 &= ~SIOP_CTEST8_CLF; 950 #ifdef DEBUG 951 ++siopngints; 952 #if 0 953 if (siopng_debug & 0x100) { 954 DCIAS(&acb->stat[0]); /* XXX */ 955 printf ("siopngchkintr: istat %x dstat %x sist %x dsps %x sbcl %x sts %x msg %x\n", 956 istat, dstat, sist, rp->siop_dsps, rp->siop_sbcl, acb->stat[0], acb->msg[0]); 957 printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n", 958 acb->msg[0], acb->msg[1], acb->msg[2], 959 acb->msg[3], acb->msg[4], acb->msg[5]); 960 } 961 #endif 962 if (rp->siop_dsp && (rp->siop_dsp < sc->sc_scriptspa || 963 rp->siop_dsp >= sc->sc_scriptspa + sizeof(siopng_scripts))) { 964 printf ("%s: dsp not within script dsp %lx scripts %lx:%lx", 965 sc->sc_dev.dv_xname, rp->siop_dsp, sc->sc_scriptspa, 966 sc->sc_scriptspa + sizeof(siopng_scripts)); 967 printf(" istat %x dstat %x sist %x\n", 968 istat, dstat, sist); 969 #ifdef DDB 970 Debugger(); 971 #endif 972 } 973 #endif 974 SIOP_TRACE('i',dstat,istat,(istat&SIOP_ISTAT_DIP)?rp->siop_dsps&0xff:sist); 975 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff00) { 976 /* Normal completion status, or check condition */ 977 #ifdef DEBUG 978 if (rp->siop_dsa != kvtop((caddr_t)&acb->ds)) { 979 printf ("siopng: invalid dsa: %lx %x\n", rp->siop_dsa, 980 kvtop((caddr_t)&acb->ds)); 981 panic("*** siopng DSA invalid ***"); 982 } 983 #endif 984 target = acb->xs->xs_periph->periph_target; 985 if (sc->sc_sync[target].state == NEG_WAITW) { 986 if (acb->msg[1] == 0xff) 987 printf ("%s: target %d ignored wide request\n", 988 sc->sc_dev.dv_xname, target); 989 else if (acb->msg[1] == MSG_REJECT) 990 printf ("%s: target %d rejected wide request\n", 991 sc->sc_dev.dv_xname, target); 992 else { 993 printf("%s: target %d (wide) %02x %02x %02x %02x\n", 994 sc->sc_dev.dv_xname, target, acb->msg[1], 995 acb->msg[2], acb->msg[3], acb->msg[4]); 996 if (acb->msg[1] == MSG_EXT_MESSAGE && 997 acb->msg[2] == 2 && 998 acb->msg[3] == MSG_WIDE_REQ) 999 sc->sc_sync[target].scntl3 = acb->msg[4] ? 1000 sc->sc_sync[target].scntl3 | SIOP_SCNTL3_EWS : 1001 sc->sc_sync[target].scntl3 & ~SIOP_SCNTL3_EWS; 1002 } 1003 sc->sc_sync[target].state = NEG_SYNC; 1004 } 1005 if (sc->sc_sync[target].state == NEG_WAITS) { 1006 if (acb->msg[1] == 0xff) 1007 printf ("%s: target %d ignored sync request\n", 1008 sc->sc_dev.dv_xname, target); 1009 else if (acb->msg[1] == MSG_REJECT) 1010 printf ("%s: target %d rejected sync request\n", 1011 sc->sc_dev.dv_xname, target); 1012 else 1013 /* XXX - need to set sync transfer parameters */ 1014 printf("%s: target %d (sync) %02x %02x %02x\n", 1015 sc->sc_dev.dv_xname, target, acb->msg[1], 1016 acb->msg[2], acb->msg[3]); 1017 sc->sc_sync[target].state = NEG_DONE; 1018 } 1019 dma_cachectl(&acb->stat[0], 1); 1020 *status = acb->stat[0]; 1021 #ifdef DEBUG 1022 if (rp->siop_sbcl & SIOP_BSY) { 1023 /*printf ("ACK! siop was busy at end: rp %x script %x dsa %x\n", 1024 rp, &siopng_scripts, &acb->ds);*/ 1025 #ifdef DDB 1026 /*Debugger();*/ 1027 #endif 1028 } 1029 if (acb->msg[0] != 0x00) 1030 printf("%s: message was not COMMAND COMPLETE: %x\n", 1031 sc->sc_dev.dv_xname, acb->msg[0]); 1032 #endif 1033 if (sc->nexus_list.tqh_first) 1034 rp->siop_dcntl |= SIOP_DCNTL_STD; 1035 return 1; 1036 } 1037 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff0b) { 1038 target = acb->xs->xs_periph->periph_target; 1039 if (acb->msg[1] == MSG_EXT_MESSAGE && acb->msg[2] == 2 && 1040 acb->msg[3] == MSG_WIDE_REQ) { 1041 #ifdef DEBUG 1042 if (siopngsync_debug) 1043 printf ("wide msg in: %02x %02x %02x %02x %02x %02x\n", 1044 acb->msg[0], acb->msg[1], acb->msg[2], 1045 acb->msg[3], acb->msg[4], acb->msg[5]); 1046 #endif 1047 sc->sc_sync[target].scntl3 &= ~(SIOP_SCNTL3_EWS); 1048 if (acb->msg[2] == 2 && 1049 acb->msg[3] == MSG_WIDE_REQ && 1050 acb->msg[4] != 0) { 1051 sc->sc_sync[target].scntl3 |= SIOP_SCNTL3_EWS; 1052 printf ("%s: target %d now wide %d\n", 1053 sc->sc_dev.dv_xname, target, 1054 acb->msg[4]); 1055 } 1056 rp->siop_scntl3 = sc->sc_sync[target].scntl3; 1057 if (sc->sc_sync[target].state == NEG_WAITW) { 1058 sc->sc_sync[target].state = NEG_SYNC; 1059 rp->siop_dsp = sc->sc_scriptspa + Ent_clear_ack; 1060 return(0); 1061 } 1062 rp->siop_dcntl |= SIOP_DCNTL_STD; 1063 sc->sc_sync[target].state = NEG_SYNC; 1064 return (0); 1065 } 1066 if (acb->msg[1] == MSG_EXT_MESSAGE && acb->msg[2] == 3 && 1067 acb->msg[3] == MSG_SYNC_REQ) { 1068 #ifdef DEBUG 1069 if (siopngsync_debug) 1070 printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n", 1071 acb->msg[0], acb->msg[1], acb->msg[2], 1072 acb->msg[3], acb->msg[4], acb->msg[5]); 1073 #endif 1074 sc->sc_sync[target].sxfer = 0; 1075 sc->sc_sync[target].scntl3 = 5 | /* XXX */ 1076 (sc->sc_sync[target].scntl3 & 0x88); /* XXX */ 1077 if (acb->msg[2] == 3 && 1078 acb->msg[3] == MSG_SYNC_REQ && 1079 acb->msg[5] != 0) { 1080 #ifdef MAXTOR_KLUDGE 1081 /* 1082 * Kludge for my Maxtor XT8580S 1083 * It accepts whatever we request, even 1084 * though it won't work. So we ask for 1085 * a short period than we can handle. If 1086 * the device says it can do it, use 208ns. 1087 * If the device says it can do less than 1088 * 100ns, then we limit it to 100ns. 1089 */ 1090 if (acb->msg[4] && acb->msg[4] < 100 / 4) { 1091 #ifdef DEBUG 1092 printf ("%d: target %d wanted %dns period\n", 1093 sc->sc_dev.dv_xname, target, 1094 acb->msg[4] * 4); 1095 #endif 1096 if (acb->msg[4] == 50 / 4) 1097 acb->msg[4] = 208 / 4; 1098 else 1099 acb->msg[4] = 100 / 4; 1100 } 1101 #endif /* MAXTOR_KLUDGE */ 1102 printf ("%s: target %d now synchronous, period=%dns, offset=%d\n", 1103 sc->sc_dev.dv_xname, target, 1104 (acb->msg[4] == 12) ? 50 : acb->msg[4] * 4, 1105 acb->msg[5]); 1106 scsi_period_to_siopng (sc, target); 1107 } 1108 rp->siop_sxfer = sc->sc_sync[target].sxfer; 1109 rp->siop_scntl3 = sc->sc_sync[target].scntl3; 1110 if (sc->sc_sync[target].state == NEG_WAITS) { 1111 sc->sc_sync[target].state = NEG_DONE; 1112 rp->siop_dsp = sc->sc_scriptspa + Ent_clear_ack; 1113 return(0); 1114 } 1115 rp->siop_dcntl |= SIOP_DCNTL_STD; 1116 sc->sc_sync[target].state = NEG_DONE; 1117 return (0); 1118 } 1119 /* XXX - not SDTR message */ 1120 } 1121 if (sist & SIOP_SIST_MA) { /* Phase mismatch */ 1122 #ifdef DEBUG 1123 ++siopngphmm; 1124 if (acb == NULL) 1125 printf("%s: Phase mismatch with no active command?\n", 1126 sc->sc_dev.dv_xname); 1127 #endif 1128 if (acb->iob_len) { 1129 int adjust; 1130 adjust = ((dfifo - (dbc & 0x7f)) & 0x7f); 1131 if (sstat0 & SIOP_SSTAT0_OLF) /* sstat0 SODL lsb */ 1132 ++adjust; 1133 if (sstat0 & SIOP_SSTAT0_ORF) /* sstat0 SODR lsb */ 1134 ++adjust; 1135 if (sstat2 & SIOP_SSTAT2_OLF1) /* sstat2 SODL msb */ 1136 ++adjust; 1137 if (sstat2 & SIOP_SSTAT2_ORF1) /* sstat2 SODR msb */ 1138 ++adjust; 1139 acb->iob_curlen = 1140 *((long *)__UNVOLATILE(&rp->siop_dcmd)) & 0xffffff; 1141 acb->iob_curlen += adjust; 1142 acb->iob_curbuf = 1143 *((long *)__UNVOLATILE(&rp->siop_dnad)) - adjust; 1144 #ifdef DEBUG 1145 if (siopng_debug & 0x100) { 1146 int i; 1147 printf ("Phase mismatch: curbuf %lx curlen %lx dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %p\n", 1148 acb->iob_curbuf, acb->iob_curlen, dfifo, 1149 dbc, sstat1, adjust, rp->siop_sbcl, siopngstarts, acb); 1150 if (acb->ds.chain[1].datalen) { 1151 for (i = 0; acb->ds.chain[i].datalen; ++i) 1152 printf("chain[%d] addr %p len %lx\n", 1153 i, acb->ds.chain[i].databuf, 1154 acb->ds.chain[i].datalen); 1155 } 1156 } 1157 #endif 1158 dma_cachectl ((caddr_t)acb, sizeof(*acb)); 1159 } 1160 #ifdef DEBUG 1161 SIOP_TRACE('m',rp->siop_sbcl,(rp->siop_dsp>>8),rp->siop_dsp); 1162 if (siopng_debug & 9) 1163 printf ("Phase mismatch: %x dsp +%lx dcmd %lx\n", 1164 rp->siop_sbcl, 1165 rp->siop_dsp - sc->sc_scriptspa, 1166 *((long *)&rp->siop_dcmd)); 1167 #endif 1168 if ((rp->siop_sbcl & SIOP_REQ) == 0) { 1169 printf ("Phase mismatch: REQ not asserted! %02x dsp %lx\n", 1170 rp->siop_sbcl, rp->siop_dsp); 1171 #if defined(DEBUG) && defined(DDB) 1172 Debugger(); 1173 #endif 1174 } 1175 switch (rp->siop_sbcl & 7) { 1176 case 0: /* data out */ 1177 case 1: /* data in */ 1178 case 2: /* status */ 1179 case 3: /* command */ 1180 case 6: /* message in */ 1181 case 7: /* message out */ 1182 rp->siop_dsp = sc->sc_scriptspa + Ent_switch; 1183 break; 1184 default: 1185 goto bad_phase; 1186 } 1187 return 0; 1188 } 1189 if (sist & SIOP_SIST_STO) { /* Select timed out */ 1190 #ifdef DEBUG 1191 if (acb == NULL) 1192 printf("%s: Select timeout with no active command?\n", 1193 sc->sc_dev.dv_xname); 1194 if (rp->siop_sbcl & SIOP_BSY) { 1195 printf ("ACK! siop was busy at timeout: rp %p script %p dsa %p\n", 1196 rp, &siopng_scripts, &acb->ds); 1197 printf(" sbcl %x sdid %x istat %x dstat %x sist %x\n", 1198 rp->siop_sbcl, rp->siop_sdid, istat, dstat, sist); 1199 if (!(rp->siop_sbcl & SIOP_BSY)) { 1200 printf ("Yikes, it's not busy now!\n"); 1201 #if 0 1202 *status = -1; 1203 if (sc->nexus_list.tqh_first) 1204 rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; 1205 return 1; 1206 #endif 1207 } 1208 /* rp->siop_dcntl |= SIOP_DCNTL_STD;*/ 1209 return (0); 1210 #ifdef DDB 1211 Debugger(); 1212 #endif 1213 } 1214 #endif 1215 *status = -1; 1216 acb->xs->error = XS_SELTIMEOUT; 1217 if (sc->nexus_list.tqh_first) 1218 rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; 1219 return 1; 1220 } 1221 if (acb) 1222 target = acb->xs->xs_periph->periph_target; 1223 else 1224 target = 7; 1225 if (sist & SIOP_SIST_UDC) { 1226 #ifdef DEBUG 1227 if (acb == NULL) 1228 printf("%s: Unexpected disconnect with no active command?\n", 1229 sc->sc_dev.dv_xname); 1230 printf ("%s: target %d disconnected unexpectedly\n", 1231 sc->sc_dev.dv_xname, target); 1232 siopng_dump_registers(sc); 1233 siopng_dump(sc); 1234 #endif 1235 #if 0 1236 siopngabort (sc, rp, "siopngchkintr"); 1237 #endif 1238 *status = STS_BUSY; 1239 if (sc->nexus_list.tqh_first) 1240 rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; 1241 return (acb != NULL); 1242 } 1243 if (dstat & SIOP_DSTAT_SIR && (rp->siop_dsps == 0xff01 || 1244 rp->siop_dsps == 0xff02)) { 1245 #ifdef DEBUG 1246 if (siopng_debug & 0x100) 1247 printf ("%s: ID %02x disconnected TEMP %lx (+%lx) curbuf %lx curlen %lx buf %p len %lx dfifo %x dbc %x sstat1 %x starts %d acb %p\n", 1248 sc->sc_dev.dv_xname, 1 << target, rp->siop_temp, 1249 rp->siop_temp ? rp->siop_temp - sc->sc_scriptspa : 0, 1250 acb->iob_curbuf, acb->iob_curlen, 1251 acb->ds.chain[0].databuf, acb->ds.chain[0].datalen, dfifo, dbc, sstat1, siopngstarts, acb); 1252 #endif 1253 if (acb == NULL) { 1254 printf("%s: Disconnect with no active command?\n", 1255 sc->sc_dev.dv_xname); 1256 return (0); 1257 } 1258 /* 1259 * XXXX need to update iob_curbuf/iob_curlen to reflect 1260 * current data transferred. If device disconnected in 1261 * the middle of a DMA block, they should already be set 1262 * by the phase change interrupt. If the disconnect 1263 * occurs on a DMA block boundary, we have to figure out 1264 * which DMA block it was. 1265 */ 1266 if (acb->iob_len && rp->siop_temp) { 1267 int n = rp->siop_temp - sc->sc_scriptspa; 1268 1269 if (acb->iob_curlen && acb->iob_curlen != acb->ds.chain[0].datalen) 1270 printf("%s: iob_curbuf/len already set? n %x iob %lx/%lx chain[0] %p/%lx\n", 1271 sc->sc_dev.dv_xname, n, acb->iob_curbuf, acb->iob_curlen, 1272 acb->ds.chain[0].databuf, acb->ds.chain[0].datalen); 1273 if (n < Ent_datain) 1274 n = (n - Ent_dataout) / 16; 1275 else 1276 n = (n - Ent_datain) / 16; 1277 if (n <= 0 && n > DMAMAXIO) 1278 printf("TEMP invalid %d\n", n); 1279 else { 1280 acb->iob_curbuf = (u_long)acb->ds.chain[n].databuf; 1281 acb->iob_curlen = acb->ds.chain[n].datalen; 1282 } 1283 #ifdef DEBUG 1284 if (siopng_debug & 0x100) { 1285 printf("%s: TEMP offset %d", sc->sc_dev.dv_xname, n); 1286 printf(" curbuf %lx curlen %lx\n", acb->iob_curbuf, 1287 acb->iob_curlen); 1288 } 1289 #endif 1290 } 1291 /* 1292 * If data transfer was interrupted by disconnect, iob_curbuf 1293 * and iob_curlen should reflect the point of interruption. 1294 * Adjust the DMA chain so that the data transfer begins 1295 * at the appropriate place upon reselection. 1296 * XXX This should only be done on save data pointer message? 1297 */ 1298 if (acb->iob_curlen) { 1299 int i, j; 1300 1301 #ifdef DEBUG 1302 if (siopng_debug & 0x100) 1303 printf ("%s: adjusting DMA chain\n", 1304 sc->sc_dev.dv_xname); 1305 if (rp->siop_dsps == 0xff02) 1306 printf ("%s: ID %02x disconnected without Save Data Pointers\n", 1307 sc->sc_dev.dv_xname, 1 << target); 1308 #endif 1309 for (i = 0; i < DMAMAXIO; ++i) { 1310 if (acb->ds.chain[i].datalen == 0) 1311 break; 1312 if (acb->iob_curbuf >= (long)acb->ds.chain[i].databuf && 1313 acb->iob_curbuf < (long)(acb->ds.chain[i].databuf + 1314 acb->ds.chain[i].datalen)) 1315 break; 1316 } 1317 if (i >= DMAMAXIO || acb->ds.chain[i].datalen == 0) { 1318 printf("couldn't find saved data pointer: "); 1319 printf("curbuf %lx curlen %lx i %d\n", 1320 acb->iob_curbuf, acb->iob_curlen, i); 1321 #ifdef DDB 1322 Debugger(); 1323 #endif 1324 } 1325 #ifdef DEBUG 1326 if (siopng_debug & 0x100) 1327 printf(" chain[0]: %p/%lx -> %lx/%lx\n", 1328 acb->ds.chain[0].databuf, 1329 acb->ds.chain[0].datalen, 1330 acb->iob_curbuf, 1331 acb->iob_curlen); 1332 #endif 1333 acb->ds.chain[0].databuf = (char *)acb->iob_curbuf; 1334 acb->ds.chain[0].datalen = acb->iob_curlen; 1335 for (j = 1, ++i; i < DMAMAXIO && acb->ds.chain[i].datalen; ++i, ++j) { 1336 #ifdef DEBUG 1337 if (siopng_debug & 0x100) 1338 printf(" chain[%d]: %p/%lx -> %p/%lx\n", j, 1339 acb->ds.chain[j].databuf, 1340 acb->ds.chain[j].datalen, 1341 acb->ds.chain[i].databuf, 1342 acb->ds.chain[i].datalen); 1343 #endif 1344 acb->ds.chain[j].databuf = acb->ds.chain[i].databuf; 1345 acb->ds.chain[j].datalen = acb->ds.chain[i].datalen; 1346 } 1347 if (j < DMAMAXIO) 1348 acb->ds.chain[j].datalen = 0; 1349 DCIAS(kvtop((caddr_t)&acb->ds.chain)); 1350 } 1351 ++sc->sc_tinfo[target].dconns; 1352 /* 1353 * add nexus to waiting list 1354 * clear nexus 1355 * try to start another command for another target/lun 1356 */ 1357 acb->status = sc->sc_flags & SIOP_INTSOFF; 1358 TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain); 1359 sc->sc_nexus = NULL; /* no current device */ 1360 /* start script to wait for reselect */ 1361 if (sc->sc_nexus == NULL) 1362 rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; 1363 /* XXXX start another command ? */ 1364 if (sc->ready_list.tqh_first) 1365 siopng_sched(sc); 1366 #if 0 1367 else 1368 rp->siop_dcntl |= SIOP_DCNTL_STD; 1369 #endif 1370 return (0); 1371 } 1372 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff03) { 1373 int reselid = rp->siop_scratcha & 0x7f; 1374 int reselun = rp->siop_sfbr & 0x07; 1375 1376 sc->sc_sstat1 = rp->siop_sbcl; /* XXXX save current SBCL */ 1377 #ifdef DEBUG 1378 if (siopng_debug & 0x100) 1379 printf ("%s: target ID %02x reselected dsps %lx\n", 1380 sc->sc_dev.dv_xname, reselid, 1381 rp->siop_dsps); 1382 if ((rp->siop_sfbr & 0x80) == 0) 1383 printf("%s: Reselect message in was not identify: %x\n", 1384 sc->sc_dev.dv_xname, rp->siop_sfbr); 1385 #endif 1386 if (sc->sc_nexus) { 1387 #ifdef DEBUG 1388 if (siopng_debug & 0x100) 1389 printf ("%s: reselect ID %02x w/active\n", 1390 sc->sc_dev.dv_xname, reselid); 1391 #endif 1392 TAILQ_INSERT_HEAD(&sc->ready_list, sc->sc_nexus, chain); 1393 sc->sc_tinfo[sc->sc_nexus->xs->xs_periph->periph_target].lubusy 1394 &= ~(1 << sc->sc_nexus->xs->xs_periph->periph_lun); 1395 --sc->sc_active; 1396 } 1397 /* 1398 * locate acb of reselecting device 1399 * set sc->sc_nexus to acb 1400 */ 1401 for (acb = sc->nexus_list.tqh_first; acb; 1402 acb = acb->chain.tqe_next) { 1403 if (reselid != ((acb->ds.scsi_addr >> 16) & 0xff) || 1404 reselun != (acb->msgout[0] & 0x07)) 1405 continue; 1406 TAILQ_REMOVE(&sc->nexus_list, acb, chain); 1407 sc->sc_nexus = acb; 1408 sc->sc_flags |= acb->status; 1409 acb->status = 0; 1410 DCIAS(kvtop(&acb->stat[0])); 1411 rp->siop_dsa = kvtop((caddr_t)&acb->ds); 1412 rp->siop_sxfer = 1413 sc->sc_sync[acb->xs->xs_periph->periph_target].sxfer; 1414 #ifndef FIXME 1415 rp->siop_scntl3 = 1416 sc->sc_sync[acb->xs->xs_periph->periph_target].scntl3; 1417 #endif 1418 break; 1419 } 1420 if (acb == NULL) { 1421 printf("%s: target ID %02x reselect nexus_list %p\n", 1422 sc->sc_dev.dv_xname, reselid, 1423 sc->nexus_list.tqh_first); 1424 panic("unable to find reselecting device"); 1425 } 1426 dma_cachectl ((caddr_t)acb, sizeof(*acb)); 1427 rp->siop_temp = 0; 1428 rp->siop_dcntl |= SIOP_DCNTL_STD; 1429 return (0); 1430 } 1431 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff04) { 1432 #ifdef DEBUG 1433 u_short ctest2 = rp->siop_ctest2; 1434 1435 /* reselect was interrupted (by Sig_P or select) */ 1436 if (siopng_debug & 0x100 || 1437 (ctest2 & SIOP_CTEST2_SIGP) == 0) 1438 printf ("%s: reselect interrupted (Sig_P?) scntl1 %x ctest2 %x sfbr %x istat %x/%x\n", 1439 sc->sc_dev.dv_xname, rp->siop_scntl1, 1440 ctest2, rp->siop_sfbr, istat, rp->siop_istat); 1441 #endif 1442 /* XXX assumes it was not select */ 1443 if (sc->sc_nexus == NULL) { 1444 #ifdef DEBUG 1445 printf("%s: reselect interrupted, sc_nexus == NULL\n", 1446 sc->sc_dev.dv_xname); 1447 #if 0 1448 siopng_dump(sc); 1449 #ifdef DDB 1450 Debugger(); 1451 #endif 1452 #endif 1453 #endif 1454 rp->siop_dcntl |= SIOP_DCNTL_STD; 1455 return(0); 1456 } 1457 target = sc->sc_nexus->xs->xs_periph->periph_target; 1458 rp->siop_temp = 0; 1459 rp->siop_dsa = kvtop((caddr_t)&sc->sc_nexus->ds); 1460 rp->siop_sxfer = sc->sc_sync[target].sxfer; 1461 #ifndef FIXME 1462 rp->siop_scntl3 = sc->sc_sync[target].scntl3; 1463 #endif 1464 rp->siop_dsp = sc->sc_scriptspa; 1465 return (0); 1466 } 1467 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff06) { 1468 if (acb == NULL) 1469 printf("%s: Bad message-in with no active command?\n", 1470 sc->sc_dev.dv_xname); 1471 /* Unrecognized message in byte */ 1472 dma_cachectl (&acb->msg[1],1); 1473 printf ("%s: Unrecognized message in data sfbr %x msg %x sbcl %x\n", 1474 sc->sc_dev.dv_xname, rp->siop_sfbr, acb->msg[1], rp->siop_sbcl); 1475 /* what should be done here? */ 1476 DCIAS(kvtop(&acb->msg[1])); 1477 rp->siop_dsp = sc->sc_scriptspa + Ent_switch; 1478 return (0); 1479 } 1480 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff0a) { 1481 /* Status phase wasn't followed by message in phase? */ 1482 printf ("%s: Status phase not followed by message in phase? sbcl %x sbdl %x\n", 1483 sc->sc_dev.dv_xname, rp->siop_sbcl, rp->siop_sbdl); 1484 if (rp->siop_sbcl == 0xa7) { 1485 /* It is now, just continue the script? */ 1486 rp->siop_dcntl |= SIOP_DCNTL_STD; 1487 return (0); 1488 } 1489 } 1490 if (sist == 0 && dstat & SIOP_DSTAT_SIR) { 1491 dma_cachectl (&acb->stat[0], 1); 1492 dma_cachectl (&acb->msg[0], 1); 1493 printf ("SIOP interrupt: %lx sts %x msg %x %x sbcl %x\n", 1494 rp->siop_dsps, acb->stat[0], acb->msg[0], acb->msg[1], 1495 rp->siop_sbcl); 1496 siopngreset (sc); 1497 *status = -1; 1498 return 0; /* siopngreset has cleaned up */ 1499 } 1500 if (sist & SIOP_SIST_SGE) 1501 printf ("SIOP: SCSI Gross Error\n"); 1502 if (sist & SIOP_SIST_PAR) 1503 printf ("SIOP: Parity Error\n"); 1504 if (dstat & SIOP_DSTAT_IID) 1505 printf ("SIOP: Invalid instruction detected\n"); 1506 bad_phase: 1507 /* 1508 * temporary panic for unhandled conditions 1509 * displays various things about the 53C720/770 status and registers 1510 * then panics. 1511 * XXXX need to clean this up to print out the info, reset, and continue 1512 */ 1513 printf ("siopngchkintr: target %x ds %p\n", target, &acb->ds); 1514 printf ("scripts %lx ds %x rp %x dsp %lx dcmd %lx\n", sc->sc_scriptspa, 1515 kvtop((caddr_t)&acb->ds), kvtop((caddr_t)__UNVOLATILE(rp)), 1516 rp->siop_dsp, *((long *)__UNVOLATILE(&rp->siop_dcmd))); 1517 printf ("siopngchkintr: istat %x dstat %x sist %x dsps %lx dsa %lx sbcl %x sts %x msg %x %x sfbr %x\n", 1518 istat, dstat, sist, rp->siop_dsps, rp->siop_dsa, 1519 rp->siop_sbcl, acb->stat[0], acb->msg[0], acb->msg[1], rp->siop_sfbr); 1520 #ifdef DEBUG 1521 if (siopng_debug & 0x20) 1522 panic("siopngchkintr: **** temp ****"); 1523 #endif 1524 #ifdef DDB 1525 Debugger (); 1526 #endif 1527 siopngreset (sc); /* hard reset */ 1528 *status = -1; 1529 return 0; /* siopngreset cleaned up */ 1530 } 1531 1532 void 1533 siopng_select(struct siop_softc *sc) 1534 { 1535 siop_regmap_p rp; 1536 struct siop_acb *acb = sc->sc_nexus; 1537 1538 #ifdef DEBUG 1539 if (siopng_debug & 1) 1540 printf ("%s: select ", sc->sc_dev.dv_xname); 1541 #endif 1542 1543 rp = sc->sc_siopp; 1544 if (acb->xs->xs_control & XS_CTL_POLL || siopng_no_dma) { 1545 sc->sc_flags |= SIOP_INTSOFF; 1546 sc->sc_flags &= ~SIOP_INTDEFER; 1547 if ((rp->siop_istat & 0x08) == 0) { 1548 rp->siop_sien = 0; 1549 rp->siop_dien = 0; 1550 } 1551 #if 0 1552 } else if ((sc->sc_flags & SIOP_INTDEFER) == 0) { 1553 sc->sc_flags &= ~SIOP_INTSOFF; 1554 if ((rp->siop_istat & 0x08) == 0) { 1555 rp->siop_sien = sc->sc_sien; 1556 rp->siop_dien = sc->sc_dien; 1557 } 1558 #endif 1559 } 1560 #ifdef DEBUG 1561 if (siopng_debug & 1) 1562 printf ("siopng_select: target %x cmd %02x ds %p\n", 1563 acb->xs->xs_periph->periph_target, acb->cmd.opcode, 1564 &sc->sc_nexus->ds); 1565 #endif 1566 1567 siopng_start(sc, acb->xs->xs_periph->periph_target, 1568 acb->xs->xs_periph->periph_lun, 1569 (u_char *)&acb->cmd, acb->clen, acb->daddr, acb->dleft); 1570 1571 return; 1572 } 1573 1574 /* 1575 * 53C720/770 interrupt handler 1576 */ 1577 1578 void 1579 siopngintr(register struct siop_softc *sc) 1580 { 1581 siop_regmap_p rp; 1582 u_char istat, dstat; 1583 u_short sist; 1584 int status; 1585 int s = splbio(); 1586 1587 istat = sc->sc_istat; 1588 if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) { 1589 splx(s); 1590 return; 1591 } 1592 1593 /* Got a valid interrupt on this device */ 1594 rp = sc->sc_siopp; 1595 dstat = sc->sc_dstat; 1596 sist = sc->sc_sist; 1597 if (dstat & SIOP_DSTAT_SIR) 1598 sc->sc_intcode = rp->siop_dsps; 1599 sc->sc_istat = 0; 1600 #ifdef DEBUG 1601 if (siopng_debug & 1) 1602 printf ("%s: intr istat %x dstat %x sist %x\n", 1603 sc->sc_dev.dv_xname, istat, dstat, sist); 1604 if (!sc->sc_active) { 1605 printf ("%s: spurious interrupt? istat %x dstat %x sist %x nexus %p status %x\n", 1606 sc->sc_dev.dv_xname, istat, dstat, sist, 1607 sc->sc_nexus, sc->sc_nexus ? sc->sc_nexus->stat[0] : 0); 1608 } 1609 #endif 1610 1611 #ifdef DEBUG 1612 if (siopng_debug & 5) { 1613 DCIAS(kvtop(&sc->sc_nexus->stat[0])); 1614 printf ("%s: intr istat %x dstat %x sist %x dsps %lx sbcl %x sts %x msg %x\n", 1615 sc->sc_dev.dv_xname, istat, dstat, sist, 1616 rp->siop_dsps, rp->siop_sbcl, 1617 sc->sc_nexus->stat[0], sc->sc_nexus->msg[0]); 1618 } 1619 #endif 1620 if (sc->sc_flags & SIOP_INTDEFER) { 1621 sc->sc_flags &= ~(SIOP_INTDEFER | SIOP_INTSOFF); 1622 rp->siop_sien = sc->sc_sien; 1623 rp->siop_dien = sc->sc_dien; 1624 } 1625 if (siopng_checkintr (sc, istat, dstat, sist, &status)) { 1626 #if 1 1627 if (status == 0xff) 1628 printf ("siopngintr: status == 0xff\n"); 1629 #endif 1630 if ((sc->sc_flags & (SIOP_INTSOFF | SIOP_INTDEFER)) != SIOP_INTSOFF) { 1631 #if 0 1632 if (rp->siop_sbcl & SIOP_BSY) { 1633 printf ("%s: SCSI bus busy at completion", 1634 sc->sc_dev.dv_xname); 1635 printf(" targ %d sbcl %02x sfbr %x respid %02x dsp +%x\n", 1636 sc->sc_nexus->xs->xs_periph->periph_target, 1637 rp->siop_sbcl, rp->siop_sfbr, rp->siop_respid, 1638 rp->siop_dsp - sc->sc_scriptspa); 1639 } 1640 #endif 1641 siopng_scsidone(sc->sc_nexus, sc->sc_nexus ? 1642 sc->sc_nexus->stat[0] : -1); 1643 } 1644 } 1645 splx(s); 1646 } 1647 1648 /* 1649 * This is based on the Progressive Peripherals 33Mhz Zeus driver and will 1650 * not be correct for other 53c710 boards. 1651 * 1652 */ 1653 void 1654 scsi_period_to_siopng(struct siop_softc *sc, int target) 1655 { 1656 int period, offset, sxfer, scntl3 = 0; 1657 1658 period = sc->sc_nexus->msg[4]; 1659 offset = sc->sc_nexus->msg[5]; 1660 #ifdef FIXME 1661 for (scntl3 = 1; scntl3 < 4; ++scntl3) { 1662 sxfer = (period * 4 - 1) / sc->sc_tcp[scntl3] - 3; 1663 if (sxfer >= 0 && sxfer <= 7) 1664 break; 1665 } 1666 if (scntl3 > 3) { 1667 printf("siopng sync: unable to compute sync params for period %dns\n", 1668 period * 4); 1669 /* 1670 * XXX need to pick a value we can do and renegotiate 1671 */ 1672 sxfer = scntl3 = 0; 1673 } else { 1674 sxfer = (sxfer << 4) | ((offset <= SIOP_MAX_OFFSET) ? 1675 offset : SIOP_MAX_OFFSET); 1676 #ifdef DEBUG_SYNC 1677 printf("siopng sync: params for period %dns: sxfer %x scntl3 %x", 1678 period * 4, sxfer, scntl3); 1679 printf(" actual period %dns\n", 1680 sc->sc_tcp[scntl3] * ((sxfer >> 4) + 4)); 1681 #endif /* DEBUG_SYNC */ 1682 } 1683 #else /* FIXME */ 1684 sxfer = offset <= SIOP_MAX_OFFSET ? offset : SIOP_MAX_OFFSET; 1685 sxfer |= 0x20; /* XXX XFERP: 5 */ 1686 #ifndef FIXME 1687 if (period <= (50 / 4)) /* XXX */ 1688 scntl3 = 0x95; /* Ultra, SCF: /1, CCF: /4 */ 1689 else if (period <= (100 / 4)) 1690 scntl3 = 0x35; /* SCF: /2, CCF: /4 */ 1691 else if (period <= (200 / 4)) 1692 scntl3 = 0x55; /* SCF: /4, CCF: /4 */ 1693 else 1694 scntl3 = 0xff; /* XXX ??? */ 1695 #else 1696 scntl3 = 5; 1697 #endif 1698 #endif 1699 sc->sc_sync[target].sxfer = sxfer; 1700 sc->sc_sync[target].scntl3 = scntl3 | 1701 (sc->sc_sync[target].scntl3 & SIOP_SCNTL3_EWS); 1702 #ifdef DEBUG_SYNC 1703 printf ("siopng sync: siop_sxfr %02x, siop_scntl3 %02x\n", sxfer, scntl3); 1704 #endif 1705 } 1706 1707 void 1708 siopng_dump_registers(struct siop_softc *sc) 1709 { 1710 siop_regmap_p rp = sc->sc_siopp; 1711 1712 printf(" scntl0 %02x scntl1 %02x scntl2 %02x scntl3 %02x\n", 1713 rp->siop_scntl0, rp->siop_scntl1, rp->siop_scntl2, rp->siop_scntl3); 1714 printf(" scid %02x sxfer %02x sdid %02x gpreg %02x\n", 1715 rp->siop_scid, rp->siop_sxfer, rp->siop_sdid, rp->siop_gpreg); 1716 printf(" sfbr %02x socl %02x ssid %02x sbcl %02x\n", 1717 rp->siop_sfbr, rp->siop_socl, rp->siop_ssid, rp->siop_sbcl); 1718 printf(" dstat %02x sstat0 %02x sstat1 %02x sstat2 %02x\n", 1719 rp->siop_dstat, rp->siop_sstat0, rp->siop_sstat1, rp->siop_sstat2); 1720 printf(" ctest0 %02x ctest1 %02x ctest2 %02x ctest3 %02x\n", 1721 rp->siop_ctest0, rp->siop_ctest1, rp->siop_ctest2, rp->siop_ctest3); 1722 printf(" dfifo %02x ctest4 %02x ctest5 %02x ctest6 %02x\n", 1723 0, rp->siop_ctest4, rp->siop_ctest5, rp->siop_ctest6); 1724 printf(" dcmd %02x dbc2 %02x dbc1 %02x dbc0 %02x\n", 1725 rp->siop_dcmd, rp->siop_dbc2, rp->siop_dbc1, rp->siop_dbc0); 1726 printf(" dmode %02x dien %02x dwt %02x dcntl %02x\n", 1727 rp->siop_dmode, rp->siop_dien, rp->siop_dwt, rp->siop_dcntl); 1728 printf(" stest0 %02x stest1 %02x stest2 %02x stest3 %02x\n", 1729 rp->siop_stest0, rp->siop_stest1, rp->siop_stest2, rp->siop_stest3); 1730 printf(" istat %02x sien %04x sist %04x respid %04x\n", 1731 rp->siop_istat, rp->siop_sien, rp->siop_sist, rp->siop_respid); 1732 printf(" sidl %04x sodl %04x sbdl %04x\n", 1733 rp->siop_sidl, rp->siop_sodl, rp->siop_sbdl); 1734 printf(" dsps %08lx dsp %08lx (+%lx)\n", 1735 rp->siop_dsps, rp->siop_dsp, rp->siop_dsp > sc->sc_scriptspa ? 1736 rp->siop_dsp - sc->sc_scriptspa : 0); 1737 printf(" dsa %08lx temp %08lx dnad %08lx\n", 1738 rp->siop_dsa, rp->siop_temp, rp->siop_dnad); 1739 printf(" scratcha %08lx scratchb %08lx adder %08lx\n", 1740 rp->siop_scratcha, rp->siop_scratchb, rp->siop_adder); 1741 } 1742 1743 #ifdef DEBUG 1744 1745 #if SIOP_TRACE_SIZE 1746 void 1747 siopng_dump_trace(void) 1748 { 1749 int i; 1750 1751 printf("siopng trace: next index %d\n", siopng_trix); 1752 i = siopng_trix; 1753 do { 1754 printf("%3d: '%c' %02x %02x %02x\n", i, siopng_trbuf[i], 1755 siopng_trbuf[i + 1], siopng_trbuf[i + 2], siopng_trbuf[i + 3]); 1756 i = (i + 4) & (SIOP_TRACE_SIZE - 1); 1757 } while (i != siopng_trix); 1758 } 1759 #endif 1760 1761 void 1762 siopng_dump_acb(struct siop_acb *acb) 1763 { 1764 u_char *b = (u_char *) &acb->cmd; 1765 int i; 1766 1767 printf("acb@%p ", acb); 1768 if (acb->xs == NULL) { 1769 printf("<unused>\n"); 1770 return; 1771 } 1772 printf("(%d:%d) flags %2x clen %2d cmd ", 1773 acb->xs->xs_periph->periph_target, 1774 acb->xs->xs_periph->periph_lun, acb->flags, acb->clen); 1775 for (i = acb->clen; i; --i) 1776 printf(" %02x", *b++); 1777 printf("\n"); 1778 printf(" xs: %p data %p:%04x ", acb->xs, acb->xs->data, 1779 acb->xs->datalen); 1780 printf("va %p:%lx ", acb->iob_buf, acb->iob_len); 1781 printf("cur %lx:%lx\n", acb->iob_curbuf, acb->iob_curlen); 1782 } 1783 1784 void 1785 siopng_dump(struct siop_softc *sc) 1786 { 1787 struct siop_acb *acb; 1788 siop_regmap_p rp = sc->sc_siopp; 1789 int s; 1790 int i; 1791 1792 s = splbio(); 1793 #if SIOP_TRACE_SIZE 1794 siopng_dump_trace(); 1795 #endif 1796 printf("%s@%p regs %p istat %x\n", 1797 sc->sc_dev.dv_xname, sc, rp, rp->siop_istat); 1798 if ((acb = sc->free_list.tqh_first) > 0) { 1799 printf("Free list:\n"); 1800 while (acb) { 1801 siopng_dump_acb(acb); 1802 acb = acb->chain.tqe_next; 1803 } 1804 } 1805 if ((acb = sc->ready_list.tqh_first) > 0) { 1806 printf("Ready list:\n"); 1807 while (acb) { 1808 siopng_dump_acb(acb); 1809 acb = acb->chain.tqe_next; 1810 } 1811 } 1812 if ((acb = sc->nexus_list.tqh_first) > 0) { 1813 printf("Nexus list:\n"); 1814 while (acb) { 1815 siopng_dump_acb(acb); 1816 acb = acb->chain.tqe_next; 1817 } 1818 } 1819 if (sc->sc_nexus) { 1820 printf("Nexus:\n"); 1821 siopng_dump_acb(sc->sc_nexus); 1822 } 1823 for (i = 0; i < 8; ++i) { 1824 if (sc->sc_tinfo[i].cmds > 2) { 1825 printf("tgt %d: cmds %d disc %d lubusy %x\n", 1826 i, sc->sc_tinfo[i].cmds, 1827 sc->sc_tinfo[i].dconns, 1828 sc->sc_tinfo[i].lubusy); 1829 } 1830 } 1831 splx(s); 1832 } 1833 #endif 1834