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

Annotation of sys/arch/mac68k/dev/sbc.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: sbc.c,v 1.16 2006/12/13 21:12:56 miod Exp $   */
        !             2: /*     $NetBSD: sbc.c,v 1.24 1997/04/18 17:38:08 scottr Exp $  */
        !             3:
        !             4: /*
        !             5:  * Copyright (C) 1996 Scott Reynolds.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *      This product includes software developed by Scott Reynolds for
        !            18:  *      the NetBSD Project.
        !            19:  * 4. The name of the author may not be used to endorse or promote products
        !            20:  *    derived from this software without specific prior written permission
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: /*
        !            35:  * This file contains only the machine-dependent parts of the mac68k
        !            36:  * NCR 5380 SCSI driver.  (Autoconfig stuff and PDMA functions.)
        !            37:  * The machine-independent parts are in ncr5380sbc.c
        !            38:  *
        !            39:  * Supported hardware includes:
        !            40:  * Macintosh II family 5380-based controller
        !            41:  *
        !            42:  * Credits, history:
        !            43:  *
        !            44:  * Scott Reynolds wrote this module, based on work by Allen Briggs
        !            45:  * (mac68k), Gordon W. Ross and David Jones (sun3), and Leo Weppelman
        !            46:  * (atari).  Thanks to Allen for supplying crucial interpretation of the
        !            47:  * NetBSD/mac68k 1.1 'ncrscsi' driver.  Also, Allen, Gordon, and Jason
        !            48:  * Thorpe all helped to refine this code, and were considerable sources
        !            49:  * of moral support.
        !            50:  */
        !            51:
        !            52: #include <sys/types.h>
        !            53: #include <sys/param.h>
        !            54: #include <sys/systm.h>
        !            55: #include <sys/kernel.h>
        !            56: #include <sys/errno.h>
        !            57: #include <sys/device.h>
        !            58: #include <sys/buf.h>
        !            59: #include <sys/proc.h>
        !            60: #include <sys/user.h>
        !            61:
        !            62: #include <scsi/scsi_all.h>
        !            63: #include <scsi/scsi_debug.h>
        !            64: #include <scsi/scsiconf.h>
        !            65:
        !            66: #include <dev/ic/ncr5380reg.h>
        !            67: #include <dev/ic/ncr5380var.h>
        !            68:
        !            69: #include <machine/cpu.h>
        !            70: #include <machine/viareg.h>
        !            71:
        !            72: #include "sbcreg.h"
        !            73: #include "sbcvar.h"
        !            74:
        !            75: int    sbc_debug = 0 /* | SBC_DB_INTR | SBC_DB_DMA */;
        !            76: int    sbc_link_flags = 0 /* | SDEV_DB2 */;
        !            77: int    sbc_options = 0 /* | SBC_PDMA */;
        !            78:
        !            79: static void    sbc_minphys(struct buf *bp);
        !            80:
        !            81: struct scsi_adapter    sbc_ops = {
        !            82:        ncr5380_scsi_cmd,               /* scsi_cmd()           */
        !            83:        sbc_minphys,                    /* scsi_minphys()       */
        !            84:        NULL,                           /* open_target_lu()     */
        !            85:        NULL,                           /* close_target_lu()    */
        !            86: };
        !            87:
        !            88: /* This is copied from julian's bt driver */
        !            89: /* "so we have a default dev struct for our link struct." */
        !            90: struct scsi_device sbc_dev = {
        !            91:        NULL,           /* Use default error handler.       */
        !            92:        NULL,           /* Use default start handler.           */
        !            93:        NULL,           /* Use default async handler.       */
        !            94:        NULL,           /* Use default "done" routine.      */
        !            95: };
        !            96:
        !            97: struct cfdriver sbc_cd = {
        !            98:        NULL, "sbc", DV_DULL
        !            99: };
        !           100:
        !           101: static int     sbc_ready(struct ncr5380_softc *);
        !           102: static void    sbc_wait_not_req(struct ncr5380_softc *);
        !           103:
        !           104: static void
        !           105: sbc_minphys(struct buf *bp)
        !           106: {
        !           107:        if (bp->b_bcount > MAX_DMA_LEN)
        !           108:                bp->b_bcount = MAX_DMA_LEN;
        !           109:        return (minphys(bp));
        !           110: }
        !           111:
        !           112:
        !           113: /***
        !           114:  * General support for Mac-specific SCSI logic.
        !           115:  ***/
        !           116:
        !           117: int
        !           118: sbc_irq_intr(p)
        !           119:        void *p;
        !           120: {
        !           121:        struct ncr5380_softc *ncr_sc = p;
        !           122:        int claimed = 0;
        !           123:
        !           124:        /* How we ever arrive here without IRQ set is a mystery... */
        !           125:        if (*ncr_sc->sci_csr & SCI_CSR_INT) {
        !           126: #ifdef SBC_DEBUG
        !           127:                if (sbc_debug & SBC_DB_INTR)
        !           128:                        decode_5380_intr(ncr_sc);
        !           129: #endif
        !           130:                claimed = ncr5380_intr(ncr_sc);
        !           131:                if (!claimed) {
        !           132:                        if (((*ncr_sc->sci_csr & ~SCI_CSR_PHASE_MATCH) == SCI_CSR_INT)
        !           133:                            && ((*ncr_sc->sci_bus_csr & ~SCI_BUS_RST) == 0))
        !           134:                                SCI_CLR_INTR(ncr_sc);   /* RST interrupt */
        !           135: #ifdef SBC_DEBUG
        !           136:                        else {
        !           137:                                printf("%s: spurious intr\n",
        !           138:                                    ncr_sc->sc_dev.dv_xname);
        !           139:                                SBC_BREAK;
        !           140:                        }
        !           141: #endif
        !           142:                }
        !           143:        }
        !           144:
        !           145:        return (claimed);
        !           146: }
        !           147:
        !           148: #ifdef SBC_DEBUG
        !           149: void
        !           150: decode_5380_intr(ncr_sc)
        !           151:        struct ncr5380_softc *ncr_sc;
        !           152: {
        !           153:        u_char csr = *ncr_sc->sci_csr;
        !           154:        u_char bus_csr = *ncr_sc->sci_bus_csr;
        !           155:
        !           156:        if (((csr & ~(SCI_CSR_PHASE_MATCH | SCI_CSR_ATN)) == SCI_CSR_INT) &&
        !           157:            ((bus_csr & ~(SCI_BUS_MSG | SCI_BUS_CD | SCI_BUS_IO | SCI_BUS_DBP)) == SCI_BUS_SEL)) {
        !           158:                if (csr & SCI_BUS_IO)
        !           159:                        printf("%s: reselect\n", ncr_sc->sc_dev.dv_xname);
        !           160:                else
        !           161:                        printf("%s: select\n", ncr_sc->sc_dev.dv_xname);
        !           162:        } else if (((csr & ~SCI_CSR_ACK) == (SCI_CSR_DONE | SCI_CSR_INT)) &&
        !           163:            ((bus_csr & (SCI_BUS_RST | SCI_BUS_BSY | SCI_BUS_SEL)) == SCI_BUS_BSY))
        !           164:                printf("%s: dma eop\n", ncr_sc->sc_dev.dv_xname);
        !           165:        else if (((csr & ~SCI_CSR_PHASE_MATCH) == SCI_CSR_INT) &&
        !           166:            ((bus_csr & ~SCI_BUS_RST) == 0))
        !           167:                printf("%s: bus reset\n", ncr_sc->sc_dev.dv_xname);
        !           168:        else if (((csr & ~(SCI_CSR_DREQ | SCI_CSR_ATN | SCI_CSR_ACK)) == (SCI_CSR_PERR | SCI_CSR_INT | SCI_CSR_PHASE_MATCH)) &&
        !           169:            ((bus_csr & (SCI_BUS_RST | SCI_BUS_BSY | SCI_BUS_SEL)) == SCI_BUS_BSY))
        !           170:                printf("%s: parity error\n", ncr_sc->sc_dev.dv_xname);
        !           171:        else if (((csr & ~SCI_CSR_ATN) == SCI_CSR_INT) &&
        !           172:            ((bus_csr & (SCI_BUS_RST | SCI_BUS_BSY | SCI_BUS_REQ | SCI_BUS_SEL)) == (SCI_BUS_BSY | SCI_BUS_REQ)))
        !           173:                printf("%s: phase mismatch\n", ncr_sc->sc_dev.dv_xname);
        !           174:        else if (((csr & ~SCI_CSR_PHASE_MATCH) == (SCI_CSR_INT | SCI_CSR_DISC)) &&
        !           175:            (bus_csr == 0))
        !           176:                printf("%s: disconnect\n", ncr_sc->sc_dev.dv_xname);
        !           177:        else
        !           178:                printf("%s: unknown intr: csr=%x, bus_csr=%x\n",
        !           179:                    ncr_sc->sc_dev.dv_xname, csr, bus_csr);
        !           180: }
        !           181: #endif
        !           182:
        !           183:
        !           184: /***
        !           185:  * The following code implements polled PDMA.
        !           186:  ***/
        !           187:
        !           188: #define        TIMEOUT 5000000                 /* x 2 usec = 10 sec */
        !           189:
        !           190: static __inline__ int
        !           191: sbc_ready(sc)
        !           192:        struct ncr5380_softc *sc;
        !           193: {
        !           194:        int i = TIMEOUT;
        !           195:
        !           196:        for (;;) {
        !           197:                if ((*sc->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) ==
        !           198:                    (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
        !           199:                        return 1;
        !           200:                if (((*sc->sci_csr & SCI_CSR_PHASE_MATCH) == 0) ||
        !           201:                    (SCI_BUSY(sc) == 0))
        !           202:                        return 0;
        !           203:                if (--i < 0)
        !           204:                        break;
        !           205:                delay(2);
        !           206:        }
        !           207:
        !           208:        printf("%s: ready timeout\n", sc->sc_dev.dv_xname);
        !           209:        return 0;
        !           210: }
        !           211:
        !           212: static __inline__ void
        !           213: sbc_wait_not_req(sc)
        !           214:        struct ncr5380_softc *sc;
        !           215: {
        !           216:        int i = TIMEOUT;
        !           217:
        !           218:        for (;;) {
        !           219:                if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0 ||
        !           220:                    (*sc->sci_csr & SCI_CSR_PHASE_MATCH) == 0 ||
        !           221:                    SCI_BUSY(sc) == 0) {
        !           222:                        return;
        !           223:                }
        !           224:                if (--i < 0)
        !           225:                        break;
        !           226:                delay(2);
        !           227:        }
        !           228:        printf("%s: pdma not_req timeout\n", sc->sc_dev.dv_xname);
        !           229: }
        !           230:
        !           231: int
        !           232: sbc_pdma_in(ncr_sc, phase, datalen, data)
        !           233:        struct ncr5380_softc *ncr_sc;
        !           234:        int phase, datalen;
        !           235:        u_char *data;
        !           236: {
        !           237:        struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
        !           238:        volatile u_int32_t *long_data = (u_int32_t *)sc->sc_drq_addr;
        !           239:        volatile u_int8_t *byte_data = (u_int8_t *)sc->sc_nodrq_addr;
        !           240:        int resid, s;
        !           241:
        !           242:        s = splbio();
        !           243:        *ncr_sc->sci_mode |= SCI_MODE_DMA;
        !           244:        *ncr_sc->sci_irecv = 0;
        !           245:
        !           246: #define R4     *((u_int32_t *)data)++ = *long_data++
        !           247: #define R1     *data++ = *byte_data++
        !           248:        for (resid = datalen; resid >= 128; resid -= 128) {
        !           249:                if (sbc_ready(ncr_sc) == 0)
        !           250:                        goto interrupt;
        !           251:                R4; R4; R4; R4; R4; R4; R4; R4;
        !           252:                R4; R4; R4; R4; R4; R4; R4; R4;
        !           253:                R4; R4; R4; R4; R4; R4; R4; R4;
        !           254:                R4; R4; R4; R4; R4; R4; R4; R4;
        !           255:
        !           256:                long_data = (u_int32_t *)sc->sc_drq_addr;
        !           257:                byte_data = (u_int8_t *)sc->sc_nodrq_addr;
        !           258:        }
        !           259:        while (resid) {
        !           260:                if (sbc_ready(ncr_sc) == 0)
        !           261:                        goto interrupt;
        !           262:                R1;
        !           263:                resid--;
        !           264:        }
        !           265: #undef R4
        !           266: #undef R1
        !           267:
        !           268:        sbc_wait_not_req(ncr_sc);
        !           269: interrupt:
        !           270:        SCI_CLR_INTR(ncr_sc);
        !           271:        *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
        !           272:        splx(s);
        !           273:        return datalen - resid;
        !           274: }
        !           275:
        !           276: int
        !           277: sbc_pdma_out(ncr_sc, phase, datalen, data)
        !           278:        struct ncr5380_softc *ncr_sc;
        !           279:        int phase, datalen;
        !           280:        u_char *data;
        !           281: {
        !           282:        struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
        !           283:        volatile u_int32_t *long_data = (u_int32_t *)sc->sc_drq_addr;
        !           284:        volatile u_int8_t *byte_data = (u_int8_t *)sc->sc_nodrq_addr;
        !           285:        int i, s, resid;
        !           286:        u_char icmd;
        !           287:
        !           288:        if (datalen < 64)
        !           289:                return ncr5380_pio_out(ncr_sc, phase, datalen, data);
        !           290:
        !           291:        s = splbio();
        !           292:        icmd = *(ncr_sc->sci_icmd) & SCI_ICMD_RMASK;
        !           293:        *ncr_sc->sci_icmd = icmd | SCI_ICMD_DATA;
        !           294:        *ncr_sc->sci_mode |= SCI_MODE_DMA;
        !           295:        *ncr_sc->sci_dma_send = 0;
        !           296:
        !           297:        resid = datalen;
        !           298:        if (sbc_ready(ncr_sc) == 0)
        !           299:                goto interrupt;
        !           300:
        !           301: #define W1     *byte_data++ = *data++
        !           302: #define W4     *long_data++ = *((u_int32_t *)data)++
        !           303:        while (resid >= 64) {
        !           304:                if (sbc_ready(ncr_sc) == 0)
        !           305:                        goto interrupt;
        !           306:                W1;
        !           307:                resid--;
        !           308:                if (sbc_ready(ncr_sc) == 0)
        !           309:                        goto interrupt;
        !           310:                W1;
        !           311:                resid--;
        !           312:                if (sbc_ready(ncr_sc) == 0)
        !           313:                        goto interrupt;
        !           314:                W1;
        !           315:                resid--;
        !           316:                if (sbc_ready(ncr_sc) == 0)
        !           317:                        goto interrupt;
        !           318:                W1;
        !           319:                resid--;
        !           320:                if (sbc_ready(ncr_sc) == 0)
        !           321:                        goto interrupt;
        !           322:                W4; W4; W4; W4;
        !           323:                W4; W4; W4; W4;
        !           324:                W4; W4; W4; W4;
        !           325:                W4; W4; W4;
        !           326:                resid -= 60;
        !           327:
        !           328:                long_data = (u_int32_t *)sc->sc_drq_addr;
        !           329:                byte_data = (u_int8_t *)sc->sc_nodrq_addr;
        !           330:        }
        !           331:        for (; resid; resid--) {
        !           332:                if (sbc_ready(ncr_sc) == 0)
        !           333:                        goto interrupt;
        !           334:                W1;
        !           335:        }
        !           336: #undef  W1
        !           337: #undef  W4
        !           338:
        !           339:        for (i = TIMEOUT; i > 0; i--) {
        !           340:                if ((*ncr_sc->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
        !           341:                    != SCI_CSR_DREQ)
        !           342:                        break;
        !           343:        }
        !           344:        if (i != 0)
        !           345:                *byte_data = 0;
        !           346:        else
        !           347:                printf("%s: timeout waiting for final SCI_DSR_DREQ.\n",
        !           348:                        ncr_sc->sc_dev.dv_xname);
        !           349:
        !           350:        sbc_wait_not_req(ncr_sc);
        !           351: interrupt:
        !           352:        SCI_CLR_INTR(ncr_sc);
        !           353:        *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
        !           354:        *ncr_sc->sci_icmd = icmd;
        !           355:        splx(s);
        !           356:        return (datalen - resid);
        !           357: }
        !           358:
        !           359:
        !           360: /***
        !           361:  * The following code implements interrupt-driven PDMA.
        !           362:  ***/
        !           363:
        !           364: /*
        !           365:  * This is the meat of the PDMA transfer.
        !           366:  * When we get here, we shove data as fast as the mac can take it.
        !           367:  * We depend on several things:
        !           368:  *   * All macs after the Mac Plus that have a 5380 chip should have a general
        !           369:  *     logic IC that handshakes data for blind transfers.
        !           370:  *   * If the SCSI controller finishes sending/receiving data before we do,
        !           371:  *     the same general logic IC will generate a /BERR for us in short order.
        !           372:  *   * The fault address for said /BERR minus the base address for the
        !           373:  *     transfer will be the amount of data that was actually written.
        !           374:  *
        !           375:  * We use the nofault flag and the setjmp/longjmp in locore.s so we can
        !           376:  * detect and handle the bus error for early termination of a command.
        !           377:  * This is usually caused by a disconnecting target.
        !           378:  */
        !           379: int
        !           380: sbc_drq_intr(p)
        !           381:        void *p;
        !           382: {
        !           383:        extern int *nofault, m68k_fault_addr;
        !           384:        struct sbc_softc *sc = (struct sbc_softc *)p;
        !           385:        struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)p;
        !           386:        struct sci_req *sr = ncr_sc->sc_current;
        !           387:        struct sbc_pdma_handle *dh = sr->sr_dma_hand;
        !           388:        label_t faultbuf;
        !           389:        volatile u_int32_t *long_drq;
        !           390:        u_int32_t *long_data;
        !           391:        volatile u_int8_t *drq;
        !           392:        u_int8_t *data;
        !           393:        int count, dcount, resid;
        !           394: #ifdef SBC_WRITE_HACK
        !           395:        u_int8_t tmp;
        !           396: #endif
        !           397:
        !           398:        /*
        !           399:         * If we're not ready to xfer data, or have no more, just return.
        !           400:         */
        !           401:        if ((*ncr_sc->sci_csr & SCI_CSR_DREQ) == 0 || dh->dh_len == 0)
        !           402:                return (0);
        !           403:
        !           404: #ifdef SBC_DEBUG
        !           405:        if (sbc_debug & SBC_DB_INTR)
        !           406:                printf("%s: drq intr, dh_len=0x%x, dh_flags=0x%x\n",
        !           407:                    ncr_sc->sc_dev.dv_xname, dh->dh_len, dh->dh_flags);
        !           408: #endif
        !           409:
        !           410:        /*
        !           411:         * Setup for a possible bus error caused by SCSI controller
        !           412:         * switching out of DATA-IN/OUT before we're done with the
        !           413:         * current transfer.
        !           414:         */
        !           415:        nofault = (int *) &faultbuf;
        !           416:
        !           417:        if (setjmp((label_t *)nofault)) {
        !           418:                nofault = (int *) 0;
        !           419:                if ((dh->dh_flags & SBC_DH_DONE) == 0) {
        !           420:                        count = ((  (u_long)m68k_fault_addr
        !           421:                                  - (u_long)sc->sc_drq_addr));
        !           422:
        !           423:                        if ((count < 0) || (count > dh->dh_len)) {
        !           424:                                printf("%s: complete=0x%x (pending 0x%x)\n",
        !           425:                                    ncr_sc->sc_dev.dv_xname, count, dh->dh_len);
        !           426:                                panic("something is wrong");
        !           427:                        }
        !           428:
        !           429:                        dh->dh_addr += count;
        !           430:                        dh->dh_len -= count;
        !           431:                } else
        !           432:                        count = 0;
        !           433:
        !           434: #ifdef SBC_DEBUG
        !           435:                if (sbc_debug & SBC_DB_INTR)
        !           436:                        printf("%s: drq /berr, complete=0x%x (pending 0x%x)\n",
        !           437:                           ncr_sc->sc_dev.dv_xname, count, dh->dh_len);
        !           438: #endif
        !           439:                m68k_fault_addr = 0;
        !           440:
        !           441:                return (1);
        !           442:        }
        !           443:
        !           444:        if (dh->dh_flags & SBC_DH_OUT) { /* Data Out */
        !           445: #if notyet /* XXX */
        !           446:                /*
        !           447:                 * Get the source address aligned.
        !           448:                 */
        !           449:                resid =
        !           450:                    count = min(dh->dh_len, 4 - (((int)dh->dh_addr) & 0x3));
        !           451:                if (count && count < 4) {
        !           452:                        drq = (volatile u_int8_t *)sc->sc_drq_addr;
        !           453:                        data = (u_int8_t *)dh->dh_addr;
        !           454:
        !           455: #define W1             *drq++ = *data++
        !           456:                        while (count) {
        !           457:                                W1; count--;
        !           458:                        }
        !           459: #undef W1
        !           460:                        dh->dh_addr += resid;
        !           461:                        dh->dh_len -= resid;
        !           462:                }
        !           463:
        !           464:                /*
        !           465:                 * Start the transfer.
        !           466:                 */
        !           467:                while (dh->dh_len) {
        !           468:                        dcount = count = min(dh->dh_len, MAX_DMA_LEN);
        !           469:                        long_drq = (volatile u_int32_t *)sc->sc_drq_addr;
        !           470:                        long_data = (u_int32_t *)dh->dh_addr;
        !           471:
        !           472: #define W4             *long_drq++ = *long_data++
        !           473:                        while (count >= 64) {
        !           474:                                W4; W4; W4; W4; W4; W4; W4; W4;
        !           475:                                W4; W4; W4; W4; W4; W4; W4; W4; /*  64 */
        !           476:                                count -= 64;
        !           477:                        }
        !           478:                        while (count >= 4) {
        !           479:                                W4; count -= 4;
        !           480:                        }
        !           481: #undef W4
        !           482:                        data = (u_int8_t *)long_data;
        !           483:                        drq = (u_int8_t *)long_drq;
        !           484: #else /* notyet */
        !           485:                /*
        !           486:                 * Start the transfer.
        !           487:                 */
        !           488:                while (dh->dh_len) {
        !           489:                        dcount = count = min(dh->dh_len, MAX_DMA_LEN);
        !           490:                        drq = (volatile u_int8_t *)sc->sc_drq_addr;
        !           491:                        data = (u_int8_t *)dh->dh_addr;
        !           492: #endif /* notyet */
        !           493:
        !           494: #define W1             *drq++ = *data++
        !           495:                        while (count) {
        !           496:                                W1; count--;
        !           497:                        }
        !           498: #undef W1
        !           499:                        dh->dh_len -= dcount;
        !           500:                        dh->dh_addr += dcount;
        !           501:                }
        !           502:                dh->dh_flags |= SBC_DH_DONE;
        !           503:
        !           504: #ifdef SBC_WRITE_HACK
        !           505:                /*
        !           506:                 * XXX -- Read a byte from the SBC to trigger a /BERR.
        !           507:                 * This seems to be necessary for us to notice that
        !           508:                 * the target has disconnected.  Ick.  06 jun 1996 (sr)
        !           509:                 */
        !           510:                if (dcount >= MAX_DMA_LEN) {
        !           511: #if 0
        !           512:                        while ((*ncr_sc->sci_csr & SCI_CSR_ACK) == 0)
        !           513:                                ;
        !           514: #endif
        !           515:                        drq = (volatile u_int8_t *)sc->sc_drq_addr;
        !           516:                }
        !           517:                tmp = *drq;
        !           518: #endif
        !           519:        } else {        /* Data In */
        !           520:                /*
        !           521:                 * Get the dest address aligned.
        !           522:                 */
        !           523:                resid =
        !           524:                    count = min(dh->dh_len, 4 - (((int)dh->dh_addr) & 0x3));
        !           525:                if (count && count < 4) {
        !           526:                        data = (u_int8_t *)dh->dh_addr;
        !           527:                        drq = (volatile u_int8_t *)sc->sc_drq_addr;
        !           528:
        !           529: #define R1             *data++ = *drq++
        !           530:                        while (count) {
        !           531:                                R1; count--;
        !           532:                        }
        !           533: #undef R1
        !           534:                        dh->dh_addr += resid;
        !           535:                        dh->dh_len -= resid;
        !           536:                }
        !           537:
        !           538:                /*
        !           539:                 * Start the transfer.
        !           540:                 */
        !           541:                while (dh->dh_len) {
        !           542:                        dcount = count = min(dh->dh_len, MAX_DMA_LEN);
        !           543:                        long_data = (u_int32_t *)dh->dh_addr;
        !           544:                        long_drq = (volatile u_int32_t *)sc->sc_drq_addr;
        !           545:
        !           546: #define R4             *long_data++ = *long_drq++
        !           547:                        while (count >= 64) {
        !           548:                                R4; R4; R4; R4; R4; R4; R4; R4;
        !           549:                                R4; R4; R4; R4; R4; R4; R4; R4; /* 64 */
        !           550:                                count -= 64;
        !           551:                        }
        !           552:                        while (count >= 4) {
        !           553:                                R4; count -= 4;
        !           554:                        }
        !           555: #undef R4
        !           556:                        data = (u_int8_t *)long_data;
        !           557:                        drq = (volatile u_int8_t *)long_drq;
        !           558:
        !           559: #define R1             *data++ = *drq++
        !           560:                        while (count) {
        !           561:                                R1; count--;
        !           562:                        }
        !           563: #undef R1
        !           564:                        dh->dh_len -= dcount;
        !           565:                        dh->dh_addr += dcount;
        !           566:                }
        !           567:                dh->dh_flags |= SBC_DH_DONE;
        !           568:        }
        !           569:
        !           570:        /*
        !           571:         * OK.  No bus error occurred above.  Clear the nofault flag
        !           572:         * so we no longer short-circuit bus errors.
        !           573:         */
        !           574:        nofault = (int *) 0;
        !           575:
        !           576: #ifdef SBC_DEBUG
        !           577:        if (sbc_debug & (SBC_DB_REG | SBC_DB_INTR))
        !           578:                printf("%s: drq intr complete: csr=0x%x, bus_csr=0x%x\n",
        !           579:                    ncr_sc->sc_dev.dv_xname, *ncr_sc->sci_csr,
        !           580:                    *ncr_sc->sci_bus_csr);
        !           581: #endif
        !           582:
        !           583:        return (1);
        !           584: }
        !           585:
        !           586: void
        !           587: sbc_dma_alloc(ncr_sc)
        !           588:        struct ncr5380_softc *ncr_sc;
        !           589: {
        !           590:        struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
        !           591:        struct sci_req *sr = ncr_sc->sc_current;
        !           592:        struct scsi_xfer *xs = sr->sr_xs;
        !           593:        struct sbc_pdma_handle *dh;
        !           594:        int             i, xlen;
        !           595:
        !           596: #ifdef DIAGNOSTIC
        !           597:        if (sr->sr_dma_hand != NULL)
        !           598:                panic("sbc_dma_alloc: already have PDMA handle");
        !           599: #endif
        !           600:
        !           601:        /* Polled transfers shouldn't allocate a PDMA handle. */
        !           602:        if (sr->sr_flags & SR_IMMED)
        !           603:                return;
        !           604:
        !           605:        xlen = ncr_sc->sc_datalen;
        !           606:
        !           607:        /* Make sure our caller checked sc_min_dma_len. */
        !           608:        if (xlen < MIN_DMA_LEN)
        !           609:                panic("sbc_dma_alloc: len=0x%x", xlen);
        !           610:
        !           611:        /*
        !           612:         * Find free PDMA handle.  Guaranteed to find one since we
        !           613:         * have as many PDMA handles as the driver has processes.
        !           614:         * (instances?)
        !           615:         */
        !           616:         for (i = 0; i < SCI_OPENINGS; i++) {
        !           617:                if ((sc->sc_pdma[i].dh_flags & SBC_DH_BUSY) == 0)
        !           618:                        goto found;
        !           619:        }
        !           620:        panic("sbc: no free PDMA handles");
        !           621: found:
        !           622:        dh = &sc->sc_pdma[i];
        !           623:        dh->dh_flags = SBC_DH_BUSY;
        !           624:        dh->dh_addr = ncr_sc->sc_dataptr;
        !           625:        dh->dh_len = xlen;
        !           626:
        !           627:        /* Copy the 'write' flag for convenience. */
        !           628:        if (xs->flags & SCSI_DATA_OUT)
        !           629:                dh->dh_flags |= SBC_DH_OUT;
        !           630:
        !           631:        sr->sr_dma_hand = dh;
        !           632: }
        !           633:
        !           634: void
        !           635: sbc_dma_free(ncr_sc)
        !           636:        struct ncr5380_softc *ncr_sc;
        !           637: {
        !           638:        struct sci_req *sr = ncr_sc->sc_current;
        !           639:        struct sbc_pdma_handle *dh = sr->sr_dma_hand;
        !           640:
        !           641: #ifdef DIAGNOSTIC
        !           642:        if (sr->sr_dma_hand == NULL)
        !           643:                panic("sbc_dma_free: no DMA handle");
        !           644: #endif
        !           645:
        !           646:        if (ncr_sc->sc_state & NCR_DOINGDMA)
        !           647:                panic("sbc_dma_free: free while in progress");
        !           648:
        !           649:        if (dh->dh_flags & SBC_DH_BUSY) {
        !           650:                dh->dh_flags = 0;
        !           651:                dh->dh_addr = NULL;
        !           652:                dh->dh_len = 0;
        !           653:        }
        !           654:        sr->sr_dma_hand = NULL;
        !           655: }
        !           656:
        !           657: void
        !           658: sbc_dma_poll(ncr_sc)
        !           659:        struct ncr5380_softc *ncr_sc;
        !           660: {
        !           661:        struct sci_req *sr = ncr_sc->sc_current;
        !           662:
        !           663:        /*
        !           664:         * We shouldn't arrive here; if SR_IMMED is set, then
        !           665:         * dma_alloc() should have refused to allocate a handle
        !           666:         * for the transfer.  This forces the polled PDMA code
        !           667:         * to handle the request...
        !           668:         */
        !           669: #ifdef SBC_DEBUG
        !           670:        if (sbc_debug & SBC_DB_DMA)
        !           671:                printf("%s: lost DRQ interrupt?\n", ncr_sc->sc_dev.dv_xname);
        !           672: #endif
        !           673:        sr->sr_flags |= SR_OVERDUE;
        !           674: }
        !           675:
        !           676: void
        !           677: sbc_dma_setup(ncr_sc)
        !           678:        struct ncr5380_softc *ncr_sc;
        !           679: {
        !           680:        /* Not needed; we don't have real DMA */
        !           681: }
        !           682:
        !           683: void
        !           684: sbc_dma_start(ncr_sc)
        !           685:        struct ncr5380_softc *ncr_sc;
        !           686: {
        !           687:        struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
        !           688:        struct sci_req *sr = ncr_sc->sc_current;
        !           689:        struct sbc_pdma_handle *dh = sr->sr_dma_hand;
        !           690:
        !           691:        /*
        !           692:         * Match bus phase, clear pending interrupts, set DMA mode, and
        !           693:         * assert data bus (for writing only), then start the transfer.
        !           694:         */
        !           695:        if (dh->dh_flags & SBC_DH_OUT) {
        !           696:                *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
        !           697:                SCI_CLR_INTR(ncr_sc);
        !           698:                if (sc->sc_clrintr)
        !           699:                        (*sc->sc_clrintr)(ncr_sc);
        !           700:                *ncr_sc->sci_mode |= SCI_MODE_DMA;
        !           701:                *ncr_sc->sci_icmd = SCI_ICMD_DATA;
        !           702:                *ncr_sc->sci_dma_send = 0;
        !           703:        } else {
        !           704:                *ncr_sc->sci_tcmd = PHASE_DATA_IN;
        !           705:                SCI_CLR_INTR(ncr_sc);
        !           706:                if (sc->sc_clrintr)
        !           707:                        (*sc->sc_clrintr)(ncr_sc);
        !           708:                *ncr_sc->sci_mode |= SCI_MODE_DMA;
        !           709:                *ncr_sc->sci_icmd = 0;
        !           710:                *ncr_sc->sci_irecv = 0;
        !           711:        }
        !           712:        ncr_sc->sc_state |= NCR_DOINGDMA;
        !           713:
        !           714: #ifdef SBC_DEBUG
        !           715:        if (sbc_debug & SBC_DB_DMA)
        !           716:                printf("%s: PDMA started, va=%p, len=0x%x\n",
        !           717:                    ncr_sc->sc_dev.dv_xname, dh->dh_addr, dh->dh_len);
        !           718: #endif
        !           719: }
        !           720:
        !           721: void
        !           722: sbc_dma_stop(ncr_sc)
        !           723:        struct ncr5380_softc *ncr_sc;
        !           724: {
        !           725:        struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
        !           726:        struct sci_req *sr = ncr_sc->sc_current;
        !           727:        struct sbc_pdma_handle *dh = sr->sr_dma_hand;
        !           728:        int ntrans;
        !           729:
        !           730:        if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
        !           731: #ifdef SBC_DEBUG
        !           732:                if (sbc_debug & SBC_DB_DMA)
        !           733:                        printf("%s: dma_stop: DMA not running\n",
        !           734:                            ncr_sc->sc_dev.dv_xname);
        !           735: #endif
        !           736:                return;
        !           737:        }
        !           738:        ncr_sc->sc_state &= ~NCR_DOINGDMA;
        !           739:
        !           740:        if ((ncr_sc->sc_state & NCR_ABORTING) == 0) {
        !           741:                ntrans = ncr_sc->sc_datalen - dh->dh_len;
        !           742:
        !           743: #ifdef SBC_DEBUG
        !           744:                if (sbc_debug & SBC_DB_DMA)
        !           745:                        printf("%s: dma_stop: ntrans=0x%x\n",
        !           746:                            ncr_sc->sc_dev.dv_xname, ntrans);
        !           747: #endif
        !           748:
        !           749:                if (ntrans > ncr_sc->sc_datalen)
        !           750:                        panic("sbc_dma_stop: excess transfer");
        !           751:
        !           752:                /* Adjust data pointer */
        !           753:                ncr_sc->sc_dataptr += ntrans;
        !           754:                ncr_sc->sc_datalen -= ntrans;
        !           755:
        !           756:                /* Clear any pending interrupts. */
        !           757:                SCI_CLR_INTR(ncr_sc);
        !           758:                if (sc->sc_clrintr)
        !           759:                        (*sc->sc_clrintr)(ncr_sc);
        !           760:        }
        !           761:
        !           762:        /* Put SBIC back into PIO mode. */
        !           763:        *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
        !           764:        *ncr_sc->sci_icmd = 0;
        !           765:
        !           766: #ifdef SBC_DEBUG
        !           767:        if (sbc_debug & SBC_DB_REG)
        !           768:                printf("%s: dma_stop: csr=0x%x, bus_csr=0x%x\n",
        !           769:                    ncr_sc->sc_dev.dv_xname, *ncr_sc->sci_csr,
        !           770:                    *ncr_sc->sci_bus_csr);
        !           771: #endif
        !           772: }

CVSweb