Annotation of sys/arch/mac68k/dev/ncr5380.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ncr5380.c,v 1.31 2007/04/24 16:48:43 miod Exp $ */
! 2: /* $NetBSD: ncr5380.c,v 1.38 1996/12/19 21:48:18 scottr Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Leo Weppelman.
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. All advertising materials mentioning features or use of this software
! 17: * must display the following acknowledgement:
! 18: * This product includes software developed by Leo Weppelman.
! 19: * 4. The name of the author may not be used to endorse or promote products
! 20: * derived from this software without specific prior written permission
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 32: */
! 33:
! 34: /*
! 35: * Bit mask of targets you want debugging to be shown
! 36: */
! 37: u_char dbg_target_mask = 0x7f;
! 38:
! 39: /*
! 40: * Set bit for target when parity checking must be disabled.
! 41: * My (LWP) Maxtor 7245S seems to generate parity errors on about 50%
! 42: * of all transfers while the data is correct!?
! 43: */
! 44: u_char ncr5380_no_parchk = 0xff;
! 45:
! 46: /*
! 47: * Flags to allow binpatching of which devices to allow or disallow
! 48: * issuance of linked commands. disallowance is favored over allowance,
! 49: * so if the same bit is set in either, the driver will not issue linked
! 50: * commands to the corresponding target.
! 51: * SCSI-2 devices can report whether or not they will accept linked
! 52: * commands. If that reports that a device supports linked commands,
! 53: * then it is treated as if the corresponding bit in ncr5380_allow_linked
! 54: * is set.
! 55: */
! 56: u_char ncr5380_allow_linked = 0x80;
! 57: u_char ncr5380_disallow_linked = 0x80;
! 58:
! 59: /*
! 60: * This is the default sense-command we send.
! 61: */
! 62: static u_char sense_cmd[] = {
! 63: REQUEST_SENSE, 0, 0, 0, sizeof(struct scsi_sense_data), 0
! 64: };
! 65:
! 66: /*
! 67: * True if the main co-routine is running
! 68: */
! 69: static volatile int main_running = 0;
! 70:
! 71: /*
! 72: * Mask of targets selected
! 73: */
! 74: static u_char busy;
! 75:
! 76: static void ncr5380_minphys(struct buf *bp);
! 77: static int mac68k_ncr5380_scsi_cmd(struct scsi_xfer *xs);
! 78: static void ncr5380_show_scsi_cmd(struct scsi_xfer *xs);
! 79:
! 80: struct scsi_adapter ncr5380_switch = {
! 81: mac68k_ncr5380_scsi_cmd, /* scsi_cmd() */
! 82: ncr5380_minphys, /* scsi_minphys() */
! 83: 0, /* open_target_lu() */
! 84: 0 /* close_target_lu() */
! 85: };
! 86:
! 87: struct scsi_device ncr5380_dev = {
! 88: NULL, /* use default error handler */
! 89: NULL, /* do not have a start functio */
! 90: NULL, /* have no async handler */
! 91: NULL /* Use default done routine */
! 92: };
! 93:
! 94:
! 95: static SC_REQ req_queue[NREQ];
! 96: static SC_REQ *free_head = NULL; /* Free request structures */
! 97:
! 98:
! 99: /*
! 100: * Inline functions:
! 101: */
! 102:
! 103: /*
! 104: * Determine the size of a SCSI command.
! 105: */
! 106: extern __inline__ int command_size(opcode)
! 107: u_char opcode;
! 108: {
! 109: switch ((opcode >> 4) & 0xf) {
! 110: case 0:
! 111: case 1:
! 112: return (6);
! 113: case 2:
! 114: case 3:
! 115: return (10);
! 116: }
! 117: return (12);
! 118: }
! 119:
! 120:
! 121: /*
! 122: * Wait for request-line to become active. When it doesn't return 0.
! 123: * Otherwise return != 0.
! 124: * The timeouts in the 'wait_req_*' functions are arbitrary and rather
! 125: * large. In 99% of the invocations nearly no timeout is needed but in
! 126: * some cases (especially when using my tapedrive, a Tandberg 3600) the
! 127: * device is busy internally and the first SCSI-phase will be delayed.
! 128: *
! 129: * -- A sleeping Fujitsu M2512 is even worse; try 2.5 sec -hf 20 Jun
! 130: */
! 131: extern __inline__ int wait_req_true(void)
! 132: {
! 133: int timeout = 2500000;
! 134:
! 135: while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
! 136: delay(1);
! 137: return (GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ);
! 138: }
! 139:
! 140: /*
! 141: * Wait for request-line to become inactive. When it doesn't return 0.
! 142: * Otherwise return != 0.
! 143: */
! 144: extern __inline__ int wait_req_false(void)
! 145: {
! 146: int timeout = 2500000;
! 147:
! 148: while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
! 149: delay(1);
! 150: return (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ));
! 151: }
! 152:
! 153: extern __inline__ void ack_message()
! 154: {
! 155: SET_5380_REG(NCR5380_ICOM, 0);
! 156: }
! 157:
! 158: extern __inline__ void nack_message(SC_REQ *reqp, u_char msg)
! 159: {
! 160: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
! 161: reqp->msgout = msg;
! 162: }
! 163:
! 164: extern __inline__ void finish_req(SC_REQ *reqp)
! 165: {
! 166: int sps;
! 167: struct scsi_xfer *xs = reqp->xs;
! 168:
! 169: #ifdef REAL_DMA
! 170: /*
! 171: * If we bounced, free the bounce buffer
! 172: */
! 173: if (reqp->dr_flag & DRIVER_BOUNCING)
! 174: free_bounceb(reqp->bounceb);
! 175: #endif /* REAL_DMA */
! 176: #ifdef DBG_REQ
! 177: if (dbg_target_mask & (1 << reqp->targ_id))
! 178: show_request(reqp, "DONE");
! 179: #endif
! 180: #ifdef DBG_ERR_RET
! 181: if (reqp->xs->error != 0)
! 182: show_request(reqp, "ERR_RET");
! 183: #endif
! 184: /*
! 185: * Return request to free-q
! 186: */
! 187: sps = splbio();
! 188: reqp->next = free_head;
! 189: free_head = reqp;
! 190:
! 191: xs->flags |= ITSDONE;
! 192: if (!(reqp->dr_flag & DRIVER_LINKCHK))
! 193: scsi_done(xs);
! 194: splx(sps);
! 195: }
! 196:
! 197: /*
! 198: * Auto config stuff....
! 199: */
! 200: void ncr_attach(struct device *, struct device *, void *);
! 201: int ncr_match(struct device *, void *, void *);
! 202:
! 203: /*
! 204: * Tricks to make driver-name configurable
! 205: */
! 206: #define CFNAME(n) __CONCAT(n,_cd)
! 207: #define CANAME(n) __CONCAT(n,_ca)
! 208: #define CFSTRING(n) __STRING(n)
! 209:
! 210: struct cfattach CANAME(DRNAME) = {
! 211: sizeof(struct ncr_softc), ncr_match, ncr_attach
! 212: };
! 213:
! 214: struct cfdriver CFNAME(DRNAME) = {
! 215: NULL, CFSTRING(DRNAME), DV_DULL
! 216: };
! 217:
! 218: int
! 219: ncr_match(parent, cf, aux)
! 220: struct device *parent;
! 221: void *cf;
! 222: void *aux;
! 223: {
! 224: return (machine_match(parent,
! 225: (struct cfdata *) cf, aux, &CFNAME(DRNAME)));
! 226: }
! 227:
! 228: void
! 229: ncr_attach(pdp, dp, auxp)
! 230: struct device *pdp, *dp;
! 231: void *auxp;
! 232: {
! 233: struct ncr_softc *sc;
! 234: struct scsibus_attach_args saa;
! 235: int i;
! 236:
! 237: sc = (struct ncr_softc *)dp;
! 238:
! 239: sc->sc_link.adapter_softc = sc;
! 240: sc->sc_link.adapter_target = 7;
! 241: sc->sc_link.adapter = &ncr5380_switch;
! 242: sc->sc_link.device = &ncr5380_dev;
! 243: sc->sc_link.openings = NREQ - 1;
! 244:
! 245: /*
! 246: * bitmasks
! 247: */
! 248: sc->sc_noselatn = 0;
! 249: sc->sc_selected = 0;
! 250:
! 251: /*
! 252: * Initialize machine-type specific things...
! 253: */
! 254: scsi_mach_init(sc);
! 255: printf("\n");
! 256:
! 257: /*
! 258: * Initialize request queue freelist.
! 259: */
! 260: for (i = 0; i < NREQ; i++) {
! 261: req_queue[i].next = free_head;
! 262: free_head = &req_queue[i];
! 263: }
! 264:
! 265: /*
! 266: * Initialize the host adapter
! 267: */
! 268: scsi_idisable();
! 269: ENABLE_NCR5380(sc);
! 270: SET_5380_REG(NCR5380_ICOM, 0);
! 271: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 272: SET_5380_REG(NCR5380_TCOM, 0);
! 273: SET_5380_REG(NCR5380_IDSTAT, 0);
! 274: scsi_ienable();
! 275:
! 276: bzero(&saa, sizeof(saa));
! 277: saa.saa_sc_link = &sc->sc_link;
! 278:
! 279: /*
! 280: * attach all scsi units on us
! 281: */
! 282: config_found(dp, &saa, scsiprint);
! 283: }
! 284:
! 285: /*
! 286: * End of auto config stuff....
! 287: */
! 288:
! 289: /*
! 290: * Carry out a request from the high level driver.
! 291: */
! 292: static int
! 293: mac68k_ncr5380_scsi_cmd(struct scsi_xfer *xs)
! 294: {
! 295: int sps;
! 296: SC_REQ *reqp, *link, *tmp;
! 297: int flags = xs->flags;
! 298:
! 299: /*
! 300: * We do not queue RESET commands
! 301: */
! 302: if (flags & SCSI_RESET) {
! 303: scsi_reset_verbose(xs->sc_link->adapter_softc,
! 304: "Got reset-command");
! 305: return (COMPLETE);
! 306: }
! 307:
! 308: /*
! 309: * Get a request block
! 310: */
! 311: sps = splbio();
! 312: if ((reqp = free_head) == 0) {
! 313: splx(sps);
! 314: return (TRY_AGAIN_LATER);
! 315: }
! 316: free_head = reqp->next;
! 317: reqp->next = NULL;
! 318: splx(sps);
! 319:
! 320: /*
! 321: * Initialize our private fields
! 322: */
! 323: reqp->dr_flag = (flags & SCSI_POLL) ? DRIVER_NOINT : 0;
! 324: reqp->phase = NR_PHASE;
! 325: reqp->msgout = MSG_NOOP;
! 326: reqp->status = SCSGOOD;
! 327: reqp->message = 0xff;
! 328: reqp->link = NULL;
! 329: reqp->xs = xs;
! 330: reqp->targ_id = xs->sc_link->target;
! 331: reqp->targ_lun = xs->sc_link->lun;
! 332: reqp->xdata_ptr = (u_char *)xs->data;
! 333: reqp->xdata_len = xs->datalen;
! 334: memcpy(&reqp->xcmd, xs->cmd, sizeof(struct scsi_generic));
! 335: reqp->xcmd.bytes[0] |= reqp->targ_lun << 5;
! 336:
! 337: /*
! 338: * Sanity check on flags...
! 339: */
! 340: if (flags & ITSDONE) {
! 341: ncr_tprint(reqp, "scsi_cmd: command already done.....\n");
! 342: xs->flags &= ~ITSDONE;
! 343: }
! 344:
! 345: #ifdef REAL_DMA
! 346: /*
! 347: * Check if DMA can be used on this request
! 348: */
! 349: if (scsi_dmaok(reqp))
! 350: reqp->dr_flag |= DRIVER_DMAOK;
! 351: #endif /* REAL_DMA */
! 352:
! 353: /*
! 354: * Insert the command into the issue queue. Note that 'REQUEST SENSE'
! 355: * commands are inserted at the head of the queue since any command
! 356: * will clear the existing contingent allegience condition and the sense
! 357: * data is only valid while the condition exists.
! 358: * When possible, link the command to a previous command to the same
! 359: * target. This is not very sensible when AUTO_SENSE is not defined!
! 360: * Interrupts are disabled while we are fiddling with the issue-queue.
! 361: */
! 362: sps = splbio();
! 363: link = NULL;
! 364: if ((issue_q == NULL) || (reqp->xcmd.opcode == REQUEST_SENSE)) {
! 365: reqp->next = issue_q;
! 366: issue_q = reqp;
! 367: }
! 368: else {
! 369: tmp = issue_q;
! 370: do {
! 371: if (!link && (tmp->targ_id == reqp->targ_id) && !tmp->link)
! 372: link = tmp;
! 373: } while (tmp->next && (tmp = tmp->next));
! 374: tmp->next = reqp;
! 375: #ifdef AUTO_SENSE
! 376: if (link && ((xs->sc_link->inqdata.flags & SID_Linked)
! 377: || ((1<<reqp->targ_id) & ncr5380_allow_linked))
! 378: && !((1<<reqp->targ_id) & ncr5380_disallow_linked)) {
! 379: link->link = reqp;
! 380: link->xcmd.bytes[link->xs->cmdlen-2] |= 1;
! 381: }
! 382: #endif
! 383: }
! 384: splx(sps);
! 385:
! 386: #ifdef DBG_REQ
! 387: if (dbg_target_mask & (1 << reqp->targ_id))
! 388: show_request(reqp, (reqp->xcmd.opcode == REQUEST_SENSE) ?
! 389: "HEAD":"TAIL");
! 390: #endif
! 391:
! 392: run_main(xs->sc_link->adapter_softc);
! 393:
! 394: if (xs->flags & (SCSI_POLL|ITSDONE))
! 395: return (COMPLETE); /* We're booting or run_main has completed */
! 396: return (SUCCESSFULLY_QUEUED);
! 397: }
! 398:
! 399: static void
! 400: ncr5380_minphys(struct buf *bp)
! 401: {
! 402: if (bp->b_bcount > MIN_PHYS)
! 403: bp->b_bcount = MIN_PHYS;
! 404: minphys(bp);
! 405: }
! 406: #undef MIN_PHYS
! 407:
! 408: static void
! 409: ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
! 410: {
! 411: u_char *b = (u_char *) xs->cmd;
! 412: int i = 0;
! 413:
! 414: if (!(xs->flags & SCSI_RESET)) {
! 415: printf("(%d:%d:%d,0x%x)-", xs->sc_link->scsibus,
! 416: xs->sc_link->target, xs->sc_link->lun, xs->sc_link->flags);
! 417: while (i < xs->cmdlen) {
! 418: if (i)
! 419: printf(",");
! 420: printf("%x",b[i++]);
! 421: }
! 422: printf("-\n");
! 423: }
! 424: else {
! 425: printf("(%d:%d:%d)-RESET-\n",
! 426: xs->sc_link->scsibus,xs->sc_link->target, xs->sc_link->lun);
! 427: }
! 428: }
! 429:
! 430: /*
! 431: * The body of the driver.
! 432: */
! 433: static void
! 434: scsi_main(sc)
! 435: struct ncr_softc *sc;
! 436: {
! 437: SC_REQ *req, *prev;
! 438: int itype;
! 439: int sps;
! 440:
! 441: /*
! 442: * While running in the driver SCSI-interrupts are disabled.
! 443: */
! 444: scsi_idisable();
! 445: ENABLE_NCR5380(sc);
! 446:
! 447: PID("scsi_main1");
! 448: for (;;) {
! 449: sps = splbio();
! 450: if (!connected) {
! 451: /*
! 452: * Check if it is fair keep any exclusive access to DMA
! 453: * claimed. If not, stop queueing new jobs so the discon_q
! 454: * will be eventually drained and DMA can be given up.
! 455: */
! 456: if (!fair_to_keep_dma())
! 457: goto main_exit;
! 458:
! 459: /*
! 460: * Search through the issue-queue for a command
! 461: * destined for a target that isn't busy.
! 462: */
! 463: prev = NULL;
! 464: for (req=issue_q; req != NULL; prev = req, req = req->next) {
! 465: if (!(busy & (1 << req->targ_id))) {
! 466: /*
! 467: * Found one, remove it from the issue queue
! 468: */
! 469: if (prev == NULL)
! 470: issue_q = req->next;
! 471: else prev->next = req->next;
! 472: req->next = NULL;
! 473: break;
! 474: }
! 475: }
! 476:
! 477: /*
! 478: * When a request has just ended, we get here before an other
! 479: * device detects that the bus is free and that it can
! 480: * reconnect. The problem is that when this happens, we always
! 481: * baffle the device because our (initiator) id is higher. This
! 482: * can cause a sort of starvation on slow devices. So we check
! 483: * for a pending reselection here.
! 484: * Note that 'connected' will be non-null if the reselection
! 485: * succeeds.
! 486: */
! 487: if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
! 488: == (SC_S_SEL|SC_S_IO)){
! 489: if (req != NULL) {
! 490: req->next = issue_q;
! 491: issue_q = req;
! 492: }
! 493: splx(sps);
! 494:
! 495: reselect(sc);
! 496: scsi_clr_ipend();
! 497: goto connected;
! 498: }
! 499:
! 500: /*
! 501: * The host is not connected and there is no request
! 502: * pending, exit.
! 503: */
! 504: if (req == NULL) {
! 505: PID("scsi_main2");
! 506: goto main_exit;
! 507: }
! 508:
! 509: /*
! 510: * Re-enable interrupts before handling the request.
! 511: */
! 512: splx(sps);
! 513:
! 514: #ifdef DBG_REQ
! 515: if (dbg_target_mask & (1 << req->targ_id))
! 516: show_request(req, "TARGET");
! 517: #endif
! 518: /*
! 519: * We found a request. Try to connect to the target. If the
! 520: * initiator fails arbitration, the command is put back in the
! 521: * issue queue.
! 522: */
! 523: if (scsi_select(req, 0)) {
! 524: sps = splbio();
! 525: req->next = issue_q;
! 526: issue_q = req;
! 527: splx(sps);
! 528: #ifdef DBG_REQ
! 529: if (dbg_target_mask & (1 << req->targ_id))
! 530: ncr_tprint(req, "Select failed\n");
! 531: #endif
! 532: }
! 533: }
! 534: else splx(sps);
! 535: connected:
! 536: if (connected) {
! 537: /*
! 538: * If the host is currently connected but a 'real-dma' transfer
! 539: * is in progress, the 'end-of-dma' interrupt restarts main.
! 540: * So quit.
! 541: */
! 542: sps = splbio();
! 543: if (connected && (connected->dr_flag & DRIVER_IN_DMA)) {
! 544: PID("scsi_main3");
! 545: goto main_exit;
! 546: }
! 547: splx(sps);
! 548:
! 549: /*
! 550: * Let the target guide us through the bus-phases
! 551: */
! 552: while (information_transfer(sc) == -1)
! 553: ;
! 554: }
! 555: }
! 556: /* NEVER TO REACH HERE */
! 557: panic("ncr5380-SCSI: not designed to come here");
! 558:
! 559: main_exit:
! 560: /*
! 561: * We enter here with interrupts disabled. We are about to exit main
! 562: * so interrupts should be re-enabled. Because interrupts are edge
! 563: * triggered, we could already have missed the interrupt. Therefore
! 564: * we check the IRQ-line here and re-enter when we really missed a
! 565: * valid interrupt.
! 566: */
! 567: PID("scsi_main4");
! 568: scsi_ienable();
! 569:
! 570: /*
! 571: * If we're not currently connected, enable reselection
! 572: * interrupts.
! 573: */
! 574: if (!connected)
! 575: SET_5380_REG(NCR5380_IDSTAT, SC_HOST_ID);
! 576:
! 577: if (scsi_ipending()) {
! 578: if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
! 579: scsi_idisable();
! 580: splx(sps);
! 581:
! 582: if (itype == INTR_RESEL)
! 583: reselect(sc);
! 584: #ifdef REAL_DMA
! 585: else dma_ready();
! 586: #else
! 587: else {
! 588: if (pdma_ready())
! 589: goto connected;
! 590: panic("Got DMA interrupt without DMA");
! 591: }
! 592: #endif
! 593: scsi_clr_ipend();
! 594: goto connected;
! 595: }
! 596: }
! 597: reconsider_dma();
! 598:
! 599: main_running = 0;
! 600: splx(sps);
! 601: PID("scsi_main5");
! 602: }
! 603:
! 604: #ifdef REAL_DMA
! 605: /*
! 606: * The SCSI-DMA interrupt.
! 607: * This interrupt can only be triggered when running in non-polled DMA
! 608: * mode. When DMA is not active, it will be silently ignored, it is usually
! 609: * too late because the EOP interrupt of the controller happens just a tiny
! 610: * bit earlier. It might become usefull when scatter/gather is implemented,
! 611: * because in that case only part of the DATAIN/DATAOUT transfer is taken
! 612: * out of a single buffer.
! 613: */
! 614: static void
! 615: ncr_dma_intr(sc)
! 616: struct ncr_softc *sc;
! 617: {
! 618: SC_REQ *reqp;
! 619: int dma_done;
! 620:
! 621: PID("ncr_dma_intr");
! 622: if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)) {
! 623: scsi_idisable();
! 624: if (!(dma_done = dma_ready())) {
! 625: transfer_dma(reqp, reqp->phase, 0);
! 626: return;
! 627: }
! 628: run_main(sc);
! 629: }
! 630: }
! 631: #endif /* REAL_DMA */
! 632:
! 633: /*
! 634: * The SCSI-controller interrupt. This interrupt occurs on reselections and
! 635: * at the end of non-polled DMA-interrupts. It is assumed to be called from
! 636: * the machine-dependent hardware interrupt.
! 637: */
! 638: static void
! 639: ncr_ctrl_intr(sc)
! 640: struct ncr_softc *sc;
! 641: {
! 642: int itype;
! 643:
! 644: while (scsi_ipending()) {
! 645: scsi_idisable();
! 646: if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
! 647: if (itype == INTR_RESEL)
! 648: reselect(sc);
! 649: else {
! 650: #ifdef REAL_DMA
! 651: int dma_done;
! 652: if (!(dma_done = dma_ready())) {
! 653: transfer_dma(connected, connected->phase, 0);
! 654: return;
! 655: }
! 656: #else
! 657: if (pdma_ready())
! 658: return;
! 659: panic("Got DMA interrupt without DMA");
! 660: #endif
! 661: }
! 662: scsi_clr_ipend();
! 663: }
! 664: run_main(sc);
! 665: return;
! 666: }
! 667: PID("ncr_ctrl_intr1");
! 668: }
! 669:
! 670: /*
! 671: * Initiate a connection path between the host and the target. The function
! 672: * first goes into arbitration for the SCSI-bus. When this succeeds, the target
! 673: * is selected and an 'IDENTIFY' message is send.
! 674: * Returns -1 when the arbitration failed. Otherwise 0 is returned. When
! 675: * the target does not respond (to either selection or 'MESSAGE OUT') the
! 676: * 'done' function is executed.
! 677: * The result code given by the driver can be influenced by setting 'code'
! 678: * to a non-zero value. This is the case when 'select' is called by abort.
! 679: */
! 680: static int
! 681: scsi_select(reqp, code)
! 682: SC_REQ *reqp;
! 683: int code;
! 684: {
! 685: u_char tmp[1];
! 686: u_char phase;
! 687: u_long cnt;
! 688: int sps;
! 689: u_int8_t atn_flag;
! 690: u_int8_t targ_bit;
! 691: struct ncr_softc *sc;
! 692:
! 693: sc = reqp->xs->sc_link->adapter_softc;
! 694: DBG_SELPRINT ("Starting arbitration\n", 0);
! 695: PID("scsi_select1");
! 696:
! 697: sps = splbio();
! 698:
! 699: /*
! 700: * Prevent a race condition here. If a reslection interrupt occurred
! 701: * between the decision to pick a new request and the call to select,
! 702: * we abort the selection.
! 703: * Interrupts are lowered when the 5380 is setup to arbitrate for the
! 704: * bus.
! 705: */
! 706: if (connected) {
! 707: splx(sps);
! 708: PID("scsi_select2");
! 709: return (-1);
! 710: }
! 711:
! 712: /*
! 713: * Set phase bits to 0, otherwise the 5380 won't drive the bus during
! 714: * selection.
! 715: */
! 716: SET_5380_REG(NCR5380_TCOM, 0);
! 717: SET_5380_REG(NCR5380_ICOM, 0);
! 718:
! 719: /*
! 720: * Arbitrate for the bus.
! 721: */
! 722: SET_5380_REG(NCR5380_DATA, SC_HOST_ID);
! 723: SET_5380_REG(NCR5380_MODE, SC_ARBIT);
! 724:
! 725: splx(sps);
! 726:
! 727: cnt = 10;
! 728: while (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP) && --cnt)
! 729: delay(1);
! 730:
! 731: if (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP)) {
! 732: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 733: SET_5380_REG(NCR5380_ICOM, 0);
! 734: DBG_SELPRINT ("Arbitration lost, bus not free\n",0);
! 735: PID("scsi_select3");
! 736: return (-1);
! 737: }
! 738:
! 739: /* The arbitration delay is 2.2 usecs */
! 740: delay(3);
! 741:
! 742: /*
! 743: * Check the result of the arbitration. If we failed, return -1.
! 744: */
! 745: if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
! 746: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 747: SET_5380_REG(NCR5380_ICOM, 0);
! 748: PID("scsi_select4");
! 749: return (-1);
! 750: }
! 751:
! 752: /*
! 753: * The spec requires that we should read the data register to
! 754: * check for higher id's and check the SC_LA again.
! 755: */
! 756: tmp[0] = GET_5380_REG(NCR5380_DATA);
! 757: if (tmp[0] & ~((SC_HOST_ID << 1) - 1)) {
! 758: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 759: SET_5380_REG(NCR5380_ICOM, 0);
! 760: DBG_SELPRINT ("Arbitration lost, higher id present\n",0);
! 761: PID("scsi_select5");
! 762: return (-1);
! 763: }
! 764: if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
! 765: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 766: SET_5380_REG(NCR5380_ICOM, 0);
! 767: DBG_SELPRINT ("Arbitration lost,deassert SC_ARBIT\n",0);
! 768: PID("scsi_select6");
! 769: return (-1);
! 770: }
! 771: SET_5380_REG(NCR5380_ICOM, SC_A_SEL | SC_A_BSY);
! 772: if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
! 773: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 774: SET_5380_REG(NCR5380_ICOM, 0);
! 775: DBG_SELPRINT ("Arbitration lost, deassert SC_A_SEL\n", 0);
! 776: PID("scsi_select7");
! 777: return (-1);
! 778: }
! 779: /* Bus settle delay + Bus clear delay = 1.2 usecs */
! 780: delay(2);
! 781: DBG_SELPRINT ("Arbitration complete\n", 0);
! 782:
! 783: /*
! 784: * Now that we won the arbitration, start the selection.
! 785: */
! 786: targ_bit = 1 << reqp->targ_id;
! 787: SET_5380_REG(NCR5380_DATA, SC_HOST_ID | targ_bit);
! 788:
! 789: if (sc->sc_noselatn & targ_bit)
! 790: atn_flag = 0;
! 791: else
! 792: atn_flag = SC_A_ATN;
! 793:
! 794: /*
! 795: * Raise ATN while SEL is true before BSY goes false from arbitration,
! 796: * since this is the only way to guarantee that we'll get a MESSAGE OUT
! 797: * phase immediately after the selection.
! 798: */
! 799: SET_5380_REG(NCR5380_ICOM, SC_A_BSY | SC_A_SEL | atn_flag | SC_ADTB);
! 800: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 801:
! 802: /*
! 803: * Turn off reselection interrupts
! 804: */
! 805: SET_5380_REG(NCR5380_IDSTAT, 0);
! 806:
! 807: /*
! 808: * Reset BSY. The delay following it, surpresses a glitch in the
! 809: * 5380 which causes us to see our own BSY signal instead of that of
! 810: * the target.
! 811: */
! 812: SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag | SC_ADTB);
! 813: delay(1);
! 814:
! 815: /*
! 816: * Wait for the target to react, the specs call for a timeout of
! 817: * 250 ms.
! 818: */
! 819: cnt = 25000;
! 820: while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) && --cnt)
! 821: delay(10);
! 822:
! 823: if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
! 824: /*
! 825: * There is no reaction from the target, start the selection
! 826: * timeout procedure. We release the databus but keep SEL
! 827: * asserted. After that we wait a 'selection abort time' (200
! 828: * usecs) and 2 deskew delays (90 ns) and check BSY again.
! 829: * When BSY is asserted, we assume the selection succeeded,
! 830: * otherwise we release the bus.
! 831: */
! 832: SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag);
! 833: delay(201);
! 834: if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
! 835: SET_5380_REG(NCR5380_ICOM, 0);
! 836: reqp->xs->error = code ? code : XS_SELTIMEOUT;
! 837: DBG_SELPRINT ("Target %d not responding to sel\n",
! 838: reqp->targ_id);
! 839: finish_req(reqp);
! 840: PID("scsi_select8");
! 841: return (0);
! 842: }
! 843: }
! 844: SET_5380_REG(NCR5380_ICOM, atn_flag);
! 845:
! 846: DBG_SELPRINT ("Target %d responding to select.\n", reqp->targ_id);
! 847:
! 848: /*
! 849: * The SCSI-interrupts are disabled while a request is being handled.
! 850: */
! 851: scsi_idisable();
! 852:
! 853: /*
! 854: * If we did not request ATN, then don't try to send IDENTIFY.
! 855: */
! 856: if (atn_flag == 0) {
! 857: reqp->phase = PH_CMD;
! 858: goto identify_failed;
! 859: }
! 860:
! 861: /*
! 862: * Here we prepare to send an 'IDENTIFY' message.
! 863: * Allow disconnect only when interrupts are allowed.
! 864: */
! 865: tmp[0] = MSG_IDENTIFY(reqp->targ_lun,
! 866: (reqp->dr_flag & DRIVER_NOINT) ? 0 : 1);
! 867: cnt = 1;
! 868: phase = PH_MSGOUT;
! 869:
! 870: /*
! 871: * Since we followed the SCSI-spec and raised ATN while SEL was true
! 872: * but before BSY was false during the selection, a 'MESSAGE OUT'
! 873: * phase should follow. Unfortunately, this does not happen on
! 874: * all targets (Asante ethernet devices, for example), so we must
! 875: * check the actual mode if the message transfer fails--if the
! 876: * new phase is PH_CMD and has never been successfully selected
! 877: * w/ATN in the past, then we assume that it is an old device
! 878: * that doesn't support select w/ATN.
! 879: */
! 880: if (transfer_pio(&phase, tmp, &cnt, 0) || cnt) {
! 881:
! 882: if ((phase == PH_CMD) && !(sc->sc_selected & targ_bit)) {
! 883: DBG_SELPRINT ("Target %d: not responding to ATN.\n",
! 884: reqp->targ_id);
! 885: sc->sc_noselatn |= targ_bit;
! 886: reqp->phase = PH_CMD;
! 887: goto identify_failed;
! 888: }
! 889:
! 890: DBG_SELPRINT ("Target %d: failed to send identify\n",
! 891: reqp->targ_id);
! 892: /*
! 893: * Try to disconnect from the target. We cannot leave
! 894: * it just hanging here.
! 895: */
! 896: if (!reach_msg_out(sc, sizeof(struct scsi_generic))) {
! 897: u_long len = 1;
! 898: u_char phase = PH_MSGOUT;
! 899: u_char msg = MSG_ABORT;
! 900:
! 901: transfer_pio(&phase, &msg, &len, 0);
! 902: }
! 903: else scsi_reset_verbose(sc, "Connected to unidentified target");
! 904:
! 905: SET_5380_REG(NCR5380_ICOM, 0);
! 906: reqp->xs->error = code ? code : XS_DRIVER_STUFFUP;
! 907: finish_req(reqp);
! 908: PID("scsi_select9");
! 909: return (0);
! 910: }
! 911: reqp->phase = PH_MSGOUT;
! 912:
! 913: identify_failed:
! 914: sc->sc_selected |= targ_bit;
! 915:
! 916: #ifdef notyet /* LWP: Do we need timeouts in the driver? */
! 917: /*
! 918: * Command is connected, start timer ticking.
! 919: */
! 920: ccb_p->xtimeout = ccb_p->timeout + Lbolt;
! 921: #endif
! 922:
! 923: connected = reqp;
! 924: busy |= targ_bit;
! 925: PID("scsi_select10");
! 926: return (0);
! 927: }
! 928:
! 929: /*
! 930: * Return codes:
! 931: * 0: Job has finished or disconnected, find something else
! 932: * -1: keep on calling information_transfer() from scsi_main()
! 933: */
! 934: static int
! 935: information_transfer(sc)
! 936: struct ncr_softc *sc;
! 937: {
! 938: SC_REQ *reqp = connected;
! 939: u_char tmp, phase;
! 940: u_long len;
! 941:
! 942: PID("info_transf1");
! 943: /*
! 944: * Clear pending interrupts from 5380-chip.
! 945: */
! 946: scsi_clr_ipend();
! 947:
! 948: /*
! 949: * The SCSI-spec requires BSY to be true while connected to a target,
! 950: * loosing it means we lost the target...
! 951: * Also REQ needs to be asserted here to indicate that the bus-phase
! 952: * is valid. When the target does not supply REQ within a 'reasonable'
! 953: * amount of time, it's probably lost in its own maze of twisting
! 954: * passages, we have to reset the bus to free it.
! 955: */
! 956: if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)
! 957: wait_req_true();
! 958: tmp = GET_5380_REG(NCR5380_IDSTAT);
! 959:
! 960:
! 961: if ((tmp & (SC_S_BSY|SC_S_REQ)) != (SC_S_BSY|SC_S_REQ)) {
! 962: busy &= ~(1 << reqp->targ_id);
! 963: connected = NULL;
! 964: reqp->xs->error = XS_TIMEOUT;
! 965: finish_req(reqp);
! 966: if (!(tmp & SC_S_REQ))
! 967: scsi_reset_verbose(sc,
! 968: "Timeout waiting for phase-change");
! 969: PID("info_transf2");
! 970: return (0);
! 971: }
! 972:
! 973: phase = (tmp >> 2) & 7;
! 974: if (phase != reqp->phase) {
! 975: reqp->phase = phase;
! 976: DBG_INFPRINT(show_phase, reqp, phase);
! 977: }
! 978: else {
! 979: /*
! 980: * Same data-phase. If same error give up
! 981: */
! 982: if ((reqp->msgout == MSG_ABORT)
! 983: && ((phase == PH_DATAOUT) || (phase == PH_DATAIN))) {
! 984: busy &= ~(1 << reqp->targ_id);
! 985: connected = NULL;
! 986: finish_req(reqp);
! 987: scsi_reset_verbose(sc, "Failure to abort command");
! 988: return (0);
! 989: }
! 990: }
! 991:
! 992: switch (phase) {
! 993: case PH_DATAOUT:
! 994: #ifdef DBG_NOWRITE
! 995: ncr_tprint(reqp, "NOWRITE set -- write attempt aborted.");
! 996: reqp->msgout = MSG_ABORT;
! 997: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
! 998: return (-1);
! 999: #endif /* DBG_NOWRITE */
! 1000: /*
! 1001: * If this is the first write using DMA, fill
! 1002: * the bounce buffer.
! 1003: */
! 1004: if (reqp->xdata_ptr == reqp->xs->data) { /* XXX */
! 1005: if (reqp->dr_flag & DRIVER_BOUNCING)
! 1006: bcopy(reqp->xdata_ptr, reqp->bounceb, reqp->xdata_len);
! 1007: }
! 1008:
! 1009: case PH_DATAIN:
! 1010: if (reqp->xdata_len <= 0) {
! 1011: /*
! 1012: * Target keeps requesting data. Try to get into
! 1013: * message-out phase by feeding/taking 100 byte.
! 1014: */
! 1015: ncr_tprint(reqp, "Target requests too much data\n");
! 1016: reqp->msgout = MSG_ABORT;
! 1017: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
! 1018: reach_msg_out(sc, 100);
! 1019: return (-1);
! 1020: }
! 1021: #ifdef REAL_DMA
! 1022: if (reqp->dr_flag & DRIVER_DMAOK) {
! 1023: int poll = REAL_DMA_POLL|(reqp->dr_flag & DRIVER_NOINT);
! 1024: transfer_dma(reqp, phase, poll);
! 1025: if (!poll)
! 1026: return (0);
! 1027: }
! 1028: else
! 1029: #endif
! 1030: {
! 1031: PID("info_transf3");
! 1032: len = reqp->xdata_len;
! 1033: #ifdef USE_PDMA
! 1034: if (transfer_pdma(&phase, reqp->xdata_ptr, &len) == 0)
! 1035: return (0);
! 1036: #else
! 1037: transfer_pio(&phase, reqp->xdata_ptr, &len, 0);
! 1038: #endif
! 1039: reqp->xdata_ptr += reqp->xdata_len - len;
! 1040: reqp->xdata_len = len;
! 1041: }
! 1042: return (-1);
! 1043: case PH_MSGIN:
! 1044: /*
! 1045: * We only expect single byte messages here.
! 1046: */
! 1047: len = 1;
! 1048: transfer_pio(&phase, &tmp, &len, 1);
! 1049: reqp->message = tmp;
! 1050: return (handle_message(reqp, tmp));
! 1051: case PH_MSGOUT:
! 1052: len = 1;
! 1053: transfer_pio(&phase, &reqp->msgout, &len, 0);
! 1054: if (reqp->msgout == MSG_ABORT) {
! 1055: busy &= ~(1 << reqp->targ_id);
! 1056: connected = NULL;
! 1057: if (!reqp->xs->error)
! 1058: reqp->xs->error = XS_DRIVER_STUFFUP;
! 1059: finish_req(reqp);
! 1060: PID("info_transf4");
! 1061: return (0);
! 1062: }
! 1063: reqp->msgout = MSG_NOOP;
! 1064: return (-1);
! 1065: case PH_CMD :
! 1066: len = command_size(reqp->xcmd.opcode);
! 1067: transfer_pio(&phase, (u_char *)&reqp->xcmd, &len, 0);
! 1068: PID("info_transf5");
! 1069: return (-1);
! 1070: case PH_STATUS:
! 1071: len = 1;
! 1072: transfer_pio(&phase, &tmp, &len, 0);
! 1073: reqp->status = tmp;
! 1074: PID("info_transf6");
! 1075: return (-1);
! 1076: default :
! 1077: ncr_tprint(reqp, "Unknown phase\n");
! 1078: }
! 1079: PID("info_transf7");
! 1080: return (-1);
! 1081: }
! 1082:
! 1083: /*
! 1084: * Handle the message 'msg' send to us by the target.
! 1085: * Return values:
! 1086: * 0 : The current command has completed.
! 1087: * -1 : Get on to the next phase.
! 1088: */
! 1089: static int
! 1090: handle_message(reqp, msg)
! 1091: SC_REQ *reqp;
! 1092: u_int msg;
! 1093: {
! 1094: int sps;
! 1095: SC_REQ *prev, *req;
! 1096:
! 1097: PID("hmessage1");
! 1098: switch (msg) {
! 1099: /*
! 1100: * Linking lets us reduce the time required to get
! 1101: * the next command to the device, skipping the arbitration
! 1102: * and selection time. In the current implementation,
! 1103: * we merely have to start the next command pointed
! 1104: * to by 'next_link'.
! 1105: */
! 1106: case MSG_LINK_CMD_COMPLETE:
! 1107: case MSG_LINK_CMD_COMPLETEF:
! 1108: if (reqp->link == NULL) {
! 1109: ncr_tprint(reqp, "No link for linked command");
! 1110: nack_message(reqp, MSG_ABORT);
! 1111: PID("hmessage2");
! 1112: return (-1);
! 1113: }
! 1114: ack_message();
! 1115: if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
! 1116: reqp->xs->resid = reqp->xdata_len;
! 1117: reqp->xs->error = 0;
! 1118: }
! 1119:
! 1120: #ifdef AUTO_SENSE
! 1121: if (check_autosense(reqp, 1) == -1)
! 1122: return (-1);
! 1123: #endif /* AUTO_SENSE */
! 1124:
! 1125: #ifdef DBG_REQ
! 1126: if (dbg_target_mask & (1 << reqp->targ_id))
! 1127: show_request(reqp->link, "LINK");
! 1128: #endif
! 1129: connected = reqp->link;
! 1130:
! 1131: /*
! 1132: * Unlink the 'linked' request from the issue_q
! 1133: */
! 1134: sps = splbio();
! 1135: prev = NULL;
! 1136: req = issue_q;
! 1137: for (; req != NULL; prev = req, req = req->next) {
! 1138: if (req == connected)
! 1139: break;
! 1140: }
! 1141: if (req == NULL)
! 1142: panic("Inconsistent issue_q");
! 1143: if (prev == NULL)
! 1144: issue_q = req->next;
! 1145: else prev->next = req->next;
! 1146: req->next = NULL;
! 1147: splx(sps);
! 1148:
! 1149: finish_req(reqp);
! 1150: PID("hmessage3");
! 1151: return (-1);
! 1152: case MSG_ABORT:
! 1153: case MSG_CMDCOMPLETE:
! 1154: ack_message();
! 1155: connected = NULL;
! 1156: busy &= ~(1 << reqp->targ_id);
! 1157: if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
! 1158: reqp->xs->resid = reqp->xdata_len;
! 1159: reqp->xs->error = 0;
! 1160: }
! 1161:
! 1162: #ifdef AUTO_SENSE
! 1163: if (check_autosense(reqp, 0) == -1) {
! 1164: PID("hmessage4");
! 1165: return (0);
! 1166: }
! 1167: #endif /* AUTO_SENSE */
! 1168:
! 1169: finish_req(reqp);
! 1170: PID("hmessage5");
! 1171: return (0);
! 1172: case MSG_MESSAGE_REJECT:
! 1173: ack_message();
! 1174: PID("hmessage6");
! 1175: return (-1);
! 1176: case MSG_DISCONNECT:
! 1177: ack_message();
! 1178: #ifdef DBG_REQ
! 1179: if (dbg_target_mask & (1 << reqp->targ_id))
! 1180: show_request(reqp, "DISCON");
! 1181: #endif
! 1182: sps = splbio();
! 1183: connected = NULL;
! 1184: reqp->next = discon_q;
! 1185: discon_q = reqp;
! 1186: splx(sps);
! 1187: PID("hmessage7");
! 1188: return (0);
! 1189: case MSG_SAVEDATAPOINTER:
! 1190: case MSG_RESTOREPOINTERS:
! 1191: /*
! 1192: * We save pointers implicitely at disconnect.
! 1193: * So we can ignore these messages.
! 1194: */
! 1195: ack_message();
! 1196: PID("hmessage8");
! 1197: return (-1);
! 1198: case MSG_EXTENDED:
! 1199: nack_message(reqp, MSG_MESSAGE_REJECT);
! 1200: PID("hmessage9");
! 1201: return (-1);
! 1202: default:
! 1203: if ((msg & 0x80) && !(msg & 0x18)) { /* IDENTIFY */
! 1204: PID("hmessage10");
! 1205: ack_message();
! 1206: return (0);
! 1207: } else {
! 1208: ncr_tprint(reqp,
! 1209: "Unknown message %x. Rejecting.\n",
! 1210: msg);
! 1211: nack_message(reqp, MSG_MESSAGE_REJECT);
! 1212: }
! 1213: return (-1);
! 1214: }
! 1215: PID("hmessage11");
! 1216: return (-1);
! 1217: }
! 1218:
! 1219: /*
! 1220: * Handle reselection. If a valid reconnection occurs, connected
! 1221: * points at the reconnected command. The command is removed from the
! 1222: * disconnected queue.
! 1223: */
! 1224: static void
! 1225: reselect(sc)
! 1226: struct ncr_softc *sc;
! 1227: {
! 1228: u_char phase;
! 1229: u_long len;
! 1230: u_char msg;
! 1231: u_char target_mask;
! 1232: int abort = 0;
! 1233: SC_REQ *tmp, *prev;
! 1234:
! 1235: PID("reselect1");
! 1236: target_mask = GET_5380_REG(NCR5380_DATA) & ~SC_HOST_ID;
! 1237:
! 1238: /*
! 1239: * At this point, we have detected that our SCSI-id is on the bus,
! 1240: * SEL is true and BSY was false for at least one bus settle
! 1241: * delay (400 ns.).
! 1242: * We must assert BSY ourselves, until the target drops the SEL signal.
! 1243: * The SCSI-spec specifies no maximum time for this, so we have to
! 1244: * choose something long enough to suit all targets.
! 1245: */
! 1246: SET_5380_REG(NCR5380_ICOM, SC_A_BSY);
! 1247: len = 250000;
! 1248: while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) && (len > 0)) {
! 1249: delay(1);
! 1250: len--;
! 1251: }
! 1252: if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) {
! 1253: /* Damn SEL isn't dropping */
! 1254: scsi_reset_verbose(sc, "Target won't drop SEL during Reselect");
! 1255: return;
! 1256: }
! 1257:
! 1258: SET_5380_REG(NCR5380_ICOM, 0);
! 1259:
! 1260: /*
! 1261: * Check if the reselection is still valid. Check twice because
! 1262: * of possible line glitches - cheaper than delay(1) and we need
! 1263: * only a few nanoseconds.
! 1264: */
! 1265: if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
! 1266: if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
! 1267: ncr_aprint(sc, "Stepped into the reselection timeout\n");
! 1268: return;
! 1269: }
! 1270: }
! 1271:
! 1272: /*
! 1273: * Get the expected identify message.
! 1274: */
! 1275: phase = PH_MSGIN;
! 1276: len = 1;
! 1277: transfer_pio(&phase, &msg, &len, 0);
! 1278: if (len || !MSG_ISIDENTIFY(msg)) {
! 1279: ncr_aprint(sc, "Expecting IDENTIFY, got 0x%x\n", msg);
! 1280: abort = 1;
! 1281: tmp = NULL;
! 1282: }
! 1283: else {
! 1284: /*
! 1285: * Find the command reconnecting
! 1286: */
! 1287: for (tmp = discon_q, prev = NULL; tmp; prev = tmp, tmp = tmp->next){
! 1288: if (target_mask == (1 << tmp->targ_id)) {
! 1289: if (prev)
! 1290: prev->next = tmp->next;
! 1291: else discon_q = tmp->next;
! 1292: tmp->next = NULL;
! 1293: break;
! 1294: }
! 1295: }
! 1296: if (tmp == NULL) {
! 1297: ncr_aprint(sc, "No disconnected job for targetmask %x\n",
! 1298: target_mask);
! 1299: abort = 1;
! 1300: }
! 1301: }
! 1302: if (abort) {
! 1303: msg = MSG_ABORT;
! 1304: len = 1;
! 1305: phase = PH_MSGOUT;
! 1306:
! 1307: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
! 1308: if (transfer_pio(&phase, &msg, &len, 0) || len)
! 1309: scsi_reset_verbose(sc, "Failure to abort reselection");
! 1310: }
! 1311: else {
! 1312: connected = tmp;
! 1313: #ifdef DBG_REQ
! 1314: if (dbg_target_mask & (1 << tmp->targ_id))
! 1315: show_request(tmp, "RECON");
! 1316: #endif
! 1317: }
! 1318: PID("reselect2");
! 1319: }
! 1320:
! 1321: /*
! 1322: * Transfer data in a given phase using programmed I/O.
! 1323: * Returns -1 when a different phase is entered without transferring the
! 1324: * maximum number of bytes, 0 if all bytes transferred or exit is in the same
! 1325: * phase.
! 1326: */
! 1327: static int
! 1328: transfer_pio(phase, data, len, dont_drop_ack)
! 1329: u_char *phase;
! 1330: u_char *data;
! 1331: u_long *len;
! 1332: int dont_drop_ack;
! 1333: {
! 1334: u_int cnt = *len;
! 1335: u_char ph = *phase;
! 1336: u_char tmp, new_icom;
! 1337:
! 1338: DBG_PIOPRINT ("SCSI: transfer_pio start: phase: %d, len: %d\n", ph,cnt);
! 1339: PID("tpio1");
! 1340: SET_5380_REG(NCR5380_TCOM, ph);
! 1341: do {
! 1342: if (!wait_req_true()) {
! 1343: DBG_PIOPRINT ("SCSI: transfer_pio: missing REQ\n", 0, 0);
! 1344: break;
! 1345: }
! 1346: if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != ph) {
! 1347: DBG_PIOPRINT ("SCSI: transfer_pio: phase mismatch\n", 0, 0);
! 1348: break;
! 1349: }
! 1350: if (PH_IN(ph)) {
! 1351: *data++ = GET_5380_REG(NCR5380_DATA);
! 1352: SET_5380_REG(NCR5380_ICOM, SC_A_ACK);
! 1353: if ((cnt == 1) && dont_drop_ack)
! 1354: new_icom = SC_A_ACK;
! 1355: else new_icom = 0;
! 1356: }
! 1357: else {
! 1358: SET_5380_REG(NCR5380_DATA, *data++);
! 1359:
! 1360: /*
! 1361: * The SCSI-standard suggests that in the 'MESSAGE OUT' phase,
! 1362: * the initiator should drop ATN on the last byte of the
! 1363: * message phase after REQ has been asserted for the handshake
! 1364: * but before the initiator raises ACK.
! 1365: */
! 1366: if (!( (ph == PH_MSGOUT) && (cnt > 1) )) {
! 1367: SET_5380_REG(NCR5380_ICOM, SC_ADTB);
! 1368: SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ACK);
! 1369: new_icom = 0;
! 1370: }
! 1371: else {
! 1372: SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ATN);
! 1373: SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ATN|SC_A_ACK);
! 1374: new_icom = SC_A_ATN;
! 1375: }
! 1376: }
! 1377: if (!wait_req_false()) {
! 1378: DBG_PIOPRINT ("SCSI: transfer_pio - REQ not dropping\n", 0, 0);
! 1379: break;
! 1380: }
! 1381: SET_5380_REG(NCR5380_ICOM, new_icom);
! 1382:
! 1383: } while (--cnt);
! 1384:
! 1385: if ((tmp = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
! 1386: *phase = (tmp >> 2) & 7;
! 1387: else *phase = NR_PHASE;
! 1388: *len = cnt;
! 1389: DBG_PIOPRINT ("SCSI: transfer_pio done: phase: %d, len: %d\n",
! 1390: *phase, cnt);
! 1391: PID("tpio2");
! 1392: if (!cnt || (*phase == ph))
! 1393: return (0);
! 1394: return (-1);
! 1395: }
! 1396:
! 1397: #ifdef REAL_DMA
! 1398: /*
! 1399: * Start a DMA-transfer on the device using the current pointers.
! 1400: * If 'poll' is true, the function busy-waits until DMA has completed.
! 1401: */
! 1402: static void
! 1403: transfer_dma(reqp, phase, poll)
! 1404: SC_REQ *reqp;
! 1405: u_int phase;
! 1406: int poll;
! 1407: {
! 1408: int dma_done;
! 1409: u_char mbase = 0;
! 1410: int sps;
! 1411:
! 1412: again:
! 1413: PID("tdma1");
! 1414:
! 1415: /*
! 1416: * We should be in phase, otherwise we are not allowed to
! 1417: * drive the bus.
! 1418: */
! 1419: SET_5380_REG(NCR5380_TCOM, phase);
! 1420:
! 1421: /*
! 1422: * Defer interrupts until DMA is fully running.
! 1423: */
! 1424: sps = splbio();
! 1425:
! 1426: /*
! 1427: * Clear pending interrupts and parity errors.
! 1428: */
! 1429: scsi_clr_ipend();
! 1430:
! 1431: if (!poll) {
! 1432: /*
! 1433: * Enable SCSI interrupts and set IN_DMA flag, set 'mbase'
! 1434: * to the interrupts we want enabled.
! 1435: */
! 1436: scsi_ienable();
! 1437: reqp->dr_flag |= DRIVER_IN_DMA;
! 1438: mbase = SC_E_EOPI | SC_MON_BSY;
! 1439: }
! 1440: else scsi_idisable();
! 1441: mbase |= IMODE_BASE | SC_M_DMA;
! 1442: scsi_dma_setup(reqp, phase, mbase);
! 1443:
! 1444: splx(sps);
! 1445:
! 1446: if (poll) {
! 1447: /*
! 1448: * On polled-dma transfers, we wait here until the
! 1449: * 'end-of-dma' condition occurs.
! 1450: */
! 1451: poll_edma(reqp);
! 1452: if (!(dma_done = dma_ready()))
! 1453: goto again;
! 1454: }
! 1455: PID("tdma2");
! 1456: }
! 1457:
! 1458: /*
! 1459: * Check results of a DMA data-transfer.
! 1460: */
! 1461: static int
! 1462: dma_ready()
! 1463: {
! 1464: SC_REQ *reqp = connected;
! 1465: int dmstat, is_edma;
! 1466: long bytes_left, bytes_done;
! 1467:
! 1468: is_edma = get_dma_result(reqp, &bytes_left);
! 1469: dmstat = GET_5380_REG(NCR5380_DMSTAT);
! 1470:
! 1471: /*
! 1472: * Check if the call is sensible and not caused by any spurious
! 1473: * interrupt.
! 1474: */
! 1475: if (!is_edma && !(dmstat & (SC_END_DMA|SC_BSY_ERR))
! 1476: && (dmstat & SC_PHS_MTCH) ) {
! 1477: ncr_tprint(reqp, "dma_ready: spurious call "
! 1478: "(dm:%x,last_hit: %s)\n",
! 1479: #ifdef DBG_PID
! 1480: dmstat, last_hit[DBG_PID-1]);
! 1481: #else
! 1482: dmstat, "unknown");
! 1483: #endif
! 1484: return (0);
! 1485: }
! 1486:
! 1487: /*
! 1488: * Clear all (pending) interrupts.
! 1489: */
! 1490: scsi_clr_ipend();
! 1491:
! 1492: /*
! 1493: * Update various transfer-pointers/lengths
! 1494: */
! 1495: bytes_done = reqp->dm_cur->dm_count - bytes_left;
! 1496:
! 1497: if ((reqp->dr_flag & DRIVER_BOUNCING) && (PH_IN(reqp->phase))) {
! 1498: /*
! 1499: * Copy the bytes read until now from the bounce buffer
! 1500: * to the 'real' destination. Flush the data-cache
! 1501: * before copying.
! 1502: */
! 1503: PCIA();
! 1504: bcopy(reqp->bouncerp, reqp->xdata_ptr, bytes_done);
! 1505: reqp->bouncerp += bytes_done;
! 1506: }
! 1507:
! 1508: reqp->xdata_ptr = &reqp->xdata_ptr[bytes_done]; /* XXX */
! 1509: reqp->xdata_len -= bytes_done; /* XXX */
! 1510: if ((reqp->dm_cur->dm_count -= bytes_done) == 0)
! 1511: reqp->dm_cur++;
! 1512: else reqp->dm_cur->dm_addr += bytes_done;
! 1513:
! 1514: if (PH_IN(reqp->phase) && (dmstat & SC_PAR_ERR)) {
! 1515: if (!(ncr5380_no_parchk & (1 << reqp->targ_id))) {
! 1516: ncr_tprint(reqp, "parity error in data-phase\n");
! 1517: reqp->xs->error = XS_TIMEOUT;
! 1518: }
! 1519: }
! 1520:
! 1521: /*
! 1522: * DMA mode should always be reset even when we will continue with the
! 1523: * next chain. It is also essential to clear the MON_BUSY because
! 1524: * when LOST_BUSY is unexpectedly set, we will not be able to drive
! 1525: * the bus....
! 1526: */
! 1527: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 1528:
! 1529:
! 1530: if ((dmstat & SC_BSY_ERR) || !(dmstat & SC_PHS_MTCH)
! 1531: || (reqp->dm_cur > reqp->dm_last) || (reqp->xs->error)) {
! 1532:
! 1533: /*
! 1534: * Tell interrupt functions DMA mode has ended.
! 1535: */
! 1536: reqp->dr_flag &= ~DRIVER_IN_DMA;
! 1537:
! 1538: /*
! 1539: * Clear mode and icom
! 1540: */
! 1541: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 1542: SET_5380_REG(NCR5380_ICOM, 0);
! 1543:
! 1544: if (dmstat & SC_BSY_ERR) {
! 1545: if (!reqp->xs->error)
! 1546: reqp->xs->error = XS_TIMEOUT;
! 1547: finish_req(reqp);
! 1548: PID("dma_ready1");
! 1549: return (1);
! 1550: }
! 1551:
! 1552: if (reqp->xs->error != 0) {
! 1553: ncr_tprint(reqp, "dma-ready: code = %d\n", reqp->xs->error); /* LWP */
! 1554: reqp->msgout = MSG_ABORT;
! 1555: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
! 1556: }
! 1557: PID("dma_ready2");
! 1558: return (1);
! 1559: }
! 1560: return (0);
! 1561: }
! 1562: #endif /* REAL_DMA */
! 1563:
! 1564: static int
! 1565: check_autosense(reqp, linked)
! 1566: SC_REQ *reqp;
! 1567: int linked;
! 1568: {
! 1569: int sps;
! 1570:
! 1571: /*
! 1572: * If we not executing an auto-sense and the status code
! 1573: * is request-sense, we automatically issue a request
! 1574: * sense command.
! 1575: */
! 1576: PID("cautos1");
! 1577: if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
! 1578: switch (reqp->status & SCSMASK) {
! 1579: case SCSCHKC:
! 1580: bcopy(sense_cmd, &reqp->xcmd, sizeof(sense_cmd));
! 1581: reqp->xdata_ptr = (u_char *)&reqp->xs->sense;
! 1582: reqp->xdata_len = sizeof(reqp->xs->sense);
! 1583: reqp->dr_flag |= DRIVER_AUTOSEN;
! 1584: reqp->dr_flag &= ~DRIVER_DMAOK;
! 1585: if (!linked) {
! 1586: sps = splbio();
! 1587: reqp->next = issue_q;
! 1588: issue_q = reqp;
! 1589: splx(sps);
! 1590: }
! 1591: else reqp->xcmd.bytes[sizeof(sense_cmd)-2] |= 1;
! 1592:
! 1593: #ifdef DBG_REQ
! 1594: bzero(reqp->xdata_ptr, reqp->xdata_len);
! 1595: if (dbg_target_mask & (1 << reqp->targ_id))
! 1596: show_request(reqp, "AUTO-SENSE");
! 1597: #endif
! 1598: PID("cautos2");
! 1599: return (-1);
! 1600: case SCSBUSY:
! 1601: reqp->xs->error = XS_BUSY;
! 1602: return (0);
! 1603: }
! 1604: }
! 1605: else {
! 1606: /*
! 1607: * An auto-sense has finished
! 1608: */
! 1609: if ((reqp->status & SCSMASK) != SCSGOOD)
! 1610: reqp->xs->error = XS_DRIVER_STUFFUP; /* SC_E_AUTOSEN; */
! 1611: else reqp->xs->error = XS_SENSE;
! 1612: reqp->status = SCSCHKC;
! 1613: }
! 1614: PID("cautos3");
! 1615: return (0);
! 1616: }
! 1617:
! 1618: static int
! 1619: reach_msg_out(sc, len)
! 1620: struct ncr_softc *sc;
! 1621: u_long len;
! 1622: {
! 1623: u_char phase;
! 1624: u_char data;
! 1625: u_long n = len;
! 1626:
! 1627: ncr_aprint(sc, "Trying to reach Message-out phase\n");
! 1628: if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
! 1629: phase = (phase >> 2) & 7;
! 1630: else return (-1);
! 1631: ncr_aprint(sc, "Trying to reach Message-out phase, now: %d\n", phase);
! 1632: if (phase == PH_MSGOUT)
! 1633: return (0);
! 1634:
! 1635: SET_5380_REG(NCR5380_TCOM, phase);
! 1636:
! 1637: do {
! 1638: if (!wait_req_true())
! 1639: break;
! 1640: if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != phase)
! 1641: break;
! 1642: if (PH_IN(phase)) {
! 1643: data = GET_5380_REG(NCR5380_DATA);
! 1644: SET_5380_REG(NCR5380_ICOM, SC_A_ACK | SC_A_ATN);
! 1645: }
! 1646: else {
! 1647: SET_5380_REG(NCR5380_DATA, 0);
! 1648: SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ACK|SC_A_ATN);
! 1649: }
! 1650: if (!wait_req_false())
! 1651: break;
! 1652: SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
! 1653: } while (--n);
! 1654:
! 1655: if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ) {
! 1656: phase = (phase >> 2) & 7;
! 1657: if (phase == PH_MSGOUT) {
! 1658: ncr_aprint(sc, "Message-out phase reached after "
! 1659: "%ld bytes.\n", len - n);
! 1660: return (0);
! 1661: }
! 1662: }
! 1663: return (-1);
! 1664: }
! 1665:
! 1666: void
! 1667: scsi_reset()
! 1668: {
! 1669: SC_REQ *tmp, *next;
! 1670: int sps;
! 1671:
! 1672: PID("scsi_reset1");
! 1673: sps = splbio();
! 1674: SET_5380_REG(NCR5380_ICOM, SC_A_RST);
! 1675: delay(100);
! 1676: SET_5380_REG(NCR5380_ICOM, 0);
! 1677: scsi_clr_ipend();
! 1678:
! 1679: /*
! 1680: * None of the jobs in the discon_q will ever be reconnected,
! 1681: * notify this to the higher level code.
! 1682: */
! 1683: for (tmp = discon_q; tmp ;) {
! 1684: next = tmp->next;
! 1685: tmp->next = NULL;
! 1686: tmp->xs->error = XS_TIMEOUT;
! 1687: busy &= ~(1 << tmp->targ_id);
! 1688: finish_req(tmp);
! 1689: tmp = next;
! 1690: }
! 1691: discon_q = NULL;
! 1692:
! 1693: /*
! 1694: * The current job will never finish either.
! 1695: * The problem is that we can't finish the job because an instance
! 1696: * of main is running on it. Our best guess is that the job is currently
! 1697: * doing REAL-DMA. In that case 'dma_ready()' should correctly finish
! 1698: * the job because it detects BSY-loss.
! 1699: */
! 1700: if ((tmp = connected) != NULL) {
! 1701: if (tmp->dr_flag & DRIVER_IN_DMA) {
! 1702: tmp->xs->error = XS_DRIVER_STUFFUP;
! 1703: #ifdef REAL_DMA
! 1704: dma_ready();
! 1705: #endif
! 1706: }
! 1707: }
! 1708: splx(sps);
! 1709: PID("scsi_reset2");
! 1710:
! 1711: /*
! 1712: * Give the attached devices some time to handle the reset. This
! 1713: * value is arbitrary but should be relatively long.
! 1714: */
! 1715: delay(100000);
! 1716: }
! 1717:
! 1718: static void
! 1719: scsi_reset_verbose(sc, why)
! 1720: struct ncr_softc *sc;
! 1721: const char *why;
! 1722: {
! 1723: ncr_aprint(sc, "Resetting SCSI-bus (%s)\n", why);
! 1724:
! 1725: scsi_reset();
! 1726: }
! 1727:
! 1728: /*
! 1729: * Check validity of the IRQ set by the 5380. If the interrupt is valid,
! 1730: * the appropriate action is carried out (reselection or DMA ready) and
! 1731: * INTR_RESEL or INTR_DMA is returned. Otherwise a console notice is written
! 1732: * and INTR_SPURIOUS is returned.
! 1733: */
! 1734: static int
! 1735: check_intr(sc)
! 1736: struct ncr_softc *sc;
! 1737: {
! 1738: SC_REQ *reqp;
! 1739:
! 1740: if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
! 1741: ==(SC_S_SEL|SC_S_IO))
! 1742: return (INTR_RESEL);
! 1743: else {
! 1744: if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)){
! 1745: reqp->dr_flag &= ~DRIVER_IN_DMA;
! 1746: return (INTR_DMA);
! 1747: }
! 1748: }
! 1749: scsi_clr_ipend();
! 1750: printf("-->");
! 1751: scsi_show();
! 1752: ncr_aprint(sc, "Spurious interrupt.\n");
! 1753: return (INTR_SPURIOUS);
! 1754: }
! 1755:
! 1756: #ifdef REAL_DMA
! 1757: /*
! 1758: * Check if DMA can be used for this request. This function also builds
! 1759: * the dma-chain.
! 1760: */
! 1761: static int
! 1762: scsi_dmaok(reqp)
! 1763: SC_REQ *reqp;
! 1764: {
! 1765: u_long phy_buf;
! 1766: u_long phy_len;
! 1767: void *req_addr;
! 1768: u_long req_len;
! 1769: struct dma_chain *dm;
! 1770:
! 1771: /*
! 1772: * Initialize locals and requests' DMA-chain.
! 1773: */
! 1774: req_len = reqp->xdata_len;
! 1775: req_addr = (void *)reqp->xdata_ptr;
! 1776: dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
! 1777: dm->dm_count = dm->dm_addr = 0;
! 1778: reqp->dr_flag &= ~DRIVER_BOUNCING;
! 1779:
! 1780: /*
! 1781: * Do not accept zero length DMA.
! 1782: */
! 1783: if (req_len == 0)
! 1784: return (0);
! 1785:
! 1786: /*
! 1787: * LWP: I think that this restriction is not strictly necessary.
! 1788: */
! 1789: if ((req_len & 0x1) || ((u_int)req_addr & 0x3))
! 1790: return (0);
! 1791:
! 1792: /*
! 1793: * Build the DMA-chain.
! 1794: */
! 1795: dm->dm_addr = phy_buf = kvtop(req_addr);
! 1796: while (req_len) {
! 1797: if (req_len < (phy_len = NBPG - m68k_page_offset(req_addr)))
! 1798: phy_len = req_len;
! 1799:
! 1800: req_addr += phy_len;
! 1801: req_len -= phy_len;
! 1802: dm->dm_count += phy_len;
! 1803:
! 1804: if (req_len) {
! 1805: u_long tmp = kvtop(req_addr);
! 1806:
! 1807: if ((phy_buf + phy_len) != tmp) {
! 1808: if (wrong_dma_range(reqp, dm)) {
! 1809: if (reqp->dr_flag & DRIVER_BOUNCING)
! 1810: goto bounceit;
! 1811: return (0);
! 1812: }
! 1813:
! 1814: if (++dm >= &reqp->dm_chain[MAXDMAIO]) {
! 1815: ncr_tprint(reqp,"dmaok: DMA chain too long!\n");
! 1816: return (0);
! 1817: }
! 1818: dm->dm_count = 0;
! 1819: dm->dm_addr = tmp;
! 1820: }
! 1821: phy_buf = tmp;
! 1822: }
! 1823: }
! 1824: if (wrong_dma_range(reqp, dm)) {
! 1825: if (reqp->dr_flag & DRIVER_BOUNCING)
! 1826: goto bounceit;
! 1827: return (0);
! 1828: }
! 1829: reqp->dm_last = dm;
! 1830: return (1);
! 1831:
! 1832: bounceit:
! 1833: if ((reqp->bounceb = alloc_bounceb(reqp->xdata_len)) == NULL) {
! 1834: /*
! 1835: * If we can't get a bounce buffer, forget DMA
! 1836: */
! 1837: reqp->dr_flag &= ~DRIVER_BOUNCING;
! 1838: return(0);
! 1839: }
! 1840: /*
! 1841: * Initialize a single DMA-range containing the bounced request
! 1842: */
! 1843: dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
! 1844: dm->dm_addr = kvtop(reqp->bounceb);
! 1845: dm->dm_count = reqp->xdata_len;
! 1846: reqp->bouncerp = reqp->bounceb;
! 1847:
! 1848: return (1);
! 1849: }
! 1850: #endif /* REAL_DMA */
! 1851:
! 1852: static void
! 1853: run_main(sc)
! 1854: struct ncr_softc *sc;
! 1855: {
! 1856: int sps = splbio();
! 1857:
! 1858: if (!main_running) {
! 1859: /*
! 1860: * If shared resources are required, claim them
! 1861: * before entering 'scsi_main'. If we can't get them
! 1862: * now, assume 'run_main' will be called when the resource
! 1863: * becomes available.
! 1864: */
! 1865: if (!claimed_dma()) {
! 1866: splx(sps);
! 1867: return;
! 1868: }
! 1869: main_running = 1;
! 1870: splx(sps);
! 1871: scsi_main(sc);
! 1872: }
! 1873: else splx(sps);
! 1874: }
! 1875:
! 1876: /*
! 1877: * Prefix message with full target info.
! 1878: */
! 1879: static void
! 1880: ncr_tprint(SC_REQ *reqp, char *fmt, ...)
! 1881: {
! 1882: va_list ap;
! 1883:
! 1884: sc_print_addr(reqp->xs->sc_link);
! 1885: va_start(ap, fmt);
! 1886: vprintf(fmt, ap);
! 1887: va_end(ap);
! 1888: }
! 1889:
! 1890: /*
! 1891: * Prefix message with adapter info.
! 1892: */
! 1893: static void
! 1894: ncr_aprint(struct ncr_softc *sc, char *fmt, ...)
! 1895: {
! 1896: va_list ap;
! 1897:
! 1898: printf("%s: ", sc->sc_dev.dv_xname);
! 1899: va_start(ap, fmt);
! 1900: vprintf(fmt, ap);
! 1901: va_end(ap);
! 1902: }
! 1903: /****************************************************************************
! 1904: * Start Debugging Functions *
! 1905: ****************************************************************************/
! 1906: static void
! 1907: show_data_sense(xs)
! 1908: struct scsi_xfer *xs;
! 1909: {
! 1910: u_char *p1, *p2;
! 1911: int i;
! 1912: int sz;
! 1913:
! 1914: p1 = (u_char *) xs->cmd;
! 1915: p2 = (u_char *)&xs->sense;
! 1916: if(*p2 == 0)
! 1917: return; /* No(n)sense */
! 1918: printf("cmd[%d,%d]: ", xs->cmdlen, sz = command_size(*p1));
! 1919: for (i = 0; i < sz; i++)
! 1920: printf("%x ", p1[i]);
! 1921: printf("\nsense: ");
! 1922: for (i = 0; i < sizeof(xs->sense); i++)
! 1923: printf("%x ", p2[i]);
! 1924: printf("\n");
! 1925: }
! 1926:
! 1927: static void
! 1928: show_request(reqp, qtxt)
! 1929: SC_REQ *reqp;
! 1930: char *qtxt;
! 1931: {
! 1932: printf("REQ-%s: %d %p[%ld] cmd[0]=%x S=%x M=%x R=%x resid=%d dr_flag=%x %s\n",
! 1933: qtxt, reqp->targ_id, reqp->xdata_ptr, reqp->xdata_len,
! 1934: reqp->xcmd.opcode, reqp->status, reqp->message,
! 1935: reqp->xs->error, reqp->xs->resid, reqp->dr_flag,
! 1936: reqp->link ? "L":"");
! 1937: if (reqp->status == SCSCHKC)
! 1938: show_data_sense(reqp->xs);
! 1939: }
! 1940:
! 1941: static char *sig_names[] = {
! 1942: "PAR", "SEL", "I/O", "C/D", "MSG", "REQ", "BSY", "RST",
! 1943: "ACK", "ATN", "LBSY", "PMATCH", "IRQ", "EPAR", "DREQ", "EDMA"
! 1944: };
! 1945:
! 1946: static void
! 1947: show_signals(dmstat, idstat)
! 1948: u_char dmstat, idstat;
! 1949: {
! 1950: u_short tmp, mask;
! 1951: int j, need_pipe;
! 1952:
! 1953: tmp = idstat | ((dmstat & 3) << 8);
! 1954: printf("Bus signals (%02x/%02x): ", idstat, dmstat & 3);
! 1955: for (mask = 1, j = need_pipe = 0; mask <= tmp; mask <<= 1, j++) {
! 1956: if (tmp & mask)
! 1957: printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
! 1958: }
! 1959: printf("\nDma status (%02x): ", dmstat);
! 1960: for (mask = 4, j = 10, need_pipe = 0; mask <= dmstat; mask <<= 1, j++) {
! 1961: if (dmstat & mask)
! 1962: printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
! 1963: }
! 1964: printf("\n");
! 1965: }
! 1966:
! 1967: void
! 1968: scsi_show()
! 1969: {
! 1970: SC_REQ *tmp;
! 1971: int sps = splhigh();
! 1972: u_char idstat, dmstat;
! 1973: #ifdef DBG_PID
! 1974: int i;
! 1975: #endif
! 1976:
! 1977: printf("scsi_show: scsi_main is%s running\n",
! 1978: main_running ? "" : " not");
! 1979: for (tmp = issue_q; tmp; tmp = tmp->next)
! 1980: show_request(tmp, "ISSUED");
! 1981: for (tmp = discon_q; tmp; tmp = tmp->next)
! 1982: show_request(tmp, "DISCONNECTED");
! 1983: if (connected)
! 1984: show_request(connected, "CONNECTED");
! 1985: idstat = GET_5380_REG(NCR5380_IDSTAT);
! 1986: dmstat = GET_5380_REG(NCR5380_DMSTAT);
! 1987: show_signals(dmstat, idstat);
! 1988: if (connected)
! 1989: printf("phase = %d, ", connected->phase);
! 1990: printf("busy:%x, spl:%04x\n", busy, sps);
! 1991: #ifdef DBG_PID
! 1992: for (i=0; i<DBG_PID; i++)
! 1993: printf("\t%d\t%s\n", i, last_hit[i]);
! 1994: #endif
! 1995:
! 1996: splx(sps);
! 1997: }
CVSweb