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:
parent
f6f8bc7ad5
commit
ff1625c61d
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
@ -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 */
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
365
sys/dev/twa/tw_osl_inline.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user