Annotation of researchv9/sys/sundev/si.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)si.c 1.1 86/02/03 Copyr 1985 Sun Micro";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             7:  */
        !             8: 
        !             9: #include "si.h"
        !            10: 
        !            11: #if NSI > 0
        !            12: /*
        !            13:  * Generic scsi routines.
        !            14:  */
        !            15:  
        !            16: #include "../h/param.h"
        !            17: #include "../h/systm.h"
        !            18: #include "../h/dk.h"
        !            19: #include "../h/buf.h"
        !            20: #include "../h/conf.h"
        !            21: #include "../h/dir.h"
        !            22: #include "../h/user.h"
        !            23: #include "../h/map.h"
        !            24: #include "../h/vmmac.h"
        !            25: /*
        !            26:  *#include "../h/ioctl.h"
        !            27:  *#include "../h/uio.h"
        !            28:  *#include "../h/kernel.h"
        !            29: */
        !            30: #include "../h/dkbad.h"
        !            31: 
        !            32: #include "../machine/pte.h"
        !            33: #include "../machine/psl.h"
        !            34: #include "../machine/mmu.h"
        !            35: #include "../machine/cpu.h"
        !            36: #include "../machine/scb.h"
        !            37: 
        !            38: #include "../sun/dklabel.h"
        !            39: #include "../sun/dkio.h"
        !            40: 
        !            41: #include "../sundev/mbvar.h"
        !            42: #include "../sundev/screg.h"
        !            43: #include "../sundev/sireg.h"
        !            44: #include "../sundev/scsi.h"
        !            45: 
        !            46: struct scsi_ctlr sictlrs[NSI];
        !            47: #define SINUM(si)      (si - sictlrs)
        !            48: 
        !            49: int    siprobe(), sislave(), siattach(), sigo(), sidone(), sipoll();
        !            50: int    siustart(), sistart(), si_getstatus();
        !            51: int    si_off(), si_cmd(), si_cmdwait(), si_reset(), si_dmacnt();
        !            52: 
        !            53: struct mb_ctlr *siinfo[NSI];
        !            54: extern struct mb_device *sdinfo[];
        !            55: struct mb_driver sidriver = {
        !            56:        siprobe, sislave, siattach, sigo, sidone, sipoll,
        !            57:        sizeof (struct scsi_si_reg), "sd", sdinfo, "si", siinfo, MDR_BIODMA,
        !            58: };
        !            59: 
        !            60: /* routines available to devices specific portion of scsi driver */
        !            61: struct scsi_ctlr_subr sisubr = {
        !            62:        siustart, sistart, sidone, si_cmd, si_getstatus, si_cmdwait,
        !            63:        si_off, si_reset, si_dmacnt, sigo,
        !            64: };
        !            65: 
        !            66: extern int scsi_debug;         /* generic debug information */
        !            67: extern int scsi_ntype;
        !            68: extern struct scsi_unit_subr scsi_unit_subr[];
        !            69: 
        !            70: int scsi_disre_enable = 0;     /* enable disconnect/reconnect */
        !            71: int scsi_dis_debug = 0;                /* disconnect debug info */
        !            72: int scsi_resel_debug = 0;      /* reselection debug info */
        !            73: int scsi_reset_debug = 0;      /* scsi bus reset debug information */
        !            74: 
        !            75: /*
        !            76:  * Determine existence of SCSI host adapter.
        !            77:  */
        !            78: siprobe(reg, ctlr)
        !            79:        register struct scsi_si_reg *reg;
        !            80:        register int ctlr;
        !            81: {
        !            82:        register struct scsi_ctlr *c;
        !            83: 
        !            84:        /* probe for different scsi host adaptor interfaces */
        !            85:        c = &sictlrs[ctlr];
        !            86: 
        !            87:        /* 
        !            88:         * Check for sbc - NCR 5380 Scsi Bus Ctlr chip.
        !            89:         * sbc is common to sun3/50 onboard scsi and vme
        !            90:         * scsi board.
        !            91:         */
        !            92:        if (peekc(&reg->sbc_rreg.cbsr) == -1) {
        !            93:                return (0);
        !            94:        }
        !            95: 
        !            96:        /*
        !            97:         * Determine whether the host adaptor interface is onboard or vme.
        !            98:         */
        !            99:        if (cpu == CPU_SUN3_50) {
        !           100:                /* probe for sun3/50 dma interface */
        !           101:                if (peek(&reg->udc_rdata) == -1)
        !           102:                        return (0);
        !           103:                c->c_flags = SCSI_ONBOARD;
        !           104:        } else {
        !           105:                /*
        !           106:                 * Probe for vme scsi card but make sure it is not
        !           107:                 * the SC host adaptor interface. SI vme scsi host
        !           108:                 * adaptor occupies 2K bytes in the vme address space. 
        !           109:                 * SC vme scsi host adaptor occupies 4K bytes in the 
        !           110:                 * vme address space. So, peek past 2K bytes to 
        !           111:                 * determine which host adaptor is there.
        !           112:                 */
        !           113:                if (peek(&reg->dma_addr) == -1)
        !           114:                        return (0);
        !           115:                if (peek((int)reg+0x800) != -1)
        !           116:                        return (0);
        !           117:                c->c_flags = 0;
        !           118:        }
        !           119: 
        !           120:        /* allocate memory for sense information */
        !           121:        c->c_sense = (struct scsi_sense *) rmalloc(iopbmap,
        !           122:            (long) sizeof (struct scsi_sense));
        !           123:        if (c->c_sense == NULL) {
        !           124:                printf("siprobe: no iopb memory for sense.\n");
        !           125:                return (0);
        !           126:        }
        !           127: 
        !           128:        /* init controller information */
        !           129:        c->c_flags |= SCSI_PRESENT;
        !           130:        if (scsi_disre_enable)
        !           131:                c->c_flags |= SCSI_EN_DISCON;
        !           132:        c->c_sir = reg;
        !           133:        c->c_ss = &sisubr;
        !           134:        si_reset(c);
        !           135:        return (sizeof (struct scsi_si_reg));
        !           136: }
        !           137: 
        !           138: 
        !           139: /*
        !           140:  * See if a slave exists.
        !           141:  * Since it may exist but be powered off, we always say yes.
        !           142:  */
        !           143: /*ARGSUSED*/
        !           144: sislave(md, reg)
        !           145:        register struct mb_device *md;
        !           146:        register struct scsi_si_reg *reg;
        !           147: {
        !           148:        register struct scsi_unit *un;
        !           149:        register int type;
        !           150: 
        !           151:        /*
        !           152:         * This kludge allows autoconfig to print out "sd" for
        !           153:         * disks and "st" for tapes.  The problem is that there
        !           154:         * is only one md_driver for scsi devices.
        !           155:         */
        !           156:        type = TYPE(md->md_flags);
        !           157:        if (type >= scsi_ntype) {
        !           158:                panic("sislave: unknown type in md_flags");
        !           159:        }
        !           160: 
        !           161:        /* link unit to its controller */
        !           162:        un = (struct scsi_unit *)(*scsi_unit_subr[type].ss_unit_ptr)(md);
        !           163:        if (un == 0) {
        !           164:                panic("sislave: md_flags scsi type not configured in\n");
        !           165:        }
        !           166:        un->un_c = &sictlrs[md->md_ctlr];
        !           167:        md->md_driver->mdr_dname = scsi_unit_subr[type].ss_devname;
        !           168:        return (1);
        !           169: }
        !           170: 
        !           171: /*
        !           172:  * Attach device (boot time).
        !           173:  */
        !           174: siattach(md)
        !           175:        register struct mb_device *md;
        !           176: {
        !           177:        register int type = TYPE(md->md_flags);
        !           178:        register struct mb_ctlr *mc = md->md_mc;
        !           179:        register struct scsi_ctlr *c = &sictlrs[md->md_ctlr];
        !           180: 
        !           181:        if (type >= scsi_ntype) {
        !           182:                panic("siattach: unknown type in md_flags");
        !           183:        }
        !           184:        (*scsi_unit_subr[type].ss_attach)(md);
        !           185: 
        !           186:        if (c->c_flags & SCSI_ONBOARD) {
        !           187:                return;
        !           188:        }
        !           189: 
        !           190:        /* 
        !           191:         * Initialize interrupt vector and address modifier register.
        !           192:         * Address modifier specifies standard supervisor data access
        !           193:         * with 24 bit vme addresses. May want to change this in the
        !           194:         * future to handle 32 bit vme addresses.
        !           195:         */
        !           196:        if (mc->mc_intr) {
        !           197:                /* setup for vectored interrupts - we will pass ctlr ptr */
        !           198:                c->c_sir->iv_am = (mc->mc_intr->v_vec & 0xff) | 
        !           199:                    VME_SUPV_DATA_24;
        !           200:                (*mc->mc_intr->v_vptr) = (int)c;
        !           201:        }
        !           202: }
        !           203: 
        !           204: /*
        !           205:  * SCSI unit start routine.
        !           206:  * Called by SCSI device drivers.
        !           207:  */
        !           208: siustart(un)
        !           209:        register struct scsi_unit *un;
        !           210: {
        !           211:        register struct buf *dp;
        !           212:        register struct mb_ctlr *mc;
        !           213:        register int s;
        !           214: 
        !           215:        mc = un->un_mc;
        !           216:        dp = &un->un_utab;
        !           217:        /* 
        !           218:         * Caller guarantees: dp->b_actf != NULL && dp->b_active == 0 
        !           219:         * Note: dp->b_active == 1 on a reconnect.
        !           220:         */
        !           221:        /*
        !           222:         * Put device on ready queue for bus.
        !           223:         */
        !           224:        if (mc->mc_tab.b_actf == NULL) {
        !           225:                mc->mc_tab.b_actf = dp;
        !           226:        } else {
        !           227:                mc->mc_tab.b_actl->b_forw = dp;
        !           228:        }
        !           229:        dp->b_forw = NULL;
        !           230:        mc->mc_tab.b_actl = dp;
        !           231:        dp->b_active = 1;
        !           232:        dp->b_un.b_addr = (caddr_t) un;
        !           233: }
        !           234: 
        !           235: /*
        !           236:  * Set up a scsi operation.
        !           237:  */
        !           238: sistart(un)
        !           239:        register struct scsi_unit *un;
        !           240: {
        !           241:        register struct mb_ctlr *mc;
        !           242:        register struct buf *bp, *dp;
        !           243: 
        !           244:        mc = un->un_mc;
        !           245:        dp = mc->mc_tab.b_actf;      /* != NULL guaranteed by caller */
        !           246:        un = (struct scsi_unit *) dp->b_un.b_addr;
        !           247:        bp = dp->b_actf;
        !           248:        for (;;) {
        !           249:                if (bp == NULL) {         /* no more blocks for this device */
        !           250:                        un->un_utab.b_active = 0;
        !           251:                        dp = mc->mc_tab.b_actf = dp->b_forw;
        !           252:                        if (dp == NULL) {  /* no more devices for this ctlr */
        !           253:                                si_idle(un->un_c);
        !           254:                                return;
        !           255:                        }
        !           256:                        un = (struct scsi_unit *) dp->b_un.b_addr;
        !           257:                        bp = dp->b_actf;
        !           258:                } else {
        !           259:                        if ((*un->un_ss->ss_start)(bp, un)) {
        !           260:                                mc->mc_tab.b_active = 1;
        !           261:                                un->un_c->c_un = un;
        !           262:                                if (bp == &un->un_sbuf  &&
        !           263:                                    ((un->un_flags & SC_UNF_DVMA) == 0)) {
        !           264:                                        sigo(mc);
        !           265:                                } else {
        !           266:                                        (void) mbgo(mc);
        !           267:                                }
        !           268:                                return;
        !           269:                        }
        !           270:                        dp->b_actf = bp = bp->av_forw;
        !           271:                }
        !           272:        }
        !           273: }
        !           274: 
        !           275: /*
        !           276:  * Start up a scsi operation.
        !           277:  * Called via mbgo after buffer is in memory.
        !           278:  */
        !           279: sigo(mc)
        !           280:        register struct mb_ctlr *mc;
        !           281: {
        !           282:        register struct scsi_unit *un;
        !           283:        register struct scsi_ctlr *c;
        !           284:        register struct buf *bp, *dp;
        !           285:        register int unit;
        !           286: 
        !           287:        c = &sictlrs[mc->mc_ctlr];
        !           288:        dp = mc->mc_tab.b_actf;
        !           289:        if (dp == NULL || dp->b_actf == NULL) {
        !           290:                panic("sigo queueing error 1");
        !           291:        }
        !           292:        bp = dp->b_actf;
        !           293:        un = c->c_un;
        !           294:        if (dp != &un->un_utab) {
        !           295:                panic("sigo queueing error 2");
        !           296:        }
        !           297:        un->un_baddr = MBI_ADDR(mc->mc_mbinfo);
        !           298:        if ((unit = un->un_md->md_dk) >= 0) {
        !           299:                dk_busy |= 1<<unit;
        !           300:                dk_xfer[unit]++;
        !           301:                dk_wds[unit] += bp->b_bcount >> 6;
        !           302:        }
        !           303:        (*un->un_ss->ss_mkcdb)(c, un);
        !           304:        if (si_cmd(c, un, 1) == 0) {
        !           305:                (*un->un_ss->ss_intr)(c, 0, SE_FATAL);
        !           306:                si_off(un);
        !           307:        }
        !           308: }
        !           309: 
        !           310: /*
        !           311:  * Handle a polling SCSI bus interrupt.
        !           312:  */
        !           313: sipoll()
        !           314: {
        !           315:        register struct scsi_ctlr *c;
        !           316:        register int serviced = 0;
        !           317: 
        !           318:        for (c = sictlrs; c < &sictlrs[NSI]; c++) {
        !           319:                if ((c->c_flags & SCSI_PRESENT) == 0)
        !           320:                        continue;
        !           321:                if ((c->c_sir->csr & 
        !           322:                    (SI_CSR_SBC_IP | SI_CSR_DMA_IP | SI_CSR_DMA_CONFLICT)) 
        !           323:                    == 0) {
        !           324:                        continue;
        !           325:                }
        !           326:                serviced = 1;
        !           327:                siintr(c);
        !           328:        }
        !           329:        return (serviced);
        !           330: }
        !           331: 
        !           332: /*
        !           333:  * Clean up queues, free resources, and start next I/O
        !           334:  * all done after I/O finishes
        !           335:  * Called by mbdone after moving read data from Mainbus
        !           336:  */
        !           337: sidone(mc)
        !           338:        register struct mb_ctlr *mc;
        !           339: {
        !           340:        register struct buf *bp, *dp;
        !           341:        register struct scsi_unit *un;
        !           342:        register struct scsi_ctlr *c;
        !           343: 
        !           344:        bp = mc->mc_tab.b_actf->b_actf;
        !           345:        c = &sictlrs[mc->mc_ctlr];
        !           346:        un = c->c_un;
        !           347: 
        !           348:        /* advance controller queue */
        !           349:        dp = mc->mc_tab.b_actf;
        !           350:        mc->mc_tab.b_active = 0;
        !           351:        mc->mc_tab.b_actf = dp->b_forw;
        !           352: 
        !           353:        /* advance unit queue */
        !           354:        dp->b_active = 0;
        !           355:        dp->b_actf = bp->av_forw;
        !           356: 
        !           357:        iodone(bp);
        !           358: 
        !           359:        /* start next I/O on unit */
        !           360:        if (dp->b_actf)
        !           361:                siustart(un);
        !           362: 
        !           363:        /* start next I/O on controller */
        !           364:        if (mc->mc_tab.b_actf && mc->mc_tab.b_active == 0) {
        !           365:                sistart(un);
        !           366:        } else {
        !           367:                c->c_un = NULL;
        !           368:                si_idle(c);
        !           369:        }
        !           370: }
        !           371: 
        !           372: /*ARGSUSED*/
        !           373: si_off(un)
        !           374:        register struct scsi_unit *un;
        !           375: {
        !           376: 
        !           377: #ifdef notdef
        !           378:        /* if done to root real bad things happen... */
        !           379:        un->un_present = 0;
        !           380:        printf("scsi unit %d/%d offline\n", un->un_target, un->un_lun);
        !           381:        if (un->un_md->md_dk > 0) {
        !           382:                dk_mspw[un->un_md->md_dk]=0;
        !           383:        }
        !           384: #endif
        !           385: }
        !           386: 
        !           387: /*
        !           388:  * Pass a command to the SCSI bus.
        !           389:  */
        !           390: si_cmd(c, un, intr)
        !           391:        register struct scsi_ctlr *c;
        !           392:        register struct scsi_unit *un;
        !           393:        register int intr;
        !           394: {
        !           395:        register u_char *cp;
        !           396:        register int i;
        !           397:        register int errct;
        !           398:        register struct scsi_si_reg *sir = c->c_sir;
        !           399: 
        !           400:        errct = 0;
        !           401:        do {
        !           402:                /* disallow disconnects if waiting for command completion */
        !           403:                if (intr == 0) {
        !           404:                        c->c_flags &= ~SCSI_EN_DISCON;
        !           405:                } else {
        !           406:                        if (scsi_disre_enable)
        !           407:                                c->c_flags |= SCSI_EN_DISCON;
        !           408:                        else
        !           409:                                c->c_flags &= ~SCSI_EN_DISCON;
        !           410:                        un->un_wantint = 1;
        !           411:                }
        !           412: 
        !           413:                /*
        !           414:                 * For vme host adaptor interface, dma enable bit may
        !           415:                 * be set to allow reconnect interrupts to come in.
        !           416:                 * This must be disabled before arbitration/selection
        !           417:                 * of target is done. Don't worry about re-enabling
        !           418:                 * dma. If arb/sel fails, then si_idle() will re-enable.
        !           419:                 * If arb/sel succeeds then handling of command will
        !           420:                 * re-enable.
        !           421:                 * Also, disallow sbc to accept reconnect attempts.
        !           422:                 * Again, si_idle() will re-enable this if arb/sel fails.
        !           423:                 * If arb/sel succeeds then we do not want to allow
        !           424:                 * reconnects anyway.
        !           425:                 */
        !           426:                if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !           427:                        sir->csr &= ~SI_CSR_DMA_EN;
        !           428:                }
        !           429:                sir->sbc_wreg.ser = 0;
        !           430:                c->c_flags &= ~SCSI_EN_RECON;
        !           431: 
        !           432:                /* performing target selection */
        !           433:                if (si_arb_sel(c, un) == 0) {
        !           434:                        goto bad;
        !           435:                }
        !           436: 
        !           437:                /*
        !           438:                 * Must split dma setup into 2 parts due to sun3/50
        !           439:                 * which requires bcr to be set before target
        !           440:                 * changes phase on scsi bus to data phase.
        !           441:                 *
        !           442:                 * Three fields in the per scsi unit structure
        !           443:                 * hold information pertaining to the current dma
        !           444:                 * operation: un_dma_curdir, un_dma_curaddr, and
        !           445:                 * un_dma_curcnt. These fields are used to track
        !           446:                 * the amount of data dma'd especially when disconnects 
        !           447:                 * and reconnects occur.
        !           448:                 * If the current command does not involve dma,
        !           449:                 * these fields are set appropriately.
        !           450:                 */
        !           451:                if (un->un_dma_count > 0) {
        !           452:                        if ((c->c_cdb.cmd == SC_READ) || 
        !           453:                            (c->c_cdb.cmd == SC_REQUEST_SENSE))  {
        !           454:                                un->un_dma_curdir = SI_RECV_DATA;
        !           455:                                sir->csr &= ~SI_CSR_SEND;
        !           456:                        } else {
        !           457:                                un->un_dma_curdir = SI_SEND_DATA;
        !           458:                                sir->csr |= SI_CSR_SEND;
        !           459:                        }
        !           460:                        /* save current dma info for disconnect */
        !           461:                        un->un_dma_curaddr = un->un_dma_addr;
        !           462:                        un->un_dma_curcnt = un->un_dma_count;
        !           463: 
        !           464:                        /* tape has scsi id of 4 */
        !           465:                        if ((un->un_target == 4) && scsi_dis_debug) {
        !           466:                                printf("si_cmd: cmd= %x, addr= %x, cnt= %x\n", 
        !           467:                                    c->c_cdb.cmd, un->un_dma_curaddr, 
        !           468:                                    un->un_dma_curcnt);
        !           469:                        }
        !           470: 
        !           471:                        /* reset fifo */
        !           472:                        sir->csr &= ~SI_CSR_FIFO_RES;
        !           473:                        sir->csr |= SI_CSR_FIFO_RES;
        !           474: 
        !           475:                        /* must init bcr before target goes into data phase */
        !           476:                        sir->bcr = un->un_dma_curcnt;
        !           477: 
        !           478:                        /* 
        !           479:                         * Currently we don't use all 24 bits of the
        !           480:                         * count register on the vme interface. To do
        !           481:                         * this changes are required other places, e.g.
        !           482:                         * in the scsi_unit structure the fields
        !           483:                         * un_dma_curcnt and un_dma_count would need to
        !           484:                         * be changed.
        !           485:                         */
        !           486:                        if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !           487:                                sir->bcrh = 0;
        !           488:                        }
        !           489:                } else {
        !           490:                        un->un_dma_curdir = SI_NO_DATA;
        !           491:                        un->un_dma_curaddr = 0;
        !           492:                        un->un_dma_curcnt = 0;
        !           493:                }
        !           494: 
        !           495:                cp = (u_char *) &c->c_cdb;
        !           496:                if (scsi_debug) {
        !           497:                        printf("si%d: si_cmd: target %d issuing command ",
        !           498:                             SINUM(c), un->un_target);
        !           499:                        for (i = 0; i < sizeof (struct scsi_cdb); i++) {
        !           500:                                printf("%x ", *cp++);
        !           501:                        }
        !           502:                        printf("\n");
        !           503:                        cp = (u_char *) &c->c_cdb;
        !           504:                }
        !           505: 
        !           506:                /* put scsi command out on scsi bus */
        !           507:                if (si_putdata(c, PHASE_COMMAND, cp, sizeof(struct scsi_cdb)) 
        !           508:                    == 0) {
        !           509:                        errct++;
        !           510:                } else {
        !           511:                        /* do final dma setup and start dma operation */
        !           512:                        if (un->un_dma_count > 0) {
        !           513:                                if (c->c_flags & SCSI_ONBOARD)
        !           514:                                        si_ob_dma_setup(c, un);
        !           515:                                else
        !           516:                                        si_vme_dma_setup(c, un);
        !           517:                        } else if (un->un_wantint) {
        !           518:                                /*
        !           519:                                 * If this command does not involve
        !           520:                                 * any dma, we must set things up
        !           521:                                 * so we get an interrupt when the
        !           522:                                 * target is ready to give us status.
        !           523:                                 * The interrupt we get is a phase
        !           524:                                 * mismatch, however, to get this
        !           525:                                 * interrupt the sbc must be in dma
        !           526:                                 * mode. Also, the vme scsi card does
        !           527:                                 * not generate any interrupts unless
        !           528:                                 * dma is enabled in the csr.
        !           529:                                 */
        !           530:                                sir->sbc_wreg.mr |= SBC_MR_DMA;
        !           531:                                sir->sbc_wreg.tcr = TCR_UNSPECIFIED;
        !           532:                                if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !           533:                                        sir->csr &= ~SI_CSR_SEND;
        !           534:                                        sir->csr |= SI_CSR_DMA_EN;
        !           535:                                }
        !           536:                        }
        !           537:                        return (1);
        !           538:                }
        !           539:        } while (errct < SI_NUM_RETRIES);
        !           540: 
        !           541:        /* clear fields if we were not able to issue scsi cmd */
        !           542:        printf("si_cmd: too many errors\n");
        !           543:        if (un->un_dma_count != 0) {
        !           544:                un->un_dma_curdir = 0;
        !           545:                un->un_dma_curaddr = 0;
        !           546:                un->un_dma_curcnt = 0;
        !           547:                sir->bcr = 0;
        !           548:                sir->csr &= ~SI_CSR_SEND;
        !           549:        }
        !           550: bad:
        !           551:        un->un_wantint = 0;
        !           552:        si_idle(c);
        !           553:        return (0);
        !           554: }
        !           555: 
        !           556: /*
        !           557:  * Perform the SCSI arbitration and selection phases.
        !           558:  */
        !           559: si_arb_sel(c, un)
        !           560:        register struct scsi_ctlr *c;
        !           561:        register struct scsi_unit *un;
        !           562: {
        !           563:        register struct scsi_si_reg *sir = c->c_sir;
        !           564:        register u_char *icrp = &sir->sbc_wreg.icr;
        !           565:        register u_char *mrp = &sir->sbc_wreg.mr;
        !           566:        register int j;
        !           567:        register u_char icr;
        !           568:        u_char id;
        !           569: 
        !           570:        /* wait for scsi bus to become free */
        !           571:        if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_BSY, 0) == 0) {
        !           572:                printf("si_arb_sel: continuously busy\n");
        !           573:                si_reset(c);
        !           574:                return (0);
        !           575:        }
        !           576: 
        !           577:        /* arbitrate for the scsi bus */
        !           578:        sir->sbc_wreg.odr = SI_HOST_ID;
        !           579:        for (j = 0; j < SI_NUM_RETRIES; j++) {
        !           580:                *mrp |= SBC_MR_ARB;
        !           581: 
        !           582:                /* wait for sbc to begin arbitration */
        !           583:                if (si_sbc_wait((caddr_t)icrp, SBC_ICR_AIP, 1) == 0) {
        !           584:                        /* problem with sbc if arb never begins */
        !           585:                        /* 
        !           586:                         * Current bug in Emulex MT02 firmware.
        !           587:                         * It does not go through the reselection timeout 
        !           588:                         * procedure documented in the scsi protocol spec.
        !           589:                         */
        !           590:                        if ((sir->sbc_rreg.cbsr & SBC_CBSR_SEL) && 
        !           591:                            (sir->sbc_rreg.cbsr & SBC_CBSR_IO) &&
        !           592:                            (sir->sbc_rreg.cdr & SI_HOST_ID)) {
        !           593:                                printf("si_arb_sel: REselect, flgs %x\n", 
        !           594:                                    c->c_flags);
        !           595:                                if (scsi_resel_debug) halt("");
        !           596:                        } else {
        !           597:                                printf("si_arb_sel: AIP never set, ??\n");
        !           598:                        }
        !           599: 
        !           600:                        *mrp &= ~SBC_MR_ARB;
        !           601:                        return (0);
        !           602:                        /* si_reset(c); */
        !           603:                }
        !           604: 
        !           605:                /* check to see if we won arbitration */
        !           606:                DELAY(SI_ARBITRATION_DELAY);
        !           607:                if ((*icrp & SBC_ICR_LA) == 0) {
        !           608:                        if ( ((sir->sbc_rreg.cdr & ~SI_HOST_ID)
        !           609:                            < SI_HOST_ID) &&
        !           610:                            ((*icrp & SBC_ICR_LA) == 0)) {
        !           611:                                /* won arbitration */
        !           612:                                icr = *icrp & ~SBC_ICR_AIP;
        !           613:                                *icrp = icr | SBC_ICR_ATN;
        !           614:                                icr = *icrp & ~SBC_ICR_AIP;
        !           615:                                *icrp = icr | SBC_ICR_SEL;
        !           616:                                DELAY(SI_BUS_CLEAR_DELAY + SI_BUS_SETTLE_DELAY);
        !           617:                                break;
        !           618:                        }
        !           619:                }
        !           620: 
        !           621:                /* lost arbitration, clear arbitration mode */
        !           622:                *mrp &= ~SBC_MR_ARB;
        !           623:        }
        !           624: 
        !           625:        /* couldn't win arbitration */
        !           626:        if (j == SI_NUM_RETRIES) {
        !           627:                /* should never happen since we have highest pri scsi id */
        !           628:                *mrp &= ~SBC_MR_ARB;
        !           629:                *icrp = 0;
        !           630:                printf("si_arb_sel: couldn't win arbitration\n");
        !           631:                return (0);
        !           632:        }
        !           633: 
        !           634:        /* won arbitration, perform selection */
        !           635:        sir->sbc_wreg.odr = (1 << un->un_target) | SI_HOST_ID;
        !           636:        icr = *icrp & ~SBC_ICR_AIP;
        !           637:        *icrp = icr | SBC_ICR_DATA | SBC_ICR_BUSY;
        !           638:        *mrp &= ~SBC_MR_ARB;
        !           639: 
        !           640:        /* wait for target to acknowledge selection */
        !           641:        *icrp &= ~SBC_ICR_BUSY;
        !           642:        if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_BSY, 1) == 0) {
        !           643:                if (scsi_debug)
        !           644:                        printf("si_arb_sel: cbsr bsy never set\n");
        !           645:                si_reset(c);
        !           646:                return (0);
        !           647:        }
        !           648:        *icrp &= ~(SBC_ICR_SEL | SBC_ICR_DATA);
        !           649: 
        !           650:        /* send target identify message */
        !           651:        if (c->c_flags & SCSI_EN_DISCON)
        !           652:                id = SC_DR_IDENTIFY | c->c_cdb.lun;
        !           653:        else
        !           654:                id = SC_IDENTIFY | c->c_cdb.lun;
        !           655:        if (si_putdata(c, PHASE_MSG_OUT, &id, 1) == 0) {
        !           656:                if (scsi_debug)
        !           657:                        printf("si_arb_sel: put of ID MSG %x failed\n", id);
        !           658:        }
        !           659:        *icrp = 0;
        !           660:        return (1);
        !           661: }
        !           662: 
        !           663: /*
        !           664:  * Set up the SCSI control logic for a dma transfer for vme host adaptor.
        !           665:  */
        !           666: si_vme_dma_setup(c, un)
        !           667:        register struct scsi_ctlr *c;
        !           668:        register struct scsi_unit *un;
        !           669: {
        !           670:        register struct scsi_si_reg *sir = c->c_sir;
        !           671: 
        !           672:        /* setup starting dma address and number bytes to dma */
        !           673:        sir->dma_addr = un->un_dma_curaddr;
        !           674:        sir->dma_count = un->un_dma_curcnt;
        !           675: 
        !           676:        /* set up byte packing control info */
        !           677:        if (sir->dma_addr & 0x2) {
        !           678:                /* setup word dma transfers across vme bus */
        !           679:                sir->csr |= SI_CSR_BPCON;
        !           680:        } else {
        !           681:                /* setup longword dma transfers across vme bus */
        !           682:                sir->csr &= ~SI_CSR_BPCON;
        !           683:        }
        !           684: 
        !           685:        if (scsi_debug) {
        !           686:                printf("si_vme_dma_setup: addr %x, cnt %x, csr %x\n", 
        !           687:                    sir->dma_addr, sir->dma_count, sir->csr);
        !           688:        }
        !           689: 
        !           690:        /* init sbc for dma transfer */
        !           691:        si_sbc_dma_setup(sir, un->un_dma_curdir);
        !           692: 
        !           693:        /* enable dma - this must be the last step */
        !           694:        sir->csr |= SI_CSR_DMA_EN;
        !           695: }
        !           696: 
        !           697: /*
        !           698:  * Set up the SCSI control logic for a dma transfer for onboard host
        !           699:  * adaptor.
        !           700:  */
        !           701: si_ob_dma_setup(c, un)
        !           702:        register struct scsi_ctlr *c;
        !           703:        register struct scsi_unit *un;
        !           704: {
        !           705:        register struct scsi_si_reg *sir = c->c_sir;
        !           706:        register struct udc_table *udct = &c->c_udct;
        !           707:        register int addr;
        !           708: 
        !           709:        /* set up udc dma information */
        !           710:        addr = un->un_dma_curaddr;
        !           711:        if (addr < DVMA_OFFSET)
        !           712:                addr += DVMA_OFFSET;
        !           713:        udct->haddr = ((addr & 0xff0000) >> 8) | UDC_ADDR_INFO;
        !           714:        udct->laddr = addr & 0xffff;
        !           715:        udct->hcmr = UDC_CMR_HIGH;
        !           716:        udct->count = un->un_dma_curcnt / 2; /* #bytes -> #words */
        !           717:        if (un->un_dma_curdir == SI_RECV_DATA) {
        !           718:                udct->rsel = UDC_RSEL_RECV;
        !           719:                udct->lcmr = UDC_CMR_LRECV;
        !           720:        } else {
        !           721:                udct->rsel = UDC_RSEL_SEND;
        !           722:                udct->lcmr = UDC_CMR_LSEND;
        !           723:                if (un->un_dma_curcnt & 1) {
        !           724:                        udct->count++;
        !           725:                }
        !           726:        }
        !           727: 
        !           728:        /* initialize udc chain address register */
        !           729:        sir->udc_raddr = UDC_ADR_CAR_HIGH;
        !           730:        DELAY(SI_UDC_WAIT);
        !           731:        sir->udc_rdata = ((int)udct & 0xff0000) >> 8;
        !           732:        DELAY(SI_UDC_WAIT);
        !           733:        sir->udc_raddr = UDC_ADR_CAR_LOW;
        !           734:        DELAY(SI_UDC_WAIT);
        !           735:        sir->udc_rdata = (int)udct & 0xffff;
        !           736: 
        !           737:        if (scsi_debug) {
        !           738:                printf("si_ob_dma_setup: udct= %x, %x -> %x\n", udct, 
        !           739:                    un->un_dma_curaddr, addr);
        !           740:        }
        !           741: 
        !           742:        /* initialize udc master mode register */
        !           743:        DELAY(SI_UDC_WAIT);
        !           744:        sir->udc_raddr = UDC_ADR_MODE;
        !           745:        DELAY(SI_UDC_WAIT);
        !           746:        sir->udc_rdata = UDC_MODE;
        !           747: 
        !           748:        /* issue channel interrupt enable command, in case of error, to udc */
        !           749:        DELAY(SI_UDC_WAIT);
        !           750:        sir->udc_raddr = UDC_ADR_COMMAND;
        !           751:        DELAY(SI_UDC_WAIT);
        !           752:        sir->udc_rdata = UDC_CMD_CIE;
        !           753: 
        !           754:        /* issue start chain command to udc */
        !           755:        DELAY(SI_UDC_WAIT);
        !           756:        sir->udc_rdata = UDC_CMD_STRT_CHN;
        !           757: 
        !           758:        /* put sbc in dma mode and start dma transfer */
        !           759:        si_sbc_dma_setup(sir, un->un_dma_curdir);
        !           760: }
        !           761: 
        !           762: /*
        !           763:  * Setup and start the sbc for a dma operation.
        !           764:  */
        !           765: si_sbc_dma_setup(sir, dir)
        !           766:        register struct scsi_si_reg *sir;
        !           767:        register int dir;
        !           768: {
        !           769:        sir->sbc_wreg.mr |= SBC_MR_DMA;
        !           770:        if (dir == SI_RECV_DATA) {
        !           771:                sir->sbc_wreg.tcr = TCR_DATA_IN;
        !           772:                sir->sbc_wreg.ircv = 0;
        !           773:        } else {
        !           774:                sir->sbc_wreg.tcr = TCR_DATA_OUT;
        !           775:                sir->sbc_wreg.icr = SBC_ICR_DATA;
        !           776:                sir->sbc_wreg.send = 0;
        !           777:        }
        !           778: }
        !           779: 
        !           780: /*
        !           781:  * Cleanup up the SCSI control logic after a dma transfer.
        !           782:  */
        !           783: si_dma_cleanup(c)
        !           784:        register struct scsi_ctlr *c;
        !           785: {
        !           786:        register struct scsi_si_reg *sir = c->c_sir;
        !           787: 
        !           788:        /* disable dma controller */
        !           789:        if (c->c_flags & SCSI_ONBOARD) {
        !           790:                sir->udc_raddr = UDC_ADR_COMMAND;
        !           791:                DELAY(SI_UDC_WAIT);
        !           792:                sir->udc_rdata = UDC_CMD_RESET;
        !           793:        } else {
        !           794:                sir->dma_addr = 0;
        !           795:                sir->dma_count = 0;
        !           796:        }
        !           797: 
        !           798:        /* reset fifo */
        !           799:        sir->csr &= ~SI_CSR_FIFO_RES;
        !           800:        sir->csr |= SI_CSR_FIFO_RES;
        !           801: 
        !           802:        /* take sbc out of dma mode and reset bcr */
        !           803:        sir->sbc_wreg.icr = 0;
        !           804:        sir->sbc_wreg.mr &= ~SBC_MR_DMA;
        !           805:        sir->sbc_wreg.tcr = 0;
        !           806:        sir->bcr = 0;
        !           807: }
        !           808: 
        !           809: /*
        !           810:  * Handle special dma receive situations, e.g. an odd number of bytes 
        !           811:  * in a dma transfer.
        !           812:  * The Sun3/50 onboard interface has different situations which
        !           813:  * must be handled than the vme interface.
        !           814:  */
        !           815: si_dma_recv(c) 
        !           816:        register struct scsi_ctlr *c;
        !           817: {
        !           818:        register struct scsi_si_reg *sir = c->c_sir;
        !           819:        register struct scsi_unit *un = c->c_un;
        !           820:        register int offset;
        !           821: 
        !           822:        offset = un->un_dma_curaddr + (un->un_dma_curcnt - sir->bcr);
        !           823: 
        !           824:        /* handle the onboard scsi situations */
        !           825:        if (c->c_flags & SCSI_ONBOARD) {
        !           826:                sir->udc_raddr = UDC_ADR_COUNT;
        !           827: 
        !           828:                /* wait for the fifo to empty */
        !           829:                if (si_wait((u_short *)&sir->csr, SI_CSR_FIFO_EMPTY, 1) == 0) {
        !           830:                        printf("si_dma_recv: fifo never emptied\n");
        !           831:                        return (0);
        !           832:                }
        !           833: 
        !           834:                /* handle odd byte */
        !           835:                if ((un->un_dma_curcnt - sir->bcr) & 1) {
        !           836:                        DVMA[offset - 1] = (sir->fifo_data & 0xff00) >> 8;
        !           837: 
        !           838:                /*
        !           839:                 * The udc may not dma the last word from the fifo_data
        !           840:                 * register into memory due to how the hardware turns
        !           841:                 * off the udc at the end of the dma operation.
        !           842:                 */
        !           843:                } else if (((sir->udc_rdata*2) - sir->bcr) == 2) {
        !           844:                        DVMA[offset - 2] = (sir->fifo_data & 0xff00) >> 8;
        !           845:                        DVMA[offset - 1] = sir->fifo_data & 0x00ff;
        !           846:                }
        !           847: 
        !           848:        /* handle the vme scsi situations */
        !           849:        } else if ((sir->csr & SI_CSR_LOB) != 0) {
        !           850:            /*
        !           851:             * Grabs last few bytes which may not have been dma'd.
        !           852:             * Worst case is when longword dma transfers are being done
        !           853:             * and there are 3 bytes leftover.
        !           854:             * If BPCON bit is set then longword dmas were being done,
        !           855:             * otherwise word dmas were being done.
        !           856:             */
        !           857:            if ((sir->csr & SI_CSR_BPCON) == 0) {
        !           858:                switch (sir->csr & SI_CSR_LOB) {
        !           859:                case SI_CSR_LOB_THREE:
        !           860:                        DVMA[offset - 3] = (sir->bpr & 0xff000000) >> 24;
        !           861:                        DVMA[offset - 2] = (sir->bpr & 0x00ff0000) >> 16;
        !           862:                        DVMA[offset - 1] = (sir->bpr & 0x0000ff00) >> 8;
        !           863:                        break;
        !           864: 
        !           865:                case SI_CSR_LOB_TWO:
        !           866:                        DVMA[offset - 2] = (sir->bpr & 0xff000000) >> 24;
        !           867:                        DVMA[offset - 1] = (sir->bpr & 0x00ff0000) >> 16;
        !           868:                        break;
        !           869: 
        !           870:                case SI_CSR_LOB_ONE:
        !           871:                        DVMA[offset - 1] = (sir->bpr & 0xff000000) >> 24;
        !           872:                        break;
        !           873:                }
        !           874:            } else {
        !           875:                DVMA[offset - 1] = (sir->bpr & 0x0000ff00) >> 8;
        !           876:            }
        !           877:        }
        !           878:        return (1);
        !           879: }
        !           880: 
        !           881: 
        !           882: /*
        !           883:  * Handle a scsi interrupt.
        !           884:  */
        !           885: siintr(c)
        !           886:        register struct scsi_ctlr *c;
        !           887: {
        !           888:        register struct scsi_si_reg *sir = c->c_sir;
        !           889:        register struct scsi_unit *un = c->c_un;
        !           890:        register int bsr;
        !           891:        register int status;
        !           892:        register int resid;
        !           893:        register int dma_cleanup;
        !           894:        register int i;
        !           895:        int disconnect;
        !           896:        u_char msg;
        !           897:        struct buf *dp;
        !           898:        int reset_occurred;
        !           899: 
        !           900:        /* set misc flags */
        !           901:        status = SE_NO_ERROR;
        !           902:        resid = 0;
        !           903:        dma_cleanup = 0;
        !           904:        disconnect = 0;
        !           905:        reset_occurred = 0;
        !           906: 
        !           907:        /* 
        !           908:         * For vme host adaptor interface, must disable dma before
        !           909:         * accessing any registers other than the csr or the 
        !           910:         * SI_CSR_DMA_CONFLICT bit in the csr will be set.
        !           911:         */
        !           912:        if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !           913:                sir->csr &= ~SI_CSR_DMA_EN;
        !           914:        }
        !           915: 
        !           916:        /* check for dma related errors */
        !           917:        if (sir->csr & (SI_CSR_DMA_IP | SI_CSR_DMA_CONFLICT)) {
        !           918:                if (sir->csr & SI_CSR_DMA_BUS_ERR) {
        !           919:                        printf("siintr: bus error during dma\n");
        !           920:                } else if (sir->csr & SI_CSR_DMA_CONFLICT) {
        !           921:                        printf("siintr: invalid reg access during dma\n");
        !           922:                } else {
        !           923:                        if (c->c_flags & SCSI_ONBOARD)
        !           924:                                printf("siintr: dma ip, unknown reason\n");
        !           925:                        else
        !           926:                                printf("siintr: dma overrun\n");
        !           927:                }
        !           928:                /*
        !           929:                 * Either we were waiting for an interrupt on a phase change 
        !           930:                 * on the scsi bus, an interrupt on a reconnect attempt,
        !           931:                 * or an interrupt upon completion of a real dma operation.
        !           932:                 * Each of these situations must be handled appropriately.
        !           933:                 */
        !           934:                if (sir->sbc_rreg.tcr == TCR_UNSPECIFIED) {
        !           935:                        sir->sbc_wreg.mr &= ~SBC_MR_DMA;
        !           936:                } else if (un == NULL) {
        !           937:                        si_reset(c);
        !           938:                        si_idle(c);
        !           939:                        return;
        !           940:                } else {
        !           941:                        dma_cleanup = 1;
        !           942:                }
        !           943:                status = SE_FATAL;
        !           944: 
        !           945:        /* check for interrupt from sbc */
        !           946:        } else  if (sir->csr & SI_CSR_SBC_IP) {
        !           947: 
        !           948:                /* grab the bsr and find out why sbc interrupted */
        !           949:                bsr = sir->sbc_rreg.bsr;
        !           950: 
        !           951:                /* acknowledge sbc interrupt */
        !           952:                msg = sir->sbc_rreg.clr;
        !           953: 
        !           954:                /*
        !           955:                 * Check for sbc end of operation interrupt.
        !           956:                 * This is the normal interrupt upon completion
        !           957:                 * of a dma operation. Very soon after this 
        !           958:                 * interrupt is generated a phase mismatch
        !           959:                 * should occur on the scsi bus as the target
        !           960:                 * changes from the data in/out phase to the
        !           961:                 * status phase.
        !           962:                 */
        !           963:                if (bsr & SBC_BSR_EDMA) {
        !           964:                        if (si_sbc_wait((caddr_t)&sir->sbc_rreg.bsr, 
        !           965:                            SBC_BSR_PMTCH, 0) == 0) {
        !           966:                                dma_cleanup = 1;
        !           967:                                status = SE_FATAL;
        !           968:                                printf("si: scsi sbc dma end op\n");
        !           969:                                goto done;
        !           970:                        }
        !           971:                        goto phmismatch;
        !           972: 
        !           973:                /* check for phase mismatch */
        !           974:                } else if ((bsr & SBC_BSR_PMTCH) == 0) {
        !           975: phmismatch:
        !           976:                        if ((sir->sbc_rreg.mr & SBC_MR_DMA) == 0) {
        !           977:                                if (c->c_flags & SCSI_EN_RECON)
        !           978:                                        goto recon;
        !           979:                                else
        !           980:                                        goto discon;
        !           981:                        }
        !           982: 
        !           983:                        /*
        !           984:                         * Handle fake dma mode which is used when we
        !           985:                         * want an interrupt when target changes scsi
        !           986:                         * bus to status phase.
        !           987:                         */
        !           988:                        sir->sbc_wreg.mr &= ~SBC_MR_DMA;
        !           989:                        if (sir->sbc_rreg.tcr == TCR_UNSPECIFIED) {
        !           990:                                sir->sbc_wreg.tcr = 0;
        !           991:                        } else {
        !           992:                                /* need to reset some registers after a dma */
        !           993:                                dma_cleanup = 1;
        !           994: 
        !           995:                                /* handle special dma recv situations */
        !           996:                                if (un->un_dma_curdir == SI_RECV_DATA) {
        !           997:                                        if (si_dma_recv(c) == 0) {
        !           998:                                                status = SE_RETRYABLE;
        !           999:                                        }
        !          1000:                                }
        !          1001:                        }
        !          1002: 
        !          1003: discon:
        !          1004:                        /* check for disconnect */
        !          1005:                        if ((sir->sbc_rreg.cbsr & SBC_CBSR_REQ) &&
        !          1006:                            ((sir->sbc_rreg.cbsr & CBSR_PHASE_BITS) == 
        !          1007:                            PHASE_MSG_IN)) {
        !          1008:                                if (scsi_debug || scsi_dis_debug)
        !          1009:                                        printf("siintr: DISconnect\n");
        !          1010:                                if (si_disconnect(c)) {
        !          1011:                                        disconnect = 1;
        !          1012:                                }
        !          1013:                        }
        !          1014:                        goto done;
        !          1015:                }
        !          1016: 
        !          1017: recon:
        !          1018:                /* check for reconnect attempt */
        !          1019:                if ((sir->sbc_rreg.cbsr & SBC_CBSR_SEL) && 
        !          1020:                    (sir->sbc_rreg.cbsr & SBC_CBSR_IO) &&
        !          1021:                    (sir->sbc_rreg.cdr & SI_HOST_ID)) {
        !          1022:                        if (scsi_debug || scsi_dis_debug)
        !          1023:                                printf("siintr: REconnect\n");
        !          1024:                        si_reconnect(c);
        !          1025:                        return;
        !          1026:                }
        !          1027: 
        !          1028:                /*
        !          1029:                 * Scsi bus reset occurred. Put registers in correct
        !          1030:                 * state. Must cleanup disconnected tasks which will
        !          1031:                 * never reconnect due to the scsi bus reset.
        !          1032:                 */
        !          1033:                if (scsi_debug)
        !          1034:                        printf("siintr: got scsi bus reset\n");
        !          1035:                sir->csr = 0;
        !          1036:                DELAY(10);
        !          1037:                sir->csr = SI_CSR_INTR_EN|SI_CSR_SCSI_RES|SI_CSR_FIFO_RES;
        !          1038:                sir->sbc_wreg.mr = SBC_MR_EEI;
        !          1039:                c->c_flags &= ~SCSI_EN_RECON;
        !          1040:                if (c->c_disqh != NULL) {
        !          1041:                        c->c_flags |= SCSI_FLUSH_DISQ;
        !          1042:                        c->c_flush = c->c_disqt;
        !          1043:                }
        !          1044:                status = SE_FATAL;
        !          1045:                reset_occurred = 1;
        !          1046: 
        !          1047:                /* flush disconnect tasks now if possible */
        !          1048:                if ((un == NULL) && c->c_disqh) {
        !          1049:                        si_idle(c);
        !          1050:                        return;
        !          1051:                }
        !          1052:        }
        !          1053: 
        !          1054: done:
        !          1055:        /* cleanup after a dma operation */
        !          1056:        if (dma_cleanup) {
        !          1057:                resid = sir->bcr;
        !          1058:                si_dma_cleanup(c);
        !          1059:        }
        !          1060: 
        !          1061:        /* pass interrupt info to unit */
        !          1062:        if (un && un->un_wantint && (disconnect == 0)) {
        !          1063:                un->un_wantint = 0;
        !          1064:                if (status == SE_NO_ERROR) {
        !          1065:                        if (si_getstatus(un, 0) == 0) {
        !          1066:                                status = SE_RETRYABLE;
        !          1067:                        }
        !          1068:                } else if (reset_occurred == 0) {
        !          1069:                        si_reset(c);
        !          1070:                }
        !          1071:                (*un->un_ss->ss_intr)(c, resid, status);
        !          1072:        }
        !          1073: 
        !          1074:        if (disconnect) {
        !          1075:                /* start next I/O activity on controller */
        !          1076:                if ((un->un_mc->mc_tab.b_actf) && 
        !          1077:                    (un->un_mc->mc_tab.b_active == 0)) {
        !          1078:                        sistart(un);
        !          1079:                } else {
        !          1080:                        /* enable reconnect attempts */
        !          1081:                        sir->sbc_wreg.ser = SI_HOST_ID;
        !          1082:                        c->c_flags |= SCSI_EN_RECON;
        !          1083:                        if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !          1084:                                sir->csr &= ~SI_CSR_SEND;
        !          1085:                                sir->csr |= SI_CSR_DMA_EN;
        !          1086:                        }
        !          1087:                }
        !          1088:        }
        !          1089: }
        !          1090: 
        !          1091: /*
        !          1092:  * Handle target disconnecting.
        !          1093:  */
        !          1094: si_disconnect(c) 
        !          1095:        register struct scsi_ctlr *c;
        !          1096: {
        !          1097:        register struct scsi_unit *un = c->c_un;
        !          1098:        register struct mb_ctlr *mc = un->un_mc;
        !          1099:        register struct buf *dp;
        !          1100:        register struct scsi_si_reg *sir = c->c_sir;
        !          1101:        register u_char msg;
        !          1102: 
        !          1103:        /* get disconnect message(s) */
        !          1104:        msg = si_getdata(c, PHASE_MSG_IN);
        !          1105:        if (msg == SC_SAVE_DATA_PTR) {
        !          1106:                msg = si_getdata(c, PHASE_MSG_IN);
        !          1107:        }
        !          1108:        if (msg != SC_DISCONNECT) {
        !          1109:                return (0);
        !          1110:        }
        !          1111: 
        !          1112:        /* save dma info for reconnect */
        !          1113:        if (un->un_dma_curdir != SI_NO_DATA) {
        !          1114: 
        !          1115:                /* debug information */
        !          1116:                if (c->c_flags & SCSI_ONBOARD) {
        !          1117:                        if (scsi_dis_debug) {
        !          1118:                                sir->udc_raddr = UDC_ADR_COUNT;
        !          1119:                                printf("\tdiscon: udc_cnt %x\n", 
        !          1120:                                    sir->udc_rdata);
        !          1121:                        }
        !          1122:                        if ((un->un_dma_curaddr & 0xffff) != c->c_udct.laddr) {
        !          1123:                                printf("discon: caddr= %x, udc= %x\n",
        !          1124:                                    un->un_dma_curaddr, c->c_udct.laddr);
        !          1125:                        }
        !          1126:                }
        !          1127:                if (scsi_dis_debug) {
        !          1128:                    printf("\taddr= %x, cnt= %x, bcr= %x, sr= %x, baddr= %x\n",
        !          1129:                        un->un_dma_curaddr, un->un_dma_curcnt, 
        !          1130:                        sir->bcr, sir->csr, un->un_baddr);
        !          1131:                }
        !          1132: 
        !          1133:                /*
        !          1134:                 * Save dma information so dma can be restarted when
        !          1135:                 * a reconnect occurs.
        !          1136:                 */
        !          1137:                un->un_dma_curaddr += un->un_dma_curcnt - sir->bcr;
        !          1138:                un->un_dma_curcnt = sir->bcr;
        !          1139:        }
        !          1140: 
        !          1141:        /* 
        !          1142:         * Remove this disconnected task from the ctlr ready queue and save 
        !          1143:         * on disconnect queue until a reconnect is done.
        !          1144:         * Advance controller queue. Remove mainbus resource alloc info.
        !          1145:         */
        !          1146:        dp = mc->mc_tab.b_actf;
        !          1147:        mc->mc_tab.b_active = 0;
        !          1148:        mc->mc_tab.b_actf = dp->b_forw;
        !          1149:        mc->mc_mbinfo = 0;
        !          1150:        if (c->c_disqh == NULL) 
        !          1151:                c->c_disqh = dp;
        !          1152:        else
        !          1153:                c->c_disqt->b_forw = dp;
        !          1154:        dp->b_forw = NULL;
        !          1155:        c->c_disqt = dp;
        !          1156:        c->c_un = NULL;
        !          1157:        return (1);
        !          1158: }
        !          1159: 
        !          1160: /*
        !          1161:  * Complete reselection phase and reconnect to target.
        !          1162:  *
        !          1163:  * NOTE: this routine cannot use si_getdata() to get identify msg
        !          1164:  * from reconnecting target due to sun3/50 scsi interface. The bcr
        !          1165:  * must be setup before the target changes scsi bus to data phase
        !          1166:  * if the command being reconnected involves dma (which we do not
        !          1167:  * know until we get the identify msg). Thus we cannot acknowledge
        !          1168:  * the identify msg until some setup of the host adaptor registers 
        !          1169:  * is done.
        !          1170:  */
        !          1171: si_reconnect(c)
        !          1172:        register struct scsi_ctlr *c;
        !          1173: {
        !          1174:        register struct scsi_si_reg *sir = c->c_sir;
        !          1175:        register struct buf *dp;
        !          1176:        register struct buf *pdp;
        !          1177:        register struct scsi_unit *un;
        !          1178:        register int i;
        !          1179:        register u_char msg;
        !          1180:        register u_char lun;
        !          1181:        register u_char cdr;
        !          1182: 
        !          1183:        /* get reselecting target scsi id */
        !          1184:        cdr = sir->sbc_rreg.cdr & ~SI_HOST_ID;
        !          1185: 
        !          1186:        /* make sure there are only 2 scsi id's set */
        !          1187:        for (i=0; i < 8; i++) {
        !          1188:                if (cdr & (1<<i))
        !          1189:                        break;
        !          1190:        }
        !          1191:        cdr &= ~(1<<i);
        !          1192:        if (cdr != 0) {
        !          1193:                printf("si_recon: > 2 scsi ids\n");
        !          1194:                return;
        !          1195:        }
        !          1196: 
        !          1197:        /* acknowledge reselection */
        !          1198:        sir->sbc_wreg.icr = SBC_ICR_BUSY;
        !          1199:        if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_SEL, 0) == 0) {
        !          1200:                printf("si_recon: target never rel SEL\n");
        !          1201:                si_reset(c);
        !          1202:                return;
        !          1203:        }
        !          1204:        sir->sbc_wreg.icr = 0;
        !          1205: 
        !          1206:        /* setup for getting identify message from reconnecting target */
        !          1207:        sir->sbc_wreg.tcr = TCR_MSG_IN;
        !          1208:        if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1) == 0) {
        !          1209:                printf("si_recon: REQ not active\n");
        !          1210:                si_reset(c);
        !          1211:                return;
        !          1212:        }
        !          1213:        if ((sir->sbc_rreg.bsr & SBC_BSR_PMTCH) == 0) {
        !          1214:                printf("si_recon: phase mismatch\n");
        !          1215:                si_reset(c);
        !          1216:                return;
        !          1217:        }
        !          1218: 
        !          1219:        /* grab identify message */
        !          1220:        msg = sir->sbc_rreg.cdr;
        !          1221:        sir->sbc_wreg.tcr = 0;
        !          1222:        if ((msg != SC_IDENTIFY) && (msg != SC_DR_IDENTIFY)) {
        !          1223:                printf("si: recon, not id msg\n");
        !          1224:                si_reset(c);
        !          1225:                return;
        !          1226:        }
        !          1227:        lun = msg & 0x07;
        !          1228: 
        !          1229:        /* search disconnect q for reconnecting task */
        !          1230:        for (dp = c->c_disqh, pdp = NULL; dp; pdp = dp, dp = dp->b_forw) {
        !          1231:                un = (struct scsi_unit *)dp->b_un.b_addr;
        !          1232:                if ((un->un_target == i) && (un->un_lun == lun))
        !          1233:                        break;
        !          1234:        }
        !          1235:        if (dp == NULL) {
        !          1236:                printf("si: recon, never found dis unit\n");
        !          1237:                si_reset(c);
        !          1238:                return;
        !          1239:        }
        !          1240: 
        !          1241:        /* make sure there is no active I/O */
        !          1242:        if (un->un_mc->mc_tab.b_actf != NULL) {
        !          1243:                printf("si: recon, other I/O active\n");
        !          1244:                si_reset(c);
        !          1245:                return;
        !          1246:        }
        !          1247: 
        !          1248:        /* disable other reconnection attempts */
        !          1249:        sir->sbc_wreg.ser = 0;
        !          1250:        c->c_flags &= ~SCSI_EN_RECON;
        !          1251: 
        !          1252:        /* remove entity from disconnect q */
        !          1253:        if (dp == c->c_disqh)
        !          1254:                c->c_disqh = dp->b_forw;
        !          1255:        else
        !          1256:                pdp->b_forw = dp->b_forw;
        !          1257:        if (dp == c->c_disqt)
        !          1258:                c->c_disqt = pdp;
        !          1259:        dp->b_forw = NULL;
        !          1260: 
        !          1261:        /* requeue on controller queue */
        !          1262:        siustart(un);
        !          1263:        un->un_mc->mc_tab.b_active = 1;
        !          1264:        c->c_un = un;
        !          1265: 
        !          1266:        /* restart disconnect activity */
        !          1267:        if (un->un_dma_curdir != SI_NO_DATA) {
        !          1268:                /* restore mainbus resource allocation info */
        !          1269:                un->un_mc->mc_mbinfo = un->un_baddr;
        !          1270: 
        !          1271:                /* do initial dma setup */
        !          1272:                if (un->un_dma_curdir == SI_RECV_DATA)
        !          1273:                        sir->csr &= ~SI_CSR_SEND;
        !          1274:                else
        !          1275:                        sir->csr |= SI_CSR_SEND;
        !          1276:                sir->csr &= ~SI_CSR_FIFO_RES;
        !          1277:                sir->csr |= SI_CSR_FIFO_RES;
        !          1278:                sir->bcr = un->un_dma_curcnt;
        !          1279:                if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !          1280:                        sir->bcrh = 0;
        !          1281:                }
        !          1282: 
        !          1283:                if (scsi_dis_debug) {
        !          1284:                    printf("\taddr= %x, cnt= %x, bcr= %x, sr= %x, baddr= %x\n", 
        !          1285:                        un->un_dma_curaddr, un->un_dma_curcnt, sir->bcr, 
        !          1286:                        sir->csr, un->un_baddr);
        !          1287:                }
        !          1288: 
        !          1289:        }
        !          1290: 
        !          1291:        /* we can finally acknowledge identify message */
        !          1292:        sir->sbc_wreg.icr = SBC_ICR_ACK;
        !          1293:        if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0) == 0) {
        !          1294:                printf("si_recon: REQ not INactive\n");
        !          1295:                si_reset(c);
        !          1296:                return;
        !          1297:        }
        !          1298:        sir->sbc_wreg.icr = 0;
        !          1299: 
        !          1300:        /* may get restore pointers message */
        !          1301:        if ((sir->sbc_rreg.cbsr & SBC_CBSR_REQ) &&
        !          1302:            ((sir->sbc_rreg.cbsr & CBSR_PHASE_BITS) == PHASE_MSG_IN)) {
        !          1303:                msg = si_getdata(c, PHASE_MSG_IN);
        !          1304:        }
        !          1305: 
        !          1306:        /* do final setup for dma operation and start dma */
        !          1307:        if (un->un_dma_curdir != SI_NO_DATA) {
        !          1308:                if (c->c_flags & SCSI_ONBOARD)
        !          1309:                        si_ob_dma_setup(c, un);
        !          1310:                else
        !          1311:                        si_vme_dma_setup(c, un);
        !          1312:        } else if (un->un_wantint) {
        !          1313:                sir->sbc_wreg.mr |= SBC_MR_DMA;
        !          1314:                sir->sbc_wreg.tcr = TCR_UNSPECIFIED;
        !          1315:                if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !          1316:                        sir->csr &= ~SI_CSR_SEND;
        !          1317:                        sir->csr |= SI_CSR_DMA_EN;
        !          1318:                }
        !          1319:        }
        !          1320: }
        !          1321: 
        !          1322: /*
        !          1323:  * No current activity for the scsi bus. May need to flush some
        !          1324:  * disconnected tasks if a scsi bus reset occurred before the
        !          1325:  * target reconnected, since a scsi bus reset causes targets to 
        !          1326:  * "forget" about any disconnected activity.
        !          1327:  * Also, enable reconnect attempts.
        !          1328:  */
        !          1329: si_idle(c)
        !          1330:        register struct scsi_ctlr *c;
        !          1331: {
        !          1332:        register struct scsi_si_reg *sir = c->c_sir;
        !          1333:        register struct buf *dp;
        !          1334:        register struct scsi_unit *un;
        !          1335:        register int i;
        !          1336:        register int resid;
        !          1337: 
        !          1338:        if (c->c_flags & SCSI_FLUSHING) {
        !          1339:                if (scsi_reset_debug)
        !          1340:                        printf("si_idle: flushing, flags %x\n", c->c_flags);
        !          1341:                return;
        !          1342:        }
        !          1343: 
        !          1344:        /* flush disconnect tasks if a reconnect will never occur */
        !          1345:        if (c->c_flags & SCSI_FLUSH_DISQ) {
        !          1346:                if (scsi_reset_debug) {
        !          1347:                    printf("si_idle: flush: flags= %x, disqh= %x, disqt= %x\n", 
        !          1348:                        c->c_flags, c->c_disqh, c->c_disqt);
        !          1349:                }
        !          1350: 
        !          1351:                /* now in process of flushing tasks */
        !          1352:                c->c_flags &= ~SCSI_FLUSH_DISQ;
        !          1353:                c->c_flags |= SCSI_FLUSHING;
        !          1354: 
        !          1355:                for (dp = c->c_disqh; dp && c->c_flush; dp = c->c_disqh) {
        !          1356:                        /* keep track of last task to flush */
        !          1357:                        if (c->c_flush == c->c_disqh) 
        !          1358:                                c->c_flush = NULL;
        !          1359: 
        !          1360:                        /* remove tasks from disconnect q */
        !          1361:                        un = (struct scsi_unit *)dp->b_un.b_addr;
        !          1362:                        c->c_disqh = dp->b_forw;
        !          1363:                        dp->b_forw = NULL;
        !          1364: 
        !          1365:                        /* requeue on controller q */
        !          1366:                        siustart(un);
        !          1367:                        un->un_mc->mc_tab.b_active = 1;
        !          1368:                        c->c_un = un;
        !          1369: 
        !          1370:                        /* inform device routines of error */
        !          1371:                        if (un->un_dma_curdir != SI_NO_DATA) {
        !          1372:                                un->un_mc->mc_mbinfo = un->un_baddr;
        !          1373:                                resid = un->un_dma_curcnt;
        !          1374:                        } else {
        !          1375:                                resid = 0;
        !          1376:                        }
        !          1377:                        (*un->un_ss->ss_intr)(c, resid, SE_FATAL);
        !          1378:                }
        !          1379:                if (c->c_disqh == NULL) {
        !          1380:                        c->c_disqt = NULL;
        !          1381:                }
        !          1382:                c->c_flags &= ~SCSI_FLUSHING;
        !          1383:        }
        !          1384: 
        !          1385:        /* enable reconnect attempts */
        !          1386:        sir->sbc_wreg.ser = SI_HOST_ID;
        !          1387:        c->c_flags |= SCSI_EN_RECON;
        !          1388:        if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !          1389:                sir->csr &= ~SI_CSR_SEND;
        !          1390:                sir->csr |= SI_CSR_DMA_EN;
        !          1391:        }
        !          1392: }
        !          1393: 
        !          1394: /*
        !          1395:  * Get status bytes from scsi bus.
        !          1396:  */
        !          1397: si_getstatus(un, recurse)
        !          1398:        register struct scsi_unit *un;
        !          1399: {
        !          1400:        register struct scsi_ctlr *c = un->un_c;
        !          1401:        register u_char *cp = (u_char *)&c->c_scb;
        !          1402:        struct scsi_cdb save_cdb;
        !          1403:        struct scsi_scb save_scb;
        !          1404:        register int i;
        !          1405:        register int b;
        !          1406:        register int save_dma_addr;
        !          1407:        register int save_dma_count;
        !          1408:        register int save_reg_dma_count;
        !          1409:        int resid;
        !          1410:        short retval = 1;
        !          1411:        int s;
        !          1412: 
        !          1413:        /* get all the status bytes */
        !          1414:        for (i = 0;;) {
        !          1415:                b = si_getdata(c, PHASE_STATUS);
        !          1416:                if (b < 0) {
        !          1417:                        break;
        !          1418:                }
        !          1419:                if (i < STATUS_LEN) {
        !          1420:                        cp[i++] = b;
        !          1421:                }
        !          1422:        }
        !          1423: 
        !          1424:        /* get command complete message */
        !          1425:        b = si_getdata(c, PHASE_MSG_IN);
        !          1426:        if (b != SC_COMMAND_COMPLETE) {
        !          1427:                if (scsi_debug) {
        !          1428:                        printf("Invalid SCSI message: %x\n", b);
        !          1429:                        printf("Status bytes (%d):", i);
        !          1430:                        for (b = 0; b < i; b++) {
        !          1431:                                printf(" %x", cp[b]);
        !          1432:                        }
        !          1433:                        printf("\n");
        !          1434:                }
        !          1435:                return (0);
        !          1436:        }
        !          1437:        if (scsi_debug) {
        !          1438:                printf("si%d: si_getstatus: Got status (%d) ", SINUM(c), i);
        !          1439:                for (b = 0; b < i; b++) {
        !          1440:                        printf(" %x", cp[b]);
        !          1441:                }
        !          1442:                printf("\n");
        !          1443:        }
        !          1444:        if (c->c_scb.busy) {
        !          1445:                return (0);
        !          1446:        }
        !          1447: 
        !          1448:        /* check for sense data */
        !          1449:        if (c->c_scb.chk) {
        !          1450:                if (recurse) {
        !          1451:                        printf("scsi: chk on sense: invalid\n");
        !          1452:                        return (0);
        !          1453:                }
        !          1454: 
        !          1455:                /* save information while we get sense */
        !          1456:                save_cdb = c->c_cdb;
        !          1457:                save_scb = c->c_scb;
        !          1458:                save_dma_addr = un->un_dma_addr;
        !          1459:                save_dma_count = un->un_dma_count;
        !          1460:                save_reg_dma_count = c->c_sir->bcr;
        !          1461: 
        !          1462:                /* set up for getting sense */
        !          1463:                c->c_cdb.cmd = SC_REQUEST_SENSE;
        !          1464:                c->c_cdb.lun = un->un_lun;
        !          1465:                cdbaddr(&c->c_cdb, 0);
        !          1466:                c->c_cdb.count = sizeof(struct scsi_sense);
        !          1467:                un->un_dma_addr = (int)c->c_sense - (int)DVMA;
        !          1468:                un->un_dma_count = sizeof(struct scsi_sense);
        !          1469: 
        !          1470:                /* get sense */
        !          1471:                if ((s=0),si_cmd(c, un, 0) == 0 ||
        !          1472:                    (s=1),si_cmdwait(c) == 0 ||
        !          1473:                    (s=2),si_getstatus(un, 1) == 0) {
        !          1474:                        printf("scsi: cannot get sense %d\n", s);
        !          1475:                        si_off(un);
        !          1476:                        retval = 0;
        !          1477:                } 
        !          1478: 
        !          1479:                /* restore pre sense information */
        !          1480:                c->c_cdb = save_cdb;
        !          1481:                c->c_scb = save_scb;
        !          1482:                un->un_dma_addr = save_dma_addr;
        !          1483:                un->un_dma_count = save_dma_count;
        !          1484:                c->c_sir->bcr = save_reg_dma_count;
        !          1485:        }
        !          1486:        return (retval);
        !          1487: }
        !          1488: 
        !          1489: /* 
        !          1490:  * Wait for a scsi dma request to complete.
        !          1491:  * Disconnects were disabled in si_cmd() when polling for command completion.
        !          1492:  */
        !          1493: si_cmdwait(c)
        !          1494:        register struct scsi_ctlr *c;
        !          1495: {
        !          1496:        register struct scsi_si_reg *sir = c->c_sir;
        !          1497:        register struct scsi_unit *un = c->c_un;
        !          1498:        register u_char junk;
        !          1499: 
        !          1500:        /* wait for dma transfer to complete */
        !          1501:        if (si_wait((u_short *)&sir->csr, SI_CSR_DMA_ACTIVE, 0) == 0) {
        !          1502:                printf("si_cmdwait: DMA_ACTIVE still on\n");
        !          1503:                si_reset(c);
        !          1504:                return (0);
        !          1505:        }
        !          1506: 
        !          1507:        /* if command does not involve dma activity, then we are finished */
        !          1508:        if (un->un_dma_curdir == SI_NO_DATA) {
        !          1509:                return (1);
        !          1510:        }
        !          1511: 
        !          1512:        /* wait for indication of dma completion */
        !          1513:        if (si_wait((u_short *)&sir->csr, 
        !          1514:            SI_CSR_SBC_IP|SI_CSR_DMA_IP|SI_CSR_DMA_CONFLICT, 1) == 0) {
        !          1515:                printf("si_cmdwait: dma op never completed\n");
        !          1516:                si_reset(c);
        !          1517:                return (0);
        !          1518:        }
        !          1519: 
        !          1520:        /* 
        !          1521:         * For vme host adaptor interface, must disable dma before
        !          1522:         * accessing any registers other than the csr or a dma
        !          1523:         * conflict error will occur.
        !          1524:         */
        !          1525:        if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !          1526:                sir->csr &= ~SI_CSR_DMA_EN;
        !          1527:        }
        !          1528: 
        !          1529:        /* make sure dma completely complete */
        !          1530:        if ((sir->csr & SI_CSR_SBC_IP) == 0) {
        !          1531:                if (sir->csr & SI_CSR_DMA_BUS_ERR) {
        !          1532:                        printf("si_cmdwait: bus error during dma\n");
        !          1533:                } else if (sir->csr & SI_CSR_DMA_CONFLICT) {
        !          1534:                        printf("si_cmdwait: invalid reg access during dma\n");
        !          1535:                } else {
        !          1536:                        if (c->c_flags & SCSI_ONBOARD)
        !          1537:                                printf("si_cmdwait: dma ip, unknown reason\n");
        !          1538:                        else
        !          1539:                                printf("si_cmdwait: dma overrun\n");
        !          1540:                }
        !          1541:                si_reset(c);
        !          1542:                return (0);
        !          1543:        }
        !          1544: 
        !          1545:        /* handle special dma recv situations */
        !          1546:        if (un->un_dma_curdir == SI_RECV_DATA) {
        !          1547:                if (si_dma_recv(c) == 0) {
        !          1548:                        si_reset(c);
        !          1549:                        return (0);
        !          1550:                }
        !          1551:        }
        !          1552: 
        !          1553:        /* ack sbc interrupt and cleanup */
        !          1554:        junk = sir->sbc_rreg.clr;
        !          1555:        si_dma_cleanup(c);
        !          1556:        return (1);
        !          1557: }
        !          1558: 
        !          1559: /*
        !          1560:  * Wait for a condition to be (de)asserted on the scsi bus.
        !          1561:  */
        !          1562: si_sbc_wait(reg, cond, set)
        !          1563:        register caddr_t reg;
        !          1564:        register u_char cond;
        !          1565:        register int set;
        !          1566: {
        !          1567:        register int i;
        !          1568:        register u_char regval;
        !          1569: 
        !          1570:        for (i = 0; i < SI_WAIT_COUNT; i++) {
        !          1571:                regval = *reg;
        !          1572:                if ((set == 1) && (regval & cond)) {
        !          1573:                        return (1);
        !          1574:                }
        !          1575:                if ((set == 0) && !(regval & cond)) {
        !          1576:                        return (1);
        !          1577:                } 
        !          1578:                DELAY(10);
        !          1579:        }
        !          1580:        return (0);
        !          1581: }
        !          1582: 
        !          1583: /*
        !          1584:  * Wait for a condition to be (de)asserted.
        !          1585:  */
        !          1586: si_wait(reg, cond, set)
        !          1587:        register u_short *reg;
        !          1588:        register u_short cond;
        !          1589:        register int set;
        !          1590: {
        !          1591:        register int i;
        !          1592:        register u_short regval;
        !          1593: 
        !          1594:        for (i = 0; i < SI_WAIT_COUNT; i++) {
        !          1595:                regval = *reg;
        !          1596:                if ((set == 1) && (regval & cond)) {
        !          1597:                        return (1);
        !          1598:                }
        !          1599:                if ((set == 0) && !(regval & cond)) {
        !          1600:                        return (1);
        !          1601:                } 
        !          1602:                DELAY(10);
        !          1603:        }
        !          1604:        return (0);
        !          1605: }
        !          1606: 
        !          1607: /*
        !          1608:  * Put data onto the scsi bus.
        !          1609:  */
        !          1610: si_putdata(c, phase, data, num)
        !          1611:        register struct scsi_ctlr *c;
        !          1612:        register u_short phase;
        !          1613:        register u_char *data;
        !          1614:        register int num;
        !          1615: {
        !          1616:        register struct scsi_si_reg *sir = c->c_sir;
        !          1617:        register int i;
        !          1618: 
        !          1619:        /* set up tcr so a phase match will occur */
        !          1620:        if (phase == PHASE_COMMAND) {
        !          1621:                sir->sbc_wreg.tcr = TCR_COMMAND;
        !          1622:        } else if (phase == PHASE_MSG_OUT) {
        !          1623:                sir->sbc_wreg.tcr = TCR_MSG_OUT;
        !          1624:        } else {
        !          1625:                if (scsi_debug)
        !          1626:                        printf("si_putdata %d phase not supported\n", phase);
        !          1627:                return (0);
        !          1628:        }
        !          1629: 
        !          1630:        /* put all desired bytes onto scsi bus */
        !          1631:        for (i = 0; i < num; i++ ) {
        !          1632: 
        !          1633:                /* wait for target to request a byte */
        !          1634:                if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1) 
        !          1635:                    == 0) {
        !          1636:                        if (scsi_debug)
        !          1637:                                printf("si: putdata, REQ not active\n");
        !          1638:                        si_reset(c);
        !          1639:                        return (0);
        !          1640:                }
        !          1641: 
        !          1642:                /* make sure phase match occurred */
        !          1643:                if ((sir->sbc_rreg.bsr & SBC_BSR_PMTCH) == 0) {
        !          1644:                        if (phase != PHASE_MSG_OUT) {
        !          1645:                                if (scsi_debug)
        !          1646:                                        printf("si: putdata, phase mismatch\n");
        !          1647:                                si_reset(c);
        !          1648:                        } else {
        !          1649:                                sir->sbc_wreg.tcr = 0;
        !          1650:                        }
        !          1651:                        return (0);
        !          1652:                }
        !          1653: 
        !          1654:                /* load data */
        !          1655:                sir->sbc_wreg.odr = *data++;
        !          1656:                sir->sbc_wreg.icr = SBC_ICR_DATA;
        !          1657: 
        !          1658:                /* complete req/ack handshake */
        !          1659:                sir->sbc_wreg.icr |= SBC_ICR_ACK;
        !          1660:                if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0) 
        !          1661:                    == 0) {
        !          1662:                        if (scsi_debug)
        !          1663:                                printf("si: putdata, req not INactive\n");
        !          1664:                        si_reset(c);
        !          1665:                        return (0);
        !          1666:                }
        !          1667:                sir->sbc_wreg.icr = 0;
        !          1668:        }
        !          1669:        sir->sbc_wreg.tcr = 0;
        !          1670:        return (1);
        !          1671: }
        !          1672: 
        !          1673: /*
        !          1674:  * Get data from the scsi bus.
        !          1675:  */
        !          1676: si_getdata(c, phase)
        !          1677:        register struct scsi_ctlr *c;
        !          1678:        register u_short phase;
        !          1679: {
        !          1680:        register struct scsi_si_reg *sir = c->c_sir;
        !          1681:        register u_char data;
        !          1682: 
        !          1683:        /* check for valid phase */
        !          1684:        if (phase == PHASE_STATUS) {
        !          1685:                sir->sbc_wreg.tcr = TCR_STATUS;
        !          1686:        } else if (phase == PHASE_MSG_IN) {
        !          1687:                sir->sbc_wreg.tcr = TCR_MSG_IN;
        !          1688:        } else {
        !          1689:                if (scsi_debug)
        !          1690:                        printf("si: getdata %d phase not supported\n", phase);
        !          1691:                return (-1);
        !          1692:        }
        !          1693: 
        !          1694:        /* wait for target request */
        !          1695:        if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1) == 0) {
        !          1696:                if (scsi_debug) {
        !          1697:                        printf("si: getdata, REQ not active, cbsr %x\n",
        !          1698:                            sir->sbc_rreg.cbsr);
        !          1699:                }
        !          1700:                sir->sbc_wreg.tcr = 0;
        !          1701:                return (-1);
        !          1702:        }
        !          1703: 
        !          1704:        /* check for correct phase on scsi bus */
        !          1705:        if ((sir->sbc_rreg.bsr & SBC_BSR_PMTCH) == 0) {
        !          1706:                if (phase != PHASE_STATUS) {
        !          1707:                        if (scsi_debug) {
        !          1708:                                printf("si: getdata, bad phase\n");
        !          1709:                        }
        !          1710:                        si_reset(c);
        !          1711:                } else {
        !          1712:                        sir->sbc_wreg.tcr = 0;
        !          1713:                }
        !          1714:                return (-1);
        !          1715:        }
        !          1716: 
        !          1717:        /* grab data and complete req/ack handshake */
        !          1718:        data = sir->sbc_rreg.cdr;
        !          1719:        sir->sbc_wreg.icr = SBC_ICR_ACK;
        !          1720:        if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0) == 0) {
        !          1721:                if (scsi_debug) 
        !          1722:                        printf("si: getdata, REQ not inactive\n");
        !          1723:                si_reset(c);
        !          1724:                return (-1);
        !          1725:        }
        !          1726:        sir->sbc_wreg.icr = 0;
        !          1727:        sir->sbc_wreg.tcr = 0;
        !          1728:        return (data);
        !          1729: }
        !          1730: 
        !          1731: /*
        !          1732:  * Reset SCSI control logic and bus.
        !          1733:  */
        !          1734: si_reset(c)
        !          1735:        register struct scsi_ctlr *c;
        !          1736: {
        !          1737:        register struct scsi_si_reg *sir = c->c_sir;
        !          1738:        register u_char junk;
        !          1739: 
        !          1740:        if (scsi_debug) {
        !          1741:                printf("scsi reset, sr= %x, bcr= %x\n", sir->csr, sir->bcr);
        !          1742:        }
        !          1743: 
        !          1744:        /* reset scsi control logic */
        !          1745:        sir->bcr = 0;
        !          1746:        sir->csr = 0;
        !          1747:        DELAY(10);
        !          1748:        sir->csr = SI_CSR_SCSI_RES|SI_CSR_FIFO_RES;
        !          1749:        if ((c->c_flags & SCSI_ONBOARD) == 0) {
        !          1750:                sir->dma_addr = 0;
        !          1751:                sir->dma_count = 0;
        !          1752:        }
        !          1753: 
        !          1754:        /* issue scsi bus reset (make sure interrupts from sbc are disabled) */
        !          1755:        sir->sbc_wreg.icr = SBC_ICR_RST;
        !          1756:        DELAY(10);
        !          1757:        sir->sbc_wreg.icr = 0;
        !          1758:        junk = sir->sbc_rreg.clr;
        !          1759: 
        !          1760:        /* enable sbc interrupts */
        !          1761:        sir->csr |= SI_CSR_INTR_EN;
        !          1762:        sir->sbc_wreg.mr = SBC_MR_EEI;
        !          1763: 
        !          1764:        /* reconnection attempts are no longer enabled */
        !          1765:        c->c_flags &= ~SCSI_EN_RECON;
        !          1766: 
        !          1767:        /* disconnect queue needs to be flushed */
        !          1768:        if (c->c_disqh != NULL) {
        !          1769:                c->c_flags |= SCSI_FLUSH_DISQ;
        !          1770:                c->c_flush = c->c_disqt;
        !          1771:        }
        !          1772: }
        !          1773: 
        !          1774: /*
        !          1775:  * Return residual count for a dma.
        !          1776:  */
        !          1777: si_dmacnt(c)
        !          1778:        register struct scsi_ctlr *c;
        !          1779: {
        !          1780:        if (c->c_flags & SCSI_ONBOARD) {
        !          1781:                return (c->c_sir->bcr);
        !          1782:        } else {
        !          1783:                return ( ((c->c_sir->bcrh) << 16) | (c->c_sir->bcr) );
        !          1784:        }
        !          1785: }
        !          1786: 
        !          1787: #endif NSI > 0

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.