Annotation of researchv9/sys/sundev/si.c, revision 1.1.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.