[BACK]Return to mac68k5380.c CVS log [TXT][DIR] Up to [local] / sys / arch / mac68k / dev

Annotation of sys/arch/mac68k/dev/mac68k5380.c, Revision 1.1.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