[BACK]Return to mscp_subr.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / mscp

Annotation of sys/arch/vax/mscp/mscp_subr.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: mscp_subr.c,v 1.9 2005/11/24 04:54:49 brad Exp $      */
        !             2: /*     $NetBSD: mscp_subr.c,v 1.18 2001/11/13 07:38:28 lukem Exp $     */
        !             3: /*
        !             4:  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
        !             5:  * Copyright (c) 1988 Regents of the University of California.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to Berkeley by
        !             9:  * Chris Torek.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. Neither the name of the University nor the names of its contributors
        !            20:  *    may be used to endorse or promote products derived from this software
        !            21:  *    without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  *
        !            35:  *     @(#)mscp.c      7.5 (Berkeley) 12/16/90
        !            36:  */
        !            37:
        !            38: /*
        !            39:  * MSCP generic driver routines
        !            40:  */
        !            41:
        !            42: #include <sys/cdefs.h>
        !            43:
        !            44: #include <sys/param.h>
        !            45: #include <sys/device.h>
        !            46: #include <sys/buf.h>
        !            47: #include <sys/systm.h>
        !            48: #include <sys/proc.h>
        !            49:
        !            50: #include <machine/bus.h>
        !            51: #include <machine/sid.h>
        !            52:
        !            53: #include <arch/vax/mscp/mscp.h>
        !            54: #include <arch/vax/mscp/mscpreg.h>
        !            55: #include <arch/vax/mscp/mscpvar.h>
        !            56:
        !            57: #include "ra.h"
        !            58: #include "mt.h"
        !            59:
        !            60: #define b_forw b_hash.le_next
        !            61:
        !            62: int    mscp_match(struct device *, struct cfdata *, void *);
        !            63: void   mscp_attach(struct device *, struct device *, void *);
        !            64: void   mscp_start(struct       mscp_softc *);
        !            65: int    mscp_init(struct  mscp_softc *);
        !            66: void   mscp_initds(struct mscp_softc *);
        !            67: int    mscp_waitstep(struct mscp_softc *, int, int);
        !            68:
        !            69: struct cfattach mscpbus_ca = {
        !            70:        sizeof(struct mscp_softc), (cfmatch_t)mscp_match, mscp_attach
        !            71: };
        !            72:
        !            73: struct cfdriver mscpbus_cd = {
        !            74:        NULL, "mscpbus", DV_DULL
        !            75: };
        !            76:
        !            77: #define        READ_SA         (bus_space_read_2(mi->mi_iot, mi->mi_sah, 0))
        !            78: #define        READ_IP         (bus_space_read_2(mi->mi_iot, mi->mi_iph, 0))
        !            79: #define        WRITE_IP(x)     bus_space_write_2(mi->mi_iot, mi->mi_iph, 0, (x))
        !            80: #define        WRITE_SW(x)     bus_space_write_2(mi->mi_iot, mi->mi_swh, 0, (x))
        !            81:
        !            82: struct mscp slavereply;
        !            83:
        !            84: /*
        !            85:  * This function is for delay during init. Some MSCP clone card (Dilog)
        !            86:  * can't handle fast read from its registers, and therefore need
        !            87:  * a delay between them.
        !            88:  */
        !            89:
        !            90: #define DELAYTEN 1000
        !            91: int
        !            92: mscp_waitstep(mi, mask, result)
        !            93:        struct mscp_softc *mi;
        !            94:        int mask, result;
        !            95: {
        !            96:        int     status = 1;
        !            97:
        !            98:        if ((READ_SA & mask) != result) {
        !            99:                volatile int count = 0;
        !           100:                while ((READ_SA & mask) != result) {
        !           101:                        DELAY(10000);
        !           102:                        count += 1;
        !           103:                        if (count > DELAYTEN)
        !           104:                                break;
        !           105:                }
        !           106:                if (count > DELAYTEN)
        !           107:                        status = 0;
        !           108:        }
        !           109:        return status;
        !           110: }
        !           111:
        !           112: int
        !           113: mscp_match(parent, match, aux)
        !           114:        struct device *parent;
        !           115:        struct cfdata *match;
        !           116:        void *aux;
        !           117: {
        !           118:        struct  mscp_attach_args *ma = aux;
        !           119:
        !           120: #if NRA || NRX
        !           121:        if (ma->ma_type & MSCPBUS_DISK)
        !           122:                return 1;
        !           123: #endif
        !           124: #if NMT
        !           125:        if (ma->ma_type & MSCPBUS_TAPE)
        !           126:                return 1;
        !           127: #endif
        !           128:        return 0;
        !           129: };
        !           130:
        !           131: void
        !           132: mscp_attach(parent, self, aux)
        !           133:        struct device *parent, *self;
        !           134:        void *aux;
        !           135: {
        !           136:        struct  mscp_attach_args *ma = aux;
        !           137:        struct  mscp_softc *mi = (void *)self;
        !           138:        volatile struct mscp *mp;
        !           139:        volatile int i;
        !           140:        int     timeout, next = 0;
        !           141:
        !           142:        mi->mi_mc = ma->ma_mc;
        !           143:        mi->mi_me = NULL;
        !           144:        mi->mi_type = ma->ma_type;
        !           145:        mi->mi_uda = ma->ma_uda;
        !           146:        mi->mi_dmat = ma->ma_dmat;
        !           147:        mi->mi_dmam = ma->ma_dmam;
        !           148:        mi->mi_iot = ma->ma_iot;
        !           149:        mi->mi_iph = ma->ma_iph;
        !           150:        mi->mi_sah = ma->ma_sah;
        !           151:        mi->mi_swh = ma->ma_swh;
        !           152:        mi->mi_ivec = ma->ma_ivec;
        !           153:        mi->mi_adapnr = ma->ma_adapnr;
        !           154:        mi->mi_ctlrnr = ma->ma_ctlrnr;
        !           155:        *ma->ma_softc = mi;
        !           156:        /*
        !           157:         * Go out to init the bus, so that we can give commands
        !           158:         * to its devices.
        !           159:         */
        !           160:        mi->mi_cmd.mri_size = NCMD;
        !           161:        mi->mi_cmd.mri_desc = mi->mi_uda->mp_ca.ca_cmddsc;
        !           162:        mi->mi_cmd.mri_ring = mi->mi_uda->mp_cmd;
        !           163:        mi->mi_rsp.mri_size = NRSP;
        !           164:        mi->mi_rsp.mri_desc = mi->mi_uda->mp_ca.ca_rspdsc;
        !           165:        mi->mi_rsp.mri_ring = mi->mi_uda->mp_rsp;
        !           166:        SIMPLEQ_INIT(&mi->mi_resq);
        !           167:
        !           168:        if (mscp_init(mi)) {
        !           169:                printf("%s: can't init, controller hung\n",
        !           170:                    mi->mi_dev.dv_xname);
        !           171:                return;
        !           172:        }
        !           173:        for (i = 0; i < NCMD; i++) {
        !           174:                mi->mi_mxiuse |= (1 << i);
        !           175:                if (bus_dmamap_create(mi->mi_dmat, (64*1024), 16, (64*1024),
        !           176:                    0, BUS_DMA_NOWAIT, &mi->mi_xi[i].mxi_dmam)) {
        !           177:                        printf("Couldn't alloc dmamap %d\n", i);
        !           178:                        return;
        !           179:                }
        !           180:        }
        !           181:
        !           182:
        !           183: #if NRA
        !           184:        if (ma->ma_type & MSCPBUS_DISK) {
        !           185:                extern  struct mscp_device ra_device;
        !           186:
        !           187:                mi->mi_me = &ra_device;
        !           188:        }
        !           189: #endif
        !           190: #if NMT
        !           191:        if (ma->ma_type & MSCPBUS_TAPE) {
        !           192:                extern  struct mscp_device mt_device;
        !           193:
        !           194:                mi->mi_me = &mt_device;
        !           195:        }
        !           196: #endif
        !           197:        /*
        !           198:         * Go out and search for sub-units on this MSCP bus,
        !           199:         * and call config_found for each found.
        !           200:         */
        !           201: findunit:
        !           202:        mp = mscp_getcp(mi, MSCP_DONTWAIT);
        !           203:        if (mp == NULL)
        !           204:                panic("mscpattach: no packets");
        !           205:        mp->mscp_opcode = M_OP_GETUNITST;
        !           206:        mp->mscp_unit = next;
        !           207:        mp->mscp_modifier = M_GUM_NEXTUNIT;
        !           208:        *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
        !           209:        slavereply.mscp_opcode = 0;
        !           210:
        !           211:        i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
        !           212:        mp = &slavereply;
        !           213:        timeout = 1000;
        !           214:        while (timeout-- > 0) {
        !           215:                DELAY(10000);
        !           216:                if (mp->mscp_opcode)
        !           217:                        goto gotit;
        !           218:        }
        !           219:        printf("%s: no response to Get Unit Status request\n",
        !           220:            mi->mi_dev.dv_xname);
        !           221:        return;
        !           222:
        !           223: gotit: /*
        !           224:         * Got a slave response.  If the unit is there, use it.
        !           225:         */
        !           226:        switch (mp->mscp_status & M_ST_MASK) {
        !           227:
        !           228:        case M_ST_SUCCESS:      /* worked */
        !           229:        case M_ST_AVAILABLE:    /* found another drive */
        !           230:                break;          /* use it */
        !           231:
        !           232:        case M_ST_OFFLINE:
        !           233:                /*
        !           234:                 * Figure out why it is off line.  It may be because
        !           235:                 * it is nonexistent, or because it is spun down, or
        !           236:                 * for some other reason.
        !           237:                 */
        !           238:                switch (mp->mscp_status & ~M_ST_MASK) {
        !           239:
        !           240:                case M_OFFLINE_UNKNOWN:
        !           241:                        /*
        !           242:                         * No such drive, and there are none with
        !           243:                         * higher unit numbers either, if we are
        !           244:                         * using M_GUM_NEXTUNIT.
        !           245:                         */
        !           246:                        mi->mi_ierr = 3;
        !           247:                        return;
        !           248:
        !           249:                case M_OFFLINE_UNMOUNTED:
        !           250:                        /*
        !           251:                         * The drive is not spun up.  Use it anyway.
        !           252:                         *
        !           253:                         * N.B.: this seems to be a common occurrance
        !           254:                         * after a power failure.  The first attempt
        !           255:                         * to bring it on line seems to spin it up
        !           256:                         * (and thus takes several minutes).  Perhaps
        !           257:                         * we should note here that the on-line may
        !           258:                         * take longer than usual.
        !           259:                         */
        !           260:                        break;
        !           261:
        !           262:                default:
        !           263:                        /*
        !           264:                         * In service, or something else equally unusable.
        !           265:                         */
        !           266:                        printf("%s: unit %d off line: ", mi->mi_dev.dv_xname,
        !           267:                                mp->mscp_unit);
        !           268:                        mscp_printevent((struct mscp *)mp);
        !           269:                        next++;
        !           270:                        goto findunit;
        !           271:                }
        !           272:                break;
        !           273:
        !           274:        default:
        !           275:                printf("%s: unable to get unit status: ", mi->mi_dev.dv_xname);
        !           276:                mscp_printevent((struct mscp *)mp);
        !           277:                return;
        !           278:        }
        !           279:
        !           280:        /*
        !           281:         * If we get a lower number, we have circulated around all
        !           282:         * devices and are finished, otherwise try to find next unit.
        !           283:         * We shouldn't ever get this, it's a workaround.
        !           284:         */
        !           285:        if (mp->mscp_unit < next)
        !           286:                return;
        !           287:
        !           288:        next = mp->mscp_unit + 1;
        !           289:        goto findunit;
        !           290: }
        !           291:
        !           292:
        !           293: /*
        !           294:  * The ctlr gets initialised, normally after boot but may also be
        !           295:  * done if the ctlr gets in an unknown state. Returns 1 if init
        !           296:  * fails, 0 otherwise.
        !           297:  */
        !           298: int
        !           299: mscp_init(mi)
        !           300:        struct  mscp_softc *mi;
        !           301: {
        !           302:        struct  mscp *mp;
        !           303:        volatile int i;
        !           304:        int     status, count;
        !           305:        unsigned int j = 0;
        !           306:
        !           307:        /*
        !           308:         * While we are thinking about it, reset the next command
        !           309:         * and response indices.
        !           310:         */
        !           311:        mi->mi_cmd.mri_next = 0;
        !           312:        mi->mi_rsp.mri_next = 0;
        !           313:
        !           314:        mi->mi_flags |= MSC_IGNOREINTR;
        !           315:
        !           316:        if ((mi->mi_type & MSCPBUS_KDB) == 0)
        !           317:                WRITE_IP(0); /* Kick off */;
        !           318:
        !           319:        status = mscp_waitstep(mi, MP_STEP1, MP_STEP1);/* Wait to it wakes up */
        !           320:        if (status == 0)
        !           321:                return 1; /* Init failed */
        !           322:        if (READ_SA & MP_ERR) {
        !           323:                (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
        !           324:                return 1;
        !           325:        }
        !           326:
        !           327:        /* step1 */
        !           328:        WRITE_SW(MP_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) |
        !           329:            MP_IE | (mi->mi_ivec >> 2));
        !           330:        status = mscp_waitstep(mi, STEP1MASK, STEP1GOOD);
        !           331:        if (status == 0) {
        !           332:                (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
        !           333:                return 1;
        !           334:        }
        !           335:
        !           336:        /* step2 */
        !           337:        WRITE_SW(((mi->mi_dmam->dm_segs[0].ds_addr & 0xffff) +
        !           338:            offsetof(struct mscp_pack, mp_ca.ca_rspdsc[0])) |
        !           339:            (vax_cputype == VAX_780 || vax_cputype == VAX_8600 ? MP_PI : 0));
        !           340:        status = mscp_waitstep(mi, STEP2MASK, STEP2GOOD(mi->mi_ivec >> 2));
        !           341:        if (status == 0) {
        !           342:                (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
        !           343:                return 1;
        !           344:        }
        !           345:
        !           346:        /* step3 */
        !           347:        WRITE_SW((mi->mi_dmam->dm_segs[0].ds_addr >> 16));
        !           348:        status = mscp_waitstep(mi, STEP3MASK, STEP3GOOD);
        !           349:        if (status == 0) {
        !           350:                (*mi->mi_mc->mc_saerror)(mi->mi_dev.dv_parent, 0);
        !           351:                return 1;
        !           352:        }
        !           353:        i = READ_SA & 0377;
        !           354:        printf(": version %d model %d\n", i & 15, i >> 4);
        !           355:
        !           356: #define BURST 4 /* XXX */
        !           357:        if (mi->mi_type & MSCPBUS_UDA) {
        !           358:                WRITE_SW(MP_GO | (BURST - 1) << 2);
        !           359:                printf("%s: DMA burst size set to %d\n",
        !           360:                    mi->mi_dev.dv_xname, BURST);
        !           361:        }
        !           362:        WRITE_SW(MP_GO);
        !           363:
        !           364:        mscp_initds(mi);
        !           365:        mi->mi_flags &= ~MSC_IGNOREINTR;
        !           366:
        !           367:        /*
        !           368:         * Set up all necessary info in the bus softc struct, get a
        !           369:         * mscp packet and set characteristics for this controller.
        !           370:         */
        !           371:        mi->mi_credits = MSCP_MINCREDITS + 1;
        !           372:        mp = mscp_getcp(mi, MSCP_DONTWAIT);
        !           373:
        !           374:        mi->mi_credits = 0;
        !           375:        mp->mscp_opcode = M_OP_SETCTLRC;
        !           376:        mp->mscp_unit = mp->mscp_modifier = mp->mscp_flags =
        !           377:            mp->mscp_sccc.sccc_version = mp->mscp_sccc.sccc_hosttimo =
        !           378:            mp->mscp_sccc.sccc_time = mp->mscp_sccc.sccc_time1 =
        !           379:            mp->mscp_sccc.sccc_errlgfl = 0;
        !           380:        mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC | M_CF_THIS;
        !           381:        *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
        !           382:        i = READ_IP;
        !           383:
        !           384:        count = 0;
        !           385:        while (count < DELAYTEN) {
        !           386:                if (((volatile int)mi->mi_flags & MSC_READY) != 0)
        !           387:                        break;
        !           388:                if ((j = READ_SA) & MP_ERR)
        !           389:                        goto out;
        !           390:                DELAY(10000);
        !           391:                count += 1;
        !           392:        }
        !           393:        if (count == DELAYTEN) {
        !           394: out:
        !           395:                printf("%s: couldn't set ctlr characteristics, sa=%x\n",
        !           396:                    mi->mi_dev.dv_xname, j);
        !           397:                return 1;
        !           398:        }
        !           399:        return 0;
        !           400: }
        !           401:
        !           402: /*
        !           403:  * Initialise the various data structures that control the mscp protocol.
        !           404:  */
        !           405: void
        !           406: mscp_initds(mi)
        !           407:        struct mscp_softc *mi;
        !           408: {
        !           409:        struct mscp_pack *ud = mi->mi_uda;
        !           410:        struct mscp *mp;
        !           411:        int i;
        !           412:
        !           413:        for (i = 0, mp = ud->mp_rsp; i < NRSP; i++, mp++) {
        !           414:                ud->mp_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |
        !           415:                    (mi->mi_dmam->dm_segs[0].ds_addr +
        !           416:                    offsetof(struct mscp_pack, mp_rsp[i].mscp_cmdref));
        !           417:                mp->mscp_addr = &ud->mp_ca.ca_rspdsc[i];
        !           418:                mp->mscp_msglen = MSCP_MSGLEN;
        !           419:        }
        !           420:        for (i = 0, mp = ud->mp_cmd; i < NCMD; i++, mp++) {
        !           421:                ud->mp_ca.ca_cmddsc[i] = MSCP_INT |
        !           422:                    (mi->mi_dmam->dm_segs[0].ds_addr +
        !           423:                    offsetof(struct mscp_pack, mp_cmd[i].mscp_cmdref));
        !           424:                mp->mscp_addr = &ud->mp_ca.ca_cmddsc[i];
        !           425:                mp->mscp_msglen = MSCP_MSGLEN;
        !           426:                if (mi->mi_type & MSCPBUS_TAPE)
        !           427:                        mp->mscp_vcid = 1;
        !           428:        }
        !           429: }
        !           430:
        !           431: static void mscp_kickaway(struct mscp_softc *);
        !           432:
        !           433: void
        !           434: mscp_intr(mi)
        !           435:        struct mscp_softc *mi;
        !           436: {
        !           437:        struct mscp_pack *ud = mi->mi_uda;
        !           438:
        !           439:        if (mi->mi_flags & MSC_IGNOREINTR)
        !           440:                return;
        !           441:        /*
        !           442:         * Check for response and command ring transitions.
        !           443:         */
        !           444:        if (ud->mp_ca.ca_rspint) {
        !           445:                ud->mp_ca.ca_rspint = 0;
        !           446:                mscp_dorsp(mi);
        !           447:        }
        !           448:        if (ud->mp_ca.ca_cmdint) {
        !           449:                ud->mp_ca.ca_cmdint = 0;
        !           450:                MSCP_DOCMD(mi);
        !           451:        }
        !           452:
        !           453:        /*
        !           454:         * If there are any not-yet-handled request, try them now.
        !           455:         */
        !           456:        if (SIMPLEQ_FIRST(&mi->mi_resq))
        !           457:                mscp_kickaway(mi);
        !           458: }
        !           459:
        !           460: int
        !           461: mscp_print(aux, name)
        !           462:        void *aux;
        !           463:        const char *name;
        !           464: {
        !           465:        struct drive_attach_args *da = aux;
        !           466:        struct  mscp *mp = da->da_mp;
        !           467:        int type = mp->mscp_guse.guse_mediaid;
        !           468:
        !           469:        if (name) {
        !           470:                printf("%c%c", MSCP_MID_CHAR(2, type), MSCP_MID_CHAR(1, type));
        !           471:                if (MSCP_MID_ECH(0, type))
        !           472:                        printf("%c", MSCP_MID_CHAR(0, type));
        !           473:                printf("%d at %s drive %d", MSCP_MID_NUM(type), name,
        !           474:                    mp->mscp_unit);
        !           475:        }
        !           476:        return UNCONF;
        !           477: }
        !           478:
        !           479: /*
        !           480:  * common strategy routine for all types of MSCP devices.
        !           481:  */
        !           482: void
        !           483: mscp_strategy(bp, usc)
        !           484:        struct buf *bp;
        !           485:        struct device *usc;
        !           486: {
        !           487:        struct  mscp_softc *mi = (void *)usc;
        !           488:        int s = spl6();
        !           489:
        !           490: /*     SIMPLEQ_INSERT_TAIL(&mi->mi_resq, bp, xxx) */
        !           491:        bp->b_actf = NULL;
        !           492:        *mi->mi_resq.sqh_last = bp;
        !           493:        mi->mi_resq.sqh_last = &bp->b_actf;
        !           494:        mscp_kickaway(mi);
        !           495:        splx(s);
        !           496: }
        !           497:
        !           498:
        !           499: void
        !           500: mscp_kickaway(mi)
        !           501:        struct  mscp_softc *mi;
        !           502: {
        !           503:        struct buf *bp;
        !           504:        struct  mscp *mp;
        !           505:        int next;
        !           506:
        !           507:        while ((bp = SIMPLEQ_FIRST(&mi->mi_resq))) {
        !           508:                /*
        !           509:                 * Ok; we are ready to try to start a xfer. Get a MSCP packet
        !           510:                 * and try to start...
        !           511:                 */
        !           512:                if ((mp = mscp_getcp(mi, MSCP_DONTWAIT)) == NULL) {
        !           513:                        if (mi->mi_credits > MSCP_MINCREDITS)
        !           514:                                printf("%s: command ring too small\n",
        !           515:                                    mi->mi_dev.dv_parent->dv_xname);
        !           516:                        /*
        !           517:                         * By some (strange) reason we didn't get a MSCP packet.
        !           518:                         * Just return and wait for free packets.
        !           519:                         */
        !           520:                        return;
        !           521:                }
        !           522:
        !           523:                if ((next = (ffs(mi->mi_mxiuse) - 1)) < 0)
        !           524:                        panic("no mxi buffers");
        !           525:                mi->mi_mxiuse &= ~(1 << next);
        !           526:                if (mi->mi_xi[next].mxi_inuse)
        !           527:                        panic("mxi inuse");
        !           528:                /*
        !           529:                 * Set up the MSCP packet and ask the ctlr to start.
        !           530:                 */
        !           531:                mp->mscp_opcode =
        !           532:                    (bp->b_flags & B_READ) ? M_OP_READ : M_OP_WRITE;
        !           533:                mp->mscp_cmdref = next;
        !           534:                mi->mi_xi[next].mxi_bp = bp;
        !           535:                mi->mi_xi[next].mxi_mp = mp;
        !           536:                mi->mi_xi[next].mxi_inuse = 1;
        !           537:                bp->b_resid = next;
        !           538:                (*mi->mi_me->me_fillin)(bp, mp);
        !           539:                (*mi->mi_mc->mc_go)(mi->mi_dev.dv_parent, &mi->mi_xi[next]);
        !           540:                if ((mi->mi_resq.sqh_first = bp->b_actf) == NULL)
        !           541:                        mi->mi_resq.sqh_last = &mi->mi_resq.sqh_first;
        !           542: #if 0
        !           543:                mi->mi_w = bp->b_actf;
        !           544: #endif
        !           545:        }
        !           546: }
        !           547:
        !           548: void
        !           549: mscp_dgo(mi, mxi)
        !           550:        struct mscp_softc *mi;
        !           551:        struct mscp_xi *mxi;
        !           552: {
        !           553:        volatile int i;
        !           554:        struct  mscp *mp;
        !           555:
        !           556:        /*
        !           557:         * Fill in the MSCP packet and move the buffer to the I/O wait queue.
        !           558:         */
        !           559:        mp = mxi->mxi_mp;
        !           560:        mp->mscp_seq.seq_buffer = mxi->mxi_dmam->dm_segs[0].ds_addr;
        !           561:
        !           562:        *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
        !           563:        i = READ_IP;
        !           564: }
        !           565:
        !           566: #ifdef DIAGNOSTIC
        !           567: /*
        !           568:  * Dump the entire contents of an MSCP packet in hex.  Mainly useful
        !           569:  * for debugging....
        !           570:  */
        !           571: void
        !           572: mscp_hexdump(mp)
        !           573:        struct mscp *mp;
        !           574: {
        !           575:        long *p = (long *) mp;
        !           576:        int i = mp->mscp_msglen;
        !           577:
        !           578:        if (i > 256)            /* sanity */
        !           579:                i = 256;
        !           580:        i /= sizeof (*p);       /* ASSUMES MULTIPLE OF sizeof(long) */
        !           581:        while (--i >= 0)
        !           582:                printf("0x%x ", (int)*p++);
        !           583:        printf("\n");
        !           584: }
        !           585: #endif
        !           586:
        !           587: /*
        !           588:  * MSCP error reporting
        !           589:  */
        !           590:
        !           591: /*
        !           592:  * Messages for the various subcodes.
        !           593:  */
        !           594: static char unknown_msg[] = "unknown subcode";
        !           595:
        !           596: /*
        !           597:  * Subcodes for Success (0)
        !           598:  */
        !           599: static char *succ_msgs[] = {
        !           600:        "normal",               /* 0 */
        !           601:        "spin down ignored",    /* 1 = Spin-Down Ignored */
        !           602:        "still connected",      /* 2 = Still Connected */
        !           603:        unknown_msg,
        !           604:        "dup. unit #",          /* 4 = Duplicate Unit Number */
        !           605:        unknown_msg,
        !           606:        unknown_msg,
        !           607:        unknown_msg,
        !           608:        "already online",       /* 8 = Already Online */
        !           609:        unknown_msg,
        !           610:        unknown_msg,
        !           611:        unknown_msg,
        !           612:        unknown_msg,
        !           613:        unknown_msg,
        !           614:        unknown_msg,
        !           615:        unknown_msg,
        !           616:        "still online",         /* 16 = Still Online */
        !           617: };
        !           618:
        !           619: /*
        !           620:  * Subcodes for Invalid Command (1)
        !           621:  */
        !           622: static char *icmd_msgs[] = {
        !           623:        "invalid msg length",   /* 0 = Invalid Message Length */
        !           624: };
        !           625:
        !           626: /*
        !           627:  * Subcodes for Command Aborted (2)
        !           628:  */
        !           629: /* none known */
        !           630:
        !           631: /*
        !           632:  * Subcodes for Unit Offline (3)
        !           633:  */
        !           634: static char *offl_msgs[] = {
        !           635:        "unknown drive",        /* 0 = Unknown, or online to other ctlr */
        !           636:        "not mounted",          /* 1 = Unmounted, or RUN/STOP at STOP */
        !           637:        "inoperative",          /* 2 = Unit Inoperative */
        !           638:        unknown_msg,
        !           639:        "duplicate",            /* 4 = Duplicate Unit Number */
        !           640:        unknown_msg,
        !           641:        unknown_msg,
        !           642:        unknown_msg,
        !           643:        "in diagnosis",         /* 8 = Disabled by FS or diagnostic */
        !           644: };
        !           645:
        !           646: /*
        !           647:  * Subcodes for Unit Available (4)
        !           648:  */
        !           649: /* none known */
        !           650:
        !           651: /*
        !           652:  * Subcodes for Media Format Error (5)
        !           653:  */
        !           654: static char *media_fmt_msgs[] = {
        !           655:        "fct unread - edc",     /* 0 = FCT unreadable */
        !           656:        "invalid sector header",/* 1 = Invalid Sector Header */
        !           657:        "not 512 sectors",      /* 2 = Not 512 Byte Sectors */
        !           658:        "not formatted",        /* 3 = Not Formatted */
        !           659:        "fct ecc",              /* 4 = FCT ECC */
        !           660: };
        !           661:
        !           662: /*
        !           663:  * Subcodes for Write Protected (6)
        !           664:  * N.B.:  Code 6 subcodes are 7 bits higher than other subcodes
        !           665:  * (i.e., bits 12-15).
        !           666:  */
        !           667: static char *wrprot_msgs[] = {
        !           668:        unknown_msg,
        !           669:        "software",             /* 1 = Software Write Protect */
        !           670:        "hardware",             /* 2 = Hardware Write Protect */
        !           671: };
        !           672:
        !           673: /*
        !           674:  * Subcodes for Compare Error (7)
        !           675:  */
        !           676: /* none known */
        !           677:
        !           678: /*
        !           679:  * Subcodes for Data Error (8)
        !           680:  */
        !           681: static char *data_msgs[] = {
        !           682:        "forced error",         /* 0 = Forced Error (software) */
        !           683:        unknown_msg,
        !           684:        "header compare",       /* 2 = Header Compare Error */
        !           685:        "sync timeout",         /* 3 = Sync Timeout Error */
        !           686:        unknown_msg,
        !           687:        unknown_msg,
        !           688:        unknown_msg,
        !           689:        "uncorrectable ecc",    /* 7 = Uncorrectable ECC */
        !           690:        "1 symbol ecc",         /* 8 = 1 bit ECC */
        !           691:        "2 symbol ecc",         /* 9 = 2 bit ECC */
        !           692:        "3 symbol ecc",         /* 10 = 3 bit ECC */
        !           693:        "4 symbol ecc",         /* 11 = 4 bit ECC */
        !           694:        "5 symbol ecc",         /* 12 = 5 bit ECC */
        !           695:        "6 symbol ecc",         /* 13 = 6 bit ECC */
        !           696:        "7 symbol ecc",         /* 14 = 7 bit ECC */
        !           697:        "8 symbol ecc",         /* 15 = 8 bit ECC */
        !           698: };
        !           699:
        !           700: /*
        !           701:  * Subcodes for Host Buffer Access Error (9)
        !           702:  */
        !           703: static char *host_buffer_msgs[] = {
        !           704:        unknown_msg,
        !           705:        "odd xfer addr",        /* 1 = Odd Transfer Address */
        !           706:        "odd xfer count",       /* 2 = Odd Transfer Count */
        !           707:        "non-exist. memory",    /* 3 = Non-Existent Memory */
        !           708:        "memory parity",        /* 4 = Memory Parity Error */
        !           709: };
        !           710:
        !           711: /*
        !           712:  * Subcodes for Controller Error (10)
        !           713:  */
        !           714: static char *cntlr_msgs[] = {
        !           715:        unknown_msg,
        !           716:        "serdes overrun",       /* 1 = Serialiser/Deserialiser Overrun */
        !           717:        "edc",                  /* 2 = Error Detection Code? */
        !           718:        "inconsistent internal data struct",/* 3 = Internal Error */
        !           719: };
        !           720:
        !           721: /*
        !           722:  * Subcodes for Drive Error (11)
        !           723:  */
        !           724: static char *drive_msgs[] = {
        !           725:        unknown_msg,
        !           726:        "sdi command timeout",  /* 1 = SDI Command Timeout */
        !           727:        "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */
        !           728:        "positioner",           /* 3 = Positioner Error */
        !           729:        "lost rd/wr ready",     /* 4 = Lost R/W Ready Error */
        !           730:        "drive clock dropout",  /* 5 = Lost Drive Clock */
        !           731:        "lost recvr ready",     /* 6 = Lost Receiver Ready */
        !           732:        "drive detected error", /* 7 = Drive Error */
        !           733:        "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */
        !           734: };
        !           735:
        !           736: /*
        !           737:  * The following table correlates message codes with the
        !           738:  * decoding strings.
        !           739:  */
        !           740: struct code_decode {
        !           741:        char    *cdc_msg;
        !           742:        int     cdc_nsubcodes;
        !           743:        char    **cdc_submsgs;
        !           744: } code_decode[] = {
        !           745: #define SC(m)  sizeof (m) / sizeof (m[0]), m
        !           746:        {"success",                     SC(succ_msgs)},
        !           747:        {"invalid command",             SC(icmd_msgs)},
        !           748:        {"command aborted",             0, 0},
        !           749:        {"unit offline",                SC(offl_msgs)},
        !           750:        {"unit available",              0, 0},
        !           751:        {"media format error",          SC(media_fmt_msgs)},
        !           752:        {"write protected",             SC(wrprot_msgs)},
        !           753:        {"compare error",               0, 0},
        !           754:        {"data error",                  SC(data_msgs)},
        !           755:        {"host buffer access error",    SC(host_buffer_msgs)},
        !           756:        {"controller error",            SC(cntlr_msgs)},
        !           757:        {"drive error",                 SC(drive_msgs)},
        !           758: #undef SC
        !           759: };
        !           760:
        !           761: /*
        !           762:  * Print the decoded error event from an MSCP error datagram.
        !           763:  */
        !           764: void
        !           765: mscp_printevent(mp)
        !           766:        struct mscp *mp;
        !           767: {
        !           768:        int event = mp->mscp_event;
        !           769:        struct code_decode *cdc;
        !           770:        int c, sc;
        !           771:        char *cm, *scm;
        !           772:
        !           773:        /*
        !           774:         * The code is the lower six bits of the event number (aka
        !           775:         * status).  If that is 6 (write protect), the subcode is in
        !           776:         * bits 12-15; otherwise, it is in bits 5-11.
        !           777:         * I WONDER WHAT THE OTHER BITS ARE FOR.  IT SURE WOULD BE
        !           778:         * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
        !           779:         */
        !           780:        c = event & M_ST_MASK;
        !           781:        sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff;
        !           782:        if (c >= sizeof code_decode / sizeof code_decode[0])
        !           783:                cm = "- unknown code", scm = "??";
        !           784:        else {
        !           785:                cdc = &code_decode[c];
        !           786:                cm = cdc->cdc_msg;
        !           787:                if (sc >= cdc->cdc_nsubcodes)
        !           788:                        scm = unknown_msg;
        !           789:                else
        !           790:                        scm = cdc->cdc_submsgs[sc];
        !           791:        }
        !           792:        printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc);
        !           793: }
        !           794:
        !           795: static char *codemsg[16] = {
        !           796:        "lbn", "code 1", "code 2", "code 3",
        !           797:        "code 4", "code 5", "rbn", "code 7",
        !           798:        "code 8", "code 9", "code 10", "code 11",
        !           799:        "code 12", "code 13", "code 14", "code 15"
        !           800: };
        !           801: /*
        !           802:  * Print the code and logical block number for an error packet.
        !           803:  * THIS IS PROBABLY PECULIAR TO DISK DRIVES.  IT SURE WOULD BE
        !           804:  * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
        !           805:  */
        !           806: int
        !           807: mscp_decodeerror(name, mp, mi)
        !           808:        char *name;
        !           809:        struct mscp *mp;
        !           810:        struct mscp_softc *mi;
        !           811: {
        !           812:        int issoft;
        !           813:        /*
        !           814:         * We will get three sdi errors of type 11 after autoconfig
        !           815:         * is finished; depending of searching for non-existing units.
        !           816:         * How can we avoid this???
        !           817:         */
        !           818:        if (((mp->mscp_event & M_ST_MASK) == 11) && (mi->mi_ierr++ < 3))
        !           819:                return 1;
        !           820:        /*
        !           821:         * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and
        !           822:         * the logical block number.  Code 0 is a regular block; code 6
        !           823:         * is a replacement block.  The remaining codes are currently
        !           824:         * undefined.  The code is in the upper four bits of the header
        !           825:         * (bits 0-27 are the lbn).
        !           826:         */
        !           827:        issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT);
        !           828: #define BADCODE(h)     (codemsg[(unsigned)(h) >> 28])
        !           829: #define BADLBN(h)      ((h) & 0xfffffff)
        !           830:
        !           831:        printf("%s: drive %d %s error datagram%s:", name, mp->mscp_unit,
        !           832:                issoft ? "soft" : "hard",
        !           833:                mp->mscp_flags & M_LF_CONT ? " (continuing)" : "");
        !           834:        switch (mp->mscp_format & 0377) {
        !           835:
        !           836:        case M_FM_CTLRERR:      /* controller error */
        !           837:                break;
        !           838:
        !           839:        case M_FM_BUSADDR:      /* host memory access error */
        !           840:                printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr);
        !           841:                break;
        !           842:
        !           843:        case M_FM_DISKTRN:
        !           844:                printf(" unit %d: level %d retry %d, %s %d:",
        !           845:                        mp->mscp_unit,
        !           846:                        mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry,
        !           847:                        BADCODE(mp->mscp_erd.erd_hdr),
        !           848:                        (int)BADLBN(mp->mscp_erd.erd_hdr));
        !           849:                break;
        !           850:
        !           851:        case M_FM_SDI:
        !           852:                printf(" unit %d: %s %d:", mp->mscp_unit,
        !           853:                        BADCODE(mp->mscp_erd.erd_hdr),
        !           854:                        (int)BADLBN(mp->mscp_erd.erd_hdr));
        !           855:                break;
        !           856:
        !           857:        case M_FM_SMLDSK:
        !           858:                printf(" unit %d: small disk error, cyl %d:",
        !           859:                        mp->mscp_unit, mp->mscp_erd.erd_sdecyl);
        !           860:                break;
        !           861:
        !           862:        case M_FM_TAPETRN:
        !           863:                printf(" unit %d: tape transfer error, grp 0x%x event 0%o:",
        !           864:                    mp->mscp_unit, mp->mscp_erd.erd_sdecyl, mp->mscp_event);
        !           865:                break;
        !           866:
        !           867:        case M_FM_STIERR:
        !           868:                printf(" unit %d: STI error, event 0%o:", mp->mscp_unit,
        !           869:                    mp->mscp_event);
        !           870:                break;
        !           871:
        !           872:        default:
        !           873:                printf(" unit %d: unknown error, format 0x%x:",
        !           874:                        mp->mscp_unit, mp->mscp_format);
        !           875:        }
        !           876:        mscp_printevent(mp);
        !           877:        return 0;
        !           878: #undef BADCODE
        !           879: #undef BADLBN
        !           880: }

CVSweb