summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2009-08-01 01:04:26 +0000
committermjacob <mjacob@FreeBSD.org>2009-08-01 01:04:26 +0000
commit2d4b24984c5d2ea2556ae2b1ef1df7f0833dc1b5 (patch)
tree884359c5bdd547b6c49dd87022ae80caeb753792 /sys
parent8cd95c9b5850387fecf5b9901ef05d9c08489a4c (diff)
downloadFreeBSD-src-2d4b24984c5d2ea2556ae2b1ef1df7f0833dc1b5.zip
FreeBSD-src-2d4b24984c5d2ea2556ae2b1ef1df7f0833dc1b5.tar.gz
Add 8Gb support (isp_2500). Fix a fair number of configuration and
firmware loading bugs. Target mode support has received some serious attention to make it more usable and stable. Some backward compatible additions to CAM have been made that make target mode async events easier to deal with have also been put into place. Further refinement and better support for NP-IV (N-port Virtualization) is now in place. Code for release prior to RELENG_7 has been stripped away for code clarity. Sponsored by: Copan Systems Reviewed by: scottl, ken, jung-uk kim Approved by: re
Diffstat (limited to 'sys')
-rw-r--r--sys/cam/cam_ccb.h102
-rw-r--r--sys/cam/cam_xpt.c4
-rw-r--r--sys/dev/isp/isp.c4087
-rw-r--r--sys/dev/isp/isp_freebsd.c5481
-rw-r--r--sys/dev/isp/isp_freebsd.h462
-rw-r--r--sys/dev/isp/isp_ioctl.h44
-rw-r--r--sys/dev/isp/isp_library.c2308
-rw-r--r--sys/dev/isp/isp_library.h373
-rw-r--r--sys/dev/isp/isp_pci.c1945
-rw-r--r--sys/dev/isp/isp_sbus.c248
-rw-r--r--sys/dev/isp/isp_stds.h20
-rw-r--r--sys/dev/isp/isp_target.c947
-rw-r--r--sys/dev/isp/isp_target.h959
-rw-r--r--sys/dev/isp/ispmbox.h1202
-rw-r--r--sys/dev/isp/ispreg.h25
-rw-r--r--sys/dev/isp/ispvar.h526
16 files changed, 10591 insertions, 8142 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 5f10cc6..61a57e3 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -173,6 +173,15 @@ typedef enum {
XPT_ATA_IO = 0x18 | XPT_FC_DEV_QUEUED,
/* Execute the requested ATA I/O operation */
+ XPT_GET_SIM_KNOB = 0x18,
+ /*
+ * Get SIM specific knob values.
+ */
+
+ XPT_SET_SIM_KNOB = 0x19,
+ /*
+ * Set SIM specific knob values.
+ */
/* HBA engine commands 0x20->0x2F */
XPT_ENG_INQ = 0x20 | XPT_FC_XPT_ONLY,
/* HBA engine feature inquiry */
@@ -189,8 +198,12 @@ typedef enum {
XPT_CONT_TARGET_IO = 0x33 | XPT_FC_DEV_QUEUED,
/* Continue Host Target I/O Connection */
XPT_IMMED_NOTIFY = 0x34 | XPT_FC_QUEUED | XPT_FC_USER_CCB,
- /* Notify Host Target driver of event */
+ /* Notify Host Target driver of event (obsolete) */
XPT_NOTIFY_ACK = 0x35,
+ /* Acknowledgement of event (obsolete) */
+ XPT_IMMEDIATE_NOTIFY = 0x36 | XPT_FC_QUEUED | XPT_FC_USER_CCB,
+ /* Notify Host Target driver of event */
+ XPT_NOTIFY_ACKNOWLEDGE = 0x37 | XPT_FC_QUEUED | XPT_FC_USER_CCB,
/* Acknowledgement of event */
/* Vendor Unique codes: 0x80->0x8F */
@@ -531,12 +544,14 @@ typedef enum {
struct ccb_pathinq_settings_spi {
u_int8_t ppr_options;
};
+
struct ccb_pathinq_settings_fc {
u_int64_t wwnn; /* world wide node name */
u_int64_t wwpn; /* world wide port name */
u_int32_t port; /* 24 bit port id, if known */
u_int32_t bitrate; /* Mbps */
};
+
struct ccb_pathinq_settings_sas {
u_int32_t bitrate; /* Mbps */
};
@@ -678,6 +693,7 @@ struct ccb_relsim {
* Definitions for the asynchronous callback CCB fields.
*/
typedef enum {
+ AC_CONTRACT = 0x1000,/* A contractual callback */
AC_GETDEV_CHANGED = 0x800,/* Getdev info might have changed */
AC_INQ_CHANGED = 0x400,/* Inquiry info might have changed */
AC_TRANSFER_NEG = 0x200,/* New transfer settings in effect */
@@ -694,6 +710,26 @@ typedef enum {
typedef void ac_callback_t (void *softc, u_int32_t code,
struct cam_path *path, void *args);
+/*
+ * Generic Asynchronous callbacks.
+ *
+ * Generic arguments passed bac which are then interpreted between a per-system
+ * contract number.
+ */
+#define AC_CONTRACT_DATA_MAX (128 - sizeof (u_int64_t))
+struct ac_contract {
+ u_int64_t contract_number;
+ u_int8_t contract_data[AC_CONTRACT_DATA_MAX];
+};
+
+#define AC_CONTRACT_DEV_CHG 1
+struct ac_device_changed {
+ u_int64_t wwpn;
+ u_int32_t port;
+ target_id_t target;
+ u_int8_t arrived;
+};
+
/* Set Asynchronous Callback CCB */
struct ccb_setasync {
struct ccb_hdr ccb_h;
@@ -823,6 +859,50 @@ struct ccb_calc_geometry {
};
/*
+ * Set or get SIM (and transport) specific knobs
+ */
+
+#define KNOB_VALID_ADDRESS 0x1
+#define KNOB_VALID_ROLE 0x2
+
+
+#define KNOB_ROLE_NONE 0x0
+#define KNOB_ROLE_INITIATOR 0x1
+#define KNOB_ROLE_TARGET 0x2
+#define KNOB_ROLE_BOTH 0x3
+
+struct ccb_sim_knob_settings_spi {
+ u_int valid;
+ u_int initiator_id;
+ u_int role;
+};
+
+struct ccb_sim_knob_settings_fc {
+ u_int valid;
+ u_int64_t wwnn; /* world wide node name */
+ u_int64_t wwpn; /* world wide port name */
+ u_int role;
+};
+
+struct ccb_sim_knob_settings_sas {
+ u_int valid;
+ u_int64_t wwnn; /* world wide node name */
+ u_int role;
+};
+#define KNOB_SETTINGS_SIZE 128
+
+struct ccb_sim_knob {
+ struct ccb_hdr ccb_h;
+ union {
+ u_int valid; /* Which fields to honor */
+ struct ccb_sim_knob_settings_spi spi;
+ struct ccb_sim_knob_settings_fc fc;
+ struct ccb_sim_knob_settings_sas sas;
+ char pad[KNOB_SETTINGS_SIZE];
+ } xport_specific;
+};
+
+/*
* Rescan the given bus, or bus/target/lun
*/
struct ccb_rescan {
@@ -847,6 +927,7 @@ struct ccb_en_lun {
u_int8_t enable;
};
+/* old, barely used immediate notify, binary compatibility */
struct ccb_immed_notify {
struct ccb_hdr ccb_h;
struct scsi_sense_data sense_data;
@@ -861,6 +942,22 @@ struct ccb_notify_ack {
u_int8_t event; /* Event flags */
};
+struct ccb_immediate_notify {
+ struct ccb_hdr ccb_h;
+ u_int tag_id; /* Tag for immediate notify */
+ u_int seq_id; /* Tag for target of notify */
+ u_int initiator_id; /* Initiator Identifier */
+ u_int arg; /* Function specific */
+};
+
+struct ccb_notify_acknowledge {
+ struct ccb_hdr ccb_h;
+ u_int tag_id; /* Tag for immediate notify */
+ u_int seq_id; /* Tar for target of notify */
+ u_int initiator_id; /* Initiator Identifier */
+ u_int arg; /* Function specific */
+};
+
/* HBA engine structures. */
typedef enum {
@@ -935,6 +1032,7 @@ union ccb {
struct ccb_dev_match cdm;
struct ccb_trans_settings cts;
struct ccb_calc_geometry ccg;
+ struct ccb_sim_knob knob;
struct ccb_abort cab;
struct ccb_resetbus crb;
struct ccb_resetdev crd;
@@ -944,6 +1042,8 @@ union ccb {
struct ccb_en_lun cel;
struct ccb_immed_notify cin;
struct ccb_notify_ack cna;
+ struct ccb_immediate_notify cin1;
+ struct ccb_notify_acknowledge cna2;
struct ccb_eng_inq cei;
struct ccb_eng_exec cee;
struct ccb_rescan crcn;
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index fe759e9..ea25966 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -2565,6 +2565,10 @@ xpt_action_default(union ccb *start_ccb)
case XPT_IMMED_NOTIFY:
case XPT_NOTIFY_ACK:
case XPT_RESET_BUS:
+ case XPT_IMMEDIATE_NOTIFY:
+ case XPT_NOTIFY_ACKNOWLEDGE:
+ case XPT_GET_SIM_KNOB:
+ case XPT_SET_SIM_KNOB:
{
struct cam_sim *sim;
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 1ad4e91..a4a40a8 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -1,17 +1,17 @@
/*-
- * Copyright (c) 1997-2007 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
- *
+ *
* 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.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY 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
@@ -23,6 +23,7 @@
* 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.
+ *
*/
/*
@@ -64,51 +65,52 @@ __FBSDID("$FreeBSD$");
*/
#define MBOX_DELAY_COUNT 1000000 / 100
-#define ISP_MARK_PORTDB(a, b) \
- isp_prt(isp, ISP_LOGSANCFG, "line %d: markportdb", __LINE__); \
- isp_mark_portdb(a, b)
+#define ISP_MARK_PORTDB(a, b, c) \
+ isp_prt(isp, ISP_LOGSANCFG, \
+ "Chan %d ISP_MARK_PORTDB@LINE %d", b, __LINE__); \
+ isp_mark_portdb(a, b, c)
/*
* Local static data
*/
-static const char fconf[] =
- "PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n"
- " database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)";
-static const char notresp[] =
- "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
-static const char xact1[] =
- "HBA attempted queued transaction with disconnect not set for %d.%d.%d";
-static const char xact2[] =
- "HBA attempted queued transaction to target routine %d on target %d bus %d";
-static const char xact3[] =
- "HBA attempted queued cmd for %d.%d.%d when queueing disabled";
-static const char pskip[] =
- "SCSI phase skipped for target %d.%d.%d";
-static const char topology[] =
- "HBA PortID 0x%06x N-Port Handle %d, Connection Topology '%s'";
-static const char ourwwn[] =
- "HBA WWNN 0x%08x%08x HBA WWPN 0x%08x%08x";
-static const char finmsg[] =
- "%d.%d.%d: FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x";
-static const char sc0[] =
- "%s CHAN %d FTHRSH %d IID %d RESETD %d RETRYC %d RETRYD %d ASD 0x%x";
-static const char sc1[] =
- "%s RAAN 0x%x DLAN 0x%x DDMAB 0x%x CDMAB 0x%x SELTIME %d MQD %d";
-static const char sc2[] = "%s CHAN %d TGT %d FLAGS 0x%x 0x%x/0x%x";
-static const char sc3[] = "Generated";
+static const char fconf[] = "Chan %d PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)";
+static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
+static const char xact1[] = "HBA attempted queued transaction with disconnect not set for %d.%d.%d";
+static const char xact2[] = "HBA attempted queued transaction to target routine %d on target %d bus %d";
+static const char xact3[] = "HBA attempted queued cmd for %d.%d.%d when queueing disabled";
+static const char pskip[] = "SCSI phase skipped for target %d.%d.%d";
+static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x N-Port Handle %d, Connection '%s'";
+static const char finmsg[] = "%d.%d.%d: FIN dl%d resid %ld STS 0x%x SKEY %c XS_ERR=0x%x";
static const char sc4[] = "NVRAM";
-static const char bun[] =
- "bad underrun for %d.%d (count %d, resid %d, status %s)";
+static const char bun[] = "bad underrun for %d.%d (count %d, resid %d, status %s)";
+static const char lipd[] = "Chan %d LIP destroyed %d active commands";
+static const char sacq[] = "unable to acquire scratch area";
+
+static const uint8_t alpa_map[] = {
+ 0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda,
+ 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
+ 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5,
+ 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
+ 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
+ 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
+ 0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81,
+ 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
+ 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69,
+ 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
+ 0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c,
+ 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
+ 0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
+ 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
+ 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
+ 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
+};
/*
* Local function prototypes.
*/
static int isp_parse_async(ispsoftc_t *, uint16_t);
-static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *,
- uint32_t *);
-static void
-isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *);
-static void
+static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, uint32_t *);
+static void isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *); static void
isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *);
static void isp_fastpost_complete(ispsoftc_t *, uint16_t);
static int isp_mbox_continue(ispsoftc_t *);
@@ -116,39 +118,37 @@ static void isp_scsi_init(ispsoftc_t *);
static void isp_scsi_channel_init(ispsoftc_t *, int);
static void isp_fibre_init(ispsoftc_t *);
static void isp_fibre_init_2400(ispsoftc_t *);
-static void isp_mark_portdb(ispsoftc_t *, int);
-static int isp_plogx(ispsoftc_t *, uint16_t, uint32_t, int, int);
+static void isp_mark_portdb(ispsoftc_t *, int, int);
+static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int, int);
static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t);
static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t);
-static int isp_getpdb(ispsoftc_t *, uint16_t, isp_pdb_t *, int);
-static uint64_t isp_get_portname(ispsoftc_t *, int, int);
-static int isp_fclink_test(ispsoftc_t *, int);
-static const char *ispfc_fw_statename(int);
-static int isp_pdb_sync(ispsoftc_t *);
-static int isp_scan_loop(ispsoftc_t *);
-static int isp_gid_ft_sns(ispsoftc_t *);
-static int isp_gid_ft_ct_passthru(ispsoftc_t *);
-static int isp_scan_fabric(ispsoftc_t *);
-static int isp_login_device(ispsoftc_t *, uint32_t, isp_pdb_t *, uint16_t *);
-static int isp_register_fc4_type(ispsoftc_t *);
-static int isp_register_fc4_type_24xx(ispsoftc_t *);
-static uint16_t isp_nxt_handle(ispsoftc_t *, uint16_t);
-static void isp_fw_state(ispsoftc_t *);
+static int isp_getpdb(ispsoftc_t *, int, uint16_t, isp_pdb_t *, int);
+static void isp_dump_chip_portdb(ispsoftc_t *, int, int);
+static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
+static int isp_fclink_test(ispsoftc_t *, int, int);
+static int isp_pdb_sync(ispsoftc_t *, int);
+static int isp_scan_loop(ispsoftc_t *, int);
+static int isp_gid_ft_sns(ispsoftc_t *, int);
+static int isp_gid_ft_ct_passthru(ispsoftc_t *, int);
+static int isp_scan_fabric(ispsoftc_t *, int);
+static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *);
+static int isp_register_fc4_type(ispsoftc_t *, int);
+static int isp_register_fc4_type_24xx(ispsoftc_t *, int);
+static uint16_t isp_nxt_handle(ispsoftc_t *, int, uint16_t);
+static void isp_fw_state(ispsoftc_t *, int);
static void isp_mboxcmd_qnw(ispsoftc_t *, mbreg_t *, int);
static void isp_mboxcmd(ispsoftc_t *, mbreg_t *);
-static void isp_update(ispsoftc_t *);
-static void isp_update_bus(ispsoftc_t *, int);
-static void isp_setdfltparm(ispsoftc_t *, int);
-static void isp_setdfltfcparm(ispsoftc_t *);
-static int isp_read_nvram(ispsoftc_t *);
-static int isp_read_nvram_2400(ispsoftc_t *);
+static void isp_spi_update(ispsoftc_t *, int);
+static void isp_setdfltsdparm(ispsoftc_t *);
+static void isp_setdfltfcparm(ispsoftc_t *, int);
+static int isp_read_nvram(ispsoftc_t *, int);
+static int isp_read_nvram_2400(ispsoftc_t *, uint8_t *);
static void isp_rdnvram_word(ispsoftc_t *, int, uint16_t *);
static void isp_rd_2400_nvram(ispsoftc_t *, uint32_t, uint32_t *);
static void isp_parse_nvram_1020(ispsoftc_t *, uint8_t *);
static void isp_parse_nvram_1080(ispsoftc_t *, int, uint8_t *);
static void isp_parse_nvram_12160(ispsoftc_t *, int, uint8_t *);
-static void isp_fix_nvram_wwns(ispsoftc_t *);
static void isp_parse_nvram_2100(ispsoftc_t *, uint8_t *);
static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
@@ -161,15 +161,20 @@ static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
*/
void
-isp_reset(ispsoftc_t *isp)
+isp_reset(ispsoftc_t *isp, int do_load_defaults)
{
mbreg_t mbs;
uint32_t code_org, val;
int loops, i, dodnld = 1;
- static const char *btype = "????";
+ const char *btype = "????";
static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
isp->isp_state = ISP_NILSTATE;
+ if (isp->isp_dead) {
+ isp_shutdown(isp);
+ ISP_DISABLE_INTS(isp);
+ return;
+ }
/*
* Basic types (SCSI, FibreChannel and PCI or SBus)
@@ -181,51 +186,6 @@ isp_reset(ispsoftc_t *isp)
* for SCSI adapters and do other settings for the 2100.
*/
- /*
- * Get the current running firmware revision out of the
- * chip before we hit it over the head (if this is our
- * first time through). Note that we store this as the
- * 'ROM' firmware revision- which it may not be. In any
- * case, we don't really use this yet, but we may in
- * the future.
- */
- if (isp->isp_touched == 0) {
- /*
- * First see whether or not we're sitting in the ISP PROM.
- * If we've just been reset, we'll have the string "ISP "
- * spread through outgoing mailbox registers 1-3. We do
- * this for PCI cards because otherwise we really don't
- * know what state the card is in and we could hang if
- * we try this command otherwise.
- *
- * For SBus cards, we just do this because they almost
- * certainly will be running firmware by now.
- */
- if (ISP_READ(isp, OUTMAILBOX1) != 0x4953 ||
- ISP_READ(isp, OUTMAILBOX2) != 0x5020 ||
- ISP_READ(isp, OUTMAILBOX3) != 0x2020) {
- /*
- * Just in case it was paused...
- */
- if (IS_24XX(isp)) {
- ISP_WRITE(isp, BIU2400_HCCR,
- HCCR_2400_CMD_RELEASE);
- } else {
- ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
- }
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_ABOUT_FIRMWARE;
- mbs.logval = MBLOGNONE;
- isp_mboxcmd(isp, &mbs);
- if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
- isp->isp_romfw_rev[0] = mbs.param[1];
- isp->isp_romfw_rev[1] = mbs.param[2];
- isp->isp_romfw_rev[2] = mbs.param[3];
- }
- }
- isp->isp_touched = 1;
- }
-
ISP_DISABLE_INTS(isp);
/*
@@ -244,17 +204,16 @@ isp_reset(ispsoftc_t *isp)
}
/*
- * Set up DMA for the request and result queues.
+ * Set up DMA for the request and response queues.
*
* We do this now so we can use the request queue
- * for a dma
+ * for dma to load firmware from.
*/
if (ISP_MBOXDMASETUP(isp) != 0) {
isp_prt(isp, ISP_LOGERR, "Cannot setup DMA");
return;
}
-
/*
* Set up default request/response queue in-pointer/out-pointer
* register indices.
@@ -264,8 +223,6 @@ isp_reset(ispsoftc_t *isp)
isp->isp_rqstoutrp = BIU2400_REQOUTP;
isp->isp_respinrp = BIU2400_RSPINP;
isp->isp_respoutrp = BIU2400_RSPOUTP;
- isp->isp_atioinrp = BIU2400_ATIO_RSPINP;
- isp->isp_atiooutrp = BIU2400_ATIO_REQINP;
} else if (IS_23XX(isp)) {
isp->isp_rqstinrp = BIU_REQINP;
isp->isp_rqstoutrp = BIU_REQOUTP;
@@ -310,6 +267,9 @@ isp_reset(ispsoftc_t *isp)
case ISP_HA_FC_2400:
btype = "2422";
break;
+ case ISP_HA_FC_2500:
+ btype = "2532";
+ break;
default:
break;
}
@@ -326,11 +286,13 @@ isp_reset(ispsoftc_t *isp)
ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
}
} else if (IS_1240(isp)) {
- sdparam *sdp = isp->isp_param;
+ sdparam *sdp;
+
btype = "1240";
isp->isp_clock = 60;
+ sdp = SDPARAM(isp, 0);
sdp->isp_ultramode = 1;
- sdp++;
+ sdp = SDPARAM(isp, 1);
sdp->isp_ultramode = 1;
/*
* XXX: Should probably do some bus sensing.
@@ -355,7 +317,7 @@ isp_reset(ispsoftc_t *isp)
} else if (IS_ULTRA2(isp)) {
static const char m[] = "bus %d is in %s Mode";
uint16_t l;
- sdparam *sdp = isp->isp_param;
+ sdparam *sdp = SDPARAM(isp, 0);
isp->isp_clock = 100;
@@ -387,10 +349,10 @@ isp_reset(ispsoftc_t *isp)
}
if (IS_DUALBUS(isp)) {
- sdp++;
+ sdp = SDPARAM(isp, 1);
l = ISP_READ(isp, SXP_PINS_DIFF|SXP_BANK1_SELECT);
l &= ISP1080_MODE_MASK;
- switch(l) {
+ switch (l) {
case ISP1080_LVD_MODE:
sdp->isp_lvdmode = 1;
isp_prt(isp, ISP_LOGCONFIG, m, 1, "LVD");
@@ -412,7 +374,7 @@ isp_reset(ispsoftc_t *isp)
}
}
} else {
- sdparam *sdp = isp->isp_param;
+ sdparam *sdp = SDPARAM(isp, 0);
i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK;
switch (i) {
default:
@@ -509,7 +471,7 @@ isp_reset(ispsoftc_t *isp)
/*
* Hit the chip over the head with hammer,
- * and give the ISP a chance to recover.
+ * and give it a chance to recover.
*/
if (IS_SCSI(isp)) {
@@ -517,15 +479,13 @@ isp_reset(ispsoftc_t *isp)
/*
* A slight delay...
*/
- USEC_DELAY(100);
+ ISP_DELAY(100);
/*
* Clear data && control DMA engines.
*/
- ISP_WRITE(isp, CDMA_CONTROL,
- DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
- ISP_WRITE(isp, DDMA_CONTROL,
- DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
+ ISP_WRITE(isp, CDMA_CONTROL, DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
+ ISP_WRITE(isp, DDMA_CONTROL, DMA_CNTRL_CLEAR_CHAN | DMA_CNTRL_RESET_INT);
} else if (IS_24XX(isp)) {
@@ -534,12 +494,12 @@ isp_reset(ispsoftc_t *isp)
*/
ISP_WRITE(isp, BIU2400_CSR, BIU2400_DMA_STOP|(3 << 4));
for (val = loops = 0; loops < 30000; loops++) {
- USEC_DELAY(10);
+ ISP_DELAY(10);
val = ISP_READ(isp, BIU2400_CSR);
if ((val & BIU2400_DMA_ACTIVE) == 0) {
break;
}
- }
+ }
if (val & BIU2400_DMA_ACTIVE) {
ISP_RESET0(isp);
isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset");
@@ -548,11 +508,10 @@ isp_reset(ispsoftc_t *isp)
/*
* Hold it in SOFT_RESET and STOP state for 100us.
*/
- ISP_WRITE(isp, BIU2400_CSR,
- BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
- USEC_DELAY(100);
+ ISP_WRITE(isp, BIU2400_CSR, BIU2400_SOFT_RESET|BIU2400_DMA_STOP|(3 << 4));
+ ISP_DELAY(100);
for (loops = 0; loops < 10000; loops++) {
- USEC_DELAY(5);
+ ISP_DELAY(5);
val = ISP_READ(isp, OUTMAILBOX0);
}
for (val = loops = 0; loops < 500000; loops ++) {
@@ -571,17 +530,14 @@ isp_reset(ispsoftc_t *isp)
/*
* A slight delay...
*/
- USEC_DELAY(100);
+ ISP_DELAY(100);
/*
* Clear data && control DMA engines.
*/
- ISP_WRITE(isp, CDMA2100_CONTROL,
- DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
- ISP_WRITE(isp, TDMA2100_CONTROL,
- DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
- ISP_WRITE(isp, RDMA2100_CONTROL,
- DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
+ ISP_WRITE(isp, CDMA2100_CONTROL, DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
+ ISP_WRITE(isp, TDMA2100_CONTROL, DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
+ ISP_WRITE(isp, RDMA2100_CONTROL, DMA_CNTRL2100_CLEAR_CHAN | DMA_CNTRL2100_RESET_INT);
}
/*
@@ -601,7 +557,7 @@ isp_reset(ispsoftc_t *isp)
if (!(ISP_READ(isp, BIU2100_CSR) & BIU2100_SOFT_RESET))
break;
}
- USEC_DELAY(100);
+ ISP_DELAY(100);
if (--loops < 0) {
ISP_DUMPREGS(isp, "chip reset timed out");
ISP_RESET0(isp);
@@ -629,17 +585,16 @@ isp_reset(ispsoftc_t *isp)
ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RESET);
} else {
ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
- USEC_DELAY(100);
+ ISP_DELAY(100);
ISP_WRITE(isp, BIU_SEMA, 0);
}
-
/*
* Post-RISC Reset stuff.
*/
if (IS_24XX(isp)) {
for (val = loops = 0; loops < 5000000; loops++) {
- USEC_DELAY(5);
+ ISP_DELAY(5);
val = ISP_READ(isp, OUTMAILBOX0);
if (val == 0) {
break;
@@ -663,8 +618,8 @@ isp_reset(ispsoftc_t *isp)
ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST);
ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST);
}
- if (SDPARAM(isp)->isp_ptisp) {
- if (SDPARAM(isp)->isp_ultramode) {
+ if (SDPARAM(isp, 0)->isp_ptisp) {
+ if (SDPARAM(isp, 0)->isp_ultramode) {
while (ISP_READ(isp, RISC_MTR) != 0x1313) {
ISP_WRITE(isp, RISC_MTR, 0x1313);
ISP_WRITE(isp, HCCR, HCCR_CMD_STEP);
@@ -692,7 +647,12 @@ isp_reset(ispsoftc_t *isp)
ISP_WRITE(isp, isp->isp_rqstoutrp, 0);
ISP_WRITE(isp, isp->isp_respinrp, 0);
ISP_WRITE(isp, isp->isp_respoutrp, 0);
-
+ if (IS_24XX(isp)) {
+ ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
+ ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
+ ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
+ ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
+ }
/*
* Do MD specific post initialization
@@ -702,15 +662,15 @@ isp_reset(ispsoftc_t *isp)
/*
* Wait for everything to finish firing up.
*
- * Avoid doing this on the 2312 because you can generate a PCI
+ * Avoid doing this on early 2312s because you can generate a PCI
* parity error (chip breakage).
*/
- if (IS_2312(isp)) {
- USEC_DELAY(100);
+ if (IS_2312(isp) && isp->isp_revision < 2) {
+ ISP_DELAY(100);
} else {
loops = MBOX_DELAY_COUNT;
while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) {
- USEC_DELAY(100);
+ ISP_DELAY(100);
if (--loops < 0) {
ISP_RESET0(isp);
isp_prt(isp, ISP_LOGERR,
@@ -727,19 +687,25 @@ isp_reset(ispsoftc_t *isp)
*/
/*
- * Do some sanity checking.
+ * Do some sanity checking by running a NOP command.
+ * If it succeeds, the ROM firmware is now running.
*/
- MEMZERO(&mbs, sizeof (mbs));
+ ISP_MEMZERO(&mbs, sizeof (mbs));
mbs.param[0] = MBOX_NO_OP;
mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGERR, "NOP ommand failed (%x)", mbs.param[0]);
ISP_RESET0(isp);
return;
}
+ /*
+ * Do some operational tests
+ */
+
if (IS_SCSI(isp) || IS_24XX(isp)) {
- MEMZERO(&mbs, sizeof (mbs));
+ ISP_MEMZERO(&mbs, sizeof (mbs));
mbs.param[0] = MBOX_MAILBOX_REG_TEST;
mbs.param[1] = 0xdead;
mbs.param[2] = 0xbeef;
@@ -758,10 +724,7 @@ isp_reset(ispsoftc_t *isp)
mbs.param[3] != 0xffff || mbs.param[4] != 0x1111 ||
mbs.param[5] != 0xa5a5) {
ISP_RESET0(isp);
- isp_prt(isp, ISP_LOGERR,
- "Register Test Failed (0x%x 0x%x 0x%x 0x%x 0x%x)",
- mbs.param[1], mbs.param[2], mbs.param[3],
- mbs.param[4], mbs.param[5]);
+ isp_prt(isp, ISP_LOGERR, "Register Test Failed (0x%x 0x%x 0x%x 0x%x 0x%x)", mbs.param[1], mbs.param[2], mbs.param[3], mbs.param[4], mbs.param[5]);
return;
}
@@ -776,8 +739,7 @@ isp_reset(ispsoftc_t *isp)
* whether we have f/w at all and whether a config flag
* has disabled our download.
*/
- if ((isp->isp_mdvec->dv_ispfw == NULL) ||
- (isp->isp_confopts & ISP_CFG_NORELOAD)) {
+ if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) {
dodnld = 0;
}
@@ -793,13 +755,6 @@ isp_reset(ispsoftc_t *isp)
const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
/*
- * NB: Whatever you do do, do *not* issue the VERIFY FIRMWARE
- * NB: command to the 2400 while loading new firmware. This
- * NB: causes the new f/w to start and immediately crash back
- * NB: to the ROM.
- */
-
- /*
* Keep loading until we run out of f/w.
*/
code_org = ptr[2]; /* 1st load address is our start addr */
@@ -807,9 +762,7 @@ isp_reset(ispsoftc_t *isp)
for (;;) {
uint32_t la, wi, wl;
- isp_prt(isp, ISP_LOGDEBUG0,
- "load 0x%x words of code at load address 0x%x",
- ptr[3], ptr[2]);
+ isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], ptr[2]);
wi = 0;
la = ptr[2];
@@ -828,23 +781,31 @@ isp_reset(ispsoftc_t *isp)
ISP_IOXPUT_32(isp, ptr[wi++], &cp[i]);
wl--;
}
- MEMORYBARRIER(isp, SYNC_REQUEST,
- 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)));
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_LOAD_RISC_RAM;
- mbs.param[1] = la;
- mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
- mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
- mbs.param[4] = nw >> 16;
- mbs.param[5] = nw;
- mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
- mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
- mbs.param[8] = la >> 16;
+ MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)));
+ ISP_MEMZERO(&mbs, sizeof (mbs));
+ if (la < 0x10000 && nw < 0x10000) {
+ mbs.param[0] = MBOX_LOAD_RISC_RAM_2100;
+ mbs.param[1] = la;
+ mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
+ mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
+ mbs.param[4] = nw;
+ mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
+ mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
+ } else {
+ mbs.param[0] = MBOX_LOAD_RISC_RAM;
+ mbs.param[1] = la;
+ mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
+ mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
+ mbs.param[4] = nw >> 16;
+ mbs.param[5] = nw;
+ mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
+ mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
+ mbs.param[8] = la >> 16;
+ }
mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGERR,
- "F/W Risc Ram Load Failed");
+ isp_prt(isp, ISP_LOGERR, "F/W Risc Ram Load Failed");
ISP_RESET0(isp);
return;
}
@@ -855,7 +816,7 @@ isp_reset(ispsoftc_t *isp)
break;
}
ptr += ptr[3];
- }
+ }
isp->isp_loaded_fw = 1;
} else if (dodnld && IS_23XX(isp)) {
const uint16_t *ptr = isp->isp_mdvec->dv_ispfw;
@@ -868,17 +829,15 @@ isp_reset(ispsoftc_t *isp)
for (;;) {
uint32_t nxtaddr;
- isp_prt(isp, ISP_LOGDEBUG0,
- "load 0x%x words of code at load address 0x%x",
- ptr[3], la);
+ isp_prt(isp, ISP_LOGDEBUG0, "load 0x%x words of code at load address 0x%x", ptr[3], la);
wi = 0;
wl = ptr[3];
while (wi < ptr[3]) {
uint16_t *cp;
- uint32_t nw;
-
+ uint16_t nw;
+
nw = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) >> 1;
if (nw > wl) {
nw = wl;
@@ -891,22 +850,30 @@ isp_reset(ispsoftc_t *isp)
ISP_IOXPUT_16(isp, ptr[wi++], &cp[i]);
wl--;
}
- MEMORYBARRIER(isp, SYNC_REQUEST,
- 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)));
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_LOAD_RISC_RAM;
- mbs.param[1] = la;
- mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
- mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
- mbs.param[4] = nw;
- mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
- mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
- mbs.param[8] = la >> 16;
+ MEMORYBARRIER(isp, SYNC_REQUEST, 0, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)));
+ ISP_MEMZERO(&mbs, sizeof (mbs));
+ if (la < 0x10000) {
+ mbs.param[0] = MBOX_LOAD_RISC_RAM_2100;
+ mbs.param[1] = la;
+ mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
+ mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
+ mbs.param[4] = nw;
+ mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
+ mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
+ } else {
+ mbs.param[0] = MBOX_LOAD_RISC_RAM;
+ mbs.param[1] = la;
+ mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
+ mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
+ mbs.param[4] = nw;
+ mbs.param[6] = DMA_WD3(isp->isp_rquest_dma);
+ mbs.param[7] = DMA_WD2(isp->isp_rquest_dma);
+ mbs.param[8] = la >> 16;
+ }
mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGERR,
- "F/W Risc Ram Load Failed");
+ isp_prt(isp, ISP_LOGERR, "F/W Risc Ram Load Failed");
ISP_RESET0(isp);
return;
}
@@ -914,19 +881,6 @@ isp_reset(ispsoftc_t *isp)
}
if (!IS_2322(isp)) {
- /*
- * Verify that it downloaded correctly.
- */
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_VERIFY_CHECKSUM;
- mbs.param[1] = code_org;
- mbs.logval = MBLOGNONE;
- isp_mboxcmd(isp, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGERR, dcrc);
- ISP_RESET0(isp);
- return;
- }
break;
}
@@ -951,41 +905,45 @@ isp_reset(ispsoftc_t *isp)
union {
const uint16_t *cp;
uint16_t *np;
- } u;
- u.cp = isp->isp_mdvec->dv_ispfw;
- isp->isp_mbxworkp = &u.np[1];
- isp->isp_mbxwrk0 = u.np[3] - 1;
+ } ucd;
+ ucd.cp = isp->isp_mdvec->dv_ispfw;
+ isp->isp_mbxworkp = &ucd.np[1];
+ isp->isp_mbxwrk0 = ucd.np[3] - 1;
isp->isp_mbxwrk1 = code_org + 1;
- MEMZERO(&mbs, sizeof (mbs));
+ ISP_MEMZERO(&mbs, sizeof (mbs));
mbs.param[0] = MBOX_WRITE_RAM_WORD;
mbs.param[1] = code_org;
- mbs.param[2] = u.np[0];
+ mbs.param[2] = ucd.np[0];
mbs.logval = MBLOGNONE;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGERR,
- "F/W download failed at word %d",
- isp->isp_mbxwrk1 - code_org);
+ isp_prt(isp, ISP_LOGERR, "F/W download failed at word %d", isp->isp_mbxwrk1 - code_org);
ISP_RESET0(isp);
return;
}
- /*
- * Verify that it downloaded correctly.
- */
- MEMZERO(&mbs, sizeof (mbs));
+ } else {
+ isp->isp_loaded_fw = 0;
+ isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
+ }
+
+ /*
+ * If we loaded firmware, verify its checksum
+ */
+ if (isp->isp_loaded_fw) {
+ ISP_MEMZERO(&mbs, sizeof (mbs));
mbs.param[0] = MBOX_VERIFY_CHECKSUM;
- mbs.param[1] = code_org;
- mbs.logval = MBLOGNONE;
+ if (IS_24XX(isp)) {
+ mbs.param[1] = code_org >> 16;
+ mbs.param[2] = code_org;
+ } else {
+ mbs.param[1] = code_org;
+ }
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
isp_prt(isp, ISP_LOGERR, dcrc);
ISP_RESET0(isp);
return;
}
- isp->isp_loaded_fw = 1;
- } else {
- isp->isp_loaded_fw = 0;
- isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
}
/*
@@ -996,9 +954,7 @@ isp_reset(ispsoftc_t *isp)
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.timeout = 1000000;
- mbs.param[0] = MBOX_EXEC_FIRMWARE;
+ MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 1000000);
if (IS_24XX(isp)) {
mbs.param[1] = code_org >> 16;
mbs.param[2] = code_org;
@@ -1007,6 +963,9 @@ isp_reset(ispsoftc_t *isp)
} else {
mbs.param[3] = 1;
}
+ if (IS_25XX(isp)) {
+ mbs.ibits |= 0x10;
+ }
} else if (IS_2322(isp)) {
mbs.param[1] = code_org;
if (isp->isp_loaded_fw) {
@@ -1017,8 +976,6 @@ isp_reset(ispsoftc_t *isp)
} else {
mbs.param[1] = code_org;
}
-
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (IS_2322(isp) || IS_24XX(isp)) {
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
@@ -1029,37 +986,45 @@ isp_reset(ispsoftc_t *isp)
/*
* Give it a chance to finish starting up.
+ * Give the 24XX more time.
*/
- USEC_DELAY(250000);
-
- if (IS_SCSI(isp)) {
+ if (IS_24XX(isp)) {
+ ISP_DELAY(500000);
/*
- * Set CLOCK RATE, but only if asked to.
+ * Check to see if the 24XX firmware really started.
*/
- if (isp->isp_clock) {
- mbs.param[0] = MBOX_SET_CLOCK_RATE;
- mbs.param[1] = isp->isp_clock;
- mbs.logval = MBLOGNONE;
- isp_mboxcmd(isp, &mbs);
- /* we will try not to care if this fails */
+ if (mbs.param[1] == 0xdead) {
+ isp_prt(isp, ISP_LOGERR, "f/w didn't *really* start");
+ ISP_RESET0(isp);
+ return;
+ }
+ } else {
+ ISP_DELAY(250000);
+ if (IS_SCSI(isp)) {
+ /*
+ * Set CLOCK RATE, but only if asked to.
+ */
+ if (isp->isp_clock) {
+ mbs.param[0] = MBOX_SET_CLOCK_RATE;
+ mbs.param[1] = isp->isp_clock;
+ mbs.logval = MBLOGNONE;
+ isp_mboxcmd(isp, &mbs);
+ /* we will try not to care if this fails */
+ }
}
}
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_ABOUT_FIRMWARE;
- mbs.logval = MBLOGALL;
+ /*
+ * Ask the chip for the current firmware version.
+ * This should prove that the new firmware is working.
+ */
+ MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 0);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
ISP_RESET0(isp);
return;
}
- if (IS_24XX(isp) && mbs.param[1] == 0xdead) {
- isp_prt(isp, ISP_LOGERR, "f/w didn't *really* start");
- ISP_RESET0(isp);
- return;
- }
-
/*
* The SBus firmware that we are using apparently does not return
* major, minor, micro revisions in the mailbox registers, which
@@ -1075,17 +1040,15 @@ isp_reset(ispsoftc_t *isp)
isp->isp_fwrev[1] = 37;
#endif
isp->isp_fwrev[2] = 0;
- }
+ }
} else {
isp->isp_fwrev[0] = mbs.param[1];
isp->isp_fwrev[1] = mbs.param[2];
isp->isp_fwrev[2] = mbs.param[3];
}
- isp_prt(isp, ISP_LOGALL,
- "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
- btype, isp->isp_revision, dodnld? "loaded" : "resident",
- isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
+ isp_prt(isp, ISP_LOGCONFIG, "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
+ btype, isp->isp_revision, dodnld? "loaded" : "resident", isp->isp_fwrev[0], isp->isp_fwrev[1], isp->isp_fwrev[2]);
if (IS_FC(isp)) {
/*
@@ -1097,50 +1060,24 @@ isp_reset(ispsoftc_t *isp)
*/
if ((ISP_FW_OLDER_THAN(isp, 1, 17, 1))) {
#ifdef USE_SMALLER_2100_FIRMWARE
- FCPARAM(isp)->isp_fwattr = ISP_FW_ATTR_SCCLUN;
+ isp->isp_fwattr = ISP_FW_ATTR_SCCLUN;
#else
- FCPARAM(isp)->isp_fwattr = 0;
+ isp->isp_fwattr = 0;
#endif
} else {
- FCPARAM(isp)->isp_fwattr = mbs.param[6];
- isp_prt(isp, ISP_LOGDEBUG0,
- "Firmware Attributes = 0x%x", mbs.param[6]);
+ isp->isp_fwattr = mbs.param[6];
+ isp_prt(isp, ISP_LOGDEBUG0, "Firmware Attributes = 0x%x", mbs.param[6]);
}
- FCPARAM(isp)->isp_2klogin = 0;
- FCPARAM(isp)->isp_sccfw = 0;
- FCPARAM(isp)->isp_tmode = 0;
- if (IS_24XX(isp)) {
- FCPARAM(isp)->isp_2klogin = 1;
- FCPARAM(isp)->isp_sccfw = 1;
- FCPARAM(isp)->isp_tmode = 1;
- } else {
- if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
- FCPARAM(isp)->isp_sccfw = 1;
- }
- if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_2KLOGINS) {
- FCPARAM(isp)->isp_2klogin = 1;
- FCPARAM(isp)->isp_sccfw = 1;
- }
- if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_TMODE) {
- FCPARAM(isp)->isp_tmode = 1;
- }
- }
- if (FCPARAM(isp)->isp_2klogin) {
- isp_prt(isp, ISP_LOGCONFIG, "2K Logins Supported");
- }
- }
-
- if (isp->isp_romfw_rev[0] || isp->isp_romfw_rev[1] ||
- isp->isp_romfw_rev[2]) {
- isp_prt(isp, ISP_LOGCONFIG, "Last F/W revision was %d.%d.%d",
- isp->isp_romfw_rev[0], isp->isp_romfw_rev[1],
- isp->isp_romfw_rev[2]);
+ } else {
+#ifndef ISP_TARGET_MODE
+ isp->isp_fwattr = ISP_FW_ATTR_TMODE;
+#else
+ isp->isp_fwattr = 0;
+#endif
}
if (!IS_24XX(isp)) {
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_GET_FIRMWARE_STATUS;
- mbs.logval = MBLOGALL;
+ MBSINIT(&mbs, MBOX_GET_FIRMWARE_STATUS, MBLOGALL, 0);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
ISP_RESET0(isp);
@@ -1150,9 +1087,26 @@ isp_reset(ispsoftc_t *isp)
isp->isp_maxcmds = mbs.param[2];
}
}
- isp_prt(isp, ISP_LOGCONFIG,
- "%d max I/O command limit set", isp->isp_maxcmds);
- isp_fw_state(isp);
+ isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds);
+
+ /*
+ * If we don't have Multi-ID f/w loaded, we need to restrict channels to one.
+ * Only make this check for non-SCSI cards (I'm not sure firmware attributes
+ * work for them).
+ */
+ if (IS_FC(isp) && ISP_CAP_MULTI_ID(isp) == 0 && isp->isp_nchan > 1) {
+ isp_prt(isp, ISP_LOGWARN, "non-MULTIID f/w loaded, only can enable 1 of %d channels", isp->isp_nchan);
+ isp->isp_nchan = 1;
+ }
+
+ for (i = 0; i < isp->isp_nchan; i++) {
+ isp_fw_state(isp, i);
+ }
+ if (isp->isp_dead) {
+ isp_shutdown(isp);
+ ISP_DISABLE_INTS(isp);
+ return;
+ }
isp->isp_state = ISP_RESETSTATE;
@@ -1184,24 +1138,27 @@ isp_reset(ispsoftc_t *isp)
isp->isp_maxluns = 8;
}
} else {
- if (FCPARAM(isp)->isp_sccfw) {
+ if (ISP_CAP_SCCFW(isp)) {
isp->isp_maxluns = 16384;
} else {
isp->isp_maxluns = 16;
}
}
+
/*
- * Must do this first to get defaults established.
+ * We get some default values established. As a side
+ * effect, NVRAM is read here (unless overriden by
+ * a configuration flag).
*/
- if (IS_SCSI(isp)) {
- isp_setdfltparm(isp, 0);
- if (IS_DUALBUS(isp)) {
- isp_setdfltparm(isp, 1);
+ if (do_load_defaults) {
+ if (IS_SCSI(isp)) {
+ isp_setdfltsdparm(isp);
+ } else {
+ for (i = 0; i < isp->isp_nchan; i++) {
+ isp_setdfltfcparm(isp, i);
+ }
}
- } else {
- isp_setdfltfcparm(isp);
}
-
}
/*
@@ -1214,23 +1171,15 @@ void
isp_init(ispsoftc_t *isp)
{
if (IS_FC(isp)) {
- /*
- * Do this *before* initializing the firmware.
- */
- ISP_MARK_PORTDB(isp, 0);
- FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
- FCPARAM(isp)->isp_loopstate = LOOP_NIL;
-
- if (isp->isp_role != ISP_ROLE_NONE) {
- if (IS_24XX(isp)) {
- isp_fibre_init_2400(isp);
- } else {
- isp_fibre_init(isp);
- }
+ if (IS_24XX(isp)) {
+ isp_fibre_init_2400(isp);
+ } else {
+ isp_fibre_init(isp);
}
} else {
isp_scsi_init(isp);
}
+ GET_NANOTIME(&isp->isp_init_time);
}
static void
@@ -1239,17 +1188,10 @@ isp_scsi_init(ispsoftc_t *isp)
sdparam *sdp_chan0, *sdp_chan1;
mbreg_t mbs;
- sdp_chan0 = isp->isp_param;
+ sdp_chan0 = SDPARAM(isp, 0);
sdp_chan1 = sdp_chan0;
if (IS_DUALBUS(isp)) {
- sdp_chan1++;
- }
-
- /*
- * If we have no role (neither target nor initiator), return.
- */
- if (isp->isp_role == ISP_ROLE_NONE) {
- return;
+ sdp_chan1 = SDPARAM(isp, 1);
}
/* First do overall per-card settings. */
@@ -1265,13 +1207,11 @@ isp_scsi_init(ispsoftc_t *isp)
* Set Retry Delay and Count.
* You set both channels at the same time.
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_RETRY_COUNT;
+ MBSINIT(&mbs, MBOX_SET_RETRY_COUNT, MBLOGALL, 0);
mbs.param[1] = sdp_chan0->isp_retry_count;
mbs.param[2] = sdp_chan0->isp_retry_delay;
mbs.param[6] = sdp_chan1->isp_retry_count;
mbs.param[7] = sdp_chan1->isp_retry_delay;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
@@ -1280,11 +1220,9 @@ isp_scsi_init(ispsoftc_t *isp)
/*
* Set ASYNC DATA SETUP time. This is very important.
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_ASYNC_DATA_SETUP_TIME;
+ MBSINIT(&mbs, MBOX_SET_ASYNC_DATA_SETUP_TIME, MBLOGALL, 0);
mbs.param[1] = sdp_chan0->isp_async_data_setup;
mbs.param[2] = sdp_chan1->isp_async_data_setup;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
@@ -1293,15 +1231,13 @@ isp_scsi_init(ispsoftc_t *isp)
/*
* Set ACTIVE Negation State.
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_ACT_NEG_STATE;
+ MBSINIT(&mbs, MBOX_SET_ACT_NEG_STATE, MBLOGNONE, 0);
mbs.param[1] =
(sdp_chan0->isp_req_ack_active_neg << 4) |
(sdp_chan0->isp_data_line_active_neg << 5);
mbs.param[2] =
(sdp_chan1->isp_req_ack_active_neg << 4) |
(sdp_chan1->isp_data_line_active_neg << 5);
- mbs.logval = MBLOGNONE;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
isp_prt(isp, ISP_LOGERR,
@@ -1318,11 +1254,9 @@ isp_scsi_init(ispsoftc_t *isp)
/*
* Set the Tag Aging limit
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_TAG_AGE_LIMIT;
+ MBSINIT(&mbs, MBOX_SET_TAG_AGE_LIMIT, MBLOGALL, 0);
mbs.param[1] = sdp_chan0->isp_tag_aging;
mbs.param[2] = sdp_chan1->isp_tag_aging;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
isp_prt(isp, ISP_LOGERR, "failed to set tag age limit (%d,%d)",
@@ -1333,11 +1267,9 @@ isp_scsi_init(ispsoftc_t *isp)
/*
* Set selection timeout.
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_SELECT_TIMEOUT;
+ MBSINIT(&mbs, MBOX_SET_SELECT_TIMEOUT, MBLOGALL, 0);
mbs.param[1] = sdp_chan0->isp_selection_timeout;
mbs.param[2] = sdp_chan1->isp_selection_timeout;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
@@ -1353,56 +1285,48 @@ isp_scsi_init(ispsoftc_t *isp)
*/
if (IS_ULTRA2(isp) || IS_1240(isp)) {
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_INIT_RES_QUEUE_A64;
+ MBSINIT(&mbs, MBOX_INIT_RES_QUEUE_A64, MBLOGALL, 0);
mbs.param[1] = RESULT_QUEUE_LEN(isp);
mbs.param[2] = DMA_WD1(isp->isp_result_dma);
mbs.param[3] = DMA_WD0(isp->isp_result_dma);
mbs.param[4] = 0;
mbs.param[6] = DMA_WD3(isp->isp_result_dma);
mbs.param[7] = DMA_WD2(isp->isp_result_dma);
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
}
isp->isp_residx = mbs.param[5];
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_INIT_REQ_QUEUE_A64;
+ MBSINIT(&mbs, MBOX_INIT_REQ_QUEUE_A64, MBLOGALL, 0);
mbs.param[1] = RQUEST_QUEUE_LEN(isp);
mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
mbs.param[5] = 0;
mbs.param[6] = DMA_WD3(isp->isp_result_dma);
mbs.param[7] = DMA_WD2(isp->isp_result_dma);
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
}
isp->isp_reqidx = isp->isp_reqodx = mbs.param[4];
} else {
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_INIT_RES_QUEUE;
+ MBSINIT(&mbs, MBOX_INIT_RES_QUEUE, MBLOGALL, 0);
mbs.param[1] = RESULT_QUEUE_LEN(isp);
mbs.param[2] = DMA_WD1(isp->isp_result_dma);
mbs.param[3] = DMA_WD0(isp->isp_result_dma);
mbs.param[4] = 0;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
}
isp->isp_residx = mbs.param[5];
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_INIT_REQ_QUEUE;
+ MBSINIT(&mbs, MBOX_INIT_REQ_QUEUE, MBLOGALL, 0);
mbs.param[1] = RQUEST_QUEUE_LEN(isp);
mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
mbs.param[5] = 0;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
@@ -1419,9 +1343,7 @@ isp_scsi_init(ispsoftc_t *isp)
* to assume not for them.
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_FW_FEATURES;
- mbs.param[1] = 0;
+ MBSINIT(&mbs, MBOX_SET_FW_FEATURES, MBLOGALL, 0);
if (IS_ULTRA2(isp))
mbs.param[1] |= FW_FEATURE_LVD_NOTIFY;
#ifndef ISP_NO_RIO
@@ -1433,7 +1355,6 @@ isp_scsi_init(ispsoftc_t *isp)
#endif
if (mbs.param[1] != 0) {
uint16_t sfeat = mbs.param[1];
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
isp_prt(isp, ISP_LOGINFO,
@@ -1441,35 +1362,29 @@ isp_scsi_init(ispsoftc_t *isp)
}
}
- /*
- * Let the outer layers decide whether to issue a SCSI bus reset.
- */
isp->isp_state = ISP_INITSTATE;
}
static void
-isp_scsi_channel_init(ispsoftc_t *isp, int channel)
+isp_scsi_channel_init(ispsoftc_t *isp, int chan)
{
sdparam *sdp;
mbreg_t mbs;
int tgt;
- sdp = isp->isp_param;
- sdp += channel;
+ sdp = SDPARAM(isp, chan);
/*
* Set (possibly new) Initiator ID.
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_INIT_SCSI_ID;
- mbs.param[1] = (channel << 7) | sdp->isp_initiator_id;
- mbs.logval = MBLOGALL;
+ MBSINIT(&mbs, MBOX_SET_INIT_SCSI_ID, MBLOGALL, 0);
+ mbs.param[1] = (chan << 7) | sdp->isp_initiator_id;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
}
- isp_prt(isp, ISP_LOGINFO, "Initiator ID is %d on Channel %d",
- sdp->isp_initiator_id, channel);
+ isp_prt(isp, ISP_LOGINFO, "Chan %d Initiator ID is %d",
+ chan, sdp->isp_initiator_id);
/*
@@ -1505,9 +1420,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel)
*/
sdp->isp_devparam[tgt].goal_flags = sdf = DPARM_DEFAULT;
#endif
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_TARGET_PARAMS;
- mbs.param[1] = (channel << 15) | (tgt << 8);
+ MBSINIT(&mbs, MBOX_SET_TARGET_PARAMS, MBLOGNONE, 0);
+ mbs.param[1] = (chan << 15) | (tgt << 8);
mbs.param[2] = sdf;
if ((sdf & DPARM_SYNC) == 0) {
mbs.param[3] = 0;
@@ -1518,18 +1432,15 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel)
}
isp_prt(isp, ISP_LOGDEBUG0,
"Initial Settings bus%d tgt%d flags 0x%x off 0x%x per 0x%x",
- channel, tgt, mbs.param[2], mbs.param[3] >> 8,
+ chan, tgt, mbs.param[2], mbs.param[3] >> 8,
mbs.param[3] & 0xff);
- mbs.logval = MBLOGNONE;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
sdf = DPARM_SAFE_DFLT;
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_TARGET_PARAMS;
- mbs.param[1] = (tgt << 8) | (channel << 15);
+ MBSINIT(&mbs, MBOX_SET_TARGET_PARAMS, MBLOGALL, 0);
+ mbs.param[1] = (tgt << 8) | (chan << 15);
mbs.param[2] = sdf;
mbs.param[3] = 0;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
continue;
@@ -1549,12 +1460,10 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel)
*/
sdp->isp_devparam[tgt].actv_flags = sdf & ~DPARM_TQING;
for (lun = 0; lun < (int) isp->isp_maxluns; lun++) {
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_DEV_QUEUE_PARAMS;
- mbs.param[1] = (channel << 15) | (tgt << 8) | lun;
+ MBSINIT(&mbs, MBOX_SET_DEV_QUEUE_PARAMS, MBLOGALL, 0);
+ mbs.param[1] = (chan << 15) | (tgt << 8) | lun;
mbs.param[2] = sdp->isp_max_queue_depth;
mbs.param[3] = sdp->isp_devparam[tgt].exc_throttle;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
break;
@@ -1563,8 +1472,8 @@ isp_scsi_channel_init(ispsoftc_t *isp, int channel)
}
for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
if (sdp->isp_devparam[tgt].dev_refresh) {
- isp->isp_sendmarker |= (1 << channel);
- isp->isp_update |= (1 << channel);
+ sdp->sendmarker = 1;
+ sdp->update = 1;
break;
}
}
@@ -1580,11 +1489,17 @@ isp_fibre_init(ispsoftc_t *isp)
isp_icb_t local, *icbp = &local;
mbreg_t mbs;
int ownloopid;
- uint64_t nwwn, pwwn;
- fcp = isp->isp_param;
+ /*
+ * We only support one channel on non-24XX cards
+ */
+ fcp = FCPARAM(isp, 0);
+ if (fcp->role == ISP_ROLE_NONE) {
+ isp->isp_state = ISP_INITSTATE;
+ return;
+ }
- MEMZERO(icbp, sizeof (*icbp));
+ ISP_MEMZERO(icbp, sizeof (*icbp));
icbp->icb_version = ICB_VERSION1;
icbp->icb_fwoptions = fcp->isp_fwoptions;
@@ -1619,24 +1534,24 @@ isp_fibre_init(ispsoftc_t *isp)
/*
* Make sure that target role reflects into fwoptions.
*/
- if (isp->isp_role & ISP_ROLE_TARGET) {
+ if (fcp->role & ISP_ROLE_TARGET) {
icbp->icb_fwoptions |= ICBOPT_TGT_ENABLE;
} else {
icbp->icb_fwoptions &= ~ICBOPT_TGT_ENABLE;
}
- if (isp->isp_role & ISP_ROLE_INITIATOR) {
+ if (fcp->role & ISP_ROLE_INITIATOR) {
icbp->icb_fwoptions &= ~ICBOPT_INI_DISABLE;
} else {
icbp->icb_fwoptions |= ICBOPT_INI_DISABLE;
}
- icbp->icb_maxfrmlen = fcp->isp_maxfrmlen;
+ icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN ||
icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
isp_prt(isp, ISP_LOGERR,
"bad frame length (%d) from NVRAM- using %d",
- fcp->isp_maxfrmlen, ICB_DFLT_FRMLEN);
+ DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
}
icbp->icb_maxalloc = fcp->isp_maxalloc;
@@ -1645,18 +1560,18 @@ isp_fibre_init(ispsoftc_t *isp)
"bad maximum allocation (%d)- using 16", fcp->isp_maxalloc);
icbp->icb_maxalloc = 16;
}
- icbp->icb_execthrottle = fcp->isp_execthrottle;
+ icbp->icb_execthrottle = DEFAULT_EXEC_THROTTLE(isp);
if (icbp->icb_execthrottle < 1) {
isp_prt(isp, ISP_LOGERR,
- "bad execution throttle of %d- using 16",
- fcp->isp_execthrottle);
+ "bad execution throttle of %d- using %d",
+ DEFAULT_EXEC_THROTTLE(isp), ICB_DFLT_THROTTLE);
icbp->icb_execthrottle = ICB_DFLT_THROTTLE;
}
icbp->icb_retry_delay = fcp->isp_retry_delay;
icbp->icb_retry_count = fcp->isp_retry_count;
icbp->icb_hardaddr = fcp->isp_loopid;
ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0;
- if (icbp->icb_hardaddr > 125) {
+ if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
icbp->icb_hardaddr = 0;
ownloopid = 0;
}
@@ -1672,7 +1587,7 @@ isp_fibre_init(ispsoftc_t *isp)
/*
* Right now we just set extended options to prefer point-to-point
* over loop based upon some soft config options.
- *
+ *
* NB: for the 2300, ICBOPT_EXTENDED is required.
*/
if (IS_2200(isp) || IS_23XX(isp)) {
@@ -1680,7 +1595,7 @@ isp_fibre_init(ispsoftc_t *isp)
/*
* Prefer or force Point-To-Point instead Loop?
*/
- switch(isp->isp_confopts & ISP_CFG_PORT_PREF) {
+ switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
case ISP_CFG_NPORT:
icbp->icb_xfwoptions |= ICBXOPT_PTP_2_LOOP;
break;
@@ -1695,7 +1610,26 @@ isp_fibre_init(ispsoftc_t *isp)
break;
}
if (IS_2200(isp)) {
+ /*
+ * There seems to just be too much breakage here
+ * with RIO and Fast Posting- it probably actually
+ * works okay but this driver is messing it up.
+ * This card is really ancient by now, so let's
+ * just opt for safety and not use the feature.
+ */
+#if 0
+ if (ISP_FW_NEWER_THAN(isp, 1, 17, 0)) {
+ icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT;
+ icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;
+ icbp->icb_racctimer = 4;
+ icbp->icb_idelaytimer = 8;
+ } else {
+ icbp->icb_fwoptions |= ICBOPT_FAST_POST;
+ }
+#else
+ icbp->icb_xfwoptions &= ~ICBXOPT_RIO_16BIT;
icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;
+#endif
} else {
/*
* QLogic recommends that FAST Posting be turned
@@ -1704,8 +1638,7 @@ isp_fibre_init(ispsoftc_t *isp)
* after a delay (ZIO).
*/
icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;
- if ((fcp->isp_xfwoptions & ICBXOPT_TIMER_MASK) ==
- ICBXOPT_ZIO) {
+ if ((fcp->isp_xfwoptions & ICBXOPT_TIMER_MASK) == ICBXOPT_ZIO) {
icbp->icb_xfwoptions |= ICBXOPT_ZIO;
icbp->icb_idelaytimer = 10;
}
@@ -1733,12 +1666,10 @@ isp_fibre_init(ispsoftc_t *isp)
* Turn on generate AE 8013 on all LIP Resets (2)
* Disable LIP F7 switching (8)
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_FIRMWARE_OPTIONS;
+ MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
mbs.param[1] = 0xb;
mbs.param[2] = 0;
mbs.param[3] = 0;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
@@ -1747,25 +1678,23 @@ isp_fibre_init(ispsoftc_t *isp)
icbp->icb_logintime = ICB_LOGIN_TOV;
icbp->icb_lunetimeout = ICB_LUN_ENABLE_TOV;
- nwwn = ISP_NODEWWN(isp);
- pwwn = ISP_PORTWWN(isp);
- if (nwwn && pwwn) {
+ if (fcp->isp_wwnn && fcp->isp_wwpn && (fcp->isp_wwnn >> 60) != 2) {
icbp->icb_fwoptions |= ICBOPT_BOTH_WWNS;
- MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, nwwn);
- MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);
+ MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
+ MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
isp_prt(isp, ISP_LOGDEBUG1,
"Setting ICB Node 0x%08x%08x Port 0x%08x%08x",
- ((uint32_t) (nwwn >> 32)),
- ((uint32_t) (nwwn & 0xffffffff)),
- ((uint32_t) (pwwn >> 32)),
- ((uint32_t) (pwwn & 0xffffffff)));
- } else if (pwwn) {
+ ((uint32_t) (fcp->isp_wwnn >> 32)),
+ ((uint32_t) (fcp->isp_wwnn)),
+ ((uint32_t) (fcp->isp_wwpn >> 32)),
+ ((uint32_t) (fcp->isp_wwpn)));
+ } else if (fcp->isp_wwpn) {
icbp->icb_fwoptions &= ~ICBOPT_BOTH_WWNS;
- MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);
+ MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
isp_prt(isp, ISP_LOGDEBUG1,
"Setting ICB Port 0x%08x%08x",
- ((uint32_t) (pwwn >> 32)),
- ((uint32_t) (pwwn & 0xffffffff)));
+ ((uint32_t) (fcp->isp_wwpn >> 32)),
+ ((uint32_t) (fcp->isp_wwpn)));
} else {
isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
return;
@@ -1787,30 +1716,31 @@ isp_fibre_init(ispsoftc_t *isp)
icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
+ if (FC_SCRATCH_ACQUIRE(isp, 0)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return;
+ }
isp_prt(isp, ISP_LOGDEBUG0,
"isp_fibre_init: fwopt 0x%x xfwopt 0x%x zfwopt 0x%x",
icbp->icb_fwoptions, icbp->icb_xfwoptions, icbp->icb_zfwoptions);
- FC_SCRATCH_ACQUIRE(isp);
isp_put_icb(isp, icbp, (isp_icb_t *)fcp->isp_scratch);
/*
* Init the firmware
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_INIT_FIRMWARE;
+ MBSINIT(&mbs, MBOX_INIT_FIRMWARE, MBLOGALL, 30000000);
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
mbs.logval = MBLOGALL;
- mbs.timeout = 30 * 1000000;
isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %p (%08x%08x)",
fcp->isp_scratch, (uint32_t) ((uint64_t)fcp->isp_scdma >> 32),
(uint32_t) fcp->isp_scdma);
MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp));
isp_mboxcmd(isp, &mbs);
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, 0);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
isp_print_bytes(isp, "isp_fibre_init", sizeof (*icbp), icbp);
return;
@@ -1831,65 +1761,71 @@ isp_fibre_init_2400(ispsoftc_t *isp)
fcparam *fcp;
isp_icb_2400_t local, *icbp = &local;
mbreg_t mbs;
- int ownloopid;
- uint64_t nwwn, pwwn;
+ int chan;
+
+ /*
+ * Check to see whether all channels have *some* kind of role
+ */
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ fcp = FCPARAM(isp, chan);
+ if (fcp->role != ISP_ROLE_NONE) {
+ break;
+ }
+ }
+ if (chan == isp->isp_nchan) {
+ isp_prt(isp, ISP_LOGDEBUG0, "all %d channels with role 'none'", chan);
+ isp->isp_state = ISP_INITSTATE;
+ return;
+ }
- fcp = isp->isp_param;
+ /*
+ * Start with channel 0.
+ */
+ fcp = FCPARAM(isp, 0);
/*
* Turn on LIP F8 async event (1)
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SET_FIRMWARE_OPTIONS;
+ MBSINIT(&mbs, MBOX_SET_FIRMWARE_OPTIONS, MBLOGALL, 0);
mbs.param[1] = 1;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
}
- /*
- * XXX: This should be applied to icb- not fwoptions
- */
- if (isp->isp_role & ISP_ROLE_TARGET) {
- fcp->isp_fwoptions |= ICB2400_OPT1_TGT_ENABLE;
+ ISP_MEMZERO(icbp, sizeof (*icbp));
+ icbp->icb_fwoptions1 = fcp->isp_fwoptions;
+ if (fcp->role & ISP_ROLE_TARGET) {
+ icbp->icb_fwoptions1 |= ICB2400_OPT1_TGT_ENABLE;
} else {
- fcp->isp_fwoptions &= ~ICB2400_OPT1_TGT_ENABLE;
+ icbp->icb_fwoptions1 &= ~ICB2400_OPT1_TGT_ENABLE;
}
- if (isp->isp_role & ISP_ROLE_INITIATOR) {
- fcp->isp_fwoptions &= ~ICB2400_OPT1_INI_DISABLE;
+ if (fcp->role & ISP_ROLE_INITIATOR) {
+ icbp->icb_fwoptions1 &= ~ICB2400_OPT1_INI_DISABLE;
} else {
- fcp->isp_fwoptions |= ICB2400_OPT1_INI_DISABLE;
+ icbp->icb_fwoptions1 |= ICB2400_OPT1_INI_DISABLE;
}
- MEMZERO(icbp, sizeof (*icbp));
icbp->icb_version = ICB_VERSION1;
- icbp->icb_maxfrmlen = fcp->isp_maxfrmlen;
- if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN ||
- icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
- isp_prt(isp, ISP_LOGERR,
- "bad frame length (%d) from NVRAM- using %d",
- fcp->isp_maxfrmlen, ICB_DFLT_FRMLEN);
+ icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
+ if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
+ isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
}
- icbp->icb_execthrottle = fcp->isp_execthrottle;
+ icbp->icb_execthrottle = DEFAULT_EXEC_THROTTLE(isp);
if (icbp->icb_execthrottle < 1) {
- isp_prt(isp, ISP_LOGERR,
- "bad execution throttle of %d- using 16",
- fcp->isp_execthrottle);
+ isp_prt(isp, ISP_LOGERR, "bad execution throttle of %d- using %d", DEFAULT_EXEC_THROTTLE(isp), ICB_DFLT_THROTTLE);
icbp->icb_execthrottle = ICB_DFLT_THROTTLE;
}
- if (isp->isp_role & ISP_ROLE_TARGET) {
+ if (icbp->icb_fwoptions1 & ICB2400_OPT1_TGT_ENABLE) {
/*
* Get current resource count
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_GET_RESOURCE_COUNT;
+ MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0);
mbs.obits = 0x4cf;
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
@@ -1897,24 +1833,28 @@ isp_fibre_init_2400(ispsoftc_t *isp)
icbp->icb_xchgcnt = mbs.param[3];
}
- icbp->icb_fwoptions1 = fcp->isp_fwoptions;
icbp->icb_hardaddr = fcp->isp_loopid;
- ownloopid = (isp->isp_confopts & ISP_CFG_OWNLOOPID) != 0;
- if (icbp->icb_hardaddr > 125) {
+ if (icbp->icb_hardaddr >= LOCAL_LOOP_LIM) {
icbp->icb_hardaddr = 0;
- ownloopid = 0;
- }
- if (ownloopid) {
- icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
}
+ /*
+ * Force this on.
+ */
+ icbp->icb_fwoptions1 |= ICB2400_OPT1_HARD_ADDRESS;
+
icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
- switch(isp->isp_confopts & ISP_CFG_PORT_PREF) {
+ switch (isp->isp_confopts & ISP_CFG_PORT_PREF) {
+#if 0
case ISP_CFG_NPORT:
+ /*
+ * XXX: This causes the f/w to crash.
+ */
icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_2_LOOP;
break;
+#endif
case ISP_CFG_NPORT_ONLY:
icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
@@ -1929,6 +1869,9 @@ isp_fibre_init_2400(ispsoftc_t *isp)
break;
}
+ /* force this on for now */
+ icbp->icb_fwoptions2 |= ICB2400_OPT2_ZIO;
+
switch (icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK) {
case ICB2400_OPT2_ZIO:
case ICB2400_OPT2_ZIO1:
@@ -1937,12 +1880,16 @@ isp_fibre_init_2400(ispsoftc_t *isp)
case 0:
break;
default:
- isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field",
- icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
+ isp_prt(isp, ISP_LOGWARN, "bad value %x in fwopt2 timer field", icbp->icb_fwoptions2 & ICB2400_OPT2_TIMER_MASK);
icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TIMER_MASK;
break;
}
+ /*
+ * We don't support FCTAPE, so clear it.
+ */
+ icbp->icb_fwoptions2 &= ~ICB2400_OPT2_FCTAPE;
+
icbp->icb_fwoptions3 = fcp->isp_zfwoptions;
icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_AUTO;
if (isp->isp_confopts & ISP_CFG_ONEGB) {
@@ -1960,26 +1907,16 @@ isp_fibre_init_2400(ispsoftc_t *isp)
}
icbp->icb_logintime = ICB_LOGIN_TOV;
- nwwn = ISP_NODEWWN(isp);
- pwwn = ISP_PORTWWN(isp);
-
- if (nwwn && pwwn) {
+ if (fcp->isp_wwnn && fcp->isp_wwpn && (fcp->isp_wwnn >> 60) != 2) {
icbp->icb_fwoptions1 |= ICB2400_OPT1_BOTH_WWNS;
- MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, nwwn);
- MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);
- isp_prt(isp, ISP_LOGDEBUG1,
- "Setting ICB Node 0x%08x%08x Port 0x%08x%08x",
- ((uint32_t) (nwwn >> 32)),
- ((uint32_t) (nwwn & 0xffffffff)),
- ((uint32_t) (pwwn >> 32)),
- ((uint32_t) (pwwn & 0xffffffff)));
- } else if (pwwn) {
+ MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
+ MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwnn);
+ isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node 0x%08x%08x Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwnn >> 32)), ((uint32_t) (fcp->isp_wwnn)),
+ ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
+ } else if (fcp->isp_wwpn) {
icbp->icb_fwoptions1 &= ~ICB2400_OPT1_BOTH_WWNS;
- MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pwwn);
- isp_prt(isp, ISP_LOGDEBUG1,
- "Setting ICB Port 0x%08x%08x",
- ((uint32_t) (pwwn >> 32)),
- ((uint32_t) (pwwn & 0xffffffff)));
+ MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_wwpn);
+ isp_prt(isp, ISP_LOGDEBUG1, "Setting ICB Node to be same as Port 0x%08x%08x", ((uint32_t) (fcp->isp_wwpn >> 32)), ((uint32_t) (fcp->isp_wwpn)));
} else {
isp_prt(isp, ISP_LOGERR, "No valid WWNs to use");
return;
@@ -1988,8 +1925,7 @@ isp_fibre_init_2400(ispsoftc_t *isp)
icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
if (icbp->icb_rqstqlen < 8) {
- isp_prt(isp, ISP_LOGERR, "bad request queue length %d",
- icbp->icb_rqstqlen);
+ isp_prt(isp, ISP_LOGERR, "bad request queue length %d", icbp->icb_rqstqlen);
return;
}
icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
@@ -2009,64 +1945,95 @@ isp_fibre_init_2400(ispsoftc_t *isp)
icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
#ifdef ISP_TARGET_MODE
- if (isp->isp_role & ISP_ROLE_TARGET) {
- icbp->icb_atioqlen = RESULT_QUEUE_LEN(isp);
- if (icbp->icb_atioqlen < 8) {
- isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d",
- icbp->icb_atioqlen);
- return;
- }
- icbp->icb_atioqaddr[RQRSP_ADDR0015] =
- DMA_WD0(isp->isp_atioq_dma);
- icbp->icb_atioqaddr[RQRSP_ADDR1631] =
- DMA_WD1(isp->isp_atioq_dma);
- icbp->icb_atioqaddr[RQRSP_ADDR3247] =
- DMA_WD2(isp->isp_atioq_dma);
- icbp->icb_atioqaddr[RQRSP_ADDR4863] =
- DMA_WD3(isp->isp_atioq_dma);
- isp_prt(isp, ISP_LOGDEBUG0,
- "isp_fibre_init_2400: atioq %04x%04x%04x%04x",
- DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
- DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
+ /* unconditionally set up the ATIO queue if we support target mode */
+ icbp->icb_atioqlen = RESULT_QUEUE_LEN(isp);
+ if (icbp->icb_atioqlen < 8) {
+ isp_prt(isp, ISP_LOGERR, "bad ATIO queue length %d", icbp->icb_atioqlen);
+ return;
}
+ icbp->icb_atioqaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_atioq_dma);
+ icbp->icb_atioqaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_atioq_dma);
+ icbp->icb_atioqaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_atioq_dma);
+ icbp->icb_atioqaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_atioq_dma);
+ isp_prt(isp, ISP_LOGDEBUG0, "isp_fibre_init_2400: atioq %04x%04x%04x%04x", DMA_WD3(isp->isp_atioq_dma), DMA_WD2(isp->isp_atioq_dma),
+ DMA_WD1(isp->isp_atioq_dma), DMA_WD0(isp->isp_atioq_dma));
#endif
- isp_prt(isp, ISP_LOGDEBUG0,
- "isp_fibre_init_2400: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x",
- icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3);
+ isp_prt(isp, ISP_LOGDEBUG0, "isp_fibre_init_2400: fwopt1 0x%x fwopt2 0x%x fwopt3 0x%x", icbp->icb_fwoptions1, icbp->icb_fwoptions2, icbp->icb_fwoptions3);
- isp_prt(isp, ISP_LOGDEBUG0,
- "isp_fibre_init_2400: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x",
- DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma),
- DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma),
- DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
+ isp_prt(isp, ISP_LOGDEBUG0, "isp_fibre_init_2400: rqst %04x%04x%04x%04x rsp %04x%04x%04x%04x", DMA_WD3(isp->isp_rquest_dma), DMA_WD2(isp->isp_rquest_dma),
+ DMA_WD1(isp->isp_rquest_dma), DMA_WD0(isp->isp_rquest_dma), DMA_WD3(isp->isp_result_dma), DMA_WD2(isp->isp_result_dma),
DMA_WD1(isp->isp_result_dma), DMA_WD0(isp->isp_result_dma));
if (isp->isp_dblev & ISP_LOGDEBUG1) {
- isp_print_bytes(isp, "isp_fibre_init_2400", sizeof (*icbp),
- icbp);
+ isp_print_bytes(isp, "isp_fibre_init_2400", sizeof (*icbp), icbp);
}
- FC_SCRATCH_ACQUIRE(isp);
+
+ if (FC_SCRATCH_ACQUIRE(isp, 0)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return;
+ }
+ ISP_MEMZERO(fcp->isp_scratch, ISP_FC_SCRLEN);
isp_put_icb_2400(isp, icbp, fcp->isp_scratch);
+ /*
+ * Now fill in information about any additional channels
+ */
+ if (isp->isp_nchan > 1) {
+ isp_icb_2400_vpinfo_t vpinfo, *vdst;
+ vp_port_info_t pi, *pdst;
+ size_t amt = 0;
+ uint8_t *off;
+
+ vpinfo.vp_count = isp->isp_nchan - 1;
+ vpinfo.vp_global_options = 0;
+ off = fcp->isp_scratch;
+ off += ICB2400_VPINFO_OFF;
+ vdst = (isp_icb_2400_vpinfo_t *) off;
+ isp_put_icb_2400_vpinfo(isp, &vpinfo, vdst);
+ amt = ICB2400_VPINFO_OFF + sizeof (isp_icb_2400_vpinfo_t);
+ for (chan = 1; chan < isp->isp_nchan; chan++) {
+ fcparam *fcp2;
+
+ ISP_MEMZERO(&pi, sizeof (pi));
+ fcp2 = FCPARAM(isp, chan);
+ if (fcp2->role != ISP_ROLE_NONE) {
+ pi.vp_port_options = ICB2400_VPOPT_ENABLED;
+ if (fcp2->role & ISP_ROLE_INITIATOR) {
+ pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE;
+ }
+ if ((fcp2->role & ISP_ROLE_TARGET) == 0) {
+ pi.vp_port_options |= ICB2400_VPOPT_TGT_DISABLE;
+ }
+ MAKE_NODE_NAME_FROM_WWN(pi.vp_port_portname, fcp2->isp_wwpn);
+ MAKE_NODE_NAME_FROM_WWN(pi.vp_port_nodename, fcp2->isp_wwnn);
+ }
+ off = fcp->isp_scratch;
+ off += ICB2400_VPINFO_PORT_OFF(chan);
+ pdst = (vp_port_info_t *) off;
+ isp_put_vp_port_info(isp, &pi, pdst);
+ amt += ICB2400_VPOPT_WRITE_SIZE;
+ }
+ }
/*
* Init the firmware
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_INIT_FIRMWARE;
+ MBSINIT(&mbs, 0, MBLOGALL, 30000000);
+ if (isp->isp_nchan > 1) {
+ mbs.param[0] = MBOX_INIT_FIRMWARE_MULTI_ID;
+ } else {
+ mbs.param[0] = MBOX_INIT_FIRMWARE;
+ }
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
- mbs.logval = MBLOGALL;
- mbs.timeout = 30 * 1000000;
- isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %04x%04x%04x%04x",
- DMA_WD3(fcp->isp_scdma), DMA_WD2(fcp->isp_scdma),
- DMA_WD1(fcp->isp_scdma), DMA_WD0(fcp->isp_scdma));
+ isp_prt(isp, ISP_LOGDEBUG0, "INIT F/W from %04x%04x%04x%04x", DMA_WD3(fcp->isp_scdma), DMA_WD2(fcp->isp_scdma), DMA_WD1(fcp->isp_scdma), DMA_WD0(fcp->isp_scdma));
MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (*icbp));
isp_mboxcmd(isp, &mbs);
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, 0);
+
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
}
@@ -2081,30 +2048,40 @@ isp_fibre_init_2400(ispsoftc_t *isp)
}
static void
-isp_mark_portdb(ispsoftc_t *isp, int onprobation)
+isp_mark_portdb(ispsoftc_t *isp, int chan, int disposition)
{
- fcparam *fcp = (fcparam *) isp->isp_param;
+ fcparam *fcp = FCPARAM(isp, chan);
int i;
+ if (chan < 0 || chan >= isp->isp_nchan) {
+ isp_prt(isp, ISP_LOGWARN, "isp_mark_portdb: bad channel %d", chan);
+ return;
+ }
for (i = 0; i < MAX_FC_TARG; i++) {
- if (onprobation == 0) {
- MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
+ if (fcp->portdb[i].target_mode) {
+ if (disposition < 0) {
+ isp_prt(isp, ISP_LOGTINFO, "isp_mark_portdb: Chan %d zeroing handle 0x" "%04x port 0x%06x", chan,
+ fcp->portdb[i].handle, fcp->portdb[i].portid);
+ ISP_MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
+ }
+ continue;
+ }
+ if (disposition == 0) {
+ ISP_MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
} else {
switch (fcp->portdb[i].state) {
case FC_PORTDB_STATE_CHANGED:
case FC_PORTDB_STATE_PENDING_VALID:
case FC_PORTDB_STATE_VALID:
case FC_PORTDB_STATE_PROBATIONAL:
- fcp->portdb[i].state =
- FC_PORTDB_STATE_PROBATIONAL;
+ fcp->portdb[i].state = FC_PORTDB_STATE_PROBATIONAL;
break;
case FC_PORTDB_STATE_ZOMBIE:
break;
case FC_PORTDB_STATE_NIL:
default:
- MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
- fcp->portdb[i].state =
- FC_PORTDB_STATE_NIL;
+ ISP_MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
+ fcp->portdb[i].state = FC_PORTDB_STATE_NIL;
break;
}
}
@@ -2116,14 +2093,18 @@ isp_mark_portdb(ispsoftc_t *isp, int onprobation)
* or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
*/
static int
-isp_plogx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int flags, int gs)
+isp_plogx(ispsoftc_t *isp, int chan, uint16_t handle, uint32_t portid,
+ int flags, int gs)
{
mbreg_t mbs;
uint8_t q[QENTRY_LEN];
isp_plogx_t *plp;
+ fcparam *fcp;
uint8_t *scp;
uint32_t sst, parm1;
- int rval;
+ int rval, lev;
+ const char *msg;
+ char buf[64];
if (!IS_24XX(isp)) {
int action = flags & PLOGX_FLG_CMD_MASK;
@@ -2136,12 +2117,13 @@ isp_plogx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int flags, int gs)
}
}
- MEMZERO(q, QENTRY_LEN);
+ ISP_MEMZERO(q, QENTRY_LEN);
plp = (isp_plogx_t *) q;
plp->plogx_header.rqs_entry_count = 1;
plp->plogx_header.rqs_entry_type = RQSTYPE_LOGIN;
plp->plogx_handle = 0xffffffff;
plp->plogx_nphdl = handle;
+ plp->plogx_vphdl = chan;
plp->plogx_portlo = portid;
plp->plogx_rspsz_porthi = (portid >> 16) & 0xff;
plp->plogx_flags = flags;
@@ -2151,21 +2133,21 @@ isp_plogx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int flags, int gs)
}
if (gs == 0) {
- FC_SCRATCH_ACQUIRE(isp);
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return (-1);
+ }
}
- scp = FCPARAM(isp)->isp_scratch;
+ fcp = FCPARAM(isp, chan);
+ scp = fcp->isp_scratch;
isp_put_plogx(isp, plp, (isp_plogx_t *) scp);
-
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64;
+ MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 500000);
mbs.param[1] = QENTRY_LEN;
- mbs.param[2] = DMA_WD1(FCPARAM(isp)->isp_scdma);
- mbs.param[3] = DMA_WD0(FCPARAM(isp)->isp_scdma);
- mbs.param[6] = DMA_WD3(FCPARAM(isp)->isp_scdma);
- mbs.param[7] = DMA_WD2(FCPARAM(isp)->isp_scdma);
- mbs.timeout = 500000;
- mbs.logval = MBLOGALL;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
@@ -2183,8 +2165,9 @@ isp_plogx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int flags, int gs)
rval = 0;
goto out;
} else if (plp->plogx_status != PLOGX_STATUS_IOCBERR) {
- isp_prt(isp, ISP_LOGWARN, "status 0x%x on port login IOCB",
- plp->plogx_status);
+ isp_prt(isp, ISP_LOGWARN,
+ "status 0x%x on port login IOCB chanel %d",
+ plp->plogx_status, chan);
rval = -1;
goto out;
}
@@ -2193,73 +2176,83 @@ isp_plogx(ispsoftc_t *isp, uint16_t handle, uint32_t portid, int flags, int gs)
parm1 = plp->plogx_ioparm[1].lo16 | (plp->plogx_ioparm[1].hi16 << 16);
rval = -1;
+ lev = ISP_LOGERR;
+ msg = NULL;
switch (sst) {
case PLOGX_IOCBERR_NOLINK:
- isp_prt(isp, ISP_LOGERR, "PLOGX failed- no link");
+ msg = "no link";
break;
case PLOGX_IOCBERR_NOIOCB:
- isp_prt(isp, ISP_LOGERR, "PLOGX failed- no IOCB buffer");
+ msg = "no IOCB buffer";
break;
case PLOGX_IOCBERR_NOXGHG:
- isp_prt(isp, ISP_LOGERR,
- "PLOGX failed- no Exchange Control Block");
+ msg = "no Exchange Control Block";
break;
case PLOGX_IOCBERR_FAILED:
- isp_prt(isp, ISP_LOGERR,
- "PLOGX(0x%x) of Port 0x%06x failed: reason 0x%x (last LOGIN"
- " state 0x%x)", flags, portid, parm1 & 0xff,
- (parm1 >> 8) & 0xff);
+ ISP_SNPRINTF(buf, sizeof (buf),
+ "reason 0x%x (last LOGIN state 0x%x)",
+ parm1 & 0xff, (parm1 >> 8) & 0xff);
+ msg = buf;
break;
case PLOGX_IOCBERR_NOFABRIC:
- isp_prt(isp, ISP_LOGERR, "PLOGX failed- no fabric");
+ msg = "no fabric";
break;
case PLOGX_IOCBERR_NOTREADY:
- isp_prt(isp, ISP_LOGERR, "PLOGX failed- f/w not ready");
+ msg = "firmware not ready";
break;
case PLOGX_IOCBERR_NOLOGIN:
- isp_prt(isp, ISP_LOGERR,
- "PLOGX failed- not logged in (last LOGIN state 0x%x)",
+ ISP_SNPRINTF(buf, sizeof (buf), "not logged in (last state 0x%x)",
parm1);
+ msg = buf;
rval = MBOX_NOT_LOGGED_IN;
break;
case PLOGX_IOCBERR_REJECT:
- isp_prt(isp, ISP_LOGERR, "PLOGX failed: LS_RJT = 0x%x", parm1);
+ ISP_SNPRINTF(buf, sizeof (buf), "LS_RJT = 0x%x", parm1);
+ msg = buf;
break;
case PLOGX_IOCBERR_NOPCB:
- isp_prt(isp, ISP_LOGERR, "PLOGX failed- no PCB allocated");
+ msg = "no PCB allocated";
break;
case PLOGX_IOCBERR_EINVAL:
- isp_prt(isp, ISP_LOGERR,
- "PLOGX failed: invalid parameter at offset 0x%x", parm1);
+ ISP_SNPRINTF(buf, sizeof (buf), "invalid parameter at offset 0x%x",
+ parm1);
+ msg = buf;
break;
case PLOGX_IOCBERR_PORTUSED:
- isp_prt(isp, ISP_LOGDEBUG0,
- "portid 0x%x already logged in with N-port handle 0x%x",
- portid, parm1);
- rval = MBOX_PORT_ID_USED | (handle << 16);
+ lev = ISP_LOGSANCFG|ISP_LOGDEBUG0;
+ ISP_SNPRINTF(buf, sizeof (buf),
+ "already logged in with N-Port handle 0x%x", parm1);
+ msg = buf;
+ rval = MBOX_PORT_ID_USED | (parm1 << 16);
break;
case PLOGX_IOCBERR_HNDLUSED:
- isp_prt(isp, ISP_LOGDEBUG0,
- "N-port handle 0x%x already used for portid 0x%x",
- handle, parm1);
+ lev = ISP_LOGSANCFG|ISP_LOGDEBUG0;
+ ISP_SNPRINTF(buf, sizeof (buf),
+ "handle already used for PortID 0x%06x", parm1);
+ msg = buf;
rval = MBOX_LOOP_ID_USED;
break;
case PLOGX_IOCBERR_NOHANDLE:
- isp_prt(isp, ISP_LOGERR, "PLOGX failed- no handle allocated");
+ msg = "no handle allocated";
break;
case PLOGX_IOCBERR_NOFLOGI:
- isp_prt(isp, ISP_LOGERR, "PLOGX failed- no FLOGI_ACC");
+ msg = "no FLOGI_ACC";
break;
default:
- isp_prt(isp, ISP_LOGERR, "status %x from %x", plp->plogx_status,
- flags);
- rval = -1;
+ ISP_SNPRINTF(buf, sizeof (buf), "status %x from %x",
+ plp->plogx_status, flags);
+ msg = buf;
break;
}
+ if (msg) {
+ isp_prt(isp, ISP_LOGERR,
+ "Chan %d PLOGX PortID 0x%06x to N-Port handle 0x%x: %s",
+ chan, portid, handle, msg);
+ }
out:
if (gs == 0) {
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
}
return (rval);
}
@@ -2269,9 +2262,8 @@ isp_port_login(ispsoftc_t *isp, uint16_t handle, uint32_t portid)
{
mbreg_t mbs;
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_FABRIC_LOGIN;
- if (FCPARAM(isp)->isp_2klogin) {
+ MBSINIT(&mbs, MBOX_FABRIC_LOGIN, MBLOGNONE, 500000);
+ if (ISP_CAP_2KLOGIN(isp)) {
mbs.param[1] = handle;
mbs.ibits = (1 << 10);
} else {
@@ -2286,13 +2278,13 @@ isp_port_login(ispsoftc_t *isp, uint16_t handle, uint32_t portid)
switch (mbs.param[0]) {
case MBOX_PORT_ID_USED:
isp_prt(isp, ISP_LOGDEBUG0,
- "isp_plogi_old: portid 0x%06x already logged in as %u",
+ "isp_port_login: portid 0x%06x already logged in as %u",
portid, mbs.param[1]);
return (MBOX_PORT_ID_USED | (mbs.param[1] << 16));
case MBOX_LOOP_ID_USED:
isp_prt(isp, ISP_LOGDEBUG0,
- "isp_plogi_old: handle %u in use for port id 0x%02xXXXX",
+ "isp_port_login: handle 0x%04x in use for port id 0x%02xXXXX",
handle, mbs.param[1] & 0xff);
return (MBOX_LOOP_ID_USED);
@@ -2301,18 +2293,18 @@ isp_port_login(ispsoftc_t *isp, uint16_t handle, uint32_t portid)
case MBOX_COMMAND_ERROR:
isp_prt(isp, ISP_LOGINFO,
- "isp_plogi_old: error 0x%x in PLOGI to port 0x%06x",
+ "isp_port_login: error 0x%x in PLOGI to port 0x%06x",
mbs.param[1], portid);
return (MBOX_COMMAND_ERROR);
case MBOX_ALL_IDS_USED:
isp_prt(isp, ISP_LOGINFO,
- "isp_plogi_old: all IDs used for fabric login");
+ "isp_port_login: all IDs used for fabric login");
return (MBOX_ALL_IDS_USED);
default:
isp_prt(isp, ISP_LOGINFO,
- "isp_plogi_old: error 0x%x on port login of 0x%06x@0x%0x",
+ "isp_port_login: error 0x%x on port login of 0x%06x@0x%0x",
mbs.param[0], portid, handle);
return (mbs.param[0]);
}
@@ -2323,38 +2315,34 @@ isp_port_logout(ispsoftc_t *isp, uint16_t handle, uint32_t portid)
{
mbreg_t mbs;
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_FABRIC_LOGOUT;
- if (FCPARAM(isp)->isp_2klogin) {
+ MBSINIT(&mbs, MBOX_FABRIC_LOGOUT, MBLOGNONE, 500000);
+ if (ISP_CAP_2KLOGIN(isp)) {
mbs.param[1] = handle;
mbs.ibits = (1 << 10);
} else {
mbs.param[1] = handle << 8;
}
- mbs.logval = MBLOGNONE;
- mbs.timeout = 100000;
isp_mboxcmd(isp, &mbs);
return (mbs.param[0] == MBOX_COMMAND_COMPLETE? 0 : mbs.param[0]);
}
static int
-isp_getpdb(ispsoftc_t *isp, uint16_t id, isp_pdb_t *pdb, int dolock)
+isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock)
{
- fcparam *fcp = (fcparam *) isp->isp_param;
+ fcparam *fcp = FCPARAM(isp, chan);
mbreg_t mbs;
union {
isp_pdb_21xx_t fred;
isp_pdb_24xx_t bill;
} un;
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_GET_PORT_DB;
+ MBSINIT(&mbs, MBOX_GET_PORT_DB, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR, 250000);
if (IS_24XX(isp)) {
- mbs.ibits = 0x3ff;
+ mbs.ibits = (1 << 9)|(1 << 10);
mbs.param[1] = id;
- } else if (FCPARAM(isp)->isp_2klogin) {
+ mbs.param[9] = chan;
+ } else if (ISP_CAP_2KLOGIN(isp)) {
mbs.param[1] = id;
- mbs.ibits = (1 << 10);
} else {
mbs.param[1] = id << 8;
}
@@ -2362,68 +2350,111 @@ isp_getpdb(ispsoftc_t *isp, uint16_t id, isp_pdb_t *pdb, int dolock)
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
- mbs.timeout = 250000;
- mbs.logval = MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR;
if (dolock) {
- FC_SCRATCH_ACQUIRE(isp);
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return (-1);
+ }
}
MEMORYBARRIER(isp, SYNC_SFORDEV, 0, sizeof (un));
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
if (dolock) {
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
}
- return (-1);
+ return (mbs.param[0]);
}
if (IS_24XX(isp)) {
isp_get_pdb_24xx(isp, fcp->isp_scratch, &un.bill);
pdb->handle = un.bill.pdb_handle;
pdb->s3_role = un.bill.pdb_prli_svc3;
pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
- MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
- MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
+ ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
+ ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d Port 0x%06x flags 0x%x curstate %x",
+ chan, pdb->portid, un.bill.pdb_flags,
+ un.bill.pdb_curstate);
+ if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE ||
+ un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
+ mbs.param[0] = MBOX_NOT_LOGGED_IN;
+ if (dolock) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ }
+ return (mbs.param[0]);
+ }
} else {
isp_get_pdb_21xx(isp, fcp->isp_scratch, &un.fred);
pdb->handle = un.fred.pdb_loopid;
pdb->s3_role = un.fred.pdb_prli_svc3;
pdb->portid = BITS2WORD(un.fred.pdb_portid_bits);
- MEMCPY(pdb->portname, un.fred.pdb_portname, 8);
- MEMCPY(pdb->nodename, un.fred.pdb_nodename, 8);
+ ISP_MEMCPY(pdb->portname, un.fred.pdb_portname, 8);
+ ISP_MEMCPY(pdb->nodename, un.fred.pdb_nodename, 8);
}
if (dolock) {
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
}
return (0);
}
+static void
+isp_dump_chip_portdb(ispsoftc_t *isp, int chan, int dolock)
+{
+ isp_pdb_t pdb;
+ int lim, loopid;
+
+ if (ISP_CAP_2KLOGIN(isp)) {
+ lim = NPH_MAX_2K;
+ } else {
+ lim = NPH_MAX;
+ }
+ for (loopid = 0; loopid != lim; loopid++) {
+ if (isp_getpdb(isp, chan, loopid, &pdb, dolock)) {
+ continue;
+ }
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGINFO, "Chan %d Loopid 0x%04x "
+ "PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x",
+ chan, loopid, pdb.portid, pdb.portname[0], pdb.portname[1],
+ pdb.portname[2], pdb.portname[3], pdb.portname[4],
+ pdb.portname[5], pdb.portname[6], pdb.portname[7]);
+ }
+}
+
static uint64_t
-isp_get_portname(ispsoftc_t *isp, int loopid, int nodename)
+isp_get_wwn(ispsoftc_t *isp, int chan, int loopid, int nodename)
{
- uint64_t wwn = (uint64_t) -1;
+ uint64_t wwn = INI_NONE;
+ fcparam *fcp = FCPARAM(isp, chan);
mbreg_t mbs;
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_GET_PORT_NAME;
- if (FCPARAM(isp)->isp_2klogin || IS_24XX(isp)) {
+ if (fcp->isp_fwstate < FW_READY ||
+ fcp->isp_loopstate < LOOP_PDB_RCVD) {
+ return (wwn);
+ }
+ MBSINIT(&mbs, MBOX_GET_PORT_NAME, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR, 500000);
+ if (ISP_CAP_2KLOGIN(isp)) {
mbs.param[1] = loopid;
mbs.ibits = (1 << 10);
if (nodename) {
mbs.param[10] = 1;
}
+ if (ISP_CAP_MULTI_ID(isp)) {
+ mbs.ibits |= (1 << 9);
+ mbs.param[9] = chan;
+ }
} else {
mbs.param[1] = loopid << 8;
if (nodename) {
mbs.param[1] |= 1;
}
}
- mbs.logval = MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return (wwn);
}
if (IS_24XX(isp)) {
wwn =
- (((uint64_t)(mbs.param[2] >> 8)) << 56) |
+ (((uint64_t)(mbs.param[2] >> 8)) << 56) |
(((uint64_t)(mbs.param[2] & 0xff)) << 48) |
(((uint64_t)(mbs.param[3] >> 8)) << 40) |
(((uint64_t)(mbs.param[3] & 0xff)) << 32) |
@@ -2450,27 +2481,20 @@ isp_get_portname(ispsoftc_t *isp, int loopid, int nodename)
*/
static int
-isp_fclink_test(ispsoftc_t *isp, int usdelay)
+isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
{
- static const char *toponames[] = {
- "Private Loop",
- "FL Port",
- "N-Port to N-Port",
- "F Port",
- "F Port (no FLOGI_ACC response)"
- };
mbreg_t mbs;
- int count, check_for_fabric;
+ int count, check_for_fabric, r;
uint8_t lwfs;
int loopid;
fcparam *fcp;
fcportdb_t *lp;
isp_pdb_t pdb;
- fcp = isp->isp_param;
+ fcp = FCPARAM(isp, chan);
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Link Test Entry");
- ISP_MARK_PORTDB(isp, 1);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d FC Link Test Entry", chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
/*
* Wait up to N microseconds for F/W to go to a ready state.
@@ -2483,12 +2507,9 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
NANOTIME_T hra, hrb;
GET_NANOTIME(&hra);
- isp_fw_state(isp);
+ isp_fw_state(isp, chan);
if (lwfs != fcp->isp_fwstate) {
- isp_prt(isp, ISP_LOGCONFIG|ISP_LOGSANCFG,
- "Firmware State <%s->%s>",
- ispfc_fw_statename((int)lwfs),
- ispfc_fw_statename((int)fcp->isp_fwstate));
+ isp_prt(isp, ISP_LOGCONFIG|ISP_LOGSANCFG, "Chan %d Firmware State <%s->%s>", chan, isp_fc_fw_statename((int)lwfs), isp_fc_fw_statename((int)fcp->isp_fwstate));
lwfs = fcp->isp_fwstate;
}
if (fcp->isp_fwstate == FW_READY) {
@@ -2502,10 +2523,7 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
*/
enano = NANOTIME_SUB(&hrb, &hra);
- isp_prt(isp, ISP_LOGDEBUG1,
- "usec%d: 0x%lx->0x%lx enano 0x%x%08x",
- count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb),
- (uint32_t)(enano >> 32), (uint32_t)(enano & 0xffffffff));
+ isp_prt(isp, ISP_LOGDEBUG1, "usec%d: 0x%lx->0x%lx enano 0x%x%08x", count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb), (uint32_t)(enano >> 32), (uint32_t)(enano));
/*
* If the elapsed time is less than 1 millisecond,
@@ -2520,12 +2538,12 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
count += 1000;
enano = (1000 * 1000) - enano;
while (enano > (uint64_t) 4000000000U) {
- USEC_SLEEP(isp, 4000000);
+ ISP_SLEEP(isp, 4000000);
enano -= (uint64_t) 4000000000U;
}
wrk = enano;
wrk /= 1000;
- USEC_SLEEP(isp, wrk);
+ ISP_SLEEP(isp, wrk);
} else {
while (enano > (uint64_t) 4000000000U) {
count += 4000000;
@@ -2536,27 +2554,31 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
}
}
+
+
/*
* If we haven't gone to 'ready' state, return.
*/
if (fcp->isp_fwstate != FW_READY) {
- isp_prt(isp, ISP_LOGSANCFG,
- "isp_fclink_test: not at FW_READY state");
+ isp_prt(isp, ISP_LOGSANCFG, "%s: chan %d not at FW_READY state", __func__, chan);
return (-1);
}
/*
* Get our Loop ID and Port ID.
*/
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_GET_LOOP_ID;
- mbs.logval = MBLOGALL;
+ MBSINIT(&mbs, MBOX_GET_LOOP_ID, MBLOGALL, 0);
+ if (ISP_CAP_MULTI_ID(isp)) {
+ mbs.param[9] = chan;
+ mbs.ibits = (1 << 9);
+ mbs.obits = (1 << 7);
+ }
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return (-1);
}
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_2KLOGIN(isp)) {
fcp->isp_loopid = mbs.param[1];
} else {
fcp->isp_loopid = mbs.param[1] & 0xff;
@@ -2583,21 +2605,52 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
} else {
check_for_fabric = 0;
}
- } else if (fcp->isp_topo == TOPO_FL_PORT ||
- fcp->isp_topo == TOPO_F_PORT) {
+ } else if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_F_PORT) {
check_for_fabric = 1;
} else {
check_for_fabric = 0;
}
- if (IS_24XX(isp)) {
+ /*
+ * Check to make sure we got a valid loopid
+ * The 24XX seems to mess this up for multiple channels.
+ */
+ if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT) {
+ uint8_t alpa = fcp->isp_portid;
+
+ if (alpa == 0) {
+ /* "Cannot Happen" */
+ isp_prt(isp, ISP_LOGWARN, "Zero AL_PA for Loop Topology?");
+ } else {
+ int i;
+ for (i = 0; alpa_map[i]; i++) {
+ if (alpa_map[i] == alpa) {
+ break;
+ }
+ }
+ if (alpa_map[i] && fcp->isp_loopid != i) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d deriving loopid %d from AL_PA map (AL_PA 0x%x) and ignoring returned value %d (AL_PA 0x%x)", chan, i, alpa_map[i], fcp->isp_loopid, alpa);
+ fcp->isp_loopid = i;
+ }
+ }
+ }
+
+
+ if (IS_24XX(isp)) { /* XXX SHOULDN'T THIS BE FOR 2K F/W? XXX */
loopid = NPH_FL_ID;
} else {
loopid = FL_ID;
}
-
- if (check_for_fabric && isp_getpdb(isp, loopid, &pdb, 1) == 0) {
- int r;
+ if (check_for_fabric) {
+ r = isp_getpdb(isp, chan, loopid, &pdb, 1);
+ if (r && (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT)) {
+ isp_prt(isp, ISP_LOGWARN, "fabric topology but cannot get info about fabric controller (0x%x)", r);
+ fcp->isp_topo = TOPO_PTP_STUB;
+ }
+ } else {
+ r = -1;
+ }
+ if (r == 0) {
if (IS_2100(isp)) {
fcp->isp_topo = TOPO_FL_PORT;
}
@@ -2622,13 +2675,30 @@ isp_fclink_test(ispsoftc_t *isp, int usdelay)
lp->new_portid = lp->portid;
lp->new_roles = lp->roles;
if (IS_24XX(isp)) {
- r = isp_register_fc4_type_24xx(isp);
+ fcp->inorder = (mbs.param[7] & ISP24XX_INORDER) != 0;
+ if (ISP_FW_NEWER_THAN(isp, 4, 0, 27)) {
+ fcp->npiv_fabric = (mbs.param[7] & ISP24XX_NPIV_SAN) != 0;
+ if (fcp->npiv_fabric) {
+ isp_prt(isp, ISP_LOGCONFIG, "fabric supports NP-IV");
+ }
+ }
+ if (chan) {
+ fcp->isp_sns_hdl = NPH_SNS_HDLBASE + chan;
+ r = isp_plogx(isp, chan, fcp->isp_sns_hdl, SNS_PORT_ID, PLOGX_FLG_CMD_PLOGI | PLOGX_FLG_COND_PLOGI | PLOGX_FLG_SKIP_PRLI, 0);
+ if (r) {
+ isp_prt(isp, ISP_LOGWARN, "%s: Chan %d cannot log into SNS", __func__, chan);
+ return (-1);
+ }
+ } else {
+ fcp->isp_sns_hdl = NPH_SNS_ID;
+ }
+ r = isp_register_fc4_type_24xx(isp, chan);
} else {
- r = isp_register_fc4_type(isp);
+ fcp->isp_sns_hdl = SNS_ID;
+ r = isp_register_fc4_type(isp, chan);
}
if (r) {
- isp_prt(isp, ISP_LOGSANCFG,
- "isp_fclink_test: register fc4 type failed");
+ isp_prt(isp, ISP_LOGWARN|ISP_LOGSANCFG, "%s: register fc4 type failed", __func__);
return (-1);
}
} else {
@@ -2638,20 +2708,23 @@ not_on_fabric:
fcp->isp_gbspeed = 1;
if (IS_23XX(isp) || IS_24XX(isp)) {
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_GET_SET_DATA_RATE;
+ MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
mbs.param[1] = MBGSD_GET_RATE;
/* mbs.param[2] undefined if we're just getting rate */
- mbs.logval = MBLOGALL;
- mbs.timeout = 3000000;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
- if (mbs.param[1] == MBGSD_FOURGB) {
- isp_prt(isp, ISP_LOGINFO, "4Gb link speed/s");
+ if (mbs.param[1] == MBGSD_EIGHTGB) {
+ isp_prt(isp, ISP_LOGINFO, "Chan %d 8Gb link speed", chan);
+ fcp->isp_gbspeed = 8;
+ } else if (mbs.param[1] == MBGSD_FOURGB) {
+ isp_prt(isp, ISP_LOGINFO, "Chan %d 4Gb link speed", chan);
fcp->isp_gbspeed = 4;
- } if (mbs.param[1] == MBGSD_TWOGB) {
- isp_prt(isp, ISP_LOGINFO, "2Gb link speed/s");
+ } else if (mbs.param[1] == MBGSD_TWOGB) {
+ isp_prt(isp, ISP_LOGINFO, "Chan %d 2Gb link speed", chan);
fcp->isp_gbspeed = 2;
+ } else if (mbs.param[1] == MBGSD_ONEGB) {
+ isp_prt(isp, ISP_LOGINFO, "Chan %d 1Gb link speed", chan);
+ fcp->isp_gbspeed = 1;
}
}
}
@@ -2659,33 +2732,11 @@ not_on_fabric:
/*
* Announce ourselves, too.
*/
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, topology, fcp->isp_portid,
- fcp->isp_loopid, toponames[fcp->isp_topo]);
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, ourwwn,
- (uint32_t) (ISP_NODEWWN(isp) >> 32),
- (uint32_t) ISP_NODEWWN(isp),
- (uint32_t) (ISP_PORTWWN(isp) >> 32),
- (uint32_t) ISP_PORTWWN(isp));
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Link Test Complete");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, topology, chan, (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) fcp->isp_wwpn, fcp->isp_portid, fcp->isp_loopid, isp_fc_toponame(fcp));
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d FC Link Test Complete", chan);
return (0);
}
-static const char *
-ispfc_fw_statename(int state)
-{
- switch(state) {
- case FW_CONFIG_WAIT: return "Config Wait";
- case FW_WAIT_AL_PA: return "Waiting for AL_PA";
- case FW_WAIT_LOGIN: return "Wait Login";
- case FW_READY: return "Ready";
- case FW_LOSS_OF_SYNC: return "Loss Of Sync";
- case FW_ERROR: return "Error";
- case FW_REINIT: return "Re-Init";
- case FW_NON_PART: return "Nonparticipating";
- default: return "?????";
- }
-}
-
/*
* Complete the synchronization of our Port Database.
*
@@ -2707,9 +2758,9 @@ ispfc_fw_statename(int state)
* entities.
*/
static int
-isp_pdb_sync(ispsoftc_t *isp)
+isp_pdb_sync(ispsoftc_t *isp, int chan)
{
- fcparam *fcp = isp->isp_param;
+ fcparam *fcp = FCPARAM(isp, chan);
fcportdb_t *lp;
uint16_t dbidx;
@@ -2732,7 +2783,7 @@ isp_pdb_sync(ispsoftc_t *isp)
fcp->isp_topo == TOPO_NL_PORT ||
fcp->isp_topo == TOPO_N_PORT) {
if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
- if (isp_scan_loop(isp) != 0) {
+ if (isp_scan_loop(isp, chan) != 0) {
isp_prt(isp, ISP_LOGWARN,
"isp_pdb_sync: isp_scan_loop failed");
return (-1);
@@ -2742,7 +2793,7 @@ isp_pdb_sync(ispsoftc_t *isp)
if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
if (fcp->isp_loopstate < LOOP_FSCAN_DONE) {
- if (isp_scan_fabric(isp) != 0) {
+ if (isp_scan_fabric(isp, chan) != 0) {
isp_prt(isp, ISP_LOGWARN,
"isp_pdb_sync: isp_scan_fabric failed");
return (-1);
@@ -2750,14 +2801,15 @@ isp_pdb_sync(ispsoftc_t *isp)
}
}
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Synchronizing PDBs");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d Synchronizing PDBs", chan);
fcp->isp_loopstate = LOOP_SYNCING_PDB;
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
lp = &fcp->portdb[dbidx];
- if (lp->state == FC_PORTDB_STATE_NIL) {
+ if (lp->state == FC_PORTDB_STATE_NIL || lp->target_mode) {
continue;
}
@@ -2774,12 +2826,13 @@ isp_pdb_sync(ispsoftc_t *isp)
case FC_PORTDB_STATE_PROBATIONAL:
case FC_PORTDB_STATE_DEAD:
/*
- * It's up to the outer layers to clear isp_ini_map.
+ * It's up to the outer layers to clear isp_dev_map.
*/
lp->state = FC_PORTDB_STATE_NIL;
- isp_async(isp, ISPASYNC_DEV_GONE, lp);
+ isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
if (lp->autologin == 0) {
- (void) isp_plogx(isp, lp->handle, lp->portid,
+ (void) isp_plogx(isp, chan, lp->handle,
+ lp->portid,
PLOGX_FLG_CMD_LOGO |
PLOGX_FLG_IMPLICIT |
PLOGX_FLG_FREE_NPHDL, 0);
@@ -2796,12 +2849,12 @@ isp_pdb_sync(ispsoftc_t *isp)
case FC_PORTDB_STATE_NEW:
/*
* It's up to the outer layers to assign a virtual
- * target id in isp_ini_map (if any).
+ * target id in isp_dev_map (if any).
*/
lp->portid = lp->new_portid;
lp->roles = lp->new_roles;
lp->state = FC_PORTDB_STATE_VALID;
- isp_async(isp, ISPASYNC_DEV_ARRIVED, lp);
+ isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
lp->new_roles = 0;
lp->new_portid = 0;
lp->reserved = 0;
@@ -2812,7 +2865,7 @@ isp_pdb_sync(ispsoftc_t *isp)
* XXXX FIX THIS
*/
lp->state = FC_PORTDB_STATE_VALID;
- isp_async(isp, ISPASYNC_DEV_CHANGED, lp);
+ isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
lp->new_roles = 0;
lp->new_portid = 0;
lp->reserved = 0;
@@ -2821,12 +2874,12 @@ isp_pdb_sync(ispsoftc_t *isp)
case FC_PORTDB_STATE_PENDING_VALID:
lp->portid = lp->new_portid;
lp->roles = lp->new_roles;
- if (lp->ini_map_idx) {
- int t = lp->ini_map_idx - 1;
- fcp->isp_ini_map[t] = dbidx + 1;
+ if (lp->dev_map_idx) {
+ int t = lp->dev_map_idx - 1;
+ fcp->isp_dev_map[t] = dbidx + 1;
}
lp->state = FC_PORTDB_STATE_VALID;
- isp_async(isp, ISPASYNC_DEV_STAYED, lp);
+ isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
if (dbidx != FL_ID) {
lp->new_roles = 0;
lp->new_portid = 0;
@@ -2840,7 +2893,7 @@ isp_pdb_sync(ispsoftc_t *isp)
isp_prt(isp, ISP_LOGWARN,
"isp_scan_loop: state %d for idx %d",
lp->state, dbidx);
- isp_dump_portdb(isp);
+ isp_dump_portdb(isp, chan);
}
}
@@ -2858,10 +2911,10 @@ isp_pdb_sync(ispsoftc_t *isp)
* Scan local loop for devices.
*/
static int
-isp_scan_loop(ispsoftc_t *isp)
+isp_scan_loop(ispsoftc_t *isp, int chan)
{
fcportdb_t *lp, tmp;
- fcparam *fcp = isp->isp_param;
+ fcparam *fcp = FCPARAM(isp, chan);
int i;
isp_pdb_t pdb;
uint16_t handle, lim = 0;
@@ -2879,53 +2932,68 @@ isp_scan_loop(ispsoftc_t *isp)
* Check our connection topology.
*
* If we're a public or private loop, we scan 0..125 as handle values.
- * The firmware has (typically) peformed a PLOGI for us.
+ * The firmware has (typically) peformed a PLOGI for us. We skip this
+ * step if we're a ISP_24XX in NP-IV mode.
*
* If we're a N-port connection, we treat this is a short loop (0..1).
- *
- * If we're in target mode, we can all possible handles to see who
- * might have logged into us.
*/
switch (fcp->isp_topo) {
case TOPO_NL_PORT:
+ lim = LOCAL_LOOP_LIM;
+ break;
case TOPO_FL_PORT:
+ if (IS_24XX(isp) && isp->isp_nchan > 1) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d Skipping Local Loop Scan", chan);
+ fcp->isp_loopstate = LOOP_LSCAN_DONE;
+ return (0);
+ }
lim = LOCAL_LOOP_LIM;
break;
case TOPO_N_PORT:
lim = 2;
break;
default:
- isp_prt(isp, ISP_LOGDEBUG0, "no loop topology to scan");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d no loop topology to scan", chan);
fcp->isp_loopstate = LOOP_LSCAN_DONE;
return (0);
}
fcp->isp_loopstate = LOOP_SCANNING_LOOP;
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC scan loop 0..%d", lim-1);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d FC scan loop 0..%d", chan, lim-1);
/*
* Run through the list and get the port database info for each one.
*/
for (handle = 0; handle < lim; handle++) {
+ int r;
/*
- * But don't even try for ourselves...
- */
- if (handle == fcp->isp_loopid) {
+ * Don't scan "special" ids.
+ */
+ if (handle >= FL_ID && handle <= SNS_ID) {
continue;
}
-
+ if (ISP_CAP_2KLOGIN(isp)) {
+ if (handle >= NPH_RESERVED && handle <= NPH_FL_ID) {
+ continue;
+ }
+ }
/*
* In older cards with older f/w GET_PORT_DATABASE has been
* known to hang. This trick gets around that problem.
*/
if (IS_2100(isp) || IS_2200(isp)) {
- uint64_t node_wwn = isp_get_portname(isp, handle, 1);
+ uint64_t node_wwn = isp_get_wwn(isp, chan, handle, 1);
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d FC scan loop DONE (bad)", chan);
return (-1);
}
- if (node_wwn == 0) {
+ if (node_wwn == INI_NONE) {
continue;
}
}
@@ -2933,16 +3001,24 @@ isp_scan_loop(ispsoftc_t *isp)
/*
* Get the port database entity for this index.
*/
- if (isp_getpdb(isp, handle, &pdb, 1) != 0) {
+ r = isp_getpdb(isp, chan, handle, &pdb, 1);
+ if (r != 0) {
+ isp_prt(isp, ISP_LOGDEBUG1,
+ "Chan %d FC scan loop handle %d returned %x",
+ chan, handle, r);
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
- ISP_MARK_PORTDB(isp, 1);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d FC scan loop DONE (bad)", chan);
return (-1);
}
continue;
}
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
- ISP_MARK_PORTDB(isp, 1);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d FC scan loop DONE (bad)", chan);
return (-1);
}
@@ -2954,8 +3030,10 @@ isp_scan_loop(ispsoftc_t *isp)
*/
if (IS_2100(isp) && pdb.handle != handle) {
isp_prt(isp, ISP_LOGWARN,
- "giving up on synchronizing the port database");
- ISP_MARK_PORTDB(isp, 1);
+ "Chan %d cannot synchronize port database", chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d FC scan loop DONE (bad)", chan);
return (-1);
}
@@ -2978,12 +3056,23 @@ isp_scan_loop(ispsoftc_t *isp)
a = (tmp.node_wwn == 0);
b = (tmp.port_wwn == 0);
c = (tmp.portid == 0);
+ if (a == 0 && b == 0) {
+ tmp.node_wwn =
+ isp_get_wwn(isp, chan, handle, 1);
+ tmp.port_wwn =
+ isp_get_wwn(isp, chan, handle, 0);
+ if (tmp.node_wwn && tmp.port_wwn) {
+ isp_prt(isp, ISP_LOGINFO, "DODGED!");
+ goto cont;
+ }
+ }
isp_prt(isp, ISP_LOGWARN,
- "bad pdb (%1d%1d%1d) @ handle 0x%x", a, b, c,
- handle);
- isp_dump_portdb(isp);
+ "Chan %d bad pdb (%1d%1d%1d) @ handle 0x%x", chan,
+ a, b, c, handle);
+ isp_dump_portdb(isp, chan);
continue;
}
+ cont:
/*
* Now search the entire port database
@@ -2991,7 +3080,9 @@ isp_scan_loop(ispsoftc_t *isp)
*/
for (i = 0; i < MAX_FC_TARG; i++) {
lp = &fcp->portdb[i];
- if (lp->state == FC_PORTDB_STATE_NIL) {
+
+ if (lp->state == FC_PORTDB_STATE_NIL ||
+ lp->target_mode) {
continue;
}
if (lp->node_wwn != tmp.node_wwn) {
@@ -3008,10 +3099,12 @@ isp_scan_loop(ispsoftc_t *isp)
if (lp->state != FC_PORTDB_STATE_PROBATIONAL &&
lp->state != FC_PORTDB_STATE_ZOMBIE) {
isp_prt(isp, ISP_LOGERR,
- "[%d] not probational/zombie (0x%x)",
- i, lp->state);
- isp_dump_portdb(isp);
- ISP_MARK_PORTDB(isp, 1);
+ "Chan %d [%d] not probational/zombie (0x%x)",
+ chan, i, lp->state);
+ isp_dump_portdb(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d FC scan loop DONE (bad)", chan);
return (-1);
}
@@ -3031,12 +3124,12 @@ isp_scan_loop(ispsoftc_t *isp)
lp->new_portid = tmp.portid;
lp->new_roles = tmp.roles;
lp->state = FC_PORTDB_STATE_PENDING_VALID;
- isp_prt(isp, ISP_LOGSANCFG,
- "Loop Port 0x%02x@0x%x Pending Valid",
- tmp.portid, tmp.handle);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d Loop Port 0x%06x@0x%04x Pending "
+ "Valid", chan, tmp.portid, tmp.handle);
break;
}
-
+
/*
* We can wipe out the old handle value
* here because it's no longer valid.
@@ -3047,9 +3140,9 @@ isp_scan_loop(ispsoftc_t *isp)
* Claim that this has changed and let somebody else
* decide what to do.
*/
- isp_prt(isp, ISP_LOGSANCFG,
- "Loop Port 0x%02x@0x%x changed",
- tmp.portid, tmp.handle);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d Loop Port 0x%06x@0x%04x changed",
+ chan, tmp.portid, tmp.handle);
lp->state = FC_PORTDB_STATE_CHANGED;
lp->new_portid = tmp.portid;
lp->new_roles = tmp.roles;
@@ -3068,17 +3161,21 @@ isp_scan_loop(ispsoftc_t *isp)
* for it and save info for later disposition.
*/
for (i = 0; i < MAX_FC_TARG; i++) {
+ if (fcp->portdb[i].target_mode) {
+ continue;
+ }
if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) {
break;
}
}
if (i == MAX_FC_TARG) {
- isp_prt(isp, ISP_LOGERR, "out of portdb entries");
+ isp_prt(isp, ISP_LOGERR,
+ "Chan %d out of portdb entries", chan);
continue;
}
lp = &fcp->portdb[i];
- MEMZERO(lp, sizeof (fcportdb_t));
+ ISP_MEMZERO(lp, sizeof (fcportdb_t));
lp->autologin = 1;
lp->state = FC_PORTDB_STATE_NEW;
lp->new_portid = tmp.portid;
@@ -3086,11 +3183,13 @@ isp_scan_loop(ispsoftc_t *isp)
lp->handle = tmp.handle;
lp->port_wwn = tmp.port_wwn;
lp->node_wwn = tmp.node_wwn;
- isp_prt(isp, ISP_LOGSANCFG,
- "Loop Port 0x%02x@0x%x is New Entry",
- tmp.portid, tmp.handle);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d Loop Port 0x%06x@0x%04x is New Entry",
+ chan, tmp.portid, tmp.handle);
}
fcp->isp_loopstate = LOOP_LSCAN_DONE;
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d FC scan loop DONE", chan);
return (0);
}
@@ -3111,31 +3210,32 @@ isp_scan_loop(ispsoftc_t *isp)
*/
/*
- * Take less than half of our scratch area to store Port IDs
+ * Take less than half of our scratch area to store Port IDs
*/
-#define GIDLEN ((ISP2100_SCRLEN >> 1) - 16 - SNS_GID_FT_REQ_SIZE)
+#define GIDLEN ((ISP_FC_SCRLEN >> 1) - 16 - SNS_GID_FT_REQ_SIZE)
#define NGENT ((GIDLEN - 16) >> 2)
#define IGPOFF (2 * QENTRY_LEN)
-#define OGPOFF (ISP2100_SCRLEN >> 1)
-#define ZTXOFF (ISP2100_SCRLEN - (1 * QENTRY_LEN))
-#define CTXOFF (ISP2100_SCRLEN - (2 * QENTRY_LEN))
-#define XTXOFF (ISP2100_SCRLEN - (3 * QENTRY_LEN))
+#define OGPOFF (ISP_FC_SCRLEN >> 1)
+#define ZTXOFF (ISP_FC_SCRLEN - (1 * QENTRY_LEN))
+#define CTXOFF (ISP_FC_SCRLEN - (2 * QENTRY_LEN))
+#define XTXOFF (ISP_FC_SCRLEN - (3 * QENTRY_LEN))
static int
-isp_gid_ft_sns(ispsoftc_t *isp)
+isp_gid_ft_sns(ispsoftc_t *isp, int chan)
{
union {
sns_gid_ft_req_t _x;
uint8_t _y[SNS_GID_FT_REQ_SIZE];
} un;
- fcparam *fcp = FCPARAM(isp);
+ fcparam *fcp = FCPARAM(isp, chan);
sns_gid_ft_req_t *rq = &un._x;
mbreg_t mbs;
- isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT) via SNS");
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "Chan %d scanning fabric (GID_FT) via SNS", chan);
- MEMZERO(rq, SNS_GID_FT_REQ_SIZE);
+ ISP_MEMZERO(rq, SNS_GID_FT_REQ_SIZE);
rq->snscb_rblen = GIDLEN >> 1;
rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + IGPOFF);
rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + IGPOFF);
@@ -3149,15 +3249,13 @@ isp_gid_ft_sns(ispsoftc_t *isp)
isp_put_gid_ft_request(isp, rq, fcp->isp_scratch);
MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE);
- MEMZERO(&mbs, sizeof (mbs));
+ MBSINIT(&mbs, MBOX_SEND_SNS, MBLOGALL, 10000000);
mbs.param[0] = MBOX_SEND_SNS;
mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1;
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
- mbs.logval = MBLOGALL;
- mbs.timeout = 10000000;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
if (mbs.param[0] == MBOX_INVALID_COMMAND) {
@@ -3170,10 +3268,10 @@ isp_gid_ft_sns(ispsoftc_t *isp)
}
static int
-isp_gid_ft_ct_passthru(ispsoftc_t *isp)
+isp_gid_ft_ct_passthru(ispsoftc_t *isp, int chan)
{
mbreg_t mbs;
- fcparam *fcp = FCPARAM(isp);
+ fcparam *fcp = FCPARAM(isp, chan);
union {
isp_ct_pt_t plocal;
ct_hdr_t clocal;
@@ -3184,7 +3282,8 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp)
uint32_t *rp;
uint8_t *scp = fcp->isp_scratch;
- isp_prt(isp, ISP_LOGDEBUG0, "scanning fabric (GID_FT) via CT");
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "Chan %d scanning fabric (GID_FT) via CT", chan);
if (!IS_24XX(isp)) {
return (1);
@@ -3194,12 +3293,13 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp)
* Build a Passthrough IOCB in memory.
*/
pt = &un.plocal;
- MEMZERO(un.q, QENTRY_LEN);
+ ISP_MEMZERO(un.q, QENTRY_LEN);
pt->ctp_header.rqs_entry_count = 1;
pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
pt->ctp_handle = 0xffffffff;
- pt->ctp_nphdl = NPH_SNS_ID;
+ pt->ctp_nphdl = fcp->isp_sns_hdl;
pt->ctp_cmd_cnt = 1;
+ pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan);
pt->ctp_time = 30;
pt->ctp_rsp_cnt = 1;
pt->ctp_rsp_bcnt = GIDLEN;
@@ -3221,7 +3321,7 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp)
* Note that the CT header has to end up as Big Endian format in memory.
*/
ct = &un.clocal;
- MEMZERO(ct, sizeof (*ct));
+ ISP_MEMZERO(ct, sizeof (*ct));
ct->ct_revision = CT_REVISION;
ct->ct_fcs_type = CT_FC_TYPE_FC;
ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
@@ -3235,16 +3335,13 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp)
isp_print_bytes(isp, "CT HDR + payload after put",
sizeof (*ct) + sizeof (uint32_t), &scp[XTXOFF]);
}
- MEMZERO(&scp[ZTXOFF], QENTRY_LEN);
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64;
+ ISP_MEMZERO(&scp[ZTXOFF], QENTRY_LEN);
+ MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 500000);
mbs.param[1] = QENTRY_LEN;
mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
- mbs.timeout = 500000;
- mbs.logval = MBLOGALL;
MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
@@ -3258,8 +3355,9 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp)
}
if (pt->ctp_status && pt->ctp_status != RQCS_DATA_UNDERRUN) {
- isp_prt(isp, ISP_LOGWARN, "CT Passthrough returned 0x%x",
- pt->ctp_status);
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d ISP GID FT CT Passthrough returned 0x%x",
+ chan, pt->ctp_status);
return (-1);
}
MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN + 16);
@@ -3270,15 +3368,17 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp)
}
static int
-isp_scan_fabric(ispsoftc_t *isp)
+isp_scan_fabric(ispsoftc_t *isp, int chan)
{
- fcparam *fcp = FCPARAM(isp);
+ fcparam *fcp = FCPARAM(isp, chan);
uint32_t portid;
- uint16_t handle, oldhandle;
+ uint16_t handle, oldhandle, loopid;
+ isp_pdb_t pdb;
int portidx, portlim, r;
sns_gid_ft_rsp_t *rs0, *rs1;
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Scan Fabric");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d FC Scan Fabric", chan);
if (fcp->isp_fwstate != FW_READY ||
fcp->isp_loopstate < LOOP_LSCAN_DONE) {
return (-1);
@@ -3289,37 +3389,72 @@ isp_scan_fabric(ispsoftc_t *isp)
if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "FC Scan Fabric Done (no fabric)");
+ "Chan %d FC Scan Fabric Done (no fabric)", chan);
return (0);
}
- FC_SCRATCH_ACQUIRE(isp);
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ return (-1);
+ }
+ if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ return (-1);
+ }
+
+ /*
+ * Make sure we still are logged into the fabric controller.
+ */
+ if (IS_24XX(isp)) { /* XXX SHOULDN'T THIS BE TRUE FOR 2K F/W? XXX */
+ loopid = NPH_FL_ID;
+ } else {
+ loopid = FL_ID;
+ }
+ r = isp_getpdb(isp, chan, loopid, &pdb, 0);
+ if (r == MBOX_NOT_LOGGED_IN) {
+ isp_dump_chip_portdb(isp, chan, 0);
+ }
+ if (r) {
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ FC_SCRATCH_RELEASE(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ return (-1);
+ }
if (IS_24XX(isp)) {
- r = isp_gid_ft_ct_passthru(isp);
+ r = isp_gid_ft_ct_passthru(isp, chan);
} else {
- r = isp_gid_ft_sns(isp);
+ r = isp_gid_ft_sns(isp, chan);
+ }
+
+ if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ return (-1);
}
if (r > 0) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
return (0);
} else if (r < 0) {
fcp->isp_loopstate = LOOP_PDB_RCVD; /* try again */
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
return (0);
}
- if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp);
- return (-1);
- }
MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN);
rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF);
rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF);
isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
+ if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ return (-1);
+ }
if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) {
int level;
if (rs1->snscb_cthdr.ct_reason == 9 &&
@@ -3328,10 +3463,11 @@ isp_scan_fabric(ispsoftc_t *isp)
} else {
level = ISP_LOGWARN;
}
- isp_prt(isp, level, "Fabric Nameserver rejected GID_FT "
- "(Reason=0x%x Expl=0x%x)", rs1->snscb_cthdr.ct_reason,
+ isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_FT"
+ " (Reason=0x%x Expl=0x%x)", chan,
+ rs1->snscb_cthdr.ct_reason,
rs1->snscb_cthdr.ct_explanation);
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
fcp->isp_loopstate = LOOP_FSCAN_DONE;
return (0);
}
@@ -3345,12 +3481,10 @@ isp_scan_fabric(ispsoftc_t *isp)
/*
* Prime the handle we will start using.
*/
- oldhandle = NIL_HANDLE;
+ oldhandle = FCPARAM(isp, 0)->isp_lasthdl;
/*
- * Okay, we now have a list of Port IDs for all FC4 SCSI devices
- * that the Fabric Name server knows about. Go through the list
- * and remove duplicate port ids.
+ * Go through the list and remove duplicate port ids.
*/
portlim = 0;
@@ -3366,11 +3500,11 @@ isp_scan_fabric(ispsoftc_t *isp)
*/
if ((rs1->snscb_ports[portidx].control & 0x80) == 0) {
isp_prt(isp, ISP_LOGWARN,
- "fabric too big for scratch area: increase ISP2100_SCRLEN");
+ "fabric too big for scratch area: increase ISP_FC_SCRLEN");
}
portlim = portidx + 1;
isp_prt(isp, ISP_LOGSANCFG,
- "got %d ports back from name server", portlim);
+ "Chan %d got %d ports back from name server", chan, portlim);
for (portidx = 0; portidx < portlim; portidx++) {
int npidx;
@@ -3395,18 +3529,18 @@ isp_scan_fabric(ispsoftc_t *isp)
rs1->snscb_ports[npidx].portid[1] = 0;
rs1->snscb_ports[npidx].portid[2] = 0;
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "removing duplicate PortID 0x%x entry from list",
- portid);
+ "Chan %d removing duplicate PortID 0x%06x"
+ " entry from list", chan, portid);
}
}
/*
- * Okay, we now have a list of Port IDs for all FC4 SCSI devices
+ * We now have a list of Port IDs for all FC4 SCSI devices
* that the Fabric Name server knows about.
*
* For each entry on this list go through our port database looking
* for probational entries- if we find one, then an old entry is
- * is maybe still this one. We get some information to find out.
+ * maybe still this one. We get some information to find out.
*
* Otherwise, it's a new fabric device, and we log into it
* (unconditionally). After searching the entire database
@@ -3417,7 +3551,6 @@ isp_scan_fabric(ispsoftc_t *isp)
for (portidx = 0; portidx < portlim; portidx++) {
fcportdb_t *lp;
- isp_pdb_t pdb;
uint64_t wwnn, wwpn;
int dbidx, nr;
@@ -3428,20 +3561,35 @@ isp_scan_fabric(ispsoftc_t *isp)
if (portid == 0) {
isp_prt(isp, ISP_LOGSANCFG,
- "skipping null PortID at idx %d", portidx);
+ "Chan %d skipping null PortID at idx %d",
+ chan, portidx);
continue;
}
/*
- * Skip ourselves...
+ * Skip ourselves here and on other channels. If we're
+ * multi-id, we can't check the portids in other FCPARAM
+ * arenas because the resolutions here aren't synchronized.
+ * The best way to do this is to exclude looking at portids
+ * that have the same domain and area code as our own
+ * portid.
*/
- if (portid == fcp->isp_portid) {
+ if (ISP_CAP_MULTI_ID(isp)) {
+ if ((portid >> 8) == (fcp->isp_portid >> 8)) {
+ isp_prt(isp, ISP_LOGSANCFG,
+ "Chan %d skip PortID 0x%06x",
+ chan, portid);
+ continue;
+ }
+ } else if (portid == fcp->isp_portid) {
isp_prt(isp, ISP_LOGSANCFG,
- "skip ourselves @ PortID 0x%06x", portid);
+ "Chan %d skip ourselves on @ PortID 0x%06x",
+ chan, portid);
continue;
}
+
isp_prt(isp, ISP_LOGSANCFG,
- "Checking Fabric Port 0x%06x", portid);
+ "Chan %d Checking Fabric Port 0x%06x", chan, portid);
/*
* We now search our Port Database for any
@@ -3452,7 +3600,8 @@ isp_scan_fabric(ispsoftc_t *isp)
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
lp = &fcp->portdb[dbidx];
- if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
+ if (lp->state != FC_PORTDB_STATE_PROBATIONAL ||
+ lp->target_mode) {
continue;
}
if (lp->portid == portid) {
@@ -3485,18 +3634,18 @@ isp_scan_fabric(ispsoftc_t *isp)
*
*/
- r = isp_getpdb(isp, lp->handle, &pdb, 0);
+ r = isp_getpdb(isp, chan, lp->handle, &pdb, 0);
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp);
- ISP_MARK_PORTDB(isp, 1);
+ FC_SCRATCH_RELEASE(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
}
if (r != 0) {
lp->new_portid = portid;
lp->state = FC_PORTDB_STATE_DEAD;
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "Fabric Port 0x%06x considered dead",
- portid);
+ "Chan %d Fabric Port 0x%06x is dead",
+ chan, portid);
continue;
}
@@ -3514,7 +3663,7 @@ isp_scan_fabric(ispsoftc_t *isp)
wwpn != lp->port_wwn ||
wwnn != lp->node_wwn) {
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- fconf, dbidx, pdb.handle, pdb.portid,
+ fconf, chan, dbidx, pdb.handle, pdb.portid,
(uint32_t) (wwnn >> 32), (uint32_t) wwnn,
(uint32_t) (wwpn >> 32), (uint32_t) wwpn,
lp->handle, portid,
@@ -3525,23 +3674,30 @@ isp_scan_fabric(ispsoftc_t *isp)
/*
* Try to re-login to this device using a
* new handle. If that fails, mark it dead.
- *
+ *
* isp_login_device will check for handle and
* portid consistency after re-login.
- *
+ *
*/
- if (isp_login_device(isp, portid, &pdb,
+ if (isp_login_device(isp, chan, portid, &pdb,
&oldhandle)) {
lp->new_portid = portid;
lp->state = FC_PORTDB_STATE_DEAD;
if (fcp->isp_loopstate !=
LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp);
- ISP_MARK_PORTDB(isp, 1);
+ FC_SCRATCH_RELEASE(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
}
continue;
}
+ if (fcp->isp_loopstate !=
+ LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ return (-1);
+ }
+ FCPARAM(isp, 0)->isp_lasthdl = oldhandle;
MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
if (wwpn != lp->port_wwn ||
@@ -3576,12 +3732,13 @@ isp_scan_fabric(ispsoftc_t *isp)
if (pdb.portid != lp->portid || nr != lp->roles ||
handle_changed) {
isp_prt(isp, ISP_LOGSANCFG,
- "Fabric Port 0x%06x changed", portid);
+ "Chan %d Fabric Port 0x%06x changed",
+ chan, portid);
lp->state = FC_PORTDB_STATE_CHANGED;
} else {
isp_prt(isp, ISP_LOGSANCFG,
- "Fabric Port 0x%06x Now Pending Valid",
- portid);
+ "Chan %d Fabric Port 0x%06x "
+ "Now Pending Valid", chan, portid);
lp->state = FC_PORTDB_STATE_PENDING_VALID;
}
continue;
@@ -3593,13 +3750,19 @@ isp_scan_fabric(ispsoftc_t *isp)
* with the same port id. While we're at it, mark where the
* last free entry was.
*/
-
+
dbidx = MAX_FC_TARG;
for (lp = fcp->portdb; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
if (lp >= &fcp->portdb[FL_ID] &&
lp <= &fcp->portdb[SNS_ID]) {
continue;
}
+ /*
+ * Skip any target mode entries.
+ */
+ if (lp->target_mode) {
+ continue;
+ }
if (lp->state == FC_PORTDB_STATE_NIL) {
if (dbidx == MAX_FC_TARG) {
dbidx = lp - fcp->portdb;
@@ -3615,9 +3778,9 @@ isp_scan_fabric(ispsoftc_t *isp)
}
if (lp < &fcp->portdb[MAX_FC_TARG]) {
- isp_prt(isp, ISP_LOGWARN,
- "PortID 0x%06x already at %d handle %d state %d",
- portid, dbidx, lp->handle, lp->state);
+ isp_prt(isp, ISP_LOGWARN, "Chan %d PortID 0x%06x "
+ "already at %d handle %d state %d",
+ chan, portid, dbidx, lp->handle, lp->state);
continue;
}
@@ -3643,14 +3806,20 @@ isp_scan_fabric(ispsoftc_t *isp)
* isp_login_device will check for handle and
* portid consistency after login.
*/
- if (isp_login_device(isp, portid, &pdb, &oldhandle)) {
+ if (isp_login_device(isp, chan, portid, &pdb, &oldhandle)) {
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp);
- ISP_MARK_PORTDB(isp, 1);
+ FC_SCRATCH_RELEASE(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
}
continue;
}
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ return (-1);
+ }
+ FCPARAM(isp, 0)->isp_lasthdl = oldhandle;
handle = pdb.handle;
MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
@@ -3666,7 +3835,7 @@ isp_scan_fabric(ispsoftc_t *isp)
if (dbidx >= FL_ID && dbidx <= SNS_ID) {
continue;
}
- if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
+ if (fcp->portdb[dbidx].target_mode) {
continue;
}
if (fcp->portdb[dbidx].node_wwn == wwnn &&
@@ -3676,7 +3845,7 @@ isp_scan_fabric(ispsoftc_t *isp)
}
if (dbidx == MAX_FC_TARG) {
- MEMZERO(lp, sizeof (fcportdb_t));
+ ISP_MEMZERO(lp, sizeof (fcportdb_t));
lp->handle = handle;
lp->node_wwn = wwnn;
lp->port_wwn = wwpn;
@@ -3684,14 +3853,15 @@ isp_scan_fabric(ispsoftc_t *isp)
lp->new_roles = nr;
lp->state = FC_PORTDB_STATE_NEW;
isp_prt(isp, ISP_LOGSANCFG,
- "Fabric Port 0x%06x is New Entry", portid);
+ "Chan %d Fabric Port 0x%06x is a New Entry",
+ chan, portid);
continue;
}
if (fcp->portdb[dbidx].state != FC_PORTDB_STATE_ZOMBIE) {
isp_prt(isp, ISP_LOGWARN,
- "PortID 0x%x 0x%08x%08x/0x%08x%08x %ld already at "
- "idx %d, state 0x%x", portid,
+ "Chan %d PortID 0x%x 0x%08x%08x/0x%08x%08x %ld "
+ "already at idx %d, state 0x%x", chan, portid,
(uint32_t) (wwnn >> 32), (uint32_t) wwnn,
(uint32_t) (wwpn >> 32), (uint32_t) wwpn,
(long) (lp - fcp->portdb), dbidx,
@@ -3713,23 +3883,25 @@ isp_scan_fabric(ispsoftc_t *isp)
lp->new_roles = nr;
if (lp->portid != portid || lp->roles != nr) {
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "Zombie Fabric Port 0x%06x Now Changed", portid);
+ "Chan %d Zombie Fabric Port 0x%06x Now Changed",
+ chan, portid);
lp->state = FC_PORTDB_STATE_CHANGED;
} else {
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "Zombie Fabric Port 0x%06x Now Pending Valid",
- portid);
+ "Chan %d Zombie Fabric Port 0x%06x "
+ "Now Pending Valid", chan, portid);
lp->state = FC_PORTDB_STATE_PENDING_VALID;
}
}
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
- ISP_MARK_PORTDB(isp, 1);
+ ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
}
fcp->isp_loopstate = LOOP_FSCAN_DONE;
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Scan Fabric Done");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Chan %d FC Scan Fabric Done", chan);
return (0);
}
@@ -3737,39 +3909,41 @@ isp_scan_fabric(ispsoftc_t *isp)
* Find an unused handle and try and use to login to a port.
*/
static int
-isp_login_device(ispsoftc_t *isp, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
+isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p,
+ uint16_t *ohp)
{
int lim, i, r;
uint16_t handle;
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_2KLOGIN(isp)) {
lim = NPH_MAX_2K;
} else {
lim = NPH_MAX;
}
- handle = isp_nxt_handle(isp, *ohp);
+ handle = isp_nxt_handle(isp, chan, *ohp);
for (i = 0; i < lim; i++) {
/*
* See if we're still logged into something with
* this handle and that something agrees with this
* port id.
*/
- r = isp_getpdb(isp, handle, p, 0);
+ r = isp_getpdb(isp, chan, handle, p, 0);
if (r == 0 && p->portid != portid) {
- (void) isp_plogx(isp, handle, portid,
+ (void) isp_plogx(isp, chan, handle, portid,
PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT, 1);
} else if (r == 0) {
break;
}
- if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
return (-1);
}
/*
* Now try and log into the device
*/
- r = isp_plogx(isp, handle, portid, PLOGX_FLG_CMD_PLOGI, 1);
- if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ r = isp_plogx(isp, chan, handle, portid,
+ PLOGX_FLG_CMD_PLOGI, 1);
+ if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
return (-1);
}
if (r == 0) {
@@ -3781,14 +3955,17 @@ isp_login_device(ispsoftc_t *isp, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
} else if (r != MBOX_LOOP_ID_USED) {
i = lim;
break;
+ } else if (r == MBOX_TIMEOUT) {
+ return (-1);
} else {
*ohp = handle;
- handle = isp_nxt_handle(isp, *ohp);
+ handle = isp_nxt_handle(isp, chan, *ohp);
}
}
if (i == lim) {
- isp_prt(isp, ISP_LOGWARN, "PLOGI 0x%06x failed", portid);
+ isp_prt(isp, ISP_LOGWARN, "Chan %d PLOGI 0x%06x failed",
+ chan, portid);
return (-1);
}
@@ -3797,34 +3974,35 @@ isp_login_device(ispsoftc_t *isp, uint32_t portid, isp_pdb_t *p, uint16_t *ohp)
* so we can crosscheck that it is still what we think it
* is and that we also have the role it plays
*/
- r = isp_getpdb(isp, handle, p, 0);
- if (FCPARAM(isp)->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ r = isp_getpdb(isp, chan, handle, p, 0);
+ if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
return (-1);
}
if (r != 0) {
- isp_prt(isp, ISP_LOGERR, "new device 0x%06x@0x%x disappeared",
- portid, handle);
+ isp_prt(isp, ISP_LOGERR,
+ "Chan %d new device 0x%06x@0x%x disappeared",
+ chan, portid, handle);
return (-1);
}
if (p->handle != handle || p->portid != portid) {
isp_prt(isp, ISP_LOGERR,
- "new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
- portid, handle, p->portid, p->handle);
+ "Chan %d new device 0x%06x@0x%x changed (0x%06x@0x%0x)",
+ chan, portid, handle, p->portid, p->handle);
return (-1);
}
return (0);
}
static int
-isp_register_fc4_type(ispsoftc_t *isp)
+isp_register_fc4_type(ispsoftc_t *isp, int chan)
{
- fcparam *fcp = isp->isp_param;
+ fcparam *fcp = FCPARAM(isp, chan);
uint8_t local[SNS_RFT_ID_REQ_SIZE];
sns_screq_t *reqp = (sns_screq_t *) local;
mbreg_t mbs;
- MEMZERO((void *) reqp, SNS_RFT_ID_REQ_SIZE);
+ ISP_MEMZERO((void *) reqp, SNS_RFT_ID_REQ_SIZE);
reqp->snscb_rblen = SNS_RFT_ID_RESP_SIZE >> 1;
reqp->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + 0x100);
reqp->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + 0x100);
@@ -3835,20 +4013,20 @@ isp_register_fc4_type(ispsoftc_t *isp)
reqp->snscb_data[4] = fcp->isp_portid & 0xffff;
reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff;
reqp->snscb_data[6] = (1 << FC4_SCSI);
- FC_SCRATCH_ACQUIRE(isp);
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return (-1);
+ }
isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch);
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_SEND_SNS;
+ MBSINIT(&mbs, MBOX_SEND_SNS, MBLOGALL, 1000000);
mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1;
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
- mbs.logval = MBLOGALL;
- mbs.timeout = 10000000;
MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_RFT_ID_REQ_SIZE);
isp_mboxcmd(isp, &mbs);
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
return (0);
} else {
@@ -3857,10 +4035,10 @@ isp_register_fc4_type(ispsoftc_t *isp)
}
static int
-isp_register_fc4_type_24xx(ispsoftc_t *isp)
+isp_register_fc4_type_24xx(ispsoftc_t *isp, int chan)
{
mbreg_t mbs;
- fcparam *fcp = FCPARAM(isp);
+ fcparam *fcp = FCPARAM(isp, chan);
union {
isp_ct_pt_t plocal;
rft_id_t clocal;
@@ -3871,17 +4049,22 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp)
rft_id_t *rp;
uint8_t *scp = fcp->isp_scratch;
- FC_SCRATCH_ACQUIRE(isp);
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return (-1);
+ }
+
/*
* Build a Passthrough IOCB in memory.
*/
- MEMZERO(un.q, QENTRY_LEN);
+ ISP_MEMZERO(un.q, QENTRY_LEN);
pt = &un.plocal;
pt->ctp_header.rqs_entry_count = 1;
pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
pt->ctp_handle = 0xffffffff;
- pt->ctp_nphdl = NPH_SNS_ID;
+ pt->ctp_nphdl = fcp->isp_sns_hdl;
pt->ctp_cmd_cnt = 1;
+ pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan);
pt->ctp_time = 1;
pt->ctp_rsp_cnt = 1;
pt->ctp_rsp_bcnt = sizeof (ct_hdr_t);
@@ -3893,13 +4076,16 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp)
pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF);
pt->ctp_dataseg[1].ds_count = sizeof (ct_hdr_t);
isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]);
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "IOCB CT Request", QENTRY_LEN, pt);
+ }
/*
* Build the CT header and command in memory.
*
* Note that the CT header has to end up as Big Endian format in memory.
*/
- MEMZERO(&un.clocal, sizeof (un.clocal));
+ ISP_MEMZERO(&un.clocal, sizeof (un.clocal));
ct = &un.clocal.rftid_hdr;
ct->ct_revision = CT_REVISION;
ct->ct_fcs_type = CT_FC_TYPE_FC;
@@ -3912,22 +4098,22 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp)
rp->rftid_portid[2] = fcp->isp_portid;
rp->rftid_fc4types[FC4_SCSI >> 5] = 1 << (FC4_SCSI & 0x1f);
isp_put_rft_id(isp, rp, (rft_id_t *) &scp[XTXOFF]);
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "CT Header", QENTRY_LEN, &scp[XTXOFF]);
+ }
- MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t));
+ ISP_MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t));
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_EXEC_COMMAND_IOCB_A64;
+ MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 1000000);
mbs.param[1] = QENTRY_LEN;
mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
- mbs.timeout = 500000;
- mbs.logval = MBLOGALL;
MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
return (-1);
}
MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN);
@@ -3937,36 +4123,38 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp)
isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt);
}
if (pt->ctp_status) {
- FC_SCRATCH_RELEASE(isp);
- isp_prt(isp, ISP_LOGWARN, "CT Passthrough returned 0x%x",
- pt->ctp_status);
- return (-1);
+ FC_SCRATCH_RELEASE(isp, chan);
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d Register FC4 Type CT Passthrough returned 0x%x",
+ chan, pt->ctp_status);
+ return (1);
}
isp_get_ct_hdr(isp, (ct_hdr_t *) &scp[IGPOFF], ct);
- FC_SCRATCH_RELEASE(isp);
+ FC_SCRATCH_RELEASE(isp, chan);
if (ct->ct_cmd_resp == LS_RJT) {
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "Register FC4 Type rejected");
+ "Chan %d Register FC4 Type rejected", chan);
return (-1);
} else if (ct->ct_cmd_resp == LS_ACC) {
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "Register FC4 Type accepted");
- return(0);
+ "Chan %d Register FC4 Type accepted", chan);
+ return (0);
} else {
isp_prt(isp, ISP_LOGWARN,
- "Register FC4 Type: 0x%x", ct->ct_cmd_resp);
+ "Chan %d Register FC4 Type: 0x%x",
+ chan, ct->ct_cmd_resp);
return (-1);
}
}
static uint16_t
-isp_nxt_handle(ispsoftc_t *isp, uint16_t handle)
+isp_nxt_handle(ispsoftc_t *isp, int chan, uint16_t handle)
{
int i;
if (handle == NIL_HANDLE) {
- if (FCPARAM(isp)->isp_topo == TOPO_F_PORT) {
+ if (FCPARAM(isp, chan)->isp_topo == TOPO_F_PORT) {
handle = 0;
} else {
handle = SNS_ID+1;
@@ -3979,7 +4167,7 @@ isp_nxt_handle(ispsoftc_t *isp, uint16_t handle)
if (handle >= NPH_RESERVED && handle <= NPH_FL_ID) {
handle = NPH_FL_ID+1;
}
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_2KLOGIN(isp)) {
if (handle == NPH_MAX_2K) {
handle = 0;
}
@@ -3989,15 +4177,16 @@ isp_nxt_handle(ispsoftc_t *isp, uint16_t handle)
}
}
}
- if (handle == FCPARAM(isp)->isp_loopid) {
- return (isp_nxt_handle(isp, handle));
+ if (handle == FCPARAM(isp, chan)->isp_loopid) {
+ return (isp_nxt_handle(isp, chan, handle));
}
for (i = 0; i < MAX_FC_TARG; i++) {
- if (FCPARAM(isp)->portdb[i].state == FC_PORTDB_STATE_NIL) {
+ if (FCPARAM(isp, chan)->portdb[i].state ==
+ FC_PORTDB_STATE_NIL) {
continue;
}
- if (FCPARAM(isp)->portdb[i].handle == handle) {
- return (isp_nxt_handle(isp, handle));
+ if (FCPARAM(isp, chan)->portdb[i].handle == handle) {
+ return (isp_nxt_handle(isp, chan, handle));
}
}
return (handle);
@@ -4011,25 +4200,17 @@ int
isp_start(XS_T *xs)
{
ispsoftc_t *isp;
- uint32_t nxti, optr, handle;
+ uint32_t handle;
uint8_t local[QENTRY_LEN];
- ispreq_t *reqp, *qep;
- void *cdbp;
+ ispreq_t *reqp;
+ void *cdbp, *qep;
uint16_t *tptr;
- int target, i, hdlidx = 0;
+ int target, dmaresult, hdlidx = 0;
XS_INITERR(xs);
isp = XS_ISP(xs);
/*
- * Check to make sure we're supporting initiator role.
- */
- if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
- XS_SETERR(xs, HBA_SELTIMEOUT);
- return (CMD_COMPLETE);
- }
-
- /*
* Now make sure we're running.
*/
@@ -4047,9 +4228,7 @@ isp_start(XS_T *xs)
*/
if (XS_CDBLEN(xs) > (IS_FC(isp)? 16 : 44) || XS_CDBLEN(xs) == 0) {
- isp_prt(isp, ISP_LOGERR,
- "unsupported cdb length (%d, CDB[0]=0x%x)",
- XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
+ isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
XS_SETERR(xs, HBA_BOTCH);
return (CMD_COMPLETE);
}
@@ -4060,13 +4239,17 @@ isp_start(XS_T *xs)
*/
target = XS_TGT(xs);
if (IS_FC(isp)) {
- fcparam *fcp = isp->isp_param;
+ fcparam *fcp = FCPARAM(isp, XS_CHANNEL(xs));
+
+ if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
+ XS_SETERR(xs, HBA_SELTIMEOUT);
+ return (CMD_COMPLETE);
+ }
/*
* Try again later.
*/
- if (fcp->isp_fwstate != FW_READY ||
- fcp->isp_loopstate != LOOP_READY) {
+ if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) {
return (CMD_RQLATER);
}
@@ -4075,9 +4258,8 @@ isp_start(XS_T *xs)
return (CMD_COMPLETE);
}
- hdlidx = fcp->isp_ini_map[XS_TGT(xs)] - 1;
- isp_prt(isp, ISP_LOGDEBUG1, "XS_TGT(xs)=%d- hdlidx value %d",
- XS_TGT(xs), hdlidx);
+ hdlidx = fcp->isp_dev_map[XS_TGT(xs)] - 1;
+ isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d- hdlidx value %d", XS_TGT(xs), hdlidx);
if (hdlidx < 0 || hdlidx >= MAX_FC_TARG) {
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
@@ -4090,22 +4272,27 @@ isp_start(XS_T *xs)
return (CMD_COMPLETE);
}
target = fcp->portdb[hdlidx].handle;
- }
-
- /*
- * Next check to see if any HBA or Device parameters need to be updated.
- */
- if (isp->isp_update != 0) {
- isp_update(isp);
+ fcp->portdb[hdlidx].dirty = 1;
+ } else {
+ sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
+ if ((sdp->role & ISP_ROLE_INITIATOR) == 0) {
+ XS_SETERR(xs, HBA_SELTIMEOUT);
+ return (CMD_COMPLETE);
+ }
+ if (sdp->update) {
+ isp_spi_update(isp, XS_CHANNEL(xs));
+ }
}
start_again:
- if (isp_getrqentry(isp, &nxti, &optr, (void *)&qep)) {
+ qep = isp_getrqentry(isp);
+ if (qep == NULL) {
isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow");
XS_SETERR(xs, HBA_BOTCH);
return (CMD_EAGAIN);
}
+ XS_SETERR(xs, HBA_NOERROR);
/*
* Now see if we need to synchronize the ISP with respect to anything.
@@ -4113,47 +4300,38 @@ isp_start(XS_T *xs)
* than which we got here to send a command to.
*/
reqp = (ispreq_t *) local;
- if (isp->isp_sendmarker) {
+ ISP_MEMZERO(local, QENTRY_LEN);
+ if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) {
if (IS_24XX(isp)) {
- isp_marker_24xx_t *m = (isp_marker_24xx_t *) qep;
- MEMZERO(m, QENTRY_LEN);
+ isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp;
m->mrk_header.rqs_entry_count = 1;
m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
m->mrk_modifier = SYNC_ALL;
- isp_put_marker_24xx(isp, m, (isp_marker_24xx_t *)qep);
- ISP_ADD_REQUEST(isp, nxti);
- isp->isp_sendmarker = 0;
- goto start_again;
+ isp_put_marker_24xx(isp, m, qep);
} else {
- for (i = 0; i < (IS_DUALBUS(isp)? 2: 1); i++) {
- isp_marker_t *m = (isp_marker_t *) qep;
- if ((isp->isp_sendmarker & (1 << i)) == 0) {
- continue;
- }
- MEMZERO(m, QENTRY_LEN);
- m->mrk_header.rqs_entry_count = 1;
- m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
- m->mrk_target = (i << 7); /* bus # */
- m->mrk_modifier = SYNC_ALL;
- isp_put_marker(isp, m, (isp_marker_t *) qep);
- ISP_ADD_REQUEST(isp, nxti);
- isp->isp_sendmarker &= ~(1 << i);
- goto start_again;
- }
+ isp_marker_t *m = (isp_marker_t *) reqp;
+ m->mrk_header.rqs_entry_count = 1;
+ m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
+ m->mrk_target = (XS_CHANNEL(xs) << 7); /* bus # */
+ m->mrk_modifier = SYNC_ALL;
+ isp_put_marker(isp, m, qep);
}
+ ISP_SYNC_REQUEST(isp);
+ ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0);
+ goto start_again;
}
- MEMZERO((void *)reqp, QENTRY_LEN);
reqp->req_header.rqs_entry_count = 1;
if (IS_24XX(isp)) {
reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
} else if (IS_FC(isp)) {
reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
} else {
- if (XS_CDBLEN(xs) > 12)
+ if (XS_CDBLEN(xs) > 12) {
reqp->req_header.rqs_entry_type = RQSTYPE_CMDONLY;
- else
+ } else {
reqp->req_header.rqs_entry_type = RQSTYPE_REQUEST;
+ }
}
/* reqp->req_header.rqs_flags = 0; */
/* reqp->req_header.rqs_seqno = 0; */
@@ -4180,7 +4358,7 @@ isp_start(XS_T *xs)
/*
* See comment in isp_intr
*/
- /* XS_RESID(xs) = 0; */
+ /* XS_SET_RESID(xs, 0); */
/*
* Fibre Channel always requires some kind of tag.
@@ -4200,10 +4378,8 @@ isp_start(XS_T *xs)
((ispreqt2_t *)reqp)->req_flags = REQFLAG_STAG;
}
} else {
- sdparam *sdp = (sdparam *)isp->isp_param;
- sdp += XS_CHANNEL(xs);
- if ((sdp->isp_devparam[target].actv_flags & DPARM_TQING) &&
- XS_TAG_P(xs)) {
+ sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
+ if ((sdp->isp_devparam[target].actv_flags & DPARM_TQING) && XS_TAG_P(xs)) {
reqp->req_flags = XS_TAG_TYPE(xs);
}
}
@@ -4217,10 +4393,11 @@ isp_start(XS_T *xs)
} else if (IS_24XX(isp)) {
fcportdb_t *lp;
- lp = &FCPARAM(isp)->portdb[hdlidx];
+ lp = &FCPARAM(isp, XS_CHANNEL(xs))->portdb[hdlidx];
((ispreqt7_t *)reqp)->req_nphdl = target;
((ispreqt7_t *)reqp)->req_tidlo = lp->portid;
((ispreqt7_t *)reqp)->req_tidhi = lp->portid >> 16;
+ ((ispreqt7_t *)reqp)->req_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(xs));
if (XS_LUN(xs) > 256) {
((ispreqt7_t *)reqp)->req_lun[0] = XS_LUN(xs) >> 8;
((ispreqt7_t *)reqp)->req_lun[0] |= 0x40;
@@ -4228,17 +4405,17 @@ isp_start(XS_T *xs)
((ispreqt7_t *)reqp)->req_lun[1] = XS_LUN(xs);
cdbp = ((ispreqt7_t *)reqp)->req_cdb;
tptr = &((ispreqt7_t *)reqp)->req_time;
- } else if (FCPARAM(isp)->isp_2klogin) {
+ } else if (ISP_CAP_2KLOGIN(isp)) {
((ispreqt2e_t *)reqp)->req_target = target;
((ispreqt2e_t *)reqp)->req_scclun = XS_LUN(xs);
- } else if (FCPARAM(isp)->isp_sccfw) {
+ } else if (ISP_CAP_SCCFW(isp)) {
((ispreqt2_t *)reqp)->req_target = target;
((ispreqt2_t *)reqp)->req_scclun = XS_LUN(xs);
} else {
((ispreqt2_t *)reqp)->req_target = target;
((ispreqt2_t *)reqp)->req_lun_trn = XS_LUN(xs);
}
- MEMCPY(cdbp, XS_CDBP(xs), XS_CDBLEN(xs));
+ ISP_MEMCPY(cdbp, XS_CDBP(xs), XS_CDBLEN(xs));
*tptr = XS_TIME(xs) / 1000;
if (*tptr == 0 && XS_TIME(xs)) {
@@ -4257,24 +4434,21 @@ isp_start(XS_T *xs)
reqp->req_handle = handle;
/*
- * Set up DMA and/or do any bus swizzling of the request entry
+ * Set up DMA and/or do any platform dependent swizzling of the request entry
* so that the Qlogic F/W understands what is being asked of it.
+ *
+ * The callee is responsible for adding all requests at this point.
*/
- i = ISP_DMASETUP(isp, xs, reqp, &nxti, optr);
- if (i != CMD_QUEUED) {
+ dmaresult = ISP_DMASETUP(isp, xs, reqp);
+ if (dmaresult != CMD_QUEUED) {
isp_destroy_handle(isp, handle);
/*
* dmasetup sets actual error in packet, and
* return what we were given to return.
*/
- return (i);
+ return (dmaresult);
}
- XS_SETERR(xs, HBA_NOERROR);
- isp_prt(isp, ISP_LOGDEBUG0,
- "START cmd for %d.%d.%d cmd 0x%x datalen %ld",
- XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0],
- (long) XS_XFRLEN(xs));
- ISP_ADD_REQUEST(isp, nxti);
+ isp_prt(isp, ISP_LOGDEBUG0, "START cmd for %d.%d.%d cmd 0x%x datalen %ld", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
isp->isp_nactive++;
return (CMD_QUEUED);
}
@@ -4285,20 +4459,15 @@ isp_start(XS_T *xs)
*/
int
-isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
+isp_control(ispsoftc_t *isp, ispctl_t ctl, ...)
{
XS_T *xs;
- mbreg_t mbs;
- int bus, tgt;
+ mbreg_t *mbr, mbs;
+ int chan, tgt;
uint32_t handle;
-
- MEMZERO(&mbs, sizeof (mbs));
+ va_list ap;
switch (ctl) {
- default:
- isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
- break;
-
case ISPCTL_RESET_BUS:
/*
* Issue a bus reset.
@@ -4308,60 +4477,128 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
break;
} else if (IS_FC(isp)) {
mbs.param[1] = 10;
- bus = 0;
+ chan = 0;
} else {
- mbs.param[1] = SDPARAM(isp)->isp_bus_reset_delay;
+ va_start(ap, ctl);
+ chan = va_arg(ap, int);
+ va_end(ap);
+ mbs.param[1] = SDPARAM(isp, chan)->isp_bus_reset_delay;
if (mbs.param[1] < 2) {
mbs.param[1] = 2;
}
- bus = *((int *) arg);
- if (IS_DUALBUS(isp)) {
- mbs.param[2] = bus;
- }
+ mbs.param[2] = chan;
}
- mbs.param[0] = MBOX_BUS_RESET;
- isp->isp_sendmarker |= (1 << bus);
- mbs.logval = MBLOGALL;
+ MBSINIT(&mbs, MBOX_BUS_RESET, MBLOGALL, 0);
+ ISP_SET_SENDMARKER(isp, chan, 1);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
break;
}
isp_prt(isp, ISP_LOGINFO,
- "driver initiated bus reset of bus %d", bus);
+ "driver initiated bus reset of bus %d", chan);
return (0);
case ISPCTL_RESET_DEV:
- tgt = (*((int *) arg)) & 0xffff;
+ va_start(ap, ctl);
+ chan = va_arg(ap, int);
+ tgt = va_arg(ap, int);
+ va_end(ap);
if (IS_24XX(isp)) {
- isp_prt(isp, ISP_LOGWARN, "RESET DEV NOT IMPLEMENTED");
+ uint8_t local[QENTRY_LEN];
+ isp24xx_tmf_t *tmf;
+ isp24xx_statusreq_t *sp;
+ fcparam *fcp = FCPARAM(isp, chan);
+ fcportdb_t *lp;
+ int hdlidx;
+
+ hdlidx = fcp->isp_dev_map[tgt] - 1;
+ if (hdlidx < 0 || hdlidx >= MAX_FC_TARG) {
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d bad handle %d trying to reset"
+ "target %d", chan, hdlidx, tgt);
+ break;
+ }
+ lp = &fcp->portdb[hdlidx];
+ if (lp->state != FC_PORTDB_STATE_VALID) {
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d handle %d for abort of target %d "
+ "no longer valid", chan,
+ hdlidx, tgt);
+ break;
+ }
+
+ tmf = (isp24xx_tmf_t *) local;
+ ISP_MEMZERO(tmf, QENTRY_LEN);
+ tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
+ tmf->tmf_header.rqs_entry_count = 1;
+ tmf->tmf_nphdl = lp->handle;
+ tmf->tmf_delay = 2;
+ tmf->tmf_timeout = 2;
+ tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
+ tmf->tmf_tidlo = lp->portid;
+ tmf->tmf_tidhi = lp->portid >> 16;
+ tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
+ isp_prt(isp, ISP_LOGALL, "Chan %d Reset N-Port Handle 0x%04x @ Port 0x%06x", chan, lp->handle, lp->portid);
+ MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000);
+ mbs.param[1] = QENTRY_LEN;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ break;
+ }
+ isp_put_24xx_tmf(isp, tmf, fcp->isp_scratch);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN);
+ fcp->sendmarker = 1;
+ isp_mboxcmd(isp, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ break;
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN,
+ QENTRY_LEN);
+ sp = (isp24xx_statusreq_t *) local;
+ isp_get_24xx_response(isp,
+ &((isp24xx_statusreq_t *)fcp->isp_scratch)[1], sp);
+ FC_SCRATCH_RELEASE(isp, chan);
+ if (sp->req_completion_status == 0) {
+ return (0);
+ }
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d reset of target %d returned 0x%x",
+ chan, tgt, sp->req_completion_status);
break;
} else if (IS_FC(isp)) {
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_2KLOGIN(isp)) {
mbs.param[1] = tgt;
mbs.ibits = (1 << 10);
} else {
mbs.param[1] = (tgt << 8);
}
- bus = 0;
} else {
- bus = (*((int *) arg)) >> 16;
- mbs.param[1] = (bus << 15) | (tgt << 8);
+ mbs.param[1] = (chan << 15) | (tgt << 8);
}
- mbs.param[0] = MBOX_ABORT_TARGET;
+ MBSINIT(&mbs, MBOX_ABORT_TARGET, MBLOGALL, 0);
mbs.param[2] = 3; /* 'delay', in seconds */
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
break;
}
isp_prt(isp, ISP_LOGINFO,
- "Target %d on Bus %d Reset Succeeded", tgt, bus);
- isp->isp_sendmarker |= (1 << bus);
+ "Target %d on Bus %d Reset Succeeded", tgt, chan);
+ ISP_SET_SENDMARKER(isp, chan, 1);
return (0);
case ISPCTL_ABORT_CMD:
- xs = (XS_T *) arg;
+ va_start(ap, ctl);
+ xs = va_arg(ap, XS_T *);
+ va_end(ap);
+
tgt = XS_TGT(xs);
+ chan = XS_CHANNEL(xs);
handle = isp_find_handle(isp, xs);
if (handle == 0) {
@@ -4370,11 +4607,74 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
break;
}
if (IS_24XX(isp)) {
- isp_prt(isp, ISP_LOGWARN, "ABORT CMD NOT IMPLEMENTED");
+ isp24xx_abrt_t local, *ab = &local, *ab2;
+ fcparam *fcp;
+ fcportdb_t *lp;
+ int hdlidx;
+
+ fcp = FCPARAM(isp, chan);
+ hdlidx = fcp->isp_dev_map[tgt] - 1;
+ if (hdlidx < 0 || hdlidx >= MAX_FC_TARG) {
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d bad handle %d trying to abort"
+ "target %d", chan, hdlidx, tgt);
+ break;
+ }
+ lp = &fcp->portdb[hdlidx];
+ if (lp->state != FC_PORTDB_STATE_VALID) {
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d handle %d for abort of target %d "
+ "no longer valid", chan, hdlidx, tgt);
+ break;
+ }
+ isp_prt(isp, ISP_LOGALL,
+ "Chan %d Abort Cmd for N-Port 0x%04x @ Port "
+ "0x%06x %p", chan, lp->handle, lp->portid, xs);
+ ISP_MEMZERO(ab, QENTRY_LEN);
+ ab->abrt_header.rqs_entry_type = RQSTYPE_ABORT_IO;
+ ab->abrt_header.rqs_entry_count = 1;
+ ab->abrt_handle = lp->handle;
+ ab->abrt_cmd_handle = handle;
+ ab->abrt_tidlo = lp->portid;
+ ab->abrt_tidhi = lp->portid >> 16;
+ ab->abrt_vpidx = ISP_GET_VPIDX(isp, chan);
+
+ ISP_MEMZERO(&mbs, sizeof (mbs));
+ MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000);
+ mbs.param[1] = QENTRY_LEN;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ break;
+ }
+ isp_put_24xx_abrt(isp, ab, fcp->isp_scratch);
+ ab2 = (isp24xx_abrt_t *)
+ &((uint8_t *)fcp->isp_scratch)[QENTRY_LEN];
+ ab2->abrt_nphdl = 0xdeaf;
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, 2 * QENTRY_LEN);
+ isp_mboxcmd(isp, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ break;
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN,
+ QENTRY_LEN);
+ isp_get_24xx_abrt(isp, ab2, ab);
+ FC_SCRATCH_RELEASE(isp, chan);
+ if (ab->abrt_nphdl == ISP24XX_ABRT_OKAY) {
+ return (0);
+ }
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d handle %d abort returned 0x%x", chan,
+ hdlidx, ab->abrt_nphdl);
break;
} else if (IS_FC(isp)) {
- if (FCPARAM(isp)->isp_sccfw) {
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_SCCFW(isp)) {
+ if (ISP_CAP_2KLOGIN(isp)) {
mbs.param[1] = tgt;
} else {
mbs.param[1] = tgt << 8;
@@ -4384,12 +4684,10 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
mbs.param[1] = tgt << 8 | XS_LUN(xs);
}
} else {
- bus = XS_CHANNEL(xs);
- mbs.param[1] = (bus << 15) | (tgt << 8) | XS_LUN(xs);
+ mbs.param[1] = (chan << 15) | (tgt << 8) | XS_LUN(xs);
}
- mbs.param[0] = MBOX_ABORT;
+ MBSINIT(&mbs, MBOX_ABORT, MBLOGALL & ~MBOX_COMMAND_ERROR, 0);
mbs.param[2] = handle;
- mbs.logval = MBLOGALL & ~MBOX_COMMAND_ERROR;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
break;
@@ -4398,49 +4696,64 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
case ISPCTL_UPDATE_PARAMS:
- isp_update(isp);
+ va_start(ap, ctl);
+ chan = va_arg(ap, int);
+ va_end(ap);
+ isp_spi_update(isp, chan);
return (0);
case ISPCTL_FCLINK_TEST:
if (IS_FC(isp)) {
- int usdelay = *((int *) arg);
+ int usdelay;
+ va_start(ap, ctl);
+ chan = va_arg(ap, int);
+ usdelay = va_arg(ap, int);
+ va_end(ap);
if (usdelay == 0) {
usdelay = 250000;
}
- return (isp_fclink_test(isp, usdelay));
+ return (isp_fclink_test(isp, chan, usdelay));
}
break;
case ISPCTL_SCAN_FABRIC:
if (IS_FC(isp)) {
- return (isp_scan_fabric(isp));
+ va_start(ap, ctl);
+ chan = va_arg(ap, int);
+ va_end(ap);
+ return (isp_scan_fabric(isp, chan));
}
break;
case ISPCTL_SCAN_LOOP:
if (IS_FC(isp)) {
- return (isp_scan_loop(isp));
+ va_start(ap, ctl);
+ chan = va_arg(ap, int);
+ va_end(ap);
+ return (isp_scan_loop(isp, chan));
}
break;
case ISPCTL_PDB_SYNC:
if (IS_FC(isp)) {
- return (isp_pdb_sync(isp));
+ va_start(ap, ctl);
+ chan = va_arg(ap, int);
+ va_end(ap);
+ return (isp_pdb_sync(isp, chan));
}
break;
case ISPCTL_SEND_LIP:
if (IS_FC(isp) && !IS_24XX(isp)) {
- mbs.param[0] = MBOX_INIT_LIP;
- if (FCPARAM(isp)->isp_2klogin) {
+ MBSINIT(&mbs, MBOX_INIT_LIP, MBLOGALL, 0);
+ if (ISP_CAP_2KLOGIN(isp)) {
mbs.ibits = (1 << 10);
}
- mbs.logval = MBLOGALL;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
return (0);
@@ -4449,42 +4762,66 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
break;
case ISPCTL_GET_PDB:
- if (IS_FC(isp) && arg) {
- int id = *((int *)arg);
- isp_pdb_t *pdb = arg;
- return (isp_getpdb(isp, id, pdb, 1));
+ if (IS_FC(isp)) {
+ isp_pdb_t *pdb;
+ va_start(ap, ctl);
+ chan = va_arg(ap, int);
+ tgt = va_arg(ap, int);
+ pdb = va_arg(ap, isp_pdb_t *);
+ va_end(ap);
+ return (isp_getpdb(isp, chan, tgt, pdb, 1));
}
break;
- case ISPCTL_GET_PORTNAME:
+ case ISPCTL_GET_NAMES:
{
- uint64_t *wwnp = arg;
- int loopid = *wwnp;
- *wwnp = isp_get_portname(isp, loopid, 0);
- if (*wwnp == (uint64_t) -1) {
+ uint64_t *wwnn, *wwnp;
+ va_start(ap, ctl);
+ chan = va_arg(ap, int);
+ tgt = va_arg(ap, int);
+ wwnn = va_arg(ap, uint64_t *);
+ wwnp = va_arg(ap, uint64_t *);
+ va_end(ap);
+ if (wwnn == NULL && wwnp == NULL) {
break;
- } else {
- return (0);
}
+ if (wwnn) {
+ *wwnn = isp_get_wwn(isp, chan, tgt, 1);
+ if (*wwnn == INI_NONE) {
+ break;
+ }
+ }
+ if (wwnp) {
+ *wwnp = isp_get_wwn(isp, chan, tgt, 0);
+ if (*wwnp == INI_NONE) {
+ break;
+ }
+ }
+ return (0);
}
case ISPCTL_RUN_MBOXCMD:
-
- isp_mboxcmd(isp, arg);
- return(0);
-
+ {
+ va_start(ap, ctl);
+ mbr = va_arg(ap, mbreg_t *);
+ va_end(ap);
+ isp_mboxcmd(isp, mbr);
+ return (0);
+ }
case ISPCTL_PLOGX:
{
- isp_plcmd_t *p = arg;
+ isp_plcmd_t *p;
int r;
- if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI ||
- (p->handle != NIL_HANDLE)) {
- return (isp_plogx(isp, p->handle, p->portid,
- p->flags, 0));
+ va_start(ap, ctl);
+ p = va_arg(ap, isp_plcmd_t *);
+ va_end(ap);
+
+ if ((p->flags & PLOGX_FLG_CMD_MASK) != PLOGX_FLG_CMD_PLOGI || (p->handle != NIL_HANDLE)) {
+ return (isp_plogx(isp, p->channel, p->handle, p->portid, p->flags, 0));
}
do {
- p->handle = isp_nxt_handle(isp, p->handle);
- r = isp_plogx(isp, p->handle, p->portid, p->flags, 0);
+ p->handle = isp_nxt_handle(isp, p->channel, p->handle);
+ r = isp_plogx(isp, p->channel, p->handle, p->portid, p->flags, 0);
if ((r & 0xffff) == MBOX_PORT_ID_USED) {
p->handle = r >> 16;
r = 0;
@@ -4493,28 +4830,10 @@ isp_control(ispsoftc_t *isp, ispctl_t ctl, void *arg)
} while ((r & 0xffff) == MBOX_LOOP_ID_USED);
return (r);
}
-#ifdef ISP_TARGET_MODE
- case ISPCTL_TOGGLE_TMODE:
- {
+ default:
+ isp_prt(isp, ISP_LOGERR, "Unknown Control Opcode 0x%x", ctl);
+ break;
- /*
- * We don't check/set against role here- that's the
- * responsibility for the outer layer to coordinate.
- */
- if (IS_SCSI(isp)) {
- int param = *(int *)arg;
- mbs.param[0] = MBOX_ENABLE_TARGET_MODE;
- mbs.param[1] = param & 0xffff;
- mbs.param[2] = param >> 16;
- mbs.logval = MBLOGALL;
- isp_mboxcmd(isp, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- break;
- }
- }
- return (0);
- }
-#endif
}
return (-1);
}
@@ -4548,6 +4867,7 @@ again:
* The mailbox semaphore will be nonzero if so.
*/
if (sema) {
+ fmbox:
if (mbox & 0x4000) {
isp->isp_intmboxc++;
if (isp->isp_mboxbsy) {
@@ -4557,8 +4877,7 @@ again:
if ((obits & (1 << i)) == 0) {
continue;
}
- isp->isp_mboxtmp[i] =
- ISP_READ(isp, MBOX_OFF(i));
+ isp->isp_mboxtmp[i] = ISP_READ(isp, MBOX_OFF(i));
}
if (isp->isp_mbxwrk0) {
if (isp_mbox_continue(isp) == 0) {
@@ -4567,14 +4886,12 @@ again:
}
MBOX_NOTIFY_COMPLETE(isp);
} else {
- isp_prt(isp, ISP_LOGWARN,
- "mailbox cmd (0x%x) with no waiters", mbox);
+ isp_prt(isp, ISP_LOGWARN, "mailbox cmd (0x%x) with no waiters", mbox);
}
} else if (isp_parse_async(isp, mbox) < 0) {
return;
}
- if ((IS_FC(isp) && mbox != ASYNC_RIO_RESP) ||
- isp->isp_state != ISP_RUNSTATE) {
+ if ((IS_FC(isp) && mbox != ASYNC_RIO_RESP) || isp->isp_state != ISP_RUNSTATE) {
goto out;
}
}
@@ -4583,13 +4900,17 @@ again:
* We can't be getting this now.
*/
if (isp->isp_state != ISP_RUNSTATE) {
- isp_prt(isp, ISP_LOGINFO,
- "interrupt (ISR=%x SEMA=%x) when not ready", isr, sema);
+ /*
+ * This seems to happen to 23XX and 24XX cards- don't know why.
+ */
+ if (isp->isp_mboxbsy && isp->isp_lastmbxcmd == MBOX_ABOUT_FIRMWARE) {
+ goto fmbox;
+ }
+ isp_prt(isp, ISP_LOGINFO, "interrupt (ISR=%x SEMA=%x) when not ready", isr, sema);
/*
* Thank you very much! *Burrrp*!
*/
- ISP_WRITE(isp, isp->isp_respoutrp,
- ISP_READ(isp, isp->isp_respinrp));
+ ISP_WRITE(isp, isp->isp_respoutrp, ISP_READ(isp, isp->isp_respinrp));
if (IS_24XX(isp)) {
ISP_DISABLE_INTS(isp);
}
@@ -4600,12 +4921,10 @@ again:
/*
* Check for ATIO Queue entries.
*/
- if (isp->isp_rspbsy == 0 && (isp->isp_role & ISP_ROLE_TARGET) &&
- IS_24XX(isp)) {
- iptr = ISP_READ(isp, isp->isp_atioinrp);
- optr = ISP_READ(isp, isp->isp_atiooutrp);
+ if (IS_24XX(isp)) {
+ iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
+ optr = ISP_READ(isp, BIU2400_ATIO_RSPOUTP);
- isp->isp_rspbsy = 1;
while (optr != iptr) {
uint8_t qe[QENTRY_LEN];
isphdr_t *hp;
@@ -4623,14 +4942,12 @@ again:
(void) isp_target_notify(isp, addr, &oop);
break;
default:
- isp_print_qentry(isp, "?ATIOQ entry?",
- oop, addr);
+ isp_print_qentry(isp, "?ATIOQ entry?", oop, addr);
break;
}
optr = ISP_NXT_QENTRY(oop, RESULT_QUEUE_LEN(isp));
- ISP_WRITE(isp, isp->isp_atiooutrp, optr);
+ ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
}
- isp->isp_rspbsy = 0;
optr = isp->isp_residx;
}
#endif
@@ -4646,9 +4963,7 @@ again:
* Debug: to be taken out eventually
*/
if (isp->isp_residx != optr) {
- isp_prt(isp, ISP_LOGINFO,
- "isp_intr: hard optr=%x, soft optr %x",
- optr, isp->isp_residx);
+ isp_prt(isp, ISP_LOGINFO, "isp_intr: hard optr=%x, soft optr %x", optr, isp->isp_residx);
isp->isp_residx = optr;
}
} else {
@@ -4669,9 +4984,7 @@ again:
} while (junk != iptr && ++i < 1000);
if (iptr != junk) {
- isp_prt(isp, ISP_LOGWARN,
- "Response Queue Out Pointer Unstable (%x, %x)",
- iptr, junk);
+ isp_prt(isp, ISP_LOGWARN, "Response Queue Out Pointer Unstable (%x, %x)", iptr, junk);
goto out;
}
} else {
@@ -4692,7 +5005,7 @@ again:
if (IS_24XX(isp)) {
junk = 0;
} else if (IS_23XX(isp)) {
- USEC_DELAY(100);
+ ISP_DELAY(100);
iptr = ISP_READ(isp, isp->isp_respinrp);
junk = ISP_READ(isp, BIU_R2HSTSLO);
} else {
@@ -4709,18 +5022,11 @@ again:
}
}
isp->isp_intbogus++;
- isp_prt(isp, ISP_LOGDEBUG1,
- "bogus intr- isr %x (%x) iptr %x optr %x",
- isr, junk, iptr, optr);
+ isp_prt(isp, ISP_LOGDEBUG1, "bogus intr- isr %x (%x) iptr %x optr %x", isr, junk, iptr, optr);
}
}
isp->isp_resodx = iptr;
-
- if (isp->isp_rspbsy) {
- goto out;
- }
- isp->isp_rspbsy = 1;
while (optr != iptr) {
uint8_t qe[QENTRY_LEN];
ispstatusreq_t *sp = (ispstatusreq_t *) qe;
@@ -4749,11 +5055,9 @@ again:
if (IS_24XX(isp) && etype == RQSTYPE_RESPONSE) {
isp24xx_statusreq_t *sp2 = (isp24xx_statusreq_t *)qe;
- isp_get_24xx_response(isp,
- (isp24xx_statusreq_t *)hp, sp2);
+ isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp2);
if (isp->isp_dblev & ISP_LOGDEBUG1) {
- isp_print_bytes(isp,
- "Response Queue Entry", QENTRY_LEN, sp2);
+ isp_print_bytes(isp, "Response Queue Entry", QENTRY_LEN, sp2);
}
scsi_status = sp2->req_scsi_status;
completion_status = sp2->req_completion_status;
@@ -4762,8 +5066,7 @@ again:
} else if (etype == RQSTYPE_RESPONSE) {
isp_get_response(isp, (ispstatusreq_t *) hp, sp);
if (isp->isp_dblev & ISP_LOGDEBUG1) {
- isp_print_bytes(isp,
- "Response Queue Entry", QENTRY_LEN, sp);
+ isp_print_bytes(isp, "Response Queue Entry", QENTRY_LEN, sp);
}
scsi_status = sp->req_scsi_status;
completion_status = sp->req_completion_status;
@@ -4774,17 +5077,15 @@ again:
isp_rio2_t *rio = (isp_rio2_t *)qe;
isp_get_rio2(isp, (isp_rio2_t *) hp, rio);
if (isp->isp_dblev & ISP_LOGDEBUG1) {
- isp_print_bytes(isp,
- "Response Queue Entry", QENTRY_LEN, rio);
+ isp_print_bytes(isp, "Response Queue Entry", QENTRY_LEN, rio);
}
for (i = 0; i < rio->req_header.rqs_seqno; i++) {
isp_fastpost_complete(isp, rio->req_handles[i]);
}
if (isp->isp_fpcchiwater < rio->req_header.rqs_seqno) {
- isp->isp_fpcchiwater =
- rio->req_header.rqs_seqno;
+ isp->isp_fpcchiwater = rio->req_header.rqs_seqno;
}
- MEMZERO(hp, QENTRY_LEN); /* PERF */
+ ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
continue;
} else {
/*
@@ -4793,13 +5094,22 @@ again:
* us, so we reload our goal index.
*/
int r;
- r = isp_handle_other_response(isp, etype, hp, &optr);
+ uint32_t tsto = oop;
+ r = isp_handle_other_response(isp, etype, hp, &tsto);
if (r < 0) {
goto read_again;
}
+ /*
+ * If somebody updated the output pointer, then reset
+ * optr to be one more than the updated amount.
+ */
+ while (tsto != oop) {
+ optr = ISP_NXT_QENTRY(tsto,
+ RESULT_QUEUE_LEN(isp));
+ }
if (r > 0) {
- iptr = isp->isp_resodx;
- MEMZERO(hp, QENTRY_LEN); /* PERF */
+ ISP_WRITE(isp, isp->isp_respoutrp, optr);
+ ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
continue;
}
@@ -4819,7 +5129,7 @@ again:
etype, oop, optr, nlooked);
isp_print_bytes(isp,
"Request Queue Entry", QENTRY_LEN, sp);
- MEMZERO(hp, QENTRY_LEN); /* PERF */
+ ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
continue;
}
buddaboom = 1;
@@ -4832,35 +5142,38 @@ again:
if (sp->req_header.rqs_flags & RQSFLAG_MASK) {
if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) {
- isp_prt(isp, ISP_LOGWARN,
- "continuation segment");
+ isp_print_bytes(isp, "unexpected continuation segment", QENTRY_LEN, sp);
ISP_WRITE(isp, isp->isp_respoutrp, optr);
continue;
}
if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
- isp_prt(isp, ISP_LOGDEBUG1,
- "internal queues full");
+ isp_prt(isp, ISP_LOGDEBUG0, "internal queues full");
/*
* We'll synthesize a QUEUE FULL message below.
*/
}
if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) {
- isp_print_bytes(isp, "bad header flag",
- QENTRY_LEN, sp);
+ isp_print_bytes(isp, "bad header flag", QENTRY_LEN, sp);
buddaboom++;
}
if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) {
- isp_print_bytes(isp, "bad request packet",
- QENTRY_LEN, sp);
+ isp_print_bytes(isp, "bad request packet", QENTRY_LEN, sp);
buddaboom++;
}
+ if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
+ isp_print_bytes(isp, "invalid entry count", QENTRY_LEN, sp);
+ buddaboom++;
+ }
+ if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
+ isp_print_bytes(isp, "invalid IOCB ordering", QENTRY_LEN, sp);
+ ISP_WRITE(isp, isp->isp_respoutrp, optr);
+ continue;
+ }
}
- if (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1) {
- isp_prt(isp, ISP_LOGERR,
- "bad request handle %d (type 0x%x)",
- sp->req_handle, etype);
- MEMZERO(hp, QENTRY_LEN); /* PERF */
+ if ((sp->req_handle != ISP_SPCL_HANDLE) && (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1)) {
+ isp_prt(isp, ISP_LOGERR, "bad request handle %d (type 0x%x)", sp->req_handle, etype);
+ ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
ISP_WRITE(isp, isp->isp_respoutrp, optr);
continue;
}
@@ -4869,25 +5182,21 @@ again:
uint8_t ts = completion_status & 0xff;
/*
* Only whine if this isn't the expected fallout of
- * aborting the command.
+ * aborting the command or resetting the target.
*/
if (etype != RQSTYPE_RESPONSE) {
- isp_prt(isp, ISP_LOGERR,
- "cannot find handle 0x%x (type 0x%x)",
- sp->req_handle, etype);
- } else if (ts != RQCS_ABORTED) {
- isp_prt(isp, ISP_LOGERR,
- "cannot find handle 0x%x (status 0x%x)",
- sp->req_handle, ts);
+ isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", sp->req_handle, etype);
+ } else if (ts != RQCS_ABORTED && ts != RQCS_RESET_OCCURRED && sp->req_handle != ISP_SPCL_HANDLE) {
+ isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts);
}
- MEMZERO(hp, QENTRY_LEN); /* PERF */
+ ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
ISP_WRITE(isp, isp->isp_respoutrp, optr);
continue;
}
isp_destroy_handle(isp, sp->req_handle);
if (req_status_flags & RQSTF_BUS_RESET) {
XS_SETERR(xs, HBA_BUSRESET);
- isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
+ ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1);
}
if (buddaboom) {
XS_SETERR(xs, HBA_BOTCH);
@@ -4912,11 +5221,9 @@ again:
*/
req_state_flags |= RQSF_GOT_STATUS|RQSF_GOT_SENSE;
if (IS_24XX(isp)) {
- snsp =
- ((isp24xx_statusreq_t *)sp)->req_rsp_sense;
+ snsp = ((isp24xx_statusreq_t *)sp)->req_rsp_sense;
snsp += rlen;
- slen =
- ((isp24xx_statusreq_t *)sp)->req_sense_len;
+ slen = ((isp24xx_statusreq_t *)sp)->req_sense_len;
} else {
snsp = sp->req_sense_data;
slen = sp->req_sense_len;
@@ -4931,27 +5238,38 @@ again:
switch (etype) {
case RQSTYPE_RESPONSE:
- XS_SET_STATE_STAT(isp, xs, sp);
- if (resp && rlen >= 4 &&
- resp[FCP_RSPNS_CODE_OFFSET] != 0) {
- isp_prt(isp, ISP_LOGWARN,
- "%d.%d.%d FCP RESPONSE: 0x%x",
- XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs),
- resp[FCP_RSPNS_CODE_OFFSET]);
- XS_SETERR(xs, HBA_BOTCH);
+ if (resp && rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
+ const char *ptr;
+ char lb[64];
+ const char *rnames[6] = {
+ "Task Management Function Done",
+ "Data Length Differs From Burst Length",
+ "Invalid FCP Cmnd",
+ "FCP DATA RO mismatch with FCP DATA_XFR_RDY RO",
+ "Task Management Function Rejected",
+ "Task Management Function Failed",
+ };
+ if (resp[FCP_RSPNS_CODE_OFFSET] > 5) {
+ ISP_SNPRINTF(lb, sizeof lb, "Unknown FCP Response Code 0x%x", resp[FCP_RSPNS_CODE_OFFSET]);
+ ptr = lb;
+ } else {
+ ptr = rnames[resp[FCP_RSPNS_CODE_OFFSET]];
+ }
+ isp_prt(isp, ISP_LOGWARN, "%d.%d.%d FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), rlen, ptr, XS_CDBP(xs)[0] & 0xff);
+ if (resp[FCP_RSPNS_CODE_OFFSET] != 0) {
+ XS_SETERR(xs, HBA_BOTCH);
+ }
}
if (IS_24XX(isp)) {
- isp_parse_status_24xx(isp,
- (isp24xx_statusreq_t *)sp, xs, &resid);
+ isp_parse_status_24xx(isp, (isp24xx_statusreq_t *)sp, xs, &resid);
} else {
isp_parse_status(isp, (void *)sp, xs, &resid);
}
- if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) &&
- (*XS_STSP(xs) == SCSI_BUSY)) {
+ if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) && (*XS_STSP(xs) == SCSI_BUSY)) {
XS_SETERR(xs, HBA_TGTBSY);
}
if (IS_SCSI(isp)) {
- XS_RESID(xs) = resid;
+ XS_SET_RESID(xs, resid);
/*
* A new synchronous rate was negotiated for
* this target. Mark state such that we'll go
@@ -4959,56 +5277,45 @@ again:
*/
if (req_status_flags & RQSTF_NEGOTIATION) {
int t = XS_TGT(xs);
- sdparam *sdp = isp->isp_param;
- sdp += XS_CHANNEL(xs);
+ sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
sdp->isp_devparam[t].dev_refresh = 1;
- isp->isp_update |=
- (1 << XS_CHANNEL(xs));
+ sdp->update = 1;
}
} else {
if (req_status_flags & RQSF_XFER_COMPLETE) {
- XS_RESID(xs) = 0;
+ XS_SET_RESID(xs, 0);
} else if (scsi_status & RQCS_RESID) {
- XS_RESID(xs) = resid;
+ XS_SET_RESID(xs, resid);
} else {
- XS_RESID(xs) = 0;
+ XS_SET_RESID(xs, 0);
}
}
if (snsp && slen) {
XS_SAVE_SENSE(xs, snsp, slen);
+ } else if ((req_status_flags & RQSF_GOT_STATUS) && (scsi_status & 0xff) == SCSI_CHECK && IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN, "CHECK CONDITION w/o sense data for CDB=0x%x", XS_CDBP(xs)[0] & 0xff);
+ isp_print_bytes(isp, "CC with no Sense", QENTRY_LEN, qe);
}
- isp_prt(isp, ISP_LOGDEBUG2,
- "asked for %ld got raw resid %ld settled for %ld",
- (long) XS_XFRLEN(xs), resid, (long) XS_RESID(xs));
+ isp_prt(isp, ISP_LOGDEBUG2, "asked for %ld got raw resid %ld settled for %ld", (long) XS_XFRLEN(xs), resid, (long) XS_GET_RESID(xs));
break;
case RQSTYPE_REQUEST:
case RQSTYPE_A64:
case RQSTYPE_T2RQS:
case RQSTYPE_T3RQS:
case RQSTYPE_T7RQS:
- if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
+ if (!IS_24XX(isp) && (sp->req_header.rqs_flags & RQSFLAG_FULL)) {
/*
* Force Queue Full status.
*/
*XS_STSP(xs) = SCSI_QFULL;
XS_SETERR(xs, HBA_NOERROR);
} else if (XS_NOERR(xs)) {
- /*
- * ????
- */
XS_SETERR(xs, HBA_BOTCH);
- isp_prt(isp, ISP_LOGDEBUG0,
- "Request Queue Entry bounced back");
- if ((isp->isp_dblev & ISP_LOGDEBUG1) == 0) {
- isp_print_bytes(isp, "Bounced Request",
- QENTRY_LEN, qe);
- }
}
- XS_RESID(xs) = XS_XFRLEN(xs);
+ XS_SET_RESID(xs, XS_XFRLEN(xs));
break;
default:
- isp_print_bytes(isp, "Unhandled Response Type",
- QENTRY_LEN, qe);
+ isp_print_bytes(isp, "Unhandled Response Type", QENTRY_LEN, qe);
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_BOTCH);
}
@@ -5023,7 +5330,7 @@ again:
ISP_DMAFREE(isp, xs, sp->req_handle);
}
- if (((isp->isp_dblev & (ISP_LOGDEBUG2|ISP_LOGDEBUG3))) ||
+ if (((isp->isp_dblev & (ISP_LOGDEBUG1|ISP_LOGDEBUG2|ISP_LOGDEBUG3))) ||
((isp->isp_dblev & ISP_LOGDEBUG0) && ((!XS_NOERR(xs)) ||
(*XS_STSP(xs) != SCSI_GOOD)))) {
char skey;
@@ -5039,14 +5346,15 @@ again:
skey = '.';
}
isp_prt(isp, ISP_LOGALL, finmsg, XS_CHANNEL(xs),
- XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs), XS_RESID(xs),
+ XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs), (long) XS_GET_RESID(xs),
*XS_STSP(xs), skey, XS_ERR(xs));
}
- if (isp->isp_nactive > 0)
+ if (isp->isp_nactive > 0) {
isp->isp_nactive--;
+ }
complist[ndone++] = xs; /* defer completion call until later */
- MEMZERO(hp, QENTRY_LEN); /* PERF */
+ ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
if (ndone == MAX_REQUESTQ_COMPLETIONS) {
break;
}
@@ -5078,7 +5386,6 @@ out:
}
isp->isp_residx = optr;
- isp->isp_rspbsy = 0;
for (i = 0; i < ndone; i++) {
xs = complist[i];
if (xs) {
@@ -5092,34 +5399,50 @@ out:
* Support routines.
*/
+#define GET_24XX_BUS(isp, chan, msg) \
+ if (IS_24XX(isp)) { \
+ chan = ISP_READ(isp, OUTMAILBOX3) & 0xff; \
+ if (chan >= isp->isp_nchan) { \
+ isp_prt(isp, ISP_LOGERR, "bogus channel %u for %s at line %d", chan, msg, __LINE__); \
+ break; \
+ } \
+ }
+
static int
isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
{
int rval = 0;
- int bus;
+ int pattern = 0;
+ uint16_t chan;
if (IS_DUALBUS(isp)) {
- bus = ISP_READ(isp, OUTMAILBOX6);
+ chan = ISP_READ(isp, OUTMAILBOX6);
} else {
- bus = 0;
+ chan = 0;
}
isp_prt(isp, ISP_LOGDEBUG2, "Async Mbox 0x%x", mbox);
switch (mbox) {
case ASYNC_BUS_RESET:
- isp->isp_sendmarker |= (1 << bus);
+ if (IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "ILLEGAL ASYNC_BUS_RESET for FC card");
+ break;
+ }
+ ISP_SET_SENDMARKER(isp, chan, 1);
#ifdef ISP_TARGET_MODE
- if (isp_target_async(isp, bus, mbox)) {
+ if (isp_target_async(isp, chan, mbox)) {
rval = -1;
}
#endif
- isp_async(isp, ISPASYNC_BUS_RESET, &bus);
+ isp_async(isp, ISPASYNC_BUS_RESET, chan);
break;
case ASYNC_SYSTEM_ERROR:
+ isp->isp_dead = 1;
isp->isp_state = ISP_CRASHED;
if (IS_FC(isp)) {
- FCPARAM(isp)->isp_loopstate = LOOP_NIL;
- FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
+ FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
+ FCPARAM(isp, chan)->isp_fwstate = FW_CONFIG_WAIT;
}
/*
* Were we waiting for a mailbox command to complete?
@@ -5134,7 +5457,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
* It's up to the handler for isp_async to reinit stuff and
* restart the firmware
*/
- isp_async(isp, ISPASYNC_FW_CRASH, NULL);
+ isp_async(isp, ISPASYNC_FW_CRASH);
rval = -1;
break;
@@ -5147,6 +5470,17 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
break;
case ASYNC_QWAKEUP:
+#ifdef ISP_TARGET_MODE
+ if (IS_24XX(isp)) {
+ isp_prt(isp, ISP_LOGERR, "ATIO Queue Transfer Error");
+ break;
+ }
+#endif
+ if (IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "ILLEGAL ASYNC_QWAKEUP for FC card");
+ break;
+ }
/*
* We've just been notified that the Queue has woken up.
* We don't need to be chatty about this- just unlatch things
@@ -5156,66 +5490,101 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
break;
case ASYNC_TIMEOUT_RESET:
+ if (IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "ILLEGAL ASYNC_TIMEOUT_RESET for FC card");
+ break;
+ }
isp_prt(isp, ISP_LOGWARN,
- "timeout initiated SCSI bus reset of bus %d", bus);
- isp->isp_sendmarker |= (1 << bus);
+ "timeout initiated SCSI bus reset of chan %d", chan);
+ ISP_SET_SENDMARKER(isp, chan, 1);
#ifdef ISP_TARGET_MODE
- if (isp_target_async(isp, bus, mbox)) {
+ if (isp_target_async(isp, chan, mbox)) {
rval = -1;
}
#endif
break;
case ASYNC_DEVICE_RESET:
- isp_prt(isp, ISP_LOGINFO, "device reset on bus %d", bus);
- isp->isp_sendmarker |= (1 << bus);
+ if (IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "ILLEGAL DEVICE_RESET for FC card");
+ break;
+ }
+ isp_prt(isp, ISP_LOGINFO, "device reset on chan %d", chan);
+ ISP_SET_SENDMARKER(isp, chan, 1);
#ifdef ISP_TARGET_MODE
- if (isp_target_async(isp, bus, mbox)) {
+ if (isp_target_async(isp, chan, mbox)) {
rval = -1;
}
#endif
break;
case ASYNC_EXTMSG_UNDERRUN:
+ if (IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "ILLEGAL ASYNC_EXTMSG_UNDERRUN for FC card");
+ break;
+ }
isp_prt(isp, ISP_LOGWARN, "extended message underrun");
break;
case ASYNC_SCAM_INT:
+ if (IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "ILLEGAL ASYNC_SCAM_INT for FC card");
+ break;
+ }
isp_prt(isp, ISP_LOGINFO, "SCAM interrupt");
break;
case ASYNC_HUNG_SCSI:
+ if (IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "ILLEGAL ASYNC_HUNG_SCSI for FC card");
+ break;
+ }
isp_prt(isp, ISP_LOGERR,
"stalled SCSI Bus after DATA Overrun");
/* XXX: Need to issue SCSI reset at this point */
break;
case ASYNC_KILLED_BUS:
+ if (IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "ILLEGAL ASYNC_KILLED_BUS for FC card");
+ break;
+ }
isp_prt(isp, ISP_LOGERR, "SCSI Bus reset after DATA Overrun");
break;
case ASYNC_BUS_TRANSIT:
+ if (IS_FC(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "ILLEGAL ASYNC_BUS_TRANSIT for FC card");
+ break;
+ }
mbox = ISP_READ(isp, OUTMAILBOX2);
switch (mbox & 0x1c00) {
case SXP_PINS_LVD_MODE:
isp_prt(isp, ISP_LOGINFO, "Transition to LVD mode");
- SDPARAM(isp)->isp_diffmode = 0;
- SDPARAM(isp)->isp_ultramode = 0;
- SDPARAM(isp)->isp_lvdmode = 1;
+ SDPARAM(isp, chan)->isp_diffmode = 0;
+ SDPARAM(isp, chan)->isp_ultramode = 0;
+ SDPARAM(isp, chan)->isp_lvdmode = 1;
break;
case SXP_PINS_HVD_MODE:
isp_prt(isp, ISP_LOGINFO,
"Transition to Differential mode");
- SDPARAM(isp)->isp_diffmode = 1;
- SDPARAM(isp)->isp_ultramode = 0;
- SDPARAM(isp)->isp_lvdmode = 0;
+ SDPARAM(isp, chan)->isp_diffmode = 1;
+ SDPARAM(isp, chan)->isp_ultramode = 0;
+ SDPARAM(isp, chan)->isp_lvdmode = 0;
break;
case SXP_PINS_SE_MODE:
isp_prt(isp, ISP_LOGINFO,
"Transition to Single Ended mode");
- SDPARAM(isp)->isp_diffmode = 0;
- SDPARAM(isp)->isp_ultramode = 1;
- SDPARAM(isp)->isp_lvdmode = 0;
+ SDPARAM(isp, chan)->isp_diffmode = 0;
+ SDPARAM(isp, chan)->isp_ultramode = 1;
+ SDPARAM(isp, chan)->isp_lvdmode = 0;
break;
default:
isp_prt(isp, ISP_LOGWARN,
@@ -5226,32 +5595,28 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
* XXX: Set up to renegotiate again!
*/
/* Can only be for a 1080... */
- isp->isp_sendmarker |= (1 << bus);
+ ISP_SET_SENDMARKER(isp, chan, 1);
break;
- /*
- * We can use bus, which will always be zero for FC cards,
- * as a mailbox pattern accumulator to be checked below.
- */
case ASYNC_RIO5:
- bus = 0x1ce; /* outgoing mailbox regs 1-3, 6-7 */
+ pattern = 0xce; /* outgoing mailbox regs 1-3, 6-7 */
break;
case ASYNC_RIO4:
- bus = 0x14e; /* outgoing mailbox regs 1-3, 6 */
+ pattern = 0x4e; /* outgoing mailbox regs 1-3, 6 */
break;
case ASYNC_RIO3:
- bus = 0x10e; /* outgoing mailbox regs 1-3 */
+ pattern = 0x0e; /* outgoing mailbox regs 1-3 */
break;
case ASYNC_RIO2:
- bus = 0x106; /* outgoing mailbox regs 1-2 */
+ pattern = 0x06; /* outgoing mailbox regs 1-2 */
break;
case ASYNC_RIO1:
case ASYNC_CMD_CMPLT:
- bus = 0x102; /* outgoing mailbox regs 1 */
+ pattern = 0x02; /* outgoing mailbox regs 1 */
break;
case ASYNC_RIO_RESP:
@@ -5260,8 +5625,15 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
case ASYNC_CTIO_DONE:
{
#ifdef ISP_TARGET_MODE
- int handle =
- (ISP_READ(isp, OUTMAILBOX2) << 16) |
+ int handle;
+ if (IS_SCSI(isp) || IS_24XX(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "bad ASYNC_CTIO_DONE for %s cards",
+ IS_SCSI(isp)? "SCSI" : "24XX");
+ break;
+ }
+ handle =
+ (ISP_READ(isp, OUTMAILBOX2) << 16) |
(ISP_READ(isp, OUTMAILBOX1));
if (isp_target_async(isp, handle, mbox)) {
rval = -1;
@@ -5270,6 +5642,12 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
isp->isp_fphccmplt++;
}
#else
+ if (IS_SCSI(isp) || IS_24XX(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "bad ASYNC_CTIO_DONE for %s cards",
+ IS_SCSI(isp)? "SCSI" : "24XX");
+ break;
+ }
isp_prt(isp, ISP_LOGINFO, "Fast Posting CTIO done");
isp->isp_fphccmplt++; /* count it as a fast posting intr */
#endif
@@ -5278,114 +5656,236 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
case ASYNC_LIP_ERROR:
case ASYNC_LIP_F8:
case ASYNC_LIP_OCCURRED:
- FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
- FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
- isp->isp_sendmarker = 1;
- ISP_MARK_PORTDB(isp, 1);
- isp_async(isp, ISPASYNC_LIP, NULL);
-#ifdef ISP_TARGET_MODE
- if (isp_target_async(isp, bus, mbox)) {
- rval = -1;
+ case ASYNC_PTPMODE:
+ if (IS_SCSI(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "bad LIP event for SCSI cards");
+ break;
}
-#endif
/*
- * We've had problems with data corruption occuring on
- * commands that complete (with no apparent error) after
- * we receive a LIP. This has been observed mostly on
- * Local Loop topologies. To be safe, let's just mark
- * all active commands as dead.
+ * These are broadcast events that have to be sent across
+ * all active channels.
*/
- if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT ||
- FCPARAM(isp)->isp_topo == TOPO_FL_PORT) {
- int i, j;
- for (i = j = 0; i < isp->isp_maxcmds; i++) {
- XS_T *xs;
- xs = isp->isp_xflist[i];
- if (xs != NULL) {
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ fcparam *fcp = FCPARAM(isp, chan);
+ int topo = fcp->isp_topo;
+
+ if (fcp->role == ISP_ROLE_NONE) {
+ continue;
+ }
+
+ fcp->isp_fwstate = FW_CONFIG_WAIT;
+ fcp->isp_loopstate = LOOP_LIP_RCVD;
+ ISP_SET_SENDMARKER(isp, chan, 1);
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_async(isp, ISPASYNC_LIP, chan);
+#ifdef ISP_TARGET_MODE
+ if (isp_target_async(isp, chan, mbox)) {
+ rval = -1;
+ }
+#endif
+ /*
+ * We've had problems with data corruption occuring on
+ * commands that complete (with no apparent error) after
+ * we receive a LIP. This has been observed mostly on
+ * Local Loop topologies. To be safe, let's just mark
+ * all active commands as dead.
+ */
+ if (topo == TOPO_NL_PORT || topo == TOPO_FL_PORT) {
+ int i, j;
+ for (i = j = 0; i < isp->isp_maxcmds; i++) {
+ XS_T *xs;
+ xs = isp->isp_xflist[i];
+ if (xs == NULL) {
+ continue;
+ }
+ if (XS_CHANNEL(xs) != chan) {
+ continue;
+ }
j++;
XS_SETERR(xs, HBA_BUSRESET);
}
- }
- if (j) {
- isp_prt(isp, ISP_LOGERR,
- "LIP destroyed %d active commands", j);
+ if (j) {
+ isp_prt(isp, ISP_LOGERR, lipd, chan, j);
+ }
}
}
break;
case ASYNC_LOOP_UP:
- isp->isp_sendmarker = 1;
- FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
- FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
- ISP_MARK_PORTDB(isp, 1);
- isp_async(isp, ISPASYNC_LOOP_UP, NULL);
-#ifdef ISP_TARGET_MODE
- if (isp_target_async(isp, bus, mbox)) {
- rval = -1;
+ if (IS_SCSI(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "bad LOOP UP event for SCSI cards");
+ break;
}
+ /*
+ * This is a broadcast event that has to be sent across
+ * all active channels.
+ */
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ fcparam *fcp = FCPARAM(isp, chan);
+
+ if (fcp->role == ISP_ROLE_NONE) {
+ continue;
+ }
+
+ ISP_SET_SENDMARKER(isp, chan, 1);
+
+ fcp->isp_fwstate = FW_CONFIG_WAIT;
+ fcp->isp_loopstate = LOOP_LIP_RCVD;
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_async(isp, ISPASYNC_LOOP_UP, chan);
+#ifdef ISP_TARGET_MODE
+ if (isp_target_async(isp, chan, mbox)) {
+ rval = -1;
+ }
#endif
+ }
break;
case ASYNC_LOOP_DOWN:
- isp->isp_sendmarker = 1;
- FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
- FCPARAM(isp)->isp_loopstate = LOOP_NIL;
- ISP_MARK_PORTDB(isp, 1);
- isp_async(isp, ISPASYNC_LOOP_DOWN, NULL);
-#ifdef ISP_TARGET_MODE
- if (isp_target_async(isp, bus, mbox)) {
- rval = -1;
+ if (IS_SCSI(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "bad LOOP DOWN event for SCSI cards");
+ break;
}
+ /*
+ * This is a broadcast event that has to be sent across
+ * all active channels.
+ */
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ fcparam *fcp = FCPARAM(isp, chan);
+
+ if (fcp->role == ISP_ROLE_NONE) {
+ continue;
+ }
+
+ ISP_SET_SENDMARKER(isp, chan, 1);
+ fcp->isp_fwstate = FW_CONFIG_WAIT;
+ fcp->isp_loopstate = LOOP_NIL;
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
+#ifdef ISP_TARGET_MODE
+ if (isp_target_async(isp, chan, mbox)) {
+ rval = -1;
+ }
#endif
+ }
break;
case ASYNC_LOOP_RESET:
- isp->isp_sendmarker = 1;
- FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
- FCPARAM(isp)->isp_loopstate = LOOP_NIL;
- ISP_MARK_PORTDB(isp, 1);
- isp_async(isp, ISPASYNC_LOOP_RESET, NULL);
-#ifdef ISP_TARGET_MODE
- if (isp_target_async(isp, bus, mbox)) {
- rval = -1;
+ if (IS_SCSI(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "bad LIP RESET event for SCSI cards");
+ break;
}
+ /*
+ * This is a broadcast event that has to be sent across
+ * all active channels.
+ */
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ fcparam *fcp = FCPARAM(isp, chan);
+
+ if (fcp->role == ISP_ROLE_NONE) {
+ continue;
+ }
+
+ ISP_SET_SENDMARKER(isp, chan, 1);
+ fcp->isp_fwstate = FW_CONFIG_WAIT;
+ fcp->isp_loopstate = LOOP_NIL;
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_async(isp, ISPASYNC_LOOP_RESET, chan);
+#ifdef ISP_TARGET_MODE
+ if (isp_target_async(isp, chan, mbox)) {
+ rval = -1;
+ }
#endif
+ }
break;
case ASYNC_PDB_CHANGED:
- isp->isp_sendmarker = 1;
- FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
- ISP_MARK_PORTDB(isp, 1);
- isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_PDB);
- break;
+ {
+ int nphdl, nlstate, reason;
+ if (IS_SCSI(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "bad PDB CHANGED event for SCSI cards");
+ break;
+ }
+ /*
+ * We *should* get a channel out of the 24XX, but we don't seem
+ * to get more than a PDB CHANGED on channel 0, so turn it into
+ * a broadcast event.
+ */
+ if (IS_24XX(isp)) {
+ nphdl = ISP_READ(isp, OUTMAILBOX1);
+ nlstate = ISP_READ(isp, OUTMAILBOX2);
+ reason = ISP_READ(isp, OUTMAILBOX3) >> 8;
+ } else {
+ nphdl = NIL_HANDLE;
+ nlstate = reason = 0;
+ }
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ fcparam *fcp = FCPARAM(isp, chan);
+ if (fcp->role == ISP_ROLE_NONE) {
+ continue;
+ }
+ ISP_SET_SENDMARKER(isp, chan, 1);
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
+ ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
+ }
+ break;
+ }
case ASYNC_CHANGE_NOTIFY:
- if (FCPARAM(isp)->isp_topo == TOPO_F_PORT) {
- FCPARAM(isp)->isp_loopstate = LOOP_LSCAN_DONE;
+ {
+ int lochan, hichan;
+
+ if (IS_SCSI(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "bad CHANGE NOTIFY event for SCSI cards");
+ break;
+ }
+ if (ISP_FW_NEWER_THAN(isp, 4, 0, 25) && ISP_CAP_MULTI_ID(isp)) {
+ GET_24XX_BUS(isp, chan, "ASYNC_CHANGE_NOTIFY");
+ lochan = chan;
+ hichan = chan + 1;
} else {
- FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
+ lochan = 0;
+ hichan = isp->isp_nchan;
}
- ISP_MARK_PORTDB(isp, 1);
- isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_SNS);
- break;
+ for (chan = lochan; chan < hichan; chan++) {
+ fcparam *fcp = FCPARAM(isp, chan);
- case ASYNC_PTPMODE:
- ISP_MARK_PORTDB(isp, 1);
- isp->isp_sendmarker = 1;
- FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
- FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
- isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
-#ifdef ISP_TARGET_MODE
- if (isp_target_async(isp, bus, mbox)) {
- rval = -1;
+ if (fcp->role == ISP_ROLE_NONE) {
+ continue;
+ }
+
+ if (fcp->isp_topo == TOPO_F_PORT) {
+ fcp->isp_loopstate = LOOP_LSCAN_DONE;
+ } else {
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ ISP_MARK_PORTDB(isp, chan, 1);
+ isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
+ ISPASYNC_CHANGE_SNS);
}
-#endif
- isp_prt(isp, ISP_LOGINFO, "Point-to-Point mode");
break;
+ }
case ASYNC_CONNMODE:
+ /*
+ * This only applies to 2100 amd 2200 cards
+ */
+ if (!IS_2200(isp) && !IS_2100(isp)) {
+ isp_prt(isp, ISP_LOGWARN,
+ "bad card for ASYNC_CONNMODE event");
+ break;
+ }
+ chan = 0;
mbox = ISP_READ(isp, OUTMAILBOX1);
- ISP_MARK_PORTDB(isp, 1);
+ ISP_MARK_PORTDB(isp, chan, 1);
switch (mbox) {
case ISP_CONN_LOOP:
isp_prt(isp, ISP_LOGINFO,
@@ -5400,8 +5900,10 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
"Point-to-Point -> Loop mode (BAD LIP)");
break;
case ISP_CONN_FATAL:
+ isp->isp_dead = 1;
+ isp->isp_state = ISP_CRASHED;
isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR");
- isp_async(isp, ISPASYNC_FW_CRASH, NULL);
+ isp_async(isp, ISPASYNC_FW_CRASH);
return (-1);
case ISP_CONN_LOOPBACK:
isp_prt(isp, ISP_LOGWARN,
@@ -5412,12 +5914,21 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
"Unknown connection mode (0x%x)", mbox);
break;
}
- isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
- isp->isp_sendmarker = 1;
- FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
- FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
+ isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
+ ISPASYNC_CHANGE_OTHER);
+ FCPARAM(isp, chan)->sendmarker = 1;
+ FCPARAM(isp, chan)->isp_fwstate = FW_CONFIG_WAIT;
+ FCPARAM(isp, chan)->isp_loopstate = LOOP_LIP_RCVD;
break;
+ case ASYNC_RCV_ERR:
+ if (IS_24XX(isp)) {
+ isp_prt(isp, ISP_LOGWARN, "Receive Error");
+ } else {
+ isp_prt(isp, ISP_LOGWARN,
+ "Unknown Async Code 0x%x", mbox);
+ }
+ break;
case ASYNC_RJT_SENT: /* same as ASYNC_QFULL_SENT */
if (IS_24XX(isp)) {
isp_prt(isp, ISP_LOGTDEBUG0, "LS_RJT sent");
@@ -5432,12 +5943,12 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
break;
}
- if (bus & 0x100) {
+ if (pattern) {
int i, nh;
uint16_t handles[16];
for (nh = 0, i = 1; i < MAX_MAILBOX(isp); i++) {
- if ((bus & (1 << i)) == 0) {
+ if ((pattern & (1 << i)) == 0) {
continue;
}
handles[nh++] = ISP_READ(isp, MBOX_OFF(i));
@@ -5493,9 +6004,18 @@ isp_handle_other_response(ispsoftc_t *isp, int type,
}
#endif
/* FALLTHROUGH */
+ case RQSTYPE_RPT_ID_ACQ:
+ if (IS_24XX(isp)) {
+ isp_ridacq_t rid;
+ isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
+ if (rid.ridacq_format == 0) {
+ }
+ return (1);
+ }
+ /* FALLTHROUGH */
case RQSTYPE_REQUEST:
default:
- USEC_DELAY(100);
+ ISP_DELAY(100);
if (type != isp_get_response_type(isp, hp)) {
/*
* This is questionable- we're just papering over
@@ -5511,9 +6031,6 @@ isp_handle_other_response(ispsoftc_t *isp, int type,
}
isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x",
isp_get_response_type(isp, hp));
- if (isp_async(isp, ISPASYNC_UNHANDLED_RESPONSE, hp)) {
- return (1);
- }
return (0);
}
}
@@ -5554,52 +6071,52 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
case RQCS_TRANSPORT_ERROR:
{
char buf[172];
- SNPRINTF(buf, sizeof (buf), "states=>");
+ ISP_SNPRINTF(buf, sizeof (buf), "states=>");
if (sp->req_state_flags & RQSF_GOT_BUS) {
- SNPRINTF(buf, sizeof (buf), "%s GOT_BUS", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s GOT_BUS", buf);
}
if (sp->req_state_flags & RQSF_GOT_TARGET) {
- SNPRINTF(buf, sizeof (buf), "%s GOT_TGT", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s GOT_TGT", buf);
}
if (sp->req_state_flags & RQSF_SENT_CDB) {
- SNPRINTF(buf, sizeof (buf), "%s SENT_CDB", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s SENT_CDB", buf);
}
if (sp->req_state_flags & RQSF_XFRD_DATA) {
- SNPRINTF(buf, sizeof (buf), "%s XFRD_DATA", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s XFRD_DATA", buf);
}
if (sp->req_state_flags & RQSF_GOT_STATUS) {
- SNPRINTF(buf, sizeof (buf), "%s GOT_STS", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s GOT_STS", buf);
}
if (sp->req_state_flags & RQSF_GOT_SENSE) {
- SNPRINTF(buf, sizeof (buf), "%s GOT_SNS", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s GOT_SNS", buf);
}
if (sp->req_state_flags & RQSF_XFER_COMPLETE) {
- SNPRINTF(buf, sizeof (buf), "%s XFR_CMPLT", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s XFR_CMPLT", buf);
}
- SNPRINTF(buf, sizeof (buf), "%s\nstatus=>", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s\nstatus=>", buf);
if (sp->req_status_flags & RQSTF_DISCONNECT) {
- SNPRINTF(buf, sizeof (buf), "%s Disconnect", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s Disconnect", buf);
}
if (sp->req_status_flags & RQSTF_SYNCHRONOUS) {
- SNPRINTF(buf, sizeof (buf), "%s Sync_xfr", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s Sync_xfr", buf);
}
if (sp->req_status_flags & RQSTF_PARITY_ERROR) {
- SNPRINTF(buf, sizeof (buf), "%s Parity", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s Parity", buf);
}
if (sp->req_status_flags & RQSTF_BUS_RESET) {
- SNPRINTF(buf, sizeof (buf), "%s Bus_Reset", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s Bus_Reset", buf);
}
if (sp->req_status_flags & RQSTF_DEVICE_RESET) {
- SNPRINTF(buf, sizeof (buf), "%s Device_Reset", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s Device_Reset", buf);
}
if (sp->req_status_flags & RQSTF_ABORTED) {
- SNPRINTF(buf, sizeof (buf), "%s Aborted", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s Aborted", buf);
}
if (sp->req_status_flags & RQSTF_TIMEOUT) {
- SNPRINTF(buf, sizeof (buf), "%s Timeout", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s Timeout", buf);
}
if (sp->req_status_flags & RQSTF_NEGOTIATION) {
- SNPRINTF(buf, sizeof (buf), "%s Negotiation", buf);
+ ISP_SNPRINTF(buf, sizeof (buf), "%s Negotiation", buf);
}
isp_prt(isp, ISP_LOGERR, "%s", buf);
isp_prt(isp, ISP_LOGERR, "transport error for %d.%d.%d:\n%s",
@@ -5608,20 +6125,24 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
break;
}
case RQCS_RESET_OCCURRED:
+ {
+ int chan;
isp_prt(isp, ISP_LOGWARN,
"bus reset destroyed command for %d.%d.%d",
XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
- isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ FCPARAM(isp, chan)->sendmarker = 1;
+ }
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_BUSRESET);
}
*rp = XS_XFRLEN(xs);
return;
-
+ }
case RQCS_ABORTED:
isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d",
XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
- isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
+ ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 1);
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_ABORTED);
}
@@ -5639,9 +6160,9 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
return;
case RQCS_DATA_OVERRUN:
- XS_RESID(xs) = sp->req_resid;
- isp_prt(isp, ISP_LOGERR, "data overrun for command on %d.%d.%d",
- XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
+ XS_SET_RESID(xs, sp->req_resid);
+ isp_prt(isp, ISP_LOGERR, "data overrun (%ld) for command on %d.%d.%d",
+ (long) XS_GET_RESID(xs), XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_DATAOVR);
}
@@ -5733,7 +6254,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
return;
}
}
- XS_RESID(xs) = sp->req_resid;
+ XS_SET_RESID(xs, sp->req_resid);
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_NOERROR);
}
@@ -5804,11 +6325,10 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
"Wide Negotiation failed for %d.%d.%d",
XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
if (IS_SCSI(isp)) {
- sdparam *sdp = isp->isp_param;
- sdp += XS_CHANNEL(xs);
+ sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
sdp->isp_devparam[XS_TGT(xs)].goal_flags &= ~DPARM_WIDE;
sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
- isp->isp_update |= (1 << XS_CHANNEL(xs));
+ sdp->update = 1;
}
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_NOERROR);
@@ -5820,11 +6340,11 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
"SDTR Message failed for target %d.%d.%d",
XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs));
if (IS_SCSI(isp)) {
- sdparam *sdp = isp->isp_param;
+ sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
sdp += XS_CHANNEL(xs);
sdp->isp_devparam[XS_TGT(xs)].goal_flags &= ~DPARM_SYNC;
sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
- isp->isp_update |= (1 << XS_CHANNEL(xs));
+ sdp->update = 1;
}
break;
@@ -5860,15 +6380,13 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
* to force a re-login of this unit. If we're on fabric,
* then we'll have to log in again as a matter of course.
*/
- if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT ||
- FCPARAM(isp)->isp_topo == TOPO_FL_PORT) {
+ if (FCPARAM(isp, 0)->isp_topo == TOPO_NL_PORT ||
+ FCPARAM(isp, 0)->isp_topo == TOPO_FL_PORT) {
mbreg_t mbs;
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_INIT_LIP;
- if (FCPARAM(isp)->isp_2klogin) {
+ MBSINIT(&mbs, MBOX_INIT_LIP, MBLOGALL, 0);
+ if (ISP_CAP_2KLOGIN(isp)) {
mbs.ibits = (1 << 10);
}
- mbs.logval = MBLOGALL;
isp_mboxcmd_qnw(isp, &mbs, 1);
}
if (XS_NOERR(xs)) {
@@ -5907,6 +6425,8 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
XS_T *xs, long *rp)
{
int ru_marked, sv_marked;
+ int chan = XS_CHANNEL(xs);
+
switch (sp->req_completion_status) {
case RQCS_COMPLETE:
if (XS_NOERR(xs)) {
@@ -5926,9 +6446,9 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
case RQCS_RESET_OCCURRED:
isp_prt(isp, ISP_LOGWARN,
- "bus reset destroyed command for %d.%d.%d",
+ "reset destroyed command for %d.%d.%d",
XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
- isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
+ FCPARAM(isp, chan)->sendmarker = 1;
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_BUSRESET);
}
@@ -5937,7 +6457,7 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
case RQCS_ABORTED:
isp_prt(isp, ISP_LOGERR, "command aborted for %d.%d.%d",
XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
- isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
+ FCPARAM(isp, chan)->sendmarker = 1;
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_ABORTED);
}
@@ -5952,7 +6472,7 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
return;
case RQCS_DATA_OVERRUN:
- XS_RESID(xs) = sp->req_resid;
+ XS_SET_RESID(xs, sp->req_resid);
isp_prt(isp, ISP_LOGERR,
"data overrun for command on %d.%d.%d",
XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs));
@@ -5962,8 +6482,9 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
return;
case RQCS_24XX_DRE: /* data reassembly error */
- isp_prt(isp, ISP_LOGERR, "data reassembly error for target %d",
- XS_TGT(xs));
+ isp_prt(isp, ISP_LOGERR,
+ "Chan %d data reassembly error for target %d",
+ chan, XS_TGT(xs));
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_ABORTED);
}
@@ -5971,8 +6492,8 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
return;
case RQCS_24XX_TABORT: /* aborted by target */
- isp_prt(isp, ISP_LOGERR, "target %d sent ABTS",
- XS_TGT(xs));
+ isp_prt(isp, ISP_LOGERR, "Chan %d target %d sent ABTS",
+ chan, XS_TGT(xs));
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_ABORTED);
}
@@ -5981,7 +6502,7 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
case RQCS_DATA_UNDERRUN:
ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
/*
- * We can get an underrun w/o things being marked
+ * We can get an underrun w/o things being marked
* if we got a non-zero status.
*/
sv_marked = (sp->req_scsi_status & (RQCS_SV|RQCS_RV)) != 0;
@@ -5995,7 +6516,7 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
}
return;
}
- XS_RESID(xs) = sp->req_resid;
+ XS_SET_RESID(xs, sp->req_resid);
isp_prt(isp, ISP_LOGDEBUG0,
"%d.%d.%d data underrun (%d) for command 0x%x",
XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs),
@@ -6023,25 +6544,12 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
reason = "logout";
}
- isp_prt(isp, ISP_LOGINFO, "port %s for target %d",
- reason, XS_TGT(xs));
+ isp_prt(isp, ISP_LOGINFO, "Chan %d port %s for target %d",
+ chan, reason, XS_TGT(xs));
/*
- * If we're on a local loop, force a LIP (which is overkill)
- * to force a re-login of this unit. If we're on fabric,
- * then we'll have to log in again as a matter of course.
+ * There is no MBOX_INIT_LIP for the 24XX.
*/
- if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT ||
- FCPARAM(isp)->isp_topo == TOPO_FL_PORT) {
- mbreg_t mbs;
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_INIT_LIP;
- if (FCPARAM(isp)->isp_2klogin) {
- mbs.ibits = (1 << 10);
- }
- mbs.logval = MBLOGALL;
- isp_mboxcmd_qnw(isp, &mbs, 1);
- }
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_SELTIMEOUT);
}
@@ -6049,7 +6557,7 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
}
case RQCS_PORT_CHANGED:
isp_prt(isp, ISP_LOGWARN,
- "port changed for target %d", XS_TGT(xs));
+ "port changed for target %d chan %d", XS_TGT(xs), chan);
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_SELTIMEOUT);
}
@@ -6058,7 +6566,8 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
case RQCS_24XX_ENOMEM: /* f/w resource unavailable */
isp_prt(isp, ISP_LOGWARN,
- "f/w resource unavailable for target %d", XS_TGT(xs));
+ "f/w resource unavailable for target %d chan %d",
+ XS_TGT(xs), chan);
if (XS_NOERR(xs)) {
*XS_STSP(xs) = SCSI_BUSY;
XS_SETERR(xs, HBA_TGTBSY);
@@ -6067,8 +6576,8 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
case RQCS_24XX_TMO: /* task management overrun */
isp_prt(isp, ISP_LOGWARN,
- "command for target %d overlapped task management",
- XS_TGT(xs));
+ "command for target %d overlapped task management for "
+ "chan %d", XS_TGT(xs), chan);
if (XS_NOERR(xs)) {
*XS_STSP(xs) = SCSI_BUSY;
XS_SETERR(xs, HBA_TGTBSY);
@@ -6076,8 +6585,9 @@ isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp,
return;
default:
- isp_prt(isp, ISP_LOGERR, "Unknown Completion Status 0x%x",
- sp->req_completion_status);
+ isp_prt(isp, ISP_LOGERR,
+ "Unknown Completion Status 0x%x on chan %d",
+ sp->req_completion_status, chan);
break;
}
if (XS_NOERR(xs)) {
@@ -6095,7 +6605,7 @@ isp_fastpost_complete(ispsoftc_t *isp, uint16_t fph)
}
xs = isp_find_xs(isp, fph);
if (xs == NULL) {
- isp_prt(isp, ISP_LOGDEBUG1,
+ isp_prt(isp, ISP_LOGWARN,
"Command for fast post handle 0x%x not found", fph);
return;
}
@@ -6106,14 +6616,14 @@ isp_fastpost_complete(ispsoftc_t *isp, uint16_t fph)
* we must believe that SCSI status is zero and
* that all data transferred.
*/
- XS_SET_STATE_STAT(isp, xs, NULL);
- XS_RESID(xs) = 0;
+ XS_SET_RESID(xs, 0);
*XS_STSP(xs) = SCSI_GOOD;
if (XS_XFRLEN(xs)) {
ISP_DMAFREE(isp, xs, fph);
}
- if (isp->isp_nactive)
+ if (isp->isp_nactive) {
isp->isp_nactive--;
+ }
isp->isp_fphccmplt++;
isp_done(xs);
}
@@ -6152,7 +6662,7 @@ isp_mbox_continue(ispsoftc_t *isp)
/*
* Continue with next word.
*/
- MEMZERO(&mbs, sizeof (mbs));
+ ISP_MEMZERO(&mbs, sizeof (mbs));
ptr = isp->isp_mbxworkp;
switch (isp->isp_lastmbxcmd) {
case MBOX_WRITE_RAM_WORD:
@@ -6397,7 +6907,7 @@ static const uint32_t mbpfc[] = {
ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
ISPOPMAP(0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */
- ISPOPMAP(0x03, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
+ ISPOPMAP(0x07, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */
ISPOPMAP(0x01, 0x4f), /* 0x08: MBOX_ABOUT_FIRMWARE */
ISPOPMAP(0xdf, 0x01), /* 0x09: MBOX_LOAD_RISC_RAM_2100 */
ISPOPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */
@@ -6462,9 +6972,9 @@ static const uint32_t mbpfc[] = {
ISPOPMAP(0x00, 0x00), /* 0x45: */
ISPOPMAP(0x00, 0x00), /* 0x46: */
ISPOPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */
- ISPOPMAP(0x00, 0x00), /* 0x48: */
- ISPOPMAP(0x00, 0x00), /* 0x49: */
- ISPOPMAP(0x00, 0x00), /* 0x4a: */
+ ISPOPMAP(0xcd, 0x01), /* 0x48: MBOX_INIT_FIRMWARE_MULTI_ID */
+ ISPOPMAP(0xcd, 0x01), /* 0x49: MBOX_GET_VP_DATABASE */
+ ISPOPMAP(0x2cd, 0x01), /* 0x4a: MBOX_GET_VP_DATABASE_ENTRY */
ISPOPMAP(0x00, 0x00), /* 0x4b: */
ISPOPMAP(0x00, 0x00), /* 0x4c: */
ISPOPMAP(0x00, 0x00), /* 0x4d: */
@@ -6521,7 +7031,7 @@ static const uint32_t mbpfc[] = {
/*
* Footnotes
*
- * (1): this sets bits 21..16 in mailbox register #8, which we nominally
+ * (1): this sets bits 21..16 in mailbox register #8, which we nominally
* do not access at this time in the core driver. The caller is
* responsible for setting this register first (Gross!). The assumption
* is that we won't overflow.
@@ -6600,9 +7110,9 @@ static const char *fc_mbcmd_names[] = {
NULL,
NULL,
"GET PORT DATABASE ENHANCED",
- NULL,
- NULL,
- NULL,
+ "INIT FIRMWARE MULTI ID",
+ "GET VP DATABASE",
+ "GET VP DATABASE ENTRY",
NULL,
NULL,
NULL,
@@ -6697,7 +7207,7 @@ isp_mboxcmd_qnw(ispsoftc_t *isp, mbreg_t *mbp, int nodelay)
* command.
*/
if (nodelay) {
- USEC_DELAY(1000);
+ ISP_DELAY(1000);
}
}
@@ -6748,7 +7258,7 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
for (box = 0; box < MAX_MAILBOX(isp); box++) {
if (ibits & (1 << box)) {
- isp_prt(isp, ISP_LOGDEBUG1, "IN mbox %d = 0x%04x", box,
+ isp_prt(isp, ISP_LOGDEBUG3, "IN mbox %d = 0x%04x", box,
mbp->param[box]);
ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]);
}
@@ -6781,6 +7291,7 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
* Did the command time out?
*/
if (mbp->param[0] == MBOX_TIMEOUT) {
+ isp->isp_mboxbsy = 0;
MBOX_RELEASE(isp);
goto out;
}
@@ -6791,21 +7302,21 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
for (box = 0; box < MAX_MAILBOX(isp); box++) {
if (obits & (1 << box)) {
mbp->param[box] = isp->isp_mboxtmp[box];
- isp_prt(isp, ISP_LOGDEBUG1, "OUT mbox %d = 0x%04x", box,
+ isp_prt(isp, ISP_LOGDEBUG3, "OUT mbox %d = 0x%04x", box,
mbp->param[box]);
}
}
+ isp->isp_mboxbsy = 0;
MBOX_RELEASE(isp);
out:
- isp->isp_mboxbsy = 0;
if (mbp->logval == 0 || opcode == MBOX_EXEC_FIRMWARE) {
return;
}
cname = (IS_FC(isp))? fc_mbcmd_names[opcode] : scsi_mbcmd_names[opcode];
if (cname == NULL) {
cname = tname;
- SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
+ ISP_SNPRINTF(tname, sizeof tname, "opcode %x", opcode);
}
/*
@@ -6862,7 +7373,7 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
xname = "TIMEOUT";
break;
default:
- SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
+ ISP_SNPRINTF(mname, sizeof mname, "error 0x%x", mbp->param[0]);
xname = mname;
break;
}
@@ -6873,15 +7384,13 @@ isp_mboxcmd(ispsoftc_t *isp, mbreg_t *mbp)
}
static void
-isp_fw_state(ispsoftc_t *isp)
+isp_fw_state(ispsoftc_t *isp, int chan)
{
if (IS_FC(isp)) {
mbreg_t mbs;
- fcparam *fcp = isp->isp_param;
+ fcparam *fcp = FCPARAM(isp, chan);
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_GET_FW_STATE;
- mbs.logval = MBLOGALL;
+ MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
fcp->isp_fwstate = mbs.param[1];
@@ -6890,34 +7399,20 @@ isp_fw_state(ispsoftc_t *isp)
}
static void
-isp_update(ispsoftc_t *isp)
-{
- int bus, upmask;
-
- for (bus = 0, upmask = isp->isp_update; upmask != 0; bus++) {
- if (upmask & (1 << bus)) {
- isp_update_bus(isp, bus);
- }
- upmask &= ~(1 << bus);
- }
-}
-
-static void
-isp_update_bus(ispsoftc_t *isp, int bus)
+isp_spi_update(ispsoftc_t *isp, int chan)
{
int tgt;
mbreg_t mbs;
sdparam *sdp;
- isp->isp_update &= ~(1 << bus);
if (IS_FC(isp)) {
/*
* There are no 'per-bus' settings for Fibre Channel.
*/
return;
}
- sdp = isp->isp_param;
- sdp += bus;
+ sdp = SDPARAM(isp, chan);
+ sdp->update = 0;
for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
uint16_t flags, period, offset;
@@ -6927,7 +7422,7 @@ isp_update_bus(ispsoftc_t *isp, int bus)
sdp->isp_devparam[tgt].dev_update = 0;
sdp->isp_devparam[tgt].dev_refresh = 0;
isp_prt(isp, ISP_LOGDEBUG0,
- "skipping target %d bus %d update", tgt, bus);
+ "skipping target %d bus %d update", tgt, chan);
continue;
}
/*
@@ -6937,7 +7432,7 @@ isp_update_bus(ispsoftc_t *isp, int bus)
* current device state, get the current parameters.
*/
- MEMZERO(&mbs, sizeof (mbs));
+ MBSINIT(&mbs, 0, MBLOGALL, 0);
/*
* Refresh overrides set
@@ -6985,20 +7480,19 @@ isp_update_bus(ispsoftc_t *isp, int bus)
(sdp->isp_devparam[tgt].goal_flags & DPARM_TQING);
isp_prt(isp, ISP_LOGDEBUG0,
"bus %d set tgt %d flags 0x%x off 0x%x period 0x%x",
- bus, tgt, mbs.param[2], mbs.param[3] >> 8,
+ chan, tgt, mbs.param[2], mbs.param[3] >> 8,
mbs.param[3] & 0xff);
get = 0;
} else {
continue;
}
- mbs.param[1] = (bus << 15) | (tgt << 8);
- mbs.logval = MBLOGALL;
+ mbs.param[1] = (chan << 15) | (tgt << 8);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
continue;
}
if (get == 0) {
- isp->isp_sendmarker |= (1 << bus);
+ sdp->sendmarker = 1;
sdp->isp_devparam[tgt].dev_update = 0;
sdp->isp_devparam[tgt].dev_refresh = 1;
} else {
@@ -7009,48 +7503,41 @@ isp_update_bus(ispsoftc_t *isp, int bus)
sdp->isp_devparam[tgt].actv_flags = flags;
sdp->isp_devparam[tgt].actv_period = period;
sdp->isp_devparam[tgt].actv_offset = offset;
- get = (bus << 16) | tgt;
- (void) isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, &get);
+ isp_async(isp, ISPASYNC_NEW_TGT_PARAMS, chan, tgt);
}
}
for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
if (sdp->isp_devparam[tgt].dev_update ||
sdp->isp_devparam[tgt].dev_refresh) {
- isp->isp_update |= (1 << bus);
+ sdp->update = 1;
break;
}
}
}
-#ifndef DEFAULT_EXEC_THROTTLE
-#define DEFAULT_EXEC_THROTTLE(isp) ISP_EXEC_THROTTLE
-#endif
-
static void
-isp_setdfltparm(ispsoftc_t *isp, int channel)
+isp_setdfltsdparm(ispsoftc_t *isp)
{
int tgt;
- sdparam *sdp;
-
- sdp = (sdparam *) isp->isp_param;
- sdp += channel;
+ sdparam *sdp, *sdp1;
- /*
- * Been there, done that, got the T-shirt...
- */
- if (sdp->isp_gotdparms) {
- return;
+ sdp = SDPARAM(isp, 0);
+ sdp->role = GET_DEFAULT_ROLE(isp, 0);
+ if (IS_DUALBUS(isp)) {
+ sdp1 = sdp + 1;
+ sdp1->role = GET_DEFAULT_ROLE(isp, 1);
+ } else {
+ sdp1 = NULL;
}
- sdp->isp_gotdparms = 1;
- sdp->isp_bad_nvram = 0;
+
/*
* Establish some default parameters.
*/
sdp->isp_cmd_dma_burst_enable = 0;
sdp->isp_data_dma_burst_enabl = 1;
sdp->isp_fifo_threshold = 0;
- sdp->isp_initiator_id = DEFAULT_IID(isp);
+ sdp->isp_initiator_id = DEFAULT_IID(isp, 0);
if (isp->isp_type >= ISP_HA_SCSI_1040) {
sdp->isp_async_data_setup = 9;
} else {
@@ -7073,50 +7560,6 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
}
/*
- * If we've not been told to avoid reading NVRAM, try and read it.
- * If we're successful reading it, we can then return because NVRAM
- * will tell us what the desired settings are. Otherwise, we establish
- * some reasonable 'fake' nvram and goal defaults.
- */
-
- if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
- if (isp_read_nvram(isp) == 0) {
- return;
- }
- sdp->isp_bad_nvram = 1;
- }
-
- /*
- * Now try and see whether we have specific values for them.
- */
- if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
- mbreg_t mbs;
-
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_GET_ACT_NEG_STATE;
- mbs.logval = MBLOGNONE;
- isp_mboxcmd(isp, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- sdp->isp_req_ack_active_neg = 1;
- sdp->isp_data_line_active_neg = 1;
- } else {
- sdp->isp_req_ack_active_neg =
- (mbs.param[1+channel] >> 4) & 0x1;
- sdp->isp_data_line_active_neg =
- (mbs.param[1+channel] >> 5) & 0x1;
- }
- }
-
- isp_prt(isp, ISP_LOGDEBUG0, sc0, sc3,
- 0, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
- sdp->isp_bus_reset_delay, sdp->isp_retry_count,
- sdp->isp_retry_delay, sdp->isp_async_data_setup);
- isp_prt(isp, ISP_LOGDEBUG0, sc1, sc3,
- sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
- sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
- sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
-
- /*
* The trick here is to establish a default for the default (honk!)
* state (goal_flags). Then try and get the current status from
* the card to fill in the current state. We don't, in fact, set
@@ -7161,49 +7604,97 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
sdp->isp_devparam[tgt].goal_period =
sdp->isp_devparam[tgt].nvrm_period = per;
- isp_prt(isp, ISP_LOGDEBUG0, sc2, sc3,
- channel, tgt, sdp->isp_devparam[tgt].nvrm_flags,
- sdp->isp_devparam[tgt].nvrm_offset,
- sdp->isp_devparam[tgt].nvrm_period);
}
+
+ /*
+ * If we're a dual bus card, just copy the data over
+ */
+ if (sdp1) {
+ *sdp1 = *sdp;
+ sdp1->isp_initiator_id = DEFAULT_IID(isp, 1);
+ }
+
+ /*
+ * If we've not been told to avoid reading NVRAM, try and read it.
+ * If we're successful reading it, we can then return because NVRAM
+ * will tell us what the desired settings are. Otherwise, we establish
+ * some reasonable 'fake' nvram and goal defaults.
+ */
+ if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
+ mbreg_t mbs;
+
+ if (isp_read_nvram(isp, 0) == 0) {
+ if (IS_DUALBUS(isp)) {
+ if (isp_read_nvram(isp, 1) == 0) {
+ return;
+ }
+ }
+ }
+ MBSINIT(&mbs, MBOX_GET_ACT_NEG_STATE, MBLOGNONE, 0);
+ isp_mboxcmd(isp, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ sdp->isp_req_ack_active_neg = 1;
+ sdp->isp_data_line_active_neg = 1;
+ if (sdp1) {
+ sdp1->isp_req_ack_active_neg = 1;
+ sdp1->isp_data_line_active_neg = 1;
+ }
+ } else {
+ sdp->isp_req_ack_active_neg =
+ (mbs.param[1] >> 4) & 0x1;
+ sdp->isp_data_line_active_neg =
+ (mbs.param[1] >> 5) & 0x1;
+ if (sdp1) {
+ sdp1->isp_req_ack_active_neg =
+ (mbs.param[2] >> 4) & 0x1;
+ sdp1->isp_data_line_active_neg =
+ (mbs.param[2] >> 5) & 0x1;
+ }
+ }
+ }
+
}
-#ifndef DEFAULT_FRAMESIZE
-#define DEFAULT_FRAMESIZE(isp) ICB_DFLT_FRMLEN
-#endif
static void
-isp_setdfltfcparm(ispsoftc_t *isp)
+isp_setdfltfcparm(ispsoftc_t *isp, int chan)
{
- fcparam *fcp = FCPARAM(isp);
+ fcparam *fcp = FCPARAM(isp, chan);
- if (fcp->isp_gotdparms) {
- return;
- }
- fcp->isp_gotdparms = 1;
- fcp->isp_bad_nvram = 0;
- fcp->isp_maxfrmlen = DEFAULT_FRAMESIZE(isp);
+ /*
+ * Establish some default parameters.
+ */
+ fcp->role = GET_DEFAULT_ROLE(isp, chan);
fcp->isp_maxalloc = ICB_DFLT_ALLOC;
- fcp->isp_execthrottle = DEFAULT_EXEC_THROTTLE(isp);
fcp->isp_retry_delay = ICB_DFLT_RDELAY;
fcp->isp_retry_count = ICB_DFLT_RCOUNT;
- /* Platform specific.... */
- fcp->isp_loopid = DEFAULT_LOOPID(isp);
- fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp);
- fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp);
+ fcp->isp_loopid = DEFAULT_LOOPID(isp, chan);
+ fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
+ fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
fcp->isp_fwoptions = 0;
- fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
- fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
- fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
- fcp->isp_fwoptions |= ICBOPT_FAST_POST;
- if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) {
- fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
+ fcp->isp_lasthdl = NIL_HANDLE;
+
+ if (IS_24XX(isp)) {
+ fcp->isp_fwoptions |= ICB2400_OPT1_FAIRNESS;
+ fcp->isp_fwoptions |= ICB2400_OPT1_HARD_ADDRESS;
+ if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) {
+ fcp->isp_fwoptions |= ICB2400_OPT1_FULL_DUPLEX;
+ }
+ fcp->isp_fwoptions |= ICB2400_OPT1_BOTH_WWNS;
+ } else {
+ fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
+ fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
+ fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
+ fcp->isp_fwoptions |= ICBOPT_FAST_POST;
+ if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) {
+ fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
+ }
+ /*
+ * Make sure this is turned off now until we get
+ * extended options from NVRAM
+ */
+ fcp->isp_fwoptions &= ~ICBOPT_EXTENDED;
}
- /*
- * Make sure this is turned off now until we get
- * extended options from NVRAM
- */
- fcp->isp_fwoptions &= ~ICBOPT_EXTENDED;
/*
* Now try and read NVRAM unless told to not do so.
@@ -7215,61 +7706,22 @@ isp_setdfltfcparm(ispsoftc_t *isp)
* Give a couple of tries at reading NVRAM.
*/
for (i = 0; i < 2; i++) {
- j = isp_read_nvram(isp);
+ j = isp_read_nvram(isp, chan);
if (j == 0) {
break;
}
}
if (j) {
- fcp->isp_bad_nvram = 1;
isp->isp_confopts |= ISP_CFG_NONVRAM;
- isp->isp_confopts |= ISP_CFG_OWNWWPN;
- isp->isp_confopts |= ISP_CFG_OWNWWNN;
}
- } else {
- isp->isp_confopts |= ISP_CFG_OWNWWPN|ISP_CFG_OWNWWNN;
}
- /*
- * Set node && port to override platform set defaults
- * unless the nvram read failed (or none was done),
- * or the platform code wants to use what had been
- * set in the defaults.
- */
- if (isp->isp_confopts & ISP_CFG_OWNWWNN) {
- isp_prt(isp, ISP_LOGCONFIG, "Using Node WWN 0x%08x%08x",
- (uint32_t) (DEFAULT_NODEWWN(isp) >> 32),
- (uint32_t) (DEFAULT_NODEWWN(isp) & 0xffffffff));
- ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
- } else {
- /*
- * We always start out with values derived
- * from NVRAM or our platform default.
- */
- ISP_NODEWWN(isp) = fcp->isp_wwnn_nvram;
- if (fcp->isp_wwnn_nvram == 0) {
- isp_prt(isp, ISP_LOGCONFIG,
- "bad WWNN- using default");
- ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
- }
- }
- if (isp->isp_confopts & ISP_CFG_OWNWWPN) {
- isp_prt(isp, ISP_LOGCONFIG, "Using Port WWN 0x%08x%08x",
- (uint32_t) (DEFAULT_PORTWWN(isp) >> 32),
- (uint32_t) (DEFAULT_PORTWWN(isp) & 0xffffffff));
- ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp);
- } else {
- /*
- * We always start out with values derived
- * from NVRAM or our platform default.
- */
- ISP_PORTWWN(isp) = fcp->isp_wwpn_nvram;
- if (fcp->isp_wwpn_nvram == 0) {
- isp_prt(isp, ISP_LOGCONFIG,
- "bad WWPN- using default");
- ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp);
- }
- }
+ fcp->isp_wwnn = ACTIVE_NODEWWN(isp, chan);
+ fcp->isp_wwpn = ACTIVE_PORTWWN(isp, chan);
+ isp_prt(isp, ISP_LOGCONFIG, "Chan %d 0x%08x%08x/0x%08x%08x Role %s",
+ chan, (uint32_t) (fcp->isp_wwnn >> 32), (uint32_t) (fcp->isp_wwnn),
+ (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) (fcp->isp_wwpn),
+ isp_class3_roles[fcp->role]);
}
/*
@@ -7279,28 +7731,28 @@ isp_setdfltfcparm(ispsoftc_t *isp)
*/
void
-isp_reinit(ispsoftc_t *isp)
+isp_reinit(ispsoftc_t *isp, int do_load_defaults)
{
- XS_T *xs;
- uint32_t tmp;
+ int i;
+
+ isp_reset(isp, do_load_defaults);
- if (IS_FC(isp)) {
- ISP_MARK_PORTDB(isp, 0);
- }
- isp_reset(isp);
if (isp->isp_state != ISP_RESETSTATE) {
- isp_prt(isp, ISP_LOGERR, "isp_reinit cannot reset card");
- } else if (isp->isp_role != ISP_ROLE_NONE) {
- isp_init(isp);
- if (isp->isp_state == ISP_INITSTATE) {
- isp->isp_state = ISP_RUNSTATE;
- }
- if (isp->isp_state != ISP_RUNSTATE) {
- isp_prt(isp, ISP_LOGERR,
- "isp_reinit cannot restart card");
- ISP_DISABLE_INTS(isp);
- }
- } else {
+ isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
+ ISP_DISABLE_INTS(isp);
+ goto cleanup;
+ }
+
+ isp_init(isp);
+
+ if (isp->isp_state == ISP_INITSTATE) {
+ isp->isp_state = ISP_RUNSTATE;
+ }
+
+ if (isp->isp_state != ISP_RUNSTATE) {
+#ifndef ISP_TARGET_MODE
+ isp_prt(isp, ISP_LOGWARN, "%s: not at runstate", __func__);
+#endif
ISP_DISABLE_INTS(isp);
if (IS_FC(isp)) {
/*
@@ -7315,51 +7767,36 @@ isp_reinit(ispsoftc_t *isp)
}
}
}
- isp->isp_nactive = 0;
- for (tmp = 0; tmp < isp->isp_maxcmds; tmp++) {
- uint32_t handle;
+ cleanup:
- xs = isp->isp_xflist[tmp];
- if (xs == NULL) {
- continue;
- }
- handle = isp_find_handle(isp, xs);
- if (handle == 0) {
- continue;
- }
- isp_destroy_handle(isp, handle);
- if (XS_XFRLEN(xs)) {
- ISP_DMAFREE(isp, xs, handle);
- XS_RESID(xs) = XS_XFRLEN(xs);
- } else {
- XS_RESID(xs) = 0;
+ isp->isp_nactive = 0;
+
+ isp_clear_commands(isp);
+ if (IS_FC(isp)) {
+ for (i = 0; i < isp->isp_nchan; i++) {
+ ISP_MARK_PORTDB(isp, i, -1);
}
- XS_SETERR(xs, HBA_BUSRESET);
- isp_done(xs);
}
-#ifdef ISP_TARGET_MODE
- MEMZERO(isp->isp_tgtlist, isp->isp_maxcmds * sizeof (void **));
-#endif
}
/*
* NVRAM Routines
*/
static int
-isp_read_nvram(ispsoftc_t *isp)
+isp_read_nvram(ispsoftc_t *isp, int bus)
{
int i, amt, retval;
uint8_t csum, minversion;
union {
- uint8_t _x[ISP2100_NVRAM_SIZE];
- uint16_t _s[ISP2100_NVRAM_SIZE>>1];
+ uint8_t _x[ISP2400_NVRAM_SIZE];
+ uint16_t _s[ISP2400_NVRAM_SIZE>>1];
} _n;
#define nvram_data _n._x
#define nvram_words _n._s
if (IS_24XX(isp)) {
- return (isp_read_nvram_2400(isp));
+ return (isp_read_nvram_2400(isp, nvram_data));
} else if (IS_FC(isp)) {
amt = ISP2100_NVRAM_SIZE;
minversion = 1;
@@ -7403,14 +7840,11 @@ isp_read_nvram(ispsoftc_t *isp)
}
if (IS_ULTRA3(isp)) {
- isp_parse_nvram_12160(isp, 0, nvram_data);
- if (IS_12160(isp))
- isp_parse_nvram_12160(isp, 1, nvram_data);
+ isp_parse_nvram_12160(isp, bus, nvram_data);
} else if (IS_1080(isp)) {
- isp_parse_nvram_1080(isp, 0, nvram_data);
+ isp_parse_nvram_1080(isp, bus, nvram_data);
} else if (IS_1280(isp) || IS_1240(isp)) {
- isp_parse_nvram_1080(isp, 0, nvram_data);
- isp_parse_nvram_1080(isp, 1, nvram_data);
+ isp_parse_nvram_1080(isp, bus, nvram_data);
} else if (IS_SCSI(isp)) {
isp_parse_nvram_1020(isp, nvram_data);
} else {
@@ -7424,18 +7858,17 @@ out:
}
static int
-isp_read_nvram_2400(ispsoftc_t *isp)
+isp_read_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
{
- uint8_t *nvram_data = FCPARAM(isp)->isp_scratch;
int retval = 0;
uint32_t addr, csum, lwrds, *dptr;
-
+
if (isp->isp_port) {
addr = ISP2400_NVRAM_PORT1_ADDR;
} else {
addr = ISP2400_NVRAM_PORT0_ADDR;
}
-
+
dptr = (uint32_t *) nvram_data;
for (lwrds = 0; lwrds < ISP2400_NVRAM_SIZE >> 2; lwrds++) {
isp_rd_2400_nvram(isp, addr++, dptr++);
@@ -7470,12 +7903,12 @@ isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp)
uint16_t bit, rqst, junk;
ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
- USEC_DELAY(10);
+ ISP_DELAY(10);
ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
- USEC_DELAY(10);
+ ISP_DELAY(10);
if (IS_FC(isp)) {
- wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1);
+ wo &= ((ISP2100_NVRAM_SIZE >> 1) - 1);
if (IS_2312(isp) && isp->isp_port) {
wo += 128;
}
@@ -7501,13 +7934,13 @@ isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp)
bit = BIU_NVRAM_SELECT;
}
ISP_WRITE(isp, BIU_NVRAM, bit);
- USEC_DELAY(10);
+ ISP_DELAY(10);
junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
ISP_WRITE(isp, BIU_NVRAM, bit | BIU_NVRAM_CLOCK);
- USEC_DELAY(10);
+ ISP_DELAY(10);
junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
ISP_WRITE(isp, BIU_NVRAM, bit);
- USEC_DELAY(10);
+ ISP_DELAY(10);
junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
}
/*
@@ -7518,18 +7951,18 @@ isp_rdnvram_word(ispsoftc_t *isp, int wo, uint16_t *rp)
uint16_t rv;
*rp <<= 1;
ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT|BIU_NVRAM_CLOCK);
- USEC_DELAY(10);
+ ISP_DELAY(10);
rv = ISP_READ(isp, BIU_NVRAM);
if (rv & BIU_NVRAM_DATAIN) {
*rp |= 1;
}
- USEC_DELAY(10);
+ ISP_DELAY(10);
ISP_WRITE(isp, BIU_NVRAM, BIU_NVRAM_SELECT);
- USEC_DELAY(10);
+ ISP_DELAY(10);
junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
}
ISP_WRITE(isp, BIU_NVRAM, 0);
- USEC_DELAY(10);
+ ISP_DELAY(10);
junk = ISP_READ(isp, BIU_NVRAM); /* force PCI flush */
ISP_SWIZZLE_NVRAM_WORD(isp, rp);
}
@@ -7538,12 +7971,15 @@ static void
isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
{
int loops = 0;
- const uint32_t base = 0x7ffe0000;
+ uint32_t base = 0x7ffe0000;
uint32_t tmp = 0;
+ if (IS_25XX(isp)) {
+ base = 0x7ff00000 | 0x48000;
+ }
ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
for (loops = 0; loops < 5000; loops++) {
- USEC_DELAY(10);
+ ISP_DELAY(10);
tmp = ISP_READ(isp, BIU2400_FLASH_ADDR);
if ((tmp & (1U << 31)) != 0) {
break;
@@ -7560,7 +7996,7 @@ isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
static void
isp_parse_nvram_1020(ispsoftc_t *isp, uint8_t *nvram_data)
{
- sdparam *sdp = (sdparam *) isp->isp_param;
+ sdparam *sdp = SDPARAM(isp, 0);
int tgt;
sdp->isp_fifo_threshold =
@@ -7616,15 +8052,6 @@ isp_parse_nvram_1020(ispsoftc_t *isp, uint8_t *nvram_data)
sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data);
- isp_prt(isp, ISP_LOGDEBUG0, sc0, sc4,
- 0, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
- sdp->isp_bus_reset_delay, sdp->isp_retry_count,
- sdp->isp_retry_delay, sdp->isp_async_data_setup);
- isp_prt(isp, ISP_LOGDEBUG0, sc1, sc4,
- sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
- sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
- sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
-
for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
sdp->isp_devparam[tgt].dev_enable =
ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt);
@@ -7670,10 +8097,6 @@ isp_parse_nvram_1020(ispsoftc_t *isp, uint8_t *nvram_data)
if (ISP_NVRAM_TGT_DISC(nvram_data, tgt))
sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
sdp->isp_devparam[tgt].actv_flags = 0; /* we don't know */
- isp_prt(isp, ISP_LOGDEBUG0, sc2, sc4,
- 0, tgt, sdp->isp_devparam[tgt].nvrm_flags,
- sdp->isp_devparam[tgt].nvrm_offset,
- sdp->isp_devparam[tgt].nvrm_period);
sdp->isp_devparam[tgt].goal_offset =
sdp->isp_devparam[tgt].nvrm_offset;
sdp->isp_devparam[tgt].goal_period =
@@ -7686,11 +8109,9 @@ isp_parse_nvram_1020(ispsoftc_t *isp, uint8_t *nvram_data)
static void
isp_parse_nvram_1080(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
{
- sdparam *sdp = (sdparam *) isp->isp_param;
+ sdparam *sdp = SDPARAM(isp, bus);
int tgt;
- sdp += bus;
-
sdp->isp_fifo_threshold =
ISP1080_NVRAM_FIFO_THRESHOLD(nvram_data);
@@ -7728,16 +8149,6 @@ isp_parse_nvram_1080(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
sdp->isp_max_queue_depth =
ISP1080_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus);
- isp_prt(isp, ISP_LOGDEBUG0, sc0, sc4,
- bus, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
- sdp->isp_bus_reset_delay, sdp->isp_retry_count,
- sdp->isp_retry_delay, sdp->isp_async_data_setup);
- isp_prt(isp, ISP_LOGDEBUG0, sc1, sc4,
- sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
- sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
- sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
-
-
for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
sdp->isp_devparam[tgt].dev_enable =
ISP1080_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt, bus);
@@ -7762,10 +8173,6 @@ isp_parse_nvram_1080(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
if (ISP1080_NVRAM_TGT_DISC(nvram_data, tgt, bus))
sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
sdp->isp_devparam[tgt].actv_flags = 0;
- isp_prt(isp, ISP_LOGDEBUG0, sc2, sc4,
- bus, tgt, sdp->isp_devparam[tgt].nvrm_flags,
- sdp->isp_devparam[tgt].nvrm_offset,
- sdp->isp_devparam[tgt].nvrm_period);
sdp->isp_devparam[tgt].goal_offset =
sdp->isp_devparam[tgt].nvrm_offset;
sdp->isp_devparam[tgt].goal_period =
@@ -7778,11 +8185,9 @@ isp_parse_nvram_1080(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
static void
isp_parse_nvram_12160(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
{
- sdparam *sdp = (sdparam *) isp->isp_param;
+ sdparam *sdp = SDPARAM(isp, bus);
int tgt;
- sdp += bus;
-
sdp->isp_fifo_threshold =
ISP12160_NVRAM_FIFO_THRESHOLD(nvram_data);
@@ -7820,15 +8225,6 @@ isp_parse_nvram_12160(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
sdp->isp_max_queue_depth =
ISP12160_NVRAM_MAX_QUEUE_DEPTH(nvram_data, bus);
- isp_prt(isp, ISP_LOGDEBUG0, sc0, sc4,
- bus, sdp->isp_fifo_threshold, sdp->isp_initiator_id,
- sdp->isp_bus_reset_delay, sdp->isp_retry_count,
- sdp->isp_retry_delay, sdp->isp_async_data_setup);
- isp_prt(isp, ISP_LOGDEBUG0, sc1, sc4,
- sdp->isp_req_ack_active_neg, sdp->isp_data_line_active_neg,
- sdp->isp_data_dma_burst_enabl, sdp->isp_cmd_dma_burst_enable,
- sdp->isp_selection_timeout, sdp->isp_max_queue_depth);
-
for (tgt = 0; tgt < MAX_TARGETS; tgt++) {
sdp->isp_devparam[tgt].dev_enable =
ISP12160_NVRAM_TGT_DEVICE_ENABLE(nvram_data, tgt, bus);
@@ -7853,10 +8249,6 @@ isp_parse_nvram_12160(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
if (ISP12160_NVRAM_TGT_DISC(nvram_data, tgt, bus))
sdp->isp_devparam[tgt].nvrm_flags |= DPARM_DISC;
sdp->isp_devparam[tgt].actv_flags = 0;
- isp_prt(isp, ISP_LOGDEBUG0, sc2, sc4,
- bus, tgt, sdp->isp_devparam[tgt].nvrm_flags,
- sdp->isp_devparam[tgt].nvrm_offset,
- sdp->isp_devparam[tgt].nvrm_period);
sdp->isp_devparam[tgt].goal_offset =
sdp->isp_devparam[tgt].nvrm_offset;
sdp->isp_devparam[tgt].goal_period =
@@ -7867,41 +8259,9 @@ isp_parse_nvram_12160(ispsoftc_t *isp, int bus, uint8_t *nvram_data)
}
static void
-isp_fix_nvram_wwns(ispsoftc_t *isp)
-{
- fcparam *fcp = FCPARAM(isp);
-
- /*
- * Make sure we have both Node and Port as non-zero values.
- */
- if (fcp->isp_wwnn_nvram != 0 && fcp->isp_wwpn_nvram == 0) {
- fcp->isp_wwpn_nvram = fcp->isp_wwnn_nvram;
- } else if (fcp->isp_wwnn_nvram == 0 && fcp->isp_wwpn_nvram != 0) {
- fcp->isp_wwnn_nvram = fcp->isp_wwpn_nvram;
- }
-
- /*
- * Make the Node and Port values sane if they're NAA == 2.
- * This means to clear bits 48..56 for the Node WWN and
- * make sure that there's some non-zero value in 48..56
- * for the Port WWN.
- */
- if (fcp->isp_wwnn_nvram && fcp->isp_wwpn_nvram) {
- if ((fcp->isp_wwnn_nvram & (((uint64_t) 0xfff) << 48)) != 0 &&
- (fcp->isp_wwnn_nvram >> 60) == 2) {
- fcp->isp_wwnn_nvram &= ~((uint64_t) 0xfff << 48);
- }
- if ((fcp->isp_wwpn_nvram & (((uint64_t) 0xfff) << 48)) == 0 &&
- (fcp->isp_wwpn_nvram >> 60) == 2) {
- fcp->isp_wwpn_nvram |= ((uint64_t) 1 << 56);
- }
- }
-}
-
-static void
isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
{
- fcparam *fcp = FCPARAM(isp);
+ fcparam *fcp = FCPARAM(isp, 0);
uint64_t wwn;
/*
@@ -7918,7 +8278,7 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
wwn = ISP2100_NVRAM_PORT_NAME(nvram_data);
if (wwn) {
isp_prt(isp, ISP_LOGCONFIG, "NVRAM Port WWN 0x%08x%08x",
- (uint32_t) (wwn >> 32), (uint32_t) (wwn & 0xffffffff));
+ (uint32_t) (wwn >> 32), (uint32_t) (wwn));
if ((wwn >> 60) == 0) {
wwn |= (((uint64_t) 2)<< 60);
}
@@ -7929,7 +8289,7 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
if (wwn) {
isp_prt(isp, ISP_LOGCONFIG, "NVRAM Node WWN 0x%08x%08x",
(uint32_t) (wwn >> 32),
- (uint32_t) (wwn & 0xffffffff));
+ (uint32_t) (wwn));
if ((wwn >> 60) == 0) {
wwn |= (((uint64_t) 2)<< 60);
}
@@ -7939,11 +8299,10 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
}
fcp->isp_wwnn_nvram = wwn;
- isp_fix_nvram_wwns(isp);
-
fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);
if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
- fcp->isp_maxfrmlen = ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data);
+ DEFAULT_FRAMESIZE(isp) =
+ ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data);
}
fcp->isp_retry_delay = ISP2100_NVRAM_RETRY_DELAY(nvram_data);
fcp->isp_retry_count = ISP2100_NVRAM_RETRY_COUNT(nvram_data);
@@ -7951,14 +8310,16 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
fcp->isp_loopid = ISP2100_NVRAM_HARDLOOPID(nvram_data);
}
if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) {
- fcp->isp_execthrottle =
+ DEFAULT_EXEC_THROTTLE(isp) =
ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data);
}
fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data);
isp_prt(isp, ISP_LOGDEBUG0,
"NVRAM 0x%08x%08x 0x%08x%08x maxalloc %d maxframelen %d",
- (uint32_t) (fcp->isp_wwnn_nvram >> 32), (uint32_t) fcp->isp_wwnn_nvram,
- (uint32_t) (fcp->isp_wwpn_nvram >> 32), (uint32_t) fcp->isp_wwpn_nvram,
+ (uint32_t) (fcp->isp_wwnn_nvram >> 32),
+ (uint32_t) fcp->isp_wwnn_nvram,
+ (uint32_t) (fcp->isp_wwpn_nvram >> 32),
+ (uint32_t) fcp->isp_wwpn_nvram,
ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data),
ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data));
isp_prt(isp, ISP_LOGDEBUG0,
@@ -7977,7 +8338,7 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
static void
isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
{
- fcparam *fcp = FCPARAM(isp);
+ fcparam *fcp = FCPARAM(isp, 0);
uint64_t wwn;
isp_prt(isp, ISP_LOGDEBUG0,
@@ -8012,343 +8373,21 @@ isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
}
fcp->isp_wwnn_nvram = wwn;
- isp_fix_nvram_wwns(isp);
-
if (ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data)) {
fcp->isp_maxalloc = ISP2400_NVRAM_EXCHANGE_COUNT(nvram_data);
}
if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) {
- fcp->isp_maxfrmlen = ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
+ DEFAULT_FRAMESIZE(isp) =
+ ISP2400_NVRAM_MAXFRAMELENGTH(nvram_data);
}
if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) {
fcp->isp_loopid = ISP2400_NVRAM_HARDLOOPID(nvram_data);
}
if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) {
- fcp->isp_execthrottle =
+ DEFAULT_EXEC_THROTTLE(isp) =
ISP2400_NVRAM_EXECUTION_THROTTLE(nvram_data);
}
fcp->isp_fwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS1(nvram_data);
fcp->isp_xfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS2(nvram_data);
fcp->isp_zfwoptions = ISP2400_NVRAM_FIRMWARE_OPTIONS3(nvram_data);
}
-
-#ifdef ISP_FW_CRASH_DUMP
-static void isp2200_fw_dump(ispsoftc_t *);
-static void isp2300_fw_dump(ispsoftc_t *);
-
-static void
-isp2200_fw_dump(ispsoftc_t *isp)
-{
- int i, j;
- mbreg_t mbs;
- uint16_t *ptr;
-
- MEMZERO(&mbs, sizeof (mbs));
- ptr = FCPARAM(isp)->isp_dump_data;
- if (ptr == NULL) {
- isp_prt(isp, ISP_LOGERR,
- "No place to dump RISC registers and SRAM");
- return;
- }
- if (*ptr++) {
- isp_prt(isp, ISP_LOGERR,
- "dump area for RISC registers and SRAM already used");
- return;
- }
- ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
- for (i = 0; i < 100; i++) {
- USEC_DELAY(100);
- if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
- break;
- }
- }
- if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
- /*
- * PBIU Registers
- */
- for (i = 0; i < 8; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + (i << 1));
- }
-
- /*
- * Mailbox Registers
- */
- for (i = 0; i < 8; i++) {
- *ptr++ = ISP_READ(isp, MBOX_BLOCK + (i << 1));
- }
-
- /*
- * DMA Registers
- */
- for (i = 0; i < 48; i++) {
- *ptr++ = ISP_READ(isp, DMA_BLOCK + 0x20 + (i << 1));
- }
-
- /*
- * RISC H/W Registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0);
- for (i = 0; i < 16; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0xA0 + (i << 1));
- }
-
- /*
- * RISC GP Registers
- */
- for (j = 0; j < 8; j++) {
- ISP_WRITE(isp, BIU_BLOCK + 0xA4, 0x2000 + (j << 8));
- for (i = 0; i < 16; i++) {
- *ptr++ =
- ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
- }
-
- /*
- * Frame Buffer Hardware Registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0x10);
- for (i = 0; i < 16; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
-
- /*
- * Fibre Protocol Module 0 Hardware Registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0x20);
- for (i = 0; i < 64; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
-
- /*
- * Fibre Protocol Module 1 Hardware Registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0x30);
- for (i = 0; i < 64; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
- } else {
- isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause");
- return;
- }
- isp_prt(isp, ISP_LOGALL,
- "isp_fw_dump: RISC registers dumped successfully");
- ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
- for (i = 0; i < 100; i++) {
- USEC_DELAY(100);
- if (ISP_READ(isp, OUTMAILBOX0) == 0) {
- break;
- }
- }
- if (ISP_READ(isp, OUTMAILBOX0) != 0) {
- isp_prt(isp, ISP_LOGERR, "Board Would Not Reset");
- return;
- }
- ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
- for (i = 0; i < 100; i++) {
- USEC_DELAY(100);
- if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
- break;
- }
- }
- if ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
- isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause After Reset");
- return;
- }
- ISP_WRITE(isp, RISC_EMB, 0xf2);
- ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
- for (i = 0; i < 100; i++) {
- USEC_DELAY(100);
- if ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) {
- break;
- }
- }
- ISP_ENABLE_INTS(isp);
- mbs.param[0] = MBOX_READ_RAM_WORD;
- mbs.param[1] = 0x1000;
- isp->isp_mbxworkp = (void *) ptr;
- isp->isp_mbxwrk0 = 0xefff; /* continuation count */
- isp->isp_mbxwrk1 = 0x1001; /* next SRAM address */
- isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGWARN,
- "RAM DUMP FAILED @ WORD %x", isp->isp_mbxwrk1);
- return;
- }
- ptr = isp->isp_mbxworkp; /* finish fetch of final word */
- *ptr++ = isp->isp_mboxtmp[2];
- isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped successfully");
- FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */
- (void) isp_async(isp, ISPASYNC_FW_DUMPED, 0);
-}
-
-static void
-isp2300_fw_dump(ispsoftc_t *isp)
-{
- int i, j;
- mbreg_t mbs;
- uint16_t *ptr;
-
- MEMZERO(&mbs, sizeof (mbs));
- ptr = FCPARAM(isp)->isp_dump_data;
- if (ptr == NULL) {
- isp_prt(isp, ISP_LOGERR,
- "No place to dump RISC registers and SRAM");
- return;
- }
- if (*ptr++) {
- isp_prt(isp, ISP_LOGERR,
- "dump area for RISC registers and SRAM already used");
- return;
- }
- ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
- for (i = 0; i < 100; i++) {
- USEC_DELAY(100);
- if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
- break;
- }
- }
- if (ISP_READ(isp, HCCR) & HCCR_PAUSE) {
- /*
- * PBIU registers
- */
- for (i = 0; i < 8; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + (i << 1));
- }
-
- /*
- * ReqQ-RspQ-Risc2Host Status registers
- */
- for (i = 0; i < 8; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x10 + (i << 1));
- }
-
- /*
- * Mailbox Registers
- */
- for (i = 0; i < 32; i++) {
- *ptr++ =
- ISP_READ(isp, PCI_MBOX_REGS2300_OFF + (i << 1));
- }
-
- /*
- * Auto Request Response DMA registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0x40);
- for (i = 0; i < 32; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
-
- /*
- * DMA registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0x50);
- for (i = 0; i < 48; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
-
- /*
- * RISC hardware registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0);
- for (i = 0; i < 16; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0xA0 + (i << 1));
- }
-
- /*
- * RISC GP? registers
- */
- for (j = 0; j < 8; j++) {
- ISP_WRITE(isp, BIU_BLOCK + 0xA4, 0x2000 + (j << 9));
- for (i = 0; i < 16; i++) {
- *ptr++ =
- ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
- }
-
- /*
- * frame buffer hardware registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0x10);
- for (i = 0; i < 64; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
-
- /*
- * FPM B0 hardware registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0x20);
- for (i = 0; i < 64; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
-
- /*
- * FPM B1 hardware registers
- */
- ISP_WRITE(isp, BIU2100_CSR, 0x30);
- for (i = 0; i < 64; i++) {
- *ptr++ = ISP_READ(isp, BIU_BLOCK + 0x80 + (i << 1));
- }
- } else {
- isp_prt(isp, ISP_LOGERR, "RISC Would Not Pause");
- return;
- }
- isp_prt(isp, ISP_LOGALL,
- "isp_fw_dump: RISC registers dumped successfully");
- ISP_WRITE(isp, BIU2100_CSR, BIU2100_SOFT_RESET);
- for (i = 0; i < 100; i++) {
- USEC_DELAY(100);
- if (ISP_READ(isp, OUTMAILBOX0) == 0) {
- break;
- }
- }
- if (ISP_READ(isp, OUTMAILBOX0) != 0) {
- isp_prt(isp, ISP_LOGERR, "Board Would Not Reset");
- return;
- }
- ISP_ENABLE_INTS(isp);
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_READ_RAM_WORD;
- mbs.param[1] = 0x800;
- isp->isp_mbxworkp = (void *) ptr;
- isp->isp_mbxwrk0 = 0xf7ff; /* continuation count */
- isp->isp_mbxwrk1 = 0x801; /* next SRAM address */
- isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGWARN,
- "RAM DUMP FAILED @ WORD %x", isp->isp_mbxwrk1);
- return;
- }
- ptr = isp->isp_mbxworkp; /* finish fetch of final word */
- *ptr++ = isp->isp_mboxtmp[2];
- MEMZERO(&mbs, sizeof (mbs));
- mbs.param[0] = MBOX_READ_RAM_WORD_EXTENDED;
- mbs.param[8] = 1;
- isp->isp_mbxworkp = (void *) ptr;
- isp->isp_mbxwrk0 = 0xffff; /* continuation count */
- isp->isp_mbxwrk1 = 0x1; /* next SRAM address */
- isp->isp_mbxwrk8 = 0x1;
- isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_prt(isp, ISP_LOGWARN,
- "RAM DUMP FAILED @ WORD %x", 0x10000 + isp->isp_mbxwrk1);
- return;
- }
- ptr = isp->isp_mbxworkp; /* finish final word */
- *ptr++ = mbs.param[2];
- isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped successfully");
- FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */
- (void) isp_async(isp, ISPASYNC_FW_DUMPED, 0);
-}
-
-void
-isp_fw_dump(ispsoftc_t *isp)
-{
- if (IS_2200(isp))
- isp2200_fw_dump(isp);
- else if (IS_23XX(isp))
- isp2300_fw_dump(isp);
- else if (IS_24XX(isp))
- isp_prt(isp, ISP_LOGERR, "24XX dump method undefined");
-
-}
-#endif
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index beb8fa1..b6f172b 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997-2006 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,39 +32,36 @@ __FBSDID("$FreeBSD$");
#include <dev/isp/isp_freebsd.h>
#include <sys/unistd.h>
#include <sys/kthread.h>
-#include <machine/stdarg.h> /* for use by isp_prt below */
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/ioccom.h>
#include <dev/isp/isp_ioctl.h>
-#if __FreeBSD_version >= 500000
-#include <sys/sysctl.h>
-#else
#include <sys/devicestat.h>
-#endif
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
-#if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025
-#define CAM_NEW_TRAN_CODE 1
+#if __FreeBSD_version < 800002
+#define THREAD_CREATE kthread_create
+#else
+#define THREAD_CREATE kproc_create
#endif
-
MODULE_VERSION(isp, 1);
MODULE_DEPEND(isp, cam, 1, 1, 1);
int isp_announced = 0;
-int isp_fabric_hysteresis = 5;
-int isp_loop_down_limit = 300; /* default loop down limit */
+int isp_fabric_hysteresis = 3;
+int isp_loop_down_limit = 60; /* default loop down limit */
int isp_change_is_bad = 0; /* "changed" devices are bad */
-int isp_quickboot_time = 15; /* don't wait more than N secs for loop up */
+int isp_quickboot_time = 7; /* don't wait more than N secs for loop up */
int isp_gone_device_time = 30; /* grace time before reporting device lost */
+int isp_autoconfig = 1; /* automatically attach/detach devices */
static const char *roles[4] = {
"(none)", "Target", "Initiator", "Target/Initiator"
};
-static const char prom3[] =
- "PortID 0x%06x Departed from Target %u because of %s";
+static const char prom3[] = "Chan %d PortID 0x%06x Departed from Target %u because of %s";
+static const char rqo[] = "%s: Request Queue Overflow\n";
-static void isp_freeze_loopdown(ispsoftc_t *, char *);
+static void isp_freeze_loopdown(ispsoftc_t *, int, char *);
static d_ioctl_t ispioctl;
static void isp_intr_enable(void *);
static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
@@ -73,100 +70,48 @@ static timeout_t isp_watchdog;
static timeout_t isp_ldt;
static void isp_kthread(void *);
static void isp_action(struct cam_sim *, union ccb *);
-
-#if __FreeBSD_version < 700000
-ispfwfunc *isp_get_firmware_p = NULL;
+#ifdef ISP_INTERNAL_TARGET
+static void isp_target_thread_pi(void *);
+static void isp_target_thread_fc(void *);
#endif
+static void isp_timer(void *);
-#if __FreeBSD_version < 500000
-#define ISP_CDEV_MAJOR 248
-static struct cdevsw isp_cdevsw = {
- /* open */ nullopen,
- /* close */ nullclose,
- /* read */ noread,
- /* write */ nowrite,
- /* ioctl */ ispioctl,
- /* poll */ nopoll,
- /* mmap */ nommap,
- /* strategy */ nostrategy,
- /* name */ "isp",
- /* maj */ ISP_CDEV_MAJOR,
- /* dump */ nodump,
- /* psize */ nopsize,
- /* flags */ D_TAPE,
-};
-#define isp_sysctl_update(x) do { ; } while (0)
-#else
static struct cdevsw isp_cdevsw = {
.d_version = D_VERSION,
-#if __FreeBSD_version < 700037
- .d_flags = D_NEEDGIANT,
-#endif
.d_ioctl = ispioctl,
.d_name = "isp",
};
-static void isp_sysctl_update(ispsoftc_t *);
-#endif
-
-static ispsoftc_t *isplist = NULL;
-void
-isp_attach(ispsoftc_t *isp)
+static int
+isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
{
- int primary, secondary;
struct ccb_setasync csa;
- struct cam_devq *devq;
struct cam_sim *sim;
struct cam_path *path;
/*
- * Establish (in case of 12X0) which bus is the primary.
- */
-
- primary = 0;
- secondary = 1;
-
- /*
- * Create the device queue for our SIM(s).
- */
- devq = cam_simq_alloc(isp->isp_maxcmds);
- if (devq == NULL) {
- return;
- }
-
- /*
* Construct our SIM entry.
*/
- sim = isp_sim_alloc(isp_action, isp_poll, "isp", isp,
- device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
+ sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp, device_get_unit(isp->isp_dev), &isp->isp_osinfo.lock, isp->isp_maxcmds, isp->isp_maxcmds, devq);
+
if (sim == NULL) {
- cam_simq_free(devq);
- return;
+ return (ENOMEM);
}
- isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
- isp->isp_osinfo.ehook.ich_arg = isp;
- ISP_UNLOCK(isp);
- if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
- ISP_LOCK(isp);
- cam_sim_free(sim, TRUE);
- isp_prt(isp, ISP_LOGERR,
- "could not establish interrupt enable hook");
- return;
- }
ISP_LOCK(isp);
-
- if (xpt_bus_register(sim, isp->isp_dev, primary) != CAM_SUCCESS) {
- cam_sim_free(sim, TRUE);
- return;
+ if (xpt_bus_register(sim, isp->isp_dev, chan) != CAM_SUCCESS) {
+ ISP_UNLOCK(isp);
+ cam_sim_free(sim, FALSE);
+ return (EIO);
}
+ ISP_UNLOCK(isp);
- if (xpt_create_path(&path, NULL, cam_sim_path(sim),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ if (xpt_create_path(&path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ ISP_LOCK(isp);
xpt_bus_deregister(cam_sim_path(sim));
- cam_sim_free(sim, TRUE);
- config_intrhook_disestablish(&isp->isp_osinfo.ehook);
- return;
+ ISP_UNLOCK(isp);
+ cam_sim_free(sim, FALSE);
+ return (ENXIO);
}
xpt_setup_ccb(&csa.ccb_h, path, 5);
@@ -175,188 +120,195 @@ isp_attach(ispsoftc_t *isp)
csa.callback = isp_cam_async;
csa.callback_arg = sim;
xpt_action((union ccb *)&csa);
- isp->isp_sim = sim;
- isp->isp_path = path;
- /*
- * If we have a second channel, construct SIM entry for that.
- */
- if (IS_DUALBUS(isp)) {
- sim = isp_sim_alloc(isp_action, isp_poll, "isp", isp,
- device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
- if (sim == NULL) {
- xpt_bus_deregister(cam_sim_path(isp->isp_sim));
- xpt_free_path(isp->isp_path);
- cam_simq_free(devq);
- config_intrhook_disestablish(&isp->isp_osinfo.ehook);
- return;
- }
- if (xpt_bus_register(sim, isp->isp_dev, secondary) !=
- CAM_SUCCESS) {
- xpt_bus_deregister(cam_sim_path(isp->isp_sim));
- xpt_free_path(isp->isp_path);
- cam_sim_free(sim, TRUE);
- config_intrhook_disestablish(&isp->isp_osinfo.ehook);
- return;
+ if (IS_SCSI(isp)) {
+ struct isp_spi *spi = ISP_SPI_PC(isp, chan);
+ spi->sim = sim;
+ spi->path = path;
+#ifdef ISP_INTERNAL_TARGET
+ ISP_SET_PC(isp, chan, proc_active, 1);
+ if (THREAD_CREATE(isp_target_thread_pi, spi, &spi->target_proc, 0, 0, "%s: isp_test_tgt%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) {
+ ISP_SET_PC(isp, chan, proc_active, 0);
+ isp_prt(isp, ISP_LOGERR, "cannot create test target thread");
}
+#endif
+ } else {
+ struct isp_fc *fc = ISP_FC_PC(isp, chan);
- if (xpt_create_path(&path, NULL, cam_sim_path(sim),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- xpt_bus_deregister(cam_sim_path(isp->isp_sim));
- xpt_free_path(isp->isp_path);
- xpt_bus_deregister(cam_sim_path(sim));
- cam_sim_free(sim, TRUE);
- config_intrhook_disestablish(&isp->isp_osinfo.ehook);
- return;
+ fc->sim = sim;
+ fc->path = path;
+ fc->isp = isp;
+
+ callout_init_mtx(&fc->ldt, &isp->isp_osinfo.lock, 0);
+ callout_init_mtx(&fc->gdt, &isp->isp_osinfo.lock, 0);
+
+ if (THREAD_CREATE(isp_kthread, fc, &fc->kproc, 0, 0, "%s: fc_thrd%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) {
+ xpt_free_path(fc->path);
+ ISP_LOCK(isp);
+ xpt_bus_deregister(cam_sim_path(fc->sim));
+ ISP_UNLOCK(isp);
+ cam_sim_free(fc->sim, FALSE);
+ }
+ /*
+ * We start by being "loop down" if we have an initiator role
+ */
+ ISP_LOCK(isp);
+ if ((FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR) && fc->ldt_running == 0) {
+ isp_freeze_loopdown(isp, chan, "isp_attach");
+ fc->ldt_running = 1;
+ callout_reset(&fc->ldt, isp_quickboot_time * hz, isp_ldt, fc);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Starting Initial Loop Down Timer @ %lu", (unsigned long) time_uptime);
+ }
+ ISP_UNLOCK(isp);
+#ifdef ISP_INTERNAL_TARGET
+ ISP_SET_PC(isp, chan, proc_active, 1);
+ if (THREAD_CREATE(isp_target_thread_fc, fc, &fc->target_proc, 0, 0, "%s: isp_test_tgt%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) {
+ ISP_SET_PC(isp, chan, proc_active, 0);
+ isp_prt(isp, ISP_LOGERR, "cannot create test target thread");
}
+#endif
+ }
+ return (0);
+}
- xpt_setup_ccb(&csa.ccb_h, path, 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_LOST_DEVICE;
- csa.callback = isp_cam_async;
- csa.callback_arg = sim;
- xpt_action((union ccb *)&csa);
- isp->isp_sim2 = sim;
- isp->isp_path2 = path;
+int
+isp_attach(ispsoftc_t *isp)
+{
+ const char *nu = device_get_nameunit(isp->isp_osinfo.dev);
+ int du = device_get_unit(isp->isp_dev);
+ int chan;
+
+ isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
+ isp->isp_osinfo.ehook.ich_arg = isp;
+ if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
+ isp_prt(isp, ISP_LOGERR, "could not establish interrupt enable hook");
+ return (-EIO);
}
+ isp->isp_osinfo.ehook_active = 1;
+
/*
- * Create device nodes
+ * Create the device queue for our SIM(s).
*/
- ISP_UNLOCK(isp);
- (void) make_dev(&isp_cdevsw, device_get_unit(isp->isp_dev), UID_ROOT,
- GID_OPERATOR, 0600, "%s", device_get_nameunit(isp->isp_dev));
- isp_sysctl_update(isp);
- ISP_LOCK(isp);
-
- if (isp->isp_role != ISP_ROLE_NONE) {
- isp->isp_state = ISP_RUNSTATE;
- ISP_ENABLE_INTS(isp);
+ isp->isp_osinfo.devq = cam_simq_alloc(isp->isp_maxcmds);
+ if (isp->isp_osinfo.devq == NULL) {
+ config_intrhook_disestablish(&isp->isp_osinfo.ehook);
+ return (EIO);
}
- if (isplist == NULL) {
- isplist = isp;
- } else {
- ispsoftc_t *tmp = isplist;
- while (tmp->isp_osinfo.next) {
- tmp = tmp->isp_osinfo.next;
+
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ if (isp_attach_chan(isp, isp->isp_osinfo.devq, chan)) {
+ goto unwind;
}
- tmp->isp_osinfo.next = isp;
}
- /*
- * Create a kernel thread for fibre channel instances.
- */
- if (IS_FC(isp)) {
- isp_callout_init(&isp->isp_osinfo.ldt);
- isp_callout_init(&isp->isp_osinfo.gdt);
- ISP_UNLOCK(isp);
-#if __FreeBSD_version >= 500000
- if (kproc_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
- RFHIGHPID, 0, "%s: fc_thrd",
- device_get_nameunit(isp->isp_dev)))
-#else
- if (kproc_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
- "%s: fc_thrd", device_get_nameunit(isp->isp_dev)))
-#endif
- {
- ISP_LOCK(isp);
- xpt_bus_deregister(cam_sim_path(sim));
- cam_sim_free(sim, TRUE);
- config_intrhook_disestablish(&isp->isp_osinfo.ehook);
- isp_prt(isp, ISP_LOGERR, "could not create kthread");
- return;
+ callout_init_mtx(&isp->isp_osinfo.tmo, &isp->isp_osinfo.lock, 0);
+ callout_reset(&isp->isp_osinfo.tmo, hz, isp_timer, isp);
+ isp->isp_osinfo.timer_active = 1;
+
+ isp->isp_osinfo.cdev = make_dev(&isp_cdevsw, du, UID_ROOT, GID_OPERATOR, 0600, "%s", nu);
+ if (isp->isp_osinfo.cdev) {
+ isp->isp_osinfo.cdev->si_drv1 = isp;
+ }
+ return (0);
+
+unwind:
+ while (--chan >= 0) {
+ struct cam_sim *sim;
+ struct cam_path *path;
+ if (IS_FC(isp)) {
+ sim = ISP_FC_PC(isp, chan)->sim;
+ path = ISP_FC_PC(isp, chan)->path;
+ } else {
+ sim = ISP_SPI_PC(isp, chan)->sim;
+ path = ISP_SPI_PC(isp, chan)->path;
}
+ xpt_free_path(path);
ISP_LOCK(isp);
- /*
- * We start by being "loop down" if we have an initiator role
- */
- if (isp->isp_role & ISP_ROLE_INITIATOR) {
- isp_freeze_loopdown(isp, "isp_attach");
- isp->isp_osinfo.ldt_running = 1;
- callout_reset(&isp->isp_osinfo.ldt,
- isp_quickboot_time * hz, isp_ldt, isp);
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "Starting Initial Loop Down Timer");
+ xpt_bus_deregister(cam_sim_path(sim));
+ ISP_UNLOCK(isp);
+ cam_sim_free(sim, FALSE);
+ }
+ if (isp->isp_osinfo.ehook_active) {
+ config_intrhook_disestablish(&isp->isp_osinfo.ehook);
+ isp->isp_osinfo.ehook_active = 0;
+ }
+ if (isp->isp_osinfo.cdev) {
+ destroy_dev(isp->isp_osinfo.cdev);
+ isp->isp_osinfo.cdev = NULL;
+ }
+ cam_simq_free(isp->isp_osinfo.devq);
+ isp->isp_osinfo.devq = NULL;
+ return (-1);
+}
+
+void
+isp_detach(ispsoftc_t *isp)
+{
+ int chan;
+
+ ISP_LOCK(isp);
+ if (isp->isp_osinfo.timer_active) {
+ callout_stop(&isp->isp_osinfo.tmo);
+ isp->isp_osinfo.timer_active = 0;
+ }
+ ISP_UNLOCK(isp);
+ for (chan = isp->isp_nchan - 1; chan >= 0; chan -= 1) {
+ struct cam_sim *sim;
+ struct cam_path *path;
+ if (IS_FC(isp)) {
+ sim = ISP_FC_PC(isp, chan)->sim;
+ path = ISP_FC_PC(isp, chan)->path;
+ } else {
+ sim = ISP_SPI_PC(isp, chan)->sim;
+ path = ISP_SPI_PC(isp, chan)->path;
}
+ xpt_free_path(path);
+ ISP_LOCK(isp);
+ xpt_bus_deregister(cam_sim_path(sim));
+ ISP_UNLOCK(isp);
+ cam_sim_free(sim, FALSE);
+ }
+ if (isp->isp_osinfo.cdev) {
+ destroy_dev(isp->isp_osinfo.cdev);
+ isp->isp_osinfo.cdev = NULL;
+ }
+ if (isp->isp_osinfo.ehook_active) {
+ config_intrhook_disestablish(&isp->isp_osinfo.ehook);
+ isp->isp_osinfo.ehook_active = 0;
+ }
+ if (isp->isp_osinfo.devq == NULL) {
+ cam_simq_free(isp->isp_osinfo.devq);
+ isp->isp_osinfo.devq = NULL;
}
}
static void
-isp_freeze_loopdown(ispsoftc_t *isp, char *msg)
+isp_freeze_loopdown(ispsoftc_t *isp, int chan, char *msg)
{
- if (isp->isp_osinfo.simqfrozen == 0) {
- isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown)", msg);
- isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
- xpt_freeze_simq(isp->isp_sim, 1);
- } else {
- isp_prt(isp, ISP_LOGDEBUG0, "%s: mark frozen (loopdown)", msg);
- isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
+ if (IS_FC(isp)) {
+ struct isp_fc *fc = ISP_FC_PC(isp, chan);
+ if (fc->simqfrozen == 0) {
+ isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown) chan %d", msg, chan);
+ fc->simqfrozen = SIMQFRZ_LOOPDOWN;
+ xpt_freeze_simq(fc->sim, 1);
+ } else {
+ isp_prt(isp, ISP_LOGDEBUG0, "%s: mark frozen (loopdown) chan %d", msg, chan);
+ fc->simqfrozen |= SIMQFRZ_LOOPDOWN;
+ }
}
}
-#if __FreeBSD_version < 500000
-#define _DEV dev_t
-#define _IOP struct proc
-#else
-#define _IOP struct thread
-#define _DEV struct cdev *
-#endif
-
static int
-ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
+ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td)
{
ispsoftc_t *isp;
- int nr, retval = ENOTTY;
+ int nr, chan, retval = ENOTTY;
- isp = isplist;
- while (isp) {
- if (dev2unit(dev) == device_get_unit(isp->isp_dev)) {
- break;
- }
- isp = isp->isp_osinfo.next;
- }
- if (isp == NULL) {
- return (ENXIO);
- }
+ isp = dev->si_drv1;
switch (c) {
-#ifdef ISP_FW_CRASH_DUMP
- case ISP_GET_FW_CRASH_DUMP:
- if (IS_FC(isp)) {
- uint16_t *ptr = FCPARAM(isp)->isp_dump_data;
- size_t sz;
-
- retval = 0;
- if (IS_2200(isp)) {
- sz = QLA2200_RISC_IMAGE_DUMP_SIZE;
- } else {
- sz = QLA2300_RISC_IMAGE_DUMP_SIZE;
- }
- if (ptr && *ptr) {
- void *uaddr = *((void **) addr);
- if (copyout(ptr, uaddr, sz)) {
- retval = EFAULT;
- } else {
- *ptr = 0;
- }
- } else {
- retval = ENXIO;
- }
- }
- break;
- case ISP_FORCE_CRASH_DUMP:
- if (IS_FC(isp)) {
- ISP_LOCK(isp);
- isp_freeze_loopdown(isp,
- "ispioctl(ISP_FORCE_CRASH_DUMP)");
- isp_fw_dump(isp);
- isp_reinit(isp);
- ISP_UNLOCK(isp);
- retval = 0;
- }
- break;
-#endif
case ISP_SDBLEV:
{
int olddblev = isp->isp_dblev;
@@ -366,28 +318,65 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
break;
}
case ISP_GETROLE:
- *(int *)addr = isp->isp_role;
+ chan = *(int *)addr;
+ if (chan < 0 || chan >= isp->isp_nchan) {
+ retval = -ENXIO;
+ break;
+ }
+ if (IS_FC(isp)) {
+ *(int *)addr = FCPARAM(isp, chan)->role;
+ } else {
+ *(int *)addr = SDPARAM(isp, chan)->role;
+ }
retval = 0;
break;
case ISP_SETROLE:
nr = *(int *)addr;
+ chan = nr >> 8;
+ if (chan < 0 || chan >= isp->isp_nchan) {
+ retval = -ENXIO;
+ break;
+ }
+ nr &= 0xff;
if (nr & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) {
retval = EINVAL;
break;
}
- *(int *)addr = isp->isp_role;
- isp->isp_role = nr;
- /* FALLTHROUGH */
+ if (IS_FC(isp)) {
+ *(int *)addr = FCPARAM(isp, chan)->role;
+#ifdef ISP_INTERNAL_TARGET
+ ISP_LOCK(isp);
+ retval = isp_fc_change_role(isp, chan, nr);
+ ISP_UNLOCK(isp);
+#else
+ FCPARAM(isp, chan)->role = nr;
+#endif
+ } else {
+ *(int *)addr = SDPARAM(isp, chan)->role;
+ SDPARAM(isp, chan)->role = nr;
+ }
+ retval = 0;
+ break;
+
case ISP_RESETHBA:
ISP_LOCK(isp);
- isp_reinit(isp);
+#ifdef ISP_TARGET_MODE
+ isp_del_all_wwn_entries(isp, ISP_NOCHAN);
+#endif
+ isp_reinit(isp, 0);
ISP_UNLOCK(isp);
retval = 0;
break;
+
case ISP_RESCAN:
if (IS_FC(isp)) {
+ chan = *(int *)addr;
+ if (chan < 0 || chan >= isp->isp_nchan) {
+ retval = -ENXIO;
+ break;
+ }
ISP_LOCK(isp);
- if (isp_fc_runstate(isp, 5 * 1000000)) {
+ if (isp_fc_runstate(isp, chan, 5 * 1000000)) {
retval = EIO;
} else {
retval = 0;
@@ -395,10 +384,16 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
ISP_UNLOCK(isp);
}
break;
+
case ISP_FC_LIP:
if (IS_FC(isp)) {
+ chan = *(int *)addr;
+ if (chan < 0 || chan >= isp->isp_nchan) {
+ retval = -ENXIO;
+ break;
+ }
ISP_LOCK(isp);
- if (isp_control(isp, ISPCTL_SEND_LIP, 0)) {
+ if (isp_control(isp, ISPCTL_SEND_LIP, chan)) {
retval = EIO;
} else {
retval = 0;
@@ -418,8 +413,8 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
retval = EINVAL;
break;
}
- lp = &FCPARAM(isp)->portdb[ifc->loopid];
- if (lp->state == FC_PORTDB_STATE_VALID) {
+ lp = &FCPARAM(isp, ifc->chan)->portdb[ifc->loopid];
+ if (lp->state == FC_PORTDB_STATE_VALID || lp->target_mode) {
ifc->role = lp->roles;
ifc->loopid = lp->handle;
ifc->portid = lp->portid;
@@ -435,7 +430,7 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
{
isp_stats_t *sp = (isp_stats_t *) addr;
- MEMZERO(sp, sizeof (*sp));
+ ISP_MEMZERO(sp, sizeof (*sp));
sp->isp_stat_version = ISP_STATS_VERSION;
sp->isp_type = isp->isp_type;
sp->isp_revision = isp->isp_revision;
@@ -468,20 +463,33 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
case ISP_FC_GETHINFO:
{
struct isp_hba_device *hba = (struct isp_hba_device *) addr;
- MEMZERO(hba, sizeof (*hba));
+ int chan = hba->fc_channel;
+ if (chan < 0 || chan >= isp->isp_nchan) {
+ retval = ENXIO;
+ break;
+ }
hba->fc_fw_major = ISP_FW_MAJORX(isp->isp_fwrev);
hba->fc_fw_minor = ISP_FW_MINORX(isp->isp_fwrev);
hba->fc_fw_micro = ISP_FW_MICROX(isp->isp_fwrev);
+ hba->fc_nchannels = isp->isp_nchan;
if (IS_FC(isp)) {
- hba->fc_speed = FCPARAM(isp)->isp_gbspeed;
- hba->fc_scsi_supported = 1;
- hba->fc_topology = FCPARAM(isp)->isp_topo + 1;
- hba->fc_loopid = FCPARAM(isp)->isp_loopid;
- hba->nvram_node_wwn = FCPARAM(isp)->isp_wwnn_nvram;
- hba->nvram_port_wwn = FCPARAM(isp)->isp_wwpn_nvram;
- hba->active_node_wwn = ISP_NODEWWN(isp);
- hba->active_port_wwn = ISP_PORTWWN(isp);
+ hba->fc_nports = MAX_FC_TARG;
+ hba->fc_speed = FCPARAM(isp, hba->fc_channel)->isp_gbspeed;
+ hba->fc_topology = FCPARAM(isp, chan)->isp_topo + 1;
+ hba->fc_loopid = FCPARAM(isp, chan)->isp_loopid;
+ hba->nvram_node_wwn = FCPARAM(isp, chan)->isp_wwnn_nvram;
+ hba->nvram_port_wwn = FCPARAM(isp, chan)->isp_wwpn_nvram;
+ hba->active_node_wwn = FCPARAM(isp, chan)->isp_wwnn;
+ hba->active_port_wwn = FCPARAM(isp, chan)->isp_wwpn;
+ } else {
+ hba->fc_nports = MAX_TARGETS;
+ hba->fc_speed = 0;
+ hba->fc_topology = 0;
+ hba->nvram_node_wwn = 0ull;
+ hba->nvram_port_wwn = 0ull;
+ hba->active_node_wwn = 0ull;
+ hba->active_port_wwn = 0ull;
}
retval = 0;
break;
@@ -497,55 +505,155 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
break;
}
- memset(&mbs, 0, sizeof (mbs));
- needmarker = retval = 0;
- loopid = fct->loopid;
- if (FCPARAM(isp)->isp_2klogin == 0) {
- loopid <<= 8;
- }
- switch (fct->action) {
- case IPT_CLEAR_ACA:
- mbs.param[0] = MBOX_CLEAR_ACA;
- mbs.param[1] = loopid;
- mbs.param[2] = fct->lun;
- break;
- case IPT_TARGET_RESET:
- mbs.param[0] = MBOX_TARGET_RESET;
- mbs.param[1] = loopid;
- needmarker = 1;
- break;
- case IPT_LUN_RESET:
- mbs.param[0] = MBOX_LUN_RESET;
- mbs.param[1] = loopid;
- mbs.param[2] = fct->lun;
- needmarker = 1;
- break;
- case IPT_CLEAR_TASK_SET:
- mbs.param[0] = MBOX_CLEAR_TASK_SET;
- mbs.param[1] = loopid;
- mbs.param[2] = fct->lun;
- needmarker = 1;
- break;
- case IPT_ABORT_TASK_SET:
- mbs.param[0] = MBOX_ABORT_TASK_SET;
- mbs.param[1] = loopid;
- mbs.param[2] = fct->lun;
- needmarker = 1;
- break;
- default:
- retval = EINVAL;
+ chan = fct->chan;
+ if (chan < 0 || chan >= isp->isp_nchan) {
+ retval = -ENXIO;
break;
}
- if (retval == 0) {
- if (needmarker) {
- isp->isp_sendmarker |= 1;
+
+ needmarker = retval = 0;
+ loopid = fct->loopid;
+ ISP_LOCK(isp);
+ if (IS_24XX(isp)) {
+ uint8_t local[QENTRY_LEN];
+ isp24xx_tmf_t *tmf;
+ isp24xx_statusreq_t *sp;
+ fcparam *fcp = FCPARAM(isp, chan);
+ fcportdb_t *lp;
+ int i;
+
+ for (i = 0; i < MAX_FC_TARG; i++) {
+ lp = &fcp->portdb[i];
+ if (lp->handle == loopid) {
+ break;
+ }
}
- ISP_LOCK(isp);
+ if (i == MAX_FC_TARG) {
+ retval = ENXIO;
+ ISP_UNLOCK(isp);
+ break;
+ }
+ /* XXX VALIDATE LP XXX */
+ tmf = (isp24xx_tmf_t *) local;
+ ISP_MEMZERO(tmf, QENTRY_LEN);
+ tmf->tmf_header.rqs_entry_type = RQSTYPE_TSK_MGMT;
+ tmf->tmf_header.rqs_entry_count = 1;
+ tmf->tmf_nphdl = lp->handle;
+ tmf->tmf_delay = 2;
+ tmf->tmf_timeout = 2;
+ tmf->tmf_tidlo = lp->portid;
+ tmf->tmf_tidhi = lp->portid >> 16;
+ tmf->tmf_vpidx = ISP_GET_VPIDX(isp, chan);
+ tmf->tmf_lun[1] = fct->lun & 0xff;
+ if (fct->lun >= 256) {
+ tmf->tmf_lun[0] = 0x40 | (fct->lun >> 8);
+ }
+ switch (fct->action) {
+ case IPT_CLEAR_ACA:
+ tmf->tmf_flags = ISP24XX_TMF_CLEAR_ACA;
+ break;
+ case IPT_TARGET_RESET:
+ tmf->tmf_flags = ISP24XX_TMF_TARGET_RESET;
+ needmarker = 1;
+ break;
+ case IPT_LUN_RESET:
+ tmf->tmf_flags = ISP24XX_TMF_LUN_RESET;
+ needmarker = 1;
+ break;
+ case IPT_CLEAR_TASK_SET:
+ tmf->tmf_flags = ISP24XX_TMF_CLEAR_TASK_SET;
+ needmarker = 1;
+ break;
+ case IPT_ABORT_TASK_SET:
+ tmf->tmf_flags = ISP24XX_TMF_ABORT_TASK_SET;
+ needmarker = 1;
+ break;
+ default:
+ retval = EINVAL;
+ break;
+ }
+ if (retval) {
+ ISP_UNLOCK(isp);
+ break;
+ }
+ MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 5000000);
+ mbs.param[1] = QENTRY_LEN;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ ISP_UNLOCK(isp);
+ retval = ENOMEM;
+ break;
+ }
+ isp_put_24xx_tmf(isp, tmf, fcp->isp_scratch);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, QENTRY_LEN);
+ sp = (isp24xx_statusreq_t *) local;
+ sp->req_completion_status = 1;
retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
- ISP_UNLOCK(isp);
- if (retval)
+ MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN);
+ isp_get_24xx_response(isp, &((isp24xx_statusreq_t *)fcp->isp_scratch)[1], sp);
+ FC_SCRATCH_RELEASE(isp, chan);
+ if (retval || sp->req_completion_status != 0) {
+ FC_SCRATCH_RELEASE(isp, chan);
retval = EIO;
+ }
+ if (retval == 0) {
+ if (needmarker) {
+ fcp->sendmarker = 1;
+ }
+ }
+ } else {
+ MBSINIT(&mbs, 0, MBLOGALL, 0);
+ if (ISP_CAP_2KLOGIN(isp) == 0) {
+ loopid <<= 8;
+ }
+ switch (fct->action) {
+ case IPT_CLEAR_ACA:
+ mbs.param[0] = MBOX_CLEAR_ACA;
+ mbs.param[1] = loopid;
+ mbs.param[2] = fct->lun;
+ break;
+ case IPT_TARGET_RESET:
+ mbs.param[0] = MBOX_TARGET_RESET;
+ mbs.param[1] = loopid;
+ needmarker = 1;
+ break;
+ case IPT_LUN_RESET:
+ mbs.param[0] = MBOX_LUN_RESET;
+ mbs.param[1] = loopid;
+ mbs.param[2] = fct->lun;
+ needmarker = 1;
+ break;
+ case IPT_CLEAR_TASK_SET:
+ mbs.param[0] = MBOX_CLEAR_TASK_SET;
+ mbs.param[1] = loopid;
+ mbs.param[2] = fct->lun;
+ needmarker = 1;
+ break;
+ case IPT_ABORT_TASK_SET:
+ mbs.param[0] = MBOX_ABORT_TASK_SET;
+ mbs.param[1] = loopid;
+ mbs.param[2] = fct->lun;
+ needmarker = 1;
+ break;
+ default:
+ retval = EINVAL;
+ break;
+ }
+ if (retval == 0) {
+ if (needmarker) {
+ FCPARAM(isp, chan)->sendmarker = 1;
+ }
+ retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
+ if (retval) {
+ retval = EIO;
+ }
+ }
}
+ ISP_UNLOCK(isp);
break;
}
default:
@@ -554,53 +662,24 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
return (retval);
}
-#if __FreeBSD_version >= 500000
-static void
-isp_sysctl_update(ispsoftc_t *isp)
-{
- struct sysctl_ctx_list *ctx =
- device_get_sysctl_ctx(isp->isp_osinfo.dev);
- struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev);
-
- if (IS_SCSI(isp)) {
- return;
- }
-
- snprintf(isp->isp_osinfo.sysctl_info.fc.wwnn,
- sizeof (isp->isp_osinfo.sysctl_info.fc.wwnn), "0x%08x%08x",
- (uint32_t) (ISP_NODEWWN(isp) >> 32), (uint32_t) ISP_NODEWWN(isp));
-
- snprintf(isp->isp_osinfo.sysctl_info.fc.wwpn,
- sizeof (isp->isp_osinfo.sysctl_info.fc.wwpn), "0x%08x%08x",
- (uint32_t) (ISP_PORTWWN(isp) >> 32), (uint32_t) ISP_PORTWWN(isp));
-
- SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
- "wwnn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwnn, 0,
- "World Wide Node Name");
-
- SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
- "wwpn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwpn, 0,
- "World Wide Port Name");
-
- SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
- "loop_down_limit",
- CTLFLAG_RW, &isp->isp_osinfo.loop_down_limit, 0,
- "How long to wait for loop to come back up");
-
- SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
- "gone_device_time",
- CTLFLAG_RW, &isp->isp_osinfo.gone_device_time, 0,
- "How long to wait for a device to reappear");
-}
-#endif
-
static void
isp_intr_enable(void *arg)
{
+ int chan;
ispsoftc_t *isp = arg;
ISP_LOCK(isp);
- if (isp->isp_role != ISP_ROLE_NONE) {
- ISP_ENABLE_INTS(isp);
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ if (IS_FC(isp)) {
+ if (FCPARAM(isp, chan)->role != ISP_ROLE_NONE) {
+ ISP_ENABLE_INTS(isp);
+ break;
+ }
+ } else {
+ if (SDPARAM(isp, chan)->role != ISP_ROLE_NONE) {
+ ISP_ENABLE_INTS(isp);
+ break;
+ }
+ }
}
ISP_UNLOCK(isp);
/* Release our hook so that the boot can continue. */
@@ -608,609 +687,770 @@ isp_intr_enable(void *arg)
}
/*
+ * Local Inlines
+ */
+
+static ISP_INLINE int isp_get_pcmd(ispsoftc_t *, union ccb *);
+static ISP_INLINE void isp_free_pcmd(ispsoftc_t *, union ccb *);
+
+static ISP_INLINE int
+isp_get_pcmd(ispsoftc_t *isp, union ccb *ccb)
+{
+ ISP_PCMD(ccb) = isp->isp_osinfo.pcmd_free;
+ if (ISP_PCMD(ccb) == NULL) {
+ return (-1);
+ }
+ isp->isp_osinfo.pcmd_free = ((struct isp_pcmd *)ISP_PCMD(ccb))->next;
+ return (0);
+}
+
+static ISP_INLINE void
+isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
+{
+ ((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free;
+ isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb);
+ ISP_PCMD(ccb) = NULL;
+}
+/*
* Put the target mode functions here, because some are inlines
*/
#ifdef ISP_TARGET_MODE
-
-static __inline int is_lun_enabled(ispsoftc_t *, int, lun_id_t);
-static __inline int are_any_luns_enabled(ispsoftc_t *, int);
-static __inline tstate_t *get_lun_statep(ispsoftc_t *, int, lun_id_t);
-static __inline void rls_lun_statep(ispsoftc_t *, tstate_t *);
-static __inline atio_private_data_t *isp_get_atpd(ispsoftc_t *, int);
-static cam_status
-create_lun_state(ispsoftc_t *, int, struct cam_path *, tstate_t **);
+static ISP_INLINE int is_lun_enabled(ispsoftc_t *, int, lun_id_t);
+static ISP_INLINE tstate_t *get_lun_statep(ispsoftc_t *, int, lun_id_t);
+static ISP_INLINE tstate_t *get_lun_statep_from_tag(ispsoftc_t *, int, uint32_t);
+static ISP_INLINE void rls_lun_statep(ispsoftc_t *, tstate_t *);
+static ISP_INLINE inot_private_data_t *get_ntp_from_tagdata(ispsoftc_t *, uint32_t, uint32_t, tstate_t **);
+static ISP_INLINE atio_private_data_t *isp_get_atpd(ispsoftc_t *, tstate_t *, uint32_t);
+static ISP_INLINE void isp_put_atpd(ispsoftc_t *, tstate_t *, atio_private_data_t *);
+static ISP_INLINE inot_private_data_t *isp_get_ntpd(ispsoftc_t *, tstate_t *);
+static ISP_INLINE inot_private_data_t *isp_find_ntpd(ispsoftc_t *, tstate_t *, uint32_t, uint32_t);
+static ISP_INLINE void isp_put_ntpd(ispsoftc_t *, tstate_t *, inot_private_data_t *);
+static cam_status create_lun_state(ispsoftc_t *, int, struct cam_path *, tstate_t **);
static void destroy_lun_state(ispsoftc_t *, tstate_t *);
-static int isp_en_lun(ispsoftc_t *, union ccb *);
+static void isp_enable_lun(ispsoftc_t *, union ccb *);
+static void isp_enable_deferred_luns(ispsoftc_t *, int);
+static cam_status isp_enable_deferred(ispsoftc_t *, int, lun_id_t);
+static void isp_disable_lun(ispsoftc_t *, union ccb *);
+static int isp_enable_target_mode(ispsoftc_t *, int);
static void isp_ledone(ispsoftc_t *, lun_entry_t *);
-static cam_status isp_abort_tgt_ccb(ispsoftc_t *, union ccb *);
static timeout_t isp_refire_putback_atio;
static void isp_complete_ctio(union ccb *);
static void isp_target_putback_atio(union ccb *);
static void isp_target_start_ctio(ispsoftc_t *, union ccb *);
-static int isp_handle_platform_atio(ispsoftc_t *, at_entry_t *);
-static int isp_handle_platform_atio2(ispsoftc_t *, at2_entry_t *);
-static int isp_handle_platform_ctio(ispsoftc_t *, void *);
-static int isp_handle_platform_notify_scsi(ispsoftc_t *, in_entry_t *);
-static int isp_handle_platform_notify_fc(ispsoftc_t *, in_fcentry_t *);
-
-static __inline int
+static void isp_handle_platform_atio(ispsoftc_t *, at_entry_t *);
+static void isp_handle_platform_atio2(ispsoftc_t *, at2_entry_t *);
+static void isp_handle_platform_atio7(ispsoftc_t *, at7_entry_t *);
+static void isp_handle_platform_ctio(ispsoftc_t *, void *);
+static void isp_handle_platform_notify_scsi(ispsoftc_t *, in_entry_t *);
+static void isp_handle_platform_notify_fc(ispsoftc_t *, in_fcentry_t *);
+static void isp_handle_platform_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *);
+static int isp_handle_platform_target_notify_ack(ispsoftc_t *, isp_notify_t *);
+static void isp_handle_platform_target_tmf(ispsoftc_t *, isp_notify_t *);
+static void isp_target_mark_aborted(ispsoftc_t *, union ccb *);
+static void isp_target_mark_aborted_early(ispsoftc_t *, tstate_t *, uint32_t);
+
+static ISP_INLINE int
is_lun_enabled(ispsoftc_t *isp, int bus, lun_id_t lun)
{
tstate_t *tptr;
- tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)];
- if (tptr == NULL) {
- return (0);
- }
- do {
- if (tptr->lun == (lun_id_t) lun && tptr->bus == bus) {
+ struct tslist *lhp;
+
+ ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(lun)], lhp);
+ SLIST_FOREACH(tptr, lhp, next) {
+ if (xpt_path_lun_id(tptr->owner) == lun) {
return (1);
}
- } while ((tptr = tptr->next) != NULL);
+ }
return (0);
}
-static __inline int
-are_any_luns_enabled(ispsoftc_t *isp, int port)
+static void
+dump_tstates(ispsoftc_t *isp, int bus)
{
- int lo, hi;
- if (IS_DUALBUS(isp)) {
- lo = (port * (LUN_HASH_SIZE >> 1));
- hi = lo + (LUN_HASH_SIZE >> 1);
- } else {
- lo = 0;
- hi = LUN_HASH_SIZE;
+ int i, j;
+ struct tslist *lhp;
+ tstate_t *tptr = NULL;
+
+ if (bus >= isp->isp_nchan) {
+ return;
}
- for (lo = 0; lo < hi; lo++) {
- if (isp->isp_osinfo.lun_hash[lo]) {
- return (1);
+ for (i = 0; i < LUN_HASH_SIZE; i++) {
+ ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
+ j = 0;
+ SLIST_FOREACH(tptr, lhp, next) {
+ xpt_print(tptr->owner, "[%d, %d] atio_cnt=%d inot_cnt=%d\n", i, j, tptr->atio_count, tptr->inot_count);
+ j++;
}
}
- return (0);
}
-static __inline tstate_t *
+static ISP_INLINE tstate_t *
get_lun_statep(ispsoftc_t *isp, int bus, lun_id_t lun)
{
tstate_t *tptr = NULL;
-
- if (lun == CAM_LUN_WILDCARD) {
- if (isp->isp_osinfo.tmflags[bus] & TM_WILDCARD_ENABLED) {
- tptr = &isp->isp_osinfo.tsdflt[bus];
- tptr->hold++;
- return (tptr);
- }
- return (NULL);
- } else {
- tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)];
- if (tptr == NULL) {
- return (NULL);
+ struct tslist *lhp;
+ int i;
+
+ if (bus < isp->isp_nchan) {
+ for (i = 0; i < LUN_HASH_SIZE; i++) {
+ ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
+ SLIST_FOREACH(tptr, lhp, next) {
+ if (xpt_path_lun_id(tptr->owner) == lun) {
+ tptr->hold++;
+ return (tptr);
+ }
+ }
}
}
+ return (NULL);
+}
- do {
- if (tptr->lun == lun && tptr->bus == bus) {
- tptr->hold++;
- return (tptr);
+static ISP_INLINE tstate_t *
+get_lun_statep_from_tag(ispsoftc_t *isp, int bus, uint32_t tagval)
+{
+ tstate_t *tptr = NULL;
+ atio_private_data_t *atp;
+ struct tslist *lhp;
+ int i;
+
+ if (bus < isp->isp_nchan && tagval != 0) {
+ for (i = 0; i < LUN_HASH_SIZE; i++) {
+ ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
+ SLIST_FOREACH(tptr, lhp, next) {
+ atp = isp_get_atpd(isp, tptr, tagval);
+ if (atp && atp->tag == tagval) {
+ tptr->hold++;
+ return (tptr);
+ }
+ }
}
- } while ((tptr = tptr->next) != NULL);
- return (tptr);
+ }
+ return (NULL);
}
-static __inline void
+static ISP_INLINE inot_private_data_t *
+get_ntp_from_tagdata(ispsoftc_t *isp, uint32_t tag_id, uint32_t seq_id, tstate_t **rslt)
+{
+ inot_private_data_t *ntp;
+ tstate_t *tptr;
+ struct tslist *lhp;
+ int bus, i;
+
+ for (bus = 0; bus < isp->isp_nchan; bus++) {
+ for (i = 0; i < LUN_HASH_SIZE; i++) {
+ ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
+ SLIST_FOREACH(tptr, lhp, next) {
+ ntp = isp_find_ntpd(isp, tptr, tag_id, seq_id);
+ if (ntp) {
+ *rslt = tptr;
+ tptr->hold++;
+ return (ntp);
+ }
+ }
+ }
+ }
+ return (NULL);
+}
+static ISP_INLINE void
rls_lun_statep(ispsoftc_t *isp, tstate_t *tptr)
{
- if (tptr->hold)
- tptr->hold--;
+ KASSERT((tptr->hold), ("tptr not held"));
+ tptr->hold--;
}
-static __inline atio_private_data_t *
-isp_get_atpd(ispsoftc_t *isp, int tag)
+static void
+isp_tmcmd_restart(ispsoftc_t *isp)
+{
+ inot_private_data_t *ntp;
+ tstate_t *tptr;
+ struct tslist *lhp;
+ int bus, i;
+
+ for (bus = 0; bus < isp->isp_nchan; bus++) {
+ for (i = 0; i < LUN_HASH_SIZE; i++) {
+ ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
+ SLIST_FOREACH(tptr, lhp, next) {
+ inot_private_data_t *restart_queue = tptr->restart_queue;
+ tptr->restart_queue = NULL;
+ while (restart_queue) {
+ ntp = restart_queue;
+ restart_queue = ntp->rd.nt.nt_hba;
+ if (IS_24XX(isp)) {
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at7_entry_t *)ntp->rd.data)->at_rxid);
+ isp_handle_platform_atio7(isp, (at7_entry_t *) ntp->rd.data);
+ } else {
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at2_entry_t *)ntp->rd.data)->at_rxid);
+ isp_handle_platform_atio2(isp, (at2_entry_t *) ntp->rd.data);
+ }
+ isp_put_ntpd(isp, tptr, ntp);
+ if (tptr->restart_queue && restart_queue != NULL) {
+ ntp = tptr->restart_queue;
+ tptr->restart_queue = restart_queue;
+ while (restart_queue->rd.nt.nt_hba) {
+ restart_queue = restart_queue->rd.nt.nt_hba;
+ }
+ restart_queue->rd.nt.nt_hba = ntp;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static ISP_INLINE atio_private_data_t *
+isp_get_atpd(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag)
{
atio_private_data_t *atp;
- for (atp = isp->isp_osinfo.atpdp;
- atp < &isp->isp_osinfo.atpdp[ATPDPSIZE]; atp++) {
- if (atp->tag == tag)
+
+ if (tag == 0) {
+ atp = tptr->atfree;
+ if (atp) {
+ tptr->atfree = atp->next;
+ }
+ return (atp);
+ }
+ for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) {
+ if (atp->tag == tag) {
return (atp);
+ }
}
return (NULL);
}
+static ISP_INLINE void
+isp_put_atpd(ispsoftc_t *isp, tstate_t *tptr, atio_private_data_t *atp)
+{
+ atp->tag = 0;
+ atp->dead = 0;
+ atp->next = tptr->atfree;
+ tptr->atfree = atp;
+}
+
+static void
+isp_dump_atpd(ispsoftc_t *isp, tstate_t *tptr)
+{
+ atio_private_data_t *atp;
+ const char *states[8] = { "Free", "ATIO", "CAM", "CTIO", "LAST_CTIO", "PDON", "?6", "7" };
+
+ for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) {
+ if (atp->tag == 0) {
+ continue;
+ }
+ xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u last_xfr %u lun %u nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n",
+ atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->last_xframt, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]);
+ }
+}
+
+
+static ISP_INLINE inot_private_data_t *
+isp_get_ntpd(ispsoftc_t *isp, tstate_t *tptr)
+{
+ inot_private_data_t *ntp;
+ ntp = tptr->ntfree;
+ if (ntp) {
+ tptr->ntfree = ntp->next;
+ }
+ return (ntp);
+}
+
+static ISP_INLINE inot_private_data_t *
+isp_find_ntpd(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag_id, uint32_t seq_id)
+{
+ inot_private_data_t *ntp;
+ for (ntp = tptr->ntpool; ntp < &tptr->ntpool[ATPDPSIZE]; ntp++) {
+ if (ntp->rd.tag_id == tag_id && ntp->rd.seq_id == seq_id) {
+ return (ntp);
+ }
+ }
+ return (NULL);
+}
+
+static ISP_INLINE void
+isp_put_ntpd(ispsoftc_t *isp, tstate_t *tptr, inot_private_data_t *ntp)
+{
+ ntp->rd.tag_id = ntp->rd.seq_id = 0;
+ ntp->next = tptr->ntfree;
+ tptr->ntfree = ntp;
+}
+
static cam_status
-create_lun_state(ispsoftc_t *isp, int bus,
- struct cam_path *path, tstate_t **rslt)
+create_lun_state(ispsoftc_t *isp, int bus, struct cam_path *path, tstate_t **rslt)
{
cam_status status;
lun_id_t lun;
- int hfx;
- tstate_t *tptr, *new;
+ struct tslist *lhp;
+ tstate_t *tptr;
+ int i;
lun = xpt_path_lun_id(path);
- if (lun >= ISP_MAX_LUNS(isp)) {
- return (CAM_LUN_INVALID);
+ if (lun != CAM_LUN_WILDCARD) {
+ if (lun >= ISP_MAX_LUNS(isp)) {
+ return (CAM_LUN_INVALID);
+ }
}
if (is_lun_enabled(isp, bus, lun)) {
return (CAM_LUN_ALRDY_ENA);
}
- new = (tstate_t *) malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT|M_ZERO);
- if (new == NULL) {
+ tptr = (tstate_t *) malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (tptr == NULL) {
return (CAM_RESRC_UNAVAIL);
}
-
- status = xpt_create_path(&new->owner, NULL, xpt_path_path_id(path),
- xpt_path_target_id(path), xpt_path_lun_id(path));
+ status = xpt_create_path(&tptr->owner, NULL, xpt_path_path_id(path), xpt_path_target_id(path), lun);
if (status != CAM_REQ_CMP) {
- free(new, M_DEVBUF);
+ free(tptr, M_DEVBUF);
return (status);
}
- new->bus = bus;
- new->lun = lun;
- SLIST_INIT(&new->atios);
- SLIST_INIT(&new->inots);
- new->hold = 1;
-
- hfx = LUN_HASH_FUNC(isp, new->bus, new->lun);
- tptr = isp->isp_osinfo.lun_hash[hfx];
- if (tptr == NULL) {
- isp->isp_osinfo.lun_hash[hfx] = new;
- } else {
- while (tptr->next)
- tptr = tptr->next;
- tptr->next = new;
+ SLIST_INIT(&tptr->atios);
+ SLIST_INIT(&tptr->inots);
+ for (i = 0; i < ATPDPSIZE-1; i++) {
+ tptr->atpool[i].next = &tptr->atpool[i+1];
+ tptr->ntpool[i].next = &tptr->ntpool[i+1];
}
- *rslt = new;
+ tptr->atfree = tptr->atpool;
+ tptr->ntfree = tptr->ntpool;
+ tptr->hold = 1;
+ ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(xpt_path_lun_id(tptr->owner))], lhp);
+ SLIST_INSERT_HEAD(lhp, tptr, next);
+ *rslt = tptr;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, path, "created tstate\n");
return (CAM_REQ_CMP);
}
-static __inline void
+static ISP_INLINE void
destroy_lun_state(ispsoftc_t *isp, tstate_t *tptr)
{
- int hfx;
- tstate_t *lw, *pw;
-
- if (tptr->hold) {
- return;
- }
- hfx = LUN_HASH_FUNC(isp, tptr->bus, tptr->lun);
- pw = isp->isp_osinfo.lun_hash[hfx];
- if (pw == NULL) {
- return;
- } else if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
- isp->isp_osinfo.lun_hash[hfx] = pw->next;
- } else {
- lw = pw;
- pw = lw->next;
- while (pw) {
- if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
- lw->next = pw->next;
- break;
- }
- lw = pw;
- pw = pw->next;
- }
- if (pw == NULL) {
- return;
- }
- }
+ struct tslist *lhp;
+ KASSERT((tptr->hold == 0), ("tptr still held"));
+ ISP_GET_PC_ADDR(isp, xpt_path_path_id(tptr->owner), lun_hash[LUN_HASH_FUNC(xpt_path_lun_id(tptr->owner))], lhp);
+ SLIST_REMOVE(lhp, tptr, tstate, next);
+ xpt_free_path(tptr->owner);
free(tptr, M_DEVBUF);
}
/*
- * Enable luns.
+ * Enable a lun.
*/
-static int
-isp_en_lun(ispsoftc_t *isp, union ccb *ccb)
+static void
+isp_enable_lun(ispsoftc_t *isp, union ccb *ccb)
{
- struct ccb_en_lun *cel = &ccb->cel;
tstate_t *tptr = NULL;
- uint32_t seq;
- int bus, cmd, av, wildcard, tm_on;
+ int bus, tm_enabled, target_role;
+ target_id_t target;
lun_id_t lun;
- target_id_t tgt;
+ /*
+ * We only support either a wildcard target/lun or a target ID of zero and a non-wildcard lun
+ */
bus = XS_CHANNEL(ccb);
- if (bus > 1) {
- xpt_print(ccb->ccb_h.path, "illegal bus %d\n", bus);
- ccb->ccb_h.status = CAM_PATH_INVALID;
- return (-1);
- }
- tgt = ccb->ccb_h.target_id;
+ target = ccb->ccb_h.target_id;
lun = ccb->ccb_h.target_lun;
+ if (target != CAM_TARGET_WILDCARD && target != 0) {
+ ccb->ccb_h.status = CAM_TID_INVALID;
+ xpt_done(ccb);
+ return;
+ }
+ if (target == CAM_TARGET_WILDCARD && lun != CAM_LUN_WILDCARD) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
+ xpt_done(ccb);
+ return;
+ }
+ if (target != CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
+ xpt_done(ccb);
+ return;
+ }
if (isp->isp_dblev & ISP_LOGTDEBUG0) {
- xpt_print(ccb->ccb_h.path, "%sabling lun 0x%x on channel %d\n",
- cel->enable? "en" : "dis", lun, bus);
+ xpt_print(ccb->ccb_h.path, "enabling lun 0x%x on channel %d\n", lun, bus);
}
- if ((lun != CAM_LUN_WILDCARD) &&
- (lun >= (lun_id_t) isp->isp_maxluns)) {
- ccb->ccb_h.status = CAM_LUN_INVALID;
- return (-1);
+ /*
+ * Wait until we're not busy with the lun enables subsystem
+ */
+ while (isp->isp_osinfo.tmbusy) {
+ isp->isp_osinfo.tmwanted = 1;
+ mtx_sleep(isp, &isp->isp_lock, PRIBIO, "want_isp_enable_lun", 0);
}
+ isp->isp_osinfo.tmbusy = 1;
- if (IS_SCSI(isp)) {
- sdparam *sdp = isp->isp_param;
- sdp += bus;
- if (tgt != CAM_TARGET_WILDCARD &&
- tgt != sdp->isp_initiator_id) {
- ccb->ccb_h.status = CAM_TID_INVALID;
- return (-1);
- }
- } else {
- /*
- * There's really no point in doing this yet w/o multi-tid
- * capability. Even then, it's problematic.
- */
-#if 0
- if (tgt != CAM_TARGET_WILDCARD &&
- tgt != FCPARAM(isp)->isp_iid) {
- ccb->ccb_h.status = CAM_TID_INVALID;
- return (-1);
- }
-#endif
- /*
- * This is as a good a place as any to check f/w capabilities.
- */
- if (FCPARAM(isp)->isp_tmode == 0) {
- xpt_print(ccb->ccb_h.path,
- "firmware does not support target mode\n");
+ /*
+ * This is as a good a place as any to check f/w capabilities.
+ */
+
+ if (IS_FC(isp)) {
+ if (ISP_CAP_TMODE(isp) == 0) {
+ xpt_print(ccb->ccb_h.path, "firmware does not support target mode\n");
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- return (-1);
+ goto done;
}
/*
- * XXX: We *could* handle non-SCCLUN f/w, but we'd have to
- * XXX: dork with our already fragile enable/disable code.
+ * We *could* handle non-SCCLUN f/w, but we'd have to
+ * dork with our already fragile enable/disable code.
*/
- if (FCPARAM(isp)->isp_sccfw == 0) {
- xpt_print(ccb->ccb_h.path,
- "firmware not SCCLUN capable\n");
+ if (ISP_CAP_SCCFW(isp) == 0) {
+ xpt_print(ccb->ccb_h.path, "firmware not SCCLUN capable\n");
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- return (-1);
+ goto done;
}
- }
- if (tgt == CAM_TARGET_WILDCARD) {
- if (lun == CAM_LUN_WILDCARD) {
- wildcard = 1;
- } else {
- ccb->ccb_h.status = CAM_LUN_INVALID;
- return (-1);
- }
+ target_role = (FCPARAM(isp, bus)->role & ISP_ROLE_TARGET) != 0;
+
} else {
- wildcard = 0;
+ target_role = (SDPARAM(isp, bus)->role & ISP_ROLE_TARGET) != 0;
}
- tm_on = (isp->isp_osinfo.tmflags[bus] & TM_TMODE_ENABLED) != 0;
-
/*
- * Next check to see whether this is a target/lun wildcard action.
- *
- * If so, we know that we can accept commands for luns that haven't
- * been enabled yet and send them upstream. Otherwise, we have to
- * handle them locally (if we see them at all).
+ * Create the state pointer.
+ * It should not already exist.
*/
-
- if (wildcard) {
- tptr = &isp->isp_osinfo.tsdflt[bus];
- if (cel->enable) {
- if (tm_on) {
- ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
- return (-1);
- }
- ccb->ccb_h.status =
- xpt_create_path(&tptr->owner, NULL,
- xpt_path_path_id(ccb->ccb_h.path),
- xpt_path_target_id(ccb->ccb_h.path),
- xpt_path_lun_id(ccb->ccb_h.path));
- if (ccb->ccb_h.status != CAM_REQ_CMP) {
- return (-1);
- }
- SLIST_INIT(&tptr->atios);
- SLIST_INIT(&tptr->inots);
- isp->isp_osinfo.tmflags[bus] |= TM_WILDCARD_ENABLED;
- } else {
- if (tm_on == 0) {
- ccb->ccb_h.status = CAM_REQ_CMP;
- return (-1);
- }
- if (tptr->hold) {
- ccb->ccb_h.status = CAM_SCSI_BUSY;
- return (-1);
- }
- xpt_free_path(tptr->owner);
- isp->isp_osinfo.tmflags[bus] &= ~TM_WILDCARD_ENABLED;
- }
+ tptr = get_lun_statep(isp, bus, lun);
+ if (tptr) {
+ ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
+ goto done;
+ }
+ ccb->ccb_h.status = create_lun_state(isp, bus, ccb->ccb_h.path, &tptr);
+ if (ccb->ccb_h.status != CAM_REQ_CMP) {
+ goto done;
}
/*
- * Now check to see whether this bus needs to be
- * enabled/disabled with respect to target mode.
+ * We have a tricky maneuver to perform here.
+ *
+ * If target mode isn't already enabled here,
+ * *and* our current role includes target mode,
+ * we enable target mode here.
+ *
*/
- av = bus << 31;
- if (cel->enable && tm_on == 0) {
- av |= ENABLE_TARGET_FLAG;
- av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
- if (av) {
- ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- if (wildcard) {
- isp->isp_osinfo.tmflags[bus] &=
- ~TM_WILDCARD_ENABLED;
- xpt_free_path(tptr->owner);
- }
- return (-1);
- }
- isp->isp_osinfo.tmflags[bus] |= TM_TMODE_ENABLED;
- xpt_print(ccb->ccb_h.path, "Target Mode Enabled\n");
- } else if (cel->enable == 0 && tm_on && wildcard) {
- if (are_any_luns_enabled(isp, bus)) {
- ccb->ccb_h.status = CAM_SCSI_BUSY;
- return (-1);
- }
- av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
- if (av) {
- ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- return (-1);
+ ISP_GET_PC(isp, bus, tm_enabled, tm_enabled);
+ if (tm_enabled == 0 && target_role != 0) {
+ if (isp_enable_target_mode(isp, bus)) {
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ destroy_lun_state(isp, tptr);
+ tptr = NULL;
+ goto done;
}
- isp->isp_osinfo.tmflags[bus] &= ~TM_TMODE_ENABLED;
- xpt_print(ccb->ccb_h.path, "Target Mode Disabled\n");
+ tm_enabled = 1;
}
- if (wildcard) {
+ /*
+ * Now check to see whether this bus is in target mode already.
+ *
+ * If not, a later role change into target mode will finish the job.
+ */
+ if (tm_enabled == 0) {
+ ISP_SET_PC(isp, bus, tm_enable_defer, 1);
ccb->ccb_h.status = CAM_REQ_CMP;
- return (-1);
+ xpt_print(ccb->ccb_h.path, "Target Mode Not Enabled Yet- Lun Enables Deferred\n");
+ goto done;
}
/*
- * Find an empty slot
+ * Enable the lun.
*/
- for (seq = 0; seq < NLEACT; seq++) {
- if (isp->isp_osinfo.leact[seq] == 0) {
- break;
- }
+ ccb->ccb_h.status = isp_enable_deferred(isp, bus, lun);
+
+done:
+ if (ccb->ccb_h.status != CAM_REQ_CMP && tptr) {
+ destroy_lun_state(isp, tptr);
+ tptr = NULL;
}
- if (seq >= NLEACT) {
- ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
- return (-1);
-
+ if (tptr) {
+ rls_lun_statep(isp, tptr);
}
- isp->isp_osinfo.leact[seq] = ccb;
-
- if (cel->enable) {
- ccb->ccb_h.status =
- create_lun_state(isp, bus, ccb->ccb_h.path, &tptr);
- if (ccb->ccb_h.status != CAM_REQ_CMP) {
- isp->isp_osinfo.leact[seq] = 0;
- return (-1);
- }
- } else {
- tptr = get_lun_statep(isp, bus, lun);
- if (tptr == NULL) {
- ccb->ccb_h.status = CAM_LUN_INVALID;
- return (-1);
- }
+ isp->isp_osinfo.tmbusy = 0;
+ if (isp->isp_osinfo.tmwanted) {
+ isp->isp_osinfo.tmwanted = 0;
+ wakeup(isp);
}
+ xpt_done(ccb);
+}
- if (cel->enable) {
- int c, n, ulun = lun;
+static void
+isp_enable_deferred_luns(ispsoftc_t *isp, int bus)
+{
+ /*
+ * XXX: not entirely implemented yet
+ */
+ (void) isp_enable_deferred(isp, bus, 0);
+}
- cmd = RQSTYPE_ENABLE_LUN;
- c = DFLT_CMND_CNT;
- n = DFLT_INOT_CNT;
- if (IS_FC(isp) && lun != 0) {
- cmd = RQSTYPE_MODIFY_LUN;
- n = 0;
- /*
- * For SCC firmware, we only deal with setting
- * (enabling or modifying) lun 0.
- */
- ulun = 0;
- }
- if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq+1) == 0) {
- rls_lun_statep(isp, tptr);
- ccb->ccb_h.status = CAM_REQ_INPROG;
- return (seq);
- }
+static uint32_t
+isp_enable_deferred(ispsoftc_t *isp, int bus, lun_id_t lun)
+{
+ cam_status status;
+
+ isp_prt(isp, ISP_LOGTINFO, "%s: bus %d lun %u", __func__, bus, lun);
+ if (IS_24XX(isp) || (IS_FC(isp) && ISP_FC_PC(isp, bus)->tm_luns_enabled)) {
+ status = CAM_REQ_CMP;
} else {
- int c, n, ulun = lun;
+ int cmd_cnt, not_cnt;
- cmd = -RQSTYPE_MODIFY_LUN;
- c = DFLT_CMND_CNT;
- n = DFLT_INOT_CNT;
- if (IS_FC(isp) && lun != 0) {
- n = 0;
- /*
- * For SCC firmware, we only deal with setting
- * (enabling or modifying) lun 0.
- */
- ulun = 0;
+ if (IS_23XX(isp)) {
+ cmd_cnt = DFLT_CMND_CNT;
+ not_cnt = DFLT_INOT_CNT;
+ } else {
+ cmd_cnt = 64;
+ not_cnt = 8;
}
- if (isp_lun_cmd(isp, cmd, bus, tgt, ulun, c, n, seq+1) == 0) {
- rls_lun_statep(isp, tptr);
- ccb->ccb_h.status = CAM_REQ_INPROG;
- return (seq);
+ status = CAM_REQ_INPROG;
+ isp->isp_osinfo.rptr = &status;
+ if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, lun, DFLT_CMND_CNT, DFLT_INOT_CNT)) {
+ status = CAM_RESRC_UNAVAIL;
+ } else {
+ mtx_sleep(&status, &isp->isp_lock, PRIBIO, "isp_enable_deferred", 0);
}
+ isp->isp_osinfo.rptr = NULL;
}
- rls_lun_statep(isp, tptr);
- xpt_print(ccb->ccb_h.path, "isp_lun_cmd failed\n");
- isp->isp_osinfo.leact[seq] = 0;
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- return (-1);
+
+ if (status == CAM_REQ_CMP) {
+ ISP_SET_PC(isp, bus, tm_luns_enabled, 1);
+ isp_prt(isp, ISP_LOGTINFO, "bus %d lun %u now enabled for target mode", bus, lun);
+ }
+ return (status);
}
static void
-isp_ledone(ispsoftc_t *isp, lun_entry_t *lep)
+isp_disable_lun(ispsoftc_t *isp, union ccb *ccb)
{
- const char lfmt[] = "now %sabled for target mode\n";
- union ccb *ccb;
- uint32_t seq;
- tstate_t *tptr;
- int av;
- struct ccb_en_lun *cel;
+ tstate_t *tptr = NULL;
+ int bus;
+ cam_status status;
+ target_id_t target;
+ lun_id_t lun;
- seq = lep->le_reserved - 1;
- if (seq >= NLEACT) {
- isp_prt(isp, ISP_LOGERR,
- "seq out of range (%u) in isp_ledone", seq);
- return;
- }
- ccb = isp->isp_osinfo.leact[seq];
- if (ccb == 0) {
- isp_prt(isp, ISP_LOGERR,
- "no ccb for seq %u in isp_ledone", seq);
+ bus = XS_CHANNEL(ccb);
+ target = ccb->ccb_h.target_id;
+ lun = ccb->ccb_h.target_lun;
+ if (target != CAM_TARGET_WILDCARD && target != 0) {
+ ccb->ccb_h.status = CAM_TID_INVALID;
+ xpt_done(ccb);
return;
}
- cel = &ccb->cel;
- tptr = get_lun_statep(isp, XS_CHANNEL(ccb), XS_LUN(ccb));
- if (tptr == NULL) {
- xpt_print(ccb->ccb_h.path, "null tptr in isp_ledone\n");
- isp->isp_osinfo.leact[seq] = 0;
+ if (target == CAM_TARGET_WILDCARD && lun != CAM_LUN_WILDCARD) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
+ xpt_done(ccb);
return;
}
- if (lep->le_status != LUN_OK) {
- xpt_print(ccb->ccb_h.path,
- "ENABLE/MODIFY LUN returned 0x%x\n", lep->le_status);
-err:
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- rls_lun_statep(isp, tptr);
- isp->isp_osinfo.leact[seq] = 0;
+ if (target != CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
xpt_done(ccb);
return;
- } else {
- isp_prt(isp, ISP_LOGTDEBUG0,
- "isp_ledone: ENABLE/MODIFY done okay");
}
+ if (isp->isp_dblev & ISP_LOGTDEBUG0) {
+ xpt_print(ccb->ccb_h.path, "enabling lun 0x%x on channel %d\n", lun, bus);
+ }
+
+ /*
+ * See if we're busy disabling a lun now.
+ */
+ while (isp->isp_osinfo.tmbusy) {
+ isp->isp_osinfo.tmwanted = 1;
+ mtx_sleep(isp, &isp->isp_lock, PRIBIO, "want_isp_disable_lun", 0);
+ }
+ isp->isp_osinfo.tmbusy = 1;
+ /*
+ * Find the state pointer.
+ */
+ if ((tptr = get_lun_statep(isp, bus, lun)) == NULL) {
+ ccb->ccb_h.status = CAM_PATH_INVALID;
+ goto done;
+ }
- if (cel->enable) {
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_print(ccb->ccb_h.path, lfmt, "en");
- rls_lun_statep(isp, tptr);
- isp->isp_osinfo.leact[seq] = 0;
- xpt_done(ccb);
- return;
+ /*
+ * If we're a 24XX card, we're done.
+ */
+ if (IS_24XX(isp)) {
+ status = CAM_REQ_CMP;
+ goto done;
}
- if (lep->le_header.rqs_entry_type == RQSTYPE_MODIFY_LUN) {
- if (isp_lun_cmd(isp, -RQSTYPE_ENABLE_LUN, XS_CHANNEL(ccb),
- XS_TGT(ccb), XS_LUN(ccb), 0, 0, seq+1)) {
- xpt_print(ccb->ccb_h.path,
- "isp_ledone: isp_lun_cmd failed\n");
- goto err;
- }
- rls_lun_statep(isp, tptr);
- return;
+ /*
+ * For SCC FW, we only deal with lun zero.
+ */
+ if (IS_FC(isp)) {
+ lun = 0;
}
- xpt_print(ccb->ccb_h.path, lfmt, "dis");
- rls_lun_statep(isp, tptr);
- destroy_lun_state(isp, tptr);
- ccb->ccb_h.status = CAM_REQ_CMP;
- isp->isp_osinfo.leact[seq] = 0;
+ isp->isp_osinfo.rptr = &status;
+ status = CAM_REQ_INPROG;
+ if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, lun, 0, 0)) {
+ status = CAM_RESRC_UNAVAIL;
+ } else {
+ mtx_sleep(ccb, &isp->isp_lock, PRIBIO, "isp_disable_lun", 0);
+ }
+done:
+ if (status == CAM_REQ_CMP) {
+ xpt_print(ccb->ccb_h.path, "now disabled for target mode\n");
+ }
+ if (tptr) {
+ rls_lun_statep(isp, tptr);
+ }
+ isp->isp_osinfo.rptr = NULL;
+ isp->isp_osinfo.tmbusy = 0;
+ if (isp->isp_osinfo.tmwanted) {
+ isp->isp_osinfo.tmwanted = 0;
+ wakeup(isp);
+ }
xpt_done(ccb);
- if (are_any_luns_enabled(isp, XS_CHANNEL(ccb)) == 0) {
- int bus = XS_CHANNEL(ccb);
- av = bus << 31;
- av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
- if (av) {
- isp_prt(isp, ISP_LOGWARN,
- "disable target mode on channel %d failed", bus);
+}
+
+static int
+isp_enable_target_mode(ispsoftc_t *isp, int bus)
+{
+ int ct;
+
+ ISP_GET_PC(isp, bus, tm_enabled, ct);
+ if (ct != 0) {
+ return (0);
+ }
+
+ if (IS_SCSI(isp)) {
+ mbreg_t mbs;
+
+ MBSINIT(&mbs, MBOX_ENABLE_TARGET_MODE, MBLOGALL, 0);
+ mbs.param[0] = MBOX_ENABLE_TARGET_MODE;
+ mbs.param[1] = ENABLE_TARGET_FLAG|ENABLE_TQING_FLAG;
+ mbs.param[2] = bus << 7;
+ if (isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs) < 0 || mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGERR, "Unable to add Target Role to Bus %d", bus);
+ return (EIO);
}
- isp->isp_osinfo.tmflags[bus] &= ~TM_TMODE_ENABLED;
+ SDPARAM(isp, bus)->role |= ISP_ROLE_TARGET;
}
+ ISP_SET_PC(isp, bus, tm_enabled, 1);
+ isp_prt(isp, ISP_LOGINFO, "Target Role added to Bus %d", bus);
+ return (0);
}
-
-static cam_status
-isp_abort_tgt_ccb(ispsoftc_t *isp, union ccb *ccb)
+#ifdef NEEDED
+static int
+isp_disable_target_mode(ispsoftc_t *isp, int bus)
{
- tstate_t *tptr;
- struct ccb_hdr_slist *lp;
- struct ccb_hdr *curelm;
- int found, *ctr;
- union ccb *accb = ccb->cab.abort_ccb;
-
- xpt_print(ccb->ccb_h.path, "aborting ccb %p\n", accb);
- if (accb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
- int badpath = 0;
- if (IS_FC(isp) && (accb->ccb_h.target_id !=
- ((fcparam *) isp->isp_param)->isp_loopid)) {
- badpath = 1;
- } else if (IS_SCSI(isp) && (accb->ccb_h.target_id !=
- ((sdparam *) isp->isp_param)->isp_initiator_id)) {
- badpath = 1;
- }
- if (badpath) {
- /*
- * Being restrictive about target ids is really about
- * making sure we're aborting for the right multi-tid
- * path. This doesn't really make much sense at present.
- */
-#if 0
- return (CAM_PATH_INVALID);
-#endif
+ int ct;
+
+ ISP_GET_PC(isp, bus, tm_enabled, ct);
+ if (ct == 0) {
+ return (0);
+ }
+
+ if (IS_SCSI(isp)) {
+ mbreg_t mbs;
+
+ MBSINIT(&mbs, MBOX_ENABLE_TARGET_MODE, MBLOGALL, 0);
+ mbs.param[2] = bus << 7;
+ if (isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs) < 0 || mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGERR, "Unable to subtract Target Role to Bus %d", bus);
+ return (EIO);
}
+ SDPARAM(isp, bus)->role &= ~ISP_ROLE_TARGET;
}
- tptr = get_lun_statep(isp, XS_CHANNEL(ccb), accb->ccb_h.target_lun);
- if (tptr == NULL) {
- xpt_print(ccb->ccb_h.path, "can't get statep\n");
- return (CAM_PATH_INVALID);
- }
- if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
- lp = &tptr->atios;
- ctr = &tptr->atio_count;
- } else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
- lp = &tptr->inots;
- ctr = &tptr->inot_count;
- } else {
- rls_lun_statep(isp, tptr);
- xpt_print(ccb->ccb_h.path, "bad function code %d\n",
- accb->ccb_h.func_code);
- return (CAM_UA_ABORT);
- }
- curelm = SLIST_FIRST(lp);
- found = 0;
- if (curelm == &accb->ccb_h) {
- found = 1;
- SLIST_REMOVE_HEAD(lp, sim_links.sle);
+ ISP_SET_PC(isp, bus, tm_enabled, 0);
+ isp_prt(isp, ISP_LOGINFO, "Target Role subtracted from Bus %d", bus);
+ return (0);
+}
+#endif
+
+static void
+isp_ledone(ispsoftc_t *isp, lun_entry_t *lep)
+{
+ uint32_t *rptr;
+
+ rptr = isp->isp_osinfo.rptr;
+ if (lep->le_status != LUN_OK) {
+ isp_prt(isp, ISP_LOGERR, "ENABLE/MODIFY LUN returned 0x%x", lep->le_status);
+ if (rptr) {
+ *rptr = CAM_REQ_CMP_ERR;
+ wakeup_one(rptr);
+ }
} else {
- while(curelm != NULL) {
- struct ccb_hdr *nextelm;
-
- nextelm = SLIST_NEXT(curelm, sim_links.sle);
- if (nextelm == &accb->ccb_h) {
- found = 1;
- SLIST_NEXT(curelm, sim_links.sle) =
- SLIST_NEXT(nextelm, sim_links.sle);
- break;
- }
- curelm = nextelm;
+ if (rptr) {
+ *rptr = CAM_REQ_CMP;
+ wakeup_one(rptr);
}
}
- rls_lun_statep(isp, tptr);
- if (found) {
- (*ctr)--;
- accb->ccb_h.status = CAM_REQ_ABORTED;
- xpt_done(accb);
- return (CAM_REQ_CMP);
- }
- xpt_print(ccb->ccb_h.path, "ccb %p not found\n", accb);
- return (CAM_PATH_INVALID);
}
static void
isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
{
void *qe;
+ tstate_t *tptr;
+ atio_private_data_t *atp;
struct ccb_scsiio *cso = &ccb->csio;
- uint32_t nxti, optr, handle;
+ uint32_t dmaresult, handle;
uint8_t local[QENTRY_LEN];
+ /*
+ * Do some sanity checks.
+ */
+ if (cso->dxfer_len == 0) {
+ if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
+ xpt_print(ccb->ccb_h.path, "a data transfer length of zero but no status to send is wrong\n");
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ return;
+ }
+ }
+
+ tptr = get_lun_statep(isp, XS_CHANNEL(ccb), XS_LUN(ccb));
+ if (tptr == NULL) {
+ tptr = get_lun_statep(isp, XS_CHANNEL(ccb), CAM_LUN_WILDCARD);
+ if (tptr == NULL) {
+ xpt_print(ccb->ccb_h.path, "%s: [0x%x] cannot find tstate pointer in %s\n", __func__, cso->tag_id);
+ dump_tstates(isp, XS_CHANNEL(ccb));
+ ccb->ccb_h.status = CAM_DEV_NOT_THERE;
+ xpt_done(ccb);
+ return;
+ }
+ }
+
+ atp = isp_get_atpd(isp, tptr, cso->tag_id);
+ if (atp == NULL) {
+ xpt_print(ccb->ccb_h.path, "%s: [0x%x] cannot find private data adjunct\n", __func__, cso->tag_id);
+ isp_dump_atpd(isp, tptr);
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ xpt_done(ccb);
+ return;
+ }
+ if (atp->dead) {
+ xpt_print(ccb->ccb_h.path, "%s: [0x%x] stopping sending a CTIO for a dead command\n", __func__, cso->tag_id);
+ ccb->ccb_h.status = CAM_REQ_ABORTED;
+ xpt_done(ccb);
+ return;
+ }
- if (isp_getrqentry(isp, &nxti, &optr, &qe)) {
- xpt_print(ccb->ccb_h.path,
- "Request Queue Overflow in isp_target_start_ctio\n");
- XS_SETERR(ccb, CAM_REQUEUE_REQ);
+ /*
+ * Check to make sure we're still in target mode.
+ */
+ if ((FCPARAM(isp, XS_CHANNEL(ccb))->role & ISP_ROLE_TARGET) == 0) {
+ xpt_print(ccb->ccb_h.path, "%s: [0x%x] stopping sending a CTIO because we're no longer in target mode\n", __func__, cso->tag_id);
+ ccb->ccb_h.status = CAM_PROVIDE_FAIL;
+ xpt_done(ccb);
+ return;
+ }
+
+ /*
+ * Get some resources
+ */
+ if (isp_get_pcmd(isp, ccb)) {
+ rls_lun_statep(isp, tptr);
+ xpt_print(ccb->ccb_h.path, "out of PCMDs\n");
+ cam_freeze_devq(ccb->ccb_h.path);
+ cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
+ ccb->ccb_h.status = CAM_REQUEUE_REQ;
+ xpt_done(ccb);
+ return;
+ }
+ qe = isp_getrqentry(isp);
+ if (qe == NULL) {
+ xpt_print(ccb->ccb_h.path, rqo, __func__);
+ cam_freeze_devq(ccb->ccb_h.path);
+ cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
+ ccb->ccb_h.status = CAM_REQUEUE_REQ;
goto out;
}
memset(local, 0, QENTRY_LEN);
@@ -1218,53 +1458,102 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
/*
* We're either moving data or completing a command here.
*/
+ if (IS_24XX(isp)) {
+ ct7_entry_t *cto = (ct7_entry_t *) local;
- if (IS_FC(isp)) {
- atio_private_data_t *atp;
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_header.rqs_seqno = 1;
+ cto->ct_nphdl = atp->nphdl;
+ cto->ct_rxid = atp->tag;
+ cto->ct_iid_lo = atp->portid;
+ cto->ct_iid_hi = atp->portid >> 16;
+ cto->ct_oxid = atp->oxid;
+ cto->ct_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(ccb));
+ cto->ct_scsi_status = cso->scsi_status;
+ cto->ct_timeout = 120;
+ cto->ct_flags = atp->tattr << CT7_TASK_ATTR_SHIFT;
+ if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
+ cto->ct_flags |= CT7_SENDSTATUS;
+ }
+ if (cso->dxfer_len == 0) {
+ cto->ct_flags |= CT7_FLAG_MODE1 | CT7_NO_DATA;
+ if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
+ int m = min(cso->sense_len, sizeof (struct scsi_sense_data));
+ cto->rsp.m1.ct_resplen = cto->ct_senselen = min(m, MAXRESPLEN_24XX);
+ memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, cto->ct_senselen);
+ cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
+ }
+ } else {
+ cto->ct_flags |= CT7_FLAG_MODE0;
+ if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ cto->ct_flags |= CT7_DATA_IN;
+ } else {
+ cto->ct_flags |= CT7_DATA_OUT;
+ }
+ cto->rsp.m0.reloff = atp->bytes_xfered;
+ /*
+ * Don't overrun the limits placed on us
+ */
+ if (atp->bytes_xfered + cso->dxfer_len > atp->orig_datalen) {
+ cso->dxfer_len = atp->orig_datalen - atp->bytes_xfered;
+ }
+ atp->last_xframt = cso->dxfer_len;
+ cto->rsp.m0.ct_xfrlen = cso->dxfer_len;
+ }
+ if (cto->ct_flags & CT7_SENDSTATUS) {
+ int lvl = (cso->scsi_status)? ISP_LOGTINFO : ISP_LOGTDEBUG0;
+ cto->ct_resid = atp->orig_datalen - (atp->bytes_xfered + cso->dxfer_len);
+ if (cto->ct_resid < 0) {
+ cto->ct_scsi_status |= (FCP_RESID_OVERFLOW << 8);
+ } else if (cto->ct_resid > 0) {
+ cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8);
+ }
+ atp->state = ATPD_STATE_LAST_CTIO;
+ ISP_PATH_PRT(isp, lvl, cso->ccb_h.path, "%s: CTIO7[%x] CDB0=%x scsi status %x flags %x resid %d xfrlen %u offset %u\n", __func__, cto->ct_rxid,
+ atp->cdb0, cto->ct_scsi_status, cto->ct_flags, cto->ct_resid, cso->dxfer_len, atp->bytes_xfered);
+ } else {
+ cto->ct_resid = 0;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, cso->ccb_h.path, "%s: CTIO7[%x] flags %x xfrlen %u offset %u\n", __func__, cto->ct_rxid, cto->ct_flags,
+ cso->dxfer_len, atp->bytes_xfered);
+ atp->state = ATPD_STATE_CTIO;
+ }
+ } else if (IS_FC(isp)) {
ct2_entry_t *cto = (ct2_entry_t *) local;
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
cto->ct_header.rqs_entry_count = 1;
- if (FCPARAM(isp)->isp_2klogin) {
+ cto->ct_header.rqs_seqno = 1;
+ if (ISP_CAP_2KLOGIN(isp) == 0) {
((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
} else {
cto->ct_iid = cso->init_id;
- if (FCPARAM(isp)->isp_sccfw == 0) {
+ if (ISP_CAP_SCCFW(isp) == 0) {
cto->ct_lun = ccb->ccb_h.target_lun;
}
}
- atp = isp_get_atpd(isp, cso->tag_id);
- if (atp == NULL) {
- xpt_print(ccb->ccb_h.path,
- "cannot find private data adjunct for tag %x\n",
- cso->tag_id);
- XS_SETERR(ccb, CAM_REQ_CMP_ERR);
- goto out;
- }
cto->ct_rxid = cso->tag_id;
if (cso->dxfer_len == 0) {
- cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA;
- if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
- cto->ct_flags |= CT2_SENDSTATUS;
- cto->rsp.m1.ct_scsi_status = cso->scsi_status;
- cto->ct_resid =
- atp->orig_datalen - atp->bytes_xfered;
- if (cto->ct_resid < 0) {
- cto->rsp.m1.ct_scsi_status |=
- CT2_DATA_OVER;
- } else if (cto->ct_resid > 0) {
- cto->rsp.m1.ct_scsi_status |=
- CT2_DATA_UNDER;
- }
+ cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA | CT2_SENDSTATUS;
+ cto->rsp.m1.ct_scsi_status = cso->scsi_status;
+ cto->ct_resid = atp->orig_datalen - atp->bytes_xfered;
+ if (cto->ct_resid < 0) {
+ cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER;
+ } else if (cto->ct_resid > 0) {
+ cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
}
if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
int m = min(cso->sense_len, MAXRESPLEN);
- memcpy(cto->rsp.m1.ct_resp,
- &cso->sense_data, m);
+ memcpy(cto->rsp.m1.ct_resp, &cso->sense_data, m);
cto->rsp.m1.ct_senselen = m;
cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
+ } else if (cso->scsi_status == SCSI_STATUS_CHECK_COND) {
+ /*
+ * XXX: DEBUG
+ */
+ xpt_print(ccb->ccb_h.path, "CHECK CONDITION being sent without associated SENSE DATA for CDB=0x%x\n", atp->cdb0);
}
} else {
cto->ct_flags |= CT2_FLAG_MODE0;
@@ -1274,18 +1563,21 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
cto->ct_flags |= CT2_DATA_OUT;
}
cto->ct_reloff = atp->bytes_xfered;
+ cto->rsp.m0.ct_xfrlen = cso->dxfer_len;
+ /*
+ * Don't overrun the limits placed on us
+ */
+ if (atp->bytes_xfered + cso->dxfer_len > atp->orig_datalen) {
+ cso->dxfer_len = atp->orig_datalen - atp->bytes_xfered;
+ }
if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
cto->ct_flags |= CT2_SENDSTATUS;
cto->rsp.m0.ct_scsi_status = cso->scsi_status;
- cto->ct_resid =
- atp->orig_datalen -
- (atp->bytes_xfered + cso->dxfer_len);
+ cto->ct_resid = atp->orig_datalen - (atp->bytes_xfered + cso->dxfer_len);
if (cto->ct_resid < 0) {
- cto->rsp.m0.ct_scsi_status |=
- CT2_DATA_OVER;
+ cto->rsp.m0.ct_scsi_status |= CT2_DATA_OVER;
} else if (cto->ct_resid > 0) {
- cto->rsp.m0.ct_scsi_status |=
- CT2_DATA_UNDER;
+ cto->rsp.m0.ct_scsi_status |= CT2_DATA_UNDER;
}
} else {
atp->last_xframt = cso->dxfer_len;
@@ -1298,14 +1590,16 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
}
if (cto->ct_flags & CT2_SENDSTATUS) {
- isp_prt(isp, ISP_LOGTDEBUG0,
- "CTIO2[%x] STATUS %x origd %u curd %u resid %u",
- cto->ct_rxid, cso->scsi_status, atp->orig_datalen,
- cso->dxfer_len, cto->ct_resid);
+ int lvl = (cso->scsi_status)? ISP_LOGTINFO : ISP_LOGTDEBUG0;
cto->ct_flags |= CT2_CCINCR;
atp->state = ATPD_STATE_LAST_CTIO;
+ ISP_PATH_PRT(isp, lvl, cso->ccb_h.path, "%s: CTIO2[%x] CDB0=%x scsi status %x flags %x resid %d xfrlen %u offset %u\n", __func__, cto->ct_rxid,
+ atp->cdb0, cto->rsp.m0.ct_scsi_status, cto->ct_flags, cto->ct_resid, cso->dxfer_len, atp->bytes_xfered);
} else {
+ cto->ct_resid = 0;
atp->state = ATPD_STATE_CTIO;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "%s: CTIO2[%x] flags %x xfrlen %u offset %u\n", __func__, cto->ct_rxid, cto->ct_flags,
+ cso->dxfer_len, atp->bytes_xfered);
}
cto->ct_timeout = 10;
} else {
@@ -1313,13 +1607,14 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
cto->ct_header.rqs_entry_count = 1;
+ cto->ct_header.rqs_seqno = 1;
cto->ct_iid = cso->init_id;
cto->ct_iid |= XS_CHANNEL(ccb) << 7;
cto->ct_tgt = ccb->ccb_h.target_id;
cto->ct_lun = ccb->ccb_h.target_lun;
- cto->ct_fwhandle = AT_GET_HANDLE(cso->tag_id);
+ cto->ct_fwhandle = cso->tag_id >> 16;
if (AT_HAS_TAG(cso->tag_id)) {
- cto->ct_tag_val = (uint8_t) AT_GET_TAG(cso->tag_id);
+ cto->ct_tag_val = cso->tag_id;
cto->ct_flags |= CT_TQAE;
}
if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
@@ -1336,19 +1631,16 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR;
cto->ct_scsi_status = cso->scsi_status;
cto->ct_resid = cso->resid;
- isp_prt(isp, ISP_LOGTDEBUG0,
- "CTIO[%x] SCSI STATUS 0x%x resid %d tag_id %x",
- cto->ct_fwhandle, cso->scsi_status, cso->resid,
- cso->tag_id);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "%s: CTIO[%x] scsi status %x resid %d tag_id %x\n", __func__,
+ cto->ct_fwhandle, cso->scsi_status, cso->resid, cso->tag_id);
}
ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
cto->ct_timeout = 10;
}
if (isp_save_xs_tgt(isp, ccb, &handle)) {
- xpt_print(ccb->ccb_h.path,
- "No XFLIST pointers for isp_target_start_ctio\n");
- XS_SETERR(ccb, CAM_REQUEUE_REQ);
+ xpt_print(ccb->ccb_h.path, "No XFLIST pointers for %s\n", __func__);
+ ccb->ccb_h.status = CAM_REQUEUE_REQ;
goto out;
}
@@ -1362,7 +1654,10 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
* format.
*/
- if (IS_FC(isp)) {
+ if (IS_24XX(isp)) {
+ ct7_entry_t *cto = (ct7_entry_t *) local;
+ cto->ct_syshandle = handle;
+ } else if (IS_FC(isp)) {
ct2_entry_t *cto = (ct2_entry_t *) local;
cto->ct_syshandle = handle;
} else {
@@ -1370,31 +1665,33 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
cto->ct_syshandle = handle;
}
- switch (ISP_DMASETUP(isp, cso, (ispreq_t *) local, &nxti, optr)) {
- case CMD_QUEUED:
- ISP_ADD_REQUEST(isp, nxti);
+ dmaresult = ISP_DMASETUP(isp, cso, (ispreq_t *) local);
+ if (dmaresult == CMD_QUEUED) {
+ isp->isp_nactive++;
ccb->ccb_h.status |= CAM_SIM_QUEUED;
+ rls_lun_statep(isp, tptr);
return;
-
- case CMD_EAGAIN:
- XS_SETERR(ccb, CAM_REQUEUE_REQ);
- break;
-
- default:
- break;
+ }
+ if (dmaresult == CMD_EAGAIN) {
+ ccb->ccb_h.status = CAM_REQUEUE_REQ;
+ } else {
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
}
isp_destroy_tgt_handle(isp, handle);
-
out:
+ rls_lun_statep(isp, tptr);
+ isp_free_pcmd(isp, ccb);
xpt_done(ccb);
}
static void
isp_refire_putback_atio(void *arg)
{
- int s = splcam();
- isp_target_putback_atio(arg);
- splx(s);
+ union ccb *ccb = arg;
+ ispsoftc_t *isp = XS_ISP(ccb);
+ ISP_LOCK(isp);
+ isp_target_putback_atio(ccb);
+ ISP_UNLOCK(isp);
}
static void
@@ -1402,14 +1699,13 @@ isp_target_putback_atio(union ccb *ccb)
{
ispsoftc_t *isp;
struct ccb_scsiio *cso;
- uint32_t nxti, optr;
void *qe;
isp = XS_ISP(ccb);
- if (isp_getrqentry(isp, &nxti, &optr, &qe)) {
- xpt_print(ccb->ccb_h.path,
- "isp_target_putback_atio: Request Queue Overflow\n");
+ qe = isp_getrqentry(isp);
+ if (qe == NULL) {
+ xpt_print(ccb->ccb_h.path, rqo, __func__);
(void) timeout(isp_refire_putback_atio, ccb, 10);
return;
}
@@ -1417,10 +1713,10 @@ isp_target_putback_atio(union ccb *ccb)
cso = &ccb->csio;
if (IS_FC(isp)) {
at2_entry_t local, *at = &local;
- MEMZERO(at, sizeof (at2_entry_t));
+ ISP_MEMZERO(at, sizeof (at2_entry_t));
at->at_header.rqs_entry_type = RQSTYPE_ATIO2;
at->at_header.rqs_entry_count = 1;
- if (FCPARAM(isp)->isp_sccfw) {
+ if (ISP_CAP_SCCFW(isp)) {
at->at_scclun = (uint16_t) ccb->ccb_h.target_lun;
} else {
at->at_lun = (uint8_t) ccb->ccb_h.target_lun;
@@ -1431,7 +1727,7 @@ isp_target_putback_atio(union ccb *ccb)
isp_put_atio2(isp, at, qe);
} else {
at_entry_t local, *at = &local;
- MEMZERO(at, sizeof (at_entry_t));
+ ISP_MEMZERO(at, sizeof (at_entry_t));
at->at_header.rqs_entry_type = RQSTYPE_ATIO;
at->at_header.rqs_entry_count = 1;
at->at_iid = cso->init_id;
@@ -1443,8 +1739,8 @@ isp_target_putback_atio(union ccb *ccb)
at->at_handle = AT_GET_HANDLE(cso->tag_id);
isp_put_atio(isp, at, qe);
}
- ISP_TDQE(isp, "isp_target_putback_atio", (int) optr, qe);
- ISP_ADD_REQUEST(isp, nxti);
+ ISP_TDQE(isp, "isp_target_putback_atio", isp->isp_reqidx, qe);
+ ISP_SYNC_REQUEST(isp);
isp_complete_ctio(ccb);
}
@@ -1455,6 +1751,7 @@ isp_complete_ctio(union ccb *ccb)
ccb->ccb_h.status |= CAM_REQ_CMP;
}
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+ isp_free_pcmd(XS_ISP(ccb), ccb);
xpt_done(ccb);
}
@@ -1463,12 +1760,13 @@ isp_complete_ctio(union ccb *ccb)
* This means handling CDBs.
*/
-static int
+static void
isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
{
tstate_t *tptr;
- int status, bus, iswildcard;
+ int status, bus;
struct ccb_accept_tio *atiop;
+ atio_private_data_t *atp;
/*
* The firmware status (except for the QLTM_SVALID bit)
@@ -1488,13 +1786,12 @@ isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
*/
isp_prt(isp, ISP_LOGWARN, "PHASE ERROR");
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
- return (0);
+ return;
}
if ((status & ~QLTM_SVALID) != AT_CDB) {
- isp_prt(isp, ISP_LOGWARN, "bad atio (0x%x) leaked to platform",
- status);
+ isp_prt(isp, ISP_LOGWARN, "bad atio (0x%x) leaked to platform", status);
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
- return (0);
+ return;
}
bus = GET_BUS_VAL(aep->at_iid);
@@ -1512,15 +1809,13 @@ isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
* blackhole driver, so they get what they deserve.
*/
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
- return (0);
+ return;
}
- iswildcard = 1;
- } else {
- iswildcard = 0;
}
+ atp = isp_get_atpd(isp, tptr, 0);
atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
- if (atiop == NULL) {
+ if (atiop == NULL || atp == NULL) {
/*
* Because we can't autofeed sense data back with
* a command for parallel SCSI, we can't give back
@@ -1529,24 +1824,25 @@ isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
* should, in fact, get this, is in the case that we've
* run out of ATIOS.
*/
- xpt_print(tptr->owner,
- "no ATIOS for lun %d from initiator %d on channel %d\n",
- aep->at_lun, GET_IID_VAL(aep->at_iid), bus);
- if (aep->at_flags & AT_TQAE)
- isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
- else
- isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
+ xpt_print(tptr->owner, "no %s for lun %d from initiator %d\n", (atp == NULL && atiop == NULL)? "ATIOs *or* ATPS" :
+ ((atp == NULL)? "ATPs" : "ATIOs"), aep->at_lun, aep->at_iid);
+ isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
+ if (atp) {
+ isp_put_atpd(isp, tptr, atp);
+ }
rls_lun_statep(isp, tptr);
- return (0);
+ return;
+ }
+ atp->tag = aep->at_tag_val;
+ if (atp->tag == 0) {
+ atp->tag = ~0;
}
+ atp->state = ATPD_STATE_ATIO;
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
tptr->atio_count--;
- isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO lun %d, count now %d",
- aep->at_lun, tptr->atio_count);
- if (iswildcard) {
- atiop->ccb_h.target_id = aep->at_tgt;
- atiop->ccb_h.target_lun = aep->at_lun;
- }
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, atiop->ccb_h.path, "Take FREE ATIO count now %d\n", tptr->atio_count);
+ atiop->ccb_h.target_id = aep->at_tgt;
+ atiop->ccb_h.target_lun = aep->at_lun;
if (aep->at_flags & AT_NODISC) {
atiop->ccb_h.flags = CAM_DIS_DISCONNECT;
} else {
@@ -1556,42 +1852,48 @@ isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
if (status & QLTM_SVALID) {
size_t amt = imin(QLTM_SENSELEN, sizeof (atiop->sense_data));
atiop->sense_len = amt;
- MEMCPY(&atiop->sense_data, aep->at_sense, amt);
+ ISP_MEMCPY(&atiop->sense_data, aep->at_sense, amt);
} else {
atiop->sense_len = 0;
}
atiop->init_id = GET_IID_VAL(aep->at_iid);
atiop->cdb_len = aep->at_cdblen;
- MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen);
+ ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen);
atiop->ccb_h.status = CAM_CDB_RECVD;
/*
* Construct a tag 'id' based upon tag value (which may be 0..255)
* and the handle (which we have to preserve).
*/
- AT_MAKE_TAGID(atiop->tag_id, bus, device_get_unit(isp->isp_dev), aep);
+ atiop->tag_id = atp->tag;
if (aep->at_flags & AT_TQAE) {
atiop->tag_action = aep->at_tag_type;
atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
}
- xpt_done((union ccb*)atiop);
- isp_prt(isp, ISP_LOGTDEBUG0,
- "ATIO[%x] CDB=0x%x bus %d iid%d->lun%d tag 0x%x ttype 0x%x %s",
- aep->at_handle, aep->at_cdb[0] & 0xff, GET_BUS_VAL(aep->at_iid),
- GET_IID_VAL(aep->at_iid), aep->at_lun, aep->at_tag_val & 0xff,
- aep->at_tag_type, (aep->at_flags & AT_NODISC)?
- "nondisc" : "disconnecting");
+ atp->orig_datalen = 0;
+ atp->bytes_xfered = 0;
+ atp->last_xframt = 0;
+ atp->lun = aep->at_lun;
+ atp->nphdl = aep->at_iid;
+ atp->portid = PORT_NONE;
+ atp->oxid = 0;
+ atp->cdb0 = atiop->cdb_io.cdb_bytes[0];
+ atp->tattr = aep->at_tag_type;
+ atp->state = ATPD_STATE_CAM;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "ATIO[%x] CDB=0x%x lun %d\n", aep->at_tag_val, atp->cdb0, atp->lun);
rls_lun_statep(isp, tptr);
- return (0);
}
-static int
+static void
isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
{
lun_id_t lun;
+ fcportdb_t *lp;
tstate_t *tptr;
struct ccb_accept_tio *atiop;
- atio_private_data_t *atp;
+ uint16_t nphdl;
+ atio_private_data_t *atp = NULL;
+ inot_private_data_t *ntp;
/*
* The firmware status (except for the QLTM_SVALID bit)
@@ -1600,127 +1902,457 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
* If QLTM_SVALID is set, the firware has recommended Sense Data.
*/
if ((aep->at_status & ~QLTM_SVALID) != AT_CDB) {
- isp_prt(isp, ISP_LOGWARN,
- "bogus atio (0x%x) leaked to platform", aep->at_status);
+ isp_prt(isp, ISP_LOGWARN, "bogus atio (0x%x) leaked to platform", aep->at_status);
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
- return (0);
+ return;
}
- if (FCPARAM(isp)->isp_sccfw) {
+ if (ISP_CAP_SCCFW(isp)) {
lun = aep->at_scclun;
} else {
lun = aep->at_lun;
}
+ if (ISP_CAP_2KLOGIN(isp)) {
+ nphdl = ((at2e_entry_t *)aep)->at_iid;
+ } else {
+ nphdl = aep->at_iid;
+ }
tptr = get_lun_statep(isp, 0, lun);
if (tptr == NULL) {
- isp_prt(isp, ISP_LOGTDEBUG0,
- "[0x%x] no state pointer for lun %d", aep->at_rxid, lun);
tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
if (tptr == NULL) {
- isp_endcmd(isp, aep,
- SCSI_STATUS_CHECK_COND | ECMD_SVALID |
- (0x5 << 12) | (0x25 << 16), 0);
- return (0);
+ isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] no state pointer for lun %d", aep->at_rxid, lun);
+ isp_endcmd(isp, aep, SCSI_STATUS_CHECK_COND | ECMD_SVALID | (0x5 << 12) | (0x25 << 16), 0);
+ return;
+ }
+ }
+
+ /*
+ * Start any commands pending resources first.
+ */
+ if (tptr->restart_queue) {
+ inot_private_data_t *restart_queue = tptr->restart_queue;
+ tptr->restart_queue = NULL;
+ while (restart_queue) {
+ ntp = restart_queue;
+ restart_queue = ntp->rd.nt.nt_hba;
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at2_entry_t *)ntp->rd.data)->at_rxid);
+ isp_handle_platform_atio2(isp, (at2_entry_t *) ntp->rd.data);
+ isp_put_ntpd(isp, tptr, ntp);
+ /*
+ * If a recursion caused the restart queue to start to fill again,
+ * stop and splice the new list on top of the old list and restore
+ * it and go to noresrc.
+ */
+ if (tptr->restart_queue) {
+ ntp = tptr->restart_queue;
+ tptr->restart_queue = restart_queue;
+ while (restart_queue->rd.nt.nt_hba) {
+ restart_queue = restart_queue->rd.nt.nt_hba;
+ }
+ restart_queue->rd.nt.nt_hba = ntp;
+ goto noresrc;
+ }
}
}
- atp = isp_get_atpd(isp, 0);
atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
- if (atiop == NULL || atp == NULL) {
+ if (atiop == NULL) {
+ goto noresrc;
+ }
- /*
- * Because we can't autofeed sense data back with
- * a command for parallel SCSI, we can't give back
- * a CHECK CONDITION. We'll give back a QUEUE FULL status
- * instead. This works out okay because the only time we
- * should, in fact, get this, is in the case that we've
- * run out of ATIOS.
- */
- xpt_print(tptr->owner,
- "no %s for lun %d from initiator %d\n",
- (atp == NULL && atiop == NULL)? "ATIO2s *or* ATPS" :
- ((atp == NULL)? "ATPs" : "ATIO2s"), lun, aep->at_iid);
- rls_lun_statep(isp, tptr);
- isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
- return (0);
+ atp = isp_get_atpd(isp, tptr, 0);
+ if (atp == NULL) {
+ goto noresrc;
}
+
+ atp->tag = aep->at_rxid;
atp->state = ATPD_STATE_ATIO;
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
tptr->atio_count--;
- isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO lun %d, count now %d",
- lun, tptr->atio_count);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, atiop->ccb_h.path, "Take FREE ATIO count now %d\n", tptr->atio_count);
+ atiop->ccb_h.target_id = FCPARAM(isp, 0)->isp_loopid;
+ atiop->ccb_h.target_lun = lun;
- if (tptr == &isp->isp_osinfo.tsdflt[0]) {
- atiop->ccb_h.target_id = FCPARAM(isp)->isp_loopid;
- atiop->ccb_h.target_lun = lun;
- }
/*
* We don't get 'suggested' sense data as we do with SCSI cards.
*/
atiop->sense_len = 0;
+ if (ISP_CAP_2KLOGIN(isp)) {
+ /*
+ * NB: We could not possibly have 2K logins if we
+ * NB: also did not have SCC FW.
+ */
+ atiop->init_id = ((at2e_entry_t *)aep)->at_iid;
+ } else {
+ atiop->init_id = aep->at_iid;
+ }
- atiop->init_id = aep->at_iid;
+ /*
+ * If we're not in the port database, add ourselves.
+ */
+ if (!IS_2100(isp) && isp_find_pdb_by_loopid(isp, 0, atiop->init_id, &lp) == 0) {
+ uint64_t iid =
+ (((uint64_t) aep->at_wwpn[0]) << 48) |
+ (((uint64_t) aep->at_wwpn[1]) << 32) |
+ (((uint64_t) aep->at_wwpn[2]) << 16) |
+ (((uint64_t) aep->at_wwpn[3]) << 0);
+ /*
+ * However, make sure we delete ourselves if otherwise
+ * we were there but at a different loop id.
+ */
+ if (isp_find_pdb_by_wwn(isp, 0, iid, &lp)) {
+ isp_del_wwn_entry(isp, 0, iid, lp->handle, lp->portid);
+ }
+ isp_add_wwn_entry(isp, 0, iid, atiop->init_id, PORT_ANY);
+ }
atiop->cdb_len = ATIO2_CDBLEN;
- MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, ATIO2_CDBLEN);
+ ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, ATIO2_CDBLEN);
atiop->ccb_h.status = CAM_CDB_RECVD;
- atiop->tag_id = aep->at_rxid;
+ atiop->tag_id = atp->tag;
switch (aep->at_taskflags & ATIO2_TC_ATTR_MASK) {
case ATIO2_TC_ATTR_SIMPLEQ:
+ atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
atiop->tag_action = MSG_SIMPLE_Q_TAG;
break;
- case ATIO2_TC_ATTR_HEADOFQ:
+ case ATIO2_TC_ATTR_HEADOFQ:
+ atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
atiop->tag_action = MSG_HEAD_OF_Q_TAG;
break;
- case ATIO2_TC_ATTR_ORDERED:
+ case ATIO2_TC_ATTR_ORDERED:
+ atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
atiop->tag_action = MSG_ORDERED_Q_TAG;
break;
- case ATIO2_TC_ATTR_ACAQ: /* ?? */
+ case ATIO2_TC_ATTR_ACAQ: /* ?? */
case ATIO2_TC_ATTR_UNTAGGED:
default:
atiop->tag_action = 0;
break;
}
- atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
- atp->tag = atiop->tag_id;
- atp->lun = lun;
atp->orig_datalen = aep->at_datalen;
- atp->last_xframt = 0;
atp->bytes_xfered = 0;
+ atp->last_xframt = 0;
+ atp->lun = lun;
+ atp->nphdl = atiop->init_id;
+ atp->sid = PORT_ANY;
+ atp->oxid = aep->at_oxid;
+ atp->cdb0 = aep->at_cdb[0];
+ atp->tattr = aep->at_taskflags & ATIO2_TC_ATTR_MASK;
atp->state = ATPD_STATE_CAM;
- xpt_done((union ccb*)atiop);
+ xpt_done((union ccb *)atiop);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "ATIO2[%x] CDB=0x%x lun %d datalen %u\n", aep->at_rxid, atp->cdb0, lun, atp->orig_datalen);
+ rls_lun_statep(isp, tptr);
+ return;
+noresrc:
+ if (atp) {
+ isp_put_atpd(isp, tptr, atp);
+ }
+ ntp = isp_get_ntpd(isp, tptr);
+ if (ntp == NULL) {
+ rls_lun_statep(isp, tptr);
+ isp_endcmd(isp, aep, nphdl, 0, SCSI_STATUS_BUSY, 0);
+ return;
+ }
+ memcpy(ntp->rd.data, aep, QENTRY_LEN);
+ ntp->rd.nt.nt_hba = tptr->restart_queue;
+ tptr->restart_queue = ntp;
+ rls_lun_statep(isp, tptr);
+}
+
+static void
+isp_handle_platform_atio7(ispsoftc_t *isp, at7_entry_t *aep)
+{
+ int cdbxlen;
+ uint16_t lun, chan, nphdl = NIL_HANDLE;
+ uint32_t did, sid;
+ uint64_t wwn = INI_NONE;
+ fcportdb_t *lp;
+ tstate_t *tptr;
+ struct ccb_accept_tio *atiop;
+ atio_private_data_t *atp = NULL;
+ inot_private_data_t *ntp;
+
+ did = (aep->at_hdr.d_id[0] << 16) | (aep->at_hdr.d_id[1] << 8) | aep->at_hdr.d_id[2];
+ sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2];
+ lun = (aep->at_cmnd.fcp_cmnd_lun[0] << 8) | aep->at_cmnd.fcp_cmnd_lun[1];
- isp_prt(isp, ISP_LOGTDEBUG0,
- "ATIO2[%x] CDB=0x%x iid%d->lun%d tattr 0x%x datalen %u",
- aep->at_rxid, aep->at_cdb[0] & 0xff, aep->at_iid,
- lun, aep->at_taskflags, aep->at_datalen);
+ /*
+ * Find the N-port handle, and Virtual Port Index for this command.
+ *
+ * If we can't, we're somewhat in trouble because we can't actually respond w/o that information.
+ * We also, as a matter of course, need to know the WWN of the initiator too.
+ */
+ if (ISP_CAP_MULTI_ID(isp)) {
+ /*
+ * Find the right channel based upon D_ID
+ */
+ isp_find_chan_by_did(isp, did, &chan);
+
+ if (chan == ISP_NOCHAN) {
+ NANOTIME_T now;
+
+ /*
+ * If we don't recognizer our own D_DID, terminate the exchange, unless we're within 2 seconds of startup
+ * It's a bit tricky here as we need to stash this command *somewhere*.
+ */
+ GET_NANOTIME(&now);
+ if (NANOTIME_SUB(&isp->isp_init_time, &now) > 2000000000ULL) {
+ isp_prt(isp, ISP_LOGWARN, "%s: [RX_ID 0x%x] D_ID %x not found on any channel- dropping", __func__, aep->at_rxid, did);
+ isp_endcmd(isp, aep, NIL_HANDLE, ISP_NOCHAN, ECMD_TERMINATE, 0);
+ return;
+ }
+ tptr = get_lun_statep(isp, 0, 0);
+ if (tptr == NULL) {
+ tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
+ if (tptr == NULL) {
+ isp_prt(isp, ISP_LOGWARN, "%s: [RX_ID 0x%x] D_ID %x not found on any channel and no tptr- dropping", __func__, aep->at_rxid, did);
+ isp_endcmd(isp, aep, NIL_HANDLE, ISP_NOCHAN, ECMD_TERMINATE, 0);
+ return;
+ }
+ }
+ isp_prt(isp, ISP_LOGWARN, "%s: [RX_ID 0x%x] D_ID %x not found on any channel- deferring", __func__, aep->at_rxid, did);
+ goto noresrc;
+ }
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] D_ID 0x%06x found on Chan %d for S_ID 0x%06x", __func__, aep->at_rxid, did, chan, sid);
+ } else {
+ chan = 0;
+ }
+
+ /*
+ * Find the PDB entry for this initiator
+ */
+ if (isp_find_pdb_by_sid(isp, chan, sid, &lp) == 0) {
+ /*
+ * If we're not in the port database terminate the exchange.
+ */
+ isp_prt(isp, ISP_LOGTINFO, "%s: [RX_ID 0x%x] D_ID 0x%06x found on Chan %d for S_ID 0x%06x wasn't in PDB already",
+ __func__, aep->at_rxid, did, chan, sid);
+ isp_endcmd(isp, aep, NIL_HANDLE, chan, ECMD_TERMINATE, 0);
+ return;
+ }
+ nphdl = lp->handle;
+ wwn = lp->port_wwn;
+
+ /*
+ * Get the tstate pointer
+ */
+ tptr = get_lun_statep(isp, chan, lun);
+ if (tptr == NULL) {
+ tptr = get_lun_statep(isp, chan, CAM_LUN_WILDCARD);
+ if (tptr == NULL) {
+ isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] no state pointer for lun %d or wildcard", aep->at_rxid, lun);
+ isp_endcmd(isp, aep, nphdl, chan, SCSI_STATUS_CHECK_COND | ECMD_SVALID | (0x5 << 12) | (0x25 << 16), 0);
+ return;
+ }
+ }
+
+ /*
+ * Start any commands pending resources first.
+ */
+ if (tptr->restart_queue) {
+ inot_private_data_t *restart_queue = tptr->restart_queue;
+ tptr->restart_queue = NULL;
+ while (restart_queue) {
+ ntp = restart_queue;
+ restart_queue = ntp->rd.nt.nt_hba;
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: restarting resrc deprived %x", __func__, ((at7_entry_t *)ntp->rd.data)->at_rxid);
+ isp_handle_platform_atio7(isp, (at7_entry_t *) ntp->rd.data);
+ isp_put_ntpd(isp, tptr, ntp);
+ /*
+ * If a recursion caused the restart queue to start to fill again,
+ * stop and splice the new list on top of the old list and restore
+ * it and go to noresrc.
+ */
+ if (tptr->restart_queue) {
+ if (restart_queue) {
+ ntp = tptr->restart_queue;
+ tptr->restart_queue = restart_queue;
+ while (restart_queue->rd.nt.nt_hba) {
+ restart_queue = restart_queue->rd.nt.nt_hba;
+ }
+ restart_queue->rd.nt.nt_hba = ntp;
+ }
+ goto noresrc;
+ }
+ }
+ }
+
+ /*
+ * If the f/w is out of resources, just send a BUSY status back.
+ */
+ if (aep->at_rxid == AT7_NORESRC_RXID) {
+ rls_lun_statep(isp, tptr);
+ isp_endcmd(isp, aep, nphdl, chan, SCSI_BUSY, 0);
+ return;
+ }
+
+ /*
+ * If we're out of resources, just send a BUSY status back.
+ */
+ atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
+ if (atiop == NULL) {
+ isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] out of atios", aep->at_rxid);
+ goto noresrc;
+ }
+
+ atp = isp_get_atpd(isp, tptr, 0);
+ if (atp == NULL) {
+ isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] out of atps", aep->at_rxid);
+ goto noresrc;
+ }
+ if (isp_get_atpd(isp, tptr, aep->at_rxid)) {
+ isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] tag wraparound in isp_handle_platforms_atio7 (N-Port Handle 0x%04x S_ID 0x%04x OX_ID 0x%04x)\n",
+ aep->at_rxid, nphdl, sid, aep->at_hdr.ox_id);
+ /*
+ * It's not a "no resource" condition- but we can treat it like one
+ */
+ goto noresrc;
+ }
+
+ atp->tag = aep->at_rxid;
+ atp->state = ATPD_STATE_ATIO;
+ SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
+ tptr->atio_count--;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, atiop->ccb_h.path, "Take FREE ATIO count now %d\n", tptr->atio_count);
+ atiop->init_id = nphdl;
+ atiop->ccb_h.target_id = FCPARAM(isp, chan)->isp_loopid;
+ atiop->ccb_h.target_lun = lun;
+ atiop->sense_len = 0;
+ cdbxlen = aep->at_cmnd.fcp_cmnd_alen_datadir >> FCP_CMND_ADDTL_CDBLEN_SHIFT;
+ if (cdbxlen) {
+ isp_prt(isp, ISP_LOGWARN, "additional CDBLEN ignored");
+ }
+ cdbxlen = sizeof (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_cdb);
+ ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cmnd.cdb_dl.sf.fcp_cmnd_cdb, cdbxlen);
+ atiop->cdb_len = cdbxlen;
+ atiop->ccb_h.status = CAM_CDB_RECVD;
+ atiop->tag_id = atp->tag;
+ switch (aep->at_cmnd.fcp_cmnd_task_attribute & FCP_CMND_TASK_ATTR_MASK) {
+ case FCP_CMND_TASK_ATTR_SIMPLE:
+ atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
+ atiop->tag_action = MSG_SIMPLE_Q_TAG;
+ break;
+ case FCP_CMND_TASK_ATTR_HEAD:
+ atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
+ atiop->tag_action = MSG_HEAD_OF_Q_TAG;
+ break;
+ case FCP_CMND_TASK_ATTR_ORDERED:
+ atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
+ atiop->tag_action = MSG_ORDERED_Q_TAG;
+ break;
+ default:
+ /* FALLTHROUGH */
+ case FCP_CMND_TASK_ATTR_ACA:
+ case FCP_CMND_TASK_ATTR_UNTAGGED:
+ atiop->tag_action = 0;
+ break;
+ }
+ atp->orig_datalen = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl;
+ atp->bytes_xfered = 0;
+ atp->last_xframt = 0;
+ atp->lun = lun;
+ atp->nphdl = nphdl;
+ atp->portid = sid;
+ atp->oxid = aep->at_hdr.ox_id;
+ atp->cdb0 = atiop->cdb_io.cdb_bytes[0];
+ atp->tattr = aep->at_cmnd.fcp_cmnd_task_attribute & FCP_CMND_TASK_ATTR_MASK;
+ atp->state = ATPD_STATE_CAM;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "ATIO7[%x] CDB=0x%x lun %d datalen %u\n", aep->at_rxid, atp->cdb0, lun, atp->orig_datalen);
+ xpt_done((union ccb *)atiop);
+ rls_lun_statep(isp, tptr);
+ return;
+noresrc:
+ if (atp) {
+ isp_put_atpd(isp, tptr, atp);
+ }
+ ntp = isp_get_ntpd(isp, tptr);
+ if (ntp == NULL) {
+ rls_lun_statep(isp, tptr);
+ isp_endcmd(isp, aep, nphdl, chan, SCSI_STATUS_BUSY, 0);
+ return;
+ }
+ memcpy(ntp->rd.data, aep, QENTRY_LEN);
+ ntp->rd.nt.nt_hba = tptr->restart_queue;
+ tptr->restart_queue = ntp;
rls_lun_statep(isp, tptr);
- return (0);
}
-static int
+static void
isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
{
union ccb *ccb;
int sentstatus, ok, notify_cam, resid = 0;
- uint16_t tval;
+ tstate_t *tptr = NULL;
+ atio_private_data_t *atp = NULL;
+ int bus;
+ uint32_t tval, handle;
/*
- * CTIO and CTIO2 are close enough....
+ * CTIO, CTIO2 and CTIO7 are close enough....
*/
- ccb = isp_find_xs_tgt(isp, ((ct_entry_t *)arg)->ct_syshandle);
- KASSERT((ccb != NULL), ("null ccb in isp_handle_platform_ctio"));
- isp_destroy_tgt_handle(isp, ((ct_entry_t *)arg)->ct_syshandle);
+ if (IS_SCSI(isp)) {
+ handle = ((ct_entry_t *)arg)->ct_syshandle;
+ } else {
+ handle = ((ct2_entry_t *)arg)->ct_syshandle;
+ }
+ ccb = isp_find_xs_tgt(isp, handle);
+ if (ccb == NULL) {
+ isp_print_bytes(isp, "null ccb in isp_handle_platform_ctio", QENTRY_LEN, arg);
+ return;
+ }
+ isp_destroy_tgt_handle(isp, handle);
+ bus = XS_CHANNEL(ccb);
+ tptr = get_lun_statep(isp, bus, XS_LUN(ccb));
+ if (tptr == NULL) {
+ tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD);
+ }
+ KASSERT((tptr != NULL), ("cannot get state pointer"));
+ if (isp->isp_nactive) {
+ isp->isp_nactive++;
+ }
+ if (IS_24XX(isp)) {
+ ct7_entry_t *ct = arg;
- if (IS_FC(isp)) {
+ atp = isp_get_atpd(isp, tptr, ct->ct_rxid);
+ if (atp == NULL) {
+ rls_lun_statep(isp, tptr);
+ isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x after I/O", __func__, ct->ct_rxid);
+ return;
+ }
+
+ sentstatus = ct->ct_flags & CT7_SENDSTATUS;
+ ok = (ct->ct_nphdl == CT7_OK);
+ if (ok && sentstatus && (ccb->ccb_h.flags & CAM_SEND_SENSE)) {
+ ccb->ccb_h.status |= CAM_SENT_SENSE;
+ }
+ notify_cam = ct->ct_header.rqs_seqno & 0x1;
+ if ((ct->ct_flags & CT7_DATAMASK) != CT7_NO_DATA) {
+ resid = ct->ct_resid;
+ atp->bytes_xfered += (atp->last_xframt - resid);
+ atp->last_xframt = 0;
+ }
+ if (ct->ct_nphdl == CT_HBA_RESET) {
+ ok = 0;
+ notify_cam = 1;
+ sentstatus = 1;
+ ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR;
+ } else if (!ok) {
+ ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
+ }
+ tval = atp->tag;
+ isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO7[%x] sts 0x%x flg 0x%x sns %d resid %d %s", __func__,
+ ct->ct_rxid, ct->ct_nphdl, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID");
+ atp->state = ATPD_STATE_PDON; /* XXX: should really come after isp_complete_ctio */
+ } else if (IS_FC(isp)) {
ct2_entry_t *ct = arg;
- atio_private_data_t *atp = isp_get_atpd(isp, ct->ct_rxid);
+
+ atp = isp_get_atpd(isp, tptr, ct->ct_rxid);
if (atp == NULL) {
- isp_prt(isp, ISP_LOGERR,
- "cannot find adjunct for %x after I/O",
- ct->ct_rxid);
- return (0);
+ rls_lun_statep(isp, tptr);
+ isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x after I/O", __func__, ct->ct_rxid);
+ return;
}
sentstatus = ct->ct_flags & CT2_SENDSTATUS;
ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
@@ -1733,18 +2365,18 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
atp->bytes_xfered += (atp->last_xframt - resid);
atp->last_xframt = 0;
}
- if (sentstatus || !ok) {
- atp->tag = 0;
- }
- isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN,
- "CTIO2[%x] sts 0x%x flg 0x%x sns %d resid %d %s",
- ct->ct_rxid, ct->ct_status, ct->ct_flags,
- (ccb->ccb_h.status & CAM_SENT_SENSE) != 0,
- resid, sentstatus? "FIN" : "MID");
- tval = ct->ct_rxid;
-
- /* XXX: should really come after isp_complete_ctio */
- atp->state = ATPD_STATE_PDON;
+ if (ct->ct_status == CT_HBA_RESET) {
+ ok = 0;
+ notify_cam = 1;
+ sentstatus = 1;
+ ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR;
+ } else if (!ok) {
+ ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
+ }
+ isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO2[%x] sts 0x%x flg 0x%x sns %d resid %d %s", __func__,
+ ct->ct_rxid, ct->ct_status, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID");
+ tval = atp->tag;
+ atp->state = ATPD_STATE_PDON; /* XXX: should really come after isp_complete_ctio */
} else {
ct_entry_t *ct = arg;
sentstatus = ct->ct_flags & CT_SENDSTATUS;
@@ -1759,22 +2391,25 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
* the auto-replenish feature for CTIOs.
*/
notify_cam = ct->ct_header.rqs_seqno & 0x1;
- if (ct->ct_status & QLTM_SVALID) {
+ if (ct->ct_status == (CT_HBA_RESET & 0xff)) {
+ ok = 0;
+ notify_cam = 1;
+ sentstatus = 1;
+ ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR;
+ } else if (!ok) {
+ ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
+ } else if (ct->ct_status & QLTM_SVALID) {
char *sp = (char *)ct;
sp += CTIO_SENSE_OFFSET;
- ccb->csio.sense_len =
- min(sizeof (ccb->csio.sense_data), QLTM_SENSELEN);
- MEMCPY(&ccb->csio.sense_data, sp, ccb->csio.sense_len);
+ ccb->csio.sense_len = min(sizeof (ccb->csio.sense_data), QLTM_SENSELEN);
+ ISP_MEMCPY(&ccb->csio.sense_data, sp, ccb->csio.sense_len);
ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
}
if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
resid = ct->ct_resid;
}
- isp_prt(isp, ISP_LOGTDEBUG0,
- "CTIO[%x] tag %x iid %d lun %d sts %x flg %x resid %d %s",
- ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_lun,
- ct->ct_status, ct->ct_flags, resid,
- sentstatus? "FIN" : "MID");
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] tag %x S_ID 0x%x lun %d sts %x flg %x resid %d %s", __func__,
+ ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_lun, ct->ct_status, ct->ct_flags, resid, sentstatus? "FIN" : "MID");
tval = ct->ct_fwhandle;
}
ccb->csio.resid += resid;
@@ -1791,86 +2426,1332 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
*/
if (notify_cam == 0) {
isp_prt(isp, ISP_LOGTDEBUG0, " INTER CTIO[0x%x] done", tval);
- return (0);
+ return;
}
+ if (tptr) {
+ rls_lun_statep(isp, tptr);
+ }
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done", (sentstatus)? " FINAL " : "MIDTERM ", tval);
- isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO[0x%x] done",
- (sentstatus)? " FINAL " : "MIDTERM ", tval);
-
- if (!ok) {
+ if (!ok && !IS_24XX(isp)) {
isp_target_putback_atio(ccb);
} else {
isp_complete_ctio(ccb);
-
}
- return (0);
}
-static int
-isp_handle_platform_notify_scsi(ispsoftc_t *isp, in_entry_t *inp)
+static void
+isp_handle_platform_notify_scsi(ispsoftc_t *isp, in_entry_t *inot)
{
- return (0); /* XXXX */
+ (void) isp_notify_ack(isp, inot);
}
-static int
+static void
isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp)
{
-
+ int needack = 1;
switch (inp->in_status) {
case IN_PORT_LOGOUT:
- isp_prt(isp, ISP_LOGWARN, "port logout of iid %d",
- inp->in_iid);
+ /*
+ * XXX: Need to delete this initiator's WWN from the database
+ * XXX: Need to send this LOGOUT upstream
+ */
+ isp_prt(isp, ISP_LOGWARN, "port logout of S_ID 0x%x", inp->in_iid);
break;
case IN_PORT_CHANGED:
- isp_prt(isp, ISP_LOGWARN, "port changed for iid %d",
- inp->in_iid);
+ isp_prt(isp, ISP_LOGWARN, "port changed for S_ID 0x%x", inp->in_iid);
break;
case IN_GLOBAL_LOGO:
+ isp_del_all_wwn_entries(isp, 0);
isp_prt(isp, ISP_LOGINFO, "all ports logged out");
break;
case IN_ABORT_TASK:
{
- atio_private_data_t *atp = isp_get_atpd(isp, inp->in_seqid);
- struct ccb_immed_notify *inot = NULL;
+ tstate_t *tptr;
+ uint16_t lun;
+ uint32_t loopid;
+ uint64_t wwn;
+ atio_private_data_t *atp;
+ fcportdb_t *lp;
+ struct ccb_immediate_notify *inot = NULL;
+
+ if (ISP_CAP_SCCFW(isp)) {
+ lun = inp->in_scclun;
+ } else {
+ lun = inp->in_lun;
+ }
+ if (ISP_CAP_2KLOGIN(isp)) {
+ loopid = ((in_fcentry_e_t *)inot)->in_iid;
+ } else {
+ loopid = inp->in_iid;
+ }
+ if (isp_find_pdb_by_loopid(isp, 0, loopid, &lp)) {
+ wwn = lp->port_wwn;
+ } else {
+ wwn = INI_ANY;
+ }
+ tptr = get_lun_statep(isp, 0, lun);
+ if (tptr == NULL) {
+ tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
+ if (tptr == NULL) {
+ isp_prt(isp, ISP_LOGWARN, "ABORT TASK for lun %u- but no tstate", lun);
+ return;
+ }
+ }
+ atp = isp_get_atpd(isp, tptr, inp->in_seqid);
if (atp) {
- tstate_t *tptr = get_lun_statep(isp, 0, atp->lun);
- if (tptr) {
- inot = (struct ccb_immed_notify *)
- SLIST_FIRST(&tptr->inots);
- if (inot) {
- tptr->inot_count--;
- SLIST_REMOVE_HEAD(&tptr->inots,
- sim_links.sle);
- isp_prt(isp, ISP_LOGTDEBUG0,
- "Take FREE INOT count now %d",
- tptr->inot_count);
- }
+ inot = (struct ccb_immediate_notify *) SLIST_FIRST(&tptr->inots);
+ isp_prt(isp, ISP_LOGTDEBUG0, "ABORT TASK RX_ID %x WWN 0x%016llx state %d", inp->in_seqid, (unsigned long long) wwn, atp->state);
+ if (inot) {
+ tptr->inot_count--;
+ SLIST_REMOVE_HEAD(&tptr->inots, sim_links.sle);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, inot->ccb_h.path, "%s: Take FREE INOT count now %d\n", __func__, tptr->inot_count);
+ } else {
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, tptr->owner, "out of INOT structures\n");
}
- isp_prt(isp, ISP_LOGWARN,
- "abort task RX_ID %x IID %d state %d",
- inp->in_seqid, inp->in_iid, atp->state);
} else {
- isp_prt(isp, ISP_LOGWARN,
- "abort task RX_ID %x from iid %d, state unknown",
- inp->in_seqid, inp->in_iid);
+ ISP_PATH_PRT(isp, ISP_LOGWARN, tptr->owner, "abort task RX_ID %x from wwn 0x%016llx, state unknown\n", inp->in_seqid, wwn);
}
if (inot) {
- inot->initiator_id = inp->in_iid;
- inot->sense_len = 0;
- inot->message_args[0] = MSG_ABORT_TAG;
- inot->message_args[1] = inp->in_seqid & 0xff;
- inot->message_args[2] = (inp->in_seqid >> 8) & 0xff;
- inot->ccb_h.status = CAM_MESSAGE_RECV;
- xpt_done((union ccb *)inot);
+ isp_notify_t tmp, *nt = &tmp;
+ ISP_MEMZERO(nt, sizeof (isp_notify_t));
+ nt->nt_hba = isp;
+ nt->nt_tgt = FCPARAM(isp, 0)->isp_wwpn;
+ nt->nt_wwn = wwn;
+ nt->nt_nphdl = loopid;
+ nt->nt_sid = PORT_ANY;
+ nt->nt_did = PORT_ANY;
+ nt->nt_lun = lun;
+ nt->nt_need_ack = 1;
+ nt->nt_channel = 0;
+ nt->nt_ncode = NT_ABORT_TASK;
+ nt->nt_lreserved = inot;
+ isp_handle_platform_target_tmf(isp, nt);
+ needack = 0;
+ }
+ rls_lun_statep(isp, tptr);
+ break;
+ }
+ default:
+ break;
+ }
+ if (needack) {
+ (void) isp_notify_ack(isp, inp);
+ }
+}
+
+static void
+isp_handle_platform_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *inot)
+{
+ uint16_t nphdl;
+ uint32_t portid;
+ fcportdb_t *lp;
+ uint8_t *ptr = NULL;
+ uint64_t wwn;
+
+ nphdl = inot->in_nphdl;
+ if (nphdl != NIL_HANDLE) {
+ portid = inot->in_portid_hi << 16 | inot->in_portid_lo;
+ } else {
+ portid = PORT_ANY;
+ }
+
+ switch (inot->in_status) {
+ case IN24XX_ELS_RCVD:
+ {
+ char buf[16], *msg;
+ int chan = ISP_GET_VPIDX(isp, inot->in_vpidx);
+
+ /*
+ * Note that we're just getting notification that an ELS was received
+ * (possibly with some associcated information sent upstream). This is
+ * *not* the same as being given the ELS frame to accept or reject.
+ */
+ switch (inot->in_status_subcode) {
+ case LOGO:
+ msg = "LOGO";
+ if (ISP_FW_NEWER_THAN(isp, 4, 0, 25)) {
+ ptr = (uint8_t *)inot; /* point to unswizzled entry! */
+ wwn = (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF]) << 56) |
+ (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+1]) << 48) |
+ (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+2]) << 40) |
+ (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+3]) << 32) |
+ (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+4]) << 24) |
+ (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+5]) << 16) |
+ (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+6]) << 8) |
+ (((uint64_t) ptr[IN24XX_LOGO_WWPN_OFF+7]));
+ } else {
+ wwn = INI_ANY;
+ }
+ isp_del_wwn_entry(isp, chan, wwn, nphdl, portid);
+ break;
+ case PRLO:
+ msg = "PRLO";
+ break;
+ case PLOGI:
+ msg = "PLOGI";
+ if (ISP_FW_NEWER_THAN(isp, 4, 0, 25)) {
+ ptr = (uint8_t *)inot; /* point to unswizzled entry! */
+ wwn = (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF]) << 56) |
+ (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+1]) << 48) |
+ (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+2]) << 40) |
+ (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+3]) << 32) |
+ (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+4]) << 24) |
+ (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+5]) << 16) |
+ (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+6]) << 8) |
+ (((uint64_t) ptr[IN24XX_PLOGI_WWPN_OFF+7]));
+ } else {
+ wwn = INI_NONE;
+ }
+ isp_add_wwn_entry(isp, chan, wwn, nphdl, portid);
+ break;
+ case PRLI:
+ msg = "PRLI";
+ break;
+ case PDISC:
+ msg = "PDISC";
+ break;
+ case ADISC:
+ msg = "ADISC";
+ break;
+ default:
+ ISP_SNPRINTF(buf, sizeof (buf), "ELS 0x%x", inot->in_status_subcode);
+ msg = buf;
+ break;
+ }
+ if (inot->in_flags & IN24XX_FLAG_PUREX_IOCB) {
+ isp_prt(isp, ISP_LOGERR, "%s Chan %d ELS N-port handle %x PortID 0x%06x marked as needing a PUREX response", msg, chan, nphdl, portid);
+ break;
+ }
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s Chan %d ELS N-port handle %x PortID 0x%06x RX_ID 0x%x OX_ID 0x%x", msg, chan, nphdl, portid,
+ inot->in_rxid, inot->in_oxid);
+ (void) isp_notify_ack(isp, inot);
+ break;
+ }
+
+ case IN24XX_PORT_LOGOUT:
+ ptr = "PORT LOGOUT";
+ if (isp_find_pdb_by_loopid(isp, ISP_GET_VPIDX(isp, inot->in_vpidx), nphdl, &lp)) {
+ isp_del_wwn_entry(isp, ISP_GET_VPIDX(isp, inot->in_vpidx), lp->port_wwn, nphdl, lp->portid);
+ }
+ /* FALLTHROUGH */
+ case IN24XX_PORT_CHANGED:
+ if (ptr == NULL) {
+ ptr = "PORT CHANGED";
}
+ /* FALLTHROUGH */
+ case IN24XX_LIP_RESET:
+ if (ptr == NULL) {
+ ptr = "LIP RESET";
+ }
+ isp_prt(isp, ISP_LOGINFO, "Chan %d %s (sub-status 0x%x) for N-port handle 0x%x", ISP_GET_VPIDX(isp, inot->in_vpidx), ptr, inot->in_status_subcode, nphdl);
+
+ /*
+ * All subcodes here are irrelevant. What is relevant
+ * is that we need to terminate all active commands from
+ * this initiator (known by N-port handle).
+ */
+ /* XXX IMPLEMENT XXX */
+ (void) isp_notify_ack(isp, inot);
+ break;
+
+ case IN24XX_LINK_RESET:
+ case IN24XX_LINK_FAILED:
+ case IN24XX_SRR_RCVD:
+ default:
+ (void) isp_notify_ack(isp, inot);
break;
}
+}
+
+static int
+isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp)
+{
+
+ if (isp->isp_state != ISP_RUNSTATE) {
+ isp_prt(isp, ISP_LOGTINFO, "Notify Code 0x%x (qevalid=%d) acked- h/w not ready (dropping)", mp->nt_ncode, mp->nt_lreserved != NULL);
+ return (0);
+ }
+
+ /*
+ * This case is for a Task Management Function, which shows up as an ATIO7 entry.
+ */
+ if (IS_24XX(isp) && mp->nt_lreserved && ((isphdr_t *)mp->nt_lreserved)->rqs_entry_type == RQSTYPE_ATIO) {
+ ct7_entry_t local, *cto = &local;
+ at7_entry_t *aep = (at7_entry_t *)mp->nt_lreserved;
+ fcportdb_t *lp;
+ uint32_t sid;
+ uint16_t nphdl;
+
+ sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2];
+ if (isp_find_pdb_by_sid(isp, mp->nt_channel, sid, &lp)) {
+ nphdl = lp->handle;
+ } else {
+ nphdl = NIL_HANDLE;
+ }
+ ISP_MEMZERO(&local, sizeof (local));
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_nphdl = nphdl;
+ cto->ct_rxid = aep->at_rxid;
+ cto->ct_vpidx = mp->nt_channel;
+ cto->ct_iid_lo = sid;
+ cto->ct_iid_hi = sid >> 16;
+ cto->ct_oxid = aep->at_hdr.ox_id;
+ cto->ct_flags = CT7_SENDSTATUS|CT7_NOACK|CT7_NO_DATA|CT7_FLAG_MODE1;
+ cto->ct_flags |= (aep->at_ta_len >> 12) << CT7_TASK_ATTR_SHIFT;
+ return (isp_target_put_entry(isp, &local));
+ }
+
+ /*
+ * This case is for a responding to an ABTS frame
+ */
+ if (IS_24XX(isp) && mp->nt_lreserved && ((isphdr_t *)mp->nt_lreserved)->rqs_entry_type == RQSTYPE_ABTS_RCVD) {
+
+ /*
+ * Overload nt_need_ack here to mark whether we've terminated the associated command.
+ */
+ if (mp->nt_need_ack) {
+ uint8_t storage[QENTRY_LEN];
+ ct7_entry_t *cto = (ct7_entry_t *) storage;
+ abts_t *abts = (abts_t *)mp->nt_lreserved;
+
+ ISP_MEMZERO(cto, sizeof (ct7_entry_t));
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: [%x] terminating after ABTS received", __func__, abts->abts_rxid_task);
+ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
+ cto->ct_header.rqs_entry_count = 1;
+ cto->ct_nphdl = mp->nt_nphdl;
+ cto->ct_rxid = abts->abts_rxid_task;
+ cto->ct_iid_lo = mp->nt_sid;
+ cto->ct_iid_hi = mp->nt_sid >> 16;
+ cto->ct_oxid = abts->abts_ox_id;
+ cto->ct_vpidx = mp->nt_channel;
+ cto->ct_flags = CT7_NOACK|CT7_TERMINATE;
+ if (isp_target_put_entry(isp, cto)) {
+ return (ENOMEM);
+ }
+ mp->nt_need_ack = 0;
+ }
+ if (isp_acknak_abts(isp, mp->nt_lreserved, 0) == ENOMEM) {
+ return (ENOMEM);
+ } else {
+ return (0);
+ }
+ }
+
+ /*
+ * Handle logout cases here
+ */
+ if (mp->nt_ncode == NT_GLOBAL_LOGOUT) {
+ isp_del_all_wwn_entries(isp, mp->nt_channel);
+ }
+
+ if (mp->nt_ncode == NT_LOGOUT) {
+ if (!IS_2100(isp) && IS_FC(isp)) {
+ isp_del_wwn_entries(isp, mp);
+ }
+ }
+
+ /*
+ * General purpose acknowledgement
+ */
+ if (mp->nt_need_ack) {
+ isp_prt(isp, ISP_LOGTINFO, "Notify Code 0x%x (qevalid=%d) being acked", mp->nt_ncode, mp->nt_lreserved != NULL);
+ return (isp_notify_ack(isp, mp->nt_lreserved));
+ }
+ return (0);
+}
+
+/*
+ * Handle task managment functions.
+ *
+ * We show up here with a notify structure filled out.
+ *
+ * The nt_lreserved tag points to the original queue entry
+ */
+static void
+isp_handle_platform_target_tmf(ispsoftc_t *isp, isp_notify_t *notify)
+{
+ tstate_t *tptr;
+ fcportdb_t *lp;
+ struct ccb_immediate_notify *inot;
+ inot_private_data_t *ntp = NULL;
+ lun_id_t lun;
+
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: code 0x%x sid 0x%x tagval 0x%016llx chan %d lun 0x%x", __func__, notify->nt_ncode,
+ notify->nt_sid, (unsigned long long) notify->nt_tagval, notify->nt_channel, notify->nt_lun);
+ /*
+ * NB: This assignment is necessary because of tricky type conversion.
+ * XXX: This is tricky and I need to check this. If the lun isn't known
+ * XXX: for the task management function, it does not of necessity follow
+ * XXX: that it should go up stream to the wildcard listener.
+ */
+ if (notify->nt_lun == LUN_ANY) {
+ lun = CAM_LUN_WILDCARD;
+ } else {
+ lun = notify->nt_lun;
+ }
+ tptr = get_lun_statep(isp, notify->nt_channel, lun);
+ if (tptr == NULL) {
+ tptr = get_lun_statep(isp, notify->nt_channel, CAM_LUN_WILDCARD);
+ if (tptr == NULL) {
+ isp_prt(isp, ISP_LOGWARN, "%s: no state pointer found for chan %d lun 0x%x", __func__, notify->nt_channel, lun);
+ goto bad;
+ }
+ }
+ inot = (struct ccb_immediate_notify *) SLIST_FIRST(&tptr->inots);
+ if (inot == NULL) {
+ isp_prt(isp, ISP_LOGWARN, "%s: out of immediate notify structures for chan %d lun 0x%x", __func__, notify->nt_channel, lun);
+ goto bad;
+ }
+
+ if (isp_find_pdb_by_sid(isp, notify->nt_channel, notify->nt_sid, &lp) == 0) {
+ inot->initiator_id = CAM_TARGET_WILDCARD;
+ } else {
+ inot->initiator_id = lp->handle;
+ }
+ inot->seq_id = notify->nt_tagval;
+ inot->tag_id = notify->nt_tagval >> 32;
+
+ switch (notify->nt_ncode) {
+ case NT_ABORT_TASK:
+ isp_target_mark_aborted_early(isp, tptr, inot->tag_id);
+ inot->arg = MSG_ABORT_TASK;
+ break;
+ case NT_ABORT_TASK_SET:
+ isp_target_mark_aborted_early(isp, tptr, TAG_ANY);
+ inot->arg = MSG_ABORT_TASK_SET;
+ break;
+ case NT_CLEAR_ACA:
+ inot->arg = MSG_CLEAR_ACA;
+ break;
+ case NT_CLEAR_TASK_SET:
+ inot->arg = MSG_CLEAR_TASK_SET;
+ break;
+ case NT_LUN_RESET:
+ inot->arg = MSG_LOGICAL_UNIT_RESET;
+ break;
+ case NT_TARGET_RESET:
+ inot->arg = MSG_TARGET_RESET;
+ break;
default:
+ isp_prt(isp, ISP_LOGWARN, "%s: unknown TMF code 0x%x for chan %d lun 0x%x", __func__, notify->nt_ncode, notify->nt_channel, lun);
+ goto bad;
+ }
+
+ ntp = isp_get_ntpd(isp, tptr);
+ if (ntp == NULL) {
+ isp_prt(isp, ISP_LOGWARN, "%s: out of inotify private structures", __func__);
+ goto bad;
+ }
+ ISP_MEMCPY(&ntp->rd.nt, notify, sizeof (isp_notify_t));
+ if (notify->nt_lreserved) {
+ ISP_MEMCPY(&ntp->rd.data, notify->nt_lreserved, QENTRY_LEN);
+ ntp->rd.nt.nt_lreserved = &ntp->rd.data;
+ }
+ ntp->rd.seq_id = notify->nt_tagval;
+ ntp->rd.tag_id = notify->nt_tagval >> 32;
+
+ tptr->inot_count--;
+ SLIST_REMOVE_HEAD(&tptr->inots, sim_links.sle);
+ rls_lun_statep(isp, tptr);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, inot->ccb_h.path, "%s: Take FREE INOT count now %d\n", __func__, tptr->inot_count);
+ inot->ccb_h.status = CAM_MESSAGE_RECV;
+ xpt_done((union ccb *)inot);
+ return;
+bad:
+ if (tptr) {
+ rls_lun_statep(isp, tptr);
+ }
+ if (notify->nt_need_ack && notify->nt_lreserved) {
+ if (((isphdr_t *)notify->nt_lreserved)->rqs_entry_type == RQSTYPE_ABTS_RCVD) {
+ (void) isp_acknak_abts(isp, notify->nt_lreserved, ENOMEM);
+ } else {
+ (void) isp_notify_ack(isp, notify->nt_lreserved);
+ }
+ }
+}
+
+/*
+ * Find the associated private data and makr it as dead so
+ * we don't try to work on it any further.
+ */
+static void
+isp_target_mark_aborted(ispsoftc_t *isp, union ccb *ccb)
+{
+ tstate_t *tptr;
+ atio_private_data_t *atp;
+
+ tptr = get_lun_statep(isp, XS_CHANNEL(ccb), XS_LUN(ccb));
+ if (tptr == NULL) {
+ tptr = get_lun_statep(isp, XS_CHANNEL(ccb), CAM_LUN_WILDCARD);
+ if (tptr == NULL) {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ return;
+ }
+ }
+
+ atp = isp_get_atpd(isp, tptr, ccb->atio.tag_id);
+ if (atp == NULL) {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ return;
+ }
+ atp->dead = 1;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+}
+
+static void
+isp_target_mark_aborted_early(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag_id)
+{
+ atio_private_data_t *atp;
+ inot_private_data_t *restart_queue = tptr->restart_queue;
+
+ /*
+ * First, clean any commands pending restart
+ */
+ tptr->restart_queue = NULL;
+ while (restart_queue) {
+ uint32_t this_tag_id;
+ inot_private_data_t *ntp = restart_queue;
+
+ restart_queue = ntp->rd.nt.nt_hba;
+
+ if (IS_24XX(isp)) {
+ this_tag_id = ((at7_entry_t *)ntp->rd.data)->at_rxid;
+ } else {
+ this_tag_id = ((at2_entry_t *)ntp->rd.data)->at_rxid;
+ }
+ if ((uint64_t)tag_id == TAG_ANY || tag_id == this_tag_id) {
+ isp_put_ntpd(isp, tptr, ntp);
+ } else {
+ ntp->rd.nt.nt_hba = tptr->restart_queue;
+ tptr->restart_queue = ntp;
+ }
+ }
+
+ /*
+ * Now mark other ones dead as well.
+ */
+ for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) {
+ if ((uint64_t)tag_id == TAG_ANY || atp->tag == tag_id) {
+ atp->dead = 1;
+ }
+ }
+}
+
+
+#ifdef ISP_INTERNAL_TARGET
+// #define ISP_FORCE_TIMEOUT 1
+#define ISP_TEST_WWNS 1
+#define ISP_TEST_SEPARATE_STATUS 1
+
+#define ccb_data_offset ppriv_field0
+#define ccb_atio ppriv_ptr1
+#define ccb_inot ppriv_ptr1
+
+#define MAX_ISP_TARG_TRANSFER (2 << 20)
+#define NISP_TARG_CMDS 1024
+#define NISP_TARG_NOTIFIES 1024
+#define DISK_SHIFT 9
+#define JUNK_SIZE 256
+
+#ifndef VERIFY_10
+#define VERIFY_10 0x2f
+#endif
+
+TAILQ_HEAD(ccb_queue, ccb_hdr);
+extern u_int vm_kmem_size;
+static int ca;
+static uint32_t disk_size;
+static uint8_t *disk_data = NULL;
+static uint8_t *junk_data;
+static MALLOC_DEFINE(M_ISPTARG, "ISPTARG", "ISP TARGET data");
+struct isptarg_softc {
+ /* CCBs (CTIOs, ATIOs, INOTs) pending on the controller */
+ struct ccb_queue work_queue;
+ struct ccb_queue rework_queue;
+ struct ccb_queue running_queue;
+ struct ccb_queue inot_queue;
+ struct cam_periph *periph;
+ struct cam_path *path;
+ ispsoftc_t *isp;
+};
+static periph_ctor_t isptargctor;
+static periph_dtor_t isptargdtor;
+static periph_start_t isptargstart;
+static periph_init_t isptarginit;
+static void isptarg_done(struct cam_periph *, union ccb *);
+static void isptargasync(void *, u_int32_t, struct cam_path *, void *);
+
+
+static int isptarg_rwparm(uint8_t *, uint8_t *, uint64_t, uint32_t, uint8_t **, uint32_t *, int *);
+
+static struct periph_driver isptargdriver =
+{
+ isptarginit, "isptarg", TAILQ_HEAD_INITIALIZER(isptargdriver.units), /* generation */ 0
+};
+
+static void
+isptarginit(void)
+{
+}
+
+static void
+isptargnotify(ispsoftc_t *isp, union ccb *iccb, struct ccb_immediate_notify *inot)
+{
+ struct ccb_notify_acknowledge *ack = &iccb->cna2;
+
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, inot->ccb_h.path, "%s: [0x%x] immediate notify for 0x%x from 0x%x status 0x%x arg 0x%x\n", __func__,
+ inot->tag_id, inot->initiator_id, inot->seq_id, inot->ccb_h.status, inot->arg);
+ ack->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
+ ack->ccb_h.flags = 0;
+ ack->ccb_h.retry_count = 0;
+ ack->ccb_h.cbfcnp = isptarg_done;
+ ack->ccb_h.timeout = 0;
+ ack->ccb_h.ccb_inot = inot;
+ ack->tag_id = inot->tag_id;
+ ack->seq_id = inot->seq_id;
+ ack->initiator_id = inot->initiator_id;
+ xpt_action(iccb);
+}
+
+static void
+isptargstart(struct cam_periph *periph, union ccb *iccb)
+{
+ const uint8_t niliqd[SHORT_INQUIRY_LENGTH] = { 0x7f };
+ const uint8_t iqd[SHORT_INQUIRY_LENGTH] = {
+ 0, 0x0, 0x2, 0x2, 32, 0, 0, 0x32,
+ 'F', 'R', 'E', 'E', 'B', 'S', 'D', ' ',
+ 'S', 'C', 'S', 'I', ' ', 'M', 'E', 'M',
+ 'O', 'R', 'Y', ' ', 'D', 'I', 'S', 'K',
+ '0', '0', '0', '1'
+ };
+ int i, more = 0, last;
+ struct isptarg_softc *softc = periph->softc;
+ struct ccb_scsiio *csio;
+ lun_id_t return_lun;
+ struct ccb_accept_tio *atio;
+ uint8_t *cdb, *ptr, status;
+ uint8_t *data_ptr;
+ uint32_t data_len, flags;
+ struct ccb_hdr *ccbh;
+
+ mtx_assert(periph->sim->mtx, MA_OWNED);
+ ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, iccb->ccb_h.path, "%s: function code 0x%x INOTQ=%c WORKQ=%c REWORKQ=%c\n", __func__, iccb->ccb_h.func_code,
+ TAILQ_FIRST(&softc->inot_queue)? 'y' : 'n', TAILQ_FIRST(&softc->work_queue)? 'y' : 'n', TAILQ_FIRST(&softc->rework_queue)? 'y' : 'n');
+ /*
+ * Check for immediate notifies first
+ */
+ ccbh = TAILQ_FIRST(&softc->inot_queue);
+ if (ccbh) {
+ TAILQ_REMOVE(&softc->inot_queue, ccbh, periph_links.tqe);
+ if (TAILQ_FIRST(&softc->inot_queue) || TAILQ_FIRST(&softc->work_queue) || TAILQ_FIRST(&softc->rework_queue)) {
+ xpt_schedule(periph, 1);
+ }
+ isptargnotify(softc->isp, iccb, (struct ccb_immediate_notify *)ccbh);
+ return;
+ }
+
+ /*
+ * Check the rework (continuation) work queue first.
+ */
+ ccbh = TAILQ_FIRST(&softc->rework_queue);
+ if (ccbh) {
+ atio = (struct ccb_accept_tio *)ccbh;
+ TAILQ_REMOVE(&softc->rework_queue, ccbh, periph_links.tqe);
+ more = TAILQ_FIRST(&softc->work_queue) || TAILQ_FIRST(&softc->rework_queue);
+ } else {
+ ccbh = TAILQ_FIRST(&softc->work_queue);
+ if (ccbh == NULL) {
+ ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, iccb->ccb_h.path, "%s: woken up but no work?\n", __func__);
+ xpt_release_ccb(iccb);
+ return;
+ }
+ atio = (struct ccb_accept_tio *)ccbh;
+ TAILQ_REMOVE(&softc->work_queue, ccbh, periph_links.tqe);
+ more = TAILQ_FIRST(&softc->work_queue) != NULL;
+ atio->ccb_h.ccb_data_offset = 0;
+ }
+
+ if (atio->tag_id == 0xffffffff || atio->ccb_h.func_code != XPT_ACCEPT_TARGET_IO) {
+ panic("BAD ATIO");
+ }
+
+ data_ptr = NULL;
+ data_len = 0;
+ csio = &iccb->csio;
+ status = SCSI_STATUS_OK;
+ flags = CAM_SEND_STATUS;
+ memset(&atio->sense_data, 0, sizeof (atio->sense_data));
+ cdb = atio->cdb_io.cdb_bytes;
+ ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, ccbh->path, "%s: [0x%x] processing ATIO from 0x%x CDB=0x%x data_offset=%u\n", __func__, atio->tag_id, atio->init_id,
+ cdb[0], atio->ccb_h.ccb_data_offset);
+
+ return_lun = XS_LUN(atio);
+ if (return_lun != 0) {
+ xpt_print(atio->ccb_h.path, "[0x%x] Non-Zero Lun %d: cdb0=0x%x\n", atio->tag_id, return_lun, cdb[0]);
+ if (cdb[0] != INQUIRY && cdb[0] != REPORT_LUNS && cdb[0] != REQUEST_SENSE) {
+ status = SCSI_STATUS_CHECK_COND;
+ atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_ILLEGAL_REQUEST;
+ atio->sense_data.add_sense_code = 0x25;
+ atio->sense_data.add_sense_code_qual = 0x0;
+ atio->sense_len = sizeof (atio->sense_data);
+ }
+ return_lun = CAM_LUN_WILDCARD;
+ }
+
+ switch (cdb[0]) {
+ case REQUEST_SENSE:
+ flags |= CAM_DIR_IN;
+ data_len = sizeof (atio->sense_data);
+ junk_data[0] = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_NO_SENSE;
+ memset(junk_data+1, 0, data_len-1);
+ if (data_len > cdb[4]) {
+ data_len = cdb[4];
+ }
+ if (data_len) {
+ data_ptr = junk_data;
+ }
+ break;
+ case READ_6:
+ case READ_10:
+ case READ_12:
+ case READ_16:
+ if (isptarg_rwparm(cdb, disk_data, disk_size, atio->ccb_h.ccb_data_offset, &data_ptr, &data_len, &last)) {
+ status = SCSI_STATUS_CHECK_COND;
+ atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
+ atio->sense_data.add_sense_code = 0x5;
+ atio->sense_data.add_sense_code_qual = 0x24;
+ atio->sense_len = sizeof (atio->sense_data);
+ } else {
+#ifdef ISP_FORCE_TIMEOUT
+ {
+ static int foo;
+ if (foo++ == 500) {
+ if (more) {
+ xpt_schedule(periph, 1);
+ }
+ foo = 0;
+ return;
+ }
+ }
+#endif
+#ifdef ISP_TEST_SEPARATE_STATUS
+ if (last && data_len) {
+ last = 0;
+ }
+#endif
+ if (last == 0) {
+ flags &= ~CAM_SEND_STATUS;
+ }
+ if (data_len) {
+ atio->ccb_h.ccb_data_offset += data_len;
+ flags |= CAM_DIR_IN;
+ } else {
+ flags |= CAM_DIR_NONE;
+ }
+ }
+ break;
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_12:
+ case WRITE_16:
+ if (isptarg_rwparm(cdb, disk_data, disk_size, atio->ccb_h.ccb_data_offset, &data_ptr, &data_len, &last)) {
+ status = SCSI_STATUS_CHECK_COND;
+ atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
+ atio->sense_data.add_sense_code = 0x5;
+ atio->sense_data.add_sense_code_qual = 0x24;
+ atio->sense_len = sizeof (atio->sense_data);
+ } else {
+#ifdef ISP_FORCE_TIMEOUT
+ {
+ static int foo;
+ if (foo++ == 500) {
+ if (more) {
+ xpt_schedule(periph, 1);
+ }
+ foo = 0;
+ return;
+ }
+ }
+#endif
+#ifdef ISP_TEST_SEPARATE_STATUS
+ if (last && data_len) {
+ last = 0;
+ }
+#endif
+ if (last == 0) {
+ flags &= ~CAM_SEND_STATUS;
+ }
+ if (data_len) {
+ atio->ccb_h.ccb_data_offset += data_len;
+ flags |= CAM_DIR_OUT;
+ } else {
+ flags |= CAM_DIR_NONE;
+ }
+ }
+ break;
+ case INQUIRY:
+ flags |= CAM_DIR_IN;
+ if (cdb[1] || cdb[2] || cdb[3]) {
+ status = SCSI_STATUS_CHECK_COND;
+ atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
+ atio->sense_data.add_sense_code = 0x5;
+ atio->sense_data.add_sense_code_qual = 0x20;
+ atio->sense_len = sizeof (atio->sense_data);
+ break;
+ }
+ data_len = sizeof (iqd);
+ if (data_len > cdb[4]) {
+ data_len = cdb[4];
+ }
+ if (data_len) {
+ if (XS_LUN(iccb) != 0) {
+ memcpy(junk_data, niliqd, sizeof (iqd));
+ } else {
+ memcpy(junk_data, iqd, sizeof (iqd));
+ }
+ data_ptr = junk_data;
+ }
+ break;
+ case TEST_UNIT_READY:
+ flags |= CAM_DIR_NONE;
+ if (ca) {
+ ca = 0;
+ status = SCSI_STATUS_CHECK_COND;
+ atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
+ atio->sense_data.add_sense_code = 0x28;
+ atio->sense_data.add_sense_code_qual = 0x0;
+ atio->sense_len = sizeof (atio->sense_data);
+ }
+ break;
+ case SYNCHRONIZE_CACHE:
+ case START_STOP:
+ case RESERVE:
+ case RELEASE:
+ case VERIFY_10:
+ flags |= CAM_DIR_NONE;
+ break;
+
+ case READ_CAPACITY:
+ flags |= CAM_DIR_IN;
+ if (cdb[2] || cdb[3] || cdb[4] || cdb[5]) {
+ status = SCSI_STATUS_CHECK_COND;
+ atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
+ atio->sense_data.add_sense_code = 0x5;
+ atio->sense_data.add_sense_code_qual = 0x24;
+ atio->sense_len = sizeof (atio->sense_data);
+ break;
+ }
+ if (cdb[8] & 0x1) { /* PMI */
+ junk_data[0] = 0xff;
+ junk_data[1] = 0xff;
+ junk_data[2] = 0xff;
+ junk_data[3] = 0xff;
+ } else {
+ uint64_t last_blk = (disk_size >> DISK_SHIFT) - 1;
+ if (last_blk < 0xffffffffULL) {
+ junk_data[0] = (last_blk >> 24) & 0xff;
+ junk_data[1] = (last_blk >> 16) & 0xff;
+ junk_data[2] = (last_blk >> 8) & 0xff;
+ junk_data[3] = (last_blk) & 0xff;
+ } else {
+ junk_data[0] = 0xff;
+ junk_data[1] = 0xff;
+ junk_data[2] = 0xff;
+ junk_data[3] = 0xff;
+ }
+ }
+ junk_data[4] = ((1 << DISK_SHIFT) >> 24) & 0xff;
+ junk_data[5] = ((1 << DISK_SHIFT) >> 16) & 0xff;
+ junk_data[6] = ((1 << DISK_SHIFT) >> 8) & 0xff;
+ junk_data[7] = ((1 << DISK_SHIFT)) & 0xff;
+ data_ptr = junk_data;
+ data_len = 8;
+ break;
+ case REPORT_LUNS:
+ flags |= CAM_DIR_IN;
+ memset(junk_data, 0, JUNK_SIZE);
+ junk_data[0] = (1 << 3) >> 24;
+ junk_data[1] = (1 << 3) >> 16;
+ junk_data[2] = (1 << 3) >> 8;
+ junk_data[3] = (1 << 3);
+ ptr = NULL;
+ for (i = 0; i < 1; i++) {
+ ptr = &junk_data[8 + (1 << 3)];
+ if (i >= 256) {
+ ptr[0] = 0x40 | ((i >> 8) & 0x3f);
+ }
+ ptr[1] = i;
+ }
+ data_ptr = junk_data;
+ data_len = (ptr + 8) - junk_data;
+ break;
+
+ default:
+ flags |= CAM_DIR_NONE;
+ status = SCSI_STATUS_CHECK_COND;
+ atio->sense_data.error_code = SSD_ERRCODE_VALID|SSD_CURRENT_ERROR|SSD_KEY_UNIT_ATTENTION;
+ atio->sense_data.add_sense_code = 0x5;
+ atio->sense_data.add_sense_code_qual = 0x20;
+ atio->sense_len = sizeof (atio->sense_data);
+ break;
+ }
+
+ /*
+ * If we are done with the transaction, tell the
+ * controller to send status and perform a CMD_CMPLT.
+ * If we have associated sense data, see if we can
+ * send that too.
+ */
+ if (status == SCSI_STATUS_CHECK_COND) {
+ flags |= CAM_SEND_SENSE;
+ csio->sense_len = atio->sense_len;
+ csio->sense_data = atio->sense_data;
+ flags &= ~CAM_DIR_MASK;
+ data_len = 0;
+ data_ptr = NULL;
+ }
+ cam_fill_ctio(csio, 0, isptarg_done, flags, MSG_SIMPLE_Q_TAG, atio->tag_id, atio->init_id, status, data_ptr, data_len, 0);
+ iccb->ccb_h.target_id = atio->ccb_h.target_id;
+ iccb->ccb_h.target_lun = return_lun;
+ iccb->ccb_h.ccb_atio = atio;
+ xpt_action(iccb);
+
+ if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ cam_release_devq(periph->path, 0, 0, 0, 0);
+ atio->ccb_h.status &= ~CAM_DEV_QFRZN;
+ }
+ if (more) {
+ xpt_schedule(periph, 1);
+ }
+}
+
+static cam_status
+isptargctor(struct cam_periph *periph, void *arg)
+{
+ struct isptarg_softc *softc;
+
+ softc = (struct isptarg_softc *)arg;
+ periph->softc = softc;
+ softc->periph = periph;
+ softc->path = periph->path;
+ ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, periph->path, "%s called\n", __func__);
+ return (CAM_REQ_CMP);
+}
+
+static void
+isptargdtor(struct cam_periph *periph)
+{
+ struct isptarg_softc *softc;
+ softc = (struct isptarg_softc *)periph->softc;
+ ISP_PATH_PRT(softc->isp, ISP_LOGTDEBUG0, periph->path, "%s called\n", __func__);
+ softc->periph = NULL;
+ softc->path = NULL;
+ periph->softc = NULL;
+}
+
+static void
+isptarg_done(struct cam_periph *periph, union ccb *ccb)
+{
+ struct isptarg_softc *softc;
+ ispsoftc_t *isp;
+ struct ccb_accept_tio *atio;
+ struct ccb_immediate_notify *inot;
+ cam_status status;
+
+ softc = (struct isptarg_softc *)periph->softc;
+ isp = softc->isp;
+ status = ccb->ccb_h.status & CAM_STATUS_MASK;
+
+ switch (ccb->ccb_h.func_code) {
+ case XPT_ACCEPT_TARGET_IO:
+ atio = (struct ccb_accept_tio *) ccb;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] ATIO seen in %s\n", atio->tag_id, __func__);
+ TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h, periph_links.tqe);
+ xpt_schedule(periph, 1);
+ break;
+ case XPT_IMMEDIATE_NOTIFY:
+ inot = (struct ccb_immediate_notify *) ccb;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] INOT for 0x%x seen in %s\n", inot->tag_id, inot->seq_id, __func__);
+ TAILQ_INSERT_TAIL(&softc->inot_queue, &ccb->ccb_h, periph_links.tqe);
+ xpt_schedule(periph, 1);
+ break;
+ case XPT_CONT_TARGET_IO:
+ if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
+ ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
+ }
+ atio = ccb->ccb_h.ccb_atio;
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ cam_error_print(ccb, CAM_ESF_ALL, CAM_EPF_ALL);
+ xpt_action((union ccb *)atio);
+ } else if ((ccb->ccb_h.flags & CAM_SEND_STATUS) == 0) {
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] MID CTIO seen in %s\n", atio->tag_id, __func__);
+ TAILQ_INSERT_TAIL(&softc->rework_queue, &atio->ccb_h, periph_links.tqe);
+ xpt_schedule(periph, 1);
+ } else {
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "[0x%x] FINAL CTIO seen in %s\n", atio->tag_id, __func__);
+ xpt_action((union ccb *)atio);
+ }
+ xpt_release_ccb(ccb);
+ break;
+ case XPT_NOTIFY_ACKNOWLEDGE:
+ if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
+ ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
+ }
+ inot = ccb->ccb_h.ccb_inot;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, inot->ccb_h.path, "[0x%x] recycle notify for tag 0x%x\n", inot->tag_id, inot->seq_id);
+ xpt_release_ccb(ccb);
+ xpt_action((union ccb *)inot);
+ break;
+ default:
+ xpt_print(ccb->ccb_h.path, "unexpected code 0x%x\n", ccb->ccb_h.func_code);
+ break;
+ }
+}
+
+static void
+isptargasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
+{
+ struct ac_contract *acp = arg;
+ struct ac_device_changed *fc = (struct ac_device_changed *) acp->contract_data;
+
+ if (code != AC_CONTRACT) {
+ return;
+ }
+ xpt_print(path, "0x%016llx Port ID 0x%06x %s\n", (unsigned long long) fc->wwpn, fc->port, fc->arrived? "arrived" : "departed");
+}
+
+static void
+isp_target_thread(ispsoftc_t *isp, int chan)
+{
+ union ccb *ccb = NULL;
+ int i;
+ void *wchan;
+ cam_status status;
+ struct isptarg_softc *softc = NULL;
+ struct cam_periph *periph = NULL, *wperiph = NULL;
+ struct cam_path *path, *wpath;
+ struct cam_sim *sim;
+
+ if (disk_data == NULL) {
+ disk_size = roundup2(vm_kmem_size >> 1, (1ULL << 20));
+ if (disk_size < (50 << 20)) {
+ disk_size = 50 << 20;
+ }
+ disk_data = malloc(disk_size, M_ISPTARG, M_WAITOK | M_ZERO);
+ if (disk_data == NULL) {
+ isp_prt(isp, ISP_LOGERR, "%s: could not allocate disk data", __func__);
+ goto out;
+ }
+ isp_prt(isp, ISP_LOGINFO, "allocated a %ju MiB disk", (uintmax_t) (disk_size >> 20));
+ }
+ junk_data = malloc(JUNK_SIZE, M_ISPTARG, M_WAITOK | M_ZERO);
+ if (junk_data == NULL) {
+ isp_prt(isp, ISP_LOGERR, "%s: could not allocate junk", __func__);
+ goto out;
+ }
+
+
+ softc = malloc(sizeof (*softc), M_ISPTARG, M_WAITOK | M_ZERO);
+ if (softc == NULL) {
+ isp_prt(isp, ISP_LOGERR, "%s: could not allocate softc", __func__);
+ goto out;
+ }
+ TAILQ_INIT(&softc->work_queue);
+ TAILQ_INIT(&softc->rework_queue);
+ TAILQ_INIT(&softc->running_queue);
+ TAILQ_INIT(&softc->inot_queue);
+ softc->isp = isp;
+
+ periphdriver_register(&isptargdriver);
+ ISP_GET_PC(isp, chan, sim, sim);
+ ISP_GET_PC(isp, chan, path, path);
+ status = xpt_create_path_unlocked(&wpath, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
+ if (status != CAM_REQ_CMP) {
+ isp_prt(isp, ISP_LOGERR, "%s: could not allocate wildcard path", __func__);
+ return;
+ }
+ status = xpt_create_path_unlocked(&path, NULL, cam_sim_path(sim), 0, 0);
+ if (status != CAM_REQ_CMP) {
+ xpt_free_path(wpath);
+ isp_prt(isp, ISP_LOGERR, "%s: could not allocate path", __func__);
+ return;
+ }
+
+ ccb = xpt_alloc_ccb();
+
+ ISP_LOCK(isp);
+ status = cam_periph_alloc(isptargctor, NULL, isptargdtor, isptargstart, "isptarg", CAM_PERIPH_BIO, wpath, NULL, 0, softc);
+ if (status != CAM_REQ_CMP) {
+ ISP_UNLOCK(isp);
+ isp_prt(isp, ISP_LOGERR, "%s: cam_periph_alloc for wildcard failed", __func__);
+ goto out;
+ }
+ wperiph = cam_periph_find(wpath, "isptarg");
+ if (wperiph == NULL) {
+ ISP_UNLOCK(isp);
+ isp_prt(isp, ISP_LOGERR, "%s: wildcard periph already allocated but doesn't exist", __func__);
+ goto out;
+ }
+
+ status = cam_periph_alloc(isptargctor, NULL, isptargdtor, isptargstart, "isptarg", CAM_PERIPH_BIO, path, NULL, 0, softc);
+ if (status != CAM_REQ_CMP) {
+ ISP_UNLOCK(isp);
+ isp_prt(isp, ISP_LOGERR, "%s: cam_periph_alloc failed", __func__);
+ goto out;
+ }
+
+ periph = cam_periph_find(path, "isptarg");
+ if (periph == NULL) {
+ ISP_UNLOCK(isp);
+ isp_prt(isp, ISP_LOGERR, "%s: periph already allocated but doesn't exist", __func__);
+ goto out;
+ }
+
+ status = xpt_register_async(AC_CONTRACT, isptargasync, isp, wpath);
+ if (status != CAM_REQ_CMP) {
+ ISP_UNLOCK(isp);
+ isp_prt(isp, ISP_LOGERR, "%s: xpt_register_async failed", __func__);
+ goto out;
+ }
+
+ ISP_UNLOCK(isp);
+
+ ccb = xpt_alloc_ccb();
+
+ /*
+ * Make sure role is none.
+ */
+ xpt_setup_ccb(&ccb->ccb_h, periph->path, 10);
+ ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
+ ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE;
+#ifdef ISP_TEST_WWNS
+ ccb->knob.xport_specific.fc.valid = KNOB_VALID_ROLE | KNOB_VALID_ADDRESS;
+ ccb->knob.xport_specific.fc.wwnn = 0x508004d000000000ULL | (device_get_unit(isp->isp_osinfo.dev) << 8) | (chan << 16);
+ ccb->knob.xport_specific.fc.wwpn = 0x508004d000000001ULL | (device_get_unit(isp->isp_osinfo.dev) << 8) | (chan << 16);
+#else
+ ccb->knob.xport_specific.fc.valid = KNOB_VALID_ROLE;
+#endif
+
+ ISP_LOCK(isp);
+ xpt_action(ccb);
+ ISP_UNLOCK(isp);
+
+ /*
+ * Now enable luns
+ */
+ xpt_setup_ccb(&ccb->ccb_h, periph->path, 10);
+ ccb->ccb_h.func_code = XPT_EN_LUN;
+ ccb->cel.enable = 1;
+ ISP_LOCK(isp);
+ xpt_action(ccb);
+ ISP_UNLOCK(isp);
+ if (ccb->ccb_h.status != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ xpt_print(periph->path, "failed to enable lun (0x%x)\n", ccb->ccb_h.status);
+ goto out;
+ }
+
+ xpt_setup_ccb(&ccb->ccb_h, wperiph->path, 10);
+ ccb->ccb_h.func_code = XPT_EN_LUN;
+ ccb->cel.enable = 1;
+ ISP_LOCK(isp);
+ xpt_action(ccb);
+ ISP_UNLOCK(isp);
+ if (ccb->ccb_h.status != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ xpt_print(wperiph->path, "failed to enable lun (0x%x)\n", ccb->ccb_h.status);
+ goto out;
+ }
+ xpt_free_ccb(ccb);
+
+ /*
+ * Add resources
+ */
+ ISP_GET_PC_ADDR(isp, chan, target_proc, wchan);
+ for (i = 0; i < 4; i++) {
+ ccb = malloc(sizeof (*ccb), M_ISPTARG, M_WAITOK | M_ZERO);
+ xpt_setup_ccb(&ccb->ccb_h, wperiph->path, 1);
+ ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
+ ccb->ccb_h.cbfcnp = isptarg_done;
+ ISP_LOCK(isp);
+ xpt_action(ccb);
+ ISP_UNLOCK(isp);
+ }
+ for (i = 0; i < NISP_TARG_CMDS; i++) {
+ ccb = malloc(sizeof (*ccb), M_ISPTARG, M_WAITOK | M_ZERO);
+ xpt_setup_ccb(&ccb->ccb_h, periph->path, 1);
+ ccb->ccb_h.func_code = XPT_ACCEPT_TARGET_IO;
+ ccb->ccb_h.cbfcnp = isptarg_done;
+ ISP_LOCK(isp);
+ xpt_action(ccb);
+ ISP_UNLOCK(isp);
+ }
+ for (i = 0; i < 4; i++) {
+ ccb = malloc(sizeof (*ccb), M_ISPTARG, M_WAITOK | M_ZERO);
+ xpt_setup_ccb(&ccb->ccb_h, wperiph->path, 1);
+ ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
+ ccb->ccb_h.cbfcnp = isptarg_done;
+ ISP_LOCK(isp);
+ xpt_action(ccb);
+ ISP_UNLOCK(isp);
+ }
+ for (i = 0; i < NISP_TARG_NOTIFIES; i++) {
+ ccb = malloc(sizeof (*ccb), M_ISPTARG, M_WAITOK | M_ZERO);
+ xpt_setup_ccb(&ccb->ccb_h, periph->path, 1);
+ ccb->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY;
+ ccb->ccb_h.cbfcnp = isptarg_done;
+ ISP_LOCK(isp);
+ xpt_action(ccb);
+ ISP_UNLOCK(isp);
+ }
+
+ /*
+ * Now turn it all back on
+ */
+ xpt_setup_ccb(&ccb->ccb_h, periph->path, 10);
+ ccb->ccb_h.func_code = XPT_SET_SIM_KNOB;
+ ccb->knob.xport_specific.fc.valid = KNOB_VALID_ROLE;
+ ccb->knob.xport_specific.fc.role = KNOB_ROLE_TARGET;
+ ISP_LOCK(isp);
+ xpt_action(ccb);
+ ISP_UNLOCK(isp);
+
+ /*
+ * Okay, while things are still active, sleep...
+ */
+ ISP_LOCK(isp);
+ for (;;) {
+ ISP_GET_PC(isp, chan, proc_active, i);
+ if (i == 0) {
+ break;
+ }
+ msleep(wchan, &isp->isp_lock, PUSER, "tsnooze", 0);
+ }
+ ISP_UNLOCK(isp);
+
+out:
+ if (wperiph) {
+ cam_periph_invalidate(wperiph);
+ }
+ if (periph) {
+ cam_periph_invalidate(periph);
+ }
+ if (junk_data) {
+ free(junk_data, M_ISPTARG);
+ }
+ if (disk_data) {
+ free(disk_data, M_ISPTARG);
+ }
+ if (softc) {
+ free(softc, M_ISPTARG);
+ }
+ xpt_free_path(path);
+ xpt_free_path(wpath);
+}
+
+static void
+isp_target_thread_pi(void *arg)
+{
+ struct isp_spi *pi = arg;
+ isp_target_thread(cam_sim_softc(pi->sim), cam_sim_bus(pi->sim));
+}
+
+static void
+isp_target_thread_fc(void *arg)
+{
+ struct isp_fc *fc = arg;
+ isp_target_thread(cam_sim_softc(fc->sim), cam_sim_bus(fc->sim));
+}
+
+static int
+isptarg_rwparm(uint8_t *cdb, uint8_t *dp, uint64_t dl, uint32_t offset, uint8_t **kp, uint32_t *tl, int *lp)
+{
+ uint32_t cnt, curcnt;
+ uint64_t lba;
+
+ switch (cdb[0]) {
+ case WRITE_16:
+ case READ_16:
+ cnt = (((uint32_t)cdb[10]) << 24) |
+ (((uint32_t)cdb[11]) << 16) |
+ (((uint32_t)cdb[12]) << 8) |
+ ((uint32_t)cdb[13]);
+
+ lba = (((uint64_t)cdb[2]) << 56) |
+ (((uint64_t)cdb[3]) << 48) |
+ (((uint64_t)cdb[4]) << 40) |
+ (((uint64_t)cdb[5]) << 32) |
+ (((uint64_t)cdb[6]) << 24) |
+ (((uint64_t)cdb[7]) << 16) |
+ (((uint64_t)cdb[8]) << 8) |
+ ((uint64_t)cdb[9]);
+ break;
+ case WRITE_12:
+ case READ_12:
+ cnt = (((uint32_t)cdb[6]) << 16) |
+ (((uint32_t)cdb[7]) << 8) |
+ ((u_int32_t)cdb[8]);
+
+ lba = (((uint32_t)cdb[2]) << 24) |
+ (((uint32_t)cdb[3]) << 16) |
+ (((uint32_t)cdb[4]) << 8) |
+ ((uint32_t)cdb[5]);
break;
+ case WRITE_10:
+ case READ_10:
+ cnt = (((uint32_t)cdb[7]) << 8) |
+ ((u_int32_t)cdb[8]);
+
+ lba = (((uint32_t)cdb[2]) << 24) |
+ (((uint32_t)cdb[3]) << 16) |
+ (((uint32_t)cdb[4]) << 8) |
+ ((uint32_t)cdb[5]);
+ break;
+ case WRITE_6:
+ case READ_6:
+ cnt = cdb[4];
+ if (cnt == 0) {
+ cnt = 256;
+ }
+ lba = (((uint32_t)cdb[1] & 0x1f) << 16) |
+ (((uint32_t)cdb[2]) << 8) |
+ ((uint32_t)cdb[3]);
+ break;
+ default:
+ return (-1);
+ }
+
+ cnt <<= DISK_SHIFT;
+ lba <<= DISK_SHIFT;
+
+ if (offset == cnt) {
+ *lp = 1;
+ return (0);
+ }
+
+ if (lba + cnt > dl) {
+ return (-1);
+ }
+
+
+ curcnt = MAX_ISP_TARG_TRANSFER;
+ if (offset + curcnt >= cnt) {
+ curcnt = cnt - offset;
+ *lp = 1;
+ } else {
+ *lp = 0;
}
+ *tl = curcnt;
+ *kp = &dp[lba + offset];
return (0);
}
+
+#endif
#endif
static void
@@ -1885,12 +3766,12 @@ isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
case AC_LOST_DEVICE:
if (IS_SCSI(isp)) {
uint16_t oflags, nflags;
- sdparam *sdp = isp->isp_param;
+ int bus = cam_sim_bus(sim);
+ sdparam *sdp = SDPARAM(isp, bus);
int tgt;
tgt = xpt_path_target_id(path);
if (tgt >= 0) {
- sdp += cam_sim_bus(sim);
nflags = sdp->isp_devparam[tgt].nvrm_flags;
#ifndef ISP_TARGET_MODE
nflags &= DPARM_SAFE_DFLT;
@@ -1903,9 +3784,8 @@ isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
oflags = sdp->isp_devparam[tgt].goal_flags;
sdp->isp_devparam[tgt].goal_flags = nflags;
sdp->isp_devparam[tgt].dev_update = 1;
- isp->isp_update |= (1 << cam_sim_bus(sim));
- (void) isp_control(isp,
- ISPCTL_UPDATE_PARAMS, NULL);
+ sdp->update = 1;
+ (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, bus);
sdp->isp_devparam[tgt].goal_flags = oflags;
}
}
@@ -1929,109 +3809,55 @@ isp_poll(struct cam_sim *sim)
}
-static int isp_watchdog_work(ispsoftc_t *, XS_T *);
-
-static int
-isp_watchdog_work(ispsoftc_t *isp, XS_T *xs)
+static void
+isp_watchdog(void *arg)
{
+ struct ccb_scsiio *xs = arg;
+ ispsoftc_t *isp;
uint32_t handle;
- /*
- * We've decided this command is dead. Make sure we're not trying
- * to kill a command that's already dead by getting it's handle and
- * and seeing whether it's still alive.
- */
+ isp = XS_ISP(xs);
+
handle = isp_find_handle(isp, xs);
if (handle) {
- uint32_t isr;
- uint16_t sema, mbox;
-
- if (XS_CMD_DONE_P(xs)) {
- isp_prt(isp, ISP_LOGDEBUG1,
- "watchdog found done cmd (handle 0x%x)", handle);
- return (1);;
- }
-
- if (XS_CMD_WDOG_P(xs)) {
- isp_prt(isp, ISP_LOGDEBUG2,
- "recursive watchdog (handle 0x%x)", handle);
- return (1);
- }
-
- XS_CMD_S_WDOG(xs);
- if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
- isp_intr(isp, isr, sema, mbox);
- }
- if (XS_CMD_DONE_P(xs)) {
- isp_prt(isp, ISP_LOGDEBUG2,
- "watchdog cleanup for handle 0x%x", handle);
- isp_free_pcmd(isp, (union ccb *)xs);
- xpt_done((union ccb *) xs);
- } else if (XS_CMD_GRACE_P(xs)) {
- /*
- * Make sure the command is *really* dead before we
- * release the handle (and DMA resources) for reuse.
- */
- (void) isp_control(isp, ISPCTL_ABORT_CMD, xs);
+ /*
+ * Make sure the command is *really* dead before we
+ * release the handle (and DMA resources) for reuse.
+ */
+ (void) isp_control(isp, ISPCTL_ABORT_CMD, xs);
- /*
- * After this point, the comamnd is really dead.
- */
- if (XS_XFRLEN(xs)) {
- ISP_DMAFREE(isp, xs, handle);
- }
- isp_destroy_handle(isp, handle);
- xpt_print(xs->ccb_h.path,
- "watchdog timeout for handle 0x%x\n", handle);
- XS_SETERR(xs, CAM_CMD_TIMEOUT);
- XS_CMD_C_WDOG(xs);
- isp_done(xs);
- } else {
- XS_CMD_C_WDOG(xs);
- callout_reset(&PISP_PCMD((union ccb *)xs)->wdog, hz,
- isp_watchdog, xs);
- XS_CMD_S_GRACE(xs);
- isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
- }
- return (1);
+ /*
+ * After this point, the comamnd is really dead.
+ */
+ if (XS_XFRLEN(xs)) {
+ ISP_DMAFREE(isp, xs, handle);
+ }
+ isp_destroy_handle(isp, handle);
+ xpt_print(xs->ccb_h.path, "watchdog timeout for handle 0x%x\n", handle);
+ XS_SETERR(xs, CAM_CMD_TIMEOUT);
+ isp_done(xs);
}
- return (0);
}
static void
-isp_watchdog(void *arg)
+isp_make_here(ispsoftc_t *isp, int chan, int tgt)
{
- ispsoftc_t *isp;
- XS_T *xs = arg;
- int r;
+ union ccb *ccb;
+ struct isp_fc *fc = ISP_FC_PC(isp, chan);
- for (r = 0, isp = isplist; r && isp; isp = isp->isp_osinfo.next) {
- ISP_LOCK(isp);
- r = isp_watchdog_work(isp, xs);
- ISP_UNLOCK(isp);
- }
- if (isp == NULL) {
- printf("isp_watchdog: nobody had %p active\n", arg);
+ if (isp_autoconfig == 0) {
+ return;
}
-}
-
-#if __FreeBSD_version >= 600000
-static void
-isp_make_here(ispsoftc_t *isp, int tgt)
-{
- union ccb *ccb;
/*
- * Allocate a CCB, create a wildcard path for this bus,
- * and schedule a rescan.
+ * Allocate a CCB, create a wildcard path for this bus/target and schedule a rescan.
*/
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) {
- isp_prt(isp, ISP_LOGWARN, "unable to alloc CCB for rescan");
+ isp_prt(isp, ISP_LOGWARN, "Chan %d unable to alloc CCB for rescan", chan);
return;
}
- if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
- cam_sim_path(isp->isp_sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(fc->sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
isp_prt(isp, ISP_LOGWARN, "unable to create path for rescan");
xpt_free_ccb(ccb);
return;
@@ -2040,20 +3866,19 @@ isp_make_here(ispsoftc_t *isp, int tgt)
}
static void
-isp_make_gone(ispsoftc_t *isp, int tgt)
+isp_make_gone(ispsoftc_t *isp, int chan, int tgt)
{
struct cam_path *tp;
- if (xpt_create_path(&tp, NULL, cam_sim_path(isp->isp_sim), tgt,
- CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
+ struct isp_fc *fc = ISP_FC_PC(isp, chan);
+
+ if (isp_autoconfig == 0) {
+ return;
+ }
+ if (xpt_create_path(&tp, NULL, cam_sim_path(fc->sim), tgt, CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
xpt_async(AC_LOST_DEVICE, tp, NULL);
xpt_free_path(tp);
}
}
-#else
-#define isp_make_here(isp, tgt) do { ; } while (0)
-#define isp_make_gone(isp, tgt) do { ; } while (0)
-#endif
-
/*
* Gone Device Timer Function- when we have decided that a device has gone
@@ -2068,19 +3893,20 @@ isp_make_gone(ispsoftc_t *isp, int tgt)
static void
isp_gdt(void *arg)
{
- ispsoftc_t *isp = arg;
+ struct isp_fc *fc = arg;
+ ispsoftc_t *isp = fc->isp;
+ int chan = fc - isp->isp_osinfo.pc.fc;
fcportdb_t *lp;
int dbidx, tgt, more_to_do = 0;
- ISP_LOCK(isp);
- isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
+ isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GDT timer expired", chan);
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
- lp = &FCPARAM(isp)->portdb[dbidx];
+ lp = &FCPARAM(isp, chan)->portdb[dbidx];
if (lp->state != FC_PORTDB_STATE_ZOMBIE) {
continue;
}
- if (lp->ini_map_idx == 0) {
+ if (lp->dev_map_idx == 0 || lp->target_mode) {
continue;
}
if (lp->new_reserved == 0) {
@@ -2091,23 +3917,20 @@ isp_gdt(void *arg)
more_to_do++;
continue;
}
- tgt = lp->ini_map_idx - 1;
- FCPARAM(isp)->isp_ini_map[tgt] = 0;
- lp->ini_map_idx = 0;
+ tgt = lp->dev_map_idx - 1;
+ FCPARAM(isp, chan)->isp_dev_map[tgt] = 0;
+ lp->dev_map_idx = 0;
lp->state = FC_PORTDB_STATE_NIL;
- isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
- "Gone Device Timeout");
- isp_make_gone(isp, tgt);
+ isp_prt(isp, ISP_LOGCONFIG, prom3, chan, lp->portid, tgt, "Gone Device Timeout");
+ isp_make_gone(isp, chan, tgt);
}
if (more_to_do) {
- isp->isp_osinfo.gdt_running = 1;
- callout_reset(&isp->isp_osinfo.gdt, hz, isp_gdt, isp);
+ fc->gdt_running = 1;
+ callout_reset(&fc->gdt, hz, isp_gdt, fc);
} else {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "stopping Gone Device Timer");
- isp->isp_osinfo.gdt_running = 0;
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d stopping Gone Device Timer", chan);
+ fc->gdt_running = 0;
}
- ISP_UNLOCK(isp);
}
/*
@@ -2122,24 +3945,24 @@ isp_gdt(void *arg)
static void
isp_ldt(void *arg)
{
- ispsoftc_t *isp = arg;
+ struct isp_fc *fc = arg;
+ ispsoftc_t *isp = fc->isp;
+ int chan = fc - isp->isp_osinfo.pc.fc;
fcportdb_t *lp;
int dbidx, tgt;
- ISP_LOCK(isp);
-
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d Loop Down Timer expired @ %lu", chan, (unsigned long) time_uptime);
/*
* Notify to the OS all targets who we now consider have departed.
*/
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
- lp = &FCPARAM(isp)->portdb[dbidx];
+ lp = &FCPARAM(isp, chan)->portdb[dbidx];
if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
continue;
}
- if (lp->ini_map_idx == 0) {
+ if (lp->dev_map_idx == 0 || lp->target_mode) {
continue;
}
@@ -2159,118 +3982,116 @@ isp_ldt(void *arg)
* will happen when loop comes back up.
*/
- tgt = lp->ini_map_idx - 1;
- FCPARAM(isp)->isp_ini_map[tgt] = 0;
- lp->ini_map_idx = 0;
- isp_prt(isp, ISP_LOGCONFIG, prom3, lp->portid, tgt,
- "Loop Down Timeout");
- isp_make_gone(isp, tgt);
+ tgt = lp->dev_map_idx - 1;
+ FCPARAM(isp, chan)->isp_dev_map[tgt] = 0;
+ lp->dev_map_idx = 0;
+ lp->state = FC_PORTDB_STATE_NIL;
+ isp_prt(isp, ISP_LOGCONFIG, prom3, chan, lp->portid, tgt, "Loop Down Timeout");
+ isp_make_gone(isp, chan, tgt);
}
/*
* The loop down timer has expired. Wake up the kthread
* to notice that fact (or make it false).
*/
- isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1;
- wakeup(ISP_KT_WCHAN(isp));
- ISP_UNLOCK(isp);
+ fc->loop_dead = 1;
+ fc->loop_down_time = fc->loop_down_limit+1;
+ wakeup(fc);
}
static void
isp_kthread(void *arg)
{
- ispsoftc_t *isp = arg;
+ struct isp_fc *fc = arg;
+ ispsoftc_t *isp = fc->isp;
+ int chan = fc - isp->isp_osinfo.pc.fc;
int slp = 0;
-#if __FreeBSD_version < 500000
- int s = splcam();
-#elif __FreeBSD_version < 700037
- mtx_lock(&Giant);
-#else
mtx_lock(&isp->isp_osinfo.lock);
-#endif
- /*
- * The first loop is for our usage where we have yet to have
- * gotten good fibre channel state.
- */
+
for (;;) {
int wasfrozen, lb, lim;
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "isp_kthread: checking FC state");
- isp->isp_osinfo.mbox_sleep_ok = 1;
- lb = isp_fc_runstate(isp, 250000);
- isp->isp_osinfo.mbox_sleep_ok = 0;
- if (lb) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d checking FC state", __func__, chan);
+ lb = isp_fc_runstate(isp, chan, 250000);
+
+ /*
+ * Our action is different based upon whether we're supporting
+ * Initiator mode or not. If we are, we might freeze the simq
+ * when loop is down and set all sorts of different delays to
+ * check again.
+ *
+ * If not, we simply just wait for loop to come up.
+ */
+ if (lb && (fc->role & ISP_ROLE_INITIATOR)) {
/*
* Increment loop down time by the last sleep interval
*/
- isp->isp_osinfo.loop_down_time += slp;
+ fc->loop_down_time += slp;
if (lb < 0) {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "kthread: FC loop not up (down count %d)",
- isp->isp_osinfo.loop_down_time);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC loop not up (down count %d)", __func__, chan, fc->loop_down_time);
} else {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "kthread: FC got to %d (down count %d)",
- lb, isp->isp_osinfo.loop_down_time);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC got to %d (down count %d)", __func__, chan, lb, fc->loop_down_time);
}
-
/*
* If we've never seen loop up and we've waited longer
* than quickboot time, or we've seen loop up but we've
* waited longer than loop_down_limit, give up and go
* to sleep until loop comes up.
*/
- if (FCPARAM(isp)->loop_seen_once == 0) {
+ if (FCPARAM(isp, chan)->loop_seen_once == 0) {
lim = isp_quickboot_time;
} else {
- lim = isp->isp_osinfo.loop_down_limit;
+ lim = fc->loop_down_limit;
}
- if (isp->isp_osinfo.loop_down_time >= lim) {
- isp_freeze_loopdown(isp, "loop limit hit");
+ if (fc->loop_down_time >= lim) {
+ isp_freeze_loopdown(isp, chan, "loop limit hit");
slp = 0;
- } else if (isp->isp_osinfo.loop_down_time < 10) {
+ } else if (fc->loop_down_time < 10) {
slp = 1;
- } else if (isp->isp_osinfo.loop_down_time < 30) {
+ } else if (fc->loop_down_time < 30) {
slp = 5;
- } else if (isp->isp_osinfo.loop_down_time < 60) {
+ } else if (fc->loop_down_time < 60) {
slp = 10;
- } else if (isp->isp_osinfo.loop_down_time < 120) {
+ } else if (fc->loop_down_time < 120) {
slp = 20;
} else {
slp = 30;
}
+ } else if (lb) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC Loop Down", __func__, chan);
+ fc->loop_down_time += slp;
+ slp = 60;
} else {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "isp_kthread: FC state OK");
- isp->isp_osinfo.loop_down_time = 0;
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC state OK", __func__, chan);
+ fc->loop_down_time = 0;
slp = 0;
}
+
/*
- * If we'd frozen the simq, unfreeze it now so that CAM
- * can start sending us commands. If the FC state isn't
- * okay yet, they'll hit that in isp_start which will
- * freeze the queue again.
+ * If this is past the first loop up or the loop is dead and if we'd frozen the simq, unfreeze it
+ * now so that CAM can start sending us commands.
+ *
+ * If the FC state isn't okay yet, they'll hit that in isp_start which will freeze the queue again
+ * or kill the commands, as appropriate.
*/
- wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
- isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
- if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "isp_kthread: releasing simq");
- xpt_release_simq(isp->isp_sim, 1);
- }
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "isp_kthread: sleep time %d", slp);
-#if __FreeBSD_version < 700037
- tsleep(ISP_KT_WCHAN(isp), PRIBIO, "ispf", slp * hz);
-#else
- msleep(ISP_KT_WCHAN(isp), &isp->isp_osinfo.lock,
- PRIBIO, "ispf", slp * hz);
-#endif
+
+ if (FCPARAM(isp, chan)->loop_seen_once || fc->loop_dead) {
+ wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN;
+ fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN;
+ if (wasfrozen && fc->simqfrozen == 0) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d releasing simq", __func__, chan);
+ xpt_release_simq(fc->sim, 1);
+ }
+ }
+
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep time %d", __func__, chan, slp);
+
+ msleep(fc, &isp->isp_osinfo.lock, PRIBIO, "ispf", slp * hz);
+
/*
* If slp is zero, we're waking up for the first time after
* things have been okay. In this case, we set a deferral state
@@ -2278,41 +4099,13 @@ isp_kthread(void *arg)
* the FC state evaluation. This gives the loop/fabric a chance
* to settle.
*/
- if (slp == 0 && isp->isp_osinfo.hysteresis) {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "isp_kthread: sleep hysteresis tick time %d",
- isp->isp_osinfo.hysteresis * hz);
-#if __FreeBSD_version < 700037
- (void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
- (isp->isp_osinfo.hysteresis * hz));
-#else
- (void) msleep(&isp_fabric_hysteresis,
- &isp->isp_osinfo.lock, PRIBIO, "ispT",
- (isp->isp_osinfo.hysteresis * hz));
-#endif
+ if (slp == 0 && fc->hysteresis) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep hysteresis ticks %d", __func__, chan, fc->hysteresis * hz);
+ (void) msleep(&isp_fabric_hysteresis, &isp->isp_osinfo.lock, PRIBIO, "ispT", (fc->hysteresis * hz));
}
}
-#if __FreeBSD_version < 500000
- splx(s);
-#elif __FreeBSD_version < 700037
- mtx_unlock(&Giant);
-#else
mtx_unlock(&isp->isp_osinfo.lock);
-#endif
-}
-
-#if __FreeBSD_version < 500000
-static void isp_action_wrk(struct cam_sim *, union ccb *);
-static void
-isp_action(struct cam_sim *sim, union ccb *ccb)
-{
- ispsoftc_t *isp = (ispsoftc_t *)cam_sim_softc(sim);
- ISP_LOCK(isp);
- isp_action_wrk(sim, ccb);
- ISP_UNLOCK(isp);
}
-#define isp_action isp_action_wrk
-#endif
static void
isp_action(struct cam_sim *sim, union ccb *ccb)
@@ -2324,8 +4117,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
isp = (ispsoftc_t *)cam_sim_softc(sim);
- if (isp->isp_state != ISP_RUNSTATE &&
- ccb->ccb_h.func_code == XPT_SCSI_IO) {
+ mtx_assert(&isp->isp_lock, MA_OWNED);
+
+ if (isp->isp_state != ISP_RUNSTATE && ccb->ccb_h.func_code == XPT_SCSI_IO) {
isp_init(isp);
if (isp->isp_state != ISP_INITSTATE) {
/*
@@ -2343,6 +4137,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
switch (ccb->ccb_h.func_code) {
case XPT_SCSI_IO: /* Execute the requested I/O operation */
+ bus = XS_CHANNEL(ccb);
/*
* Do a couple of preliminary checks...
*/
@@ -2370,8 +4165,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
if (isp_get_pcmd(isp, ccb)) {
isp_prt(isp, ISP_LOGWARN, "out of PCMDs");
cam_freeze_devq(ccb->ccb_h.path);
- cam_release_devq(ccb->ccb_h.path,
- RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
+ cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
xpt_done(ccb);
break;
}
@@ -2388,54 +4182,48 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
ts = 60*1000;
}
ts = isp_mstohz(ts);
- callout_reset(&PISP_PCMD(ccb)->wdog, ts,
- isp_watchdog, ccb);
+ callout_reset(&PISP_PCMD(ccb)->wdog, ts, isp_watchdog, ccb);
break;
case CMD_RQLATER:
/*
- * Handle initial and subsequent loop down cases
+ * We get this result for FC devices if the loop state isn't ready yet
+ * or if the device in question has gone zombie on us.
+ *
+ * If we've never seen Loop UP at all, we requeue this request and wait
+ * for the initial loop up delay to expire.
*/
- if (FCPARAM(isp)->loop_seen_once == 0) {
- lim = isp_quickboot_time;
- } else {
- lim = isp->isp_osinfo.loop_down_limit;
- }
- if (isp->isp_osinfo.loop_down_time >= lim) {
- isp_prt(isp, ISP_LOGDEBUG0,
- "%d.%d downtime (%d) > lim (%d)",
- XS_TGT(ccb), XS_LUN(ccb),
- isp->isp_osinfo.loop_down_time, lim);
- ccb->ccb_h.status =
- CAM_SEL_TIMEOUT|CAM_DEV_QFRZN;
+ lim = ISP_FC_PC(isp, bus)->loop_down_limit;
+ if (FCPARAM(isp, bus)->loop_seen_once == 0 || ISP_FC_PC(isp, bus)->loop_down_time >= lim) {
+ if (FCPARAM(isp, bus)->loop_seen_once == 0) {
+ isp_prt(isp, ISP_LOGDEBUG0, "%d.%d loop not seen yet @ %lu", XS_TGT(ccb), XS_LUN(ccb), (unsigned long) time_uptime);
+ } else {
+ isp_prt(isp, ISP_LOGDEBUG0, "%d.%d downtime (%d) > lim (%d)", XS_TGT(ccb), XS_LUN(ccb), ISP_FC_PC(isp, bus)->loop_down_time, lim);
+ }
+ ccb->ccb_h.status = CAM_SEL_TIMEOUT|CAM_DEV_QFRZN;
xpt_freeze_devq(ccb->ccb_h.path, 1);
isp_free_pcmd(isp, ccb);
xpt_done(ccb);
break;
}
- isp_prt(isp, ISP_LOGDEBUG0,
- "%d.%d retry later", XS_TGT(ccb), XS_LUN(ccb));
- /*
- * Otherwise, retry in a while.
- */
+ isp_prt(isp, ISP_LOGDEBUG0, "%d.%d retry later", XS_TGT(ccb), XS_LUN(ccb));
cam_freeze_devq(ccb->ccb_h.path);
- cam_release_devq(ccb->ccb_h.path,
- RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
+ cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
XS_SETERR(ccb, CAM_REQUEUE_REQ);
isp_free_pcmd(isp, ccb);
xpt_done(ccb);
break;
case CMD_EAGAIN:
- XS_SETERR(ccb, CAM_REQUEUE_REQ);
isp_free_pcmd(isp, ccb);
+ cam_freeze_devq(ccb->ccb_h.path);
+ cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 100, 0);
+ XS_SETERR(ccb, CAM_REQUEUE_REQ);
xpt_done(ccb);
break;
case CMD_COMPLETE:
isp_done((struct ccb_scsiio *) ccb);
break;
default:
- isp_prt(isp, ISP_LOGERR,
- "What's this? 0x%x at %d in file %s",
- error, __LINE__, __FILE__);
+ isp_prt(isp, ISP_LOGERR, "What's this? 0x%x at %d in file %s", error, __LINE__, __FILE__);
XS_SETERR(ccb, CAM_REQ_CMP_ERR);
isp_free_pcmd(isp, ccb);
xpt_done(ccb);
@@ -2443,33 +4231,34 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
break;
#ifdef ISP_TARGET_MODE
- case XPT_EN_LUN: /* Enable LUN as a target */
- {
- int seq, i;
- seq = isp_en_lun(isp, ccb);
- if (seq < 0) {
- xpt_done(ccb);
- break;
- }
- for (i = 0; isp->isp_osinfo.leact[seq] && i < 30 * 1000; i++) {
- uint32_t isr;
- uint16_t sema, mbox;
- if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
- isp_intr(isp, isr, sema, mbox);
- }
- DELAY(1000);
+ case XPT_EN_LUN: /* Enable/Disable LUN as a target */
+ if (ccb->cel.enable) {
+ isp_enable_lun(isp, ccb);
+ } else {
+ isp_disable_lun(isp, ccb);
}
break;
- }
- case XPT_NOTIFY_ACK: /* recycle notify ack */
- case XPT_IMMED_NOTIFY: /* Add Immediate Notify Resource */
+ case XPT_IMMEDIATE_NOTIFY: /* Add Immediate Notify Resource */
case XPT_ACCEPT_TARGET_IO: /* Add Accept Target IO Resource */
{
- tstate_t *tptr =
- get_lun_statep(isp, XS_CHANNEL(ccb), ccb->ccb_h.target_lun);
+ tstate_t *tptr = get_lun_statep(isp, XS_CHANNEL(ccb), ccb->ccb_h.target_lun);
if (tptr == NULL) {
- ccb->ccb_h.status = CAM_LUN_INVALID;
- xpt_done(ccb);
+ tptr = get_lun_statep(isp, XS_CHANNEL(ccb), CAM_LUN_WILDCARD);
+ }
+ if (tptr == NULL) {
+ const char *str;
+ uint32_t tag;
+
+ if (ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) {
+ str = "XPT_IMMEDIATE_NOTIFY";
+ tag = ccb->cin1.seq_id;
+ } else {
+ tag = ccb->atio.tag_id;
+ str = "XPT_ACCEPT_TARGET_IO";
+ }
+ ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "%s: [0x%x] no state pointer found for %s\n", __func__, tag, str);
+ dump_tstates(isp, XS_CHANNEL(ccb));
+ ccb->ccb_h.status = CAM_DEV_NOT_THERE;
break;
}
ccb->ccb_h.sim_priv.entries[0].field = 0;
@@ -2477,35 +4266,70 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.flags = 0;
if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
- /*
- * Note that the command itself may not be done-
- * it may not even have had the first CTIO sent.
- */
+ if (ccb->atio.tag_id) {
+ atio_private_data_t *atp = isp_get_atpd(isp, tptr, ccb->atio.tag_id);
+ if (atp) {
+ isp_put_atpd(isp, tptr, atp);
+ }
+ }
tptr->atio_count++;
- isp_prt(isp, ISP_LOGTDEBUG0,
- "Put FREE ATIO, lun %d, count now %d",
- ccb->ccb_h.target_lun, tptr->atio_count);
- SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h,
- sim_links.sle);
- } else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
+ SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h, sim_links.sle);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "Put FREE ATIO (tag id 0x%x), count now %d\n",
+ ((struct ccb_accept_tio *)ccb)->tag_id, tptr->atio_count);
+ } else if (ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) {
+ if (ccb->cin1.tag_id) {
+ inot_private_data_t *ntp = isp_find_ntpd(isp, tptr, ccb->cin1.tag_id, ccb->cin1.seq_id);
+ if (ntp) {
+ isp_put_ntpd(isp, tptr, ntp);
+ }
+ }
tptr->inot_count++;
- isp_prt(isp, ISP_LOGTDEBUG0,
- "Put FREE INOT, lun %d, count now %d",
- ccb->ccb_h.target_lun, tptr->inot_count);
- SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h,
- sim_links.sle);
- } else {
- isp_prt(isp, ISP_LOGWARN, "Got Notify ACK");;
+ SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h, sim_links.sle);
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "Put FREE INOT, (seq id 0x%x) count now %d\n",
+ ((struct ccb_immediate_notify *)ccb)->seq_id, tptr->inot_count);
}
rls_lun_statep(isp, tptr);
ccb->ccb_h.status = CAM_REQ_INPROG;
break;
}
- case XPT_CONT_TARGET_IO:
+ case XPT_NOTIFY_ACKNOWLEDGE: /* notify ack */
{
- isp_target_start_ctio(isp, ccb);
+ tstate_t *tptr;
+ inot_private_data_t *ntp;
+
+ /*
+ * XXX: Because we cannot guarantee that the path information in the notify acknowledge ccb
+ * XXX: matches that for the immediate notify, we have to *search* for the notify structure
+ */
+ /*
+ * All the relevant path information is in the associated immediate notify
+ */
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "%s: [0x%x] NOTIFY ACKNOWLEDGE for 0x%x seen\n", __func__, ccb->cna2.tag_id, ccb->cna2.seq_id);
+ ntp = get_ntp_from_tagdata(isp, ccb->cna2.tag_id, ccb->cna2.seq_id, &tptr);
+ if (ntp == NULL) {
+ ISP_PATH_PRT(isp, ISP_LOGWARN, ccb->ccb_h.path, "%s: [0x%x] XPT_NOTIFY_ACKNOWLEDGE of 0x%x cannot find ntp private data\n", __func__,
+ ccb->cna2.tag_id, ccb->cna2.seq_id);
+ ccb->ccb_h.status = CAM_DEV_NOT_THERE;
+ xpt_done(ccb);
+ break;
+ }
+ if (isp_handle_platform_target_notify_ack(isp, &ntp->rd.nt)) {
+ rls_lun_statep(isp, tptr);
+ cam_freeze_devq(ccb->ccb_h.path);
+ cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
+ XS_SETERR(ccb, CAM_REQUEUE_REQ);
+ break;
+ }
+ isp_put_ntpd(isp, tptr, ntp);
+ rls_lun_statep(isp, tptr);
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ ISP_PATH_PRT(isp, ISP_LOGTDEBUG0, ccb->ccb_h.path, "%s: [0x%x] calling xpt_done for tag 0x%x\n", __func__, ccb->cna2.tag_id, ccb->cna2.seq_id);
+ xpt_done(ccb);
break;
}
+ case XPT_CONT_TARGET_IO:
+ isp_target_start_ctio(isp, ccb);
+ break;
#endif
case XPT_RESET_DEV: /* BDR the specified SCSI device */
@@ -2513,7 +4337,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
tgt = ccb->ccb_h.target_id;
tgt |= (bus << 16);
- error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
+ error = isp_control(isp, ISPCTL_RESET_DEV, bus, tgt);
if (error) {
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
} else {
@@ -2527,12 +4351,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
switch (accb->ccb_h.func_code) {
#ifdef ISP_TARGET_MODE
case XPT_ACCEPT_TARGET_IO:
- case XPT_IMMED_NOTIFY:
- ccb->ccb_h.status = isp_abort_tgt_ccb(isp, ccb);
- break;
- case XPT_CONT_TARGET_IO:
- isp_prt(isp, ISP_LOGERR, "cannot abort CTIOs yet");
- ccb->ccb_h.status = CAM_UA_ABORT;
+ isp_target_mark_aborted(isp, accb);
break;
#endif
case XPT_SCSI_IO:
@@ -2550,11 +4369,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
xpt_done(ccb);
break;
}
-#ifdef CAM_NEW_TRAN_CODE
#define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS)
-#else
-#define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS)
-#endif
case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */
cts = &ccb->cts;
if (!IS_CURRENT_SETTINGS(cts)) {
@@ -2563,72 +4378,11 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
break;
}
tgt = cts->ccb_h.target_id;
+ bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
if (IS_SCSI(isp)) {
-#ifndef CAM_NEW_TRAN_CODE
- sdparam *sdp = isp->isp_param;
- uint16_t *dptr;
-
- bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
-
- sdp += bus;
- /*
- * We always update (internally) from goal_flags
- * so any request to change settings just gets
- * vectored to that location.
- */
- dptr = &sdp->isp_devparam[tgt].goal_flags;
-
- /*
- * Note that these operations affect the
- * the goal flags (goal_flags)- not
- * the current state flags. Then we mark
- * things so that the next operation to
- * this HBA will cause the update to occur.
- */
- if (cts->valid & CCB_TRANS_DISC_VALID) {
- if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) {
- *dptr |= DPARM_DISC;
- } else {
- *dptr &= ~DPARM_DISC;
- }
- }
- if (cts->valid & CCB_TRANS_TQ_VALID) {
- if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) {
- *dptr |= DPARM_TQING;
- } else {
- *dptr &= ~DPARM_TQING;
- }
- }
- if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) {
- switch (cts->bus_width) {
- case MSG_EXT_WDTR_BUS_16_BIT:
- *dptr |= DPARM_WIDE;
- break;
- default:
- *dptr &= ~DPARM_WIDE;
- }
- }
- /*
- * Any SYNC RATE of nonzero and SYNC_OFFSET
- * of nonzero will cause us to go to the
- * selected (from NVRAM) maximum value for
- * this device. At a later point, we'll
- * allow finer control.
- */
- if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) &&
- (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) &&
- (cts->sync_offset > 0)) {
- *dptr |= DPARM_SYNC;
- } else {
- *dptr &= ~DPARM_SYNC;
- }
- *dptr |= DPARM_SAFE_DFLT;
-#else
- struct ccb_trans_settings_scsi *scsi =
- &cts->proto_specific.scsi;
- struct ccb_trans_settings_spi *spi =
- &cts->xport_specific.spi;
- sdparam *sdp = isp->isp_param;
+ struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
+ struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi;
+ sdparam *sdp = SDPARAM(isp, bus);
uint16_t *dptr;
if (spi->valid == 0 && scsi->valid == 0) {
@@ -2636,9 +4390,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
xpt_done(ccb);
break;
}
-
- bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
- sdp += bus;
+
/*
* We always update (internally) from goal_flags
* so any request to change settings just gets
@@ -2670,29 +4422,20 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
/*
* XXX: FIX ME
*/
- if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) &&
- (spi->valid & CTS_SPI_VALID_SYNC_RATE) &&
- (spi->sync_period && spi->sync_offset)) {
+ if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) && (spi->valid & CTS_SPI_VALID_SYNC_RATE) && (spi->sync_period && spi->sync_offset)) {
*dptr |= DPARM_SYNC;
/*
* XXX: CHECK FOR LEGALITY
*/
- sdp->isp_devparam[tgt].goal_period =
- spi->sync_period;
- sdp->isp_devparam[tgt].goal_offset =
- spi->sync_offset;
+ sdp->isp_devparam[tgt].goal_period = spi->sync_period;
+ sdp->isp_devparam[tgt].goal_offset = spi->sync_offset;
} else {
*dptr &= ~DPARM_SYNC;
}
-#endif
- isp_prt(isp, ISP_LOGDEBUG0,
- "SET (%d.%d.%d) to flags %x off %x per %x",
- bus, tgt, cts->ccb_h.target_lun,
- sdp->isp_devparam[tgt].goal_flags,
- sdp->isp_devparam[tgt].goal_offset,
- sdp->isp_devparam[tgt].goal_period);
+ isp_prt(isp, ISP_LOGDEBUG0, "SET (%d.%d.%d) to flags %x off %x per %x", bus, tgt, cts->ccb_h.target_lun, sdp->isp_devparam[tgt].goal_flags,
+ sdp->isp_devparam[tgt].goal_offset, sdp->isp_devparam[tgt].goal_period);
sdp->isp_devparam[tgt].dev_update = 1;
- isp->isp_update |= (1 << bus);
+ sdp->update = 1;
}
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
@@ -2700,27 +4443,11 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
case XPT_GET_TRAN_SETTINGS:
cts = &ccb->cts;
tgt = cts->ccb_h.target_id;
+ bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
if (IS_FC(isp)) {
-#ifndef CAM_NEW_TRAN_CODE
- /*
- * a lot of normal SCSI things don't make sense.
- */
- cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB;
- cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
- /*
- * How do you measure the width of a high
- * speed serial bus? Well, in bytes.
- *
- * Offset and period make no sense, though, so we set
- * (above) a 'base' transfer speed to be gigabit.
- */
- cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
-#else
- fcparam *fcp = isp->isp_param;
- struct ccb_trans_settings_scsi *scsi =
- &cts->proto_specific.scsi;
- struct ccb_trans_settings_fc *fc =
- &cts->xport_specific.fc;
+ fcparam *fcp = FCPARAM(isp, bus);
+ struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
+ struct ccb_trans_settings_fc *fc = &cts->xport_specific.fc;
cts->protocol = PROTO_SCSI;
cts->protocol_version = SCSI_REV_2;
@@ -2731,35 +4458,24 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
fc->valid = CTS_FC_VALID_SPEED;
fc->bitrate = 100000;
- if (fcp->isp_gbspeed == 4 || fcp->isp_gbspeed == 2)
- fc->bitrate *= fcp->isp_gbspeed;
+ fc->bitrate *= fcp->isp_gbspeed;
if (tgt > 0 && tgt < MAX_FC_TARG) {
fcportdb_t *lp = &fcp->portdb[tgt];
fc->wwnn = lp->node_wwn;
fc->wwpn = lp->port_wwn;
fc->port = lp->portid;
- fc->valid |= CTS_FC_VALID_WWNN |
- CTS_FC_VALID_WWPN | CTS_FC_VALID_PORT;
+ fc->valid |= CTS_FC_VALID_WWNN | CTS_FC_VALID_WWPN | CTS_FC_VALID_PORT;
}
-#endif
} else {
-#ifdef CAM_NEW_TRAN_CODE
- struct ccb_trans_settings_scsi *scsi =
- &cts->proto_specific.scsi;
- struct ccb_trans_settings_spi *spi =
- &cts->xport_specific.spi;
-#endif
- sdparam *sdp = isp->isp_param;
- int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
+ struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
+ struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi;
+ sdparam *sdp = SDPARAM(isp, bus);
uint16_t dval, pval, oval;
- sdp += bus;
-
if (IS_CURRENT_SETTINGS(cts)) {
sdp->isp_devparam[tgt].dev_refresh = 1;
- isp->isp_update |= (1 << bus);
- (void) isp_control(isp, ISPCTL_UPDATE_PARAMS,
- NULL);
+ sdp->update = 1;
+ (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, bus);
dval = sdp->isp_devparam[tgt].actv_flags;
oval = sdp->isp_devparam[tgt].actv_offset;
pval = sdp->isp_devparam[tgt].actv_period;
@@ -2769,31 +4485,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
pval = sdp->isp_devparam[tgt].nvrm_period;
}
-#ifndef CAM_NEW_TRAN_CODE
- cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
-
- if (dval & DPARM_DISC) {
- cts->flags |= CCB_TRANS_DISC_ENB;
- }
- if (dval & DPARM_TQING) {
- cts->flags |= CCB_TRANS_TAG_ENB;
- }
- if (dval & DPARM_WIDE) {
- cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
- } else {
- cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
- }
- cts->valid = CCB_TRANS_BUS_WIDTH_VALID |
- CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
-
- if ((dval & DPARM_SYNC) && oval != 0) {
- cts->sync_period = pval;
- cts->sync_offset = oval;
- cts->valid |=
- CCB_TRANS_SYNC_RATE_VALID |
- CCB_TRANS_SYNC_OFFSET_VALID;
- }
-#else
cts->protocol = PROTO_SCSI;
cts->protocol_version = SCSI_REV_2;
cts->transport = XPORT_SPI;
@@ -2828,10 +4519,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
}
spi->valid |= CTS_SPI_VALID_DISC;
}
-#endif
- isp_prt(isp, ISP_LOGDEBUG0,
- "GET %s (%d.%d.%d) to flags %x off %x per %x",
- IS_CURRENT_SETTINGS(cts)? "ACTIVE" : "NVRAM",
+ isp_prt(isp, ISP_LOGDEBUG0, "GET %s (%d.%d.%d) to flags %x off %x per %x", IS_CURRENT_SETTINGS(cts)? "ACTIVE" : "NVRAM",
bus, tgt, cts->ccb_h.target_lun, dval, oval, pval);
}
ccb->ccb_h.status = CAM_REQ_CMP;
@@ -2839,62 +4527,133 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
break;
case XPT_CALC_GEOMETRY:
-#if __FreeBSD_version < 500000
- {
- struct ccb_calc_geometry *ccg;
- u_int32_t secs_per_cylinder;
- u_int32_t size_mb;
+ cam_calc_geometry(&ccb->ccg, 1);
+ xpt_done(ccb);
+ break;
- ccg = &ccb->ccg;
- if (ccg->block_size == 0) {
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ case XPT_RESET_BUS: /* Reset the specified bus */
+ bus = cam_sim_bus(sim);
+ error = isp_control(isp, ISPCTL_RESET_BUS, bus);
+ if (error) {
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
xpt_done(ccb);
break;
}
- size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size);
- if (size_mb > 1024) {
- ccg->heads = 255;
- ccg->secs_per_track = 63;
+ if (bootverbose) {
+ xpt_print(ccb->ccb_h.path, "reset bus on channel %d\n", bus);
+ }
+ if (IS_FC(isp)) {
+ xpt_async(AC_BUS_RESET, ISP_FC_PC(isp, bus)->path, 0);
} else {
- ccg->heads = 64;
- ccg->secs_per_track = 32;
+ xpt_async(AC_BUS_RESET, ISP_SPI_PC(isp, bus)->path, 0);
}
- secs_per_cylinder = ccg->heads * ccg->secs_per_track;
- ccg->cylinders = ccg->volume_size / secs_per_cylinder;
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
- }
-#else
- {
- cam_calc_geometry(&ccb->ccg, /*extended*/1);
+
+ case XPT_TERM_IO: /* Terminate the I/O process */
+ ccb->ccb_h.status = CAM_REQ_INVALID;
xpt_done(ccb);
break;
- }
+
+ case XPT_SET_SIM_KNOB: /* Set SIM knobs */
+ {
+ struct ccb_sim_knob *kp = &ccb->knob;
+ fcparam *fcp;
+
+
+ if (!IS_FC(isp)) {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ break;
+ }
+
+ bus = cam_sim_bus(xpt_path_sim(kp->ccb_h.path));
+ fcp = FCPARAM(isp, bus);
+
+ if (kp->xport_specific.fc.valid & KNOB_VALID_ADDRESS) {
+ fcp->isp_wwnn = ISP_FC_PC(isp, bus)->def_wwnn = kp->xport_specific.fc.wwnn;
+ fcp->isp_wwpn = ISP_FC_PC(isp, bus)->def_wwpn = kp->xport_specific.fc.wwpn;
+isp_prt(isp, ISP_LOGALL, "Setting Channel %d wwns to 0x%jx 0x%jx", bus, fcp->isp_wwnn, fcp->isp_wwpn);
+ }
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ if (kp->xport_specific.fc.valid & KNOB_VALID_ROLE) {
+ int rchange = 0;
+ int newrole = 0;
+
+ switch (kp->xport_specific.fc.role) {
+ case KNOB_ROLE_NONE:
+ if (fcp->role != ISP_ROLE_NONE) {
+ rchange = 1;
+ newrole = ISP_ROLE_NONE;
+ }
+ break;
+ case KNOB_ROLE_TARGET:
+ if (fcp->role != ISP_ROLE_TARGET) {
+ rchange = 1;
+ newrole = ISP_ROLE_TARGET;
+ }
+ break;
+ case KNOB_ROLE_INITIATOR:
+ if (fcp->role != ISP_ROLE_INITIATOR) {
+ rchange = 1;
+ newrole = ISP_ROLE_INITIATOR;
+ }
+ break;
+ case KNOB_ROLE_BOTH:
+ if (fcp->role != ISP_ROLE_BOTH) {
+ rchange = 1;
+ newrole = ISP_ROLE_BOTH;
+ }
+ break;
+ }
+ if (rchange) {
+ if (isp_fc_change_role(isp, bus, newrole) != 0) {
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+#ifdef ISP_TARGET_MODE
+ } else if (newrole == ISP_ROLE_TARGET || newrole == ISP_ROLE_BOTH) {
+ isp_enable_deferred_luns(isp, bus);
#endif
- case XPT_RESET_BUS: /* Reset the specified bus */
- bus = cam_sim_bus(sim);
- error = isp_control(isp, ISPCTL_RESET_BUS, &bus);
- if (error)
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
- else {
- if (bootverbose) {
- xpt_print(ccb->ccb_h.path, "reset bus\n");
- }
- if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
- xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
- else if (isp->isp_path != NULL)
- xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
- ccb->ccb_h.status = CAM_REQ_CMP;
+ }
+ }
}
xpt_done(ccb);
break;
+ }
+ case XPT_GET_SIM_KNOB: /* Set SIM knobs */
+ {
+ struct ccb_sim_knob *kp = &ccb->knob;
- case XPT_TERM_IO: /* Terminate the I/O process */
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ if (IS_FC(isp)) {
+ fcparam *fcp;
+
+ bus = cam_sim_bus(xpt_path_sim(kp->ccb_h.path));
+ fcp = FCPARAM(isp, bus);
+
+ kp->xport_specific.fc.wwnn = fcp->isp_wwnn;
+ kp->xport_specific.fc.wwpn = fcp->isp_wwpn;
+ switch (fcp->role) {
+ case ISP_ROLE_NONE:
+ kp->xport_specific.fc.role = KNOB_ROLE_NONE;
+ break;
+ case ISP_ROLE_TARGET:
+ kp->xport_specific.fc.role = KNOB_ROLE_TARGET;
+ break;
+ case ISP_ROLE_INITIATOR:
+ kp->xport_specific.fc.role = KNOB_ROLE_INITIATOR;
+ break;
+ case ISP_ROLE_BOTH:
+ kp->xport_specific.fc.role = KNOB_ROLE_BOTH;
+ break;
+ }
+ kp->xport_specific.fc.valid = KNOB_VALID_ADDRESS | KNOB_VALID_ROLE;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ } else {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ }
xpt_done(ccb);
break;
-
+ }
case XPT_PATH_INQ: /* Path routing inquiry */
{
struct ccb_pathinq *cpi = &ccb->cpi;
@@ -2909,8 +4668,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
cpi->max_target = ISP_MAX_TARGETS(isp) - 1;
cpi->max_lun = ISP_MAX_LUNS(isp) - 1;
cpi->bus_id = cam_sim_bus(sim);
+ bus = cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
if (IS_FC(isp)) {
+ fcparam *fcp = FCPARAM(isp, bus);
+
cpi->hba_misc = PIM_NOBUSRESET;
+
/*
* Because our loop ID can shift from time to time,
* make our initiator ID out of range of our bus.
@@ -2918,37 +4681,33 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
cpi->initiator_id = cpi->max_target + 1;
/*
- * Set base transfer capabilities for Fibre Channel.
- * Technically not correct because we don't know
- * what media we're running on top of- but we'll
- * look good if we always say 100MB/s.
+ * Set base transfer capabilities for Fibre Channel, for this HBA.
*/
- cpi->base_transfer_speed = 100000;
- if (FCPARAM(isp)->isp_gbspeed == 4 ||
- FCPARAM(isp)->isp_gbspeed == 2)
- cpi->base_transfer_speed *=
- FCPARAM(isp)->isp_gbspeed;
+ if (IS_24XX(isp)) {
+ cpi->base_transfer_speed = 4000000;
+ } else if (IS_23XX(isp)) {
+ cpi->base_transfer_speed = 2000000;
+ } else {
+ cpi->base_transfer_speed = 1000000;
+ }
cpi->hba_inquiry = PI_TAG_ABLE;
-#ifdef CAM_NEW_TRAN_CODE
cpi->transport = XPORT_FC;
cpi->transport_version = 0;
-#endif
+ cpi->xport_specific.fc.wwnn = fcp->isp_wwnn;
+ cpi->xport_specific.fc.wwpn = fcp->isp_wwpn;
+ cpi->xport_specific.fc.port = fcp->isp_portid;
+ cpi->xport_specific.fc.bitrate = fcp->isp_gbspeed * 1000;
} else {
- sdparam *sdp = isp->isp_param;
- sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
+ sdparam *sdp = SDPARAM(isp, bus);
cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
cpi->hba_misc = 0;
cpi->initiator_id = sdp->isp_initiator_id;
cpi->base_transfer_speed = 3300;
-#ifdef CAM_NEW_TRAN_CODE
cpi->transport = XPORT_SPI;
cpi->transport_version = 2;
-#endif
}
-#ifdef CAM_NEW_TRAN_CODE
cpi->protocol = PROTO_SCSI;
cpi->protocol_version = SCSI_REV_2;
-#endif
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
@@ -2967,18 +4726,16 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
#define ISPDDB (CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB)
void
-isp_done(struct ccb_scsiio *sccb)
+isp_done(XS_T *sccb)
{
ispsoftc_t *isp = XS_ISP(sccb);
if (XS_NOERR(sccb))
XS_SETERR(sccb, CAM_REQ_CMP);
- if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
- (sccb->scsi_status != SCSI_STATUS_OK)) {
+ if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP && (sccb->scsi_status != SCSI_STATUS_OK)) {
sccb->ccb_h.status &= ~CAM_STATUS_MASK;
- if ((sccb->scsi_status == SCSI_STATUS_CHECK_COND) &&
- (sccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0) {
+ if ((sccb->scsi_status == SCSI_STATUS_CHECK_COND) && (sccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0) {
sccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
} else {
sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
@@ -2987,78 +4744,58 @@ isp_done(struct ccb_scsiio *sccb)
sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- isp_prt(isp, ISP_LOGDEBUG0,
- "target %d lun %d CAM status 0x%x SCSI status 0x%x",
- XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status,
- sccb->scsi_status);
+ isp_prt(isp, ISP_LOGDEBUG0, "target %d lun %d CAM status 0x%x SCSI status 0x%x", XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status, sccb->scsi_status);
if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
sccb->ccb_h.status |= CAM_DEV_QFRZN;
xpt_freeze_devq(sccb->ccb_h.path, 1);
}
}
- if ((CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB)) &&
- (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- xpt_print(sccb->ccb_h.path,
- "cam completion status 0x%x\n", sccb->ccb_h.status);
+ if ((CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB)) && (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ xpt_print(sccb->ccb_h.path, "cam completion status 0x%x\n", sccb->ccb_h.status);
}
XS_CMD_S_DONE(sccb);
- if (XS_CMD_WDOG_P(sccb) == 0) {
- callout_stop(&PISP_PCMD(sccb)->wdog);
- if (XS_CMD_GRACE_P(sccb)) {
- isp_prt(isp, ISP_LOGDEBUG2,
- "finished command on borrowed time");
- }
- XS_CMD_S_CLEAR(sccb);
- isp_free_pcmd(isp, (union ccb *) sccb);
- xpt_done((union ccb *) sccb);
- }
+ callout_stop(&PISP_PCMD(sccb)->wdog);
+ XS_CMD_S_CLEAR(sccb);
+ isp_free_pcmd(isp, (union ccb *) sccb);
+ xpt_done((union ccb *) sccb);
}
-int
-isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
-{
- int bus, rv = 0;
- static const char prom[] =
- "PortID 0x%06x handle 0x%x role %s %s\n"
- " WWNN 0x%08x%08x WWPN 0x%08x%08x";
- static const char prom2[] =
- "PortID 0x%06x handle 0x%x role %s %s tgt %u\n"
- " WWNN 0x%08x%08x WWPN 0x%08x%08x";
+void
+isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
+{
+ int bus;
+ static const char prom[] = "Chan %d PortID 0x%06x handle 0x%x role %s %s WWPN 0x%08x%08x";
+ static const char prom2[] = "Chan %d PortID 0x%06x handle 0x%x role %s %s tgt %u WWPN 0x%08x%08x";
char *msg = NULL;
target_id_t tgt;
fcportdb_t *lp;
struct cam_path *tmppath;
+ va_list ap;
switch (cmd) {
case ISPASYNC_NEW_TGT_PARAMS:
{
-#ifdef CAM_NEW_TRAN_CODE
struct ccb_trans_settings_scsi *scsi;
struct ccb_trans_settings_spi *spi;
-#endif
int flags, tgt;
- sdparam *sdp = isp->isp_param;
+ sdparam *sdp;
struct ccb_trans_settings cts;
memset(&cts, 0, sizeof (struct ccb_trans_settings));
- tgt = *((int *)arg);
- bus = (tgt >> 16) & 0xffff;
- tgt &= 0xffff;
- sdp += bus;
- if (xpt_create_path(&tmppath, NULL,
- cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim),
- tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- isp_prt(isp, ISP_LOGWARN,
- "isp_async cannot make temp path for %d.%d",
- tgt, bus);
- rv = -1;
+ va_start(ap, cmd);
+ bus = va_arg(ap, int);
+ tgt = va_arg(ap, int);
+ va_end(ap);
+ sdp = SDPARAM(isp, bus);
+
+ if (xpt_create_path(&tmppath, NULL, cam_sim_path(ISP_SPI_PC(isp, bus)->sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ isp_prt(isp, ISP_LOGWARN, "isp_async cannot make temp path for %d.%d", tgt, bus);
break;
}
flags = sdp->isp_devparam[tgt].actv_flags;
-#ifdef CAM_NEW_TRAN_CODE
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.protocol = PROTO_SCSI;
cts.transport = XPORT_SPI;
@@ -3087,45 +4824,25 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
spi->sync_period = sdp->isp_devparam[tgt].actv_period;
spi->sync_offset = sdp->isp_devparam[tgt].actv_offset;
}
-#else
- cts.flags = CCB_TRANS_CURRENT_SETTINGS;
- cts.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
- if (flags & DPARM_DISC) {
- cts.flags |= CCB_TRANS_DISC_ENB;
- }
- if (flags & DPARM_TQING) {
- cts.flags |= CCB_TRANS_TAG_ENB;
- }
- cts.valid |= CCB_TRANS_BUS_WIDTH_VALID;
- cts.bus_width = (flags & DPARM_WIDE)?
- MSG_EXT_WDTR_BUS_8_BIT : MSG_EXT_WDTR_BUS_16_BIT;
- cts.sync_period = sdp->isp_devparam[tgt].actv_period;
- cts.sync_offset = sdp->isp_devparam[tgt].actv_offset;
- if (flags & DPARM_SYNC) {
- cts.valid |=
- CCB_TRANS_SYNC_RATE_VALID |
- CCB_TRANS_SYNC_OFFSET_VALID;
- }
-#endif
- isp_prt(isp, ISP_LOGDEBUG2,
- "NEW_TGT_PARAMS bus %d tgt %d period %x offset %x flags %x",
- bus, tgt, sdp->isp_devparam[tgt].actv_period,
- sdp->isp_devparam[tgt].actv_offset, flags);
+ isp_prt(isp, ISP_LOGDEBUG2, "NEW_TGT_PARAMS bus %d tgt %d period %x offset %x flags %x", bus, tgt, sdp->isp_devparam[tgt].actv_period, sdp->isp_devparam[tgt].actv_offset, flags);
xpt_setup_ccb(&cts.ccb_h, tmppath, 1);
xpt_async(AC_TRANSFER_NEG, tmppath, &cts);
xpt_free_path(tmppath);
break;
}
case ISPASYNC_BUS_RESET:
- bus = *((int *)arg);
- isp_prt(isp, ISP_LOGINFO, "SCSI bus reset on bus %d detected",
- bus);
- if (bus > 0 && isp->isp_path2) {
- xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
- } else if (isp->isp_path) {
- xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
+ {
+ va_start(ap, cmd);
+ bus = va_arg(ap, int);
+ va_end(ap);
+ isp_prt(isp, ISP_LOGINFO, "SCSI bus reset on bus %d detected", bus);
+ if (IS_FC(isp)) {
+ xpt_async(AC_BUS_RESET, ISP_FC_PC(isp, bus)->path, NULL);
+ } else {
+ xpt_async(AC_BUS_RESET, ISP_SPI_PC(isp, bus)->path, NULL);
}
break;
+ }
case ISPASYNC_LIP:
if (msg == NULL) {
msg = "LIP Received";
@@ -3137,144 +4854,134 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
}
/* FALLTHROUGH */
case ISPASYNC_LOOP_DOWN:
+ {
+ struct isp_fc *fc;
if (msg == NULL) {
msg = "LOOP Down";
}
- if (isp->isp_path) {
- isp_freeze_loopdown(isp, msg);
- }
- if (isp->isp_osinfo.ldt_running == 0) {
- isp->isp_osinfo.ldt_running = 1;
- callout_reset(&isp->isp_osinfo.ldt,
- isp->isp_osinfo.loop_down_limit * hz, isp_ldt, isp);
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "starting Loop Down Timer");
+ va_start(ap, cmd);
+ bus = va_arg(ap, int);
+ va_end(ap);
+
+ FCPARAM(isp, bus)->link_active = 1;
+
+ fc = ISP_FC_PC(isp, bus);
+ /*
+ * We don't do any simq freezing if we are only in target mode
+ */
+ if (fc->role & ISP_ROLE_INITIATOR) {
+ if (fc->path) {
+ isp_freeze_loopdown(isp, bus, msg);
+ }
+ if (fc->ldt_running == 0) {
+ fc->ldt_running = 1;
+ callout_reset(&fc->ldt, fc->loop_down_limit * hz, isp_ldt, fc);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "starting Loop Down Timer @ %lu", (unsigned long) time_uptime);
+ }
}
- isp_prt(isp, ISP_LOGINFO, msg);
+ isp_prt(isp, ISP_LOGINFO, "Chan %d: %s", bus, msg);
break;
+ }
case ISPASYNC_LOOP_UP:
+ va_start(ap, cmd);
+ bus = va_arg(ap, int);
+ va_end(ap);
/*
* Now we just note that Loop has come up. We don't
* actually do anything because we're waiting for a
* Change Notify before activating the FC cleanup
* thread to look at the state of the loop again.
*/
- isp_prt(isp, ISP_LOGINFO, "Loop UP");
+ FCPARAM(isp, bus)->link_active = 1;
+ ISP_FC_PC(isp, bus)->loop_dead = 0;
+ ISP_FC_PC(isp, bus)->loop_down_time = 0;
+ isp_prt(isp, ISP_LOGINFO, "Chan %d Loop UP", bus);
break;
case ISPASYNC_DEV_ARRIVED:
- lp = arg;
+ va_start(ap, cmd);
+ bus = va_arg(ap, int);
+ lp = va_arg(ap, fcportdb_t *);
+ va_end(ap);
lp->reserved = 0;
- if ((isp->isp_role & ISP_ROLE_INITIATOR) &&
- (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
- int dbidx = lp - FCPARAM(isp)->portdb;
+ if ((ISP_FC_PC(isp, bus)->role & ISP_ROLE_INITIATOR) && (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
+ int dbidx = lp - FCPARAM(isp, bus)->portdb;
int i;
for (i = 0; i < MAX_FC_TARG; i++) {
if (i >= FL_ID && i <= SNS_ID) {
continue;
}
- if (FCPARAM(isp)->isp_ini_map[i] == 0) {
+ if (FCPARAM(isp, bus)->isp_dev_map[i] == 0) {
break;
}
}
if (i < MAX_FC_TARG) {
- FCPARAM(isp)->isp_ini_map[i] = dbidx + 1;
- lp->ini_map_idx = i + 1;
+ FCPARAM(isp, bus)->isp_dev_map[i] = dbidx + 1;
+ lp->dev_map_idx = i + 1;
} else {
isp_prt(isp, ISP_LOGWARN, "out of target ids");
- isp_dump_portdb(isp);
- }
- }
- if (lp->ini_map_idx) {
- tgt = lp->ini_map_idx - 1;
- isp_prt(isp, ISP_LOGCONFIG, prom2,
- lp->portid, lp->handle,
- roles[lp->roles], "arrived at", tgt,
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) lp->node_wwn,
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) lp->port_wwn);
- isp_make_here(isp, tgt);
+ isp_dump_portdb(isp, bus);
+ }
+ }
+ if (lp->dev_map_idx) {
+ tgt = lp->dev_map_idx - 1;
+ isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, roles[lp->roles], "arrived at", tgt, (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
+ isp_make_here(isp, bus, tgt);
} else {
- isp_prt(isp, ISP_LOGCONFIG, prom,
- lp->portid, lp->handle,
- roles[lp->roles], "arrived",
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) lp->node_wwn,
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) lp->port_wwn);
+ isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "arrived", (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
}
break;
case ISPASYNC_DEV_CHANGED:
- lp = arg;
+ va_start(ap, cmd);
+ bus = va_arg(ap, int);
+ lp = va_arg(ap, fcportdb_t *);
+ va_end(ap);
+ lp->reserved = 0;
if (isp_change_is_bad) {
lp->state = FC_PORTDB_STATE_NIL;
- if (lp->ini_map_idx) {
- tgt = lp->ini_map_idx - 1;
- FCPARAM(isp)->isp_ini_map[tgt] = 0;
- lp->ini_map_idx = 0;
- isp_prt(isp, ISP_LOGCONFIG, prom3,
- lp->portid, tgt, "change is bad");
- isp_make_gone(isp, tgt);
+ if (lp->dev_map_idx) {
+ tgt = lp->dev_map_idx - 1;
+ FCPARAM(isp, bus)->isp_dev_map[tgt] = 0;
+ lp->dev_map_idx = 0;
+ isp_prt(isp, ISP_LOGCONFIG, prom3, bus, lp->portid, tgt, "change is bad");
+ isp_make_gone(isp, bus, tgt);
} else {
- isp_prt(isp, ISP_LOGCONFIG, prom,
- lp->portid, lp->handle,
- roles[lp->roles],
- "changed and departed",
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) lp->node_wwn,
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) lp->port_wwn);
+ isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "changed and departed",
+ (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
}
} else {
lp->portid = lp->new_portid;
lp->roles = lp->new_roles;
- if (lp->ini_map_idx) {
- int t = lp->ini_map_idx - 1;
- FCPARAM(isp)->isp_ini_map[t] =
- (lp - FCPARAM(isp)->portdb) + 1;
- tgt = lp->ini_map_idx - 1;
- isp_prt(isp, ISP_LOGCONFIG, prom2,
- lp->portid, lp->handle,
- roles[lp->roles], "changed at", tgt,
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) lp->node_wwn,
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) lp->port_wwn);
+ if (lp->dev_map_idx) {
+ int t = lp->dev_map_idx - 1;
+ FCPARAM(isp, bus)->isp_dev_map[t] = (lp - FCPARAM(isp, bus)->portdb) + 1;
+ tgt = lp->dev_map_idx - 1;
+ isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, roles[lp->roles], "changed at", tgt,
+ (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
} else {
- isp_prt(isp, ISP_LOGCONFIG, prom,
- lp->portid, lp->handle,
- roles[lp->roles], "changed",
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) lp->node_wwn,
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) lp->port_wwn);
+ isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "changed", (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
}
}
break;
case ISPASYNC_DEV_STAYED:
- lp = arg;
- if (lp->ini_map_idx) {
- tgt = lp->ini_map_idx - 1;
- isp_prt(isp, ISP_LOGCONFIG, prom2,
- lp->portid, lp->handle,
- roles[lp->roles], "stayed at", tgt,
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) lp->node_wwn,
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) lp->port_wwn);
+ va_start(ap, cmd);
+ bus = va_arg(ap, int);
+ lp = va_arg(ap, fcportdb_t *);
+ va_end(ap);
+ if (lp->dev_map_idx) {
+ tgt = lp->dev_map_idx - 1;
+ isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, roles[lp->roles], "stayed at", tgt,
+ (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
} else {
- isp_prt(isp, ISP_LOGCONFIG, prom,
- lp->portid, lp->handle,
- roles[lp->roles], "stayed",
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) lp->node_wwn,
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) lp->port_wwn);
+ isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "stayed",
+ (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
}
break;
case ISPASYNC_DEV_GONE:
- lp = arg;
+ va_start(ap, cmd);
+ bus = va_arg(ap, int);
+ lp = va_arg(ap, fcportdb_t *);
+ va_end(ap);
/*
* If this has a virtual target and we haven't marked it
* that we're going to have isp_gdt tell the OS it's gone,
@@ -3283,100 +4990,230 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
* If it isn't marked that isp_gdt is going to get rid of it,
* announce that it's gone.
*/
- if (lp->ini_map_idx && lp->reserved == 0) {
+ if (lp->dev_map_idx && lp->reserved == 0) {
lp->reserved = 1;
- lp->new_reserved = isp->isp_osinfo.gone_device_time;
+ lp->new_reserved = ISP_FC_PC(isp, bus)->gone_device_time;
lp->state = FC_PORTDB_STATE_ZOMBIE;
- if (isp->isp_osinfo.gdt_running == 0) {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "starting Gone Device Timer");
- isp->isp_osinfo.gdt_running = 1;
- callout_reset(&isp->isp_osinfo.gdt, hz,
- isp_gdt, isp);
- }
- tgt = lp->ini_map_idx - 1;
- isp_prt(isp, ISP_LOGCONFIG, prom2,
- lp->portid, lp->handle,
- roles[lp->roles], "gone zombie at", tgt,
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) lp->node_wwn,
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) lp->port_wwn);
+ if (ISP_FC_PC(isp, bus)->gdt_running == 0) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d starting Gone Device Timer", bus);
+ ISP_FC_PC(isp, bus)->gdt_running = 1;
+ callout_reset(&ISP_FC_PC(isp, bus)->gdt, hz, isp_gdt, ISP_FC_PC(isp, bus));
+ }
+ tgt = lp->dev_map_idx - 1;
+ isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, roles[lp->roles], "gone zombie at", tgt, (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
} else if (lp->reserved == 0) {
- isp_prt(isp, ISP_LOGCONFIG, prom,
- lp->portid, lp->handle,
- roles[lp->roles], "departed",
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) lp->node_wwn,
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) lp->port_wwn);
+ isp_prt(isp, ISP_LOGCONFIG, prom, bus, lp->portid, lp->handle, roles[lp->roles], "departed", (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
}
break;
case ISPASYNC_CHANGE_NOTIFY:
{
char *msg;
- if (arg == ISPASYNC_CHANGE_PDB) {
- msg = "Port Database Changed";
- } else if (arg == ISPASYNC_CHANGE_SNS) {
- msg = "Name Server Database Changed";
+ int evt, nphdl, nlstate, reason;
+
+ va_start(ap, cmd);
+ bus = va_arg(ap, int);
+ evt = va_arg(ap, int);
+ if (IS_24XX(isp) && evt == ISPASYNC_CHANGE_PDB) {
+ nphdl = va_arg(ap, int);
+ nlstate = va_arg(ap, int);
+ reason = va_arg(ap, int);
} else {
- msg = "Other Change Notify";
+ nphdl = NIL_HANDLE;
+ nlstate = reason = 0;
}
+ va_end(ap);
+
+ if (evt == ISPASYNC_CHANGE_PDB) {
+ msg = "Chan %d Port Database Changed";
+ } else if (evt == ISPASYNC_CHANGE_SNS) {
+ msg = "Chan %d Name Server Database Changed";
+ } else {
+ msg = "Chan %d Other Change Notify";
+ }
+
/*
* If the loop down timer is running, cancel it.
*/
- if (isp->isp_osinfo.ldt_running) {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "Stopping Loop Down Timer");
- isp->isp_osinfo.ldt_running = 0;
- callout_stop(&isp->isp_osinfo.ldt);
+ if (ISP_FC_PC(isp, bus)->ldt_running) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Stopping Loop Down Timer @ %lu", (unsigned long) time_uptime);
+ ISP_FC_PC(isp, bus)->ldt_running = 0;
+ callout_stop(&ISP_FC_PC(isp, bus)->ldt);
+ }
+ isp_prt(isp, ISP_LOGINFO, msg, bus);
+ if (ISP_FC_PC(isp, bus)->role & ISP_ROLE_INITIATOR) {
+ isp_freeze_loopdown(isp, bus, msg);
}
- isp_prt(isp, ISP_LOGINFO, msg);
- isp_freeze_loopdown(isp, msg);
- wakeup(ISP_KT_WCHAN(isp));
+ wakeup(ISP_FC_PC(isp, bus));
break;
}
#ifdef ISP_TARGET_MODE
case ISPASYNC_TARGET_NOTIFY:
{
- tmd_notify_t *nt = arg;
- isp_prt(isp, ISP_LOGALL,
- "target notify code 0x%x", nt->nt_ncode);
+ isp_notify_t *notify;
+ va_start(ap, cmd);
+ notify = va_arg(ap, isp_notify_t *);
+ va_end(ap);
+ switch (notify->nt_ncode) {
+ case NT_ABORT_TASK:
+ case NT_ABORT_TASK_SET:
+ case NT_CLEAR_ACA:
+ case NT_CLEAR_TASK_SET:
+ case NT_LUN_RESET:
+ case NT_TARGET_RESET:
+ /*
+ * These are task management functions.
+ */
+ isp_handle_platform_target_tmf(isp, notify);
+ break;
+ case NT_BUS_RESET:
+ case NT_LIP_RESET:
+ case NT_LINK_UP:
+ case NT_LINK_DOWN:
+ /*
+ * No action need be taken here.
+ */
+ break;
+ case NT_HBA_RESET:
+ isp_del_all_wwn_entries(isp, ISP_NOCHAN);
+ break;
+ case NT_LOGOUT:
+ /*
+ * This is device arrival/departure notification
+ */
+ isp_handle_platform_target_notify_ack(isp, notify);
+ break;
+ case NT_ARRIVED:
+ {
+ struct ac_contract ac;
+ struct ac_device_changed *fc;
+
+ ac.contract_number = AC_CONTRACT_DEV_CHG;
+ fc = (struct ac_device_changed *) ac.contract_data;
+ fc->wwpn = notify->nt_wwn;
+ fc->port = notify->nt_sid;
+ fc->target = notify->nt_nphdl;
+ fc->arrived = 1;
+ xpt_async(AC_CONTRACT, ISP_FC_PC(isp, notify->nt_channel)->path, &ac);
+ break;
+ }
+ case NT_DEPARTED:
+ {
+ struct ac_contract ac;
+ struct ac_device_changed *fc;
+
+ ac.contract_number = AC_CONTRACT_DEV_CHG;
+ fc = (struct ac_device_changed *) ac.contract_data;
+ fc->wwpn = notify->nt_wwn;
+ fc->port = notify->nt_sid;
+ fc->target = notify->nt_nphdl;
+ fc->arrived = 0;
+ xpt_async(AC_CONTRACT, ISP_FC_PC(isp, notify->nt_channel)->path, &ac);
+ break;
+ }
+ default:
+ isp_prt(isp, ISP_LOGALL, "target notify code 0x%x", notify->nt_ncode);
+ isp_handle_platform_target_notify_ack(isp, notify);
+ break;
+ }
break;
}
case ISPASYNC_TARGET_ACTION:
- switch (((isphdr_t *)arg)->rqs_entry_type) {
+ {
+ isphdr_t *hp;
+
+ va_start(ap, cmd);
+ hp = va_arg(ap, isphdr_t *);
+ va_end(ap);
+ switch (hp->rqs_entry_type) {
default:
- isp_prt(isp, ISP_LOGWARN,
- "event 0x%x for unhandled target action",
- ((isphdr_t *)arg)->rqs_entry_type);
+ isp_prt(isp, ISP_LOGWARN, "%s: unhandled target action 0x%x", __func__, hp->rqs_entry_type);
break;
case RQSTYPE_NOTIFY:
if (IS_SCSI(isp)) {
- rv = isp_handle_platform_notify_scsi(isp,
- (in_entry_t *) arg);
+ isp_handle_platform_notify_scsi(isp, (in_entry_t *) hp);
+ } else if (IS_24XX(isp)) {
+ isp_handle_platform_notify_24xx(isp, (in_fcentry_24xx_t *) hp);
} else {
- rv = isp_handle_platform_notify_fc(isp,
- (in_fcentry_t *) arg);
+ isp_handle_platform_notify_fc(isp, (in_fcentry_t *) hp);
}
break;
case RQSTYPE_ATIO:
- rv = isp_handle_platform_atio(isp, (at_entry_t *) arg);
+ if (IS_24XX(isp)) {
+ isp_handle_platform_atio7(isp, (at7_entry_t *) hp);
+ } else {
+ isp_handle_platform_atio(isp, (at_entry_t *) hp);
+ }
break;
case RQSTYPE_ATIO2:
- rv = isp_handle_platform_atio2(isp, (at2_entry_t *)arg);
+ isp_handle_platform_atio2(isp, (at2_entry_t *) hp);
break;
+ case RQSTYPE_CTIO7:
case RQSTYPE_CTIO3:
case RQSTYPE_CTIO2:
case RQSTYPE_CTIO:
- rv = isp_handle_platform_ctio(isp, arg);
+ isp_handle_platform_ctio(isp, hp);
break;
+ case RQSTYPE_ABTS_RCVD:
+ {
+ abts_t *abts = (abts_t *)hp;
+ isp_notify_t notify, *nt = &notify;
+ tstate_t *tptr;
+ fcportdb_t *lp;
+ uint16_t chan;
+ uint32_t sid, did;
+
+ did = (abts->abts_did_hi << 16) | abts->abts_did_lo;
+ sid = (abts->abts_sid_hi << 16) | abts->abts_sid_lo;
+ ISP_MEMZERO(nt, sizeof (isp_notify_t));
+
+ nt->nt_hba = isp;
+ nt->nt_did = did;
+ nt->nt_nphdl = abts->abts_nphdl;
+ nt->nt_sid = sid;
+ isp_find_chan_by_did(isp, did, &chan);
+ if (chan == ISP_NOCHAN) {
+ nt->nt_tgt = TGT_ANY;
+ } else {
+ nt->nt_tgt = FCPARAM(isp, chan)->isp_wwpn;
+ if (isp_find_pdb_by_loopid(isp, chan, abts->abts_nphdl, &lp)) {
+ nt->nt_wwn = lp->port_wwn;
+ } else {
+ nt->nt_wwn = INI_ANY;
+ }
+ }
+ /*
+ * Try hard to find the lun for this command.
+ */
+ tptr = get_lun_statep_from_tag(isp, chan, abts->abts_rxid_task);
+ if (tptr) {
+ nt->nt_lun = xpt_path_lun_id(tptr->owner);
+ rls_lun_statep(isp, tptr);
+ } else {
+ nt->nt_lun = LUN_ANY;
+ }
+ nt->nt_need_ack = 1;
+ nt->nt_tagval = abts->abts_rxid_task;
+ nt->nt_tagval |= (((uint64_t) abts->abts_rxid_abts) << 32);
+ if (abts->abts_rxid_task == ISP24XX_NO_TASK) {
+ isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS from N-Port handle 0x%x Port 0x%06x has no task id (rx_id 0x%04x ox_id 0x%04x)",
+ abts->abts_rxid_abts, abts->abts_nphdl, sid, abts->abts_rx_id, abts->abts_ox_id);
+ } else {
+ isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS from N-Port handle 0x%x Port 0x%06x for task 0x%x (rx_id 0x%04x ox_id 0x%04x)",
+ abts->abts_rxid_abts, abts->abts_nphdl, sid, abts->abts_rxid_task, abts->abts_rx_id, abts->abts_ox_id);
+ }
+ nt->nt_channel = chan;
+ nt->nt_ncode = NT_ABORT_TASK;
+ nt->nt_lreserved = hp;
+ isp_handle_platform_target_tmf(isp, nt);
+ break;
+ }
case RQSTYPE_ENABLE_LUN:
case RQSTYPE_MODIFY_LUN:
- isp_ledone(isp, (lun_entry_t *) arg);
+ isp_ledone(isp, (lun_entry_t *) hp);
break;
}
break;
+ }
#endif
case ISPASYNC_FW_CRASH:
{
@@ -3387,36 +5224,18 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
} else {
mbox6 = 0;
}
- isp_prt(isp, ISP_LOGERR,
- "Internal Firmware Error on bus %d @ RISC Address 0x%x",
- mbox6, mbox1);
-#ifdef ISP_FW_CRASH_DUMP
+ isp_prt(isp, ISP_LOGERR, "Internal Firmware Error on bus %d @ RISC Address 0x%x", mbox6, mbox1);
mbox1 = isp->isp_osinfo.mbox_sleep_ok;
isp->isp_osinfo.mbox_sleep_ok = 0;
- if (IS_FC(isp)) {
- FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
- FCPARAM(isp)->isp_loopstate = LOOP_NIL;
- isp_freeze_loopdown(isp, "f/w crash");
- isp_fw_dump(isp);
- }
- isp_reinit(isp);
+ isp_reinit(isp, 1);
isp->isp_osinfo.mbox_sleep_ok = mbox1;
-#else
- mbox1 = isp->isp_osinfo.mbox_sleep_ok;
- isp->isp_osinfo.mbox_sleep_ok = 0;
- isp_reinit(isp);
- isp->isp_osinfo.mbox_sleep_ok = mbox1;
-#endif
isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
break;
}
- case ISPASYNC_UNHANDLED_RESPONSE:
- break;
default:
isp_prt(isp, ISP_LOGERR, "unknown isp_async event %d", cmd);
break;
}
- return (rv);
}
@@ -3434,6 +5253,94 @@ isp_uninit(ispsoftc_t *isp)
ISP_DISABLE_INTS(isp);
}
+/*
+ * When we want to get the 'default' WWNs (when lacking NVRAM), we pick them
+ * up from our platform default (defww{p|n}n) and morph them based upon
+ * channel.
+ *
+ * When we want to get the 'active' WWNs, we get NVRAM WWNs and then morph them
+ * based upon channel.
+ */
+
+uint64_t
+isp_default_wwn(ispsoftc_t * isp, int chan, int isactive, int iswwnn)
+{
+ uint64_t seed;
+ struct isp_fc *fc = ISP_FC_PC(isp, chan);
+
+ /*
+ * If we're asking for a active WWN, the default overrides get
+ * returned, otherwise the NVRAM value is picked.
+ *
+ * If we're asking for a default WWN, we just pick the default override.
+ */
+ if (isactive) {
+ seed = iswwnn ? fc->def_wwnn : fc->def_wwpn;
+ if (seed) {
+ return (seed);
+ }
+ seed = iswwnn ? FCPARAM(isp, chan)->isp_wwnn_nvram : FCPARAM(isp, chan)->isp_wwpn_nvram;
+ } else {
+ seed = iswwnn ? fc->def_wwnn : fc->def_wwpn;
+ }
+
+
+ /*
+ * For channel zero just return what we have. For either ACIIVE or
+ * DEFAULT cases, we depend on default override of NVRAM values for
+ * channel zero.
+ */
+ if (chan == 0) {
+ return (seed);
+ }
+
+ /*
+ * For other channels, we are doing one of three things:
+ *
+ * 1. If what we have now is non-zero, return it. Otherwise we morph
+ * values from channel 0. 2. If we're here for a WWPN we synthesize
+ * it if Channel 0's wwpn has a type 2 NAA. 3. If we're here for a
+ * WWNN we synthesize it if Channel 0's wwnn has a type 2 NAA.
+ */
+
+ if (seed) {
+ return (seed);
+ }
+ if (isactive) {
+ seed = iswwnn ? FCPARAM(isp, 0)->isp_wwnn_nvram : FCPARAM(isp, 0)->isp_wwpn_nvram;
+ } else {
+ seed = iswwnn ? ISP_FC_PC(isp, 0)->def_wwnn : ISP_FC_PC(isp, 0)->def_wwpn;
+ }
+
+ if (((seed >> 60) & 0xf) == 2) {
+ /*
+ * The type 2 NAA fields for QLogic cards appear be laid out
+ * thusly:
+ *
+ * bits 63..60 NAA == 2 bits 59..57 unused/zero bit 56
+ * port (1) or node (0) WWN distinguishor bit 48
+ * physical port on dual-port chips (23XX/24XX)
+ *
+ * This is somewhat nutty, particularly since bit 48 is
+ * irrelevant as they assign seperate serial numbers to
+ * different physical ports anyway.
+ *
+ * We'll stick our channel number plus one first into bits
+ * 57..59 and thence into bits 52..55 which allows for 8 bits
+ * of channel which is comfortably more than our maximum
+ * (126) now.
+ */
+ seed &= ~0x0FF0000000000000ULL;
+ if (iswwnn == 0) {
+ seed |= ((uint64_t) (chan + 1) & 0xf) << 56;
+ seed |= ((uint64_t) ((chan + 1) >> 4) & 0xf) << 52;
+ }
+ } else {
+ seed = 0;
+ }
+ return (seed);
+}
+
void
isp_prt(ispsoftc_t *isp, int level, const char *fmt, ...)
{
@@ -3489,13 +5396,7 @@ isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
isp->isp_osinfo.mbox_sleep_ok = 0;
isp->isp_osinfo.mbox_sleeping = 1;
for (olim = 0; olim < max; olim++) {
-#if __FreeBSD_version < 700037
- tsleep(&isp->isp_mbxworkp, PRIBIO, "ispmbx_sleep",
- isp_mstohz(ms));
-#else
- msleep(&isp->isp_mbxworkp, &isp->isp_osinfo.lock,
- PRIBIO, "ispmbx_sleep", isp_mstohz(ms));
-#endif
+ msleep(&isp->isp_mbxworkp, &isp->isp_osinfo.lock, PRIBIO, "ispmbx_sleep", isp_mstohz(ms));
if (isp->isp_osinfo.mboxcmd_done) {
break;
}
@@ -3516,7 +5417,7 @@ isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
break;
}
}
- USEC_DELAY(100);
+ ISP_DELAY(100);
}
if (isp->isp_osinfo.mboxcmd_done) {
break;
@@ -3524,10 +5425,8 @@ isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
}
}
if (isp->isp_osinfo.mboxcmd_done == 0) {
- isp_prt(isp, ISP_LOGWARN,
- "%s Mailbox Command (0x%x) Timeout (%uus)",
- isp->isp_osinfo.mbox_sleep_ok? "Interrupting" : "Polled",
- isp->isp_lastmbxcmd, usecs);
+ isp_prt(isp, ISP_LOGWARN, "%s Mailbox Command (0x%x) Timeout (%uus) (started @ %s:%d)",
+ isp->isp_osinfo.mbox_sleep_ok? "Interrupting" : "Polled", isp->isp_lastmbxcmd, usecs, mbp->func, mbp->lineno);
mbp->param[0] = MBOX_TIMEOUT;
isp->isp_osinfo.mboxcmd_done = 1;
}
@@ -3549,6 +5448,18 @@ isp_mbox_release(ispsoftc_t *isp)
}
int
+isp_fc_scratch_acquire(ispsoftc_t *isp, int chan)
+{
+ int ret = 0;
+ if (isp->isp_osinfo.pc.fc[chan].fcbsy) {
+ ret = -1;
+ } else {
+ isp->isp_osinfo.pc.fc[chan].fcbsy = 1;
+ }
+ return (ret);
+}
+
+int
isp_mstohz(int ms)
{
int hz;
@@ -3586,11 +5497,19 @@ void
isp_common_dmateardown(ispsoftc_t *isp, struct ccb_scsiio *csio, uint32_t hdl)
{
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTREAD);
} else {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTWRITE);
}
bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap);
}
+
+void
+isp_timer(void *arg)
+{
+ ispsoftc_t *isp = arg;
+#ifdef ISP_TARGET_MODE
+ isp_tmcmd_restart(isp);
+#endif
+ callout_reset(&isp->isp_osinfo.tmo, hz, isp_timer, isp);
+}
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index e8c36ca..2988e30 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -2,7 +2,7 @@
/*-
* Qlogic ISP SCSI Host Adapter FreeBSD Wrapper Definitions
*
- * Copyright (c) 1997-2006 by Matthew Jacob
+ * Copyright (c) 1997-2008 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,27 +32,19 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/endian.h>
-#if __FreeBSD_version < 500000
-#include <sys/kernel.h>
-#include <sys/queue.h>
-#include <sys/malloc.h>
-#else
#include <sys/lock.h>
#include <sys/kernel.h>
#include <sys/queue.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
-#endif
#include <sys/proc.h>
#include <sys/bus.h>
#include <machine/bus.h>
-#if __FreeBSD_version < 500000
-#include <machine/clock.h>
-#endif
#include <machine/cpu.h>
+#include <machine/stdarg.h>
#include <cam/cam.h>
#include <cam/cam_debug.h>
@@ -67,13 +59,8 @@
#include "opt_ddb.h"
#include "opt_isp.h"
-#if __FreeBSD_version < 500000
-#define ISP_PLATFORM_VERSION_MAJOR 4
-#define ISP_PLATFORM_VERSION_MINOR 17
-#else
-#define ISP_PLATFORM_VERSION_MAJOR 5
-#define ISP_PLATFORM_VERSION_MINOR 9
-#endif
+#define ISP_PLATFORM_VERSION_MAJOR 7
+#define ISP_PLATFORM_VERSION_MINOR 0
/*
* Efficiency- get rid of SBus code && tests unless we need them.
@@ -84,28 +71,30 @@
#define ISP_SBUS_SUPPORTED 0
#endif
-
-#if __FreeBSD_version < 500000
-#define ISP_IFLAGS INTR_TYPE_CAM
-#elif __FreeBSD_version < 700037
-#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY
-#else
#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE
-#endif
-
-#if __FreeBSD_version < 700000
-typedef void ispfwfunc(int, int, int, const void **);
-#endif
#ifdef ISP_TARGET_MODE
#define ISP_TARGET_FUNCTIONS 1
-#define ATPDPSIZE 256
+#define ATPDPSIZE 4096
+
+#include <dev/isp/isp_target.h>
+
typedef struct {
+ void * next;
uint32_t orig_datalen;
uint32_t bytes_xfered;
uint32_t last_xframt;
- uint32_t tag : 16,
- lun : 13, /* not enough */
+ uint32_t tag;
+ uint32_t lun;
+ uint32_t nphdl;
+ uint32_t sid;
+ uint32_t portid;
+ uint32_t
+ oxid : 16,
+ cdb0 : 8,
+ : 1,
+ dead : 1,
+ tattr : 3,
state : 3;
} atio_private_data_t;
#define ATPD_STATE_FREE 0
@@ -115,23 +104,34 @@ typedef struct {
#define ATPD_STATE_LAST_CTIO 4
#define ATPD_STATE_PDON 5
+typedef union inot_private_data inot_private_data_t;
+union inot_private_data {
+ inot_private_data_t *next;
+ struct {
+ isp_notify_t nt; /* must be first! */
+ uint8_t data[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
+ uint32_t tag_id, seq_id;
+ } rd;
+};
+
typedef struct tstate {
- struct tstate *next;
+ SLIST_ENTRY(tstate) next;
struct cam_path *owner;
struct ccb_hdr_slist atios;
struct ccb_hdr_slist inots;
- lun_id_t lun;
- int bus;
uint32_t hold;
int atio_count;
int inot_count;
+ inot_private_data_t * restart_queue;
+ inot_private_data_t * ntfree;
+ inot_private_data_t ntpool[ATPDPSIZE];
+ atio_private_data_t * atfree;
+ atio_private_data_t atpool[ATPDPSIZE];
} tstate_t;
-#define LUN_HASH_SIZE 32
-#define LUN_HASH_FUNC(isp, port, lun) \
- ((IS_DUALBUS(isp)) ? \
- (((lun) & ((LUN_HASH_SIZE >> 1) - 1)) << (port)) : \
- ((lun) & (LUN_HASH_SIZE - 1)))
+#define LUN_HASH_SIZE 32
+#define LUN_HASH_FUNC(lun) ((lun) & (LUN_HASH_SIZE - 1))
+
#endif
/*
@@ -146,72 +146,162 @@ struct isp_pcmd {
#define ISP_PCMD(ccb) (ccb)->ccb_h.spriv_ptr1
#define PISP_PCMD(ccb) ((struct isp_pcmd *)ISP_PCMD(ccb))
-struct isposinfo {
- struct ispsoftc * next;
- bus_space_tag_t bus_tag;
- bus_space_handle_t bus_handle;
- bus_dma_tag_t dmat;
- uint64_t default_port_wwn;
- uint64_t default_node_wwn;
- uint32_t default_id;
- device_t dev;
- struct cam_sim *sim;
- struct cam_path *path;
- struct cam_sim *sim2;
- struct cam_path *path2;
- struct intr_config_hook ehook;
- uint32_t loop_down_time;
- uint32_t loop_down_limit;
- uint32_t gone_device_time;
- uint32_t : 5,
+/*
+ * Per channel information
+ */
+SLIST_HEAD(tslist, tstate);
+
+struct isp_fc {
+ struct cam_sim *sim;
+ struct cam_path *path;
+ struct ispsoftc *isp;
+ struct proc *kproc;
+ bus_dma_tag_t tdmat;
+ bus_dmamap_t tdmap;
+ uint64_t def_wwpn;
+ uint64_t def_wwnn;
+ uint32_t loop_down_time;
+ uint32_t loop_down_limit;
+ uint32_t gone_device_time;
+ uint32_t
+#ifdef ISP_TARGET_MODE
+#ifdef ISP_INTERNAL_TARGET
+ proc_active : 1,
+#endif
+ tm_luns_enabled : 1,
+ tm_enable_defer : 1,
+ tm_enabled : 1,
+#endif
simqfrozen : 3,
+ default_id : 8,
hysteresis : 8,
+ role : 2,
gdt_running : 1,
ldt_running : 1,
- disabled : 1,
- fcbsy : 1,
- mbox_sleeping : 1,
- mbox_sleep_ok : 1,
- mboxcmd_done : 1,
- mboxbsy : 1;
- struct callout ldt; /* loop down timer */
- struct callout gdt; /* gone device timer */
-#if __FreeBSD_version < 500000
- uint32_t splcount;
- uint32_t splsaved;
-#else
+ loop_dead : 1,
+ fcbsy : 1;
+ struct callout ldt; /* loop down timer */
+ struct callout gdt; /* gone device timer */
+#ifdef ISP_TARGET_MODE
+ struct tslist lun_hash[LUN_HASH_SIZE];
+#ifdef ISP_INTERNAL_TARGET
+ struct proc * target_proc;
+#endif
+#endif
+};
+
+struct isp_spi {
+ struct cam_sim *sim;
+ struct cam_path *path;
+ uint32_t
+#ifdef ISP_TARGET_MODE
+#ifdef ISP_INTERNAL_TARGET
+ proc_active : 1,
+#endif
+ tm_luns_enabled : 1,
+ tm_enable_defer : 1,
+ tm_enabled : 1,
+#endif
+ simqfrozen : 3,
+ role : 3,
+ iid : 4;
+#ifdef ISP_TARGET_MODE
+ struct tslist lun_hash[LUN_HASH_SIZE];
+#ifdef ISP_INTERNAL_TARGET
+ struct proc * target_proc;
+#endif
+#endif
+};
+
+struct isposinfo {
+ /*
+ * Linkage, locking, and identity
+ */
struct mtx lock;
+ device_t dev;
+ struct cdev * cdev;
+ struct intr_config_hook ehook;
+ struct cam_devq * devq;
+
+ /*
+ * Firmware pointer
+ */
const struct firmware * fw;
- union {
- struct {
- char wwnn[19];
- char wwpn[19];
- } fc;
- } sysctl_info;
-#endif
- struct proc *kproc;
+
+ /*
+ * DMA related sdtuff
+ */
+ bus_space_tag_t bus_tag;
+ bus_dma_tag_t dmat;
+ bus_space_handle_t bus_handle;
bus_dma_tag_t cdmat;
bus_dmamap_t cdmap;
-#define isp_cdmat isp_osinfo.cdmat
-#define isp_cdmap isp_osinfo.cdmap
+
/*
- * Per command information.
+ * Command and transaction related related stuff
*/
struct isp_pcmd * pcmd_pool;
struct isp_pcmd * pcmd_free;
+ uint32_t
+#ifdef ISP_TARGET_MODE
+ tmwanted : 1,
+ tmbusy : 1,
+#else
+ : 2,
+#endif
+ forcemulti : 1,
+ timer_active : 1,
+ autoconf : 1,
+ ehook_active : 1,
+ disabled : 1,
+ mbox_sleeping : 1,
+ mbox_sleep_ok : 1,
+ mboxcmd_done : 1,
+ mboxbsy : 1;
+
+ struct callout tmo; /* general timer */
+
+ /*
+ * misc- needs to be sorted better XXXXXX
+ */
+ int framesize;
+ int exec_throttle;
+ int cont_max;
+
#ifdef ISP_TARGET_MODE
-#define TM_WILDCARD_ENABLED 0x02
-#define TM_TMODE_ENABLED 0x01
- uint8_t tmflags[2]; /* two busses */
-#define NLEACT 4
- union ccb * leact[NLEACT];
- tstate_t tsdflt[2]; /* two busses */
- tstate_t *lun_hash[LUN_HASH_SIZE];
- atio_private_data_t atpdp[ATPDPSIZE];
+ cam_status * rptr;
#endif
+
+ /*
+ * Per-type private storage...
+ */
+ union {
+ struct isp_fc *fc;
+ struct isp_spi *spi;
+ void *ptr;
+ } pc;
};
-#define ISP_KT_WCHAN(isp) (&(isp)->isp_osinfo.kproc)
+#define ISP_FC_PC(isp, chan) (&(isp)->isp_osinfo.pc.fc[(chan)])
+#define ISP_SPI_PC(isp, chan) (&(isp)->isp_osinfo.pc.spi[(chan)])
+#define ISP_GET_PC(isp, chan, tag, rslt) \
+ if (IS_SCSI(isp)) { \
+ rslt = ISP_SPI_PC(isp, chan)-> tag; \
+ } else { \
+ rslt = ISP_FC_PC(isp, chan)-> tag; \
+ }
+#define ISP_GET_PC_ADDR(isp, chan, tag, rp) \
+ if (IS_SCSI(isp)) { \
+ rp = &ISP_SPI_PC(isp, chan)-> tag; \
+ } else { \
+ rp = &ISP_FC_PC(isp, chan)-> tag; \
+ }
+#define ISP_SET_PC(isp, chan, tag, val) \
+ if (IS_SCSI(isp)) { \
+ ISP_SPI_PC(isp, chan)-> tag = val; \
+ } else { \
+ ISP_FC_PC(isp, chan)-> tag = val; \
+ }
#define isp_lock isp_osinfo.lock
#define isp_bus_tag isp_osinfo.bus_tag
@@ -220,37 +310,26 @@ struct isposinfo {
/*
* Locking macros...
*/
-#if __FreeBSD_version < 500000
-#define ISP_LOCK(isp) \
- if (isp->isp_osinfo.splcount++ == 0) { \
- isp->isp_osinfo.splsaved = splcam(); \
- }
-#define ISP_UNLOCK(isp) \
- if (isp->isp_osinfo.splcount > 1) { \
- isp->isp_osinfo.splcount--; \
- } else { \
- isp->isp_osinfo.splcount = 0; \
- splx(isp->isp_osinfo.splsaved); \
- }
-#elif __FreeBSD_version < 700037
-#define ISP_LOCK(isp) do {} while (0)
-#define ISP_UNLOCK(isp) do {} while (0)
-#else
#define ISP_LOCK(isp) mtx_lock(&isp->isp_osinfo.lock)
#define ISP_UNLOCK(isp) mtx_unlock(&isp->isp_osinfo.lock)
-#endif
/*
* Required Macros/Defines
*/
-#define ISP2100_SCRLEN 0x1000
+#define ISP_FC_SCRLEN 0x1000
-#define MEMZERO(a, b) memset(a, 0, b)
-#define MEMCPY memcpy
-#define SNPRINTF snprintf
-#define USEC_DELAY DELAY
-#define USEC_SLEEP(isp, x) DELAY(x)
+#define ISP_MEMZERO(a, b) memset(a, 0, b)
+#define ISP_MEMCPY memcpy
+#define ISP_SNPRINTF snprintf
+#define ISP_DELAY DELAY
+#define ISP_SLEEP(isp, x) DELAY(x)
+
+#ifndef DIAGNOSTIC
+#define ISP_INLINE __inline
+#else
+#define ISP_INLINE
+#endif
#define NANOTIME_T struct timespec
#define GET_NANOTIME nanotime
@@ -263,17 +342,19 @@ struct isposinfo {
switch (type) { \
case SYNC_SFORDEV: \
case SYNC_REQUEST: \
- bus_dmamap_sync(isp->isp_cdmat, isp->isp_cdmap, \
+ bus_dmamap_sync(isp->isp_osinfo.cdmat, \
+ isp->isp_osinfo.cdmap, \
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); \
break; \
case SYNC_SFORCPU: \
case SYNC_RESULT: \
- bus_dmamap_sync(isp->isp_cdmat, isp->isp_cdmap, \
+ bus_dmamap_sync(isp->isp_osinfo.cdmat, \
+ isp->isp_osinfo.cdmap, \
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); \
break; \
case SYNC_REG: \
- bus_space_barrier(isp->isp_bus_tag, \
- isp->isp_bus_handle, offset, size, \
+ bus_space_barrier(isp->isp_osinfo.bus_tag, \
+ isp->isp_osinfo.bus_handle, offset, size, \
BUS_SPACE_BARRIER_READ); \
break; \
default: \
@@ -285,13 +366,8 @@ default: \
#define MBOX_NOTIFY_COMPLETE isp_mbox_notify_done
#define MBOX_RELEASE isp_mbox_release
-#define FC_SCRATCH_ACQUIRE(isp) \
- if (isp->isp_osinfo.fcbsy) { \
- isp_prt(isp, ISP_LOGWARN, \
- "FC scratch area busy (line %d)!", __LINE__); \
- } else \
- isp->isp_osinfo.fcbsy = 1
-#define FC_SCRATCH_RELEASE(isp) isp->isp_osinfo.fcbsy = 0
+#define FC_SCRATCH_ACQUIRE isp_fc_scratch_acquire
+#define FC_SCRATCH_RELEASE(isp, chan) isp->isp_osinfo.pc.fc[chan].fcbsy = 0
#ifndef SCSI_GOOD
#define SCSI_GOOD SCSI_STATUS_OK
@@ -308,6 +384,25 @@ default: \
#define XS_T struct ccb_scsiio
#define XS_DMA_ADDR_T bus_addr_t
+#define XS_GET_DMA64_SEG(a, b, c) \
+{ \
+ ispds64_t *d = a; \
+ bus_dma_segment_t *e = b; \
+ uint32_t f = c; \
+ e += f; \
+ d->ds_base = DMA_LO32(e->ds_addr); \
+ d->ds_basehi = DMA_HI32(e->ds_addr); \
+ d->ds_count = e->ds_len; \
+}
+#define XS_GET_DMA_SEG(a, b, c) \
+{ \
+ ispds_t *d = a; \
+ bus_dma_segment_t *e = b; \
+ uint32_t f = c; \
+ e += f; \
+ d->ds_base = DMA_LO32(e->ds_addr); \
+ d->ds_count = e->ds_len; \
+}
#define XS_ISP(ccb) cam_sim_softc(xpt_path_sim((ccb)->ccb_h.path))
#define XS_CHANNEL(ccb) cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path))
#define XS_TGT(ccb) (ccb)->ccb_h.target_id
@@ -320,7 +415,8 @@ default: \
#define XS_CDBLEN(ccb) (ccb)->cdb_len
#define XS_XFRLEN(ccb) (ccb)->dxfer_len
#define XS_TIME(ccb) (ccb)->ccb_h.timeout
-#define XS_RESID(ccb) (ccb)->resid
+#define XS_GET_RESID(ccb) (ccb)->resid
+#define XS_SET_RESID(ccb, r) (ccb)->resid = r
#define XS_STSP(ccb) (&(ccb)->scsi_status)
#define XS_SNSP(ccb) (&(ccb)->sense_data)
@@ -367,23 +463,27 @@ default: \
#define XS_SET_STATE_STAT(a, b, c)
-#define DEFAULT_IID(x) (isp)->isp_osinfo.default_id
-#define DEFAULT_LOOPID(x) (isp)->isp_osinfo.default_id
-#define DEFAULT_NODEWWN(isp) (isp)->isp_osinfo.default_node_wwn
-#define DEFAULT_PORTWWN(isp) (isp)->isp_osinfo.default_port_wwn
-#define ISP_NODEWWN(isp) FCPARAM(isp)->isp_wwnn_nvram
-#define ISP_PORTWWN(isp) FCPARAM(isp)->isp_wwpn_nvram
+#define DEFAULT_FRAMESIZE(isp) isp->isp_osinfo.framesize
+#define DEFAULT_EXEC_THROTTLE(isp) isp->isp_osinfo.exec_throttle
+#define GET_DEFAULT_ROLE(isp, chan) \
+ (IS_FC(isp)? ISP_FC_PC(isp, chan)->role : ISP_SPI_PC(isp, chan)->role)
+#define SET_DEFAULT_ROLE(isp, chan, val) \
+ if (IS_FC(isp)) { \
+ ISP_FC_PC(isp, chan)->role = val; \
+ } else { \
+ ISP_SPI_PC(isp, chan)->role = val; \
+ }
+
+#define DEFAULT_IID(isp, chan) isp->isp_osinfo.pc.spi[chan].iid
+
+#define DEFAULT_LOOPID(x, chan) isp->isp_osinfo.pc.fc[chan].default_id
+
+#define DEFAULT_NODEWWN(isp, chan) isp_default_wwn(isp, chan, 0, 1)
+#define DEFAULT_PORTWWN(isp, chan) isp_default_wwn(isp, chan, 0, 0)
+#define ACTIVE_NODEWWN(isp, chan) isp_default_wwn(isp, chan, 1, 1)
+#define ACTIVE_PORTWWN(isp, chan) isp_default_wwn(isp, chan, 1, 0)
-#if __FreeBSD_version < 500000
-#if _BYTE_ORDER == _LITTLE_ENDIAN
-#define bswap16 htobe16
-#define bswap32 htobe32
-#else
-#define bswap16 htole16
-#define bswap32 htole32
-#endif
-#endif
#if BYTE_ORDER == BIG_ENDIAN
#ifdef ISP_SBUS_SUPPORTED
@@ -450,10 +550,6 @@ default: \
#include <dev/isp/ispvar.h>
#include <dev/isp/ispmbox.h>
-#ifdef ISP_TARGET_MODE
-#include <dev/isp/isp_tpublic.h>
-#endif
-
/*
* isp_osinfo definiitions && shorthand
*/
@@ -461,17 +557,15 @@ default: \
#define SIMQFRZ_LOOPDOWN 0x2
#define SIMQFRZ_TIMED 0x4
-#define isp_sim isp_osinfo.sim
-#define isp_path isp_osinfo.path
-#define isp_sim2 isp_osinfo.sim2
-#define isp_path2 isp_osinfo.path2
#define isp_dev isp_osinfo.dev
/*
* prototypes for isp_pci && isp_freebsd to share
*/
-extern void isp_attach(ispsoftc_t *);
+extern int isp_attach(ispsoftc_t *);
+extern void isp_detach(ispsoftc_t *);
extern void isp_uninit(ispsoftc_t *);
+extern uint64_t isp_default_wwn(ispsoftc_t *, int, int, int);
/*
* driver global data
@@ -481,23 +575,14 @@ extern int isp_fabric_hysteresis;
extern int isp_loop_down_limit;
extern int isp_gone_device_time;
extern int isp_quickboot_time;
+extern int isp_autoconfig;
/*
* Platform private flags
*/
#define ISP_SPRIV_ERRSET 0x1
-#define ISP_SPRIV_INWDOG 0x2
-#define ISP_SPRIV_GRACE 0x4
#define ISP_SPRIV_DONE 0x8
-#define XS_CMD_S_WDOG(sccb) (sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_INWDOG
-#define XS_CMD_C_WDOG(sccb) (sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_INWDOG
-#define XS_CMD_WDOG_P(sccb) ((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_INWDOG)
-
-#define XS_CMD_S_GRACE(sccb) (sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_GRACE
-#define XS_CMD_C_GRACE(sccb) (sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_GRACE
-#define XS_CMD_GRACE_P(sccb) ((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_GRACE)
-
#define XS_CMD_S_DONE(sccb) (sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_DONE
#define XS_CMD_C_DONE(sccb) (sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_DONE
#define XS_CMD_DONE_P(sccb) ((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_DONE)
@@ -513,6 +598,7 @@ int isp_mbox_acquire(ispsoftc_t *);
void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *);
void isp_mbox_notify_done(ispsoftc_t *);
void isp_mbox_release(ispsoftc_t *);
+int isp_fc_scratch_acquire(ispsoftc_t *, int);
int isp_mstohz(int);
void isp_platform_intr(void *);
void isp_common_dmateardown(ispsoftc_t *, struct ccb_scsiio *, uint32_t);
@@ -520,75 +606,27 @@ void isp_common_dmateardown(ispsoftc_t *, struct ccb_scsiio *, uint32_t);
/*
* Platform Version specific defines
*/
-#if __FreeBSD_version < 500000
-#define BUS_DMA_ROOTARG(x) NULL
-#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \
- bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z)
-#elif __FreeBSD_version < 700020
-#define BUS_DMA_ROOTARG(x) NULL
-#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \
- bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
- busdma_lock_mutex, &Giant, z)
-#elif __FreeBSD_version < 700037
-#define BUS_DMA_ROOTARG(x) bus_get_dma_tag(x)
-#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \
- bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
- busdma_lock_mutex, &Giant, z)
-#else
#define BUS_DMA_ROOTARG(x) bus_get_dma_tag(x)
#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \
bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
busdma_lock_mutex, &isp->isp_osinfo.lock, z)
-#endif
-#if __FreeBSD_version < 700031
-#define isp_setup_intr(d, i, f, U, if, ifa, hp) \
- bus_setup_intr(d, i, f, if, ifa, hp)
-#else
#define isp_setup_intr bus_setup_intr
-#endif
-#if __FreeBSD_version < 500000
-#define isp_sim_alloc cam_sim_alloc
-#define isp_callout_init(x) callout_init(x)
-#elif __FreeBSD_version < 700037
-#define isp_callout_init(x) callout_init(x, 0)
-#define isp_sim_alloc cam_sim_alloc
-#else
-#define isp_callout_init(x) callout_init(x, 1)
#define isp_sim_alloc(a, b, c, d, e, f, g, h) \
cam_sim_alloc(a, b, c, d, e, &(d)->isp_osinfo.lock, f, g, h)
-#endif
/* Should be BUS_SPACE_MAXSIZE, but MAXPHYS is larger than BUS_SPACE_MAXSIZE */
-#define ISP_MAXPHYS (128 * 1024)
-#define ISP_NSEGS ((ISP_MAXPHYS / PAGE_SIZE) + 1)
+#define ISP_NSEGS ((MAXPHYS / PAGE_SIZE) + 1)
+
+#define ISP_PATH_PRT(i, l, p, ...) \
+ if ((l) == ISP_LOGALL || ((l)& (i)->isp_dblev) != 0) { \
+ xpt_print(p, __VA_ARGS__); \
+ }
/*
* Platform specific inline functions
*/
-static __inline int isp_get_pcmd(ispsoftc_t *, union ccb *);
-static __inline void isp_free_pcmd(ispsoftc_t *, union ccb *);
-
-static __inline int
-isp_get_pcmd(ispsoftc_t *isp, union ccb *ccb)
-{
- ISP_PCMD(ccb) = isp->isp_osinfo.pcmd_free;
- if (ISP_PCMD(ccb) == NULL) {
- return (-1);
- }
- isp->isp_osinfo.pcmd_free = ((struct isp_pcmd *)ISP_PCMD(ccb))->next;
- return (0);
-}
-
-static __inline void
-isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
-{
- ((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free;
- isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb);
- ISP_PCMD(ccb) = NULL;
-}
-
/*
* ISP General Library functions
diff --git a/sys/dev/isp/isp_ioctl.h b/sys/dev/isp/isp_ioctl.h
index b52c6f1..8fda052 100644
--- a/sys/dev/isp/isp_ioctl.h
+++ b/sys/dev/isp/isp_ioctl.h
@@ -54,6 +54,8 @@
* This ioctl performs a reset and then will set the adapter to the
* role that was passed in (the old role will be returned). It almost
* goes w/o saying: use with caution.
+ *
+ * Channel selector stored in bits 8..32 as input to driver.
*/
#define ISP_SETROLE _IOWR(ISP_IOC, 4, int)
@@ -64,6 +66,7 @@
/*
* Get the current adapter role
+ * Channel selector passed in first argument.
*/
#define ISP_GETROLE _IOR(ISP_IOC, 5, int)
@@ -107,8 +110,9 @@ typedef struct {
* only), 24 bit Port ID and Node and Port WWNs.
*/
struct isp_fc_device {
- uint32_t loopid; /* 0..255 */
- uint32_t : 6,
+ uint32_t loopid; /* 0..255,2047 */
+ uint32_t
+ chan : 6,
role : 2,
portid : 24; /* 24 bit Port ID */
uint64_t node_wwn;
@@ -129,18 +133,16 @@ struct isp_fc_device {
struct isp_hba_device {
uint32_t
: 8,
- : 4,
fc_speed : 4, /* Gbps */
- : 2,
- fc_class2 : 1,
- fc_ip_supported : 1,
- fc_scsi_supported : 1,
+ : 1,
fc_topology : 3,
- fc_loopid : 8;
+ fc_channel : 8,
+ fc_loopid : 16;
uint8_t fc_fw_major;
uint8_t fc_fw_minor;
uint8_t fc_fw_micro;
- uint8_t reserved;
+ uint8_t fc_nchannels; /* number of supported channels */
+ uint16_t fc_nports; /* number of supported ports */
uint64_t nvram_node_wwn;
uint64_t nvram_port_wwn;
uint64_t active_node_wwn;
@@ -153,14 +155,16 @@ struct isp_hba_device {
#define ISP_TOPO_NPORT 3 /* N-port */
#define ISP_TOPO_FPORT 4 /* F-port */
-#define ISP_FC_GETHINFO _IOR(ISP_IOC, 12, struct isp_hba_device)
+/* don't use 12 any more */
+#define ISP_FC_GETHINFO _IOWR(ISP_IOC, 13, struct isp_hba_device)
/*
* Various Reset Goodies
*/
struct isp_fc_tsk_mgmt {
- uint32_t loopid; /* 0..255 */
- uint32_t lun;
+ uint32_t loopid; /* 0..255/2048 */
+ uint16_t lun;
+ uint16_t chan;
enum {
IPT_CLEAR_ACA,
IPT_TARGET_RESET,
@@ -169,4 +173,18 @@ struct isp_fc_tsk_mgmt {
IPT_ABORT_TASK_SET
} action;
};
-#define ISP_TSK_MGMT _IOWR(ISP_IOC, 97, struct isp_fc_tsk_mgmt)
+/* don't use 97 any more */
+#define ISP_TSK_MGMT _IOWR(ISP_IOC, 98, struct isp_fc_tsk_mgmt)
+
+/*
+ * Just gimme a list of WWPNs that are logged into us.
+ */
+typedef struct {
+ uint16_t count;
+ uint16_t channel;
+ struct wwnpair {
+ uint64_t wwnn;
+ uint64_t wwpn;
+ } wwns[1];
+} isp_dlist_t;
+#define ISP_FC_GETDLIST _IO(ISP_IOC, 14)
diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c
index 1d6e6ee..5e64309 100644
--- a/sys/dev/isp/isp_library.c
+++ b/sys/dev/isp/isp_library.c
@@ -1,17 +1,17 @@
/*-
- * Copyright (c) 1997-2007 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
- *
+ *
* 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.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY 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
@@ -23,6 +23,7 @@
* 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.
+ *
*/
/*
* Qlogic Host Adapter Internal Library Functions
@@ -47,6 +48,203 @@ __FBSDID("$FreeBSD$");
#include "isp_solaris.h"
#endif
+const char *isp_class3_roles[4] = {
+ "None", "Target", "Initiator", "Target/Initiator"
+};
+
+/*
+ * Command shipping- finish off first queue entry and do dma mapping and additional segments as needed.
+ *
+ * Called with the first queue entry at least partially filled out.
+ */
+int
+isp_send_cmd(ispsoftc_t *isp, void *fqe, void *segp, uint32_t nsegs, uint32_t totalcnt, isp_ddir_t ddir)
+{
+ uint8_t storage[QENTRY_LEN];
+ uint8_t type, nqe;
+ uint32_t seg, curseg, seglim, nxt, nxtnxt, ddf;
+ ispds_t *dsp = NULL;
+ ispds64_t *dsp64 = NULL;
+ void *qe0, *qe1;
+
+ qe0 = isp_getrqentry(isp);
+ if (qe0 == NULL) {
+ return (CMD_EAGAIN);
+ }
+ nxt = ISP_NXT_QENTRY(isp->isp_reqidx, RQUEST_QUEUE_LEN(isp));
+
+ type = ((isphdr_t *)fqe)->rqs_entry_type;
+ nqe = 1;
+
+ /*
+ * If we have no data to transmit, just copy the first IOCB and start it up.
+ */
+ if (ddir == ISP_NOXFR) {
+ if (type == RQSTYPE_T2RQS || type == RQSTYPE_T3RQS) {
+ ddf = CT2_NO_DATA;
+ } else {
+ ddf = 0;
+ }
+ goto copy_and_sync;
+ }
+
+ /*
+ * First figure out how many pieces of data to transfer and what kind and how many we can put into the first queue entry.
+ */
+ switch (type) {
+ case RQSTYPE_REQUEST:
+ ddf = (ddir == ISP_TO_DEVICE)? REQFLAG_DATA_OUT : REQFLAG_DATA_IN;
+ dsp = ((ispreq_t *)fqe)->req_dataseg;
+ seglim = ISP_RQDSEG;
+ break;
+ case RQSTYPE_CMDONLY:
+ ddf = (ddir == ISP_TO_DEVICE)? REQFLAG_DATA_OUT : REQFLAG_DATA_IN;
+ seglim = 0;
+ break;
+ case RQSTYPE_T2RQS:
+ ddf = (ddir == ISP_TO_DEVICE)? REQFLAG_DATA_OUT : REQFLAG_DATA_IN;
+ dsp = ((ispreqt2_t *)fqe)->req_dataseg;
+ seglim = ISP_RQDSEG_T2;
+ break;
+ case RQSTYPE_A64:
+ ddf = (ddir == ISP_TO_DEVICE)? REQFLAG_DATA_OUT : REQFLAG_DATA_IN;
+ dsp64 = ((ispreqt3_t *)fqe)->req_dataseg;
+ seglim = ISP_RQDSEG_T3;
+ break;
+ case RQSTYPE_T3RQS:
+ ddf = (ddir == ISP_TO_DEVICE)? REQFLAG_DATA_OUT : REQFLAG_DATA_IN;
+ dsp64 = ((ispreqt3_t *)fqe)->req_dataseg;
+ seglim = ISP_RQDSEG_T3;
+ break;
+ case RQSTYPE_T7RQS:
+ ddf = (ddir == ISP_TO_DEVICE)? FCP_CMND_DATA_WRITE : FCP_CMND_DATA_READ;
+ dsp64 = &((ispreqt7_t *)fqe)->req_dataseg;
+ seglim = 1;
+ break;
+ default:
+ return (CMD_COMPLETE);
+ }
+
+ if (seglim > nsegs) {
+ seglim = nsegs;
+ }
+
+ for (seg = curseg = 0; curseg < seglim; curseg++) {
+ if (dsp64) {
+ XS_GET_DMA64_SEG(dsp64++, segp, seg++);
+ } else {
+ XS_GET_DMA_SEG(dsp++, segp, seg++);
+ }
+ }
+
+
+ /*
+ * Second, start building additional continuation segments as needed.
+ */
+ while (seg < nsegs) {
+ nxtnxt = ISP_NXT_QENTRY(nxt, RQUEST_QUEUE_LEN(isp));
+ if (nxtnxt == isp->isp_reqodx) {
+ return (CMD_EAGAIN);
+ }
+ ISP_MEMZERO(storage, QENTRY_LEN);
+ qe1 = ISP_QUEUE_ENTRY(isp->isp_rquest, nxt);
+ nxt = nxtnxt;
+ if (dsp64) {
+ ispcontreq64_t *crq = (ispcontreq64_t *) storage;
+ seglim = ISP_CDSEG64;
+ crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT;
+ crq->req_header.rqs_entry_count = 1;
+ dsp64 = crq->req_dataseg;
+ } else {
+ ispcontreq_t *crq = (ispcontreq_t *) storage;
+ seglim = ISP_CDSEG;
+ crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
+ crq->req_header.rqs_entry_count = 1;
+ dsp = crq->req_dataseg;
+ }
+ if (seg + seglim > nsegs) {
+ seglim = nsegs - seg;
+ }
+ for (curseg = 0; curseg < seglim; curseg++) {
+ if (dsp64) {
+ XS_GET_DMA64_SEG(dsp64++, segp, seg++);
+ } else {
+ XS_GET_DMA_SEG(dsp++, segp, seg++);
+ }
+ }
+ if (dsp64) {
+ isp_put_cont64_req(isp, (ispcontreq64_t *)storage, qe1);
+ } else {
+ isp_put_cont_req(isp, (ispcontreq_t *)storage, qe1);
+ }
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "additional queue entry", QENTRY_LEN, storage);
+ }
+ nqe++;
+ }
+
+copy_and_sync:
+ ((isphdr_t *)fqe)->rqs_entry_count = nqe;
+ switch (type) {
+ case RQSTYPE_REQUEST:
+ ((ispreq_t *)fqe)->req_flags |= ddf;
+ /*
+ * This is historical and not clear whether really needed.
+ */
+ if (nsegs == 0) {
+ nsegs = 1;
+ }
+ ((ispreq_t *)fqe)->req_seg_count = nsegs;
+ isp_put_request(isp, fqe, qe0);
+ break;
+ case RQSTYPE_CMDONLY:
+ ((ispreq_t *)fqe)->req_flags |= ddf;
+ /*
+ * This is historical and not clear whether really needed.
+ */
+ if (nsegs == 0) {
+ nsegs = 1;
+ }
+ ((ispextreq_t *)fqe)->req_seg_count = nsegs;
+ isp_put_extended_request(isp, fqe, qe0);
+ break;
+ case RQSTYPE_T2RQS:
+ ((ispreqt2_t *)fqe)->req_flags |= ddf;
+ ((ispreqt2_t *)fqe)->req_seg_count = nsegs;
+ ((ispreqt2_t *)fqe)->req_totalcnt = totalcnt;
+ if (ISP_CAP_2KLOGIN(isp)) {
+ isp_put_request_t2e(isp, fqe, qe0);
+ } else {
+ isp_put_request_t2(isp, fqe, qe0);
+ }
+ break;
+ case RQSTYPE_A64:
+ case RQSTYPE_T3RQS:
+ ((ispreqt3_t *)fqe)->req_flags |= ddf;
+ ((ispreqt3_t *)fqe)->req_seg_count = nsegs;
+ ((ispreqt3_t *)fqe)->req_totalcnt = totalcnt;
+ if (ISP_CAP_2KLOGIN(isp)) {
+ isp_put_request_t3e(isp, fqe, qe0);
+ } else {
+ isp_put_request_t3(isp, fqe, qe0);
+ }
+ break;
+ case RQSTYPE_T7RQS:
+ ((ispreqt7_t *)fqe)->req_alen_datadir = ddf;
+ ((ispreqt7_t *)fqe)->req_seg_count = nsegs;
+ ((ispreqt7_t *)fqe)->req_dl = totalcnt;
+ isp_put_request_t7(isp, fqe, qe0);
+ break;
+ default:
+ return (CMD_COMPLETE);
+ }
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "first queue entry", QENTRY_LEN, fqe);
+ }
+ ISP_ADD_REQUEST(isp, nxt);
+ return (CMD_QUEUED);
+}
+
int
isp_save_xs(ispsoftc_t *isp, XS_T *xs, uint32_t *handlep)
{
@@ -110,29 +308,25 @@ isp_destroy_handle(ispsoftc_t *isp, uint32_t handle)
}
}
-int
-isp_getrqentry(ispsoftc_t *isp, uint32_t *iptrp,
- uint32_t *optrp, void **resultp)
-{
- volatile uint32_t iptr, optr;
-
- optr = isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp);
- iptr = isp->isp_reqidx;
- *resultp = ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
- iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN(isp));
- if (iptr == optr) {
- return (1);
- }
- if (optrp)
- *optrp = optr;
- if (iptrp)
- *iptrp = iptr;
- return (0);
+/*
+ * Make sure we have space to put something on the request queue.
+ * Return a pointer to that entry if we do. A side effect of this
+ * function is to update the output index. The input index
+ * stays the same.
+ */
+void *
+isp_getrqentry(ispsoftc_t *isp)
+{
+ isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp);
+ if (ISP_NXT_QENTRY(isp->isp_reqidx, RQUEST_QUEUE_LEN(isp)) == isp->isp_reqodx) {
+ return (NULL);
+ }
+ return (ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx));
}
#define TBA (4 * (((QENTRY_LEN >> 2) * 3) + 1) + 1)
void
-isp_print_qentry(ispsoftc_t *isp, char *msg, int idx, void *arg)
+isp_print_qentry(ispsoftc_t *isp, const char *msg, int idx, void *arg)
{
char buf[TBA];
int amt, i, j;
@@ -141,9 +335,9 @@ isp_print_qentry(ispsoftc_t *isp, char *msg, int idx, void *arg)
isp_prt(isp, ISP_LOGALL, "%s index %d=>", msg, idx);
for (buf[0] = 0, amt = i = 0; i < 4; i++) {
buf[0] = 0;
- SNPRINTF(buf, TBA, " ");
+ ISP_SNPRINTF(buf, TBA, " ");
for (j = 0; j < (QENTRY_LEN >> 2); j++) {
- SNPRINTF(buf, TBA, "%s %02x", buf, ptr[amt++] & 0xff);
+ ISP_SNPRINTF(buf, TBA, "%s %02x", buf, ptr[amt++] & 0xff);
}
isp_prt(isp, ISP_LOGALL, buf);
}
@@ -164,9 +358,10 @@ isp_print_bytes(ispsoftc_t *isp, const char *msg, int amt, void *arg)
int j, to;
to = off;
for (j = 0; j < 16; j++) {
- SNPRINTF(buf, 128, "%s %02x", buf, ptr[off++] & 0xff);
- if (off == amt)
+ ISP_SNPRINTF(buf, 128, "%s %02x", buf, ptr[off++] & 0xff);
+ if (off == amt) {
break;
+ }
}
isp_prt(isp, ISP_LOGALL, "0x%08x:%s", to, buf);
buf[0] = 0;
@@ -186,62 +381,55 @@ isp_print_bytes(ispsoftc_t *isp, const char *msg, int amt, void *arg)
*/
int
-isp_fc_runstate(ispsoftc_t *isp, int tval)
+isp_fc_runstate(ispsoftc_t *isp, int chan, int tval)
{
fcparam *fcp;
- int *tptr;
- if (isp->isp_role == ISP_ROLE_NONE) {
+ fcp = FCPARAM(isp, chan);
+ if (fcp->role == ISP_ROLE_NONE) {
return (0);
}
- fcp = FCPARAM(isp);
- tptr = &tval;
- if (fcp->isp_fwstate < FW_READY ||
- fcp->isp_loopstate < LOOP_PDB_RCVD) {
- if (isp_control(isp, ISPCTL_FCLINK_TEST, tptr) != 0) {
- isp_prt(isp, ISP_LOGSANCFG,
- "isp_fc_runstate: linktest failed");
+ if (fcp->isp_fwstate < FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) {
+ if (isp_control(isp, ISPCTL_FCLINK_TEST, chan, tval) != 0) {
+ isp_prt(isp, ISP_LOGSANCFG, "isp_fc_runstate: linktest failed for channel %d", chan);
return (-1);
}
- if (fcp->isp_fwstate != FW_READY ||
- fcp->isp_loopstate < LOOP_PDB_RCVD) {
- isp_prt(isp, ISP_LOGSANCFG,
- "isp_fc_runstate: f/w not ready");
+ if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) {
+ isp_prt(isp, ISP_LOGSANCFG, "isp_fc_runstate: f/w not ready for channel %d", chan);
return (-1);
}
}
- if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
+
+ if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
return (0);
}
- if (isp_control(isp, ISPCTL_SCAN_LOOP, NULL) != 0) {
- isp_prt(isp, ISP_LOGSANCFG,
- "isp_fc_runstate: scan loop fails");
+
+ if (isp_control(isp, ISPCTL_SCAN_LOOP, chan) != 0) {
+ isp_prt(isp, ISP_LOGSANCFG, "isp_fc_runstate: scan loop fails on channel %d", chan);
return (LOOP_PDB_RCVD);
}
- if (isp_control(isp, ISPCTL_SCAN_FABRIC, NULL) != 0) {
- isp_prt(isp, ISP_LOGSANCFG,
- "isp_fc_runstate: scan fabric fails");
+ if (isp_control(isp, ISPCTL_SCAN_FABRIC, chan) != 0) {
+ isp_prt(isp, ISP_LOGSANCFG, "isp_fc_runstate: scan fabric fails on channel %d", chan);
return (LOOP_LSCAN_DONE);
}
- if (isp_control(isp, ISPCTL_PDB_SYNC, NULL) != 0) {
- isp_prt(isp, ISP_LOGSANCFG, "isp_fc_runstate: pdb_sync fails");
+ if (isp_control(isp, ISPCTL_PDB_SYNC, chan) != 0) {
+ isp_prt(isp, ISP_LOGSANCFG, "isp_fc_runstate: pdb_sync fails on channel %d", chan);
return (LOOP_FSCAN_DONE);
}
if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) {
- isp_prt(isp, ISP_LOGSANCFG,
- "isp_fc_runstate: f/w not ready again");
+ isp_prt(isp, ISP_LOGSANCFG, "isp_fc_runstate: f/w not ready again on channel %d", chan);
return (-1);
}
return (0);
}
/*
- * Fibre Channel Support- get the port database for the id.
+ * Fibre Channel Support routines
*/
void
-isp_dump_portdb(ispsoftc_t *isp)
+isp_dump_portdb(ispsoftc_t *isp, int chan)
{
- fcparam *fcp = (fcparam *) isp->isp_param;
+ fcparam *fcp = FCPARAM(isp, chan);
int i;
for (i = 0; i < MAX_FC_TARG; i++) {
@@ -261,25 +449,247 @@ isp_dump_portdb(ispsoftc_t *isp)
};
fcportdb_t *lp = &fcp->portdb[i];
- if (lp->state == FC_PORTDB_STATE_NIL) {
+ if (lp->state == FC_PORTDB_STATE_NIL && lp->target_mode == 0) {
+ continue;
+ }
+ if (lp->dev_map_idx) {
+ ISP_SNPRINTF(mb, sizeof (mb), "%3d", ((int) lp->dev_map_idx) - 1);
+ } else {
+ ISP_SNPRINTF(mb, sizeof (mb), "---");
+ }
+ isp_prt(isp, ISP_LOGALL, "Chan %d [%d]: hdl 0x%x %s al%d tgt %s %s 0x%06x =>%s 0x%06x; WWNN 0x%08x%08x WWPN 0x%08x%08x",
+ chan, i, lp->handle, dbs[lp->state], lp->autologin, mb, roles[lp->roles], lp->portid, roles[lp->new_roles], lp->new_portid,
+ (uint32_t) (lp->node_wwn >> 32), (uint32_t) (lp->node_wwn), (uint32_t) (lp->port_wwn >> 32), (uint32_t) (lp->port_wwn));
+ }
+}
+
+const char *
+isp_fc_fw_statename(int state)
+{
+ switch (state) {
+ case FW_CONFIG_WAIT: return "Config Wait";
+ case FW_WAIT_AL_PA: return "Waiting for AL_PA";
+ case FW_WAIT_LOGIN: return "Wait Login";
+ case FW_READY: return "Ready";
+ case FW_LOSS_OF_SYNC: return "Loss Of Sync";
+ case FW_ERROR: return "Error";
+ case FW_REINIT: return "Re-Init";
+ case FW_NON_PART: return "Nonparticipating";
+ default: return "?????";
+ }
+}
+
+const char *
+isp_fc_loop_statename(int state)
+{
+ switch (state) {
+ case LOOP_NIL: return "NIL";
+ case LOOP_LIP_RCVD: return "LIP Received";
+ case LOOP_PDB_RCVD: return "PDB Received";
+ case LOOP_SCANNING_LOOP: return "Scanning";
+ case LOOP_LSCAN_DONE: return "Loop Scan Done";
+ case LOOP_SCANNING_FABRIC: return "Scanning Fabric";
+ case LOOP_FSCAN_DONE: return "Fabric Scan Done";
+ case LOOP_SYNCING_PDB: return "Syncing PDB";
+ case LOOP_READY: return "Ready";
+ default: return "?????";
+ }
+}
+
+const char *
+isp_fc_toponame(fcparam *fcp)
+{
+
+ if (fcp->isp_fwstate != FW_READY) {
+ return "Unavailable";
+ }
+ switch (fcp->isp_topo) {
+ case TOPO_NL_PORT: return "Private Loop";
+ case TOPO_FL_PORT: return "FL Port";
+ case TOPO_N_PORT: return "N-Port to N-Port";
+ case TOPO_F_PORT: return "F Port";
+ case TOPO_PTP_STUB: return "F Port (no FLOGI_ACC response)";
+ default: return "?????";
+ }
+}
+
+/*
+ * Change Roles
+ */
+int
+isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
+{
+ fcparam *fcp = FCPARAM(isp, chan);
+
+ if (chan >= isp->isp_nchan) {
+ isp_prt(isp, ISP_LOGWARN, "%s: bad channel %d", __func__, chan);
+ return (ENXIO);
+ }
+ if (chan == 0) {
+#ifdef ISP_TARGET_MODE
+ isp_del_all_wwn_entries(isp, chan);
+#endif
+ isp_clear_commands(isp);
+
+ isp_reset(isp, 0);
+ if (isp->isp_state != ISP_RESETSTATE) {
+ isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
+ return (EIO);
+ }
+ fcp->role = new_role;
+ isp_init(isp);
+ if (isp->isp_state != ISP_INITSTATE) {
+ isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
+ return (EIO);
+ }
+ isp->isp_state = ISP_RUNSTATE;
+ return (0);
+ } else if (ISP_CAP_MULTI_ID(isp)) {
+ mbreg_t mbs;
+ vp_modify_t *vp;
+ uint8_t qe[QENTRY_LEN], *scp;
+
+ ISP_MEMZERO(qe, QENTRY_LEN);
+ /* Acquire Scratch */
+
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ return (EBUSY);
+ }
+ scp = fcp->isp_scratch;
+
+ /*
+ * Build a VP MODIFY command in memory
+ */
+ vp = (vp_modify_t *) qe;
+ vp->vp_mod_hdr.rqs_entry_type = RQSTYPE_VP_MODIFY;
+ vp->vp_mod_hdr.rqs_entry_count = 1;
+ vp->vp_mod_cnt = 1;
+ vp->vp_mod_idx0 = chan;
+ vp->vp_mod_cmd = VP_MODIFY_ENA;
+ vp->vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED;
+ if (new_role & ISP_ROLE_INITIATOR) {
+ vp->vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
+ }
+ if ((new_role & ISP_ROLE_TARGET) == 0) {
+ vp->vp_mod_ports[0].options |= ICB2400_VPOPT_TGT_DISABLE;
+ }
+ MAKE_NODE_NAME_FROM_WWN(vp->vp_mod_ports[0].wwpn, fcp->isp_wwpn);
+ MAKE_NODE_NAME_FROM_WWN(vp->vp_mod_ports[0].wwnn, fcp->isp_wwnn);
+ isp_put_vp_modify(isp, vp, (vp_modify_t *) scp);
+
+ /*
+ * Build a EXEC IOCB A64 command that points to the VP MODIFY command
+ */
+ MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 0);
+ mbs.param[1] = QENTRY_LEN;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, 2 * QENTRY_LEN);
+ isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ return (EIO);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, QENTRY_LEN, QENTRY_LEN);
+ isp_get_vp_modify(isp, (vp_modify_t *)&scp[QENTRY_LEN], vp);
+
+#ifdef ISP_TARGET_MODE
+ isp_del_all_wwn_entries(isp, chan);
+#endif
+ /*
+ * Release Scratch
+ */
+ FC_SCRATCH_RELEASE(isp, chan);
+
+ if (vp->vp_mod_status != VP_STS_OK) {
+ isp_prt(isp, ISP_LOGERR, "%s: VP_MODIFY of Chan %d failed with status %d", __func__, chan, vp->vp_mod_status);
+ return (EIO);
+ }
+ fcp->role = new_role;
+ return (0);
+ } else {
+ return (EINVAL);
+ }
+}
+
+void
+isp_clear_commands(ispsoftc_t *isp)
+{
+ XS_T *xs;
+ uint32_t tmp, handle;
+#ifdef ISP_TARGET_MODE
+ isp_notify_t notify;
+#endif
+
+ for (tmp = 0; isp->isp_xflist && tmp < isp->isp_maxcmds; tmp++) {
+ xs = isp->isp_xflist[tmp];
+ if (xs == NULL) {
+ continue;
+ }
+ handle = isp_find_handle(isp, xs);
+ if (handle == 0) {
continue;
}
- if (lp->ini_map_idx) {
- SNPRINTF(mb, sizeof (mb), "%3d",
- ((int) lp->ini_map_idx) - 1);
+ if (XS_XFRLEN(xs)) {
+ ISP_DMAFREE(isp, xs, handle);
+ XS_SET_RESID(xs, XS_XFRLEN(xs));
} else {
- SNPRINTF(mb, sizeof (mb), "---");
+ XS_SET_RESID(xs, 0);
}
- isp_prt(isp, ISP_LOGALL, "%d: hdl 0x%x %s al%d tgt %s %s "
- "0x%06x =>%s 0x%06x; WWNN 0x%08x%08x WWPN 0x%08x%08x", i,
- lp->handle, dbs[lp->state], lp->autologin, mb,
- roles[lp->roles], lp->portid,
- roles[lp->new_roles], lp->new_portid,
- (uint32_t) (lp->node_wwn >> 32),
- (uint32_t) (lp->node_wwn),
- (uint32_t) (lp->port_wwn >> 32),
- (uint32_t) (lp->port_wwn));
+ isp_destroy_handle(isp, handle);
+ XS_SETERR(xs, HBA_BUSRESET);
+ isp_done(xs);
}
+#ifdef ISP_TARGET_MODE
+ for (tmp = 0; isp->isp_tgtlist && tmp < isp->isp_maxcmds; tmp++) {
+ uint8_t local[QENTRY_LEN];
+
+ xs = isp->isp_tgtlist[tmp];
+ if (xs == NULL) {
+ continue;
+ }
+ handle = isp_find_tgt_handle(isp, xs);
+ if (handle == 0) {
+ continue;
+ }
+ ISP_DMAFREE(isp, xs, handle);
+
+ ISP_MEMZERO(local, QENTRY_LEN);
+ if (IS_24XX(isp)) {
+ ct7_entry_t *ctio = (ct7_entry_t *) local;
+ ctio->ct_syshandle = handle;
+ ctio->ct_nphdl = CT_HBA_RESET;
+ ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
+ } else if (IS_FC(isp)) {
+ ct2_entry_t *ctio = (ct2_entry_t *) local;
+ ctio->ct_syshandle = handle;
+ ctio->ct_status = CT_HBA_RESET;
+ ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
+ } else {
+ ct_entry_t *ctio = (ct_entry_t *) local;
+ ctio->ct_syshandle = handle & 0xffff;
+ ctio->ct_status = CT_HBA_RESET & 0xff;;
+ ctio->ct_header.rqs_entry_type = RQSTYPE_CTIO;
+ }
+ isp_async(isp, ISPASYNC_TARGET_ACTION, local);
+ }
+ for (tmp = 0; tmp < isp->isp_nchan; tmp++) {
+ ISP_MEMZERO(&notify, sizeof (isp_notify_t));
+ notify.nt_ncode = NT_HBA_RESET;
+ notify.nt_hba = isp;
+ notify.nt_wwn = INI_ANY;
+ notify.nt_nphdl = NIL_HANDLE;
+ notify.nt_sid = PORT_ANY;
+ notify.nt_did = PORT_ANY;
+ notify.nt_tgt = TGT_ANY;
+ notify.nt_channel = tmp;
+ notify.nt_lun = LUN_ANY;
+ notify.nt_tagval = TAG_ANY;
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ }
+#endif
}
void
@@ -315,8 +725,7 @@ isp_shutdown(ispsoftc_t *isp)
* (with a few exceptions for efficiency).
*/
-#define ISP_IS_SBUS(isp) \
- (ISP_SBUS_SUPPORTED && (isp)->isp_bustype == ISP_BT_SBUS)
+#define ISP_IS_SBUS(isp) (ISP_SBUS_SUPPORTED && (isp)->isp_bustype == ISP_BT_SBUS)
#define ASIZE(x) (sizeof (x) / sizeof (x[0]))
/*
@@ -326,23 +735,15 @@ void
isp_put_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst)
{
if (ISP_IS_SBUS(isp)) {
- ISP_IOXPUT_8(isp, hpsrc->rqs_entry_type,
- &hpdst->rqs_entry_count);
- ISP_IOXPUT_8(isp, hpsrc->rqs_entry_count,
- &hpdst->rqs_entry_type);
- ISP_IOXPUT_8(isp, hpsrc->rqs_seqno,
- &hpdst->rqs_flags);
- ISP_IOXPUT_8(isp, hpsrc->rqs_flags,
- &hpdst->rqs_seqno);
+ ISP_IOXPUT_8(isp, hpsrc->rqs_entry_type, &hpdst->rqs_entry_count);
+ ISP_IOXPUT_8(isp, hpsrc->rqs_entry_count, &hpdst->rqs_entry_type);
+ ISP_IOXPUT_8(isp, hpsrc->rqs_seqno, &hpdst->rqs_flags);
+ ISP_IOXPUT_8(isp, hpsrc->rqs_flags, &hpdst->rqs_seqno);
} else {
- ISP_IOXPUT_8(isp, hpsrc->rqs_entry_type,
- &hpdst->rqs_entry_type);
- ISP_IOXPUT_8(isp, hpsrc->rqs_entry_count,
- &hpdst->rqs_entry_count);
- ISP_IOXPUT_8(isp, hpsrc->rqs_seqno,
- &hpdst->rqs_seqno);
- ISP_IOXPUT_8(isp, hpsrc->rqs_flags,
- &hpdst->rqs_flags);
+ ISP_IOXPUT_8(isp, hpsrc->rqs_entry_type, &hpdst->rqs_entry_type);
+ ISP_IOXPUT_8(isp, hpsrc->rqs_entry_count, &hpdst->rqs_entry_count);
+ ISP_IOXPUT_8(isp, hpsrc->rqs_seqno, &hpdst->rqs_seqno);
+ ISP_IOXPUT_8(isp, hpsrc->rqs_flags, &hpdst->rqs_flags);
}
}
@@ -350,23 +751,15 @@ void
isp_get_hdr(ispsoftc_t *isp, isphdr_t *hpsrc, isphdr_t *hpdst)
{
if (ISP_IS_SBUS(isp)) {
- ISP_IOXGET_8(isp, &hpsrc->rqs_entry_type,
- hpdst->rqs_entry_count);
- ISP_IOXGET_8(isp, &hpsrc->rqs_entry_count,
- hpdst->rqs_entry_type);
- ISP_IOXGET_8(isp, &hpsrc->rqs_seqno,
- hpdst->rqs_flags);
- ISP_IOXGET_8(isp, &hpsrc->rqs_flags,
- hpdst->rqs_seqno);
+ ISP_IOXGET_8(isp, &hpsrc->rqs_entry_type, hpdst->rqs_entry_count);
+ ISP_IOXGET_8(isp, &hpsrc->rqs_entry_count, hpdst->rqs_entry_type);
+ ISP_IOXGET_8(isp, &hpsrc->rqs_seqno, hpdst->rqs_flags);
+ ISP_IOXGET_8(isp, &hpsrc->rqs_flags, hpdst->rqs_seqno);
} else {
- ISP_IOXGET_8(isp, &hpsrc->rqs_entry_type,
- hpdst->rqs_entry_type);
- ISP_IOXGET_8(isp, &hpsrc->rqs_entry_count,
- hpdst->rqs_entry_count);
- ISP_IOXGET_8(isp, &hpsrc->rqs_seqno,
- hpdst->rqs_seqno);
- ISP_IOXGET_8(isp, &hpsrc->rqs_flags,
- hpdst->rqs_flags);
+ ISP_IOXGET_8(isp, &hpsrc->rqs_entry_type, hpdst->rqs_entry_type);
+ ISP_IOXGET_8(isp, &hpsrc->rqs_entry_count, hpdst->rqs_entry_count);
+ ISP_IOXGET_8(isp, &hpsrc->rqs_seqno, hpdst->rqs_seqno);
+ ISP_IOXGET_8(isp, &hpsrc->rqs_flags, hpdst->rqs_flags);
}
}
@@ -403,10 +796,8 @@ isp_put_request(ispsoftc_t *isp, ispreq_t *rqsrc, ispreq_t *rqdst)
ISP_IOXPUT_8(isp, rqsrc->req_cdb[i], &rqdst->req_cdb[i]);
}
for (i = 0; i < ISP_RQDSEG; i++) {
- ISP_IOXPUT_32(isp, rqsrc->req_dataseg[i].ds_base,
- &rqdst->req_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, rqsrc->req_dataseg[i].ds_count,
- &rqdst->req_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, rqsrc->req_dataseg[i].ds_base, &rqdst->req_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, rqsrc->req_dataseg[i].ds_count, &rqdst->req_dataseg[i].ds_count);
}
}
@@ -427,14 +818,12 @@ isp_put_marker(ispsoftc_t *isp, isp_marker_t *src, isp_marker_t *dst)
ISP_IOXPUT_16(isp, src->mrk_flags, &dst->mrk_flags);
ISP_IOXPUT_16(isp, src->mrk_lun, &dst->mrk_lun);
for (i = 0; i < ASIZE(src->mrk_reserved1); i++) {
- ISP_IOXPUT_8(isp, src->mrk_reserved1[i],
- &dst->mrk_reserved1[i]);
+ ISP_IOXPUT_8(isp, src->mrk_reserved1[i], &dst->mrk_reserved1[i]);
}
}
void
-isp_put_marker_24xx(ispsoftc_t *isp,
- isp_marker_24xx_t *src, isp_marker_24xx_t *dst)
+isp_put_marker_24xx(ispsoftc_t *isp, isp_marker_24xx_t *src, isp_marker_24xx_t *dst)
{
int i;
isp_put_hdr(isp, &src->mrk_header, &dst->mrk_header);
@@ -449,8 +838,7 @@ isp_put_marker_24xx(ispsoftc_t *isp,
ISP_IOXPUT_8(isp, src->mrk_lun[i], &dst->mrk_lun[i]);
}
for (i = 0; i < ASIZE(src->mrk_reserved3); i++) {
- ISP_IOXPUT_8(isp, src->mrk_reserved3[i],
- &dst->mrk_reserved3[i]);
+ ISP_IOXPUT_8(isp, src->mrk_reserved3[i], &dst->mrk_reserved3[i]);
}
}
@@ -472,10 +860,8 @@ isp_put_request_t2(ispsoftc_t *isp, ispreqt2_t *src, ispreqt2_t *dst)
}
ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt);
for (i = 0; i < ISP_RQDSEG_T2; i++) {
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
- &dst->req_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
- &dst->req_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, &dst->req_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, &dst->req_dataseg[i].ds_count);
}
}
@@ -496,10 +882,8 @@ isp_put_request_t2e(ispsoftc_t *isp, ispreqt2e_t *src, ispreqt2e_t *dst)
}
ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt);
for (i = 0; i < ISP_RQDSEG_T2; i++) {
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
- &dst->req_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
- &dst->req_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, &dst->req_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, &dst->req_dataseg[i].ds_count);
}
}
@@ -521,12 +905,9 @@ isp_put_request_t3(ispsoftc_t *isp, ispreqt3_t *src, ispreqt3_t *dst)
}
ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt);
for (i = 0; i < ISP_RQDSEG_T3; i++) {
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
- &dst->req_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi,
- &dst->req_dataseg[i].ds_basehi);
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
- &dst->req_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, &dst->req_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi, &dst->req_dataseg[i].ds_basehi);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, &dst->req_dataseg[i].ds_count);
}
}
@@ -547,12 +928,9 @@ isp_put_request_t3e(ispsoftc_t *isp, ispreqt3e_t *src, ispreqt3e_t *dst)
}
ISP_IOXPUT_32(isp, src->req_totalcnt, &dst->req_totalcnt);
for (i = 0; i < ISP_RQDSEG_T3; i++) {
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
- &dst->req_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi,
- &dst->req_dataseg[i].ds_basehi);
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
- &dst->req_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, &dst->req_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi, &dst->req_dataseg[i].ds_basehi);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, &dst->req_dataseg[i].ds_count);
}
}
@@ -608,12 +986,40 @@ isp_put_request_t7(ispsoftc_t *isp, ispreqt7_t *src, ispreqt7_t *dst)
ISP_IOXPUT_16(isp, src->req_tidlo, &dst->req_tidlo);
ISP_IOXPUT_8(isp, src->req_tidhi, &dst->req_tidhi);
ISP_IOXPUT_8(isp, src->req_vpidx, &dst->req_vpidx);
- ISP_IOXPUT_32(isp, src->req_dataseg.ds_base,
- &dst->req_dataseg.ds_base);
- ISP_IOXPUT_32(isp, src->req_dataseg.ds_basehi,
- &dst->req_dataseg.ds_basehi);
- ISP_IOXPUT_32(isp, src->req_dataseg.ds_count,
- &dst->req_dataseg.ds_count);
+ ISP_IOXPUT_32(isp, src->req_dataseg.ds_base, &dst->req_dataseg.ds_base);
+ ISP_IOXPUT_32(isp, src->req_dataseg.ds_basehi, &dst->req_dataseg.ds_basehi);
+ ISP_IOXPUT_32(isp, src->req_dataseg.ds_count, &dst->req_dataseg.ds_count);
+}
+
+void
+isp_put_24xx_tmf(ispsoftc_t *isp, isp24xx_tmf_t *src, isp24xx_tmf_t *dst)
+{
+ int i;
+ uint32_t *a, *b;
+
+ isp_put_hdr(isp, &src->tmf_header, &dst->tmf_header);
+ ISP_IOXPUT_32(isp, src->tmf_handle, &dst->tmf_handle);
+ ISP_IOXPUT_16(isp, src->tmf_nphdl, &dst->tmf_nphdl);
+ ISP_IOXPUT_16(isp, src->tmf_delay, &dst->tmf_delay);
+ ISP_IOXPUT_16(isp, src->tmf_timeout, &dst->tmf_timeout);
+ for (i = 0; i < ASIZE(src->tmf_reserved0); i++) {
+ ISP_IOXPUT_8(isp, src->tmf_reserved0[i], &dst->tmf_reserved0[i]);
+ }
+ a = (uint32_t *) src->tmf_lun;
+ b = (uint32_t *) dst->tmf_lun;
+ for (i = 0; i < (ASIZE(src->tmf_lun) >> 2); i++ ) {
+ *b++ = ISP_SWAP32(isp, *a++);
+ }
+ ISP_IOXPUT_32(isp, src->tmf_flags, &dst->tmf_flags);
+ for (i = 0; i < ASIZE(src->tmf_reserved1); i++) {
+ ISP_IOXPUT_8(isp, src->tmf_reserved1[i], &dst->tmf_reserved1[i]);
+ }
+ ISP_IOXPUT_16(isp, src->tmf_tidlo, &dst->tmf_tidlo);
+ ISP_IOXPUT_8(isp, src->tmf_tidhi, &dst->tmf_tidhi);
+ ISP_IOXPUT_8(isp, src->tmf_vpidx, &dst->tmf_vpidx);
+ for (i = 0; i < ASIZE(src->tmf_reserved2); i++) {
+ ISP_IOXPUT_8(isp, src->tmf_reserved2[i], &dst->tmf_reserved2[i]);
+ }
}
void
@@ -626,15 +1032,13 @@ isp_put_24xx_abrt(ispsoftc_t *isp, isp24xx_abrt_t *src, isp24xx_abrt_t *dst)
ISP_IOXPUT_16(isp, src->abrt_options, &dst->abrt_options);
ISP_IOXPUT_32(isp, src->abrt_cmd_handle, &dst->abrt_cmd_handle);
for (i = 0; i < ASIZE(src->abrt_reserved); i++) {
- ISP_IOXPUT_8(isp, src->abrt_reserved[i],
- &dst->abrt_reserved[i]);
+ ISP_IOXPUT_8(isp, src->abrt_reserved[i], &dst->abrt_reserved[i]);
}
ISP_IOXPUT_16(isp, src->abrt_tidlo, &dst->abrt_tidlo);
ISP_IOXPUT_8(isp, src->abrt_tidhi, &dst->abrt_tidhi);
ISP_IOXPUT_8(isp, src->abrt_vpidx, &dst->abrt_vpidx);
for (i = 0; i < ASIZE(src->abrt_reserved1); i++) {
- ISP_IOXPUT_8(isp, src->abrt_reserved1[i],
- &dst->abrt_reserved1[i]);
+ ISP_IOXPUT_8(isp, src->abrt_reserved1[i], &dst->abrt_reserved1[i]);
}
}
@@ -644,10 +1048,8 @@ isp_put_cont_req(ispsoftc_t *isp, ispcontreq_t *src, ispcontreq_t *dst)
int i;
isp_put_hdr(isp, &src->req_header, &dst->req_header);
for (i = 0; i < ISP_CDSEG; i++) {
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
- &dst->req_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
- &dst->req_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, &dst->req_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, &dst->req_dataseg[i].ds_count);
}
}
@@ -657,12 +1059,9 @@ isp_put_cont64_req(ispsoftc_t *isp, ispcontreq64_t *src, ispcontreq64_t *dst)
int i;
isp_put_hdr(isp, &src->req_header, &dst->req_header);
for (i = 0; i < ISP_CDSEG64; i++) {
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base,
- &dst->req_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi,
- &dst->req_dataseg[i].ds_basehi);
- ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count,
- &dst->req_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_base, &dst->req_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_basehi, &dst->req_dataseg[i].ds_basehi);
+ ISP_IOXPUT_32(isp, src->req_dataseg[i].ds_count, &dst->req_dataseg[i].ds_count);
}
}
@@ -673,34 +1072,29 @@ isp_get_response(ispsoftc_t *isp, ispstatusreq_t *src, ispstatusreq_t *dst)
isp_get_hdr(isp, &src->req_header, &dst->req_header);
ISP_IOXGET_32(isp, &src->req_handle, dst->req_handle);
ISP_IOXGET_16(isp, &src->req_scsi_status, dst->req_scsi_status);
- ISP_IOXGET_16(isp, &src->req_completion_status,
- dst->req_completion_status);
+ ISP_IOXGET_16(isp, &src->req_completion_status, dst->req_completion_status);
ISP_IOXGET_16(isp, &src->req_state_flags, dst->req_state_flags);
ISP_IOXGET_16(isp, &src->req_status_flags, dst->req_status_flags);
ISP_IOXGET_16(isp, &src->req_time, dst->req_time);
ISP_IOXGET_16(isp, &src->req_sense_len, dst->req_sense_len);
ISP_IOXGET_32(isp, &src->req_resid, dst->req_resid);
for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->req_response[i],
- dst->req_response[i]);
+ ISP_IOXGET_8(isp, &src->req_response[i], dst->req_response[i]);
}
for (i = 0; i < 32; i++) {
- ISP_IOXGET_8(isp, &src->req_sense_data[i],
- dst->req_sense_data[i]);
+ ISP_IOXGET_8(isp, &src->req_sense_data[i], dst->req_sense_data[i]);
}
}
void
-isp_get_24xx_response(ispsoftc_t *isp, isp24xx_statusreq_t *src,
- isp24xx_statusreq_t *dst)
+isp_get_24xx_response(ispsoftc_t *isp, isp24xx_statusreq_t *src, isp24xx_statusreq_t *dst)
{
int i;
uint32_t *s, *d;
isp_get_hdr(isp, &src->req_header, &dst->req_header);
ISP_IOXGET_32(isp, &src->req_handle, dst->req_handle);
- ISP_IOXGET_16(isp, &src->req_completion_status,
- dst->req_completion_status);
+ ISP_IOXGET_16(isp, &src->req_completion_status, dst->req_completion_status);
ISP_IOXGET_16(isp, &src->req_oxid, dst->req_oxid);
ISP_IOXGET_32(isp, &src->req_resid, dst->req_resid);
ISP_IOXGET_16(isp, &src->req_reserved0, dst->req_reserved0);
@@ -727,15 +1121,13 @@ isp_get_24xx_abrt(ispsoftc_t *isp, isp24xx_abrt_t *src, isp24xx_abrt_t *dst)
ISP_IOXGET_16(isp, &src->abrt_options, dst->abrt_options);
ISP_IOXGET_32(isp, &src->abrt_cmd_handle, dst->abrt_cmd_handle);
for (i = 0; i < ASIZE(src->abrt_reserved); i++) {
- ISP_IOXGET_8(isp, &src->abrt_reserved[i],
- dst->abrt_reserved[i]);
+ ISP_IOXGET_8(isp, &src->abrt_reserved[i], dst->abrt_reserved[i]);
}
ISP_IOXGET_16(isp, &src->abrt_tidlo, dst->abrt_tidlo);
ISP_IOXGET_8(isp, &src->abrt_tidhi, dst->abrt_tidhi);
ISP_IOXGET_8(isp, &src->abrt_vpidx, dst->abrt_vpidx);
for (i = 0; i < ASIZE(src->abrt_reserved1); i++) {
- ISP_IOXGET_8(isp, &src->abrt_reserved1[i],
- dst->abrt_reserved1[i]);
+ ISP_IOXGET_8(isp, &src->abrt_reserved1[i], dst->abrt_reserved1[i]);
}
}
@@ -749,8 +1141,7 @@ isp_get_rio2(ispsoftc_t *isp, isp_rio2_t *r2src, isp_rio2_t *r2dst)
r2dst->req_header.rqs_seqno = 30;
}
for (i = 0; i < r2dst->req_header.rqs_seqno; i++) {
- ISP_IOXGET_16(isp, &r2src->req_handles[i],
- r2dst->req_handles[i]);
+ ISP_IOXGET_16(isp, &r2src->req_handles[i], r2dst->req_handles[i]);
}
while (i < 30) {
r2dst->req_handles[i++] = 0;
@@ -858,14 +1249,12 @@ isp_put_icb_2400(ispsoftc_t *isp, isp_icb_2400_t *src, isp_icb_2400_t *dst)
ISP_IOXPUT_16(isp, src->icb_priaddr[i], &dst->icb_priaddr[i]);
}
for (i = 0; i < 4; i++) {
- ISP_IOXPUT_16(isp, src->icb_reserved1[i],
- &dst->icb_reserved1[i]);
+ ISP_IOXPUT_16(isp, src->icb_reserved1[i], &dst->icb_reserved1[i]);
}
ISP_IOXPUT_16(isp, src->icb_atio_in, &dst->icb_atio_in);
ISP_IOXPUT_16(isp, src->icb_atioqlen, &dst->icb_atioqlen);
for (i = 0; i < 4; i++) {
- ISP_IOXPUT_16(isp, src->icb_atioqaddr[i],
- &dst->icb_atioqaddr[i]);
+ ISP_IOXPUT_16(isp, src->icb_atioqaddr[i], &dst->icb_atioqaddr[i]);
}
ISP_IOXPUT_16(isp, src->icb_idelaytimer, &dst->icb_idelaytimer);
ISP_IOXPUT_16(isp, src->icb_logintime, &dst->icb_logintime);
@@ -873,8 +1262,139 @@ isp_put_icb_2400(ispsoftc_t *isp, isp_icb_2400_t *src, isp_icb_2400_t *dst)
ISP_IOXPUT_32(isp, src->icb_fwoptions2, &dst->icb_fwoptions2);
ISP_IOXPUT_32(isp, src->icb_fwoptions3, &dst->icb_fwoptions3);
for (i = 0; i < 12; i++) {
- ISP_IOXPUT_16(isp, src->icb_reserved2[i],
- &dst->icb_reserved2[i]);
+ ISP_IOXPUT_16(isp, src->icb_reserved2[i], &dst->icb_reserved2[i]);
+ }
+}
+
+void
+isp_put_icb_2400_vpinfo(ispsoftc_t *isp, isp_icb_2400_vpinfo_t *src, isp_icb_2400_vpinfo_t *dst)
+{
+ ISP_IOXPUT_16(isp, src->vp_count, &dst->vp_count);
+ ISP_IOXPUT_16(isp, src->vp_global_options, &dst->vp_global_options);
+}
+
+void
+isp_put_vp_port_info(ispsoftc_t *isp, vp_port_info_t *src, vp_port_info_t *dst)
+{
+ int i;
+ ISP_IOXPUT_16(isp, src->vp_port_status, &dst->vp_port_status);
+ ISP_IOXPUT_8(isp, src->vp_port_options, &dst->vp_port_options);
+ ISP_IOXPUT_8(isp, src->vp_port_loopid, &dst->vp_port_loopid);
+ for (i = 0; i < 8; i++) {
+ ISP_IOXPUT_8(isp, src->vp_port_portname[i], &dst->vp_port_portname[i]);
+ }
+ for (i = 0; i < 8; i++) {
+ ISP_IOXPUT_8(isp, src->vp_port_nodename[i], &dst->vp_port_nodename[i]);
+ }
+ /* we never *put* portid_lo/portid_hi */
+}
+
+void
+isp_get_vp_port_info(ispsoftc_t *isp, vp_port_info_t *src, vp_port_info_t *dst)
+{
+ int i;
+ ISP_IOXGET_16(isp, &src->vp_port_status, dst->vp_port_status);
+ ISP_IOXGET_8(isp, &src->vp_port_options, dst->vp_port_options);
+ ISP_IOXGET_8(isp, &src->vp_port_loopid, dst->vp_port_loopid);
+ for (i = 0; i < ASIZE(src->vp_port_portname); i++) {
+ ISP_IOXGET_8(isp, &src->vp_port_portname[i], dst->vp_port_portname[i]);
+ }
+ for (i = 0; i < ASIZE(src->vp_port_nodename); i++) {
+ ISP_IOXGET_8(isp, &src->vp_port_nodename[i], dst->vp_port_nodename[i]);
+ }
+ ISP_IOXGET_16(isp, &src->vp_port_portid_lo, dst->vp_port_portid_lo);
+ ISP_IOXGET_16(isp, &src->vp_port_portid_hi, dst->vp_port_portid_hi);
+}
+
+void
+isp_put_vp_ctrl_info(ispsoftc_t *isp, vp_ctrl_info_t *src, vp_ctrl_info_t *dst)
+{
+ int i;
+ isp_put_hdr(isp, &src->vp_ctrl_hdr, &dst->vp_ctrl_hdr);
+ ISP_IOXPUT_32(isp, src->vp_ctrl_handle, &dst->vp_ctrl_handle);
+ ISP_IOXPUT_16(isp, src->vp_ctrl_index_fail, &dst->vp_ctrl_index_fail);
+ ISP_IOXPUT_16(isp, src->vp_ctrl_status, &dst->vp_ctrl_status);
+ ISP_IOXPUT_16(isp, src->vp_ctrl_command, &dst->vp_ctrl_command);
+ ISP_IOXPUT_16(isp, src->vp_ctrl_vp_count, &dst->vp_ctrl_vp_count);
+ for (i = 0; i < ASIZE(src->vp_ctrl_idmap); i++) {
+ ISP_IOXPUT_16(isp, src->vp_ctrl_idmap[i], &dst->vp_ctrl_idmap[i]);
+ }
+ for (i = 0; i < ASIZE(src->vp_ctrl_reserved); i++) {
+ ISP_IOXPUT_8(isp, src->vp_ctrl_idmap[i], &dst->vp_ctrl_idmap[i]);
+ }
+}
+
+void
+isp_get_vp_ctrl_info(ispsoftc_t *isp, vp_ctrl_info_t *src, vp_ctrl_info_t *dst)
+{
+ int i;
+ isp_get_hdr(isp, &src->vp_ctrl_hdr, &dst->vp_ctrl_hdr);
+ ISP_IOXGET_32(isp, &src->vp_ctrl_handle, dst->vp_ctrl_handle);
+ ISP_IOXGET_16(isp, &src->vp_ctrl_index_fail, dst->vp_ctrl_index_fail);
+ ISP_IOXGET_16(isp, &src->vp_ctrl_status, dst->vp_ctrl_status);
+ ISP_IOXGET_16(isp, &src->vp_ctrl_command, dst->vp_ctrl_command);
+ ISP_IOXGET_16(isp, &src->vp_ctrl_vp_count, dst->vp_ctrl_vp_count);
+ for (i = 0; i < ASIZE(src->vp_ctrl_idmap); i++) {
+ ISP_IOXGET_16(isp, &src->vp_ctrl_idmap[i], dst->vp_ctrl_idmap[i]);
+ }
+ for (i = 0; i < ASIZE(src->vp_ctrl_reserved); i++) {
+ ISP_IOXGET_8(isp, &src->vp_ctrl_reserved[i], dst->vp_ctrl_reserved[i]);
+ }
+}
+
+void
+isp_put_vp_modify(ispsoftc_t *isp, vp_modify_t *src, vp_modify_t *dst)
+{
+ int i, j;
+ isp_put_hdr(isp, &src->vp_mod_hdr, &dst->vp_mod_hdr);
+ ISP_IOXPUT_32(isp, src->vp_mod_hdl, &dst->vp_mod_hdl);
+ ISP_IOXPUT_16(isp, src->vp_mod_reserved0, &dst->vp_mod_reserved0);
+ ISP_IOXPUT_16(isp, src->vp_mod_status, &dst->vp_mod_status);
+ ISP_IOXPUT_8(isp, src->vp_mod_cmd, &dst->vp_mod_cmd);
+ ISP_IOXPUT_8(isp, src->vp_mod_cnt, &dst->vp_mod_cnt);
+ ISP_IOXPUT_8(isp, src->vp_mod_idx0, &dst->vp_mod_idx0);
+ ISP_IOXPUT_8(isp, src->vp_mod_idx1, &dst->vp_mod_idx1);
+ for (i = 0; i < ASIZE(src->vp_mod_ports); i++) {
+ ISP_IOXPUT_8(isp, src->vp_mod_ports[i].options, &dst->vp_mod_ports[i].options);
+ ISP_IOXPUT_8(isp, src->vp_mod_ports[i].loopid, &dst->vp_mod_ports[i].loopid);
+ ISP_IOXPUT_16(isp, src->vp_mod_ports[i].reserved1, &dst->vp_mod_ports[i].reserved1);
+ for (j = 0; j < ASIZE(src->vp_mod_ports[i].wwpn); j++) {
+ ISP_IOXPUT_8(isp, src->vp_mod_ports[i].wwpn[j], &dst->vp_mod_ports[i].wwpn[j]);
+ }
+ for (j = 0; j < ASIZE(src->vp_mod_ports[i].wwnn); j++) {
+ ISP_IOXPUT_8(isp, src->vp_mod_ports[i].wwnn[j], &dst->vp_mod_ports[i].wwnn[j]);
+ }
+ }
+ for (i = 0; i < ASIZE(src->vp_mod_reserved2); i++) {
+ ISP_IOXPUT_8(isp, src->vp_mod_reserved2[i], &dst->vp_mod_reserved2[i]);
+ }
+}
+
+void
+isp_get_vp_modify(ispsoftc_t *isp, vp_modify_t *src, vp_modify_t *dst)
+{
+ int i, j;
+ isp_get_hdr(isp, &src->vp_mod_hdr, &dst->vp_mod_hdr);
+ ISP_IOXGET_32(isp, &src->vp_mod_hdl, dst->vp_mod_hdl);
+ ISP_IOXGET_16(isp, &src->vp_mod_reserved0, dst->vp_mod_reserved0);
+ ISP_IOXGET_16(isp, &src->vp_mod_status, dst->vp_mod_status);
+ ISP_IOXGET_8(isp, &src->vp_mod_cmd, dst->vp_mod_cmd);
+ ISP_IOXGET_8(isp, &src->vp_mod_cnt, dst->vp_mod_cnt);
+ ISP_IOXGET_8(isp, &src->vp_mod_idx0, dst->vp_mod_idx0);
+ ISP_IOXGET_8(isp, &src->vp_mod_idx1, dst->vp_mod_idx1);
+ for (i = 0; i < ASIZE(src->vp_mod_ports); i++) {
+ ISP_IOXGET_8(isp, &src->vp_mod_ports[i].options, dst->vp_mod_ports[i].options);
+ ISP_IOXGET_8(isp, &src->vp_mod_ports[i].loopid, dst->vp_mod_ports[i].loopid);
+ ISP_IOXGET_16(isp, &src->vp_mod_ports[i].reserved1, dst->vp_mod_ports[i].reserved1);
+ for (j = 0; j < ASIZE(src->vp_mod_ports[i].wwpn); j++) {
+ ISP_IOXGET_8(isp, &src->vp_mod_ports[i].wwpn[j], dst->vp_mod_ports[i].wwpn[j]);
+ }
+ for (j = 0; j < ASIZE(src->vp_mod_ports[i].wwnn); j++) {
+ ISP_IOXGET_8(isp, &src->vp_mod_ports[i].wwnn[j], dst->vp_mod_ports[i].wwnn[j]);
+ }
+ }
+ for (i = 0; i < ASIZE(src->vp_mod_reserved2); i++) {
+ ISP_IOXGET_8(isp, &src->vp_mod_reserved2[i], dst->vp_mod_reserved2[i]);
}
}
@@ -886,12 +1406,10 @@ isp_get_pdb_21xx(ispsoftc_t *isp, isp_pdb_21xx_t *src, isp_pdb_21xx_t *dst)
ISP_IOXGET_8(isp, &src->pdb_mstate, dst->pdb_mstate);
ISP_IOXGET_8(isp, &src->pdb_sstate, dst->pdb_sstate);
for (i = 0; i < 4; i++) {
- ISP_IOXGET_8(isp, &src->pdb_hardaddr_bits[i],
- dst->pdb_hardaddr_bits[i]);
+ ISP_IOXGET_8(isp, &src->pdb_hardaddr_bits[i], dst->pdb_hardaddr_bits[i]);
}
for (i = 0; i < 4; i++) {
- ISP_IOXGET_8(isp, &src->pdb_portid_bits[i],
- dst->pdb_portid_bits[i]);
+ ISP_IOXGET_8(isp, &src->pdb_portid_bits[i], dst->pdb_portid_bits[i]);
}
for (i = 0; i < 8; i++) {
ISP_IOXGET_8(isp, &src->pdb_nodename[i], dst->pdb_nodename[i]);
@@ -940,12 +1458,10 @@ isp_get_pdb_24xx(ispsoftc_t *isp, isp_pdb_24xx_t *src, isp_pdb_24xx_t *dst)
ISP_IOXGET_8(isp, &src->pdb_curstate, dst->pdb_curstate);
ISP_IOXGET_8(isp, &src->pdb_laststate, dst->pdb_laststate);
for (i = 0; i < 4; i++) {
- ISP_IOXGET_8(isp, &src->pdb_hardaddr_bits[i],
- dst->pdb_hardaddr_bits[i]);
+ ISP_IOXGET_8(isp, &src->pdb_hardaddr_bits[i], dst->pdb_hardaddr_bits[i]);
}
for (i = 0; i < 4; i++) {
- ISP_IOXGET_8(isp, &src->pdb_portid_bits[i],
- dst->pdb_portid_bits[i]);
+ ISP_IOXGET_8(isp, &src->pdb_portid_bits[i], dst->pdb_portid_bits[i]);
}
ISP_IOXGET_16(isp, &src->pdb_retry_timer, dst->pdb_retry_timer);
ISP_IOXGET_16(isp, &src->pdb_handle, dst->pdb_handle);
@@ -960,8 +1476,7 @@ isp_get_pdb_24xx(ispsoftc_t *isp, isp_pdb_24xx_t *src, isp_pdb_24xx_t *dst)
ISP_IOXGET_8(isp, &src->pdb_portname[i], dst->pdb_portname[i]);
}
for (i = 0; i < 24; i++) {
- ISP_IOXGET_8(isp, &src->pdb_reserved1[i],
- dst->pdb_reserved1[i]);
+ ISP_IOXGET_8(isp, &src->pdb_reserved1[i], dst->pdb_reserved1[i]);
}
}
@@ -982,10 +1497,8 @@ isp_get_plogx(ispsoftc_t *isp, isp_plogx_t *src, isp_plogx_t *dst)
ISP_IOXGET_16(isp, &src->plogx_portlo, dst->plogx_portlo);
ISP_IOXGET_16(isp, &src->plogx_rspsz_porthi, dst->plogx_rspsz_porthi);
for (i = 0; i < 11; i++) {
- ISP_IOXGET_16(isp, &src->plogx_ioparm[i].lo16,
- dst->plogx_ioparm[i].lo16);
- ISP_IOXGET_16(isp, &src->plogx_ioparm[i].hi16,
- dst->plogx_ioparm[i].hi16);
+ ISP_IOXGET_16(isp, &src->plogx_ioparm[i].lo16, dst->plogx_ioparm[i].lo16);
+ ISP_IOXGET_16(isp, &src->plogx_ioparm[i].hi16, dst->plogx_ioparm[i].hi16);
}
}
@@ -1002,13 +1515,43 @@ isp_put_plogx(ispsoftc_t *isp, isp_plogx_t *src, isp_plogx_t *dst)
ISP_IOXPUT_16(isp, src->plogx_portlo, &dst->plogx_portlo);
ISP_IOXPUT_16(isp, src->plogx_rspsz_porthi, &dst->plogx_rspsz_porthi);
for (i = 0; i < 11; i++) {
- ISP_IOXPUT_16(isp, src->plogx_ioparm[i].lo16,
- &dst->plogx_ioparm[i].lo16);
- ISP_IOXPUT_16(isp, src->plogx_ioparm[i].hi16,
- &dst->plogx_ioparm[i].hi16);
+ ISP_IOXPUT_16(isp, src->plogx_ioparm[i].lo16, &dst->plogx_ioparm[i].lo16);
+ ISP_IOXPUT_16(isp, src->plogx_ioparm[i].hi16, &dst->plogx_ioparm[i].hi16);
+ }
+}
+
+/*
+ * Report ID canonicalization
+ */
+void
+isp_get_ridacq(ispsoftc_t *isp, isp_ridacq_t *src, isp_ridacq_t *dst)
+{
+ int i;
+ isp_get_hdr(isp, &src->ridacq_hdr, &dst->ridacq_hdr);
+ ISP_IOXGET_32(isp, &src->ridacq_handle, dst->ridacq_handle);
+ ISP_IOXGET_16(isp, &src->ridacq_vp_port_lo, dst->ridacq_vp_port_lo);
+ ISP_IOXGET_8(isp, &src->ridacq_vp_port_hi, dst->ridacq_vp_port_hi);
+ ISP_IOXGET_8(isp, &src->ridacq_format, dst->ridacq_format);
+ for (i = 0; i < sizeof (src->ridacq_map) / sizeof (src->ridacq_map[0]); i++) {
+ ISP_IOXGET_16(isp, &src->ridacq_map[i], dst->ridacq_map[i]);
+ }
+ for (i = 0; i < sizeof (src->ridacq_reserved1) / sizeof (src->ridacq_reserved1[0]); i++) {
+ ISP_IOXGET_16(isp, &src->ridacq_reserved1[i], dst->ridacq_reserved1[i]);
+ }
+ if (dst->ridacq_format == 0) {
+ ISP_IOXGET_8(isp, &src->un.type0.ridacq_vp_acquired, dst->un.type0.ridacq_vp_acquired);
+ ISP_IOXGET_8(isp, &src->un.type0.ridacq_vp_setup, dst->un.type0.ridacq_vp_setup);
+ ISP_IOXGET_16(isp, &src->un.type0.ridacq_reserved0, dst->un.type0.ridacq_reserved0);
+ } else if (dst->ridacq_format == 1) {
+ ISP_IOXGET_16(isp, &src->un.type1.ridacq_vp_count, dst->un.type1.ridacq_vp_count);
+ ISP_IOXGET_8(isp, &src->un.type1.ridacq_vp_index, dst->un.type1.ridacq_vp_index);
+ ISP_IOXGET_8(isp, &src->un.type1.ridacq_vp_status, dst->un.type1.ridacq_vp_status);
+ } else {
+ ISP_MEMZERO(&dst->un, sizeof (dst->un));
}
}
+
/*
* CT Passthru canonicalization
*/
@@ -1022,23 +1565,20 @@ isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst)
ISP_IOXGET_16(isp, &src->ctp_status, dst->ctp_status);
ISP_IOXGET_16(isp, &src->ctp_nphdl, dst->ctp_nphdl);
ISP_IOXGET_16(isp, &src->ctp_cmd_cnt, dst->ctp_cmd_cnt);
- ISP_IOXGET_16(isp, &src->ctp_vpidx, dst->ctp_vpidx);
+ ISP_IOXGET_8(isp, &src->ctp_vpidx, dst->ctp_vpidx);
+ ISP_IOXGET_8(isp, &src->ctp_reserved0, dst->ctp_reserved0);
ISP_IOXGET_16(isp, &src->ctp_time, dst->ctp_time);
- ISP_IOXGET_16(isp, &src->ctp_reserved0, dst->ctp_reserved0);
+ ISP_IOXGET_16(isp, &src->ctp_reserved1, dst->ctp_reserved1);
ISP_IOXGET_16(isp, &src->ctp_rsp_cnt, dst->ctp_rsp_cnt);
for (i = 0; i < 5; i++) {
- ISP_IOXGET_16(isp, &src->ctp_reserved1[i],
- dst->ctp_reserved1[i]);
+ ISP_IOXGET_16(isp, &src->ctp_reserved2[i], dst->ctp_reserved2[i]);
}
ISP_IOXGET_32(isp, &src->ctp_rsp_bcnt, dst->ctp_rsp_bcnt);
ISP_IOXGET_32(isp, &src->ctp_cmd_bcnt, dst->ctp_cmd_bcnt);
for (i = 0; i < 2; i++) {
- ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_base,
- dst->ctp_dataseg[i].ds_base);
- ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_basehi,
- dst->ctp_dataseg[i].ds_basehi);
- ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_count,
- dst->ctp_dataseg[i].ds_count);
+ ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_base, dst->ctp_dataseg[i].ds_base);
+ ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_basehi, dst->ctp_dataseg[i].ds_basehi);
+ ISP_IOXGET_32(isp, &src->ctp_dataseg[i].ds_count, dst->ctp_dataseg[i].ds_count);
}
}
@@ -1063,12 +1603,9 @@ isp_get_ms(ispsoftc_t *isp, isp_ms_t *src, isp_ms_t *dst)
ISP_IOXGET_32(isp, &src->ms_rsp_bcnt, dst->ms_rsp_bcnt);
ISP_IOXGET_32(isp, &src->ms_cmd_bcnt, dst->ms_cmd_bcnt);
for (i = 0; i < 2; i++) {
- ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_base,
- dst->ms_dataseg[i].ds_base);
- ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_basehi,
- dst->ms_dataseg[i].ds_basehi);
- ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_count,
- dst->ms_dataseg[i].ds_count);
+ ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_base, dst->ms_dataseg[i].ds_base);
+ ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_basehi, dst->ms_dataseg[i].ds_basehi);
+ ISP_IOXGET_32(isp, &src->ms_dataseg[i].ds_count, dst->ms_dataseg[i].ds_count);
}
}
@@ -1082,23 +1619,20 @@ isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *src, isp_ct_pt_t *dst)
ISP_IOXPUT_16(isp, src->ctp_status, &dst->ctp_status);
ISP_IOXPUT_16(isp, src->ctp_nphdl, &dst->ctp_nphdl);
ISP_IOXPUT_16(isp, src->ctp_cmd_cnt, &dst->ctp_cmd_cnt);
- ISP_IOXPUT_16(isp, src->ctp_vpidx, &dst->ctp_vpidx);
+ ISP_IOXPUT_8(isp, src->ctp_vpidx, &dst->ctp_vpidx);
+ ISP_IOXPUT_8(isp, src->ctp_reserved0, &dst->ctp_reserved0);
ISP_IOXPUT_16(isp, src->ctp_time, &dst->ctp_time);
- ISP_IOXPUT_16(isp, src->ctp_reserved0, &dst->ctp_reserved0);
+ ISP_IOXPUT_16(isp, src->ctp_reserved1, &dst->ctp_reserved1);
ISP_IOXPUT_16(isp, src->ctp_rsp_cnt, &dst->ctp_rsp_cnt);
for (i = 0; i < 5; i++) {
- ISP_IOXPUT_16(isp, src->ctp_reserved1[i],
- &dst->ctp_reserved1[i]);
+ ISP_IOXPUT_16(isp, src->ctp_reserved2[i], &dst->ctp_reserved2[i]);
}
ISP_IOXPUT_32(isp, src->ctp_rsp_bcnt, &dst->ctp_rsp_bcnt);
ISP_IOXPUT_32(isp, src->ctp_cmd_bcnt, &dst->ctp_cmd_bcnt);
for (i = 0; i < 2; i++) {
- ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_base,
- &dst->ctp_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_basehi,
- &dst->ctp_dataseg[i].ds_basehi);
- ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_count,
- &dst->ctp_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_base, &dst->ctp_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_basehi, &dst->ctp_dataseg[i].ds_basehi);
+ ISP_IOXPUT_32(isp, src->ctp_dataseg[i].ds_count, &dst->ctp_dataseg[i].ds_count);
}
}
@@ -1123,12 +1657,9 @@ isp_put_ms(ispsoftc_t *isp, isp_ms_t *src, isp_ms_t *dst)
ISP_IOXPUT_32(isp, src->ms_rsp_bcnt, &dst->ms_rsp_bcnt);
ISP_IOXPUT_32(isp, src->ms_cmd_bcnt, &dst->ms_cmd_bcnt);
for (i = 0; i < 2; i++) {
- ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_base,
- &dst->ms_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_basehi,
- &dst->ms_dataseg[i].ds_basehi);
- ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_count,
- &dst->ms_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_base, &dst->ms_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_basehi, &dst->ms_dataseg[i].ds_basehi);
+ ISP_IOXPUT_32(isp, src->ms_dataseg[i].ds_count, &dst->ms_dataseg[i].ds_count);
}
}
@@ -1148,12 +1679,10 @@ isp_put_sns_request(ispsoftc_t *isp, sns_screq_t *src, sns_screq_t *dst)
for (i = 0; i < nw; i++) {
ISP_IOXPUT_16(isp, src->snscb_data[i], &dst->snscb_data[i]);
}
-
}
void
-isp_put_gid_ft_request(ispsoftc_t *isp, sns_gid_ft_req_t *src,
- sns_gid_ft_req_t *dst)
+isp_put_gid_ft_request(ispsoftc_t *isp, sns_gid_ft_req_t *src, sns_gid_ft_req_t *dst)
{
ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
ISP_IOXPUT_16(isp, src->snscb_reserved0, &dst->snscb_reserved0);
@@ -1170,8 +1699,7 @@ isp_put_gid_ft_request(ispsoftc_t *isp, sns_gid_ft_req_t *src,
}
void
-isp_put_gxn_id_request(ispsoftc_t *isp, sns_gxn_id_req_t *src,
- sns_gxn_id_req_t *dst)
+isp_put_gxn_id_request(ispsoftc_t *isp, sns_gxn_id_req_t *src, sns_gxn_id_req_t *dst)
{
ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
ISP_IOXPUT_16(isp, src->snscb_reserved0, &dst->snscb_reserved0);
@@ -1192,8 +1720,7 @@ isp_put_gxn_id_request(ispsoftc_t *isp, sns_gxn_id_req_t *src,
* isn't always 16 bit words.
*/
void
-isp_get_sns_response(ispsoftc_t *isp, sns_scrsp_t *src,
- sns_scrsp_t *dst, int nwords)
+isp_get_sns_response(ispsoftc_t *isp, sns_scrsp_t *src, sns_scrsp_t *dst, int nwords)
{
int i;
isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
@@ -1212,20 +1739,15 @@ isp_get_sns_response(ispsoftc_t *isp, sns_scrsp_t *src,
}
void
-isp_get_gid_ft_response(ispsoftc_t *isp, sns_gid_ft_rsp_t *src,
- sns_gid_ft_rsp_t *dst, int nwords)
+isp_get_gid_ft_response(ispsoftc_t *isp, sns_gid_ft_rsp_t *src, sns_gid_ft_rsp_t *dst, int nwords)
{
int i;
isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
for (i = 0; i < nwords; i++) {
int j;
- ISP_IOXGET_8(isp,
- &src->snscb_ports[i].control,
- dst->snscb_ports[i].control);
+ ISP_IOXGET_8(isp, &src->snscb_ports[i].control, dst->snscb_ports[i].control);
for (j = 0; j < 3; j++) {
- ISP_IOXGET_8(isp,
- &src->snscb_ports[i].portid[j],
- dst->snscb_ports[i].portid[j]);
+ ISP_IOXGET_8(isp, &src->snscb_ports[i].portid[j], dst->snscb_ports[i].portid[j]);
}
if (dst->snscb_ports[i].control & 0x80) {
break;
@@ -1234,76 +1756,66 @@ isp_get_gid_ft_response(ispsoftc_t *isp, sns_gid_ft_rsp_t *src,
}
void
-isp_get_gxn_id_response(ispsoftc_t *isp, sns_gxn_id_rsp_t *src,
- sns_gxn_id_rsp_t *dst)
+isp_get_gxn_id_response(ispsoftc_t *isp, sns_gxn_id_rsp_t *src, sns_gxn_id_rsp_t *dst)
{
int i;
isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
ISP_IOXGET_8(isp, &src->snscb_wwn[i], dst->snscb_wwn[i]);
+ }
}
void
-isp_get_gff_id_response(ispsoftc_t *isp, sns_gff_id_rsp_t *src,
- sns_gff_id_rsp_t *dst)
+isp_get_gff_id_response(ispsoftc_t *isp, sns_gff_id_rsp_t *src, sns_gff_id_rsp_t *dst)
{
int i;
isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
for (i = 0; i < 32; i++) {
- ISP_IOXGET_32(isp, &src->snscb_fc4_features[i],
- dst->snscb_fc4_features[i]);
+ ISP_IOXGET_32(isp, &src->snscb_fc4_features[i], dst->snscb_fc4_features[i]);
}
}
void
-isp_get_ga_nxt_response(ispsoftc_t *isp, sns_ga_nxt_rsp_t *src,
- sns_ga_nxt_rsp_t *dst)
+isp_get_ga_nxt_response(ispsoftc_t *isp, sns_ga_nxt_rsp_t *src, sns_ga_nxt_rsp_t *dst)
{
int i;
isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
ISP_IOXGET_8(isp, &src->snscb_port_type, dst->snscb_port_type);
for (i = 0; i < 3; i++) {
- ISP_IOXGET_8(isp, &src->snscb_port_id[i],
- dst->snscb_port_id[i]);
+ ISP_IOXGET_8(isp, &src->snscb_port_id[i], dst->snscb_port_id[i]);
}
for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->snscb_portname[i],
- dst->snscb_portname[i]);
+ ISP_IOXGET_8(isp, &src->snscb_portname[i], dst->snscb_portname[i]);
}
ISP_IOXGET_8(isp, &src->snscb_pnlen, dst->snscb_pnlen);
for (i = 0; i < 255; i++) {
ISP_IOXGET_8(isp, &src->snscb_pname[i], dst->snscb_pname[i]);
}
for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->snscb_nodename[i],
- dst->snscb_nodename[i]);
+ ISP_IOXGET_8(isp, &src->snscb_nodename[i], dst->snscb_nodename[i]);
}
ISP_IOXGET_8(isp, &src->snscb_nnlen, dst->snscb_nnlen);
for (i = 0; i < 255; i++) {
ISP_IOXGET_8(isp, &src->snscb_nname[i], dst->snscb_nname[i]);
}
for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->snscb_ipassoc[i],
- dst->snscb_ipassoc[i]);
+ ISP_IOXGET_8(isp, &src->snscb_ipassoc[i], dst->snscb_ipassoc[i]);
}
for (i = 0; i < 16; i++) {
ISP_IOXGET_8(isp, &src->snscb_ipaddr[i], dst->snscb_ipaddr[i]);
}
for (i = 0; i < 4; i++) {
- ISP_IOXGET_8(isp, &src->snscb_svc_class[i],
- dst->snscb_svc_class[i]);
+ ISP_IOXGET_8(isp, &src->snscb_svc_class[i], dst->snscb_svc_class[i]);
}
for (i = 0; i < 32; i++) {
- ISP_IOXGET_8(isp, &src->snscb_fc4_types[i],
- dst->snscb_fc4_types[i]);
+ ISP_IOXGET_8(isp, &src->snscb_fc4_types[i], dst->snscb_fc4_types[i]);
}
for (i = 0; i < 8; i++) {
ISP_IOXGET_8(isp, &src->snscb_fpname[i], dst->snscb_fpname[i]);
}
ISP_IOXGET_8(isp, &src->snscb_reserved, dst->snscb_reserved);
for (i = 0; i < 3; i++) {
- ISP_IOXGET_8(isp, &src->snscb_hardaddr[i],
- dst->snscb_hardaddr[i]);
+ ISP_IOXGET_8(isp, &src->snscb_hardaddr[i], dst->snscb_hardaddr[i]);
}
}
@@ -1333,8 +1845,7 @@ isp_get_els(ispsoftc_t *isp, els_t *src, els_t *dst)
ISP_IOXGET_32(isp, &src->els_subcode1, dst->els_subcode1);
ISP_IOXGET_32(isp, &src->els_subcode2, dst->els_subcode2);
for (i = 0; i < 20; i++) {
- ISP_IOXGET_8(isp, &src->els_reserved4[i],
- dst->els_reserved4[i]);
+ ISP_IOXGET_8(isp, &src->els_reserved4[i], dst->els_reserved4[i]);
}
}
@@ -1388,19 +1899,14 @@ isp_get_fc_hdr(ispsoftc_t *isp, fc_hdr_t *src, fc_hdr_t *dst)
ISP_IOZGET_8(isp, &src->s_id[1], dst->s_id[1]);
ISP_IOZGET_8(isp, &src->s_id[2], dst->s_id[2]);
ISP_IOZGET_8(isp, &src->type, dst->type);
- ISP_IOZGET_8(isp, &src->f_ctl, dst->f_ctl);
+ ISP_IOZGET_8(isp, &src->f_ctl[0], dst->f_ctl[0]);
+ ISP_IOZGET_8(isp, &src->f_ctl[1], dst->f_ctl[1]);
+ ISP_IOZGET_8(isp, &src->f_ctl[2], dst->f_ctl[2]);
ISP_IOZGET_8(isp, &src->seq_id, dst->seq_id);
ISP_IOZGET_8(isp, &src->df_ctl, dst->df_ctl);
ISP_IOZGET_16(isp, &src->seq_cnt, dst->seq_cnt);
- /* XXX SOMETHING WAS AND STILL CONTINUES WRONG HERE XXX */
-#if 0
ISP_IOZGET_16(isp, &src->ox_id, dst->ox_id);
ISP_IOZGET_16(isp, &src->rx_id, dst->rx_id);
-#else
- ISP_IOZGET_32(isp, &src->ox_id, dst->parameter);
- dst->ox_id = dst->parameter;
- dst->rx_id = dst->parameter >> 16;
-#endif
ISP_IOZGET_32(isp, &src->parameter, dst->parameter);
}
@@ -1413,18 +1919,13 @@ isp_get_fcp_cmnd_iu(ispsoftc_t *isp, fcp_cmnd_iu_t *src, fcp_cmnd_iu_t *dst)
ISP_IOZGET_8(isp, &src->fcp_cmnd_lun[i], dst->fcp_cmnd_lun[i]);
}
ISP_IOZGET_8(isp, &src->fcp_cmnd_crn, dst->fcp_cmnd_crn);
- ISP_IOZGET_8(isp, &src->fcp_cmnd_task_attribute,
- dst->fcp_cmnd_task_attribute);
- ISP_IOZGET_8(isp, &src->fcp_cmnd_task_management,
- dst->fcp_cmnd_task_management);
- ISP_IOZGET_8(isp, &src->fcp_cmnd_alen_datadir,
- dst->fcp_cmnd_alen_datadir);
+ ISP_IOZGET_8(isp, &src->fcp_cmnd_task_attribute, dst->fcp_cmnd_task_attribute);
+ ISP_IOZGET_8(isp, &src->fcp_cmnd_task_management, dst->fcp_cmnd_task_management);
+ ISP_IOZGET_8(isp, &src->fcp_cmnd_alen_datadir, dst->fcp_cmnd_alen_datadir);
for (i = 0; i < 16; i++) {
- ISP_IOZGET_8(isp, &src->cdb_dl.sf.fcp_cmnd_cdb[i],
- dst->cdb_dl.sf.fcp_cmnd_cdb[i]);
+ ISP_IOZGET_8(isp, &src->cdb_dl.sf.fcp_cmnd_cdb[i], dst->cdb_dl.sf.fcp_cmnd_cdb[i]);
}
- ISP_IOZGET_32(isp, &src->cdb_dl.sf.fcp_cmnd_dl,
- dst->cdb_dl.sf.fcp_cmnd_dl);
+ ISP_IOZGET_32(isp, &src->cdb_dl.sf.fcp_cmnd_dl, dst->cdb_dl.sf.fcp_cmnd_dl);
}
void
@@ -1437,8 +1938,7 @@ isp_put_rft_id(ispsoftc_t *isp, rft_id_t *src, rft_id_t *dst)
ISP_IOZPUT_8(isp, src->rftid_portid[i], &dst->rftid_portid[i]);
}
for (i = 0; i < 8; i++) {
- ISP_IOZPUT_32(isp, src->rftid_fc4types[i],
- &dst->rftid_fc4types[i]);
+ ISP_IOZPUT_32(isp, src->rftid_fc4types[i], &dst->rftid_fc4types[i]);
}
}
@@ -1481,6 +1981,253 @@ isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst)
}
#ifdef ISP_TARGET_MODE
+
+/*
+ * Command shipping- finish off first queue entry and do dma mapping and
+ * additional segments as needed.
+ *
+ * Called with the first queue entry at least partially filled out.
+ */
+int
+isp_send_tgt_cmd(ispsoftc_t *isp, void *fqe, void *segp, uint32_t nsegs, uint32_t totalcnt, isp_ddir_t ddir, void *snsptr, uint32_t snslen)
+{
+ uint8_t storage[QENTRY_LEN], storage2[QENTRY_LEN];
+ uint8_t type, nqe;
+ uint32_t seg, curseg, seglim, nxt, nxtnxt;
+ ispds_t *dsp = NULL;
+ ispds64_t *dsp64 = NULL;
+ void *qe0, *qe1, *sqe = NULL;
+
+ qe0 = isp_getrqentry(isp);
+ if (qe0 == NULL) {
+ return (CMD_EAGAIN);
+ }
+ nxt = ISP_NXT_QENTRY(isp->isp_reqidx, RQUEST_QUEUE_LEN(isp));
+
+ type = ((isphdr_t *)fqe)->rqs_entry_type;
+ nqe = 1;
+ seglim = 0;
+
+ /*
+ * If we have no data to transmit, just copy the first IOCB and start it up.
+ */
+ if (ddir != ISP_NOXFR) {
+ /*
+ * First, figure out how many pieces of data to transfer and what kind and how many we can put into the first queue entry.
+ */
+ switch (type) {
+ case RQSTYPE_CTIO:
+ dsp = ((ct_entry_t *)fqe)->ct_dataseg;
+ seglim = ISP_RQDSEG;
+ break;
+ case RQSTYPE_CTIO2:
+ case RQSTYPE_CTIO3:
+ {
+ ct2_entry_t *ct = fqe, *ct2 = (ct2_entry_t *) storage2;
+ uint16_t swd = ct->rsp.m0.ct_scsi_status & 0xff;
+
+ if ((ct->ct_flags & CT2_SENDSTATUS) && (swd || ct->ct_resid)) {
+ memcpy(ct2, ct, QENTRY_LEN);
+ /*
+ * Clear fields from first CTIO2 that now need to be cleared
+ */
+ ct->ct_header.rqs_seqno = 0;
+ ct->ct_flags &= ~(CT2_SENDSTATUS|CT2_CCINCR|CT2_FASTPOST);
+ ct->ct_resid = 0;
+ ct->ct_syshandle = 0;
+ ct->rsp.m0.ct_scsi_status = 0;
+
+ /*
+ * Reset fields in the second CTIO2 as appropriate.
+ */
+ ct2->ct_flags &= ~(CT2_FLAG_MMASK|CT2_DATAMASK|CT2_FASTPOST);
+ ct2->ct_flags |= CT2_NO_DATA|CT2_FLAG_MODE1;
+ ct2->ct_seg_count = 0;
+ ct2->ct_reloff = 0;
+ memset(&ct2->rsp, 0, sizeof (ct2->rsp));
+ if (swd == SCSI_CHECK && snsptr && snslen) {
+ ct2->rsp.m1.ct_senselen = min(snslen, MAXRESPLEN);
+ memcpy(ct2->rsp.m1.ct_resp, snsptr, ct2->rsp.m1.ct_senselen);
+ swd |= CT2_SNSLEN_VALID;
+ }
+ if (ct2->ct_resid > 0) {
+ swd |= CT2_DATA_UNDER;
+ } else if (ct2->ct_resid < 0) {
+ swd |= CT2_DATA_OVER;
+ }
+ ct2->rsp.m1.ct_scsi_status = swd;
+ sqe = storage2;
+ }
+ if (type == RQSTYPE_CTIO2) {
+ dsp = ct->rsp.m0.u.ct_dataseg;
+ seglim = ISP_RQDSEG_T2;
+ } else {
+ dsp64 = ct->rsp.m0.u.ct_dataseg64;
+ seglim = ISP_RQDSEG_T3;
+ }
+ break;
+ }
+ case RQSTYPE_CTIO7:
+ {
+ ct7_entry_t *ct = fqe, *ct2 = (ct7_entry_t *)storage2;
+ uint16_t swd = ct->ct_scsi_status & 0xff;
+
+ dsp64 = &ct->rsp.m0.ds;
+ seglim = 1;
+ if ((ct->ct_flags & CT7_SENDSTATUS) && (swd || ct->ct_resid)) {
+ memcpy(ct2, ct, sizeof (ct7_entry_t));
+
+ /*
+ * Clear fields from first CTIO7 that now need to be cleared
+ */
+ ct->ct_header.rqs_seqno = 0;
+ ct->ct_flags &= ~CT7_SENDSTATUS;
+ ct->ct_resid = 0;
+ ct->ct_syshandle = 0;
+ ct->ct_scsi_status = 0;
+
+ /*
+ * Reset fields in the second CTIO7 as appropriate.
+ */
+ ct2->ct_flags &= ~(CT7_FLAG_MMASK|CT7_DATAMASK);
+ ct2->ct_flags |= CT7_NO_DATA|CT7_NO_DATA|CT7_FLAG_MODE1;
+ ct2->ct_seg_count = 0;
+ memset(&ct2->rsp, 0, sizeof (ct2->rsp));
+ if (swd == SCSI_CHECK && snsptr && snslen) {
+ ct2->rsp.m1.ct_resplen = min(snslen, MAXRESPLEN_24XX);
+ memcpy(ct2->rsp.m1.ct_resp, snsptr, ct2->rsp.m1.ct_resplen);
+ swd |= (FCP_SNSLEN_VALID << 8);
+ }
+ if (ct2->ct_resid < 0) {
+ swd |= (FCP_RESID_OVERFLOW << 8);
+ } else if (ct2->ct_resid > 0) {
+ swd |= (FCP_RESID_UNDERFLOW << 8);
+ }
+ ct2->ct_scsi_status = swd;
+ sqe = storage2;
+ }
+ break;
+ }
+ default:
+ return (CMD_COMPLETE);
+ }
+ }
+
+ /*
+ * Fill out the data transfer stuff in the first queue entry
+ */
+ if (seglim > nsegs) {
+ seglim = nsegs;
+ }
+
+ for (seg = curseg = 0; curseg < seglim; curseg++) {
+ if (dsp64) {
+ XS_GET_DMA64_SEG(dsp64++, segp, seg++);
+ } else {
+ XS_GET_DMA_SEG(dsp++, segp, seg++);
+ }
+ }
+
+ /*
+ * First, if we are sending status with data and we have a non-zero
+ * status or non-zero residual, we have to make a synthetic extra CTIO
+ * that contains the status that we'll ship separately (FC cards only).
+ */
+
+ /*
+ * Second, start building additional continuation segments as needed.
+ */
+ while (seg < nsegs) {
+ nxtnxt = ISP_NXT_QENTRY(nxt, RQUEST_QUEUE_LEN(isp));
+ if (nxtnxt == isp->isp_reqodx) {
+ return (CMD_EAGAIN);
+ }
+ ISP_MEMZERO(storage, QENTRY_LEN);
+ qe1 = ISP_QUEUE_ENTRY(isp->isp_rquest, nxt);
+ nxt = nxtnxt;
+ if (dsp64) {
+ ispcontreq64_t *crq = (ispcontreq64_t *) storage;
+ seglim = ISP_CDSEG64;
+ crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT;
+ crq->req_header.rqs_entry_count = 1;
+ dsp64 = crq->req_dataseg;
+ } else {
+ ispcontreq_t *crq = (ispcontreq_t *) storage;
+ seglim = ISP_CDSEG;
+ crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
+ crq->req_header.rqs_entry_count = 1;
+ dsp = crq->req_dataseg;
+ }
+ if (seg + seglim > nsegs) {
+ seglim = nsegs - seg;
+ }
+ for (curseg = 0; curseg < seglim; curseg++) {
+ if (dsp64) {
+ XS_GET_DMA64_SEG(dsp64++, segp, seg++);
+ } else {
+ XS_GET_DMA_SEG(dsp++, segp, seg++);
+ }
+ }
+ if (dsp64) {
+ isp_put_cont64_req(isp, (ispcontreq64_t *)storage, qe1);
+ } else {
+ isp_put_cont_req(isp, (ispcontreq_t *)storage, qe1);
+ }
+ if (isp->isp_dblev & ISP_LOGTDEBUG1) {
+ isp_print_bytes(isp, "additional queue entry", QENTRY_LEN, storage);
+ }
+ nqe++;
+ }
+
+ /*
+ * If we have a synthetic queue entry to complete things, do it here.
+ */
+ if (sqe) {
+ nxtnxt = ISP_NXT_QENTRY(nxt, RQUEST_QUEUE_LEN(isp));
+ if (nxtnxt == isp->isp_reqodx) {
+ return (CMD_EAGAIN);
+ }
+ qe1 = ISP_QUEUE_ENTRY(isp->isp_rquest, nxt);
+ nxt = nxtnxt;
+ if (type == RQSTYPE_CTIO7) {
+ isp_put_ctio7(isp, sqe, qe1);
+ } else {
+ isp_put_ctio2(isp, sqe, qe1);
+ }
+ if (isp->isp_dblev & ISP_LOGTDEBUG1) {
+ isp_print_bytes(isp, "synthetic final queue entry", QENTRY_LEN, storage2);
+ }
+ }
+
+ ((isphdr_t *)fqe)->rqs_entry_count = nqe;
+ switch (type) {
+ case RQSTYPE_CTIO:
+ ((ct_entry_t *)fqe)->ct_seg_count = nsegs;
+ isp_put_ctio(isp, fqe, qe0);
+ break;
+ case RQSTYPE_CTIO2:
+ case RQSTYPE_CTIO3:
+ ((ct2_entry_t *)fqe)->ct_seg_count = nsegs;
+ if (ISP_CAP_2KLOGIN(isp)) {
+ isp_put_ctio2e(isp, fqe, qe0);
+ } else {
+ isp_put_ctio2(isp, fqe, qe0);
+ }
+ break;
+ case RQSTYPE_CTIO7:
+ ((ct7_entry_t *)fqe)->ct_seg_count = nsegs;
+ isp_put_ctio7(isp, fqe, qe0);
+ break;
+ default:
+ return (CMD_COMPLETE);
+ }
+ if (isp->isp_dblev & ISP_LOGTDEBUG1) {
+ isp_print_bytes(isp, "first queue entry", QENTRY_LEN, fqe);
+ }
+ ISP_ADD_REQUEST(isp, nxt);
+ return (CMD_QUEUED);
+}
+
int
isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint32_t *handlep)
{
@@ -1502,9 +2249,8 @@ isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint32_t *handlep)
void *
isp_find_xs_tgt(ispsoftc_t *isp, uint32_t handle)
{
- if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 ||
- (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) {
- isp_prt(isp, ISP_LOGERR, "bad handle in isp_find_xs_tgt");
+ if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 || (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) {
+ isp_prt(isp, ISP_LOGERR, "bad handle %u in isp_find_xs_tgt", handle);
return (NULL);
} else {
return (isp->isp_tgtlist[(handle & ISP_HANDLE_MASK) - 1]);
@@ -1518,7 +2264,11 @@ isp_find_tgt_handle(ispsoftc_t *isp, void *xs)
if (xs != NULL) {
for (i = 0; i < isp->isp_maxcmds; i++) {
if (isp->isp_tgtlist[i] == xs) {
- return ((i+1) & ISP_HANDLE_MASK);
+ uint32_t handle = i;
+ handle += 1;
+ handle &= ISP_HANDLE_MASK;
+ handle |= 0x8000;
+ return (handle);
}
}
}
@@ -1528,15 +2278,358 @@ isp_find_tgt_handle(ispsoftc_t *isp, void *xs)
void
isp_destroy_tgt_handle(ispsoftc_t *isp, uint32_t handle)
{
- if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 ||
- (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) {
- isp_prt(isp, ISP_LOGERR,
- "bad handle in isp_destroy_tgt_handle");
+ if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 || (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) {
+ isp_prt(isp, ISP_LOGERR, "bad handle in isp_destroy_tgt_handle");
} else {
isp->isp_tgtlist[(handle & ISP_HANDLE_MASK) - 1] = NULL;
}
}
+/*
+ * Find target mode entries
+ */
+int
+isp_find_pdb_by_wwn(ispsoftc_t *isp, int chan, uint64_t wwn, fcportdb_t **lptr)
+{
+ fcparam *fcp;
+ int i;
+
+ if (chan < isp->isp_nchan) {
+ fcp = FCPARAM(isp, chan);
+ for (i = 0; i < MAX_FC_TARG; i++) {
+ fcportdb_t *lp = &fcp->portdb[i];
+
+ if (lp->target_mode == 0) {
+ continue;
+ }
+ if (lp->port_wwn == wwn) {
+ *lptr = lp;
+ return (1);
+ }
+ }
+ }
+ return (0);
+}
+
+int
+isp_find_pdb_by_loopid(ispsoftc_t *isp, int chan, uint32_t loopid, fcportdb_t **lptr)
+{
+ fcparam *fcp;
+ int i;
+
+ if (chan < isp->isp_nchan) {
+ fcp = FCPARAM(isp, chan);
+ for (i = 0; i < MAX_FC_TARG; i++) {
+ fcportdb_t *lp = &fcp->portdb[i];
+
+ if (lp->target_mode == 0) {
+ continue;
+ }
+ if (lp->handle == loopid) {
+ *lptr = lp;
+ return (1);
+ }
+ }
+ }
+ return (0);
+}
+
+int
+isp_find_pdb_by_sid(ispsoftc_t *isp, int chan, uint32_t sid, fcportdb_t **lptr)
+{
+ fcparam *fcp;
+ int i;
+
+ if (chan >= isp->isp_nchan) {
+ return (0);
+ }
+
+ fcp = FCPARAM(isp, chan);
+ for (i = 0; i < MAX_FC_TARG; i++) {
+ fcportdb_t *lp = &fcp->portdb[i];
+
+ if (lp->target_mode == 0) {
+ continue;
+ }
+ if (lp->portid == sid) {
+ *lptr = lp;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+void
+isp_find_chan_by_did(ispsoftc_t *isp, uint32_t did, uint16_t *cp)
+{
+ uint16_t chan;
+
+ *cp = ISP_NOCHAN;
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ fcparam *fcp = FCPARAM(isp, chan);
+ if ((fcp->role & ISP_ROLE_TARGET) == 0 || fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) {
+ continue;
+ }
+ if (fcp->isp_portid == did) {
+ *cp = chan;
+ break;
+ }
+ }
+}
+
+/*
+ * Add an initiator device to the port database
+ */
+void
+isp_add_wwn_entry(ispsoftc_t *isp, int chan, uint64_t ini, uint16_t nphdl, uint32_t s_id)
+{
+ fcparam *fcp;
+ fcportdb_t *lp;
+ isp_notify_t nt;
+ int i;
+
+ fcp = FCPARAM(isp, chan);
+
+ if (nphdl >= MAX_NPORT_HANDLE) {
+ isp_prt(isp, ISP_LOGWARN, "%s: Chan %d IID 0x%016llx bad N-Port handle 0x%04x Port ID 0x%06x",
+ __func__, chan, (unsigned long long) ini, nphdl, s_id);
+ return;
+ }
+
+ lp = NULL;
+ if (fcp->isp_tgt_map[nphdl]) {
+ lp = &fcp->portdb[fcp->isp_tgt_map[nphdl] - 1];
+ } else {
+ /*
+ * Make sure the addition of a new target mode entry doesn't duplicate entries
+ * with the same N-Port handles, the same portids or the same Port WWN.
+ */
+ for (i = 0; i < MAX_FC_TARG; i++) {
+ lp = &fcp->portdb[i];
+ if (lp->target_mode == 0) {
+ lp = NULL;
+ continue;
+ }
+ if (lp->handle == nphdl) {
+ break;
+ }
+ if (s_id != PORT_ANY && lp->portid == s_id) {
+ break;
+ }
+ if (VALID_INI(ini) && lp->port_wwn == ini) {
+ break;
+ }
+ lp = NULL;
+ }
+
+ }
+
+ if (lp) {
+ int something = 0;
+ if (lp->handle != nphdl) {
+ isp_prt(isp, ISP_LOGWARN, "%s: Chan %d attempt to re-enter N-port handle 0x%04x IID 0x%016llx Port ID 0x%06x finds IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x",
+ __func__, chan, nphdl, (unsigned long long)ini, s_id, (unsigned long long) lp->port_wwn, lp->handle, lp->portid);
+ isp_dump_portdb(isp, chan);
+ return;
+ }
+ if (s_id != PORT_NONE) {
+ if (lp->portid == PORT_NONE) {
+ lp->portid = s_id;
+ isp_prt(isp, ISP_LOGTINFO, "%s: Chan %d N-port handle 0x%04x gets Port ID 0x%06x", __func__, chan, nphdl, s_id);
+ something++;
+ } else if (lp->portid != s_id) {
+ isp_prt(isp, ISP_LOGTINFO, "%s: Chan %d N-port handle 0x%04x tries to change Port ID 0x%06x to 0x%06x", __func__, chan, nphdl,
+ lp->portid, s_id);
+ isp_dump_portdb(isp, chan);
+ return;
+ }
+ }
+ if (VALID_INI(ini)) {
+ if (!VALID_INI(lp->port_wwn)) {
+ lp->port_wwn = ini;
+ isp_prt(isp, ISP_LOGTINFO, "%s: Chan %d N-port handle 0x%04x gets WWN 0x%016llxx", __func__, chan, nphdl, (unsigned long long) ini);
+ something++;
+ } else if (lp->port_wwn != ini) {
+ isp_prt(isp, ISP_LOGWARN, "%s: Chan %d N-port handle 0x%04x tries to change WWN 0x%016llx to 0x%016llx", __func__, chan, nphdl,
+ (unsigned long long) lp->port_wwn, (unsigned long long) ini);
+ isp_dump_portdb(isp, chan);
+ return;
+ }
+ }
+
+ if (!something) {
+ isp_prt(isp, ISP_LOGWARN, "%s: Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x reentered", __func__, chan,
+ (unsigned long long) lp->port_wwn, lp->handle, lp->portid);
+ }
+ return;
+ }
+
+ /*
+ * Find a new spot
+ */
+ for (i = MAX_FC_TARG - 1; i >= 0; i--) {
+ if (fcp->portdb[i].target_mode == 1) {
+ continue;
+ }
+ if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) {
+ break;
+ }
+ }
+ if (i < 0) {
+ isp_prt(isp, ISP_LOGWARN, "%s: Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x- no room in port database",
+ __func__, chan, (unsigned long long) ini, nphdl, s_id);
+ return;
+ }
+
+ lp = &fcp->portdb[i];
+ ISP_MEMZERO(lp, sizeof (fcportdb_t));
+ lp->target_mode = 1;
+ lp->handle = nphdl;
+ lp->portid = s_id;
+ lp->port_wwn = ini;
+ fcp->isp_tgt_map[nphdl] = i + 1;
+
+ isp_prt(isp, ISP_LOGTINFO, "%s: Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x vtgt %d added", __func__, chan, (unsigned long long) ini, nphdl, s_id, fcp->isp_tgt_map[nphdl] - 1);
+
+ ISP_MEMZERO(&nt, sizeof (nt));
+ nt.nt_hba = isp;
+ nt.nt_wwn = ini;
+ nt.nt_tgt = FCPARAM(isp, chan)->isp_wwpn;
+ nt.nt_sid = s_id;
+ nt.nt_did = FCPARAM(isp, chan)->isp_portid;
+ nt.nt_nphdl = nphdl;
+ nt.nt_channel = chan;
+ nt.nt_ncode = NT_ARRIVED;
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
+}
+
+/*
+ * Remove a target device to the port database
+ */
+void
+isp_del_wwn_entry(ispsoftc_t *isp, int chan, uint64_t ini, uint16_t nphdl, uint32_t s_id)
+{
+ fcparam *fcp;
+ isp_notify_t nt;
+ fcportdb_t *lp;
+
+ if (nphdl >= MAX_NPORT_HANDLE) {
+ isp_prt(isp, ISP_LOGWARN, "%s: Chan %d IID 0x%016llx bad N-Port handle 0x%04x Port ID 0x%06x",
+ __func__, chan, (unsigned long long) ini, nphdl, s_id);
+ return;
+ }
+
+ fcp = FCPARAM(isp, chan);
+ if (fcp->isp_tgt_map[nphdl] == 0) {
+ lp = NULL;
+ } else {
+ lp = &fcp->portdb[fcp->isp_tgt_map[nphdl] - 1];
+ if (lp->target_mode == 0) {
+ lp = NULL;
+ }
+ }
+ if (lp == NULL) {
+ isp_prt(isp, ISP_LOGWARN, "%s: Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x cannot be found to be cleared",
+ __func__, chan, (unsigned long long) ini, nphdl, s_id);
+ isp_dump_portdb(isp, chan);
+ return;
+ }
+ isp_prt(isp, ISP_LOGTINFO, "%s: Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x vtgt %d cleared",
+ __func__, chan, (unsigned long long) lp->port_wwn, nphdl, lp->portid, fcp->isp_tgt_map[nphdl] - 1);
+ fcp->isp_tgt_map[nphdl] = 0;
+
+ ISP_MEMZERO(&nt, sizeof (nt));
+ nt.nt_hba = isp;
+ nt.nt_wwn = lp->port_wwn;
+ nt.nt_tgt = FCPARAM(isp, chan)->isp_wwpn;
+ nt.nt_sid = lp->portid;
+ nt.nt_did = FCPARAM(isp, chan)->isp_portid;
+ nt.nt_nphdl = nphdl;
+ nt.nt_channel = chan;
+ nt.nt_ncode = NT_DEPARTED;
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
+}
+
+void
+isp_del_all_wwn_entries(ispsoftc_t *isp, int chan)
+{
+ fcparam *fcp;
+ int i;
+
+ if (!IS_FC(isp)) {
+ return;
+ }
+
+ /*
+ * Handle iterations over all channels via recursion
+ */
+ if (chan == ISP_NOCHAN) {
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ isp_del_all_wwn_entries(isp, chan);
+ }
+ return;
+ }
+
+ if (chan > isp->isp_nchan) {
+ return;
+ }
+
+ fcp = FCPARAM(isp, chan);
+ if (fcp == NULL) {
+ return;
+ }
+ for (i = 0; i < MAX_NPORT_HANDLE; i++) {
+ if (fcp->isp_tgt_map[i]) {
+ fcportdb_t *lp = &fcp->portdb[fcp->isp_tgt_map[i] - 1];
+ isp_del_wwn_entry(isp, chan, lp->port_wwn, lp->handle, lp->portid);
+ }
+ }
+}
+
+void
+isp_del_wwn_entries(ispsoftc_t *isp, isp_notify_t *mp)
+{
+ fcportdb_t *lp;
+
+ /*
+ * Handle iterations over all channels via recursion
+ */
+ if (mp->nt_channel == ISP_NOCHAN) {
+ for (mp->nt_channel = 0; mp->nt_channel < isp->isp_nchan; mp->nt_channel++) {
+ isp_del_wwn_entries(isp, mp);
+ }
+ mp->nt_channel = ISP_NOCHAN;
+ return;
+ }
+
+ /*
+ * We have an entry which is only partially identified.
+ *
+ * It's only known by WWN, N-Port handle, or Port ID.
+ * We need to find the actual entry so we can delete it.
+ */
+ if (mp->nt_nphdl != NIL_HANDLE) {
+ if (isp_find_pdb_by_loopid(isp, mp->nt_channel, mp->nt_nphdl, &lp)) {
+ isp_del_wwn_entry(isp, mp->nt_channel, lp->port_wwn, lp->handle, lp->portid);
+ return;
+ }
+ }
+ if (mp->nt_wwn != INI_ANY) {
+ if (isp_find_pdb_by_wwn(isp, mp->nt_channel, mp->nt_wwn, &lp)) {
+ isp_del_wwn_entry(isp, mp->nt_channel, lp->port_wwn, lp->handle, lp->portid);
+ return;
+ }
+ }
+ if (mp->nt_sid != PORT_ANY && mp->nt_sid != PORT_NONE) {
+ if (isp_find_pdb_by_sid(isp, mp->nt_channel, mp->nt_sid, &lp)) {
+ isp_del_wwn_entry(isp, mp->nt_channel, lp->port_wwn, lp->handle, lp->portid);
+ return;
+ }
+ }
+ isp_prt(isp, ISP_LOGWARN, "%s: Chan %d unable to find entry to delete N-port handle 0x%04x initiator WWN 0x%016llx Port ID 0x%06x", __func__,
+ mp->nt_channel, mp->nt_nphdl, (unsigned long long) mp->nt_wwn, mp->nt_sid);
+}
+
void
isp_put_atio(ispsoftc_t *isp, at_entry_t *src, at_entry_t *dst)
{
@@ -1559,8 +2652,7 @@ isp_put_atio(ispsoftc_t *isp, at_entry_t *src, at_entry_t *dst)
ISP_IOXPUT_8(isp, src->at_cdblen, &dst->at_cdblen);
ISP_IOXPUT_8(isp, src->at_tgt, &dst->at_tgt);
ISP_IOXPUT_8(isp, src->at_status, &dst->at_status);
- ISP_IOXPUT_8(isp, src->at_scsi_status,
- &dst->at_scsi_status);
+ ISP_IOXPUT_8(isp, src->at_scsi_status, &dst->at_scsi_status);
ISP_IOXPUT_8(isp, src->at_tag_val, &dst->at_tag_val);
ISP_IOXPUT_8(isp, src->at_tag_type, &dst->at_tag_type);
}
@@ -1595,8 +2687,7 @@ isp_get_atio(ispsoftc_t *isp, at_entry_t *src, at_entry_t *dst)
ISP_IOXGET_8(isp, &src->at_cdblen, dst->at_cdblen);
ISP_IOXGET_8(isp, &src->at_tgt, dst->at_tgt);
ISP_IOXGET_8(isp, &src->at_status, dst->at_status);
- ISP_IOXGET_8(isp, &src->at_scsi_status,
- dst->at_scsi_status);
+ ISP_IOXGET_8(isp, &src->at_scsi_status, dst->at_scsi_status);
ISP_IOXGET_8(isp, &src->at_tag_val, dst->at_tag_val);
ISP_IOXGET_8(isp, &src->at_tag_type, dst->at_tag_type);
}
@@ -1633,8 +2724,7 @@ isp_put_atio2(ispsoftc_t *isp, at2_entry_t *src, at2_entry_t *dst)
ISP_IOXPUT_16(isp, src->at_wwpn[i], &dst->at_wwpn[i]);
}
for (i = 0; i < 6; i++) {
- ISP_IOXPUT_16(isp, src->at_reserved2[i],
- &dst->at_reserved2[i]);
+ ISP_IOXPUT_16(isp, src->at_reserved2[i], &dst->at_reserved2[i]);
}
ISP_IOXPUT_16(isp, src->at_oxid, &dst->at_oxid);
}
@@ -1662,8 +2752,7 @@ isp_put_atio2e(ispsoftc_t *isp, at2e_entry_t *src, at2e_entry_t *dst)
ISP_IOXPUT_16(isp, src->at_wwpn[i], &dst->at_wwpn[i]);
}
for (i = 0; i < 6; i++) {
- ISP_IOXPUT_16(isp, src->at_reserved2[i],
- &dst->at_reserved2[i]);
+ ISP_IOXPUT_16(isp, src->at_reserved2[i], &dst->at_reserved2[i]);
}
ISP_IOXPUT_16(isp, src->at_oxid, &dst->at_oxid);
}
@@ -1692,8 +2781,7 @@ isp_get_atio2(ispsoftc_t *isp, at2_entry_t *src, at2_entry_t *dst)
ISP_IOXGET_16(isp, &src->at_wwpn[i], dst->at_wwpn[i]);
}
for (i = 0; i < 6; i++) {
- ISP_IOXGET_16(isp, &src->at_reserved2[i],
- dst->at_reserved2[i]);
+ ISP_IOXGET_16(isp, &src->at_reserved2[i], dst->at_reserved2[i]);
}
ISP_IOXGET_16(isp, &src->at_oxid, dst->at_oxid);
}
@@ -1721,8 +2809,7 @@ isp_get_atio2e(ispsoftc_t *isp, at2e_entry_t *src, at2e_entry_t *dst)
ISP_IOXGET_16(isp, &src->at_wwpn[i], dst->at_wwpn[i]);
}
for (i = 0; i < 6; i++) {
- ISP_IOXGET_16(isp, &src->at_reserved2[i],
- dst->at_reserved2[i]);
+ ISP_IOXGET_16(isp, &src->at_reserved2[i], dst->at_reserved2[i]);
}
ISP_IOXGET_16(isp, &src->at_oxid, dst->at_oxid);
}
@@ -1771,10 +2858,8 @@ isp_put_ctio(ispsoftc_t *isp, ct_entry_t *src, ct_entry_t *dst)
ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout);
ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count);
for (i = 0; i < ISP_RQDSEG; i++) {
- ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_base,
- &dst->ct_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_count,
- &dst->ct_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_base, &dst->ct_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->ct_dataseg[i].ds_count, &dst->ct_dataseg[i].ds_count);
}
}
@@ -1800,8 +2885,7 @@ isp_get_ctio(ispsoftc_t *isp, ct_entry_t *src, ct_entry_t *dst)
ISP_IOXGET_8(isp, &src->ct_reserved2, dst->ct_reserved2);
ISP_IOXGET_8(isp, &src->ct_tgt, dst->ct_tgt);
ISP_IOXGET_8(isp, &src->ct_status, dst->ct_status);
- ISP_IOXGET_8(isp, &src->ct_scsi_status,
- dst->ct_scsi_status);
+ ISP_IOXGET_8(isp, &src->ct_scsi_status, dst->ct_scsi_status);
ISP_IOXGET_8(isp, &src->ct_tag_val, dst->ct_tag_val);
ISP_IOXGET_8(isp, &src->ct_tag_type, dst->ct_tag_type);
}
@@ -1811,12 +2895,8 @@ isp_get_ctio(ispsoftc_t *isp, ct_entry_t *src, ct_entry_t *dst)
ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout);
ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count);
for (i = 0; i < ISP_RQDSEG; i++) {
- ISP_IOXGET_32(isp,
- &src->ct_dataseg[i].ds_base,
- dst->ct_dataseg[i].ds_base);
- ISP_IOXGET_32(isp,
- &src->ct_dataseg[i].ds_count,
- dst->ct_dataseg[i].ds_count);
+ ISP_IOXGET_32(isp, &src->ct_dataseg[i].ds_base, dst->ct_dataseg[i].ds_base);
+ ISP_IOXGET_32(isp, &src->ct_dataseg[i].ds_count, dst->ct_dataseg[i].ds_count);
}
}
@@ -1835,71 +2915,42 @@ isp_put_ctio2(ispsoftc_t *isp, ct2_entry_t *src, ct2_entry_t *dst)
ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid);
ISP_IOXPUT_32(isp, src->ct_reloff, &dst->ct_reloff);
if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) {
- ISP_IOXPUT_32(isp, src->rsp.m0._reserved,
- &dst->rsp.m0._reserved);
- ISP_IOXPUT_16(isp, src->rsp.m0._reserved2,
- &dst->rsp.m0._reserved2);
- ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status,
- &dst->rsp.m0.ct_scsi_status);
- ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen,
- &dst->rsp.m0.ct_xfrlen);
+ ISP_IOXPUT_32(isp, src->rsp.m0._reserved, &dst->rsp.m0._reserved);
+ ISP_IOXPUT_16(isp, src->rsp.m0._reserved2, &dst->rsp.m0._reserved2);
+ ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status, &dst->rsp.m0.ct_scsi_status);
+ ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen, &dst->rsp.m0.ct_xfrlen);
if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) {
for (i = 0; i < ISP_RQDSEG_T2; i++) {
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg[i].ds_base,
- &dst->rsp.m0.u.ct_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg[i].ds_count,
- &dst->rsp.m0.u.ct_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg[i].ds_base, &dst->rsp.m0.u.ct_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg[i].ds_count, &dst->rsp.m0.u.ct_dataseg[i].ds_count);
}
} else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
for (i = 0; i < ISP_RQDSEG_T3; i++) {
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg64[i].ds_base,
- &dst->rsp.m0.u.ct_dataseg64[i].ds_base);
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg64[i].ds_basehi,
- &dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg64[i].ds_count,
- &dst->rsp.m0.u.ct_dataseg64[i].ds_count);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg64[i].ds_base, &dst->rsp.m0.u.ct_dataseg64[i].ds_base);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg64[i].ds_basehi, &dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg64[i].ds_count, &dst->rsp.m0.u.ct_dataseg64[i].ds_count);
}
} else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO4) {
- ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type,
- &dst->rsp.m0.u.ct_dslist.ds_type);
- ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment,
+ ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type, &dst->rsp.m0.u.ct_dslist.ds_type); ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment,
&dst->rsp.m0.u.ct_dslist.ds_segment);
- ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base,
- &dst->rsp.m0.u.ct_dslist.ds_base);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base, &dst->rsp.m0.u.ct_dslist.ds_base);
}
} else if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) {
- ISP_IOXPUT_16(isp, src->rsp.m1._reserved,
- &dst->rsp.m1._reserved);
- ISP_IOXPUT_16(isp, src->rsp.m1._reserved2,
- &dst->rsp.m1._reserved2);
- ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen,
- &dst->rsp.m1.ct_senselen);
- ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status,
- &dst->rsp.m1.ct_scsi_status);
- ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen,
- &dst->rsp.m1.ct_resplen);
+ ISP_IOXPUT_16(isp, src->rsp.m1._reserved, &dst->rsp.m1._reserved);
+ ISP_IOXPUT_16(isp, src->rsp.m1._reserved2, &dst->rsp.m1._reserved2);
+ ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen, &dst->rsp.m1.ct_senselen);
+ ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status, &dst->rsp.m1.ct_scsi_status);
+ ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen, &dst->rsp.m1.ct_resplen);
for (i = 0; i < MAXRESPLEN; i++) {
- ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i],
- &dst->rsp.m1.ct_resp[i]);
+ ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i], &dst->rsp.m1.ct_resp[i]);
}
} else {
- ISP_IOXPUT_32(isp, src->rsp.m2._reserved,
- &dst->rsp.m2._reserved);
- ISP_IOXPUT_16(isp, src->rsp.m2._reserved2,
- &dst->rsp.m2._reserved2);
- ISP_IOXPUT_16(isp, src->rsp.m2._reserved3,
- &dst->rsp.m2._reserved3);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen,
- &dst->rsp.m2.ct_datalen);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
- &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
- &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+ ISP_IOXPUT_32(isp, src->rsp.m2._reserved, &dst->rsp.m2._reserved);
+ ISP_IOXPUT_16(isp, src->rsp.m2._reserved2, &dst->rsp.m2._reserved2);
+ ISP_IOXPUT_16(isp, src->rsp.m2._reserved3, &dst->rsp.m2._reserved3);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen, &dst->rsp.m2.ct_datalen);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base, &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count, &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
}
}
@@ -1917,71 +2968,42 @@ isp_put_ctio2e(ispsoftc_t *isp, ct2e_entry_t *src, ct2e_entry_t *dst)
ISP_IOXPUT_32(isp, src->ct_resid, &dst->ct_resid);
ISP_IOXPUT_32(isp, src->ct_reloff, &dst->ct_reloff);
if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) {
- ISP_IOXPUT_32(isp, src->rsp.m0._reserved,
- &dst->rsp.m0._reserved);
- ISP_IOXPUT_16(isp, src->rsp.m0._reserved2,
- &dst->rsp.m0._reserved2);
- ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status,
- &dst->rsp.m0.ct_scsi_status);
- ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen,
- &dst->rsp.m0.ct_xfrlen);
+ ISP_IOXPUT_32(isp, src->rsp.m0._reserved, &dst->rsp.m0._reserved);
+ ISP_IOXPUT_16(isp, src->rsp.m0._reserved2, &dst->rsp.m0._reserved2);
+ ISP_IOXPUT_16(isp, src->rsp.m0.ct_scsi_status, &dst->rsp.m0.ct_scsi_status);
+ ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen, &dst->rsp.m0.ct_xfrlen);
if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) {
for (i = 0; i < ISP_RQDSEG_T2; i++) {
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg[i].ds_base,
- &dst->rsp.m0.u.ct_dataseg[i].ds_base);
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg[i].ds_count,
- &dst->rsp.m0.u.ct_dataseg[i].ds_count);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg[i].ds_base, &dst->rsp.m0.u.ct_dataseg[i].ds_base);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg[i].ds_count, &dst->rsp.m0.u.ct_dataseg[i].ds_count);
}
} else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
for (i = 0; i < ISP_RQDSEG_T3; i++) {
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg64[i].ds_base,
- &dst->rsp.m0.u.ct_dataseg64[i].ds_base);
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg64[i].ds_basehi,
- &dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
- ISP_IOXPUT_32(isp,
- src->rsp.m0.u.ct_dataseg64[i].ds_count,
- &dst->rsp.m0.u.ct_dataseg64[i].ds_count);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg64[i].ds_base, &dst->rsp.m0.u.ct_dataseg64[i].ds_base);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg64[i].ds_basehi, &dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dataseg64[i].ds_count, &dst->rsp.m0.u.ct_dataseg64[i].ds_count);
}
} else if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO4) {
- ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type,
- &dst->rsp.m0.u.ct_dslist.ds_type);
- ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment,
- &dst->rsp.m0.u.ct_dslist.ds_segment);
- ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base,
- &dst->rsp.m0.u.ct_dslist.ds_base);
+ ISP_IOXPUT_16(isp, src->rsp.m0.u.ct_dslist.ds_type, &dst->rsp.m0.u.ct_dslist.ds_type);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_segment, &dst->rsp.m0.u.ct_dslist.ds_segment);
+ ISP_IOXPUT_32(isp, src->rsp.m0.u.ct_dslist.ds_base, &dst->rsp.m0.u.ct_dslist.ds_base);
}
} else if ((src->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) {
- ISP_IOXPUT_16(isp, src->rsp.m1._reserved,
- &dst->rsp.m1._reserved);
- ISP_IOXPUT_16(isp, src->rsp.m1._reserved2,
- &dst->rsp.m1._reserved2);
- ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen,
- &dst->rsp.m1.ct_senselen);
- ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status,
- &dst->rsp.m1.ct_scsi_status);
- ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen,
- &dst->rsp.m1.ct_resplen);
+ ISP_IOXPUT_16(isp, src->rsp.m1._reserved, &dst->rsp.m1._reserved);
+ ISP_IOXPUT_16(isp, src->rsp.m1._reserved2, &dst->rsp.m1._reserved2);
+ ISP_IOXPUT_16(isp, src->rsp.m1.ct_senselen, &dst->rsp.m1.ct_senselen);
+ ISP_IOXPUT_16(isp, src->rsp.m1.ct_scsi_status, &dst->rsp.m1.ct_scsi_status);
+ ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen, &dst->rsp.m1.ct_resplen);
for (i = 0; i < MAXRESPLEN; i++) {
- ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i],
- &dst->rsp.m1.ct_resp[i]);
+ ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i], &dst->rsp.m1.ct_resp[i]);
}
} else {
- ISP_IOXPUT_32(isp, src->rsp.m2._reserved,
- &dst->rsp.m2._reserved);
- ISP_IOXPUT_16(isp, src->rsp.m2._reserved2,
- &dst->rsp.m2._reserved2);
- ISP_IOXPUT_16(isp, src->rsp.m2._reserved3,
- &dst->rsp.m2._reserved3);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen,
- &dst->rsp.m2.ct_datalen);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
- &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
- &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+ ISP_IOXPUT_32(isp, src->rsp.m2._reserved, &dst->rsp.m2._reserved);
+ ISP_IOXPUT_16(isp, src->rsp.m2._reserved2, &dst->rsp.m2._reserved2);
+ ISP_IOXPUT_16(isp, src->rsp.m2._reserved3, &dst->rsp.m2._reserved3);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen, &dst->rsp.m2.ct_datalen);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base, &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count, &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
}
}
@@ -1995,7 +3017,7 @@ isp_put_ctio7(ispsoftc_t *isp, ct7_entry_t *src, ct7_entry_t *dst)
ISP_IOXPUT_16(isp, src->ct_nphdl, &dst->ct_nphdl);
ISP_IOXPUT_16(isp, src->ct_timeout, &dst->ct_timeout);
ISP_IOXPUT_16(isp, src->ct_seg_count, &dst->ct_seg_count);
- ISP_IOXPUT_8(isp, src->ct_vpindex, &dst->ct_vpindex);
+ ISP_IOXPUT_8(isp, src->ct_vpidx, &dst->ct_vpidx);
ISP_IOXPUT_8(isp, src->ct_xflags, &dst->ct_xflags);
ISP_IOXPUT_16(isp, src->ct_iid_lo, &dst->ct_iid_lo);
ISP_IOXPUT_8(isp, src->ct_iid_hi, &dst->ct_iid_hi);
@@ -2008,39 +3030,29 @@ isp_put_ctio7(ispsoftc_t *isp, ct7_entry_t *src, ct7_entry_t *dst)
ISP_IOXPUT_16(isp, src->ct_scsi_status, &dst->ct_scsi_status);
if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE0) {
ISP_IOXPUT_32(isp, src->rsp.m0.reloff, &dst->rsp.m0.reloff);
- ISP_IOXPUT_32(isp, src->rsp.m0.reserved0,
- &dst->rsp.m0.reserved0);
- ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen,
- &dst->rsp.m0.ct_xfrlen);
- ISP_IOXPUT_32(isp, src->rsp.m0.reserved1,
- &dst->rsp.m0.reserved1);
- ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_base,
- &dst->rsp.m0.ds.ds_base);
- ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_basehi,
- &dst->rsp.m0.ds.ds_basehi);
- ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_count,
- &dst->rsp.m0.ds.ds_count);
+ ISP_IOXPUT_32(isp, src->rsp.m0.reserved0, &dst->rsp.m0.reserved0);
+ ISP_IOXPUT_32(isp, src->rsp.m0.ct_xfrlen, &dst->rsp.m0.ct_xfrlen);
+ ISP_IOXPUT_32(isp, src->rsp.m0.reserved1, &dst->rsp.m0.reserved1);
+ ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_base, &dst->rsp.m0.ds.ds_base);
+ ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_basehi, &dst->rsp.m0.ds.ds_basehi);
+ ISP_IOXPUT_32(isp, src->rsp.m0.ds.ds_count, &dst->rsp.m0.ds.ds_count);
} else if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE1) {
- ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen,
- &dst->rsp.m1.ct_resplen);
+ uint32_t *a, *b;
+
+ ISP_IOXPUT_16(isp, src->rsp.m1.ct_resplen, &dst->rsp.m1.ct_resplen);
ISP_IOXPUT_16(isp, src->rsp.m1.reserved, &dst->rsp.m1.reserved);
- for (i = 0; i < MAXRESPLEN_24XX; i++) {
- ISP_IOXPUT_8(isp, src->rsp.m1.ct_resp[i],
- &dst->rsp.m1.ct_resp[i]);
+ a = (uint32_t *) src->rsp.m1.ct_resp;
+ b = (uint32_t *) dst->rsp.m1.ct_resp;
+ for (i = 0; i < (ASIZE(src->rsp.m1.ct_resp) >> 2); i++) {
+ *b++ = ISP_SWAP32(isp, *a++);
}
} else {
- ISP_IOXPUT_32(isp, src->rsp.m2.reserved0,
- &dst->rsp.m2.reserved0);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen,
- &dst->rsp.m2.ct_datalen);
- ISP_IOXPUT_32(isp, src->rsp.m2.reserved1,
- &dst->rsp.m2.reserved1);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
- &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi,
- &dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi);
- ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
- &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+ ISP_IOXPUT_32(isp, src->rsp.m2.reserved0, &dst->rsp.m2.reserved0);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_datalen, &dst->rsp.m2.ct_datalen);
+ ISP_IOXPUT_32(isp, src->rsp.m2.reserved1, &dst->rsp.m2.reserved1);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_base, &dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi, &dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi);
+ ISP_IOXPUT_32(isp, src->rsp.m2.ct_fcp_rsp_iudata.ds_count, &dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
}
}
@@ -2062,71 +3074,42 @@ isp_get_ctio2(ispsoftc_t *isp, ct2_entry_t *src, ct2_entry_t *dst)
ISP_IOXGET_32(isp, &src->ct_reloff, dst->ct_reloff);
ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid);
if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) {
- ISP_IOXGET_32(isp, &src->rsp.m0._reserved,
- dst->rsp.m0._reserved);
- ISP_IOXGET_16(isp, &src->rsp.m0._reserved2,
- dst->rsp.m0._reserved2);
- ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status,
- dst->rsp.m0.ct_scsi_status);
- ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen,
- dst->rsp.m0.ct_xfrlen);
+ ISP_IOXGET_32(isp, &src->rsp.m0._reserved, dst->rsp.m0._reserved);
+ ISP_IOXGET_16(isp, &src->rsp.m0._reserved2, dst->rsp.m0._reserved2);
+ ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status, dst->rsp.m0.ct_scsi_status);
+ ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen, dst->rsp.m0.ct_xfrlen);
if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO2) {
for (i = 0; i < ISP_RQDSEG_T2; i++) {
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg[i].ds_base,
- dst->rsp.m0.u.ct_dataseg[i].ds_base);
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg[i].ds_count,
- dst->rsp.m0.u.ct_dataseg[i].ds_count);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg[i].ds_base, dst->rsp.m0.u.ct_dataseg[i].ds_base);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg[i].ds_count, dst->rsp.m0.u.ct_dataseg[i].ds_count);
}
} else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
for (i = 0; i < ISP_RQDSEG_T3; i++) {
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg64[i].ds_base,
- dst->rsp.m0.u.ct_dataseg64[i].ds_base);
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg64[i].ds_basehi,
- dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg64[i].ds_count,
- dst->rsp.m0.u.ct_dataseg64[i].ds_count);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg64[i].ds_base, dst->rsp.m0.u.ct_dataseg64[i].ds_base);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg64[i].ds_basehi, dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg64[i].ds_count, dst->rsp.m0.u.ct_dataseg64[i].ds_count);
}
} else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO4) {
- ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type,
- dst->rsp.m0.u.ct_dslist.ds_type);
- ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment,
- dst->rsp.m0.u.ct_dslist.ds_segment);
- ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base,
- dst->rsp.m0.u.ct_dslist.ds_base);
+ ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type, dst->rsp.m0.u.ct_dslist.ds_type);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment, dst->rsp.m0.u.ct_dslist.ds_segment);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base, dst->rsp.m0.u.ct_dslist.ds_base);
}
} else if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) {
- ISP_IOXGET_16(isp, &src->rsp.m1._reserved,
- dst->rsp.m1._reserved);
- ISP_IOXGET_16(isp, &src->rsp.m1._reserved2,
- dst->rsp.m1._reserved2);
- ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen,
- dst->rsp.m1.ct_senselen);
- ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status,
- dst->rsp.m1.ct_scsi_status);
- ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen,
- dst->rsp.m1.ct_resplen);
+ ISP_IOXGET_16(isp, &src->rsp.m1._reserved, dst->rsp.m1._reserved);
+ ISP_IOXGET_16(isp, &src->rsp.m1._reserved2, dst->rsp.m1._reserved2);
+ ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen, dst->rsp.m1.ct_senselen);
+ ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status, dst->rsp.m1.ct_scsi_status);
+ ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen, dst->rsp.m1.ct_resplen);
for (i = 0; i < MAXRESPLEN; i++) {
- ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i],
- dst->rsp.m1.ct_resp[i]);
+ ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i], dst->rsp.m1.ct_resp[i]);
}
} else {
- ISP_IOXGET_32(isp, &src->rsp.m2._reserved,
- dst->rsp.m2._reserved);
- ISP_IOXGET_16(isp, &src->rsp.m2._reserved2,
- dst->rsp.m2._reserved2);
- ISP_IOXGET_16(isp, &src->rsp.m2._reserved3,
- dst->rsp.m2._reserved3);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen,
- dst->rsp.m2.ct_datalen);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
- dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
- dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+ ISP_IOXGET_32(isp, &src->rsp.m2._reserved, dst->rsp.m2._reserved);
+ ISP_IOXGET_16(isp, &src->rsp.m2._reserved2, dst->rsp.m2._reserved2);
+ ISP_IOXGET_16(isp, &src->rsp.m2._reserved3, dst->rsp.m2._reserved3);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen, dst->rsp.m2.ct_datalen);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base, dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count, dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
}
}
@@ -2146,71 +3129,42 @@ isp_get_ctio2e(ispsoftc_t *isp, ct2e_entry_t *src, ct2e_entry_t *dst)
ISP_IOXGET_32(isp, &src->ct_reloff, dst->ct_reloff);
ISP_IOXGET_32(isp, &src->ct_resid, dst->ct_resid);
if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE0) {
- ISP_IOXGET_32(isp, &src->rsp.m0._reserved,
- dst->rsp.m0._reserved);
- ISP_IOXGET_16(isp, &src->rsp.m0._reserved2,
- dst->rsp.m0._reserved2);
- ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status,
- dst->rsp.m0.ct_scsi_status);
- ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen,
- dst->rsp.m0.ct_xfrlen);
+ ISP_IOXGET_32(isp, &src->rsp.m0._reserved, dst->rsp.m0._reserved);
+ ISP_IOXGET_16(isp, &src->rsp.m0._reserved2, dst->rsp.m0._reserved2);
+ ISP_IOXGET_16(isp, &src->rsp.m0.ct_scsi_status, dst->rsp.m0.ct_scsi_status);
+ ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen, dst->rsp.m0.ct_xfrlen);
if (src->ct_header.rqs_entry_type == RQSTYPE_CTIO2) {
for (i = 0; i < ISP_RQDSEG_T2; i++) {
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg[i].ds_base,
- dst->rsp.m0.u.ct_dataseg[i].ds_base);
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg[i].ds_count,
- dst->rsp.m0.u.ct_dataseg[i].ds_count);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg[i].ds_base, dst->rsp.m0.u.ct_dataseg[i].ds_base);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg[i].ds_count, dst->rsp.m0.u.ct_dataseg[i].ds_count);
}
} else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
for (i = 0; i < ISP_RQDSEG_T3; i++) {
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg64[i].ds_base,
- dst->rsp.m0.u.ct_dataseg64[i].ds_base);
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg64[i].ds_basehi,
- dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
- ISP_IOXGET_32(isp,
- &src->rsp.m0.u.ct_dataseg64[i].ds_count,
- dst->rsp.m0.u.ct_dataseg64[i].ds_count);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg64[i].ds_base, dst->rsp.m0.u.ct_dataseg64[i].ds_base);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg64[i].ds_basehi, dst->rsp.m0.u.ct_dataseg64[i].ds_basehi);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dataseg64[i].ds_count, dst->rsp.m0.u.ct_dataseg64[i].ds_count);
}
} else if (dst->ct_header.rqs_entry_type == RQSTYPE_CTIO4) {
- ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type,
- dst->rsp.m0.u.ct_dslist.ds_type);
- ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment,
- dst->rsp.m0.u.ct_dslist.ds_segment);
- ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base,
- dst->rsp.m0.u.ct_dslist.ds_base);
+ ISP_IOXGET_16(isp, &src->rsp.m0.u.ct_dslist.ds_type, dst->rsp.m0.u.ct_dslist.ds_type);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_segment, dst->rsp.m0.u.ct_dslist.ds_segment);
+ ISP_IOXGET_32(isp, &src->rsp.m0.u.ct_dslist.ds_base, dst->rsp.m0.u.ct_dslist.ds_base);
}
} else if ((dst->ct_flags & CT2_FLAG_MMASK) == CT2_FLAG_MODE1) {
- ISP_IOXGET_16(isp, &src->rsp.m1._reserved,
- dst->rsp.m1._reserved);
- ISP_IOXGET_16(isp, &src->rsp.m1._reserved2,
- dst->rsp.m1._reserved2);
- ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen,
- dst->rsp.m1.ct_senselen);
- ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status,
- dst->rsp.m1.ct_scsi_status);
- ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen,
- dst->rsp.m1.ct_resplen);
+ ISP_IOXGET_16(isp, &src->rsp.m1._reserved, dst->rsp.m1._reserved);
+ ISP_IOXGET_16(isp, &src->rsp.m1._reserved2, dst->rsp.m1._reserved2);
+ ISP_IOXGET_16(isp, &src->rsp.m1.ct_senselen, dst->rsp.m1.ct_senselen);
+ ISP_IOXGET_16(isp, &src->rsp.m1.ct_scsi_status, dst->rsp.m1.ct_scsi_status);
+ ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen, dst->rsp.m1.ct_resplen);
for (i = 0; i < MAXRESPLEN; i++) {
- ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i],
- dst->rsp.m1.ct_resp[i]);
+ ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i], dst->rsp.m1.ct_resp[i]);
}
} else {
- ISP_IOXGET_32(isp, &src->rsp.m2._reserved,
- dst->rsp.m2._reserved);
- ISP_IOXGET_16(isp, &src->rsp.m2._reserved2,
- dst->rsp.m2._reserved2);
- ISP_IOXGET_16(isp, &src->rsp.m2._reserved3,
- dst->rsp.m2._reserved3);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen,
- dst->rsp.m2.ct_datalen);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
- dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
- dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+ ISP_IOXGET_32(isp, &src->rsp.m2._reserved, dst->rsp.m2._reserved);
+ ISP_IOXGET_16(isp, &src->rsp.m2._reserved2, dst->rsp.m2._reserved2);
+ ISP_IOXGET_16(isp, &src->rsp.m2._reserved3, dst->rsp.m2._reserved3);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen, dst->rsp.m2.ct_datalen);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base, dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count, dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
}
}
@@ -2224,7 +3178,7 @@ isp_get_ctio7(ispsoftc_t *isp, ct7_entry_t *src, ct7_entry_t *dst)
ISP_IOXGET_16(isp, &src->ct_nphdl, dst->ct_nphdl);
ISP_IOXGET_16(isp, &src->ct_timeout, dst->ct_timeout);
ISP_IOXGET_16(isp, &src->ct_seg_count, dst->ct_seg_count);
- ISP_IOXGET_8(isp, &src->ct_vpindex, dst->ct_vpindex);
+ ISP_IOXGET_8(isp, &src->ct_vpidx, dst->ct_vpidx);
ISP_IOXGET_8(isp, &src->ct_xflags, dst->ct_xflags);
ISP_IOXGET_16(isp, &src->ct_iid_lo, dst->ct_iid_lo);
ISP_IOXGET_8(isp, &src->ct_iid_hi, dst->ct_iid_hi);
@@ -2237,39 +3191,32 @@ isp_get_ctio7(ispsoftc_t *isp, ct7_entry_t *src, ct7_entry_t *dst)
ISP_IOXGET_16(isp, &src->ct_scsi_status, dst->ct_scsi_status);
if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE0) {
ISP_IOXGET_32(isp, &src->rsp.m0.reloff, dst->rsp.m0.reloff);
- ISP_IOXGET_32(isp, &src->rsp.m0.reserved0,
- dst->rsp.m0.reserved0);
- ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen,
- dst->rsp.m0.ct_xfrlen);
- ISP_IOXGET_32(isp, &src->rsp.m0.reserved1,
- dst->rsp.m0.reserved1);
- ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_base,
- dst->rsp.m0.ds.ds_base);
- ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_basehi,
- dst->rsp.m0.ds.ds_basehi);
- ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_count,
- dst->rsp.m0.ds.ds_count);
+ ISP_IOXGET_32(isp, &src->rsp.m0.reserved0, dst->rsp.m0.reserved0);
+ ISP_IOXGET_32(isp, &src->rsp.m0.ct_xfrlen, dst->rsp.m0.ct_xfrlen);
+ ISP_IOXGET_32(isp, &src->rsp.m0.reserved1, dst->rsp.m0.reserved1);
+ ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_base, dst->rsp.m0.ds.ds_base);
+ ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_basehi, dst->rsp.m0.ds.ds_basehi);
+ ISP_IOXGET_32(isp, &src->rsp.m0.ds.ds_count, dst->rsp.m0.ds.ds_count);
} else if ((dst->ct_flags & CT7_FLAG_MMASK) == CT7_FLAG_MODE1) {
- ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen,
- dst->rsp.m1.ct_resplen);
+ uint32_t *a, *b;
+
+ ISP_IOXGET_16(isp, &src->rsp.m1.ct_resplen, dst->rsp.m1.ct_resplen);
ISP_IOXGET_16(isp, &src->rsp.m1.reserved, dst->rsp.m1.reserved);
+ a = (uint32_t *) src->rsp.m1.ct_resp;
+ b = (uint32_t *) dst->rsp.m1.ct_resp;
for (i = 0; i < MAXRESPLEN_24XX; i++) {
- ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i],
- dst->rsp.m1.ct_resp[i]);
+ ISP_IOXGET_8(isp, &src->rsp.m1.ct_resp[i], dst->rsp.m1.ct_resp[i]);
+ }
+ for (i = 0; i < (ASIZE(src->rsp.m1.ct_resp) >> 2); i++) {
+ *b++ = ISP_SWAP32(isp, *a++);
}
} else {
- ISP_IOXGET_32(isp, &src->rsp.m2.reserved0,
- dst->rsp.m2.reserved0);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen,
- dst->rsp.m2.ct_datalen);
- ISP_IOXGET_32(isp, &src->rsp.m2.reserved1,
- dst->rsp.m2.reserved1);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base,
- dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi,
- dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi);
- ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count,
- dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
+ ISP_IOXGET_32(isp, &src->rsp.m2.reserved0, dst->rsp.m2.reserved0);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_datalen, dst->rsp.m2.ct_datalen);
+ ISP_IOXGET_32(isp, &src->rsp.m2.reserved1, dst->rsp.m2.reserved1);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_base, dst->rsp.m2.ct_fcp_rsp_iudata.ds_base);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_basehi, dst->rsp.m2.ct_fcp_rsp_iudata.ds_basehi);
+ ISP_IOXGET_32(isp, &src->rsp.m2.ct_fcp_rsp_iudata.ds_count, dst->rsp.m2.ct_fcp_rsp_iudata.ds_count);
}
}
@@ -2305,8 +3252,7 @@ isp_put_enable_lun(ispsoftc_t *isp, lun_entry_t *lesrc, lun_entry_t *ledst)
ISP_IOXPUT_32(isp, lesrc->le_flags, &ledst->le_flags);
ISP_IOXPUT_16(isp, lesrc->le_timeout, &ledst->le_timeout);
for (i = 0; i < 20; i++) {
- ISP_IOXPUT_8(isp, lesrc->le_reserved3[i],
- &ledst->le_reserved3[i]);
+ ISP_IOXPUT_8(isp, lesrc->le_reserved3[i], &ledst->le_reserved3[i]);
}
}
@@ -2342,8 +3288,7 @@ isp_get_enable_lun(ispsoftc_t *isp, lun_entry_t *lesrc, lun_entry_t *ledst)
ISP_IOXGET_32(isp, &lesrc->le_flags, ledst->le_flags);
ISP_IOXGET_16(isp, &lesrc->le_timeout, ledst->le_timeout);
for (i = 0; i < 20; i++) {
- ISP_IOXGET_8(isp, &lesrc->le_reserved3[i],
- ledst->le_reserved3[i]);
+ ISP_IOXGET_8(isp, &lesrc->le_reserved3[i], ledst->le_reserved3[i]);
}
}
@@ -2378,12 +3323,10 @@ isp_put_notify(ispsoftc_t *isp, in_entry_t *src, in_entry_t *dst)
ISP_IOXPUT_8(isp, src->in_msg[i], &dst->in_msg[i]);
}
for (i = 0; i < IN_RSVDLEN; i++) {
- ISP_IOXPUT_8(isp, src->in_reserved3[i],
- &dst->in_reserved3[i]);
+ ISP_IOXPUT_8(isp, src->in_reserved3[i], &dst->in_reserved3[i]);
}
for (i = 0; i < QLTM_SENSELEN; i++) {
- ISP_IOXPUT_8(isp, src->in_sense[i],
- &dst->in_sense[i]);
+ ISP_IOXPUT_8(isp, src->in_sense[i], &dst->in_sense[i]);
}
}
@@ -2418,18 +3361,15 @@ isp_get_notify(ispsoftc_t *isp, in_entry_t *src, in_entry_t *dst)
ISP_IOXGET_8(isp, &src->in_msg[i], dst->in_msg[i]);
}
for (i = 0; i < IN_RSVDLEN; i++) {
- ISP_IOXGET_8(isp, &src->in_reserved3[i],
- dst->in_reserved3[i]);
+ ISP_IOXGET_8(isp, &src->in_reserved3[i], dst->in_reserved3[i]);
}
for (i = 0; i < QLTM_SENSELEN; i++) {
- ISP_IOXGET_8(isp, &src->in_sense[i],
- dst->in_sense[i]);
+ ISP_IOXGET_8(isp, &src->in_sense[i], dst->in_sense[i]);
}
}
void
-isp_put_notify_fc(ispsoftc_t *isp, in_fcentry_t *src,
- in_fcentry_t *dst)
+isp_put_notify_fc(ispsoftc_t *isp, in_fcentry_t *src, in_fcentry_t *dst)
{
isp_put_hdr(isp, &src->in_header, &dst->in_header);
ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved);
@@ -2443,8 +3383,7 @@ isp_put_notify_fc(ispsoftc_t *isp, in_fcentry_t *src,
}
void
-isp_put_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src,
- in_fcentry_e_t *dst)
+isp_put_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src, in_fcentry_e_t *dst)
{
isp_put_hdr(isp, &src->in_header, &dst->in_header);
ISP_IOXPUT_32(isp, src->in_reserved, &dst->in_reserved);
@@ -2457,8 +3396,7 @@ isp_put_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src,
}
void
-isp_put_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src,
- in_fcentry_24xx_t *dst)
+isp_put_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src, in_fcentry_24xx_t *dst)
{
int i;
@@ -2476,22 +3414,25 @@ isp_put_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src,
ISP_IOXPUT_16(isp, src->in_srr_reloff_lo, &dst->in_srr_reloff_lo);
ISP_IOXPUT_16(isp, src->in_srr_iu, &dst->in_srr_iu);
ISP_IOXPUT_16(isp, src->in_srr_oxid, &dst->in_srr_oxid);
- for (i = 0; i < 18; i++) {
- ISP_IOXPUT_8(isp, src->in_reserved3[i], &dst->in_reserved3[i]);
- }
- ISP_IOXPUT_8(isp, src->in_reserved4, &dst->in_reserved4);
- ISP_IOXPUT_8(isp, src->in_vpindex, &dst->in_vpindex);
- ISP_IOXPUT_32(isp, src->in_reserved5, &dst->in_reserved5);
+ ISP_IOXPUT_16(isp, src->in_nport_id_hi, &dst->in_nport_id_hi);
+ ISP_IOXPUT_8(isp, src->in_nport_id_lo, &dst->in_nport_id_lo);
+ ISP_IOXPUT_8(isp, src->in_reserved3, &dst->in_reserved3);
+ ISP_IOXPUT_16(isp, src->in_np_handle, &dst->in_np_handle);
+ for (i = 0; i < ASIZE(src->in_reserved4); i++) {
+ ISP_IOXPUT_8(isp, src->in_reserved4[i], &dst->in_reserved4[i]);
+ }
+ ISP_IOXPUT_8(isp, src->in_reserved5, &dst->in_reserved5);
+ ISP_IOXPUT_8(isp, src->in_vpidx, &dst->in_vpidx);
+ ISP_IOXPUT_32(isp, src->in_reserved6, &dst->in_reserved6);
ISP_IOXPUT_16(isp, src->in_portid_lo, &dst->in_portid_lo);
ISP_IOXPUT_8(isp, src->in_portid_hi, &dst->in_portid_hi);
- ISP_IOXPUT_8(isp, src->in_reserved6, &dst->in_reserved6);
- ISP_IOXPUT_16(isp, src->in_reserved7, &dst->in_reserved7);
+ ISP_IOXPUT_8(isp, src->in_reserved7, &dst->in_reserved7);
+ ISP_IOXPUT_16(isp, src->in_reserved8, &dst->in_reserved8);
ISP_IOXPUT_16(isp, src->in_oxid, &dst->in_oxid);
}
void
-isp_get_notify_fc(ispsoftc_t *isp, in_fcentry_t *src,
- in_fcentry_t *dst)
+isp_get_notify_fc(ispsoftc_t *isp, in_fcentry_t *src, in_fcentry_t *dst)
{
isp_get_hdr(isp, &src->in_header, &dst->in_header);
ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved);
@@ -2505,8 +3446,7 @@ isp_get_notify_fc(ispsoftc_t *isp, in_fcentry_t *src,
}
void
-isp_get_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src,
- in_fcentry_e_t *dst)
+isp_get_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src, in_fcentry_e_t *dst)
{
isp_get_hdr(isp, &src->in_header, &dst->in_header);
ISP_IOXGET_32(isp, &src->in_reserved, dst->in_reserved);
@@ -2519,8 +3459,7 @@ isp_get_notify_fc_e(ispsoftc_t *isp, in_fcentry_e_t *src,
}
void
-isp_get_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src,
- in_fcentry_24xx_t *dst)
+isp_get_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src, in_fcentry_24xx_t *dst)
{
int i;
@@ -2538,16 +3477,20 @@ isp_get_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *src,
ISP_IOXGET_16(isp, &src->in_srr_reloff_lo, dst->in_srr_reloff_lo);
ISP_IOXGET_16(isp, &src->in_srr_iu, dst->in_srr_iu);
ISP_IOXGET_16(isp, &src->in_srr_oxid, dst->in_srr_oxid);
- for (i = 0; i < 18; i++) {
- ISP_IOXGET_8(isp, &src->in_reserved3[i], dst->in_reserved3[i]);
- }
- ISP_IOXGET_8(isp, &src->in_reserved4, dst->in_reserved4);
- ISP_IOXGET_8(isp, &src->in_vpindex, dst->in_vpindex);
- ISP_IOXGET_32(isp, &src->in_reserved5, dst->in_reserved5);
+ ISP_IOXGET_16(isp, &src->in_nport_id_hi, dst->in_nport_id_hi);
+ ISP_IOXGET_8(isp, &src->in_nport_id_lo, dst->in_nport_id_lo);
+ ISP_IOXGET_8(isp, &src->in_reserved3, dst->in_reserved3);
+ ISP_IOXGET_16(isp, &src->in_np_handle, dst->in_np_handle);
+ for (i = 0; i < ASIZE(src->in_reserved4); i++) {
+ ISP_IOXGET_8(isp, &src->in_reserved4[i], dst->in_reserved4[i]);
+ }
+ ISP_IOXGET_8(isp, &src->in_reserved5, dst->in_reserved5);
+ ISP_IOXGET_8(isp, &src->in_vpidx, dst->in_vpidx);
+ ISP_IOXGET_32(isp, &src->in_reserved6, dst->in_reserved6);
ISP_IOXGET_16(isp, &src->in_portid_lo, dst->in_portid_lo);
ISP_IOXGET_8(isp, &src->in_portid_hi, dst->in_portid_hi);
- ISP_IOXGET_8(isp, &src->in_reserved6, dst->in_reserved6);
- ISP_IOXGET_16(isp, &src->in_reserved7, dst->in_reserved7);
+ ISP_IOXGET_8(isp, &src->in_reserved7, dst->in_reserved7);
+ ISP_IOXGET_16(isp, &src->in_reserved8, dst->in_reserved8);
ISP_IOXGET_16(isp, &src->in_oxid, dst->in_oxid);
}
@@ -2570,8 +3513,7 @@ isp_put_notify_ack(ispsoftc_t *isp, na_entry_t *src, na_entry_t *dst)
}
ISP_IOXPUT_32(isp, src->na_flags, &dst->na_flags);
for (i = 0; i < NA_RSVDLEN; i++) {
- ISP_IOXPUT_16(isp, src->na_reserved3[i],
- &dst->na_reserved3[i]);
+ ISP_IOXPUT_16(isp, src->na_reserved3[i], &dst->na_reserved3[i]);
}
}
@@ -2594,14 +3536,12 @@ isp_get_notify_ack(ispsoftc_t *isp, na_entry_t *src, na_entry_t *dst)
}
ISP_IOXGET_32(isp, &src->na_flags, dst->na_flags);
for (i = 0; i < NA_RSVDLEN; i++) {
- ISP_IOXGET_16(isp, &src->na_reserved3[i],
- dst->na_reserved3[i]);
+ ISP_IOXGET_16(isp, &src->na_reserved3[i], dst->na_reserved3[i]);
}
}
void
-isp_put_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src,
- na_fcentry_t *dst)
+isp_put_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src, na_fcentry_t *dst)
{
int i;
isp_put_hdr(isp, &src->na_header, &dst->na_header);
@@ -2615,14 +3555,12 @@ isp_put_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src,
ISP_IOXPUT_16(isp, src->na_task_flags, &dst->na_task_flags);
ISP_IOXPUT_16(isp, src->na_seqid, &dst->na_seqid);
for (i = 0; i < NA2_RSVDLEN; i++) {
- ISP_IOXPUT_16(isp, src->na_reserved3[i],
- &dst->na_reserved3[i]);
+ ISP_IOXPUT_16(isp, src->na_reserved3[i], &dst->na_reserved3[i]);
}
}
void
-isp_put_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src,
- na_fcentry_e_t *dst)
+isp_put_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src, na_fcentry_e_t *dst)
{
int i;
isp_put_hdr(isp, &src->na_header, &dst->na_header);
@@ -2635,14 +3573,12 @@ isp_put_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src,
ISP_IOXPUT_16(isp, src->na_task_flags, &dst->na_task_flags);
ISP_IOXPUT_16(isp, src->na_seqid, &dst->na_seqid);
for (i = 0; i < NA2_RSVDLEN; i++) {
- ISP_IOXPUT_16(isp, src->na_reserved3[i],
- &dst->na_reserved3[i]);
+ ISP_IOXPUT_16(isp, src->na_reserved3[i], &dst->na_reserved3[i]);
}
}
void
-isp_put_notify_24xx_ack(ispsoftc_t *isp, na_fcentry_24xx_t *src,
- na_fcentry_24xx_t *dst)
+isp_put_notify_24xx_ack(ispsoftc_t *isp, na_fcentry_24xx_t *src, na_fcentry_24xx_t *dst)
{
int i;
@@ -2664,11 +3600,9 @@ isp_put_notify_24xx_ack(ispsoftc_t *isp, na_fcentry_24xx_t *src,
ISP_IOXPUT_8(isp, src->na_reserved3[i], &dst->na_reserved3[i]);
}
ISP_IOXPUT_8(isp, src->na_reserved4, &dst->na_reserved4);
- ISP_IOXPUT_8(isp, src->na_vpindex, &dst->na_vpindex);
- ISP_IOXPUT_8(isp, src->na_srr_reject_vunique,
- &dst->na_srr_reject_vunique);
- ISP_IOXPUT_8(isp, src->na_srr_reject_explanation,
- &dst->na_srr_reject_explanation);
+ ISP_IOXPUT_8(isp, src->na_vpidx, &dst->na_vpidx);
+ ISP_IOXPUT_8(isp, src->na_srr_reject_vunique, &dst->na_srr_reject_vunique);
+ ISP_IOXPUT_8(isp, src->na_srr_reject_explanation, &dst->na_srr_reject_explanation);
ISP_IOXPUT_8(isp, src->na_srr_reject_code, &dst->na_srr_reject_code);
ISP_IOXPUT_8(isp, src->na_reserved5, &dst->na_reserved5);
for (i = 0; i < 6; i++) {
@@ -2678,8 +3612,7 @@ isp_put_notify_24xx_ack(ispsoftc_t *isp, na_fcentry_24xx_t *src,
}
void
-isp_get_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src,
- na_fcentry_t *dst)
+isp_get_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src, na_fcentry_t *dst)
{
int i;
isp_get_hdr(isp, &src->na_header, &dst->na_header);
@@ -2693,14 +3626,12 @@ isp_get_notify_ack_fc(ispsoftc_t *isp, na_fcentry_t *src,
ISP_IOXGET_16(isp, &src->na_task_flags, dst->na_task_flags);
ISP_IOXGET_16(isp, &src->na_seqid, dst->na_seqid);
for (i = 0; i < NA2_RSVDLEN; i++) {
- ISP_IOXGET_16(isp, &src->na_reserved3[i],
- dst->na_reserved3[i]);
+ ISP_IOXGET_16(isp, &src->na_reserved3[i], dst->na_reserved3[i]);
}
}
void
-isp_get_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src,
- na_fcentry_e_t *dst)
+isp_get_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src, na_fcentry_e_t *dst)
{
int i;
isp_get_hdr(isp, &src->na_header, &dst->na_header);
@@ -2713,14 +3644,12 @@ isp_get_notify_ack_fc_e(ispsoftc_t *isp, na_fcentry_e_t *src,
ISP_IOXGET_16(isp, &src->na_task_flags, dst->na_task_flags);
ISP_IOXGET_16(isp, &src->na_seqid, dst->na_seqid);
for (i = 0; i < NA2_RSVDLEN; i++) {
- ISP_IOXGET_16(isp, &src->na_reserved3[i],
- dst->na_reserved3[i]);
+ ISP_IOXGET_16(isp, &src->na_reserved3[i], dst->na_reserved3[i]);
}
}
void
-isp_get_notify_ack_24xx(ispsoftc_t *isp, na_fcentry_24xx_t *src,
- na_fcentry_24xx_t *dst)
+isp_get_notify_ack_24xx(ispsoftc_t *isp, na_fcentry_24xx_t *src, na_fcentry_24xx_t *dst)
{
int i;
@@ -2742,11 +3671,9 @@ isp_get_notify_ack_24xx(ispsoftc_t *isp, na_fcentry_24xx_t *src,
ISP_IOXGET_8(isp, &src->na_reserved3[i], dst->na_reserved3[i]);
}
ISP_IOXGET_8(isp, &src->na_reserved4, dst->na_reserved4);
- ISP_IOXGET_8(isp, &src->na_vpindex, dst->na_vpindex);
- ISP_IOXGET_8(isp, &src->na_srr_reject_vunique,
- dst->na_srr_reject_vunique);
- ISP_IOXGET_8(isp, &src->na_srr_reject_explanation,
- dst->na_srr_reject_explanation);
+ ISP_IOXGET_8(isp, &src->na_vpidx, dst->na_vpidx);
+ ISP_IOXGET_8(isp, &src->na_srr_reject_vunique, dst->na_srr_reject_vunique);
+ ISP_IOXGET_8(isp, &src->na_srr_reject_explanation, dst->na_srr_reject_explanation);
ISP_IOXGET_8(isp, &src->na_srr_reject_code, dst->na_srr_reject_code);
ISP_IOXGET_8(isp, &src->na_reserved5, dst->na_reserved5);
for (i = 0; i < 6; i++) {
@@ -2762,8 +3689,7 @@ isp_get_abts(ispsoftc_t *isp, abts_t *src, abts_t *dst)
isp_get_hdr(isp, &src->abts_header, &dst->abts_header);
for (i = 0; i < 6; i++) {
- ISP_IOXGET_8(isp, &src->abts_reserved0[i],
- dst->abts_reserved0[i]);
+ ISP_IOXGET_8(isp, &src->abts_reserved0[i], dst->abts_reserved0[i]);
}
ISP_IOXGET_16(isp, &src->abts_nphdl, dst->abts_nphdl);
ISP_IOXGET_16(isp, &src->abts_reserved1, dst->abts_reserved1);
@@ -2785,8 +3711,7 @@ isp_get_abts(ispsoftc_t *isp, abts_t *src, abts_t *dst)
ISP_IOXGET_16(isp, &src->abts_ox_id, dst->abts_ox_id);
ISP_IOXGET_32(isp, &src->abts_param, dst->abts_param);
for (i = 0; i < 16; i++) {
- ISP_IOXGET_8(isp, &src->abts_reserved2[i],
- dst->abts_reserved2[i]);
+ ISP_IOXGET_8(isp, &src->abts_reserved2[i], dst->abts_reserved2[i]);
}
ISP_IOXGET_32(isp, &src->abts_rxid_task, dst->abts_rxid_task);
}
@@ -2819,43 +3744,27 @@ isp_put_abts_rsp(ispsoftc_t *isp, abts_rsp_t *src, abts_rsp_t *dst)
ISP_IOXPUT_16(isp, src->abts_rsp_ox_id, &dst->abts_rsp_ox_id);
ISP_IOXPUT_32(isp, src->abts_rsp_param, &dst->abts_rsp_param);
if (src->abts_rsp_r_ctl == BA_ACC) {
- ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.reserved,
- &dst->abts_rsp_payload.ba_acc.reserved);
- ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.last_seq_id,
- &dst->abts_rsp_payload.ba_acc.last_seq_id);
- ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.seq_id_valid,
- &dst->abts_rsp_payload.ba_acc.seq_id_valid);
- ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_rx_id,
- &dst->abts_rsp_payload.ba_acc.aborted_rx_id);
- ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_ox_id,
- &dst->abts_rsp_payload.ba_acc.aborted_ox_id);
- ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.high_seq_cnt,
- &dst->abts_rsp_payload.ba_acc.high_seq_cnt);
- ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.low_seq_cnt,
- &dst->abts_rsp_payload.ba_acc.low_seq_cnt);
+ ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.reserved, &dst->abts_rsp_payload.ba_acc.reserved);
+ ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.last_seq_id, &dst->abts_rsp_payload.ba_acc.last_seq_id);
+ ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_acc.seq_id_valid, &dst->abts_rsp_payload.ba_acc.seq_id_valid);
+ ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_rx_id, &dst->abts_rsp_payload.ba_acc.aborted_rx_id);
+ ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.aborted_ox_id, &dst->abts_rsp_payload.ba_acc.aborted_ox_id);
+ ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.high_seq_cnt, &dst->abts_rsp_payload.ba_acc.high_seq_cnt);
+ ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.low_seq_cnt, &dst->abts_rsp_payload.ba_acc.low_seq_cnt);
for (i = 0; i < 4; i++) {
- ISP_IOXPUT_16(isp,
- src->abts_rsp_payload.ba_acc.reserved2[i],
- &dst->abts_rsp_payload.ba_acc.reserved2[i]);
+ ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_acc.reserved2[i], &dst->abts_rsp_payload.ba_acc.reserved2[i]);
}
} else if (src->abts_rsp_r_ctl == BA_RJT) {
- ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.vendor_unique,
- &dst->abts_rsp_payload.ba_rjt.vendor_unique);
- ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.explanation,
- &dst->abts_rsp_payload.ba_rjt.explanation);
- ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reason,
- &dst->abts_rsp_payload.ba_rjt.reason);
- ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reserved,
- &dst->abts_rsp_payload.ba_rjt.reserved);
+ ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.vendor_unique, &dst->abts_rsp_payload.ba_rjt.vendor_unique);
+ ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.explanation, &dst->abts_rsp_payload.ba_rjt.explanation);
+ ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reason, &dst->abts_rsp_payload.ba_rjt.reason);
+ ISP_IOXPUT_8(isp, src->abts_rsp_payload.ba_rjt.reserved, &dst->abts_rsp_payload.ba_rjt.reserved);
for (i = 0; i < 12; i++) {
- ISP_IOXPUT_16(isp,
- src->abts_rsp_payload.ba_rjt.reserved2[i],
- &dst->abts_rsp_payload.ba_rjt.reserved2[i]);
+ ISP_IOXPUT_16(isp, src->abts_rsp_payload.ba_rjt.reserved2[i], &dst->abts_rsp_payload.ba_rjt.reserved2[i]);
}
} else {
for (i = 0; i < 16; i++) {
- ISP_IOXPUT_8(isp, src->abts_rsp_payload.reserved[i],
- &dst->abts_rsp_payload.reserved[i]);
+ ISP_IOXPUT_8(isp, src->abts_rsp_payload.reserved[i], &dst->abts_rsp_payload.reserved[i]);
}
}
ISP_IOXPUT_32(isp, src->abts_rsp_rxid_task, &dst->abts_rsp_rxid_task);
@@ -2889,13 +3798,10 @@ isp_get_abts_rsp(ispsoftc_t *isp, abts_rsp_t *src, abts_rsp_t *dst)
ISP_IOXGET_16(isp, &src->abts_rsp_ox_id, dst->abts_rsp_ox_id);
ISP_IOXGET_32(isp, &src->abts_rsp_param, dst->abts_rsp_param);
for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->abts_rsp_payload.rsp.reserved[i],
- dst->abts_rsp_payload.rsp.reserved[i]);
+ ISP_IOXGET_8(isp, &src->abts_rsp_payload.rsp.reserved[i], dst->abts_rsp_payload.rsp.reserved[i]);
}
- ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode1,
- dst->abts_rsp_payload.rsp.subcode1);
- ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode2,
- dst->abts_rsp_payload.rsp.subcode2);
+ ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode1, dst->abts_rsp_payload.rsp.subcode1);
+ ISP_IOXGET_32(isp, &src->abts_rsp_payload.rsp.subcode2, dst->abts_rsp_payload.rsp.subcode2);
ISP_IOXGET_32(isp, &src->abts_rsp_rxid_task, dst->abts_rsp_rxid_task);
}
#endif /* ISP_TARGET_MODE */
diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h
index a614bb6..9a9e397 100644
--- a/sys/dev/isp/isp_library.h
+++ b/sys/dev/isp/isp_library.h
@@ -1,6 +1,6 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 1997-2007 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,201 +24,190 @@
* 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.
+ *
+ */
+#ifndef _ISP_LIBRARY_H
+#define _ISP_LIBRARY_H
+
+/*
+ * Common command shipping routine.
+ *
+ * This used to be platform specific, but basically once you get the segment
+ * stuff figured out, you can make all the code in one spot.
+ */
+typedef enum { ISP_TO_DEVICE, ISP_FROM_DEVICE, ISP_NOXFR} isp_ddir_t;
+int isp_send_cmd(ispsoftc_t *, void *, void *, uint32_t, uint32_t, isp_ddir_t);
+
+/*
+ * Handle management functions.
+ *
+ * These handles are associate with a command.
+ */
+int isp_save_xs(ispsoftc_t *, XS_T *, uint32_t *);
+XS_T * isp_find_xs(ispsoftc_t *, uint32_t);
+uint32_t isp_find_handle(ispsoftc_t *, XS_T *);
+uint32_t isp_handle_index(uint32_t);
+void isp_destroy_handle(ispsoftc_t *, uint32_t);
+
+/*
+ * Request Queue allocation
+ */
+void *isp_getrqentry(ispsoftc_t *);
+
+/*
+ * Queue Entry debug functions
+ */
+void isp_print_qentry (ispsoftc_t *, const char *, int, void *);
+void isp_print_bytes(ispsoftc_t *, const char *, int, void *);
+
+/*
+ * Fibre Channel specific routines and data.
+ */
+extern const char *isp_class3_roles[4];
+int isp_fc_runstate(ispsoftc_t *, int, int);
+void isp_dump_portdb(ispsoftc_t *, int);
+
+const char *isp_fc_fw_statename(int);
+const char *isp_fc_loop_statename(int);
+const char *isp_fc_toponame(fcparam *);
+
+int isp_fc_change_role(ispsoftc_t *, int, int);
+
+
+/*
+ * Cleanup
+ */
+void isp_clear_commands(ispsoftc_t *);
+
+/*
+ * Common chip shutdown function
+ */
+void isp_shutdown(ispsoftc_t *);
+
+/*
+ * Put/Get routines to push from CPU view to device view
+ * or to pull from device view to CPU view for various
+ * data structures (IOCB)
*/
-#ifndef _ISP_LIBRARY_H
-#define _ISP_LIBRARY_H
-
-extern int isp_save_xs(ispsoftc_t *, XS_T *, uint32_t *);
-extern XS_T *isp_find_xs(ispsoftc_t *, uint32_t);
-extern uint32_t isp_find_handle(ispsoftc_t *, XS_T *);
-extern uint32_t isp_handle_index(uint32_t);
-extern void isp_destroy_handle(ispsoftc_t *, uint32_t);
-extern int isp_getrqentry(ispsoftc_t *, uint32_t *, uint32_t *, void **);
-extern void isp_print_qentry (ispsoftc_t *, char *, int, void *);
-extern void isp_print_bytes(ispsoftc_t *, const char *, int, void *);
-extern int isp_fc_runstate(ispsoftc_t *, int);
-extern void isp_dump_portdb(ispsoftc_t *);
-extern void isp_shutdown(ispsoftc_t *);
-extern void isp_put_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
-extern void isp_get_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
-extern int isp_get_response_type(ispsoftc_t *, isphdr_t *);
-extern void
-isp_put_request(ispsoftc_t *, ispreq_t *, ispreq_t *);
-extern void
-isp_put_marker(ispsoftc_t *, isp_marker_t *, isp_marker_t *);
-extern void
-isp_put_marker_24xx(ispsoftc_t *, isp_marker_24xx_t *, isp_marker_24xx_t *);
-extern void
-isp_put_request_t2(ispsoftc_t *, ispreqt2_t *, ispreqt2_t *);
-extern void
-isp_put_request_t2e(ispsoftc_t *, ispreqt2e_t *, ispreqt2e_t *);
-extern void
-isp_put_request_t3(ispsoftc_t *, ispreqt3_t *, ispreqt3_t *);
-extern void
-isp_put_request_t3e(ispsoftc_t *, ispreqt3e_t *, ispreqt3e_t *);
-extern void
-isp_put_extended_request(ispsoftc_t *, ispextreq_t *, ispextreq_t *);
-extern void
-isp_put_request_t7(ispsoftc_t *, ispreqt7_t *, ispreqt7_t *);
-extern void
-isp_put_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *);
-extern void
-isp_put_cont_req(ispsoftc_t *, ispcontreq_t *, ispcontreq_t *);
-extern void
-isp_put_cont64_req(ispsoftc_t *, ispcontreq64_t *, ispcontreq64_t *);
-extern void
-isp_get_response(ispsoftc_t *, ispstatusreq_t *, ispstatusreq_t *);
-extern void isp_get_24xx_response(ispsoftc_t *, isp24xx_statusreq_t *,
- isp24xx_statusreq_t *);
-void
-isp_get_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *);
-extern void
-isp_get_rio2(ispsoftc_t *, isp_rio2_t *, isp_rio2_t *);
-extern void
-isp_put_icb(ispsoftc_t *, isp_icb_t *, isp_icb_t *);
-extern void
-isp_put_icb_2400(ispsoftc_t *, isp_icb_2400_t *, isp_icb_2400_t *);
-extern void
-isp_get_pdb_21xx(ispsoftc_t *, isp_pdb_21xx_t *, isp_pdb_21xx_t *);
-extern void
-isp_get_pdb_24xx(ispsoftc_t *, isp_pdb_24xx_t *, isp_pdb_24xx_t *);
-extern void
-isp_get_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);
-extern void
-isp_put_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);
-extern void
-isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *);
-extern void
-isp_get_ms(ispsoftc_t *isp, isp_ms_t *, isp_ms_t *);
-extern void
-isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *);
-extern void
-isp_put_ms(ispsoftc_t *isp, isp_ms_t *, isp_ms_t *);
-extern void
-isp_put_sns_request(ispsoftc_t *, sns_screq_t *, sns_screq_t *);
-extern void
-isp_put_gid_ft_request(ispsoftc_t *, sns_gid_ft_req_t *,
- sns_gid_ft_req_t *);
-extern void
-isp_put_gxn_id_request(ispsoftc_t *, sns_gxn_id_req_t *,
- sns_gxn_id_req_t *);
-extern void
-isp_get_sns_response(ispsoftc_t *, sns_scrsp_t *, sns_scrsp_t *, int);
-extern void
-isp_get_gid_ft_response(ispsoftc_t *, sns_gid_ft_rsp_t *,
- sns_gid_ft_rsp_t *, int);
-extern void
-isp_get_gxn_id_response(ispsoftc_t *, sns_gxn_id_rsp_t *,
- sns_gxn_id_rsp_t *);
-extern void
-isp_get_gff_id_response(ispsoftc_t *, sns_gff_id_rsp_t *,
- sns_gff_id_rsp_t *);
-extern void
-isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *,
- sns_ga_nxt_rsp_t *);
-extern void
-isp_get_els(ispsoftc_t *, els_t *, els_t *);
-extern void
-isp_put_els(ispsoftc_t *, els_t *, els_t *);
-extern void
-isp_get_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *);
-extern void
-isp_get_fcp_cmnd_iu(ispsoftc_t *, fcp_cmnd_iu_t *, fcp_cmnd_iu_t *);
-extern void isp_put_rft_id(ispsoftc_t *, rft_id_t *, rft_id_t *);
-extern void isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
-extern void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
-
-#define ISP_HANDLE_MASK 0x7fff
-
-#ifdef ISP_TARGET_MODE
-#if defined(__NetBSD__) || defined(__OpenBSD__)
+void isp_put_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
+void isp_get_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
+int isp_get_response_type(ispsoftc_t *, isphdr_t *);
+void isp_put_request(ispsoftc_t *, ispreq_t *, ispreq_t *);
+void isp_put_marker(ispsoftc_t *, isp_marker_t *, isp_marker_t *);
+void isp_put_marker_24xx(ispsoftc_t *, isp_marker_24xx_t *, isp_marker_24xx_t *);
+void isp_put_request_t2(ispsoftc_t *, ispreqt2_t *, ispreqt2_t *);
+void isp_put_request_t2e(ispsoftc_t *, ispreqt2e_t *, ispreqt2e_t *);
+void isp_put_request_t3(ispsoftc_t *, ispreqt3_t *, ispreqt3_t *);
+void isp_put_request_t3e(ispsoftc_t *, ispreqt3e_t *, ispreqt3e_t *);
+void isp_put_extended_request(ispsoftc_t *, ispextreq_t *, ispextreq_t *);
+void isp_put_request_t7(ispsoftc_t *, ispreqt7_t *, ispreqt7_t *);
+void isp_put_24xx_tmf(ispsoftc_t *, isp24xx_tmf_t *, isp24xx_tmf_t *);
+void isp_put_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *);
+void isp_put_cont_req(ispsoftc_t *, ispcontreq_t *, ispcontreq_t *);
+void isp_put_cont64_req(ispsoftc_t *, ispcontreq64_t *, ispcontreq64_t *);
+void isp_get_response(ispsoftc_t *, ispstatusreq_t *, ispstatusreq_t *);
+void isp_get_24xx_response(ispsoftc_t *, isp24xx_statusreq_t *, isp24xx_statusreq_t *);
+void isp_get_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *);
+void isp_get_rio2(ispsoftc_t *, isp_rio2_t *, isp_rio2_t *);
+void isp_put_icb(ispsoftc_t *, isp_icb_t *, isp_icb_t *);
+void isp_put_icb_2400(ispsoftc_t *, isp_icb_2400_t *, isp_icb_2400_t *);
+void isp_put_icb_2400_vpinfo(ispsoftc_t *, isp_icb_2400_vpinfo_t *, isp_icb_2400_vpinfo_t *);
+void isp_put_vp_port_info(ispsoftc_t *, vp_port_info_t *, vp_port_info_t *);
+void isp_get_vp_port_info(ispsoftc_t *, vp_port_info_t *, vp_port_info_t *);
+void isp_put_vp_ctrl_info(ispsoftc_t *, vp_ctrl_info_t *, vp_ctrl_info_t *);
+void isp_get_vp_ctrl_info(ispsoftc_t *, vp_ctrl_info_t *, vp_ctrl_info_t *);
+void isp_put_vp_modify(ispsoftc_t *, vp_modify_t *, vp_modify_t *);
+void isp_get_vp_modify(ispsoftc_t *, vp_modify_t *, vp_modify_t *);
+void isp_get_pdb_21xx(ispsoftc_t *, isp_pdb_21xx_t *, isp_pdb_21xx_t *);
+void isp_get_pdb_24xx(ispsoftc_t *, isp_pdb_24xx_t *, isp_pdb_24xx_t *);
+void isp_get_ridacq(ispsoftc_t *, isp_ridacq_t *, isp_ridacq_t *);
+void isp_get_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);
+void isp_put_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);
+void isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *);
+void isp_get_ms(ispsoftc_t *isp, isp_ms_t *, isp_ms_t *);
+void isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *);
+void isp_put_ms(ispsoftc_t *isp, isp_ms_t *, isp_ms_t *);
+void isp_put_sns_request(ispsoftc_t *, sns_screq_t *, sns_screq_t *);
+void isp_put_gid_ft_request(ispsoftc_t *, sns_gid_ft_req_t *, sns_gid_ft_req_t *);
+void isp_put_gxn_id_request(ispsoftc_t *, sns_gxn_id_req_t *, sns_gxn_id_req_t *);
+void isp_get_sns_response(ispsoftc_t *, sns_scrsp_t *, sns_scrsp_t *, int);
+void isp_get_gid_ft_response(ispsoftc_t *, sns_gid_ft_rsp_t *, sns_gid_ft_rsp_t *, int);
+void isp_get_gxn_id_response(ispsoftc_t *, sns_gxn_id_rsp_t *, sns_gxn_id_rsp_t *);
+void isp_get_gff_id_response(ispsoftc_t *, sns_gff_id_rsp_t *, sns_gff_id_rsp_t *);
+void isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *, sns_ga_nxt_rsp_t *);
+void isp_get_els(ispsoftc_t *, els_t *, els_t *);
+void isp_put_els(ispsoftc_t *, els_t *, els_t *);
+void isp_get_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *);
+void isp_get_fcp_cmnd_iu(ispsoftc_t *, fcp_cmnd_iu_t *, fcp_cmnd_iu_t *);
+void isp_put_rft_id(ispsoftc_t *, rft_id_t *, rft_id_t *);
+void isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
+void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
+
+#define ISP_HANDLE_MASK 0x7fff
+
+#ifdef ISP_TARGET_MODE
+#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <dev/ic/isp_target.h>
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__)
#include <dev/isp/isp_target.h>
#else
#include "isp_target.h"
#endif
-#define IS_TARGET_HANDLE(x) ((x) & 0x8000)
-
-extern int isp_save_xs_tgt(ispsoftc_t *, void *, uint32_t *);
-extern void *isp_find_xs_tgt(ispsoftc_t *, uint32_t);
-extern uint32_t isp_find_tgt_handle(ispsoftc_t *, void *);
-extern void isp_destroy_tgt_handle(ispsoftc_t *, uint32_t);
-
-extern void
-isp_put_atio(ispsoftc_t *, at_entry_t *, at_entry_t *);
-extern void
-isp_get_atio(ispsoftc_t *, at_entry_t *, at_entry_t *);
-extern void
-isp_put_atio2(ispsoftc_t *, at2_entry_t *, at2_entry_t *);
-extern void
-isp_put_atio2e(ispsoftc_t *, at2e_entry_t *, at2e_entry_t *);
-extern void
-isp_get_atio2(ispsoftc_t *, at2_entry_t *, at2_entry_t *);
-extern void
-isp_get_atio2e(ispsoftc_t *, at2e_entry_t *, at2e_entry_t *);
-extern void
-isp_get_atio7(ispsoftc_t *isp, at7_entry_t *, at7_entry_t *);
-extern void
-isp_put_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *);
-extern void
-isp_get_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *);
-extern void
-isp_put_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *);
-extern void
-isp_put_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *);
-extern void
-isp_put_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *);
-extern void
-isp_get_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *);
-extern void
-isp_get_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *);
-extern void
-isp_get_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *);
-extern void
-isp_put_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *);
-extern void
-isp_get_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *);
-extern void
-isp_put_notify(ispsoftc_t *, in_entry_t *, in_entry_t *);
-extern void
-isp_get_notify(ispsoftc_t *, in_entry_t *, in_entry_t *);
-extern void
-isp_put_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *);
-extern void
-isp_put_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *);
-extern void
-isp_put_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *);
-extern void
-isp_get_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *);
-extern void
-isp_get_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *);
-extern void
-isp_get_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *);
-extern void
-isp_put_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *);
-extern void
-isp_get_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *);
-extern void
-isp_put_notify_24xx_ack(ispsoftc_t *, na_fcentry_24xx_t *, na_fcentry_24xx_t *);
-extern void
-isp_put_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *);
-extern void
-isp_put_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *);
-extern void isp_put_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *,
- na_fcentry_24xx_t *);
-extern void
-isp_get_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *);
-extern void
-isp_get_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *);
-extern void isp_get_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *,
- na_fcentry_24xx_t *);
-extern void
-isp_get_abts(ispsoftc_t *, abts_t *, abts_t *);
-extern void
-isp_put_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *);
-extern void
-isp_get_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *);
-#endif /* ISP_TARGET_MODE */
-#endif /* _ISP_LIBRARY_H */
+int isp_send_tgt_cmd(ispsoftc_t *, void *, void *, uint32_t, uint32_t, isp_ddir_t, void *, uint32_t);
+
+#define IS_TARGET_HANDLE(x) ((x) & 0x8000)
+
+int isp_save_xs_tgt(ispsoftc_t *, void *, uint32_t *);
+void *isp_find_xs_tgt(ispsoftc_t *, uint32_t);
+uint32_t isp_find_tgt_handle(ispsoftc_t *, void *);
+void isp_destroy_tgt_handle(ispsoftc_t *, uint32_t);
+
+int isp_find_pdb_by_wwn(ispsoftc_t *, int, uint64_t, fcportdb_t **);
+int isp_find_pdb_by_loopid(ispsoftc_t *, int, uint32_t, fcportdb_t **);
+int isp_find_pdb_by_sid(ispsoftc_t *, int, uint32_t, fcportdb_t **);
+void isp_find_chan_by_did(ispsoftc_t *, uint32_t, uint16_t *);
+void isp_add_wwn_entry(ispsoftc_t *, int, uint64_t, uint16_t, uint32_t);
+void isp_del_wwn_entry(ispsoftc_t *, int, uint64_t, uint16_t, uint32_t);
+void isp_del_all_wwn_entries(ispsoftc_t *, int);
+void isp_del_wwn_entries(ispsoftc_t *, isp_notify_t *);
+
+void isp_put_atio(ispsoftc_t *, at_entry_t *, at_entry_t *);
+void isp_get_atio(ispsoftc_t *, at_entry_t *, at_entry_t *);
+void isp_put_atio2(ispsoftc_t *, at2_entry_t *, at2_entry_t *);
+void isp_put_atio2e(ispsoftc_t *, at2e_entry_t *, at2e_entry_t *);
+void isp_get_atio2(ispsoftc_t *, at2_entry_t *, at2_entry_t *);
+void isp_get_atio2e(ispsoftc_t *, at2e_entry_t *, at2e_entry_t *);
+void isp_get_atio7(ispsoftc_t *isp, at7_entry_t *, at7_entry_t *);
+void isp_put_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *);
+void isp_get_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *);
+void isp_put_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *);
+void isp_put_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *);
+void isp_put_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *);
+void isp_get_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *);
+void isp_get_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *);
+void isp_get_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *);
+void isp_put_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *);
+void isp_get_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *);
+void isp_put_notify(ispsoftc_t *, in_entry_t *, in_entry_t *);
+void isp_get_notify(ispsoftc_t *, in_entry_t *, in_entry_t *);
+void isp_put_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *);
+void isp_put_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *);
+void isp_put_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *);
+void isp_get_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *);
+void isp_get_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *);
+void isp_get_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *);
+void isp_put_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *);
+void isp_get_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *);
+void isp_put_notify_24xx_ack(ispsoftc_t *, na_fcentry_24xx_t *, na_fcentry_24xx_t *);
+void isp_put_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *);
+void isp_put_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *);
+void isp_put_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *, na_fcentry_24xx_t *);
+void isp_get_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *);
+void isp_get_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *);
+void isp_get_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *, na_fcentry_24xx_t *);
+void isp_get_abts(ispsoftc_t *, abts_t *, abts_t *);
+void isp_put_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *);
+void isp_get_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *);
+#endif /* ISP_TARGET_MODE */
+#endif /* _ISP_LIBRARY_H */
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 526337c..47dd350 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997-2006 by Matthew Jacob
+ * Copyright (c) 1997-2008 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,47 +34,31 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
-#if __FreeBSD_version >= 700000
#include <sys/linker.h>
#include <sys/firmware.h>
-#endif
#include <sys/bus.h>
-#if __FreeBSD_version < 500000
-#include <pci/pcireg.h>
-#include <pci/pcivar.h>
-#include <machine/bus_memio.h>
-#include <machine/bus_pio.h>
-#else
#include <sys/stdint.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#endif
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <sys/malloc.h>
+#include <sys/uio.h>
#include <dev/isp/isp_freebsd.h>
-#if __FreeBSD_version < 500000
-#define BUS_PROBE_DEFAULT 0
-#endif
-
static uint32_t isp_pci_rd_reg(ispsoftc_t *, int);
static void isp_pci_wr_reg(ispsoftc_t *, int, uint32_t);
static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int);
static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t);
static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int);
static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t);
-static int
-isp_pci_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
-static int
-isp_pci_rd_isr_2300(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
-static int
-isp_pci_rd_isr_2400(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
+static int isp_pci_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
+static int isp_pci_rd_isr_2300(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
+static int isp_pci_rd_isr_2400(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
static int isp_pci_mbxdma(ispsoftc_t *);
-static int
-isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
+static int isp_pci_dmasetup(ispsoftc_t *, XS_T *, void *);
static void isp_pci_reset0(ispsoftc_t *);
@@ -171,6 +155,18 @@ static struct ispmdvec mdvec_2400 = {
NULL
};
+static struct ispmdvec mdvec_2500 = {
+ isp_pci_rd_isr_2400,
+ isp_pci_rd_reg_2400,
+ isp_pci_wr_reg_2400,
+ isp_pci_mbxdma,
+ isp_pci_dmasetup,
+ isp_common_dmateardown,
+ isp_pci_reset0,
+ isp_pci_reset1,
+ NULL
+};
+
#ifndef PCIM_CMD_INVEN
#define PCIM_CMD_INVEN 0x10
#endif
@@ -259,6 +255,10 @@ static struct ispmdvec mdvec_2400 = {
#define PCI_PRODUCT_QLOGIC_ISP2432 0x2432
#endif
+#ifndef PCI_PRODUCT_QLOGIC_ISP2532
+#define PCI_PRODUCT_QLOGIC_ISP2532 0x2532
+#endif
+
#ifndef PCI_PRODUCT_QLOGIC_ISP6312
#define PCI_PRODUCT_QLOGIC_ISP6312 0x6312
#endif
@@ -307,6 +307,9 @@ static struct ispmdvec mdvec_2400 = {
#define PCI_QLOGIC_ISP2432 \
((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC)
+#define PCI_QLOGIC_ISP2532 \
+ ((PCI_PRODUCT_QLOGIC_ISP2532 << 16) | PCI_VENDOR_QLOGIC)
+
#define PCI_QLOGIC_ISP6312 \
((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC)
@@ -337,9 +340,7 @@ struct isp_pcisoftc {
void * ih;
int16_t pci_poff[_NREG_BLKS];
bus_dma_tag_t dmat;
-#if __FreeBSD_version > 700025
int msicount;
-#endif
};
@@ -356,14 +357,11 @@ static driver_t isp_pci_driver = {
};
static devclass_t isp_devclass;
DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0);
-#if __FreeBSD_version < 700000
-extern ispfwfunc *isp_get_firmware_p;
-#endif
static int
isp_pci_probe(device_t dev)
{
- switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) {
+ switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) {
case PCI_QLOGIC_ISP1020:
device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter");
break;
@@ -406,6 +404,9 @@ isp_pci_probe(device_t dev)
case PCI_QLOGIC_ISP2432:
device_set_desc(dev, "Qlogic ISP 2432 PCI FC-AL Adapter");
break;
+ case PCI_QLOGIC_ISP2532:
+ device_set_desc(dev, "Qlogic ISP 2532 PCI FC-AL Adapter");
+ break;
case PCI_QLOGIC_ISP6312:
device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter");
break;
@@ -429,176 +430,8 @@ isp_pci_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
-#if __FreeBSD_version < 500000
-static void
-isp_get_generic_options(device_t dev, ispsoftc_t *isp)
-{
- int bitmap, unit;
-
- unit = device_get_unit(dev);
- if (getenv_int("isp_disable", &bitmap)) {
- if (bitmap & (1 << unit)) {
- isp->isp_osinfo.disabled = 1;
- return;
- }
- }
- if (getenv_int("isp_no_fwload", &bitmap)) {
- if (bitmap & (1 << unit))
- isp->isp_confopts |= ISP_CFG_NORELOAD;
- }
- if (getenv_int("isp_fwload", &bitmap)) {
- if (bitmap & (1 << unit))
- isp->isp_confopts &= ~ISP_CFG_NORELOAD;
- }
- if (getenv_int("isp_no_nvram", &bitmap)) {
- if (bitmap & (1 << unit))
- isp->isp_confopts |= ISP_CFG_NONVRAM;
- }
- if (getenv_int("isp_nvram", &bitmap)) {
- if (bitmap & (1 << unit))
- isp->isp_confopts &= ~ISP_CFG_NONVRAM;
- }
-
- bitmap = 0;
- (void) getenv_int("isp_debug", &bitmap);
- if (bitmap) {
- isp->isp_dblev = bitmap;
- } else {
- isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
- }
- if (bootverbose) {
- isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
- }
-
- bitmap = 0;
- if (getenv_int("role", &bitmap)) {
- isp->isp_role = bitmap;
- } else {
- isp->isp_role = ISP_DEFAULT_ROLES;
- }
-
-}
-
-static void
-isp_get_pci_options(device_t dev, int *m1, int *m2)
-{
- int bitmap;
- int unit = device_get_unit(dev);
-
- *m1 = PCIM_CMD_MEMEN;
- *m2 = PCIM_CMD_PORTEN;
- if (getenv_int("isp_mem_map", &bitmap)) {
- if (bitmap & (1 << unit)) {
- *m1 = PCIM_CMD_MEMEN;
- *m2 = PCIM_CMD_PORTEN;
- }
- }
- bitmap = 0;
- if (getenv_int("isp_io_map", &bitmap)) {
- if (bitmap & (1 << unit)) {
- *m1 = PCIM_CMD_PORTEN;
- *m2 = PCIM_CMD_MEMEN;
- }
- }
-}
-
static void
-isp_get_specific_options(device_t dev, ispsoftc_t *isp)
-{
- uint64_t wwn;
- int bitmap;
- int unit = device_get_unit(dev);
-
-
- if (IS_SCSI(isp)) {
- return;
- }
-
- if (getenv_int("isp_fcduplex", &bitmap)) {
- if (bitmap & (1 << unit))
- isp->isp_confopts |= ISP_CFG_FULL_DUPLEX;
- }
- if (getenv_int("isp_no_fcduplex", &bitmap)) {
- if (bitmap & (1 << unit))
- isp->isp_confopts &= ~ISP_CFG_FULL_DUPLEX;
- }
- if (getenv_int("isp_nport", &bitmap)) {
- if (bitmap & (1 << unit))
- isp->isp_confopts |= ISP_CFG_NPORT;
- }
-
- /*
- * Because the resource_*_value functions can neither return
- * 64 bit integer values, nor can they be directly coerced
- * to interpret the right hand side of the assignment as
- * you want them to interpret it, we have to force WWN
- * hint replacement to specify WWN strings with a leading
- * 'w' (e..g w50000000aaaa0001). Sigh.
- */
- if (getenv_quad("isp_portwwn", &wwn)) {
- isp->isp_osinfo.default_port_wwn = wwn;
- isp->isp_confopts |= ISP_CFG_OWNWWPN;
- }
- if (isp->isp_osinfo.default_port_wwn == 0) {
- isp->isp_osinfo.default_port_wwn = 0x400000007F000009ull;
- }
-
- if (getenv_quad("isp_nodewwn", &wwn)) {
- isp->isp_osinfo.default_node_wwn = wwn;
- isp->isp_confopts |= ISP_CFG_OWNWWNN;
- }
- if (isp->isp_osinfo.default_node_wwn == 0) {
- isp->isp_osinfo.default_node_wwn = 0x400000007F000009ull;
- }
-
- bitmap = 0;
- (void) getenv_int("isp_fabric_hysteresis", &bitmap);
- if (bitmap >= 0 && bitmap < 256) {
- isp->isp_osinfo.hysteresis = bitmap;
- } else {
- isp->isp_osinfo.hysteresis = isp_fabric_hysteresis;
- }
-
- bitmap = 0;
- (void) getenv_int("isp_loop_down_limit", &bitmap);
- if (bitmap >= 0 && bitmap < 0xffff) {
- isp->isp_osinfo.loop_down_limit = bitmap;
- } else {
- isp->isp_osinfo.loop_down_limit = isp_loop_down_limit;
- }
-
- bitmap = 0;
- (void) getenv_int("isp_gone_device_time", &bitmap);
- if (bitmap >= 0 && bitmap < 0xffff) {
- isp->isp_osinfo.gone_device_time = bitmap;
- } else {
- isp->isp_osinfo.gone_device_time = isp_gone_device_time;
- }
-#ifdef ISP_FW_CRASH_DUMP
- bitmap = 0;
- if (getenv_int("isp_fw_dump_enable", &bitmap)) {
- if (bitmap & (1 << unit) {
- size_t amt = 0;
- if (IS_2200(isp)) {
- amt = QLA2200_RISC_IMAGE_DUMP_SIZE;
- } else if (IS_23XX(isp)) {
- amt = QLA2300_RISC_IMAGE_DUMP_SIZE;
- }
- if (amt) {
- FCPARAM(isp)->isp_dump_data =
- malloc(amt, M_DEVBUF, M_WAITOK);
- memset(FCPARAM(isp)->isp_dump_data, 0, amt);
- } else {
- device_printf(dev,
- "f/w crash dumps not supported for card\n");
- }
- }
- }
-#endif
-}
-#else
-static void
-isp_get_generic_options(device_t dev, ispsoftc_t *isp)
+isp_get_generic_options(device_t dev, ispsoftc_t *isp, int *nvp)
{
int tval;
@@ -606,41 +439,22 @@ isp_get_generic_options(device_t dev, ispsoftc_t *isp)
* Figure out if we're supposed to skip this one.
*/
tval = 0;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "disable", &tval) == 0 && tval) {
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "disable", &tval) == 0 && tval) {
device_printf(dev, "disabled at user request\n");
isp->isp_osinfo.disabled = 1;
return;
}
- tval = -1;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "role", &tval) == 0 && tval != -1) {
- tval &= (ISP_ROLE_INITIATOR|ISP_ROLE_TARGET);
- isp->isp_role = tval;
- device_printf(dev, "setting role to 0x%x\n", isp->isp_role);
- } else {
-#ifdef ISP_TARGET_MODE
- isp->isp_role = ISP_ROLE_TARGET;
-#else
- isp->isp_role = ISP_DEFAULT_ROLES;
-#endif
- }
-
tval = 0;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "fwload_disable", &tval) == 0 && tval != 0) {
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fwload_disable", &tval) == 0 && tval != 0) {
isp->isp_confopts |= ISP_CFG_NORELOAD;
}
tval = 0;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "ignore_nvram", &tval) == 0 && tval != 0) {
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "ignore_nvram", &tval) == 0 && tval != 0) {
isp->isp_confopts |= ISP_CFG_NONVRAM;
}
-
tval = 0;
- (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
- "debug", &tval);
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &tval);
if (tval) {
isp->isp_dblev = tval;
} else {
@@ -649,7 +463,23 @@ isp_get_generic_options(device_t dev, ispsoftc_t *isp)
if (bootverbose) {
isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
}
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "vports", &tval);
+ if (tval > 0 && tval < 127) {
+ *nvp = tval;
+ } else {
+ *nvp = 0;
+ }
+ tval = 1;
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "autoconfig", &tval);
+ isp_autoconfig = tval;
+ tval = 7;
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "quickboot_time", &tval);
+ isp_quickboot_time = tval;
+ tval = 0;
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "forcemulti", &tval) == 0 && tval != 0) {
+ isp->isp_osinfo.forcemulti = 1;
+ }
}
static void
@@ -666,70 +496,68 @@ isp_get_pci_options(device_t dev, int *m1, int *m2)
*m2 = PCIM_CMD_PORTEN;
tval = 0;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "prefer_iomap", &tval) == 0 && tval != 0) {
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "prefer_iomap", &tval) == 0 && tval != 0) {
*m1 = PCIM_CMD_PORTEN;
*m2 = PCIM_CMD_MEMEN;
}
tval = 0;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "prefer_memmap", &tval) == 0 && tval != 0) {
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "prefer_memmap", &tval) == 0 && tval != 0) {
*m1 = PCIM_CMD_MEMEN;
*m2 = PCIM_CMD_PORTEN;
}
}
static void
-isp_get_specific_options(device_t dev, ispsoftc_t *isp)
+isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
{
const char *sptr;
int tval;
- isp->isp_osinfo.default_id = -1;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "iid", &tval) == 0) {
- isp->isp_osinfo.default_id = tval;
- isp->isp_confopts |= ISP_CFG_OWNLOOPID;
- }
- if (isp->isp_osinfo.default_id == -1) {
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "iid", &tval)) {
if (IS_FC(isp)) {
- isp->isp_osinfo.default_id = 109;
+ ISP_FC_PC(isp, chan)->default_id = 109 - chan;
} else {
- isp->isp_osinfo.default_id = 7;
+ ISP_SPI_PC(isp, chan)->iid = 7;
}
+ } else {
+ if (IS_FC(isp)) {
+ ISP_FC_PC(isp, chan)->default_id = tval - chan;
+ } else {
+ ISP_SPI_PC(isp, chan)->iid = tval;
+ }
+ isp->isp_confopts |= ISP_CFG_OWNLOOPID;
+ }
+
+ tval = -1;
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "role", &tval) == 0) {
+ switch (tval) {
+ case ISP_ROLE_NONE:
+ case ISP_ROLE_INITIATOR:
+ case ISP_ROLE_TARGET:
+ case ISP_ROLE_INITIATOR|ISP_ROLE_TARGET:
+ device_printf(dev, "setting role to 0x%x\n", tval);
+ break;
+ default:
+ tval = -1;
+ break;
+ }
+ }
+ if (tval == -1) {
+ tval = ISP_DEFAULT_ROLES;
}
if (IS_SCSI(isp)) {
+ ISP_SPI_PC(isp, chan)->role = tval;
return;
}
+ ISP_FC_PC(isp, chan)->role = tval;
tval = 0;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "fullduplex", &tval) == 0 && tval != 0) {
+ if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fullduplex", &tval) == 0 && tval != 0) {
isp->isp_confopts |= ISP_CFG_FULL_DUPLEX;
}
-#ifdef ISP_FW_CRASH_DUMP
- tval = 0;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "fw_dump_enable", &tval) == 0 && tval != 0) {
- size_t amt = 0;
- if (IS_2200(isp)) {
- amt = QLA2200_RISC_IMAGE_DUMP_SIZE;
- } else if (IS_23XX(isp)) {
- amt = QLA2300_RISC_IMAGE_DUMP_SIZE;
- }
- if (amt) {
- FCPARAM(isp)->isp_dump_data =
- malloc(amt, M_DEVBUF, M_WAITOK | M_ZERO);
- } else {
- device_printf(dev,
- "f/w crash dumps not supported for this model\n");
- }
- }
-#endif
sptr = 0;
- if (resource_string_value(device_get_name(dev), device_get_unit(dev),
- "topology", (const char **) &sptr) == 0 && sptr != 0) {
+ if (resource_string_value(device_get_name(dev), device_get_unit(dev), "topology", (const char **) &sptr) == 0 && sptr != 0) {
if (strcmp(sptr, "lport") == 0) {
isp->isp_confopts |= ISP_CFG_LPORT;
} else if (strcmp(sptr, "nport") == 0) {
@@ -750,81 +578,63 @@ isp_get_specific_options(device_t dev, ispsoftc_t *isp)
* 'w' (e..g w50000000aaaa0001). Sigh.
*/
sptr = 0;
- tval = resource_string_value(device_get_name(dev), device_get_unit(dev),
- "portwwn", (const char **) &sptr);
+ tval = resource_string_value(device_get_name(dev), device_get_unit(dev), "portwwn", (const char **) &sptr);
if (tval == 0 && sptr != 0 && *sptr++ == 'w') {
char *eptr = 0;
- isp->isp_osinfo.default_port_wwn = strtouq(sptr, &eptr, 16);
- if (eptr < sptr + 16 || isp->isp_osinfo.default_port_wwn == 0) {
+ ISP_FC_PC(isp, chan)->def_wwpn = strtouq(sptr, &eptr, 16);
+ if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwpn == -1) {
device_printf(dev, "mangled portwwn hint '%s'\n", sptr);
- isp->isp_osinfo.default_port_wwn = 0;
- } else {
- isp->isp_confopts |= ISP_CFG_OWNWWPN;
+ ISP_FC_PC(isp, chan)->def_wwpn = 0;
}
}
- if (isp->isp_osinfo.default_port_wwn == 0) {
- isp->isp_osinfo.default_port_wwn = 0x400000007F000009ull;
- }
sptr = 0;
- tval = resource_string_value(device_get_name(dev), device_get_unit(dev),
- "nodewwn", (const char **) &sptr);
+ tval = resource_string_value(device_get_name(dev), device_get_unit(dev), "nodewwn", (const char **) &sptr);
if (tval == 0 && sptr != 0 && *sptr++ == 'w') {
char *eptr = 0;
- isp->isp_osinfo.default_node_wwn = strtouq(sptr, &eptr, 16);
- if (eptr < sptr + 16 || isp->isp_osinfo.default_node_wwn == 0) {
+ ISP_FC_PC(isp, chan)->def_wwnn = strtouq(sptr, &eptr, 16);
+ if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwnn == 0) {
device_printf(dev, "mangled nodewwn hint '%s'\n", sptr);
- isp->isp_osinfo.default_node_wwn = 0;
- } else {
- isp->isp_confopts |= ISP_CFG_OWNWWNN;
+ ISP_FC_PC(isp, chan)->def_wwnn = 0;
}
}
- if (isp->isp_osinfo.default_node_wwn == 0) {
- isp->isp_osinfo.default_node_wwn = 0x400000007F000009ull;
- }
-
tval = 0;
- (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
- "hysteresis", &tval);
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "hysteresis", &tval);
if (tval >= 0 && tval < 256) {
- isp->isp_osinfo.hysteresis = tval;
+ ISP_FC_PC(isp, chan)->hysteresis = tval;
} else {
- isp->isp_osinfo.hysteresis = isp_fabric_hysteresis;
+ ISP_FC_PC(isp, chan)->hysteresis = isp_fabric_hysteresis;
}
tval = -1;
- (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
- "loop_down_limit", &tval);
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "loop_down_limit", &tval);
if (tval >= 0 && tval < 0xffff) {
- isp->isp_osinfo.loop_down_limit = tval;
+ ISP_FC_PC(isp, chan)->loop_down_limit = tval;
} else {
- isp->isp_osinfo.loop_down_limit = isp_loop_down_limit;
+ ISP_FC_PC(isp, chan)->loop_down_limit = isp_loop_down_limit;
}
tval = -1;
- (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
- "gone_device_time", &tval);
+ (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "gone_device_time", &tval);
if (tval >= 0 && tval < 0xffff) {
- isp->isp_osinfo.gone_device_time = tval;
+ ISP_FC_PC(isp, chan)->gone_device_time = tval;
} else {
- isp->isp_osinfo.gone_device_time = isp_gone_device_time;
+ ISP_FC_PC(isp, chan)->gone_device_time = isp_gone_device_time;
}
}
-#endif
static int
isp_pci_attach(device_t dev)
{
struct resource *regs, *irq;
- int rtp, rgd, iqd, m1, m2;
- uint32_t data, cmd, linesz, psize, basetype;
+ int rtp, rgd, iqd, i, m1, m2, locksetup = 0;
+ int isp_nvports = 0;
+ uint32_t data, cmd, linesz, did;
struct isp_pcisoftc *pcs;
ispsoftc_t *isp = NULL;
- struct ispmdvec *mdvp;
-#if __FreeBSD_version >= 500000
- int locksetup = 0;
-#endif
+ size_t psize, xsize;
+ char fwname[32];
pcs = device_get_softc(dev);
if (pcs == NULL) {
@@ -832,13 +642,16 @@ isp_pci_attach(device_t dev)
return (ENOMEM);
}
memset(pcs, 0, sizeof (*pcs));
+
pcs->pci_dev = dev;
isp = &pcs->pci_isp;
+ isp->isp_dev = dev;
+ isp->isp_nchan = 1;
/*
* Get Generic Options
*/
- isp_get_generic_options(dev, isp);
+ isp_get_generic_options(dev, isp, &isp_nvports);
/*
* Check to see if options have us disabled
@@ -875,68 +688,62 @@ isp_pci_attach(device_t dev)
goto bad;
}
if (bootverbose) {
- device_printf(dev, "using %s space register mapping\n",
- (rgd == IO_MAP_REG)? "I/O" : "Memory");
+ device_printf(dev, "using %s space register mapping\n", (rgd == IO_MAP_REG)? "I/O" : "Memory");
}
- pcs->pci_dev = dev;
- pcs->pci_reg = regs;
isp->isp_bus_tag = rman_get_bustag(regs);
isp->isp_bus_handle = rman_get_bushandle(regs);
+ pcs->pci_dev = dev;
+ pcs->pci_reg = regs;
pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF;
pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
- mdvp = &mdvec;
- basetype = ISP_HA_SCSI_UNKNOWN;
- psize = sizeof (sdparam);
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP1020) {
- mdvp = &mdvec;
- basetype = ISP_HA_SCSI_UNKNOWN;
- psize = sizeof (sdparam);
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP1080) {
- mdvp = &mdvec_1080;
- basetype = ISP_HA_SCSI_1080;
- psize = sizeof (sdparam);
- pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
- ISP1080_DMA_REGS_OFF;
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP1240) {
- mdvp = &mdvec_1080;
- basetype = ISP_HA_SCSI_1240;
- psize = 2 * sizeof (sdparam);
- pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
- ISP1080_DMA_REGS_OFF;
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP1280) {
- mdvp = &mdvec_1080;
- basetype = ISP_HA_SCSI_1280;
- psize = 2 * sizeof (sdparam);
- pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
- ISP1080_DMA_REGS_OFF;
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP10160) {
- mdvp = &mdvec_12160;
- basetype = ISP_HA_SCSI_10160;
- psize = sizeof (sdparam);
- pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
- ISP1080_DMA_REGS_OFF;
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP12160) {
- mdvp = &mdvec_12160;
- basetype = ISP_HA_SCSI_12160;
- psize = 2 * sizeof (sdparam);
- pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
- ISP1080_DMA_REGS_OFF;
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP2100) {
- mdvp = &mdvec_2100;
- basetype = ISP_HA_FC_2100;
- psize = sizeof (fcparam);
- pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
- PCI_MBOX_REGS2100_OFF;
+
+ switch (pci_get_devid(dev)) {
+ case PCI_QLOGIC_ISP1020:
+ did = 0x1040;
+ isp->isp_mdvec = &mdvec;
+ isp->isp_type = ISP_HA_SCSI_UNKNOWN;
+ break;
+ case PCI_QLOGIC_ISP1080:
+ did = 0x1080;
+ isp->isp_mdvec = &mdvec_1080;
+ isp->isp_type = ISP_HA_SCSI_1080;
+ pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
+ break;
+ case PCI_QLOGIC_ISP1240:
+ did = 0x1080;
+ isp->isp_mdvec = &mdvec_1080;
+ isp->isp_type = ISP_HA_SCSI_1240;
+ isp->isp_nchan = 2;
+ pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
+ break;
+ case PCI_QLOGIC_ISP1280:
+ did = 0x1080;
+ isp->isp_mdvec = &mdvec_1080;
+ isp->isp_type = ISP_HA_SCSI_1280;
+ pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
+ break;
+ case PCI_QLOGIC_ISP10160:
+ did = 0x12160;
+ isp->isp_mdvec = &mdvec_12160;
+ isp->isp_type = ISP_HA_SCSI_10160;
+ pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
+ break;
+ case PCI_QLOGIC_ISP12160:
+ did = 0x12160;
+ isp->isp_nchan = 2;
+ isp->isp_mdvec = &mdvec_12160;
+ isp->isp_type = ISP_HA_SCSI_12160;
+ pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
+ break;
+ case PCI_QLOGIC_ISP2100:
+ did = 0x2100;
+ isp->isp_mdvec = &mdvec_2100;
+ isp->isp_type = ISP_HA_FC_2100;
+ pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF;
if (pci_get_revid(dev) < 3) {
/*
* XXX: Need to get the actual revision
@@ -946,121 +753,100 @@ isp_pci_attach(device_t dev)
*/
linesz = 1;
}
+ break;
+ case PCI_QLOGIC_ISP2200:
+ did = 0x2200;
+ isp->isp_mdvec = &mdvec_2200;
+ isp->isp_type = ISP_HA_FC_2200;
+ pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF;
+ break;
+ case PCI_QLOGIC_ISP2300:
+ did = 0x2300;
+ isp->isp_mdvec = &mdvec_2300;
+ isp->isp_type = ISP_HA_FC_2300;
+ pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF;
+ break;
+ case PCI_QLOGIC_ISP2312:
+ case PCI_QLOGIC_ISP6312:
+ did = 0x2300;
+ isp->isp_mdvec = &mdvec_2300;
+ isp->isp_type = ISP_HA_FC_2312;
+ pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF;
+ break;
+ case PCI_QLOGIC_ISP2322:
+ case PCI_QLOGIC_ISP6322:
+ did = 0x2322;
+ isp->isp_mdvec = &mdvec_2300;
+ isp->isp_type = ISP_HA_FC_2322;
+ pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF;
+ break;
+ case PCI_QLOGIC_ISP2422:
+ case PCI_QLOGIC_ISP2432:
+ did = 0x2400;
+ isp->isp_nchan += isp_nvports;
+ isp->isp_mdvec = &mdvec_2400;
+ isp->isp_type = ISP_HA_FC_2400;
+ pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF;
+ break;
+ case PCI_QLOGIC_ISP2532:
+ did = 0x2500;
+ isp->isp_nchan += isp_nvports;
+ isp->isp_mdvec = &mdvec_2500;
+ isp->isp_type = ISP_HA_FC_2500;
+ pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF;
+ break;
+ default:
+ device_printf(dev, "unknown device type\n");
+ goto bad;
+ break;
}
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP2200) {
- mdvp = &mdvec_2200;
- basetype = ISP_HA_FC_2200;
- psize = sizeof (fcparam);
- pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
- PCI_MBOX_REGS2100_OFF;
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP2300) {
- mdvp = &mdvec_2300;
- basetype = ISP_HA_FC_2300;
- psize = sizeof (fcparam);
- pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
- PCI_MBOX_REGS2300_OFF;
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP2312 ||
- pci_get_devid(dev) == PCI_QLOGIC_ISP6312) {
- mdvp = &mdvec_2300;
- basetype = ISP_HA_FC_2312;
- psize = sizeof (fcparam);
- pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
- PCI_MBOX_REGS2300_OFF;
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP2322 ||
- pci_get_devid(dev) == PCI_QLOGIC_ISP6322) {
- mdvp = &mdvec_2300;
- basetype = ISP_HA_FC_2322;
- psize = sizeof (fcparam);
- pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
- PCI_MBOX_REGS2300_OFF;
- }
- if (pci_get_devid(dev) == PCI_QLOGIC_ISP2422 ||
- pci_get_devid(dev) == PCI_QLOGIC_ISP2432) {
- mdvp = &mdvec_2400;
- basetype = ISP_HA_FC_2400;
+ isp->isp_revision = pci_get_revid(dev);
+
+ if (IS_FC(isp)) {
psize = sizeof (fcparam);
- pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
- PCI_MBOX_REGS2400_OFF;
+ xsize = sizeof (struct isp_fc);
+ } else {
+ psize = sizeof (sdparam);
+ xsize = sizeof (struct isp_spi);
}
- isp = &pcs->pci_isp;
+ psize *= isp->isp_nchan;
+ xsize *= isp->isp_nchan;
isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO);
if (isp->isp_param == NULL) {
device_printf(dev, "cannot allocate parameter data\n");
goto bad;
}
- isp->isp_mdvec = mdvp;
- isp->isp_type = basetype;
- isp->isp_revision = pci_get_revid(dev);
- isp->isp_dev = dev;
+ isp->isp_osinfo.pc.ptr = malloc(xsize, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (isp->isp_osinfo.pc.ptr == NULL) {
+ device_printf(dev, "cannot allocate parameter data\n");
+ goto bad;
+ }
/*
* Now that we know who we are (roughly) get/set specific options
*/
- isp_get_specific_options(dev, isp);
+ for (i = 0; i < isp->isp_nchan; i++) {
+ isp_get_specific_options(dev, i, isp);
+ }
-#if __FreeBSD_version >= 700000
/*
- * Try and find firmware for this device.
+ * The 'it' suffix really only matters for SCSI cards in target mode.
*/
- {
- char fwname[32];
- unsigned int did = pci_get_device(dev);
-
- /*
- * Map a few pci ids to fw names
- */
- switch (did) {
- case PCI_PRODUCT_QLOGIC_ISP1020:
- did = 0x1040;
- break;
- case PCI_PRODUCT_QLOGIC_ISP1240:
- did = 0x1080;
- break;
- case PCI_PRODUCT_QLOGIC_ISP10160:
- case PCI_PRODUCT_QLOGIC_ISP12160:
- did = 0x12160;
- break;
- case PCI_PRODUCT_QLOGIC_ISP6312:
- case PCI_PRODUCT_QLOGIC_ISP2312:
- did = 0x2300;
- break;
- case PCI_PRODUCT_QLOGIC_ISP6322:
- did = 0x2322;
- break;
- case PCI_PRODUCT_QLOGIC_ISP2422:
- case PCI_PRODUCT_QLOGIC_ISP2432:
- did = 0x2400;
- break;
- default:
- break;
- }
-
- isp->isp_osinfo.fw = NULL;
- if (isp->isp_role & ISP_ROLE_TARGET) {
- snprintf(fwname, sizeof (fwname), "isp_%04x_it", did);
- isp->isp_osinfo.fw = firmware_get(fwname);
- }
- if (isp->isp_osinfo.fw == NULL) {
- snprintf(fwname, sizeof (fwname), "isp_%04x", did);
- isp->isp_osinfo.fw = firmware_get(fwname);
- }
- if (isp->isp_osinfo.fw != NULL) {
- isp->isp_mdvec->dv_ispfw = isp->isp_osinfo.fw->data;
- }
+ isp->isp_osinfo.fw = NULL;
+ if (IS_SCSI(isp) && (ISP_SPI_PC(isp, 0)->role & ISP_ROLE_TARGET)) {
+ snprintf(fwname, sizeof (fwname), "isp_%04x_it", did);
+ isp->isp_osinfo.fw = firmware_get(fwname);
+ } else if (IS_24XX(isp) && (isp->isp_nchan > 1 || isp->isp_osinfo.forcemulti)) {
+ snprintf(fwname, sizeof (fwname), "isp_%04x_multi", did);
+ isp->isp_osinfo.fw = firmware_get(fwname);
}
-#else
- if (isp_get_firmware_p) {
- int device = (int) pci_get_device(dev);
-#ifdef ISP_TARGET_MODE
- (*isp_get_firmware_p)(0, 1, device, &mdvp->dv_ispfw);
-#else
- (*isp_get_firmware_p)(0, 0, device, &mdvp->dv_ispfw);
-#endif
+ if (isp->isp_osinfo.fw == NULL) {
+ snprintf(fwname, sizeof (fwname), "isp_%04x", did);
+ isp->isp_osinfo.fw = firmware_get(fwname);
+ }
+ if (isp->isp_osinfo.fw != NULL) {
+ isp->isp_mdvec->dv_ispfw = isp->isp_osinfo.fw->data;
}
-#endif
/*
* Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER
@@ -1077,43 +863,9 @@ isp_pci_attach(device_t dev)
cmd &= ~PCIM_CMD_INTX_DISABLE;
}
-#ifdef WE_KNEW_WHAT_WE_WERE_DOING
- if (IS_24XX(isp)) {
- int reg;
-
- cmd &= ~PCIM_CMD_INTX_DISABLE;
-
- /*
- * Is this a PCI-X card? If so, set max read byte count.
- */
- if (pci_find_extcap(dev, PCIY_PCIX, &reg) == 0) {
- uint16_t pxcmd;
- reg += 2;
-
- pxcmd = pci_read_config(dev, reg, 2);
- pxcmd &= ~0xc;
- pxcmd |= 0x8;
- pci_write_config(dev, reg, 2, pxcmd);
- }
-
- /*
- * Is this a PCI Express card? If so, set max read byte count.
- */
- if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
- uint16_t pectl;
-
- reg += 0x8;
- pectl = pci_read_config(dev, reg, 2);
- pectl &= ~0x7000;
- pectl |= 0x4000;
- pci_write_config(dev, reg, 2, pectl);
- }
- }
-#else
if (IS_24XX(isp)) {
cmd &= ~PCIM_CMD_INTX_DISABLE;
}
-#endif
pci_write_config(dev, PCIR_COMMAND, cmd, 2);
@@ -1122,8 +874,7 @@ isp_pci_attach(device_t dev)
*/
data = pci_read_config(dev, PCIR_CACHELNSZ, 1);
if (data == 0 || (linesz != PCI_DFLT_LNSZ && data != linesz)) {
- isp_prt(isp, ISP_LOGCONFIG, "set PCI line size to %d from %d",
- linesz, data);
+ isp_prt(isp, ISP_LOGCONFIG, "set PCI line size to %d from %d", linesz, data);
data = linesz;
pci_write_config(dev, PCIR_CACHELNSZ, data, 1);
}
@@ -1144,7 +895,12 @@ isp_pci_attach(device_t dev)
data = pci_read_config(dev, PCIR_ROMADDR, 4);
data &= ~1;
pci_write_config(dev, PCIR_ROMADDR, data, 4);
-#if __FreeBSD_version > 700025
+
+ /*
+ * Do MSI
+ *
+ * NB: MSI-X needs to be disabled for the 2432 (PCI-Express)
+ */
if (IS_24XX(isp) || IS_2322(isp)) {
pcs->msicount = pci_msi_count(dev);
if (pcs->msicount > 1) {
@@ -1156,24 +912,17 @@ isp_pci_attach(device_t dev)
iqd = 0;
}
}
-#else
- iqd = 0;
-#endif
- irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
- RF_ACTIVE | RF_SHAREABLE);
+ irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, RF_ACTIVE | RF_SHAREABLE);
if (irq == NULL) {
device_printf(dev, "could not allocate interrupt\n");
goto bad;
}
-#if __FreeBSD_version >= 500000
/* Make sure the lock is set up. */
mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
locksetup++;
-#endif
- if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_platform_intr, isp,
- &pcs->ih)) {
+ if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) {
device_printf(dev, "could not setup interrupt\n");
goto bad;
}
@@ -1185,65 +934,52 @@ isp_pci_attach(device_t dev)
isp->isp_port = pci_get_function(dev);
}
- if (IS_23XX(isp)) {
- /*
- * Can't tell if ROM will hang on 'ABOUT FIRMWARE' command.
- */
- isp->isp_touched = 1;
- }
-
/*
* Make sure we're in reset state.
*/
ISP_LOCK(isp);
- isp_reset(isp);
+ isp_reset(isp, 1);
if (isp->isp_state != ISP_RESETSTATE) {
ISP_UNLOCK(isp);
goto bad;
}
isp_init(isp);
- if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) {
- isp_uninit(isp);
- ISP_UNLOCK(isp);
- goto bad;
+ if (isp->isp_state == ISP_INITSTATE) {
+ isp->isp_state = ISP_RUNSTATE;
}
- isp_attach(isp);
- if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) {
+ ISP_UNLOCK(isp);
+ if (isp_attach(isp)) {
+ ISP_LOCK(isp);
isp_uninit(isp);
ISP_UNLOCK(isp);
goto bad;
}
- ISP_UNLOCK(isp);
return (0);
bad:
if (pcs && pcs->ih) {
(void) bus_teardown_intr(dev, irq, pcs->ih);
}
-#if __FreeBSD_version >= 500000
if (locksetup && isp) {
mtx_destroy(&isp->isp_osinfo.lock);
}
-#endif
if (irq) {
(void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq);
}
-#if __FreeBSD_version > 700025
if (pcs && pcs->msicount) {
pci_release_msi(dev);
}
-#endif
if (regs) {
(void) bus_release_resource(dev, rtp, rgd, regs);
}
if (pcs) {
if (pcs->pci_isp.isp_param) {
-#ifdef ISP_FW_CRASH_DUMP
- if (IS_FC(isp) && FCPARAM(isp)->isp_dump_data) {
- free(FCPARAM(isp)->isp_dump_data, M_DEVBUF);
- }
-#endif
free(pcs->pci_isp.isp_param, M_DEVBUF);
+ pcs->pci_isp.isp_param = NULL;
+ }
+ if (pcs->pci_isp.isp_osinfo.pc.ptr) {
+ free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF);
+ pcs->pci_isp.isp_osinfo.pc.ptr = NULL;
}
}
return (ENXIO);
@@ -1261,6 +997,7 @@ isp_pci_detach(device_t dev)
}
isp = (ispsoftc_t *) pcs;
ISP_DISABLE_INTS(isp);
+ mtx_destroy(&isp->isp_osinfo.lock);
return (0);
}
@@ -1278,7 +1015,7 @@ isp_pci_detach(device_t dev)
bus_space_write_4(isp->isp_bus_tag, isp->isp_bus_handle, off, v)
-static __inline int
+static ISP_INLINE int
isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp)
{
uint32_t val0, val1;
@@ -1577,10 +1314,10 @@ isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff)
case BIU2400_REQOUTP:
case BIU2400_RSPINP:
case BIU2400_RSPOUTP:
- case BIU2400_PRI_RQINP:
- case BIU2400_PRI_RSPINP:
+ case BIU2400_PRI_REQINP:
+ case BIU2400_PRI_REQOUTP:
case BIU2400_ATIO_RSPINP:
- case BIU2400_ATIO_REQINP:
+ case BIU2400_ATIO_RSPOUTP:
case BIU2400_HCCR:
case BIU2400_GPIOD:
case BIU2400_GPIOE:
@@ -1639,10 +1376,10 @@ isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val)
case BIU2400_REQOUTP:
case BIU2400_RSPINP:
case BIU2400_RSPOUTP:
- case BIU2400_PRI_RQINP:
- case BIU2400_PRI_RSPINP:
+ case BIU2400_PRI_REQINP:
+ case BIU2400_PRI_REQOUTP:
case BIU2400_ATIO_RSPINP:
- case BIU2400_ATIO_REQINP:
+ case BIU2400_ATIO_RSPOUTP:
case BIU2400_HCCR:
case BIU2400_GPIOD:
case BIU2400_GPIOE:
@@ -1660,29 +1397,58 @@ isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val)
struct imush {
ispsoftc_t *isp;
+ caddr_t vbase;
+ int chan;
int error;
};
static void imc(void *, bus_dma_segment_t *, int, int);
+static void imc1(void *, bus_dma_segment_t *, int, int);
static void
imc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
struct imush *imushp = (struct imush *) arg;
+
if (error) {
imushp->error = error;
- } else {
- ispsoftc_t *isp =imushp->isp;
- bus_addr_t addr = segs->ds_addr;
+ return;
+ }
+ if (nseg != 1) {
+ imushp->error = EINVAL;
+ return;
+ }
+ imushp->isp->isp_rquest = imushp->vbase;
+ imushp->isp->isp_rquest_dma = segs->ds_addr;
+ segs->ds_addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp));
+ imushp->vbase += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp));
+ imushp->isp->isp_result_dma = segs->ds_addr;
+ imushp->isp->isp_result = imushp->vbase;
- isp->isp_rquest_dma = addr;
- addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
- isp->isp_result_dma = addr;
- if (IS_FC(isp)) {
- addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
- FCPARAM(isp)->isp_scdma = addr;
- }
+#ifdef ISP_TARGET_MODE
+ if (IS_24XX(imushp->isp)) {
+ segs->ds_addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
+ imushp->vbase += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
+ imushp->isp->isp_atioq_dma = segs->ds_addr;
+ imushp->isp->isp_atioq = imushp->vbase;
}
+#endif
+}
+
+static void
+imc1(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ struct imush *imushp = (struct imush *) arg;
+ if (error) {
+ imushp->error = error;
+ return;
+ }
+ if (nseg != 1) {
+ imushp->error = EINVAL;
+ return;
+ }
+ FCPARAM(imushp->isp, imushp->chan)->isp_scdma = segs->ds_addr;
+ FCPARAM(imushp->isp, imushp->chan)->isp_scratch = imushp->vbase;
}
static int
@@ -1690,7 +1456,7 @@ isp_pci_mbxdma(ispsoftc_t *isp)
{
caddr_t base;
uint32_t len;
- int i, error, ns;
+ int i, error, ns, cmap = 0;
bus_size_t slim; /* segment size */
bus_addr_t llim; /* low limit of unavailable dma */
bus_addr_t hlim; /* high limit of unavailable dma */
@@ -1724,8 +1490,7 @@ isp_pci_mbxdma(ispsoftc_t *isp)
}
len = isp->isp_maxcmds * sizeof (struct isp_pcmd);
- isp->isp_osinfo.pcmd_pool =
- (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+ isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
if (isp->isp_osinfo.pcmd_pool == NULL) {
isp_prt(isp, ISP_LOGERR, "cannot allocate pcmds");
ISP_LOCK(isp);
@@ -1738,22 +1503,19 @@ isp_pci_mbxdma(ispsoftc_t *isp)
#ifdef ISP_TARGET_MODE
if (IS_SCSI(isp) && sizeof (bus_addr_t) > 4) {
free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
- ISP_LOCK(isp);
isp_prt(isp, ISP_LOGERR, "we cannot do DAC for SPI cards yet");
+ ISP_LOCK(isp);
return (1);
}
#endif
- if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_PCD(isp)), 1,
- slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, ISP_NSEGS,
- slim, 0, &isp->isp_osinfo.dmat)) {
+ if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_PCD(isp)), 1, slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, ISP_NSEGS, slim, 0, &isp->isp_osinfo.dmat)) {
free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
ISP_LOCK(isp);
isp_prt(isp, ISP_LOGERR, "could not create master dma tag");
return (1);
}
-
len = sizeof (XS_T **) * isp->isp_maxcmds;
isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
if (isp->isp_xflist == NULL) {
@@ -1775,23 +1537,25 @@ isp_pci_mbxdma(ispsoftc_t *isp)
#endif
/*
- * Allocate and map the request, result queues, plus FC scratch area.
+ * Allocate and map the request and result queues (and ATIO queue
+ * if we're a 2400 supporting target mode).
*/
len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
- if (IS_FC(isp)) {
- len += ISP2100_SCRLEN;
+#ifdef ISP_TARGET_MODE
+ if (IS_24XX(isp)) {
+ len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
}
+#endif
ns = (len / PAGE_SIZE) + 1;
+
/*
- * Create a tag for the control spaces- force it to within 32 bits.
+ * Create a tag for the control spaces. We don't always need this
+ * to be 32 bits, but we do this for simplicity and speed's sake.
*/
- if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
- NULL, NULL, len, ns, slim, 0, &isp->isp_cdmat)) {
- isp_prt(isp, ISP_LOGERR,
- "cannot create a dma tag for control spaces");
+ if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, ns, slim, 0, &isp->isp_osinfo.cdmat)) {
+ isp_prt(isp, ISP_LOGERR, "cannot create a dma tag for control spaces");
free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
free(isp->isp_xflist, M_DEVBUF);
#ifdef ISP_TARGET_MODE
@@ -1801,11 +1565,9 @@ isp_pci_mbxdma(ispsoftc_t *isp)
return (1);
}
- if (bus_dmamem_alloc(isp->isp_cdmat, (void **)&base, BUS_DMA_NOWAIT,
- &isp->isp_cdmap) != 0) {
- isp_prt(isp, ISP_LOGERR,
- "cannot allocate %d bytes of CCB memory", len);
- bus_dma_tag_destroy(isp->isp_cdmat);
+ if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT, &isp->isp_osinfo.cdmap) != 0) {
+ isp_prt(isp, ISP_LOGERR, "cannot allocate %d bytes of CCB memory", len);
+ bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
free(isp->isp_xflist, M_DEVBUF);
#ifdef ISP_TARGET_MODE
@@ -1815,19 +1577,51 @@ isp_pci_mbxdma(ispsoftc_t *isp)
return (1);
}
+ im.isp = isp;
+ im.chan = 0;
+ im.vbase = base;
+ im.error = 0;
+
+ bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0);
+ if (im.error) {
+ isp_prt(isp, ISP_LOGERR, "error %d loading dma map for control areas", im.error);
+ goto bad;
+ }
+
+ if (IS_FC(isp)) {
+ for (cmap = 0; cmap < isp->isp_nchan; cmap++) {
+ struct isp_fc *fc = ISP_FC_PC(isp, cmap);
+ if (isp_dma_tag_create(isp->isp_osinfo.dmat, 64, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, ISP_FC_SCRLEN, 1, slim, 0, &fc->tdmat)) {
+ goto bad;
+ }
+ if (bus_dmamem_alloc(fc->tdmat, (void **)&base, BUS_DMA_NOWAIT, &fc->tdmap) != 0) {
+ bus_dma_tag_destroy(fc->tdmat);
+ goto bad;
+ }
+ im.isp = isp;
+ im.chan = cmap;
+ im.vbase = base;
+ im.error = 0;
+ bus_dmamap_load(fc->tdmat, fc->tdmap, base, ISP_FC_SCRLEN, imc1, &im, 0);
+ if (im.error) {
+ bus_dmamem_free(fc->tdmat, base, fc->tdmap);
+ bus_dma_tag_destroy(fc->tdmat);
+ goto bad;
+ }
+ }
+ }
+
for (i = 0; i < isp->isp_maxcmds; i++) {
struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i];
error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap);
if (error) {
- isp_prt(isp, ISP_LOGERR,
- "error %d creating per-cmd DMA maps", error);
+ isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error);
while (--i >= 0) {
- bus_dmamap_destroy(isp->isp_osinfo.dmat,
- isp->isp_osinfo.pcmd_pool[i].dmap);
+ bus_dmamap_destroy(isp->isp_osinfo.dmat, isp->isp_osinfo.pcmd_pool[i].dmap);
}
goto bad;
}
- isp_callout_init(&pcmd->wdog);
+ callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0);
if (i == isp->isp_maxcmds-1) {
pcmd->next = NULL;
} else {
@@ -1835,29 +1629,17 @@ isp_pci_mbxdma(ispsoftc_t *isp)
}
}
isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0];
-
- im.isp = isp;
- im.error = 0;
- bus_dmamap_load(isp->isp_cdmat, isp->isp_cdmap, base, len, imc, &im, 0);
- if (im.error) {
- isp_prt(isp, ISP_LOGERR,
- "error %d loading dma map for control areas", im.error);
- goto bad;
- }
-
- isp->isp_rquest = base;
- base += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
- isp->isp_result = base;
- if (IS_FC(isp)) {
- base += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
- FCPARAM(isp)->isp_scratch = base;
- }
ISP_LOCK(isp);
return (0);
bad:
- bus_dmamem_free(isp->isp_cdmat, base, isp->isp_cdmap);
- bus_dma_tag_destroy(isp->isp_cdmat);
+ while (--cmap >= 0) {
+ struct isp_fc *fc = ISP_FC_PC(isp, cmap);
+ bus_dmamem_free(fc->tdmat, base, fc->tdmap);
+ bus_dma_tag_destroy(fc->tdmat);
+ }
+ bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap);
+ bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
free(isp->isp_xflist, M_DEVBUF);
#ifdef ISP_TARGET_MODE
free(isp->isp_tgtlist, M_DEVBUF);
@@ -1871,721 +1653,91 @@ bad:
typedef struct {
ispsoftc_t *isp;
void *cmd_token;
- void *rq;
- uint32_t *nxtip;
- uint32_t optr;
+ void *rq; /* original request */
int error;
+ bus_size_t mapsize;
} mush_t;
#define MUSHERR_NOQENTRIES -2
#ifdef ISP_TARGET_MODE
-/*
- * We need to handle DMA for target mode differently from initiator mode.
- *
- * DMA mapping and construction and submission of CTIO Request Entries
- * and rendevous for completion are very tightly coupled because we start
- * out by knowing (per platform) how much data we have to move, but we
- * don't know, up front, how many DMA mapping segments will have to be used
- * cover that data, so we don't know how many CTIO Request Entries we
- * will end up using. Further, for performance reasons we may want to
- * (on the last CTIO for Fibre Channel), send status too (if all went well).
- *
- * The standard vector still goes through isp_pci_dmasetup, but the callback
- * for the DMA mapping routines comes here instead with the whole transfer
- * mapped and a pointer to a partially filled in already allocated request
- * queue entry. We finish the job.
- */
-static void tdma_mk(void *, bus_dma_segment_t *, int, int);
-static void tdma_mkfc(void *, bus_dma_segment_t *, int, int);
+static void tdma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int);
+static void tdma2(void *, bus_dma_segment_t *, int, int);
-#define STATUS_WITH_DATA 1
+static void
+tdma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error)
+{
+ mush_t *mp;
+ mp = (mush_t *)arg;
+ mp->mapsize = mapsize;
+ tdma2(arg, dm_segs, nseg, error);
+}
static void
-tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
+tdma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
{
mush_t *mp;
- struct ccb_scsiio *csio;
ispsoftc_t *isp;
- ct_entry_t *cto, *qe;
- uint8_t scsi_status;
- uint32_t curi, nxti, handle;
- uint32_t sflags;
- int32_t resid;
- int nth_ctio, nctios, send_status;
+ struct ccb_scsiio *csio;
+ isp_ddir_t ddir;
+ ispreq_t *rq;
mp = (mush_t *) arg;
if (error) {
mp->error = error;
return;
}
-
- isp = mp->isp;
csio = mp->cmd_token;
- cto = mp->rq;
- curi = isp->isp_reqidx;
- qe = (ct_entry_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, curi);
-
- cto->ct_xfrlen = 0;
- cto->ct_seg_count = 0;
- cto->ct_header.rqs_entry_count = 1;
- MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg));
-
- if (nseg == 0) {
- cto->ct_header.rqs_seqno = 1;
- isp_prt(isp, ISP_LOGTDEBUG1,
- "CTIO[%x] lun%d iid%d tag %x flgs %x sts %x ssts %x res %d",
- cto->ct_fwhandle, csio->ccb_h.target_lun, cto->ct_iid,
- cto->ct_tag_val, cto->ct_flags, cto->ct_status,
- cto->ct_scsi_status, cto->ct_resid);
- ISP_TDQE(isp, "tdma_mk[no data]", curi, cto);
- isp_put_ctio(isp, cto, qe);
- return;
- }
-
- nctios = nseg / ISP_RQDSEG;
- if (nseg % ISP_RQDSEG) {
- nctios++;
- }
-
- /*
- * Save syshandle, and potentially any SCSI status, which we'll
- * reinsert on the last CTIO we're going to send.
- */
-
- handle = cto->ct_syshandle;
- cto->ct_syshandle = 0;
- cto->ct_header.rqs_seqno = 0;
- send_status = (cto->ct_flags & CT_SENDSTATUS) != 0;
-
- if (send_status) {
- sflags = cto->ct_flags & (CT_SENDSTATUS | CT_CCINCR);
- cto->ct_flags &= ~(CT_SENDSTATUS | CT_CCINCR);
- /*
- * Preserve residual.
- */
- resid = cto->ct_resid;
-
- /*
- * Save actual SCSI status.
- */
- scsi_status = cto->ct_scsi_status;
-
-#ifndef STATUS_WITH_DATA
- sflags |= CT_NO_DATA;
- /*
- * We can't do a status at the same time as a data CTIO, so
- * we need to synthesize an extra CTIO at this level.
- */
- nctios++;
-#endif
- } else {
- sflags = scsi_status = resid = 0;
- }
-
- cto->ct_resid = 0;
- cto->ct_scsi_status = 0;
-
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
- } else {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
- }
-
- nxti = *mp->nxtip;
-
- for (nth_ctio = 0; nth_ctio < nctios; nth_ctio++) {
- int seglim;
-
- seglim = nseg;
- if (seglim) {
- int seg;
-
- if (seglim > ISP_RQDSEG)
- seglim = ISP_RQDSEG;
-
- for (seg = 0; seg < seglim; seg++, nseg--) {
- /*
- * Unlike normal initiator commands, we don't
- * do any swizzling here.
- */
- cto->ct_dataseg[seg].ds_count = dm_segs->ds_len;
- cto->ct_dataseg[seg].ds_base = dm_segs->ds_addr;
- cto->ct_xfrlen += dm_segs->ds_len;
- dm_segs++;
- }
- cto->ct_seg_count = seg;
- } else {
- /*
- * This case should only happen when we're sending an
- * extra CTIO with final status.
- */
- if (send_status == 0) {
- isp_prt(isp, ISP_LOGWARN,
- "tdma_mk ran out of segments");
- mp->error = EINVAL;
+ isp = mp->isp;
+ rq = mp->rq;
+ if (nseg) {
+ if (sizeof (bus_addr_t) > 4) {
+ if (nseg >= ISP_NSEG64_MAX) {
+ isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX);
+ mp->error = EFAULT;
return;
}
- }
-
- /*
- * At this point, the fields ct_lun, ct_iid, ct_tagval,
- * ct_tagtype, and ct_timeout have been carried over
- * unchanged from what our caller had set.
- *
- * The dataseg fields and the seg_count fields we just got
- * through setting. The data direction we've preserved all
- * along and only clear it if we're now sending status.
- */
-
- if (nth_ctio == nctios - 1) {
- /*
- * We're the last in a sequence of CTIOs, so mark
- * this CTIO and save the handle to the CCB such that
- * when this CTIO completes we can free dma resources
- * and do whatever else we need to do to finish the
- * rest of the command. We *don't* give this to the
- * firmware to work on- the caller will do that.
- */
-
- cto->ct_syshandle = handle;
- cto->ct_header.rqs_seqno = 1;
-
- if (send_status) {
- cto->ct_scsi_status = scsi_status;
- cto->ct_flags |= sflags;
- cto->ct_resid = resid;
- }
- if (send_status) {
- isp_prt(isp, ISP_LOGTDEBUG1,
- "CTIO[%x] lun%d iid %d tag %x ct_flags %x "
- "scsi status %x resid %d",
- cto->ct_fwhandle, csio->ccb_h.target_lun,
- cto->ct_iid, cto->ct_tag_val, cto->ct_flags,
- cto->ct_scsi_status, cto->ct_resid);
- } else {
- isp_prt(isp, ISP_LOGTDEBUG1,
- "CTIO[%x] lun%d iid%d tag %x ct_flags 0x%x",
- cto->ct_fwhandle, csio->ccb_h.target_lun,
- cto->ct_iid, cto->ct_tag_val,
- cto->ct_flags);
- }
- isp_put_ctio(isp, cto, qe);
- ISP_TDQE(isp, "last tdma_mk", curi, cto);
- if (nctios > 1) {
- MEMORYBARRIER(isp, SYNC_REQUEST,
- curi, QENTRY_LEN);
+ if (rq->req_header.rqs_entry_type == RQSTYPE_CTIO2) {
+ rq->req_header.rqs_entry_type = RQSTYPE_CTIO3;
}
} else {
- ct_entry_t *oqe = qe;
-
- /*
- * Make sure syshandle fields are clean
- */
- cto->ct_syshandle = 0;
- cto->ct_header.rqs_seqno = 0;
-
- isp_prt(isp, ISP_LOGTDEBUG1,
- "CTIO[%x] lun%d for ID%d ct_flags 0x%x",
- cto->ct_fwhandle, csio->ccb_h.target_lun,
- cto->ct_iid, cto->ct_flags);
-
- /*
- * Get a new CTIO
- */
- qe = (ct_entry_t *)
- ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
- nxti = ISP_NXT_QENTRY(nxti, RQUEST_QUEUE_LEN(isp));
- if (nxti == mp->optr) {
- isp_prt(isp, ISP_LOGTDEBUG0,
- "Queue Overflow in tdma_mk");
- mp->error = MUSHERR_NOQENTRIES;
+ if (nseg >= ISP_NSEG_MAX) {
+ isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX);
+ mp->error = EFAULT;
return;
}
-
- /*
- * Now that we're done with the old CTIO,
- * flush it out to the request queue.
- */
- ISP_TDQE(isp, "dma_tgt_fc", curi, cto);
- isp_put_ctio(isp, cto, oqe);
- if (nth_ctio != 0) {
- MEMORYBARRIER(isp, SYNC_REQUEST, curi,
- QENTRY_LEN);
- }
- curi = ISP_NXT_QENTRY(curi, RQUEST_QUEUE_LEN(isp));
-
- /*
- * Reset some fields in the CTIO so we can reuse
- * for the next one we'll flush to the request
- * queue.
- */
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
- cto->ct_header.rqs_entry_count = 1;
- cto->ct_header.rqs_flags = 0;
- cto->ct_status = 0;
- cto->ct_scsi_status = 0;
- cto->ct_xfrlen = 0;
- cto->ct_resid = 0;
- cto->ct_seg_count = 0;
- MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg));
- }
- }
- *mp->nxtip = nxti;
-}
-
-/*
- * We don't have to do multiple CTIOs here. Instead, we can just do
- * continuation segments as needed. This greatly simplifies the code
- * improves performance.
- */
-
-static void
-tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
-{
- mush_t *mp;
- struct ccb_scsiio *csio;
- ispsoftc_t *isp;
- ct2_entry_t *cto, *qe;
- uint32_t curi, nxti;
- ispds_t *ds;
- ispds64_t *ds64;
- int segcnt, seglim;
-
- mp = (mush_t *) arg;
- if (error) {
- mp->error = error;
- return;
- }
-
- isp = mp->isp;
- csio = mp->cmd_token;
- cto = mp->rq;
-
- curi = isp->isp_reqidx;
- qe = (ct2_entry_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, curi);
-
- if (nseg == 0) {
- if ((cto->ct_flags & CT2_FLAG_MMASK) != CT2_FLAG_MODE1) {
- isp_prt(isp, ISP_LOGWARN,
- "dma2_tgt_fc, a status CTIO2 without MODE1 "
- "set (0x%x)", cto->ct_flags);
- mp->error = EINVAL;
- return;
}
- /*
- * We preserve ct_lun, ct_iid, ct_rxid. We set the data
- * flags to NO DATA and clear relative offset flags.
- * We preserve the ct_resid and the response area.
- */
- cto->ct_header.rqs_seqno = 1;
- cto->ct_seg_count = 0;
- cto->ct_reloff = 0;
- isp_prt(isp, ISP_LOGTDEBUG1,
- "CTIO2[%x] lun %d->iid%d flgs 0x%x sts 0x%x ssts "
- "0x%x res %d", cto->ct_rxid, csio->ccb_h.target_lun,
- cto->ct_iid, cto->ct_flags, cto->ct_status,
- cto->rsp.m1.ct_scsi_status, cto->ct_resid);
- if (FCPARAM(isp)->isp_2klogin) {
- isp_put_ctio2e(isp,
- (ct2e_entry_t *)cto, (ct2e_entry_t *)qe);
+ if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
+ ddir = ISP_TO_DEVICE;
+ } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
+ bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
+ ddir = ISP_FROM_DEVICE;
} else {
- isp_put_ctio2(isp, cto, qe);
+ ddir = ISP_NOXFR;
}
- ISP_TDQE(isp, "dma2_tgt_fc[no data]", curi, qe);
- return;
- }
-
- if ((cto->ct_flags & CT2_FLAG_MMASK) != CT2_FLAG_MODE0) {
- isp_prt(isp, ISP_LOGERR,
- "dma2_tgt_fc, a data CTIO2 without MODE0 set "
- "(0x%x)", cto->ct_flags);
- mp->error = EINVAL;
- return;
- }
-
-
- nxti = *mp->nxtip;
-
- /*
- * Check to see if we need to DAC addressing or not.
- *
- * Any address that's over the 4GB boundary causes this
- * to happen.
- */
- segcnt = nseg;
- if (sizeof (bus_addr_t) > 4) {
- for (segcnt = 0; segcnt < nseg; segcnt++) {
- uint64_t addr = dm_segs[segcnt].ds_addr;
- if (addr >= 0x100000000LL) {
- break;
- }
- }
- }
- if (segcnt != nseg) {
- cto->ct_header.rqs_entry_type = RQSTYPE_CTIO3;
- seglim = ISP_RQDSEG_T3;
- ds64 = &cto->rsp.m0.u.ct_dataseg64[0];
- ds = NULL;
} else {
- seglim = ISP_RQDSEG_T2;
- ds64 = NULL;
- ds = &cto->rsp.m0.u.ct_dataseg[0];
+ dm_segs = NULL;
+ nseg = 0;
+ ddir = ISP_NOXFR;
}
- cto->ct_seg_count = 0;
- /*
- * Set up the CTIO2 data segments.
- */
- for (segcnt = 0; cto->ct_seg_count < seglim && segcnt < nseg;
- cto->ct_seg_count++, segcnt++) {
- if (ds64) {
- ds64->ds_basehi =
- ((uint64_t) (dm_segs[segcnt].ds_addr) >> 32);
- ds64->ds_base = dm_segs[segcnt].ds_addr;
- ds64->ds_count = dm_segs[segcnt].ds_len;
- ds64++;
- } else {
- ds->ds_base = dm_segs[segcnt].ds_addr;
- ds->ds_count = dm_segs[segcnt].ds_len;
- ds++;
- }
- cto->rsp.m0.ct_xfrlen += dm_segs[segcnt].ds_len;
-#if __FreeBSD_version < 500000
- isp_prt(isp, ISP_LOGTDEBUG1,
- "isp_send_ctio2: ent0[%d]0x%llx:%llu",
- cto->ct_seg_count, (uint64_t)dm_segs[segcnt].ds_addr,
- (uint64_t)dm_segs[segcnt].ds_len);
-#else
- isp_prt(isp, ISP_LOGTDEBUG1,
- "isp_send_ctio2: ent0[%d]0x%jx:%ju",
- cto->ct_seg_count, (uintmax_t)dm_segs[segcnt].ds_addr,
- (uintmax_t)dm_segs[segcnt].ds_len);
-#endif
+ if (isp_send_tgt_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, &csio->sense_data, csio->sense_len) != CMD_QUEUED) {
+ mp->error = MUSHERR_NOQENTRIES;
}
-
- while (segcnt < nseg) {
- uint32_t curip;
- int seg;
- ispcontreq_t local, *crq = &local, *qep;
-
- qep = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
- curip = nxti;
- nxti = ISP_NXT_QENTRY(curip, RQUEST_QUEUE_LEN(isp));
- if (nxti == mp->optr) {
- isp_prt(isp, ISP_LOGTDEBUG0,
- "tdma_mkfc: request queue overflow");
- mp->error = MUSHERR_NOQENTRIES;
- return;
- }
- cto->ct_header.rqs_entry_count++;
- MEMZERO((void *)crq, sizeof (*crq));
- crq->req_header.rqs_entry_count = 1;
- if (cto->ct_header.rqs_entry_type == RQSTYPE_CTIO3) {
- seglim = ISP_CDSEG64;
- ds = NULL;
- ds64 = &((ispcontreq64_t *)crq)->req_dataseg[0];
- crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT;
- } else {
- seglim = ISP_CDSEG;
- ds = &crq->req_dataseg[0];
- ds64 = NULL;
- crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
- }
- for (seg = 0; segcnt < nseg && seg < seglim;
- segcnt++, seg++) {
- if (ds64) {
- ds64->ds_basehi =
- ((uint64_t) (dm_segs[segcnt].ds_addr) >> 32);
- ds64->ds_base = dm_segs[segcnt].ds_addr;
- ds64->ds_count = dm_segs[segcnt].ds_len;
- ds64++;
- } else {
- ds->ds_base = dm_segs[segcnt].ds_addr;
- ds->ds_count = dm_segs[segcnt].ds_len;
- ds++;
- }
-#if __FreeBSD_version < 500000
- isp_prt(isp, ISP_LOGTDEBUG1,
- "isp_send_ctio2: ent%d[%d]%llx:%llu",
- cto->ct_header.rqs_entry_count-1, seg,
- (uint64_t)dm_segs[segcnt].ds_addr,
- (uint64_t)dm_segs[segcnt].ds_len);
-#else
- isp_prt(isp, ISP_LOGTDEBUG1,
- "isp_send_ctio2: ent%d[%d]%jx:%ju",
- cto->ct_header.rqs_entry_count-1, seg,
- (uintmax_t)dm_segs[segcnt].ds_addr,
- (uintmax_t)dm_segs[segcnt].ds_len);
-#endif
- cto->rsp.m0.ct_xfrlen += dm_segs[segcnt].ds_len;
- cto->ct_seg_count++;
- }
- MEMORYBARRIER(isp, SYNC_REQUEST, curip, QENTRY_LEN);
- isp_put_cont_req(isp, crq, qep);
- ISP_TDQE(isp, "cont entry", curi, qep);
- }
-
- /*
- * No do final twiddling for the CTIO itself.
- */
- cto->ct_header.rqs_seqno = 1;
- isp_prt(isp, ISP_LOGTDEBUG1,
- "CTIO2[%x] lun %d->iid%d flgs 0x%x sts 0x%x ssts 0x%x resid %d",
- cto->ct_rxid, csio->ccb_h.target_lun, (int) cto->ct_iid,
- cto->ct_flags, cto->ct_status, cto->rsp.m1.ct_scsi_status,
- cto->ct_resid);
- if (FCPARAM(isp)->isp_2klogin) {
- isp_put_ctio2e(isp, (ct2e_entry_t *)cto, (ct2e_entry_t *)qe);
- } else {
- isp_put_ctio2(isp, cto, qe);
- }
- ISP_TDQE(isp, "last dma2_tgt_fc", curi, qe);
- *mp->nxtip = nxti;
}
#endif
-static void dma_2400(void *, bus_dma_segment_t *, int, int);
-static void dma2_a64(void *, bus_dma_segment_t *, int, int);
+static void dma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int);
static void dma2(void *, bus_dma_segment_t *, int, int);
static void
-dma_2400(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
-{
- mush_t *mp;
- ispsoftc_t *isp;
- struct ccb_scsiio *csio;
- bus_dma_segment_t *eseg;
- ispreqt7_t *rq;
- int seglim, datalen;
- uint32_t nxti;
-
- mp = (mush_t *) arg;
- if (error) {
- mp->error = error;
- return;
- }
-
- if (nseg < 1) {
- isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg);
- mp->error = EFAULT;
- return;
- }
-
- csio = mp->cmd_token;
- isp = mp->isp;
- rq = mp->rq;
- nxti = *mp->nxtip;
-
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
- } else {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
- }
- datalen = XS_XFRLEN(csio);
-
- /*
- * We're passed an initial partially filled in entry that
- * has most fields filled in except for data transfer
- * related values.
- *
- * Our job is to fill in the initial request queue entry and
- * then to start allocating and filling in continuation entries
- * until we've covered the entire transfer.
- */
-
- rq->req_header.rqs_entry_type = RQSTYPE_T7RQS;
- rq->req_dl = datalen;
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- rq->req_alen_datadir = 0x2;
- } else {
- rq->req_alen_datadir = 0x1;
- }
-
- eseg = dm_segs + nseg;
-
- rq->req_dataseg.ds_base = DMA_LO32(dm_segs->ds_addr);
- rq->req_dataseg.ds_basehi = DMA_HI32(dm_segs->ds_addr);
- rq->req_dataseg.ds_count = dm_segs->ds_len;
-
- datalen -= dm_segs->ds_len;
-
- dm_segs++;
- rq->req_seg_count++;
-
- while (datalen > 0 && dm_segs != eseg) {
- uint32_t onxti;
- ispcontreq64_t local, *crq = &local, *cqe;
-
- cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
- onxti = nxti;
- nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
- if (nxti == mp->optr) {
- isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
- mp->error = MUSHERR_NOQENTRIES;
- return;
- }
- rq->req_header.rqs_entry_count++;
- MEMZERO((void *)crq, sizeof (*crq));
- crq->req_header.rqs_entry_count = 1;
- crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT;
-
- seglim = 0;
- while (datalen > 0 && seglim < ISP_CDSEG64 && dm_segs != eseg) {
- crq->req_dataseg[seglim].ds_base =
- DMA_LO32(dm_segs->ds_addr);
- crq->req_dataseg[seglim].ds_basehi =
- DMA_HI32(dm_segs->ds_addr);
- crq->req_dataseg[seglim].ds_count =
- dm_segs->ds_len;
- rq->req_seg_count++;
- dm_segs++;
- seglim++;
- datalen -= dm_segs->ds_len;
- }
- if (isp->isp_dblev & ISP_LOGDEBUG1) {
- isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq);
- }
- isp_put_cont64_req(isp, crq, cqe);
- MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
- }
- *mp->nxtip = nxti;
-}
-
-static void
-dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
+dma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error)
{
mush_t *mp;
- ispsoftc_t *isp;
- struct ccb_scsiio *csio;
- bus_dma_segment_t *eseg;
- ispreq64_t *rq;
- int seglim, datalen;
- uint32_t nxti;
-
- mp = (mush_t *) arg;
- if (error) {
- mp->error = error;
- return;
- }
-
- if (nseg < 1) {
- isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg);
- mp->error = EFAULT;
- return;
- }
- csio = mp->cmd_token;
- isp = mp->isp;
- rq = mp->rq;
- nxti = *mp->nxtip;
-
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
- } else {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
- }
- datalen = XS_XFRLEN(csio);
-
- /*
- * We're passed an initial partially filled in entry that
- * has most fields filled in except for data transfer
- * related values.
- *
- * Our job is to fill in the initial request queue entry and
- * then to start allocating and filling in continuation entries
- * until we've covered the entire transfer.
- */
-
- if (IS_FC(isp)) {
- rq->req_header.rqs_entry_type = RQSTYPE_T3RQS;
- seglim = ISP_RQDSEG_T3;
- ((ispreqt3_t *)rq)->req_totalcnt = datalen;
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- ((ispreqt3_t *)rq)->req_flags |= REQFLAG_DATA_IN;
- } else {
- ((ispreqt3_t *)rq)->req_flags |= REQFLAG_DATA_OUT;
- }
- } else {
- rq->req_header.rqs_entry_type = RQSTYPE_A64;
- if (csio->cdb_len > 12) {
- seglim = 0;
- } else {
- seglim = ISP_RQDSEG_A64;
- }
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- rq->req_flags |= REQFLAG_DATA_IN;
- } else {
- rq->req_flags |= REQFLAG_DATA_OUT;
- }
- }
-
- eseg = dm_segs + nseg;
-
- while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) {
- if (IS_FC(isp)) {
- ispreqt3_t *rq3 = (ispreqt3_t *)rq;
- rq3->req_dataseg[rq3->req_seg_count].ds_base =
- DMA_LO32(dm_segs->ds_addr);
- rq3->req_dataseg[rq3->req_seg_count].ds_basehi =
- DMA_HI32(dm_segs->ds_addr);
- rq3->req_dataseg[rq3->req_seg_count].ds_count =
- dm_segs->ds_len;
- } else {
- rq->req_dataseg[rq->req_seg_count].ds_base =
- DMA_LO32(dm_segs->ds_addr);
- rq->req_dataseg[rq->req_seg_count].ds_basehi =
- DMA_HI32(dm_segs->ds_addr);
- rq->req_dataseg[rq->req_seg_count].ds_count =
- dm_segs->ds_len;
- }
- datalen -= dm_segs->ds_len;
- rq->req_seg_count++;
- dm_segs++;
- }
-
- while (datalen > 0 && dm_segs != eseg) {
- uint32_t onxti;
- ispcontreq64_t local, *crq = &local, *cqe;
-
- cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
- onxti = nxti;
- nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
- if (nxti == mp->optr) {
- isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
- mp->error = MUSHERR_NOQENTRIES;
- return;
- }
- rq->req_header.rqs_entry_count++;
- MEMZERO((void *)crq, sizeof (*crq));
- crq->req_header.rqs_entry_count = 1;
- crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT;
-
- seglim = 0;
- while (datalen > 0 && seglim < ISP_CDSEG64 && dm_segs != eseg) {
- crq->req_dataseg[seglim].ds_base =
- DMA_LO32(dm_segs->ds_addr);
- crq->req_dataseg[seglim].ds_basehi =
- DMA_HI32(dm_segs->ds_addr);
- crq->req_dataseg[seglim].ds_count =
- dm_segs->ds_len;
- rq->req_seg_count++;
- dm_segs++;
- seglim++;
- datalen -= dm_segs->ds_len;
- }
- if (isp->isp_dblev & ISP_LOGDEBUG1) {
- isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq);
- }
- isp_put_cont64_req(isp, crq, cqe);
- MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
- }
- *mp->nxtip = nxti;
+ mp = (mush_t *)arg;
+ mp->mapsize = mapsize;
+ dma2(arg, dm_segs, nseg, error);
}
static void
@@ -2594,206 +1746,99 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
mush_t *mp;
ispsoftc_t *isp;
struct ccb_scsiio *csio;
- bus_dma_segment_t *eseg;
+ isp_ddir_t ddir;
ispreq_t *rq;
- int seglim, datalen;
- uint32_t nxti;
mp = (mush_t *) arg;
if (error) {
mp->error = error;
return;
}
-
- if (nseg < 1) {
- isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg);
- mp->error = EFAULT;
- return;
- }
csio = mp->cmd_token;
isp = mp->isp;
rq = mp->rq;
- nxti = *mp->nxtip;
-
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
- } else {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
- }
-
- datalen = XS_XFRLEN(csio);
-
- /*
- * We're passed an initial partially filled in entry that
- * has most fields filled in except for data transfer
- * related values.
- *
- * Our job is to fill in the initial request queue entry and
- * then to start allocating and filling in continuation entries
- * until we've covered the entire transfer.
- */
-
- if (IS_FC(isp)) {
- seglim = ISP_RQDSEG_T2;
- ((ispreqt2_t *)rq)->req_totalcnt = datalen;
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- ((ispreqt2_t *)rq)->req_flags |= REQFLAG_DATA_IN;
- } else {
- ((ispreqt2_t *)rq)->req_flags |= REQFLAG_DATA_OUT;
- }
- } else {
- if (csio->cdb_len > 12) {
- seglim = 0;
+ if (nseg) {
+ if (sizeof (bus_addr_t) > 4) {
+ if (nseg >= ISP_NSEG64_MAX) {
+ isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX);
+ mp->error = EFAULT;
+ return;
+ }
+ if (rq->req_header.rqs_entry_type == RQSTYPE_T2RQS) {
+ rq->req_header.rqs_entry_type = RQSTYPE_T3RQS;
+ } else if (rq->req_header.rqs_entry_type == RQSTYPE_REQUEST) {
+ rq->req_header.rqs_entry_type = RQSTYPE_A64;
+ }
} else {
- seglim = ISP_RQDSEG;
+ if (nseg >= ISP_NSEG_MAX) {
+ isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX);
+ mp->error = EFAULT;
+ return;
+ }
}
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- rq->req_flags |= REQFLAG_DATA_IN;
+ bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
+ ddir = ISP_FROM_DEVICE;
+ } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
+ bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
+ ddir = ISP_TO_DEVICE;
} else {
- rq->req_flags |= REQFLAG_DATA_OUT;
+ ddir = ISP_NOXFR;
}
+ } else {
+ dm_segs = NULL;
+ nseg = 0;
+ ddir = ISP_NOXFR;
}
- eseg = dm_segs + nseg;
-
- while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) {
- if (IS_FC(isp)) {
- ispreqt2_t *rq2 = (ispreqt2_t *)rq;
- rq2->req_dataseg[rq2->req_seg_count].ds_base =
- DMA_LO32(dm_segs->ds_addr);
- rq2->req_dataseg[rq2->req_seg_count].ds_count =
- dm_segs->ds_len;
- } else {
- rq->req_dataseg[rq->req_seg_count].ds_base =
- DMA_LO32(dm_segs->ds_addr);
- rq->req_dataseg[rq->req_seg_count].ds_count =
- dm_segs->ds_len;
- }
- datalen -= dm_segs->ds_len;
- rq->req_seg_count++;
- dm_segs++;
- }
-
- while (datalen > 0 && dm_segs != eseg) {
- uint32_t onxti;
- ispcontreq_t local, *crq = &local, *cqe;
-
- cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
- onxti = nxti;
- nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
- if (nxti == mp->optr) {
- isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
- mp->error = MUSHERR_NOQENTRIES;
- return;
- }
- rq->req_header.rqs_entry_count++;
- MEMZERO((void *)crq, sizeof (*crq));
- crq->req_header.rqs_entry_count = 1;
- crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
-
- seglim = 0;
- while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) {
- crq->req_dataseg[seglim].ds_base =
- DMA_LO32(dm_segs->ds_addr);
- crq->req_dataseg[seglim].ds_count =
- dm_segs->ds_len;
- rq->req_seg_count++;
- dm_segs++;
- seglim++;
- datalen -= dm_segs->ds_len;
- }
- if (isp->isp_dblev & ISP_LOGDEBUG1) {
- isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq);
- }
- isp_put_cont_req(isp, crq, cqe);
- MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
+ if (isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir) != CMD_QUEUED) {
+ mp->error = MUSHERR_NOQENTRIES;
}
- *mp->nxtip = nxti;
}
-/*
- */
static int
-isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
- uint32_t *nxtip, uint32_t optr)
+isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff)
{
- ispreq_t *qep;
mush_t mush, *mp;
void (*eptr)(void *, bus_dma_segment_t *, int, int);
+ void (*eptr2)(void *, bus_dma_segment_t *, int, bus_size_t, int);
+
+ mp = &mush;
+ mp->isp = isp;
+ mp->cmd_token = csio;
+ mp->rq = ff;
+ mp->error = 0;
+ mp->mapsize = 0;
- qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx);
#ifdef ISP_TARGET_MODE
if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) {
- if (IS_FC(isp)) {
- eptr = tdma_mkfc;
- } else {
- eptr = tdma_mk;
- }
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
- (csio->dxfer_len == 0)) {
- mp = &mush;
- mp->isp = isp;
- mp->cmd_token = csio;
- mp->rq = rq; /* really a ct_entry_t or ct2_entry_t */
- mp->nxtip = nxtip;
- mp->optr = optr;
- mp->error = 0;
- (*eptr)(mp, NULL, 0, 0);
- goto mbxsync;
- }
+ eptr = tdma2;
+ eptr2 = tdma2_2;
} else
#endif
- if (IS_24XX(isp)) {
- eptr = dma_2400;
- } else if (sizeof (bus_addr_t) > 4) {
- eptr = dma2_a64;
- } else {
+ {
eptr = dma2;
+ eptr2 = dma2_2;
}
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
- (csio->dxfer_len == 0)) {
- rq->req_seg_count = 1;
- goto mbxsync;
- }
-
- /*
- * Do a virtual grapevine step to collect info for
- * the callback dma allocation that we have to use...
- */
- mp = &mush;
- mp->isp = isp;
- mp->cmd_token = csio;
- mp->rq = rq;
- mp->nxtip = nxtip;
- mp->optr = optr;
- mp->error = 0;
-
- if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
+ if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || (csio->dxfer_len == 0)) {
+ (*eptr)(mp, NULL, 0, 0);
+ } else if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) {
int error;
-#if __FreeBSD_version < 500000
- int s = splsoftvm();
-#endif
- error = bus_dmamap_load(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, csio->data_ptr,
- csio->dxfer_len, eptr, mp, 0);
-#if __FreeBSD_version < 500000
- splx(s);
+ error = bus_dmamap_load(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, csio->data_ptr, csio->dxfer_len, eptr, mp, 0);
+#if 0
+ xpt_print(csio->ccb_h.path, "%s: bus_dmamap_load " "ptr %p len %d returned %d\n", __func__, csio->data_ptr, csio->dxfer_len, error);
#endif
+
if (error == EINPROGRESS) {
- bus_dmamap_unload(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap);
+ bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap);
mp->error = EINVAL;
- isp_prt(isp, ISP_LOGERR,
- "deferred dma allocation not supported");
+ isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported");
} else if (error && mp->error == 0) {
#ifdef DIAGNOSTIC
- isp_prt(isp, ISP_LOGERR,
- "error %d in dma mapping code", error);
+ isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error);
#endif
mp->error = error;
}
@@ -2808,13 +1853,34 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
struct bus_dma_segment *segs;
if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) {
- isp_prt(isp, ISP_LOGERR,
- "Physical segment pointers unsupported");
+ isp_prt(isp, ISP_LOGERR, "Physical segment pointers unsupported");
mp->error = EINVAL;
} else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) {
- isp_prt(isp, ISP_LOGERR,
- "Virtual segment addresses unsupported");
- mp->error = EINVAL;
+ struct uio sguio;
+ int error;
+
+ /*
+ * We're taking advantage of the fact that
+ * the pointer/length sizes and layout of the iovec
+ * structure are the same as the bus_dma_segment
+ * structure. This might be a little dangerous,
+ * but only if they change the structures, which
+ * seems unlikely.
+ */
+ KASSERT((sizeof (sguio.uio_iov) == sizeof (csio->data_ptr) &&
+ sizeof (sguio.uio_iovcnt) >= sizeof (csio->sglist_cnt) &&
+ sizeof (sguio.uio_resid) >= sizeof (csio->dxfer_len)), ("Ken's assumption failed"));
+ sguio.uio_iov = (struct iovec *)csio->data_ptr;
+ sguio.uio_iovcnt = csio->sglist_cnt;
+ sguio.uio_resid = csio->dxfer_len;
+ sguio.uio_segflg = UIO_SYSSPACE;
+
+ error = bus_dmamap_load_uio(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, &sguio, eptr2, mp, 0);
+
+ if (error != 0 && mp->error == 0) {
+ isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error);
+ mp->error = error;
+ }
} else {
/* Just use the segments provided */
segs = (struct bus_dma_segment *) csio->data_ptr;
@@ -2834,41 +1900,6 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
}
return (retval);
}
-mbxsync:
- if (isp->isp_dblev & ISP_LOGDEBUG1) {
- isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq);
- }
- switch (rq->req_header.rqs_entry_type) {
- case RQSTYPE_REQUEST:
- isp_put_request(isp, rq, qep);
- break;
- case RQSTYPE_CMDONLY:
- isp_put_extended_request(isp, (ispextreq_t *)rq,
- (ispextreq_t *)qep);
- break;
- case RQSTYPE_T2RQS:
- if (FCPARAM(isp)->isp_2klogin) {
- isp_put_request_t2e(isp,
- (ispreqt2e_t *) rq, (ispreqt2e_t *) qep);
- } else {
- isp_put_request_t2(isp,
- (ispreqt2_t *) rq, (ispreqt2_t *) qep);
- }
- break;
- case RQSTYPE_T3RQS:
- if (FCPARAM(isp)->isp_2klogin) {
- isp_put_request_t3e(isp,
- (ispreqt3e_t *) rq, (ispreqt3e_t *) qep);
- break;
- }
- /* FALLTHROUGH */
- case RQSTYPE_A64:
- isp_put_request_t3(isp, (ispreqt3_t *) rq, (ispreqt3_t *) qep);
- break;
- case RQSTYPE_T7RQS:
- isp_put_request_t7(isp, (ispreqt7_t *) rq, (ispreqt7_t *) qep);
- break;
- }
return (CMD_QUEUED);
}
diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c
index 839d7eb..af7cb88 100644
--- a/sys/dev/isp/isp_sbus.c
+++ b/sys/dev/isp/isp_sbus.c
@@ -33,10 +33,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#if __FreeBSD_version >= 700000
#include <sys/linker.h>
#include <sys/firmware.h>
-#endif
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
@@ -51,15 +49,12 @@ __FBSDID("$FreeBSD$");
#include <dev/isp/isp_freebsd.h>
-static uint32_t
-isp_sbus_rd_reg(ispsoftc_t *, int);
-static void
-isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t);
-static int
-isp_sbus_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
+static uint32_t isp_sbus_rd_reg(ispsoftc_t *, int);
+static void isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t);
+static int isp_sbus_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
static int isp_sbus_mbxdma(ispsoftc_t *);
-static int
-isp_sbus_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
+static int isp_sbus_dmasetup(ispsoftc_t *, XS_T *, void *);
+
static void isp_sbus_reset0(ispsoftc_t *);
static void isp_sbus_reset1(ispsoftc_t *);
@@ -91,6 +86,7 @@ struct isp_sbussoftc {
void * ih;
int16_t sbus_poff[_NREG_BLKS];
sdparam sbus_param;
+ struct isp_spi sbus_spi;
struct ispmdvec sbus_mdvec;
struct resource * sbus_ires;
};
@@ -108,9 +104,6 @@ static driver_t isp_sbus_driver = {
};
static devclass_t isp_devclass;
DRIVER_MODULE(isp, sbus, isp_sbus_driver, isp_devclass, 0, 0);
-#if __FreeBSD_version < 700000
-extern ispfwfunc *isp_get_firmware_p;
-#endif
static int
isp_sbus_probe(device_t dev)
@@ -140,7 +133,7 @@ static int
isp_sbus_attach(device_t dev)
{
struct resource *regs;
- int tval, iqd, isp_debug, role, rid, ispburst;
+ int tval, iqd, isp_debug, role, rid, ispburst, default_id;
struct isp_sbussoftc *sbs;
ispsoftc_t *isp = NULL;
int locksetup = 0;
@@ -165,11 +158,7 @@ isp_sbus_attach(device_t dev)
((role & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) == 0)) {
device_printf(dev, "setting role to 0x%x\n", role);
} else {
-#ifdef ISP_TARGET_MODE
- role = ISP_ROLE_INITIATOR|ISP_ROLE_TARGET;
-#else
role = ISP_DEFAULT_ROLES;
-#endif
}
sbs = malloc(sizeof (*sbs), M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -202,9 +191,9 @@ isp_sbus_attach(device_t dev)
isp->isp_bustype = ISP_BT_SBUS;
isp->isp_type = ISP_HA_SCSI_UNKNOWN;
isp->isp_param = &sbs->sbus_param;
+ isp->isp_osinfo.pc.ptr = &sbs->sbus_spi;
isp->isp_revision = 0; /* XXX */
- isp->isp_role = role;
- isp->isp_dev = dev;
+ ISP_SET_PC(isp, 0, role, role);
/*
* Get the clock frequency and convert it from HZ to MHz,
@@ -246,11 +235,10 @@ isp_sbus_attach(device_t dev)
*/
if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 ||
strcmp("ptisp", ofw_bus_get_name(dev)) == 0) {
- SDPARAM(isp)->isp_ptisp = 1;
+ SDPARAM(isp, 0)->isp_ptisp = 1;
}
-#if __FreeBSD_version >= 700000
isp->isp_osinfo.fw = firmware_get("isp_1000");
if (isp->isp_osinfo.fw) {
union {
@@ -260,14 +248,6 @@ isp_sbus_attach(device_t dev)
stupid.cp = isp->isp_osinfo.fw->data;
isp->isp_mdvec->dv_ispfw = stupid.sp;
}
-#else
- /*
- * Try and find firmware for this device.
- */
- if (isp_get_firmware_p) {
- (*isp_get_firmware_p)(0, 0, 0x1000, &sbs->sbus_mdvec.dv_ispfw);
- }
-#endif
tval = 0;
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
@@ -275,19 +255,20 @@ isp_sbus_attach(device_t dev)
isp->isp_confopts |= ISP_CFG_NORELOAD;
}
- isp->isp_osinfo.default_id = -1;
+ default_id = -1;
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"iid", &tval) == 0) {
- isp->isp_osinfo.default_id = tval;
+ default_id = tval;
isp->isp_confopts |= ISP_CFG_OWNLOOPID;
}
- if (isp->isp_osinfo.default_id == -1) {
+ if (default_id == -1) {
/*
* XXX: should be a way to get properties w/o having
* XXX: to call OF_xxx functions
*/
- isp->isp_osinfo.default_id = 7;
+ default_id = 7;
}
+ ISP_SPI_PC(isp, 0)->iid = default_id;
isp_debug = 0;
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
@@ -328,20 +309,20 @@ isp_sbus_attach(device_t dev)
* Make sure we're in reset state.
*/
ISP_LOCK(isp);
- isp_reset(isp);
+ isp_reset(isp, 1);
if (isp->isp_state != ISP_RESETSTATE) {
isp_uninit(isp);
ISP_UNLOCK(isp);
goto bad;
}
isp_init(isp);
- if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) {
+ if (role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) {
isp_uninit(isp);
ISP_UNLOCK(isp);
goto bad;
}
isp_attach(isp);
- if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) {
+ if (role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) {
isp_uninit(isp);
ISP_UNLOCK(isp);
goto bad;
@@ -507,7 +488,7 @@ isp_sbus_mbxdma(ispsoftc_t *isp)
if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN,
BUS_SPACE_MAXADDR_24BIT+1, BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR_32BIT, NULL, NULL, len, ns,
- BUS_SPACE_MAXADDR_24BIT, 0, &isp->isp_cdmat)) {
+ BUS_SPACE_MAXADDR_24BIT, 0, &isp->isp_osinfo.cdmat)) {
isp_prt(isp, ISP_LOGERR,
"cannot create a dma tag for control spaces");
free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
@@ -516,11 +497,11 @@ isp_sbus_mbxdma(ispsoftc_t *isp)
return (1);
}
- if (bus_dmamem_alloc(isp->isp_cdmat, (void **)&base, BUS_DMA_NOWAIT,
- &isp->isp_cdmap) != 0) {
+ if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT,
+ &isp->isp_osinfo.cdmap) != 0) {
isp_prt(isp, ISP_LOGERR,
"cannot allocate %d bytes of CCB memory", len);
- bus_dma_tag_destroy(isp->isp_cdmat);
+ bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
free(isp->isp_xflist, M_DEVBUF);
ISP_LOCK(isp);
@@ -539,7 +520,7 @@ isp_sbus_mbxdma(ispsoftc_t *isp)
}
goto bad;
}
- isp_callout_init(&pcmd->wdog);
+ callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0);
if (i == isp->isp_maxcmds-1) {
pcmd->next = NULL;
} else {
@@ -550,7 +531,7 @@ isp_sbus_mbxdma(ispsoftc_t *isp)
im.isp = isp;
im.error = 0;
- bus_dmamap_load(isp->isp_cdmat, isp->isp_cdmap, base, len, imc, &im, 0);
+ bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0);
if (im.error) {
isp_prt(isp, ISP_LOGERR,
"error %d loading dma map for control areas", im.error);
@@ -564,8 +545,8 @@ isp_sbus_mbxdma(ispsoftc_t *isp)
return (0);
bad:
- bus_dmamem_free(isp->isp_cdmat, base, isp->isp_cdmap);
- bus_dma_tag_destroy(isp->isp_cdmat);
+ bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap);
+ bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
free(isp->isp_xflist, M_DEVBUF);
free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
isp->isp_rquest = NULL;
@@ -576,15 +557,13 @@ bad:
typedef struct {
ispsoftc_t *isp;
void *cmd_token;
- void *rq;
- uint32_t *nxtip;
- uint32_t optr;
+ void *rq; /* original request */
int error;
+ bus_size_t mapsize;
} mush_t;
#define MUSHERR_NOQENTRIES -2
-
static void dma2(void *, bus_dma_segment_t *, int, int);
static void
@@ -593,154 +572,84 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
mush_t *mp;
ispsoftc_t *isp;
struct ccb_scsiio *csio;
- bus_dma_segment_t *eseg;
+ isp_ddir_t ddir;
ispreq_t *rq;
- int seglim, datalen;
- uint16_t nxti;
mp = (mush_t *) arg;
if (error) {
mp->error = error;
return;
}
-
- if (nseg < 1) {
- isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg);
- mp->error = EFAULT;
- return;
- }
csio = mp->cmd_token;
isp = mp->isp;
rq = mp->rq;
- nxti = *mp->nxtip;
-
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
- } else {
- bus_dmamap_sync(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
- }
-
- datalen = XS_XFRLEN(csio);
-
- /*
- * We're passed an initial partially filled in entry that
- * has most fields filled in except for data transfer
- * related values.
- *
- * Our job is to fill in the initial request queue entry and
- * then to start allocating and filling in continuation entries
- * until we've covered the entire transfer.
- */
-
- if (csio->cdb_len > 12) {
- seglim = 0;
- } else {
- seglim = ISP_RQDSEG;
- }
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- rq->req_flags |= REQFLAG_DATA_IN;
+ if (nseg) {
+ if (sizeof (bus_addr_t) > 4) {
+ if (rq->req_header.rqs_entry_type == RQSTYPE_T2RQS) {
+ rq->req_header.rqs_entry_type = RQSTYPE_T3RQS;
+ } else if (rq->req_header.rqs_entry_type == RQSTYPE_REQUEST) {
+ rq->req_header.rqs_entry_type = RQSTYPE_A64;
+ }
+ }
+ if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
+ ddir = ISP_FROM_DEVICE;
+ } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
+ bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
+ ddir = ISP_TO_DEVICE;
+ } else {
+ ddir = ISP_NOXFR;
+ }
} else {
- rq->req_flags |= REQFLAG_DATA_OUT;
+ dm_segs = NULL;
+ nseg = 0;
+ ddir = ISP_NOXFR;
}
- eseg = dm_segs + nseg;
-
- while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) {
- rq->req_dataseg[rq->req_seg_count].ds_base = dm_segs->ds_addr;
- rq->req_dataseg[rq->req_seg_count].ds_count = dm_segs->ds_len;
- datalen -= dm_segs->ds_len;
- rq->req_seg_count++;
- dm_segs++;
+ if (isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir) != CMD_QUEUED) {
+ mp->error = MUSHERR_NOQENTRIES;
}
-
- while (datalen > 0 && dm_segs != eseg) {
- uint16_t onxti;
- ispcontreq_t local, *crq = &local, *cqe;
-
- cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
- onxti = nxti;
- nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
- if (nxti == mp->optr) {
- isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
- mp->error = MUSHERR_NOQENTRIES;
- return;
- }
- rq->req_header.rqs_entry_count++;
- MEMZERO((void *)crq, sizeof (*crq));
- crq->req_header.rqs_entry_count = 1;
- crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
-
- seglim = 0;
- while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) {
- crq->req_dataseg[seglim].ds_base =
- dm_segs->ds_addr;
- crq->req_dataseg[seglim].ds_count =
- dm_segs->ds_len;
- rq->req_seg_count++;
- dm_segs++;
- seglim++;
- datalen -= dm_segs->ds_len;
- }
- isp_put_cont_req(isp, crq, cqe);
- MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
- }
- *mp->nxtip = nxti;
}
static int
-isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
- uint32_t *nxtip, uint32_t optr)
+isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff)
{
- ispreq_t *qep;
mush_t mush, *mp;
void (*eptr)(void *, bus_dma_segment_t *, int, int);
- qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx);
- eptr = dma2;
-
-
- if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
- (csio->dxfer_len == 0)) {
- rq->req_seg_count = 1;
- goto mbxsync;
- }
-
- /*
- * Do a virtual grapevine step to collect info for
- * the callback dma allocation that we have to use...
- */
mp = &mush;
mp->isp = isp;
mp->cmd_token = csio;
- mp->rq = rq;
- mp->nxtip = nxtip;
- mp->optr = optr;
+ mp->rq = ff;
mp->error = 0;
+ mp->mapsize = 0;
+
+ eptr = dma2;
- if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
+ if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || (csio->dxfer_len == 0)) {
+ (*eptr)(mp, NULL, 0, 0);
+ } else if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) {
- int error = bus_dmamap_load(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap, csio->data_ptr,
- csio->dxfer_len, eptr, mp, 0);
+ int error;
+ error = bus_dmamap_load(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, csio->data_ptr, csio->dxfer_len, eptr, mp, 0);
+#if 0
+ xpt_print(csio->ccb_h.path, "%s: bus_dmamap_load " "ptr %p len %d returned %d\n", __func__, csio->data_ptr, csio->dxfer_len, error);
+#endif
+
if (error == EINPROGRESS) {
- bus_dmamap_unload(isp->isp_osinfo.dmat,
- PISP_PCMD(csio)->dmap);
+ bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap);
mp->error = EINVAL;
- isp_prt(isp, ISP_LOGERR,
- "deferred dma allocation not supported");
+ isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported");
} else if (error && mp->error == 0) {
#ifdef DIAGNOSTIC
- isp_prt(isp, ISP_LOGERR,
- "error %d in dma mapping code", error);
+ isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error);
#endif
mp->error = error;
}
} else {
/* Pointer to physical buffer */
struct bus_dma_segment seg;
- seg.ds_addr = (bus_addr_t)csio->data_ptr;
+ seg.ds_addr = (bus_addr_t)(vm_offset_t)csio->data_ptr;
seg.ds_len = csio->dxfer_len;
(*eptr)(mp, &seg, 1, 0);
}
@@ -748,12 +657,10 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
struct bus_dma_segment *segs;
if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) {
- isp_prt(isp, ISP_LOGERR,
- "Physical segment pointers unsupported");
+ isp_prt(isp, ISP_LOGERR, "Physical segment pointers unsupported");
mp->error = EINVAL;
} else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) {
- isp_prt(isp, ISP_LOGERR,
- "Virtual segment addresses unsupported");
+ isp_prt(isp, ISP_LOGERR, "Physical SG/LIST Phys segment pointers unsupported");
mp->error = EINVAL;
} else {
/* Just use the segments provided */
@@ -774,19 +681,6 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
}
return (retval);
}
-mbxsync:
- if (isp->isp_dblev & ISP_LOGDEBUG1) {
- isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq);
- }
- switch (rq->req_header.rqs_entry_type) {
- case RQSTYPE_REQUEST:
- isp_put_request(isp, rq, qep);
- break;
- case RQSTYPE_CMDONLY:
- isp_put_extended_request(isp, (ispextreq_t *)rq,
- (ispextreq_t *)qep);
- break;
- }
return (CMD_QUEUED);
}
diff --git a/sys/dev/isp/isp_stds.h b/sys/dev/isp/isp_stds.h
index 42bffd9..d0a9812 100644
--- a/sys/dev/isp/isp_stds.h
+++ b/sys/dev/isp/isp_stds.h
@@ -1,6 +1,6 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 1997-2007 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,6 +24,7 @@
* 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.
+ *
*/
/*
* Structures that derive directly from public standards.
@@ -43,7 +44,7 @@ typedef struct {
uint8_t cs_ctl;
uint8_t s_id[3];
uint8_t type;
- uint8_t f_ctl;
+ uint8_t f_ctl[3];
uint8_t seq_id;
uint8_t df_ctl;
uint16_t seq_cnt;
@@ -137,8 +138,18 @@ typedef struct {
} rft_id_t;
/*
+ * FCP Response IU Bits of interest
+ * Source: NCITS T10, Project 1144D, Revision 08 (aka FCP2r08)
+ */
+#define FCP_CONF_REQ 0x10
+#define FCP_RESID_UNDERFLOW 0x08
+#define FCP_RESID_OVERFLOW 0x04
+#define FCP_SNSLEN_VALID 0x02
+#define FCP_RSPLEN_VALID 0x01
+
+/*
* FCP Response Code Definitions
- * Source: NCITS T10, Project 1144D, Revision 07a (aka FCP2r07a)
+ * Source: NCITS T10, Project 1144D, Revision 08 (aka FCP2r08)
*/
#define FCP_RSPNS_CODE_OFFSET 3
@@ -176,7 +187,10 @@ typedef struct {
#define ABTX 0x06
#define PRLI 0x20
#define PRLO 0x21
+#define SCN 0x22
#define TPRLO 0x24
+#define PDISC 0x50
+#define ADISC 0x52
#define RNC 0x53
/*
diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c
index 531f64b..68c42b4 100644
--- a/sys/dev/isp/isp_target.c
+++ b/sys/dev/isp/isp_target.c
@@ -1,17 +1,17 @@
/*-
- * Copyright (c) 1997-2007 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
- *
+ *
* 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.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY 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
@@ -23,6 +23,7 @@
* 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.
+ *
*/
/*
* Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters.
@@ -51,12 +52,9 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef ISP_TARGET_MODE
-static const char atiocope[] =
- "ATIO returned for lun %d because it was in the middle of Bus Device Reset "
- "on bus %d";
-static const char atior[] =
- "ATIO returned on for lun %d on from loopid %d because a Bus Reset "
- "occurred on bus %d";
+static const char atiocope[] = "ATIO returned for lun %d because it was in the middle of Bus Device Reset on bus %d";
+static const char atior[] = "ATIO returned on for lun %d on from loopid %d because a Bus Reset occurred on bus %d";
+static const char rqo[] = "%s: Request Queue Overflow";
static void isp_got_msg(ispsoftc_t *, in_entry_t *);
static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *);
@@ -66,6 +64,7 @@ static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *);
static void isp_handle_ctio(ispsoftc_t *, ct_entry_t *);
static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *);
static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *);
+static void isp_handle_24xx_inotify(ispsoftc_t *, in_fcentry_24xx_t *);
/*
* The Qlogic driver gets an interrupt to look at response queue entries.
@@ -164,14 +163,16 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
#define hdrp unp.hp
} unp;
uint8_t local[QENTRY_LEN];
+ uint16_t iid;
int bus, type, level, rval = 1;
+ isp_notify_t notify;
type = isp_get_response_type(isp, (isphdr_t *)vptr);
unp.vp = vptr;
ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr);
- switch(type) {
+ switch (type) {
case RQSTYPE_ATIO:
if (IS_24XX(isp)) {
int len;
@@ -179,17 +180,15 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
isp_get_atio7(isp, at7iop, (at7_entry_t *) local);
at7iop = (at7_entry_t *) local;
/*
- * Check for and do something with commands whose IULEN
- * extends past a singel queue entry.
+ * Check for and do something with commands whose
+ * IULEN extends past a single queue entry.
*/
len = at7iop->at_ta_len & 0xfffff;
if (len > (QENTRY_LEN - 8)) {
len -= (QENTRY_LEN - 8);
- isp_prt(isp, ISP_LOGINFO,
- "long IU length (%d) ignored", len);
+ isp_prt(isp, ISP_LOGINFO, "long IU length (%d) ignored", len);
while (len > 0) {
- *optrp = ISP_NXT_QENTRY(*optrp,
- RESULT_QUEUE_LEN(isp));
+ *optrp = ISP_NXT_QENTRY(*optrp, RESULT_QUEUE_LEN(isp));
len -= QENTRY_LEN;
}
}
@@ -203,7 +202,7 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
/*
* Just go straight to outer layer for this one.
*/
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, local);
+ isp_async(isp, ISPASYNC_TARGET_ACTION, local);
} else {
isp_get_atio(isp, atiop, (at_entry_t *) local);
isp_handle_atio(isp, (at_entry_t *) local);
@@ -216,7 +215,7 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
break;
case RQSTYPE_ATIO2:
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_2KLOGIN(isp)) {
isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local);
} else {
isp_get_atio2(isp, at2iop, (at2_entry_t *) local);
@@ -226,7 +225,7 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
case RQSTYPE_CTIO3:
case RQSTYPE_CTIO2:
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_2KLOGIN(isp)) {
isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local);
} else {
isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local);
@@ -242,71 +241,44 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
case RQSTYPE_ENABLE_LUN:
case RQSTYPE_MODIFY_LUN:
isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local);
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, local);
+ isp_async(isp, ISPASYNC_TARGET_ACTION, local);
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).
- */
bus = 0;
if (IS_24XX(isp)) {
- isp_get_notify_24xx(isp, inot_24xx,
- (in_fcentry_24xx_t *)local);
+ isp_get_notify_24xx(isp, inot_24xx, (in_fcentry_24xx_t *)local);
inot_24xx = (in_fcentry_24xx_t *) local;
- status = inot_24xx->in_status;
- seqid = inot_24xx->in_rxid;
- isp_prt(isp, ISP_LOGTDEBUG0,
- "Immediate Notify status=0x%x seqid=0x%x",
- status, seqid);
- switch (status) {
- case IN24XX_LIP_RESET:
- case IN24XX_LINK_RESET:
- case IN24XX_PORT_LOGOUT:
- case IN24XX_PORT_CHANGED:
- case IN24XX_LINK_FAILED:
- case IN24XX_SRR_RCVD:
- case IN24XX_ELS_RCVD:
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION,
- &local);
- break;
- default:
- isp_prt(isp, ISP_LOGINFO,
- "isp_target_notify: unknown status (0x%x)",
- status);
- isp_notify_ack(isp, local);
- break;
- }
+ isp_handle_24xx_inotify(isp, inot_24xx);
break;
- } else if (IS_FC(isp)) {
- if (FCPARAM(isp)->isp_2klogin) {
- isp_get_notify_fc_e(isp, inote_fcp,
- (in_fcentry_e_t *)local);
+ }
+ if (IS_FC(isp)) {
+ if (ISP_CAP_2KLOGIN(isp)) {
+ in_fcentry_e_t *ecp = (in_fcentry_e_t *)local;
+ isp_get_notify_fc_e(isp, inote_fcp, ecp);
+ iid = ecp->in_iid;
+ status = ecp->in_status;
+ seqid = ecp->in_seqid;
} else {
- isp_get_notify_fc(isp, inot_fcp,
- (in_fcentry_t *)local);
+ in_fcentry_t *fcp = (in_fcentry_t *)local;
+ isp_get_notify_fc(isp, inot_fcp, fcp);
+ iid = fcp->in_iid;
+ status = fcp->in_status;
+ seqid = fcp->in_seqid;
}
- inot_fcp = (in_fcentry_t *) local;
- status = inot_fcp->in_status;
- seqid = inot_fcp->in_seqid;
} else {
- isp_get_notify(isp, inotp, (in_entry_t *)local);
- inotp = (in_entry_t *) local;
- status = inotp->in_status & 0xff;
- seqid = inotp->in_seqid;
+ in_entry_t *inp = (in_entry_t *)local;
+ isp_get_notify(isp, inotp, inp);
+ status = inp->in_status & 0xff;
+ seqid = inp->in_seqid;
+ iid = inp->in_iid;
if (IS_DUALBUS(isp)) {
- bus = GET_BUS_VAL(inotp->in_iid);
- SET_BUS_VAL(inotp->in_iid, 0);
+ bus = GET_BUS_VAL(inp->in_iid);
+ SET_BUS_VAL(inp->in_iid, 0);
}
}
- isp_prt(isp, ISP_LOGTDEBUG0,
- "Immediate Notify On Bus %d, status=0x%x seqid=0x%x",
- bus, status, seqid);
+ isp_prt(isp, ISP_LOGTDEBUG0, "Immediate Notify On Bus %d, status=0x%x seqid=0x%x", bus, status, seqid);
switch (status) {
case IN_MSG_RECEIVED:
@@ -319,38 +291,74 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
break;
case IN_RSRC_UNAVAIL:
isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs");
- isp_notify_ack(isp, local);
+ (void) isp_notify_ack(isp, local);
break;
- case IN_RESET:
- {
- /*
- * We form the notify structure here because we need
- * to mark it as needing a NOTIFY ACK on return.
- */
- tmd_notify_t notify;
- MEMZERO(&notify, sizeof (tmd_notify_t));
+ case IN_RESET:
+ ISP_MEMZERO(&notify, sizeof (isp_notify_t));
notify.nt_hba = isp;
- notify.nt_iid = INI_ANY;
- /* nt_tgt set in outer layers */
+ notify.nt_wwn = INI_ANY;
+ notify.nt_tgt = TGT_ANY;
+ notify.nt_nphdl = iid;
+ notify.nt_sid = PORT_ANY;
+ notify.nt_did = PORT_ANY;
notify.nt_lun = LUN_ANY;
notify.nt_tagval = TAG_ANY;
+ notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
notify.nt_ncode = NT_BUS_RESET;
notify.nt_need_ack = 1;
- (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ notify.nt_lreserved = local;
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
break;
- }
+
case IN_PORT_LOGOUT:
+ ISP_MEMZERO(&notify, sizeof (isp_notify_t));
+ notify.nt_hba = isp;
+ notify.nt_wwn = INI_ANY;
+ notify.nt_nphdl = iid;
+ notify.nt_sid = PORT_ANY;
+ notify.nt_did = PORT_ANY;
+ notify.nt_ncode = NT_LOGOUT;
+ notify.nt_need_ack = 1;
+ notify.nt_lreserved = local;
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ break;
+
case IN_ABORT_TASK:
- case IN_PORT_CHANGED:
+ ISP_MEMZERO(&notify, sizeof (isp_notify_t));
+ notify.nt_hba = isp;
+ notify.nt_wwn = INI_ANY;
+ notify.nt_nphdl = iid;
+ notify.nt_sid = PORT_ANY;
+ notify.nt_did = PORT_ANY;
+ notify.nt_ncode = NT_ABORT_TASK;
+ notify.nt_need_ack = 1;
+ notify.nt_lreserved = local;
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ break;
+
case IN_GLOBAL_LOGO:
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
+ isp_prt(isp, ISP_LOGTINFO, "%s: all ports logged out", __func__);
+ ISP_MEMZERO(&notify, sizeof (isp_notify_t));
+ notify.nt_hba = isp;
+ notify.nt_wwn = INI_ANY;
+ notify.nt_nphdl = NIL_HANDLE;
+ notify.nt_sid = PORT_ANY;
+ notify.nt_did = PORT_ANY;
+ notify.nt_ncode = NT_GLOBAL_LOGOUT;
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ (void) isp_notify_ack(isp, local);
+ break;
+
+ case IN_PORT_CHANGED:
+ isp_prt(isp, ISP_LOGTINFO, "%s: port changed", __func__);
+ (void) isp_notify_ack(isp, local);
break;
+
default:
- isp_prt(isp, ISP_LOGINFO,
- "isp_target_notify: unknown status (0x%x)",
- status);
- isp_notify_ack(isp, local);
+ ISP_SNPRINTF(local, sizeof local, "%s: unknown status to RQSTYPE_NOTIFY (0x%x)", __func__, status);
+ isp_print_bytes(isp, local, QENTRY_LEN, vptr);
+ (void) isp_notify_ack(isp, local);
break;
}
break;
@@ -361,25 +369,19 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
* Immediate Notify entry for some asynchronous event.
*/
if (IS_24XX(isp)) {
- isp_get_notify_ack_24xx(isp, nack_24xx,
- (na_fcentry_24xx_t *) local);
+ isp_get_notify_ack_24xx(isp, nack_24xx, (na_fcentry_24xx_t *) local);
nack_24xx = (na_fcentry_24xx_t *) local;
if (nack_24xx->na_status != NA_OK) {
level = ISP_LOGINFO;
} else {
level = ISP_LOGTDEBUG1;
}
- isp_prt(isp, level,
- "Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x",
- nack_24xx->na_status, nack_24xx->na_status_subcode,
- nack_24xx->na_rxid);
+ isp_prt(isp, level, "Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x", nack_24xx->na_status, nack_24xx->na_status_subcode, nack_24xx->na_rxid);
} else if (IS_FC(isp)) {
- if (FCPARAM(isp)->isp_2klogin) {
- isp_get_notify_ack_fc_e(isp, nacke_fcp,
- (na_fcentry_e_t *)local);
+ if (ISP_CAP_2KLOGIN(isp)) {
+ isp_get_notify_ack_fc_e(isp, nacke_fcp, (na_fcentry_e_t *)local);
} else {
- isp_get_notify_ack_fc(isp, nack_fcp,
- (na_fcentry_t *)local);
+ isp_get_notify_ack_fc(isp, nack_fcp, (na_fcentry_t *)local);
}
nack_fcp = (na_fcentry_t *)local;
if (nack_fcp->na_status != NA_OK) {
@@ -387,9 +389,7 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
} else {
level = ISP_LOGTDEBUG1;
}
- isp_prt(isp, level,
- "Notify Ack Status=0x%x seqid 0x%x",
- nack_fcp->na_status, nack_fcp->na_seqid);
+ isp_prt(isp, level, "Notify Ack Status=0x%x seqid 0x%x", nack_fcp->na_status, nack_fcp->na_seqid);
} else {
isp_get_notify_ack(isp, nackp, (na_entry_t *)local);
nackp = (na_entry_t *)local;
@@ -398,15 +398,13 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
} else {
level = ISP_LOGTDEBUG1;
}
- isp_prt(isp, level,
- "Notify Ack event 0x%x status=0x%x seqid 0x%x",
- nackp->na_event, nackp->na_status, nackp->na_seqid);
+ isp_prt(isp, level, "Notify Ack event 0x%x status=0x%x seqid 0x%x", nackp->na_event, nackp->na_status, nackp->na_seqid);
}
break;
case RQSTYPE_ABTS_RCVD:
isp_get_abts(isp, abts, (abts_t *)local);
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
+ isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
break;
case RQSTYPE_ABTS_RSP:
isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local);
@@ -416,15 +414,11 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
} else {
level = ISP_LOGTDEBUG0;
}
- isp_prt(isp, level,
- "ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)",
- abts_rsp->abts_rsp_rxid_task, abts_rsp->abts_rsp_status,
- abts_rsp->abts_rsp_payload.rsp.subcode1,
- abts_rsp->abts_rsp_payload.rsp.subcode2);
+ isp_prt(isp, level, "ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)", abts_rsp->abts_rsp_rxid_task, abts_rsp->abts_rsp_status,
+ abts_rsp->abts_rsp_payload.rsp.subcode1, abts_rsp->abts_rsp_payload.rsp.subcode2);
break;
default:
- isp_prt(isp, ISP_LOGERR,
- "Unknown entry type 0x%x in isp_target_notify", type);
+ isp_prt(isp, ISP_LOGERR, "%s: unknown entry type 0x%x", __func__, type);
rval = 0;
break;
}
@@ -452,26 +446,23 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
return (rval);
}
-
+
/*
- * Toggle (on/off) target mode for bus/target/lun
+ * 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.
+ * a response entry. The caller is responsible for synchronizing with this.
*/
int
-isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun,
- int cmd_cnt, int inot_cnt, uint32_t opaque)
+isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int lun, int cmd_cnt, int inot_cnt)
{
lun_entry_t el;
- uint32_t nxti, optr;
void *outp;
-
- MEMZERO(&el, sizeof (el));
+ ISP_MEMZERO(&el, sizeof (el));
if (IS_DUALBUS(isp)) {
el.le_rsvd = (bus & 0x1) << 7;
}
@@ -495,37 +486,34 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun,
}
el.le_header.rqs_entry_type = cmd;
el.le_header.rqs_entry_count = 1;
- el.le_reserved = opaque;
if (IS_SCSI(isp)) {
- el.le_tgt = tgt;
+ el.le_tgt = SDPARAM(isp, bus)->isp_initiator_id;
el.le_lun = lun;
- } else if (FCPARAM(isp)->isp_sccfw == 0) {
+ } else if (ISP_CAP_SCCFW(isp) == 0) {
el.le_lun = lun;
}
el.le_timeout = 30;
- if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
- isp_prt(isp, ISP_LOGERR,
- "Request Queue Overflow in isp_lun_cmd");
+ outp = isp_getrqentry(isp);
+ if (outp == NULL) {
+ isp_prt(isp, ISP_LOGERR, rqo, __func__);
return (-1);
}
- ISP_TDQE(isp, "isp_lun_cmd", (int) optr, &el);
isp_put_enable_lun(isp, &el, outp);
- ISP_ADD_REQUEST(isp, nxti);
+ ISP_TDQE(isp, "isp_lun_cmd", isp->isp_reqidx, &el);
+ ISP_SYNC_REQUEST(isp);
return (0);
}
-
int
isp_target_put_entry(ispsoftc_t *isp, void *ap)
{
void *outp;
- uint32_t nxti, optr;
uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type;
- if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
- isp_prt(isp, ISP_LOGWARN,
- "Request Queue Overflow in isp_target_put_entry");
+ outp = isp_getrqentry(isp);
+ if (outp == NULL) {
+ isp_prt(isp, ISP_LOGWARN, rqo, __func__);
return (-1);
}
switch (etype) {
@@ -533,36 +521,31 @@ isp_target_put_entry(ispsoftc_t *isp, void *ap)
isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp);
break;
case RQSTYPE_ATIO2:
- if (FCPARAM(isp)->isp_2klogin) {
- isp_put_atio2e(isp, (at2e_entry_t *) ap,
- (at2e_entry_t *) outp);
+ if (ISP_CAP_2KLOGIN(isp)) {
+ isp_put_atio2e(isp, (at2e_entry_t *) ap, (at2e_entry_t *) outp);
} else {
- isp_put_atio2(isp, (at2_entry_t *) ap,
- (at2_entry_t *) outp);
+ isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp);
}
break;
case RQSTYPE_CTIO:
isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp);
break;
case RQSTYPE_CTIO2:
- if (FCPARAM(isp)->isp_2klogin) {
- isp_put_ctio2e(isp, (ct2e_entry_t *) ap,
- (ct2e_entry_t *) outp);
+ if (ISP_CAP_2KLOGIN(isp)) {
+ isp_put_ctio2e(isp, (ct2e_entry_t *) ap, (ct2e_entry_t *) outp);
} else {
- isp_put_ctio2(isp, (ct2_entry_t *) ap,
- (ct2_entry_t *) outp);
+ isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp);
}
break;
case RQSTYPE_CTIO7:
isp_put_ctio7(isp, (ct7_entry_t *) ap, (ct7_entry_t *) outp);
break;
default:
- isp_prt(isp, ISP_LOGERR,
- "Unknown type 0x%x in isp_put_entry", etype);
+ isp_prt(isp, ISP_LOGERR, "%s: Unknown type 0x%x", __func__, etype);
return (-1);
}
- ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap);
- ISP_ADD_REQUEST(isp, nxti);
+ ISP_TDQE(isp, __func__, isp->isp_reqidx, ap);
+ ISP_SYNC_REQUEST(isp);
return (0);
}
@@ -575,17 +558,17 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg)
at2e_entry_t _atio2e;
} atun;
- MEMZERO(&atun, sizeof atun);
+ ISP_MEMZERO(&atun, sizeof atun);
if (IS_FC(isp)) {
at2_entry_t *aep = arg;
atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2;
atun._atio2.at_header.rqs_entry_count = 1;
- if (FCPARAM(isp)->isp_sccfw) {
+ if (ISP_CAP_SCCFW(isp)) {
atun._atio2.at_scclun = aep->at_scclun;
} else {
atun._atio2.at_lun = (uint8_t) aep->at_lun;
}
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_2KLOGIN(isp)) {
atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid;
} else {
atun._atio2.at_iid = aep->at_iid;
@@ -627,56 +610,91 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg)
*/
int
-isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint32_t hdl)
+isp_endcmd(ispsoftc_t *isp, ...)
{
- int sts;
+ uint32_t code, hdl;
+ uint8_t sts;
union {
ct_entry_t _ctio;
ct2_entry_t _ctio2;
ct2e_entry_t _ctio2e;
ct7_entry_t _ctio7;
} un;
+ va_list ap;
- MEMZERO(&un, sizeof un);
- sts = code & 0xff;
+ ISP_MEMZERO(&un, sizeof un);
if (IS_24XX(isp)) {
- at7_entry_t *aep = arg;
+ int vpidx, nphdl;
+ at7_entry_t *aep;
ct7_entry_t *cto = &un._ctio7;
+ va_start(ap, isp);
+ aep = va_arg(ap, at7_entry_t *);
+ nphdl = va_arg(ap, int);
+ /*
+ * Note that vpidx may equal 0xff (unknown) here
+ */
+ vpidx = va_arg(ap, int);
+ code = va_arg(ap, uint32_t);
+ hdl = va_arg(ap, uint32_t);
+ va_end(ap);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] chan %d code %x", __func__, aep->at_rxid, vpidx, code);
+
+ sts = code & 0xff;
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
cto->ct_header.rqs_entry_count = 1;
-/* XXXX */ cto->ct_nphdl = aep->at_hdr.seq_id;
+ cto->ct_nphdl = nphdl;
cto->ct_rxid = aep->at_rxid;
- cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) |
- aep->at_hdr.s_id[2];
+ cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2];
cto->ct_iid_hi = aep->at_hdr.s_id[0];
cto->ct_oxid = aep->at_hdr.ox_id;
cto->ct_scsi_status = sts;
- cto->ct_flags = CT7_FLAG_MODE1 | CT7_NO_DATA | CT7_SENDSTATUS;
- if (sts == SCSI_CHECK && (code & ECMD_SVALID)) {
- cto->rsp.m1.ct_resplen = 16;
+ cto->ct_vpidx = vpidx;
+ cto->ct_flags = CT7_NOACK;
+ if (code & ECMD_TERMINATE) {
+ cto->ct_flags |= CT7_TERMINATE;
+ } else if (code & ECMD_SVALID) {
+ cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS;
+ cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
+ cto->rsp.m1.ct_resplen = cto->ct_senselen = min(16, MAXRESPLEN_24XX);
+ ISP_MEMZERO(cto->rsp.m1.ct_resp, sizeof (cto->rsp.m1.ct_resp));
cto->rsp.m1.ct_resp[0] = 0xf0;
cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;
cto->rsp.m1.ct_resp[7] = 8;
cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;
cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;
+ } else {
+ cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS;
}
if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl) {
cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl;
- cto->ct_scsi_status |= CT2_DATA_UNDER;
+ if (cto->ct_resid < 0) {
+ cto->ct_scsi_status |= (FCP_RESID_OVERFLOW << 8);
+ } else if (cto->ct_resid > 0) {
+ cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8);
+ }
}
cto->ct_syshandle = hdl;
} else if (IS_FC(isp)) {
- at2_entry_t *aep = arg;
+ at2_entry_t *aep;
ct2_entry_t *cto = &un._ctio2;
+ va_start(ap, isp);
+ aep = va_arg(ap, at2_entry_t *);
+ code = va_arg(ap, uint32_t);
+ hdl = va_arg(ap, uint32_t);
+ va_end(ap);
+
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] code %x", __func__, aep->at_rxid, code);
+
+ sts = code & 0xff;
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
cto->ct_header.rqs_entry_count = 1;
- if (FCPARAM(isp)->isp_sccfw == 0) {
+ if (ISP_CAP_SCCFW(isp) == 0) {
cto->ct_lun = aep->at_lun;
}
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_2KLOGIN(isp)) {
un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid;
} else {
cto->ct_iid = aep->at_iid;
@@ -702,9 +720,17 @@ isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint32_t hdl)
}
cto->ct_syshandle = hdl;
} else {
- at_entry_t *aep = arg;
+ at_entry_t *aep;
ct_entry_t *cto = &un._ctio;
+ va_start(ap, isp);
+ aep = va_arg(ap, at_entry_t *);
+ code = va_arg(ap, uint32_t);
+ hdl = va_arg(ap, uint32_t);
+ va_end(ap);
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: [IID %d] code %x", __func__, aep->at_iid, code);
+ sts = code;
+
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
cto->ct_header.rqs_entry_count = 1;
cto->ct_fwhandle = aep->at_handle;
@@ -729,58 +755,66 @@ isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint32_t hdl)
/*
* These are either broadcast events or specifically CTIO fast completion
*/
+
int
isp_target_async(ispsoftc_t *isp, int bus, int event)
{
- tmd_notify_t notify;
+ isp_notify_t notify;
- MEMZERO(&notify, sizeof (tmd_notify_t));
+ ISP_MEMZERO(&notify, sizeof (isp_notify_t));
notify.nt_hba = isp;
- notify.nt_iid = INI_ANY;
- /* nt_tgt set in outer layers */
+ notify.nt_wwn = INI_ANY;
+ notify.nt_nphdl = NIL_HANDLE;
+ notify.nt_sid = PORT_ANY;
+ notify.nt_did = PORT_ANY;
+ notify.nt_tgt = TGT_ANY;
+ notify.nt_channel = bus;
notify.nt_lun = LUN_ANY;
notify.nt_tagval = TAG_ANY;
-
- if (IS_SCSI(isp)) {
- TAG_INSERT_BUS(notify.nt_tagval, bus);
- }
+ notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
switch (event) {
case ASYNC_LOOP_UP:
case ASYNC_PTPMODE:
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP UP", __func__);
notify.nt_ncode = NT_LINK_UP;
- (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
break;
case ASYNC_LOOP_DOWN:
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP DOWN", __func__);
notify.nt_ncode = NT_LINK_DOWN;
- (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
break;
case ASYNC_LIP_ERROR:
case ASYNC_LIP_F8:
case ASYNC_LIP_OCCURRED:
case ASYNC_LOOP_RESET:
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: LIP RESET", __func__);
notify.nt_ncode = NT_LIP_RESET;
- (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
break;
case ASYNC_BUS_RESET:
case ASYNC_TIMEOUT_RESET: /* XXX: where does this come from ? */
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: BUS RESET", __func__);
notify.nt_ncode = NT_BUS_RESET;
- (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
break;
case ASYNC_DEVICE_RESET:
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: DEVICE RESET", __func__);
notify.nt_ncode = NT_TARGET_RESET;
- (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
break;
case ASYNC_CTIO_DONE:
{
uint8_t storage[QENTRY_LEN];
+ isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO DONE", __func__);
memset(storage, 0, QENTRY_LEN);
if (IS_24XX(isp)) {
ct7_entry_t *ct = (ct7_entry_t *) storage;
ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
ct->ct_nphdl = CT7_OK;
ct->ct_syshandle = bus;
- ct->ct_flags = CT7_SENDSTATUS|CT7_FASTPOST;
+ ct->ct_flags = CT7_SENDSTATUS;
} else if (IS_FC(isp)) {
/* This should also suffice for 2K login code */
ct2_entry_t *ct = (ct2_entry_t *) storage;
@@ -795,14 +829,13 @@ isp_target_async(ispsoftc_t *isp, int bus, int event)
ct->ct_fwhandle = bus;
ct->ct_flags = CT_SENDSTATUS;
}
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage);
+ isp_async(isp, ISPASYNC_TARGET_ACTION, storage);
break;
}
default:
- isp_prt(isp, ISP_LOGERR,
- "isp_target_async: unknown event 0x%x", event);
+ isp_prt(isp, ISP_LOGERR, "%s: unknown event 0x%x", __func__, event);
if (isp->isp_state == ISP_RUNSTATE) {
- isp_notify_ack(isp, NULL);
+ (void) isp_notify_ack(isp, NULL);
}
break;
}
@@ -821,51 +854,54 @@ isp_target_async(ispsoftc_t *isp, int bus, int event)
static void
isp_got_msg(ispsoftc_t *isp, in_entry_t *inp)
{
- tmd_notify_t nt;
+ isp_notify_t notify;
uint8_t status = inp->in_status & ~QLTM_SVALID;
- MEMZERO(&nt, sizeof (nt));
- nt.nt_hba = isp;
- nt.nt_iid = GET_IID_VAL(inp->in_iid);
- nt.nt_tgt = inp->in_tgt;
- nt.nt_lun = inp->in_lun;
- IN_MAKE_TAGID(nt.nt_tagval, GET_BUS_VAL(inp->in_iid), 0, inp);
- nt.nt_lreserved = inp;
+ ISP_MEMZERO(&notify, sizeof (notify));
+ notify.nt_hba = isp;
+ notify.nt_wwn = INI_ANY;
+ notify.nt_nphdl = GET_IID_VAL(inp->in_iid);
+ notify.nt_sid = PORT_ANY;
+ notify.nt_did = PORT_ANY;
+ notify.nt_channel = GET_BUS_VAL(inp->in_iid);
+ notify.nt_tgt = inp->in_tgt;
+ notify.nt_lun = inp->in_lun;
+ IN_MAKE_TAGID(notify.nt_tagval, inp);
+ notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
+ notify.nt_lreserved = inp;
if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) {
switch (inp->in_msg[0]) {
case MSG_ABORT:
- nt.nt_ncode = NT_ABORT_TASK_SET;
+ notify.nt_ncode = NT_ABORT_TASK_SET;
break;
case MSG_BUS_DEV_RESET:
- nt.nt_ncode = NT_TARGET_RESET;
+ notify.nt_ncode = NT_TARGET_RESET;
break;
case MSG_ABORT_TAG:
- nt.nt_ncode = NT_ABORT_TASK;
+ notify.nt_ncode = NT_ABORT_TASK;
break;
case MSG_CLEAR_QUEUE:
- nt.nt_ncode = NT_CLEAR_TASK_SET;
+ notify.nt_ncode = NT_CLEAR_TASK_SET;
break;
case MSG_REL_RECOVERY:
- nt.nt_ncode = NT_CLEAR_ACA;
+ notify.nt_ncode = NT_CLEAR_ACA;
break;
case MSG_TERM_IO_PROC:
- nt.nt_ncode = NT_ABORT_TASK;
+ notify.nt_ncode = NT_ABORT_TASK;
break;
case MSG_LUN_RESET:
- nt.nt_ncode = NT_LUN_RESET;
+ notify.nt_ncode = NT_LUN_RESET;
break;
default:
- isp_prt(isp, ISP_LOGERR,
- "unhandled message 0x%x", inp->in_msg[0]);
- isp_notify_ack(isp, inp);
+ isp_prt(isp, ISP_LOGERR, "%s: unhandled message 0x%x", __func__, inp->in_msg[0]);
+ (void) isp_notify_ack(isp, inp);
return;
}
- (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
} else {
- isp_prt(isp, ISP_LOGERR,
- "unknown immediate notify status 0x%x", inp->in_status);
- isp_notify_ack(isp, inp);
+ isp_prt(isp, ISP_LOGERR, "%s: unknown immediate notify status 0x%x", __func__, inp->in_status);
+ (void) isp_notify_ack(isp, inp);
}
}
@@ -875,169 +911,156 @@ isp_got_msg(ispsoftc_t *isp, in_entry_t *inp)
static void
isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
{
- tmd_notify_t nt;
+ isp_notify_t notify;
static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x";
- static const char f2[] = "unknown %s 0x%x lun %d N-Port handle 0x%x "
- "task flags 0x%x seq 0x%x\n";
+ static const char f2[] = "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
uint16_t seqid, loopid;
- MEMZERO(&nt, sizeof (tmd_notify_t));
- nt.nt_hba = isp;
- if (FCPARAM(isp)->isp_2klogin) {
- nt.nt_iid = ((in_fcentry_e_t *)inp)->in_iid;
+ ISP_MEMZERO(&notify, sizeof (isp_notify_t));
+ notify.nt_hba = isp;
+ notify.nt_wwn = INI_ANY;
+ if (ISP_CAP_2KLOGIN(isp)) {
+ notify.nt_nphdl = ((in_fcentry_e_t *)inp)->in_iid;
loopid = ((in_fcentry_e_t *)inp)->in_iid;
seqid = ((in_fcentry_e_t *)inp)->in_seqid;
} else {
- nt.nt_iid = inp->in_iid;
+ notify.nt_nphdl = inp->in_iid;
loopid = inp->in_iid;
seqid = inp->in_seqid;
}
+ notify.nt_sid = PORT_ANY;
+ notify.nt_did = PORT_ANY;
+
/* nt_tgt set in outer layers */
- if (FCPARAM(isp)->isp_sccfw) {
- nt.nt_lun = inp->in_scclun;
+ if (ISP_CAP_SCCFW(isp)) {
+ notify.nt_lun = inp->in_scclun;
} else {
- nt.nt_lun = inp->in_lun;
+ notify.nt_lun = inp->in_lun;
}
- IN_FC_MAKE_TAGID(nt.nt_tagval, 0, 0, seqid);
- nt.nt_need_ack = 1;
- nt.nt_lreserved = inp;
+ notify.nt_tagval = seqid;
+ notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
+ notify.nt_need_ack = 1;
+ notify.nt_lreserved = inp;
if (inp->in_status != IN_MSG_RECEIVED) {
- isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status",
- inp->in_status, nt.nt_lun, loopid, inp->in_task_flags,
- inp->in_seqid);
- isp_notify_ack(isp, inp);
+ isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", inp->in_status, notify.nt_lun, loopid, inp->in_task_flags, inp->in_seqid);
+ (void) isp_notify_ack(isp, inp);
return;
}
if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) {
- isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET",
- loopid, nt.nt_lun, inp->in_seqid);
- nt.nt_ncode = NT_ABORT_TASK_SET;
+ isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", loopid, notify.nt_lun, inp->in_seqid);
+ notify.nt_ncode = NT_ABORT_TASK_SET;
} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) {
- isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET",
- loopid, nt.nt_lun, inp->in_seqid);
- nt.nt_ncode = NT_CLEAR_TASK_SET;
+ isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", loopid, notify.nt_lun, inp->in_seqid);
+ notify.nt_ncode = NT_CLEAR_TASK_SET;
} else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) {
- isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET",
- loopid, nt.nt_lun, inp->in_seqid);
- nt.nt_ncode = NT_LUN_RESET;
+ isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", loopid, notify.nt_lun, inp->in_seqid);
+ notify.nt_ncode = NT_LUN_RESET;
} else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) {
- isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET",
- loopid, nt.nt_lun, inp->in_seqid);
- nt.nt_ncode = NT_TARGET_RESET;
+ isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", loopid, notify.nt_lun, inp->in_seqid);
+ notify.nt_ncode = NT_TARGET_RESET;
} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) {
- isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA",
- loopid, nt.nt_lun, inp->in_seqid);
- nt.nt_ncode = NT_CLEAR_ACA;
+ isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", loopid, notify.nt_lun, inp->in_seqid);
+ notify.nt_ncode = NT_CLEAR_ACA;
} else {
- isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status,
- nt.nt_lun, loopid, inp->in_task_flags, inp->in_seqid);
- isp_notify_ack(isp, inp);
+ isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, notify.nt_lun, loopid, inp->in_task_flags, inp->in_seqid);
+ (void) isp_notify_ack(isp, inp);
return;
}
- (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
}
-#define HILO(x) (uint32_t) (x >> 32), (uint32_t) x
static void
isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep)
{
- tmd_notify_t nt;
- static const char f1[] =
- "%s from PortID 0x%06x lun %d seq 0x%08x%08x";
- static const char f2[] =
- "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%08x%08x";
- uint32_t sid;
-
- MEMZERO(&nt, sizeof (tmd_notify_t));
- nt.nt_hba = isp;
- nt.nt_iid = INI_ANY;
- nt.nt_lun =
- (aep->at_cmnd.fcp_cmnd_lun[0] << 8) |
- (aep->at_cmnd.fcp_cmnd_lun[1]);
- /*
- * XXX: VPIDX HAS TO BE DERIVED FROM DESTINATION PORT
- */
- nt.nt_tagval = aep->at_rxid;
- nt.nt_lreserved = aep;
- sid =
- (aep->at_hdr.s_id[0] << 16) |
- (aep->at_hdr.s_id[1] << 8) |
- (aep->at_hdr.s_id[2]);
-
- if (aep->at_cmnd.fcp_cmnd_task_management &
- FCP_CMND_TMF_ABORT_TASK_SET) {
- isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET",
- sid, nt.nt_lun, HILO(nt.nt_tagval));
- nt.nt_ncode = NT_ABORT_TASK_SET;
- } else if (aep->at_cmnd.fcp_cmnd_task_management &
- FCP_CMND_TMF_CLEAR_TASK_SET) {
- isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET",
- sid, nt.nt_lun, HILO(nt.nt_tagval));
- nt.nt_ncode = NT_CLEAR_TASK_SET;
- } else if (aep->at_cmnd.fcp_cmnd_task_management &
- FCP_CMND_TMF_LUN_RESET) {
- isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET",
- sid, nt.nt_lun, HILO(nt.nt_tagval));
- nt.nt_ncode = NT_LUN_RESET;
- } else if (aep->at_cmnd.fcp_cmnd_task_management &
- FCP_CMND_TMF_TGT_RESET) {
- isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET",
- sid, nt.nt_lun, HILO(nt.nt_tagval));
- nt.nt_ncode = NT_TARGET_RESET;
- nt.nt_lun = LUN_ANY;
- } else if (aep->at_cmnd.fcp_cmnd_task_management &
- FCP_CMND_TMF_CLEAR_ACA) {
- isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA",
- sid, nt.nt_lun, HILO(nt.nt_tagval));
- nt.nt_ncode = NT_CLEAR_ACA;
+ isp_notify_t notify;
+ static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%08x";
+ static const char f2[] = "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%08x";
+ uint16_t chan;
+ uint32_t sid, did;
+
+ ISP_MEMZERO(&notify, sizeof (isp_notify_t));
+ notify.nt_hba = isp;
+ notify.nt_wwn = INI_ANY;
+ notify.nt_lun = (aep->at_cmnd.fcp_cmnd_lun[0] << 8) | (aep->at_cmnd.fcp_cmnd_lun[1]);
+ notify.nt_tagval = aep->at_rxid;
+ notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32);
+ notify.nt_lreserved = aep;
+ sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] << 8) | (aep->at_hdr.s_id[2]);
+
+ /* Channel has to derived from D_ID */
+ did = (aep->at_hdr.d_id[0] << 16) | (aep->at_hdr.d_id[1] << 8) | aep->at_hdr.d_id[2];
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ if (FCPARAM(isp, chan)->isp_portid == did) {
+ break;
+ }
+ }
+ if (chan == isp->isp_nchan) {
+ isp_prt(isp, ISP_LOGWARN, "%s: D_ID 0x%x not found on any channel", __func__, did);
+ /* just drop on the floor */
+ return;
+ }
+ notify.nt_nphdl = NIL_HANDLE; /* unknown here */
+ notify.nt_sid = sid;
+ notify.nt_did = did;
+ notify.nt_channel = chan;
+ if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_ABORT_TASK_SET) {
+ isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", sid, notify.nt_lun, aep->at_rxid);
+ notify.nt_ncode = NT_ABORT_TASK_SET;
+ } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_TASK_SET) {
+ isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", sid, notify.nt_lun, aep->at_rxid);
+ notify.nt_ncode = NT_CLEAR_TASK_SET;
+ } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_LUN_RESET) {
+ isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", sid, notify.nt_lun, aep->at_rxid);
+ notify.nt_ncode = NT_LUN_RESET;
+ } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_TGT_RESET) {
+ isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", sid, notify.nt_lun, aep->at_rxid);
+ notify.nt_ncode = NT_TARGET_RESET;
+ } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_ACA) {
+ isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", sid, notify.nt_lun, aep->at_rxid);
+ notify.nt_ncode = NT_CLEAR_ACA;
} else {
- isp_prt(isp, ISP_LOGWARN, f2,
- aep->at_cmnd.fcp_cmnd_task_management,
- nt.nt_lun, sid, HILO(nt.nt_tagval));
- isp_endcmd(isp, aep, 0, 0);
+ isp_prt(isp, ISP_LOGWARN, f2, aep->at_cmnd.fcp_cmnd_task_management, notify.nt_lun, sid, aep->at_rxid);
+ notify.nt_ncode = NT_UNKNOWN;
return;
}
- (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
+ isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
}
-void
+int
isp_notify_ack(ispsoftc_t *isp, void *arg)
{
char storage[QENTRY_LEN];
- uint32_t nxti, optr;
void *outp;
- if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
- isp_prt(isp, ISP_LOGWARN,
- "Request Queue Overflow For isp_notify_ack");
- return;
+ /*
+ * This is in case a Task Management Function ends up here.
+ */
+ if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) {
+ at7_entry_t *aep = arg;
+ return (isp_endcmd(isp, aep, NIL_HANDLE, 0, 0, 0));
}
- MEMZERO(storage, QENTRY_LEN);
+ outp = isp_getrqentry(isp);
+ if (outp == NULL) {
+ isp_prt(isp, ISP_LOGWARN, rqo, __func__);
+ return (1);
+ }
- if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) {
- at7_entry_t *aep = arg;
- isp_endcmd(isp, aep, 0, 0);
- return;
- } else if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ABTS_RSP)) {
- abts_rsp_t *abts_rsp = (abts_rsp_t *) storage;
- /*
- * The caller will have set response values as appropriate
- * in the ABTS structure just before calling us.
- */
- MEMCPY(abts_rsp, arg, QENTRY_LEN);
- isp_put_abts_rsp(isp, abts_rsp, (abts_rsp_t *)outp);
- } else if (IS_24XX(isp)) {
+ ISP_MEMZERO(storage, QENTRY_LEN);
+
+ if (IS_24XX(isp)) {
na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage;
if (arg) {
in_fcentry_24xx_t *in = arg;
na->na_nphdl = in->in_nphdl;
+ na->na_flags = in->in_flags & IN24XX_FLAG_PUREX_IOCB;
na->na_status = in->in_status;
na->na_status_subcode = in->in_status_subcode;
na->na_rxid = in->in_rxid;
na->na_oxid = in->in_oxid;
+ na->na_vpidx = in->in_vpidx;
if (in->in_status == IN24XX_SRR_RCVD) {
na->na_srr_rxid = in->in_srr_rxid;
na->na_srr_reloff_hi = in->in_srr_reloff_hi;
@@ -1058,17 +1081,15 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
if (arg) {
in_fcentry_t *inp = arg;
- MEMCPY(storage, arg, sizeof (isphdr_t));
- if (FCPARAM(isp)->isp_2klogin) {
- ((na_fcentry_e_t *)na)->na_iid =
- ((in_fcentry_e_t *)inp)->in_iid;
+ ISP_MEMCPY(storage, arg, sizeof (isphdr_t));
+ if (ISP_CAP_2KLOGIN(isp)) {
+ ((na_fcentry_e_t *)na)->na_iid = ((in_fcentry_e_t *)inp)->in_iid;
iid = ((na_fcentry_e_t *)na)->na_iid;
} else {
na->na_iid = inp->in_iid;
iid = na->na_iid;
}
- na->na_task_flags =
- inp->in_task_flags & TASK_FLAGS_RESERVED_MASK;
+ na->na_task_flags = inp->in_task_flags & TASK_FLAGS_RESERVED_MASK;
na->na_seqid = inp->in_seqid;
na->na_flags = NAFC_RCOUNT;
na->na_status = inp->in_status;
@@ -1084,20 +1105,18 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
}
na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
na->na_header.rqs_entry_count = 1;
- if (FCPARAM(isp)->isp_2klogin) {
- isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na,
- (na_fcentry_e_t *)outp);
+ if (ISP_CAP_2KLOGIN(isp)) {
+ isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na, (na_fcentry_e_t *)outp);
} else {
isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp);
}
- isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x "
- "flags %x tflags %x response %x", iid, na->na_seqid,
+ isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x flags %x tflags %x response %x", iid, na->na_seqid,
na->na_flags, na->na_task_flags, na->na_response);
} else {
na_entry_t *na = (na_entry_t *) storage;
if (arg) {
in_entry_t *inp = arg;
- MEMCPY(storage, arg, sizeof (isphdr_t));
+ ISP_MEMCPY(storage, arg, sizeof (isphdr_t));
na->na_iid = inp->in_iid;
na->na_lun = inp->in_lun;
na->na_tgt = inp->in_tgt;
@@ -1111,12 +1130,90 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
na->na_header.rqs_entry_count = 1;
isp_put_notify_ack(isp, na, (na_entry_t *)outp);
- isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt "
- "%u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt,
- na->na_seqid, na->na_event);
+ isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt %u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, na->na_seqid, na->na_event);
+ }
+ ISP_TDQE(isp, "isp_notify_ack", isp->isp_reqidx, storage);
+ ISP_SYNC_REQUEST(isp);
+ return (0);
+}
+
+int
+isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno)
+{
+ char storage[QENTRY_LEN];
+ uint16_t tmpw;
+ uint8_t tmpb;
+ abts_t *abts = arg;
+ abts_rsp_t *rsp = (abts_rsp_t *) storage;
+ void *outp;
+
+ if (!IS_24XX(isp)) {
+ isp_prt(isp, ISP_LOGERR, "%s: called for non-24XX card", __func__);
+ return (0);
+ }
+
+ if (abts->abts_header.rqs_entry_type != RQSTYPE_ABTS_RCVD) {
+ isp_prt(isp, ISP_LOGERR, "%s: called for non-ABTS entry (0x%x)", __func__, abts->abts_header.rqs_entry_type);
+ return (0);
+ }
+
+ outp = isp_getrqentry(isp);
+ if (outp == NULL) {
+ isp_prt(isp, ISP_LOGWARN, rqo, __func__);
+ return (1);
+ }
+
+ ISP_MEMCPY(rsp, abts, QENTRY_LEN);
+ rsp->abts_rsp_header.rqs_entry_type = RQSTYPE_ABTS_RSP;
+
+ /*
+ * Swap destination and source for response.
+ */
+ rsp->abts_rsp_r_ctl = BA_ACC;
+ tmpw = rsp->abts_rsp_did_lo;
+ tmpb = rsp->abts_rsp_did_hi;
+ rsp->abts_rsp_did_lo = rsp->abts_rsp_sid_lo;
+ rsp->abts_rsp_did_hi = rsp->abts_rsp_sid_hi;
+ rsp->abts_rsp_sid_lo = tmpw;
+ rsp->abts_rsp_sid_hi = tmpb;
+
+ rsp->abts_rsp_f_ctl_hi ^= 0x80; /* invert Exchange Context */
+ rsp->abts_rsp_f_ctl_hi &= ~0x7f; /* clear Sequence Initiator and other bits */
+ rsp->abts_rsp_f_ctl_hi |= 0x10; /* abort the whole exchange */
+ rsp->abts_rsp_f_ctl_hi |= 0x8; /* last data frame of sequence */
+ rsp->abts_rsp_f_ctl_hi |= 0x1; /* transfer Sequence Initiative */
+ rsp->abts_rsp_f_ctl_lo = 0;
+
+ if (errno == 0) {
+ uint16_t rx_id, ox_id;
+
+ rx_id = rsp->abts_rsp_rx_id;
+ ox_id = rsp->abts_rsp_ox_id;
+ ISP_MEMZERO(&rsp->abts_rsp_payload.ba_acc, sizeof (rsp->abts_rsp_payload.ba_acc));
+ isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS of 0x%x being BA_ACC'd", rsp->abts_rsp_rxid_abts, rsp->abts_rsp_rxid_task);
+ rsp->abts_rsp_payload.ba_acc.aborted_rx_id = rx_id;
+ rsp->abts_rsp_payload.ba_acc.aborted_ox_id = ox_id;
+ rsp->abts_rsp_payload.ba_acc.high_seq_cnt = 0xffff;
+ } else {
+ ISP_MEMZERO(&rsp->abts_rsp_payload.ba_rjt, sizeof (rsp->abts_rsp_payload.ba_acc));
+ switch (errno) {
+ case ENOMEM:
+ rsp->abts_rsp_payload.ba_rjt.reason = 5; /* Logical Busy */
+ break;
+ default:
+ rsp->abts_rsp_payload.ba_rjt.reason = 9; /* Unable to perform command request */
+ break;
+ }
}
- ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage);
- ISP_ADD_REQUEST(isp, nxti);
+
+ /*
+ * The caller will have set response values as appropriate
+ * in the ABTS structure just before calling us.
+ */
+ isp_put_abts_rsp(isp, rsp, (abts_rsp_t *)outp);
+ ISP_TDQE(isp, "isp_acknak_abts", isp->isp_reqidx, storage);
+ ISP_SYNC_REQUEST(isp);
+ return (0);
}
static void
@@ -1136,13 +1233,12 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
* about this so it's ignored.
*/
- switch(aep->at_status & ~QLTM_SVALID) {
+ switch (aep->at_status & ~QLTM_SVALID) {
case AT_PATH_INVALID:
/*
* ATIO rejected by the firmware due to disabled lun.
*/
- isp_prt(isp, ISP_LOGERR,
- "rejected ATIO for disabled lun %d", lun);
+ isp_prt(isp, ISP_LOGERR, "rejected ATIO for disabled lun %d", lun);
break;
case AT_NOCAP:
/*
@@ -1150,9 +1246,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
* We sent an ATIO that overflowed the firmware's
* command resource count.
*/
- isp_prt(isp, ISP_LOGERR,
- "rejected ATIO for lun %d because of command count"
- " overflow", lun);
+ isp_prt(isp, ISP_LOGERR, "rejected ATIO for lun %d because of command count overflow", lun);
break;
case AT_BDR_MSG:
@@ -1165,8 +1259,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
* not increment it. Therefore we should never get
* this status here.
*/
- isp_prt(isp, ISP_LOGERR, atiocope, lun,
- GET_BUS_VAL(aep->at_iid));
+ isp_prt(isp, ISP_LOGERR, atiocope, lun, GET_BUS_VAL(aep->at_iid));
break;
case AT_CDB: /* Got a CDB */
@@ -1174,7 +1267,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
/*
* Punt to platform specific layer.
*/
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
+ isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
break;
case AT_RESET:
@@ -1186,15 +1279,12 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
* Ignore it because the async event will clear things
* up for us.
*/
- isp_prt(isp, ISP_LOGWARN, atior, lun,
- GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid));
+ isp_prt(isp, ISP_LOGWARN, atior, lun, GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid));
break;
default:
- isp_prt(isp, ISP_LOGERR,
- "Unknown ATIO status 0x%x from loopid %d for lun %d",
- aep->at_status, aep->at_iid, lun);
+ isp_prt(isp, ISP_LOGERR, "Unknown ATIO status 0x%x from loopid %d for lun %d", aep->at_status, aep->at_iid, lun);
(void) isp_target_put_atio(isp, aep);
break;
}
@@ -1205,13 +1295,13 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
{
int lun, iid;
- if (FCPARAM(isp)->isp_sccfw) {
+ if (ISP_CAP_SCCFW(isp)) {
lun = aep->at_scclun;
} else {
lun = aep->at_lun;
}
- if (FCPARAM(isp)->isp_2klogin) {
+ if (ISP_CAP_2KLOGIN(isp)) {
iid = ((at2e_entry_t *)aep)->at_iid;
} else {
iid = aep->at_iid;
@@ -1229,13 +1319,12 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
* about this so it's ignored.
*/
- switch(aep->at_status & ~QLTM_SVALID) {
+ switch (aep->at_status & ~QLTM_SVALID) {
case AT_PATH_INVALID:
/*
* ATIO rejected by the firmware due to disabled lun.
*/
- isp_prt(isp, ISP_LOGERR,
- "rejected ATIO2 for disabled lun %d", lun);
+ isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for disabled lun %d", lun);
break;
case AT_NOCAP:
/*
@@ -1243,8 +1332,7 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
* We sent an ATIO that overflowed the firmware's
* command resource count.
*/
- isp_prt(isp, ISP_LOGERR,
- "rejected ATIO2 for lun %d- command count overflow", lun);
+ isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for lun %d- command count overflow", lun);
break;
case AT_BDR_MSG:
@@ -1264,7 +1352,7 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
/*
* Punt to platform specific layer.
*/
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
+ isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
break;
case AT_RESET:
@@ -1281,9 +1369,7 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
default:
- isp_prt(isp, ISP_LOGERR,
- "Unknown ATIO2 status 0x%x from loopid %d for lun %d",
- aep->at_status, iid, lun);
+ isp_prt(isp, ISP_LOGERR, "Unknown ATIO2 status 0x%x from loopid %d for lun %d", aep->at_status, iid, lun);
(void) isp_target_put_atio(isp, aep);
break;
}
@@ -1305,7 +1391,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
xs = NULL;
}
- switch(ct->ct_status & ~QLTM_SVALID) {
+ switch (ct->ct_status & ~QLTM_SVALID) {
case CT_OK:
/*
* There are generally 3 possibilities as to why we'd get
@@ -1321,8 +1407,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
/*
* Nothing to do in this case.
*/
- isp_prt(isp, pl, "CTIO- iid %d disconnected OK",
- ct->ct_iid);
+ isp_prt(isp, pl, "CTIO- iid %d disconnected OK", ct->ct_iid);
return;
}
break;
@@ -1351,7 +1436,6 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
*/
if (fmsg == NULL)
fmsg = "ABORT TAG message sent by Initiator";
-
isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg);
break;
@@ -1360,9 +1444,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
* CTIO rejected by the firmware due to disabled lun.
* "Cannot Happen".
*/
- isp_prt(isp, ISP_LOGERR,
- "Firmware rejected CTIO for disabled lun %d",
- ct->ct_lun);
+ isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for disabled lun %d", ct->ct_lun);
break;
case CT_NOPATH:
@@ -1372,9 +1454,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
* we tried to access the bus while a non-disconnecting
* command is in process.
*/
- isp_prt(isp, ISP_LOGERR,
- "Firmware rejected CTIO for bad nexus %d/%d/%d",
- ct->ct_iid, ct->ct_tgt, ct->ct_lun);
+ isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for bad nexus %d/%d/%d", ct->ct_iid, ct->ct_tgt, ct->ct_lun);
break;
case CT_RSELTMO:
@@ -1383,7 +1463,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
case CT_TIMEOUT:
if (fmsg == NULL)
fmsg = "Command";
- isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
+ isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg);
break;
case CT_PANIC:
@@ -1408,8 +1488,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
break;
default:
- isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x",
- ct->ct_status & ~QLTM_SVALID);
+ isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x", ct->ct_status & ~QLTM_SVALID);
break;
}
@@ -1423,16 +1502,12 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
*/
if (ct->ct_syshandle == 0) {
if ((ct->ct_flags & CT_SENDSTATUS) == 0) {
- isp_prt(isp, pl,
- "intermediate CTIO completed ok");
+ isp_prt(isp, pl, "intermediate CTIO completed ok");
} else {
- isp_prt(isp, pl,
- "unmonitored CTIO completed ok");
+ isp_prt(isp, pl, "unmonitored CTIO completed ok");
}
} else {
- isp_prt(isp, pl,
- "NO xs for CTIO (handle 0x%x) status 0x%x",
- ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
+ isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
}
} else {
/*
@@ -1446,7 +1521,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
/*
* The platform layer will destroy the handle if appropriate.
*/
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
+ isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
}
}
@@ -1466,7 +1541,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
xs = NULL;
}
- switch(ct->ct_status & ~QLTM_SVALID) {
+ switch (ct->ct_status & ~QLTM_SVALID) {
case CT_BUS_ERROR:
isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
/* FALL Through */
@@ -1507,8 +1582,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
fmsg = "ABORT";
}
- isp_prt(isp, ISP_LOGTDEBUG0,
- "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
+ isp_prt(isp, ISP_LOGTDEBUG0, "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
break;
case CT_INVAL:
@@ -1524,7 +1598,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
case CT_TIMEOUT:
if (fmsg == NULL)
fmsg = "command";
- isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
+ isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg);
break;
case CT_ERR:
@@ -1553,13 +1627,11 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
* CTIO rejected by the firmware because an invalid RX_ID.
* Just print a message.
*/
- isp_prt(isp, ISP_LOGWARN,
- "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
+ isp_prt(isp, ISP_LOGWARN, "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
break;
default:
- isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x",
- ct->ct_status & ~QLTM_SVALID);
+ isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x", ct->ct_status & ~QLTM_SVALID);
break;
}
@@ -1573,16 +1645,12 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
*/
if (ct->ct_syshandle == 0) {
if ((ct->ct_flags & CT2_SENDSTATUS) == 0) {
- isp_prt(isp, pl,
- "intermediate CTIO completed ok");
+ isp_prt(isp, pl, "intermediate CTIO completed ok");
} else {
- isp_prt(isp, pl,
- "unmonitored CTIO completed ok");
+ isp_prt(isp, pl, "unmonitored CTIO completed ok");
}
} else {
- isp_prt(isp, pl,
- "NO xs for CTIO (handle 0x%x) status 0x%x",
- ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
+ isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
}
} else {
if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
@@ -1605,7 +1673,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
*/
isp_prt(isp, pl, "data CTIO complete");
}
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
+ isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
/*
* The platform layer will destroy the handle if appropriate.
*/
@@ -1628,7 +1696,7 @@ isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
xs = NULL;
}
- switch(ct->ct_nphdl) {
+ switch (ct->ct_nphdl) {
case CT7_BUS_ERROR:
isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
/* FALL Through */
@@ -1658,15 +1726,14 @@ isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
if (fmsg == NULL) {
fmsg = "ABORT";
}
- isp_prt(isp, ISP_LOGTDEBUG0,
- "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
+ isp_prt(isp, ISP_LOGTDEBUG0, "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
break;
case CT7_TIMEOUT:
if (fmsg == NULL) {
fmsg = "command";
}
- isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
+ isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg);
break;
case CT7_ERR:
@@ -1694,8 +1761,7 @@ isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
* CTIO rejected by the firmware because an invalid RX_ID.
* Just print a message.
*/
- isp_prt(isp, ISP_LOGWARN,
- "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
+ isp_prt(isp, ISP_LOGWARN, "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
break;
case CT7_REASSY_ERR:
@@ -1707,8 +1773,7 @@ isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
break;
default:
- isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x",
- ct->ct_nphdl);
+ isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x", ct->ct_nphdl);
break;
}
@@ -1722,26 +1787,20 @@ isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
*/
if (ct->ct_syshandle == 0) {
if (ct->ct_flags & CT7_TERMINATE) {
- isp_prt(isp, ISP_LOGINFO,
- "termination of 0x%x complete",
- ct->ct_rxid);
+ isp_prt(isp, ISP_LOGINFO, "termination of 0x%x complete", ct->ct_rxid);
} else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) {
- isp_prt(isp, pl,
- "intermediate CTIO completed ok");
+ isp_prt(isp, pl, "intermediate CTIO completed ok");
} else {
- isp_prt(isp, pl,
- "unmonitored CTIO completed ok");
+ isp_prt(isp, pl, "unmonitored CTIO completed ok");
}
} else {
- isp_prt(isp, pl,
- "NO xs for CTIO (handle 0x%x) status 0x%x",
- ct->ct_syshandle, ct->ct_nphdl);
+ isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_nphdl);
}
} else {
- if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
+ if ((ct->ct_flags & CT7_DATAMASK) != CT7_NO_DATA) {
ISP_DMAFREE(isp, xs, ct->ct_syshandle);
}
- if (ct->ct_flags & CT2_SENDSTATUS) {
+ if (ct->ct_flags & CT7_SENDSTATUS) {
/*
* Sent status and command complete.
*
@@ -1758,10 +1817,56 @@ isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
*/
isp_prt(isp, pl, "data CTIO complete");
}
- (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
+ isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
/*
* The platform layer will destroy the handle if appropriate.
*/
}
}
+
+static void
+isp_handle_24xx_inotify(ispsoftc_t *isp, in_fcentry_24xx_t *inot_24xx)
+{
+ uint8_t ochan, chan, lochan, hichan;
+
+ /*
+ * Check to see whether we got a wildcard channel.
+ * If so, we have to iterate over all channels.
+ */
+ ochan = chan = ISP_GET_VPIDX(isp, inot_24xx->in_vpidx);
+ if (chan == 0xff) {
+ lochan = 0;
+ hichan = isp->isp_nchan;
+ } else {
+ if (chan >= isp->isp_nchan) {
+ char buf[64];
+ ISP_SNPRINTF(buf, sizeof buf, "%s: bad channel %d for status 0x%x", __func__, chan, inot_24xx->in_status);
+ isp_print_bytes(isp, buf, QENTRY_LEN, inot_24xx);
+ (void) isp_notify_ack(isp, inot_24xx);
+ return;
+ }
+ lochan = chan;
+ hichan = chan + 1;
+ }
+ isp_prt(isp, ISP_LOGTDEBUG1, "%s: Immediate Notify Channels %d..%d status=0x%x seqid=0x%x", __func__, lochan, hichan-1, inot_24xx->in_status, inot_24xx->in_rxid);
+ for (chan = lochan; chan < hichan; chan++) {
+ switch (inot_24xx->in_status) {
+ case IN24XX_LIP_RESET:
+ case IN24XX_LINK_RESET:
+ case IN24XX_PORT_LOGOUT:
+ case IN24XX_PORT_CHANGED:
+ case IN24XX_LINK_FAILED:
+ case IN24XX_SRR_RCVD:
+ case IN24XX_ELS_RCVD:
+ inot_24xx->in_vpidx = chan;
+ isp_async(isp, ISPASYNC_TARGET_ACTION, inot_24xx);
+ break;
+ default:
+ isp_prt(isp, ISP_LOGINFO, "%s: unhandled status (0x%x) for chan %d", __func__, inot_24xx->in_status, chan);
+ (void) isp_notify_ack(isp, inot_24xx);
+ break;
+ }
+ }
+ inot_24xx->in_vpidx = ochan;
+}
#endif
diff --git a/sys/dev/isp/isp_target.h b/sys/dev/isp/isp_target.h
index e57df6c..9905c4f 100644
--- a/sys/dev/isp/isp_target.h
+++ b/sys/dev/isp/isp_target.h
@@ -1,6 +1,6 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 1997-2007 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,6 +24,7 @@
* 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.
+ *
*/
/*
* Qlogic Target Mode Structure and Flag Definitions
@@ -31,858 +32,56 @@
#ifndef _ISP_TARGET_H
#define _ISP_TARGET_H
-#define QLTM_SENSELEN 18 /* non-FC cards only */
-#define QLTM_SVALID 0x80
-
-/*
- * Structure for Enable Lun and Modify Lun queue entries
- */
-typedef struct {
- isphdr_t le_header;
- uint32_t le_reserved;
- uint8_t le_lun;
- uint8_t le_rsvd;
- uint8_t le_ops; /* Modify LUN only */
- uint8_t le_tgt; /* Not for FC */
- uint32_t le_flags; /* Not for FC */
- uint8_t le_status;
- uint8_t le_reserved2;
- uint8_t le_cmd_count;
- uint8_t le_in_count;
- uint8_t le_cdb6len; /* Not for FC */
- uint8_t le_cdb7len; /* Not for FC */
- uint16_t le_timeout;
- uint16_t le_reserved3[20];
-} lun_entry_t;
-
-/*
- * le_flags values
- */
-#define LUN_TQAE 0x00000002 /* bit1 Tagged Queue Action Enable */
-#define LUN_DSSM 0x01000000 /* bit24 Disable Sending SDP Message */
-#define LUN_DISAD 0x02000000 /* bit25 Disable autodisconnect */
-#define LUN_DM 0x40000000 /* bit30 Disconnects Mandatory */
-
-/*
- * le_ops values
- */
-#define LUN_CCINCR 0x01 /* increment command count */
-#define LUN_CCDECR 0x02 /* decrement command count */
-#define LUN_ININCR 0x40 /* increment immed. notify count */
-#define LUN_INDECR 0x80 /* decrement immed. notify count */
-
-/*
- * le_status values
- */
-#define LUN_OK 0x01 /* we be rockin' */
-#define LUN_ERR 0x04 /* request completed with error */
-#define LUN_INVAL 0x06 /* invalid request */
-#define LUN_NOCAP 0x16 /* can't provide requested capability */
-#define LUN_ENABLED 0x3E /* LUN already enabled */
-
-/*
- * Immediate Notify Entry structure
- */
-#define IN_MSGLEN 8 /* 8 bytes */
-#define IN_RSVDLEN 8 /* 8 words */
-typedef struct {
- isphdr_t in_header;
- uint32_t in_reserved;
- uint8_t in_lun; /* lun */
- uint8_t in_iid; /* initiator */
- uint8_t in_reserved2;
- uint8_t in_tgt; /* target */
- uint32_t in_flags;
- uint8_t in_status;
- uint8_t in_rsvd2;
- uint8_t in_tag_val; /* tag value */
- uint8_t in_tag_type; /* tag type */
- uint16_t in_seqid; /* sequence id */
- uint8_t in_msg[IN_MSGLEN]; /* SCSI message bytes */
- uint16_t in_reserved3[IN_RSVDLEN];
- uint8_t in_sense[QLTM_SENSELEN];/* suggested sense data */
-} in_entry_t;
-
-typedef struct {
- isphdr_t in_header;
- uint32_t in_reserved;
- uint8_t in_lun; /* lun */
- uint8_t in_iid; /* initiator */
- uint16_t in_scclun;
- uint32_t in_reserved2;
- uint16_t in_status;
- uint16_t in_task_flags;
- uint16_t in_seqid; /* sequence id */
-} in_fcentry_t;
-
-typedef struct {
- isphdr_t in_header;
- uint32_t in_reserved;
- uint16_t in_iid; /* initiator */
- uint16_t in_scclun;
- uint32_t in_reserved2;
- uint16_t in_status;
- uint16_t in_task_flags;
- uint16_t in_seqid; /* sequence id */
-} in_fcentry_e_t;
-
-/*
- * Values for the in_status field
- */
-#define IN_REJECT 0x0D /* Message Reject message received */
-#define IN_RESET 0x0E /* Bus Reset occurred */
-#define IN_NO_RCAP 0x16 /* requested capability not available */
-#define IN_IDE_RECEIVED 0x33 /* Initiator Detected Error msg received */
-#define IN_RSRC_UNAVAIL 0x34 /* resource unavailable */
-#define IN_MSG_RECEIVED 0x36 /* SCSI message received */
-#define IN_ABORT_TASK 0x20 /* task named in RX_ID is being aborted (FC) */
-#define IN_PORT_LOGOUT 0x29 /* port has logged out (FC) */
-#define IN_PORT_CHANGED 0x2A /* port changed */
-#define IN_GLOBAL_LOGO 0x2E /* all ports logged out */
-#define IN_NO_NEXUS 0x3B /* Nexus not established */
-
-/*
- * Values for the in_task_flags field- should only get one at a time!
- */
-#define TASK_FLAGS_RESERVED_MASK (0xe700)
-#define TASK_FLAGS_CLEAR_ACA (1<<14)
-#define TASK_FLAGS_TARGET_RESET (1<<13)
-#define TASK_FLAGS_LUN_RESET (1<<12)
-#define TASK_FLAGS_CLEAR_TASK_SET (1<<10)
-#define TASK_FLAGS_ABORT_TASK_SET (1<<9)
-
-/*
- * ISP24XX Immediate Notify
- */
-typedef struct {
- isphdr_t in_header;
- uint32_t in_reserved;
- uint16_t in_nphdl;
- uint16_t in_reserved1;
- uint16_t in_flags;
- uint16_t in_srr_rxid;
- uint16_t in_status;
- uint8_t in_status_subcode;
- uint8_t in_reserved2;
- uint32_t in_rxid;
- uint16_t in_srr_reloff_lo;
- uint16_t in_srr_reloff_hi;
- uint16_t in_srr_iu;
- uint16_t in_srr_oxid;
- uint8_t in_reserved3[18];
- uint8_t in_reserved4;
- uint8_t in_vpindex;
- uint32_t in_reserved5;
- uint16_t in_portid_lo;
- uint8_t in_portid_hi;
- uint8_t in_reserved6;
- uint16_t in_reserved7;
- uint16_t in_oxid;
-} in_fcentry_24xx_t;
-
-#define IN24XX_FLAG_PUREX_IOCB 0x1
-#define IN24XX_FLAG_GLOBAL_LOGOUT 0x2
-
-#define IN24XX_LIP_RESET 0x0E
-#define IN24XX_LINK_RESET 0x0F
-#define IN24XX_PORT_LOGOUT 0x29
-#define IN24XX_PORT_CHANGED 0x2A
-#define IN24XX_LINK_FAILED 0x2E
-#define IN24XX_SRR_RCVD 0x45
-#define IN24XX_ELS_RCVD 0x46 /*
- * login-affectin ELS received- check
- * subcode for specific opcode
- */
-/*
- * Notify Acknowledge Entry structure
- */
-#define NA_RSVDLEN 22
-typedef struct {
- isphdr_t na_header;
- uint32_t na_reserved;
- uint8_t na_lun; /* lun */
- uint8_t na_iid; /* initiator */
- uint8_t na_reserved2;
- uint8_t na_tgt; /* target */
- uint32_t na_flags;
- uint8_t na_status;
- uint8_t na_event;
- uint16_t na_seqid; /* sequence id */
- uint16_t na_reserved3[NA_RSVDLEN];
-} na_entry_t;
-
-/*
- * Value for the na_event field
- */
-#define NA_RST_CLRD 0x80 /* Clear an async event notification */
-#define NA_OK 0x01 /* Notify Acknowledge Succeeded */
-#define NA_INVALID 0x06 /* Invalid Notify Acknowledge */
-
-#define NA2_RSVDLEN 21
-typedef struct {
- isphdr_t na_header;
- uint32_t na_reserved;
- uint8_t na_reserved1;
- uint8_t na_iid; /* initiator loop id */
- uint16_t na_response;
- uint16_t na_flags;
- uint16_t na_reserved2;
- uint16_t na_status;
- uint16_t na_task_flags;
- uint16_t na_seqid; /* sequence id */
- uint16_t na_reserved3[NA2_RSVDLEN];
-} na_fcentry_t;
-
-typedef struct {
- isphdr_t na_header;
- uint32_t na_reserved;
- uint16_t na_iid; /* initiator loop id */
- uint16_t na_response; /* response code */
- uint16_t na_flags;
- uint16_t na_reserved2;
- uint16_t na_status;
- uint16_t na_task_flags;
- uint16_t na_seqid; /* sequence id */
- uint16_t na_reserved3[NA2_RSVDLEN];
-} na_fcentry_e_t;
-
-#define NAFC_RCOUNT 0x80 /* increment resource count */
-#define NAFC_RST_CLRD 0x20 /* Clear LIP Reset */
-#define NAFC_TVALID 0x10 /* task mangement response code is valid */
-
-/*
- * ISP24XX Notify Acknowledge
- */
-
-typedef struct {
- isphdr_t na_header;
- uint32_t na_handle;
- uint16_t na_nphdl;
- uint16_t na_reserved1;
- uint16_t na_flags;
- uint16_t na_srr_rxid;
- uint16_t na_status;
- uint8_t na_status_subcode;
- uint8_t na_reserved2;
- uint32_t na_rxid;
- uint16_t na_srr_reloff_lo;
- uint16_t na_srr_reloff_hi;
- uint16_t na_srr_iu;
- uint16_t na_srr_flags;
- uint8_t na_reserved3[18];
- uint8_t na_reserved4;
- uint8_t na_vpindex;
- uint8_t na_srr_reject_vunique;
- uint8_t na_srr_reject_explanation;
- uint8_t na_srr_reject_code;
- uint8_t na_reserved5;
- uint8_t na_reserved6[6];
- uint16_t na_oxid;
-} na_fcentry_24xx_t;
-
-/*
- * Accept Target I/O Entry structure
- */
-#define ATIO_CDBLEN 26
-
-typedef struct {
- isphdr_t at_header;
- uint16_t at_reserved;
- uint16_t at_handle;
- uint8_t at_lun; /* lun */
- uint8_t at_iid; /* initiator */
- uint8_t at_cdblen; /* cdb length */
- uint8_t at_tgt; /* target */
- uint32_t at_flags;
- uint8_t at_status; /* firmware status */
- uint8_t at_scsi_status; /* scsi status */
- uint8_t at_tag_val; /* tag value */
- uint8_t at_tag_type; /* tag type */
- uint8_t at_cdb[ATIO_CDBLEN]; /* received CDB */
- uint8_t at_sense[QLTM_SENSELEN];/* suggested sense data */
-} at_entry_t;
-
-/*
- * at_flags values
- */
-#define AT_NODISC 0x00008000 /* disconnect disabled */
-#define AT_TQAE 0x00000002 /* Tagged Queue Action enabled */
-
-/*
- * at_status values
- */
-#define AT_PATH_INVALID 0x07 /* ATIO sent to firmware for disabled lun */
-#define AT_RESET 0x0E /* SCSI Bus Reset Occurred */
-#define AT_PHASE_ERROR 0x14 /* Bus phase sequence error */
-#define AT_NOCAP 0x16 /* Requested capability not available */
-#define AT_BDR_MSG 0x17 /* Bus Device Reset msg received */
-#define AT_CDB 0x3D /* CDB received */
-/*
- * Macros to create and fetch and test concatenated handle and tag value macros
- */
-
-#define AT_MAKE_TAGID(tid, bus, inst, aep) \
- tid = aep->at_handle; \
- if (aep->at_flags & AT_TQAE) { \
- tid |= (aep->at_tag_val << 16); \
- tid |= (1 << 24); \
- } \
- tid |= (bus << 25); \
- tid |= (inst << 26)
-
-#define CT_MAKE_TAGID(tid, bus, inst, ct) \
- tid = ct->ct_fwhandle; \
- if (ct->ct_flags & CT_TQAE) { \
- tid |= (ct->ct_tag_val << 16); \
- tid |= (1 << 24); \
- } \
- tid |= ((bus & 0x1) << 25); \
- tid |= (inst << 26)
-
-#define AT_HAS_TAG(val) ((val) & (1 << 24))
-#define AT_GET_TAG(val) (((val) >> 16) & 0xff)
-#define AT_GET_INST(val) (((val) >> 26) & 0x3f)
-#define AT_GET_BUS(val) (((val) >> 25) & 0x1)
-#define AT_GET_HANDLE(val) ((val) & 0xffff)
-
-#define IN_MAKE_TAGID(tid, bus, inst, inp) \
- tid = inp->in_seqid; \
- tid |= (inp->in_tag_val << 16); \
- tid |= (1 << 24); \
- tid |= (bus << 25); \
- tid |= (inst << 26)
-
-#define TAG_INSERT_INST(tid, inst) \
- tid &= ~(0x3ffffff); \
- tid |= (inst << 26)
-
-#define TAG_INSERT_BUS(tid, bus) \
- tid &= ~(1 << 25); \
- tid |= (bus << 25)
-
-/*
- * Accept Target I/O Entry structure, Type 2
- */
-#define ATIO2_CDBLEN 16
-
-typedef struct {
- isphdr_t at_header;
- uint32_t at_reserved;
- uint8_t at_lun; /* lun or reserved */
- uint8_t at_iid; /* initiator */
- uint16_t at_rxid; /* response ID */
- uint16_t at_flags;
- uint16_t at_status; /* firmware status */
- uint8_t at_crn; /* command reference number */
- uint8_t at_taskcodes;
- uint8_t at_taskflags;
- uint8_t at_execodes;
- uint8_t at_cdb[ATIO2_CDBLEN]; /* received CDB */
- uint32_t at_datalen; /* allocated data len */
- uint16_t at_scclun; /* SCC Lun or reserved */
- uint16_t at_wwpn[4]; /* WWPN of initiator */
- uint16_t at_reserved2[6];
- uint16_t at_oxid;
-} at2_entry_t;
-
-typedef struct {
- isphdr_t at_header;
- uint32_t at_reserved;
- uint16_t at_iid; /* initiator */
- uint16_t at_rxid; /* response ID */
- uint16_t at_flags;
- uint16_t at_status; /* firmware status */
- uint8_t at_crn; /* command reference number */
- uint8_t at_taskcodes;
- uint8_t at_taskflags;
- uint8_t at_execodes;
- uint8_t at_cdb[ATIO2_CDBLEN]; /* received CDB */
- uint32_t at_datalen; /* allocated data len */
- uint16_t at_scclun; /* SCC Lun or reserved */
- uint16_t at_wwpn[4]; /* WWPN of initiator */
- uint16_t at_reserved2[6];
- uint16_t at_oxid;
-} at2e_entry_t;
-
-#define ATIO2_WWPN_OFFSET 0x2A
-#define ATIO2_OXID_OFFSET 0x3E
-
-#define ATIO2_TC_ATTR_MASK 0x7
-#define ATIO2_TC_ATTR_SIMPLEQ 0
-#define ATIO2_TC_ATTR_HEADOFQ 1
-#define ATIO2_TC_ATTR_ORDERED 2
-#define ATIO2_TC_ATTR_ACAQ 4
-#define ATIO2_TC_ATTR_UNTAGGED 5
-
-#define ATIO2_EX_WRITE 0x1
-#define ATIO2_EX_READ 0x2
-/*
- * Macros to create and fetch and test concatenated handle and tag value macros
- */
-#define AT2_MAKE_TAGID(tid, bus, inst, aep) \
- tid = aep->at_rxid; \
- tid |= (((uint64_t)inst) << 32); \
- tid |= (((uint64_t)bus) << 48)
-
-#define CT2_MAKE_TAGID(tid, bus, inst, ct) \
- tid = ct->ct_rxid; \
- tid |= (((uint64_t)inst) << 32); \
- tid |= (((uint64_t)(bus & 0xff)) << 48)
-
-#define AT2_HAS_TAG(val) 1
-#define AT2_GET_TAG(val) ((val) & 0xffffffff)
-#define AT2_GET_INST(val) ((val) >> 32)
-#define AT2_GET_HANDLE AT2_GET_TAG
-#define AT2_GET_BUS(val) (((val) >> 48) & 0xff)
-
-#define FC_HAS_TAG AT2_HAS_TAG
-#define FC_GET_TAG AT2_GET_TAG
-#define FC_GET_INST AT2_GET_INST
-#define FC_GET_HANDLE AT2_GET_HANDLE
-
-#define IN_FC_MAKE_TAGID(tid, bus, inst, seqid) \
- tid = seqid; \
- tid |= (((uint64_t)inst) << 32); \
- tid |= (((uint64_t)(bus & 0xff)) << 48)
-
-#define FC_TAG_INSERT_INST(tid, inst) \
- tid &= ~0xffff00000000ull; \
- tid |= (((uint64_t)inst) << 32)
-
-/*
- * 24XX ATIO Definition
- *
- * This is *quite* different from other entry types.
- * First of all, it has its own queue it comes in on.
- *
- * Secondly, it doesn't have a normal header.
- *
- * Thirdly, it's just a passthru of the FCP CMND IU
- * which is recorded in big endian mode.
- */
-typedef struct {
- uint8_t at_type;
- uint8_t at_count;
- /*
- * Task attribute in high four bits,
- * the rest is the FCP CMND IU Length.
- * NB: the command can extend past the
- * length for a single queue entry.
- */
- uint16_t at_ta_len;
- uint32_t at_rxid;
- fc_hdr_t at_hdr;
- fcp_cmnd_iu_t at_cmnd;
-} at7_entry_t;
-
-
-/*
- * Continue Target I/O Entry structure
- * Request from driver. The response from the
- * ISP firmware is the same except that the last 18
- * bytes are overwritten by suggested sense data if
- * the 'autosense valid' bit is set in the status byte.
- */
-typedef struct {
- isphdr_t ct_header;
- uint16_t ct_syshandle;
- uint16_t ct_fwhandle; /* required by f/w */
- uint8_t ct_lun; /* lun */
- uint8_t ct_iid; /* initiator id */
- uint8_t ct_reserved2;
- uint8_t ct_tgt; /* our target id */
- uint32_t ct_flags;
- uint8_t ct_status; /* isp status */
- uint8_t ct_scsi_status; /* scsi status */
- uint8_t ct_tag_val; /* tag value */
- uint8_t ct_tag_type; /* tag type */
- uint32_t ct_xfrlen; /* transfer length */
- uint32_t ct_resid; /* residual length */
- uint16_t ct_timeout;
- uint16_t ct_seg_count;
- ispds_t ct_dataseg[ISP_RQDSEG];
-} ct_entry_t;
-
-/*
- * For some of the dual port SCSI adapters, port (bus #) is reported
- * in the MSbit of ct_iid. Bit fields are a bit too awkward here.
- *
- * Note that this does not apply to FC adapters at all which can and
- * do report IIDs between 0x81 && 0xfe (or 0x7ff) which represent devices
- * that have logged in across a SCSI fabric.
- */
-#define GET_IID_VAL(x) (x & 0x3f)
-#define GET_BUS_VAL(x) ((x >> 7) & 0x1)
-#define SET_IID_VAL(y, x) y = ((y & ~0x3f) | (x & 0x3f))
-#define SET_BUS_VAL(y, x) y = ((y & 0x3f) | ((x & 0x1) << 7))
-
-/*
- * ct_flags values
- */
-#define CT_TQAE 0x00000002 /* bit 1, Tagged Queue Action enable */
-#define CT_DATA_IN 0x00000040 /* bits 6&7, Data direction */
-#define CT_DATA_OUT 0x00000080 /* bits 6&7, Data direction */
-#define CT_NO_DATA 0x000000C0 /* bits 6&7, Data direction */
-#define CT_CCINCR 0x00000100 /* bit 8, autoincrement atio count */
-#define CT_DATAMASK 0x000000C0 /* bits 6&7, Data direction */
-#define CT_INISYNCWIDE 0x00004000 /* bit 14, Do Sync/Wide Negotiation */
-#define CT_NODISC 0x00008000 /* bit 15, Disconnects disabled */
-#define CT_DSDP 0x01000000 /* bit 24, Disable Save Data Pointers */
-#define CT_SENDRDP 0x04000000 /* bit 26, Send Restore Pointers msg */
-#define CT_SENDSTATUS 0x80000000 /* bit 31, Send SCSI status byte */
-
-/*
- * ct_status values
- * - set by the firmware when it returns the CTIO
- */
-#define CT_OK 0x01 /* completed without error */
-#define CT_ABORTED 0x02 /* aborted by host */
-#define CT_ERR 0x04 /* see sense data for error */
-#define CT_INVAL 0x06 /* request for disabled lun */
-#define CT_NOPATH 0x07 /* invalid ITL nexus */
-#define CT_INVRXID 0x08 /* (FC only) Invalid RX_ID */
-#define CT_DATA_OVER 0x09 /* (FC only) Data Overrun */
-#define CT_RSELTMO 0x0A /* reselection timeout after 2 tries */
-#define CT_TIMEOUT 0x0B /* timed out */
-#define CT_RESET 0x0E /* SCSI Bus Reset occurred */
-#define CT_PARITY 0x0F /* Uncorrectable Parity Error */
-#define CT_BUS_ERROR 0x10 /* (FC Only) DMA PCI Error */
-#define CT_PANIC 0x13 /* Unrecoverable Error */
-#define CT_PHASE_ERROR 0x14 /* Bus phase sequence error */
-#define CT_DATA_UNDER 0x15 /* (FC only) Data Underrun */
-#define CT_BDR_MSG 0x17 /* Bus Device Reset msg received */
-#define CT_TERMINATED 0x19 /* due to Terminate Transfer mbox cmd */
-#define CT_PORTUNAVAIL 0x28 /* port not available */
-#define CT_LOGOUT 0x29 /* port logout */
-#define CT_PORTCHANGED 0x2A /* port changed */
-#define CT_IDE 0x33 /* Initiator Detected Error */
-#define CT_NOACK 0x35 /* Outstanding Immed. Notify. entry */
-#define CT_SRR 0x45 /* SRR Received */
-#define CT_LUN_RESET 0x48 /* Lun Reset Received */
-
-/*
- * When the firmware returns a CTIO entry, it may overwrite the last
- * part of the structure with sense data. This starts at offset 0x2E
- * into the entry, which is in the middle of ct_dataseg[1]. Rather
- * than define a new struct for this, I'm just using the sense data
- * offset.
- */
-#define CTIO_SENSE_OFFSET 0x2E
-
-/*
- * Entry length in u_longs. All entries are the same size so
- * any one will do as the numerator.
- */
-#define UINT32_ENTRY_SIZE (sizeof(at_entry_t)/sizeof(uint32_t))
-
-/*
- * QLA2100 CTIO (type 2) entry
- */
-#define MAXRESPLEN 26
-typedef struct {
- isphdr_t ct_header;
- uint32_t ct_syshandle;
- uint8_t ct_lun; /* lun */
- uint8_t ct_iid; /* initiator id */
- uint16_t ct_rxid; /* response ID */
- uint16_t ct_flags;
- uint16_t ct_status; /* isp status */
- uint16_t ct_timeout;
- uint16_t ct_seg_count;
- uint32_t ct_reloff; /* relative offset */
- int32_t ct_resid; /* residual length */
- union {
- /*
- * The three different modes that the target driver
- * can set the CTIO{2,3,4} up as.
- *
- * The first is for sending FCP_DATA_IUs as well as
- * (optionally) sending a terminal SCSI status FCP_RSP_IU.
- *
- * The second is for sending SCSI sense data in an FCP_RSP_IU.
- * Note that no FCP_DATA_IUs will be sent.
- *
- * The third is for sending FCP_RSP_IUs as built specifically
- * in system memory as located by the isp_dataseg.
- */
- struct {
- uint32_t _reserved;
- uint16_t _reserved2;
- uint16_t ct_scsi_status;
- uint32_t ct_xfrlen;
- union {
- ispds_t ct_dataseg[ISP_RQDSEG_T2];
- ispds64_t ct_dataseg64[ISP_RQDSEG_T3];
- ispdslist_t ct_dslist;
- } u;
- } m0;
- struct {
- uint16_t _reserved;
- uint16_t _reserved2;
- uint16_t ct_senselen;
- uint16_t ct_scsi_status;
- uint16_t ct_resplen;
- uint8_t ct_resp[MAXRESPLEN];
- } m1;
- struct {
- uint32_t _reserved;
- uint16_t _reserved2;
- uint16_t _reserved3;
- uint32_t ct_datalen;
- ispds_t ct_fcp_rsp_iudata;
- } m2;
- } rsp;
-} ct2_entry_t;
-
-typedef struct {
- isphdr_t ct_header;
- uint32_t ct_syshandle;
- uint16_t ct_iid; /* initiator id */
- uint16_t ct_rxid; /* response ID */
- uint16_t ct_flags;
- uint16_t ct_status; /* isp status */
- uint16_t ct_timeout;
- uint16_t ct_seg_count;
- uint32_t ct_reloff; /* relative offset */
- int32_t ct_resid; /* residual length */
- union {
- struct {
- uint32_t _reserved;
- uint16_t _reserved2;
- uint16_t ct_scsi_status;
- uint32_t ct_xfrlen;
- union {
- ispds_t ct_dataseg[ISP_RQDSEG_T2];
- ispds64_t ct_dataseg64[ISP_RQDSEG_T3];
- ispdslist_t ct_dslist;
- } u;
- } m0;
- struct {
- uint16_t _reserved;
- uint16_t _reserved2;
- uint16_t ct_senselen;
- uint16_t ct_scsi_status;
- uint16_t ct_resplen;
- uint8_t ct_resp[MAXRESPLEN];
- } m1;
- struct {
- uint32_t _reserved;
- uint16_t _reserved2;
- uint16_t _reserved3;
- uint32_t ct_datalen;
- ispds_t ct_fcp_rsp_iudata;
- } m2;
- } rsp;
-} ct2e_entry_t;
-
-/*
- * ct_flags values for CTIO2
- */
-#define CT2_FLAG_MODE0 0x0000
-#define CT2_FLAG_MODE1 0x0001
-#define CT2_FLAG_MODE2 0x0002
-#define CT2_FLAG_MMASK 0x0003
-#define CT2_DATA_IN 0x0040
-#define CT2_DATA_OUT 0x0080
-#define CT2_NO_DATA 0x00C0
-#define CT2_DATAMASK 0x00C0
-#define CT2_CCINCR 0x0100
-#define CT2_FASTPOST 0x0200
-#define CT2_CONFIRM 0x2000
-#define CT2_TERMINATE 0x4000
-#define CT2_SENDSTATUS 0x8000
-
-/*
- * ct_status values are (mostly) the same as that for ct_entry.
- */
-
-/*
- * ct_scsi_status values- the low 8 bits are the normal SCSI status
- * we know and love. The upper 8 bits are validity markers for FCP_RSP_IU
- * fields.
- */
-#define CT2_RSPLEN_VALID 0x0100
-#define CT2_SNSLEN_VALID 0x0200
-#define CT2_DATA_OVER 0x0400
-#define CT2_DATA_UNDER 0x0800
-
-/*
- * ISP24XX CTIO
- */
-#define MAXRESPLEN_24XX 24
-typedef struct {
- isphdr_t ct_header;
- uint32_t ct_syshandle;
- uint16_t ct_nphdl; /* status on returned CTIOs */
- uint16_t ct_timeout;
- uint16_t ct_seg_count;
- uint8_t ct_vpindex;
- uint8_t ct_xflags;
- uint16_t ct_iid_lo; /* low 16 bits of portid */
- uint8_t ct_iid_hi; /* hi 8 bits of portid */
- uint8_t ct_reserved;
- uint32_t ct_rxid;
- uint16_t ct_senselen; /* mode 0 only */
- uint16_t ct_flags;
- int32_t ct_resid; /* residual length */
- uint16_t ct_oxid;
- uint16_t ct_scsi_status; /* modes 0 && 1 only */
- union {
- struct {
- uint32_t reloff;
- uint32_t reserved0;
- uint32_t ct_xfrlen;
- uint32_t reserved1;
- ispds64_t ds;
- } m0;
- struct {
- uint16_t ct_resplen;
- uint16_t reserved;
- uint8_t ct_resp[MAXRESPLEN_24XX];
- } m1;
- struct {
- uint32_t reserved0;
- uint32_t ct_datalen;
- uint32_t reserved1;
- ispds64_t ct_fcp_rsp_iudata;
- } m2;
- } rsp;
-} ct7_entry_t;
-
-/*
- * ct_flags values for CTIO7
- */
-#define CT7_DATA_IN 0x0002
-#define CT7_DATA_OUT 0x0001
-#define CT7_NO_DATA 0x0000
-#define CT7_DATAMASK 0x003
-#define CT7_DSD_ENABLE 0x0004
-#define CT7_CONF_STSFD 0x0010
-#define CT7_EXPLCT_CONF 0x0020
-#define CT7_FLAG_MODE0 0x0000
-#define CT7_FLAG_MODE1 0x0040
-#define CT7_FLAG_MODE7 0x0080
-#define CT7_FLAG_MMASK 0x00C0
-#define CT7_FASTPOST 0x0100
-#define CT7_ATTR_MASK 0x1e00 /* task attributes from atio7 */
-#define CT7_CONFIRM 0x2000
-#define CT7_TERMINATE 0x4000
-#define CT7_SENDSTATUS 0x8000
-
/*
- * Type 7 CTIO status codes
- */
-#define CT7_OK 0x01 /* completed without error */
-#define CT7_ABORTED 0x02 /* aborted by host */
-#define CT7_ERR 0x04 /* see sense data for error */
-#define CT7_INVAL 0x06 /* request for disabled lun */
-#define CT7_INVRXID 0x08 /* (FC only) Invalid RX_ID */
-#define CT7_DATA_OVER 0x09 /* (FC only) Data Overrun */
-#define CT7_TIMEOUT 0x0B /* timed out */
-#define CT7_RESET 0x0E /* LIP Rset Received */
-#define CT7_BUS_ERROR 0x10 /* DMA PCI Error */
-#define CT7_REASSY_ERR 0x11 /* DMA reassembly error */
-#define CT7_DATA_UNDER 0x15 /* (FC only) Data Underrun */
-#define CT7_PORTUNAVAIL 0x28 /* port not available */
-#define CT7_LOGOUT 0x29 /* port logout */
-#define CT7_PORTCHANGED 0x2A /* port changed */
-#define CT7_SRR 0x45 /* SRR Received */
-
-/*
- * Other 24XX related target IOCBs
- */
-
-/*
- * ABTS Received
- */
-typedef struct {
- isphdr_t abts_header;
- uint8_t abts_reserved0[6];
- uint16_t abts_nphdl;
- uint16_t abts_reserved1;
- uint16_t abts_sof;
- uint32_t abts_rxid_abts;
- uint16_t abts_did_lo;
- uint8_t abts_did_hi;
- uint8_t abts_r_ctl;
- uint16_t abts_sid_lo;
- uint8_t abts_sid_hi;
- uint8_t abts_cs_ctl;
- uint16_t abts_fs_ctl;
- uint8_t abts_f_ctl;
- uint8_t abts_type;
- uint16_t abts_seq_cnt;
- uint8_t abts_df_ctl;
- uint8_t abts_seq_id;
- uint16_t abts_rx_id;
- uint16_t abts_ox_id;
- uint32_t abts_param;
- uint8_t abts_reserved2[16];
- uint32_t abts_rxid_task;
-} abts_t;
-
-typedef struct {
- isphdr_t abts_rsp_header;
- uint32_t abts_rsp_handle;
- uint16_t abts_rsp_status;
- uint16_t abts_rsp_nphdl;
- uint16_t abts_rsp_ctl_flags;
- uint16_t abts_rsp_sof;
- uint32_t abts_rsp_rxid_abts;
- uint16_t abts_rsp_did_lo;
- uint8_t abts_rsp_did_hi;
- uint8_t abts_rsp_r_ctl;
- uint16_t abts_rsp_sid_lo;
- uint8_t abts_rsp_sid_hi;
- uint8_t abts_rsp_cs_ctl;
- uint16_t abts_rsp_f_ctl_lo;
- uint8_t abts_rsp_f_ctl_hi;
- uint8_t abts_rsp_type;
- uint16_t abts_rsp_seq_cnt;
- uint8_t abts_rsp_df_ctl;
- uint8_t abts_rsp_seq_id;
- uint16_t abts_rsp_rx_id;
- uint16_t abts_rsp_ox_id;
- uint32_t abts_rsp_param;
- union {
- struct {
- uint16_t reserved;
- uint8_t last_seq_id;
- uint8_t seq_id_valid;
- uint16_t aborted_rx_id;
- uint16_t aborted_ox_id;
- uint16_t high_seq_cnt;
- uint16_t low_seq_cnt;
- uint8_t reserved2[4];
- } ba_acc;
- struct {
- uint8_t vendor_unique;
- uint8_t explanation;
- uint8_t reason;
- uint8_t reserved;
- uint8_t reserved2[12];
- } ba_rjt;
- struct {
- uint8_t reserved[8];
- uint32_t subcode1;
- uint32_t subcode2;
- } rsp;
- uint8_t reserved[16];
- } abts_rsp_payload;
- uint32_t abts_rsp_rxid_task;
-} abts_rsp_t;
-
-/* terminate this ABTS exchange */
-#define ISP24XX_ABTS_RSP_TERMINATE 0x01
-
-#define ISP24XX_ABTS_RSP_COMPLETE 0x00
-#define ISP24XX_ABTS_RSP_RESET 0x04
-#define ISP24XX_ABTS_RSP_ABORTED 0x05
-#define ISP24XX_ABTS_RSP_TIMEOUT 0x06
-#define ISP24XX_ABTS_RSP_INVXID 0x08
-#define ISP24XX_ABTS_RSP_LOGOUT 0x29
-#define ISP24XX_ABTS_RSP_SUBCODE 0x31
-
+ * Notify structure- these are for asynchronous events that need to be sent
+ * as notifications to the outer layer. It should be pretty self-explanatory.
+ */
+typedef enum {
+ NT_UNKNOWN=0x999,
+ NT_ABORT_TASK=0x1000,
+ NT_ABORT_TASK_SET,
+ NT_CLEAR_ACA,
+ NT_CLEAR_TASK_SET,
+ NT_LUN_RESET,
+ NT_TARGET_RESET,
+ NT_BUS_RESET,
+ NT_LIP_RESET,
+ NT_LINK_UP,
+ NT_LINK_DOWN,
+ NT_LOGOUT,
+ NT_GLOBAL_LOGOUT,
+ NT_ARRIVED,
+ NT_DEPARTED,
+ NT_HBA_RESET
+} isp_ncode_t;
+
+typedef struct isp_notify {
+ void * nt_hba; /* HBA tag */
+ void * nt_tmd;
+ void * nt_lreserved;
+ void * nt_hreserved;
+ uint64_t nt_wwn; /* source (wwn) */
+ uint64_t nt_tgt; /* destination (wwn) */
+ uint64_t nt_tagval; /* tag value */
+ uint32_t
+ nt_sid : 24; /* source port id */
+ uint32_t
+ nt_failed : 1, /* notify operation failed */
+ nt_need_ack : 1, /* this notify needs an ACK */
+ nt_did : 24; /* destination port id */
+ uint32_t
+ nt_lun : 16, /* logical unit */
+ nt_nphdl : 16; /* n-port handle */
+ uint8_t nt_channel; /* channel id */
+ isp_ncode_t nt_ncode; /* action */
+} isp_notify_t;
+#define MATCH_TMD(tmd, iid, lun, tag) \
+ ( \
+ (tmd) && \
+ (iid == INI_ANY || iid == tmd->cd_iid) && \
+ (lun == LUN_ANY || lun == tmd->cd_lun) && \
+ (tag == TAG_ANY || tag == tmd->cd_tagval) \
+ )
/*
* Debug macros
*/
@@ -890,56 +89,12 @@ typedef struct {
#define ISP_TDQE(isp, msg, idx, arg) \
if (isp->isp_dblev & ISP_LOGTDEBUG2) isp_print_qentry(isp, msg, idx, arg)
-#ifndef ISP_TOOLS
-/*
- * The functions below are for the publicly available
- * target mode functions that are internal to the Qlogic driver.
- */
-
-/*
- * This function handles new response queue entry appropriate for target mode.
- */
-int isp_target_notify(ispsoftc_t *, void *, uint32_t *);
-
-/*
- * This function externalizes the ability to acknowledge an Immediate Notify
- * request.
- */
-void isp_notify_ack(ispsoftc_t *, void *);
-
-/*
- * Enable/Disable/Modify a logical unit.
- * (softc, cmd, bus, tgt, lun, cmd_cnt, inotify_cnt, opaque)
- */
-#define DFLT_CMND_CNT 0xfe /* unmonitored */
-#define DFLT_INOT_CNT 0xfe /* unmonitored */
-int isp_lun_cmd(ispsoftc_t *, int, int, int, int, int, int, uint32_t);
-
-/*
- * General request queue 'put' routine for target mode entries.
- */
-int isp_target_put_entry(ispsoftc_t *isp, void *);
-
-/*
- * General routine to put back an ATIO entry-
- * used for replenishing f/w resource counts.
- * The argument is a pointer to a source ATIO
- * or ATIO2.
- */
-int isp_target_put_atio(ispsoftc_t *, void *);
-
-/*
- * General routine to send a final CTIO for a command- used mostly for
- * local responses.
- */
-int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint32_t);
-#define ECMD_SVALID 0x100
-
/*
- * Handle an asynchronous event
- *
- * Return nonzero if the interrupt that generated this event has been dismissed.
+ * Special Constatns
*/
-int isp_target_async(ispsoftc_t *, int, int);
-#endif
+#define INI_ANY ((uint64_t) -1)
+#define VALID_INI(ini) (ini != INI_NONE && ini != INI_ANY)
+#define LUN_ANY 0xffff
+#define TGT_ANY ((uint64_t) -1)
+#define TAG_ANY ((uint64_t) 0)
#endif /* _ISP_TARGET_H */
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index 272d74e..8f68937 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -1,6 +1,6 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 1997-2007 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,6 +24,7 @@
* 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.
+ *
*/
/*
* Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters.
@@ -121,11 +122,20 @@
/* These are for the ISP2X00 FC cards */
#define MBOX_GET_LOOP_ID 0x0020
+/* for 24XX cards, outgoing mailbox 7 has these values for F or FL topologies */
+#define ISP24XX_INORDER 0x0100
+#define ISP24XX_NPIV_SAN 0x0400
+#define ISP24XX_VSAN_SAN 0x1000
+#define ISP24XX_FC_SP_SAN 0x2000
+
#define MBOX_GET_FIRMWARE_OPTIONS 0x0028
#define MBOX_SET_FIRMWARE_OPTIONS 0x0038
#define MBOX_GET_RESOURCE_COUNT 0x0042
#define MBOX_REQUEST_OFFLINE_MODE 0x0043
#define MBOX_ENHANCED_GET_PDB 0x0047
+#define MBOX_INIT_FIRMWARE_MULTI_ID 0x0048 /* 2400 only */
+#define MBOX_GET_VP_DATABASE 0x0049 /* 2400 only */
+#define MBOX_GET_VP_DATABASE_ENTRY 0x004a /* 2400 only */
#define MBOX_EXEC_COMMAND_IOCB_A64 0x0054
#define MBOX_INIT_FIRMWARE 0x0060
#define MBOX_GET_INIT_CONTROL_BLOCK 0x0061
@@ -158,6 +168,7 @@
#define MBGSD_TWOGB 1
#define MBGSD_AUTO 2
#define MBGSD_FOURGB 3 /* 24XX only */
+#define MBGSD_EIGHTGB 4 /* 25XX only */
#define ISP2100_SET_PCI_PARAM 0x00ff
@@ -250,6 +261,11 @@
#define QENTRY_LEN 64
/*
+ * Special Internal Handle for IOCBs
+ */
+#define ISP_SPCL_HANDLE 0xa5dead5a
+
+/*
* Command Structure Definitions
*/
@@ -273,15 +289,6 @@ typedef struct {
} ispdslist_t;
-/*
- * These elements get swizzled around for SBus instances.
- */
-#define ISP_SWAP8(a, b) { \
- uint8_t tmp; \
- tmp = a; \
- a = b; \
- b = tmp; \
-}
typedef struct {
uint8_t rqs_entry_type;
uint8_t rqs_entry_count;
@@ -294,7 +301,9 @@ typedef struct {
#define RQSFLAG_FULL 0x02
#define RQSFLAG_BADHEADER 0x04
#define RQSFLAG_BADPACKET 0x08
-#define RQSFLAG_MASK 0x0f
+#define RQSFLAG_BADCOUNT 0x10
+#define RQSFLAG_BADORDER 0x20
+#define RQSFLAG_MASK 0x3f
/* RQS entry_type definitions */
#define RQSTYPE_REQUEST 0x01
@@ -331,6 +340,9 @@ typedef struct {
#define RQSTYPE_IP_RECV_CONT 0x24
#define RQSTYPE_CT_PASSTHRU 0x29
#define RQSTYPE_MS_PASSTHRU 0x29
+#define RQSTYPE_VP_CTRL 0x30 /* 24XX only */
+#define RQSTYPE_VP_MODIFY 0x31 /* 24XX only */
+#define RQSTYPE_RPT_ID_ACQ 0x32 /* 24XX only */
#define RQSTYPE_ABORT_IO 0x33
#define RQSTYPE_T6RQS 0x48
#define RQSTYPE_LOGIN 0x52
@@ -533,6 +545,31 @@ typedef struct {
ispds64_t req_dataseg;
} ispreqt7_t;
+/* Task Management Request Function */
+typedef struct {
+ isphdr_t tmf_header;
+ uint32_t tmf_handle;
+ uint16_t tmf_nphdl;
+ uint8_t tmf_reserved0[2];
+ uint16_t tmf_delay;
+ uint16_t tmf_timeout;
+ uint8_t tmf_lun[8];
+ uint32_t tmf_flags;
+ uint8_t tmf_reserved1[20];
+ uint16_t tmf_tidlo;
+ uint8_t tmf_tidhi;
+ uint8_t tmf_vpidx;
+ uint8_t tmf_reserved2[12];
+} isp24xx_tmf_t;
+
+#define ISP24XX_TMF_NOSEND 0x80000000
+
+#define ISP24XX_TMF_LUN_RESET 0x00000010
+#define ISP24XX_TMF_ABORT_TASK_SET 0x00000008
+#define ISP24XX_TMF_CLEAR_TASK_SET 0x00000004
+#define ISP24XX_TMF_TARGET_RESET 0x00000002
+#define ISP24XX_TMF_CLEAR_ACA 0x00000001
+
/* I/O Abort Structure */
typedef struct {
isphdr_t abrt_header;
@@ -546,7 +583,9 @@ typedef struct {
uint8_t abrt_vpidx;
uint8_t abrt_reserved1[12];
} isp24xx_abrt_t;
-#define ISP24XX_ABRT_NO_ABTS 0x01 /* don't actually send an ABTS */
+
+#define ISP24XX_ABRT_NOSEND 0x01 /* don't actually send ABTS */
+#define ISP24XX_ABRT_OKAY 0x00 /* in nphdl on return */
#define ISP24XX_ABRT_ENXIO 0x31 /* in nphdl on return */
#define ISP_CDSEG 7
@@ -623,11 +662,12 @@ typedef struct {
uint16_t ctp_status;
uint16_t ctp_nphdl; /* n-port handle */
uint16_t ctp_cmd_cnt; /* Command DSD count */
- uint16_t ctp_vpidx; /* low 8 bits */
+ uint8_t ctp_vpidx;
+ uint8_t ctp_reserved0;
uint16_t ctp_time;
- uint16_t ctp_reserved0;
+ uint16_t ctp_reserved1;
uint16_t ctp_rsp_cnt; /* Response DSD count */
- uint16_t ctp_reserved1[5];
+ uint16_t ctp_reserved2[5];
uint32_t ctp_rsp_bcnt; /* Response byte count */
uint32_t ctp_cmd_bcnt; /* Command byte count */
ispds64_t ctp_dataseg[2];
@@ -766,24 +806,36 @@ typedef struct {
* About Firmware returns an 'attribute' word in mailbox 6.
* These attributes are for 2200 and 2300.
*/
-#define ISP_FW_ATTR_TMODE 0x01
-#define ISP_FW_ATTR_SCCLUN 0x02
-#define ISP_FW_ATTR_FABRIC 0x04
-#define ISP_FW_ATTR_CLASS2 0x08
-#define ISP_FW_ATTR_FCTAPE 0x10
-#define ISP_FW_ATTR_IP 0x20
-#define ISP_FW_ATTR_VI 0x40
-#define ISP_FW_ATTR_VI_SOLARIS 0x80
-#define ISP_FW_ATTR_2KLOGINS 0x100 /* XXX: just a guess */
+#define ISP_FW_ATTR_TMODE 0x0001
+#define ISP_FW_ATTR_SCCLUN 0x0002
+#define ISP_FW_ATTR_FABRIC 0x0004
+#define ISP_FW_ATTR_CLASS2 0x0008
+#define ISP_FW_ATTR_FCTAPE 0x0010
+#define ISP_FW_ATTR_IP 0x0020
+#define ISP_FW_ATTR_VI 0x0040
+#define ISP_FW_ATTR_VI_SOLARIS 0x0080
+#define ISP_FW_ATTR_2KLOGINS 0x0100 /* just a guess... */
/* and these are for the 2400 */
-#define ISP2400_FW_ATTR_CLASS2 (1 << 0)
-#define ISP2400_FW_ATTR_IP (1 << 1)
-#define ISP2400_FW_ATTR_MULTIID (1 << 2)
-#define ISP2400_FW_ATTR_SB2 (1 << 3)
-#define ISP2400_FW_ATTR_T10CRC (1 << 4)
-#define ISP2400_FW_ATTR_VI (1 << 5)
-#define ISP2400_FW_ATTR_EXPFW (1 << 13)
+#define ISP2400_FW_ATTR_CLASS2 0x0001
+#define ISP2400_FW_ATTR_IP 0x0002
+#define ISP2400_FW_ATTR_MULTIID 0x0004
+#define ISP2400_FW_ATTR_SB2 0x0008
+#define ISP2400_FW_ATTR_T10CRC 0x0010
+#define ISP2400_FW_ATTR_VI 0x0020
+#define ISP2400_FW_ATTR_EXPFW 0x2000
+
+#define ISP_CAP_TMODE(isp) \
+ (IS_24XX(isp)? 1 : (isp->isp_fwattr & ISP_FW_ATTR_TMODE))
+#define ISP_CAP_SCCFW(isp) \
+ (IS_24XX(isp)? 1 : (isp->isp_fwattr & ISP_FW_ATTR_SCCLUN))
+#define ISP_CAP_2KLOGIN(isp) \
+ (IS_24XX(isp)? 1 : (isp->isp_fwattr & ISP_FW_ATTR_2KLOGINS))
+#define ISP_CAP_MULTI_ID(isp) \
+ (IS_24XX(isp)? (isp->isp_fwattr & ISP2400_FW_ATTR_MULTIID) : 0)
+
+#define ISP_GET_VPIDX(isp, tag) \
+ (ISP_CAP_MULTI_ID(isp) ? tag : 0)
/*
* Reduced Interrupt Operation Response Queue Entreis
@@ -928,6 +980,7 @@ typedef struct {
#define ICB2400_OPT3_RATE_TWOGB 0x00002000
#define ICB2400_OPT3_RATE_AUTO 0x00004000
#define ICB2400_OPT3_RATE_FOURGB 0x00006000
+#define ICB2400_OPT3_RATE_EIGHTGB 0x00008000
#define ICB2400_OPT3_ENA_OOF_XFRDY 0x00000200
#define ICB2400_OPT3_NO_LOCAL_PLOGI 0x00000080
#define ICB2400_OPT3_ENA_OOF 0x00000040
@@ -1021,6 +1074,95 @@ typedef struct {
((uint64_t) array[ICB_NNM6] << 48) | \
((uint64_t) array[ICB_NNM7] << 56)
+
+/*
+ * For MULTI_ID firmware, this describes a
+ * virtual port entity for getting status.
+ */
+typedef struct {
+ uint16_t vp_port_status;
+ uint8_t vp_port_options;
+ uint8_t vp_port_loopid;
+ uint8_t vp_port_portname[8];
+ uint8_t vp_port_nodename[8];
+ uint16_t vp_port_portid_lo; /* not present when trailing icb */
+ uint16_t vp_port_portid_hi; /* not present when trailing icb */
+} vp_port_info_t;
+
+#define ICB2400_VPOPT_TGT_DISABLE 0x00000020 /* disable target mode */
+#define ICB2400_VPOPT_INI_ENABLE 0x00000010 /* enable initiator mode */
+#define ICB2400_VPOPT_ENABLED 0x00000008
+#define ICB2400_VPOPT_NOPLAY 0x00000004
+#define ICB2400_VPOPT_PREVLOOP 0x00000002
+#define ICB2400_VPOPT_HARD_ADDRESS 0x00000001
+
+#define ICB2400_VPOPT_WRITE_SIZE 20
+
+/*
+ * For MULTI_ID firmware, we append this structure
+ * to the isp_icb_2400_t above, followed by a list
+ * structures that are *most* of the vp_port_info_t.
+ */
+typedef struct {
+ uint16_t vp_count;
+ uint16_t vp_global_options;
+} isp_icb_2400_vpinfo_t;
+
+#define ICB2400_VPINFO_OFF 0x80 /* offset from start of ICB */
+#define ICB2400_VPINFO_PORT_OFF(chan) \
+ ICB2400_VPINFO_OFF + \
+ sizeof (isp_icb_2400_vpinfo_t) + ((chan - 1) * ICB2400_VPOPT_WRITE_SIZE)
+
+#define ICB2400_VPGOPT_MID_DISABLE 0x02
+
+typedef struct {
+ isphdr_t vp_ctrl_hdr;
+ uint32_t vp_ctrl_handle;
+ uint16_t vp_ctrl_index_fail;
+ uint16_t vp_ctrl_status;
+ uint16_t vp_ctrl_command;
+ uint16_t vp_ctrl_vp_count;
+ uint16_t vp_ctrl_idmap[8];
+ uint8_t vp_ctrl_reserved[32];
+} vp_ctrl_info_t;
+
+#define VP_CTRL_CMD_ENABLE_VP 0
+#define VP_CTRL_CMD_DISABLE_VP 8
+#define VP_CTRL_CMD_DISABLE_VP_REINIT_LINK 9
+#define VP_CTRL_CMD_DISABLE_VP_LOGO 0xA
+
+/*
+ * We can use this structure for modifying either one or two VP ports after initialization
+ */
+typedef struct {
+ isphdr_t vp_mod_hdr;
+ uint32_t vp_mod_hdl;
+ uint16_t vp_mod_reserved0;
+ uint16_t vp_mod_status;
+ uint8_t vp_mod_cmd;
+ uint8_t vp_mod_cnt;
+ uint8_t vp_mod_idx0;
+ uint8_t vp_mod_idx1;
+ struct {
+ uint8_t options;
+ uint8_t loopid;
+ uint16_t reserved1;
+ uint8_t wwpn[8];
+ uint8_t wwnn[8];
+ } vp_mod_ports[2];
+ uint8_t vp_mod_reserved2[8];
+} vp_modify_t;
+
+#define VP_STS_OK 0x00
+#define VP_STS_ERR 0x01
+#define VP_CNT_ERR 0x02
+#define VP_GEN_ERR 0x03
+#define VP_IDX_ERR 0x04
+#define VP_STS_BSY 0x05
+
+#define VP_MODIFY_VP 0x00
+#define VP_MODIFY_ENA 0x01
+
/*
* Port Data Base Element
*/
@@ -1120,6 +1262,14 @@ typedef struct {
#define PDB2400_CLASS2 0x0010
#define PDB2400_ADDR_VALID 0x0002
+#define PDB2400_STATE_PLOGI_PEND 0x03
+#define PDB2400_STATE_PLOGI_DONE 0x04
+#define PDB2400_STATE_PRLI_PEND 0x05
+#define PDB2400_STATE_LOGGED_IN 0x06
+#define PDB2400_STATE_PORT_UNAVAIL 0x07
+#define PDB2400_STATE_PRLO_PEND 0x09
+#define PDB2400_STATE_LOGO_PEND 0x0B
+
/*
* Common elements from the above two structures that are actually useful to us.
*/
@@ -1133,10 +1283,40 @@ typedef struct {
} isp_pdb_t;
/*
+ * Port Database Changed Async Event information for 24XX cards
+ */
+#define PDB24XX_AE_OK 0x00
+#define PDB24XX_AE_IMPL_LOGO_1 0x01
+#define PDB24XX_AE_IMPL_LOGO_2 0x02
+#define PDB24XX_AE_IMPL_LOGO_3 0x03
+#define PDB24XX_AE_PLOGI_RCVD 0x04
+#define PDB24XX_AE_PLOGI_RJT 0x05
+#define PDB24XX_AE_PRLI_RCVD 0x06
+#define PDB24XX_AE_PRLI_RJT 0x07
+#define PDB24XX_AE_TPRLO 0x08
+#define PDB24XX_AE_TPRLO_RJT 0x09
+#define PDB24XX_AE_PRLO_RCVD 0x0a
+#define PDB24XX_AE_LOGO_RCVD 0x0b
+#define PDB24XX_AE_TOPO_CHG 0x0c
+#define PDB24XX_AE_NPORT_CHG 0x0d
+#define PDB24XX_AE_FLOGI_RJT 0x0e
+#define PDB24XX_AE_BAD_FANN 0x0f
+#define PDB24XX_AE_FLOGI_TIMO 0x10
+#define PDB24XX_AE_ABX_LOGO 0x11
+#define PDB24XX_AE_PLOGI_DONE 0x12
+#define PDB24XX_AE_PRLI_DONJE 0x13
+#define PDB24XX_AE_OPN_1 0x14
+#define PDB24XX_AE_OPN_2 0x15
+#define PDB24XX_AE_TXERR 0x16
+#define PDB24XX_AE_FORCED_LOGO 0x17
+#define PDB24XX_AE_DISC_TIMO 0x18
+
+/*
* Genericized Port Login/Logout software structure
*/
typedef struct {
uint16_t handle;
+ uint16_t channel;
uint32_t
flags : 8,
portid : 24;
@@ -1201,6 +1381,36 @@ typedef struct {
#define PLOGX_FLG_FCP2_OVERRIDE 0x200 /* if with PRLOG, PRLI */
/*
+ * Report ID Acquisistion (24XX multi-id firmware)
+ */
+typedef struct {
+ isphdr_t ridacq_hdr;
+ uint32_t ridacq_handle;
+ union {
+ struct {
+ uint8_t ridacq_vp_acquired;
+ uint8_t ridacq_vp_setup;
+ uint16_t ridacq_reserved0;
+ } type0; /* type 0 */
+ struct {
+ uint16_t ridacq_vp_count;
+ uint8_t ridacq_vp_index;
+ uint8_t ridacq_vp_status;
+ } type1; /* type 1 */
+ } un;
+ uint16_t ridacq_vp_port_lo;
+ uint8_t ridacq_vp_port_hi;
+ uint8_t ridacq_format; /* 0 or 1 */
+ uint16_t ridacq_map[8];
+ uint8_t ridacq_reserved1[32];
+} isp_ridacq_t;
+
+#define RIDACQ_STS_COMPLETE 0
+#define RIDACQ_STS_UNACQUIRED 1
+#define RIDACQ_STS_CHANGED 20
+
+
+/*
* Simple Name Server Data Structures
*/
#define SNS_GA_NXT 0x100
@@ -1385,18 +1595,21 @@ typedef struct {
} els_t;
/*
- * A handy package structure for running FC-SCSI commands via RUN IOCB A64.
+ * A handy package structure for running FC-SCSI commands internally
*/
typedef struct {
uint16_t handle;
uint16_t lun;
- uint32_t portid;
+ uint32_t
+ channel : 8,
+ portid : 24;
uint32_t timeout;
union {
struct {
uint32_t data_length;
- uint8_t do_read;
- uint8_t pad[3];
+ uint32_t
+ no_wait : 1,
+ do_read : 1;
uint8_t cdb[16];
void *data_ptr;
} beg;
@@ -1409,4 +1622,923 @@ typedef struct {
} end;
} fcd;
} isp_xcmd_t;
+
+/*
+ * Target Mode related definitions
+ */
+#define QLTM_SENSELEN 18 /* non-FC cards only */
+#define QLTM_SVALID 0x80
+
+/*
+ * Structure for Enable Lun and Modify Lun queue entries
+ */
+typedef struct {
+ isphdr_t le_header;
+ uint32_t le_reserved;
+ uint8_t le_lun;
+ uint8_t le_rsvd;
+ uint8_t le_ops; /* Modify LUN only */
+ uint8_t le_tgt; /* Not for FC */
+ uint32_t le_flags; /* Not for FC */
+ uint8_t le_status;
+ uint8_t le_reserved2;
+ uint8_t le_cmd_count;
+ uint8_t le_in_count;
+ uint8_t le_cdb6len; /* Not for FC */
+ uint8_t le_cdb7len; /* Not for FC */
+ uint16_t le_timeout;
+ uint16_t le_reserved3[20];
+} lun_entry_t;
+
+/*
+ * le_flags values
+ */
+#define LUN_TQAE 0x00000002 /* bit1 Tagged Queue Action Enable */
+#define LUN_DSSM 0x01000000 /* bit24 Disable Sending SDP Message */
+#define LUN_DISAD 0x02000000 /* bit25 Disable autodisconnect */
+#define LUN_DM 0x40000000 /* bit30 Disconnects Mandatory */
+
+/*
+ * le_ops values
+ */
+#define LUN_CCINCR 0x01 /* increment command count */
+#define LUN_CCDECR 0x02 /* decrement command count */
+#define LUN_ININCR 0x40 /* increment immed. notify count */
+#define LUN_INDECR 0x80 /* decrement immed. notify count */
+
+/*
+ * le_status values
+ */
+#define LUN_OK 0x01 /* we be rockin' */
+#define LUN_ERR 0x04 /* request completed with error */
+#define LUN_INVAL 0x06 /* invalid request */
+#define LUN_NOCAP 0x16 /* can't provide requested capability */
+#define LUN_ENABLED 0x3E /* LUN already enabled */
+
+/*
+ * Immediate Notify Entry structure
+ */
+#define IN_MSGLEN 8 /* 8 bytes */
+#define IN_RSVDLEN 8 /* 8 words */
+typedef struct {
+ isphdr_t in_header;
+ uint32_t in_reserved;
+ uint8_t in_lun; /* lun */
+ uint8_t in_iid; /* initiator */
+ uint8_t in_reserved2;
+ uint8_t in_tgt; /* target */
+ uint32_t in_flags;
+ uint8_t in_status;
+ uint8_t in_rsvd2;
+ uint8_t in_tag_val; /* tag value */
+ uint8_t in_tag_type; /* tag type */
+ uint16_t in_seqid; /* sequence id */
+ uint8_t in_msg[IN_MSGLEN]; /* SCSI message bytes */
+ uint16_t in_reserved3[IN_RSVDLEN];
+ uint8_t in_sense[QLTM_SENSELEN];/* suggested sense data */
+} in_entry_t;
+
+typedef struct {
+ isphdr_t in_header;
+ uint32_t in_reserved;
+ uint8_t in_lun; /* lun */
+ uint8_t in_iid; /* initiator */
+ uint16_t in_scclun;
+ uint32_t in_reserved2;
+ uint16_t in_status;
+ uint16_t in_task_flags;
+ uint16_t in_seqid; /* sequence id */
+} in_fcentry_t;
+
+typedef struct {
+ isphdr_t in_header;
+ uint32_t in_reserved;
+ uint16_t in_iid; /* initiator */
+ uint16_t in_scclun;
+ uint32_t in_reserved2;
+ uint16_t in_status;
+ uint16_t in_task_flags;
+ uint16_t in_seqid; /* sequence id */
+} in_fcentry_e_t;
+
+/*
+ * Values for the in_status field
+ */
+#define IN_REJECT 0x0D /* Message Reject message received */
+#define IN_RESET 0x0E /* Bus Reset occurred */
+#define IN_NO_RCAP 0x16 /* requested capability not available */
+#define IN_IDE_RECEIVED 0x33 /* Initiator Detected Error msg received */
+#define IN_RSRC_UNAVAIL 0x34 /* resource unavailable */
+#define IN_MSG_RECEIVED 0x36 /* SCSI message received */
+#define IN_ABORT_TASK 0x20 /* task named in RX_ID is being aborted (FC) */
+#define IN_PORT_LOGOUT 0x29 /* port has logged out (FC) */
+#define IN_PORT_CHANGED 0x2A /* port changed */
+#define IN_GLOBAL_LOGO 0x2E /* all ports logged out */
+#define IN_NO_NEXUS 0x3B /* Nexus not established */
+
+/*
+ * Values for the in_task_flags field- should only get one at a time!
+ */
+#define TASK_FLAGS_RESERVED_MASK (0xe700)
+#define TASK_FLAGS_CLEAR_ACA (1<<14)
+#define TASK_FLAGS_TARGET_RESET (1<<13)
+#define TASK_FLAGS_LUN_RESET (1<<12)
+#define TASK_FLAGS_CLEAR_TASK_SET (1<<10)
+#define TASK_FLAGS_ABORT_TASK_SET (1<<9)
+
+/*
+ * ISP24XX Immediate Notify
+ */
+typedef struct {
+ isphdr_t in_header;
+ uint32_t in_reserved;
+ uint16_t in_nphdl;
+ uint16_t in_reserved1;
+ uint16_t in_flags;
+ uint16_t in_srr_rxid;
+ uint16_t in_status;
+ uint8_t in_status_subcode;
+ uint8_t in_reserved2;
+ uint32_t in_rxid;
+ uint16_t in_srr_reloff_lo;
+ uint16_t in_srr_reloff_hi;
+ uint16_t in_srr_iu;
+ uint16_t in_srr_oxid;
+ /*
+ * If bit 2 is set in in_flags, the following
+ * two tags are valid. If the received ELS is
+ * a LOGO, then these tags contain the N Port ID
+ * from the LOGO payload. If the received ELS
+ * request is TPRLO, these tags contain the
+ * Third Party Originator N Port ID.
+ */
+ uint16_t in_nport_id_hi;
+ uint8_t in_nport_id_lo;
+ uint8_t in_reserved3;
+ /*
+ * If bit 2 is set in in_flags, the following
+ * tag is valid. If the received ELS is a LOGO,
+ * then this tag contains the n-port handle
+ * from the LOGO payload. If the received ELS
+ * request is TPRLO, this tag contain the
+ * n-port handle for the Third Party Originator.
+ */
+ uint16_t in_np_handle;
+ uint8_t in_reserved4[12];
+ uint8_t in_reserved5;
+ uint8_t in_vpidx;
+ uint32_t in_reserved6;
+ uint16_t in_portid_lo;
+ uint8_t in_portid_hi;
+ uint8_t in_reserved7;
+ uint16_t in_reserved8;
+ uint16_t in_oxid;
+} in_fcentry_24xx_t;
+
+#define IN24XX_FLAG_PUREX_IOCB 0x1
+#define IN24XX_FLAG_GLOBAL_LOGOUT 0x2
+#define IN24XX_FLAG_NPHDL_VALID 0x4
+
+#define IN24XX_LIP_RESET 0x0E
+#define IN24XX_LINK_RESET 0x0F
+#define IN24XX_PORT_LOGOUT 0x29
+#define IN24XX_PORT_CHANGED 0x2A
+#define IN24XX_LINK_FAILED 0x2E
+#define IN24XX_SRR_RCVD 0x45
+#define IN24XX_ELS_RCVD 0x46 /*
+ * login-affectin ELS received- check
+ * subcode for specific opcode
+ */
+
+/*
+ * For f/w > 4.0.25, these offsets in the Immediate Notify contain
+ * the WWNN/WWPN if the ELS is PLOGI, PDISC or ADISC. The WWN is in
+ * Big Endian format.
+ */
+#define IN24XX_PLOGI_WWNN_OFF 0x20
+#define IN24XX_PLOGI_WWPN_OFF 0x28
+
+/*
+ * For f/w > 4.0.25, this offset in the Immediate Notify contain
+ * the WWPN if the ELS is LOGO. The WWN is in Big Endian format.
+ */
+#define IN24XX_LOGO_WWPN_OFF 0x28
+
+/*
+ * Immediate Notify Status Subcodes for IN24XX_PORT_LOGOUT
+ */
+#define IN24XX_PORT_LOGOUT_PDISC_TMO 0x00
+#define IN24XX_PORT_LOGOUT_UXPR_DISC 0x01
+#define IN24XX_PORT_LOGOUT_OWN_OPN 0x02
+#define IN24XX_PORT_LOGOUT_OWN_OPN_SFT 0x03
+#define IN24XX_PORT_LOGOUT_ABTS_TMO 0x04
+#define IN24XX_PORT_LOGOUT_DISC_RJT 0x05
+#define IN24XX_PORT_LOGOUT_LOGIN_NEEDED 0x06
+#define IN24XX_PORT_LOGOUT_BAD_DISC 0x07
+#define IN24XX_PORT_LOGOUT_LOST_ALPA 0x08
+#define IN24XX_PORT_LOGOUT_XMIT_FAILURE 0x09
+
+/*
+ * Immediate Notify Status Subcodes for IN24XX_PORT_CHANGED
+ */
+#define IN24XX_PORT_CHANGED_BADFAN 0x00
+#define IN24XX_PORT_CHANGED_TOPO_CHANGE 0x01
+#define IN24XX_PORT_CHANGED_FLOGI_ACC 0x02
+#define IN24XX_PORT_CHANGED_FLOGI_RJT 0x03
+#define IN24XX_PORT_CHANGED_TIMEOUT 0x04
+#define IN24XX_PORT_CHANGED_PORT_CHANGE 0x05
+
+/*
+ * Notify Acknowledge Entry structure
+ */
+#define NA_RSVDLEN 22
+typedef struct {
+ isphdr_t na_header;
+ uint32_t na_reserved;
+ uint8_t na_lun; /* lun */
+ uint8_t na_iid; /* initiator */
+ uint8_t na_reserved2;
+ uint8_t na_tgt; /* target */
+ uint32_t na_flags;
+ uint8_t na_status;
+ uint8_t na_event;
+ uint16_t na_seqid; /* sequence id */
+ uint16_t na_reserved3[NA_RSVDLEN];
+} na_entry_t;
+
+/*
+ * Value for the na_event field
+ */
+#define NA_RST_CLRD 0x80 /* Clear an async event notification */
+#define NA_OK 0x01 /* Notify Acknowledge Succeeded */
+#define NA_INVALID 0x06 /* Invalid Notify Acknowledge */
+
+#define NA2_RSVDLEN 21
+typedef struct {
+ isphdr_t na_header;
+ uint32_t na_reserved;
+ uint8_t na_reserved1;
+ uint8_t na_iid; /* initiator loop id */
+ uint16_t na_response;
+ uint16_t na_flags;
+ uint16_t na_reserved2;
+ uint16_t na_status;
+ uint16_t na_task_flags;
+ uint16_t na_seqid; /* sequence id */
+ uint16_t na_reserved3[NA2_RSVDLEN];
+} na_fcentry_t;
+
+typedef struct {
+ isphdr_t na_header;
+ uint32_t na_reserved;
+ uint16_t na_iid; /* initiator loop id */
+ uint16_t na_response; /* response code */
+ uint16_t na_flags;
+ uint16_t na_reserved2;
+ uint16_t na_status;
+ uint16_t na_task_flags;
+ uint16_t na_seqid; /* sequence id */
+ uint16_t na_reserved3[NA2_RSVDLEN];
+} na_fcentry_e_t;
+
+#define NAFC_RCOUNT 0x80 /* increment resource count */
+#define NAFC_RST_CLRD 0x20 /* Clear LIP Reset */
+#define NAFC_TVALID 0x10 /* task mangement response code is valid */
+
+/*
+ * ISP24XX Notify Acknowledge
+ */
+
+typedef struct {
+ isphdr_t na_header;
+ uint32_t na_handle;
+ uint16_t na_nphdl;
+ uint16_t na_reserved1;
+ uint16_t na_flags;
+ uint16_t na_srr_rxid;
+ uint16_t na_status;
+ uint8_t na_status_subcode;
+ uint8_t na_reserved2;
+ uint32_t na_rxid;
+ uint16_t na_srr_reloff_lo;
+ uint16_t na_srr_reloff_hi;
+ uint16_t na_srr_iu;
+ uint16_t na_srr_flags;
+ uint8_t na_reserved3[18];
+ uint8_t na_reserved4;
+ uint8_t na_vpidx;
+ uint8_t na_srr_reject_vunique;
+ uint8_t na_srr_reject_explanation;
+ uint8_t na_srr_reject_code;
+ uint8_t na_reserved5;
+ uint8_t na_reserved6[6];
+ uint16_t na_oxid;
+} na_fcentry_24xx_t;
+
+/*
+ * Accept Target I/O Entry structure
+ */
+#define ATIO_CDBLEN 26
+
+typedef struct {
+ isphdr_t at_header;
+ uint16_t at_reserved;
+ uint16_t at_handle;
+ uint8_t at_lun; /* lun */
+ uint8_t at_iid; /* initiator */
+ uint8_t at_cdblen; /* cdb length */
+ uint8_t at_tgt; /* target */
+ uint32_t at_flags;
+ uint8_t at_status; /* firmware status */
+ uint8_t at_scsi_status; /* scsi status */
+ uint8_t at_tag_val; /* tag value */
+ uint8_t at_tag_type; /* tag type */
+ uint8_t at_cdb[ATIO_CDBLEN]; /* received CDB */
+ uint8_t at_sense[QLTM_SENSELEN];/* suggested sense data */
+} at_entry_t;
+
+/*
+ * at_flags values
+ */
+#define AT_NODISC 0x00008000 /* disconnect disabled */
+#define AT_TQAE 0x00000002 /* Tagged Queue Action enabled */
+
+/*
+ * at_status values
+ */
+#define AT_PATH_INVALID 0x07 /* ATIO sent to firmware for disabled lun */
+#define AT_RESET 0x0E /* SCSI Bus Reset Occurred */
+#define AT_PHASE_ERROR 0x14 /* Bus phase sequence error */
+#define AT_NOCAP 0x16 /* Requested capability not available */
+#define AT_BDR_MSG 0x17 /* Bus Device Reset msg received */
+#define AT_CDB 0x3D /* CDB received */
+/*
+ * Macros to create and fetch and test concatenated handle and tag value macros
+ * (SPI only)
+ */
+#define AT_MAKE_TAGID(tid, aep) \
+ tid = aep->at_handle; \
+ if (aep->at_flags & AT_TQAE) { \
+ tid |= (aep->at_tag_val << 16); \
+ tid |= (1 << 24); \
+ }
+
+#define CT_MAKE_TAGID(tid, ct) \
+ tid = ct->ct_fwhandle; \
+ if (ct->ct_flags & CT_TQAE) { \
+ tid |= (ct->ct_tag_val << 16); \
+ tid |= (1 << 24); \
+ }
+
+#define AT_HAS_TAG(val) ((val) & (1 << 24))
+#define AT_GET_TAG(val) (((val) >> 16) & 0xff)
+#define AT_GET_HANDLE(val) ((val) & 0xffff)
+
+#define IN_MAKE_TAGID(tid, inp) \
+ tid = inp->in_seqid; \
+ tid |= (inp->in_tag_val << 16); \
+ tid |= (1 << 24)
+
+/*
+ * Accept Target I/O Entry structure, Type 2
+ */
+#define ATIO2_CDBLEN 16
+
+typedef struct {
+ isphdr_t at_header;
+ uint32_t at_reserved;
+ uint8_t at_lun; /* lun or reserved */
+ uint8_t at_iid; /* initiator */
+ uint16_t at_rxid; /* response ID */
+ uint16_t at_flags;
+ uint16_t at_status; /* firmware status */
+ uint8_t at_crn; /* command reference number */
+ uint8_t at_taskcodes;
+ uint8_t at_taskflags;
+ uint8_t at_execodes;
+ uint8_t at_cdb[ATIO2_CDBLEN]; /* received CDB */
+ uint32_t at_datalen; /* allocated data len */
+ uint16_t at_scclun; /* SCC Lun or reserved */
+ uint16_t at_wwpn[4]; /* WWPN of initiator */
+ uint16_t at_reserved2[6];
+ uint16_t at_oxid;
+} at2_entry_t;
+
+typedef struct {
+ isphdr_t at_header;
+ uint32_t at_reserved;
+ uint16_t at_iid; /* initiator */
+ uint16_t at_rxid; /* response ID */
+ uint16_t at_flags;
+ uint16_t at_status; /* firmware status */
+ uint8_t at_crn; /* command reference number */
+ uint8_t at_taskcodes;
+ uint8_t at_taskflags;
+ uint8_t at_execodes;
+ uint8_t at_cdb[ATIO2_CDBLEN]; /* received CDB */
+ uint32_t at_datalen; /* allocated data len */
+ uint16_t at_scclun; /* SCC Lun or reserved */
+ uint16_t at_wwpn[4]; /* WWPN of initiator */
+ uint16_t at_reserved2[6];
+ uint16_t at_oxid;
+} at2e_entry_t;
+
+#define ATIO2_WWPN_OFFSET 0x2A
+#define ATIO2_OXID_OFFSET 0x3E
+
+#define ATIO2_TC_ATTR_MASK 0x7
+#define ATIO2_TC_ATTR_SIMPLEQ 0
+#define ATIO2_TC_ATTR_HEADOFQ 1
+#define ATIO2_TC_ATTR_ORDERED 2
+#define ATIO2_TC_ATTR_ACAQ 4
+#define ATIO2_TC_ATTR_UNTAGGED 5
+
+#define ATIO2_EX_WRITE 0x1
+#define ATIO2_EX_READ 0x2
+/*
+ * Macros to create and fetch and test concatenated handle and tag value macros
+ */
+#define AT2_MAKE_TAGID(tid, bus, inst, aep) \
+ tid = aep->at_rxid; \
+ tid |= (((uint64_t)inst) << 32); \
+ tid |= (((uint64_t)bus) << 48)
+
+#define CT2_MAKE_TAGID(tid, bus, inst, ct) \
+ tid = ct->ct_rxid; \
+ tid |= (((uint64_t)inst) << 32); \
+ tid |= (((uint64_t)(bus & 0xff)) << 48)
+
+#define AT2_HAS_TAG(val) 1
+#define AT2_GET_TAG(val) ((val) & 0xffffffff)
+#define AT2_GET_INST(val) (((val) >> 32) & 0xffff)
+#define AT2_GET_HANDLE AT2_GET_TAG
+#define AT2_GET_BUS(val) (((val) >> 48) & 0xff)
+
+#define FC_HAS_TAG AT2_HAS_TAG
+#define FC_GET_TAG AT2_GET_TAG
+#define FC_GET_INST AT2_GET_INST
+#define FC_GET_HANDLE AT2_GET_HANDLE
+
+#define IN_FC_MAKE_TAGID(tid, bus, inst, seqid) \
+ tid = seqid; \
+ tid |= (((uint64_t)inst) << 32); \
+ tid |= (((uint64_t)(bus & 0xff)) << 48)
+
+#define FC_TAG_INSERT_INST(tid, inst) \
+ tid &= ~0x0000ffff00000000ull; \
+ tid |= (((uint64_t)inst) << 32)
+
+/*
+ * 24XX ATIO Definition
+ *
+ * This is *quite* different from other entry types.
+ * First of all, it has its own queue it comes in on.
+ *
+ * Secondly, it doesn't have a normal header.
+ *
+ * Thirdly, it's just a passthru of the FCP CMND IU
+ * which is recorded in big endian mode.
+ */
+typedef struct {
+ uint8_t at_type;
+ uint8_t at_count;
+ /*
+ * Task attribute in high four bits,
+ * the rest is the FCP CMND IU Length.
+ * NB: the command can extend past the
+ * length for a single queue entry.
+ */
+ uint16_t at_ta_len;
+ uint32_t at_rxid;
+ fc_hdr_t at_hdr;
+ fcp_cmnd_iu_t at_cmnd;
+} at7_entry_t;
+#define AT7_NORESRC_RXID 0xffffffff
+
+
+/*
+ * Continue Target I/O Entry structure
+ * Request from driver. The response from the
+ * ISP firmware is the same except that the last 18
+ * bytes are overwritten by suggested sense data if
+ * the 'autosense valid' bit is set in the status byte.
+ */
+typedef struct {
+ isphdr_t ct_header;
+ uint16_t ct_syshandle;
+ uint16_t ct_fwhandle; /* required by f/w */
+ uint8_t ct_lun; /* lun */
+ uint8_t ct_iid; /* initiator id */
+ uint8_t ct_reserved2;
+ uint8_t ct_tgt; /* our target id */
+ uint32_t ct_flags;
+ uint8_t ct_status; /* isp status */
+ uint8_t ct_scsi_status; /* scsi status */
+ uint8_t ct_tag_val; /* tag value */
+ uint8_t ct_tag_type; /* tag type */
+ uint32_t ct_xfrlen; /* transfer length */
+ int32_t ct_resid; /* residual length */
+ uint16_t ct_timeout;
+ uint16_t ct_seg_count;
+ ispds_t ct_dataseg[ISP_RQDSEG];
+} ct_entry_t;
+
+/*
+ * For some of the dual port SCSI adapters, port (bus #) is reported
+ * in the MSbit of ct_iid. Bit fields are a bit too awkward here.
+ *
+ * Note that this does not apply to FC adapters at all which can and
+ * do report IIDs between 0x81 && 0xfe (or 0x7ff) which represent devices
+ * that have logged in across a SCSI fabric.
+ */
+#define GET_IID_VAL(x) (x & 0x3f)
+#define GET_BUS_VAL(x) ((x >> 7) & 0x1)
+#define SET_IID_VAL(y, x) y = ((y & ~0x3f) | (x & 0x3f))
+#define SET_BUS_VAL(y, x) y = ((y & 0x3f) | ((x & 0x1) << 7))
+
+/*
+ * ct_flags values
+ */
+#define CT_TQAE 0x00000002 /* bit 1, Tagged Queue Action enable */
+#define CT_DATA_IN 0x00000040 /* bits 6&7, Data direction */
+#define CT_DATA_OUT 0x00000080 /* bits 6&7, Data direction */
+#define CT_NO_DATA 0x000000C0 /* bits 6&7, Data direction */
+#define CT_CCINCR 0x00000100 /* bit 8, autoincrement atio count */
+#define CT_DATAMASK 0x000000C0 /* bits 6&7, Data direction */
+#define CT_INISYNCWIDE 0x00004000 /* bit 14, Do Sync/Wide Negotiation */
+#define CT_NODISC 0x00008000 /* bit 15, Disconnects disabled */
+#define CT_DSDP 0x01000000 /* bit 24, Disable Save Data Pointers */
+#define CT_SENDRDP 0x04000000 /* bit 26, Send Restore Pointers msg */
+#define CT_SENDSTATUS 0x80000000 /* bit 31, Send SCSI status byte */
+
+/*
+ * ct_status values
+ * - set by the firmware when it returns the CTIO
+ */
+#define CT_OK 0x01 /* completed without error */
+#define CT_ABORTED 0x02 /* aborted by host */
+#define CT_ERR 0x04 /* see sense data for error */
+#define CT_INVAL 0x06 /* request for disabled lun */
+#define CT_NOPATH 0x07 /* invalid ITL nexus */
+#define CT_INVRXID 0x08 /* (FC only) Invalid RX_ID */
+#define CT_DATA_OVER 0x09 /* (FC only) Data Overrun */
+#define CT_RSELTMO 0x0A /* reselection timeout after 2 tries */
+#define CT_TIMEOUT 0x0B /* timed out */
+#define CT_RESET 0x0E /* SCSI Bus Reset occurred */
+#define CT_PARITY 0x0F /* Uncorrectable Parity Error */
+#define CT_BUS_ERROR 0x10 /* (FC Only) DMA PCI Error */
+#define CT_PANIC 0x13 /* Unrecoverable Error */
+#define CT_PHASE_ERROR 0x14 /* Bus phase sequence error */
+#define CT_DATA_UNDER 0x15 /* (FC only) Data Underrun */
+#define CT_BDR_MSG 0x17 /* Bus Device Reset msg received */
+#define CT_TERMINATED 0x19 /* due to Terminate Transfer mbox cmd */
+#define CT_PORTUNAVAIL 0x28 /* port not available */
+#define CT_LOGOUT 0x29 /* port logout */
+#define CT_PORTCHANGED 0x2A /* port changed */
+#define CT_IDE 0x33 /* Initiator Detected Error */
+#define CT_NOACK 0x35 /* Outstanding Immed. Notify. entry */
+#define CT_SRR 0x45 /* SRR Received */
+#define CT_LUN_RESET 0x48 /* Lun Reset Received */
+
+#define CT_HBA_RESET 0xffff /* pseudo error - command destroyed by HBA reset*/
+
+/*
+ * When the firmware returns a CTIO entry, it may overwrite the last
+ * part of the structure with sense data. This starts at offset 0x2E
+ * into the entry, which is in the middle of ct_dataseg[1]. Rather
+ * than define a new struct for this, I'm just using the sense data
+ * offset.
+ */
+#define CTIO_SENSE_OFFSET 0x2E
+
+/*
+ * Entry length in u_longs. All entries are the same size so
+ * any one will do as the numerator.
+ */
+#define UINT32_ENTRY_SIZE (sizeof(at_entry_t)/sizeof(uint32_t))
+
+/*
+ * QLA2100 CTIO (type 2) entry
+ */
+#define MAXRESPLEN 26
+typedef struct {
+ isphdr_t ct_header;
+ uint32_t ct_syshandle;
+ uint8_t ct_lun; /* lun */
+ uint8_t ct_iid; /* initiator id */
+ uint16_t ct_rxid; /* response ID */
+ uint16_t ct_flags;
+ uint16_t ct_status; /* isp status */
+ uint16_t ct_timeout;
+ uint16_t ct_seg_count;
+ uint32_t ct_reloff; /* relative offset */
+ int32_t ct_resid; /* residual length */
+ union {
+ /*
+ * The three different modes that the target driver
+ * can set the CTIO{2,3,4} up as.
+ *
+ * The first is for sending FCP_DATA_IUs as well as
+ * (optionally) sending a terminal SCSI status FCP_RSP_IU.
+ *
+ * The second is for sending SCSI sense data in an FCP_RSP_IU.
+ * Note that no FCP_DATA_IUs will be sent.
+ *
+ * The third is for sending FCP_RSP_IUs as built specifically
+ * in system memory as located by the isp_dataseg.
+ */
+ struct {
+ uint32_t _reserved;
+ uint16_t _reserved2;
+ uint16_t ct_scsi_status;
+ uint32_t ct_xfrlen;
+ union {
+ ispds_t ct_dataseg[ISP_RQDSEG_T2];
+ ispds64_t ct_dataseg64[ISP_RQDSEG_T3];
+ ispdslist_t ct_dslist;
+ } u;
+ } m0;
+ struct {
+ uint16_t _reserved;
+ uint16_t _reserved2;
+ uint16_t ct_senselen;
+ uint16_t ct_scsi_status;
+ uint16_t ct_resplen;
+ uint8_t ct_resp[MAXRESPLEN];
+ } m1;
+ struct {
+ uint32_t _reserved;
+ uint16_t _reserved2;
+ uint16_t _reserved3;
+ uint32_t ct_datalen;
+ ispds_t ct_fcp_rsp_iudata;
+ } m2;
+ } rsp;
+} ct2_entry_t;
+
+typedef struct {
+ isphdr_t ct_header;
+ uint32_t ct_syshandle;
+ uint16_t ct_iid; /* initiator id */
+ uint16_t ct_rxid; /* response ID */
+ uint16_t ct_flags;
+ uint16_t ct_status; /* isp status */
+ uint16_t ct_timeout;
+ uint16_t ct_seg_count;
+ uint32_t ct_reloff; /* relative offset */
+ int32_t ct_resid; /* residual length */
+ union {
+ struct {
+ uint32_t _reserved;
+ uint16_t _reserved2;
+ uint16_t ct_scsi_status;
+ uint32_t ct_xfrlen;
+ union {
+ ispds_t ct_dataseg[ISP_RQDSEG_T2];
+ ispds64_t ct_dataseg64[ISP_RQDSEG_T3];
+ ispdslist_t ct_dslist;
+ } u;
+ } m0;
+ struct {
+ uint16_t _reserved;
+ uint16_t _reserved2;
+ uint16_t ct_senselen;
+ uint16_t ct_scsi_status;
+ uint16_t ct_resplen;
+ uint8_t ct_resp[MAXRESPLEN];
+ } m1;
+ struct {
+ uint32_t _reserved;
+ uint16_t _reserved2;
+ uint16_t _reserved3;
+ uint32_t ct_datalen;
+ ispds_t ct_fcp_rsp_iudata;
+ } m2;
+ } rsp;
+} ct2e_entry_t;
+
+/*
+ * ct_flags values for CTIO2
+ */
+#define CT2_FLAG_MODE0 0x0000
+#define CT2_FLAG_MODE1 0x0001
+#define CT2_FLAG_MODE2 0x0002
+#define CT2_FLAG_MMASK 0x0003
+#define CT2_DATA_IN 0x0040
+#define CT2_DATA_OUT 0x0080
+#define CT2_NO_DATA 0x00C0
+#define CT2_DATAMASK 0x00C0
+#define CT2_CCINCR 0x0100
+#define CT2_FASTPOST 0x0200
+#define CT2_CONFIRM 0x2000
+#define CT2_TERMINATE 0x4000
+#define CT2_SENDSTATUS 0x8000
+
+/*
+ * ct_status values are (mostly) the same as that for ct_entry.
+ */
+
+/*
+ * ct_scsi_status values- the low 8 bits are the normal SCSI status
+ * we know and love. The upper 8 bits are validity markers for FCP_RSP_IU
+ * fields.
+ */
+#define CT2_RSPLEN_VALID 0x0100
+#define CT2_SNSLEN_VALID 0x0200
+#define CT2_DATA_OVER 0x0400
+#define CT2_DATA_UNDER 0x0800
+
+/*
+ * ISP24XX CTIO
+ */
+#define MAXRESPLEN_24XX 24
+typedef struct {
+ isphdr_t ct_header;
+ uint32_t ct_syshandle;
+ uint16_t ct_nphdl; /* status on returned CTIOs */
+ uint16_t ct_timeout;
+ uint16_t ct_seg_count;
+ uint8_t ct_vpidx;
+ uint8_t ct_xflags;
+ uint16_t ct_iid_lo; /* low 16 bits of portid */
+ uint8_t ct_iid_hi; /* hi 8 bits of portid */
+ uint8_t ct_reserved;
+ uint32_t ct_rxid;
+ uint16_t ct_senselen; /* mode 1 only */
+ uint16_t ct_flags;
+ int32_t ct_resid; /* residual length */
+ uint16_t ct_oxid;
+ uint16_t ct_scsi_status; /* modes 0 && 1 only */
+ union {
+ struct {
+ uint32_t reloff;
+ uint32_t reserved0;
+ uint32_t ct_xfrlen;
+ uint32_t reserved1;
+ ispds64_t ds;
+ } m0;
+ struct {
+ uint16_t ct_resplen;
+ uint16_t reserved;
+ uint8_t ct_resp[MAXRESPLEN_24XX];
+ } m1;
+ struct {
+ uint32_t reserved0;
+ uint32_t ct_datalen;
+ uint32_t reserved1;
+ ispds64_t ct_fcp_rsp_iudata;
+ } m2;
+ } rsp;
+} ct7_entry_t;
+
+/*
+ * ct_flags values for CTIO7
+ */
+#define CT7_DATA_IN 0x0002
+#define CT7_DATA_OUT 0x0001
+#define CT7_NO_DATA 0x0000
+#define CT7_DATAMASK 0x003
+#define CT7_DSD_ENABLE 0x0004
+#define CT7_CONF_STSFD 0x0010
+#define CT7_EXPLCT_CONF 0x0020
+#define CT7_FLAG_MODE0 0x0000
+#define CT7_FLAG_MODE1 0x0040
+#define CT7_FLAG_MODE2 0x0080
+#define CT7_FLAG_MMASK 0x00C0
+#define CT7_NOACK 0x0100
+#define CT7_TASK_ATTR_SHIFT 9
+#define CT7_CONFIRM 0x2000
+#define CT7_TERMINATE 0x4000
+#define CT7_SENDSTATUS 0x8000
+
+/*
+ * Type 7 CTIO status codes
+ */
+#define CT7_OK 0x01 /* completed without error */
+#define CT7_ABORTED 0x02 /* aborted by host */
+#define CT7_ERR 0x04 /* see sense data for error */
+#define CT7_INVAL 0x06 /* request for disabled lun */
+#define CT7_INVRXID 0x08 /* Invalid RX_ID */
+#define CT7_DATA_OVER 0x09 /* Data Overrun */
+#define CT7_TIMEOUT 0x0B /* timed out */
+#define CT7_RESET 0x0E /* LIP Rset Received */
+#define CT7_BUS_ERROR 0x10 /* DMA PCI Error */
+#define CT7_REASSY_ERR 0x11 /* DMA reassembly error */
+#define CT7_DATA_UNDER 0x15 /* Data Underrun */
+#define CT7_PORTUNAVAIL 0x28 /* port not available */
+#define CT7_LOGOUT 0x29 /* port logout */
+#define CT7_PORTCHANGED 0x2A /* port changed */
+#define CT7_SRR 0x45 /* SRR Received */
+
+/*
+ * Other 24XX related target IOCBs
+ */
+
+/*
+ * ABTS Received
+ */
+typedef struct {
+ isphdr_t abts_header;
+ uint8_t abts_reserved0[6];
+ uint16_t abts_nphdl;
+ uint16_t abts_reserved1;
+ uint16_t abts_sof;
+ uint32_t abts_rxid_abts;
+ uint16_t abts_did_lo;
+ uint8_t abts_did_hi;
+ uint8_t abts_r_ctl;
+ uint16_t abts_sid_lo;
+ uint8_t abts_sid_hi;
+ uint8_t abts_cs_ctl;
+ uint16_t abts_fs_ctl;
+ uint8_t abts_f_ctl;
+ uint8_t abts_type;
+ uint16_t abts_seq_cnt;
+ uint8_t abts_df_ctl;
+ uint8_t abts_seq_id;
+ uint16_t abts_rx_id;
+ uint16_t abts_ox_id;
+ uint32_t abts_param;
+ uint8_t abts_reserved2[16];
+ uint32_t abts_rxid_task;
+} abts_t;
+
+typedef struct {
+ isphdr_t abts_rsp_header;
+ uint32_t abts_rsp_handle;
+ uint16_t abts_rsp_status;
+ uint16_t abts_rsp_nphdl;
+ uint16_t abts_rsp_ctl_flags;
+ uint16_t abts_rsp_sof;
+ uint32_t abts_rsp_rxid_abts;
+ uint16_t abts_rsp_did_lo;
+ uint8_t abts_rsp_did_hi;
+ uint8_t abts_rsp_r_ctl;
+ uint16_t abts_rsp_sid_lo;
+ uint8_t abts_rsp_sid_hi;
+ uint8_t abts_rsp_cs_ctl;
+ uint16_t abts_rsp_f_ctl_lo;
+ uint8_t abts_rsp_f_ctl_hi;
+ uint8_t abts_rsp_type;
+ uint16_t abts_rsp_seq_cnt;
+ uint8_t abts_rsp_df_ctl;
+ uint8_t abts_rsp_seq_id;
+ uint16_t abts_rsp_rx_id;
+ uint16_t abts_rsp_ox_id;
+ uint32_t abts_rsp_param;
+ union {
+ struct {
+ uint16_t reserved;
+ uint8_t last_seq_id;
+ uint8_t seq_id_valid;
+ uint16_t aborted_rx_id;
+ uint16_t aborted_ox_id;
+ uint16_t high_seq_cnt;
+ uint16_t low_seq_cnt;
+ uint8_t reserved2[4];
+ } ba_acc;
+ struct {
+ uint8_t vendor_unique;
+ uint8_t explanation;
+ uint8_t reason;
+ uint8_t reserved;
+ uint8_t reserved2[12];
+ } ba_rjt;
+ struct {
+ uint8_t reserved[8];
+ uint32_t subcode1;
+ uint32_t subcode2;
+ } rsp;
+ uint8_t reserved[16];
+ } abts_rsp_payload;
+ uint32_t abts_rsp_rxid_task;
+} abts_rsp_t;
+
+/* terminate this ABTS exchange */
+#define ISP24XX_ABTS_RSP_TERMINATE 0x01
+
+#define ISP24XX_ABTS_RSP_COMPLETE 0x00
+#define ISP24XX_ABTS_RSP_RESET 0x04
+#define ISP24XX_ABTS_RSP_ABORTED 0x05
+#define ISP24XX_ABTS_RSP_TIMEOUT 0x06
+#define ISP24XX_ABTS_RSP_INVXID 0x08
+#define ISP24XX_ABTS_RSP_LOGOUT 0x29
+#define ISP24XX_ABTS_RSP_SUBCODE 0x31
+
+#define ISP24XX_NO_TASK 0xffffffff
+
+/*
+ * Miscellaneous
+ *
+ * These are the limits of the number of dma segments we
+ * can deal with based not on the size of the segment counter
+ * (which is 16 bits), but on the size of the number of
+ * queue entries field (which is 8 bits). We assume no
+ * segments in the first queue entry, so we can either
+ * have 7 dma segments per continuation entry or 5
+ * (for 64 bit dma).. multiplying out by 254....
+ */
+#define ISP_NSEG_MAX 1778
+#define ISP_NSEG64_MAX 1270
+
#endif /* _ISPMBOX_H */
diff --git a/sys/dev/isp/ispreg.h b/sys/dev/isp/ispreg.h
index ee0e154..08df337 100644
--- a/sys/dev/isp/ispreg.h
+++ b/sys/dev/isp/ispreg.h
@@ -1,6 +1,6 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 1997-2007 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,6 +24,7 @@
* 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.
+ *
*/
/*
* Machine Independent (well, as best as possible) register
@@ -362,11 +363,12 @@
#define BIU2400_REQOUTP (BIU_BLOCK+0x20) /* Request Queue Out */
#define BIU2400_RSPINP (BIU_BLOCK+0x24) /* Response Queue In */
#define BIU2400_RSPOUTP (BIU_BLOCK+0x28) /* Response Queue Out */
-#define BIU2400_PRI_RQINP (BIU_BLOCK+0x2C) /* Priority Request Q In */
-#define BIU2400_PRI_RSPINP (BIU_BLOCK+0x30) /* Priority Request Q Out */
-#define BIU2400_ATIO_RSPINP (BIU_BLOCK+0x3C) /* ATIO Queue In */
-#define BIU2400_ATIO_REQINP (BIU_BLOCK+0x40) /* ATIO Queue Out */
+#define BIU2400_PRI_REQINP (BIU_BLOCK+0x2C) /* Priority Request Q In */
+#define BIU2400_PRI_REQOUTP (BIU_BLOCK+0x30) /* Priority Request Q Out */
+
+#define BIU2400_ATIO_RSPINP (BIU_BLOCK+0x3C) /* ATIO Queue In */
+#define BIU2400_ATIO_RSPOUTP (BIU_BLOCK+0x40) /* ATIO Queue Out */
#define BIU2400_R2HSTSLO (BIU_BLOCK+0x44)
#define BIU2400_R2HSTSHI (BIU_BLOCK+0x46)
@@ -469,10 +471,21 @@ typedef struct {
uint16_t param[MAILBOX_STORAGE];
uint16_t ibits;
uint16_t obits;
- uint32_t : 28,
+ uint32_t
+ lineno : 16,
+ : 12,
logval : 4;
uint32_t timeout;
+ const char *func;
} mbreg_t;
+#define MBSINIT(mbxp, code, loglev, timo) \
+ ISP_MEMZERO((mbxp), sizeof (mbreg_t)); \
+ (mbxp)->param[0] = code; \
+ (mbxp)->lineno = __LINE__; \
+ (mbxp)->func = __func__; \
+ (mbxp)->logval = loglev; \
+ (mbxp)->timeout = timo
+
/*
* Fibre Protocol Module and Frame Buffer Register Offsets/Definitions (2X00).
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index 96c8b06..e568a1c 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -1,18 +1,18 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 1997-2007 by Matthew Jacob
+ * Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
- *
+ *
* 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.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY 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
@@ -24,6 +24,7 @@
* 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.
+ *
*/
/*
* Soft Definitions for for Qlogic ISP SCSI adapters.
@@ -49,7 +50,7 @@
#include "ispmbox.h"
#endif
-#define ISP_CORE_VERSION_MAJOR 3
+#define ISP_CORE_VERSION_MAJOR 6
#define ISP_CORE_VERSION_MINOR 0
/*
@@ -57,13 +58,11 @@
*/
typedef struct ispsoftc ispsoftc_t;
struct ispmdvec {
- int (*dv_rd_isr)
- (ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
+ int (*dv_rd_isr) (ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
uint32_t (*dv_rd_reg) (ispsoftc_t *, int);
void (*dv_wr_reg) (ispsoftc_t *, int, uint32_t);
int (*dv_mbxdma) (ispsoftc_t *);
- int (*dv_dmaset)
- (ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
+ int (*dv_dmaset) (ispsoftc_t *, XS_T *, void *);
void (*dv_dmaclr) (ispsoftc_t *, XS_T *, uint32_t);
void (*dv_reset0) (ispsoftc_t *);
void (*dv_reset1) (ispsoftc_t *);
@@ -77,7 +76,9 @@ struct ispmdvec {
* Overall parameters
*/
#define MAX_TARGETS 16
+#ifndef MAX_FC_TARG
#define MAX_FC_TARG 512
+#endif
#define ISP_MAX_TARGETS(isp) (IS_FC(isp)? MAX_FC_TARG : MAX_TARGETS)
#define ISP_MAX_LUNS(isp) (isp)->isp_maxluns
@@ -97,8 +98,8 @@ struct ispmdvec {
#define ISP_MBOXDMASETUP(isp) \
(*(isp)->isp_mdvec->dv_mbxdma)((isp))
-#define ISP_DMASETUP(isp, xs, req, iptrp, optr) \
- (*(isp)->isp_mdvec->dv_dmaset)((isp), (xs), (req), (iptrp), (optr))
+#define ISP_DMASETUP(isp, xs, req) \
+ (*(isp)->isp_mdvec->dv_dmaset)((isp), (xs), (req))
#define ISP_DMAFREE(isp, xs, hndl) \
if ((isp)->isp_mdvec->dv_dmaclr) \
@@ -158,13 +159,19 @@ struct ispmdvec {
ISP_WRITE(isp, isp->isp_rqstinrp, nxti); \
isp->isp_reqidx = nxti
+#define ISP_SYNC_REQUEST(isp) \
+ MEMORYBARRIER(isp, SYNC_REQUEST, isp->isp_reqidx, QENTRY_LEN); \
+ isp->isp_reqidx = ISP_NXT_QENTRY(isp->isp_reqidx, RQUEST_QUEUE_LEN(isp)); \
+ ISP_WRITE(isp, isp->isp_rqstinrp, isp->isp_reqidx)
+
/*
* SCSI Specific Host Adapter Parameters- per bus, per target
*/
typedef struct {
- uint32_t : 10,
- isp_bad_nvram : 1,
- isp_gotdparms : 1,
+ uint32_t : 8,
+ update : 1,
+ sendmarker : 1,
+ role : 2,
isp_req_ack_active_neg : 1,
isp_data_line_active_neg: 1,
isp_cmd_dma_burst_enable: 1,
@@ -184,7 +191,7 @@ typedef struct {
uint8_t isp_retry_count;
uint8_t isp_retry_delay;
struct {
- uint32_t
+ uint32_t
exc_throttle : 8,
: 1,
dev_enable : 1, /* ignored */
@@ -237,11 +244,16 @@ typedef struct {
#define SNS_ID 0x80 /* SNS Server Special ID */
#define NPH_MAX 0xfe
+/* Use this handle for the base for multi-id firmware SNS logins */
+#define NPH_SNS_HDLBASE 0x400
+
/* These are for 2K Login Firmware cards */
#define NPH_RESERVED 0x7F0 /* begin of reserved N-port handles */
#define NPH_MGT_ID 0x7FA /* Management Server Special ID */
#define NPH_SNS_ID 0x7FC /* SNS Server Special ID */
-#define NPH_FL_ID 0x7FE /* FL Port Special ID */
+#define NPH_FABRIC_CTLR 0x7FD /* Fabric Controller (0xFFFFFD) */
+#define NPH_FL_ID 0x7FE /* F Port Special ID (0xFFFFFE) */
+#define NPH_IP_BCST 0x7ff /* IP Broadcast Special ID (0xFFFFFF) */
#define NPH_MAX_2K 0x800
/*
@@ -255,11 +267,26 @@ typedef struct {
#define LOCAL_LOOP_LIM 126
/*
+ * Limit for (2K login) N-port handle amounts
+ */
+#define MAX_NPORT_HANDLE 2048
+
+/*
+ * Special Constants
+ */
+#define INI_NONE ((uint64_t) 0)
+#define ISP_NOCHAN 0xff
+
+/*
* Special Port IDs
*/
#define MANAGEMENT_PORT_ID 0xFFFFFA
#define SNS_PORT_ID 0xFFFFFC
#define FABRIC_PORT_ID 0xFFFFFE
+#define PORT_ANY 0xFFFFFF
+#define PORT_NONE 0
+#define DOMAIN_CONTROLLER_BASE 0xFFFC00
+#define DOMAIN_CONTROLLER_END 0xFFFCFF
/*
@@ -271,11 +298,11 @@ typedef struct {
*
* It has a state. If the state if VALID, that means that we've logged into
* the device. We also *may* have a initiator map index entry. This is a value
- * from 0..MAX_FC_TARG that is used to index into the isp_ini_map array. If
+ * from 0..MAX_FC_TARG that is used to index into the isp_dev_map array. If
* the value therein is non-zero, then that value minus one is used to index
* into the Port Database to find the handle for forming commands. There is
- * back-index minus one value within to Port Database entry that tells us
- * which entry in isp_ini_map points to us (to avoid searching).
+ * back-index minus one value within to Port Database entry that tells us
+ * which entry in isp_dev_map points to us (to avoid searching).
*
* Local loop devices the firmware automatically performs PLOGI on for us
* (which is why that handle is imposed upon us). Fabric devices we assign
@@ -308,7 +335,7 @@ typedef struct {
*
* + There can never be two non-NIL entries with the same handle.
*
- * + There can never be two non-NIL entries which have the same ini_map_idx
+ * + There can never be two non-NIL entries which have the same dev_map_idx
* value.
*/
typedef struct {
@@ -318,27 +345,36 @@ typedef struct {
* the 'loopid'.
*/
uint16_t handle;
+
/*
- * The ini_map_idx, if nonzero, is the system virtual target ID (+1)
- * as a cross-reference with the isp_ini_map.
+ * The dev_map_idx, if nonzero, is the system virtual target ID (+1)
+ * as a cross-reference with the isp_dev_map.
*
* A device is 'autologin' if the firmware automatically logs into
* it (re-logins as needed). Basically, local private loop devices.
*
- * The state is the current state of thsi entry.
+ * The state is the current state of this entry.
*
* Role is Initiator, Target, Both
*
- * Portid is obvious, as or node && port WWNs. The new_role and
+ * Portid is obvious, as are node && port WWNs. The new_role and
* new_portid is for when we are pending a change.
+ *
+ * The 'target_mode' tag means that this entry arrived via a
+ * target mode command and is immune from normal flushing rules.
+ * You should also never see anything with an initiator role
+ * with this set.
*/
- uint16_t ini_map_idx : 12,
+ uint16_t dev_map_idx : 12,
autologin : 1, /* F/W does PLOGI/PLOGO */
state : 3;
- uint32_t reserved : 6,
+ uint32_t reserved : 5,
+ target_mode : 1,
roles : 2,
portid : 24;
- uint32_t new_reserved : 6,
+ uint32_t
+ dirty : 1, /* commands have been run */
+ new_reserved : 5,
new_roles : 2,
new_portid : 24;
uint64_t node_wwn;
@@ -356,34 +392,47 @@ typedef struct {
/*
* FC card specific information
+ *
+ * This structure is replicated across multiple channels for multi-id
+ * capapble chipsets, with some entities different on a per-channel basis.
*/
+
typedef struct {
- uint32_t : 10,
- isp_tmode : 1,
- isp_2klogin : 1,
- isp_sccfw : 1,
- isp_gbspeed : 3,
- : 1,
- : 1,
- isp_gotdparms : 1,
- isp_bad_nvram : 1,
+ uint32_t
+ link_active : 1,
+ npiv_fabric : 1,
+ inorder : 1,
+ sendmarker : 1,
+ role : 2,
+ isp_gbspeed : 4,
isp_loopstate : 4, /* Current Loop State */
isp_fwstate : 4, /* ISP F/W state */
- isp_topo : 3,
+ isp_topo : 3, /* Connection Type */
loop_seen_once : 1;
+
uint32_t : 8,
isp_portid : 24; /* S_ID */
+
+
uint16_t isp_fwoptions;
uint16_t isp_xfwoptions;
uint16_t isp_zfwoptions;
- uint16_t isp_loopid; /* hard loop id */
- uint16_t isp_fwattr; /* firmware attributes */
- uint16_t isp_execthrottle;
+ uint16_t isp_loopid; /* hard loop id */
+ uint16_t isp_sns_hdl; /* N-port handle for SNS */
+ uint16_t isp_lasthdl; /* only valid for channel 0 */
+ uint16_t isp_maxalloc;
uint8_t isp_retry_delay;
uint8_t isp_retry_count;
- uint8_t isp_reserved;
- uint16_t isp_maxalloc;
- uint16_t isp_maxfrmlen;
+
+ /*
+ * Current active WWNN/WWPN
+ */
+ uint64_t isp_wwnn;
+ uint64_t isp_wwpn;
+
+ /*
+ * NVRAM WWNN/WWPN
+ */
uint64_t isp_wwnn_nvram;
uint64_t isp_wwpn_nvram;
@@ -399,16 +448,25 @@ typedef struct {
* subtract one to get the portdb index. This means that
* entries which are zero are unmapped (i.e., don't exist).
*/
- uint16_t isp_ini_map[MAX_FC_TARG];
+ uint16_t isp_dev_map[MAX_FC_TARG];
+
+#ifdef ISP_TARGET_MODE
+ /*
+ * This maps N-Port Handle to portdb entry so we
+ * don't have to search for every incoming command.
+ *
+ * The mapping function is to take any non-zero entry and
+ * subtract one to get the portdb index. This means that
+ * entries which are zero are unmapped (i.e., don't exist).
+ */
+ uint16_t isp_tgt_map[MAX_NPORT_HANDLE];
+#endif
/*
* Scratch DMA mapped in area to fetch Port Database stuff, etc.
*/
void * isp_scratch;
XS_DMA_ADDR_T isp_scdma;
-#ifdef ISP_FW_CRASH_DUMP
- uint16_t * isp_dump_data;
-#endif
} fcparam;
#define FW_CONFIG_WAIT 0
@@ -457,7 +515,6 @@ struct ispsoftc {
void * isp_param; /* type specific */
uint16_t isp_fwrev[3]; /* Loaded F/W revision */
- uint16_t isp_romfw_rev[3]; /* PROM F/W revision */
uint16_t isp_maxcmds; /* max possible I/O cmds */
uint8_t isp_type; /* HBA Chip Type */
uint8_t isp_revision; /* HBA Chip H/W Revision */
@@ -466,22 +523,20 @@ struct ispsoftc {
uint32_t isp_clock : 8, /* input clock */
: 4,
isp_port : 1, /* 23XX/24XX only */
- isp_failed : 1, /* board failed */
isp_open : 1, /* opened (ioctl) */
- isp_touched : 1, /* board ever seen? */
isp_bustype : 1, /* SBus or PCI */
isp_loaded_fw : 1, /* loaded firmware */
- isp_role : 2, /* roles supported */
- isp_dblev : 12; /* debug log mask */
+ isp_dblev : 16; /* debug log mask */
+
+ uint16_t isp_fwattr; /* firmware attributes */
+ uint16_t isp_nchan; /* number of channels */
- uint32_t isp_confopts; /* config options */
+ uint32_t isp_confopts; /* config options */
uint32_t isp_rqstinrp; /* register for REQINP */
uint32_t isp_rqstoutrp; /* register for REQOUTP */
uint32_t isp_respinrp; /* register for RESINP */
uint32_t isp_respoutrp; /* register for RESOUTP */
- uint32_t isp_atioinrp; /* register for ATIOINP */
- uint32_t isp_atiooutrp; /* register for ATIOOUTP */
/*
* Instrumentation
@@ -494,24 +549,26 @@ struct ispsoftc {
uint64_t isp_fphccmplt; /* CMDs via fastpost */
uint16_t isp_rscchiwater;
uint16_t isp_fpcchiwater;
+ NANOTIME_T isp_init_time; /* time were last initialized */
/*
* Volatile state
*/
volatile uint32_t : 8,
+ : 2,
+ isp_dead : 1,
+ : 1,
isp_mboxbsy : 1, /* mailbox command active */
isp_state : 3,
- isp_sendmarker : 2, /* send a marker entry */
- isp_update : 2, /* update parameters */
isp_nactive : 16; /* how many commands active */
volatile uint32_t isp_reqodx; /* index of last ISP pickup */
volatile uint32_t isp_reqidx; /* index of next request */
volatile uint32_t isp_residx; /* index of next result */
volatile uint32_t isp_resodx; /* index of next result */
- volatile uint32_t isp_rspbsy;
volatile uint32_t isp_lasthdls; /* last handle seed */
volatile uint32_t isp_obits; /* mailbox command output */
+ volatile uint32_t isp_serno; /* rolling serial number */
volatile uint16_t isp_mboxtmp[MAILBOX_STORAGE];
volatile uint16_t isp_lastmbxcmd; /* last mbox command sent */
volatile uint16_t isp_mbxwrk0;
@@ -527,7 +584,7 @@ struct ispsoftc {
#ifdef ISP_TARGET_MODE
/*
- * Active target commands are stored here, indexed by handle function.
+ * Active target commands are stored here, indexed by handle functions.
*/
void **isp_tgtlist;
#endif
@@ -546,8 +603,20 @@ struct ispsoftc {
#endif
};
-#define SDPARAM(isp) ((sdparam *) (isp)->isp_param)
-#define FCPARAM(isp) ((fcparam *) (isp)->isp_param)
+#define SDPARAM(isp, chan) (&((sdparam *)(isp)->isp_param)[(chan)])
+#define FCPARAM(isp, chan) (&((fcparam *)(isp)->isp_param)[(chan)])
+
+#define ISP_SET_SENDMARKER(isp, chan, val) \
+ if (IS_FC(isp)) { \
+ FCPARAM(isp, chan)->sendmarker = val; \
+ } else { \
+ SDPARAM(isp, chan)->sendmarker = val; \
+ }
+
+#define ISP_TST_SENDMARKER(isp, chan) \
+ (IS_FC(isp)? \
+ FCPARAM(isp, chan)->sendmarker != 0 : \
+ SDPARAM(isp, chan)->sendmarker != 0)
/*
* ISP Driver Run States
@@ -571,23 +640,22 @@ struct ispsoftc {
#define ISP_CFG_NPORT 0x04 /* prefer {N/F}-Port connection */
#define ISP_CFG_NPORT_ONLY 0x08 /* insist on {N/F}-Port connection */
#define ISP_CFG_LPORT_ONLY 0x0C /* insist on {N/F}L-Port connection */
-#define ISP_CFG_OWNWWPN 0x100 /* override NVRAM wwpn */
-#define ISP_CFG_OWNWWNN 0x200 /* override NVRAM wwnn */
#define ISP_CFG_OWNFSZ 0x400 /* override NVRAM frame size */
#define ISP_CFG_OWNLOOPID 0x800 /* override NVRAM loopid */
#define ISP_CFG_OWNEXCTHROTTLE 0x1000 /* override NVRAM execution throttle */
#define ISP_CFG_FOURGB 0x2000 /* force 4GB connection (24XX only) */
/*
- * Prior to calling isp_reset for the first time, the outer layer
- * should set isp_role to one of NONE, INITIATOR, TARGET, BOTH.
+ * For each channel, the outer layers should know what role that channel
+ * will take: ISP_ROLE_NONE, ISP_ROLE_INITIATOR, ISP_ROLE_TARGET,
+ * ISP_ROLE_BOTH.
*
* If you set ISP_ROLE_NONE, the cards will be reset, new firmware loaded,
* NVRAM read, and defaults set, but any further initialization (e.g.
* INITIALIZE CONTROL BLOCK commands for 2X00 cards) won't be done.
*
* If INITIATOR MODE isn't set, attempts to run commands will be stopped
- * at isp_start and completed with the moral equivalent of SELECTION TIMEOUT.
+ * at isp_start and completed with the equivalent of SELECTION TIMEOUT.
*
* If TARGET MODE is set, it doesn't mean that the rest of target mode support
* needs to be enabled, or will even work. What happens with the 2X00 cards
@@ -665,8 +733,10 @@ struct ispsoftc {
#define ISP_HA_FC_2312 0x40
#define ISP_HA_FC_2322 0x50
#define ISP_HA_FC_2400 0x60
+#define ISP_HA_FC_2500 0x70
#define IS_SCSI(isp) (isp->isp_type & ISP_HA_SCSI)
+#define IS_1020(isp) (isp->isp_type < ISP_HA_SCSI_1240)
#define IS_1240(isp) (isp->isp_type == ISP_HA_SCSI_1240)
#define IS_1080(isp) (isp->isp_type == ISP_HA_SCSI_1080)
#define IS_1280(isp) (isp->isp_type == ISP_HA_SCSI_1280)
@@ -688,6 +758,7 @@ struct ispsoftc {
#define IS_2312(isp) ((isp)->isp_type == ISP_HA_FC_2312)
#define IS_2322(isp) ((isp)->isp_type == ISP_HA_FC_2322)
#define IS_24XX(isp) ((isp)->isp_type >= ISP_HA_FC_2400)
+#define IS_25XX(isp) ((isp)->isp_type >= ISP_HA_FC_2500)
/*
* DMA related macros
@@ -705,10 +776,9 @@ struct ispsoftc {
*/
/*
- * Reset Hardware. Totally. Assumes that you'll follow this with
- * a call to isp_init.
+ * Reset Hardware. Totally. Assumes that you'll follow this with a call to isp_init.
*/
-void isp_reset(ispsoftc_t *);
+void isp_reset(ispsoftc_t *, int);
/*
* Initialize Hardware to known state
@@ -718,14 +788,7 @@ void isp_init(ispsoftc_t *);
/*
* Reset the ISP and call completion for any orphaned commands.
*/
-void isp_reinit(ispsoftc_t *);
-
-#ifdef ISP_FW_CRASH_DUMP
-/*
- * Dump firmware entry point.
- */
-void isp_fw_dump(ispsoftc_t *isp);
-#endif
+void isp_reinit(ispsoftc_t *, int);
/*
* Internal Interrupt Service Routine
@@ -757,27 +820,34 @@ void isp_done(XS_T *);
* Platform Dependent to External to Internal Control Function
*
* Assumes locks are held on entry. You should note that with many of
- * these commands and locks may be released while this is occurring.
- *
- * A few notes about some of these functions:
- *
- * ISPCTL_FCLINK_TEST tests to make sure we have good fibre channel link.
- * The argument is a pointer to an integer which is the time, in microseconds,
- * we should wait to see whether we have good link. This test, if successful,
- * lets us know our connection topology and our Loop ID/AL_PA and so on.
- * You can't get anywhere without this.
+ * these commands locks may be released while this function is called.
*
- * ISPCTL_SCAN_FABRIC queries the name server (if we're on a fabric) for
- * all entities using the FC Generic Services subcommand GET ALL NEXT.
- * For each found entity, an ISPASYNC_FABRICDEV event is generated (see
- * below).
- *
- * ISPCTL_SCAN_LOOP does a local loop scan. This is only done if the connection
- * topology is NL or FL port (private or public loop). Since the Qlogic f/w
- * 'automatically' manages local loop connections, this function essentially
- * notes the arrival, departure, and possible shuffling around of local loop
- * entities. Thus for each arrival and departure this generates an isp_async
- * event of ISPASYNC_PROMENADE (see below).
+ * ... ISPCTL_RESET_BUS, int channel);
+ * Reset BUS on this channel
+ * ... ISPCTL_RESET_DEV, int channel, int target);
+ * Reset Device on this channel at this target.
+ * ... ISPCTL_ABORT_CMD, XS_T *xs);
+ * Abort active transaction described by xs.
+ * ... IPCTL_UPDATE_PARAMS);
+ * Update any operating parameters (speed, etc.)
+ * ... ISPCTL_FCLINK_TEST, int channel);
+ * Test FC link status on this channel
+ * ... ISPCTL_SCAN_FABRIC, int channel);
+ * Scan fabric on this channel
+ * ... ISPCTL_SCAN_LOOP, int channel);
+ * Scan local loop on this channel
+ * ... ISPCTL_PDB_SYNC, int channel);
+ * Synchronize port database on this channel
+ * ... ISPCTL_SEND_LIP, int channel);
+ * Send a LIP on this channel
+ * ... ISPCTL_GET_NAMES, int channel, int np, uint64_t *wwnn, uint64_t *wwpn)
+ * Get a WWNN/WWPN for this N-port handle on this channel
+ * ... ISPCTL_RUN_MBOXCMD, mbreg_t *mbp)
+ * Run this mailbox command
+ * ... ISPCTL_GET_PDB, int channel, int nphandle, isp_pdb_t *pdb)
+ * Get PDB on this channel for this N-port handle
+ * ... ISPCTL_PLOGX, isp_plcmd_t *)
+ * Performa a port login/logout
*
* ISPCTL_PDB_SYNC is somewhat misnamed. It actually is the final step, in
* order, of ISPCTL_FCLINK_TEST, ISPCTL_SCAN_FABRIC, and ISPCTL_SCAN_LOOP.
@@ -788,89 +858,48 @@ void isp_done(XS_T *);
* part of this function. It's now been separated to allow for finer control.
*/
typedef enum {
- ISPCTL_RESET_BUS, /* Reset Bus */
- ISPCTL_RESET_DEV, /* Reset Device */
- ISPCTL_ABORT_CMD, /* Abort Command */
- ISPCTL_UPDATE_PARAMS, /* Update Operating Parameters (SCSI) */
- ISPCTL_FCLINK_TEST, /* Test FC Link Status */
- ISPCTL_SCAN_FABRIC, /* (Re)scan Fabric Name Server */
- ISPCTL_SCAN_LOOP, /* (Re)scan Local Loop */
- ISPCTL_PDB_SYNC, /* Synchronize Port Database */
- ISPCTL_SEND_LIP, /* Send a LIP */
- ISPCTL_GET_PORTNAME, /* get portname from an N-port handle */
- ISPCTL_RUN_MBOXCMD, /* run a mailbox command */
- ISPCTL_TOGGLE_TMODE, /* toggle target mode */
- ISPCTL_GET_PDB, /* get a single port database entry */
- ISPCTL_PLOGX /* do a port login/logout */
+ ISPCTL_RESET_BUS,
+ ISPCTL_RESET_DEV,
+ ISPCTL_ABORT_CMD,
+ ISPCTL_UPDATE_PARAMS,
+ ISPCTL_FCLINK_TEST,
+ ISPCTL_SCAN_FABRIC,
+ ISPCTL_SCAN_LOOP,
+ ISPCTL_PDB_SYNC,
+ ISPCTL_SEND_LIP,
+ ISPCTL_GET_NAMES,
+ ISPCTL_RUN_MBOXCMD,
+ ISPCTL_GET_PDB,
+ ISPCTL_PLOGX
} ispctl_t;
-int isp_control(ispsoftc_t *, ispctl_t, void *);
-
+int isp_control(ispsoftc_t *, ispctl_t, ...);
/*
* Platform Dependent to Internal to External Control Function
- * (each platform must provide such a function)
- *
- * Assumes locks are held.
- *
- * A few notes about some of these functions:
- *
- * ISPASYNC_CHANGE_NOTIFY notifies the outer layer that a change has
- * occurred that invalidates the list of fabric devices known and/or
- * the list of known loop devices. The argument passed is a pointer
- * whose values are defined below (local loop change, name server
- * change, other). 'Other' may simply be a LIP, or a change in
- * connection topology.
- *
- * ISPASYNC_FABRIC_DEV announces the next element in a list of
- * fabric device names we're getting out of the name server. The
- * argument points to a GET ALL NEXT response structure. The list
- * is known to terminate with an entry that refers to ourselves.
- * One of the main purposes of this function is to allow outer
- * layers, which are OS dependent, to set policy as to which fabric
- * devices might actually be logged into (and made visible) later
- * at ISPCTL_PDB_SYNC time. Since there's a finite number of fabric
- * devices that we can log into (256 less 3 'reserved' for F-port
- * topologies), and fabrics can grow up to 8 million or so entries
- * (24 bits of Port Address, less a wad of reserved spaces), clearly
- * we had better let the OS determine login policy.
- *
- * ISPASYNC_PROMENADE has an argument that is a pointer to an integer which
- * is an index into the portdb in the softc ('target'). Whether that entry's
- * valid tag is set or not says whether something has arrived or departed.
- * The name refers to a favorite pastime of many city dwellers- watching
- * people come and go, talking of Michaelangelo, and so on..
- *
- * ISPASYNC_UNHANDLED_RESPONSE gives outer layers a chance to parse a
- * response queue entry not otherwise handled. The outer layer should
- * return non-zero if it handled it. The 'arg' points to an unmassaged
- * response queue entry.
*/
typedef enum {
- ISPASYNC_NEW_TGT_PARAMS, /* New Target Parameters Negotiated */
- ISPASYNC_BUS_RESET, /* Bus Was Reset */
+ ISPASYNC_NEW_TGT_PARAMS, /* SPI New Target Parameters */
+ ISPASYNC_BUS_RESET, /* All Bus Was Reset */
ISPASYNC_LOOP_DOWN, /* FC Loop Down */
ISPASYNC_LOOP_UP, /* FC Loop Up */
- ISPASYNC_LIP, /* LIP Received */
- ISPASYNC_LOOP_RESET, /* Loop Reset Received */
+ ISPASYNC_LIP, /* FC LIP Received */
+ ISPASYNC_LOOP_RESET, /* FC Loop Reset Received */
ISPASYNC_CHANGE_NOTIFY, /* FC Change Notification */
- ISPASYNC_DEV_ARRIVED, /* FC Device Arrival */
- ISPASYNC_DEV_CHANGED, /* FC Device Change */
- ISPASYNC_DEV_STAYED, /* FC Device Stayed the Same */
- ISPASYNC_DEV_GONE, /* FC Device Depart */
- ISPASYNC_TARGET_NOTIFY, /* target asynchronous notification event */
- ISPASYNC_TARGET_ACTION, /* target action requested */
- ISPASYNC_CONF_CHANGE, /* Platform Configuration Change */
- ISPASYNC_UNHANDLED_RESPONSE, /* Unhandled Response Entry */
- ISPASYNC_FW_CRASH, /* Firmware has crashed */
- ISPASYNC_FW_DUMPED, /* Firmware crashdump taken */
- ISPASYNC_FW_RESTARTED /* Firmware has been restarted */
+ ISPASYNC_DEV_ARRIVED, /* FC Device Arrived */
+ ISPASYNC_DEV_CHANGED, /* FC Device Changed */
+ ISPASYNC_DEV_STAYED, /* FC Device Stayed */
+ ISPASYNC_DEV_GONE, /* FC Device Departure */
+ ISPASYNC_TARGET_NOTIFY, /* All target async notification */
+ ISPASYNC_TARGET_ACTION, /* All target action requested */
+ ISPASYNC_FW_CRASH, /* All Firmware has crashed */
+ ISPASYNC_FW_RESTARTED /* All Firmware has been restarted */
} ispasync_t;
-int isp_async(ispsoftc_t *, ispasync_t, void *);
+void isp_async(ispsoftc_t *, ispasync_t, ...);
-#define ISPASYNC_CHANGE_PDB ((void *) 0)
-#define ISPASYNC_CHANGE_SNS ((void *) 1)
-#define ISPASYNC_CHANGE_OTHER ((void *) 2)
+#define ISPASYNC_CHANGE_PDB 0
+#define ISPASYNC_CHANGE_SNS 1
+#define ISPASYNC_CHANGE_OTHER 2
/*
* Platform Dependent Error and Debug Printout
@@ -893,9 +922,10 @@ int isp_async(ispsoftc_t *, ispasync_t, void *);
#define ISP_LOGDEBUG2 0x40 /* log most debug messages */
#define ISP_LOGDEBUG3 0x80 /* log high frequency debug messages */
#define ISP_LOGSANCFG 0x100 /* log SAN configuration */
-#define ISP_LOGTDEBUG0 0x200 /* log simple debug messages (target mode) */
-#define ISP_LOGTDEBUG1 0x400 /* log intermediate debug messages (target) */
-#define ISP_LOGTDEBUG2 0x800 /* log all debug messages (target) */
+#define ISP_LOGTINFO 0x1000 /* log informational messages (target mode) */
+#define ISP_LOGTDEBUG0 0x2000 /* log simple debug messages (target mode) */
+#define ISP_LOGTDEBUG1 0x4000 /* log intermediate debug messages (target) */
+#define ISP_LOGTDEBUG2 0x8000 /* log all debug messages (target) */
/*
* Each Platform provides it's own isposinfo substructure of the ispsoftc
@@ -904,13 +934,16 @@ int isp_async(ispsoftc_t *, ispasync_t, void *);
* Each platform must also provide the following macros/defines:
*
*
- * ISP2100_SCRLEN - length for the Fibre Channel scratch DMA area
+ * ISP_FC_SCRLEN FC scratch area DMA length
+ *
+ * ISP_MEMZERO(dst, src) platform zeroing function
+ * ISP_MEMCPY(dst, src, count) platform copying function
+ * ISP_SNPRINTF(buf, bufsize, fmt, ...) snprintf
+ * ISP_DELAY(usecs) microsecond spindelay function
+ * ISP_SLEEP(isp, usecs) microsecond sleep function
*
- * MEMZERO(dst, src) platform zeroing function
- * MEMCPY(dst, src, count) platform copying function
- * SNPRINTF(buf, bufsize, fmt, ...) snprintf
- * USEC_DELAY(usecs) microsecond spindelay function
- * USEC_SLEEP(isp, usecs) microsecond sleep function
+ * ISP_INLINE ___inline or not- depending on how
+ * good your debugger is
*
* NANOTIME_T nanosecond time type
*
@@ -921,8 +954,7 @@ int isp_async(ispsoftc_t *, ispasync_t, void *);
* NANOTIME_SUB(NANOTIME_T *, NANOTIME_T *)
* subtract two NANOTIME_T values
*
- *
- * MAXISPREQUEST(ispsoftc_t *) maximum request queue size
+ * MAXISPREQUEST(ispsoftc_t *) maximum request queue size
* for this particular board type
*
* MEMORYBARRIER(ispsoftc_t *, barrier_type, offset, size)
@@ -936,32 +968,36 @@ int isp_async(ispsoftc_t *, ispasync_t, void *);
* MBOX_NOTIFY_COMPLETE(ispsoftc_t *) notification of mbox cmd donee
* MBOX_RELEASE(ispsoftc_t *) release lock on mailbox regs
*
- * FC_SCRATCH_ACQUIRE(ispsoftc_t *) acquire lock on FC scratch area
- * FC_SCRATCH_RELEASE(ispsoftc_t *) acquire lock on FC scratch area
+ * FC_SCRATCH_ACQUIRE(ispsoftc_t *, chan) acquire lock on FC scratch area
+ * return -1 if you cannot
+ * FC_SCRATCH_RELEASE(ispsoftc_t *, chan) acquire lock on FC scratch area
*
* SCSI_GOOD SCSI 'Good' Status
* SCSI_CHECK SCSI 'Check Condition' Status
* SCSI_BUSY SCSI 'Busy' Status
* SCSI_QFULL SCSI 'Queue Full' Status
*
- * XS_T Platform SCSI transaction type (i.e., command for HBA)
- * XS_DMA_ADDR_T Platform PCI DMA Address Type
- * XS_ISP(xs) gets an instance out of an XS_T
- * XS_CHANNEL(xs) gets the channel (bus # for DUALBUS cards) ""
- * XS_TGT(xs) gets the target ""
- * XS_LUN(xs) gets the lun ""
- * XS_CDBP(xs) gets a pointer to the scsi CDB ""
- * XS_CDBLEN(xs) gets the CDB's length ""
- * XS_XFRLEN(xs) gets the associated data transfer length ""
- * XS_TIME(xs) gets the time (in milliseconds) for this command
- * XS_RESID(xs) gets the current residual count
- * XS_STSP(xs) gets a pointer to the SCSI status byte ""
- * XS_SNSP(xs) gets a pointer to the associate sense data
- * XS_SNSLEN(xs) gets the length of sense data storage
- * XS_SNSKEY(xs) dereferences XS_SNSP to get the current stored Sense Key
- * XS_TAG_P(xs) predicate of whether this command should be tagged
- * XS_TAG_TYPE(xs) which type of tag to use
- * XS_SETERR(xs) set error state
+ * XS_T Platform SCSI transaction type (i.e., command for HBA)
+ * XS_DMA_ADDR_T Platform PCI DMA Address Type
+ * XS_GET_DMA_SEG(..) Get 32 bit dma segment list value
+ * XS_GET_DMA64_SEG(..) Get 64 bit dma segment list value
+ * XS_ISP(xs) gets an instance out of an XS_T
+ * XS_CHANNEL(xs) gets the channel (bus # for DUALBUS cards) ""
+ * XS_TGT(xs) gets the target ""
+ * XS_LUN(xs) gets the lun ""
+ * XS_CDBP(xs) gets a pointer to the scsi CDB ""
+ * XS_CDBLEN(xs) gets the CDB's length ""
+ * XS_XFRLEN(xs) gets the associated data transfer length ""
+ * XS_TIME(xs) gets the time (in milliseconds) for this command
+ * XS_GET_RESID(xs) gets the current residual count
+ * XS_GET_RESID(xs, resid) sets the current residual count
+ * XS_STSP(xs) gets a pointer to the SCSI status byte ""
+ * XS_SNSP(xs) gets a pointer to the associate sense data
+ * XS_SNSLEN(xs) gets the length of sense data storage
+ * XS_SNSKEY(xs) dereferences XS_SNSP to get the current stored Sense Key
+ * XS_TAG_P(xs) predicate of whether this command should be tagged
+ * XS_TAG_TYPE(xs) which type of tag to use
+ * XS_SETERR(xs) set error state
*
* HBA_NOERROR command has no erros
* HBA_BOTCH hba botched something
@@ -979,32 +1015,31 @@ int isp_async(ispsoftc_t *, ispasync_t, void *);
*
* XS_SAVE_SENSE(xs, sp, len) save sense data
*
- * XS_SET_STATE_STAT(isp, sp, xs) platform dependent interpreter of
- * response queue entry status bits
+ * DEFAULT_FRAMESIZE(ispsoftc_t *) Default Frame Size
+ * DEFAULT_EXEC_THROTTLE(ispsoftc_t *) Default Execution Throttle
*
+ * GET_DEFAULT_ROLE(ispsoftc_t *, int) Get Default Role for a channel
+ * SET_DEFAULT_ROLE(ispsoftc_t *, int, int) Set Default Role for a channel
+ * DEFAULT_IID(ispsoftc_t *, int) Default SCSI initiator ID
+ * DEFAULT_LOOPID(ispsoftc_t *, int) Default FC Loop ID
*
- * DEFAULT_IID(ispsoftc_t *) Default SCSI initiator ID
- * DEFAULT_LOOPID(ispsoftc_t *) Default FC Loop ID
- * DEFAULT_NODEWWN(ispsoftc_t *) Default Node WWN
- * DEFAULT_PORTWWN(ispsoftc_t *) Default Port WWN
- * DEFAULT_FRAMESIZE(ispsoftc_t *) Default Frame Size
- * DEFAULT_EXEC_THROTTLE(ispsoftc_t *) Default Execution Throttle
* These establish reasonable defaults for each platform.
* These must be available independent of card NVRAM and are
* to be used should NVRAM not be readable.
*
- * ISP_NODEWWN(ispsoftc_t *) FC Node WWN to use
- * ISP_PORTWWN(ispsoftc_t *) FC Port WWN to use
+ * DEFAULT_NODEWWN(ispsoftc_t *, chan) Default FC Node WWN to use
+ * DEFAULT_PORTWWN(ispsoftc_t *, chan) Default FC Port WWN to use
+ *
+ * These defines are hooks to allow the setting of node and
+ * port WWNs when NVRAM cannot be read or is to be overriden.
+ *
+ * ACTIVE_NODEWWN(ispsoftc_t *, chan) FC Node WWN to use
+ * ACTIVE_PORTWWN(ispsoftc_t *, chan) FC Port WWN to use
*
- * These are to be used after NVRAM is read. The tags
- * in fcparam.isp_ww{n,p}n_nvram reflect the values
- * read from NVRAM (possibly corrected for card botches).
- * Each platform can take that information and override
- * it or ignore and return the Node and Port WWNs to be
- * used when sending the Qlogic f/w the Initialization
- * Control Block.
+ * After NVRAM is read, these will be invoked to get the
+ * node and port WWNs that will actually be used for this
+ * channel.
*
- * (XXX these do endian specific transformations- in transition XXX)
*
* ISP_IOXPUT_8(ispsoftc_t *, uint8_t srcval, uint8_t *dstptr)
* ISP_IOXPUT_16(ispsoftc_t *, uint16_t srcval, uint16_t *dstptr)
@@ -1020,4 +1055,61 @@ int isp_async(ispsoftc_t *, ispasync_t, void *);
* ISP_SWAP32(ispsoftc_t *, uint32_t srcval)
*/
+#ifdef ISP_TARGET_MODE
+/*
+ * The functions below are for the publicly available
+ * target mode functions that are internal to the Qlogic driver.
+ */
+
+/*
+ * This function handles new response queue entry appropriate for target mode.
+ */
+int isp_target_notify(ispsoftc_t *, void *, uint32_t *);
+
+/*
+ * This function externalizes the ability to acknowledge an Immediate Notify request.
+ */
+int isp_notify_ack(ispsoftc_t *, void *);
+
+/*
+ * This function externalized acknowledging (success/fail) an ABTS frame
+ */
+int isp_acknak_abts(ispsoftc_t *, void *, int);
+
+/*
+ * Enable/Disable/Modify a logical unit.
+ * (softc, cmd, bus, tgt, lun, cmd_cnt, inotify_cnt)
+ */
+#define DFLT_CMND_CNT 0xfe /* unmonitored */
+#define DFLT_INOT_CNT 0xfe /* unmonitored */
+int isp_lun_cmd(ispsoftc_t *, int, int, int, int, int);
+
+/*
+ * General request queue 'put' routine for target mode entries.
+ */
+int isp_target_put_entry(ispsoftc_t *isp, void *);
+
+/*
+ * General routine to put back an ATIO entry-
+ * used for replenishing f/w resource counts.
+ * The argument is a pointer to a source ATIO
+ * or ATIO2.
+ */
+int isp_target_put_atio(ispsoftc_t *, void *);
+
+/*
+ * General routine to send a final CTIO for a command- used mostly for
+ * local responses.
+ */
+int isp_endcmd(ispsoftc_t *, ...);
+#define ECMD_SVALID 0x100
+#define ECMD_TERMINATE 0x200
+
+/*
+ * Handle an asynchronous event
+ *
+ * Return nonzero if the interrupt that generated this event has been dismissed.
+ */
+int isp_target_async(ispsoftc_t *, int, int);
+#endif
#endif /* _ISPVAR_H */
OpenPOWER on IntegriCloud