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.
This commit is contained in:
Vinod Kashyap 2005-11-08 22:51:43 +00:00
parent f6f8bc7ad5
commit ff1625c61d
18 changed files with 48042 additions and 26466 deletions

View File

@ -937,8 +937,10 @@ dev/twa/tw_cl_io.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twa/tw_cl_misc.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twa/tw_osl_cam.c optional twa
dev/twa/tw_osl_freebsd.c optional twa
dev/twa/tw_osl_cam.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twa/tw_osl_freebsd.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twe/twe.c optional twe
dev/twe/twe_freebsd.c optional twe
dev/tx/if_tx.c optional tx

View File

@ -66,6 +66,10 @@
#define TW_CLI_CTLR_STATE_GET_MORE_AENS (1<<3)
/* Controller is being reset. */
#define TW_CLI_CTLR_STATE_RESET_IN_PROGRESS (1<<4)
/* G133 controller is in 'phase 1' of being reset. */
#define TW_CLI_CTLR_STATE_RESET_PHASE1_IN_PROGRESS (1<<5)
/* G66 register write access bug needs to be worked around. */
#define TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED (1<<6)
/* Possible values of ctlr->ioctl_lock.lock. */
#define TW_CLI_LOCK_FREE 0x0 /* lock is free */
@ -157,8 +161,12 @@ struct tw_cli_ctlr_context {
TW_UINT64 cmd_pkt_phys; /* phys addr of cmd_pkt_buf */
TW_UINT32 device_id; /* controller device id */
TW_UINT32 arch_id; /* controller architecture id */
TW_UINT32 state; /* controller state */
TW_UINT32 flags; /* controller settings */
TW_UINT32 sg_size_factor; /* SG element size should be a
multiple of this */
/* Request queues and arrays. */
struct tw_cl_link req_q_head[TW_CLI_Q_COUNT];
@ -191,6 +199,11 @@ struct tw_cli_ctlr_context {
that the driver is compatible with */
TW_UINT16 working_build; /* build # of the firmware
that the driver is compatible with */
TW_UINT16 fw_on_ctlr_srl; /* srl of running firmware */
TW_UINT16 fw_on_ctlr_branch;/* branch # of running
firmware */
TW_UINT16 fw_on_ctlr_build;/* build # of running
firmware */
TW_UINT32 operating_mode; /* base mode/current mode */
TW_INT32 host_intr_pending;/* host intr processing
@ -309,11 +322,34 @@ tw_cli_req_q_insert_tail(struct tw_cli_req_context *req, TW_UINT8 q_type)
return;
if ((q_type == TW_CLI_FREE_Q) &&
(!(req->flags & TW_CLI_REQ_FLAGS_INTERNAL))) {
TW_SYNC_HANDLE sync_handle;
tw_osl_get_lock(ctlr->ctlr_handle, ctlr->gen_lock);
if (req->state == TW_CLI_REQ_STATE_COMPLETE) {
if (ctlr->flags & TW_CL_DEFERRED_INTR_USED)
tw_osl_sync_io_block(ctlr->ctlr_handle,
&sync_handle);
} else {
if (!(ctlr->flags & TW_CL_DEFERRED_INTR_USED))
tw_osl_sync_isr_block(ctlr->ctlr_handle,
&sync_handle);
}
ctlr->free_req_ids[ctlr->free_req_tail] = req->request_id;
ctlr->busy_reqs[req->request_id] = TW_CL_NULL;
ctlr->free_req_tail = (ctlr->free_req_tail + 1) %
(ctlr->max_simult_reqs - 1);
ctlr->num_free_req_ids++;
if (req->state == TW_CLI_REQ_STATE_COMPLETE) {
if (ctlr->flags & TW_CL_DEFERRED_INTR_USED)
tw_osl_sync_io_unblock(ctlr->ctlr_handle,
&sync_handle);
} else {
if (!(ctlr->flags & TW_CL_DEFERRED_INTR_USED))
tw_osl_sync_isr_unblock(ctlr->ctlr_handle,
&sync_handle);
}
tw_osl_free_lock(ctlr->ctlr_handle, ctlr->gen_lock);
return;
}
#endif /* TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST */

View File

@ -179,6 +179,10 @@ extern TW_VOID tw_cli_drain_pending_queue(struct tw_cli_ctlr_context *ctlr);
/* Drain the controller response queue. */
extern TW_INT32 tw_cli_drain_response_queue(struct tw_cli_ctlr_context *ctlr);
/* Find a particular response in the controller response queue. */
extern TW_INT32 tw_cli_find_response(struct tw_cli_ctlr_context *ctlr,
TW_INT32 req_id);
/* Drain the controller AEN queue. */
extern TW_INT32 tw_cli_drain_aen_queue(struct tw_cli_ctlr_context *ctlr);

View File

@ -52,10 +52,10 @@
#define TWA_RESPONSE_QUEUE_OFFSET 0xC
#define TWA_COMMAND_QUEUE_OFFSET_LOW 0x20
#define TWA_COMMAND_QUEUE_OFFSET_HIGH 0x24
#define TWA_LARGE_RESPONSE_QUEUE_OFFSET 0x30
/* Control register bit definitions. */
#define TWA_CONTROL_CLEAR_SBUF_WRITE_ERROR 0x00000008
#define TWA_CONTROL_ISSUE_HOST_INTERRUPT 0x00000020
#define TWA_CONTROL_DISABLE_INTERRUPTS 0x00000040
#define TWA_CONTROL_ENABLE_INTERRUPTS 0x00000080
@ -73,7 +73,6 @@
/* Status register bit definitions. */
#define TWA_STATUS_ROM_BIOS_IN_SBUF 0x00000002
#define TWA_STATUS_SBUF_WRITE_ERROR 0x00000008
#define TWA_STATUS_COMMAND_QUEUE_EMPTY 0x00001000
#define TWA_STATUS_MICROCONTROLLER_READY 0x00002000
#define TWA_STATUS_RESPONSE_QUEUE_EMPTY 0x00004000
@ -99,6 +98,9 @@
#define TWA_PCI_CONFIG_CLEAR_PARITY_ERROR 0xc100
#define TWA_PCI_CONFIG_CLEAR_PCI_ABORT 0x2000
#define TWA_RESET_PHASE1_NOTIFICATION_RESPONSE 0xFFFF
#define TWA_RESET_PHASE1_WAIT_TIME_MS 500
/* Command packet opcodes. */
#define TWA_FW_CMD_NOP 0x00
@ -132,7 +134,7 @@
/* Misc defines. */
#define TWA_BUNDLED_FW_VERSION_STRING "2.06.00.009"
#define TWA_BUNDLED_FW_VERSION_STRING "3.02.00.004"
#define TWA_SHUTDOWN_MESSAGE_CREDITS 0x001
#define TWA_64BIT_SG_ADDRESSES 0x00000001
#define TWA_EXTENDED_INIT_CONNECT 0x00000002
@ -140,11 +142,14 @@
#define TWA_BASE_FW_SRL 24
#define TWA_BASE_FW_BRANCH 0
#define TWA_BASE_FW_BUILD 1
#define TWA_CURRENT_FW_SRL 28
#define TWA_CURRENT_FW_BRANCH 4
#define TWA_CURRENT_FW_BUILD 9
#define TWA_CURRENT_FW_SRL 30
#define TWA_CURRENT_FW_BRANCH_9K 4
#define TWA_CURRENT_FW_BUILD_9K 8
#define TWA_CURRENT_FW_BRANCH_9K_X 8
#define TWA_CURRENT_FW_BUILD_9K_X 4
#define TWA_MULTI_LUN_FW_SRL 28
#define TWA_9000_ARCH_ID 0x5 /* 9000 series controllers */
#define TWA_ARCH_ID_9K 0x5 /* 9000 PCI controllers */
#define TWA_ARCH_ID_9K_X 0x6 /* 9000 PCI-X controllers */
#define TWA_CTLR_FW_SAME_OR_NEWER 0x00000001
#define TWA_CTLR_FW_COMPATIBLE 0x00000002
#define TWA_BUNDLED_FW_SAFE_TO_FLASH 0x00000004
@ -152,13 +157,24 @@
#define TWA_SENSE_DATA_LENGTH 18
#define TWA_ARCH_ID(device_id) \
(((device_id) == TW_CL_DEVICE_ID_9K) ? TWA_ARCH_ID_9K : \
TWA_ARCH_ID_9K_X)
#define TWA_CURRENT_FW_BRANCH(arch_id) \
(((arch_id) == TWA_ARCH_ID_9K) ? TWA_CURRENT_FW_BRANCH_9K : \
TWA_CURRENT_FW_BRANCH_9K_X)
#define TWA_CURRENT_FW_BUILD(arch_id) \
(((arch_id) == TWA_ARCH_ID_9K) ? TWA_CURRENT_FW_BUILD_9K : \
TWA_CURRENT_FW_BUILD_9K_X)
/*
* All SG addresses and DMA'able memory allocated by the OSL should be
* TWA_ALIGNMENT bytes aligned, and have a size that is a multiple of
* TWA_SG_ELEMENT_SIZE_FACTOR.
*/
#define TWA_ALIGNMENT 0x4
#define TWA_SG_ELEMENT_SIZE_FACTOR 512
#define TWA_ALIGNMENT(device_id) 0x4
#define TWA_SG_ELEMENT_SIZE_FACTOR(device_id) \
(((device_id) == TW_CL_DEVICE_ID_9K) ? 512 : 4)
/*
@ -180,6 +196,7 @@
#define TWA_PARAM_VERSION_TABLE 0x0402
#define TWA_PARAM_VERSION_FW 3 /* firmware version [16] */
#define TWA_PARAM_VERSION_BIOS 4 /* BIOSs version [16] */
#define TWA_PARAM_CTLR_MODEL 8 /* Controller model [16] */
#define TWA_PARAM_CONTROLLER_TABLE 0x0403
#define TWA_PARAM_CONTROLLER_PORT_COUNT 3 /* number of ports [1] */
@ -352,6 +369,10 @@ struct tw_cl_param_9k {
tw_osl_read_reg(ctlr_handle, TWA_RESPONSE_QUEUE_OFFSET, 4)
#define TW_CLI_READ_LARGE_RESPONSE_QUEUE(ctlr_handle) \
tw_osl_read_reg(ctlr_handle, TWA_LARGE_RESPONSE_QUEUE_OFFSET, 4)
#define TW_CLI_SOFT_RESET(ctlr) \
TW_CLI_WRITE_CONTROL_REGISTER(ctlr, \
TWA_CONTROL_ISSUE_SOFT_RESET | \
@ -408,6 +429,12 @@ struct tw_cl_param_9k {
#define GET_RESP_ID(undef2__resp_id__undef1) \
((undef2__resp_id__undef1 >> 4) & 0xFF) /* 20:8:4 */
#define GET_RESP_ID_9K_X(undef2__resp_id) \
((undef2__resp_id) & 0xFFF) /* 20:12 */
#define GET_LARGE_RESP_ID(misc__large_resp_id) \
((misc__large_resp_id) & 0xFFFF) /* 16:16 */
#define GET_REQ_ID(lun_l4__req_id) \
(lun_l4__req_id & 0xFFF) /* 4:12 */

File diff suppressed because it is too large Load Diff

View File

@ -61,19 +61,96 @@
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);
}
/*
* 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 */

View File

@ -70,10 +70,11 @@ tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
/*
* Serialize access to this function so multiple threads don't try to
* do the same thing (such as clearing interrupt bits).
* Synchronize access between writes to command and control registers
* in 64-bit environments, on G66.
*/
tw_osl_get_lock(ctlr_handle, ctlr->intr_lock);
if (ctlr->state & TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED)
tw_osl_get_lock(ctlr_handle, ctlr->io_lock);
/* Read the status register to determine the type of interrupt. */
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
@ -114,7 +115,8 @@ tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
rc |= TW_CL_TRUE; /* request for a deferred isr call */
}
out:
tw_osl_free_lock(ctlr_handle, ctlr->intr_lock);
if (ctlr->state & TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED)
tw_osl_free_lock(ctlr_handle, ctlr->io_lock);
return(rc);
}
@ -319,10 +321,13 @@ tw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr)
tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q);
req->state = TW_CLI_REQ_STATE_COMPLETE;
tw_cli_req_q_insert_tail(req, TW_CLI_COMPLETE_Q);
#ifdef TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST
tw_osl_free_lock(ctlr->ctlr_handle, ctlr->intr_lock);
/* Call the CL internal callback, if there's one. */
if (req->tw_cli_callback)
req->tw_cli_callback(req);
tw_osl_get_lock(ctlr->ctlr_handle, ctlr->intr_lock);
#endif /* TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST */
}

