summaryrefslogtreecommitdiffstats
path: root/sys/dev/twa/tw_cl_init.c
diff options
context:
space:
mode:
authorvkashyap <vkashyap@FreeBSD.org>2005-11-08 22:51:43 +0000
committervkashyap <vkashyap@FreeBSD.org>2005-11-08 22:51:43 +0000
commit066b259890e4fbc852c3f553652301b443fca6b5 (patch)
treed3b09b687cb2efad93eb3286b6afdbfd1aeedd27 /sys/dev/twa/tw_cl_init.c
parent7b1764bfb31e62628c6007172883c7e4e97bbe37 (diff)
downloadFreeBSD-src-066b259890e4fbc852c3f553652301b443fca6b5.zip
FreeBSD-src-066b259890e4fbc852c3f553652301b443fca6b5.tar.gz
twa corresponding to the 9.3.0.1 release on the 3ware website. This driver has
support for the 9xxxSX controllers, along with the earlier 9xxxS series controllers.
Diffstat (limited to 'sys/dev/twa/tw_cl_init.c')
-rw-r--r--sys/dev/twa/tw_cl_init.c194
1 files changed, 164 insertions, 30 deletions
diff --git a/sys/dev/twa/tw_cl_init.c b/sys/dev/twa/tw_cl_init.c
index 11d848d..b1da0af 100644
--- a/sys/dev/twa/tw_cl_init.c
+++ b/sys/dev/twa/tw_cl_init.c
@@ -61,7 +61,9 @@
TW_INT32
tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id)
{
- if ((vendor_id == TW_CL_VENDOR_ID) && (device_id == TW_CL_DEVICE_ID_9K))
+ if ((vendor_id == TW_CL_VENDOR_ID) &&
+ ((device_id == TW_CL_DEVICE_ID_9K) ||
+ (device_id == TW_CL_DEVICE_ID_9K_X)))
return(TW_CL_TRUE);
return(TW_CL_FALSE);
}
@@ -69,11 +71,86 @@ tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id)
/*
+ * Function name: tw_cl_get_pci_bar_info
+ * Description: Returns PCI BAR info.
+ *
+ * Input: device_id -- device id of the controller
+ * bar_type -- type of PCI BAR in question
+ * Output: bar_num -- PCI BAR number corresponding to bar_type
+ * bar0_offset -- byte offset from BAR 0 (0x10 in
+ * PCI config space)
+ * bar_size -- size, in bytes, of the BAR in question
+ * Return value: 0 -- success
+ * non-zero -- failure
+ */
+TW_INT32
+tw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type,
+ TW_INT32 *bar_num, TW_INT32 *bar0_offset, TW_INT32 *bar_size)
+{
+ TW_INT32 error = TW_OSL_ESUCCESS;
+
+ switch(device_id) {
+ case TW_CL_DEVICE_ID_9K:
+ switch(bar_type) {
+ case TW_CL_BAR_TYPE_IO:
+ *bar_num = 0;
+ *bar0_offset = 0;
+ *bar_size = 4;
+ break;
+
+ case TW_CL_BAR_TYPE_MEM:
+ *bar_num = 1;
+ *bar0_offset = 0x4;
+ *bar_size = 8;
+ break;
+
+ case TW_CL_BAR_TYPE_SBUF:
+ *bar_num = 2;
+ *bar0_offset = 0xC;
+ *bar_size = 8;
+ break;
+ }
+ break;
+
+ case TW_CL_DEVICE_ID_9K_X:
+ switch(bar_type) {
+ case TW_CL_BAR_TYPE_IO:
+ *bar_num = 2;
+ *bar0_offset = 0x10;
+ *bar_size = 4;
+ break;
+
+ case TW_CL_BAR_TYPE_MEM:
+ *bar_num = 1;
+ *bar0_offset = 0x8;
+ *bar_size = 8;
+ break;
+
+ case TW_CL_BAR_TYPE_SBUF:
+ *bar_num = 0;
+ *bar0_offset = 0;
+ *bar_size = 8;
+ break;
+ }
+ break;
+
+ default:
+ error = TW_OSL_ENOTTY;
+ break;
+ }
+
+ return(error);
+}
+
+
+
+/*
* Function name: tw_cl_get_mem_requirements
* Description: Provides info about Common Layer requirements for a
* controller, given the controller type (in 'flags').
* Input: ctlr_handle -- controller handle
* flags -- more info passed by the OS Layer
+ * device_id -- device id of the controller
* max_simult_reqs -- maximum # of simultaneous
* requests that the OS Layer expects
* the Common Layer to support
@@ -98,8 +175,8 @@ tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id)
*/
TW_INT32
tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
- TW_UINT32 flags, TW_INT32 max_simult_reqs, TW_INT32 max_aens,
- TW_UINT32 *alignment, TW_UINT32 *sg_size_factor,
+ TW_UINT32 flags, TW_INT32 device_id, TW_INT32 max_simult_reqs,
+ TW_INT32 max_aens, TW_UINT32 *alignment, TW_UINT32 *sg_size_factor,
TW_UINT32 *non_dma_mem_size, TW_UINT32 *dma_mem_size
#ifdef TW_OSL_FLASH_FIRMWARE
, TW_UINT32 *flash_dma_mem_size
@@ -112,6 +189,9 @@ tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
#endif /* TW_OSL_N0N_DMA_MEM_ALLOC_PER_REQUEST */
)
{
+ if (device_id == 0)
+ device_id = TW_CL_DEVICE_ID_9K;
+
if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) {
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
@@ -123,8 +203,8 @@ tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
return(TW_OSL_EBIG);
}
- *alignment = TWA_ALIGNMENT;
- *sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR;
+ *alignment = TWA_ALIGNMENT(device_id);
+ *sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
/*
* Total non-DMA memory needed is the sum total of memory needed for
@@ -171,8 +251,9 @@ tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
/* Memory needed to hold the firmware image while flashing. */
*flash_dma_mem_size =
((tw_cli_fw_img_size / TW_CLI_NUM_FW_IMAGE_CHUNKS) +
- (TWA_SG_ELEMENT_SIZE_FACTOR - 1)) &
- ~(TWA_SG_ELEMENT_SIZE_FACTOR - 1);
+ 511) & ~511;
+/* (TWA_SG_ELEMENT_SIZE_FACTOR(device_id) - 1)) &
+ ~(TWA_SG_ELEMENT_SIZE_FACTOR(device_id) - 1); */
#endif /* TW_OSL_FLASH_FIRMWARE */
@@ -187,6 +268,7 @@ tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
*
* Input: ctlr_handle -- controller handle
* flags -- more info passed by the OS Layer
+ * device_id -- device id of the controller
* max_simult_reqs -- maximum # of simultaneous requests
* that the OS Layer expects the Common
* Layer to support
@@ -203,8 +285,8 @@ tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
*/
TW_INT32
tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
- TW_INT32 max_simult_reqs, TW_INT32 max_aens, TW_VOID *non_dma_mem,
- TW_VOID *dma_mem, TW_UINT64 dma_mem_phys
+ TW_INT32 device_id, TW_INT32 max_simult_reqs, TW_INT32 max_aens,
+ TW_VOID *non_dma_mem, TW_VOID *dma_mem, TW_UINT64 dma_mem_phys
#ifdef TW_OSL_FLASH_FIRMWARE
, TW_VOID *flash_dma_mem,
TW_UINT64 flash_dma_mem_phys
@@ -280,9 +362,12 @@ tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
ctlr_handle->cl_ctlr_ctxt = ctlr;
ctlr->ctlr_handle = ctlr_handle;
+ ctlr->device_id = (TW_UINT32)device_id;
+ ctlr->arch_id = TWA_ARCH_ID(device_id);
+ ctlr->flags = flags;
+ ctlr->sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
ctlr->max_simult_reqs = max_simult_reqs + 1;
ctlr->max_aens_supported = max_aens;
- ctlr->flags = flags;
#ifdef TW_OSL_FLASH_FIRMWARE
ctlr->flash_dma_mem = flash_dma_mem;
@@ -302,18 +387,20 @@ tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
tw_osl_init_lock(ctlr_handle, "tw_cl_io_lock", ctlr->io_lock);
/*
* If 64 bit cmd pkt addresses are used, we will need to serialize
- * writes to the hardware (across registers), since existing hardware
- * will get confused if, for example, we wrote the low 32 bits of the
- * cmd pkt address, followed by a response interrupt mask to the
+ * writes to the hardware (across registers), since existing (G66)
+ * hardware will get confused if, for example, we wrote the low 32 bits
+ * of the cmd pkt address, followed by a response interrupt mask to the
* control register, followed by the high 32 bits of the cmd pkt
* address. It will then interpret the value written to the control
* register as the low cmd pkt address. So, for this case, we will
- * only use one lock (io_lock) by making io_lock & intr_lock one and
- * the same.
+ * make a note that we will need to synchronize control register writes
+ * with command register writes.
*/
- if (ctlr->flags & TW_CL_64BIT_ADDRESSES)
+ if ((ctlr->flags & TW_CL_64BIT_ADDRESSES) &&
+ (ctlr->device_id == TW_CL_DEVICE_ID_9K)) {
+ ctlr->state |= TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED;
ctlr->intr_lock = ctlr->io_lock;
- else {
+ } else {
ctlr->intr_lock = &(ctlr->intr_lock_handle);
tw_osl_init_lock(ctlr_handle, "tw_cl_intr_lock",
ctlr->intr_lock);
@@ -481,11 +568,14 @@ tw_cli_flash_firmware(struct tw_cli_ctlr_context *ctlr)
/*
* Determine amount of memory needed to hold a chunk of the
- * firmware image.
+ * firmware image. As yet, the Download_Firmware command does not
+ * support SG elements that are ctlr->sg_size_factor multiples. It
+ * requires them to be 512-byte multiples.
*/
fw_img_chunk_size = ((tw_cli_fw_img_size / TW_CLI_NUM_FW_IMAGE_CHUNKS) +
- (TWA_SG_ELEMENT_SIZE_FACTOR - 1)) &
- ~(TWA_SG_ELEMENT_SIZE_FACTOR - 1);
+ 511) & ~511;
+/* (ctlr->sg_size_factor - 1)) &
+ ~(ctlr->sg_size_factor - 1); */
/* Calculate the actual number of chunks needed. */
num_chunks = (tw_cli_fw_img_size / fw_img_chunk_size) +
@@ -528,9 +618,9 @@ tw_cli_flash_firmware(struct tw_cli_ctlr_context *ctlr)
/*
* The next line will effect only the last chunk.
*/
- req->length = (this_chunk_size +
- (TWA_SG_ELEMENT_SIZE_FACTOR - 1)) &
- ~(TWA_SG_ELEMENT_SIZE_FACTOR - 1);
+ req->length = (this_chunk_size + 511) & ~511;
+/* (ctlr->sg_size_factor - 1)) &
+ ~(ctlr->sg_size_factor - 1); */
if (ctlr->flags & TW_CL_64BIT_ADDRESSES) {
((struct tw_cl_sg_desc64 *)(cmd->sgl))[0].address =
@@ -659,6 +749,12 @@ tw_cli_hard_reset(struct tw_cli_ctlr_context *ctlr)
req->data = TW_CL_NULL;
req->length = 0;
+ tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
+ TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
+ 0x1017, 0x3, TW_CL_SEVERITY_INFO_STRING,
+ "Issuing hard (commanded) reset to the controller...",
+ " ");
+
error = tw_cli_submit_and_poll_request(req,
TW_CLI_REQUEST_TIMEOUT_PERIOD);
if (error) {
@@ -683,6 +779,36 @@ tw_cli_hard_reset(struct tw_cli_ctlr_context *ctlr)
"error = %d", error);
}
+ if (ctlr->device_id == TW_CL_DEVICE_ID_9K_X) {
+ /*
+ * There's a hardware bug in the G133 ASIC, which can lead to
+ * PCI parity errors and hangs, if the host accesses any
+ * registers when the firmware is resetting the hardware, as
+ * part of a hard/soft reset. The window of time when the
+ * problem can occur is about 10 ms. Here, we will handshake
+ * with the firmware to find out when the firmware is pulling
+ * down the hardware reset pin, and wait for about 500 ms to
+ * make sure we don't access any hardware registers (for
+ * polling) during that window.
+ */
+ ctlr->state |= TW_CLI_CTLR_STATE_RESET_PHASE1_IN_PROGRESS;
+ while (tw_cli_find_response(ctlr,
+ TWA_RESET_PHASE1_NOTIFICATION_RESPONSE) != TW_OSL_ESUCCESS)
+ tw_osl_delay(10);
+ tw_osl_delay(TWA_RESET_PHASE1_WAIT_TIME_MS * 1000);
+ ctlr->state &= ~TW_CLI_CTLR_STATE_RESET_PHASE1_IN_PROGRESS;
+ }
+
+ /* Wait for the MC_RDY bit to get set. */
+ if ((error = tw_cli_poll_status(ctlr, TWA_STATUS_MICROCONTROLLER_READY,
+ TW_CLI_RESET_TIMEOUT_PERIOD))) {
+ tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
+ TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
+ 0x1018, 0x1, TW_CL_SEVERITY_ERROR_STRING,
+ "Micro-ctlr not ready following hard reset",
+ "error = %d", error);
+ }
+
out:
if (req)
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
@@ -748,10 +874,12 @@ tw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr)
if ((error = tw_cli_init_connection(ctlr,
(TW_UINT16)(ctlr->max_simult_reqs),
TWA_EXTENDED_INIT_CONNECT, TWA_CURRENT_FW_SRL,
- TWA_9000_ARCH_ID, TWA_CURRENT_FW_BRANCH,
- TWA_CURRENT_FW_BUILD, &fw_on_ctlr_srl,
- &fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
- &fw_on_ctlr_build, &init_connect_result))) {
+ (TW_UINT16)(ctlr->arch_id),
+ TWA_CURRENT_FW_BRANCH(ctlr->arch_id),
+ TWA_CURRENT_FW_BUILD(ctlr->arch_id),
+ &fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
+ &fw_on_ctlr_branch, &fw_on_ctlr_build,
+ &init_connect_result))) {
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x100B, 0x2, TW_CL_SEVERITY_WARNING_STRING,
@@ -825,8 +953,10 @@ tw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr)
/* Yes, we can. Make note of the operating mode. */
if (init_connect_result & TWA_CTLR_FW_SAME_OR_NEWER) {
ctlr->working_srl = TWA_CURRENT_FW_SRL;
- ctlr->working_branch = TWA_CURRENT_FW_BRANCH;
- ctlr->working_build = TWA_CURRENT_FW_BUILD;
+ ctlr->working_branch =
+ TWA_CURRENT_FW_BRANCH(ctlr->arch_id);
+ ctlr->working_build =
+ TWA_CURRENT_FW_BUILD(ctlr->arch_id);
} else {
ctlr->working_srl = fw_on_ctlr_srl;
ctlr->working_branch = fw_on_ctlr_branch;
@@ -847,7 +977,8 @@ tw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr)
if ((error = tw_cli_init_connection(ctlr,
(TW_UINT16)(ctlr->max_simult_reqs),
TWA_EXTENDED_INIT_CONNECT,
- TWA_BASE_FW_SRL, TWA_9000_ARCH_ID,
+ TWA_BASE_FW_SRL,
+ (TW_UINT16)(ctlr->arch_id),
TWA_BASE_FW_BRANCH, TWA_BASE_FW_BUILD,
&fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
&fw_on_ctlr_branch, &fw_on_ctlr_build,
@@ -901,6 +1032,9 @@ tw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr)
ctlr->working_build = TWA_BASE_FW_BUILD;
ctlr->operating_mode = TWA_BASE_MODE;
}
+ ctlr->fw_on_ctlr_srl = fw_on_ctlr_srl;
+ ctlr->fw_on_ctlr_branch = fw_on_ctlr_branch;
+ ctlr->fw_on_ctlr_build = fw_on_ctlr_build;
}
/* Drain the AEN queue */
OpenPOWER on IntegriCloud