Annotation of sys/arch/mvme68k/dev/sbic.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: sbic.c,v 1.19 2007/05/29 13:56:14 pyr Exp $ */
! 2: /* $NetBSD: sbic.c,v 1.2 1996/04/23 16:32:54 chuck Exp $ */
! 3:
! 4: /*
! 5: * Changes Copyright (c) 1996 Steve Woodford
! 6: * Original Copyright (c) 1994 Christian E. Hopps
! 7: * Copyright (c) 1990 The Regents of the University of California.
! 8: * All rights reserved.
! 9: *
! 10: * This code is derived from software contributed to Berkeley by
! 11: * Van Jacobson of Lawrence Berkeley Laboratory.
! 12: *
! 13: * Redistribution and use in source and binary forms, with or without
! 14: * modification, are permitted provided that the following conditions
! 15: * are met:
! 16: * 1. Redistributions of source code must retain the above copyright
! 17: * notice, this list of conditions and the following disclaimer.
! 18: * 2. Redistributions in binary form must reproduce the above copyright
! 19: * notice, this list of conditions and the following disclaimer in the
! 20: * documentation and/or other materials provided with the distribution.
! 21: * 3. Neither the name of the University nor the names of its contributors
! 22: * may be used to endorse or promote products derived from this software
! 23: * without specific prior written permission.
! 24: *
! 25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 35: * SUCH DAMAGE.
! 36: *
! 37: * @(#)scsi.c 7.5 (Berkeley) 5/4/91
! 38: */
! 39:
! 40: /*
! 41: * Steve Woodford (SCW), Apr, 1996
! 42: * MVME147S WD33C93 Scsi Bus Interface Controller driver,
! 43: *
! 44: * Basically a de-loused and tidied up version of the Amiga AMD 33C93 driver.
! 45: *
! 46: * The original driver used features which required at least a WD33C93A
! 47: * chip. The '147 has the original WD33C93 chip (no 'A' suffix).
! 48: *
! 49: * This version of the driver is pretty well generic, so should work with
! 50: * any flavour of WD33C93 chip.
! 51: */
! 52:
! 53: #include <sys/param.h>
! 54: #include <sys/systm.h>
! 55: #include <sys/device.h>
! 56: #include <sys/kernel.h> /* For hz */
! 57: #include <sys/disklabel.h>
! 58: #include <sys/dkstat.h>
! 59: #include <sys/buf.h>
! 60: #include <sys/queue.h>
! 61: #include <scsi/scsi_all.h>
! 62: #include <scsi/scsiconf.h>
! 63: #include <uvm/uvm_extern.h>
! 64: #include <mvme68k/dev/dmavar.h>
! 65: #include <mvme68k/dev/sbicreg.h>
! 66: #include <mvme68k/dev/sbicvar.h>
! 67: #include <machine/autoconf.h>
! 68: #include <mvme68k/dev/pccreg.h>
! 69:
! 70:
! 71: /*
! 72: * Since I can't find this in any other header files
! 73: */
! 74: #define SCSI_PHASE(reg) (reg&0x07)
! 75:
! 76: /*
! 77: * SCSI delays
! 78: * In u-seconds, primarily for state changes on the SPC.
! 79: */
! 80: #define SBIC_CMD_WAIT 50000 /* wait per step of 'immediate' cmds */
! 81: #define SBIC_DATA_WAIT 50000 /* wait per data in/out step */
! 82: #define SBIC_INIT_WAIT 50000 /* wait per step (both) during init */
! 83:
! 84: /*
! 85: * Convenience macro for waiting for a particular sbic event
! 86: */
! 87: #define SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__)
! 88:
! 89: int sbicicmd(struct sbic_softc *, void *, int, void *, int);
! 90: int sbicgo(struct sbic_softc *, struct scsi_xfer *);
! 91: int sbicdmaok(struct sbic_softc *, struct scsi_xfer *);
! 92: int sbicwait(sbic_regmap_p, u_char, int , int);
! 93: int sbiccheckdmap(void *, u_long, u_long);
! 94: u_char sbicselectbus(struct sbic_softc *);
! 95: int sbicxfout(sbic_regmap_p, int, void *);
! 96: int sbicxfin(sbic_regmap_p, int, void *);
! 97: int sbicfromscsiperiod(struct sbic_softc *, int);
! 98: int sbictoscsiperiod(struct sbic_softc *, int);
! 99: int sbicintr(struct sbic_softc *);
! 100: int sbicpoll(struct sbic_softc *);
! 101: int sbicnextstate(struct sbic_softc *, u_char, u_char);
! 102: int sbicmsgin(struct sbic_softc *);
! 103: int sbicabort(struct sbic_softc *, char *);
! 104: void sbicxfdone(struct sbic_softc *);
! 105: void sbicerror(struct sbic_softc *,u_char);
! 106: void sbicreset(struct sbic_softc *);
! 107: void sbic_scsidone(struct sbic_acb *, int);
! 108: void sbic_sched(struct sbic_softc *);
! 109: void sbic_save_ptrs(struct sbic_softc *);
! 110: void sbic_load_ptrs(struct sbic_softc *);
! 111: void sbicinit(struct sbic_softc *);
! 112:
! 113: /*
! 114: * Synch xfer parameters, and timing conversions
! 115: */
! 116: int sbic_min_period = SBIC_SYN_MIN_PERIOD; /* in cycles = f(ICLK,FSn) */
! 117: int sbic_max_offset = SBIC_SYN_MAX_OFFSET; /* pure number */
! 118: int sbic_cmd_wait = SBIC_CMD_WAIT;
! 119: int sbic_data_wait = SBIC_DATA_WAIT;
! 120: int sbic_init_wait = SBIC_INIT_WAIT;
! 121:
! 122: /*
! 123: * was broken before.. now if you want this you get it for all drives
! 124: * on sbic controllers.
! 125: */
! 126: u_char sbic_inhibit_sync[8];
! 127: int sbic_enable_reselect = 1; /* Allow Disconnect / Reselect */
! 128: int sbic_no_dma = 0; /* Use PIO transfers instead of DMA */
! 129: int sbic_parallel_operations = 1; /* Allow command queues */
! 130:
! 131: /*
! 132: * Some useful stuff for debugging purposes
! 133: */
! 134: #ifdef DEBUG
! 135: int sbicdma_ops = 0; /* total DMA operations */
! 136: int sbicdma_hits = 0; /* number of DMA chains that were contiguous */
! 137: int sbicdma_misses = 0; /* number of DMA chains that were not contiguous */
! 138: int sbicdma_saves = 0;
! 139:
! 140: #define QPRINTF(a) if (sbic_debug > 1) printf a
! 141:
! 142: int sbic_debug = 0; /* Debug all chip related things */
! 143: int sync_debug = 0; /* Debug all Synchronous Scsi related things */
! 144: int reselect_debug = 0; /* Debug all reselection related things */
! 145: int report_sense = 0; /* Always print Sense information */
! 146: int data_pointer_debug = 0; /* Debug Data Pointer related things */
! 147:
! 148: void sbictimeout(struct sbic_softc *dev);
! 149:
! 150: #else
! 151: #define QPRINTF(a) /* */
! 152: #endif
! 153:
! 154:
! 155: /*
! 156: * default minphys routine for sbic based controllers
! 157: */
! 158: void
! 159: sbic_minphys(bp)
! 160: struct buf *bp;
! 161: {
! 162: /*
! 163: * No max transfer at this level.
! 164: */
! 165: minphys(bp);
! 166: }
! 167:
! 168:
! 169: /*
! 170: * Save DMA pointers. Take into account partial transfer. Shut down DMA.
! 171: */
! 172: void
! 173: sbic_save_ptrs(dev)
! 174: struct sbic_softc *dev;
! 175: {
! 176: sbic_regmap_p regs;
! 177: struct sbic_acb* acb;
! 178: int count,
! 179: asr,
! 180: s;
! 181:
! 182: /*
! 183: * Only need to save pointers if DMA was active...
! 184: */
! 185: if ( dev->sc_cur == NULL || (dev->sc_flags & SBICF_INDMA) == 0 )
! 186: return;
! 187:
! 188: regs = dev->sc_sbicp;
! 189:
! 190: s = splbio();
! 191:
! 192: /*
! 193: * Wait until WD chip is idle
! 194: */
! 195: do {
! 196: GET_SBIC_asr(regs, asr);
! 197: if( asr & SBIC_ASR_DBR ) {
! 198: printf("sbic_save_ptrs: asr %02x canceled!\n", asr);
! 199: splx(s);
! 200: return;
! 201: }
! 202: } while( asr & (SBIC_ASR_BSY|SBIC_ASR_CIP) );
! 203:
! 204:
! 205: /*
! 206: * Save important state.
! 207: * must be done before dmastop
! 208: */
! 209: acb = dev->sc_nexus;
! 210: acb->sc_dmacmd = dev->sc_dmacmd;
! 211:
! 212: /*
! 213: * Fetch the residual count
! 214: */
! 215: SBIC_TC_GET(regs, count);
! 216:
! 217: /*
! 218: * Shut down DMA
! 219: */
! 220: dev->sc_dmastop(dev);
! 221:
! 222: /*
! 223: * No longer in DMA
! 224: */
! 225: dev->sc_flags &= ~SBICF_INDMA;
! 226:
! 227: /*
! 228: * Ensure the WD chip is back in polled I/O mode, with nothing to
! 229: * transfer.
! 230: */
! 231: SBIC_TC_PUT(regs, 0);
! 232: SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
! 233:
! 234: /*
! 235: * Update current count...
! 236: */
! 237: acb->sc_tcnt = count;
! 238:
! 239: /*
! 240: * Work out how many bytes were actually transferred
! 241: */
! 242: count = dev->sc_tcnt - count;
! 243: dev->sc_tcnt = acb->sc_tcnt;
! 244:
! 245: /*
! 246: * Fixup partial xfers
! 247: */
! 248: acb->sc_kv.dc_addr += count;
! 249: acb->sc_kv.dc_count -= count;
! 250: acb->sc_pa.dc_addr += count;
! 251: acb->sc_pa.dc_count -= count >> 1;
! 252:
! 253: #ifdef DEBUG
! 254: if ( data_pointer_debug )
! 255: printf("save at (%x,%x):%x\n",
! 256: dev->sc_cur->dc_addr, dev->sc_cur->dc_count,count);
! 257: sbicdma_saves++;
! 258: #endif
! 259:
! 260: splx(s);
! 261: }
! 262:
! 263:
! 264: /*
! 265: * DOES NOT RESTART DMA!!!
! 266: */
! 267: void
! 268: sbic_load_ptrs(dev)
! 269: struct sbic_softc *dev;
! 270: {
! 271: struct sbic_acb *acb = dev->sc_nexus;
! 272: int s;
! 273:
! 274: if ( acb->sc_kv.dc_count == 0 ) {
! 275: /*
! 276: * No data to xfer
! 277: */
! 278: return;
! 279: }
! 280:
! 281: s = splbio();
! 282:
! 283: /*
! 284: * Reset the Scatter-Gather chain
! 285: */
! 286: dev->sc_last = dev->sc_cur = &acb->sc_pa;
! 287:
! 288: /*
! 289: * Restore the Transfer Count and DMA specific data
! 290: */
! 291: dev->sc_tcnt = acb->sc_tcnt;
! 292: dev->sc_dmacmd = acb->sc_dmacmd;
! 293:
! 294: #ifdef DEBUG
! 295: sbicdma_ops++;
! 296: #endif
! 297:
! 298: /*
! 299: * Need to fixup new segment?
! 300: */
! 301: if ( dev->sc_tcnt == 0 ) {
! 302: /*
! 303: * sc_tcnt == 0 implies end of segment
! 304: */
! 305: char *vaddr, *paddr;
! 306: int count;
! 307:
! 308: /*
! 309: * do kvm to pa mappings
! 310: */
! 311: vaddr = acb->sc_kv.dc_addr;
! 312: paddr = acb->sc_pa.dc_addr = (char *)kvtop((vaddr_t)vaddr);
! 313:
! 314: for (count = (NBPG - ((int)vaddr & PGOFSET));
! 315: count < acb->sc_kv.dc_count &&
! 316: (char *)kvtop((vaddr_t)vaddr + count + 4) == paddr + count + 4;
! 317: count += NBPG)
! 318: ; /* Do nothing */
! 319:
! 320: /*
! 321: * If it's all contiguous...
! 322: */
! 323: if ( count > acb->sc_kv.dc_count ) {
! 324: count = acb->sc_kv.dc_count;
! 325: #ifdef DEBUG
! 326: sbicdma_hits++;
! 327: #endif
! 328: }
! 329: #ifdef DEBUG
! 330: else
! 331: sbicdma_misses++;
! 332: #endif
! 333:
! 334: acb->sc_tcnt = count;
! 335: acb->sc_pa.dc_count = count >> 1;
! 336:
! 337: #ifdef DEBUG
! 338: if ( data_pointer_debug )
! 339: printf("DMA recalc:kv(%x,%x)pa(%x,%x)\n", acb->sc_kv.dc_addr,
! 340: acb->sc_kv.dc_count,
! 341: acb->sc_pa.dc_addr,
! 342: acb->sc_tcnt);
! 343: #endif
! 344:
! 345: }
! 346:
! 347: splx(s);
! 348: }
! 349:
! 350: /*
! 351: * used by specific sbic controller
! 352: *
! 353: * it appears that the higher level code does nothing with LUN's
! 354: * so I will too. I could plug it in, however so could they
! 355: * in scsi_scsi_cmd().
! 356: */
! 357: int
! 358: sbic_scsicmd(xs)
! 359: struct scsi_xfer *xs;
! 360: {
! 361: struct scsi_link *slp = xs->sc_link;
! 362: struct sbic_softc *dev = slp->adapter_softc;
! 363: struct sbic_acb *acb;
! 364: int flags = xs->flags,
! 365: s;
! 366:
! 367: if ( flags & SCSI_DATA_UIO )
! 368: panic("sbic: scsi data uio requested");
! 369:
! 370: if ( dev->sc_nexus && (flags & SCSI_POLL) )
! 371: panic("sbic_scsicmd: busy");
! 372:
! 373: if ( slp->target == slp->adapter_target )
! 374: return ESCAPE_NOT_SUPPORTED;
! 375:
! 376: s = splbio();
! 377:
! 378: if ( (acb = TAILQ_FIRST(&dev->free_list)) != NULL )
! 379: TAILQ_REMOVE(&dev->free_list, acb, chain);
! 380:
! 381: splx(s);
! 382:
! 383: if ( acb == NULL ) {
! 384: #ifdef DEBUG
! 385: printf("sbic_scsicmd: unable to queue request for target %d\n",
! 386: slp->target);
! 387: #ifdef DDB
! 388: Debugger();
! 389: #endif
! 390: #endif
! 391: return(TRY_AGAIN_LATER);
! 392: }
! 393:
! 394: if ( flags & SCSI_DATA_IN )
! 395: acb->flags = ACB_ACTIVE | ACB_DATAIN;
! 396: else
! 397: acb->flags = ACB_ACTIVE;
! 398:
! 399: acb->xs = xs;
! 400: acb->clen = xs->cmdlen;
! 401: acb->sc_kv.dc_addr = xs->data;
! 402: acb->sc_kv.dc_count = xs->datalen;
! 403: acb->pa_addr = xs->data ? (char *)kvtop((vaddr_t)xs->data) : 0;
! 404: bcopy(xs->cmd, &acb->cmd, xs->cmdlen);
! 405:
! 406: if ( flags & SCSI_POLL ) {
! 407: /*
! 408: * This has major side effects -- it locks up the machine
! 409: */
! 410: int stat;
! 411:
! 412: s = splbio();
! 413:
! 414: dev->sc_flags |= SBICF_ICMD;
! 415:
! 416: do {
! 417: /*
! 418: * If we already had a nexus, while away the time until idle...
! 419: * This is likely only to happen if a reselection occurs between
! 420: * here and our earlier check for ICMD && sc_nexus (which would
! 421: * have resulted in a panic() had it been true).
! 422: */
! 423: while ( dev->sc_nexus )
! 424: sbicpoll(dev);
! 425:
! 426: /*
! 427: * Fix up the new nexus
! 428: */
! 429: dev->sc_nexus = acb;
! 430: dev->sc_xs = xs;
! 431: dev->target = slp->target;
! 432: dev->lun = slp->lun;
! 433:
! 434: stat = sbicicmd(dev, &acb->cmd, acb->clen,
! 435: acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
! 436:
! 437: } while ( dev->sc_nexus != acb );
! 438:
! 439: sbic_scsidone(acb, stat);
! 440:
! 441: splx(s);
! 442:
! 443: return(COMPLETE);
! 444: }
! 445:
! 446: s = splbio();
! 447: TAILQ_INSERT_TAIL(&dev->ready_list, acb, chain);
! 448:
! 449: /*
! 450: * If nothing is active, try to start it now.
! 451: */
! 452: if ( dev->sc_nexus == NULL )
! 453: sbic_sched(dev);
! 454:
! 455: splx(s);
! 456:
! 457: return(SUCCESSFULLY_QUEUED);
! 458: }
! 459:
! 460: /*
! 461: * attempt to start the next available command
! 462: */
! 463: void
! 464: sbic_sched(dev)
! 465: struct sbic_softc *dev;
! 466: {
! 467: struct scsi_xfer *xs;
! 468: struct scsi_link *slp = NULL; /* Gag the compiler */
! 469: struct sbic_acb *acb;
! 470: int flags,
! 471: stat;
! 472:
! 473: /*
! 474: * XXXSCW
! 475: * I'll keep this test here, even though I can't see any obvious way
! 476: * in which sbic_sched() could be called with sc_nexus non NULL
! 477: */
! 478: if ( dev->sc_nexus )
! 479: return; /* a command is current active */
! 480:
! 481: /*
! 482: * Loop through the ready list looking for work to do...
! 483: */
! 484: TAILQ_FOREACH(acb, &dev->ready_list, chain) {
! 485: int i, j;
! 486:
! 487: slp = acb->xs->sc_link;
! 488: i = slp->target;
! 489: j = 1 << slp->lun;
! 490:
! 491: /*
! 492: * We've found a potential command, but is the target/lun busy?
! 493: */
! 494: if ( (dev->sc_tinfo[i].lubusy & j) == 0 ) {
! 495: /*
! 496: * Nope, it's not busy, so we can use it.
! 497: */
! 498: dev->sc_tinfo[i].lubusy |= j;
! 499: TAILQ_REMOVE(&dev->ready_list, acb, chain);
! 500: dev->sc_nexus = acb;
! 501: acb->sc_pa.dc_addr = acb->pa_addr; /* XXXX check */
! 502: break;
! 503: }
! 504: }
! 505:
! 506: if ( acb == NULL ) {
! 507: QPRINTF(("sbicsched: no work\n"));
! 508: return; /* did not find an available command */
! 509: }
! 510:
! 511: #ifdef DEBUG
! 512: if ( data_pointer_debug > 1 )
! 513: printf("sbic_sched(%d,%d)\n", slp->target, slp->lun);
! 514: #endif
! 515:
! 516: dev->sc_xs = xs = acb->xs;
! 517: flags = xs->flags;
! 518:
! 519: if ( flags & SCSI_RESET )
! 520: sbicreset(dev);
! 521:
! 522: dev->sc_stat[0] = -1;
! 523: dev->target = slp->target;
! 524: dev->lun = slp->lun;
! 525:
! 526: if ( flags & SCSI_POLL || (!sbic_parallel_operations &&
! 527: (sbicdmaok(dev, xs) == 0)) )
! 528: stat = sbicicmd(dev, &acb->cmd, acb->clen,
! 529: acb->sc_kv.dc_addr, acb->sc_kv.dc_count);
! 530: else
! 531: if ( sbicgo(dev, xs) == 0 )
! 532: return;
! 533: else
! 534: stat = dev->sc_stat[0];
! 535:
! 536: sbic_scsidone(acb, stat);
! 537: }
! 538:
! 539: void
! 540: sbic_scsidone(acb, stat)
! 541: struct sbic_acb *acb;
! 542: int stat;
! 543: {
! 544: struct scsi_xfer *xs = acb->xs;
! 545: struct scsi_link *slp = xs->sc_link;
! 546: struct sbic_softc *dev = slp->adapter_softc;
! 547: int dosched = 0;
! 548:
! 549: #ifdef DIAGNOSTIC
! 550: if ( acb == NULL || xs == NULL ) {
! 551: printf("sbic_scsidone -- (%d,%d) no scsi_xfer\n", dev->target, dev->lun);
! 552: #ifdef DDB
! 553: Debugger();
! 554: #endif
! 555: return;
! 556: }
! 557: #endif
! 558:
! 559: /*
! 560: * is this right?
! 561: */
! 562: xs->status = stat;
! 563:
! 564: #ifdef DEBUG
! 565: if ( data_pointer_debug > 1 )
! 566: printf("scsidone: (%d,%d)->(%d,%d)%02x\n", slp->target, slp->lun,
! 567: dev->target, dev->lun, stat);
! 568:
! 569: if ( xs->sc_link->target == dev->sc_link.adapter_target )
! 570: panic("target == hostid");
! 571: #endif
! 572:
! 573: if ( xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE) == 0 ) {
! 574:
! 575: if ( stat == SCSI_CHECK ) {
! 576: /*
! 577: * Schedule a REQUEST SENSE
! 578: */
! 579: struct scsi_sense *ss = (void *)&acb->cmd;
! 580:
! 581: #ifdef DEBUG
! 582: if ( report_sense )
! 583: printf("sbic_scsidone: autosense %02x targ %d lun %d",
! 584: acb->cmd.opcode, slp->target, slp->lun);
! 585: #endif
! 586:
! 587: bzero(ss, sizeof(*ss));
! 588:
! 589: ss->opcode = REQUEST_SENSE;
! 590: ss->byte2 = slp->lun << 5;
! 591: ss->length = sizeof(struct scsi_sense_data);
! 592:
! 593: acb->clen = sizeof(*ss);
! 594: acb->sc_kv.dc_addr = (char *)&xs->sense;
! 595: acb->sc_kv.dc_count = sizeof(struct scsi_sense_data);
! 596: acb->pa_addr = (char *)kvtop((vaddr_t)&xs->sense); /* XXX check */
! 597: acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN;
! 598:
! 599: TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain);
! 600:
! 601: dev->sc_tinfo[slp->target].lubusy &= ~(1 << slp->lun);
! 602: dev->sc_tinfo[slp->target].senses++;
! 603:
! 604: if ( dev->sc_nexus == acb ) {
! 605: dev->sc_nexus = NULL;
! 606: dev->sc_xs = NULL;
! 607: sbic_sched(dev);
! 608: }
! 609: return;
! 610: }
! 611: }
! 612:
! 613: if ( xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE) != 0 ) {
! 614:
! 615: xs->error = XS_SENSE;
! 616:
! 617: #ifdef DEBUG
! 618: if (report_sense)
! 619: printf(" => %02x %02x\n", xs->sense.flags,
! 620: xs->sense.extra_bytes[3]);
! 621: #endif
! 622:
! 623: } else {
! 624: xs->resid = 0; /* XXXX */
! 625: }
! 626:
! 627: xs->flags |= ITSDONE;
! 628:
! 629: /*
! 630: * Remove the ACB from whatever queue it's on. We have to do a bit of
! 631: * a hack to figure out which queue it's on. Note that it is *not*
! 632: * necessary to cdr down the ready queue, but we must cdr down the
! 633: * nexus queue and see if it's there, so we can mark the unit as no
! 634: * longer busy. This code is sickening, but it works.
! 635: */
! 636: if ( acb == dev->sc_nexus ) {
! 637:
! 638: dev->sc_nexus = NULL;
! 639: dev->sc_xs = NULL;
! 640:
! 641: dev->sc_tinfo[slp->target].lubusy &= ~(1 << slp->lun);
! 642:
! 643: if ( !TAILQ_EMPTY(&dev->ready_list) )
! 644: dosched = 1; /* start next command */
! 645:
! 646: } else
! 647: if (TAILQ_LAST(&dev->ready_list, acb_list) == TAILQ_NEXT(acb, chain)) {
! 648:
! 649: TAILQ_REMOVE(&dev->ready_list, acb, chain);
! 650:
! 651: } else {
! 652:
! 653: register struct sbic_acb *a;
! 654:
! 655: TAILQ_FOREACH(a, &dev->nexus_list, chain) {
! 656: if ( a == acb ) {
! 657: TAILQ_REMOVE(&dev->nexus_list, acb, chain);
! 658: dev->sc_tinfo[slp->target].lubusy &= ~(1 << slp->lun);
! 659: break;
! 660: }
! 661: }
! 662:
! 663: if ( a )
! 664: ;
! 665: else if ( TAILQ_NEXT(acb, chain) != NULL) {
! 666: TAILQ_REMOVE(&dev->ready_list, acb, chain);
! 667: } else {
! 668: printf("%s: can't find matching acb\n", dev->sc_dev.dv_xname);
! 669: #ifdef DDB
! 670: Debugger();
! 671: #endif
! 672: }
! 673: }
! 674:
! 675: /*
! 676: * Put it on the free list.
! 677: */
! 678: acb->flags = ACB_FREE;
! 679: TAILQ_INSERT_HEAD(&dev->free_list, acb, chain);
! 680:
! 681: dev->sc_tinfo[slp->target].cmds++;
! 682:
! 683: scsi_done(xs);
! 684:
! 685: if ( dosched )
! 686: sbic_sched(dev);
! 687: }
! 688:
! 689: int
! 690: sbicdmaok(dev, xs)
! 691: struct sbic_softc *dev;
! 692: struct scsi_xfer *xs;
! 693: {
! 694: if ( sbic_no_dma || xs->datalen & 0x03 || (int)xs->data & 0x03)
! 695: return(0);
! 696:
! 697: /*
! 698: * controller supports dma to any addresses?
! 699: */
! 700: if ( (dev->sc_flags & SBICF_BADDMA) == 0 )
! 701: return(1);
! 702:
! 703: /*
! 704: * this address is ok for dma?
! 705: */
! 706: if ( sbiccheckdmap(xs->data, xs->datalen, dev->sc_dmamask) == 0 )
! 707: return(1);
! 708:
! 709: return(0);
! 710: }
! 711:
! 712: int
! 713: sbicwait(regs, until, timeo, line)
! 714: sbic_regmap_p regs;
! 715: u_char until;
! 716: int timeo;
! 717: int line;
! 718: {
! 719: u_char val;
! 720:
! 721: if ( timeo == 0 )
! 722: timeo = 1000000; /* some large value.. */
! 723:
! 724: GET_SBIC_asr(regs, val);
! 725:
! 726: while ( (val & until) == 0 ) {
! 727:
! 728: if ( timeo-- == 0 ) {
! 729: int csr;
! 730: GET_SBIC_csr(regs, csr);
! 731: printf("sbicwait TIMEO @%d with asr=x%x csr=x%x\n", line, val, csr);
! 732: #if defined(DDB) && defined(DEBUG)
! 733: Debugger();
! 734: #endif
! 735: return(val); /* Maybe I should abort */
! 736: break;
! 737: }
! 738:
! 739: DELAY(1);
! 740: GET_SBIC_asr(regs, val);
! 741: }
! 742:
! 743: return(val);
! 744: }
! 745:
! 746: int
! 747: sbicabort(dev, where)
! 748: struct sbic_softc *dev;
! 749: char *where;
! 750: {
! 751: sbic_regmap_p regs = dev->sc_sbicp;
! 752: u_char csr,
! 753: asr;
! 754:
! 755: GET_SBIC_asr(regs, asr);
! 756: GET_SBIC_csr(regs, csr);
! 757:
! 758: printf ("%s: abort %s: csr = 0x%02x, asr = 0x%02x\n",
! 759: dev->sc_dev.dv_xname, where, csr, asr);
! 760:
! 761: /*
! 762: * Clean up chip itself
! 763: */
! 764: if ( dev->sc_flags & SBICF_SELECTED ) {
! 765:
! 766: while ( asr & SBIC_ASR_DBR ) {
! 767: /*
! 768: * sbic is jammed w/data. need to clear it
! 769: * But we don't know what direction it needs to go
! 770: */
! 771: GET_SBIC_data(regs, asr);
! 772: printf("%s: abort %s: clearing data buffer 0x%02x\n",
! 773: dev->sc_dev.dv_xname, where, asr);
! 774: GET_SBIC_asr(regs, asr);
! 775: if ( asr & SBIC_ASR_DBR ) /* Not the read direction, then */
! 776: SET_SBIC_data(regs, asr);
! 777: GET_SBIC_asr(regs, asr);
! 778: }
! 779:
! 780: WAIT_CIP(regs);
! 781:
! 782: printf("%s: sbicabort - sending ABORT command\n", dev->sc_dev.dv_xname);
! 783: SET_SBIC_cmd(regs, SBIC_CMD_ABORT);
! 784: WAIT_CIP(regs);
! 785:
! 786: GET_SBIC_asr(regs, asr);
! 787:
! 788: if ( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI) ) {
! 789: /*
! 790: * ok, get more drastic..
! 791: */
! 792: printf("%s: sbicabort - asr %x, trying to reset\n",
! 793: dev->sc_dev.dv_xname, asr);
! 794: sbicreset(dev);
! 795: dev->sc_flags &= ~SBICF_SELECTED;
! 796: return SBIC_STATE_ERROR;
! 797: }
! 798:
! 799: printf("%s: sbicabort - sending DISC command\n", dev->sc_dev.dv_xname);
! 800: SET_SBIC_cmd(regs, SBIC_CMD_DISC);
! 801:
! 802: do {
! 803: SBIC_WAIT (regs, SBIC_ASR_INT, 0);
! 804: GET_SBIC_asr(regs, asr);
! 805: GET_SBIC_csr (regs, csr);
! 806: QPRINTF(("csr: 0x%02x, asr: 0x%02x\n", csr, asr));
! 807: } while ( (csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) &&
! 808: (csr != SBIC_CSR_CMD_INVALID) );
! 809:
! 810: /*
! 811: * lets just hope it worked..
! 812: */
! 813: dev->sc_flags &= ~SBICF_SELECTED;
! 814: }
! 815:
! 816: return SBIC_STATE_ERROR;
! 817: }
! 818:
! 819:
! 820: /*
! 821: * Initialize driver-private structures
! 822: */
! 823: void
! 824: sbicinit(dev)
! 825: struct sbic_softc *dev;
! 826: {
! 827: u_int i;
! 828:
! 829: extern u_long scsi_nosync;
! 830: extern int shift_nosync;
! 831:
! 832: if ( (dev->sc_flags & SBICF_ALIVE) == 0 ) {
! 833:
! 834: struct sbic_acb *acb;
! 835:
! 836: TAILQ_INIT(&dev->ready_list);
! 837: TAILQ_INIT(&dev->nexus_list);
! 838: TAILQ_INIT(&dev->free_list);
! 839:
! 840: dev->sc_nexus = NULL;
! 841: dev->sc_xs = NULL;
! 842:
! 843: acb = dev->sc_acb;
! 844: bzero(acb, sizeof(dev->sc_acb));
! 845:
! 846: for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) {
! 847: TAILQ_INSERT_TAIL(&dev->free_list, acb, chain);
! 848: acb++;
! 849: }
! 850:
! 851: bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo));
! 852:
! 853: #ifdef DEBUG
! 854: /*
! 855: * make sure timeout is really not needed
! 856: */
! 857: timeout((void *)sbictimeout, dev, 30 * hz);
! 858: #endif
! 859:
! 860: } else
! 861: panic("sbic: reinitializing driver!");
! 862:
! 863: dev->sc_flags |= SBICF_ALIVE;
! 864: dev->sc_flags &= ~SBICF_SELECTED;
! 865:
! 866: /*
! 867: * initialize inhibit array
! 868: */
! 869: if ( scsi_nosync ) {
! 870:
! 871: u_int inhibit_sync = (scsi_nosync >> shift_nosync) & 0xff;
! 872:
! 873: shift_nosync += 8;
! 874:
! 875: #ifdef DEBUG
! 876: if ( inhibit_sync )
! 877: printf("%s: Inhibiting synchronous transfer %02x\n",
! 878: dev->sc_dev.dv_xname, inhibit_sync);
! 879: #endif
! 880: for (i = 0; i < 8; ++i) {
! 881: if ( inhibit_sync & (1 << i) )
! 882: sbic_inhibit_sync[i] = 1;
! 883: }
! 884: }
! 885:
! 886: sbicreset(dev);
! 887: }
! 888:
! 889: void
! 890: sbicreset(dev)
! 891: struct sbic_softc *dev;
! 892: {
! 893: sbic_regmap_p regs = dev->sc_sbicp;
! 894: u_int my_id,
! 895: s;
! 896: u_char csr;
! 897:
! 898: s = splbio();
! 899:
! 900: my_id = dev->sc_link.adapter_target & SBIC_ID_MASK;
! 901:
! 902: if (dev->sc_clkfreq < 110)
! 903: my_id |= SBIC_ID_FS_8_10;
! 904: else if (dev->sc_clkfreq < 160)
! 905: my_id |= SBIC_ID_FS_12_15;
! 906: else if (dev->sc_clkfreq < 210)
! 907: my_id |= SBIC_ID_FS_16_20;
! 908:
! 909: SET_SBIC_myid(regs, my_id);
! 910:
! 911: /*
! 912: * Reset the chip
! 913: */
! 914: SET_SBIC_cmd(regs, SBIC_CMD_RESET);
! 915: DELAY(25);
! 916:
! 917: SBIC_WAIT(regs, SBIC_ASR_INT, 0);
! 918: GET_SBIC_csr(regs, csr); /* clears interrupt also */
! 919:
! 920: /*
! 921: * Set up various chip parameters
! 922: */
! 923: SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
! 924:
! 925: /*
! 926: * don't allow Selection (SBIC_RID_ES)
! 927: * until we can handle target mode!!
! 928: */
! 929: SET_SBIC_rselid(regs, SBIC_RID_ER);
! 930:
! 931: /*
! 932: * Asynchronous for now
! 933: */
! 934: SET_SBIC_syn(regs, 0);
! 935:
! 936: /*
! 937: * Anything else was zeroed by reset
! 938: */
! 939: splx(s);
! 940:
! 941: dev->sc_flags &= ~SBICF_SELECTED;
! 942: }
! 943:
! 944: void
! 945: sbicerror(dev, csr)
! 946: struct sbic_softc *dev;
! 947: u_char csr;
! 948: {
! 949: struct scsi_xfer *xs = dev->sc_xs;
! 950:
! 951: #ifdef DIAGNOSTIC
! 952: if ( xs == NULL )
! 953: panic("sbicerror: dev->sc_xs == NULL");
! 954: #endif
! 955:
! 956: if ( xs->flags & SCSI_SILENT )
! 957: return;
! 958:
! 959: printf("%s: csr == 0x%02x\n", dev->sc_dev.dv_xname, csr);
! 960: }
! 961:
! 962: /*
! 963: * select the bus, return when selected or error.
! 964: *
! 965: * Returns the current CSR following selection and optionally MSG out phase.
! 966: * i.e. the returned CSR *should* indicate CMD phase...
! 967: * If the return value is 0, some error happened.
! 968: */
! 969: u_char
! 970: sbicselectbus(dev)
! 971: struct sbic_softc *dev;
! 972: {
! 973: sbic_regmap_p regs = dev->sc_sbicp;
! 974: u_char target = dev->target,
! 975: lun = dev->lun,
! 976: asr,
! 977: csr,
! 978: id;
! 979:
! 980: /*
! 981: * if we're already selected, return (XXXX panic maybe?)
! 982: */
! 983: if ( dev->sc_flags & SBICF_SELECTED )
! 984: return(0);
! 985:
! 986: QPRINTF(("sbicselectbus %d: ", target));
! 987:
! 988: /*
! 989: * issue select
! 990: */
! 991: SET_SBIC_selid(regs, target);
! 992: SET_SBIC_timeo(regs, SBIC_TIMEOUT(250, dev->sc_clkfreq));
! 993:
! 994: GET_SBIC_asr(regs, asr);
! 995:
! 996: if ( asr & (SBIC_ASR_INT|SBIC_ASR_BSY) ) {
! 997: /*
! 998: * This means we got ourselves reselected upon
! 999: */
! 1000: QPRINTF(("WD busy (reselect?)\n"));
! 1001: return 0;
! 1002: }
! 1003:
! 1004: SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN);
! 1005:
! 1006: /*
! 1007: * wait for select (merged from separate function may need
! 1008: * cleanup)
! 1009: */
! 1010: WAIT_CIP(regs);
! 1011:
! 1012: do {
! 1013:
! 1014: asr = SBIC_WAIT(regs, SBIC_ASR_INT | SBIC_ASR_LCI, 0);
! 1015:
! 1016: if ( asr & SBIC_ASR_LCI ) {
! 1017: QPRINTF(("late LCI: asr %02x\n", asr));
! 1018: return 0;
! 1019: }
! 1020:
! 1021: /*
! 1022: * Clear interrupt
! 1023: */
! 1024: GET_SBIC_csr (regs, csr);
! 1025:
! 1026: QPRINTF(("%02x ", csr));
! 1027:
! 1028: /*
! 1029: * Reselected from under our feet?
! 1030: */
! 1031: if ( csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY ) {
! 1032: QPRINTF(("got reselected, asr %02x\n", asr));
! 1033: /*
! 1034: * We need to handle this now so we don't lock up later
! 1035: */
! 1036: sbicnextstate(dev, csr, asr);
! 1037:
! 1038: return 0;
! 1039: }
! 1040:
! 1041: /*
! 1042: * Whoops!
! 1043: */
! 1044: if ( csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN ) {
! 1045: panic("sbicselectbus: target issued select!");
! 1046: return 0;
! 1047: }
! 1048:
! 1049: } while (csr != (SBIC_CSR_MIS_2 | MESG_OUT_PHASE) &&
! 1050: csr != (SBIC_CSR_MIS_2 | CMD_PHASE) &&
! 1051: csr != SBIC_CSR_SEL_TIMEO);
! 1052:
! 1053: /*
! 1054: * Anyone at home?
! 1055: */
! 1056: if ( csr == SBIC_CSR_SEL_TIMEO ) {
! 1057: dev->sc_xs->error = XS_SELTIMEOUT;
! 1058: QPRINTF(("Selection Timeout\n"));
! 1059: return 0;
! 1060: }
! 1061:
! 1062: QPRINTF(("Selection Complete\n"));
! 1063:
! 1064: /*
! 1065: * Assume we're now selected
! 1066: */
! 1067: GET_SBIC_selid(regs, id);
! 1068: dev->target = id;
! 1069: dev->lun = lun;
! 1070: dev->sc_flags |= SBICF_SELECTED;
! 1071:
! 1072: /*
! 1073: * Enable (or not) reselection
! 1074: * XXXSCW This is probably not necessary since we don't use use the
! 1075: * Select-and-Xfer-with-ATN command to initiate a selection...
! 1076: */
! 1077: if ( !sbic_enable_reselect && TAILQ_EMPTY(&dev->nexus_list))
! 1078: SET_SBIC_rselid (regs, 0);
! 1079: else
! 1080: SET_SBIC_rselid (regs, SBIC_RID_ER);
! 1081:
! 1082: /*
! 1083: * We only really need to do anything when the target goes to MSG out
! 1084: * If the device ignored ATN, it's probably old and brain-dead,
! 1085: * but we'll try to support it anyhow.
! 1086: * If it doesn't support message out, it definitely doesn't
! 1087: * support synchronous transfers, so no point in even asking...
! 1088: */
! 1089: if ( csr == (SBIC_CSR_MIS_2 | MESG_OUT_PHASE) ) {
! 1090: /*
! 1091: * Send identify message (SCSI-2 requires an identify msg)
! 1092: */
! 1093: if ( sbic_inhibit_sync[id] && dev->sc_sync[id].state == SYNC_START ) {
! 1094: /*
! 1095: * Handle drives that don't want to be asked
! 1096: * whether to go sync at all.
! 1097: */
! 1098: dev->sc_sync[id].offset = 0;
! 1099: dev->sc_sync[id].period = sbic_min_period;
! 1100: dev->sc_sync[id].state = SYNC_DONE;
! 1101: }
! 1102:
! 1103: /*
! 1104: * Do we need to negotiate Synchronous Xfers for this target?
! 1105: */
! 1106: if ( dev->sc_sync[id].state != SYNC_START ) {
! 1107: /*
! 1108: * Nope, we've already negotiated.
! 1109: * Now see if we should allow the target to disconnect/reselect...
! 1110: */
! 1111: if ( dev->sc_xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD ||
! 1112: !sbic_enable_reselect )
! 1113: SEND_BYTE (regs, MSG_IDENTIFY | lun);
! 1114: else
! 1115: SEND_BYTE (regs, MSG_IDENTIFY_DR | lun);
! 1116:
! 1117: } else {
! 1118: /*
! 1119: * try to initiate a sync transfer.
! 1120: * So compose the sync message we're going
! 1121: * to send to the target
! 1122: */
! 1123: #ifdef DEBUG
! 1124: if ( sync_debug )
! 1125: printf("\nSending sync request to target %d ... ", id);
! 1126: #endif
! 1127: /*
! 1128: * setup scsi message sync message request
! 1129: */
! 1130: dev->sc_msg[0] = MSG_IDENTIFY | lun;
! 1131: dev->sc_msg[1] = MSG_EXT_MESSAGE;
! 1132: dev->sc_msg[2] = 3;
! 1133: dev->sc_msg[3] = MSG_SYNC_REQ;
! 1134: dev->sc_msg[4] = sbictoscsiperiod(dev, sbic_min_period);
! 1135: dev->sc_msg[5] = sbic_max_offset;
! 1136:
! 1137: sbicxfout(regs, 6, dev->sc_msg);
! 1138:
! 1139: dev->sc_sync[id].state = SYNC_SENT;
! 1140: #ifdef DEBUG
! 1141: if ( sync_debug )
! 1142: printf ("sent\n");
! 1143: #endif
! 1144: }
! 1145:
! 1146: /*
! 1147: * There's one interrupt still to come: the change to CMD phase...
! 1148: */
! 1149: SBIC_WAIT(regs, SBIC_ASR_INT , 0);
! 1150: GET_SBIC_csr(regs, csr);
! 1151: }
! 1152:
! 1153: /*
! 1154: * set sync or async
! 1155: */
! 1156: if ( dev->sc_sync[target].state == SYNC_DONE ) {
! 1157: #ifdef DEBUG
! 1158: if ( sync_debug )
! 1159: printf("select(%d): sync reg = 0x%02x\n", target,
! 1160: SBIC_SYN(dev->sc_sync[target].offset,
! 1161: dev->sc_sync[target].period));
! 1162: #endif
! 1163: SET_SBIC_syn(regs, SBIC_SYN(dev->sc_sync[target].offset,
! 1164: dev->sc_sync[target].period));
! 1165: } else {
! 1166: #ifdef DEBUG
! 1167: if ( sync_debug )
! 1168: printf("select(%d): sync reg = 0x%02x\n", target,
! 1169: SBIC_SYN(0,sbic_min_period));
! 1170: #endif
! 1171: SET_SBIC_syn(regs, SBIC_SYN(0, sbic_min_period));
! 1172: }
! 1173:
! 1174: return csr;
! 1175: }
! 1176:
! 1177: /*
! 1178: * Information Transfer *to* a Scsi Target.
! 1179: *
! 1180: * Note: Don't expect there to be an interrupt immediately after all
! 1181: * the data is transferred out. The WD spec sheet says that the Transfer-
! 1182: * Info command for non-MSG_IN phases only completes when the target
! 1183: * next asserts 'REQ'. That is, when the SCSI bus changes to a new state.
! 1184: *
! 1185: * This can have a nasty effect on commands which take a relatively long
! 1186: * time to complete, for example a START/STOP unit command may remain in
! 1187: * CMD phase until the disk has spun up. Only then will the target change
! 1188: * to STATUS phase. This is really only a problem for immediate commands
! 1189: * since we don't allow disconnection for them (yet).
! 1190: */
! 1191: int
! 1192: sbicxfout(regs, len, bp)
! 1193: sbic_regmap_p regs;
! 1194: int len;
! 1195: void *bp;
! 1196: {
! 1197: int wait = sbic_data_wait;
! 1198: u_char asr,
! 1199: *buf = bp;
! 1200:
! 1201: QPRINTF(("sbicxfout {%d} %02x %02x %02x %02x %02x "
! 1202: "%02x %02x %02x %02x %02x\n", len, buf[0], buf[1], buf[2],
! 1203: buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]));
! 1204:
! 1205: /*
! 1206: * sigh.. WD-PROTO strikes again.. sending the command in one go
! 1207: * causes the chip to lock up if talking to certain (misbehaving?)
! 1208: * targets. Anyway, this procedure should work for all targets, but
! 1209: * it's slightly slower due to the overhead
! 1210: */
! 1211: WAIT_CIP (regs);
! 1212:
! 1213: SBIC_TC_PUT (regs, 0);
! 1214: SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
! 1215: SBIC_TC_PUT (regs, (unsigned)len);
! 1216: SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
! 1217:
! 1218: /*
! 1219: * Loop for each byte transferred
! 1220: */
! 1221: do {
! 1222:
! 1223: GET_SBIC_asr (regs, asr);
! 1224:
! 1225: if ( asr & SBIC_ASR_DBR ) {
! 1226: if ( len ) {
! 1227: SET_SBIC_data (regs, *buf);
! 1228: buf++;
! 1229: len--;
! 1230: } else {
! 1231: SET_SBIC_data (regs, 0);
! 1232: }
! 1233: wait = sbic_data_wait;
! 1234: }
! 1235:
! 1236: } while ( len && (asr & SBIC_ASR_INT) == 0 && wait-- > 0 );
! 1237:
! 1238: #ifdef DEBUG
! 1239: QPRINTF(("sbicxfout done: %d bytes remaining (wait:%d)\n", len, wait));
! 1240: #endif
! 1241:
! 1242: /*
! 1243: * Normally, an interrupt will be pending when this routing returns.
! 1244: */
! 1245: return(len);
! 1246: }
! 1247:
! 1248: /*
! 1249: * Information Transfer *from* a Scsi Target
! 1250: * returns # bytes left to read
! 1251: */
! 1252: int
! 1253: sbicxfin(regs, len, bp)
! 1254: sbic_regmap_p regs;
! 1255: int len;
! 1256: void *bp;
! 1257: {
! 1258: int wait = sbic_data_wait;
! 1259: u_char *buf = bp;
! 1260: u_char asr;
! 1261: #ifdef DEBUG
! 1262: u_char *obp = bp;
! 1263: #endif
! 1264:
! 1265: WAIT_CIP (regs);
! 1266:
! 1267: SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
! 1268: SBIC_TC_PUT (regs, (unsigned)len);
! 1269: SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO);
! 1270:
! 1271: /*
! 1272: * Loop for each byte transferred
! 1273: */
! 1274: do {
! 1275:
! 1276: GET_SBIC_asr (regs, asr);
! 1277:
! 1278: if ( asr & SBIC_ASR_DBR ) {
! 1279: if ( len ) {
! 1280: GET_SBIC_data (regs, *buf);
! 1281: buf++;
! 1282: len--;
! 1283: } else {
! 1284: u_char foo;
! 1285: GET_SBIC_data (regs, foo);
! 1286: }
! 1287: wait = sbic_data_wait;
! 1288: }
! 1289:
! 1290: } while ( (asr & SBIC_ASR_INT) == 0 && wait-- > 0 );
! 1291:
! 1292: QPRINTF(("sbicxfin {%d} %02x %02x %02x %02x %02x %02x "
! 1293: "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2],
! 1294: obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9]));
! 1295:
! 1296: SBIC_TC_PUT (regs, 0);
! 1297:
! 1298: /*
! 1299: * this leaves with one csr to be read
! 1300: */
! 1301: return len;
! 1302: }
! 1303:
! 1304: /*
! 1305: * SCSI 'immediate' command: issue a command to some SCSI device
! 1306: * and get back an 'immediate' response (i.e., do programmed xfer
! 1307: * to get the response data). 'cbuf' is a buffer containing a scsi
! 1308: * command of length clen bytes. 'buf' is a buffer of length 'len'
! 1309: * bytes for data. The transfer direction is determined by the device
! 1310: * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the
! 1311: * command must supply no data.
! 1312: *
! 1313: * Note that although this routine looks like it can handle disconnect/
! 1314: * reselect, the fact is that it can't. There is still some work to be
! 1315: * done to clean this lot up.
! 1316: */
! 1317: int
! 1318: sbicicmd(dev, cbuf, clen, buf, len)
! 1319: struct sbic_softc *dev;
! 1320: void *cbuf,
! 1321: *buf;
! 1322: int clen,
! 1323: len;
! 1324: {
! 1325: sbic_regmap_p regs = dev->sc_sbicp;
! 1326: struct sbic_acb *acb = dev->sc_nexus;
! 1327: u_char csr,
! 1328: asr;
! 1329: int still_busy = SBIC_STATE_RUNNING;
! 1330: #ifdef DEBUG
! 1331: int counter = 0;
! 1332: #endif
! 1333:
! 1334: /*
! 1335: * Make sure pointers are OK
! 1336: */
! 1337: dev->sc_last = dev->sc_cur = &acb->sc_pa;
! 1338: dev->sc_tcnt = acb->sc_tcnt = 0;
! 1339:
! 1340: acb->sc_dmacmd = 0;
! 1341: acb->sc_pa.dc_count = 0; /* No DMA */
! 1342: acb->sc_kv.dc_addr = buf;
! 1343: acb->sc_kv.dc_count = len;
! 1344:
! 1345: #ifdef DEBUG
! 1346: if ( data_pointer_debug > 1 )
! 1347: printf("sbicicmd(%d,%d):%d\n", dev->target, dev->lun, acb->sc_kv.dc_count);
! 1348: #endif
! 1349:
! 1350: /*
! 1351: * set the sbic into non-DMA mode
! 1352: */
! 1353: SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
! 1354:
! 1355: dev->sc_stat[0] = 0xff;
! 1356: dev->sc_msg[0] = 0xff;
! 1357:
! 1358: /*
! 1359: * We're stealing the SCSI bus
! 1360: */
! 1361: dev->sc_flags |= SBICF_ICMD;
! 1362:
! 1363: do {
! 1364: GET_SBIC_asr (regs, asr);
! 1365:
! 1366: /*
! 1367: * select the SCSI bus (it's an error if bus isn't free)
! 1368: */
! 1369: if ( (dev->sc_flags & SBICF_SELECTED) == 0 &&
! 1370: still_busy != SBIC_STATE_DISCONNECT ) {
! 1371: if ( (csr = sbicselectbus(dev)) == 0 ) {
! 1372: dev->sc_flags &= ~SBICF_ICMD;
! 1373: return(-1);
! 1374: }
! 1375: } else
! 1376: if ( (asr & (SBIC_ASR_BSY | SBIC_ASR_INT)) == SBIC_ASR_INT )
! 1377: GET_SBIC_csr(regs, csr);
! 1378: else
! 1379: csr = 0;
! 1380:
! 1381: if ( csr ) {
! 1382:
! 1383: QPRINTF((">ASR:0x%02x CSR:0x%02x< ", asr, csr));
! 1384:
! 1385: switch ( csr ) {
! 1386:
! 1387: case SBIC_CSR_S_XFERRED:
! 1388: case SBIC_CSR_DISC:
! 1389: case SBIC_CSR_DISC_1:
! 1390: {
! 1391: u_char phase;
! 1392:
! 1393: dev->sc_flags &= ~SBICF_SELECTED;
! 1394: GET_SBIC_cmd_phase (regs, phase);
! 1395:
! 1396: if ( phase == 0x60 ) {
! 1397: GET_SBIC_tlun (regs, dev->sc_stat[0]);
! 1398: still_busy = SBIC_STATE_DONE; /* done */
! 1399: } else {
! 1400: #ifdef DEBUG
! 1401: if ( reselect_debug > 1 )
! 1402: printf("sbicicmd: handling disconnect\n");
! 1403: #endif
! 1404: still_busy = SBIC_STATE_DISCONNECT;
! 1405: }
! 1406: }
! 1407: break;
! 1408:
! 1409: case SBIC_CSR_XFERRED | CMD_PHASE:
! 1410: case SBIC_CSR_MIS | CMD_PHASE:
! 1411: case SBIC_CSR_MIS_1 | CMD_PHASE:
! 1412: case SBIC_CSR_MIS_2 | CMD_PHASE:
! 1413: {
! 1414: if ( sbicxfout(regs, clen, cbuf) )
! 1415: still_busy = sbicabort(dev, "icmd sending cmd");
! 1416: }
! 1417: break;
! 1418:
! 1419: case SBIC_CSR_XFERRED | STATUS_PHASE:
! 1420: case SBIC_CSR_MIS | STATUS_PHASE:
! 1421: case SBIC_CSR_MIS_1 | STATUS_PHASE:
! 1422: case SBIC_CSR_MIS_2 | STATUS_PHASE:
! 1423: {
! 1424: /*
! 1425: * The sbic does the status/cmd-complete reading ok,
! 1426: * so do this with its hi-level commands.
! 1427: */
! 1428: #ifdef DEBUG
! 1429: if ( sbic_debug )
! 1430: printf("SBICICMD status phase (bsy=%d)\n", still_busy);
! 1431: #endif
! 1432: SET_SBIC_cmd_phase(regs, 0x46);
! 1433: SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
! 1434: }
! 1435: break;
! 1436:
! 1437: default:
! 1438: {
! 1439: still_busy = sbicnextstate(dev, csr, asr);
! 1440: }
! 1441: break;
! 1442: }
! 1443:
! 1444: /*
! 1445: * make sure the last command was taken,
! 1446: * ie. we're not hunting after an ignored command..
! 1447: */
! 1448: GET_SBIC_asr(regs, asr);
! 1449:
! 1450: /*
! 1451: * tapes may take a loooong time..
! 1452: */
! 1453: while (asr & SBIC_ASR_BSY ) {
! 1454:
! 1455: if ( asr & SBIC_ASR_DBR ) {
! 1456: int i;
! 1457:
! 1458: printf("sbicicmd: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n", csr,asr);
! 1459: #ifdef DDB
! 1460: Debugger();
! 1461: #endif
! 1462: /*
! 1463: * SBIC is jammed
! 1464: * DUNNO which direction
! 1465: * Try old direction
! 1466: */
! 1467: GET_SBIC_data(regs, i);
! 1468: GET_SBIC_asr(regs, asr);
! 1469:
! 1470: if ( asr & SBIC_ASR_DBR ) /* Wants us to write */
! 1471: SET_SBIC_data(regs, i);
! 1472: }
! 1473:
! 1474: GET_SBIC_asr(regs, asr);
! 1475: }
! 1476: }
! 1477:
! 1478: /*
! 1479: * wait for last command to complete
! 1480: */
! 1481: if ( asr & SBIC_ASR_LCI ) {
! 1482: printf("sbicicmd: last command ignored\n");
! 1483: }
! 1484: else
! 1485: if ( still_busy >= SBIC_STATE_RUNNING ) /* Bsy */
! 1486: SBIC_WAIT (regs, SBIC_ASR_INT, sbic_cmd_wait);
! 1487:
! 1488: /*
! 1489: * do it again
! 1490: */
! 1491: } while ( still_busy >= SBIC_STATE_RUNNING && dev->sc_stat[0] == 0xff );
! 1492:
! 1493: /*
! 1494: * Sometimes we need to do an extra read of the CSR
! 1495: */
! 1496: GET_SBIC_csr(regs, csr);
! 1497:
! 1498: #ifdef DEBUG
! 1499: if ( data_pointer_debug > 1 )
! 1500: printf("sbicicmd done(%d,%d):%d =%d=\n", dev->target, dev->lun,
! 1501: acb->sc_kv.dc_count,
! 1502: dev->sc_stat[0]);
! 1503: #endif
! 1504:
! 1505: dev->sc_flags &= ~SBICF_ICMD;
! 1506:
! 1507: return(dev->sc_stat[0]);
! 1508: }
! 1509:
! 1510: /*
! 1511: * Finish SCSI xfer command: After the completion interrupt from
! 1512: * a read/write operation, sequence through the final phases in
! 1513: * programmed i/o. This routine is a lot like sbicicmd except we
! 1514: * skip (and don't allow) the select, cmd out and data in/out phases.
! 1515: */
! 1516: void
! 1517: sbicxfdone(dev)
! 1518: struct sbic_softc *dev;
! 1519: {
! 1520: sbic_regmap_p regs = dev->sc_sbicp;
! 1521: u_char phase,
! 1522: csr;
! 1523: int s;
! 1524:
! 1525: QPRINTF(("{"));
! 1526: s = splbio();
! 1527:
! 1528: /*
! 1529: * have the sbic complete on its own
! 1530: */
! 1531: SBIC_TC_PUT(regs, 0);
! 1532: SET_SBIC_cmd_phase(regs, 0x46);
! 1533: SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER);
! 1534:
! 1535: do {
! 1536:
! 1537: SBIC_WAIT (regs, SBIC_ASR_INT, 0);
! 1538: GET_SBIC_csr (regs, csr);
! 1539: QPRINTF(("%02x:", csr));
! 1540:
! 1541: } while ( (csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) &&
! 1542: (csr != SBIC_CSR_S_XFERRED));
! 1543:
! 1544: dev->sc_flags &= ~SBICF_SELECTED;
! 1545:
! 1546: GET_SBIC_cmd_phase (regs, phase);
! 1547: QPRINTF(("}%02x", phase));
! 1548:
! 1549: if ( phase == 0x60 )
! 1550: GET_SBIC_tlun(regs, dev->sc_stat[0]);
! 1551: else
! 1552: sbicerror(dev, csr);
! 1553:
! 1554: QPRINTF(("=STS:%02x=\n", dev->sc_stat[0]));
! 1555:
! 1556: splx(s);
! 1557: }
! 1558:
! 1559: /*
! 1560: * No DMA chains
! 1561: */
! 1562: int
! 1563: sbicgo(dev, xs)
! 1564: struct sbic_softc *dev;
! 1565: struct scsi_xfer *xs;
! 1566: {
! 1567: struct sbic_acb *acb = dev->sc_nexus;
! 1568: sbic_regmap_p regs = dev->sc_sbicp;
! 1569: int i,
! 1570: dmaflags,
! 1571: count,
! 1572: usedma;
! 1573: u_char csr,
! 1574: asr,
! 1575: *addr;
! 1576:
! 1577: dev->target = xs->sc_link->target;
! 1578: dev->lun = xs->sc_link->lun;
! 1579:
! 1580: usedma = sbicdmaok(dev, xs);
! 1581:
! 1582: #ifdef DEBUG
! 1583: if ( data_pointer_debug > 1 )
! 1584: printf("sbicgo(%d,%d): usedma=%d\n", dev->target, dev->lun, usedma);
! 1585: #endif
! 1586:
! 1587: /*
! 1588: * select the SCSI bus (it's an error if bus isn't free)
! 1589: */
! 1590: if ( (csr = sbicselectbus(dev)) == 0 )
! 1591: return(0); /* Not done: needs to be rescheduled */
! 1592:
! 1593: dev->sc_stat[0] = 0xff;
! 1594:
! 1595: /*
! 1596: * Calculate DMA chains now
! 1597: */
! 1598: if ( acb->flags & ACB_DATAIN )
! 1599: dmaflags = DMAGO_READ;
! 1600: else
! 1601: dmaflags = 0;
! 1602:
! 1603: addr = acb->sc_kv.dc_addr;
! 1604: count = acb->sc_kv.dc_count;
! 1605:
! 1606: if ( count && ((char *)kvtop((vaddr_t)addr) != acb->sc_pa.dc_addr) ) {
! 1607: printf("sbic: DMA buffer mapping changed %p->%lx\n",
! 1608: acb->sc_pa.dc_addr, kvtop((vaddr_t)addr));
! 1609: #ifdef DDB
! 1610: Debugger();
! 1611: #endif
! 1612: }
! 1613:
! 1614: #ifdef DEBUG
! 1615: ++sbicdma_ops; /* count total DMA operations */
! 1616: #endif
! 1617:
! 1618: /*
! 1619: * Allocate the DMA chain
! 1620: * Mark end of segment...
! 1621: */
! 1622: acb->sc_tcnt = dev->sc_tcnt = 0;
! 1623: acb->sc_pa.dc_count = 0;
! 1624:
! 1625: sbic_load_ptrs(dev);
! 1626:
! 1627: /*
! 1628: * Enable interrupts but don't do any DMA
! 1629: * enintr() also enables interrupts for the sbic
! 1630: */
! 1631: dev->sc_enintr(dev);
! 1632:
! 1633: if ( usedma ) {
! 1634: dev->sc_tcnt = dev->sc_dmago(dev, acb->sc_pa.dc_addr,
! 1635: acb->sc_pa.dc_count, dmaflags);
! 1636: #ifdef DEBUG
! 1637: dev->sc_dmatimo = dev->sc_tcnt ? 1 : 0;
! 1638: #endif
! 1639: } else
! 1640: dev->sc_dmacmd = 0; /* Don't use DMA */
! 1641:
! 1642: acb->sc_dmacmd = dev->sc_dmacmd;
! 1643:
! 1644: #ifdef DEBUG
! 1645: if ( data_pointer_debug > 1 ) {
! 1646: printf("sbicgo dmago:%d(%x:%x) dmacmd=0x%02x\n", dev->target,
! 1647: dev->sc_cur->dc_addr,
! 1648: dev->sc_tcnt,
! 1649: dev->sc_dmacmd);
! 1650: }
! 1651: #endif
! 1652:
! 1653: /*
! 1654: * Lets cycle a while then let the interrupt handler take over.
! 1655: */
! 1656: GET_SBIC_asr(regs, asr);
! 1657:
! 1658: do {
! 1659:
! 1660: QPRINTF(("go "));
! 1661:
! 1662: /*
! 1663: * Handle the new phase
! 1664: */
! 1665: i = sbicnextstate(dev, csr, asr);
! 1666: #if 0
! 1667: WAIT_CIP(regs);
! 1668: #endif
! 1669: if ( i == SBIC_STATE_RUNNING ) {
! 1670: GET_SBIC_asr(regs, asr);
! 1671:
! 1672: if ( asr & SBIC_ASR_LCI )
! 1673: printf("sbicgo: LCI asr:%02x csr:%02x\n", asr, csr);
! 1674:
! 1675: if ( asr & SBIC_ASR_INT )
! 1676: GET_SBIC_csr(regs, csr);
! 1677: }
! 1678:
! 1679: } while ( i == SBIC_STATE_RUNNING && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) );
! 1680:
! 1681: if ( i == SBIC_STATE_DONE ) {
! 1682: if ( dev->sc_stat[0] == 0xff )
! 1683: #if 0
! 1684: printf("sbicgo: done & stat = 0xff\n");
! 1685: #else
! 1686: ;
! 1687: #endif
! 1688: else
! 1689: return 1; /* Did we really finish that fast? */
! 1690: }
! 1691:
! 1692: return 0;
! 1693: }
! 1694:
! 1695:
! 1696: int
! 1697: sbicintr(dev)
! 1698: struct sbic_softc *dev;
! 1699: {
! 1700: sbic_regmap_p regs = dev->sc_sbicp;
! 1701: u_char asr,
! 1702: csr;
! 1703: int i;
! 1704:
! 1705: /*
! 1706: * pending interrupt?
! 1707: */
! 1708: GET_SBIC_asr (regs, asr);
! 1709: if ( (asr & SBIC_ASR_INT) == 0 )
! 1710: return(0);
! 1711:
! 1712: GET_SBIC_csr(regs, csr);
! 1713:
! 1714: do {
! 1715:
! 1716: QPRINTF(("intr[0x%x]", csr));
! 1717:
! 1718: i = sbicnextstate(dev, csr, asr);
! 1719: #if 0
! 1720: WAIT_CIP(regs);
! 1721: #endif
! 1722: if ( i == SBIC_STATE_RUNNING ) {
! 1723: GET_SBIC_asr(regs, asr);
! 1724:
! 1725: if ( asr & SBIC_ASR_LCI )
! 1726: printf("sbicgo: LCI asr:%02x csr:%02x\n", asr, csr);
! 1727:
! 1728: if ( asr & SBIC_ASR_INT )
! 1729: GET_SBIC_csr(regs, csr);
! 1730: }
! 1731:
! 1732: } while ( i == SBIC_STATE_RUNNING && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) );
! 1733:
! 1734: QPRINTF(("intr done. state=%d, asr=0x%02x\n", i, asr));
! 1735:
! 1736: return(1);
! 1737: }
! 1738:
! 1739: /*
! 1740: * Run commands and wait for disconnect.
! 1741: * This is only ever called when a command is in progress, when we
! 1742: * want to busy wait for it to finish.
! 1743: */
! 1744: int
! 1745: sbicpoll(dev)
! 1746: struct sbic_softc *dev;
! 1747: {
! 1748: sbic_regmap_p regs = dev->sc_sbicp;
! 1749: u_char asr,
! 1750: csr = 0;
! 1751: int i;
! 1752:
! 1753: /*
! 1754: * Wait for the next interrupt
! 1755: */
! 1756: SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
! 1757:
! 1758: do {
! 1759: GET_SBIC_asr (regs, asr);
! 1760:
! 1761: if ( asr & SBIC_ASR_INT )
! 1762: GET_SBIC_csr(regs, csr);
! 1763:
! 1764: QPRINTF(("poll[0x%x]", csr));
! 1765:
! 1766: /*
! 1767: * Handle it
! 1768: */
! 1769: i = sbicnextstate(dev, csr, asr);
! 1770:
! 1771: WAIT_CIP(regs);
! 1772: GET_SBIC_asr(regs, asr);
! 1773:
! 1774: /*
! 1775: * tapes may take a loooong time..
! 1776: */
! 1777: while ( asr & SBIC_ASR_BSY ) {
! 1778: u_char z = 0;
! 1779:
! 1780: if ( asr & SBIC_ASR_DBR ) {
! 1781: printf("sbipoll: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n", csr,asr);
! 1782: #ifdef DDB
! 1783: Debugger();
! 1784: #endif
! 1785: /*
! 1786: * SBIC is jammed
! 1787: * DUNNO which direction
! 1788: * Try old direction
! 1789: */
! 1790: GET_SBIC_data(regs, z);
! 1791: GET_SBIC_asr(regs, asr);
! 1792:
! 1793: if ( asr & SBIC_ASR_DBR ) /* Wants us to write */
! 1794: SET_SBIC_data(regs, z);
! 1795: }
! 1796:
! 1797: GET_SBIC_asr(regs, asr);
! 1798: }
! 1799:
! 1800: if ( asr & SBIC_ASR_LCI )
! 1801: printf("sbicpoll: LCI asr:%02x csr:%02x\n", asr,csr);
! 1802: else
! 1803: if ( i == SBIC_STATE_RUNNING ) /* BSY */
! 1804: SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait);
! 1805:
! 1806: } while ( i == SBIC_STATE_RUNNING );
! 1807:
! 1808: return(1);
! 1809: }
! 1810:
! 1811: /*
! 1812: * Handle a single msgin
! 1813: */
! 1814: int
! 1815: sbicmsgin(dev)
! 1816: struct sbic_softc *dev;
! 1817: {
! 1818: sbic_regmap_p regs = dev->sc_sbicp;
! 1819: int recvlen = 1;
! 1820: u_char asr,
! 1821: csr,
! 1822: *tmpaddr,
! 1823: *msgaddr;
! 1824:
! 1825: tmpaddr = msgaddr = dev->sc_msg;
! 1826:
! 1827: tmpaddr[0] = 0xff;
! 1828: tmpaddr[1] = 0xff;
! 1829:
! 1830: GET_SBIC_asr(regs, asr);
! 1831:
! 1832: #ifdef DEBUG
! 1833: if ( reselect_debug > 1 )
! 1834: printf("sbicmsgin asr=%02x\n", asr);
! 1835: #endif
! 1836:
! 1837: GET_SBIC_selid (regs, csr);
! 1838: SET_SBIC_selid (regs, csr | SBIC_SID_FROM_SCSI);
! 1839:
! 1840: SBIC_TC_PUT(regs, 0);
! 1841: SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
! 1842:
! 1843: do {
! 1844: while( recvlen-- ) {
! 1845:
! 1846: /*
! 1847: * Fetch the next byte of the message
! 1848: */
! 1849: RECV_BYTE(regs, *tmpaddr);
! 1850:
! 1851: /*
! 1852: * get the command completion interrupt, or we
! 1853: * can't send a new command (LCI)
! 1854: */
! 1855: SBIC_WAIT(regs, SBIC_ASR_INT, 0);
! 1856: GET_SBIC_csr(regs, csr);
! 1857:
! 1858: #ifdef DEBUG
! 1859: if ( reselect_debug > 1 )
! 1860: printf("sbicmsgin: got %02x csr %02x\n", *tmpaddr, csr);
! 1861: #endif
! 1862:
! 1863: tmpaddr++;
! 1864:
! 1865: if ( recvlen ) {
! 1866: /*
! 1867: * Clear ACK, and wait for the interrupt for the next byte
! 1868: */
! 1869: SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
! 1870: SBIC_WAIT(regs, SBIC_ASR_INT, 0);
! 1871: GET_SBIC_csr(regs, csr);
! 1872: }
! 1873: }
! 1874:
! 1875: if ( msgaddr[0] == 0xff ) {
! 1876: printf("sbicmsgin: sbic swallowed our message\n");
! 1877: break;
! 1878: }
! 1879:
! 1880: #ifdef DEBUG
! 1881: if ( sync_debug ) {
! 1882: GET_SBIC_asr(regs, asr);
! 1883: printf("msgin done csr 0x%x asr 0x%x msg 0x%x\n", csr, asr, msgaddr[0]);
! 1884: }
! 1885: #endif
! 1886: /*
! 1887: * test whether this is a reply to our sync
! 1888: * request
! 1889: */
! 1890: if ( MSG_ISIDENTIFY(msgaddr[0]) ) {
! 1891:
! 1892: /*
! 1893: * Got IFFY msg -- ack it
! 1894: */
! 1895: QPRINTF(("IFFY"));
! 1896:
! 1897: } else
! 1898: if ( msgaddr[0] == MSG_REJECT &&
! 1899: dev->sc_sync[dev->target].state == SYNC_SENT) {
! 1900:
! 1901: /*
! 1902: * Target probably rejected our Sync negotiation.
! 1903: */
! 1904: QPRINTF(("REJECT of SYN"));
! 1905:
! 1906: #ifdef DEBUG
! 1907: if ( sync_debug )
! 1908: printf("target %d rejected sync, going async\n", dev->target);
! 1909: #endif
! 1910:
! 1911: dev->sc_sync[dev->target].period = sbic_min_period;
! 1912: dev->sc_sync[dev->target].offset = 0;
! 1913: dev->sc_sync[dev->target].state = SYNC_DONE;
! 1914: SET_SBIC_syn(regs, SBIC_SYN(dev->sc_sync[dev->target].offset,
! 1915: dev->sc_sync[dev->target].period));
! 1916:
! 1917: } else
! 1918: if ( msgaddr[0] == MSG_REJECT ) {
! 1919:
! 1920: /*
! 1921: * we'll never REJECt a REJECT message..
! 1922: */
! 1923: QPRINTF(("REJECT"));
! 1924:
! 1925: } else
! 1926: if ( msgaddr[0] == MSG_SAVE_DATA_PTR ) {
! 1927:
! 1928: /*
! 1929: * don't reject this either.
! 1930: */
! 1931: QPRINTF(("MSG_SAVE_DATA_PTR"));
! 1932:
! 1933: } else
! 1934: if ( msgaddr[0] == MSG_RESTORE_PTR ) {
! 1935:
! 1936: /*
! 1937: * don't reject this either.
! 1938: */
! 1939: QPRINTF(("MSG_RESTORE_PTR"));
! 1940:
! 1941: } else
! 1942: if ( msgaddr[0] == MSG_DISCONNECT ) {
! 1943:
! 1944: /*
! 1945: * Target is disconnecting...
! 1946: */
! 1947: QPRINTF(("DISCONNECT"));
! 1948:
! 1949: #ifdef DEBUG
! 1950: if ( reselect_debug > 1 && msgaddr[0] == MSG_DISCONNECT )
! 1951: printf("sbicmsgin: got disconnect msg %s\n",
! 1952: (dev->sc_flags & SBICF_ICMD) ? "rejecting" : "");
! 1953: #endif
! 1954:
! 1955: if ( dev->sc_flags & SBICF_ICMD ) {
! 1956: /*
! 1957: * We're in immediate mode. Prevent disconnects.
! 1958: * prepare to reject the message, NACK
! 1959: */
! 1960: SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
! 1961: WAIT_CIP(regs);
! 1962: }
! 1963:
! 1964: } else
! 1965: if ( msgaddr[0] == MSG_CMD_COMPLETE ) {
! 1966:
! 1967: /*
! 1968: * !! KLUDGE ALERT !! quite a few drives don't seem to
! 1969: * really like the current way of sending the
! 1970: * sync-handshake together with the ident-message, and
! 1971: * they react by sending command-complete and
! 1972: * disconnecting right after returning the valid sync
! 1973: * handshake. So, all I can do is reselect the drive,
! 1974: * and hope it won't disconnect again. I don't think
! 1975: * this is valid behavior, but I can't help fixing a
! 1976: * problem that apparently exists.
! 1977: *
! 1978: * Note: we should not get here on `normal' command
! 1979: * completion, as that condition is handled by the
! 1980: * high-level sel&xfer resume command used to walk
! 1981: * thru status/cc-phase.
! 1982: */
! 1983: QPRINTF(("CMD_COMPLETE"));
! 1984:
! 1985: #ifdef DEBUG
! 1986: if ( sync_debug )
! 1987: printf ("GOT MSG %d! target %d acting weird.."
! 1988: " waiting for disconnect...\n", msgaddr[0], dev->target);
! 1989: #endif
! 1990:
! 1991: /*
! 1992: * Check to see if sbic is handling this
! 1993: */
! 1994: GET_SBIC_asr(regs, asr);
! 1995:
! 1996: /*
! 1997: * XXXSCW: I'm not convinced of this, we haven't negated ACK yet...
! 1998: */
! 1999: if ( asr & SBIC_ASR_BSY )
! 2000: return SBIC_STATE_RUNNING;
! 2001:
! 2002: /*
! 2003: * Let's try this: Assume it works and set status to 00
! 2004: */
! 2005: dev->sc_stat[0] = 0;
! 2006:
! 2007: } else
! 2008: if ( msgaddr[0] == MSG_EXT_MESSAGE && tmpaddr == &(msgaddr[1]) ) {
! 2009:
! 2010: /*
! 2011: * Target is sending us an extended message. We'll assume it's
! 2012: * the response to our Sync. negotiation.
! 2013: */
! 2014: QPRINTF(("ExtMSG\n"));
! 2015:
! 2016: /*
! 2017: * Read in whole extended message. First, negate ACK to accept
! 2018: * the MSG_EXT_MESSAGE byte...
! 2019: */
! 2020: SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
! 2021:
! 2022: /*
! 2023: * Wait for the interrupt for the next byte (length)
! 2024: */
! 2025: SBIC_WAIT(regs, SBIC_ASR_INT, 0);
! 2026: GET_SBIC_csr(regs, csr);
! 2027:
! 2028: #ifdef DEBUG
! 2029: QPRINTF(("CLR ACK csr %02x\n", csr));
! 2030: #endif
! 2031:
! 2032: /*
! 2033: * Read the length byte
! 2034: */
! 2035: RECV_BYTE(regs, *tmpaddr);
! 2036:
! 2037: /*
! 2038: * Wait for command completion IRQ
! 2039: */
! 2040: SBIC_WAIT(regs, SBIC_ASR_INT, 0);
! 2041: GET_SBIC_csr(regs, csr);
! 2042:
! 2043: /*
! 2044: * Reload the loop counter
! 2045: */
! 2046: recvlen = *tmpaddr++;
! 2047:
! 2048: QPRINTF(("Recving ext msg, csr %02x len %02x\n", csr, recvlen));
! 2049:
! 2050: } else
! 2051: if ( msgaddr[0] == MSG_EXT_MESSAGE && msgaddr[1] == 3 &&
! 2052: msgaddr[2] == MSG_SYNC_REQ ) {
! 2053:
! 2054: /*
! 2055: * We've received the complete Extended Message Sync. Request...
! 2056: */
! 2057: QPRINTF(("SYN"));
! 2058:
! 2059: /*
! 2060: * Compute the required Transfer Period for the WD chip...
! 2061: */
! 2062: dev->sc_sync[dev->target].period = sbicfromscsiperiod(dev, msgaddr[3]);
! 2063: dev->sc_sync[dev->target].offset = msgaddr[4];
! 2064: dev->sc_sync[dev->target].state = SYNC_DONE;
! 2065:
! 2066: /*
! 2067: * Put the WD chip in synchronous mode
! 2068: */
! 2069: SET_SBIC_syn(regs, SBIC_SYN(dev->sc_sync[dev->target].offset,
! 2070: dev->sc_sync[dev->target].period));
! 2071: #ifdef DEBUG
! 2072: if ( sync_debug )
! 2073: printf("msgin(%d): sync reg = 0x%02x\n", dev->target,
! 2074: SBIC_SYN(dev->sc_sync[dev->target].offset,
! 2075: dev->sc_sync[dev->target].period));
! 2076: #endif
! 2077:
! 2078: printf("%s: target %d now synchronous, period=%dns, offset=%d.\n",
! 2079: dev->sc_dev.dv_xname, dev->target,
! 2080: msgaddr[3] * 4, msgaddr[4]);
! 2081:
! 2082: } else {
! 2083:
! 2084: /*
! 2085: * We don't support whatever this message is...
! 2086: */
! 2087: #ifdef DEBUG
! 2088: if ( sbic_debug || sync_debug )
! 2089: printf ("sbicmsgin: Rejecting message 0x%02x\n", msgaddr[0]);
! 2090: #endif
! 2091:
! 2092: /*
! 2093: * prepare to reject the message, NACK
! 2094: */
! 2095: SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN);
! 2096: WAIT_CIP(regs);
! 2097: }
! 2098:
! 2099: /*
! 2100: * Negate ACK to complete the transfer
! 2101: */
! 2102: SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
! 2103:
! 2104: /*
! 2105: * Wait for the interrupt for the next byte, or phase change.
! 2106: * Only read the CSR if we have more data to transfer.
! 2107: * XXXSCW: We should really verify that we're still in MSG IN phase
! 2108: * before blindly going back around this loop, but that would mean
! 2109: * we read the CSR... <sigh>
! 2110: */
! 2111: SBIC_WAIT(regs, SBIC_ASR_INT, 0);
! 2112: if ( recvlen > 0 )
! 2113: GET_SBIC_csr(regs, csr);
! 2114:
! 2115: } while ( recvlen > 0 );
! 2116:
! 2117: /*
! 2118: * Should still have one CSR to read
! 2119: */
! 2120: return SBIC_STATE_RUNNING;
! 2121: }
! 2122:
! 2123:
! 2124: /*
! 2125: * sbicnextstate()
! 2126: * return:
! 2127: * SBIC_STATE_DONE == done
! 2128: * SBIC_STATE_RUNNING == working
! 2129: * SBIC_STATE_DISCONNECT == disconnected
! 2130: * SBIC_STATE_ERROR == error
! 2131: */
! 2132: int
! 2133: sbicnextstate(dev, csr, asr)
! 2134: struct sbic_softc *dev;
! 2135: u_char csr,
! 2136: asr;
! 2137: {
! 2138: sbic_regmap_p regs = dev->sc_sbicp;
! 2139: struct sbic_acb *acb = dev->sc_nexus;
! 2140:
! 2141: QPRINTF(("next[%02x,%02x]: ",asr,csr));
! 2142:
! 2143: switch (csr) {
! 2144:
! 2145: case SBIC_CSR_XFERRED | CMD_PHASE:
! 2146: case SBIC_CSR_MIS | CMD_PHASE:
! 2147: case SBIC_CSR_MIS_1 | CMD_PHASE:
! 2148: case SBIC_CSR_MIS_2 | CMD_PHASE:
! 2149: {
! 2150: if ( sbicxfout(regs, acb->clen, &acb->cmd) )
! 2151: goto abort;
! 2152: }
! 2153: break;
! 2154:
! 2155: case SBIC_CSR_XFERRED | STATUS_PHASE:
! 2156: case SBIC_CSR_MIS | STATUS_PHASE:
! 2157: case SBIC_CSR_MIS_1 | STATUS_PHASE:
! 2158: case SBIC_CSR_MIS_2 | STATUS_PHASE:
! 2159: {
! 2160: SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
! 2161:
! 2162: /*
! 2163: * this should be the normal i/o completion case.
! 2164: * get the status & cmd complete msg then let the
! 2165: * device driver look at what happened.
! 2166: */
! 2167: sbicxfdone(dev);
! 2168:
! 2169: #ifdef DEBUG
! 2170: dev->sc_dmatimo = 0;
! 2171: if ( data_pointer_debug > 1 )
! 2172: printf("next dmastop: %d(%x:%x)\n", dev->target,
! 2173: dev->sc_cur->dc_addr,
! 2174: dev->sc_tcnt);
! 2175: #endif
! 2176: /*
! 2177: * Stop the DMA chip
! 2178: */
! 2179: dev->sc_dmastop(dev);
! 2180:
! 2181: dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH);
! 2182:
! 2183: /*
! 2184: * Indicate to the upper layers that the command is done
! 2185: */
! 2186: sbic_scsidone(acb, dev->sc_stat[0]);
! 2187:
! 2188: return SBIC_STATE_DONE;
! 2189: }
! 2190:
! 2191: case SBIC_CSR_XFERRED | DATA_OUT_PHASE:
! 2192: case SBIC_CSR_XFERRED | DATA_IN_PHASE:
! 2193: case SBIC_CSR_MIS | DATA_OUT_PHASE:
! 2194: case SBIC_CSR_MIS | DATA_IN_PHASE:
! 2195: case SBIC_CSR_MIS_1 | DATA_OUT_PHASE:
! 2196: case SBIC_CSR_MIS_1 | DATA_IN_PHASE:
! 2197: case SBIC_CSR_MIS_2 | DATA_OUT_PHASE:
! 2198: case SBIC_CSR_MIS_2 | DATA_IN_PHASE:
! 2199: {
! 2200: /*
! 2201: * Verify that we expected to transfer data...
! 2202: */
! 2203: if ( acb->sc_kv.dc_count <= 0 ) {
! 2204: printf("next: DATA phase with xfer count == %d, asr:0x%02x csr:0x%02x\n",
! 2205: acb->sc_kv.dc_count, asr, csr);
! 2206: goto abort;
! 2207: }
! 2208:
! 2209: /*
! 2210: * Should we transfer using PIO or DMA ?
! 2211: */
! 2212: if ( dev->sc_xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD ||
! 2213: acb->sc_dmacmd == 0 ) {
! 2214:
! 2215: /*
! 2216: * Do PIO transfer
! 2217: */
! 2218: int i;
! 2219:
! 2220: #ifdef DEBUG
! 2221: if ( data_pointer_debug > 1 )
! 2222: printf("next PIO: %d(%x:%x)\n", dev->target,
! 2223: acb->sc_kv.dc_addr,
! 2224: acb->sc_kv.dc_count);
! 2225: #endif
! 2226:
! 2227: if ( SBIC_PHASE(csr) == DATA_IN_PHASE )
! 2228: /*
! 2229: * data in
! 2230: */
! 2231: i = sbicxfin(regs, acb->sc_kv.dc_count,
! 2232: acb->sc_kv.dc_addr);
! 2233: else
! 2234: /*
! 2235: * data out
! 2236: */
! 2237: i = sbicxfout(regs, acb->sc_kv.dc_count,
! 2238: acb->sc_kv.dc_addr);
! 2239:
! 2240: acb->sc_kv.dc_addr += (acb->sc_kv.dc_count - i);
! 2241: acb->sc_kv.dc_count = i;
! 2242:
! 2243: /*
! 2244: * Update current count...
! 2245: */
! 2246: acb->sc_tcnt = dev->sc_tcnt = i;
! 2247:
! 2248: dev->sc_flags &= ~SBICF_INDMA;
! 2249:
! 2250: } else {
! 2251:
! 2252: /*
! 2253: * Do DMA transfer
! 2254: * set next dma addr and dec count
! 2255: */
! 2256: sbic_save_ptrs(dev);
! 2257: sbic_load_ptrs(dev);
! 2258:
! 2259: SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI |
! 2260: SBIC_MACHINE_DMA_MODE);
! 2261:
! 2262: #ifdef DEBUG
! 2263: dev->sc_dmatimo = 1;
! 2264: if ( data_pointer_debug > 1 )
! 2265: printf("next DMA: %d(%x:%x)\n", dev->target,
! 2266: dev->sc_cur->dc_addr,
! 2267: dev->sc_tcnt);
! 2268: #endif
! 2269: /*
! 2270: * Start the DMA chip going
! 2271: */
! 2272: dev->sc_tcnt = dev->sc_dmanext(dev);
! 2273:
! 2274: /*
! 2275: * Tell the WD chip how much to transfer this time around
! 2276: */
! 2277: SBIC_TC_PUT(regs, (unsigned)dev->sc_tcnt);
! 2278:
! 2279: /*
! 2280: * Start the transfer
! 2281: */
! 2282: SET_SBIC_cmd(regs, SBIC_CMD_XFER_INFO);
! 2283:
! 2284: /*
! 2285: * Indicate that we're in DMA mode
! 2286: */
! 2287: dev->sc_flags |= SBICF_INDMA;
! 2288: }
! 2289: }
! 2290: break;
! 2291:
! 2292: case SBIC_CSR_XFERRED | MESG_IN_PHASE:
! 2293: case SBIC_CSR_MIS | MESG_IN_PHASE:
! 2294: case SBIC_CSR_MIS_1 | MESG_IN_PHASE:
! 2295: case SBIC_CSR_MIS_2 | MESG_IN_PHASE:
! 2296: {
! 2297: sbic_save_ptrs(dev);
! 2298:
! 2299: /*
! 2300: * Handle a single message in...
! 2301: */
! 2302: return sbicmsgin(dev);
! 2303: }
! 2304:
! 2305: case SBIC_CSR_MSGIN_W_ACK:
! 2306: {
! 2307: /*
! 2308: * We should never see this since it's handled in 'sbicmsgin()'
! 2309: * but just for the sake of paranoia...
! 2310: */
! 2311: SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); /* Dunno what I'm ACKing */
! 2312: printf("Acking unknown msgin CSR:%02x",csr);
! 2313: }
! 2314: break;
! 2315:
! 2316: case SBIC_CSR_XFERRED | MESG_OUT_PHASE:
! 2317: case SBIC_CSR_MIS | MESG_OUT_PHASE:
! 2318: case SBIC_CSR_MIS_1 | MESG_OUT_PHASE:
! 2319: case SBIC_CSR_MIS_2 | MESG_OUT_PHASE:
! 2320: {
! 2321: /*
! 2322: * We only ever handle a message out phase here for sending a
! 2323: * REJECT message.
! 2324: */
! 2325: sbic_save_ptrs(dev);
! 2326:
! 2327: #ifdef DEBUG
! 2328: if (sync_debug)
! 2329: printf ("sending REJECT msg to last msg.\n");
! 2330: #endif
! 2331:
! 2332: SEND_BYTE(regs, MSG_REJECT);
! 2333: WAIT_CIP(regs);
! 2334: }
! 2335: break;
! 2336:
! 2337: case SBIC_CSR_DISC:
! 2338: case SBIC_CSR_DISC_1:
! 2339: {
! 2340: /*
! 2341: * Try to schedule another target
! 2342: */
! 2343: sbic_save_ptrs(dev);
! 2344:
! 2345: dev->sc_flags &= ~SBICF_SELECTED;
! 2346:
! 2347: #ifdef DEBUG
! 2348: if ( reselect_debug > 1 )
! 2349: printf("sbicnext target %d disconnected\n", dev->target);
! 2350: #endif
! 2351:
! 2352: TAILQ_INSERT_HEAD(&dev->nexus_list, acb, chain);
! 2353:
! 2354: ++dev->sc_tinfo[dev->target].dconns;
! 2355:
! 2356: dev->sc_nexus = NULL;
! 2357: dev->sc_xs = NULL;
! 2358:
! 2359: if ( acb->xs->flags & SCSI_POLL || dev->sc_flags & SBICF_ICMD ||
! 2360: !sbic_parallel_operations )
! 2361: return SBIC_STATE_DISCONNECT;
! 2362:
! 2363: QPRINTF(("sbicnext: calling sbic_sched\n"));
! 2364:
! 2365: sbic_sched(dev);
! 2366:
! 2367: QPRINTF(("sbicnext: sbic_sched returned\n"));
! 2368:
! 2369: return SBIC_STATE_DISCONNECT;
! 2370: }
! 2371:
! 2372: case SBIC_CSR_RSLT_NI:
! 2373: case SBIC_CSR_RSLT_IFY:
! 2374: {
! 2375: /*
! 2376: * A reselection.
! 2377: * Note that since we don't enable Advanced Features (assuming
! 2378: * the WD chip is at least the 'A' revision), we're only ever
! 2379: * likely to see the 'SBIC_CSR_RSLT_NI' status. But for the
! 2380: * hell of it, we'll handle it anyway, for all the extra code
! 2381: * it needs...
! 2382: */
! 2383: u_char newtarget,
! 2384: newlun;
! 2385:
! 2386: GET_SBIC_rselid(regs, newtarget);
! 2387:
! 2388: /*
! 2389: * check SBIC_RID_SIV?
! 2390: */
! 2391: newtarget &= SBIC_RID_MASK;
! 2392:
! 2393: if ( csr == SBIC_CSR_RSLT_IFY ) {
! 2394:
! 2395: /*
! 2396: * Read Identify msg to avoid lockup
! 2397: */
! 2398: GET_SBIC_data(regs, newlun);
! 2399: WAIT_CIP(regs);
! 2400: newlun &= SBIC_TLUN_MASK;
! 2401:
! 2402: } else {
! 2403:
! 2404: /*
! 2405: * Need to read Identify message the hard way, assuming
! 2406: * the target even sends us one...
! 2407: */
! 2408: for (newlun = 255; newlun; --newlun) {
! 2409: GET_SBIC_asr(regs, asr);
! 2410: if (asr & SBIC_ASR_INT)
! 2411: break;
! 2412: delay(10);
! 2413: }
! 2414:
! 2415: /*
! 2416: * If we didn't get an interrupt, somethink's up
! 2417: */
! 2418: if ( (asr & SBIC_ASR_INT) == 0 ) {
! 2419: printf("%s: Reselect without identify? asr %x\n",
! 2420: dev->sc_dev.dv_xname, asr);
! 2421: newlun = 0; /* XXXX */
! 2422: } else {
! 2423: /*
! 2424: * We got an interrupt, verify that it's a change to
! 2425: * message in phase, and if so read the message.
! 2426: */
! 2427: GET_SBIC_csr(regs,csr);
! 2428:
! 2429: if (csr == (SBIC_CSR_MIS | MESG_IN_PHASE) ||
! 2430: csr == (SBIC_CSR_MIS_1 | MESG_IN_PHASE) ||
! 2431: csr == (SBIC_CSR_MIS_2 | MESG_IN_PHASE)) {
! 2432: /*
! 2433: * Yup, gone to message in. Fetch the target LUN
! 2434: */
! 2435: sbicmsgin(dev);
! 2436: newlun = dev->sc_msg[0] & 0x07;
! 2437:
! 2438: } else {
! 2439: /*
! 2440: * Whoops! Target didn't go to message in phase!!
! 2441: */
! 2442: printf("RSLT_NI - not MESG_IN_PHASE %x\n", csr);
! 2443: newlun = 0; /* XXXSCW */
! 2444: }
! 2445: }
! 2446: }
! 2447:
! 2448: /*
! 2449: * Ok, we have the identity of the reselecting target.
! 2450: */
! 2451: #ifdef DEBUG
! 2452: if ( reselect_debug > 1 ||
! 2453: (reselect_debug && csr == SBIC_CSR_RSLT_NI) ) {
! 2454: printf("sbicnext: reselect %s from targ %d lun %d\n",
! 2455: csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget, newlun);
! 2456: }
! 2457: #endif
! 2458:
! 2459: if ( dev->sc_nexus ) {
! 2460: /*
! 2461: * Whoops! We've been reselected with an command in progress!
! 2462: * The best we can do is to put the current command back on the
! 2463: * ready list and hope for the best.
! 2464: */
! 2465: #ifdef DEBUG
! 2466: if ( reselect_debug > 1 ) {
! 2467: printf("%s: reselect %s with active command\n",
! 2468: dev->sc_dev.dv_xname,
! 2469: csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY");
! 2470: }
! 2471: #endif
! 2472:
! 2473: TAILQ_INSERT_HEAD(&dev->ready_list, dev->sc_nexus, chain);
! 2474:
! 2475: dev->sc_tinfo[dev->target].lubusy &= ~(1 << dev->lun);
! 2476:
! 2477: dev->sc_nexus = NULL;
! 2478: dev->sc_xs = NULL;
! 2479: }
! 2480:
! 2481: /*
! 2482: * Reload sync values for this target
! 2483: */
! 2484: if ( dev->sc_sync[newtarget].state == SYNC_DONE )
! 2485: SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[newtarget].offset,
! 2486: dev->sc_sync[newtarget].period));
! 2487: else
! 2488: SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period));
! 2489:
! 2490: /*
! 2491: * Loop through the nexus list until we find the saved entry
! 2492: * for the reselecting target...
! 2493: */
! 2494: TAILQ_FOREACH(acb, &dev->nexus_list, chain) {
! 2495:
! 2496: if ( acb->xs->sc_link->target == newtarget &&
! 2497: acb->xs->sc_link->lun == newlun) {
! 2498: /*
! 2499: * We've found the saved entry. Dequeue it, and
! 2500: * make it current again.
! 2501: */
! 2502: TAILQ_REMOVE(&dev->nexus_list, acb, chain);
! 2503:
! 2504: dev->sc_nexus = acb;
! 2505: dev->sc_xs = acb->xs;
! 2506: dev->sc_flags |= SBICF_SELECTED;
! 2507: dev->target = newtarget;
! 2508: dev->lun = newlun;
! 2509: break;
! 2510: }
! 2511: }
! 2512:
! 2513: if ( acb == NULL ) {
! 2514: printf("%s: reselect %s targ %d not in nexus_list %p\n",
! 2515: dev->sc_dev.dv_xname,
! 2516: csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget,
! 2517: &TAILQ_FIRST(&dev->nexus_list));
! 2518: panic("bad reselect in sbic");
! 2519: }
! 2520:
! 2521: if ( csr == SBIC_CSR_RSLT_IFY )
! 2522: SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK);
! 2523: }
! 2524: break;
! 2525:
! 2526: default:
! 2527: abort:
! 2528: {
! 2529: /*
! 2530: * Something unexpected happened -- deal with it.
! 2531: */
! 2532: printf("next: aborting asr 0x%02x csr 0x%02x\n", asr, csr);
! 2533:
! 2534: #ifdef DDB
! 2535: Debugger();
! 2536: #endif
! 2537:
! 2538: #ifdef DEBUG
! 2539: dev->sc_dmatimo = 0;
! 2540: if ( data_pointer_debug > 1 )
! 2541: printf("next dmastop: %d(%x:%x)\n", dev->target,
! 2542: dev->sc_cur->dc_addr,
! 2543: dev->sc_tcnt);
! 2544: #endif
! 2545:
! 2546: dev->sc_dmastop(dev);
! 2547: SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI);
! 2548: if ( dev->sc_xs ) sbicerror(dev, csr);
! 2549: sbicabort(dev, "next");
! 2550:
! 2551: if ( dev->sc_flags & SBICF_INDMA ) {
! 2552: dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH);
! 2553:
! 2554: #ifdef DEBUG
! 2555: dev->sc_dmatimo = 0;
! 2556: if ( data_pointer_debug > 1 )
! 2557: printf("next dmastop: %d(%x:%x)\n", dev->target,
! 2558: dev->sc_cur->dc_addr,
! 2559: dev->sc_tcnt);
! 2560: #endif
! 2561: sbic_scsidone(acb, -1);
! 2562: }
! 2563:
! 2564: return SBIC_STATE_ERROR;
! 2565: }
! 2566: }
! 2567:
! 2568: return(SBIC_STATE_RUNNING);
! 2569: }
! 2570:
! 2571:
! 2572: /*
! 2573: * Check if DMA can not be used with specified buffer
! 2574: */
! 2575: int
! 2576: sbiccheckdmap(bp, len, mask)
! 2577: void *bp;
! 2578: u_long len,
! 2579: mask;
! 2580: {
! 2581: u_char *buffer;
! 2582: u_long phy_buf;
! 2583: u_long phy_len;
! 2584:
! 2585: buffer = bp;
! 2586:
! 2587: if ( len == 0 )
! 2588: return(1);
! 2589:
! 2590: while ( len ) {
! 2591:
! 2592: phy_buf = kvtop((vaddr_t)buffer);
! 2593: phy_len = NBPG - ((int) buffer & PGOFSET);
! 2594:
! 2595: if ( len < phy_len )
! 2596: phy_len = len;
! 2597:
! 2598: if ( phy_buf & mask )
! 2599: return(1);
! 2600:
! 2601: buffer += phy_len;
! 2602: len -= phy_len;
! 2603: }
! 2604:
! 2605: return(0);
! 2606: }
! 2607:
! 2608: int
! 2609: sbictoscsiperiod(dev, a)
! 2610: struct sbic_softc *dev;
! 2611: int a;
! 2612: {
! 2613: unsigned int fs;
! 2614:
! 2615: /*
! 2616: * cycle = DIV / (2 * CLK)
! 2617: * DIV = FS + 2
! 2618: * best we can do is 200ns at 20MHz, 2 cycles
! 2619: */
! 2620:
! 2621: GET_SBIC_myid(dev->sc_sbicp, fs);
! 2622:
! 2623: fs = (fs >> 6) + 2; /* DIV */
! 2624:
! 2625: fs = (fs * 10000) / (dev->sc_clkfreq << 1); /* Cycle, in ns */
! 2626:
! 2627: if ( a < 2 )
! 2628: a = 8; /* map to Cycles */
! 2629:
! 2630: return ( (fs * a) >> 2 ); /* in 4 ns units */
! 2631: }
! 2632:
! 2633: int
! 2634: sbicfromscsiperiod(dev, p)
! 2635: struct sbic_softc *dev;
! 2636: int p;
! 2637: {
! 2638: unsigned fs,
! 2639: ret;
! 2640:
! 2641: /*
! 2642: * Just the inverse of the above
! 2643: */
! 2644: GET_SBIC_myid(dev->sc_sbicp, fs);
! 2645:
! 2646: fs = (fs >> 6) + 2; /* DIV */
! 2647:
! 2648: fs = (fs * 10000) / (dev->sc_clkfreq << 1); /* Cycle, in ns */
! 2649:
! 2650: ret = p << 2; /* in ns units */
! 2651: ret = ret / fs; /* in Cycles */
! 2652:
! 2653: if ( ret < sbic_min_period )
! 2654: return(sbic_min_period);
! 2655:
! 2656: /*
! 2657: * verify rounding
! 2658: */
! 2659: if ( sbictoscsiperiod(dev, ret) < p )
! 2660: ret++;
! 2661:
! 2662: return( (ret >= 8) ? 0 : ret );
! 2663: }
! 2664:
! 2665: #ifdef DEBUG
! 2666: void
! 2667: sbictimeout(dev)
! 2668: struct sbic_softc *dev;
! 2669: {
! 2670: int s,
! 2671: asr;
! 2672:
! 2673: s = splbio();
! 2674:
! 2675: if ( dev->sc_dmatimo ) {
! 2676:
! 2677: if ( dev->sc_dmatimo > 1 ) {
! 2678:
! 2679: printf("%s: dma timeout #%d\n", dev->sc_dev.dv_xname,
! 2680: dev->sc_dmatimo - 1);
! 2681:
! 2682: GET_SBIC_asr(dev->sc_sbicp, asr);
! 2683:
! 2684: if ( asr & SBIC_ASR_INT ) {
! 2685: /*
! 2686: * We need to service a missed IRQ
! 2687: */
! 2688: sbicintr(dev);
! 2689: } else {
! 2690: (void) sbicabort(dev, "timeout");
! 2691: splx(s);
! 2692: return;
! 2693: }
! 2694: }
! 2695:
! 2696: dev->sc_dmatimo++;
! 2697: }
! 2698:
! 2699: splx(s);
! 2700:
! 2701: timeout((void *)sbictimeout, dev, 30 * hz);
! 2702: }
! 2703: #endif
CVSweb