View File

@ -78,6 +78,7 @@ tw_cl_start_io(struct tw_cl_ctlr_handle *ctlr_handle,
tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
"I/O during reset: returning busy. Ctlr state = 0x%x",
ctlr->state);
tw_osl_ctlr_busy(ctlr_handle, req_handle);
return(TW_OSL_EBUSY);
}
@ -101,6 +102,7 @@ tw_cl_start_io(struct tw_cl_ctlr_handle *ctlr_handle,
)) == TW_CL_NULL) {
tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
"Out of request context packets: returning busy");
tw_osl_ctlr_busy(ctlr_handle, req_handle);
return(TW_OSL_EBUSY);
}
@ -178,16 +180,30 @@ TW_INT32
tw_cli_submit_cmd(struct tw_cli_req_context *req)
{
struct tw_cli_ctlr_context *ctlr = req->ctlr;
struct tw_cl_ctlr_handle *ctlr_handle = ctlr->ctlr_handle;
TW_UINT32 status_reg;
TW_INT32 error;
TW_UINT8 notify_osl_of_ctlr_busy = TW_CL_FALSE;
#ifdef TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST
TW_SYNC_HANDLE sync_handle;
#endif /* TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST */
tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
/* Serialize access to the controller cmd queue. */
tw_osl_get_lock(ctlr->ctlr_handle, ctlr->io_lock);
tw_osl_get_lock(ctlr_handle, ctlr->io_lock);
#ifdef TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST
if (req->flags & TW_CLI_REQ_FLAGS_EXTERNAL) {
if (!(ctlr->flags & TW_CL_DEFERRED_INTR_USED))
tw_osl_sync_isr_block(ctlr_handle, &sync_handle);
} else {
if (ctlr->flags & TW_CL_DEFERRED_INTR_USED)
tw_osl_sync_io_block(ctlr_handle, &sync_handle);
}
#endif /* TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST */
/* Check to see if we can post a command. */
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
if ((error = tw_cli_check_ctlr_state(ctlr, status_reg)))
goto out;
@ -195,7 +211,7 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
struct tw_cl_req_packet *req_pkt =
(struct tw_cl_req_packet *)(req->orig_req);
tw_cli_dbg_printf(7, ctlr->ctlr_handle, tw_osl_cur_func(),
tw_cli_dbg_printf(7, ctlr_handle, tw_osl_cur_func(),
"Cmd queue full");
if ((req->flags & TW_CLI_REQ_FLAGS_INTERNAL)
@ -205,7 +221,7 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
#endif /* TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST */
) {
if (req->state != TW_CLI_REQ_STATE_PENDING) {
tw_cli_dbg_printf(2, ctlr->ctlr_handle,
tw_cli_dbg_printf(2, ctlr_handle,
tw_osl_cur_func(),
"pending internal/ioctl request");
req->state = TW_CLI_REQ_STATE_PENDING;
@ -213,14 +229,12 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
error = 0;
} else
error = TW_OSL_EBUSY;
} else
} else {
notify_osl_of_ctlr_busy = TW_CL_TRUE;
error = TW_OSL_EBUSY;
/* Unmask command interrupt. */
TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
}
} else {
tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(),
tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
"Submitting command");
/*
@ -230,13 +244,42 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req)
*/
req->state = TW_CLI_REQ_STATE_BUSY;
tw_cli_req_q_insert_tail(req, TW_CLI_BUSY_Q);
TW_CLI_WRITE_COMMAND_QUEUE(ctlr->ctlr_handle,
TW_CLI_WRITE_COMMAND_QUEUE(ctlr_handle,
req->cmd_pkt_phys +
sizeof(struct tw_cl_command_header));
}
out:
tw_osl_free_lock(ctlr->ctlr_handle, ctlr->io_lock);
#ifdef TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST
if (req->flags & TW_CLI_REQ_FLAGS_EXTERNAL) {
if (!(ctlr->flags & TW_CL_DEFERRED_INTR_USED))
tw_osl_sync_isr_unblock(ctlr_handle, &sync_handle);
} else {
if (ctlr->flags & TW_CL_DEFERRED_INTR_USED)
tw_osl_sync_io_unblock(ctlr_handle, &sync_handle);
}
#endif /* TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST */
tw_osl_free_lock(ctlr_handle, ctlr->io_lock);
if (status_reg & TWA_STATUS_COMMAND_QUEUE_FULL) {
if (notify_osl_of_ctlr_busy)
tw_osl_ctlr_busy(ctlr_handle, req->req_handle);
/*
* Synchronize access between writes to command and control
* registers in 64-bit environments, on G66.
*/
if (ctlr->state & TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED)
tw_osl_get_lock(ctlr_handle, ctlr->io_lock);
/* Unmask command interrupt. */
TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
TWA_CONTROL_UNMASK_COMMAND_INTERRUPT);
if (ctlr->state & TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED)
tw_osl_free_lock(ctlr_handle, ctlr->io_lock);
}
return(error);
}
@ -276,6 +319,7 @@ tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle,
"Passthru request during reset: returning busy. "
"Ctlr state = 0x%x",
ctlr->state);
tw_osl_ctlr_busy(ctlr_handle, req_handle);
return(TW_OSL_EBUSY);
}
@ -286,6 +330,7 @@ tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle,
)) == TW_CL_NULL) {
tw_cli_dbg_printf(2, ctlr_handle, tw_osl_cur_func(),
"Out of request context packets: returning busy");
tw_osl_ctlr_busy(ctlr_handle, req_handle);
return(TW_OSL_EBUSY);
}
@ -673,6 +718,17 @@ tw_cl_ioctl(struct tw_cl_ctlr_handle *ctlr_handle, TW_INT32 cmd, TW_VOID *buf)
comp_pkt.working_srl = ctlr->working_srl;
comp_pkt.working_branch = ctlr->working_branch;
comp_pkt.working_build = ctlr->working_build;
comp_pkt.driver_srl_high = TWA_CURRENT_FW_SRL;
comp_pkt.driver_branch_high =
TWA_CURRENT_FW_BRANCH(ctlr->arch_id);
comp_pkt.driver_build_high =
TWA_CURRENT_FW_BUILD(ctlr->arch_id);
comp_pkt.driver_srl_low = TWA_BASE_FW_SRL;
comp_pkt.driver_branch_low = TWA_BASE_FW_BRANCH;
comp_pkt.driver_build_high = TWA_BASE_FW_BUILD;
comp_pkt.fw_on_ctlr_srl = ctlr->fw_on_ctlr_srl;
comp_pkt.fw_on_ctlr_branch = ctlr->fw_on_ctlr_branch;
comp_pkt.fw_on_ctlr_build = ctlr->fw_on_ctlr_build;
user_buf->driver_pkt.status = 0;
/* Copy compatibility information to user space. */
@ -1176,6 +1232,26 @@ tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr)
TW_CLI_SOFT_RESET(ctlr_handle);
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;
}
if ((error = tw_cli_poll_status(ctlr,
TWA_STATUS_MICROCONTROLLER_READY |
TWA_STATUS_ATTENTION_INTERRUPT,

View File

@ -73,6 +73,15 @@ struct tw_cl_compatibility_packet {
driver is compatible with */
TW_UINT16 working_build; /* build # of the firmware that the
driver is compatible with */
TW_UINT16 driver_srl_high;/* highest driver supported srl */
TW_UINT16 driver_branch_high;/* highest driver supported branch */
TW_UINT16 driver_build_high;/* highest driver supported build */
TW_UINT16 driver_srl_low;/* lowest driver supported srl */
TW_UINT16 driver_branch_low;/* lowest driver supported branch */
TW_UINT16 driver_build_low;/* lowest driver supported build */
TW_UINT16 fw_on_ctlr_srl; /* srl of running firmware */
TW_UINT16 fw_on_ctlr_branch;/* branch # of running firmware */
TW_UINT16 fw_on_ctlr_build;/* build # of running firmware */
};

View File

@ -64,9 +64,9 @@ TW_INT8 *tw_cli_severity_string_table[] = {
/*
* Function name: tw_cli_drain_complete_queue
* Description: This function gets called during a controller reset.
* It errors back to CAM, all those requests that are
* in the complete queue, at the time of the reset. Any
* CL internal requests will be simply freed.
* It errors back to the OS Layer, all those requests that
* are in the complete queue, at the time of the reset.
* Any CL internal requests will be simply freed.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
@ -116,8 +116,9 @@ tw_cli_drain_complete_queue(struct tw_cli_ctlr_context *ctlr)
/*
* Function name: tw_cli_drain_busy_queue
* Description: This function gets called during a controller reset.
* It errors back to CAM, all those requests that were
* pending with the firmware, at the time of the reset.
* It errors back to the OS Layer, all those requests that
* were pending with the firmware, at the time of the
* reset.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
@ -166,8 +167,8 @@ tw_cli_drain_busy_queue(struct tw_cli_ctlr_context *ctlr)
/*
* Function name: tw_cli_drain_pending_queue
* Description: This function gets called during a controller reset.
* It errors back to CAM, all those requests that were
* in the pending queue, at the time of the reset.
* It errors back to the OS Layer, all those requests that
* were in the pending queue, at the time of the reset.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
@ -248,6 +249,49 @@ tw_cli_drain_response_queue(struct tw_cli_ctlr_context *ctlr)
/*
* Function name: tw_cli_find_response
* Description: Find a particular response in the ctlr response queue.
*
* Input: ctlr -- ptr to per ctlr structure
* req_id -- request id of the response to look for
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cli_find_response(struct tw_cli_ctlr_context *ctlr, TW_INT32 req_id)
{
TW_UINT32 resp;
TW_INT32 resp_id;
TW_UINT32 status_reg;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
for (;;) {
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
if (tw_cli_check_ctlr_state(ctlr, status_reg))
return(TW_OSL_EGENFAILURE);
if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
return(TW_OSL_ENOTTY); /* no more response queue entries */
if (ctlr->device_id == TW_CL_DEVICE_ID_9K) {
resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
resp_id = GET_RESP_ID(resp);
} else {
resp = TW_CLI_READ_LARGE_RESPONSE_QUEUE(
ctlr->ctlr_handle);
resp_id = GET_LARGE_RESP_ID(resp);
}
if (resp_id == req_id)
return(TW_OSL_ESUCCESS); /* found the req_id */
}
}
/*
* Function name: tw_cli_drain_aen_queue
* Description: Fetches all un-retrieved AEN's posted by fw.
@ -479,6 +523,7 @@ tw_cl_create_event(struct tw_cl_ctlr_handle *ctlr_handle,
struct tw_cli_ctlr_context *ctlr = ctlr_handle->cl_ctlr_ctxt;
struct tw_cl_event_packet event_pkt;
struct tw_cl_event_packet *event;
TW_UINT32 aen_head;
va_list ap;
tw_cli_dbg_printf(8, ctlr_handle, tw_osl_cur_func(), "entered");
@ -487,19 +532,25 @@ tw_cl_create_event(struct tw_cl_ctlr_handle *ctlr_handle,
/* Protect access to ctlr->aen_head. */
tw_osl_get_lock(ctlr_handle, ctlr->gen_lock);
aen_head = ctlr->aen_head;
ctlr->aen_head = (aen_head + 1) % ctlr->max_aens_supported;
/* Queue the event. */
event = &(ctlr->aen_queue[ctlr->aen_head]);
event = &(ctlr->aen_queue[aen_head]);
tw_osl_memzero(event->parameter_data,
sizeof(event->parameter_data));
if (event->retrieved == TW_CL_AEN_NOT_RETRIEVED)
ctlr->aen_q_overflow = TW_CL_TRUE;
event->sequence_id = ++(ctlr->aen_cur_seq_id);
if ((ctlr->aen_head + 1) == ctlr->max_aens_supported) {
if ((aen_head + 1) == ctlr->max_aens_supported) {
tw_cli_dbg_printf(4, ctlr->ctlr_handle,
tw_osl_cur_func(), "AEN queue wrapped");
ctlr->aen_q_wrapped = TW_CL_TRUE;
}
/* Free access to ctlr->aen_head. */
tw_osl_free_lock(ctlr_handle, ctlr->gen_lock);
} else {
event = &event_pkt;
tw_osl_memzero(event, sizeof(struct tw_cl_event_packet));
@ -533,12 +584,6 @@ tw_cl_create_event(struct tw_cl_ctlr_handle *ctlr_handle,
event->parameter_len,
event->parameter_data);
if ((ctlr) && (queue_event)) {
ctlr->aen_head =
(ctlr->aen_head + 1) % ctlr->max_aens_supported;
/* Free access to ctlr->aen_head. */
tw_osl_free_lock(ctlr_handle, ctlr->gen_lock);
}
tw_osl_notify_event(ctlr_handle, event);
}
@ -568,10 +613,9 @@ tw_cli_get_request(struct tw_cli_ctlr_context *ctlr
#ifdef TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST
if (req_pkt) {
if (ctlr->num_free_req_ids == 0) {
DbgPrint("Out of req_ids!!\n");
if (ctlr->num_free_req_ids == 0)
return(TW_CL_NULL);
}
ctlr->num_free_req_ids--;
req = (struct tw_cli_req_context *)(req_pkt->non_dma_mem);
req->ctlr = ctlr;
@ -673,7 +717,8 @@ tw_cli_notify_ctlr_info(struct tw_cli_ctlr_context *ctlr)
{
TW_INT8 fw_ver[16];
TW_INT8 bios_ver[16];
TW_INT32 error[2];
TW_INT8 ctlr_model[16];
TW_INT32 error[3];
TW_UINT8 num_ports = 0;
tw_cli_dbg_printf(5, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
@ -688,12 +733,15 @@ tw_cli_notify_ctlr_info(struct tw_cli_ctlr_context *ctlr)
TWA_PARAM_VERSION_FW, fw_ver, 16, TW_CL_NULL);
error[1] = tw_cli_get_param(ctlr, TWA_PARAM_VERSION_TABLE,
TWA_PARAM_VERSION_BIOS, bios_ver, 16, TW_CL_NULL);
error[2] = tw_cli_get_param(ctlr, TWA_PARAM_VERSION_TABLE,
TWA_PARAM_CTLR_MODEL, ctlr_model, 16, TW_CL_NULL);
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1300, 0x3, TW_CL_SEVERITY_INFO_STRING,
"Controller details:",
"%d ports, Firmware %.16s, BIOS %.16s",
"Model %.16s, %d ports, Firmware %.16s, BIOS %.16s",
error[2]?(TW_INT8 *)TW_CL_NULL:ctlr_model,
num_ports,
error[0]?(TW_INT8 *)TW_CL_NULL:fw_ver,
error[1]?(TW_INT8 *)TW_CL_NULL:bios_ver);
@ -726,15 +774,19 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
TW_INT8 desc[200];
tw_osl_memzero(desc, 200);
tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1301, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Missing expected status bit(s)",
"status reg = 0x%x; Missing bits: %s",
status_reg,
tw_cli_describe_bits (~status_reg &
TWA_STATUS_EXPECTED_BITS, desc));
error = TW_OSL_EGENFAILURE;
if ((status_reg & TWA_STATUS_MICROCONTROLLER_READY) ||
(!(ctlr->state &
TW_CLI_CTLR_STATE_RESET_PHASE1_IN_PROGRESS))) {
tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1301, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Missing expected status bit(s)",
"status reg = 0x%x; Missing bits: %s",
status_reg,
tw_cli_describe_bits (~status_reg &
TWA_STATUS_EXPECTED_BITS, desc));
error = TW_OSL_EGENFAILURE;
}
}
/* Check if any error bits are set. */
@ -802,18 +854,6 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
TWA_CONTROL_CLEAR_QUEUE_ERROR);
}
if (status_reg & TWA_STATUS_SBUF_WRITE_ERROR) {
tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1306, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"SBUF write error: clearing... ",
"status reg = 0x%x %s",
status_reg,
tw_cli_describe_bits(status_reg, desc));
TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
TWA_CONTROL_CLEAR_SBUF_WRITE_ERROR);
}
if (status_reg & TWA_STATUS_MICROCONTROLLER_ERROR) {
tw_cl_create_event(ctlr_handle, TW_CL_TRUE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
@ -844,8 +884,6 @@ tw_cli_describe_bits(TW_UINT32 reg, TW_INT8 *str)
{
tw_osl_strcpy(str, "[");
if (reg & TWA_STATUS_SBUF_WRITE_ERROR)
tw_osl_strcpy(str, "SBUF_WR_ERR,");
if (reg & TWA_STATUS_COMMAND_QUEUE_EMPTY)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "CMD_Q_EMPTY,");
if (reg & TWA_STATUS_MICROCONTROLLER_READY)

View File

@ -46,16 +46,27 @@
*/
#define TW_CL_VERSION_STRING "1.00.00.007"
#define TW_CL_VERSION_STRING "1.00.01.011"
#define TW_CL_NULL ((TW_VOID *)0)
#define TW_CL_TRUE 1
#define TW_CL_FALSE 0
#define TW_CL_VENDOR_ID 0x13C1 /* 3ware vendor id */
#define TW_CL_DEVICE_ID_9K 0x1002 /* 9000 series device id */
#define TW_CL_DEVICE_ID_9K 0x1002 /* 9000 PCI series device id */
#define TW_CL_DEVICE_ID_9K_X 0x1003 /* 9000 PCI-X series device id */
#define TW_CL_BAR_TYPE_IO 1 /* I/O base address */
#define TW_CL_BAR_TYPE_MEM 2 /* memory base address */
#define TW_CL_BAR_TYPE_SBUF 3 /* SBUF base address */
#ifdef TW_OSL_ENCLOSURE_SUPPORT
#define TW_CL_MAX_NUM_UNITS 65 /* max # of units we support
-- enclosure target id is 64 */
#else /* TW_OSL_ENCLOSURE_SUPPORT */
#define TW_CL_MAX_NUM_UNITS 16 /* max # of units we support */
#endif /* TW_OSL_ENCLOSURE_SUPPORT */
#define TW_CL_MAX_NUM_LUNS 16 /* max # of LUN's we support */
#define TW_CL_MAX_IO_SIZE 0x20000 /* 128K */
@ -76,6 +87,7 @@
#define TW_CL_START_CTLR_ONLY (1<<2) /* Start ctlr only */
#define TW_CL_STOP_CTLR_ONLY (1<<3) /* Stop ctlr only */
#define TW_CL_FLASH_FIRMWARE (1<<4) /* Flash firmware */
#define TW_CL_DEFERRED_INTR_USED (1<<5) /* OS Layer uses deferred intr */
/* Possible error values from the Common Layer. */
#define TW_CL_ERR_REQ_SUCCESS 0
@ -331,6 +343,12 @@ struct tw_cl_sg_desc64 {
#ifndef TW_BUILDING_API
#include "tw_osl_inline.h"
/*
* The following are extern declarations of OS Layer defined functions called
* by the Common Layer. If any function has been defined as a macro in
@ -343,6 +361,13 @@ extern TW_VOID tw_osl_breakpoint(TW_VOID);
#endif
#ifndef tw_osl_ctlr_busy
/* Called when CL is too busy to accept new requests. */
extern TW_VOID tw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
struct tw_cl_req_handle *req_handle);
#endif
#ifndef tw_osl_ctlr_ready
/* Called on cmd interrupt. Allows re-submission of any pending requests. */
extern TW_VOID tw_osl_ctlr_ready(struct tw_cl_ctlr_handle *ctlr_handle);
@ -472,6 +497,44 @@ extern TW_INT32 tw_osl_strlen(TW_VOID *str);
#endif
#ifdef TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST
#ifndef tw_osl_sync_io_block
/* Block new I/O requests from being sent by the OS Layer. */
extern TW_VOID tw_osl_sync_io_block(struct tw_cl_ctlr_handle *ctlr_handle,
TW_SYNC_HANDLE *sync_handle);
#endif
#ifndef tw_osl_sync_io_unblock
/* Allow new I/O requests from the OS Layer. */
extern TW_VOID tw_osl_sync_io_unblock(struct tw_cl_ctlr_handle *ctlr_handle,
TW_SYNC_HANDLE *sync_handle);
#endif
#ifndef tw_osl_sync_isr_block
/* Block the ISR from being called by the OS Layer. */
extern TW_VOID tw_osl_sync_isr_block(struct tw_cl_ctlr_handle *ctlr_handle,
TW_SYNC_HANDLE *sync_handle);
#endif
#ifndef tw_osl_sync_isr_unblock
/* Allow calls to the ISR from the OS Layer. */
extern TW_VOID tw_osl_sync_isr_unblock(struct tw_cl_ctlr_handle *ctlr_handle,
TW_SYNC_HANDLE *sync_handle);
#endif
#endif /* TW_OSL_NON_DMA_MEM_ALLOC_PER_REQUEST */
#ifndef tw_osl_vsprintf
/* Standard vsprintf. */
extern TW_INT32 tw_osl_vsprintf(TW_INT8 *dest, const TW_INT8 *fmt, va_list ap);
#endif
#ifdef TW_OSL_CAN_SLEEP
#ifndef tw_osl_wakeup
/* Wake up a thread sleeping by a call to tw_osl_sleep. */
@ -525,7 +588,7 @@ extern TW_INT32 tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle,
/* Find out how much memory CL needs. */
extern 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_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
@ -540,10 +603,16 @@ extern TW_INT32 tw_cl_get_mem_requirements(
);
/* Return PCI BAR info. */
extern 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);
/* Initialize Common Layer for a given controller. */
extern 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_UINT32 flags, 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
#endif /* TW_OSL_FLASH_FIRMWARE */
@ -588,4 +657,6 @@ extern TW_INT32 tw_cl_start_io(struct tw_cl_ctlr_handle *ctlr_handle,
struct tw_cl_req_packet *req_pkt, struct tw_cl_req_handle *req_handle);
#endif /* TW_BUILDING_API */
#endif /* TW_CL_SHARE_H */

View File

@ -51,6 +51,8 @@
#define TW_OSLI_MAX_NUM_IOS TW_CL_MAX_SIMULTANEOUS_REQUESTS
#define TW_OSLI_MAX_NUM_AENS 0x100
#define TW_OSLI_DEFERRED_INTR_USED
/* Possible values of req->state. */
#define TW_OSLI_REQ_STATE_INIT 0x0 /* being initialized */
#define TW_OSLI_REQ_STATE_BUSY 0x1 /* submitted to CL */
@ -124,6 +126,7 @@ struct twa_softc {
TW_UINT32 state;
TW_UINT32 flags;
TW_INT32 device_id;
TW_UINT32 alignment;
TW_UINT32 sg_size_factor;

View File

@ -120,6 +120,7 @@ tw_osli_cam_attach(struct twa_softc *sc)
* Register the bus.
*/
tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
mtx_lock(&Giant);
if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) {
cam_sim_free(sc->sim, TRUE);
sc->sim = NULL; /* so cam_detach will not try to free it */
@ -156,6 +157,7 @@ tw_osli_cam_attach(struct twa_softc *sc)
csa.callback = twa_async;
csa.callback_arg = sc;
xpt_action((union ccb *)&csa);
mtx_unlock(&Giant);
tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
/*
@ -449,7 +451,7 @@ twa_action(struct cam_sim *sim, union ccb *ccb)
path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
path_inq->unit_number = cam_sim_unit(sim);
path_inq->bus_id = cam_sim_bus(sim);
path_inq->initiator_id = 12;
path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
path_inq->base_transfer_speed = 100000;
strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
@ -570,6 +572,9 @@ tw_osli_request_bus_scan(struct twa_softc *sc)
tw_osli_dbg_dprintf(3, sc, "entering");
/* If we get here before sc->sim is initialized, return an error. */
if (!(sc->sim))
return(ENXIO);
if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
return(ENOMEM);
bzero(ccb, sizeof(union ccb));
@ -648,12 +653,33 @@ tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb)
TW_VOID
tw_osli_disallow_new_requests(struct twa_softc *sc)
{
mtx_lock(&Giant);
xpt_freeze_simq(sc->sim, 1);
mtx_unlock(&Giant);
sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
}
/*
* Function name: tw_osl_ctlr_busy
* Description: CL calls this function on cmd queue full or otherwise,
* when it is too busy to accept new requests.
*
* Input: ctlr_handle -- ptr to controller handle
* req_handle -- ptr to request handle sent by OSL.
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
struct tw_cl_req_handle *req_handle)
{
tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt);
}
/*
* Function name: tw_osl_scan_bus
* Description: CL calls this function to request for a bus scan.
@ -722,12 +748,12 @@ tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
/* This request never got submitted to the firmware. */
if (req->error_code == EBUSY) {
/*
* Cmd queue is full, or common layer is out
* of resources. Freeze the simq to maintain
* ccb ordering. The next ccb that gets
* Cmd queue is full, or the Common Layer is out of
* resources. The simq will already have been frozen
* by CL's call to tw_osl_ctlr_busy, and this will
* maintain ccb ordering. The next ccb that gets
* completed will unfreeze the simq.
*/
tw_osli_disallow_new_requests(req->ctlr);
ccb->ccb_h.status |= CAM_REQUEUE_REQ;
}
else if (req->error_code == EFBIG)

View File

@ -175,7 +175,9 @@ static TW_INT32 twa_detach(device_t dev);
static TW_INT32 twa_shutdown(device_t dev);
static TW_VOID twa_busdma_lock(TW_VOID *lock_arg, bus_dma_lock_op_t op);
static TW_VOID twa_pci_intr(TW_VOID *arg);
#ifdef TW_OSLI_DEFERRED_INTR_USED
static TW_VOID twa_deferred_intr(TW_VOID *context, TW_INT32 pending);
#endif /* TW_OSLI_DEFERRED_INTR_USED */
static TW_INT32 tw_osli_alloc_mem(struct twa_softc *sc);
static TW_VOID tw_osli_free_resources(struct twa_softc *sc);
@ -257,6 +259,9 @@ twa_attach(device_t dev)
{
struct twa_softc *sc = device_get_softc(dev);
TW_UINT32 command;
TW_INT32 bar_num;
TW_INT32 bar0_offset;
TW_INT32 bar_size;
TW_INT32 error;
tw_osli_dbg_dprintf(3, sc, "entered");
@ -265,6 +270,7 @@ twa_attach(device_t dev)
/* Initialize the softc structure. */
sc->bus_dev = dev;
sc->device_id = pci_get_device(dev);
/* Initialize the mutexes right here. */
sc->io_lock = &(sc->io_lock_handle);
@ -307,8 +313,19 @@ twa_attach(device_t dev)
pci_write_config(dev, PCIR_COMMAND, command, 2);
/* Allocate the PCI register window. */
sc->reg_res_id = PCIR_BARS;
if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
if ((error = tw_cl_get_pci_bar_info(sc->device_id, TW_CL_BAR_TYPE_MEM,
&bar_num, &bar0_offset, &bar_size))) {
tw_osli_printf(sc, "error = %d",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x201F,
"Can't get PCI BAR info",
error);
tw_osli_free_resources(sc);
return(error);
}
sc->reg_res_id = PCIR_BARS + bar0_offset;
if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
&(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE))
== NULL) {
tw_osli_printf(sc, "error = %d",
@ -338,8 +355,11 @@ twa_attach(device_t dev)
return(ENXIO);
}
if ((error = bus_setup_intr(sc->bus_dev, sc->irq_res,
((mp_ncpus > 1) ? (INTR_MPSAFE | INTR_FAST) : 0) |
INTR_TYPE_CAM,
((mp_ncpus > 1) ? (INTR_MPSAFE
#ifdef TW_OSLI_DEFERRED_INTR_USED
| INTR_FAST
#endif /* TW_OSLI_DEFERRED_INTR_USED */
) : 0) | INTR_TYPE_CAM,
twa_pci_intr, sc, &sc->intr_handle))) {
tw_osli_printf(sc, "error = %d",
TW_CL_SEVERITY_ERROR_STRING,
@ -351,7 +371,9 @@ twa_attach(device_t dev)
return(error);
}
#ifdef TW_OSLI_DEFERRED_INTR_USED
TASK_INIT(&sc->deferred_intr_callback, 0, twa_deferred_intr, sc);
#endif /* TW_OSLI_DEFERRED_INTR_USED */
if ((error = tw_osli_alloc_mem(sc))) {
tw_osli_printf(sc, "error = %d",
@ -365,7 +387,7 @@ twa_attach(device_t dev)
}
/* Initialize the Common Layer for this controller. */
if ((error = tw_cl_init_ctlr(&sc->ctlr_handle, sc->flags,
if ((error = tw_cl_init_ctlr(&sc->ctlr_handle, sc->flags, sc->device_id,
TW_OSLI_MAX_NUM_IOS, TW_OSLI_MAX_NUM_AENS,
sc->non_dma_mem, sc->dma_mem,
sc->dma_mem_phys
@ -454,12 +476,15 @@ tw_osli_alloc_mem(struct twa_softc *sc)
#ifdef TW_OSL_FLASH_FIRMWARE
sc->flags |= TW_CL_FLASH_FIRMWARE;
#endif /* TW_OSL_FLASH_FIRMWARE */
#ifdef TW_OSLI_DEFERRED_INTR_USED
sc->flags |= TW_CL_DEFERRED_INTR_USED;
#endif /* TW_OSLI_DEFERRED_INTR_USED */
max_sg_elements = (sizeof(bus_addr_t) == 8) ?
TW_CL_MAX_64BIT_SG_ELEMENTS : TW_CL_MAX_32BIT_SG_ELEMENTS;
if ((error = tw_cl_get_mem_requirements(&sc->ctlr_handle, sc->flags,
TW_OSLI_MAX_NUM_IOS, TW_OSLI_MAX_NUM_AENS,
sc->device_id, TW_OSLI_MAX_NUM_IOS, TW_OSLI_MAX_NUM_AENS,
&(sc->alignment), &(sc->sg_size_factor),
&non_dma_mem_size, &dma_mem_size
#ifdef TW_OSL_FLASH_FIRMWARE
@ -757,9 +782,10 @@ tw_osli_free_resources(struct twa_softc *sc)
"dmamap_destroy(dma) returned %d",
error);
if ((error = bus_dmamap_destroy(sc->ioctl_tag, sc->ioctl_map)))
tw_osli_dbg_dprintf(1, sc,
"dmamap_destroy(ioctl) returned %d", error);
if ((sc->ioctl_tag) && (sc->ioctl_map))
if ((error = bus_dmamap_destroy(sc->ioctl_tag, sc->ioctl_map)))
tw_osli_dbg_dprintf(1, sc,
"dmamap_destroy(ioctl) returned %d", error);
/* Free all memory allocated so far. */
if (sc->req_ctxt_buf)
@ -827,7 +853,7 @@ tw_osli_free_resources(struct twa_softc *sc)
/* Release the register window mapping. */
if (sc->reg_res != NULL)
if ((error = bus_release_resource(sc->bus_dev,
SYS_RES_IOPORT, sc->reg_res_id, sc->reg_res)))
SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res)))
tw_osli_dbg_dprintf(1, sc,
"release_resource(io) returned %d", error);
@ -965,12 +991,18 @@ twa_pci_intr(TW_VOID *arg)
tw_osli_dbg_dprintf(10, sc, "entered");
if (tw_cl_interrupt(&(sc->ctlr_handle)))
#ifdef TW_OSLI_DEFERRED_INTR_USED
taskqueue_enqueue_fast(taskqueue_fast,
&(sc->deferred_intr_callback));
#else /* TW_OSLI_DEFERRED_INTR_USED */
tw_cl_deferred_interrupt(&(sc->ctlr_handle));
#endif /* TW_OSLI_DEFERRED_INTR_USED */
}
#ifdef TW_OSLI_DEFERRED_INTR_USED
/*
* Function name: twa_deferred_intr
* Description: Deferred interrupt handler.
@ -990,6 +1022,8 @@ twa_deferred_intr(TW_VOID *context, TW_INT32 pending)
tw_cl_deferred_interrupt(&(sc->ctlr_handle));
}
#endif /* TW_OSLI_DEFERRED_INTR_USED */
/*
@ -1733,251 +1767,3 @@ twa_reset_stats(TW_VOID)
}
#endif /* TW_OSL_DEBUG */
#ifdef TW_OSL_DEBUG
/*
* Function name: tw_osl_dbg_printf
* Description: Prints passed info (prefixed by ctlr name)to syslog
*
* Input: ctlr_handle -- controller handle
* fmt -- format string for the arguments to follow
* ... -- variable number of arguments, to be printed
* based on the fmt string
* Output: None
* Return value: Number of bytes printed
*/
TW_INT32
tw_osl_dbg_printf(struct tw_cl_ctlr_handle *ctlr_handle,
const TW_INT8 *fmt, ...)
{
va_list args;
TW_INT32 bytes_printed;
bytes_printed = device_print_prettyname(((struct twa_softc *)
(ctlr_handle->osl_ctlr_ctxt))->bus_dev);
va_start(args, fmt);
bytes_printed += vprintf(fmt, args);
va_end(args);
return(bytes_printed);
}
#endif /* TW_OSL_DEBUG */
/*
* Function name: tw_osl_notify_event
* Description: Prints passed event info (prefixed by ctlr name)
* to syslog
*
* Input: ctlr_handle -- controller handle
* event -- ptr to a packet describing the event/error
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_notify_event(struct tw_cl_ctlr_handle *ctlr_handle,
struct tw_cl_event_packet *event)
{
struct twa_softc *sc =
(struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt);
twa_printf(sc, "%s: (0x%02X: 0x%04X): %s: %s\n",
event->severity_str,
event->event_src,
event->aen_code,
event->parameter_data +
strlen(event->parameter_data) + 1,
event->parameter_data);
}
/*
* Function name: tw_osl_read_reg
* Description: Reads a register on the controller
*
* Input: ctlr_handle -- controller handle
* offset -- offset from Base Address
* size -- # of bytes to read
* Output: None
* Return value: Value read
*/
TW_UINT32
tw_osl_read_reg(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 size)
{
bus_space_tag_t bus_tag =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_tag;
bus_space_handle_t bus_handle =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_handle;
if (size == 4)
return((TW_UINT32)bus_space_read_4(bus_tag, bus_handle,
offset));
else if (size == 2)
return((TW_UINT32)bus_space_read_2(bus_tag, bus_handle,
offset));
else
return((TW_UINT32)bus_space_read_1(bus_tag, bus_handle,
offset));
}
/*
* Function name: tw_osl_write_reg
* Description: Writes to a register on the controller
*
* Input: ctlr_handle -- controller handle
* offset -- offset from Base Address
* value -- value to write
* size -- # of bytes to write
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_write_reg(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 value, TW_INT32 size)
{
bus_space_tag_t bus_tag =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_tag;
bus_space_handle_t bus_handle =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_handle;
if (size == 4)
bus_space_write_4(bus_tag, bus_handle, offset, value);
else if (size == 2)
bus_space_write_2(bus_tag, bus_handle, offset, (TW_INT16)value);
else
bus_space_write_1(bus_tag, bus_handle, offset, (TW_INT8)value);
}
#ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
/*
* Function name: tw_osl_read_pci_config
* Description: Reads from the PCI config space.
*
* Input: sc -- ptr to per ctlr structure
* offset -- register offset
* size -- # of bytes to be read
* Output: None
* Return value: Value read
*/
TW_UINT32
tw_osl_read_pci_config(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 size)
{
struct twa_softc *sc =
(struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt);
tw_osli_dbg_dprintf(1, sc, "entered");
return(pci_read_config(sc->bus_dev, offset, size));
}
/*
* Function name: tw_osl_write_pci_config
* Description: Writes to the PCI config space.
*
* Input: sc -- ptr to per ctlr structure
* offset -- register offset
* value -- value to write
* size -- # of bytes to be written
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_write_pci_config(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 value, TW_INT32 size)
{
struct twa_softc *sc =
(struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt);
tw_osli_dbg_dprintf(1, sc, "entered");
pci_write_config(sc->bus_dev, offset/*PCIR_STATUS*/, value, size);
}
#endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
/*
* Function name: tw_osl_get_local_time
* Description: Gets the local time
*
* Input: None
* Output: None
* Return value: local time
*/
TW_TIME
tw_osl_get_local_time()
{
return(time_second - (tz_minuteswest * 60) -
(wall_cmos_clock ? adjkerntz : 0));
}
/*
* Function name: tw_osl_delay
* Description: Spin for the specified time
*
* Input: usecs -- micro-seconds to spin
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_delay(TW_INT32 usecs)
{
DELAY(usecs);
}
#ifdef TW_OSL_CAN_SLEEP
/*
* Function name: tw_osl_sleep
* Description: Sleep for the specified time, or until woken up
*
* Input: ctlr_handle -- controller handle
* sleep_handle -- handle to sleep on
* timeout -- time period (in ms) to sleep
* Output: None
* Return value: 0 -- successfully woken up
* EWOULDBLOCK -- time out
* ERESTART -- woken up by a signal
*/
TW_INT32
tw_osl_sleep(struct tw_cl_ctlr_handle *ctlr_handle,
TW_SLEEP_HANDLE *sleep_handle, TW_INT32 timeout)
{
return(tsleep((TW_VOID *)sleep_handle, PRIBIO, NULL, timeout));
}
/*
* Function name: tw_osl_wakeup
* Description: Wake up a sleeping process
*
* Input: ctlr_handle -- controller handle
* sleep_handle -- handle of sleeping process to be
woken up
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_wakeup(struct tw_cl_ctlr_handle *ctlr_handle,
TW_SLEEP_HANDLE *sleep_handle)
{
wakeup_one(sleep_handle);
}
#endif /* TW_OSL_CAN_SLEEP */

View File

@ -72,7 +72,6 @@
#include <dev/twa/tw_osl_share.h>
#include <dev/twa/tw_cl_share.h>
#include <dev/twa/tw_osl.h>
#include <dev/twa/tw_osl_externs.h>

365
sys/dev/twa/tw_osl_inline.h Normal file
View File

@ -0,0 +1,365 @@
/*
* Copyright (c) 2004-05 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap.
* 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 THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
*/
#ifndef TW_OSL_INLINE_H
#define TW_OSL_INLINE_H
/*
* Inline functions shared between OSL and CL, and defined by OSL.
*/
#include <dev/twa/tw_osl.h>
/*
* Function name: tw_osl_init_lock
* Description: Initializes a lock.
*
* Input: ctlr_handle -- ptr to controller handle
* lock_name -- string indicating name of the lock
* Output: lock -- ptr to handle to the initialized lock
* Return value: None
*/
#define tw_osl_init_lock(ctlr_handle, lock_name, lock) \
mtx_init(lock, lock_name, NULL, MTX_SPIN)
/*
* Function name: tw_osl_destroy_lock
* Description: Destroys a previously initialized lock.
*
* Input: ctlr_handle -- ptr to controller handle
* lock -- ptr to handle to the lock to be
* destroyed
* Output: None
* Return value: None
*/
#define tw_osl_destroy_lock(ctlr_handle, lock) \
mtx_destroy(lock)
/*
* Function name: tw_osl_get_lock
* Description: Acquires the specified lock.
*
* Input: ctlr_handle -- ptr to controller handle
* lock -- ptr to handle to the lock to be
* acquired
* Output: None
* Return value: None
*/
#define tw_osl_get_lock(ctlr_handle, lock) \
mtx_lock_spin(lock)
/*
* Function name: tw_osl_free_lock
* Description: Frees a previously acquired lock.
*
* Input: ctlr_handle -- ptr to controller handle
* lock -- ptr to handle to the lock to be freed
* Output: None
* Return value: None
*/
#define tw_osl_free_lock(ctlr_handle, lock) \
mtx_unlock_spin(lock)
/*
* Function name: tw_osl_ctlr_ready
* Description: CL calls this function to notify the OS Layer that it
* is ready to accept new requests. This function is
* called only if a call to tw_osl_ctlr_busy has been
* made previously. We don't use this function as of now.
*
* Input: ctlr_handle -- ptr to controller handle
* Output: None
* Return value: None
*/
#define tw_osl_ctlr_ready(ctlr_handle)
#ifdef TW_OSL_DEBUG
/*
* Function name: tw_osl_dbg_printf
* Description: Prints passed info (prefixed by ctlr name)to syslog
*
* Input: ctlr_handle -- controller handle
* fmt -- format string for the arguments to follow
* ... -- variable number of arguments, to be printed
* based on the fmt string
* Output: None
* Return value: Number of bytes printed
*/
#define tw_osl_dbg_printf(ctlr_handle, fmt, args...) \
twa_printf((ctlr_handle->osl_ctlr_ctxt), fmt, ##args)
#endif /* TW_OSL_DEBUG */
/*
* Function name: tw_osl_notify_event
* Description: Prints passed event info (prefixed by ctlr name)
* to syslog
*
* Input: ctlr_handle -- controller handle
* event -- ptr to a packet describing the event/error
* Output: None
* Return value: None
*/
#define tw_osl_notify_event(ctlr_handle, event) \
twa_printf((ctlr_handle->osl_ctlr_ctxt), \
"%s: (0x%02X: 0x%04X): %s: %s\n", \
event->severity_str, \
event->event_src, \
event->aen_code, \
event->parameter_data + \
strlen(event->parameter_data) + 1, \
event->parameter_data)
/*
* Function name: tw_osl_read_reg
* Description: Reads a register on the controller
*
* Input: ctlr_handle -- controller handle
* offset -- offset from Base Address
* size -- # of bytes to read
* Output: None
* Return value: Value read
*/
#define tw_osl_read_reg tw_osl_read_reg_inline
static __inline TW_UINT32
tw_osl_read_reg_inline(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 size)
{
bus_space_tag_t bus_tag =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_tag;
bus_space_handle_t bus_handle =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_handle;
if (size == 4)
return((TW_UINT32)bus_space_read_4(bus_tag, bus_handle,
offset));
else if (size == 2)
return((TW_UINT32)bus_space_read_2(bus_tag, bus_handle,
offset));
else
return((TW_UINT32)bus_space_read_1(bus_tag, bus_handle,
offset));
}
/*
* Function name: tw_osl_write_reg
* Description: Writes to a register on the controller
*
* Input: ctlr_handle -- controller handle
* offset -- offset from Base Address
* value -- value to write
* size -- # of bytes to write
* Output: None
* Return value: None
*/
#define tw_osl_write_reg tw_osl_write_reg_inline
static __inline TW_VOID
tw_osl_write_reg_inline(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 value, TW_INT32 size)
{
bus_space_tag_t bus_tag =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_tag;
bus_space_handle_t bus_handle =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_handle;
if (size == 4)
bus_space_write_4(bus_tag, bus_handle, offset, value);
else if (size == 2)
bus_space_write_2(bus_tag, bus_handle, offset, (TW_INT16)value);
else
bus_space_write_1(bus_tag, bus_handle, offset, (TW_INT8)value);
}
#ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
/*
* Function name: tw_osl_read_pci_config
* Description: Reads from the PCI config space.
*
* Input: sc -- ptr to per ctlr structure
* offset -- register offset
* size -- # of bytes to be read
* Output: None
* Return value: Value read
*/
#define tw_osl_read_pci_config(ctlr_handle, offset, size) \
pci_read_config( \
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_dev, \
offset, size)
/*
* Function name: tw_osl_write_pci_config
* Description: Writes to the PCI config space.
*
* Input: sc -- ptr to per ctlr structure
* offset -- register offset
* value -- value to write
* size -- # of bytes to be written
* Output: None
* Return value: None
*/
#define tw_osl_write_pci_config(ctlr_handle, offset, value, size) \
pci_write_config( \
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_dev, \
offset/*PCIR_STATUS*/, value, size)
#endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
/*
* Function name: tw_osl_get_local_time
* Description: Gets the local time
*
* Input: None
* Output: None
* Return value: local time
*/
#define tw_osl_get_local_time() \
(time_second - (tz_minuteswest * 60) - \
(wall_cmos_clock ? adjkerntz : 0))
/*
* Function name: tw_osl_delay
* Description: Spin for the specified time
*
* Input: usecs -- micro-seconds to spin
* Output: None
* Return value: None
*/
#define tw_osl_delay(usecs) DELAY(usecs)
#ifdef TW_OSL_CAN_SLEEP
/*
* Function name: tw_osl_sleep
* Description: Sleep for the specified time, or until woken up
*
* Input: ctlr_handle -- controller handle
* sleep_handle -- handle to sleep on
* timeout -- time period (in ms) to sleep
* Output: None
* Return value: 0 -- successfully woken up
* EWOULDBLOCK -- time out
* ERESTART -- woken up by a signal
*/
#define tw_osl_sleep(ctlr_handle, sleep_handle, timeout) \
tsleep((TW_VOID *)sleep_handle, PRIBIO, NULL, timeout)
/*
* Function name: tw_osl_wakeup
* Description: Wake up a sleeping process
*
* Input: ctlr_handle -- controller handle
* sleep_handle -- handle of sleeping process to be
woken up
* Output: None
* Return value: None
*/
#define tw_osl_wakeup(ctlr_handle, sleep_handle) \
wakeup_one(sleep_handle)
#endif /* TW_OSL_CAN_SLEEP */
/* Allows setting breakpoints in the CL code for debugging purposes. */
#define tw_osl_breakpoint() breakpoint()
/* Text name of current function. */
#define tw_osl_cur_func() __func__
/* Copy 'size' bytes from 'src' to 'dest'. */
#define tw_osl_memcpy(dest, src, size) bcopy(src, dest, size)
/* Zero 'size' bytes starting at 'addr'. */
#define tw_osl_memzero bzero
/* Standard sprintf. */
#define tw_osl_sprintf sprintf
/* Copy string 'src' to 'dest'. */
#define tw_osl_strcpy strcpy
/* Return length of string pointed at by 'str'. */
#define tw_osl_strlen strlen
/* Standard vsprintf. */
#define tw_osl_vsprintf vsprintf
#endif /* TW_OSL_INLINE_H */

View File

@ -48,11 +48,20 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
#include <sys/bus.h>
#include <sys/taskqueue.h>
#include <machine/bus.h>
#include <machine/clock.h>
#include <machine/endian.h>
#include <machine/stdarg.h>
#include <dev/pci/pcivar.h>
#include <dev/twa/tw_osl_types.h>
#include "opt_twa.h"
@ -65,7 +74,11 @@
#define TW_OSL_FLASH_FIRMWARE
#endif
#define TW_OSL_DRIVER_VERSION_STRING "3.60.00.017"
#ifdef TWA_ENCLOSURE_SUPPORT
#define TW_OSL_ENCLOSURE_SUPPORT
#endif
#define TW_OSL_DRIVER_VERSION_STRING "3.70.02.012"
#define TW_OSL_CAN_SLEEP
@ -100,35 +113,5 @@ extern TW_INT32 TW_OSL_DEBUG_LEVEL_FOR_CL;
#define TW_OSL_ERESTART ERESTART /* sleep terminated by a signal */
#define tw_osl_breakpoint() breakpoint
#define tw_osl_cur_func() __func__
/*
* Submit any requests previously returned with TW_OSL_EBUSY.
* We don't use it as of now.
*/
#define tw_osl_ctlr_ready(ctlr_handle)
#define tw_osl_destroy_lock(ctlr_handle, lock) \
mtx_destroy(lock)
#define tw_osl_free_lock(ctlr_handle, lock) \
mtx_unlock_spin(lock)
#define tw_osl_get_lock(ctlr_handle, lock) \
mtx_lock_spin(lock)
#define tw_osl_init_lock(ctlr_handle, lock_name, lock) \
mtx_init(lock, lock_name, NULL, MTX_SPIN)
#define tw_osl_memcpy(dest, src, size) bcopy(src, dest, size)
#define tw_osl_memzero bzero
#define tw_osl_sprintf sprintf
#define tw_osl_strcpy strcpy
#define tw_osl_strlen strlen
#define tw_osl_vsprintf vsprintf
#endif /* TW_OSL_SHARE_H */

View File

@ -23,31 +23,53 @@
# 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.
#
#
# 3ware driver for 9000 series storage controllers.
#
# Author: Vinod Kashyap
#
#
# In the line following this comment, a value of 0 on the right hand
# side will not cause firmware to be bundled. Change this value to 1
# to bundle the firmware with the driver, which may be flashed onto
# the controller, if the firmware on the controller is older than the
# one bundled, and needs to be upgraded. The size of the driver will
# increase significantly (to over 500kB) if this option is selected.
# Typically, the firmware image bundled (in tw_cl_fwimg.c) corresponds
# to the latest controller architecture as of the date of the release.
# If the firmware for an earlier controller architecture needs to be
# flashed, the (older) driver with the appropriate firmware image
# bundled can be downloaded from the 3ware website, used to flash the
# firmware, and then the newer driver can be switched to. Alternatively,
# the appropriate firmware image (tw_cl_fwimg.c) from the older driver can
# be used to re-build the newer driver. In this case, the branch
# (TWA_CURRENT_FW_BRANCH_*) and build (TWA_CURRENT_FW_BUILD_*) numbers for
# the bundled firmware need to be appropriately updated in tw_cl_fwif.h
# before building the driver.
#
TWA_FLASH_FIRMWARE?=0
KMOD = twa
.PATH: ${.CURDIR}/../../dev/${KMOD}
SRCS= tw_osl_freebsd.c tw_osl_cam.c \
tw_cl_init.c tw_cl_io.c tw_cl_intr.c tw_cl_misc.c \
bus_if.h device_if.h pci_if.h opt_scsi.h opt_cam.h opt_twa.h
SRCS= tw_osl_freebsd.c tw_osl_cam.c \
tw_cl_init.c tw_cl_io.c tw_cl_intr.c tw_cl_misc.c \
bus_if.h device_if.h pci_if.h opt_scsi.h opt_cam.h opt_twa.h
# Uncomment the following line to turn on Enclosure Services support.
#CFLAGS+= -DTWA_ENCLOSURE_SUPPORT
#CFLAGS+= -DTWA_DEBUG=0
CFLAGS+= -I${.CURDIR}/../../dev/${KMOD}
.if $(TWA_FLASH_FIRMWARE) != 0
CFLAGS+= -DTWA_FLASH_FIRMWARE
SRCS+= tw_cl_fwimg.c
SRCS+= tw_cl_fwimg.c
.endif
.include <bsd.kmod.mk>