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

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

1.1     ! nbrk        1: /*     $OpenBSD: ncr5380.c,v 1.31 2007/04/24 16:48:43 miod Exp $       */
        !             2: /*     $NetBSD: ncr5380.c,v 1.38 1996/12/19 21:48:18 scottr Exp $      */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Leo Weppelman.
        !             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 Leo Weppelman.
        !            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:  * Bit mask of targets you want debugging to be shown
        !            36:  */
        !            37: u_char dbg_target_mask = 0x7f;
        !            38:
        !            39: /*
        !            40:  * Set bit for target when parity checking must be disabled.
        !            41:  * My (LWP) Maxtor 7245S  seems to generate parity errors on about 50%
        !            42:  * of all transfers while the data is correct!?
        !            43:  */
        !            44: u_char ncr5380_no_parchk = 0xff;
        !            45:
        !            46: /*
        !            47:  * Flags to allow binpatching of which devices to allow or disallow
        !            48:  * issuance of linked commands.  disallowance is favored over allowance,
        !            49:  * so if the same bit is set in either, the driver will not issue linked
        !            50:  * commands to the corresponding target.
        !            51:  * SCSI-2 devices can report whether or not they will accept linked
        !            52:  * commands.  If that reports that a device supports linked commands,
        !            53:  * then it is treated as if the corresponding bit in ncr5380_allow_linked
        !            54:  * is set.
        !            55:  */
        !            56: u_char ncr5380_allow_linked = 0x80;
        !            57: u_char ncr5380_disallow_linked = 0x80;
        !            58:
        !            59: /*
        !            60:  * This is the default sense-command we send.
        !            61:  */
        !            62: static u_char  sense_cmd[] = {
        !            63:                REQUEST_SENSE, 0, 0, 0, sizeof(struct scsi_sense_data), 0
        !            64: };
        !            65:
        !            66: /*
        !            67:  * True if the main co-routine is running
        !            68:  */
        !            69: static volatile int    main_running = 0;
        !            70:
        !            71: /*
        !            72:  * Mask of targets selected
        !            73:  */
        !            74: static u_char  busy;
        !            75:
        !            76: static void    ncr5380_minphys(struct buf *bp);
        !            77: static int     mac68k_ncr5380_scsi_cmd(struct scsi_xfer *xs);
        !            78: static void    ncr5380_show_scsi_cmd(struct scsi_xfer *xs);
        !            79:
        !            80: struct scsi_adapter ncr5380_switch = {
        !            81:        mac68k_ncr5380_scsi_cmd,        /* scsi_cmd()                   */
        !            82:        ncr5380_minphys,                /* scsi_minphys()               */
        !            83:        0,                              /* open_target_lu()             */
        !            84:        0                               /* close_target_lu()            */
        !            85: };
        !            86:
        !            87: struct scsi_device ncr5380_dev = {
        !            88:        NULL,           /* use default error handler            */
        !            89:        NULL,           /* do not have a start functio          */
        !            90:        NULL,           /* have no async handler                */
        !            91:        NULL            /* Use default done routine             */
        !            92: };
        !            93:
        !            94:
        !            95: static SC_REQ  req_queue[NREQ];
        !            96: static SC_REQ  *free_head = NULL;      /* Free request structures      */
        !            97:
        !            98:
        !            99: /*
        !           100:  * Inline functions:
        !           101:  */
        !           102:
        !           103: /*
        !           104:  * Determine the size of a SCSI command.
        !           105:  */
        !           106: extern __inline__ int command_size(opcode)
        !           107: u_char opcode;
        !           108: {
        !           109:        switch ((opcode >> 4) & 0xf) {
        !           110:                case 0:
        !           111:                case 1:
        !           112:                        return (6);
        !           113:                case 2:
        !           114:                case 3:
        !           115:                        return (10);
        !           116:        }
        !           117:        return (12);
        !           118: }
        !           119:
        !           120:
        !           121: /*
        !           122:  * Wait for request-line to become active. When it doesn't return 0.
        !           123:  * Otherwise return != 0.
        !           124:  * The timeouts in the 'wait_req_*' functions are arbitrary and rather
        !           125:  * large. In 99% of the invocations nearly no timeout is needed but in
        !           126:  * some cases (especially when using my tapedrive, a Tandberg 3600) the
        !           127:  * device is busy internally and the first SCSI-phase will be delayed.
        !           128:  *
        !           129:  * -- A sleeping Fujitsu M2512 is even worse; try 2.5 sec     -hf 20 Jun
        !           130:  */
        !           131: extern __inline__ int wait_req_true(void)
        !           132: {
        !           133:        int     timeout = 2500000;
        !           134:
        !           135:        while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
        !           136:                delay(1);
        !           137:        return (GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ);
        !           138: }
        !           139:
        !           140: /*
        !           141:  * Wait for request-line to become inactive. When it doesn't return 0.
        !           142:  * Otherwise return != 0.
        !           143:  */
        !           144: extern __inline__ int wait_req_false(void)
        !           145: {
        !           146:        int     timeout = 2500000;
        !           147:
        !           148:        while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ) && --timeout)
        !           149:                delay(1);
        !           150:        return (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_REQ));
        !           151: }
        !           152:
        !           153: extern __inline__ void ack_message()
        !           154: {
        !           155:        SET_5380_REG(NCR5380_ICOM, 0);
        !           156: }
        !           157:
        !           158: extern __inline__ void nack_message(SC_REQ *reqp, u_char msg)
        !           159: {
        !           160:        SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
        !           161:        reqp->msgout = msg;
        !           162: }
        !           163:
        !           164: extern __inline__ void finish_req(SC_REQ *reqp)
        !           165: {
        !           166:        int                     sps;
        !           167:        struct scsi_xfer        *xs = reqp->xs;
        !           168:
        !           169: #ifdef REAL_DMA
        !           170:        /*
        !           171:         * If we bounced, free the bounce buffer
        !           172:         */
        !           173:        if (reqp->dr_flag & DRIVER_BOUNCING)
        !           174:                free_bounceb(reqp->bounceb);
        !           175: #endif /* REAL_DMA */
        !           176: #ifdef DBG_REQ
        !           177:        if (dbg_target_mask & (1 << reqp->targ_id))
        !           178:                show_request(reqp, "DONE");
        !           179: #endif
        !           180: #ifdef DBG_ERR_RET
        !           181:        if (reqp->xs->error != 0)
        !           182:                show_request(reqp, "ERR_RET");
        !           183: #endif
        !           184:        /*
        !           185:         * Return request to free-q
        !           186:         */
        !           187:        sps = splbio();
        !           188:        reqp->next = free_head;
        !           189:        free_head  = reqp;
        !           190:
        !           191:        xs->flags |= ITSDONE;
        !           192:        if (!(reqp->dr_flag & DRIVER_LINKCHK))
        !           193:                scsi_done(xs);
        !           194:        splx(sps);
        !           195: }
        !           196:
        !           197: /*
        !           198:  * Auto config stuff....
        !           199:  */
        !           200: void   ncr_attach(struct device *, struct device *, void *);
        !           201: int    ncr_match(struct device *, void *, void *);
        !           202:
        !           203: /*
        !           204:  * Tricks to make driver-name configurable
        !           205:  */
        !           206: #define CFNAME(n)      __CONCAT(n,_cd)
        !           207: #define CANAME(n)      __CONCAT(n,_ca)
        !           208: #define CFSTRING(n)    __STRING(n)
        !           209:
        !           210: struct cfattach CANAME(DRNAME) = {
        !           211:        sizeof(struct ncr_softc), ncr_match, ncr_attach
        !           212: };
        !           213:
        !           214: struct cfdriver CFNAME(DRNAME) = {
        !           215:        NULL, CFSTRING(DRNAME), DV_DULL
        !           216: };
        !           217:
        !           218: int
        !           219: ncr_match(parent, cf, aux)
        !           220:        struct device *parent;
        !           221:        void *cf;
        !           222:        void *aux;
        !           223: {
        !           224:        return (machine_match(parent,
        !           225:                                (struct cfdata *) cf, aux, &CFNAME(DRNAME)));
        !           226: }
        !           227:
        !           228: void
        !           229: ncr_attach(pdp, dp, auxp)
        !           230: struct device  *pdp, *dp;
        !           231: void           *auxp;
        !           232: {
        !           233:        struct ncr_softc        *sc;
        !           234:        struct scsibus_attach_args saa;
        !           235:        int                     i;
        !           236:
        !           237:        sc = (struct ncr_softc *)dp;
        !           238:
        !           239:        sc->sc_link.adapter_softc   = sc;
        !           240:        sc->sc_link.adapter_target  = 7;
        !           241:        sc->sc_link.adapter         = &ncr5380_switch;
        !           242:        sc->sc_link.device          = &ncr5380_dev;
        !           243:        sc->sc_link.openings        = NREQ - 1;
        !           244:
        !           245:        /*
        !           246:         * bitmasks
        !           247:         */
        !           248:        sc->sc_noselatn = 0;
        !           249:        sc->sc_selected = 0;
        !           250:
        !           251:        /*
        !           252:         * Initialize machine-type specific things...
        !           253:         */
        !           254:        scsi_mach_init(sc);
        !           255:        printf("\n");
        !           256:
        !           257:        /*
        !           258:         * Initialize request queue freelist.
        !           259:         */
        !           260:        for (i = 0; i < NREQ; i++) {
        !           261:                req_queue[i].next = free_head;
        !           262:                free_head = &req_queue[i];
        !           263:        }
        !           264:
        !           265:        /*
        !           266:         * Initialize the host adapter
        !           267:         */
        !           268:        scsi_idisable();
        !           269:        ENABLE_NCR5380(sc);
        !           270:        SET_5380_REG(NCR5380_ICOM, 0);
        !           271:        SET_5380_REG(NCR5380_MODE, IMODE_BASE);
        !           272:        SET_5380_REG(NCR5380_TCOM, 0);
        !           273:        SET_5380_REG(NCR5380_IDSTAT, 0);
        !           274:        scsi_ienable();
        !           275:
        !           276:        bzero(&saa, sizeof(saa));
        !           277:        saa.saa_sc_link = &sc->sc_link;
        !           278:
        !           279:        /*
        !           280:         * attach all scsi units on us
        !           281:         */
        !           282:        config_found(dp, &saa, scsiprint);
        !           283: }
        !           284:
        !           285: /*
        !           286:  * End of auto config stuff....
        !           287:  */
        !           288:
        !           289: /*
        !           290:  * Carry out a request from the high level driver.
        !           291:  */
        !           292: static int
        !           293: mac68k_ncr5380_scsi_cmd(struct scsi_xfer *xs)
        !           294: {
        !           295:        int     sps;
        !           296:        SC_REQ  *reqp, *link, *tmp;
        !           297:        int     flags = xs->flags;
        !           298:
        !           299:        /*
        !           300:         * We do not queue RESET commands
        !           301:         */
        !           302:        if (flags & SCSI_RESET) {
        !           303:                scsi_reset_verbose(xs->sc_link->adapter_softc,
        !           304:                                   "Got reset-command");
        !           305:                return (COMPLETE);
        !           306:        }
        !           307:
        !           308:        /*
        !           309:         * Get a request block
        !           310:         */
        !           311:        sps = splbio();
        !           312:        if ((reqp = free_head) == 0) {
        !           313:                splx(sps);
        !           314:                return (TRY_AGAIN_LATER);
        !           315:        }
        !           316:        free_head  = reqp->next;
        !           317:        reqp->next = NULL;
        !           318:        splx(sps);
        !           319:
        !           320:        /*
        !           321:         * Initialize our private fields
        !           322:         */
        !           323:        reqp->dr_flag   = (flags & SCSI_POLL) ? DRIVER_NOINT : 0;
        !           324:        reqp->phase     = NR_PHASE;
        !           325:        reqp->msgout    = MSG_NOOP;
        !           326:        reqp->status    = SCSGOOD;
        !           327:        reqp->message   = 0xff;
        !           328:        reqp->link      = NULL;
        !           329:        reqp->xs        = xs;
        !           330:        reqp->targ_id   = xs->sc_link->target;
        !           331:        reqp->targ_lun  = xs->sc_link->lun;
        !           332:        reqp->xdata_ptr = (u_char *)xs->data;
        !           333:        reqp->xdata_len = xs->datalen;
        !           334:        memcpy(&reqp->xcmd, xs->cmd, sizeof(struct scsi_generic));
        !           335:        reqp->xcmd.bytes[0] |= reqp->targ_lun << 5;
        !           336:
        !           337:        /*
        !           338:         * Sanity check on flags...
        !           339:         */
        !           340:        if (flags & ITSDONE) {
        !           341:                ncr_tprint(reqp, "scsi_cmd: command already done.....\n");
        !           342:                xs->flags &= ~ITSDONE;
        !           343:        }
        !           344:
        !           345: #ifdef REAL_DMA
        !           346:        /*
        !           347:         * Check if DMA can be used on this request
        !           348:         */
        !           349:        if (scsi_dmaok(reqp))
        !           350:                reqp->dr_flag |= DRIVER_DMAOK;
        !           351: #endif /* REAL_DMA */
        !           352:
        !           353:        /*
        !           354:         * Insert the command into the issue queue. Note that 'REQUEST SENSE'
        !           355:         * commands are inserted at the head of the queue since any command
        !           356:         * will clear the existing contingent allegience condition and the sense
        !           357:         * data is only valid while the condition exists.
        !           358:         * When possible, link the command to a previous command to the same
        !           359:         * target. This is not very sensible when AUTO_SENSE is not defined!
        !           360:         * Interrupts are disabled while we are fiddling with the issue-queue.
        !           361:         */
        !           362:        sps = splbio();
        !           363:        link = NULL;
        !           364:        if ((issue_q == NULL) || (reqp->xcmd.opcode == REQUEST_SENSE)) {
        !           365:                reqp->next = issue_q;
        !           366:                issue_q    = reqp;
        !           367:        }
        !           368:        else {
        !           369:                tmp  = issue_q;
        !           370:                do {
        !           371:                    if (!link && (tmp->targ_id == reqp->targ_id) && !tmp->link)
        !           372:                                link = tmp;
        !           373:                } while (tmp->next && (tmp = tmp->next));
        !           374:                tmp->next = reqp;
        !           375: #ifdef AUTO_SENSE
        !           376:                if (link && ((xs->sc_link->inqdata.flags & SID_Linked)
        !           377:                             || ((1<<reqp->targ_id) & ncr5380_allow_linked))
        !           378:                         && !((1<<reqp->targ_id) & ncr5380_disallow_linked)) {
        !           379:                        link->link = reqp;
        !           380:                        link->xcmd.bytes[link->xs->cmdlen-2] |= 1;
        !           381:                }
        !           382: #endif
        !           383:        }
        !           384:        splx(sps);
        !           385:
        !           386: #ifdef DBG_REQ
        !           387:        if (dbg_target_mask & (1 << reqp->targ_id))
        !           388:                show_request(reqp, (reqp->xcmd.opcode == REQUEST_SENSE) ?
        !           389:                                                                "HEAD":"TAIL");
        !           390: #endif
        !           391:
        !           392:        run_main(xs->sc_link->adapter_softc);
        !           393:
        !           394:        if (xs->flags & (SCSI_POLL|ITSDONE))
        !           395:                return (COMPLETE); /* We're booting or run_main has completed */
        !           396:        return (SUCCESSFULLY_QUEUED);
        !           397: }
        !           398:
        !           399: static void
        !           400: ncr5380_minphys(struct buf *bp)
        !           401: {
        !           402:     if (bp->b_bcount > MIN_PHYS)
        !           403:        bp->b_bcount = MIN_PHYS;
        !           404:     minphys(bp);
        !           405: }
        !           406: #undef MIN_PHYS
        !           407:
        !           408: static void
        !           409: ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
        !           410: {
        !           411:        u_char  *b = (u_char *) xs->cmd;
        !           412:        int     i  = 0;
        !           413:
        !           414:        if (!(xs->flags & SCSI_RESET)) {
        !           415:                printf("(%d:%d:%d,0x%x)-", xs->sc_link->scsibus,
        !           416:                    xs->sc_link->target, xs->sc_link->lun, xs->sc_link->flags);
        !           417:                while (i < xs->cmdlen) {
        !           418:                        if (i)
        !           419:                                printf(",");
        !           420:                        printf("%x",b[i++]);
        !           421:                }
        !           422:                printf("-\n");
        !           423:        }
        !           424:        else {
        !           425:                printf("(%d:%d:%d)-RESET-\n",
        !           426:                    xs->sc_link->scsibus,xs->sc_link->target, xs->sc_link->lun);
        !           427:        }
        !           428: }
        !           429:
        !           430: /*
        !           431:  * The body of the driver.
        !           432:  */
        !           433: static void
        !           434: scsi_main(sc)
        !           435: struct ncr_softc *sc;
        !           436: {
        !           437:        SC_REQ  *req, *prev;
        !           438:        int     itype;
        !           439:        int     sps;
        !           440:
        !           441:        /*
        !           442:         * While running in the driver SCSI-interrupts are disabled.
        !           443:         */
        !           444:        scsi_idisable();
        !           445:        ENABLE_NCR5380(sc);
        !           446:
        !           447:        PID("scsi_main1");
        !           448:        for (;;) {
        !           449:            sps = splbio();
        !           450:            if (!connected) {
        !           451:                /*
        !           452:                 * Check if it is fair keep any exclusive access to DMA
        !           453:                 * claimed. If not, stop queueing new jobs so the discon_q
        !           454:                 * will be eventually drained and DMA can be given up.
        !           455:                 */
        !           456:                if (!fair_to_keep_dma())
        !           457:                        goto main_exit;
        !           458:
        !           459:                /*
        !           460:                 * Search through the issue-queue for a command
        !           461:                 * destined for a target that isn't busy.
        !           462:                 */
        !           463:                prev = NULL;
        !           464:                for (req=issue_q; req != NULL; prev = req, req = req->next) {
        !           465:                        if (!(busy & (1 << req->targ_id))) {
        !           466:                                /*
        !           467:                                 * Found one, remove it from the issue queue
        !           468:                                 */
        !           469:                                if (prev == NULL)
        !           470:                                        issue_q = req->next;
        !           471:                                else prev->next = req->next;
        !           472:                                req->next = NULL;
        !           473:                                break;
        !           474:                        }
        !           475:                }
        !           476:
        !           477:                /*
        !           478:                 * When a request has just ended, we get here before an other
        !           479:                 * device detects that the bus is free and that it can
        !           480:                 * reconnect. The problem is that when this happens, we always
        !           481:                 * baffle the device because our (initiator) id is higher. This
        !           482:                 * can cause a sort of starvation on slow devices. So we check
        !           483:                 * for a pending reselection here.
        !           484:                 * Note that 'connected' will be non-null if the reselection
        !           485:                 * succeeds.
        !           486:                 */
        !           487:                if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
        !           488:                                                == (SC_S_SEL|SC_S_IO)){
        !           489:                        if (req != NULL) {
        !           490:                                req->next = issue_q;
        !           491:                                issue_q = req;
        !           492:                        }
        !           493:                        splx(sps);
        !           494:
        !           495:                        reselect(sc);
        !           496:                        scsi_clr_ipend();
        !           497:                        goto connected;
        !           498:                }
        !           499:
        !           500:                /*
        !           501:                 * The host is not connected and there is no request
        !           502:                 * pending, exit.
        !           503:                 */
        !           504:                if (req == NULL) {
        !           505:                        PID("scsi_main2");
        !           506:                        goto main_exit;
        !           507:                }
        !           508:
        !           509:                /*
        !           510:                 * Re-enable interrupts before handling the request.
        !           511:                 */
        !           512:                splx(sps);
        !           513:
        !           514: #ifdef DBG_REQ
        !           515:                if (dbg_target_mask & (1 << req->targ_id))
        !           516:                        show_request(req, "TARGET");
        !           517: #endif
        !           518:                /*
        !           519:                 * We found a request. Try to connect to the target. If the
        !           520:                 * initiator fails arbitration, the command is put back in the
        !           521:                 * issue queue.
        !           522:                 */
        !           523:                if (scsi_select(req, 0)) {
        !           524:                        sps = splbio();
        !           525:                        req->next = issue_q;
        !           526:                        issue_q = req;
        !           527:                        splx(sps);
        !           528: #ifdef DBG_REQ
        !           529:                        if (dbg_target_mask & (1 << req->targ_id))
        !           530:                                ncr_tprint(req, "Select failed\n");
        !           531: #endif
        !           532:                }
        !           533:            }
        !           534:            else splx(sps);
        !           535: connected:
        !           536:            if (connected) {
        !           537:                /*
        !           538:                 * If the host is currently connected but a 'real-dma' transfer
        !           539:                 * is in progress, the 'end-of-dma' interrupt restarts main.
        !           540:                 * So quit.
        !           541:                 */
        !           542:                sps = splbio();
        !           543:                if (connected && (connected->dr_flag & DRIVER_IN_DMA)) {
        !           544:                        PID("scsi_main3");
        !           545:                        goto main_exit;
        !           546:                }
        !           547:                splx(sps);
        !           548:
        !           549:                /*
        !           550:                 * Let the target guide us through the bus-phases
        !           551:                 */
        !           552:                while (information_transfer(sc) == -1)
        !           553:                        ;
        !           554:            }
        !           555:        }
        !           556:        /* NEVER TO REACH HERE */
        !           557:        panic("ncr5380-SCSI: not designed to come here");
        !           558:
        !           559: main_exit:
        !           560:        /*
        !           561:         * We enter here with interrupts disabled. We are about to exit main
        !           562:         * so interrupts should be re-enabled. Because interrupts are edge
        !           563:         * triggered, we could already have missed the interrupt. Therefore
        !           564:         * we check the IRQ-line here and re-enter when we really missed a
        !           565:         * valid interrupt.
        !           566:         */
        !           567:        PID("scsi_main4");
        !           568:        scsi_ienable();
        !           569:
        !           570:        /*
        !           571:         * If we're not currently connected, enable reselection
        !           572:         * interrupts.
        !           573:         */
        !           574:        if (!connected)
        !           575:                SET_5380_REG(NCR5380_IDSTAT, SC_HOST_ID);
        !           576:
        !           577:        if (scsi_ipending()) {
        !           578:                if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
        !           579:                        scsi_idisable();
        !           580:                        splx(sps);
        !           581:
        !           582:                        if (itype == INTR_RESEL)
        !           583:                                reselect(sc);
        !           584: #ifdef REAL_DMA
        !           585:                        else dma_ready();
        !           586: #else
        !           587:                        else {
        !           588:                                if (pdma_ready())
        !           589:                                        goto connected;
        !           590:                                panic("Got DMA interrupt without DMA");
        !           591:                        }
        !           592: #endif
        !           593:                        scsi_clr_ipend();
        !           594:                        goto connected;
        !           595:                }
        !           596:        }
        !           597:        reconsider_dma();
        !           598:
        !           599:        main_running = 0;
        !           600:        splx(sps);
        !           601:        PID("scsi_main5");
        !           602: }
        !           603:
        !           604: #ifdef REAL_DMA
        !           605: /*
        !           606:  * The SCSI-DMA interrupt.
        !           607:  * This interrupt can only be triggered when running in non-polled DMA
        !           608:  * mode. When DMA is not active, it will be silently ignored, it is usually
        !           609:  * too late because the EOP interrupt of the controller happens just a tiny
        !           610:  * bit earlier. It might become usefull when scatter/gather is implemented,
        !           611:  * because in that case only part of the DATAIN/DATAOUT transfer is taken
        !           612:  * out of a single buffer.
        !           613:  */
        !           614: static void
        !           615: ncr_dma_intr(sc)
        !           616: struct ncr_softc *sc;
        !           617: {
        !           618:        SC_REQ  *reqp;
        !           619:        int     dma_done;
        !           620:
        !           621:        PID("ncr_dma_intr");
        !           622:        if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)) {
        !           623:                scsi_idisable();
        !           624:                if (!(dma_done = dma_ready())) {
        !           625:                        transfer_dma(reqp, reqp->phase, 0);
        !           626:                        return;
        !           627:                }
        !           628:                run_main(sc);
        !           629:        }
        !           630: }
        !           631: #endif /* REAL_DMA */
        !           632:
        !           633: /*
        !           634:  * The SCSI-controller interrupt. This interrupt occurs on reselections and
        !           635:  * at the end of non-polled DMA-interrupts. It is assumed to be called from
        !           636:  * the machine-dependent hardware interrupt.
        !           637:  */
        !           638: static void
        !           639: ncr_ctrl_intr(sc)
        !           640: struct ncr_softc *sc;
        !           641: {
        !           642:        int     itype;
        !           643:
        !           644:        while (scsi_ipending()) {
        !           645:                scsi_idisable();
        !           646:                if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
        !           647:                        if (itype == INTR_RESEL)
        !           648:                                reselect(sc);
        !           649:                        else {
        !           650: #ifdef REAL_DMA
        !           651:                            int dma_done;
        !           652:                            if (!(dma_done = dma_ready())) {
        !           653:                                transfer_dma(connected, connected->phase, 0);
        !           654:                                return;
        !           655:                            }
        !           656: #else
        !           657:                            if (pdma_ready())
        !           658:                                return;
        !           659:                            panic("Got DMA interrupt without DMA");
        !           660: #endif
        !           661:                        }
        !           662:                        scsi_clr_ipend();
        !           663:                }
        !           664:                run_main(sc);
        !           665:                return;
        !           666:        }
        !           667:        PID("ncr_ctrl_intr1");
        !           668: }
        !           669:
        !           670: /*
        !           671:  * Initiate a connection path between the host and the target. The function
        !           672:  * first goes into arbitration for the SCSI-bus. When this succeeds, the target
        !           673:  * is selected and an 'IDENTIFY' message is send.
        !           674:  * Returns -1 when the arbitration failed. Otherwise 0 is returned. When
        !           675:  * the target does not respond (to either selection or 'MESSAGE OUT') the
        !           676:  * 'done' function is executed.
        !           677:  * The result code given by the driver can be influenced by setting 'code'
        !           678:  * to a non-zero value. This is the case when 'select' is called by abort.
        !           679:  */
        !           680: static int
        !           681: scsi_select(reqp, code)
        !           682: SC_REQ *reqp;
        !           683: int    code;
        !           684: {
        !           685:        u_char                  tmp[1];
        !           686:        u_char                  phase;
        !           687:        u_long                  cnt;
        !           688:        int                     sps;
        !           689:        u_int8_t                atn_flag;
        !           690:        u_int8_t                targ_bit;
        !           691:        struct ncr_softc        *sc;
        !           692:
        !           693:        sc = reqp->xs->sc_link->adapter_softc;
        !           694:        DBG_SELPRINT ("Starting arbitration\n", 0);
        !           695:        PID("scsi_select1");
        !           696:
        !           697:        sps = splbio();
        !           698:
        !           699:        /*
        !           700:         * Prevent a race condition here. If a reslection interrupt occurred
        !           701:         * between the decision to pick a new request and the call to select,
        !           702:         * we abort the selection.
        !           703:         * Interrupts are lowered when the 5380 is setup to arbitrate for the
        !           704:         * bus.
        !           705:         */
        !           706:        if (connected) {
        !           707:                splx(sps);
        !           708:                PID("scsi_select2");
        !           709:                return (-1);
        !           710:        }
        !           711:
        !           712:        /*
        !           713:         * Set phase bits to 0, otherwise the 5380 won't drive the bus during
        !           714:         * selection.
        !           715:         */
        !           716:        SET_5380_REG(NCR5380_TCOM, 0);
        !           717:        SET_5380_REG(NCR5380_ICOM, 0);
        !           718:
        !           719:        /*
        !           720:         * Arbitrate for the bus.
        !           721:         */
        !           722:        SET_5380_REG(NCR5380_DATA, SC_HOST_ID);
        !           723:        SET_5380_REG(NCR5380_MODE, SC_ARBIT);
        !           724:
        !           725:        splx(sps);
        !           726:
        !           727:        cnt = 10;
        !           728:        while (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP) && --cnt)
        !           729:                delay(1);
        !           730:
        !           731:        if (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP)) {
        !           732:                SET_5380_REG(NCR5380_MODE, IMODE_BASE);
        !           733:                SET_5380_REG(NCR5380_ICOM, 0);
        !           734:                DBG_SELPRINT ("Arbitration lost, bus not free\n",0);
        !           735:                PID("scsi_select3");
        !           736:                return (-1);
        !           737:        }
        !           738:
        !           739:        /* The arbitration delay is 2.2 usecs */
        !           740:        delay(3);
        !           741:
        !           742:        /*
        !           743:         * Check the result of the arbitration. If we failed, return -1.
        !           744:         */
        !           745:        if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
        !           746:                SET_5380_REG(NCR5380_MODE, IMODE_BASE);
        !           747:                SET_5380_REG(NCR5380_ICOM, 0);
        !           748:                PID("scsi_select4");
        !           749:                return (-1);
        !           750:        }
        !           751:
        !           752:        /*
        !           753:         * The spec requires that we should read the data register to
        !           754:         * check for higher id's and check the SC_LA again.
        !           755:         */
        !           756:        tmp[0] = GET_5380_REG(NCR5380_DATA);
        !           757:        if (tmp[0] & ~((SC_HOST_ID << 1) - 1)) {
        !           758:                SET_5380_REG(NCR5380_MODE, IMODE_BASE);
        !           759:                SET_5380_REG(NCR5380_ICOM, 0);
        !           760:                DBG_SELPRINT ("Arbitration lost, higher id present\n",0);
        !           761:                PID("scsi_select5");
        !           762:                return (-1);
        !           763:        }
        !           764:        if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
        !           765:                SET_5380_REG(NCR5380_MODE, IMODE_BASE);
        !           766:                SET_5380_REG(NCR5380_ICOM, 0);
        !           767:                DBG_SELPRINT ("Arbitration lost,deassert SC_ARBIT\n",0);
        !           768:                PID("scsi_select6");
        !           769:                return (-1);
        !           770:        }
        !           771:        SET_5380_REG(NCR5380_ICOM, SC_A_SEL | SC_A_BSY);
        !           772:        if (GET_5380_REG(NCR5380_ICOM) & SC_LA) {
        !           773:                SET_5380_REG(NCR5380_MODE, IMODE_BASE);
        !           774:                SET_5380_REG(NCR5380_ICOM, 0);
        !           775:                DBG_SELPRINT ("Arbitration lost, deassert SC_A_SEL\n", 0);
        !           776:                PID("scsi_select7");
        !           777:                return (-1);
        !           778:        }
        !           779:        /* Bus settle delay + Bus clear delay = 1.2 usecs */
        !           780:        delay(2);
        !           781:        DBG_SELPRINT ("Arbitration complete\n", 0);
        !           782:
        !           783:        /*
        !           784:         * Now that we won the arbitration, start the selection.
        !           785:         */
        !           786:        targ_bit = 1 << reqp->targ_id;
        !           787:        SET_5380_REG(NCR5380_DATA, SC_HOST_ID | targ_bit);
        !           788:
        !           789:        if (sc->sc_noselatn & targ_bit)
        !           790:                atn_flag = 0;
        !           791:        else
        !           792:                atn_flag = SC_A_ATN;
        !           793:
        !           794:        /*
        !           795:         * Raise ATN while SEL is true before BSY goes false from arbitration,
        !           796:         * since this is the only way to guarantee that we'll get a MESSAGE OUT
        !           797:         * phase immediately after the selection.
        !           798:         */
        !           799:        SET_5380_REG(NCR5380_ICOM, SC_A_BSY | SC_A_SEL | atn_flag | SC_ADTB);
        !           800:        SET_5380_REG(NCR5380_MODE, IMODE_BASE);
        !           801:
        !           802:        /*
        !           803:         * Turn off reselection interrupts
        !           804:         */
        !           805:        SET_5380_REG(NCR5380_IDSTAT, 0);
        !           806:
        !           807:        /*
        !           808:         * Reset BSY. The delay following it, surpresses a glitch in the
        !           809:         * 5380 which causes us to see our own BSY signal instead of that of
        !           810:         * the target.
        !           811:         */
        !           812:        SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag | SC_ADTB);
        !           813:        delay(1);
        !           814:
        !           815:        /*
        !           816:         * Wait for the target to react, the specs call for a timeout of
        !           817:         * 250 ms.
        !           818:         */
        !           819:        cnt = 25000;
        !           820:        while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) && --cnt)
        !           821:                delay(10);
        !           822:
        !           823:        if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
        !           824:                /*
        !           825:                 * There is no reaction from the target, start the selection
        !           826:                 * timeout procedure. We release the databus but keep SEL
        !           827:                 * asserted. After that we wait a 'selection abort time' (200
        !           828:                 * usecs) and 2 deskew delays (90 ns) and check BSY again.
        !           829:                 * When BSY is asserted, we assume the selection succeeded,
        !           830:                 * otherwise we release the bus.
        !           831:                 */
        !           832:                SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag);
        !           833:                delay(201);
        !           834:                if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
        !           835:                        SET_5380_REG(NCR5380_ICOM, 0);
        !           836:                        reqp->xs->error      = code ? code : XS_SELTIMEOUT;
        !           837:                        DBG_SELPRINT ("Target %d not responding to sel\n",
        !           838:                                                                reqp->targ_id);
        !           839:                        finish_req(reqp);
        !           840:                        PID("scsi_select8");
        !           841:                        return (0);
        !           842:                }
        !           843:        }
        !           844:        SET_5380_REG(NCR5380_ICOM, atn_flag);
        !           845:
        !           846:        DBG_SELPRINT ("Target %d responding to select.\n", reqp->targ_id);
        !           847:
        !           848:        /*
        !           849:         * The SCSI-interrupts are disabled while a request is being handled.
        !           850:         */
        !           851:        scsi_idisable();
        !           852:
        !           853:        /*
        !           854:         * If we did not request ATN, then don't try to send IDENTIFY.
        !           855:         */
        !           856:        if (atn_flag == 0) {
        !           857:                reqp->phase = PH_CMD;
        !           858:                goto identify_failed;
        !           859:        }
        !           860:
        !           861:        /*
        !           862:         * Here we prepare to send an 'IDENTIFY' message.
        !           863:         * Allow disconnect only when interrupts are allowed.
        !           864:         */
        !           865:        tmp[0] = MSG_IDENTIFY(reqp->targ_lun,
        !           866:                        (reqp->dr_flag & DRIVER_NOINT) ? 0 : 1);
        !           867:        cnt    = 1;
        !           868:        phase  = PH_MSGOUT;
        !           869:
        !           870:        /*
        !           871:         * Since we followed the SCSI-spec and raised ATN while SEL was true
        !           872:         * but before BSY was false during the selection, a 'MESSAGE OUT'
        !           873:         * phase should follow.  Unfortunately, this does not happen on
        !           874:         * all targets (Asante ethernet devices, for example), so we must
        !           875:         * check the actual mode if the message transfer fails--if the
        !           876:         * new phase is PH_CMD and has never been successfully selected
        !           877:         * w/ATN in the past, then we assume that it is an old device
        !           878:         * that doesn't support select w/ATN.
        !           879:         */
        !           880:        if (transfer_pio(&phase, tmp, &cnt, 0) || cnt) {
        !           881:
        !           882:                if ((phase == PH_CMD) && !(sc->sc_selected & targ_bit)) {
        !           883:                        DBG_SELPRINT ("Target %d: not responding to ATN.\n",
        !           884:                                                        reqp->targ_id);
        !           885:                        sc->sc_noselatn |= targ_bit;
        !           886:                        reqp->phase = PH_CMD;
        !           887:                        goto identify_failed;
        !           888:                }
        !           889:
        !           890:                DBG_SELPRINT ("Target %d: failed to send identify\n",
        !           891:                                                        reqp->targ_id);
        !           892:                /*
        !           893:                 * Try to disconnect from the target.  We cannot leave
        !           894:                 * it just hanging here.
        !           895:                 */
        !           896:                if (!reach_msg_out(sc, sizeof(struct scsi_generic))) {
        !           897:                        u_long  len   = 1;
        !           898:                        u_char  phase = PH_MSGOUT;
        !           899:                        u_char  msg   = MSG_ABORT;
        !           900:
        !           901:                        transfer_pio(&phase, &msg, &len, 0);
        !           902:                }
        !           903:                else scsi_reset_verbose(sc, "Connected to unidentified target");
        !           904:
        !           905:                SET_5380_REG(NCR5380_ICOM, 0);
        !           906:                reqp->xs->error = code ? code : XS_DRIVER_STUFFUP;
        !           907:                finish_req(reqp);
        !           908:                PID("scsi_select9");
        !           909:                return (0);
        !           910:        }
        !           911:        reqp->phase = PH_MSGOUT;
        !           912:
        !           913: identify_failed:
        !           914:        sc->sc_selected |= targ_bit;
        !           915:
        !           916: #ifdef notyet /* LWP: Do we need timeouts in the driver? */
        !           917:        /*
        !           918:         * Command is connected, start timer ticking.
        !           919:         */
        !           920:        ccb_p->xtimeout = ccb_p->timeout + Lbolt;
        !           921: #endif
        !           922:
        !           923:        connected  = reqp;
        !           924:        busy      |= targ_bit;
        !           925:        PID("scsi_select10");
        !           926:        return (0);
        !           927: }
        !           928:
        !           929: /*
        !           930:  * Return codes:
        !           931:  *      0: Job has finished or disconnected, find something else
        !           932:  *     -1: keep on calling information_transfer() from scsi_main()
        !           933:  */
        !           934: static int
        !           935: information_transfer(sc)
        !           936: struct ncr_softc *sc;
        !           937: {
        !           938:        SC_REQ  *reqp = connected;
        !           939:        u_char  tmp, phase;
        !           940:        u_long  len;
        !           941:
        !           942:        PID("info_transf1");
        !           943:        /*
        !           944:         * Clear pending interrupts from 5380-chip.
        !           945:         */
        !           946:        scsi_clr_ipend();
        !           947:
        !           948:        /*
        !           949:         * The SCSI-spec requires BSY to be true while connected to a target,
        !           950:         * loosing it means we lost the target...
        !           951:         * Also REQ needs to be asserted here to indicate that the bus-phase
        !           952:         * is valid. When the target does not supply REQ within a 'reasonable'
        !           953:         * amount of time, it's probably lost in its own maze of twisting
        !           954:         * passages, we have to reset the bus to free it.
        !           955:         */
        !           956:        if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)
        !           957:                wait_req_true();
        !           958:        tmp = GET_5380_REG(NCR5380_IDSTAT);
        !           959:
        !           960:
        !           961:        if ((tmp & (SC_S_BSY|SC_S_REQ)) != (SC_S_BSY|SC_S_REQ)) {
        !           962:                busy           &= ~(1 << reqp->targ_id);
        !           963:                connected       = NULL;
        !           964:                reqp->xs->error = XS_TIMEOUT;
        !           965:                finish_req(reqp);
        !           966:                if (!(tmp & SC_S_REQ))
        !           967:                        scsi_reset_verbose(sc,
        !           968:                                           "Timeout waiting for phase-change");
        !           969:                PID("info_transf2");
        !           970:                return (0);
        !           971:        }
        !           972:
        !           973:        phase = (tmp >> 2) & 7;
        !           974:        if (phase != reqp->phase) {
        !           975:                reqp->phase = phase;
        !           976:                DBG_INFPRINT(show_phase, reqp, phase);
        !           977:        }
        !           978:        else {
        !           979:                /*
        !           980:                 * Same data-phase. If same error give up
        !           981:                 */
        !           982:                if ((reqp->msgout == MSG_ABORT)
        !           983:                     && ((phase == PH_DATAOUT) || (phase == PH_DATAIN))) {
        !           984:                        busy     &= ~(1 << reqp->targ_id);
        !           985:                        connected = NULL;
        !           986:                        finish_req(reqp);
        !           987:                        scsi_reset_verbose(sc, "Failure to abort command");
        !           988:                        return (0);
        !           989:                }
        !           990:        }
        !           991:
        !           992:        switch (phase) {
        !           993:            case PH_DATAOUT:
        !           994: #ifdef DBG_NOWRITE
        !           995:                ncr_tprint(reqp, "NOWRITE set -- write attempt aborted.");
        !           996:                reqp->msgout = MSG_ABORT;
        !           997:                SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
        !           998:                return (-1);
        !           999: #endif /* DBG_NOWRITE */
        !          1000:                /*
        !          1001:                 * If this is the first write using DMA, fill
        !          1002:                 * the bounce buffer.
        !          1003:                 */
        !          1004:                if (reqp->xdata_ptr == reqp->xs->data) { /* XXX */
        !          1005:                    if (reqp->dr_flag & DRIVER_BOUNCING)
        !          1006:                        bcopy(reqp->xdata_ptr, reqp->bounceb, reqp->xdata_len);
        !          1007:                }
        !          1008:
        !          1009:           case PH_DATAIN:
        !          1010:                if (reqp->xdata_len <= 0) {
        !          1011:                        /*
        !          1012:                         * Target keeps requesting data. Try to get into
        !          1013:                         * message-out phase by feeding/taking 100 byte.
        !          1014:                         */
        !          1015:                        ncr_tprint(reqp, "Target requests too much data\n");
        !          1016:                        reqp->msgout = MSG_ABORT;
        !          1017:                        SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
        !          1018:                        reach_msg_out(sc, 100);
        !          1019:                        return (-1);
        !          1020:                }
        !          1021: #ifdef REAL_DMA
        !          1022:                if (reqp->dr_flag & DRIVER_DMAOK) {
        !          1023:                        int poll = REAL_DMA_POLL|(reqp->dr_flag & DRIVER_NOINT);
        !          1024:                        transfer_dma(reqp, phase, poll);
        !          1025:                        if (!poll)
        !          1026:                                return (0);
        !          1027:                }
        !          1028:                else
        !          1029: #endif
        !          1030:                {
        !          1031:                        PID("info_transf3");
        !          1032:                        len = reqp->xdata_len;
        !          1033: #ifdef USE_PDMA
        !          1034:                        if (transfer_pdma(&phase, reqp->xdata_ptr, &len) == 0)
        !          1035:                                return (0);
        !          1036: #else
        !          1037:                        transfer_pio(&phase, reqp->xdata_ptr, &len, 0);
        !          1038: #endif
        !          1039:                        reqp->xdata_ptr += reqp->xdata_len - len;
        !          1040:                        reqp->xdata_len  = len;
        !          1041:                }
        !          1042:                return (-1);
        !          1043:           case PH_MSGIN:
        !          1044:                /*
        !          1045:                 * We only expect single byte messages here.
        !          1046:                 */
        !          1047:                len = 1;
        !          1048:                transfer_pio(&phase, &tmp, &len, 1);
        !          1049:                reqp->message = tmp;
        !          1050:                return (handle_message(reqp, tmp));
        !          1051:           case PH_MSGOUT:
        !          1052:                len = 1;
        !          1053:                transfer_pio(&phase, &reqp->msgout, &len, 0);
        !          1054:                if (reqp->msgout == MSG_ABORT) {
        !          1055:                        busy     &= ~(1 << reqp->targ_id);
        !          1056:                        connected = NULL;
        !          1057:                        if (!reqp->xs->error)
        !          1058:                                reqp->xs->error = XS_DRIVER_STUFFUP;
        !          1059:                        finish_req(reqp);
        !          1060:                        PID("info_transf4");
        !          1061:                        return (0);
        !          1062:                }
        !          1063:                reqp->msgout = MSG_NOOP;
        !          1064:                return (-1);
        !          1065:           case PH_CMD :
        !          1066:                len = command_size(reqp->xcmd.opcode);
        !          1067:                transfer_pio(&phase, (u_char *)&reqp->xcmd, &len, 0);
        !          1068:                PID("info_transf5");
        !          1069:                return (-1);
        !          1070:           case PH_STATUS:
        !          1071:                len = 1;
        !          1072:                transfer_pio(&phase, &tmp, &len, 0);
        !          1073:                reqp->status = tmp;
        !          1074:                PID("info_transf6");
        !          1075:                return (-1);
        !          1076:           default :
        !          1077:                ncr_tprint(reqp, "Unknown phase\n");
        !          1078:        }
        !          1079:        PID("info_transf7");
        !          1080:        return (-1);
        !          1081: }
        !          1082:
        !          1083: /*
        !          1084:  * Handle the message 'msg' send to us by the target.
        !          1085:  * Return values:
        !          1086:  *      0 : The current command has completed.
        !          1087:  *     -1 : Get on to the next phase.
        !          1088:  */
        !          1089: static int
        !          1090: handle_message(reqp, msg)
        !          1091: SC_REQ *reqp;
        !          1092: u_int  msg;
        !          1093: {
        !          1094:        int     sps;
        !          1095:        SC_REQ  *prev, *req;
        !          1096:
        !          1097:        PID("hmessage1");
        !          1098:        switch (msg) {
        !          1099:                /*
        !          1100:                 * Linking lets us reduce the time required to get
        !          1101:                 * the next command to the device, skipping the arbitration
        !          1102:                 * and selection time. In the current implementation,
        !          1103:                 * we merely have to start the next command pointed
        !          1104:                 * to by 'next_link'.
        !          1105:                 */
        !          1106:                case MSG_LINK_CMD_COMPLETE:
        !          1107:                case MSG_LINK_CMD_COMPLETEF:
        !          1108:                        if (reqp->link == NULL) {
        !          1109:                                ncr_tprint(reqp, "No link for linked command");
        !          1110:                                nack_message(reqp, MSG_ABORT);
        !          1111:                                PID("hmessage2");
        !          1112:                                return (-1);
        !          1113:                        }
        !          1114:                        ack_message();
        !          1115:                        if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
        !          1116:                                reqp->xs->resid = reqp->xdata_len;
        !          1117:                                reqp->xs->error = 0;
        !          1118:                        }
        !          1119:
        !          1120: #ifdef AUTO_SENSE
        !          1121:                        if (check_autosense(reqp, 1) == -1)
        !          1122:                                return (-1);
        !          1123: #endif /* AUTO_SENSE */
        !          1124:
        !          1125: #ifdef DBG_REQ
        !          1126:                        if (dbg_target_mask & (1 << reqp->targ_id))
        !          1127:                                show_request(reqp->link, "LINK");
        !          1128: #endif
        !          1129:                        connected = reqp->link;
        !          1130:
        !          1131:                        /*
        !          1132:                         * Unlink the 'linked' request from the issue_q
        !          1133:                         */
        !          1134:                        sps  = splbio();
        !          1135:                        prev = NULL;
        !          1136:                        req  = issue_q;
        !          1137:                        for (; req != NULL; prev = req, req = req->next) {
        !          1138:                                if (req == connected)
        !          1139:                                        break;
        !          1140:                        }
        !          1141:                        if (req == NULL)
        !          1142:                                panic("Inconsistent issue_q");
        !          1143:                        if (prev == NULL)
        !          1144:                                issue_q = req->next;
        !          1145:                        else prev->next = req->next;
        !          1146:                        req->next = NULL;
        !          1147:                        splx(sps);
        !          1148:
        !          1149:                        finish_req(reqp);
        !          1150:                        PID("hmessage3");
        !          1151:                        return (-1);
        !          1152:                case MSG_ABORT:
        !          1153:                case MSG_CMDCOMPLETE:
        !          1154:                        ack_message();
        !          1155:                        connected = NULL;
        !          1156:                        busy     &= ~(1 << reqp->targ_id);
        !          1157:                        if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
        !          1158:                                reqp->xs->resid = reqp->xdata_len;
        !          1159:                                reqp->xs->error = 0;
        !          1160:                        }
        !          1161:
        !          1162: #ifdef AUTO_SENSE
        !          1163:                        if (check_autosense(reqp, 0) == -1) {
        !          1164:                                PID("hmessage4");
        !          1165:                                return (0);
        !          1166:                        }
        !          1167: #endif /* AUTO_SENSE */
        !          1168:
        !          1169:                        finish_req(reqp);
        !          1170:                        PID("hmessage5");
        !          1171:                        return (0);
        !          1172:                case MSG_MESSAGE_REJECT:
        !          1173:                        ack_message();
        !          1174:                        PID("hmessage6");
        !          1175:                        return (-1);
        !          1176:                case MSG_DISCONNECT:
        !          1177:                        ack_message();
        !          1178: #ifdef DBG_REQ
        !          1179:                        if (dbg_target_mask & (1 << reqp->targ_id))
        !          1180:                                show_request(reqp, "DISCON");
        !          1181: #endif
        !          1182:                        sps = splbio();
        !          1183:                        connected  = NULL;
        !          1184:                        reqp->next = discon_q;
        !          1185:                        discon_q   = reqp;
        !          1186:                        splx(sps);
        !          1187:                        PID("hmessage7");
        !          1188:                        return (0);
        !          1189:                case MSG_SAVEDATAPOINTER:
        !          1190:                case MSG_RESTOREPOINTERS:
        !          1191:                        /*
        !          1192:                         * We save pointers implicitely at disconnect.
        !          1193:                         * So we can ignore these messages.
        !          1194:                         */
        !          1195:                        ack_message();
        !          1196:                        PID("hmessage8");
        !          1197:                        return (-1);
        !          1198:                case MSG_EXTENDED:
        !          1199:                        nack_message(reqp, MSG_MESSAGE_REJECT);
        !          1200:                        PID("hmessage9");
        !          1201:                        return (-1);
        !          1202:                default:
        !          1203:                        if ((msg & 0x80) && !(msg & 0x18)) {    /* IDENTIFY */
        !          1204:                                PID("hmessage10");
        !          1205:                                ack_message();
        !          1206:                                return (0);
        !          1207:                        } else {
        !          1208:                                ncr_tprint(reqp,
        !          1209:                                           "Unknown message %x.  Rejecting.\n",
        !          1210:                                           msg);
        !          1211:                                nack_message(reqp, MSG_MESSAGE_REJECT);
        !          1212:                        }
        !          1213:                        return (-1);
        !          1214:        }
        !          1215:        PID("hmessage11");
        !          1216:        return (-1);
        !          1217: }
        !          1218:
        !          1219: /*
        !          1220:  * Handle reselection. If a valid reconnection occurs, connected
        !          1221:  * points at the reconnected command. The command is removed from the
        !          1222:  * disconnected queue.
        !          1223:  */
        !          1224: static void
        !          1225: reselect(sc)
        !          1226: struct ncr_softc *sc;
        !          1227: {
        !          1228:        u_char  phase;
        !          1229:        u_long  len;
        !          1230:        u_char  msg;
        !          1231:        u_char  target_mask;
        !          1232:        int     abort = 0;
        !          1233:        SC_REQ  *tmp, *prev;
        !          1234:
        !          1235:        PID("reselect1");
        !          1236:        target_mask = GET_5380_REG(NCR5380_DATA) & ~SC_HOST_ID;
        !          1237:
        !          1238:        /*
        !          1239:         * At this point, we have detected that our SCSI-id is on the bus,
        !          1240:         * SEL is true and BSY was false for at least one bus settle
        !          1241:         * delay (400 ns.).
        !          1242:         * We must assert BSY ourselves, until the target drops the SEL signal.
        !          1243:         * The SCSI-spec specifies no maximum time for this, so we have to
        !          1244:         * choose something long enough to suit all targets.
        !          1245:         */
        !          1246:        SET_5380_REG(NCR5380_ICOM, SC_A_BSY);
        !          1247:        len = 250000;
        !          1248:        while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) && (len > 0)) {
        !          1249:                delay(1);
        !          1250:                len--;
        !          1251:        }
        !          1252:        if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) {
        !          1253:                /* Damn SEL isn't dropping */
        !          1254:                scsi_reset_verbose(sc, "Target won't drop SEL during Reselect");
        !          1255:                return;
        !          1256:        }
        !          1257:
        !          1258:        SET_5380_REG(NCR5380_ICOM, 0);
        !          1259:
        !          1260:        /*
        !          1261:         * Check if the reselection is still valid. Check twice because
        !          1262:         * of possible line glitches - cheaper than delay(1) and we need
        !          1263:         * only a few nanoseconds.
        !          1264:         */
        !          1265:        if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
        !          1266:            if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) {
        !          1267:                ncr_aprint(sc, "Stepped into the reselection timeout\n");
        !          1268:                return;
        !          1269:            }
        !          1270:        }
        !          1271:
        !          1272:        /*
        !          1273:         * Get the expected identify message.
        !          1274:         */
        !          1275:        phase = PH_MSGIN;
        !          1276:        len   = 1;
        !          1277:        transfer_pio(&phase, &msg, &len, 0);
        !          1278:        if (len || !MSG_ISIDENTIFY(msg)) {
        !          1279:                ncr_aprint(sc, "Expecting IDENTIFY, got 0x%x\n", msg);
        !          1280:                abort = 1;
        !          1281:                tmp = NULL;
        !          1282:        }
        !          1283:        else {
        !          1284:            /*
        !          1285:             * Find the command reconnecting
        !          1286:             */
        !          1287:            for (tmp = discon_q, prev = NULL; tmp; prev = tmp, tmp = tmp->next){
        !          1288:                if (target_mask == (1 << tmp->targ_id)) {
        !          1289:                        if (prev)
        !          1290:                                prev->next = tmp->next;
        !          1291:                        else discon_q = tmp->next;
        !          1292:                        tmp->next = NULL;
        !          1293:                        break;
        !          1294:                }
        !          1295:            }
        !          1296:            if (tmp == NULL) {
        !          1297:                ncr_aprint(sc, "No disconnected job for targetmask %x\n",
        !          1298:                                                                target_mask);
        !          1299:                abort = 1;
        !          1300:            }
        !          1301:        }
        !          1302:        if (abort) {
        !          1303:                msg   = MSG_ABORT;
        !          1304:                len   = 1;
        !          1305:                phase = PH_MSGOUT;
        !          1306:
        !          1307:                SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
        !          1308:                if (transfer_pio(&phase, &msg, &len, 0) || len)
        !          1309:                        scsi_reset_verbose(sc, "Failure to abort reselection");
        !          1310:        }
        !          1311:        else {
        !          1312:                connected = tmp;
        !          1313: #ifdef DBG_REQ
        !          1314:                if (dbg_target_mask & (1 << tmp->targ_id))
        !          1315:                        show_request(tmp, "RECON");
        !          1316: #endif
        !          1317:        }
        !          1318:        PID("reselect2");
        !          1319: }
        !          1320:
        !          1321: /*
        !          1322:  * Transfer data in a given phase using programmed I/O.
        !          1323:  * Returns -1 when a different phase is entered without transferring the
        !          1324:  * maximum number of bytes, 0 if all bytes transferred or exit is in the same
        !          1325:  * phase.
        !          1326:  */
        !          1327: static int
        !          1328: transfer_pio(phase, data, len, dont_drop_ack)
        !          1329: u_char *phase;
        !          1330: u_char *data;
        !          1331: u_long *len;
        !          1332: int    dont_drop_ack;
        !          1333: {
        !          1334:        u_int   cnt = *len;
        !          1335:        u_char  ph  = *phase;
        !          1336:        u_char  tmp, new_icom;
        !          1337:
        !          1338:        DBG_PIOPRINT ("SCSI: transfer_pio start: phase: %d, len: %d\n", ph,cnt);
        !          1339:        PID("tpio1");
        !          1340:        SET_5380_REG(NCR5380_TCOM, ph);
        !          1341:        do {
        !          1342:            if (!wait_req_true()) {
        !          1343:                DBG_PIOPRINT ("SCSI: transfer_pio: missing REQ\n", 0, 0);
        !          1344:                break;
        !          1345:            }
        !          1346:            if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != ph) {
        !          1347:                DBG_PIOPRINT ("SCSI: transfer_pio: phase mismatch\n", 0, 0);
        !          1348:                break;
        !          1349:            }
        !          1350:            if (PH_IN(ph)) {
        !          1351:                *data++ = GET_5380_REG(NCR5380_DATA);
        !          1352:                SET_5380_REG(NCR5380_ICOM, SC_A_ACK);
        !          1353:                if ((cnt == 1) && dont_drop_ack)
        !          1354:                        new_icom = SC_A_ACK;
        !          1355:                else new_icom = 0;
        !          1356:            }
        !          1357:            else {
        !          1358:                SET_5380_REG(NCR5380_DATA, *data++);
        !          1359:
        !          1360:                /*
        !          1361:                 * The SCSI-standard suggests that in the 'MESSAGE OUT' phase,
        !          1362:                 * the initiator should drop ATN on the last byte of the
        !          1363:                 * message phase after REQ has been asserted for the handshake
        !          1364:                 * but before the initiator raises ACK.
        !          1365:                 */
        !          1366:                if (!( (ph == PH_MSGOUT) && (cnt > 1) )) {
        !          1367:                        SET_5380_REG(NCR5380_ICOM, SC_ADTB);
        !          1368:                        SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ACK);
        !          1369:                        new_icom = 0;
        !          1370:                }
        !          1371:                else {
        !          1372:                        SET_5380_REG(NCR5380_ICOM, SC_ADTB | SC_A_ATN);
        !          1373:                        SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ATN|SC_A_ACK);
        !          1374:                        new_icom = SC_A_ATN;
        !          1375:                }
        !          1376:            }
        !          1377:            if (!wait_req_false()) {
        !          1378:                DBG_PIOPRINT ("SCSI: transfer_pio - REQ not dropping\n", 0, 0);
        !          1379:                break;
        !          1380:            }
        !          1381:            SET_5380_REG(NCR5380_ICOM, new_icom);
        !          1382:
        !          1383:        } while (--cnt);
        !          1384:
        !          1385:        if ((tmp = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
        !          1386:                *phase = (tmp >> 2) & 7;
        !          1387:        else *phase = NR_PHASE;
        !          1388:        *len = cnt;
        !          1389:        DBG_PIOPRINT ("SCSI: transfer_pio done: phase: %d, len: %d\n",
        !          1390:                                                                *phase, cnt);
        !          1391:        PID("tpio2");
        !          1392:        if (!cnt || (*phase == ph))
        !          1393:                return (0);
        !          1394:        return (-1);
        !          1395: }
        !          1396:
        !          1397: #ifdef REAL_DMA
        !          1398: /*
        !          1399:  * Start a DMA-transfer on the device using the current pointers.
        !          1400:  * If 'poll' is true, the function busy-waits until DMA has completed.
        !          1401:  */
        !          1402: static void
        !          1403: transfer_dma(reqp, phase, poll)
        !          1404: SC_REQ *reqp;
        !          1405: u_int  phase;
        !          1406: int    poll;
        !          1407: {
        !          1408:        int     dma_done;
        !          1409:        u_char  mbase = 0;
        !          1410:        int     sps;
        !          1411:
        !          1412: again:
        !          1413:        PID("tdma1");
        !          1414:
        !          1415:        /*
        !          1416:         * We should be in phase, otherwise we are not allowed to
        !          1417:         * drive the bus.
        !          1418:         */
        !          1419:        SET_5380_REG(NCR5380_TCOM, phase);
        !          1420:
        !          1421:        /*
        !          1422:         * Defer interrupts until DMA is fully running.
        !          1423:         */
        !          1424:        sps = splbio();
        !          1425:
        !          1426:        /*
        !          1427:         * Clear pending interrupts and parity errors.
        !          1428:         */
        !          1429:        scsi_clr_ipend();
        !          1430:
        !          1431:        if (!poll) {
        !          1432:                /*
        !          1433:                 * Enable SCSI interrupts and set IN_DMA flag, set 'mbase'
        !          1434:                 * to the interrupts we want enabled.
        !          1435:                 */
        !          1436:                scsi_ienable();
        !          1437:                reqp->dr_flag |= DRIVER_IN_DMA;
        !          1438:                mbase = SC_E_EOPI | SC_MON_BSY;
        !          1439:        }
        !          1440:        else scsi_idisable();
        !          1441:        mbase |=  IMODE_BASE | SC_M_DMA;
        !          1442:        scsi_dma_setup(reqp, phase, mbase);
        !          1443:
        !          1444:        splx(sps);
        !          1445:
        !          1446:        if (poll) {
        !          1447:                /*
        !          1448:                 * On polled-dma transfers, we wait here until the
        !          1449:                 * 'end-of-dma' condition occurs.
        !          1450:                 */
        !          1451:                poll_edma(reqp);
        !          1452:                if (!(dma_done = dma_ready()))
        !          1453:                        goto again;
        !          1454:        }
        !          1455:        PID("tdma2");
        !          1456: }
        !          1457:
        !          1458: /*
        !          1459:  * Check results of a DMA data-transfer.
        !          1460:  */
        !          1461: static int
        !          1462: dma_ready()
        !          1463: {
        !          1464:        SC_REQ  *reqp = connected;
        !          1465:        int     dmstat, is_edma;
        !          1466:        long    bytes_left, bytes_done;
        !          1467:
        !          1468:        is_edma = get_dma_result(reqp, &bytes_left);
        !          1469:        dmstat  = GET_5380_REG(NCR5380_DMSTAT);
        !          1470:
        !          1471:        /*
        !          1472:         * Check if the call is sensible and not caused by any spurious
        !          1473:         * interrupt.
        !          1474:         */
        !          1475:        if (!is_edma && !(dmstat & (SC_END_DMA|SC_BSY_ERR))
        !          1476:                     && (dmstat & SC_PHS_MTCH) ) {
        !          1477:                ncr_tprint(reqp, "dma_ready: spurious call "
        !          1478:                                 "(dm:%x,last_hit: %s)\n",
        !          1479: #ifdef DBG_PID
        !          1480:                                        dmstat, last_hit[DBG_PID-1]);
        !          1481: #else
        !          1482:                                        dmstat, "unknown");
        !          1483: #endif
        !          1484:                return (0);
        !          1485:        }
        !          1486:
        !          1487:        /*
        !          1488:         * Clear all (pending) interrupts.
        !          1489:         */
        !          1490:        scsi_clr_ipend();
        !          1491:
        !          1492:        /*
        !          1493:         * Update various transfer-pointers/lengths
        !          1494:         */
        !          1495:        bytes_done = reqp->dm_cur->dm_count - bytes_left;
        !          1496:
        !          1497:        if ((reqp->dr_flag & DRIVER_BOUNCING) && (PH_IN(reqp->phase))) {
        !          1498:                /*
        !          1499:                 * Copy the bytes read until now from the bounce buffer
        !          1500:                 * to the 'real' destination. Flush the data-cache
        !          1501:                 * before copying.
        !          1502:                 */
        !          1503:                PCIA();
        !          1504:                bcopy(reqp->bouncerp, reqp->xdata_ptr, bytes_done);
        !          1505:                reqp->bouncerp += bytes_done;
        !          1506:        }
        !          1507:
        !          1508:        reqp->xdata_ptr  = &reqp->xdata_ptr[bytes_done];        /* XXX */
        !          1509:        reqp->xdata_len -= bytes_done;                          /* XXX */
        !          1510:        if ((reqp->dm_cur->dm_count -= bytes_done) == 0)
        !          1511:                reqp->dm_cur++;
        !          1512:        else reqp->dm_cur->dm_addr += bytes_done;
        !          1513:
        !          1514:        if (PH_IN(reqp->phase) && (dmstat & SC_PAR_ERR)) {
        !          1515:                if (!(ncr5380_no_parchk & (1 << reqp->targ_id))) {
        !          1516:                        ncr_tprint(reqp, "parity error in data-phase\n");
        !          1517:                        reqp->xs->error = XS_TIMEOUT;
        !          1518:                }
        !          1519:        }
        !          1520:
        !          1521:        /*
        !          1522:         * DMA mode should always be reset even when we will continue with the
        !          1523:         * next chain. It is also essential to clear the MON_BUSY because
        !          1524:         * when LOST_BUSY is unexpectedly set, we will not be able to drive
        !          1525:         * the bus....
        !          1526:         */
        !          1527:        SET_5380_REG(NCR5380_MODE, IMODE_BASE);
        !          1528:
        !          1529:
        !          1530:        if ((dmstat & SC_BSY_ERR) || !(dmstat & SC_PHS_MTCH)
        !          1531:                 || (reqp->dm_cur > reqp->dm_last) || (reqp->xs->error)) {
        !          1532:
        !          1533:                /*
        !          1534:                 * Tell interrupt functions DMA mode has ended.
        !          1535:                 */
        !          1536:                reqp->dr_flag &= ~DRIVER_IN_DMA;
        !          1537:
        !          1538:                /*
        !          1539:                 * Clear mode and icom
        !          1540:                 */
        !          1541:                SET_5380_REG(NCR5380_MODE, IMODE_BASE);
        !          1542:                SET_5380_REG(NCR5380_ICOM, 0);
        !          1543:
        !          1544:                if (dmstat & SC_BSY_ERR) {
        !          1545:                        if (!reqp->xs->error)
        !          1546:                                reqp->xs->error = XS_TIMEOUT;
        !          1547:                        finish_req(reqp);
        !          1548:                        PID("dma_ready1");
        !          1549:                        return (1);
        !          1550:                }
        !          1551:
        !          1552:                if (reqp->xs->error != 0) {
        !          1553: ncr_tprint(reqp, "dma-ready: code = %d\n", reqp->xs->error); /* LWP */
        !          1554:                        reqp->msgout = MSG_ABORT;
        !          1555:                        SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
        !          1556:                }
        !          1557:                PID("dma_ready2");
        !          1558:                return (1);
        !          1559:        }
        !          1560:        return (0);
        !          1561: }
        !          1562: #endif /* REAL_DMA */
        !          1563:
        !          1564: static int
        !          1565: check_autosense(reqp, linked)
        !          1566: SC_REQ *reqp;
        !          1567: int    linked;
        !          1568: {
        !          1569:        int     sps;
        !          1570:
        !          1571:        /*
        !          1572:         * If we not executing an auto-sense and the status code
        !          1573:         * is request-sense, we automatically issue a request
        !          1574:         * sense command.
        !          1575:         */
        !          1576:        PID("cautos1");
        !          1577:        if (!(reqp->dr_flag & DRIVER_AUTOSEN)) {
        !          1578:                switch (reqp->status & SCSMASK) {
        !          1579:                    case SCSCHKC:
        !          1580:                        bcopy(sense_cmd, &reqp->xcmd, sizeof(sense_cmd));
        !          1581:                        reqp->xdata_ptr = (u_char *)&reqp->xs->sense;
        !          1582:                        reqp->xdata_len = sizeof(reqp->xs->sense);
        !          1583:                        reqp->dr_flag  |= DRIVER_AUTOSEN;
        !          1584:                        reqp->dr_flag  &= ~DRIVER_DMAOK;
        !          1585:                        if (!linked) {
        !          1586:                                sps = splbio();
        !          1587:                                reqp->next = issue_q;
        !          1588:                                issue_q    = reqp;
        !          1589:                                splx(sps);
        !          1590:                        }
        !          1591:                        else reqp->xcmd.bytes[sizeof(sense_cmd)-2] |= 1;
        !          1592:
        !          1593: #ifdef DBG_REQ
        !          1594:                        bzero(reqp->xdata_ptr, reqp->xdata_len);
        !          1595:                        if (dbg_target_mask & (1 << reqp->targ_id))
        !          1596:                                show_request(reqp, "AUTO-SENSE");
        !          1597: #endif
        !          1598:                        PID("cautos2");
        !          1599:                        return (-1);
        !          1600:                    case SCSBUSY:
        !          1601:                        reqp->xs->error = XS_BUSY;
        !          1602:                        return (0);
        !          1603:                }
        !          1604:        }
        !          1605:        else {
        !          1606:                /*
        !          1607:                 * An auto-sense has finished
        !          1608:                 */
        !          1609:                if ((reqp->status & SCSMASK) != SCSGOOD)
        !          1610:                        reqp->xs->error = XS_DRIVER_STUFFUP; /* SC_E_AUTOSEN; */
        !          1611:                else reqp->xs->error = XS_SENSE;
        !          1612:                reqp->status = SCSCHKC;
        !          1613:        }
        !          1614:        PID("cautos3");
        !          1615:        return (0);
        !          1616: }
        !          1617:
        !          1618: static int
        !          1619: reach_msg_out(sc, len)
        !          1620: struct ncr_softc *sc;
        !          1621: u_long          len;
        !          1622: {
        !          1623:        u_char  phase;
        !          1624:        u_char  data;
        !          1625:        u_long  n = len;
        !          1626:
        !          1627:        ncr_aprint(sc, "Trying to reach Message-out phase\n");
        !          1628:        if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ)
        !          1629:                phase = (phase >> 2) & 7;
        !          1630:        else return (-1);
        !          1631:        ncr_aprint(sc, "Trying to reach Message-out phase, now: %d\n", phase);
        !          1632:        if (phase == PH_MSGOUT)
        !          1633:                return (0);
        !          1634:
        !          1635:        SET_5380_REG(NCR5380_TCOM, phase);
        !          1636:
        !          1637:        do {
        !          1638:                if (!wait_req_true())
        !          1639:                        break;
        !          1640:                if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != phase)
        !          1641:                        break;
        !          1642:                if (PH_IN(phase)) {
        !          1643:                        data = GET_5380_REG(NCR5380_DATA);
        !          1644:                        SET_5380_REG(NCR5380_ICOM, SC_A_ACK | SC_A_ATN);
        !          1645:                }
        !          1646:                else {
        !          1647:                        SET_5380_REG(NCR5380_DATA, 0);
        !          1648:                        SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ACK|SC_A_ATN);
        !          1649:                }
        !          1650:                if (!wait_req_false())
        !          1651:                        break;
        !          1652:                SET_5380_REG(NCR5380_ICOM, SC_A_ATN);
        !          1653:        } while (--n);
        !          1654:
        !          1655:        if ((phase = GET_5380_REG(NCR5380_IDSTAT)) & SC_S_REQ) {
        !          1656:                phase = (phase >> 2) & 7;
        !          1657:                if (phase == PH_MSGOUT) {
        !          1658:                        ncr_aprint(sc, "Message-out phase reached after "
        !          1659:                                        "%ld bytes.\n", len - n);
        !          1660:                        return (0);
        !          1661:                }
        !          1662:        }
        !          1663:        return (-1);
        !          1664: }
        !          1665:
        !          1666: void
        !          1667: scsi_reset()
        !          1668: {
        !          1669:        SC_REQ  *tmp, *next;
        !          1670:        int     sps;
        !          1671:
        !          1672:        PID("scsi_reset1");
        !          1673:        sps = splbio();
        !          1674:        SET_5380_REG(NCR5380_ICOM, SC_A_RST);
        !          1675:        delay(100);
        !          1676:        SET_5380_REG(NCR5380_ICOM, 0);
        !          1677:        scsi_clr_ipend();
        !          1678:
        !          1679:        /*
        !          1680:         * None of the jobs in the discon_q will ever be reconnected,
        !          1681:         * notify this to the higher level code.
        !          1682:         */
        !          1683:        for (tmp = discon_q; tmp ;) {
        !          1684:                next = tmp->next;
        !          1685:                tmp->next = NULL;
        !          1686:                tmp->xs->error = XS_TIMEOUT;
        !          1687:                busy &= ~(1 << tmp->targ_id);
        !          1688:                finish_req(tmp);
        !          1689:                tmp = next;
        !          1690:        }
        !          1691:        discon_q = NULL;
        !          1692:
        !          1693:        /*
        !          1694:         * The current job will never finish either.
        !          1695:         * The problem is that we can't finish the job because an instance
        !          1696:         * of main is running on it. Our best guess is that the job is currently
        !          1697:         * doing REAL-DMA. In that case 'dma_ready()' should correctly finish
        !          1698:         * the job because it detects BSY-loss.
        !          1699:         */
        !          1700:        if ((tmp = connected) != NULL) {
        !          1701:                if (tmp->dr_flag & DRIVER_IN_DMA) {
        !          1702:                        tmp->xs->error = XS_DRIVER_STUFFUP;
        !          1703: #ifdef REAL_DMA
        !          1704:                        dma_ready();
        !          1705: #endif
        !          1706:                }
        !          1707:        }
        !          1708:        splx(sps);
        !          1709:        PID("scsi_reset2");
        !          1710:
        !          1711:        /*
        !          1712:         * Give the attached devices some time to handle the reset. This
        !          1713:         * value is arbitrary but should be relatively long.
        !          1714:         */
        !          1715:        delay(100000);
        !          1716: }
        !          1717:
        !          1718: static void
        !          1719: scsi_reset_verbose(sc, why)
        !          1720: struct ncr_softc *sc;
        !          1721: const char      *why;
        !          1722: {
        !          1723:        ncr_aprint(sc, "Resetting SCSI-bus (%s)\n", why);
        !          1724:
        !          1725:        scsi_reset();
        !          1726: }
        !          1727:
        !          1728: /*
        !          1729:  * Check validity of the IRQ set by the 5380. If the interrupt is valid,
        !          1730:  * the appropriate action is carried out (reselection or DMA ready) and
        !          1731:  * INTR_RESEL or INTR_DMA is returned. Otherwise a console notice is written
        !          1732:  * and INTR_SPURIOUS is returned.
        !          1733:  */
        !          1734: static int
        !          1735: check_intr(sc)
        !          1736: struct ncr_softc *sc;
        !          1737: {
        !          1738:        SC_REQ  *reqp;
        !          1739:
        !          1740:        if ((GET_5380_REG(NCR5380_IDSTAT) & (SC_S_SEL|SC_S_IO))
        !          1741:                                                        ==(SC_S_SEL|SC_S_IO))
        !          1742:                return (INTR_RESEL);
        !          1743:        else {
        !          1744:                if ((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)){
        !          1745:                        reqp->dr_flag &= ~DRIVER_IN_DMA;
        !          1746:                        return (INTR_DMA);
        !          1747:                }
        !          1748:        }
        !          1749:        scsi_clr_ipend();
        !          1750:        printf("-->");
        !          1751:        scsi_show();
        !          1752:        ncr_aprint(sc, "Spurious interrupt.\n");
        !          1753:        return (INTR_SPURIOUS);
        !          1754: }
        !          1755:
        !          1756: #ifdef REAL_DMA
        !          1757: /*
        !          1758:  * Check if DMA can be used for this request. This function also builds
        !          1759:  * the dma-chain.
        !          1760:  */
        !          1761: static int
        !          1762: scsi_dmaok(reqp)
        !          1763: SC_REQ *reqp;
        !          1764: {
        !          1765:        u_long                  phy_buf;
        !          1766:        u_long                  phy_len;
        !          1767:        void                    *req_addr;
        !          1768:        u_long                  req_len;
        !          1769:        struct dma_chain        *dm;
        !          1770:
        !          1771:        /*
        !          1772:         * Initialize locals and requests' DMA-chain.
        !          1773:         */
        !          1774:        req_len        = reqp->xdata_len;
        !          1775:        req_addr       = (void *)reqp->xdata_ptr;
        !          1776:        dm             = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
        !          1777:        dm->dm_count   = dm->dm_addr = 0;
        !          1778:        reqp->dr_flag &= ~DRIVER_BOUNCING;
        !          1779:
        !          1780:        /*
        !          1781:         * Do not accept zero length DMA.
        !          1782:         */
        !          1783:        if (req_len == 0)
        !          1784:                return (0);
        !          1785:
        !          1786:        /*
        !          1787:         * LWP: I think that this restriction is not strictly necessary.
        !          1788:         */
        !          1789:        if ((req_len & 0x1) || ((u_int)req_addr & 0x3))
        !          1790:                return (0);
        !          1791:
        !          1792:        /*
        !          1793:         * Build the DMA-chain.
        !          1794:         */
        !          1795:        dm->dm_addr = phy_buf = kvtop(req_addr);
        !          1796:        while (req_len) {
        !          1797:                if (req_len < (phy_len = NBPG - m68k_page_offset(req_addr)))
        !          1798:                        phy_len = req_len;
        !          1799:
        !          1800:                req_addr     += phy_len;
        !          1801:                req_len      -= phy_len;
        !          1802:                dm->dm_count += phy_len;
        !          1803:
        !          1804:                if (req_len) {
        !          1805:                        u_long  tmp = kvtop(req_addr);
        !          1806:
        !          1807:                        if ((phy_buf + phy_len) != tmp) {
        !          1808:                            if (wrong_dma_range(reqp, dm)) {
        !          1809:                                if (reqp->dr_flag & DRIVER_BOUNCING)
        !          1810:                                        goto bounceit;
        !          1811:                                return (0);
        !          1812:                            }
        !          1813:
        !          1814:                            if (++dm >= &reqp->dm_chain[MAXDMAIO]) {
        !          1815:                                ncr_tprint(reqp,"dmaok: DMA chain too long!\n");
        !          1816:                                return (0);
        !          1817:                            }
        !          1818:                            dm->dm_count = 0;
        !          1819:                            dm->dm_addr  = tmp;
        !          1820:                        }
        !          1821:                        phy_buf = tmp;
        !          1822:                }
        !          1823:        }
        !          1824:         if (wrong_dma_range(reqp, dm)) {
        !          1825:                if (reqp->dr_flag & DRIVER_BOUNCING)
        !          1826:                        goto bounceit;
        !          1827:                return (0);
        !          1828:        }
        !          1829:        reqp->dm_last = dm;
        !          1830:        return (1);
        !          1831:
        !          1832: bounceit:
        !          1833:        if ((reqp->bounceb = alloc_bounceb(reqp->xdata_len)) == NULL) {
        !          1834:                /*
        !          1835:                 * If we can't get a bounce buffer, forget DMA
        !          1836:                 */
        !          1837:                reqp->dr_flag &= ~DRIVER_BOUNCING;
        !          1838:                return(0);
        !          1839:        }
        !          1840:        /*
        !          1841:         * Initialize a single DMA-range containing the bounced request
        !          1842:         */
        !          1843:        dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
        !          1844:        dm->dm_addr    = kvtop(reqp->bounceb);
        !          1845:        dm->dm_count   = reqp->xdata_len;
        !          1846:        reqp->bouncerp = reqp->bounceb;
        !          1847:
        !          1848:        return (1);
        !          1849: }
        !          1850: #endif /* REAL_DMA */
        !          1851:
        !          1852: static void
        !          1853: run_main(sc)
        !          1854: struct ncr_softc *sc;
        !          1855: {
        !          1856:        int     sps = splbio();
        !          1857:
        !          1858:        if (!main_running) {
        !          1859:                /*
        !          1860:                 * If shared resources are required, claim them
        !          1861:                 * before entering 'scsi_main'. If we can't get them
        !          1862:                 * now, assume 'run_main' will be called when the resource
        !          1863:                 * becomes available.
        !          1864:                 */
        !          1865:                if (!claimed_dma()) {
        !          1866:                        splx(sps);
        !          1867:                        return;
        !          1868:                }
        !          1869:                main_running = 1;
        !          1870:                splx(sps);
        !          1871:                scsi_main(sc);
        !          1872:        }
        !          1873:        else splx(sps);
        !          1874: }
        !          1875:
        !          1876: /*
        !          1877:  * Prefix message with full target info.
        !          1878:  */
        !          1879: static void
        !          1880: ncr_tprint(SC_REQ *reqp, char *fmt, ...)
        !          1881: {
        !          1882:        va_list ap;
        !          1883:
        !          1884:        sc_print_addr(reqp->xs->sc_link);
        !          1885:        va_start(ap, fmt);
        !          1886:        vprintf(fmt, ap);
        !          1887:        va_end(ap);
        !          1888: }
        !          1889:
        !          1890: /*
        !          1891:  * Prefix message with adapter info.
        !          1892:  */
        !          1893: static void
        !          1894: ncr_aprint(struct ncr_softc *sc, char *fmt, ...)
        !          1895: {
        !          1896:        va_list ap;
        !          1897:
        !          1898:        printf("%s: ", sc->sc_dev.dv_xname);
        !          1899:        va_start(ap, fmt);
        !          1900:        vprintf(fmt, ap);
        !          1901:        va_end(ap);
        !          1902: }
        !          1903: /****************************************************************************
        !          1904:  *             Start Debugging Functions                                   *
        !          1905:  ****************************************************************************/
        !          1906: static void
        !          1907: show_data_sense(xs)
        !          1908: struct scsi_xfer       *xs;
        !          1909: {
        !          1910:        u_char  *p1, *p2;
        !          1911:        int     i;
        !          1912:        int     sz;
        !          1913:
        !          1914:        p1 = (u_char *) xs->cmd;
        !          1915:        p2 = (u_char *)&xs->sense;
        !          1916:        if(*p2 == 0)
        !          1917:                return; /* No(n)sense */
        !          1918:        printf("cmd[%d,%d]: ", xs->cmdlen, sz = command_size(*p1));
        !          1919:        for (i = 0; i < sz; i++)
        !          1920:                printf("%x ", p1[i]);
        !          1921:        printf("\nsense: ");
        !          1922:        for (i = 0; i < sizeof(xs->sense); i++)
        !          1923:                printf("%x ", p2[i]);
        !          1924:        printf("\n");
        !          1925: }
        !          1926:
        !          1927: static void
        !          1928: show_request(reqp, qtxt)
        !          1929: SC_REQ *reqp;
        !          1930: char   *qtxt;
        !          1931: {
        !          1932:        printf("REQ-%s: %d %p[%ld] cmd[0]=%x S=%x M=%x R=%x resid=%d dr_flag=%x %s\n",
        !          1933:                        qtxt, reqp->targ_id, reqp->xdata_ptr, reqp->xdata_len,
        !          1934:                        reqp->xcmd.opcode, reqp->status, reqp->message,
        !          1935:                        reqp->xs->error, reqp->xs->resid, reqp->dr_flag,
        !          1936:                        reqp->link ? "L":"");
        !          1937:        if (reqp->status == SCSCHKC)
        !          1938:                show_data_sense(reqp->xs);
        !          1939: }
        !          1940:
        !          1941: static char *sig_names[] = {
        !          1942:        "PAR", "SEL", "I/O", "C/D", "MSG", "REQ", "BSY", "RST",
        !          1943:        "ACK", "ATN", "LBSY", "PMATCH", "IRQ", "EPAR", "DREQ", "EDMA"
        !          1944: };
        !          1945:
        !          1946: static void
        !          1947: show_signals(dmstat, idstat)
        !          1948: u_char dmstat, idstat;
        !          1949: {
        !          1950:        u_short tmp, mask;
        !          1951:        int     j, need_pipe;
        !          1952:
        !          1953:        tmp = idstat | ((dmstat & 3) << 8);
        !          1954:        printf("Bus signals (%02x/%02x): ", idstat, dmstat & 3);
        !          1955:        for (mask = 1, j = need_pipe = 0; mask <= tmp; mask <<= 1, j++) {
        !          1956:                if (tmp & mask)
        !          1957:                        printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
        !          1958:        }
        !          1959:        printf("\nDma status (%02x): ", dmstat);
        !          1960:        for (mask = 4, j = 10, need_pipe = 0; mask <= dmstat; mask <<= 1, j++) {
        !          1961:                if (dmstat & mask)
        !          1962:                        printf("%s%s", need_pipe++ ? "|" : "", sig_names[j]);
        !          1963:        }
        !          1964:        printf("\n");
        !          1965: }
        !          1966:
        !          1967: void
        !          1968: scsi_show()
        !          1969: {
        !          1970:        SC_REQ  *tmp;
        !          1971:        int     sps = splhigh();
        !          1972:        u_char  idstat, dmstat;
        !          1973: #ifdef DBG_PID
        !          1974:        int     i;
        !          1975: #endif
        !          1976:
        !          1977:        printf("scsi_show: scsi_main is%s running\n",
        !          1978:                main_running ? "" : " not");
        !          1979:        for (tmp = issue_q; tmp; tmp = tmp->next)
        !          1980:                show_request(tmp, "ISSUED");
        !          1981:        for (tmp = discon_q; tmp; tmp = tmp->next)
        !          1982:                show_request(tmp, "DISCONNECTED");
        !          1983:        if (connected)
        !          1984:                show_request(connected, "CONNECTED");
        !          1985:        idstat = GET_5380_REG(NCR5380_IDSTAT);
        !          1986:        dmstat = GET_5380_REG(NCR5380_DMSTAT);
        !          1987:        show_signals(dmstat, idstat);
        !          1988:        if (connected)
        !          1989:                printf("phase = %d, ", connected->phase);
        !          1990:        printf("busy:%x, spl:%04x\n", busy, sps);
        !          1991: #ifdef DBG_PID
        !          1992:        for (i=0; i<DBG_PID; i++)
        !          1993:                printf("\t%d\t%s\n", i, last_hit[i]);
        !          1994: #endif
        !          1995:
        !          1996:        splx(sps);
        !          1997: }

CVSweb