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