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