diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2009-11-24 21:29:17 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2009-11-24 21:29:17 +0000 |
commit | 6d9b3a0771ef214f1cac6d243d9bd0e4a9176d5c (patch) | |
tree | cea348b87892b5b10d59e3469419971838cd289e /sys/dev/pci | |
parent | e417e1bb19ad3276619ff9d813531ecb55d3a558 (diff) |
Add event framework.
Map IR volumes & disks at discovery time in predictable manner.
From James Giannoules
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/mpii.c | 1625 |
1 files changed, 1373 insertions, 252 deletions
diff --git a/sys/dev/pci/mpii.c b/sys/dev/pci/mpii.c index 917f700932b..afac55a210d 100644 --- a/sys/dev/pci/mpii.c +++ b/sys/dev/pci/mpii.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpii.c,v 1.3 2009/11/05 03:43:18 marco Exp $ */ +/* $OpenBSD: mpii.c,v 1.4 2009/11/24 21:29:16 marco Exp $ */ /* * Copyright (c) James Giannoules * Copyright (c) 2005 David Gwynne <dlg@openbsd.org> @@ -46,7 +46,7 @@ #include <dev/biovar.h> -#define MPII_DOORBELL 0x00 +#define MPII_DOORBELL (0x00) /* doorbell read bits */ #define MPII_DOORBELL_STATE (0xf<<28) /* ioc state */ #define MPII_DOORBELL_STATE_RESET (0x0<<28) @@ -63,7 +63,7 @@ #define MPII_DOORBELL_WHOINIT_MANUFACT (0x5<<24) /* manufacturing */ #define MPII_DOORBELL_FAULT (0xffff<<0) /* fault code */ /* doorbell write bits */ -#define MPII_DOORBELL_FUNCTION_SHIFT 24 +#define MPII_DOORBELL_FUNCTION_SHIFT (24) #define MPII_DOORBELL_FUNCTION_MASK (0xff << MPII_DOORBELL_FUNCTION_SHIFT) #define MPII_DOORBELL_FUNCTION(x) \ (((x) << MPII_DOORBELL_FUNCTION_SHIFT) & MPII_DOORBELL_FUNCTION_MASK) @@ -71,20 +71,20 @@ #define MPII_DOORBELL_DWORDS_MASK (0xff << MPII_DOORBELL_DWORDS_SHIFT) #define MPII_DOORBELL_DWORDS(x) \ (((x) << MPII_DOORBELL_DWORDS_SHIFT) & MPII_DOORBELL_DWORDS_MASK) -#define MPII_DOORBELL_DATA_MASK 0xffff - -#define MPII_WRITESEQ 0x04 -#define MPII_WRITESEQ_KEY_VALUE_MASK 0x0000000f /* key value */ -#define MPII_WRITESEQ_FLUSH 0x00 -#define MPII_WRITESEQ_1 0x0f -#define MPII_WRITESEQ_2 0x04 -#define MPII_WRITESEQ_3 0x0b -#define MPII_WRITESEQ_4 0x03 -#define MPII_WRITESEQ_5 0x07 -#define MPII_WRITESEQ_6 0x0d - -#define MPII_HOSTDIAG 0x08 -#define MPII_HOSTDIAG_BDS_MASK 0x00001800 /* boot device select */ +#define MPII_DOORBELL_DATA_MASK (0xffff) + +#define MPII_WRITESEQ (0x04) +#define MPII_WRITESEQ_KEY_VALUE_MASK (0x0000000f) /* key value */ +#define MPII_WRITESEQ_FLUSH (0x00) +#define MPII_WRITESEQ_1 (0x0f) +#define MPII_WRITESEQ_2 (0x04) +#define MPII_WRITESEQ_3 (0x0b) +#define MPII_WRITESEQ_4 (0x02) +#define MPII_WRITESEQ_5 (0x07) +#define MPII_WRITESEQ_6 (0x0d) + +#define MPII_HOSTDIAG (0x08) +#define MPII_HOSTDIAG_BDS_MASK (0x00001800) /* boot device select */ #define MPII_HOSTDIAG_BDS_DEFAULT (0<<11) /* default address map, flash */ #define MPII_HOSTDIAG_BDS_HCDW (1<<11) /* host code and data window */ #define MPII_HOSTDIAG_CLEARFBS (1<<10) /* clear flash bad sig */ @@ -98,38 +98,38 @@ #define MPII_HOSTDIAG_HOLD_IOC_RESET (1<<1) /* hold ioc in reset */ #define MPII_HOSTDIAG_DIAGMEM_EN (1<<0) /* diag mem enable */ -#define MPII_DIAGRWDATA 0x10 +#define MPII_DIAGRWDATA (0x10) -#define MPII_DIAGRWADDRLOW 0x14 +#define MPII_DIAGRWADDRLOW (0x14) -#define MPII_DIAGRWADDRHIGH 0x18 +#define MPII_DIAGRWADDRHIGH (0x18) -#define MPII_INTR_STATUS 0x30 +#define MPII_INTR_STATUS (0x30) #define MPII_INTR_STATUS_SYS2IOCDB (1<<31) /* ioc written to by host */ #define MPII_INTR_STATUS_RESET (1<<30) /* physical ioc reset */ #define MPII_INTR_STATUS_REPLY (1<<3) /* reply message interrupt */ #define MPII_INTR_STATUS_IOC2SYSDB (1<<0) /* ioc write to doorbell */ -#define MPII_INTR_MASK 0x34 +#define MPII_INTR_MASK (0x34) #define MPII_INTR_MASK_RESET (1<<30) /* ioc reset intr mask */ #define MPII_INTR_MASK_REPLY (1<<3) /* reply message intr mask */ #define MPII_INTR_MASK_DOORBELL (1<<0) /* doorbell interrupt mask */ -#define MPII_DCR_DATA 0x38 +#define MPII_DCR_DATA (0x38) -#define MPII_DCR_ADDRESS 0x3C +#define MPII_DCR_ADDRESS (0x3c) -#define MPII_REPLY_FREE_HOST_INDEX 0x48 +#define MPII_REPLY_FREE_HOST_INDEX (0x48) -#define MPII_REPLY_POST_HOST_INDEX 0x6C +#define MPII_REPLY_POST_HOST_INDEX (0x6c) -#define MPII_HCB_SIZE 0x74 +#define MPII_HCB_SIZE (0x74) -#define MPII_HCB_ADDRESS_LOW 0x78 -#define MPII_HCB_ADDRESS_HIGH 0x7C +#define MPII_HCB_ADDRESS_LOW (0x78) +#define MPII_HCB_ADDRESS_HIGH (0x7c) -#define MPII_REQ_DESC_POST_LOW 0xC0 -#define MPII_REQ_DESC_POST_HIGH 0xC4 +#define MPII_REQ_DESC_POST_LOW (0xc0) +#define MPII_REQ_DESC_POST_HIGH (0xc4) /* * Scatter Gather Lists @@ -184,10 +184,10 @@ struct mpii_fw_tce { #define MPII_FUNCTION_EVENT_NOTIFICATION (0x07) #define MPII_FUNCTION_EVENT_ACK (0x08) #define MPII_FUNCTION_FW_DOWNLOAD (0x09) -#define MPII_FUNCTION_TARGET_CMD_BUFFER_POST (0x0A) -#define MPII_FUNCTION_TARGET_ASSIST (0x0B) -#define MPII_FUNCTION_TARGET_STATUS_SEND (0x0C) -#define MPII_FUNCTION_TARGET_MODE_ABORT (0x0D) +#define MPII_FUNCTION_TARGET_CMD_BUFFER_POST (0x0a) +#define MPII_FUNCTION_TARGET_ASSIST (0x0b) +#define MPII_FUNCTION_TARGET_STATUS_SEND (0x0c) +#define MPII_FUNCTION_TARGET_MODE_ABORT (0x0d) #define MPII_FUNCTION_FW_UPLOAD (0x12) #define MPII_FUNCTION_RAID_ACTION (0x15) @@ -197,12 +197,12 @@ struct mpii_fw_tce { #define MPII_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) -#define MPII_FUNCTION_SMP_PASSTHROUGH (0x1A) -#define MPII_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) -#define MPII_FUNCTION_SATA_PASSTHROUGH (0x1C) +#define MPII_FUNCTION_SMP_PASSTHROUGH (0x1a) +#define MPII_FUNCTION_SAS_IO_UNIT_CONTROL (0x1b) +#define MPII_FUNCTION_SATA_PASSTHROUGH (0x1c) -#define MPII_FUNCTION_DIAG_BUFFER_POST (0x1D) -#define MPII_FUNCTION_DIAG_RELEASE (0x1E) +#define MPII_FUNCTION_DIAG_BUFFER_POST (0x1d) +#define MPII_FUNCTION_DIAG_RELEASE (0x1e) #define MPII_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) #define MPII_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) @@ -225,7 +225,7 @@ struct mpii_fw_tce { /* reply flags */ #define MPII_REP_FLAGS_CONT (1<<7) /* continuation reply */ -#define MPII_REP_IOCSTATUS_AVAIL (1<<15) /* logging info available */ +#define MPII_REP_IOCSTATUS_AVAIL (1<<15) /* log info available */ #define MPII_REP_IOCSTATUS (0x7fff) /* status */ /* Common IOCStatus values for all replies */ @@ -256,72 +256,66 @@ struct mpii_fw_tce { #define MPII_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) #define MPII_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) #define MPII_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) -#define MPII_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) -#define MPII_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) -#define MPII_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) +#define MPII_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004a) +#define MPII_IOCSTATUS_SCSI_IOC_TERMINATED (0x004b) +#define MPII_IOCSTATUS_SCSI_EXT_TERMINATED (0x004c) /* For use by SCSI Initiator and SCSI Target end-to-end data protection */ -#define MPII_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) -#define MPII_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) -#define MPII_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) +#define MPII_IOCSTATUS_EEDP_GUARD_ERROR (0x004d) +#define MPII_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004e) +#define MPII_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004f) /* SCSI (SPI & FCP) target values */ #define MPII_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) #define MPII_IOCSTATUS_TARGET_ABORTED (0x0063) #define MPII_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) #define MPII_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) -#define MPII_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) -#define MPII_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) -#define MPII_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) -#define MPII_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) +#define MPII_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006a) +#define MPII_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006d) +#define MPII_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006e) +#define MPII_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006f) #define MPII_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) #define MPII_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) /* Serial Attached SCSI values */ #define MPII_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) #define MPII_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) /* Diagnostic Tools values */ -#define MPII_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) +#define MPII_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00a0) -#define MPII_REP_IOCLOGINFO_TYPE (0xf<<28) /* logging info type */ +#define MPII_REP_IOCLOGINFO_TYPE (0xf<<28) /* log info type */ #define MPII_REP_IOCLOGINFO_TYPE_NONE (0x0<<28) #define MPII_REP_IOCLOGINFO_TYPE_SCSI (0x1<<28) #define MPII_REP_IOCLOGINFO_TYPE_FC (0x2<<28) #define MPII_REP_IOCLOGINFO_TYPE_SAS (0x3<<28) #define MPII_REP_IOCLOGINFO_TYPE_ISCSI (0x4<<28) -#define MPII_REP_IOCLOGINFO_DATA (0x0fffffff) /* logging info data */ +#define MPII_REP_IOCLOGINFO_DATA (0x0fffffff) /* log info data */ /* event notification types */ -#define MPII_EVENT_NONE 0x00 -#define MPII_EVENT_LOG_DATA 0x01 -#define MPII_EVENT_STATE_CHANGE 0x02 -#define MPII_EVENT_UNIT_ATTENTION 0x03 -#define MPII_EVENT_IOC_BUS_RESET 0x04 -#define MPII_EVENT_EXT_BUS_RESET 0x05 -#define MPII_EVENT_RESCAN 0x06 -#define MPII_EVENT_LINK_STATUS_CHANGE 0x07 -#define MPII_EVENT_LOOP_STATE_CHANGE 0x08 -#define MPII_EVENT_LOGOUT 0x09 -#define MPII_EVENT_EVENT_CHANGE 0x0a -#define MPII_EVENT_INTEGRATED_RAID 0x0b -#define MPII_EVENT_SCSI_DEVICE_STATUS_CHANGE 0x0c -#define MPII_EVENT_ON_BUS_TIMER_EXPIRED 0x0d -#define MPII_EVENT_QUEUE_FULL 0x0e -#define MPII_EVENT_SAS_DEVICE_STATUS_CHANGE 0x0f -#define MPII_EVENT_SAS_SES 0x10 -#define MPII_EVENT_PERSISTENT_TABLE_FULL 0x11 -#define MPII_EVENT_SAS_PHY_LINK_STATUS 0x12 -#define MPII_EVENT_SAS_DISCOVERY_ERROR 0x13 -#define MPII_EVENT_IR_RESYNC_UPDATE 0x14 -#define MPII_EVENT_IR2 0x15 -#define MPII_EVENT_SAS_DISCOVERY 0x16 -#define MPII_EVENT_LOG_ENTRY_ADDED 0x21 +#define MPII_EVENT_NONE (0x00) +#define MPII_EVENT_LOG_DATA (0x01) +#define MPII_EVENT_STATE_CHANGE (0x02) +#define MPII_EVENT_HARD_RESET_RECEIVED (0x05) +#define MPII_EVENT_EVENT_CHANGE (0x0a) +#define MPII_EVENT_TASK_SET_FULL (0x0e) +#define MPII_EVENT_SAS_DEVICE_STATUS_CHANGE (0x0f) +#define MPII_EVENT_IR_OPERATION_STATUS (0x14) +#define MPII_EVENT_SAS_DISCOVERY (0x16) +#define MPII_EVENT_SAS_BROADCAST_PRIMITIVE (0x17) +#define MPII_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x18) +#define MPII_EVENT_SAS_INIT_TABLE_OVERFLOW (0x19) +#define MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x1c) +#define MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x1d) +#define MPII_EVENT_IR_VOLUME (0x1e) +#define MPII_EVENT_IR_PHYSICAL_DISK (0x1f) +#define MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x20) +#define MPII_EVENT_LOG_ENTRY_ADDED (0x21) /* messages */ -#define MPII_WHOINIT_NOONE 0x00 -#define MPII_WHOINIT_SYSTEM_BIOS 0x01 -#define MPII_WHOINIT_ROM_BIOS 0x02 -#define MPII_WHOINIT_PCI_PEER 0x03 -#define MPII_WHOINIT_HOST_DRIVER 0x04 -#define MPII_WHOINIT_MANUFACTURER 0x05 +#define MPII_WHOINIT_NOONE (0x00) +#define MPII_WHOINIT_SYSTEM_BIOS (0x01) +#define MPII_WHOINIT_ROM_BIOS (0x02) +#define MPII_WHOINIT_PCI_PEER (0x03) +#define MPII_WHOINIT_HOST_DRIVER (0x04) +#define MPII_WHOINIT_MANUFACTURER (0x05) /* page address fields */ #define MPII_PAGE_ADDRESS_FC_BTID (1<<24) /* Bus Target ID */ @@ -551,11 +545,11 @@ struct mpii_msg_portfacts_reply { u_int8_t reserved5; u_int8_t port_type; -#define MPII_PORTFACTS_PORTTYPE_INACTIVE 0x00 -#define MPII_PORTFACTS_PORTTYPE_FC 0x10 -#define MPII_PORTFACTS_PORTTYPE_ISCSI 0x20 -#define MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL 0x30 -#define MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL 0x31 +#define MPII_PORTFACTS_PORTTYPE_INACTIVE (0x00) +#define MPII_PORTFACTS_PORTTYPE_FC (0x10) +#define MPII_PORTFACTS_PORTTYPE_ISCSI (0x20) +#define MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30) +#define MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31) u_int16_t reserved6; u_int16_t max_posted_cmd_buffers; @@ -660,14 +654,14 @@ struct mpii_evt_change { struct mpii_evt_sas_phy { u_int8_t phy_num; u_int8_t link_rates; -#define MPII_EVT_SASPHY_LINK_CUR(x) (((x) & 0xf0) >> 4) -#define MPII_EVT_SASPHY_LINK_PREV(x) ((x) & 0x0f) -#define MPII_EVT_SASPHY_LINK_ENABLED 0x0 -#define MPII_EVT_SASPHY_LINK_DISABLED 0x1 -#define MPII_EVT_SASPHY_LINK_NEGFAIL 0x2 -#define MPII_EVT_SASPHY_LINK_SATAOOB 0x3 -#define MPII_EVT_SASPHY_LINK_1_5GBPS 0x8 -#define MPII_EVT_SASPHY_LINK_3_0GBPS 0x9 +#define MPII_EVT_SASPHY_LINK_CUR(x) ((x) & 0xf0) >> 4 +#define MPII_EVT_SASPHY_LINK_PREV(x) (x) & 0x0f +#define MPII_EVT_SASPHY_LINK_ENABLED (0x0) +#define MPII_EVT_SASPHY_LINK_DISABLED (0x1) +#define MPII_EVT_SASPHY_LINK_NEGFAIL (0x2) +#define MPII_EVT_SASPHY_LINK_SATAOOB (0x3) +#define MPII_EVT_SASPHY_LINK_1_5GBPS (0x8) +#define MPII_EVT_SASPHY_LINK_3_0GBPS (0x9) u_int16_t dev_handle; u_int64_t sas_addr; @@ -676,17 +670,17 @@ struct mpii_evt_sas_phy { struct mpii_evt_sas_change { u_int16_t task_tag; u_int8_t reason; -#define MPII_EVT_SASCH_REASON_SMART_DATA 0x05 -#define MPII_EVT_SASCH_REASON_UNSUPPORTED 0x07 -#define MPII_EVT_SASCH_REASON_INTERNAL_RESET 0x08 -#define MPII_EVT_SASCH_REASON_TASK_ABORT_INTERVAL 0x09 -#define MPII_EVT_SASCH_REASON_ABORT_TASK_SET_INTERVAL 0x0A -#define MPII_EVT_SASCH_REASON_CLEAR_TASK_SET_INTERVAL 0x0B -#define MPII_EVT_SASCH_REASON_QUERY_TASK_INTERVAL 0x0C -#define MPII_EVT_SASCH_REASON_ASYNC_NOTIFICATION 0x0D -#define MPII_EVT_SASCH_REASON_CMP_INTERNAL_DEV_RESET 0x0E -#define MPII_EVT_SASCH_REASON_CMP_TASK_ABORT_INTERNAL 0x0F -#define MPII_EVT_SASCH_REASON_SATA_INIT_FAILURE 0x10 +#define MPII_EVT_SASCH_REASON_SMART_DATA (0x05) +#define MPII_EVT_SASCH_REASON_UNSUPPORTED (0x07) +#define MPII_EVT_SASCH_REASON_INTERNAL_RESET (0x08) +#define MPII_EVT_SASCH_REASON_TASK_ABORT_INTERVAL (0x09) +#define MPII_EVT_SASCH_REASON_ABORT_TASK_SET_INTERVAL (0x0a) +#define MPII_EVT_SASCH_REASON_CLEAR_TASK_SET_INTERVAL (0x0b) +#define MPII_EVT_SASCH_REASON_QUERY_TASK_INTERVAL (0x0c) +#define MPII_EVT_SASCH_REASON_ASYNC_NOTIFICATION (0x0d) +#define MPII_EVT_SASCH_REASON_CMP_INTERNAL_DEV_RESET (0x0e) +#define MPII_EVT_SASCH_REASON_CMP_TASK_ABORT_INTERNAL (0x0f) +#define MPII_EVT_SASCH_REASON_SATA_INIT_FAILURE (0x10) u_int8_t reserved1; u_int8_t asc; @@ -745,8 +739,8 @@ struct mpii_msg_fwupload_request { #define MPII_FWUPLOAD_IMAGETYPE_NV_CONFIG_1 (0x07) #define MPII_FWUPLOAD_IMAGETYPE_NV_CONFIG_2 (0x08) #define MPII_FWUPLOAD_IMAGETYPE_NV_MEGARAID (0x09) -#define MPII_FWUPLOAD_IMAGETYPE_NV_COMPLETE (0x0A) -#define MPII_FWUPLOAD_IMAGETYPE_COMMON_BOOT_BLOCK (0x0B) +#define MPII_FWUPLOAD_IMAGETYPE_NV_COMPLETE (0x0a) +#define MPII_FWUPLOAD_IMAGETYPE_COMMON_BOOT_BLOCK (0x0b) u_int8_t reserved1; u_int8_t chain_offset; u_int8_t function; @@ -845,7 +839,7 @@ struct mpii_msg_scsi_io { #define MPII_SCSIIO_DIR_WRITE (0x1) #define MPII_SCSIIO_DIR_READ (0x2) -#define MPII_CDB_LEN 32 +#define MPII_CDB_LEN (32) u_int8_t cdb[MPII_CDB_LEN]; /* followed by an sgl */ @@ -921,12 +915,12 @@ struct mpii_request_descriptor { struct mpii_reply_descriptor { u_int8_t reply_flags; -#define MPII_REPLY_DESCR_FLAGS_TYPE_MASK (0x0F) +#define MPII_REPLY_DESCR_FLAGS_TYPE_MASK (0x0f) #define MPII_REPLY_DESCR_FLAGS_SCSI_IO_SUCCESS (0x00) #define MPII_REPLY_DESCR_FLAGS_ADDRESS_REPLY (0x01) #define MPII_REPLY_DESCR_FLAGS_TARGETASSIST_SUCCESS (0x02) #define MPII_REPLY_DESCR_FLAGS_TARGET_COMMAND_BUFFER (0x03) -#define MPII_REPLY_DESCR_FLAGS_UNUSED (0x0F) +#define MPII_REPLY_DESCR_FLAGS_UNUSED (0x0f) u_int8_t vf_id; /* * the following field is reply descriptor type dependent @@ -1023,8 +1017,9 @@ struct mpii_cfg_hdr { #define MPII_CONFIG_REQ_PAGE_TYPE_BIOS (0x02) #define MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL (0x08) #define MPII_CONFIG_REQ_PAGE_TYPE_MANUFACTURING (0x09) -#define MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD (0x0A) -#define MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED (0x0F) +#define MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD (0x0a) +#define MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED (0x0f) +#define MPII_CONFIG_REQ_PAGE_TYPE_DRIVER_MAPPING (0x17) } __packed; struct mpii_ecfg_hdr { @@ -1168,9 +1163,19 @@ struct mpii_cfg_ioc_pg8 { u_int16_t max_num_physical_mapped_ids; u_int16_t flags; +#define MPII_IOC_PG8_FLAGS_DA_START_SLOT_1 (1<<5) +#define MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0 (1<<4) +#define MPII_IOC_PG8_FLAGS_MAPPING_MODE_MASK (0x0000000e) +#define MPII_IOC_PG8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0<<1) +#define MPII_IOC_PG8_FLAGS_ENCLOSURE_SLOT_MAPPING (1<<1) +#define MPII_IOC_PG8_FLAGS_DISABLE_PERSISTENT_MAPPING (1<<0) +#define MPII_IOC_PG8_FLAGS_ENABLE_PERSISTENT_MAPPING (0<<0) u_int16_t reserved3; u_int16_t ir_volume_mapping_flags; +#define MPII_IOC_PG8_IRFLAGS_VOLUME_MAPPING_MODE_MASK (0x00000003) +#define MPII_IOC_PG8_IRFLAGS_LOW_VOLUME_MAPPING (0<<0) +#define MPII_IOC_PG8_IRFLAGS_HIGH_VOLUME_MAPPING (1<<0) u_int16_t reserved4; u_int32_t reserved5; @@ -1487,6 +1492,32 @@ struct mpii_cfg_sas_dev_pg0 { u_int8_t reserved; } __packed; +struct mpii_cfg_bios_pg2 { + struct mpii_cfg_hdr config_header; + + u_int32_t reserved1[6]; + + u_int8_t req_boot_device_form; +#define MPII_CFG_BIOS_PG2_DEVICE_FORM_MASK (0xf) +#define MPII_CFG_BIOS_PG2_DEVICE_FORM_NO_BOOT_DEVICE (0x0) +#define MPII_CFG_BIOS_PG2_DEVICE_FORM_SAS_WWID (0x5) +#define MPII_CFG_BIOS_PG2_DEVICE_FORM_ENCLOSURE_SLOT (0x6) +#define MPII_CFG_BIOS_PG2_DEVICE_FORM_DEVICE_NAME (0x7) + u_int8_t reserved2[3]; + + u_int32_t a; + + u_int8_t req_alt_boot_device_form; + u_int8_t reserved3[3]; + + u_int32_t b; + + u_int8_t current_boot_device_form; + u_int8_t reserved4[3]; + + u_int32_t c; +} __packed; + struct mpii_cfg_raid_config_pg0 { struct mpii_ecfg_hdr config_header; @@ -1522,22 +1553,162 @@ struct mpii_raid_config_element { u_int16_t phys_disk_dev_handle; } __packed; -/*#define MPII_DEBUG*/ +struct mpii_cfg_dpm_pg0 { + struct mpii_ecfg_hdr config_header; +#define MPII_DPM_ADDRESS_FORM_MASK (0xf0000000) +#define MPII_DPM_ADDRESS_FORM_ENTRY_RANGE (0x00000000) +#define MPII_DPM_ADDRESS_ENTRY_COUNT_MASK (0x0fff0000) +#define MPII_DPM_ADDRESS_ENTRY_COUNT_SHIFT (16) +#define MPII_DPM_ADDRESS_START_ENTRY_MASK (0x0000ffff) + + /* followed by struct mpii_dpm_entry structs */ +} __packed; + +struct mpii_dpm_entry { + u_int64_t physical_identifier; + + u_int16_t mapping_information; + u_int16_t device_index; + + u_int32_t physical_bits_mapping; + + u_int32_t reserved1; +} __packed; + +struct mpii_evt_sas_discovery { + u_int8_t flags; +#define MPII_EVENT_SAS_DISC_FLAGS_DEV_CHANGE_MASK (1<<1) +#define MPII_EVENT_SAS_DISC_FLAGS_DEV_CHANGE_NO_CHANGE (0<<1) +#define MPII_EVENT_SAS_DISC_FLAGS_DEV_CHANGE_CHANGE (1<<1) +#define MPII_EVENT_SAS_DISC_FLAGS_DISC_IN_PROG_MASK (1<<0) +#define MPII_EVENT_SAS_DISC_FLAGS_DISC_NOT_IN_PROGRESS (1<<0) +#define MPII_EVENT_SAS_DISC_FLAGS_DISC_IN_PROGRESS (0<<0) + u_int8_t reason_code; +#define MPII_EVENT_SAS_DISC_REASON_CODE_STARTED (0x01) +#define MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED (0x02) + u_int8_t physical_port; + u_int8_t reserved1; + + u_int32_t discovery_status; +/* lots of defines go in here */ +} __packed; + +struct mpii_evt_ir_physical_disk { + u_int16_t reserved1; + u_int8_t reason_code; +#define MPII_EVENT_IR_PD_RC_SETTINGS_CHANGED (0x01) +#define MPII_EVENT_IR_PD_RC_STATUS_FLAGS_CHANGED (0x02) +#define MPII_EVENT_IR_PD_RC_STATUS_CHANGED (0x03) + u_int8_t phys_disk_num; + + u_int16_t phys_disk_dev_handle; + u_int16_t reserved2; + + u_int16_t slot; + u_int16_t enclosure_handle; + + u_int32_t new_value; + u_int32_t previous_value; +} __packed; + +struct mpii_evt_sas_topo_change_list { + u_int16_t enclosure_handle; + u_int16_t expander_dev_handle; + + u_int8_t num_phys; + u_int8_t reserved1[3]; + + u_int8_t num_entries; + u_int8_t start_phy_num; + u_int8_t exp_status; +#define MPII_EVENT_SAS_TOPO_ES_ADDED (0x01) +#define MPII_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02) +#define MPII_EVENT_SAS_TOPO_ES_RESPONDING (0x03) +#define MPII_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04) + u_int8_t physical_port; + + /* followed by num_entries number of struct mpii_evt_phy_entry */ +} __packed; + +struct mpii_evt_phy_entry { + u_int16_t attached_dev_handle; + u_int8_t link_rate; +#define MPII_EVENT_SAS_TOPO_LR_CURRENT_LINK_RATE_MASK (0xf0) +#define MPII_EVENT_SAS_TOPO_LR_CURRENT_LINK_RATE_SHIFT (4) +#define MPII_EVENT_SAS_TOPO_LR_PREVIOUS_LINK_RATE_MASK (0x0f) +#define MPII_EVENT_SAS_TOPO_LR_PHY_EN_UNKNOWN_RATE (0x0) +#define MPII_EVENT_SAS_TOPO_LR_PHY_DISABLE (0x1) +#define MPII_EVENT_SAS_TOPO_LR_PHY_EN_FAIL_SPEED_NEG (0x2) +#define MPII_EVENT_SAS_TOPO_LR_PHY_EN_SATA_OOB_COMPLETE (0x3) +#define MPII_EVENT_SAS_TOPO_LR_PHY_EN_SATA_PORT_SEL (0x4) +#define MPII_EVENT_SAS_TOPO_LR_PHY_EN_SMP_RESET_IN_PROG (0x5) +#define MPII_EVENT_SAS_TOPO_LR_PHY_EN_1_5_GBPS (0x8) +#define MPII_EVENT_SAS_TOPO_LR_PHY_EN_3_0_GBPS (0x9) +#define MPII_EVENT_SAS_TOPO_LR_PHY_EN_6_0_GBPS (0xa) + u_int8_t phy_status; +#define MPII_EVENT_SAS_TOPO_PS_RC_MASK (0x0f) +#define MPII_EVENT_SAS_TOPO_PS_RC_TARG_ADDED (0x01) +#define MPII_EVENT_SAS_TOPO_PS_RC_TARG_NO_RESPOND_MISS (0x02) +#define MPII_EVENT_SAS_TOPO_PS_RC_PHY_LINK_STATE_CHANGE (0x03) +#define MPII_EVENT_SAS_TOPO_PS_RC_PHY_LINK_STATE_NOCHNG (0x04) +#define MPII_EVENT_SAS_TOPO_PS_RC_WITHIN_DELAY_TIMER (0x05) +#define MPII_EVENT_SAS_TOPO_PS_PHY_VACANT_MASK (0x80) +#define MPII_EVENT_SAS_TOPO_PS_PHY_VACANT_NOT_VACANT (0x00) +#define MPII_EVENT_SAS_TOOP_PS_PHY_VACANT_ACCESS_DENIED (0x80) +} __packed; + +struct mpii_evt_ir_cfg_change_list { + u_int8_t num_elements; + u_int16_t reserved; + u_int8_t config_num; + + u_int32_t flags; +#define MPII_EVT_IR_CFG_CHANGE_LIST_FLAGS_CFG_MASK (0x1) +#define MPII_EVT_IR_CFG_CHANGE_LIST_FLAGS_CFG_NATIVE (0) +#define MPII_EVT_IR_CFG_CHANGE_LIST_FLAGS_CFG_FOREIGN (1) + + /* followed by num_elements struct mpii_evt_ir_cfg_elements */ +} __packed; + +struct mpii_evt_ir_cfg_element { + u_int16_t element_flags; +#define MPII_EVT_IR_CFG_ELEMENT_EF_ELEMENT_TYPE_MASK (0xf) +#define MPII_EVT_IR_CFG_ELEMENT_EF_ELEMENT_TYPE_VOLUME (0x0) +#define MPII_EVT_IR_CFG_ELEMENT_EF_ELEMENT_TYPE_VOL_PD (0x1) +#define MPII_EVT_IR_CFG_ELEMENT_EF_ELEMENT_TYPE_HSP_PD (0x2) + u_int16_t vol_dev_handle; + + u_int8_t reason_code; +#define MPII_EVT_IR_CFG_ELEMENT_RC_ADDED (0x01) +#define MPII_EVT_IR_CFG_ELEMENT_RC_REMOVED (0x02) +#define MPII_EVT_IR_CFG_ELEMENT_RC_NO_CHANGE (0x03) +#define MPII_EVT_IR_CFG_ELEMENT_RC_HIDE (0x04) +#define MPII_EVT_IR_CFG_ELEMENT_RC_UNHIDE (0x05) +#define MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_CREATED (0x06) +#define MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_DELETED (0x07) +#define MPII_EVT_IR_CFG_ELEMENT_RC_PD_CREATED (0x08) +#define MPII_EVT_IR_CFG_ELEMENT_RC_PD_DELETED (0x09) + u_int8_t phys_disk_num; + u_int16_t phys_disk_dev_handle; +} __packed; + +/* #define MPII_DEBUG */ #ifdef MPII_DEBUG #define DPRINTF(x...) do { if (mpii_debug) printf(x); } while(0) #define DNPRINTF(n,x...) do { if (mpii_debug & (n)) printf(x); } while(0) -#define MPII_D_CMD 0x0001 -#define MPII_D_INTR 0x0002 -#define MPII_D_MISC 0x0004 -#define MPII_D_DMA 0x0008 -#define MPII_D_IOCTL 0x0010 -#define MPII_D_RW 0x0020 -#define MPII_D_MEM 0x0040 -#define MPII_D_CCB 0x0080 -#define MPII_D_PPR 0x0100 -#define MPII_D_RAID 0x0200 -#define MPII_D_EVT 0x0400 -#define MPII_D_CFG 0x0800 +#define MPII_D_CMD (0x0001) +#define MPII_D_INTR (0x0002) +#define MPII_D_MISC (0x0004) +#define MPII_D_DMA (0x0008) +#define MPII_D_IOCTL (0x0010) +#define MPII_D_RW (0x0020) +#define MPII_D_MEM (0x0040) +#define MPII_D_CCB (0x0080) +#define MPII_D_PPR (0x0100) +#define MPII_D_RAID (0x0200) +#define MPII_D_EVT (0x0400) +#define MPII_D_CFG (0x0800) +#define MPII_D_MAP (0x1000) uint32_t mpii_debug = 0 | MPII_D_CMD @@ -1552,24 +1723,25 @@ uint32_t mpii_debug = 0 | MPII_D_RAID | MPII_D_EVT | MPII_D_CFG + | MPII_D_MAP ; #else #define DPRINTF(x...) #define DNPRINTF(n,x...) #endif -#define MPII_REQUEST_SIZE 512 -#define MPII_REPLY_SIZE 128 -#define MPII_REPLY_COUNT (PAGE_SIZE / MPII_REPLY_SIZE) +#define MPII_REQUEST_SIZE (512) +#define MPII_REPLY_SIZE (128) +#define MPII_REPLY_COUNT PAGE_SIZE / MPII_REPLY_SIZE /* * this is the max number of sge's we can stuff in a request frame: * sizeof(scsi_io) + sizeof(sense) + sizeof(sge) * 32 = MPII_REQUEST_SIZE */ -#define MPII_MAX_SGL 32 +#define MPII_MAX_SGL (32) -#define MPII_MAX_REQUEST_CREDIT 500 -#define MPII_MAX_REPLY_POST_QDEPTH 128 +#define MPII_MAX_REQUEST_CREDIT (500) +#define MPII_MAX_REPLY_POST_QDEPTH (128) struct mpii_dmamem { bus_dmamap_t mdm_map; @@ -1577,9 +1749,9 @@ struct mpii_dmamem { size_t mdm_size; caddr_t mdm_kva; }; -#define MPII_DMA_MAP(_mdm) ((_mdm)->mdm_map) -#define MPII_DMA_DVA(_mdm) ((_mdm)->mdm_map->dm_segs[0].ds_addr) -#define MPII_DMA_KVA(_mdm) ((void *)(_mdm)->mdm_kva) +#define MPII_DMA_MAP(_mdm) (_mdm)->mdm_map +#define MPII_DMA_DVA(_mdm) (_mdm)->mdm_map->dm_segs[0].ds_addr +#define MPII_DMA_KVA(_mdm) (void *)(_mdm)->mdm_kva struct mpii_ccb_bundle { struct mpii_msg_scsi_io mcb_io; /* sgl must follow */ @@ -1594,6 +1766,46 @@ struct mpii_rcb { u_int32_t rcb_reply_dva; }; +struct mpii_device { + + RB_ENTRY(mpii_device) rb_entry; + + u_int16_t dev_handle; + u_int8_t phy_num; + u_int8_t type; +#define MPII_DEV_TYPE_PD (0x00) +#define MPII_DEV_TYPE_VD_PD (0x01) +#define MPII_DEV_TYPE_VD (0x02) + + u_int16_t enclosure_handle; + + u_int16_t expander_dev_handle; + u_int8_t physical_port; + + u_int32_t wwid; + + u_int32_t flags; +#define MPII_DEV_HIDDEN (1<<0) +#define MPII_DEV_INTERFACE_SAS (1<<4) +#define MPII_DEV_INTERFACE_SATA (1<<5) +#define MPII_DEV_SCSI_ML_ATTACH (1<<8) +#define MPII_DEV_UNUSED (1<<31) +}; + +int mpii_dev_cmp(struct mpii_device *, struct mpii_device *); + +int +mpii_dev_cmp(struct mpii_device *a, struct mpii_device *b) +{ + return (a->dev_handle < b->dev_handle ? -1 : + a->dev_handle > b->dev_handle); +} + +RB_HEAD(mpii_dev_tree, mpii_device) mpii_dev_head = + RB_INITIALIZER(&mpii_dev_head); +RB_PROTOTYPE(mpii_dev_tree, mpii_device, rb_entry, mpii_dev_cmp) +RB_GENERATE(mpii_dev_tree, mpii_device, rb_entry, mpii_dev_cmp) + struct mpii_ccb { struct mpii_softc *ccb_sc; int ccb_smid; @@ -1629,6 +1841,8 @@ struct mpii_softc { struct scsibus_softc *sc_scsibus; + struct mpii_device **sc_mpii_dev; + bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; bus_size_t sc_ios; @@ -1643,9 +1857,28 @@ struct mpii_softc { int sc_first_sgl_len; int sc_chain_len; int sc_max_sgl_len; + u_int8_t sc_ir_firmware; - - int sc_buswidth; + u_int8_t sc_ioc_event_replay; + u_int16_t sc_max_enclosures; + u_int16_t sc_max_expanders; + u_int8_t sc_max_volumes; + u_int16_t sc_max_devices; + u_int16_t sc_max_dpm_entries; + u_int8_t sc_dpm_enabled; + u_int8_t sc_num_reserved_entries; + u_int8_t sc_reserve_tid0; + u_int16_t sc_vd_id_low; + u_int16_t sc_vd_id_hi; + u_int16_t sc_pd_id_start; + u_int16_t sc_vd_count; + u_int8_t sc_num_channels; + /* XXX not sure these below will stay */ + u_int8_t sc_num_enclosure_table_entries; + u_int32_t sc_pending_map_events; + u_int8_t sc_tracking_map_events; + int sc_discovery_in_progress; + /* end list of likely to be cut entries */ int sc_target; int sc_ioc_number; u_int8_t sc_vf_id; @@ -1675,8 +1908,10 @@ struct mpii_softc { struct rwlock sc_lock; struct mpii_cfg_hdr sc_cfg_hdr; struct mpii_cfg_ioc_pg2 *sc_vol_page; - struct mpii_cfg_raid_vol *sc_vol_list; + struct mpii_cfg_raid_vol *sc_vol_list; struct mpii_cfg_raid_vol_pg0 *sc_rpg0; + struct mpii_cfg_dpm_pg0 *sc_dpm_pg0; + struct mpii_cfg_bios_pg2 *sc_bios_pg2; struct ksensor *sc_sensors; struct ksensordev sc_sensordev; @@ -1839,7 +2074,7 @@ int mpii_scsi_ioctl(struct scsi_link *, u_long, caddr_t, struct scsi_adapter mpii_switch = { mpii_scsi_cmd, mpii_minphys, - NULL, + mpii_scsi_probe, /* XXX JPG scsi_probe may prove useful for mapping nonsense */ NULL, NULL }; @@ -1859,6 +2094,7 @@ struct mpii_ccb *mpii_get_ccb(struct mpii_softc *); void mpii_put_ccb(struct mpii_softc *, struct mpii_ccb *); int mpii_alloc_replies(struct mpii_softc *); int mpii_alloc_queues(struct mpii_softc *); +int mpii_alloc_dev(struct mpii_softc *); void mpii_push_reply(struct mpii_softc *, u_int32_t); void mpii_push_replies(struct mpii_softc *); @@ -1898,12 +2134,23 @@ int mpii_cfg_coalescing(struct mpii_softc *); /* void mpii_get_raid(struct mpii_softc *); int mpii_fwupload(struct mpii_softc *); - +*/ int mpii_eventnotify(struct mpii_softc *); void mpii_eventnotify_done(struct mpii_ccb *); void mpii_eventack(struct mpii_softc *, struct mpii_msg_event_reply *); void mpii_eventack_done(struct mpii_ccb *); +void mpii_event_process(struct mpii_softc *, + struct mpii_msg_reply *); +void mpii_event_process_sas_discovery(struct mpii_softc *, + struct mpii_msg_event_reply *); +void mpii_event_process_sas_topo_change(struct mpii_softc *, + struct mpii_msg_event_reply *); +void mpii_event_process_ir_cfg_change_list(struct mpii_softc *, + struct mpii_msg_event_reply *); +void mpii_event_process_ir_phys_disk(struct mpii_softc *, + struct mpii_msg_event_reply *); +/* void mpii_evt_sas(void *, void *); */ int mpii_req_cfg_header(struct mpii_softc *, u_int8_t, @@ -1911,8 +2158,15 @@ int mpii_req_cfg_header(struct mpii_softc *, u_int8_t, int mpii_req_cfg_page(struct mpii_softc *, u_int32_t, int, void *, int, void *, size_t); -void mpii_get_ioc_pg8(struct mpii_softc *); +int mpii_get_ioc_pg8(struct mpii_softc *); void mpii_get_raid_config_pg0(struct mpii_softc *); +int mpii_get_dpm(struct mpii_softc *); +int mpii_get_dpm_pg0(struct mpii_softc *, struct mpii_cfg_dpm_pg0 *); +int mpii_get_bios_pg2(struct mpii_softc *); + +int mpii_dev_reorder(struct mpii_softc *); +void mpii_reorder_vds(struct mpii_softc *); +void mpii_reorder_boot_device(struct mpii_softc *); #if NBIO > 0 int mpii_bio_get_pg0_raid(struct mpii_softc *, int); @@ -1953,15 +2207,23 @@ void mpii_refresh_sensors(void *); #define mpii_wait_db_ack(s) mpii_wait_eq((s), MPII_INTR_STATUS, \ MPII_INTR_STATUS_SYS2IOCDB, 0) +#define MPII_PG_EXTENDED (1<<0) +#define MPII_PG_POLL (1<<1) +#define MPII_PG_FMT "\020" "\002POLL" "\001EXTENDED" + #define mpii_cfg_header(_s, _t, _n, _a, _h) \ - mpii_req_cfg_header((_s), (_t), (_n), (_a), 0, (_h)) + mpii_req_cfg_header((_s), (_t), (_n), (_a), \ + MPII_PG_POLL, (_h)) #define mpii_ecfg_header(_s, _t, _n, _a, _h) \ - mpii_req_cfg_header((_s), (_t), (_n), (_a), 1, (_h)) + mpii_req_cfg_header((_s), (_t), (_n), (_a), \ + MPII_PG_POLL|MPII_PG_EXTENDED, (_h)) #define mpii_cfg_page(_s, _a, _h, _r, _p, _l) \ - mpii_req_cfg_page((_s), (_a), 0, (_h), (_r), (_p), (_l)) + mpii_req_cfg_page((_s), (_a), MPII_PG_POLL, \ + (_h), (_r), (_p), (_l)) #define mpii_ecfg_page(_s, _a, _h, _r, _p, _l) \ - mpii_req_cfg_page((_s), (_a), 1, (_h), (_r), (_p), (_l)) + mpii_req_cfg_page((_s), (_a), MPII_PG_POLL|MPII_PG_EXTENDED, \ + (_h), (_r), (_p), (_l)) int mpii_attach(struct mpii_softc *sc) @@ -2003,7 +2265,7 @@ mpii_attach(struct mpii_softc *sc) if (mpii_iocinit(sc) != 0) { printf("%s: unable to send iocinit\n", DEVNAME(sc)); - goto free_ccbs; + goto free_queues; } if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE, @@ -2011,7 +2273,7 @@ mpii_attach(struct mpii_softc *sc) printf("%s: state: 0x%08x\n", DEVNAME(sc), mpii_read_db(sc) & MPII_DOORBELL_STATE); printf("%s: operational state timeout\n", DEVNAME(sc)); - goto free_ccbs; + goto free_queues; } mpii_push_replies(sc); @@ -2019,26 +2281,69 @@ mpii_attach(struct mpii_softc *sc) if (mpii_portfacts(sc) != 0) { printf("%s: unable to get portfacts\n", DEVNAME(sc)); - goto free_replies; + goto free_queues; } + if (mpii_get_ioc_pg8(sc) != 0) { + printf("%s: unable to get ioc page 8\n", DEVNAME(sc)); + goto free_queues; + } + + if (mpii_get_dpm(sc) != 0) { + printf("%s: unable to get driver persistent mapping\n", + DEVNAME(sc)); + goto free_queues; + } + + if (mpii_cfg_coalescing(sc) != 0) { + printf("%s: unable to configure coalescing\n", DEVNAME(sc)); + goto free_dpm; + } + + /* XXX bail on unsupported porttype? */ + if ((sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL) || + (sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL)) { + if (mpii_eventnotify(sc) != 0) { + printf("%s: unable to enable events\n", DEVNAME(sc)); + goto free_dpm; + } + } + + if (mpii_alloc_dev(sc) != 0) { + printf("%s: unable to allocate memory for mpii_dev\n", + DEVNAME(sc)); + goto free_dpm; + } + + /* enable interrupts */ + mpii_write(sc, MPII_INTR_MASK, MPII_INTR_MASK_DOORBELL + | MPII_INTR_MASK_RESET); + if (mpii_portenable(sc) != 0) { printf("%s: unable to enable port\n", DEVNAME(sc)); - goto free_replies; + goto free_dev; + } /* assume all discovery events are complete by now */ + + if (sc->sc_discovery_in_progress) + printf("%s: warning: discovery still in progress\n", + DEVNAME(sc)); + + if (mpii_get_bios_pg2(sc) != 0) { + printf("%s: unable to get bios page 2\n", DEVNAME(sc)); + goto free_dev; } - mpii_get_ioc_pg8(sc); - mpii_get_raid_config_pg0(sc); - - if (mpii_cfg_coalescing(sc) != 0) - /* this is fatal in mpi */ - printf("%s: unable to configure coalescing\n", DEVNAME(sc)); + if (mpii_dev_reorder(sc) != 0) { + /* error already printed */ + goto free_bios_pg2; + } - /* XXX JPG not yet implemented + /* XXX if (mpii_fwupload(sc) != 0) { printf("%s: unabel to upload firmware\n", DEVNAME(sc)); goto free_replies; - }*/ + } + */ rw_init(&sc->sc_lock, "mpii_lock"); @@ -2047,8 +2352,8 @@ mpii_attach(struct mpii_softc *sc) sc->sc_link.adapter = &mpii_switch; sc->sc_link.adapter_softc = sc; sc->sc_link.adapter_target = sc->sc_target; - sc->sc_link.adapter_buswidth = sc->sc_buswidth; - sc->sc_link.openings = sc->sc_request_depth / sc->sc_buswidth; + sc->sc_link.adapter_buswidth = sc->sc_max_devices; + sc->sc_link.openings = sc->sc_request_depth / sc->sc_max_devices; bzero(&saa, sizeof(saa)); saa.saa_sc_link = &sc->sc_link; @@ -2057,18 +2362,28 @@ mpii_attach(struct mpii_softc *sc) sc->sc_scsibus = (struct scsibus_softc *) config_found(&sc->sc_dev, &saa, scsiprint); - /* XXX JPG here we need to: - * - * get raid pages - * do whatever is necessary for MPI2 host mapping - * update our array/RB tree for target -> dev_handle mapping - */ + return (0); - /* enable interrupts */ - mpii_write(sc, MPII_INTR_MASK, MPII_INTR_MASK_DOORBELL - | MPII_INTR_MASK_RESET); +free_bios_pg2: + if (sc->sc_bios_pg2) + free(sc->sc_bios_pg2, M_TEMP); - return (0); +free_dev: + if (sc->sc_mpii_dev) + free(sc->sc_mpii_dev, M_DEVBUF); + +free_dpm: + if (sc->sc_dpm_pg0) + free(sc->sc_dpm_pg0, M_DEVBUF); + +free_queues: + bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq), + 0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD); + mpii_dmamem_free(sc, sc->sc_reply_freeq); + + bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq), + 0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD); + mpii_dmamem_free(sc, sc->sc_reply_postq); free_replies: bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies), @@ -2229,6 +2544,30 @@ mpii_minphys(struct buf *bp, struct scsi_link *sl) minphys(bp); } +int +mpii_scsi_probe(struct scsi_link *link) +{ + struct mpii_softc *sc = link->adapter_softc; + struct mpii_device *device; + u_int8_t flags; + + if ((sc->sc_porttype != MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL) && + (sc->sc_porttype != MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL)) + return (1); + + if (sc->sc_mpii_dev[link->target] == NULL) + return (1); + + device = (struct mpii_device *)sc->sc_mpii_dev[link->target]; + flags = device->flags; + if ((flags & MPII_DEV_UNUSED) || (flags & MPII_DEV_HIDDEN)) + return (1); + + sc->sc_mpii_dev[link->target]->flags |= MPII_DEV_SCSI_ML_ATTACH; + + return (0); +} + u_int32_t mpii_read(struct mpii_softc *sc, bus_size_t r) { @@ -2263,7 +2602,7 @@ mpii_wait_eq(struct mpii_softc *sc, bus_size_t r, u_int32_t mask, DNPRINTF(MPII_D_RW, "%s: mpii_wait_eq %#x %#x %#x\n", DEVNAME(sc), r, mask, target); - for (i = 0; i < 10000; i++) { + for (i = 0; i < 15000; i++) { if ((mpii_read(sc, r) & mask) == target) return (0); delay(1000); @@ -2281,7 +2620,7 @@ mpii_wait_ne(struct mpii_softc *sc, bus_size_t r, u_int32_t mask, DNPRINTF(MPII_D_RW, "%s: mpii_wait_ne %#x %#x %#x\n", DEVNAME(sc), r, mask, target); - for (i = 0; i < 10000; i++) { + for (i = 0; i < 15000; i++) { if ((mpii_read(sc, r) & mask) != target) return (0); delay(1000); @@ -2321,11 +2660,18 @@ mpii_init(struct mpii_softc *sc) return (0); case MPII_DOORBELL_STATE_OPER: + DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is oper\n", + DEVNAME(sc)); + if (sc->sc_ioc_event_replay) + mpii_reset_soft(sc); + else + mpii_reset_hard(sc); + break; + case MPII_DOORBELL_STATE_FAULT: DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is being " - "reset\n" , DEVNAME(sc)); - if (mpii_reset_soft(sc) != 0) - mpii_reset_hard(sc); + "reset hard\n" , DEVNAME(sc)); + mpii_reset_hard(sc); break; case MPII_DOORBELL_STATE_RESET: @@ -2348,7 +2694,6 @@ mpii_reset_soft(struct mpii_softc *sc) DNPRINTF(MPII_D_MISC, "%s: mpii_reset_soft\n", DEVNAME(sc)); if (mpii_read_db(sc) & MPII_DOORBELL_INUSE) { - printf("db in use\n"); return (1); } @@ -2387,11 +2732,13 @@ mpii_reset_hard(struct mpii_softc *sc) mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_5); mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_6); - delay(100); - if ((mpii_read(sc, MPII_HOSTDIAG) & MPII_HOSTDIAG_DWRE) == 0) + if ((mpii_read(sc, MPII_HOSTDIAG) & MPII_HOSTDIAG_DWRE) == 0) { + DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard failure to enable " + "diagnostic read/write\n", DEVNAME(sc)); return(1); + } /* reset ioc */ mpii_write(sc, MPII_HOSTDIAG, MPII_HOSTDIAG_RESET_ADAPTER); @@ -2601,12 +2948,16 @@ mpii_iocfacts(struct mpii_softc *sc) sc->sc_ioc_number = ifp.ioc_number; sc->sc_vf_id = ifp.vf_id; - /* XXX JPG should this be max targets + max vol from cfg page ?? */ - sc->sc_buswidth = (ifp.max_targets == 0) ? 256 : - letoh16(ifp.max_targets); sc->sc_num_ports = ifp.number_of_ports; sc->sc_ir_firmware = (letoh32(ifp.ioc_capabilities) & MPII_IOCFACTS_CAPABILITY_INTEGRATED_RAID) ? 1 : 0; + sc->sc_ioc_event_replay = (letoh32(ifp.ioc_capabilities) & + MPII_IOCFACTS_CAPABILITY_EVENT_REPLAY) ? 1 : 0; + sc->sc_max_enclosures = letoh16(ifp.max_enclosures); + sc->sc_max_expanders = letoh16(ifp.max_sas_expanders); + sc->sc_max_volumes = ifp.max_volumes; + sc->sc_max_devices = ifp.max_volumes + letoh16(ifp.max_targets); + sc->sc_num_channels = 1; sc->sc_request_depth = MIN(letoh16(ifp.request_credit), MPII_MAX_REQUEST_CREDIT); @@ -2828,7 +3179,7 @@ mpii_portfacts(struct mpii_softc *sc) letoh16(pfp->max_posted_cmd_buffers)); sc->sc_porttype = pfp->port_type; - /* no such field in MPI2 .... but the dilemma is what + /* XXX JPG no such field in MPI2 .... but the dilemma is what * to return to sc_link.adapter_target ... is -1 acceptable? fake 255? if (sc->sc_target == -1) sc->sc_target = letoh16(pfp->port_scsi_id); @@ -2842,6 +3193,41 @@ err: return (rv); } +void +mpii_eventack(struct mpii_softc *sc, struct mpii_msg_event_reply *enp) +{ + struct mpii_ccb *ccb; + struct mpii_msg_eventack_request *eaq; + + ccb = mpii_get_ccb(sc); + if (ccb == NULL) { + DNPRINTF(MPII_D_EVT, "%s: mpii_eventack ccb_get\n", DEVNAME(sc)); + return; + } + + ccb->ccb_done = mpii_eventack_done; + eaq = ccb->ccb_cmd; + + eaq->function = MPII_FUNCTION_EVENT_ACK; + + eaq->event = enp->event; + eaq->event_context = enp->event_context; + + mpii_start(sc, ccb); + return; +} + +void +mpii_eventack_done(struct mpii_ccb *ccb) +{ + struct mpii_softc *sc = ccb->ccb_sc; + + DNPRINTF(MPII_D_EVT, "%s: event ack done\n", DEVNAME(sc)); + + mpii_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); + mpii_put_ccb(sc, ccb); +} + int mpii_portenable(struct mpii_softc *sc) { @@ -2886,6 +3272,34 @@ mpii_portenable(struct mpii_softc *sc) } int +mpii_dev_reorder(struct mpii_softc *sc) +{ + if ((sc->sc_ir_firmware) && (sc->sc_vd_count)) + mpii_reorder_vds(sc); + + if (sc->sc_reserve_tid0) + mpii_reorder_boot_device(sc); + + return (0); +} + +void +mpii_reorder_vds(struct mpii_softc *sc) +{ + /* XXX need to implement + * ideas: VD creation order (still not sure what data to key off of), + * member PD slot IDs, + * random fun + */ +} + +void +mpii_reorder_boot_device(struct mpii_softc *sc) +{ + /* mpii_get_boot_dev(sc) */ +} + +int mpii_cfg_coalescing(struct mpii_softc *sc) { struct mpii_cfg_hdr hdr; @@ -2926,6 +3340,440 @@ mpii_cfg_coalescing(struct mpii_softc *sc) return (0); } +int +mpii_eventnotify(struct mpii_softc *sc) +{ + struct mpii_ccb *ccb; + struct mpii_msg_event_request *enq; + int s; + + s = splbio(); + ccb = mpii_get_ccb(sc); + splx(s); + if (ccb == NULL) { + DNPRINTF(MPII_D_MISC, "%s: mpii_eventnotify ccb_get\n", + DEVNAME(sc)); + return (1); + } + + ccb->ccb_done = mpii_eventnotify_done; + enq = ccb->ccb_cmd; + + enq->function = MPII_FUNCTION_EVENT_NOTIFICATION; + + /* enable reporting of the following events: + * + * MPII_EVENT_SAS_DISCOVERY + * XXX remove MPII_EVENT_SAS_BROADCAST_PRIMITIVE + * MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST + * MPII_EVENT_SAS_DEVICE_STATUS_CHANGE + * MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE + * MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST + * MPII_EVENT_IR_VOLUME + * MPII_EVENT_IR_PHYSICAL_DISK + * MPII_EVENT_IR_OPERATION_STATUS + * MPII_EVENT_TASK_SET_FULL + * MPII_EVENT_LOG_ENTRY_ADDED + */ + + /* XXX dynamically build event mask */ + enq->event_masks[0] = htole32(0x0f2f3fff); + enq->event_masks[1] = htole32(0xfffffffc); + enq->event_masks[2] = htole32(0xffffffff); + enq->event_masks[3] = htole32(0xffffffff); + + mpii_start(sc, ccb); + + return (0); +} + +void +mpii_event_process_ir_cfg_change_list(struct mpii_softc *sc, + struct mpii_msg_event_reply *enp) +{ + struct mpii_evt_ir_cfg_change_list *ccl; + struct mpii_evt_ir_cfg_element *ce; + struct mpii_device *device; //, n; + u_int16_t type; + u_int32_t flags; + int i, volid; + + ccl = (struct mpii_evt_ir_cfg_change_list *)(enp + 1); + + flags = letoh32(ccl->flags); + + DNPRINTF(MPII_D_MAP, "%s: mpii_event_process_ir_cfg_change\n", + DEVNAME(sc)); + DNPRINTF(MPII_D_MAP," %s: flags: 0x%08x num_elements: %d\n", + DEVNAME(sc), flags, ccl->num_elements); + + if ((flags & MPII_EVT_IR_CFG_CHANGE_LIST_FLAGS_CFG_MASK) == + MPII_EVT_IR_CFG_CHANGE_LIST_FLAGS_CFG_FOREIGN) + /* bail on foreign configurations */ + return; + + if (ccl->num_elements == 0) + return; + + ce = (struct mpii_evt_ir_cfg_element *)(ccl + 1); + + for (i = 0; i < ccl->num_elements; i++, ce++) { + + for (volid = 0; volid < sc->sc_max_devices; volid++) + + type = (letoh16(ce->element_flags) & + MPII_EVT_IR_CFG_ELEMENT_EF_ELEMENT_TYPE_MASK); + + switch (type) { + case MPII_EVT_IR_CFG_ELEMENT_EF_ELEMENT_TYPE_VOLUME: + switch (ce->reason_code) { + case MPII_EVT_IR_CFG_ELEMENT_RC_ADDED: + case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_CREATED: + /* XXX check for exceeding boundaries */ + volid = sc->sc_vd_id_low + sc->sc_vd_count; + + /* do magic to map vol dev_handle to TID */ + DNPRINTF(MPII_D_MAP, "%s: mapping: attaching " + "vol_dev_handle: 0x%04x to volid %d\n", + DEVNAME(sc), letoh16(ce->vol_dev_handle), + volid); + + if (sc->sc_mpii_dev[volid] == NULL) { + device = malloc(sizeof(struct mpii_device), + M_DEVBUF, M_ZERO); + if (device == NULL) { + printf("%s: mpii_event_ir_cfg_change_list " + "unable to allocate mpii_device\n", + DEVNAME(sc)); + continue; + } + + sc->sc_vd_count++; + device->type = MPII_DEV_TYPE_VD; + device->dev_handle = letoh16(ce->vol_dev_handle); + /* XXX bunch more fields */ + + sc->sc_mpii_dev[volid] = device; + RB_INSERT(mpii_dev_tree, &mpii_dev_head, sc->sc_mpii_dev[volid]); + } else { + if (!(sc->sc_mpii_dev[volid]->flags & MPII_DEV_UNUSED)) { + printf("%s: mpii_evt_ir_cfg_change_list " + "volume id collision - volid %d\n", + DEVNAME(sc), volid); + continue; + } else { + /* sc->sc_mpii_dev[volid] already + * exists and is not flagged as + * UNUSED so we gracefully (sic) + * do nothing at this time. + */ + } + } + break; + + case MPII_EVT_IR_CFG_ELEMENT_RC_REMOVED: + case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_DELETED: + /* do magic to remove volume */ + break; + + case MPII_EVT_IR_CFG_ELEMENT_RC_NO_CHANGE: + default: + break; + } + break; + + case MPII_EVT_IR_CFG_ELEMENT_EF_ELEMENT_TYPE_VOL_PD: + switch (ce->reason_code) { + case MPII_EVT_IR_CFG_ELEMENT_RC_HIDE: + case MPII_EVT_IR_CFG_ELEMENT_RC_PD_CREATED: + /* do magic to hide/tag from OS view */ + //DNPRINTF(MPII_D_MAP, "%s: mapping: hiding " + // "pd_dev_handle: 0x%04x\n", DEVNAME(sc), + // letoh16(ce->phys_disk_dev_handle)); + // n.dev_handle = letoh16(ce->phys_disk_dev_handle); + // device = RB_FIND(mpii_dev_tree, &mpii_dev_head, &n); + //device = NULL; + //if (device) + // device->flags |= MPII_DEV_HIDDEN; + break; + + case MPII_EVT_IR_CFG_ELEMENT_RC_UNHIDE: + case MPII_EVT_IR_CFG_ELEMENT_RC_PD_DELETED: + /* + * XXX remove evidence of this disk (and no longer + * bother to hide it + */ + break; + + case MPII_EVT_IR_CFG_ELEMENT_RC_NO_CHANGE: + default: + break; + + } + break; + + case MPII_EVT_IR_CFG_ELEMENT_EF_ELEMENT_TYPE_HSP_PD: + break; + + default: + /* XXX oops */ + break; + } + } +} + +void +mpii_event_process_sas_topo_change(struct mpii_softc *sc, + struct mpii_msg_event_reply *enp) +{ + struct mpii_evt_sas_topo_change_list *tcl; + struct mpii_evt_phy_entry *pe; + u_int8_t reason_code; + struct mpii_device *device; + int i, slotid; + + tcl = (struct mpii_evt_sas_topo_change_list *)(enp + 1); + + DNPRINTF(MPII_D_MAP, "%s: sas_topo_change: start_phy_num: %d " + "num_entries: %d physical_port %d\n", DEVNAME(sc), + tcl->start_phy_num, tcl->num_entries, tcl->physical_port); + + if (tcl->num_entries <= 0) + return; + + pe = (struct mpii_evt_phy_entry *)(tcl + 1); + + for (i = 0; i < tcl->num_entries; i++, pe++) { + reason_code = (pe->phy_status & MPII_EVENT_SAS_TOPO_PS_RC_MASK); + + switch (reason_code) { + case MPII_EVENT_SAS_TOPO_PS_RC_TARG_ADDED: + /* XXX begging to move this into a f() */ + DNPRINTF(MPII_D_MAP, "%s: mapping: attached_dev_handle: " + "0x%04x link_rate: 0x%02x phy_status: 0x%02x\n", + DEVNAME(sc), letoh16(pe->attached_dev_handle), + pe->link_rate, pe->phy_status); + + /* XXX check for exceeding boundaries */ + slotid = sc->sc_pd_id_start + tcl->start_phy_num + i; + + if (sc->sc_mpii_dev[slotid]) + if (!(sc->sc_mpii_dev[slotid]->flags & MPII_DEV_UNUSED)) { + printf("%s: mpii_evt_sas_topo_change " + "slot id collision - slot %d\n", + DEVNAME(sc), slotid); + continue; + } + + device = malloc(sizeof(struct mpii_device), + M_DEVBUF, M_ZERO); + if (device == NULL) { + printf("%s: mpii_event_ir_cfg_change_list " + "unable to allocate mpii_device\n", + DEVNAME(sc)); + break; + } + + device->dev_handle = letoh16(pe->attached_dev_handle); + device->phy_num = tcl->start_phy_num + i; + device->type = MPII_DEV_TYPE_PD; + if (tcl->enclosure_handle) + device->physical_port = tcl->physical_port; + device->enclosure_handle = letoh16(tcl->enclosure_handle); + device->expander_dev_handle = letoh16(tcl->expander_dev_handle); + /* XXX + device->wwid = + device->flags = + */ + sc->sc_mpii_dev[slotid] = device; + RB_INSERT(mpii_dev_tree, &mpii_dev_head, device); + break; + + case MPII_EVENT_SAS_TOPO_PS_RC_TARG_NO_RESPOND_MISS: + /* according to MPI2 we need to: + * a. abort all outstanding I/O operations + * b. send a SAS IO unit control request w/ operation + * set to MPII_SAS_OP_REMOVE_DEVICE to remove all IOC + * resources associated with the device. + */ + case MPII_EVENT_SAS_TOPO_PS_RC_PHY_LINK_STATE_CHANGE: + case MPII_EVENT_SAS_TOPO_PS_RC_PHY_LINK_STATE_NOCHNG: + case MPII_EVENT_SAS_TOPO_PS_RC_WITHIN_DELAY_TIMER: + default: + DNPRINTF(MPII_D_EVT, "%s: unhandled " + "mpii_event_sas_topo_change reason code\n", + DEVNAME(sc)); + break; + } + } +} + +void +mpii_event_process_sas_discovery(struct mpii_softc *sc, struct mpii_msg_event_reply *enp) +{ + struct mpii_evt_sas_discovery *ds; + + ds = (struct mpii_evt_sas_discovery *)(enp + 1); + + if ((ds->flags & MPII_EVENT_SAS_DISC_FLAGS_DISC_IN_PROG_MASK) == + MPII_EVENT_SAS_DISC_FLAGS_DISC_IN_PROGRESS) + sc->sc_discovery_in_progress = 1; + else + sc->sc_discovery_in_progress = 0; + + switch (ds->reason_code) { + case MPII_EVENT_SAS_DISC_REASON_CODE_STARTED: + break; + case MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED: + /* XXX look at ds->discovery_status */ + break; + default: + DNPRINTF(MPII_D_EVT, "%s: unknown reason for SAS device status " + "change: 0x%02x\n", DEVNAME(sc), ds->reason_code); + break; + } +} + +void +mpii_event_process_ir_phys_disk(struct mpii_softc *sc, struct mpii_msg_event_reply *enp) +{ + struct mpii_evt_ir_physical_disk *ipd; + + ipd = (struct mpii_evt_ir_physical_disk *)(enp + 1); + + /* XXX TODO: + * process the event fully + * understand that this is necesarily a IR_PD + */ +} + +void +mpii_event_process(struct mpii_softc *sc, struct mpii_msg_reply *prm) +{ + struct mpii_msg_event_reply *enp = (struct mpii_msg_event_reply *)prm; + + DNPRINTF(MPII_D_EVT, "%s: mpii_event_process\n", DEVNAME(sc)); + + DNPRINTF(MPII_D_EVT, "%s: function: 0x%02x msg_length: %d " + "event_data_length: %d\n", DEVNAME(sc), enp->function, + enp->msg_length, letoh16(enp->event_data_length)); + DNPRINTF(MPII_D_EVT, "%s: ack_required: %d msg_flags 0x%02x\n", + DEVNAME(sc), enp->ack_required, enp->msg_flags); + DNPRINTF(MPII_D_EVT, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), + letoh16(enp->ioc_status)); + DNPRINTF(MPII_D_EVT, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), + letoh32(enp->ioc_loginfo)); + DNPRINTF(MPII_D_EVT, "%s: event: 0x%08x\n", DEVNAME(sc), + letoh32(enp->event)); + DNPRINTF(MPII_D_EVT, "%s: event_context: 0x%08x\n", DEVNAME(sc), + letoh32(enp->event_context)); + + switch (letoh32(enp->event)) { + case MPII_EVENT_SAS_DISCOVERY: + mpii_event_process_sas_discovery(sc, enp); + break; + + case MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST: + mpii_event_process_sas_topo_change(sc, enp); + break; + + case MPII_EVENT_SAS_DEVICE_STATUS_CHANGE: + /* XXX */ + break; + + case MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: + /* XXX track enclosures coming/going */ + break; + + case MPII_EVENT_IR_VOLUME: + /* XXX */ + break; + + case MPII_EVENT_IR_PHYSICAL_DISK: + mpii_event_process_ir_phys_disk(sc, enp); + break; + + case MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST: + mpii_event_process_ir_cfg_change_list(sc, enp); + break; + + case MPII_EVENT_IR_OPERATION_STATUS: + case MPII_EVENT_TASK_SET_FULL: + case MPII_EVENT_LOG_ENTRY_ADDED: + + default: + DNPRINTF(MPII_D_EVT, "%s: unhandled event 0x%02x\n", + DEVNAME(sc), letoh32(enp->event)); + break; + } + +#ifdef MPII_DEBUG + int i; + for (i = 0; i < enp->event_data_length; i++) { + DNPRINTF(MPII_D_EVT, "%s: event_data: 0x%08x\n", DEVNAME(sc), + dwordn((enp+1), i)); + } +#endif /* MPII_DEBUG */ + + if (enp->ack_required) + mpii_eventack(sc, enp); +} + +void +mpii_eventnotify_done(struct mpii_ccb *ccb) +{ + struct mpii_softc *sc = ccb->ccb_sc; + + DNPRINTF(MPII_D_EVT, "%s: mpii_eventnotify_done\n", DEVNAME(sc)); + + mpii_event_process(sc, ccb->ccb_rcb->rcb_reply); + + mpii_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); + mpii_put_ccb(sc, ccb); +} + +int +mpii_get_bios_pg2(struct mpii_softc *sc) +{ + struct mpii_cfg_hdr hdr; + size_t pagelen; + int rv = 0; + + DNPRINTF(MPII_D_RAID, "%s: mpii_get_bios_pg2\n", DEVNAME(sc)); + + if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_BIOS, 2, 0, &hdr) != 0) { + DNPRINTF(MPII_D_RAID, "%s: mpii_get_bios_pg2 unable to fetch " + "header for BIOS page 2\n", DEVNAME(sc)); + return (1); + } + + pagelen = hdr.page_length * 4; + sc->sc_bios_pg2 = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL); + if (sc->sc_bios_pg2 == NULL) { + DNPRINTF(MPII_D_RAID, "%s: mpii_get_bios_pg2 unable to " + "allocate space for BIOS page 2\n", DEVNAME(sc)); + return (1); + } + + if (mpii_cfg_page(sc, 0, &hdr, 1, sc->sc_bios_pg2, pagelen) != 0) { + DNPRINTF(MPII_D_RAID, "%s: mpii_get_bios_pg2 unable to " + "fetch BIOS config page 2\n", DEVNAME(sc)); + rv = 1; + goto out; + } + + DNPRINTF(MPII_D_RAID, "%s: req_boot_device_form: 0x%02x " + "req_alt_boot_device_form: 0x%02x current_boot_device_form: " + "0x%02x\n", DEVNAME(sc), sc->sc_bios_pg2->req_boot_device_form, + sc->sc_bios_pg2->req_alt_boot_device_form, + sc->sc_bios_pg2->current_boot_device_form); + +out: + free(sc->sc_bios_pg2, M_TEMP); + + return (rv); +} + void mpii_get_raid_config_pg0(struct mpii_softc *sc) { @@ -3011,68 +3859,286 @@ out: free(config_page, M_TEMP); } -void +int +mpii_get_dpm(struct mpii_softc *sc) +{ + /* XXX consider expanding (or is that reducing) functionality to support + * non-dpm mode of operation when the following fails, but iocfacts + * indicated that the ioc supported dmp + */ + if (!sc->sc_dpm_enabled) + return (1); + + if (mpii_get_dpm_pg0(sc, sc->sc_dpm_pg0) != 0) + return (1); + + return (0); +} + +int +mpii_get_dpm_pg0(struct mpii_softc *sc, struct mpii_cfg_dpm_pg0 *dpm_page) +{ + struct mpii_msg_config_request *cq; + struct mpii_msg_config_reply *cp; + struct mpii_ccb *ccb; + struct mpii_dpm_entry *dpm_entry; + struct mpii_ecfg_hdr ehdr; + struct mpii_dmamem *dmapage; + bus_addr_t dva; + char *kva; + size_t pagelen; + u_int32_t address; + int rv = 0, s; + + DNPRINTF(MPII_D_RAID, "%s: mpii_get_dpm_pg0\n", DEVNAME(sc)); + + if (mpii_ecfg_header(sc, + MPII_CONFIG_REQ_PAGE_TYPE_DRIVER_MAPPING, 0, 0, &ehdr)) { + DNPRINTF(MPII_D_MISC, "%s: mpii_get_dpm_pg0 unable to fetch" + " header for driver mapping page 0\n", DEVNAME(sc)); + return (1); + } + + pagelen = sizeof(struct mpii_ecfg_hdr) + sc->sc_max_dpm_entries * + sizeof(struct mpii_dpm_entry); + + dpm_page = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL); + if (dpm_page == NULL) { + DNPRINTF(MPII_D_MISC, "%s: mpii_get_dpm_pg0 unable to allocate " + "space for device persistence mapping page 0\n", DEVNAME(sc)); + return (1); + } + + dmapage = mpii_dmamem_alloc(sc, pagelen); + if (dmapage == NULL) { + DNPRINTF(MPII_D_MISC, "%s: mpii_get_dpm_pg0 unable to allocate " + "space for dpm dma buffer\n", DEVNAME(sc)); + return (1); + } + + /* the current mpii_req_cfg_page() (and associated macro wrappers) do + * not allow large page length nor is is flexible in allowing actions + * other that READ_CURRENT or WRITE_CURRENT. since we need to READ_NVRAM + * and we need a pagelength around 2580 bytes this function currently + * manually creates and drives the config request. + * + * XXX modify the mpii_req_cfg_page() to allow the caller to specify: + * - alternate actions + * - use passed-in dma-able buffer OR allocate within function if + * the page length exceeds the left over space in the request frame + */ + + s = splbio(); + ccb = mpii_get_ccb(sc); + splx(s); + if (ccb == NULL) { + DNPRINTF(MPII_D_MISC, "%s: mpii_get_dpm_pg0 ccb_get\n", DEVNAME(sc)); + return (1); + } + + address = sc->sc_max_dpm_entries << MPII_DPM_ADDRESS_ENTRY_COUNT_SHIFT; + + cq = ccb->ccb_cmd; + + cq->function = MPII_FUNCTION_CONFIG; + cq->action = MPII_CONFIG_REQ_ACTION_PAGE_READ_NVRAM; + + cq->config_header.page_version = ehdr.page_version; + cq->config_header.page_number = ehdr.page_number; + cq->config_header.page_type = ehdr.page_type; + cq->ext_page_len = htole16(pagelen / 4); + cq->ext_page_type = ehdr.ext_page_type; + cq->config_header.page_type &= MPII_CONFIG_REQ_PAGE_TYPE_MASK; + cq->page_address = htole32(address); + cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE | + MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL | + (pagelen * 4) | MPII_SGE_FL_DIR_IN); + + dva = MPII_DMA_DVA(dmapage); + cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32)); + cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva); + +/* kva = ccb->ccb_cmd; + kva += sizeof(struct mpii_msg_config_request); +*/ + //kva = MPII_DMA_KVA(page); + + ccb->ccb_done = mpii_empty_done; + if (mpii_poll(sc, ccb, 50000) != 0) { + DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n", + DEVNAME(sc)); + return (1); + } + + if (ccb->ccb_rcb == NULL) { + mpii_put_ccb(sc, ccb); + return (1); + } + cp = ccb->ccb_rcb->rcb_reply; + + DNPRINTF(MPII_D_MISC, "%s: action: 0x%02x sglflags: 0x%02x " + "msg_length: %d function: 0x%02x\n", DEVNAME(sc), cp->action, + cp->msg_length, cp->function); + DNPRINTF(MPII_D_MISC, "%s: ext_page_length: %d ext_page_type: 0x%02x " + "msg_flags: 0x%02x\n", DEVNAME(sc), + letoh16(cp->ext_page_length), cp->ext_page_type, + cp->msg_flags); + DNPRINTF(MPII_D_MISC, "%s: vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc), + cp->vp_id, cp->vf_id); + DNPRINTF(MPII_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), + letoh16(cp->ioc_status)); + DNPRINTF(MPII_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), + letoh32(cp->ioc_loginfo)); + DNPRINTF(MPII_D_MISC, "%s: page_version: 0x%02x page_length: %d " + "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc), + cp->config_header.page_version, + cp->config_header.page_length, + cp->config_header.page_number, + cp->config_header.page_type); + + kva = MPII_DMA_KVA(dmapage); + +#ifdef MPII_DEBUG + int i, j; + for (i = 0; i < sc->sc_max_dpm_entries; i++) { + printf(" (%d) ", i); + for (j = 0; j < sizeof(struct mpii_dpm_entry); j++) + printf("%x", (char *)(kva + j + (i * sizeof(struct mpii_dpm_entry)))); + printf("\n"); + } +#endif + + if (letoh16(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS) + rv = 1; + /*else + bcopy(kva, page, pagelen); +*/ + mpii_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); + mpii_put_ccb(sc, ccb); + + dpm_entry = (struct mpii_dpm_entry *)(kva + sizeof(struct mpii_ecfg_hdr)); + +// bcopy(dpm_page, cp, pagelen * 4); + +#ifdef MPII_DEBUG + for (i = 0; i < sc->sc_max_dpm_entries; i++, dpm_entry++) + printf("%s: [%d] physid: 0x%lx mappinginfo: 0x%04x devindex: 0x%04x " + "physicabitsmapping: 0x%08x\n", DEVNAME(sc), i, + letoh64(dpm_entry->physical_identifier), + letoh16(dpm_entry->mapping_information), + letoh16(dpm_entry->device_index), + letoh32(dpm_entry->physical_bits_mapping)); +#endif + + free(dpm_page, M_TEMP); + mpii_dmamem_free(sc, dmapage); + return (rv); +} + +int mpii_get_ioc_pg8(struct mpii_softc *sc) { - struct mpii_cfg_raid_vol *vol_list; struct mpii_cfg_hdr hdr; - struct mpii_cfg_ioc_pg8 *vol_page; + struct mpii_cfg_ioc_pg8 *page; size_t pagelen; + u_int16_t flags; + int rv = 0; DNPRINTF(MPII_D_RAID, "%s: mpii_get_ioc_pg8\n", DEVNAME(sc)); if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_IOC, 8, 0, &hdr) != 0) { - DNPRINTF(MPII_D_RAID, "%s: mpii_get_ioc_pg8 unable to fetch header" + DNPRINTF(MPII_D_CFG, "%s: mpii_get_ioc_pg8 unable to fetch header" "for IOC page 8\n", DEVNAME(sc)); - return; + return (1); } pagelen = hdr.page_length * 4; /* dwords to bytes */ - vol_page = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL); - if (vol_page == NULL) { - DNPRINTF(MPII_D_RAID, "%s: mpii_get_ioc_pg8 unable to allocate " + + page = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL); + if (page == NULL) { + DNPRINTF(MPII_D_CFG, "%s: mpii_get_ioc_pg8 unable to allocate " "space for ioc config page 8\n", DEVNAME(sc)); - return; + return (1); } - vol_list = (struct mpii_cfg_raid_vol *)(vol_page + 1); - if (mpii_cfg_page(sc, 0, &hdr, 1, vol_page, pagelen) != 0) { - DNPRINTF(MPII_D_RAID, "%s: mpii_get_raid unable to fetch IOC " + if (mpii_cfg_page(sc, 0, &hdr, 1, page, pagelen) != 0) { + DNPRINTF(MPII_D_CFG, "%s: mpii_get_raid unable to fetch IOC " "page 8\n", DEVNAME(sc)); + rv = 1; goto out; } - DNPRINTF(MPII_D_RAID, "%s: numdevsperenclosure: 0x%02x\n", DEVNAME(sc), - vol_page->num_devs_per_enclosure); - DNPRINTF(MPII_D_RAID, "%s: maxpersistententries: 0x%04x " + DNPRINTF(MPII_D_CFG, "%s: numdevsperenclosure: 0x%02x\n", DEVNAME(sc), + page->num_devs_per_enclosure); + DNPRINTF(MPII_D_CFG, "%s: maxpersistententries: 0x%04x " "maxnumphysicalmappedids: 0x%04x\n", DEVNAME(sc), - letoh16(vol_page->max_persistent_entries), - letoh16(vol_page->max_num_physical_mapped_ids)); - DNPRINTF(MPII_D_RAID, "%s: flags: 0x%04x\n", DEVNAME(sc), - letoh16(vol_page->flags)); - DNPRINTF(MPII_D_RAID, "%s: irvolumemappingflags: 0x%04x\n", - DEVNAME(sc), letoh16(vol_page->ir_volume_mapping_flags)); + letoh16(page->max_persistent_entries), + letoh16(page->max_num_physical_mapped_ids)); + DNPRINTF(MPII_D_CFG, "%s: flags: 0x%04x\n", DEVNAME(sc), + letoh16(page->flags)); + DNPRINTF(MPII_D_CFG, "%s: irvolumemappingflags: 0x%04x\n", + DEVNAME(sc), letoh16(page->ir_volume_mapping_flags)); + + if (!(page->flags & MPII_IOC_PG8_FLAGS_ENCLOSURE_SLOT_MAPPING)) + /* XXX we don't currently handle persistent mapping mode */ + printf("%s: warning: controller requested device persistence " + "mapping mode is not supported.\n"); + + sc->sc_max_dpm_entries = page->max_persistent_entries; + sc->sc_dpm_enabled = (sc->sc_max_dpm_entries) ? 1 : 0; + + if (page->flags & MPII_IOC_PG8_FLAGS_DISABLE_PERSISTENT_MAPPING) + sc->sc_dpm_enabled = 0; + + sc->sc_pd_id_start = 0; + + if (page->flags & MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0) { + sc->sc_reserve_tid0 = 1; + sc->sc_num_reserved_entries = 1; + sc->sc_pd_id_start = 1; + } else + sc->sc_num_reserved_entries = 0; + + flags = page->ir_volume_mapping_flags && + MPII_IOC_PG8_IRFLAGS_VOLUME_MAPPING_MODE_MASK; + if (sc->sc_ir_firmware) { + if (flags == MPII_IOC_PG8_IRFLAGS_LOW_VOLUME_MAPPING) { + sc->sc_num_reserved_entries += sc->sc_max_volumes; + sc->sc_vd_id_low = 0; + if (page->flags & MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0) + sc->sc_vd_id_low = 1; + } else + sc->sc_vd_id_low = sc->sc_max_devices - sc->sc_max_volumes; + sc->sc_vd_id_hi = sc->sc_vd_id_low + sc->sc_max_volumes - 1; + sc->sc_pd_id_start = sc->sc_vd_id_hi + 1; + } + + DNPRINTF(MPII_D_MAP, "%s: mpii_get_ioc_pg8 mapping: sc_pd_id_start: %d " + "sc_vd_id_low: %d sc_vd_id_hi: %d\n", DEVNAME(sc), + sc->sc_pd_id_start, sc->sc_vd_id_low, sc->sc_vd_id_hi); out: - free(vol_page, M_TEMP); + free(page, M_TEMP); + + return(rv); } int mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number, - u_int32_t address, int extended, void *p) + u_int32_t address, int flags, void *p) { - struct mpii_msg_config_request *cq; - struct mpii_msg_config_reply *cp; - struct mpii_ccb *ccb; + struct mpii_msg_config_request *cq; + struct mpii_msg_config_reply *cp; struct mpii_cfg_hdr *hdr = p; + struct mpii_ccb *ccb; struct mpii_ecfg_hdr *ehdr = p; int etype = 0; int rv = 0; int s; DNPRINTF(MPII_D_MISC, "%s: mpii_req_cfg_header type: %#x number: %x " - "address: 0x%08x extended: %d\n", DEVNAME(sc), type, number, - address, extended); + "address: 0x%08x flags: 0x%b\n", DEVNAME(sc), type, number, + address, flags, MPII_PG_FMT); s = splbio(); ccb = mpii_get_ccb(sc); @@ -3083,12 +4149,11 @@ mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number, return (1); } - if (extended) { + if (ISSET(flags, MPII_PG_EXTENDED)) { etype = type; type = MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED; } - ccb->ccb_done = mpii_empty_done; cq = ccb->ccb_cmd; cq->function = MPII_FUNCTION_CONFIG; @@ -3102,9 +4167,20 @@ mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number, cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE | MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL); - if (mpii_poll(sc, ccb, 50000) != 0) { - DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n", DEVNAME(sc)); - return (1); + if (ISSET(flags, MPII_PG_POLL)) { + ccb->ccb_done = mpii_empty_done; + if (mpii_poll(sc, ccb, 50000) != 0) { + DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n", + DEVNAME(sc)); + return (1); + } + } else { + ccb->ccb_done = (void (*)(struct mpii_ccb *))wakeup; + s = splbio(); + mpii_start(sc, ccb); + while (ccb->ccb_state != MPII_CCB_READY) + tsleep(ccb, PRIBIO, "mpiipghdr", 0); + splx(s); } if (ccb->ccb_rcb == NULL) @@ -3133,7 +4209,7 @@ mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number, if (letoh16(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS) rv = 1; - else if (extended) { + else if (ISSET(flags, MPII_PG_EXTENDED)) { bzero(ehdr, sizeof(*ehdr)); ehdr->page_version = cp->config_header.page_version; ehdr->page_number = cp->config_header.page_number; @@ -3150,13 +4226,13 @@ mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number, } int -mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int extended, +mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int flags, void *p, int read, void *page, size_t len) { struct mpii_msg_config_request *cq; struct mpii_msg_config_reply *cp; - struct mpii_ccb *ccb; struct mpii_cfg_hdr *hdr = p; + struct mpii_ccb *ccb; struct mpii_ecfg_hdr *ehdr = p; u_int64_t dva; char *kva; @@ -3164,14 +4240,14 @@ mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int extended, int rv = 0; int s; - DNPRINTF(MPII_D_MISC, "%s: mpii_req_cfg_page address: %d read: %d type: %x\n", + DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page address: %d read: %d type: %x\n", DEVNAME(sc), address, read, hdr->page_type); - page_length = extended ? + page_length = ISSET(flags, MPII_PG_EXTENDED) ? letoh16(ehdr->ext_page_length) : hdr->page_length; if (len > MPII_REQUEST_SIZE - sizeof(struct mpii_msg_config_request) || - len < page_length * 4) + len < page_length * 4) return (1); s = splbio(); @@ -3182,7 +4258,6 @@ mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int extended, return (1); } - ccb->ccb_done = mpii_empty_done; cq = ccb->ccb_cmd; cq->function = MPII_FUNCTION_CONFIG; @@ -3190,7 +4265,7 @@ mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int extended, cq->action = (read ? MPII_CONFIG_REQ_ACTION_PAGE_READ_CURRENT : MPII_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT); - if (extended) { + if (ISSET(flags, MPII_PG_EXTENDED)) { cq->config_header.page_version = ehdr->page_version; cq->config_header.page_number = ehdr->page_number; cq->config_header.page_type = ehdr->page_type; @@ -3213,12 +4288,24 @@ mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int extended, kva = ccb->ccb_cmd; kva += sizeof(struct mpii_msg_config_request); + if (!read) bcopy(page, kva, len); - if (mpii_poll(sc, ccb, 50000) != 0) { - DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page poll\n", DEVNAME(sc)); - return (1); + if (ISSET(flags, MPII_PG_POLL)) { + ccb->ccb_done = mpii_empty_done; + if (mpii_poll(sc, ccb, 50000) != 0) { + DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n", + DEVNAME(sc)); + return (1); + } + } else { + ccb->ccb_done = (void (*)(struct mpii_ccb *))wakeup; + s = splbio(); + mpii_start(sc, ccb); + while (ccb->ccb_state != MPII_CCB_READY) + tsleep(ccb, PRIBIO, "mpiipghdr", 0); + splx(s); } if (ccb->ccb_rcb == NULL) { @@ -3246,7 +4333,7 @@ mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int extended, cp->config_header.page_length, cp->config_header.page_number, cp->config_header.page_type); - + if (letoh16(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS) rv = 1; else if (read) @@ -3262,7 +4349,7 @@ int mpii_reply(struct mpii_softc *sc) { struct mpii_reply_descriptor *rdp; - struct mpii_ccb *ccb; + struct mpii_ccb *ccb = NULL; struct mpii_rcb *rcb = NULL; struct mpii_msg_reply *reply = NULL; u_int8_t reply_flags; @@ -3289,7 +4376,7 @@ mpii_reply(struct mpii_softc *sc) * ioc is still writing to the reply post queue * race condition - bail! */ - return (0); + return (-1); DNPRINTF(MPII_D_INTR, "%s: dword[0]: 0x%08x\n", DEVNAME(sc), letoh32(dwordn(rdp, 0))); @@ -3318,19 +4405,17 @@ mpii_reply(struct mpii_softc *sc) DNPRINTF(MPII_D_INTR, "%s: mpii_reply reply_flags: %d smid: %d reply: %p\n", DEVNAME(sc), reply_flags, smid, reply); - if (smid == 0) { - printf("smid == 0 !!\n"); - goto end; - } - ccb = &sc->sc_ccbs[smid - 1]; + if (smid) { + ccb = &sc->sc_ccbs[smid - 1]; - /* XXX why is this necessary ? */ - bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_requests), - ccb->ccb_offset, MPII_REQUEST_SIZE, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + /* XXX why is this necessary ? */ + bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_requests), + ccb->ccb_offset, MPII_REQUEST_SIZE, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - ccb->ccb_state = MPII_CCB_READY; - ccb->ccb_rcb = rcb; + ccb->ccb_state = MPII_CCB_READY; + ccb->ccb_rcb = rcb; + } DNPRINTF(MPII_D_INTR, " rcb: 0x%04x\n", rcb); @@ -3343,9 +4428,11 @@ mpii_reply(struct mpii_softc *sc) sc->sc_reply_post_host_index = (sc->sc_reply_post_host_index + 1) % sc->sc_reply_post_qdepth; - ccb->ccb_done(ccb); -end: + if (smid) + ccb->ccb_done(ccb); + else + mpii_event_process(sc, rcb->rcb_reply); return (smid); } @@ -3411,6 +4498,23 @@ mpii_dmamem_free(struct mpii_softc *sc, struct mpii_dmamem *mdm) } int +mpii_alloc_dev(struct mpii_softc *sc) +{ + DNPRINTF(MPII_D_MEM, "%s: mpii_alloc_dev: sc_max_devices: %d " + "sizeof(sc_mpii_dev): %d\n", DEVNAME(sc), sc->sc_max_devices, + sizeof(struct mpii_device *) * sc->sc_max_devices); + + sc->sc_mpii_dev = malloc(sc->sc_max_devices * + sizeof(struct mpii_device *), M_DEVBUF, + M_WAITOK | M_CANFAIL | M_ZERO); + + if (sc->sc_mpii_dev == NULL) + return (1); + + return (0); +} + +int mpii_alloc_ccbs(struct mpii_softc *sc) { struct mpii_ccb *ccb; @@ -3435,11 +4539,10 @@ mpii_alloc_ccbs(struct mpii_softc *sc) cmd = MPII_DMA_KVA(sc->sc_requests); bzero(cmd, MPII_REQUEST_SIZE * sc->sc_request_depth); - /* - * we have sc->sc_request_depth system request message frames, but - * smid zero cannot be used. - * - * we then have (sc->sc_request_depth - 1) number of ccbs + /* + * we have sc->sc_request_depth system request message + * frames, but smid zero cannot be used. so we then + * have (sc->sc_request_depth - 1) number of ccbs */ for (i = 1; i < sc->sc_request_depth; i++) { ccb = &sc->sc_ccbs[i - 1]; @@ -3698,9 +4801,6 @@ mpii_init_queues(struct mpii_softc *sc) mpii_write_reply_post(sc, sc->sc_reply_post_host_index); } - - - int mpii_poll(struct mpii_softc *sc, struct mpii_ccb *ccb, int timeout) { @@ -3750,6 +4850,27 @@ mpii_scsi_cmd(struct scsi_xfer *xs) splx(s); if (ccb == NULL) return (NO_CCB); + + /* XXX */ + if (sc->sc_mpii_dev[link->target] == NULL) { + DNPRINTF(MPII_D_MAP, "%s: mpii_scsi_cmd nonexistent tid %d\n", + DEVNAME(sc), link->target); + return (99); + } + + /* XXX */ + if (sc->sc_mpii_dev[link->target]->flags & MPII_DEV_UNUSED) { + DNPRINTF(MPII_D_MAP, "%s: mpii_scsi_cmd tid %d is " + "MPII_DEV_UNUSED\n", DEVNAME(sc), link->target); + return (99); + } + + /* XXX */ + if (sc->sc_mpii_dev[link->target]->flags & MPII_DEV_HIDDEN) { + DNPRINTF(MPII_D_MAP, "%s: mpii_scsi_cmd tid %d is " + "MPII_DEV_HIDDEN\n", DEVNAME(sc), link->target); + return (99); + } DNPRINTF(MPII_D_CMD, "%s: ccb_smid: %d xs->flags: 0x%x\n", DEVNAME(sc), ccb->ccb_smid, xs->flags); @@ -3764,7 +4885,7 @@ mpii_scsi_cmd(struct scsi_xfer *xs) io->sense_buffer_length = sizeof(xs->sense); io->sgl_offset0 = 24; /* XXX fix this */ io->io_flags = htole16(xs->cmdlen); - io->dev_handle = htole32(link->target); + io->dev_handle = htole16(sc->sc_mpii_dev[link->target]->dev_handle); io->lun[0] = htobe16(link->lun); switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { |