Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/mscp Copied from ../../arch/vax/mscp/mscp.c, v
details: https://anonhg.NetBSD.org/src/rev/877e0a70c59d
branches: trunk
changeset: 473332:877e0a70c59d
user: ragge <ragge%NetBSD.org@localhost>
date: Sat May 29 19:11:02 1999 +0000
description:
Copied from ../../arch/vax/mscp/mscp.c,v
diffstat:
sys/dev/mscp/mscp.c | 517 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 517 insertions(+), 0 deletions(-)
diffs (truncated from 521 to 300 lines):
diff -r b0d81735cc61 -r 877e0a70c59d sys/dev/mscp/mscp.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/mscp/mscp.c Sat May 29 19:11:02 1999 +0000
@@ -0,0 +1,517 @@
+/* $NetBSD: mscp.c,v 1.10 1999/05/29 19:11:02 ragge Exp $ */
+
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * 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 <sys/param.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+#include <vax/mscp/mscp.h>
+#include <vax/mscp/mscpvar.h>
+
+#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_softc *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
+
+/*
+ * Handle a response ring transition.
+ */
+void
+mscp_dorsp(mi)
+ register struct mscp_softc *mi;
+{
+ struct device *drive;
+ struct mscp_device *me = mi->mi_me;
+ struct mscp_ctlr *mc = mi->mi_mc;
+ register struct buf *bp;
+ register struct mscp *mp;
+ register int nextrsp;
+ int st, error, info;
+ extern int cold;
+ extern struct mscp slavereply;
+
+ 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;
+ }
+
+ mp = &mi->mi_rsp.mri_ring[nextrsp];
+ mi->mi_credits += MSCP_CREDITS(mp->mscp_msgtc);
+ /*
+ * 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)) {
+ if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS) {
+ mi->mi_flags |= MSC_READY;
+ } else {
+ printf("%s: SETCTLRC failed: %d ",
+ mi->mi_dev.dv_xname, mp->mscp_status);
+ mscp_printevent(mp);
+ }
+ goto done;
+ }
+
+ /*
+ * Found a response. Update credit information. If there is
+ * nothing else to do, jump to `done' to get the next response.
+ */
+ if (mp->mscp_unit >= mi->mi_driveno) { /* Must expand drive table */
+ int tmpno = ((mp->mscp_unit + 32) & 0xffe0) * sizeof(void *);
+ struct device **tmp = (struct device **)
+ malloc(tmpno, M_DEVBUF, M_NOWAIT);
+ bzero(tmp, tmpno);
+ if (mi->mi_driveno) {
+ bcopy(mi->mi_dp, tmp, mi->mi_driveno);
+ free(mi->mi_dp, mi->mi_driveno);
+ }
+ mi->mi_driveno = tmpno;
+ mi->mi_dp = tmp;
+ }
+
+ drive = mi->mi_dp[mp->mscp_unit];
+
+ switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {
+
+ case MSCPT_SEQ:
+ break;
+
+ case MSCPT_DATAGRAM:
+ (*me->me_dgram)(drive, mp, mi);
+ goto done;
+
+ case MSCPT_CREDITS:
+ goto done;
+
+ case MSCPT_MAINTENANCE:
+ default:
+ printf("%s: unit %d: unknown message type 0x%x ignored\n",
+ mi->mi_dev.dv_xname, mp->mscp_unit,
+ MSCP_MSGTYPE(mp->mscp_msgtc));
+ 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: bad lbn (%d)?\n", drive->dv_xname,
+ (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.
+ */
+ (*me->me_online)(drive, mp);
+ break;
+
+ case M_OP_GETUNITST | M_OP_END:
+ /*
+ * Got unit status. If we are autoconfiguring, save
+ * the mscp struct so that mscp_attach know what to do.
+ * If the drive isn't configured, call config_found()
+ * to set it up, otherwise it's just a "normal" unit
+ * status.
+ */
+ if (cold)
+ bcopy(mp, &slavereply, sizeof(struct mscp));
+
+ if (mp->mscp_status == (M_ST_OFFLINE|M_OFFLINE_UNKNOWN))
+ break;
+
+ if (drive == 0) {
+ struct drive_attach_args da;
+
+ da.da_mp = (struct mscp *)mp;
+ da.da_typ = mi->mi_type;
+ config_found(&mi->mi_dev, (void *)&da, mscp_print);
+ } else
+ /* Hack to avoid complaints */
+ if (!(((mp->mscp_event & M_ST_MASK) == M_ST_AVAILABLE)
+ && cold))
+ (*me->me_gotstatus)(drive, mp);
+ 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??
+ */
+#ifdef notyet
+ (*md->md_offline)(ui, mp);
+#endif
+ break;
+
+ case M_OP_POS | M_OP_END:
+ case M_OP_WRITM | M_OP_END:
+ case M_OP_AVAILABLE | M_OP_END:
+ /*
Home |
Main Index |
Thread Index |
Old Index