[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     ! 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