[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

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