1 /* $NetBSD: siop2.c,v 1.23 2004/03/28 18:59:39 mhitch 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.23 2004/03/28 18:59:39 mhitch 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, 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 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, 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)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 = *((long *)&rp->siop_dcmd) & 0xffffff; 1140 acb->iob_curlen += adjust; 1141 acb->iob_curbuf = *((long *)&rp->siop_dnad) - adjust; 1142 #ifdef DEBUG 1143 if (siopng_debug & 0x100) { 1144 int i; 1145 printf ("Phase mismatch: curbuf %lx curlen %lx dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %p\n", 1146 acb->iob_curbuf, acb->iob_curlen, dfifo, 1147 dbc, sstat1, adjust, rp->siop_sbcl, siopngstarts, acb); 1148 if (acb->ds.chain[1].datalen) { 1149 for (i = 0; acb->ds.chain[i].datalen; ++i) 1150 printf("chain[%d] addr %p len %lx\n", 1151 i, acb->ds.chain[i].databuf, 1152 acb->ds.chain[i].datalen); 1153 } 1154 } 1155 #endif 1156 dma_cachectl ((caddr_t)acb, sizeof(*acb)); 1157 } 1158 #ifdef DEBUG 1159 SIOP_TRACE('m',rp->siop_sbcl,(rp->siop_dsp>>8),rp->siop_dsp); 1160 if (siopng_debug & 9) 1161 printf ("Phase mismatch: %x dsp +%lx dcmd %lx\n", 1162 rp->siop_sbcl, 1163 rp->siop_dsp - sc->sc_scriptspa, 1164 *((long *)&rp->siop_dcmd)); 1165 #endif 1166 if ((rp->siop_sbcl & SIOP_REQ) == 0) { 1167 printf ("Phase mismatch: REQ not asserted! %02x dsp %lx\n", 1168 rp->siop_sbcl, rp->siop_dsp); 1169 #if defined(DEBUG) && defined(DDB) 1170 Debugger(); 1171 #endif 1172 } 1173 switch (rp->siop_sbcl & 7) { 1174 case 0: /* data out */ 1175 case 1: /* data in */ 1176 case 2: /* status */ 1177 case 3: /* command */ 1178 case 6: /* message in */ 1179 case 7: /* message out */ 1180 rp->siop_dsp = sc->sc_scriptspa + Ent_switch; 1181 break; 1182 default: 1183 goto bad_phase; 1184 } 1185 return 0; 1186 } 1187 if (sist & SIOP_SIST_STO) { /* Select timed out */ 1188 #ifdef DEBUG 1189 if (acb == NULL) 1190 printf("%s: Select timeout with no active command?\n", 1191 sc->sc_dev.dv_xname); 1192 if (rp->siop_sbcl & SIOP_BSY) { 1193 printf ("ACK! siop was busy at timeout: rp %p script %p dsa %p\n", 1194 rp, &siopng_scripts, &acb->ds); 1195 printf(" sbcl %x sdid %x istat %x dstat %x sist %x\n", 1196 rp->siop_sbcl, rp->siop_sdid, istat, dstat, sist); 1197 if (!(rp->siop_sbcl & SIOP_BSY)) { 1198 printf ("Yikes, it's not busy now!\n"); 1199 #if 0 1200 *status = -1; 1201 if (sc->nexus_list.tqh_first) 1202 rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; 1203 return 1; 1204 #endif 1205 } 1206 /* rp->siop_dcntl |= SIOP_DCNTL_STD;*/ 1207 return (0); 1208 #ifdef DDB 1209 Debugger(); 1210 #endif 1211 } 1212 #endif 1213 *status = -1; 1214 acb->xs->error = XS_SELTIMEOUT; 1215 if (sc->nexus_list.tqh_first) 1216 rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; 1217 return 1; 1218 } 1219 if (acb) 1220 target = acb->xs->xs_periph->periph_target; 1221 else 1222 target = 7; 1223 if (sist & SIOP_SIST_UDC) { 1224 #ifdef DEBUG 1225 if (acb == NULL) 1226 printf("%s: Unexpected disconnect with no active command?\n", 1227 sc->sc_dev.dv_xname); 1228 printf ("%s: target %d disconnected unexpectedly\n", 1229 sc->sc_dev.dv_xname, target); 1230 siopng_dump_registers(sc); 1231 siopng_dump(sc); 1232 #endif 1233 #if 0 1234 siopngabort (sc, rp, "siopngchkintr"); 1235 #endif 1236 *status = STS_BUSY; 1237 if (sc->nexus_list.tqh_first) 1238 rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; 1239 return (acb != NULL); 1240 } 1241 if (dstat & SIOP_DSTAT_SIR && (rp->siop_dsps == 0xff01 || 1242 rp->siop_dsps == 0xff02)) { 1243 #ifdef DEBUG 1244 if (siopng_debug & 0x100) 1245 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", 1246 sc->sc_dev.dv_xname, 1 << target, rp->siop_temp, 1247 rp->siop_temp ? rp->siop_temp - sc->sc_scriptspa : 0, 1248 acb->iob_curbuf, acb->iob_curlen, 1249 acb->ds.chain[0].databuf, acb->ds.chain[0].datalen, dfifo, dbc, sstat1, siopngstarts, acb); 1250 #endif 1251 if (acb == NULL) { 1252 printf("%s: Disconnect with no active command?\n", 1253 sc->sc_dev.dv_xname); 1254 return (0); 1255 } 1256 /* 1257 * XXXX need to update iob_curbuf/iob_curlen to reflect 1258 * current data transferred. If device disconnected in 1259 * the middle of a DMA block, they should already be set 1260 * by the phase change interrupt. If the disconnect 1261 * occurs on a DMA block boundary, we have to figure out 1262 * which DMA block it was. 1263 */ 1264 if (acb->iob_len && rp->siop_temp) { 1265 int n = rp->siop_temp - sc->sc_scriptspa; 1266 1267 if (acb->iob_curlen && acb->iob_curlen != acb->ds.chain[0].datalen) 1268 printf("%s: iob_curbuf/len already set? n %x iob %lx/%lx chain[0] %p/%lx\n", 1269 sc->sc_dev.dv_xname, n, acb->iob_curbuf, acb->iob_curlen, 1270 acb->ds.chain[0].databuf, acb->ds.chain[0].datalen); 1271 if (n < Ent_datain) 1272 n = (n - Ent_dataout) / 16; 1273 else 1274 n = (n - Ent_datain) / 16; 1275 if (n <= 0 && n > DMAMAXIO) 1276 printf("TEMP invalid %d\n", n); 1277 else { 1278 acb->iob_curbuf = (u_long)acb->ds.chain[n].databuf; 1279 acb->iob_curlen = acb->ds.chain[n].datalen; 1280 } 1281 #ifdef DEBUG 1282 if (siopng_debug & 0x100) { 1283 printf("%s: TEMP offset %d", sc->sc_dev.dv_xname, n); 1284 printf(" curbuf %lx curlen %lx\n", acb->iob_curbuf, 1285 acb->iob_curlen); 1286 } 1287 #endif 1288 } 1289 /* 1290 * If data transfer was interrupted by disconnect, iob_curbuf 1291 * and iob_curlen should reflect the point of interruption. 1292 * Adjust the DMA chain so that the data transfer begins 1293 * at the appropriate place upon reselection. 1294 * XXX This should only be done on save data pointer message? 1295 */ 1296 if (acb->iob_curlen) { 1297 int i, j; 1298 1299 #ifdef DEBUG 1300 if (siopng_debug & 0x100) 1301 printf ("%s: adjusting DMA chain\n", 1302 sc->sc_dev.dv_xname); 1303 if (rp->siop_dsps == 0xff02) 1304 printf ("%s: ID %02x disconnected without Save Data Pointers\n", 1305 sc->sc_dev.dv_xname, 1 << target); 1306 #endif 1307 for (i = 0; i < DMAMAXIO; ++i) { 1308 if (acb->ds.chain[i].datalen == 0) 1309 break; 1310 if (acb->iob_curbuf >= (long)acb->ds.chain[i].databuf && 1311 acb->iob_curbuf < (long)(acb->ds.chain[i].databuf + 1312 acb->ds.chain[i].datalen)) 1313 break; 1314 } 1315 if (i >= DMAMAXIO || acb->ds.chain[i].datalen == 0) { 1316 printf("couldn't find saved data pointer: "); 1317 printf("curbuf %lx curlen %lx i %d\n", 1318 acb->iob_curbuf, acb->iob_curlen, i); 1319 #ifdef DDB 1320 Debugger(); 1321 #endif 1322 } 1323 #ifdef DEBUG 1324 if (siopng_debug & 0x100) 1325 printf(" chain[0]: %p/%lx -> %lx/%lx\n", 1326 acb->ds.chain[0].databuf, 1327 acb->ds.chain[0].datalen, 1328 acb->iob_curbuf, 1329 acb->iob_curlen); 1330 #endif 1331 acb->ds.chain[0].databuf = (char *)acb->iob_curbuf; 1332 acb->ds.chain[0].datalen = acb->iob_curlen; 1333 for (j = 1, ++i; i < DMAMAXIO && acb->ds.chain[i].datalen; ++i, ++j) { 1334 #ifdef DEBUG 1335 if (siopng_debug & 0x100) 1336 printf(" chain[%d]: %p/%lx -> %p/%lx\n", j, 1337 acb->ds.chain[j].databuf, 1338 acb->ds.chain[j].datalen, 1339 acb->ds.chain[i].databuf, 1340 acb->ds.chain[i].datalen); 1341 #endif 1342 acb->ds.chain[j].databuf = acb->ds.chain[i].databuf; 1343 acb->ds.chain[j].datalen = acb->ds.chain[i].datalen; 1344 } 1345 if (j < DMAMAXIO) 1346 acb->ds.chain[j].datalen = 0; 1347 DCIAS(kvtop((caddr_t)&acb->ds.chain)); 1348 } 1349 ++sc->sc_tinfo[target].dconns; 1350 /* 1351 * add nexus to waiting list 1352 * clear nexus 1353 * try to start another command for another target/lun 1354 */ 1355 acb->status = sc->sc_flags & SIOP_INTSOFF; 1356 TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain); 1357 sc->sc_nexus = NULL; /* no current device */ 1358 /* start script to wait for reselect */ 1359 if (sc->sc_nexus == NULL) 1360 rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect; 1361 /* XXXX start another command ? */ 1362 if (sc->ready_list.tqh_first) 1363 siopng_sched(sc); 1364 #if 0 1365 else 1366 rp->siop_dcntl |= SIOP_DCNTL_STD; 1367 #endif 1368 return (0); 1369 } 1370 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff03) { 1371 int reselid = rp->siop_scratcha & 0x7f; 1372 int reselun = rp->siop_sfbr & 0x07; 1373 1374 sc->sc_sstat1 = rp->siop_sbcl; /* XXXX save current SBCL */ 1375 #ifdef DEBUG 1376 if (siopng_debug & 0x100) 1377 printf ("%s: target ID %02x reselected dsps %lx\n", 1378 sc->sc_dev.dv_xname, reselid, 1379 rp->siop_dsps); 1380 if ((rp->siop_sfbr & 0x80) == 0) 1381 printf("%s: Reselect message in was not identify: %x\n", 1382 sc->sc_dev.dv_xname, rp->siop_sfbr); 1383 #endif 1384 if (sc->sc_nexus) { 1385 #ifdef DEBUG 1386 if (siopng_debug & 0x100) 1387 printf ("%s: reselect ID %02x w/active\n", 1388 sc->sc_dev.dv_xname, reselid); 1389 #endif 1390 TAILQ_INSERT_HEAD(&sc->ready_list, sc->sc_nexus, chain); 1391 sc->sc_tinfo[sc->sc_nexus->xs->xs_periph->periph_target].lubusy 1392 &= ~(1 << sc->sc_nexus->xs->xs_periph->periph_lun); 1393 --sc->sc_active; 1394 } 1395 /* 1396 * locate acb of reselecting device 1397 * set sc->sc_nexus to acb 1398 */ 1399 for (acb = sc->nexus_list.tqh_first; acb; 1400 acb = acb->chain.tqe_next) { 1401 if (reselid != ((acb->ds.scsi_addr >> 16) & 0xff) || 1402 reselun != (acb->msgout[0] & 0x07)) 1403 continue; 1404 TAILQ_REMOVE(&sc->nexus_list, acb, chain); 1405 sc->sc_nexus = acb; 1406 sc->sc_flags |= acb->status; 1407 acb->status = 0; 1408 DCIAS(kvtop(&acb->stat[0])); 1409 rp->siop_dsa = kvtop((caddr_t)&acb->ds); 1410 rp->siop_sxfer = 1411 sc->sc_sync[acb->xs->xs_periph->periph_target].sxfer; 1412 #ifndef FIXME 1413 rp->siop_scntl3 = 1414 sc->sc_sync[acb->xs->xs_periph->periph_target].scntl3; 1415 #endif 1416 break; 1417 } 1418 if (acb == NULL) { 1419 printf("%s: target ID %02x reselect nexus_list %p\n", 1420 sc->sc_dev.dv_xname, reselid, 1421 sc->nexus_list.tqh_first); 1422 panic("unable to find reselecting device"); 1423 } 1424 dma_cachectl ((caddr_t)acb, sizeof(*acb)); 1425 rp->siop_temp = 0; 1426 rp->siop_dcntl |= SIOP_DCNTL_STD; 1427 return (0); 1428 } 1429 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff04) { 1430 #ifdef DEBUG 1431 u_short ctest2 = rp->siop_ctest2; 1432 1433 /* reselect was interrupted (by Sig_P or select) */ 1434 if (siopng_debug & 0x100 || 1435 (ctest2 & SIOP_CTEST2_SIGP) == 0) 1436 printf ("%s: reselect interrupted (Sig_P?) scntl1 %x ctest2 %x sfbr %x istat %x/%x\n", 1437 sc->sc_dev.dv_xname, rp->siop_scntl1, 1438 ctest2, rp->siop_sfbr, istat, rp->siop_istat); 1439 #endif 1440 /* XXX assumes it was not select */ 1441 if (sc->sc_nexus == NULL) { 1442 #ifdef DEBUG 1443 printf("%s: reselect interrupted, sc_nexus == NULL\n", 1444 sc->sc_dev.dv_xname); 1445 #if 0 1446 siopng_dump(sc); 1447 #ifdef DDB 1448 Debugger(); 1449 #endif 1450 #endif 1451 #endif 1452 rp->siop_dcntl |= SIOP_DCNTL_STD; 1453 return(0); 1454 } 1455 target = sc->sc_nexus->xs->xs_periph->periph_target; 1456 rp->siop_temp = 0; 1457 rp->siop_dsa = kvtop((caddr_t)&sc->sc_nexus->ds); 1458 rp->siop_sxfer = sc->sc_sync[target].sxfer; 1459 #ifndef FIXME 1460 rp->siop_scntl3 = sc->sc_sync[target].scntl3; 1461 #endif 1462 rp->siop_dsp = sc->sc_scriptspa; 1463 return (0); 1464 } 1465 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff06) { 1466 if (acb == NULL) 1467 printf("%s: Bad message-in with no active command?\n", 1468 sc->sc_dev.dv_xname); 1469 /* Unrecognized message in byte */ 1470 dma_cachectl (&acb->msg[1],1); 1471 printf ("%s: Unrecognized message in data sfbr %x msg %x sbcl %x\n", 1472 sc->sc_dev.dv_xname, rp->siop_sfbr, acb->msg[1], rp->siop_sbcl); 1473 /* what should be done here? */ 1474 DCIAS(kvtop(&acb->msg[1])); 1475 rp->siop_dsp = sc->sc_scriptspa + Ent_switch; 1476 return (0); 1477 } 1478 if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff0a) { 1479 /* Status phase wasn't followed by message in phase? */ 1480 printf ("%s: Status phase not followed by message in phase? sbcl %x sbdl %x\n", 1481 sc->sc_dev.dv_xname, rp->siop_sbcl, rp->siop_sbdl); 1482 if (rp->siop_sbcl == 0xa7) { 1483 /* It is now, just continue the script? */ 1484 rp->siop_dcntl |= SIOP_DCNTL_STD; 1485 return (0); 1486 } 1487 } 1488 if (sist == 0 && dstat & SIOP_DSTAT_SIR) { 1489 dma_cachectl (&acb->stat[0], 1); 1490 dma_cachectl (&acb->msg[0], 1); 1491 printf ("SIOP interrupt: %lx sts %x msg %x %x sbcl %x\n", 1492 rp->siop_dsps, acb->stat[0], acb->msg[0], acb->msg[1], 1493 rp->siop_sbcl); 1494 siopngreset (sc); 1495 *status = -1; 1496 return 0; /* siopngreset has cleaned up */ 1497 } 1498 if (sist & SIOP_SIST_SGE) 1499 printf ("SIOP: SCSI Gross Error\n"); 1500 if (sist & SIOP_SIST_PAR) 1501 printf ("SIOP: Parity Error\n"); 1502 if (dstat & SIOP_DSTAT_IID) 1503 printf ("SIOP: Invalid instruction detected\n"); 1504 bad_phase: 1505 /* 1506 * temporary panic for unhandled conditions 1507 * displays various things about the 53C720/770 status and registers 1508 * then panics. 1509 * XXXX need to clean this up to print out the info, reset, and continue 1510 */ 1511 printf ("siopngchkintr: target %x ds %p\n", target, &acb->ds); 1512 printf ("scripts %lx ds %x rp %x dsp %lx dcmd %lx\n", sc->sc_scriptspa, 1513 kvtop((caddr_t)&acb->ds), kvtop((caddr_t)rp), rp->siop_dsp, 1514 *((long *)&rp->siop_dcmd)); 1515 printf ("siopngchkintr: istat %x dstat %x sist %x dsps %lx dsa %lx sbcl %x sts %x msg %x %x sfbr %x\n", 1516 istat, dstat, sist, rp->siop_dsps, rp->siop_dsa, 1517 rp->siop_sbcl, acb->stat[0], acb->msg[0], acb->msg[1], rp->siop_sfbr); 1518 #ifdef DEBUG 1519 if (siopng_debug & 0x20) 1520 panic("siopngchkintr: **** temp ****"); 1521 #endif 1522 #ifdef DDB 1523 Debugger (); 1524 #endif 1525 siopngreset (sc); /* hard reset */ 1526 *status = -1; 1527 return 0; /* siopngreset cleaned up */ 1528 } 1529 1530 void 1531 siopng_select(struct siop_softc *sc) 1532 { 1533 siop_regmap_p rp; 1534 struct siop_acb *acb = sc->sc_nexus; 1535 1536 #ifdef DEBUG 1537 if (siopng_debug & 1) 1538 printf ("%s: select ", sc->sc_dev.dv_xname); 1539 #endif 1540 1541 rp = sc->sc_siopp; 1542 if (acb->xs->xs_control & XS_CTL_POLL || siopng_no_dma) { 1543 sc->sc_flags |= SIOP_INTSOFF; 1544 sc->sc_flags &= ~SIOP_INTDEFER; 1545 if ((rp->siop_istat & 0x08) == 0) { 1546 rp->siop_sien = 0; 1547 rp->siop_dien = 0; 1548 } 1549 #if 0 1550 } else if ((sc->sc_flags & SIOP_INTDEFER) == 0) { 1551 sc->sc_flags &= ~SIOP_INTSOFF; 1552 if ((rp->siop_istat & 0x08) == 0) { 1553 rp->siop_sien = sc->sc_sien; 1554 rp->siop_dien = sc->sc_dien; 1555 } 1556 #endif 1557 } 1558 #ifdef DEBUG 1559 if (siopng_debug & 1) 1560 printf ("siopng_select: target %x cmd %02x ds %p\n", 1561 acb->xs->xs_periph->periph_target, acb->cmd.opcode, 1562 &sc->sc_nexus->ds); 1563 #endif 1564 1565 siopng_start(sc, acb->xs->xs_periph->periph_target, 1566 acb->xs->xs_periph->periph_lun, 1567 (u_char *)&acb->cmd, acb->clen, acb->daddr, acb->dleft); 1568 1569 return; 1570 } 1571 1572 /* 1573 * 53C720/770 interrupt handler 1574 */ 1575 1576 void 1577 siopngintr(register struct siop_softc *sc) 1578 { 1579 siop_regmap_p rp; 1580 u_char istat, dstat; 1581 u_short sist; 1582 int status; 1583 int s = splbio(); 1584 1585 istat = sc->sc_istat; 1586 if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) { 1587 splx(s); 1588 return; 1589 } 1590 1591 /* Got a valid interrupt on this device */ 1592 rp = sc->sc_siopp; 1593 dstat = sc->sc_dstat; 1594 sist = sc->sc_sist; 1595 if (dstat & SIOP_DSTAT_SIR) 1596 sc->sc_intcode = rp->siop_dsps; 1597 sc->sc_istat = 0; 1598 #ifdef DEBUG 1599 if (siopng_debug & 1) 1600 printf ("%s: intr istat %x dstat %x sist %x\n", 1601 sc->sc_dev.dv_xname, istat, dstat, sist); 1602 if (!sc->sc_active) { 1603 printf ("%s: spurious interrupt? istat %x dstat %x sist %x nexus %p status %x\n", 1604 sc->sc_dev.dv_xname, istat, dstat, sist, 1605 sc->sc_nexus, sc->sc_nexus ? sc->sc_nexus->stat[0] : 0); 1606 } 1607 #endif 1608 1609 #ifdef DEBUG 1610 if (siopng_debug & 5) { 1611 DCIAS(kvtop(&sc->sc_nexus->stat[0])); 1612 printf ("%s: intr istat %x dstat %x sist %x dsps %lx sbcl %x sts %x msg %x\n", 1613 sc->sc_dev.dv_xname, istat, dstat, sist, 1614 rp->siop_dsps, rp->siop_sbcl, 1615 sc->sc_nexus->stat[0], sc->sc_nexus->msg[0]); 1616 } 1617 #endif 1618 if (sc->sc_flags & SIOP_INTDEFER) { 1619 sc->sc_flags &= ~(SIOP_INTDEFER | SIOP_INTSOFF); 1620 rp->siop_sien = sc->sc_sien; 1621 rp->siop_dien = sc->sc_dien; 1622 } 1623 if (siopng_checkintr (sc, istat, dstat, sist, &status)) { 1624 #if 1 1625 if (status == 0xff) 1626 printf ("siopngintr: status == 0xff\n"); 1627 #endif 1628 if ((sc->sc_flags & (SIOP_INTSOFF | SIOP_INTDEFER)) != SIOP_INTSOFF) { 1629 #if 0 1630 if (rp->siop_sbcl & SIOP_BSY) { 1631 printf ("%s: SCSI bus busy at completion", 1632 sc->sc_dev.dv_xname); 1633 printf(" targ %d sbcl %02x sfbr %x respid %02x dsp +%x\n", 1634 sc->sc_nexus->xs->xs_periph->periph_target, 1635 rp->siop_sbcl, rp->siop_sfbr, rp->siop_respid, 1636 rp->siop_dsp - sc->sc_scriptspa); 1637 } 1638 #endif 1639 siopng_scsidone(sc->sc_nexus, sc->sc_nexus ? 1640 sc->sc_nexus->stat[0] : -1); 1641 } 1642 } 1643 splx(s); 1644 } 1645 1646 /* 1647 * This is based on the Progressive Peripherals 33Mhz Zeus driver and will 1648 * not be correct for other 53c710 boards. 1649 * 1650 */ 1651 void 1652 scsi_period_to_siopng(struct siop_softc *sc, int target) 1653 { 1654 int period, offset, sxfer, scntl3 = 0; 1655 1656 period = sc->sc_nexus->msg[4]; 1657 offset = sc->sc_nexus->msg[5]; 1658 #ifdef FIXME 1659 for (scntl3 = 1; scntl3 < 4; ++scntl3) { 1660 sxfer = (period * 4 - 1) / sc->sc_tcp[scntl3] - 3; 1661 if (sxfer >= 0 && sxfer <= 7) 1662 break; 1663 } 1664 if (scntl3 > 3) { 1665 printf("siopng sync: unable to compute sync params for period %dns\n", 1666 period * 4); 1667 /* 1668 * XXX need to pick a value we can do and renegotiate 1669 */ 1670 sxfer = scntl3 = 0; 1671 } else { 1672 sxfer = (sxfer << 4) | ((offset <= SIOP_MAX_OFFSET) ? 1673 offset : SIOP_MAX_OFFSET); 1674 #ifdef DEBUG_SYNC 1675 printf("siopng sync: params for period %dns: sxfer %x scntl3 %x", 1676 period * 4, sxfer, scntl3); 1677 printf(" actual period %dns\n", 1678 sc->sc_tcp[scntl3] * ((sxfer >> 4) + 4)); 1679 #endif /* DEBUG_SYNC */ 1680 } 1681 #else /* FIXME */ 1682 sxfer = offset <= SIOP_MAX_OFFSET ? offset : SIOP_MAX_OFFSET; 1683 sxfer |= 0x20; /* XXX XFERP: 5 */ 1684 #ifndef FIXME 1685 if (period <= (50 / 4)) /* XXX */ 1686 scntl3 = 0x95; /* Ultra, SCF: /1, CCF: /4 */ 1687 else if (period <= (100 / 4)) 1688 scntl3 = 0x35; /* SCF: /2, CCF: /4 */ 1689 else if (period <= (200 / 4)) 1690 scntl3 = 0x55; /* SCF: /4, CCF: /4 */ 1691 else 1692 scntl3 = 0xff; /* XXX ??? */ 1693 #else 1694 scntl3 = 5; 1695 #endif 1696 #endif 1697 sc->sc_sync[target].sxfer = sxfer; 1698 sc->sc_sync[target].scntl3 = scntl3 | 1699 (sc->sc_sync[target].scntl3 & SIOP_SCNTL3_EWS); 1700 #ifdef DEBUG_SYNC 1701 printf ("siopng sync: siop_sxfr %02x, siop_scntl3 %02x\n", sxfer, scntl3); 1702 #endif 1703 } 1704 1705 void 1706 siopng_dump_registers(struct siop_softc *sc) 1707 { 1708 siop_regmap_p rp = sc->sc_siopp; 1709 1710 printf(" scntl0 %02x scntl1 %02x scntl2 %02x scntl3 %02x\n", 1711 rp->siop_scntl0, rp->siop_scntl1, rp->siop_scntl2, rp->siop_scntl3); 1712 printf(" scid %02x sxfer %02x sdid %02x gpreg %02x\n", 1713 rp->siop_scid, rp->siop_sxfer, rp->siop_sdid, rp->siop_gpreg); 1714 printf(" sfbr %02x socl %02x ssid %02x sbcl %02x\n", 1715 rp->siop_sfbr, rp->siop_socl, rp->siop_ssid, rp->siop_sbcl); 1716 printf(" dstat %02x sstat0 %02x sstat1 %02x sstat2 %02x\n", 1717 rp->siop_dstat, rp->siop_sstat0, rp->siop_sstat1, rp->siop_sstat2); 1718 printf(" ctest0 %02x ctest1 %02x ctest2 %02x ctest3 %02x\n", 1719 rp->siop_ctest0, rp->siop_ctest1, rp->siop_ctest2, rp->siop_ctest3); 1720 printf(" dfifo %02x ctest4 %02x ctest5 %02x ctest6 %02x\n", 1721 0, rp->siop_ctest4, rp->siop_ctest5, rp->siop_ctest6); 1722 printf(" dcmd %02x dbc2 %02x dbc1 %02x dbc0 %02x\n", 1723 rp->siop_dcmd, rp->siop_dbc2, rp->siop_dbc1, rp->siop_dbc0); 1724 printf(" dmode %02x dien %02x dwt %02x dcntl %02x\n", 1725 rp->siop_dmode, rp->siop_dien, rp->siop_dwt, rp->siop_dcntl); 1726 printf(" stest0 %02x stest1 %02x stest2 %02x stest3 %02x\n", 1727 rp->siop_stest0, rp->siop_stest1, rp->siop_stest2, rp->siop_stest3); 1728 printf(" istat %02x sien %04x sist %04x respid %04x\n", 1729 rp->siop_istat, rp->siop_sien, rp->siop_sist, rp->siop_respid); 1730 printf(" sidl %04x sodl %04x sbdl %04x\n", 1731 rp->siop_sidl, rp->siop_sodl, rp->siop_sbdl); 1732 printf(" dsps %08lx dsp %08lx (+%lx)\n", 1733 rp->siop_dsps, rp->siop_dsp, rp->siop_dsp > sc->sc_scriptspa ? 1734 rp->siop_dsp - sc->sc_scriptspa : 0); 1735 printf(" dsa %08lx temp %08lx dnad %08lx\n", 1736 rp->siop_dsa, rp->siop_temp, rp->siop_dnad); 1737 printf(" scratcha %08lx scratchb %08lx adder %08lx\n", 1738 rp->siop_scratcha, rp->siop_scratchb, rp->siop_adder); 1739 } 1740 1741 #ifdef DEBUG 1742 1743 #if SIOP_TRACE_SIZE 1744 void 1745 siopng_dump_trace(void) 1746 { 1747 int i; 1748 1749 printf("siopng trace: next index %d\n", siopng_trix); 1750 i = siopng_trix; 1751 do { 1752 printf("%3d: '%c' %02x %02x %02x\n", i, siopng_trbuf[i], 1753 siopng_trbuf[i + 1], siopng_trbuf[i + 2], siopng_trbuf[i + 3]); 1754 i = (i + 4) & (SIOP_TRACE_SIZE - 1); 1755 } while (i != siopng_trix); 1756 } 1757 #endif 1758 1759 void 1760 siopng_dump_acb(struct siop_acb *acb) 1761 { 1762 u_char *b = (u_char *) &acb->cmd; 1763 int i; 1764 1765 printf("acb@%p ", acb); 1766 if (acb->xs == NULL) { 1767 printf("<unused>\n"); 1768 return; 1769 } 1770 printf("(%d:%d) flags %2x clen %2d cmd ", 1771 acb->xs->xs_periph->periph_target, 1772 acb->xs->xs_periph->periph_lun, acb->flags, acb->clen); 1773 for (i = acb->clen; i; --i) 1774 printf(" %02x", *b++); 1775 printf("\n"); 1776 printf(" xs: %p data %p:%04x ", acb->xs, acb->xs->data, 1777 acb->xs->datalen); 1778 printf("va %p:%lx ", acb->iob_buf, acb->iob_len); 1779 printf("cur %lx:%lx\n", acb->iob_curbuf, acb->iob_curlen); 1780 } 1781 1782 void 1783 siopng_dump(struct siop_softc *sc) 1784 { 1785 struct siop_acb *acb; 1786 siop_regmap_p rp = sc->sc_siopp; 1787 int s; 1788 int i; 1789 1790 s = splbio(); 1791 #if SIOP_TRACE_SIZE 1792 siopng_dump_trace(); 1793 #endif 1794 printf("%s@%p regs %p istat %x\n", 1795 sc->sc_dev.dv_xname, sc, rp, rp->siop_istat); 1796 if ((acb = sc->free_list.tqh_first) > 0) { 1797 printf("Free list:\n"); 1798 while (acb) { 1799 siopng_dump_acb(acb); 1800 acb = acb->chain.tqe_next; 1801 } 1802 } 1803 if ((acb = sc->ready_list.tqh_first) > 0) { 1804 printf("Ready list:\n"); 1805 while (acb) { 1806 siopng_dump_acb(acb); 1807 acb = acb->chain.tqe_next; 1808 } 1809 } 1810 if ((acb = sc->nexus_list.tqh_first) > 0) { 1811 printf("Nexus list:\n"); 1812 while (acb) { 1813 siopng_dump_acb(acb); 1814 acb = acb->chain.tqe_next; 1815 } 1816 } 1817 if (sc->sc_nexus) { 1818 printf("Nexus:\n"); 1819 siopng_dump_acb(sc->sc_nexus); 1820 } 1821 for (i = 0; i < 8; ++i) { 1822 if (sc->sc_tinfo[i].cmds > 2) { 1823 printf("tgt %d: cmds %d disc %d lubusy %x\n", 1824 i, sc->sc_tinfo[i].cmds, 1825 sc->sc_tinfo[i].dconns, 1826 sc->sc_tinfo[i].lubusy); 1827 } 1828 } 1829 splx(s); 1830 } 1831 #endif 1832