Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Add in MI target mode code modules
details: https://anonhg.NetBSD.org/src/rev/a31206914680
branches: trunk
changeset: 480166:a31206914680
user: mjacob <mjacob%NetBSD.org@localhost>
date: Wed Jan 05 19:50:05 2000 +0000
description:
Add in MI target mode code modules
diffstat:
sys/dev/ic/isp_target.c | 1227 +++++++++++++++++++++++++++++++++++++++++++++++
sys/dev/ic/isp_target.h | 619 +++++++++++++++++++++++
2 files changed, 1846 insertions(+), 0 deletions(-)
diffs (truncated from 1854 to 300 lines):
diff -r 8b8b3735327f -r a31206914680 sys/dev/ic/isp_target.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ic/isp_target.c Wed Jan 05 19:50:05 2000 +0000
@@ -0,0 +1,1227 @@
+/* $NetBSD: isp_target.c,v 1.1 2000/01/05 19:50:05 mjacob Exp $ */
+/*
+ * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters.
+ *
+ * Copyright (c) 1999 by Matthew Jacob
+ * All rights reserved.
+ * mjacob%feral.com@localhost
+ *
+ * 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 immediately at the beginning of the file, without modification,
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * Include header file appropriate for platform we're building on.
+ */
+
+#ifdef __NetBSD__
+#include <dev/ic/isp_netbsd.h>
+#endif
+#ifdef __FreeBSD__
+#include <dev/isp/isp_freebsd.h>
+#endif
+#ifdef __OpenBSD__
+#include <dev/ic/isp_openbsd.h>
+#endif
+#ifdef __linux__
+#include "isp_linux.h"
+#endif
+
+#ifdef ISP_TARGET_MODE
+int isp_tdebug = 0;
+
+static void isp_got_msg __P((struct ispsoftc *, int, in_entry_t *));
+static void isp_got_msg_fc __P((struct ispsoftc *, int, in_fcentry_t *));
+static void isp_notify_ack __P((struct ispsoftc *, void *));
+static void isp_handle_atio(struct ispsoftc *, at_entry_t *);
+static void isp_handle_atio2(struct ispsoftc *, at2_entry_t *);
+static void isp_handle_ctio(struct ispsoftc *, ct_entry_t *);
+static void isp_handle_ctio2(struct ispsoftc *, ct2_entry_t *);
+
+/*
+ * The Qlogic driver gets an interrupt to look at response queue entries.
+ * Some of these are status completions for initiatior mode commands, but
+ * if target mode is enabled, we get a whole wad of response queue entries
+ * to be handled here.
+ *
+ * Basically the split into 3 main groups: Lun Enable/Modification responses,
+ * SCSI Command processing, and Immediate Notification events.
+ *
+ * You start by writing a request queue entry to enable target mode (and
+ * establish some resource limitations which you can modify later).
+ * The f/w responds with a LUN ENABLE or LUN MODIFY response with
+ * the status of this action. If the enable was successful, you can expect...
+ *
+ * Response queue entries with SCSI commands encapsulate show up in an ATIO
+ * (Accept Target IO) type- sometimes with enough info to stop the command at
+ * this level. Ultimately the driver has to feed back to the f/w's request
+ * queue a sequence of CTIOs (continue target I/O) that describe data to
+ * be moved and/or status to be sent) and finally finishing with sending
+ * to the f/w's response queue an ATIO which then completes the handshake
+ * with the f/w for that command. There's a lot of variations on this theme,
+ * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel
+ * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic
+ * gist of it.
+ *
+ * The third group that can show up in the response queue are Immediate
+ * Notification events. These include things like notifications of SCSI bus
+ * resets, or Bus Device Reset messages or other messages received. This
+ * a classic oddbins area. It can get a little wierd because you then turn
+ * around and acknowledge the Immediate Notify by writing an entry onto the
+ * request queue and then the f/w turns around and gives you an acknowledgement
+ * to *your* acknowledgement on the response queue (the idea being to let
+ * the f/w tell you when the event is *really* over I guess).
+ *
+ */
+
+
+/*
+ * A new response queue entry has arrived. The interrupt service code
+ * has already swizzled it into the platform dependent from canonical form.
+ *
+ * Because of the way this driver is designed, unfortunately most of the
+ * actual synchronization work has to be done in the platform specific
+ * code- we have no synchroniation primitives in the common code.
+ */
+
+int
+isp_target_notify(isp, vptr, optrp)
+ struct ispsoftc *isp;
+ void *vptr;
+ u_int16_t *optrp;
+{
+ u_int16_t status, seqid;
+ union {
+ at_entry_t *atiop;
+ at2_entry_t *at2iop;
+ ct_entry_t *ctiop;
+ ct2_entry_t *ct2iop;
+ lun_entry_t *lunenp;
+ in_entry_t *inotp;
+ in_fcentry_t *inot_fcp;
+ na_entry_t *nackp;
+ na_fcentry_t *nack_fcp;
+ isphdr_t *hp;
+ void * *vp;
+#define atiop unp.atiop
+#define at2iop unp.at2iop
+#define ctiop unp.ctiop
+#define ct2iop unp.ct2iop
+#define lunenp unp.lunenp
+#define inotp unp.inotp
+#define inot_fcp unp.inot_fcp
+#define nackp unp.nackp
+#define nack_fcp unp.nack_fcp
+#define hdrp unp.hp
+ } unp;
+ int bus, rval = 0;
+
+ unp.vp = vptr;
+
+ ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr);
+
+ switch(hdrp->rqs_entry_type) {
+ case RQSTYPE_ATIO:
+ isp_handle_atio(isp, atiop);
+ break;
+ case RQSTYPE_CTIO:
+ isp_handle_ctio(isp, ctiop);
+ break;
+ case RQSTYPE_ATIO2:
+ isp_handle_atio2(isp, at2iop);
+ break;
+ case RQSTYPE_CTIO2:
+ isp_handle_ctio2(isp, ct2iop);
+ break;
+ case RQSTYPE_ENABLE_LUN:
+ case RQSTYPE_MODIFY_LUN:
+ (void) isp_async(isp, ISPASYNC_TARGET_ACTION, vptr);
+ break;
+
+ case RQSTYPE_NOTIFY:
+ /*
+ * Either the ISP received a SCSI message it can't
+ * handle, or it's returning an Immed. Notify entry
+ * we sent. We can send Immed. Notify entries to
+ * increment the firmware's resource count for them
+ * (we set this initially in the Enable Lun entry).
+ */
+ if (IS_FC(isp)) {
+ status = inot_fcp->in_status;
+ seqid = inot_fcp->in_seqid;
+ } else {
+ status = inotp->in_status & 0xff;
+ seqid = inotp->in_seqid;
+ }
+ bus = 0; /* XXX: Which Channel? */
+ ITDEBUG(2, ("isp_target_notify: Immediate Notify, "
+ "status=0x%x seqid=0x%x\n", status, seqid));
+ switch (status) {
+ case IN_RESET:
+ (void) isp_async(isp, ISPASYNC_BUS_RESET, &bus);
+ break;
+ case IN_MSG_RECEIVED:
+ case IN_IDE_RECEIVED:
+ if (IS_FC(isp)) {
+ isp_got_msg_fc(isp, bus, vptr);
+ } else {
+ isp_got_msg(isp, bus, vptr);
+ }
+ break;
+ case IN_RSRC_UNAVAIL:
+ PRINTF("%s: Firmware out of ATIOs\n", isp->isp_name);
+ break;
+ case IN_ABORT_TASK:
+ PRINTF("%s: Abort Task for Initiator %d RX_ID 0x%x\n",
+ isp->isp_name, inot_fcp->in_iid, seqid);
+ break;
+ case IN_PORT_LOGOUT:
+ PRINTF("%s: Port Logout for Initiator %d RX_ID 0x%x\n",
+ isp->isp_name, inot_fcp->in_iid, seqid);
+ break;
+ case IN_PORT_CHANGED:
+ PRINTF("%s: Port Changed for Initiator %d RX_ID 0x%x\n",
+ isp->isp_name, inot_fcp->in_iid, seqid);
+ break;
+ case IN_GLOBAL_LOGO:
+ PRINTF("%s: All ports logged out\n", isp->isp_name);
+ break;
+ default:
+ PRINTF("%s: bad status (0x%x) in isp_target_notify\n",
+ isp->isp_name, status);
+ break;
+ }
+ isp_notify_ack(isp, vptr);
+ break;
+
+ case RQSTYPE_NOTIFY_ACK:
+ /*
+ * The ISP is acknowledging our acknowledgement of an
+ * Immediate Notify entry for some asynchronous event.
+ */
+ if (IS_FC(isp)) {
+ ITDEBUG(2, ("%s: Notify Ack status=0x%x seqid 0x%x\n",
+ isp->isp_name, nack_fcp->na_status,
+ nack_fcp->na_seqid));
+ } else {
+ ITDEBUG(2, ("%s: Notify Ack event 0x%x status=0x%x "
+ "seqid 0x%x\n", isp->isp_name, nackp->na_event,
+ nackp->na_status, nackp->na_seqid));
+ }
+ break;
+ default:
+ PRINTF("%s: Unknown entry type 0x%x in isp_target_notify",
+ isp->isp_name, hdrp->rqs_entry_type);
+ rval = -1;
+ break;
+ }
+#undef atiop
+#undef at2iop
+#undef ctiop
+#undef ct2iop
+#undef lunenp
+#undef inotp
+#undef inot_fcp
+#undef nackp
+#undef nack_fcp
+#undef hdrp
+ return (rval);
+}
+
+
+/*
+ * Toggle (on/off) target mode for bus/target/lun
+ *
+ * The caller has checked for overlap and legality.
+ *
+ * Note that not all of bus, target or lun can be paid attention to.
+ * Note also that this action will not be complete until the f/w writes
+ * response entry. The caller is responsible for synchronizing this.
+ */
+int
+isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque)
+ struct ispsoftc *isp;
+ int cmd;
+ int bus;
+ int tgt;
+ int lun;
+ u_int32_t opaque;
+{
+ lun_entry_t el;
+ u_int16_t iptr, optr;
+ void *outp;
+
+ bus = bus; /* XXX */
+
+ MEMZERO(&el, sizeof (el));
+ el.le_cmd_count = DFLT_CMD_CNT;
+ el.le_in_count = DFLT_INOTIFY;
+ if (cmd == RQSTYPE_ENABLE_LUN) {
+ if (IS_SCSI(isp)) {
+ el.le_flags = LUN_TQAE;
+ el.le_cdb6len = 12;
+ el.le_cdb7len = 12;
+ }
+ } else if (cmd == -RQSTYPE_ENABLE_LUN) {
+ cmd = RQSTYPE_ENABLE_LUN;
+ el.le_cmd_count = 0;
+ el.le_in_count = 0;
+ } else if (cmd == -RQSTYPE_MODIFY_LUN) {
+ cmd = RQSTYPE_MODIFY_LUN;
+ el.le_ops = LUN_CCDECR | LUN_INDECR;
+ } else {
+ el.le_ops = LUN_CCINCR | LUN_ININCR;
+ }
+ el.le_header.rqs_entry_type = cmd;
Home |
Main Index |
Thread Index |
Old Index