Annotation of sys/arch/mac68k/dev/mac68k5380.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: mac68k5380.c,v 1.22 2006/01/16 21:45:57 miod Exp $ */
! 2: /* $NetBSD: mac68k5380.c,v 1.29 1997/02/28 15:50:50 scottr Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Allen Briggs
! 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 Allen Briggs
! 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: * Derived from atari5380.c for the mac68k port of NetBSD.
! 34: *
! 35: */
! 36:
! 37: #include <sys/param.h>
! 38: #include <sys/systm.h>
! 39: #include <sys/kernel.h>
! 40: #include <sys/device.h>
! 41: #include <sys/syslog.h>
! 42: #include <sys/buf.h>
! 43: #include <scsi/scsi_all.h>
! 44: #include <scsi/scsi_message.h>
! 45: #include <scsi/scsiconf.h>
! 46:
! 47: /*
! 48: * Include the driver definitions
! 49: */
! 50:
! 51: #include <machine/viareg.h>
! 52:
! 53: #include "ncr5380reg.h"
! 54: #include "ncr5380var.h"
! 55:
! 56: /*
! 57: * Set the various driver options
! 58: */
! 59: #define NREQ 18 /* Size of issue queue */
! 60: #define AUTO_SENSE 1 /* Automatically issue a request-sense */
! 61:
! 62: #define DRNAME ncrscsi /* used in various prints */
! 63: #undef DBG_SEL /* Show the selection process */
! 64: #undef DBG_REQ /* Show enqueued/ready requests */
! 65: #undef DBG_NOWRITE /* Do not allow writes to the targets */
! 66: #undef DBG_PIO /* Show the polled-I/O process */
! 67: #undef DBG_INF /* Show information transfer process */
! 68: #define DBG_NOSTATIC /* No static functions, all in DDB trace*/
! 69: #define DBG_PID 25 /* Keep track of driver */
! 70: #ifdef DBG_NOSTATIC
! 71: # define static
! 72: #endif
! 73: #ifdef DBG_SEL
! 74: # define DBG_SELPRINT(a,b) printf(a,b)
! 75: #else
! 76: # define DBG_SELPRINT(a,b)
! 77: #endif
! 78: #ifdef DBG_PIO
! 79: # define DBG_PIOPRINT(a,b,c) printf(a,b,c)
! 80: #else
! 81: # define DBG_PIOPRINT(a,b,c)
! 82: #endif
! 83: #ifdef DBG_INF
! 84: # define DBG_INFPRINT(a,b,c) a(b,c)
! 85: #else
! 86: # define DBG_INFPRINT(a,b,c)
! 87: #endif
! 88: #ifdef DBG_PID
! 89: /* static char *last_hit = NULL, *olast_hit = NULL; */
! 90: static char *last_hit[DBG_PID];
! 91: # define PID(a) \
! 92: { int i; \
! 93: for (i=0; i < DBG_PID-1; i++) \
! 94: last_hit[i] = last_hit[i + 1]; \
! 95: last_hit[DBG_PID - 1] = a; }
! 96: #else
! 97: # define PID(a)
! 98: #endif
! 99:
! 100: #undef REAL_DMA /* Use DMA if sensible */
! 101: #define scsi_ipending() (GET_5380_REG(NCR5380_DMSTAT) & SC_IRQ_SET)
! 102: #define fair_to_keep_dma() 1
! 103: #define claimed_dma() 1
! 104: #define reconsider_dma()
! 105: #define USE_PDMA 1 /* Use special pdma-transfer function */
! 106: #define MIN_PHYS 0x2000 /* pdma space w/ /DSACK is only 0x2000 */
! 107:
! 108: #define ENABLE_NCR5380(sc) cur_softc = sc;
! 109:
! 110: /*
! 111: * softc of currently active controller (well, we only have one for now).
! 112: */
! 113:
! 114: static struct ncr_softc *cur_softc;
! 115:
! 116: struct scsi_5380 {
! 117: volatile u_char scsi_5380[8*16]; /* 8 regs, 1 every 16th byte. */
! 118: };
! 119:
! 120: extern vaddr_t SCSIBase;
! 121: static volatile u_char *ncr = (volatile u_char *) 0x10000;
! 122: static volatile u_char *ncr_5380_with_drq = (volatile u_char *) 0x6000;
! 123: static volatile u_char *ncr_5380_without_drq = (volatile u_char *) 0x12000;
! 124:
! 125: #define SCSI_5380 ((struct scsi_5380 *) ncr)
! 126: #define GET_5380_REG(rnum) SCSI_5380->scsi_5380[((rnum)<<4)]
! 127: #define SET_5380_REG(rnum,val) (SCSI_5380->scsi_5380[((rnum)<<4)] = (val))
! 128:
! 129: static int ncr5380_irq_intr(void *);
! 130: static int ncr5380_drq_intr(void *);
! 131: static void do_ncr5380_drq_intr(void *);
! 132:
! 133: static __inline__ void scsi_clr_ipend(void);
! 134: static void scsi_mach_init(struct ncr_softc *sc);
! 135: static int machine_match(struct device *parent,
! 136: struct cfdata *cf, void *aux,
! 137: struct cfdriver *cd);
! 138: static __inline__ int pdma_ready(void);
! 139: static int transfer_pdma(u_char *phasep, u_char *data,
! 140: u_long *count);
! 141:
! 142: static __inline__ void
! 143: scsi_clr_ipend(void)
! 144: {
! 145: int tmp;
! 146:
! 147: tmp = GET_5380_REG(NCR5380_IRCV);
! 148: scsi_clear_irq();
! 149: }
! 150:
! 151: static void
! 152: scsi_mach_init(sc)
! 153: struct ncr_softc *sc;
! 154: {
! 155: static int initted = 0;
! 156:
! 157: if (initted++)
! 158: panic("scsi_mach_init called again.");
! 159:
! 160: ncr = (volatile u_char *)
! 161: (SCSIBase + (u_long) ncr);
! 162: ncr_5380_with_drq = (volatile u_char *)
! 163: (SCSIBase + (u_int) ncr_5380_with_drq);
! 164: ncr_5380_without_drq = (volatile u_char *)
! 165: (SCSIBase + (u_int) ncr_5380_without_drq);
! 166:
! 167: if (VIA2 == VIA2OFF) {
! 168: scsi_enable = Via1Base + VIA2 * 0x2000 + vIER;
! 169: scsi_flag = Via1Base + VIA2 * 0x2000 + vIFR;
! 170: } else {
! 171: scsi_enable = Via1Base + VIA2 * 0x2000 + rIER;
! 172: scsi_flag = Via1Base + VIA2 * 0x2000 + rIFR;
! 173: }
! 174:
! 175: sc->sc_ih_irq.vh_fn = ncr5380_irq_intr;
! 176: sc->sc_ih_irq.vh_arg = sc;
! 177: sc->sc_ih_irq.vh_ipl = VIA2_SCSIIRQ;
! 178: via2_register_irq(&sc->sc_ih_irq, sc->sc_dev.dv_xname);
! 179: sc->sc_ih_drq.vh_fn = ncr5380_drq_intr;
! 180: sc->sc_ih_drq.vh_arg = sc;
! 181: sc->sc_ih_drq.vh_ipl = VIA2_SCSIDRQ;
! 182: via2_register_irq(&sc->sc_ih_drq, sc->sc_dev.dv_xname);
! 183: }
! 184:
! 185: static int
! 186: machine_match(parent, cf, aux, cd)
! 187: struct device *parent;
! 188: struct cfdata *cf;
! 189: void *aux;
! 190: struct cfdriver *cd;
! 191: {
! 192: if (!mac68k_machine.scsi80)
! 193: return 0;
! 194: return 1;
! 195: }
! 196:
! 197: #if USE_PDMA
! 198: int pdma_5380_dir = 0;
! 199:
! 200: u_char *pending_5380_data;
! 201: u_long pending_5380_count;
! 202:
! 203: #define NCR5380_PDMA_DEBUG 1 /* Maybe we try with this off eventually. */
! 204:
! 205: #if NCR5380_PDMA_DEBUG
! 206: int pdma_5380_sends = 0;
! 207: int pdma_5380_bytes = 0;
! 208:
! 209: void
! 210: pdma_stat(void)
! 211: {
! 212: printf("PDMA SCSI: %d xfers completed for %d bytes.\n",
! 213: pdma_5380_sends, pdma_5380_bytes);
! 214: printf("pdma_5380_dir = %d\t",
! 215: pdma_5380_dir);
! 216: printf("datap = %p, remainder = %ld.\n",
! 217: pending_5380_data, pending_5380_count);
! 218: scsi_show();
! 219: }
! 220: #endif
! 221:
! 222: void
! 223: pdma_cleanup(void)
! 224: {
! 225: SC_REQ *reqp = connected;
! 226: int s;
! 227:
! 228: s = splbio();
! 229: PID("pdma_cleanup0");
! 230:
! 231: pdma_5380_dir = 0;
! 232:
! 233: #if NCR5380_PDMA_DEBUG
! 234: pdma_5380_sends++;
! 235: pdma_5380_bytes+=(reqp->xdata_len - pending_5380_count);
! 236: #endif
! 237:
! 238: /*
! 239: * Update pointers.
! 240: */
! 241: reqp->xdata_ptr += reqp->xdata_len - pending_5380_count;
! 242: reqp->xdata_len = pending_5380_count;
! 243:
! 244: /*
! 245: * Reset DMA mode.
! 246: */
! 247: SET_5380_REG(NCR5380_MODE, GET_5380_REG(NCR5380_MODE) & ~SC_M_DMA);
! 248:
! 249: /*
! 250: * Clear any pending interrupts.
! 251: */
! 252: scsi_clr_ipend();
! 253:
! 254: /*
! 255: * Tell interrupt functions that DMA has ended.
! 256: */
! 257: reqp->dr_flag &= ~DRIVER_IN_DMA;
! 258:
! 259: SET_5380_REG(NCR5380_MODE, IMODE_BASE);
! 260: SET_5380_REG(NCR5380_ICOM, 0);
! 261:
! 262: splx(s);
! 263:
! 264: /*
! 265: * Back for more punishment.
! 266: */
! 267: PID("pdma_cleanup1");
! 268: run_main(cur_softc);
! 269: PID("pdma_cleanup2");
! 270: }
! 271: #endif
! 272:
! 273: static __inline__ int
! 274: pdma_ready(void)
! 275: {
! 276: #if USE_PDMA
! 277: SC_REQ *reqp = connected;
! 278: int dmstat, idstat;
! 279: extern u_char ncr5380_no_parchk;
! 280:
! 281: PID("pdma_ready0");
! 282: if (pdma_5380_dir) {
! 283: PID("pdma_ready1.");
! 284: /*
! 285: * For a phase mis-match, ATN is a "don't care," IRQ is 1 and
! 286: * all other bits in the Bus & Status Register are 0. Also,
! 287: * the current SCSI Bus Status Register has a 1 for BSY and
! 288: * REQ. Since we're just checking that this interrupt isn't a
! 289: * reselection or a reset, we just check for either.
! 290: */
! 291: dmstat = GET_5380_REG(NCR5380_DMSTAT);
! 292: idstat = GET_5380_REG(NCR5380_IDSTAT);
! 293: if ( ((dmstat & (0xff & ~SC_ATN_STAT)) == SC_IRQ_SET)
! 294: && ((idstat & (SC_S_BSY|SC_S_REQ))
! 295: == (SC_S_BSY | SC_S_REQ)) ) {
! 296: PID("pdma_ready2");
! 297: pdma_cleanup();
! 298: return 1;
! 299: } else if (PH_IN(reqp->phase) && (dmstat & SC_PAR_ERR)) {
! 300: if (!(ncr5380_no_parchk & (1 << reqp->targ_id)))
! 301: /* XXX: Should be parity error ???? */
! 302: reqp->xs->error = XS_DRIVER_STUFFUP;
! 303: PID("pdma_ready3");
! 304: /* XXX: is this the right reaction? */
! 305: pdma_cleanup();
! 306: return 1;
! 307: } else if ( !(idstat & SC_S_REQ)
! 308: || (((idstat>>2) & 7) != reqp->phase)) {
! 309: #ifdef DIAGNOSTIC
! 310: /* XXX: is this the right reaction? Can this happen? */
! 311: scsi_show();
! 312: printf("Unexpected phase change.\n");
! 313: #endif
! 314: reqp->xs->error = XS_DRIVER_STUFFUP;
! 315: pdma_cleanup();
! 316: return 1;
! 317: } else {
! 318: scsi_show();
! 319: panic("Spurious interrupt during PDMA xfer.");
! 320: }
! 321: } else
! 322: PID("pdma_ready4");
! 323: #endif
! 324: return 0;
! 325: }
! 326:
! 327: static int
! 328: ncr5380_irq_intr(p)
! 329: void *p;
! 330: {
! 331: PID("irq");
! 332:
! 333: #if USE_PDMA
! 334: if (pdma_ready()) {
! 335: return (1);
! 336: }
! 337: #endif
! 338: scsi_idisable();
! 339: ncr_ctrl_intr(cur_softc);
! 340: return (1);
! 341: }
! 342:
! 343: /*
! 344: * This is the meat of the PDMA transfer.
! 345: * When we get here, we shove data as fast as the mac can take it.
! 346: * We depend on several things:
! 347: * * All macs after the Mac Plus that have a 5380 chip should have a general
! 348: * logic IC that handshakes data for blind transfers.
! 349: * * If the SCSI controller finishes sending/receiving data before we do,
! 350: * the same general logic IC will generate a /BERR for us in short order.
! 351: * * The fault address for said /BERR minus the base address for the
! 352: * transfer will be the amount of data that was actually written.
! 353: *
! 354: * We use the nofault flag and the setjmp/longjmp in locore.s so we can
! 355: * detect and handle the bus error for early termination of a command.
! 356: * This is usually caused by a disconnecting target.
! 357: */
! 358: static void
! 359: do_ncr5380_drq_intr(p)
! 360: void *p;
! 361: {
! 362: #if USE_PDMA
! 363: extern int *nofault, m68k_fault_addr;
! 364: label_t faultbuf;
! 365: register int count;
! 366: volatile u_int32_t *long_drq;
! 367: u_int32_t *long_data;
! 368: volatile u_int8_t *drq, tmp_data;
! 369: u_int8_t *data;
! 370:
! 371: #if DBG_PID
! 372: if (pdma_5380_dir == 2) {
! 373: PID("drq (in)");
! 374: } else {
! 375: PID("drq (out)");
! 376: }
! 377: #endif
! 378:
! 379: /*
! 380: * Setup for a possible bus error caused by SCSI controller
! 381: * switching out of DATA-IN/OUT before we're done with the
! 382: * current transfer.
! 383: */
! 384: nofault = (int *) &faultbuf;
! 385:
! 386: if (setjmp((label_t *) nofault)) {
! 387: PID("drq berr");
! 388: nofault = (int *) 0;
! 389: count = ( (u_long) m68k_fault_addr
! 390: - (u_long) ncr_5380_with_drq);
! 391: if ((count < 0) || (count > pending_5380_count)) {
! 392: printf("pdma %s: cnt = %d (0x%x) (pending cnt %ld)\n",
! 393: (pdma_5380_dir == 2) ? "in" : "out",
! 394: count, count, pending_5380_count);
! 395: panic("something is wrong");
! 396: }
! 397:
! 398: pending_5380_data += count;
! 399: pending_5380_count -= count;
! 400:
! 401: m68k_fault_addr = 0;
! 402:
! 403: PID("end drq early");
! 404:
! 405: return;
! 406: }
! 407:
! 408: if (pdma_5380_dir == 2) { /* Data In */
! 409: int resid;
! 410:
! 411: /*
! 412: * Get the dest address aligned.
! 413: */
! 414: resid = count = min(pending_5380_count,
! 415: 4 - (((int) pending_5380_data) & 0x3));
! 416: if (count && (count < 4)) {
! 417: data = (u_int8_t *) pending_5380_data;
! 418: drq = (u_int8_t *) ncr_5380_with_drq;
! 419: while (count) {
! 420: #define R1 *data++ = *drq++
! 421: R1; count--;
! 422: #undef R1
! 423: }
! 424: pending_5380_data += resid;
! 425: pending_5380_count -= resid;
! 426: }
! 427:
! 428: /*
! 429: * Get ready to start the transfer.
! 430: */
! 431: while (pending_5380_count) {
! 432: int dcount;
! 433:
! 434: dcount = count = min(pending_5380_count, MIN_PHYS);
! 435: long_drq = (volatile u_int32_t *) ncr_5380_with_drq;
! 436: long_data = (u_int32_t *) pending_5380_data;
! 437:
! 438: #define R4 *long_data++ = *long_drq++
! 439: while ( count > 64 ) {
! 440: R4; R4; R4; R4; R4; R4; R4; R4;
! 441: R4; R4; R4; R4; R4; R4; R4; R4; /* 64 */
! 442: count -= 64;
! 443: }
! 444: while (count > 8) {
! 445: R4; R4; count -= 8;
! 446: }
! 447: #undef R4
! 448: data = (u_int8_t *) long_data;
! 449: drq = (u_int8_t *) long_drq;
! 450: while (count) {
! 451: #define R1 *data++ = *drq++
! 452: R1; count--;
! 453: #undef R1
! 454: }
! 455: pending_5380_count -= dcount;
! 456: pending_5380_data += dcount;
! 457: }
! 458: } else {
! 459: int resid;
! 460:
! 461: /*
! 462: * Get the source address aligned.
! 463: */
! 464: resid = count = min(pending_5380_count,
! 465: 4 - (((int) pending_5380_data) & 0x3));
! 466: if (count && (count < 4)) {
! 467: data = (u_int8_t *) pending_5380_data;
! 468: drq = (u_int8_t *) ncr_5380_with_drq;
! 469: while (count) {
! 470: #define W1 *drq++ = *data++
! 471: W1; count--;
! 472: #undef W1
! 473: }
! 474: pending_5380_data += resid;
! 475: pending_5380_count -= resid;
! 476: }
! 477:
! 478: /*
! 479: * Get ready to start the transfer.
! 480: */
! 481: while (pending_5380_count) {
! 482: int dcount;
! 483:
! 484: dcount = count = min(pending_5380_count, MIN_PHYS);
! 485: long_drq = (volatile u_int32_t *) ncr_5380_with_drq;
! 486: long_data = (u_int32_t *) pending_5380_data;
! 487:
! 488: #define W4 *long_drq++ = *long_data++
! 489: while ( count > 64 ) {
! 490: W4; W4; W4; W4; W4; W4; W4; W4;
! 491: W4; W4; W4; W4; W4; W4; W4; W4; /* 64 */
! 492: count -= 64;
! 493: }
! 494: while ( count > 8 ) {
! 495: W4; W4;
! 496: count -= 8;
! 497: }
! 498: #undef W4
! 499: data = (u_int8_t *) long_data;
! 500: drq = (u_int8_t *) long_drq;
! 501: while (count) {
! 502: #define W1 *drq++ = *data++
! 503: W1; count--;
! 504: #undef W1
! 505: }
! 506: pending_5380_count -= dcount;
! 507: pending_5380_data += dcount;
! 508: }
! 509:
! 510: PID("write complete");
! 511:
! 512: drq = (volatile u_int8_t *) ncr_5380_with_drq;
! 513: tmp_data = *drq;
! 514:
! 515: PID("read a byte to force a phase change");
! 516: }
! 517:
! 518: /*
! 519: * OK. No bus error occurred above. Clear the nofault flag
! 520: * so we no longer short-circuit bus errors.
! 521: */
! 522: nofault = (int *) 0;
! 523:
! 524: PID("end drq");
! 525: #endif /* if USE_PDMA */
! 526: }
! 527:
! 528: static int
! 529: ncr5380_drq_intr(p)
! 530: void *p;
! 531: {
! 532: int rv = 0;
! 533:
! 534: while (GET_5380_REG(NCR5380_DMSTAT) & SC_DMA_REQ) {
! 535: do_ncr5380_drq_intr(p);
! 536: scsi_clear_drq();
! 537: rv = 1;
! 538: }
! 539:
! 540: return (rv);
! 541: }
! 542:
! 543: #if USE_PDMA
! 544:
! 545: #define SCSI_TIMEOUT_VAL 10000000
! 546:
! 547: static int
! 548: transfer_pdma(phasep, data, count)
! 549: u_char *phasep;
! 550: u_char *data;
! 551: u_long *count;
! 552: {
! 553: SC_REQ *reqp = connected;
! 554: int len = *count, s, scsi_timeout = SCSI_TIMEOUT_VAL;
! 555:
! 556: if (pdma_5380_dir) {
! 557: panic("ncrscsi: transfer_pdma called when operation already "
! 558: "pending.");
! 559: }
! 560: PID("transfer_pdma0")
! 561:
! 562: /*
! 563: * Don't bother with PDMA if we can't sleep or for small transfers.
! 564: */
! 565: if (reqp->dr_flag & DRIVER_NOINT) {
! 566: PID("pdma, falling back to transfer_pio.")
! 567: transfer_pio(phasep, data, count, 0);
! 568: return -1;
! 569: }
! 570:
! 571: /*
! 572: * We are probably already at spl2(), so this is likely a no-op.
! 573: * Paranoia.
! 574: */
! 575: s = splbio();
! 576:
! 577: scsi_idisable();
! 578:
! 579: /*
! 580: * Match phases with target.
! 581: */
! 582: SET_5380_REG(NCR5380_TCOM, *phasep);
! 583:
! 584: /*
! 585: * Clear pending interrupts.
! 586: */
! 587: scsi_clr_ipend();
! 588:
! 589: /*
! 590: * Wait until target asserts BSY.
! 591: */
! 592: while ( ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) == 0)
! 593: && (--scsi_timeout) );
! 594: if (!scsi_timeout) {
! 595: #ifdef DIAGNOSTIC
! 596: printf("scsi timeout: waiting for BSY in %s.\n",
! 597: (*phasep == PH_DATAOUT) ? "pdma_out" : "pdma_in");
! 598: #endif
! 599: goto scsi_timeout_error;
! 600: }
! 601:
! 602: /*
! 603: * Tell the driver that we're in DMA mode.
! 604: */
! 605: reqp->dr_flag |= DRIVER_IN_DMA;
! 606:
! 607: /*
! 608: * Load transfer values for DRQ interrupt handlers.
! 609: */
! 610: pending_5380_data = data;
! 611: pending_5380_count = len;
! 612:
! 613: /*
! 614: * Set the transfer function to be called on DRQ interrupts.
! 615: * And note that we're waiting.
! 616: */
! 617: switch (*phasep) {
! 618: default:
! 619: panic("Unexpected phase in transfer_pdma.");
! 620: case PH_DATAOUT:
! 621: pdma_5380_dir = 1;
! 622: SET_5380_REG(NCR5380_ICOM, GET_5380_REG(NCR5380_ICOM)|SC_ADTB);
! 623: SET_5380_REG(NCR5380_MODE, GET_5380_REG(NCR5380_MODE)|SC_M_DMA);
! 624: SET_5380_REG(NCR5380_DMSTAT, 0);
! 625: break;
! 626: case PH_DATAIN:
! 627: pdma_5380_dir = 2;
! 628: SET_5380_REG(NCR5380_ICOM, 0);
! 629: SET_5380_REG(NCR5380_MODE, GET_5380_REG(NCR5380_MODE)|SC_M_DMA);
! 630: SET_5380_REG(NCR5380_IRCV, 0);
! 631: break;
! 632: }
! 633:
! 634: PID("waiting for interrupt.")
! 635:
! 636: /*
! 637: * Now that we're set up, enable interrupts and drop processor
! 638: * priority back down.
! 639: */
! 640: scsi_ienable();
! 641: splx(s);
! 642: return 0;
! 643:
! 644: scsi_timeout_error:
! 645: /*
! 646: * Clear the DMA mode.
! 647: */
! 648: SET_5380_REG(NCR5380_MODE, GET_5380_REG(NCR5380_MODE) & ~SC_M_DMA);
! 649: splx(s);
! 650: return -1;
! 651: }
! 652: #endif /* if USE_PDMA */
! 653:
! 654: /* Include general routines. */
! 655: #include <mac68k/dev/ncr5380.c>
CVSweb