diff --git a/sys/arch/vax/vax/mscp.c b/sys/arch/vax/vax/mscp.c deleted file mode 100644 index 427c0258b880..000000000000 --- a/sys/arch/vax/vax/mscp.c +++ /dev/null @@ -1,980 +0,0 @@ -/* $NetBSD: mscp.c,v 1.9 1996/04/08 18:32:50 ragge Exp $ */ - -/* - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mscp.c 7.5 (Berkeley) 12/16/90 - */ - -/* - * MSCP generic driver routines - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -void mscp_hexdump __P((struct mscp *)); - - - - -#define PCMD PSWP /* priority for command packet waits */ - -/* - * During transfers, mapping info is saved in the buffer's b_resid. - */ -#define b_info b_resid - -/* - * Get a command packet. Second argument is true iff we are - * to wait if necessary. Return NULL if none are available and - * we cannot wait. - */ -struct mscp * -mscp_getcp(mi, canwait) - register struct mscp_info *mi; - int canwait; -{ -#define mri (&mi->mi_cmd) - register struct mscp *mp; - register int i; - int s = splbio(); - -again: - /* - * Ensure that we have some command credits, and - * that the next command packet is free. - */ - if (mi->mi_credits <= MSCP_MINCREDITS) { - if (!canwait) { - splx(s); - return (NULL); - } - mi->mi_wantcredits = 1; - sleep((caddr_t) &mi->mi_wantcredits, PCMD); - goto again; - } - i = mri->mri_next; - if (mri->mri_desc[i] & MSCP_OWN) { - if (!canwait) { - splx(s); - return (NULL); - } - mi->mi_wantcmd = 1; - sleep((caddr_t) &mi->mi_wantcmd, PCMD); - goto again; - } - mi->mi_credits--; - mri->mri_desc[i] &= ~MSCP_INT; - mri->mri_next = (mri->mri_next + 1) % mri->mri_size; - splx(s); - mp = &mri->mri_ring[i]; - - /* - * Initialise some often-zero fields. - * ARE THE LAST TWO NECESSARY IN GENERAL? IT SURE WOULD BE - * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. - */ - mp->mscp_msglen = MSCP_MSGLEN; - mp->mscp_flags = 0; - mp->mscp_modifier = 0; - mp->mscp_seq.seq_bytecount = 0; - mp->mscp_seq.seq_buffer = 0; - mp->mscp_seq.seq_mapbase = 0; -/*???*/ mp->mscp_sccc.sccc_errlgfl = 0; -/*???*/ mp->mscp_sccc.sccc_copyspd = 0; - return (mp); -#undef mri -} - -#ifdef AVOID_EMULEX_BUG -int mscp_aeb_xor = 0x8000bb80; -#endif - -/* - * Do a device go. The driver calls this once it has allocated - * resources for the transfer. Save the resource information in - * bp->b_ubinfo, and finish the MSCP packet. - * - * N.B.: If we were blocked for some time, the drive could have gone - * off line and might still be that way. We should probably handle - * such a case by changing this command into an on line request and - * not dequeuing the transfer after all. - */ -void -mscp_go(mi, mp, info) - register struct mscp_info *mi; - register struct mscp *mp; - int info; -{ - register struct buf *bp, *dp; - - /* - * Now is also the time to move the transfer off the - * controller and drive queues, and shuffle the drive - * queue on the controller queue. The idea is to try - * to keep as many drives busy as possible---to deal - * the controller's credits out to the drives in a `fair - * share' arrangement. (To do this fully would be more - * trouble than it is worth, though.) - */ - dp = mi->mi_tab->b_actf; - bp = dp->b_actf; - dp->b_actf = bp->b_actf; /* transfer off drive queue */ - mi->mi_tab->b_actf = dp->b_hash.le_next;/* drive off ctlr queue */ - MSCP_APPEND(dp, mi->mi_tab, b_hash.le_next); /* then back again */ - -#ifdef oldway - dp->b_actf = bp->av_forw; /* transfer off drive queue */ - mi->mi_tab->b_actf = dp->b_forw; /* drive off ctlr queue */ - MSCP_APPEND(dp, mi->mi_tab, b_forw); /* then back again */ -#endif - - /* - * Move the buffer to the I/O wait queue. - */ - { - struct buf *tmp; - - bp->b_actf=&mi->mi_wtab; - if(mi->mi_wtab.b_actf==&mi->mi_wtab){ - mi->mi_wtab.b_actf=bp; - } else { - tmp=mi->mi_wtab.b_actf; - while(tmp->b_actf!=&mi->mi_wtab) tmp=tmp->b_actf; - tmp->b_actf=bp; - }} - -#ifdef oldway - bp->av_back = mi->mi_wtab.av_back; - bp->av_forw = &mi->mi_wtab; - mi->mi_wtab.av_back->av_forw = bp; - mi->mi_wtab.av_back = bp; -#endif - - /* - * Save the mapping info, finish the command packet, and give - * it to the device. The device's dgo routine should then - * initiate polling. - */ - bp->b_info = info; -#ifdef AVOID_EMULEX_BUG - /* - * The Emulex SC41/MS will occasionally zero the lower half word - * of the command reference number. The upper half word remains - * intact. To keep running, we convert the buffer address into - * a small but nonzero integer that is unique over all pending - * transfers, and store that value in the upper half word. To - * catch occurrances of the bug (so that we can gripe to Emulex), - * we also put a nonzero value in the lower word. - */ - { - register u_int i = mi->mi_nextbp; - - do { /* find a free value */ - if (mi->mi_bp[i] == 0) - goto found; - i = (i + 1) % AEB_MAX_BP; - } while (i != mi->mi_nextbp); - panic("mscp_go: AEB_MAX_BP too small"); -found: - mi->mi_bp[i++] = bp; - mi->mi_nextbp = i % AEB_MAX_BP; - mp->mscp_cmdref = (i << 16) ^ mscp_aeb_xor; - } -#else - mp->mscp_cmdref = (long) bp; -#endif - *mp->mscp_addr |= MSCP_OWN | MSCP_INT; -} - -/* - * Handle a response ring transition. - */ -void -mscp_dorsp(mi) - register struct mscp_info *mi; -{ - register struct uba_device *ui; - register struct buf *bp; - register struct mscp *mp; - register int nextrsp; - struct mscp_driver *md = mi->mi_md; - char *ctlrname, *drivename; - int st, error, info; - - ctlrname = md->md_mname; - drivename = md->md_dname; - nextrsp = mi->mi_rsp.mri_next; -loop: - if (mi->mi_rsp.mri_desc[nextrsp] & MSCP_OWN) { - /* - * No more responses. Remember the next expected - * response index. Check to see if we have some - * credits back, and wake up sleepers if so. - */ - mi->mi_rsp.mri_next = nextrsp; - if (mi->mi_wantcredits && mi->mi_credits > MSCP_MINCREDITS) { - mi->mi_wantcredits = 0; - wakeup((caddr_t) &mi->mi_wantcredits); - } - return; - } - - /* - * Found a response. Update credit information. If there is - * nothing else to do, jump to `done' to get the next response. - */ - mp = &mi->mi_rsp.mri_ring[nextrsp]; - mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc); - switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { - - case MSCPT_SEQ: - break; - - case MSCPT_DATAGRAM: - (*md->md_dgram)(mi, mp); - goto done; - - case MSCPT_CREDITS: - goto done; - - case MSCPT_MAINTENANCE: - default: - printf("%s%d: unit %d: unknown message type 0x%x ignored\n", - ctlrname, mi->mi_ctlr, mp->mscp_unit, - MSCP_MSGTYPE(mp->mscp_msgtc)); - goto done; - } - - /* - * Controllers are allowed to interrupt as any drive, so we - * must check the command before checking for a drive. - */ - if (mp->mscp_opcode == (M_OP_SETCTLRC | M_OP_END)) { - (*md->md_ctlrdone)(mi, mp); - goto done; - } - - /* - * Find the drive info. If there is none, and this is an - * available attention response, try configuring a new drive. - */ - if (mp->mscp_unit > md->md_ndpc) { - printf("%s%d: unit %d out of range\n", - ctlrname, mi->mi_ctlr, mp->mscp_unit); - goto done; - } - if ((ui = mi->mi_ip[mp->mscp_unit]) == NULL) { - if ((*md->md_unconf)(mi, mp) != MSCP_DONE) { - printf("%s%d: unit %d not configured, ", - ctlrname, mi->mi_ctlr, mp->mscp_unit); - if (mp->mscp_opcode == M_OP_AVAILATTN) - printf("available attn"); - else - printf("stray response op 0x%x status 0x%x", - mp->mscp_opcode, mp->mscp_status); - printf(" ignored\n"); - } - goto done; - } - - /* - * Handle individual responses. - */ - st = mp->mscp_status & M_ST_MASK; - error = 0; - switch (mp->mscp_opcode) { - - case M_OP_END: - /* - * The controller presents a bogus END packet when - * a read/write command is given with an illegal - * block number. This is contrary to the MSCP - * specification (ENDs are to be given only for - * invalid commands), but that is the way of it. - */ - if (st == M_ST_INVALCMD && mp->mscp_cmdref != 0) { - printf("%s%d: bad lbn (%d)?\n", drivename, - ui->ui_unit, (int)mp->mscp_seq.seq_lbn); - error = EIO; - goto rwend; - } - goto unknown; - - case M_OP_ONLINE | M_OP_END: - /* - * Finished an ON LINE request. Call the driver to - * find out whether it succeeded. If so, mark it on - * line. - */ - if (ui->ui_flags & UNIT_ONLINE) { - printf("%s%d: duplicate ONLINE ignored\n", - drivename, ui->ui_unit); - break; - } - if ((*md->md_online)(ui, mp) == MSCP_DONE) - ui->ui_flags |= UNIT_ONLINE; - break; - - case M_OP_GETUNITST | M_OP_END: - /* - * Got unit status. Call the driver to find out - * whether it succeeded, and if so, mark it. - */ - if ((*md->md_gotstatus)(ui, mp) == MSCP_DONE) - ui->ui_flags |= UNIT_HAVESTATUS; - break; - - case M_OP_AVAILATTN: - /* - * The drive went offline and we did not notice. - * Mark it off line now, to force an on line request - * next, so we can make sure it is still the same - * drive. - * - * IF THE UDA DRIVER HAS A COMMAND AWAITING UNIBUS - * RESOURCES, THAT COMMAND MAY GO OUT BEFORE THE ON - * LINE. IS IT WORTH FIXING?? - */ - ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS); -#ifdef notyet - (*md->md_offline)(ui, mp); -#endif - break; - - case M_OP_READ | M_OP_END: - case M_OP_WRITE | M_OP_END: - /* - * A transfer finished. Get the buffer, and release its - * map registers via ubadone(). If the command finished - * with an off line or available status, the drive went - * off line (the idiot controller does not tell us until - * it comes back *on* line, or until we try to use it). - */ - if (mp->mscp_cmdref == 0) { - /* - * No buffer means there is a bug somewhere! - */ - printf("%s%d: io done, but no buffer?\n", - drivename, ui->ui_unit); - mscp_hexdump(mp); - break; - } - -rwend: -#ifdef AVOID_EMULEX_BUG - { - register u_short *p = (u_short *) &mp->mscp_cmdref; - - /* - * Note any errors on the part of the controller. - * The lower word should be zero after exclusive - * or'ing with mscp_aeb_xor, and the upper should - * then be in the range [1..AEB_MAX_BP]. - */ - mp->mscp_cmdref ^= mscp_aeb_xor; - p[1]--; - if (p[1] >= AEB_MAX_BP) - panic("unrecoverable Emulex screwup"); - if (p[0] == 0) - mi->mi_ok++; - else { - /* - * Calculate the expected response, - * assuming p[1] is correct. The - * actual response is then the expected - * response xor p[0]. - */ - int sb = ((p[1] + 1) << 16) ^ mscp_aeb_xor; - - log(LOG_WARNING, "\ -Emulex SC41/MS screwup: %s%d, got %d correct, then changed 0x%x to 0x%x\n", - ctlrname, mi->mi_ctlr, - mi->mi_ok, sb, sb ^ p[0]); - mi->mi_ok = 0; - } - /* convert index back to buffer, and mark free */ - bp = mi->mi_bp[p[1]]; - mi->mi_bp[p[1]] = 0; - } -#else - bp = (struct buf *) mp->mscp_cmdref; -#ifdef MSCP_PARANOIA - { - register struct buf *q = mi->mi_wtab.av_forw; - - /* - * Ensure that this response corresponds to - * some outstanding request. If not, ignore - * it entirely. This will likely cause a - * Unibus reset soon, after which the controller - * just might behave. - */ - while (q != bp && q != &mi->mi_wtab) - q = q->av_forw; - if (q != bp) { - printf("%s%d: bad response packet ignored\n", - ctlrname, mi->mi_ctlr); - mscp_hexdump(mp); - goto out; - } - } -#endif MSCP_PARANOIA -#endif AVOID_EMULEX_BUG - - /* - * Mark any error-due-to-bad-LBN (via `goto rwend'). - * WHAT STATUS WILL THESE HAVE? IT SURE WOULD BE NICE - * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. - */ - if (error) { - bp->b_flags |= B_ERROR; - bp->b_error = error; - } - if (st == M_ST_OFFLINE || st == M_ST_AVAILABLE) { - ui->ui_flags &= ~(UNIT_ONLINE | UNIT_HAVESTATUS); -#ifdef notyet - (*md->md_offline)(ui, mp); -#endif - } - - /* - * Unlink the transfer from the wait queue mi_wtab. - * If there are no more transfers on the drive queue - * for this drive, and it is a profiled disk, turn - * off its busy bit. - */ - - - { /* Insane */ - struct buf *tmp; - - tmp=bp->b_actf; - if(!tmp){ - printf("Found 0 - bad!\n"); - asm("halt"); - } - while(tmp->b_actf!=bp){ - if(!tmp){ - printf("Got lost in chains...\n"); - asm("halt"); - } - tmp=tmp->b_actf; - } - tmp->b_actf=bp->b_actf; - } - if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_hash.le_next == NULL) - dk_busy &= ~(1 << ui->ui_dk); - -/* Was: bp->av_back->av_forw = bp->av_forw; - bp->av_forw->av_back = bp->av_back; - if (ui->ui_dk >= 0 && md->md_utab[ui->ui_unit].b_forw == NULL) - dk_busy &= ~(1 << ui->ui_dk); -*/ - /* - * If the transfer has something to do with bad - * block forwarding, let the driver handle the - * rest. - */ - if ((bp->b_flags & B_BAD) != 0 && md->md_bb != NULL) { - (*md->md_bb)(ui, mp, bp); - goto out; - } - - /* - * If the transfer failed, give the driver a crack - * at fixing things up. - */ - if (st != M_ST_SUCCESS) { - switch ((*md->md_ioerr)(ui, mp, bp)) { - - case MSCP_DONE: /* fixed */ - break; - - case MSCP_RESTARTED: /* still working on it */ - goto out; - - case MSCP_FAILED: /* no luck */ - diskerr(bp, drivename, "hard error", - LOG_PRINTF, -1, md->md_lab ? - &md->md_lab[ui->ui_unit] : md->md_lab); - mscp_printevent(mp); - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - break; - } - } - - /* - * Set the residual count and mark the transfer as - * done. If the I/O wait queue is now empty, release - * the shared BDP, if any. - */ - info = bp->b_info; /* we are about to clobber it */ - bp->b_resid = bp->b_bcount - mp->mscp_seq.seq_bytecount; - (*md->md_iodone)(mi, bp, info); -out: - break; - - case M_OP_REPLACE | M_OP_END: - /* - * A replace operation finished. Just let the driver - * handle it (if it does replaces). - */ - if (md->md_replace == NULL) - printf("%s%d: bogus REPLACE end\n", - drivename, ui->ui_unit); - else - (*md->md_replace)(ui, mp); - break; - - default: - /* - * If it is not one of the above, we cannot handle it. - * (And we should not have received it, for that matter.) - */ -unknown: - printf("%s%d: unknown opcode 0x%x status 0x%x ignored\n", - mi->mi_md->md_dname, ui->ui_unit, - mp->mscp_opcode, mp->mscp_status); - mscp_hexdump(mp); - break; - } - - /* - * If the drive needs to be put back in the controller queue, - * do that now. (`bp' below ought to be `dp', but they are all - * struct buf *.) Note that b_active was cleared in the driver; - * we presume that there is something to be done, hence reassert it. - */ - if (ui->ui_flags & UNIT_REQUEUE) { - bp = &md->md_utab[ui->ui_unit]; - if (bp->b_active) panic("mscp_dorsp requeue"); - MSCP_APPEND(bp, mi->mi_tab, b_hash.le_next); -/* Was: MSCP_APPEND(bp, mi->mi_tab, b_forw); */ - bp->b_active = 1; - ui->ui_flags &= ~UNIT_REQUEUE; - } - -done: - /* - * Give back the response packet, and take a look at the next. - */ - mp->mscp_msglen = MSCP_MSGLEN; - mi->mi_rsp.mri_desc[nextrsp] |= MSCP_OWN; - nextrsp = (nextrsp + 1) % mi->mi_rsp.mri_size; - goto loop; -} - -/* - * Dump the entire contents of an MSCP packet in hex. Mainly useful - * for debugging.... - */ -void -mscp_hexdump(mp) - register struct mscp *mp; -{ - register long *p = (long *) mp; - register int i = mp->mscp_msglen; - - if (i > 256) /* sanity */ - i = 256; - i /= sizeof (*p); /* ASSUMES MULTIPLE OF sizeof(long) */ - while (--i >= 0) - printf("0x%x ", (int)*p++); - printf("\n"); -} - -/* - * Requeue outstanding transfers, e.g., after bus reset. - * Also requeue any drives that have on line or unit status - * info pending. - */ -void -mscp_requeue(mi) - struct mscp_info *mi; -{ - register struct uba_device *ui; - register struct mscp_driver *md = mi->mi_md; - register struct buf *bp, *dp; - register int unit; - struct buf *nextbp; - - /* - * Clear the controller chain. Mark everything un-busy; we - * will soon fix any that are in fact busy. - */ - mi->mi_tab->b_actf = NULL; - mi->mi_tab->b_active = 0; - for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { - ui = md->md_dinfo[unit]; - if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) - continue; /* not ours */ - dp->b_hash.le_next = NULL; - dp->b_active = 0; - } - - /* - * Scan the wait queue, linking buffers onto drive queues. - * Note that these must be put at the front of the drive queue, - * lest we reorder I/O operations. - */ - for (bp = *mi->mi_wtab.b_actb; bp != &mi->mi_wtab; bp = nextbp) { - nextbp = *bp->b_actb; - dp = &md->md_utab[minor(bp->b_dev) >> md->md_unitshift]; - bp->b_actf = dp->b_actf; - if (dp->b_actf == NULL) - dp->b_actb = (void *)bp; - dp->b_actf = bp; - } - mi->mi_wtab.b_actf = *mi->mi_wtab.b_actb = &mi->mi_wtab; - - /* - * Scan for drives waiting for on line or status responses, - * and for drives with pending transfers. Put these on the - * controller queue, and mark the controller busy. - */ - for (unit = 0, dp = md->md_utab; unit < md->md_nunits; unit++, dp++) { - ui = md->md_dinfo[unit]; - if (ui == NULL || !ui->ui_alive || ui->ui_ctlr != mi->mi_ctlr) - continue; - ui->ui_flags &= ~(UNIT_HAVESTATUS | UNIT_ONLINE); - if ((ui->ui_flags & UNIT_REQUEUE) == 0 && dp->b_actf == NULL) - continue; - ui->ui_flags &= ~UNIT_REQUEUE; - MSCP_APPEND(dp, mi->mi_tab, b_hash.le_next); - - dp->b_active = 1; - mi->mi_tab->b_active = 1; - } - -#ifdef AVOID_EMULEX_BUG - /* - * ... and clear the index-to-buffer table. - */ - for (unit = 0; unit < AEB_MAX_BP; unit++) - mi->mi_bp[unit] = 0; -#endif -} - - -/* - * MSCP error reporting - */ - -/* - * Messages for the various subcodes. - */ -static char unknown_msg[] = "unknown subcode"; - -/* - * Subcodes for Success (0) - */ -static char *succ_msgs[] = { - "normal", /* 0 */ - "spin down ignored", /* 1 = Spin-Down Ignored */ - "still connected", /* 2 = Still Connected */ - unknown_msg, - "dup. unit #", /* 4 = Duplicate Unit Number */ - unknown_msg, - unknown_msg, - unknown_msg, - "already online", /* 8 = Already Online */ - unknown_msg, - unknown_msg, - unknown_msg, - unknown_msg, - unknown_msg, - unknown_msg, - unknown_msg, - "still online", /* 16 = Still Online */ -}; - -/* - * Subcodes for Invalid Command (1) - */ -static char *icmd_msgs[] = { - "invalid msg length", /* 0 = Invalid Message Length */ -}; - -/* - * Subcodes for Command Aborted (2) - */ -/* none known */ - -/* - * Subcodes for Unit Offline (3) - */ -static char *offl_msgs[] = { - "unknown drive", /* 0 = Unknown, or online to other ctlr */ - "not mounted", /* 1 = Unmounted, or RUN/STOP at STOP */ - "inoperative", /* 2 = Unit Inoperative */ - unknown_msg, - "duplicate", /* 4 = Duplicate Unit Number */ - unknown_msg, - unknown_msg, - unknown_msg, - "in diagnosis", /* 8 = Disabled by FS or diagnostic */ -}; - -/* - * Subcodes for Unit Available (4) - */ -/* none known */ - -/* - * Subcodes for Media Format Error (5) - */ -static char *media_fmt_msgs[] = { - "fct unread - edc", /* 0 = FCT unreadable */ - "invalid sector header",/* 1 = Invalid Sector Header */ - "not 512 sectors", /* 2 = Not 512 Byte Sectors */ - "not formatted", /* 3 = Not Formatted */ - "fct ecc", /* 4 = FCT ECC */ -}; - -/* - * Subcodes for Write Protected (6) - * N.B.: Code 6 subcodes are 7 bits higher than other subcodes - * (i.e., bits 12-15). - */ -static char *wrprot_msgs[] = { - unknown_msg, - "software", /* 1 = Software Write Protect */ - "hardware", /* 2 = Hardware Write Protect */ -}; - -/* - * Subcodes for Compare Error (7) - */ -/* none known */ - -/* - * Subcodes for Data Error (8) - */ -static char *data_msgs[] = { - "forced error", /* 0 = Forced Error (software) */ - unknown_msg, - "header compare", /* 2 = Header Compare Error */ - "sync timeout", /* 3 = Sync Timeout Error */ - unknown_msg, - unknown_msg, - unknown_msg, - "uncorrectable ecc", /* 7 = Uncorrectable ECC */ - "1 symbol ecc", /* 8 = 1 bit ECC */ - "2 symbol ecc", /* 9 = 2 bit ECC */ - "3 symbol ecc", /* 10 = 3 bit ECC */ - "4 symbol ecc", /* 11 = 4 bit ECC */ - "5 symbol ecc", /* 12 = 5 bit ECC */ - "6 symbol ecc", /* 13 = 6 bit ECC */ - "7 symbol ecc", /* 14 = 7 bit ECC */ - "8 symbol ecc", /* 15 = 8 bit ECC */ -}; - -/* - * Subcodes for Host Buffer Access Error (9) - */ -static char *host_buffer_msgs[] = { - unknown_msg, - "odd xfer addr", /* 1 = Odd Transfer Address */ - "odd xfer count", /* 2 = Odd Transfer Count */ - "non-exist. memory", /* 3 = Non-Existent Memory */ - "memory parity", /* 4 = Memory Parity Error */ -}; - -/* - * Subcodes for Controller Error (10) - */ -static char *cntlr_msgs[] = { - unknown_msg, - "serdes overrun", /* 1 = Serialiser/Deserialiser Overrun */ - "edc", /* 2 = Error Detection Code? */ - "inconsistant internal data struct",/* 3 = Internal Error */ -}; - -/* - * Subcodes for Drive Error (11) - */ -static char *drive_msgs[] = { - unknown_msg, - "sdi command timeout", /* 1 = SDI Command Timeout */ - "ctlr detected protocol",/* 2 = Controller Detected Protocol Error */ - "positioner", /* 3 = Positioner Error */ - "lost rd/wr ready", /* 4 = Lost R/W Ready Error */ - "drive clock dropout", /* 5 = Lost Drive Clock */ - "lost recvr ready", /* 6 = Lost Receiver Ready */ - "drive detected error", /* 7 = Drive Error */ - "ctlr detected pulse or parity",/* 8 = Pulse or Parity Error */ -}; - -/* - * The following table correlates message codes with the - * decoding strings. - */ -struct code_decode { - char *cdc_msg; - int cdc_nsubcodes; - char **cdc_submsgs; -} code_decode[] = { -#define SC(m) sizeof (m) / sizeof (m[0]), m - {"success", SC(succ_msgs)}, - {"invalid command", SC(icmd_msgs)}, - {"command aborted", 0, 0}, - {"unit offline", SC(offl_msgs)}, - {"unit available", 0, 0}, - {"media format error", SC(media_fmt_msgs)}, - {"write protected", SC(wrprot_msgs)}, - {"compare error", 0, 0}, - {"data error", SC(data_msgs)}, - {"host buffer access error", SC(host_buffer_msgs)}, - {"controller error", SC(cntlr_msgs)}, - {"drive error", SC(drive_msgs)}, -#undef SC -}; - -/* - * Print the decoded error event from an MSCP error datagram. - */ -void -mscp_printevent(mp) - struct mscp *mp; -{ - register int event = mp->mscp_event; - register struct code_decode *cdc; - int c, sc; - char *cm, *scm; - - /* - * The code is the lower six bits of the event number (aka - * status). If that is 6 (write protect), the subcode is in - * bits 12-15; otherwise, it is in bits 5-11. - * I WONDER WHAT THE OTHER BITS ARE FOR. IT SURE WOULD BE - * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. - */ - c = event & M_ST_MASK; - sc = (c != 6 ? event >> 5 : event >> 12) & 0x7ff; - if (c >= sizeof code_decode / sizeof code_decode[0]) - cm = "- unknown code", scm = "??"; - else { - cdc = &code_decode[c]; - cm = cdc->cdc_msg; - if (sc >= cdc->cdc_nsubcodes) - scm = unknown_msg; - else - scm = cdc->cdc_submsgs[sc]; - } - printf(" %s (%s) (code %d, subcode %d)\n", cm, scm, c, sc); -} - -/* - * Print the code and logical block number for an error packet. - * THIS IS PROBABLY PECULIAR TO DISK DRIVES. IT SURE WOULD BE - * NICE IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. - */ -void -mscp_decodeerror(name, ctlr, mp) - char *name; - int ctlr; - register struct mscp *mp; -{ - /* - * For bad blocks, mp->mscp_erd.erd_hdr identifies a code and - * the logical block number. Code 0 is a regular block; code 6 - * is a replacement block. The remaining codes are currently - * undefined. The code is in the upper four bits of the header - * (bits 0-27 are the lbn). - */ - int issoft = mp->mscp_flags & (M_LF_SUCC | M_LF_CONT); - static char *codemsg[16] = { - "lbn", "code 1", "code 2", "code 3", - "code 4", "code 5", "rbn", "code 7", - "code 8", "code 9", "code 10", "code 11", - "code 12", "code 13", "code 14", "code 15" - }; -#define BADCODE(h) (codemsg[(unsigned)(h) >> 28]) -#define BADLBN(h) ((h) & 0xfffffff) - - printf("%s%d: %s error datagram%s:", name, ctlr, - issoft ? "soft" : "hard", - mp->mscp_flags & M_LF_CONT ? " (continuing)" : ""); - switch (mp->mscp_format & 0377) { - - case M_FM_CTLRERR: /* controller error */ - break; - - case M_FM_BUSADDR: /* host memory access error */ - printf(" memory addr 0x%x:", (int)mp->mscp_erd.erd_busaddr); - break; - - case M_FM_DISKTRN: - printf(" unit %d: level %d retry %d, %s %d:", - mp->mscp_unit, - mp->mscp_erd.erd_level, mp->mscp_erd.erd_retry, - BADCODE(mp->mscp_erd.erd_hdr), - (int)BADLBN(mp->mscp_erd.erd_hdr)); - break; - - case M_FM_SDI: - printf(" unit %d: %s %d:", mp->mscp_unit, - BADCODE(mp->mscp_erd.erd_hdr), - (int)BADLBN(mp->mscp_erd.erd_hdr)); - break; - - case M_FM_SMLDSK: - printf(" unit %d: small disk error, cyl %d:", - mp->mscp_unit, mp->mscp_erd.erd_sdecyl); - break; - - default: - printf(" unit %d: unknown error, format 0x%x:", - mp->mscp_unit, mp->mscp_format); - } - mscp_printevent(mp); -#undef BADCODE -#undef BADLBN -} diff --git a/sys/arch/vax/vax/mscp.h b/sys/arch/vax/vax/mscp.h deleted file mode 100644 index 1f5383822777..000000000000 --- a/sys/arch/vax/vax/mscp.h +++ /dev/null @@ -1,473 +0,0 @@ -/* $NetBSD: mscp.h,v 1.3 1995/10/20 13:51:56 ragge Exp $ */ - -/* - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mscp.h 7.5 (Berkeley) 6/28/90 - */ - -/* - * Definitions for the Mass Storage Control Protocol - * I WISH I KNEW WHAT MORE OF THESE WERE. IT SURE WOULD BE NICE - * IF DEC SOLD DOCUMENTATION FOR THEIR OWN CONTROLLERS. - */ - -/* - * Control message opcodes - */ -#define M_OP_ABORT 0x01 /* Abort command */ -#define M_OP_GETCMDST 0x02 /* Get command status command */ -#define M_OP_GETUNITST 0x03 /* Get unit status command */ -#define M_OP_SETCTLRC 0x04 /* Set controller characteristics command */ -#define M_OP_SEREX 0x07 /* Serious exception end message */ -#define M_OP_AVAILABLE 0x08 /* Available command */ -#define M_OP_ONLINE 0x09 /* Online command */ -#define M_OP_SETUNITC 0x0a /* Set unit characteristics command */ -#define M_OP_DTACCPATH 0x0b /* Determine access paths command */ -#define M_OP_ACCESS 0x10 /* Access command */ -#define M_OP_COMPCD 0x11 /* Compare controller data command */ -#define M_OP_ERASE 0x12 /* Erase command */ -#define M_OP_FLUSH 0x13 /* Flush command */ -#define M_OP_REPLACE 0x14 /* Replace command */ -#define M_OP_COMPHD 0x20 /* Compare host data command */ -#define M_OP_READ 0x21 /* Read command */ -#define M_OP_WRITE 0x22 /* Write command */ -#define M_OP_POS 0x25 /* Positioning command */ -#define M_OP_AVAILATTN 0x40 /* Available attention message */ -#define M_OP_DUPUNIT 0x41 /* Duplicate unit number attention message */ -#define M_OP_ACCPATH 0x42 /* Access path attention message */ -#define M_OP_END 0x80 /* End message flag */ - - -/* - * Generic command modifiers - */ -#define M_MD_EXPRS 0x8000 /* Express request */ -#define M_MD_COMP 0x4000 /* Compare */ -#define M_MD_CLSEX 0x2000 /* Clear serious exception */ -#define M_MD_ERROR 0x1000 /* Force error */ -#define M_MD_SCCHH 0x0800 /* Suppress caching (high speed) */ -#define M_MD_SCCHL 0x0400 /* Suppress caching (low speed) */ -#define M_MD_SECOR 0x0200 /* Suppress error correction */ -#define M_MD_SEREC 0x0100 /* Suppress error recovery */ -#define M_MD_SSHDW 0x0080 /* Suppress shadowing */ -#define M_MD_WBKNV 0x0040 /* Write back (non-volatile) */ -#define M_MD_WBKVL 0x0020 /* Write back (volatile) */ -#define M_MD_WRSEQ 0x0010 /* Write shadow set one unit at a time */ - -/* - * AVAILABLE command modifiers - */ -#define M_AVM_ALLCD 0x0002 /* All class drivers */ -#define M_AVM_SPINDOWN 0x0001 /* Spin down */ - -/* - * FLUSH command modifiers - */ -#define M_FLM_FLUSHENU 0x0001 /* Flush entire unit */ -#define M_FLM_VOLATILE 0x0002 /* Volatile only */ - -/* - * GET UNIT STATUS command modifiers - */ -#define M_GUM_NEXTUNIT 0x0001 /* Next unit */ - -/* - * ONLINE command modifiers - */ -#define M_OLM_RIP 0x0001 /* Allow self destruction */ -#define M_OLM_IGNMF 0x0002 /* Ignore media format error */ - -/* - * ONLINE and SET UNIT CHARACTERISTICS command modifiers - */ -#define M_OSM_ALTERHI 0x0020 /* Alter host identifier */ -#define M_OSM_SHADOWSP 0x0010 /* Shadow unit specified */ -#define M_OSM_CLEARWBL 0x0008 /* Clear write-back data lost */ -#define M_OSM_SETWRPROT 0x0004 /* Set write protect */ - -/* - * REPLACE command modifiers - */ -#define M_RPM_PRIMARY 0x0001 /* Primary replacement block */ - -/* - * End message flags - */ -#define M_EF_BBLKR 0x80 /* Bad block reported */ -#define M_EF_BBLKU 0x40 /* Bad block unreported */ -#define M_EF_ERLOG 0x20 /* Error log generated */ -#define M_EF_SEREX 0x10 /* Serious exception */ - -/* - * Controller flags - */ -#define M_CF_ATTN 0x80 /* Enable attention messages */ -#define M_CF_MISC 0x40 /* Enable miscellaneous error log messages */ -#define M_CF_OTHER 0x20 /* Enable other host's error log messages */ -#define M_CF_THIS 0x10 /* Enable this host's error log messages */ -#define M_CF_MLTHS 0x04 /* Multi-host */ -#define M_CF_SHADW 0x02 /* Shadowing */ -#define M_CF_576 0x01 /* 576 byte sectors */ - -/* - * Unit flags - */ -#define M_UF_REPLC 0x8000 /* Controller initiated bad block replacement */ -#define M_UF_INACT 0x4000 /* Inactive shadow set unit */ -#define M_UF_WRTPH 0x2000 /* Write protect (hardware) */ -#define M_UF_WRTPS 0x1000 /* Write protect (software or volume) */ -#define M_UF_SCCHH 0x8000 /* Suppress caching (high speed) */ -#define M_UF_SCCHL 0x4000 /* Suppress caching (low speed) */ -#define M_UF_RMVBL 0x0080 /* Removable media */ -#define M_UF_WBKNV 0x0040 /* Write back (non-volatile) */ -#define M_UF_576 0x0004 /* 576 byte sectors */ -#define M_UF_CMPWR 0x0002 /* Compare writes */ -#define M_UF_CMPRD 0x0001 /* Compare reads */ - -/* - * Error Log message format codes - */ -#define M_FM_CTLRERR 0x00 /* Controller error */ -#define M_FM_BUSADDR 0x01 /* Host memory access error */ -#define M_FM_DISKTRN 0x02 /* Disk transfer error */ -#define M_FM_SDI 0x03 /* SDI error */ -#define M_FM_SMLDSK 0x04 /* Small disk error */ - -/* - * Error Log message flags - */ -#define M_LF_SUCC 0x80 /* Operation successful */ -#define M_LF_CONT 0x40 /* Operation continuing */ -#define M_LF_SQNRS 0x01 /* Sequence number reset */ - -/* - * Status codes - */ -#define M_ST_MASK 0x1f /* Status code mask */ -#define M_ST_SUCCESS 0x00 /* Success */ -#define M_ST_INVALCMD 0x01 /* Invalid command */ -#define M_ST_ABORTED 0x02 /* Command aborted */ -#define M_ST_OFFLINE 0x03 /* Unit offline */ -#define M_ST_AVAILABLE 0x04 /* Unit available */ -#define M_ST_MFMTERR 0x05 /* Media format error */ -#define M_ST_WRPROT 0x06 /* Write protected */ -#define M_ST_COMPERR 0x07 /* Compare error */ -#define M_ST_DATAERR 0x08 /* Data error */ -#define M_ST_HOSTBUFERR 0x09 /* Host buffer access error */ -#define M_ST_CTLRERR 0x0a /* Controller error */ -#define M_ST_DRIVEERR 0x0b /* Drive error */ -#define M_ST_DIAG 0x1f /* Message from an internal diagnostic */ - -/* - * Subcodes of M_ST_OFFLINE - */ -#define M_OFFLINE_UNKNOWN (0 << 5) /* unknown or on other ctlr */ -#define M_OFFLINE_UNMOUNTED (1 << 5) /* unmounted or RUN/STOP at STOP */ -#define M_OFFLINE_INOPERATIVE (2 << 5) /* inoperative? */ -#define M_OFFLINE_DUPLICATE (4 << 5) /* duplicate unit number */ -#define M_OFFLINE_INDIAGNOSTIC (8 << 5) /* disabled by FS or diagnostic */ - -/* - * An MSCP packet begins with a header giving the length of - * the entire packet (including the header itself)(?), two bytes - * of device specific data, and the a whole bunch of variants - * depending on message type. - * - * N.B.: In most cases we distinguish between a `command' and - * an `end' variant as well. The command variant is that which - * is given to the controller; the `end' variant is its response. - */ - -/* - * Generic sequential message variant (command and response). - */ -struct mscpv_seq { - long seq_bytecount; /* byte count */ -#define seq_rbn seq_bytecount /* aka RBN (replace) */ -#define seq_outref seq_bytecount /* aka outref (abort/get cmd status) */ - long seq_buffer; /* buffer descriptor */ - long seq_mapbase; /* page map (first PTE) phys address */ - long seq_xxx1; /* ? */ /* unused */ - long seq_lbn; /* logical block number */ - long seq_xxx2; /* ? */ /* unused */ - long *seq_addr; /* pointer to cmd descriptor */ - long seq_software[4]; /* reserved to software; unused */ -}; - -/* - * Set Controller Characteristics command variant - */ -struct mscpv_sccc { - u_short sccc_version; /* MSCP version number */ - u_short sccc_ctlrflags; /* controller flags */ - u_short sccc_hosttimo; /* host timeout */ - u_short sccc_usefrac; /* use fraction */ - long sccc_time; /* time and date */ - long sccc_xxx1; /* ? */ - long sccc_errlgfl; /* ? */ - short sccc_xxx2; /* ? */ - short sccc_copyspd; /* ? */ -}; - -/* - * Set Controller Characteristics end variant - */ -struct mscpv_scce { - u_short scce_version; /* MSCP version number */ - u_short scce_ctlrflags; /* controller flags */ - u_short scce_ctlrtimo; /* controller timeout */ - u_short scce_ctlrcmdl; /* ??? */ - quad_t scce_ctlrid; /* controller ID */ - long scce_xxx[3]; /* ? */ - long scce_volser; /* volume serial number */ -}; - -/* - * On Line command variant - */ -struct mscpv_onlc { - long onlc_xxx1[4]; /* ? */ - long onlc_errlgfl; /* error log flag? */ - short onlc_xxx2; /* ? */ - short onlc_copyspd; /* copy speed? */ -}; - -/* - * On Line end variant - */ -struct mscpv_onle { - long onle_xxx1[3]; /* ? */ -/*???*/ short onle_xxx2; /* ? */ - u_char onle_drivetype; /* drive type index (same in guse) */ - char onle_xxx3; /* ? */ - long onle_mediaid; /* media type id (same in guse) */ - long onle_xxx4; /* ? */ - long onle_unitsize; /* unit size in sectors */ - long onle_volser; /* volume serial number */ -}; - -/* - * Get Unit Status end variant (and Avail Attn?) - */ -struct mscpv_guse { - u_short guse_multunit; /* multi-unit code */ - u_short guse_unitflags; /* unit flags */ - long guse_hostid; /* host id */ - long guse_unitid0; /*???*/ - short guse_unitid1; /*???*/ - u_char guse_drivetype; /* drive type index */ - u_char guse_unitid2; /*???*/ - long guse_mediaid; /* media type id (encoded) */ - short guse_shadowunit; /* shadow unit */ - short guse_shadowstat; /* shadow status */ - u_short guse_nspt; /* sectors per track */ - u_short guse_group; /* track group size */ - u_short guse_ngpc; /* groups per cylinder */ - u_short guse_xxx; /* reserved */ - u_short guse_rctsize; /* RCT size (sectors) */ - u_char guse_nrpt; /* RBNs per track */ - u_char guse_nrct; /* number of RCTs */ -}; - -/* - * Macros to break up and build media IDs. An ID encodes the port - * type in the top 10 bits, and the drive type in the remaining 22. - * The 10 bits, and 15 of the 22, are in groups of 5, with the value - * 0 representing space and values 1..26 representing A..Z. The low - * 7 bits represent a number in 0..127. Hence an RA81 on a UDA50 - * is < >81, or 0x25641051. This encoding scheme is known - * in part in uda.c. - * - * The casts below are just to make pcc generate better code. - */ -#define MSCP_MEDIA_PORT(id) (((long)(id) >> 22) & 0x3ff) /* port */ -#define MSCP_MEDIA_DRIVE(id) ((long)(id) & 0x003fffff) /* drive */ -#define MSCP_MID_ECH(n, id) (((long)(id) >> ((n) * 5 + 7)) & 0x1f) -#define MSCP_MID_CHAR(n, id) \ - (MSCP_MID_ECH(n, id) ? MSCP_MID_ECH(n, id) + '@' : ' ') -#define MSCP_MID_NUM(id) ((id) & 0x7f) -/* for, e.g., RA81 */ -#define MSCP_MKDRIVE2(a, b, n) \ - (((a) - '@') << 17 | ((b) - '@') << 12 | (n)) -/* for, e.g., RRD50 */ -#define MSCP_MKDRIVE3(a, b, c, n) \ - (((a) - '@') << 17 | ((b) - '@') << 12 | ((c) - '@') << 7 | (n)) - -/* - * Error datagram variant. - */ -struct mscpv_erd { - quad_t erd_ctlrid; /* controller ID */ - u_char erd_ctlrsoftware; /* controller software version */ - u_char erd_ctlrhardware; /* controller hardware version */ - u_short erd_multiunit; /* multi-unit code (?) */ - union { - u_long un_busaddr; /* bus address, if mem access err */ - quad_t un_unitid; /* unit id, otherwise */ - } erd_un1; -#define erd_busaddr erd_un1.un_busaddr -#define erd_unitid erd_un1.un_unitid - u_char erd_unitsoftware; /* unit software version */ - u_char erd_unithardware; /* unit hardware version */ - union { - u_char un_b[2]; /* level, retry (if disk xfer err) */ - u_short un_s; /* cylinder (if small disk error) */ - } erd_un2; -#define erd_level erd_un2.un_b[0] -#define erd_retry erd_un2.un_b[1] -#define erd_sdecyl erd_un2.un_s - long erd_volser; /* volume serial number */ - u_long erd_hdr; /* `header' (block number) */ - u_char erd_sdistat[12]; /* SDI status information (?) */ -}; - -/* - * I am making brash assumptions about the first four bytes of all - * MSCP packets. These appear to be true for both UDA50s and TMSCP - * devices (TU81, TA81, TK50). DEC claim that these four bytes are - * not part of MSCP itself, yet at least the length is necessary - * for, e.g., error checking. - */ -struct mscp { - u_short mscp_msglen; /* length in bytes */ - u_char mscp_msgtc; /* type (high 4 bits) and credits */ - u_char mscp_vcid; /* virtual circuit ID */ - long mscp_cmdref; /* command reference number */ - u_short mscp_unit; /* unit number */ - u_short mscp_seqnum; /* sequence number */ - u_char mscp_opcode; /* opcode */ -#define mscp_format mscp_opcode /* aka format (datagrams) */ - u_char mscp_flags; /* flags */ - u_short mscp_modifier; /* modifier (commands) */ -#define mscp_status mscp_modifier /* aka status (ends) */ -#define mscp_event mscp_modifier /* aka event (datagrams) */ - union { - struct mscpv_seq un_seq; /* generic sequential msg */ - struct mscpv_sccc un_sccc; /* SCC command */ - struct mscpv_scce un_scce; /* SCC end */ - struct mscpv_onlc un_onlc; /* on line command */ - struct mscpv_onle un_onle; /* on line end */ - struct mscpv_guse un_guse; /* get unit status */ - struct mscpv_erd un_erd; /* error datagram */ - } mscp_un; -/*???*/ long mscp_xxx; /* pad to 64 bytes */ -}; - -/* - * Define message length according to the DEC specifications by dropping - * the four byte header. - */ -#define MSCP_MSGLEN (sizeof (struct mscp) - 4) - -/* - * Shorthand - */ - -/* - * Generic packet - */ -#define mscp_seq mscp_un.un_seq - -/* - * Set Controller Characteristics packet - */ -#define mscp_sccc mscp_un.un_sccc - -/* - * Set Controller Characteristics end packet - */ -#define mscp_scce mscp_un.un_scce - -/* - * Online / Set Unit Characteristics command packet - */ -#define mscp_onlc mscp_un.un_onlc - -/* - * Online end packet - */ -#define mscp_onle mscp_un.un_onle - -/* - * Get Unit Status end packet - */ -#define mscp_guse mscp_un.un_guse - -/* - * MSCP Error Log packet - */ -#define mscp_erd mscp_un.un_erd - -/* - * MSCP seq_addr field actually belongs to overall packet. - */ -#define mscp_addr mscp_seq.seq_addr - -/* - * Macros to break up mscp_msgtc, and types. - */ -#define MSCP_MSGTYPE(m) ((m) & 0xf0) -#define MSCP_CREDITS(m) ((m) & 0x0f) - -#define MSCPT_SEQ 0x00 /* sequential message */ -#define MSCPT_DATAGRAM 0x10 /* error datagram */ -#define MSCPT_CREDITS 0x20 /* credit notification */ -#define MSCPT_MAINTENANCE 0xf0 /* who knows */ - - -/* - * Here begin more perhaps brash assumptions about MSCP devices... - */ - -/* - * MSCP controllers have `command rings' and `response rings'. A - * command ring is a pool of MSCP packets that the host uses to give - * commands to the controller; a response ring is a pool of MSCP - * packets that the controller uses to give back responses. Entries - * in the command and response rings are `owned' by either the host - * or the controller; only the owner is allowed to alter any of the - * fields in the MSCP packet. Thus, free command packets are owned - * by the host, and free response packets by the controller. When - * the host gives a packet to the controller, it tells the controller - * by touching a device register; when the controller gives a response - * to the host, it generates an interrupt if enabled, and sets - * a device register as well. - * - * The pool is `described' by a set of pointers to the packets, along - * with the two flags below. - */ -#define MSCP_OWN 0x80000000 /* controller owns this packet */ -#define MSCP_INT 0x40000000 /* controller should interrupt */ diff --git a/sys/arch/vax/vax/mscpvar.h b/sys/arch/vax/vax/mscpvar.h deleted file mode 100644 index 52213fab8690..000000000000 --- a/sys/arch/vax/vax/mscpvar.h +++ /dev/null @@ -1,242 +0,0 @@ -/* $NetBSD: mscpvar.h,v 1.7 1996/04/08 18:32:51 ragge Exp $ */ - -/* - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mscpvar.h 7.3 (Berkeley) 6/28/90 - */ - -/* - * MSCP generic driver configuration - */ - -/* - * Enabling MSCP_PARANOIA makes the response code perform various checks - * on the hardware. (Right now it verifies only the buffer pointer in - * mscp_cmdref.) - * - * Enabling AVOID_EMULEX_BUG selects an alternative method of identifying - * transfers in progress, which gets around a rather peculiar bug in the - * SC41/MS. Enabling MSCP_PARANOIA instead should work, but will cause - * `extra' Unibus resets. - * - * Either of these flags can simply be included as an `options' line in - * your configuration file. - */ - -/* #define MSCP_PARANOIA */ -/* #define AVOID_EMULEX_BUG */ - -/* - * Per driver information. - * - * md_ndpc sets the maximum unit number allowed in response packets. - * md_nunits is the number of drives attached to all controllers. - * md_unitshift is the divisor for converting a minor device number - * to a unit index for the device queues in md_utab. - * - * The routines are called from the generic response dispatcher. - * THE FOLLOWING IS OUT OF DATE - * The first three (dgram, ctlrdone, and unconf) get passed a pointer - * to the uba_ctlr and to the packet; the rest get a pointer to the - * uba_device and to the packet (`um, mp' and `ui, mp' respectively). - * The routines unconf, online, gotstatus, and ioerr are functions - * and should return one of the values given below. In addition, - * the ioerr and bb routines get a third argument, `bp': a pointer - * to the buffer describing the transfer in error. - * END OUT OF DATE - */ -struct mscp_info; - -struct mscp_driver { - int md_ndpc; /* number of drives per ctlr */ - int md_nunits; /* total number drives (all ctlrs) */ - int md_unitshift; /* device number to unit: >> count */ - struct buf *md_utab; /* pointer to device queues */ - struct disklabel *md_lab; /* pointer to devicee disklabels */ - struct uba_device **md_dinfo; /* pointer to device info */ - /* error datagram */ - void (*md_dgram) __P((struct mscp_info *, struct mscp *)); - /* controller operation complete */ - void (*md_ctlrdone) __P((struct mscp_info *, struct mscp *)); - /* response from unconfigured drive */ - int (*md_unconf) __P((struct mscp_info *, struct mscp *)); - /* normal I/O is done */ - void (*md_iodone) __P((struct mscp_info *, struct buf *, int)); - /* drive on line */ - int (*md_online) __P((struct uba_device *, struct mscp *));/*XXX*/ - /* got unit status */ - int (*md_gotstatus) __P((struct uba_device *, struct mscp *)); - /* replace done */ - void (*md_replace) __P((struct uba_device *, struct mscp *)); - /* read or write failed */ - int (*md_ioerr) __P((struct uba_device *, struct mscp *, - struct buf *)); - /* B_BAD io done */ - void (*md_bb) __P((struct uba_device *, struct mscp *, - struct buf *)); - char *md_mname; /* name of controllers */ - char *md_dname; /* name of drives */ -}; - -/* - * Return values from functions. - * MSCP_RESTARTED is peculiar to I/O errors. - */ -#define MSCP_DONE 0 /* all ok */ -#define MSCP_FAILED 1 /* no go */ -#define MSCP_RESTARTED 2 /* transfer restarted */ - -/* - * Ring information, per ring (one each for commands and responses). - */ -struct mscp_ri { - int mri_size; /* ring size */ - int mri_next; /* next (expected|free) */ - long *mri_desc; /* base address of descriptors */ - struct mscp *mri_ring; /* base address of packets */ -}; - -/* - * Per device information. - * - * mi_ip is a pointer to the inverting pointers (things that get `ui's - * given unit numbers) FOR THIS CONTROLLER (NOT the whole set!). - * - * mi_wtab holds a queue of those transfers that were started but have - * not yet finished. Other Unibus drivers do not need this as they hand - * out requests one at a time. MSCP devices, however, take a slew of - * requests and pick their own order to execute them. This means that - * we have to have a place to move transfers that were given to the - * controller, so we can tell those apart from those that have not yet - * been handed out; mi_wtab is that place. - */ -struct mscp_info { - struct mscp_driver *mi_md; /* pointer to driver info */ - int mi_ctlr; /* controller index */ - struct buf *mi_tab; /* pointer to ctlr's drive queue */ - struct uba_device **mi_ip; /* pointer to inverting pointers */ - struct mscp_ri mi_cmd; /* MSCP command ring info */ - struct mscp_ri mi_rsp; /* MSCP response ring info */ - short mi_credits; /* transfer credits */ - char mi_wantcmd; /* waiting for command packet */ - char mi_wantcredits; /* waiting for transfer credits */ - struct buf mi_wtab; /* transfer wait queue */ -#ifdef AVOID_EMULEX_BUG -#define AEB_MAX_BP 32 /* max pend xfers (power of 2) XXX */ - volatile struct buf *mi_bp[AEB_MAX_BP]; /* xfer no. to buffer */ - u_int mi_nextbp; /* generates unique xfer no's */ - int mi_ok; /* for error rate statistics */ -#endif AVOID_EMULEX_BUG -}; - -/* - * We have run out of credits when mi_credits is <= MSCP_MINCREDITS. - * It is still possible to issue one command in this case, but it must - * not be a data transfer. E.g., `get command status' or `abort command' - * is legal, while `read' is not. - */ -#define MSCP_MINCREDITS 1 - -/* - * Flags for mscp_getcp(). - */ -#define MSCP_WAIT 1 -#define MSCP_DONTWAIT 0 - - /* get a command packet */ -struct mscp *mscp_getcp __P((struct mscp_info *, int)); - -/* - * Unit flags - */ -#define UNIT_ONLINE 0x01 /* drive is on line */ -#define UNIT_HAVESTATUS 0x02 /* got unit status */ -#define UNIT_REQUEUE 0x04 /* requeue after response */ - -/* - * Handle a command ring transition: wake up sleepers for command packets. - * This is too simple to bother with a function call. - */ -#define MSCP_DOCMD(mi) { \ - if ((mi)->mi_wantcmd) { \ - (mi)->mi_wantcmd = 0; \ - wakeup((caddr_t) &(mi)->mi_wantcmd); \ - } \ -} - -/* - * The following macro appends a buffer to a drive queue or a drive to - * a controller queue, given the name of the forward link. Use as - * `APPEND(dp, &um->um_tab, b_forw)' or `APPEND(bp, dp, av_forw)', - * where `bp' is a transfer request, `dp' is a drive queue, and `um_tab' - * is a controller queue. (That is, the forward link for controller - * queues is `b_forw'; for drive queues, it is `av_forw'.) - * - * Changed to new buf structure 940605/Ragge - */ -#define MSCP_APPEND(bp, queue, link) { \ - struct buf *tmp; \ - \ - (bp)->link = NULL; \ - if ((queue)->b_actf == NULL) \ - (queue)->b_actf = (bp); \ - else { \ - tmp=(queue)->b_actf; \ - while(tmp->link) tmp=tmp->link; \ - tmp->link = (bp); \ - } \ -} - -/* Old APPEND macro */ -/* -#define APPEND(bp, queue, link) { \ - (bp)->link = NULL; \ - if ((queue)->b_actf == NULL) \ - (queue)->b_actf = (bp); \ - else \ - (queue)->b_actl->link = (bp); \ - (queue)->b_actl = (bp); \ -} -*/ - -/* Prototypes */ - -void mscp_printevent __P((struct mscp *)); -void mscp_go __P((struct mscp_info *, struct mscp *, int)); -void mscp_requeue __P((struct mscp_info *)); -void mscp_dorsp __P((struct mscp_info *)); -void mscp_decodeerror __P((char *, int, struct mscp *)); -