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

Annotation of sys/arch/vax/mscp/mscp.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: mscp.c,v 1.9 2005/11/24 04:53:56 brad Exp $   */
                      2: /*     $NetBSD: mscp.c,v 1.16 2001/11/13 07:38:28 lukem Exp $  */
                      3:
                      4: /*
                      5:  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
                      6:  * Copyright (c) 1988 Regents of the University of California.
                      7:  * All rights reserved.
                      8:  *
                      9:  * This code is derived from software contributed to Berkeley by
                     10:  * Chris Torek.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  *     @(#)mscp.c      7.5 (Berkeley) 12/16/90
                     37:  */
                     38:
                     39: /*
                     40:  * MSCP generic driver routines
                     41:  */
                     42:
                     43: #include <sys/cdefs.h>
                     44:
                     45: #include <sys/param.h>
                     46: #include <sys/buf.h>
                     47: #include <sys/malloc.h>
                     48: #include <sys/device.h>
                     49: #include <sys/proc.h>
                     50: #include <sys/systm.h>
                     51:
                     52: #include <machine/bus.h>
                     53:
                     54: #include <arch/vax/mscp/mscp.h>
                     55: #include <arch/vax/mscp/mscpreg.h>
                     56: #include <arch/vax/mscp/mscpvar.h>
                     57:
                     58: #define PCMD   PSWP            /* priority for command packet waits */
                     59:
                     60: /*
                     61:  * Get a command packet.  Second argument is true iff we are
                     62:  * to wait if necessary.  Return NULL if none are available and
                     63:  * we cannot wait.
                     64:  */
                     65: struct mscp *
                     66: mscp_getcp(mi, canwait)
                     67:        struct mscp_softc *mi;
                     68:        int canwait;
                     69: {
                     70: #define mri    (&mi->mi_cmd)
                     71:        struct mscp *mp;
                     72:        int i;
                     73:        int s = splbio();
                     74:
                     75: again:
                     76:        /*
                     77:         * Ensure that we have some command credits, and
                     78:         * that the next command packet is free.
                     79:         */
                     80:        if (mi->mi_credits <= MSCP_MINCREDITS) {
                     81:                if (!canwait) {
                     82:                        splx(s);
                     83:                        return (NULL);
                     84:                }
                     85:                mi->mi_wantcredits = 1;
                     86:                (void) tsleep(&mi->mi_wantcredits, PCMD, "mscpwcrd", 0);
                     87:                goto again;
                     88:        }
                     89:        i = mri->mri_next;
                     90:        if (mri->mri_desc[i] & MSCP_OWN) {
                     91:                if (!canwait) {
                     92:                        splx(s);
                     93:                        return (NULL);
                     94:                }
                     95:                mi->mi_wantcmd = 1;
                     96:                (void) tsleep(&mi->mi_wantcmd, PCMD, "mscpwcmd", 0);
                     97:                goto again;
                     98:        }
                     99:        mi->mi_credits--;
                    100:        mri->mri_desc[i] &= ~MSCP_INT;
                    101:        mri->mri_next = (mri->mri_next + 1) % mri->mri_size;
                    102:        splx(s);
                    103:        mp = &mri->mri_ring[i];
                    104:
                    105:        /*
                    106:         * Initialise some often-zero fields.
                    107:         * ARE THE LAST TWO NECESSARY IN GENERAL?  IT SURE WOULD BE
                    108:         * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
                    109:         */
                    110:        mp->mscp_msglen = MSCP_MSGLEN;
                    111:        mp->mscp_flags = 0;
                    112:        mp->mscp_modifier = 0;
                    113:        mp->mscp_seq.seq_bytecount = 0;
                    114:        mp->mscp_seq.seq_buffer = 0;
                    115:        mp->mscp_seq.seq_mapbase = 0;
                    116: /*???*/ mp->mscp_sccc.sccc_errlgfl = 0;
                    117: /*???*/ mp->mscp_sccc.sccc_copyspd = 0;
                    118:        return (mp);
                    119: #undef mri
                    120: }
                    121:
                    122: #ifdef AVOID_EMULEX_BUG
                    123: int    mscp_aeb_xor = 0x8000bb80;
                    124: #endif
                    125:
                    126: /*
                    127:  * Handle a response ring transition.
                    128:  */
                    129: void
                    130: mscp_dorsp(mi)
                    131:        struct mscp_softc *mi;
                    132: {
                    133:        struct device *drive;
                    134:        struct mscp_device *me = mi->mi_me;
                    135:        struct mscp_ctlr *mc = mi->mi_mc;
                    136:        struct buf *bp;
                    137:        struct mscp *mp;
                    138:        struct mscp_xi *mxi;
                    139:        int nextrsp;
                    140:        int st, error;
                    141:        extern int cold;
                    142:        extern struct mscp slavereply;
                    143:
                    144:        nextrsp = mi->mi_rsp.mri_next;
                    145: loop:
                    146:        if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) {
                    147:                /*
                    148:                 * No more responses.  Remember the next expected
                    149:                 * response index.  Check to see if we have some
                    150:                 * credits back, and wake up sleepers if so.
                    151:                 */
                    152:                mi->mi_rsp.mri_next = nextrsp;
                    153:                if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) {
                    154:                        mi->mi_wantcredits = 0;
                    155:                        wakeup((caddr_t) &mi->mi_wantcredits);
                    156:                }
                    157:                return;
                    158:        }
                    159:
                    160:        mp = &mi->mi_rsp.mri_ring[nextrsp];
                    161:        mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc);
                    162:        /*
                    163:         * Controllers are allowed to interrupt as any drive, so we
                    164:         * must check the command before checking for a drive.
                    165:         */
                    166:        if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) {
                    167:                if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) {
                    168:                        mi->mi_flags |= MSC_READY;
                    169:                } else {
                    170:                        printf("%s: SETCTLRC failed: %d ",
                    171:                            mi->mi_dev.dv_xname, mp->mscp_status);
                    172:                        mscp_printevent(mp);
                    173:                }
                    174:                goto done;
                    175:        }
                    176:
                    177:        /*
                    178:         * Found a response.  Update credit information.  If there is
                    179:         * nothing else to do, jump to `done' to get the next response.
                    180:         */
                    181:        if (mp->mscp_unit >= mi->mi_driveno) { /* Must expand drive table */
                    182:                int tmpno = ((mp->mscp_unit + 32) & 0xffe0) * sizeof(void *);
                    183:                struct device **tmp = (struct device **)
                    184:                    malloc(tmpno, M_DEVBUF, M_NOWAIT);
                    185:                if (tmp == NULL)
                    186:                        panic("mscp_dorsp");
                    187:                bzero(tmp, tmpno);
                    188:                if (mi->mi_driveno) {
                    189:                        bcopy(mi->mi_dp, tmp, mi->mi_driveno);
                    190:                        free(mi->mi_dp, mi->mi_driveno);
                    191:                }
                    192:                mi->mi_driveno = tmpno;
                    193:                mi->mi_dp = tmp;
                    194:        }
                    195:
                    196:        drive = mi->mi_dp[mp->mscp_unit];
                    197:
                    198:        switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
                    199:
                    200:        case MSCPT_SEQ:
                    201:                break;
                    202:
                    203:        case MSCPT_DATAGRAM:
                    204:                (*me->me_dgram)(drive, mp, mi);
                    205:                goto done;
                    206:
                    207:        case MSCPT_CREDITS:
                    208:                goto done;
                    209:
                    210:        case MSCPT_MAINTENANCE:
                    211:        default:
                    212:                printf("%s: unit %d: unknown message type 0x%x ignored\n",
                    213:                        mi->mi_dev.dv_xname, mp->mscp_unit,
                    214:                        MSCP_MSGTYPE(mp->mscp_msgtc));
                    215:                goto done;
                    216:        }
                    217:
                    218:        /*
                    219:         * Handle individual responses.
                    220:         */
                    221:        st = mp->mscp_status & M_ST_MASK;
                    222:        error = 0;
                    223:        switch (mp->mscp_opcode) {
                    224:
                    225:        case M_OP_END:
                    226:                /*
                    227:                 * The controller presents a bogus END packet when
                    228:                 * a read/write command is given with an illegal
                    229:                 * block number.  This is contrary to the MSCP
                    230:                 * specification (ENDs are to be given only for
                    231:                 * invalid commands), but that is the way of it.
                    232:                 */
                    233:                if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) {
                    234:                        printf("%s: bad lbn (%d)?\n", drive->dv_xname,
                    235:                                (int)mp->mscp_seq.seq_lbn);
                    236:                        error = EIO;
                    237:                        goto rwend;
                    238:                }
                    239:                goto unknown;
                    240:
                    241:        case M_OP_ONLINE | M_OP_END:
                    242:                /*
                    243:                 * Finished an ON LINE request.  Call the driver to
                    244:                 * find out whether it succeeded.  If so, mark it on
                    245:                 * line.
                    246:                 */
                    247:                (*me->me_online)(drive, mp);
                    248:                break;
                    249:
                    250:        case M_OP_GETUNITST | M_OP_END:
                    251:                /*
                    252:                 * Got unit status.  If we are autoconfiguring, save
                    253:                 * the mscp struct so that mscp_attach know what to do.
                    254:                 * If the drive isn't configured, call config_found()
                    255:                 * to set it up, otherwise it's just a "normal" unit
                    256:                 * status.
                    257:                 */
                    258:                if (cold)
                    259:                        bcopy(mp, &slavereply, sizeof(struct mscp));
                    260:
                    261:                if (mp->mscp_status == (M_ST_OFFLINE|M_OFFLINE_UNKNOWN))
                    262:                        break;
                    263:
                    264:                if (drive == 0) {
                    265:                        struct  drive_attach_args da;
                    266:
                    267:                        da.da_mp = (struct mscp *)mp;
                    268:                        da.da_typ = mi->mi_type;
                    269:                        config_found(&mi->mi_dev, (void *)&da, mscp_print);
                    270:                } else
                    271:                        /* Hack to avoid complaints */
                    272:                        if (!(((mp->mscp_event & M_ST_MASK) == M_ST_AVAILABLE)
                    273:                            && cold))
                    274:                                (*me->me_gotstatus)(drive, mp);
                    275:                break;
                    276:
                    277:        case M_OP_AVAILATTN:
                    278:                /*
                    279:                 * The drive went offline and we did not notice.
                    280:                 * Mark it off line now, to force an on line request
                    281:                 * next, so we can make sure it is still the same
                    282:                 * drive.
                    283:                 *
                    284:                 * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS
                    285:                 * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON
                    286:                 * LINE.  IS IT WORTH FIXING??
                    287:                 */
                    288: #ifdef notyet
                    289:                (*md->md_offline)(ui, mp);
                    290: #endif
                    291:                break;
                    292:
                    293:        case M_OP_POS | M_OP_END:
                    294:        case M_OP_WRITM | M_OP_END:
                    295:        case M_OP_AVAILABLE | M_OP_END:
                    296:                /*
                    297:                 * A non-data transfer operation completed.
                    298:                 */
                    299:                (*me->me_cmddone)(drive, mp);
                    300:                break;
                    301:
                    302:        case M_OP_READ | M_OP_END:
                    303:        case M_OP_WRITE | M_OP_END:
                    304:                /*
                    305:                 * A transfer finished.  Get the buffer, and release its
                    306:                 * map registers via ubadone().  If the command finished
                    307:                 * with an off line or available status, the drive went
                    308:                 * off line (the idiot controller does not tell us until
                    309:                 * it comes back *on* line, or until we try to use it).
                    310:                 */
                    311: rwend:
                    312: #ifdef DIAGNOSTIC
                    313:                if (mp->mscp_cmdref >= NCMD) {
                    314:                        /*
                    315:                         * No buffer means there is a bug somewhere!
                    316:                         */
                    317:                        printf("%s: io done, but bad xfer number?\n",
                    318:                            drive->dv_xname);
                    319:                        mscp_hexdump(mp);
                    320:                        break;
                    321:                }
                    322: #endif
                    323:
                    324:                if (mp->mscp_cmdref == -1) {
                    325:                        (*me->me_cmddone)(drive, mp);
                    326:                        break;
                    327:                }
                    328:                mxi = &mi->mi_xi[mp->mscp_cmdref];
                    329:                if (mxi->mxi_inuse == 0)
                    330:                        panic("mxi not inuse");
                    331:                bp = mxi->mxi_bp;
                    332:                /*
                    333:                 * Mark any error-due-to-bad-LBN (via `goto rwend').
                    334:                 * WHAT STATUS WILL THESE HAVE?  IT SURE WOULD BE NICE
                    335:                 * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS.
                    336:                 */
                    337:                if (error) {
                    338:                        bp->b_flags |= B_ERROR;
                    339:                        bp->b_error = error;
                    340:                }
                    341:                if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) {
                    342: #ifdef notyet
                    343:                        (*md->md_offline)(ui, mp);
                    344: #endif
                    345:                }
                    346:
                    347:                /*
                    348:                 * If the transfer has something to do with bad
                    349:                 * block forwarding, let the driver handle the
                    350:                 * rest.
                    351:                 */
                    352:                if ((bp->b_flags & B_BAD) != 0 && me->me_bb != NULL) {
                    353:                        (*me->me_bb)(drive, mp, bp);
                    354:                        goto out;
                    355:                }
                    356:
                    357:                /*
                    358:                 * If the transfer failed, give the driver a crack
                    359:                 * at fixing things up.
                    360:                 */
                    361:                if (st != M_ST_SUCCESS) {
                    362:                        switch ((*me->me_ioerr)(drive, mp, bp)) {
                    363:
                    364:                        case MSCP_DONE:         /* fixed */
                    365:                                break;
                    366:
                    367:                        case MSCP_RESTARTED:    /* still working on it */
                    368:                                goto out;
                    369:
                    370:                        case MSCP_FAILED:       /* no luck */
                    371:                                /* XXX must move to ra.c */
                    372:                                mscp_printevent(mp);
                    373:                                break;
                    374:                        }
                    375:                }
                    376:
                    377:                /*
                    378:                 * Set the residual count and mark the transfer as
                    379:                 * done.  If the I/O wait queue is now empty, release
                    380:                 * the shared BDP, if any.
                    381:                 */
                    382:                bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount;
                    383:                bus_dmamap_unload(mi->mi_dmat, mxi->mxi_dmam);
                    384:
                    385:                (*mc->mc_ctlrdone)(mi->mi_dev.dv_parent);
                    386:                (*me->me_iodone)(drive, bp);
                    387: out:
                    388:                mxi->mxi_inuse = 0;
                    389:                mi->mi_mxiuse |= (1 << mp->mscp_cmdref);
                    390:                break;
                    391:
                    392:        case M_OP_REPLACE | M_OP_END:
                    393:                /*
                    394:                 * A replace operation finished.  Just let the driver
                    395:                 * handle it (if it does replaces).
                    396:                 */
                    397:                if (me->me_replace == NULL)
                    398:                        printf("%s: bogus REPLACE end\n", drive->dv_xname);
                    399:                else
                    400:                        (*me->me_replace)(drive, mp);
                    401:                break;
                    402:
                    403:        default:
                    404:                /*
                    405:                 * If it is not one of the above, we cannot handle it.
                    406:                 * (And we should not have received it, for that matter.)
                    407:                 */
                    408: unknown:
                    409:                printf("%s: unknown opcode 0x%x status 0x%x ignored\n",
                    410:                        drive->dv_xname, mp->mscp_opcode, mp->mscp_status);
                    411: #ifdef DIAGNOSTIC
                    412:                mscp_hexdump(mp);
                    413: #endif
                    414:                break;
                    415:        }
                    416:
                    417:        /*
                    418:         * If the drive needs to be put back in the controller queue,
                    419:         * do that now.  (`bp' below ought to be `dp', but they are all
                    420:         * struct buf *.)  Note that b_active was cleared in the driver;
                    421:         * we presume that there is something to be done, hence reassert it.
                    422:         */
                    423: #ifdef notyet /* XXX */
                    424:        if (ui->ui_flags & UNIT_REQUEUE) {
                    425:                ...
                    426:        }
                    427: #endif
                    428: done:
                    429:        /*
                    430:         * Give back the response packet, and take a look at the next.
                    431:         */
                    432:        mp->mscp_msglen = MSCP_MSGLEN;
                    433:        mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN;
                    434:        nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size;
                    435:        goto loop;
                    436: }
                    437:
                    438: /*
                    439:  * Requeue outstanding transfers, e.g., after bus reset.
                    440:  * Also requeue any drives that have on line or unit status
                    441:  * info pending.
                    442:  */
                    443: void
                    444: mscp_requeue(mi)
                    445:        struct mscp_softc *mi;
                    446: {
                    447:        panic("mscp_requeue");
                    448: }
                    449:

CVSweb