cpqary3_talk2ctlr.c revision 80c94ecd7a524eb933a4bb221a9618b9dc490e76
/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
*/
/*
* Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
*/
/*
* This module contains routines that program the controller. All
* operations viz., initialization of controller, submision &
* retrieval of commands, enabling & disabling of interrupts,
* checking interrupt status are performed here.
*/
#include "cpqary3.h"
/*
* Local Functions Definitions
*/
/*
* Function : cpqary3_check_simple_ctlr_intr
* Description : This routine determines if the controller did interrupt.
* Called By : cpqary3_hw_isr()
* Parameters : per-controller
* Calls : None
* Return Values: SUCCESS : This controller did interrupt.
* FAILURE : It did not.
*/
{
/*
* Read the Interrupt Status Register and
* if bit 3 is set, it indicates that we have completed commands
* in the controller
*/
if (intr_pending_mask &
return (CPQARY3_SUCCESS);
return (CPQARY3_FAILURE);
}
/*
* Function : cpqary3_check_perf_ctlr_intr
* Description : This routine determines if the
* controller did interrupt.
* Called By : cpqary3_hw_isr()
* Parameters : per-controller
* Calls : None
* Return Values: SUCCESS : This controller did interrupt.
* FAILURE : It did not.
*/
{
/*
* Read the Interrupt Status Register and
* if bit 3 is set, it indicates that we have completed commands
* in the controller
*/
return (CPQARY3_SUCCESS);
}
return (CPQARY3_FAILURE);
}
/*
* Function : cpqary3_check_perf_e200_intr
* Description : This routine determines if the controller
* did interrupt.
* Called By : cpqary3_hw_isr()
* Parameters : per-controller
* Calls : None
* Return Values: SUCCESS : This controller did interrupt.
* FAILURE : It did not.
*/
{
/*
* Read the Interrupt Status Register and
* if bit 3 is set, it indicates that we have completed commands
* in the controller
*/
return (CPQARY3_SUCCESS);
}
return (CPQARY3_FAILURE);
}
/*
* Function : cpqary3_retrieve
* Description : This routine retrieves the completed command from the
* controller reply queue.
* and processes the completed commands.
* Called By : cpqary3_sw_isr(), cpqary3_handle_flag_nointr()
* Parameters : per-controller
* Calls : packet completion routines
* Return Values: SUCCESS : A completed command has been retrieved
* and processed.
* FAILURE : No completed command was in the controller.
*/
{
/*
* Get the Reply Command List Addr
* Update the returned Tag in that particular command structure.
* If a valid one, de-q that from the SUBMITTED Q and
* enqueue that to the RETRIEVED Q.
*/
/* PERF */
/* command has completed */
/* Get the tag */
"CPQary3 : HBA returned Spurious Tag");
return (CPQARY3_FAILURE);
}
tag >> CPQARY3_GET_MEM_TAG];
/* Traverse to the next command in reply queue */
++replyq_ptr->index;
replyq_ptr->index = 0;
/* Toggle at wraparound */
/* LINTED: alignment */
} else {
}
}
/* PERF */
return (CPQARY3_SUCCESS);
}
/*
* Function : cpqary3_poll_retrieve
* Description : This routine retrieves the completed command from the
* controller reply queue in poll mode.
* and processes the completed commands.
* Called By : cpqary3_poll
* Parameters : per-controller
* Calls : packet completion routines
* Return Values: If the polled command is completed, send back a success.
* If not return failure.
*/
{
/* PERF */
tag >> CPQARY3_GET_MEM_TAG];
tag_flag = 1;
}
} else {
/* command has completed */
/* Get the tag */
"CPQary3 : HBA returned Spurious Tag");
return (CPQARY3_FAILURE);
}
tag >> CPQARY3_GET_MEM_TAG];
tag_flag = 1;
/* Traverse to the next command in reply queue */
++replyq_ptr->index;
replyq_ptr->index = 0;
/* Toggle at wraparound */
/* LINTED: alignment */
} else {
}
}
}
/* PERF */
if (tag_flag) {
return (CPQARY3_SUCCESS);
}
return (CPQARY3_FAILURE);
}
/*
* Function : cpqary3_submit
* Description : This routine submits the command to the Inbound Post Q.
* Called By : cpqary3_transport(), cpqary3_send_NOE_command(),
* cpqary3_disable_NOE_command(),
* cpqary3_handle_flag_nointr(),
* cpqary3_tick_hdlr(), cpqary3_synccmd_send()
* Parameters : per-controller, physical address
* Calls : None
* Return Values: None
*/
{
/*
* Write the Physical Address of the command-to-be-submitted
* into the Controller's Inbound Post Q.
*/
#ifdef AMD64_DEBUG
{
char debug_char;
}
#endif
/* CONTROLLER_LOCKUP */
return (retval);
}
/* CONTROLLER_LOCKUP */
} else {
/* The driver always uses the 0th block fetch count always */
}
/* PERF */
/*
* Command submission can NEVER FAIL since the number of commands that
* can reside in the controller at any time is 1024 and our memory
* allocation is for 225 commands ONLY. Thus, at any given time the
* maximum number of commands in the controller is 225.
*/
/* CONTROLLER_LOCKUP */
return (retval);
/* CONTROLLER_LOCKUP */
}
/*
* Function : cpqary3_intr_onoff
* Called By : cpqary3_attach(), ry3_handle_flag_nointr(),
* cpqary3_tick_hdlr(), cpqary3_init_ctlr_resource()
* Calls : None
* Return Values: None
*/
void
{
/*
* Enable or disable the interrupt based on the flag
* Read the Interrupt Mask Register first and then update it
* accordingly
*/
if (flag == CPQARY3_INTR_ENABLE) {
} else {
}
}
/*
* Function : cpqary3_lockup_intr_onoff
* Called By : cpqary3_attach(), cpqary3_handle_flag_nointr(),
* cpqary3_tick_hdlr(), cpqary3_hw_isr,
* cpqary3_init_ctlr_resource()
* Calls : None
* Return Values: None
*/
void
{
uint32_t intr_lockup_mask = 0;
/*
* Enable or disable the interrupt based on the flag
* Read the Interrupt Mask Register first and then update it
* accordingly
*/
if (flag == CPQARY3_INTR_ENABLE) {
} else {
}
}
/*
* Function : cpqary3_init_ctlr
* Description : This routine initialises the HBA to Simple Transport
* Method. Refer to CISS for more information.
* It checks the readiness of the HBA.
* Called By : cpqary3_init_ctlr_resource()
* Parameters : per-controller(), physical address()
* Calls : cpqary3_check_ctlr_init
* Return Values: SUCCESS / FAILURE
* [Shall return failure if the initialization of the
* controller to the Simple Transport Method fails]
*/
{
volatile CfgTable_t *ctp;
volatile CfgTrans_Perf_t *perf_cfg;
/* SG */
uint32_t max_sg_cnt = 0;
uint32_t optimal_sg = 0;
uint32_t optimal_sg_size = 0;
/* Header + Request + Error */
uint32_t size_of_HRE = 0;
uint32_t size_of_cmdlist = 0;
/* SG */
/* QUEUE CHANGES */
/* QUEUE CHANGES */
if (!cpqary3_check_ctlr_init(cpqary3p))
return (CPQARY3_FAILURE);
/*
* Validate the signature - should be "CISS"
* Use of cntr in the for loop does not suggest a counter - it just
* saves declaration of another variable.
*/
"Signature not stamped");
return (CPQARY3_FAILURE);
}
}
if (CmdsOutMax == 0) {
"Commands set to Zero\n");
"initialization \n");
return (CPQARY3_FAILURE);
}
/* QUEUE CHANGES */
/* LINTED: alignment */
/* LINTED: alignment */
/* PERF */
/*
* Check for support of SIMPLE Transport Method
*/
"NOT YET INITIALIZED");
"try again later \n");
return (CPQARY3_FAILURE);
}
/*
* Configuration Table Initialization
* Set bit 0 of InBound Door Bell Reg to inform the controller
* about the changes related to the Configuration table
*/
/*
* Check whether the controller is ready
*/
cntr = 0;
cntr++;
/*
* Wait for a maximum of 90 seconds. No f/w should take
* more than 90 secs to initialize. If the controller
* is not ready even after 90 secs, it suggests that
* something is wrong
* (wrt the controller, what else) !!!
*/
"Initialization Failed \n");
return (CPQARY3_FAILURE);
}
}
/*
* Check whether controller accepts the requested method of
* transport
*/
"Controller \n");
"try again later\n");
return (CPQARY3_FAILURE);
}
/*
* Check if Controller is ready to accept Commands
*/
CFGTBL_ACC_CMDS)) {
"accept Commands \n");
return (CPQARY3_FAILURE);
}
/*
* Check if the maximum number of oustanding commands for the
* initialized controller is something greater than Zero.
*/
if (CmdsOutMax == 0) {
"Commands set to Zero\n");
"initialization \n");
return (CPQARY3_FAILURE);
}
/*
* Zero the Upper 32 Address in the Controller
*/
/* Set the controller interrupt check routine */
} else {
/* PERF */
/*
* Check for support of PERF Transport Method
*/
& CFGTBL_XPORT_PERFORMANT)) {
"NOT YET INITIALIZED");
"try again later \n");
return (CPQARY3_FAILURE);
}
if (CmdsOutMax == 0)
if (CmdsOutMax == 0) {
"Commands set to Zero\n");
"initialization \n");
return (CPQARY3_FAILURE);
}
/* Initialize the Performant Method Transport Method Table */
if (!cpqary3_phyctgp) {
"CPQary3: Initial mem zalloc failed");
return (CPQARY3_FAILURE);
}
phy_addr = 0;
if (!replyq_start_addr) {
return (CPQARY3_FAILURE);
}
/* LINTED: alignment */
/*
* For non-proton FW controllers, max_blk_fetch_count is not
* implemented in the firmware
*/
/*
* When blk fetch count is 0, FW auto fetches 564 bytes
* corresponding to an optimal S/G of 31
*/
if (max_blk_fetch_cnt == 0) {
BlockFetchCnt[0] = 35;
} else {
/*
* With MAX_PERF_SG_CNT set to 64, block fetch count
* is got by:(sizeof (CommandList_t) + 15)/16
*/
if (max_blk_fetch_cnt > 68)
BlockFetchCnt[0] = 68;
else
}
BlockFetchCnt[0]);
/*
* Check whether the controller is ready
*/
cntr = 0;
cntr++;
/*
* Wait for a maximum of 90 seconds. No f/w should take
* more than 90 secs to initialize. If the controller
* is not ready even after 90 secs, it suggests that
* something is wrong
* (wrt the controller, what else) !!!
*/
"Initialization Failed \n");
return (CPQARY3_FAILURE);
}
}
/*
* Check whether controller accepts the requested method of
* transport
*/
"Controller");
"try again later\n");
return (CPQARY3_FAILURE);
}
/*
* Check if Controller is ready to accept Commands
*/
CFGTBL_ACC_CMDS)) {
"accept Commands");
return (CPQARY3_FAILURE);
}
/*
* Check if the maximum number of oustanding commands for the
* initialized controller is something greater than Zero.
*/
if (CmdsOutMax == 0)
if (CmdsOutMax == 0) {
"Commands set to Zero");
"initialization");
return (CPQARY3_FAILURE);
}
/* SG */
/* 32 byte aligned - size_of_cmdlist */
(sizeof (SGDescriptor_t) * CISS_MAXSGENTRIES);
if ((max_blk_fetch_cnt == 0) || (max_sg_cnt == 0) ||
} else {
/*
* Get the optimal_sg - no of the SG's that will fit
* into the max_blk_fetch_cnt
*/
if (optimal_sg_size < sizeof (SGDescriptor_t)) {
} else {
optimal_sg_size / sizeof (SGDescriptor_t);
}
}
/* SG */
/*
* Zero the Upper 32 Address in the Controller
*/
/* Set the controller interrupt check routine */
} else {
}
}
}
return (CPQARY3_SUCCESS);
}
/*
* Function : cpqary3_check_ctlr_init
* Description : This routine checks to see if the HBA is initialized.
* Called By : cpqary3_init_ctlr()
* Parameters : per-controller
* Calls : None
* Return Values: SUCCESS / FAILURE
*/
{
uint16_t i;
/*
* Set up the mapping for a Register at offset 0xB0 from I2O Bar
* The value 0xB0 taken from the CONFIGM utility.
* It should read 0xffff0000 if the controller is initialized.
* if not yet initialized, read it every second for 300 secs.
* If not set even after 300 secs, return FAILURE.
* If set, free the mapping and continue
*/
if (retvalue != DDI_SUCCESS) {
if (DDI_REGS_ACC_CONFLICT == retvalue)
"CPQary3 : HBA Init Register Mapping Conflict");
"CPQary3 : HBA Init Regsiter Mapping Failed");
return (CPQARY3_FAILURE);
}
for (i = 0; i < 300; i++) { /* loop for 300 seconds */
break;
} else {
}
}
if (i >= 300) { /* HBA not initialized even after 300 seconds !!! */
"function properly. Please replace the hardware or check "
return (CPQARY3_FAILURE);
}
return (CPQARY3_SUCCESS);
}