summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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