cpqary3_util.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.
*/
#include "cpqary3.h"
/*
* Local Functions Definitions
*/
int cpqary3_target_geometry(struct scsi_address *);
/*
* Function : cpqary3_read_conf_file
* Description : This routine reads the driver configuration file.
* Called By : cpqary3_attach()
* Parameters : device-information pointer, per_controller
* Calls : None
* Return Values: None
*/
void
{
char *ptr;
cpqary3p->noe_support = 0;
/*
* Plugin the code necessary to read from driver's conf file.
* As of now, we are not interested in reading the onf file
* for any purpose.
*
* eg. :
*
* retvalue = ddi_getprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
* "cpqary3_online_debug", -1);
*/
/*
* We are calling ddi_prop_lookup_string
* which gets the property value, which is passed at
* the grub menu. If the user wants to use the older
* target mapping algorithm,(prior to 1.80)at the grub menu
* "cpqary3_tgtmap=off" should be entered. if this
* string is entered, then we will set the
* value of the variable legacy_mapping to one, which
* will be used in
* cpqary3_detect_target_geometry()
* and cpqary3_probe4LVs(), to decide on the
* mapping algorithm
*/
}
}
}
cpqary3p->noe_support = 0;
}
}
}
/*
* Function : cpqary3_tick_hdlr
* Description : This routine is called once in 60 seconds to detect any
* command that is pending with the controller and has
* timed out.
* Once invoked, it re-initializes itself such that it is
* invoked after an interval of 60 seconds.
* Called By : kernel
* Parameters : per_controller
* Calls : None
* Return Values: None
*/
void
cpqary3_tick_hdlr(void *arg)
{
volatile CfgTable_t *ctp;
uint32_t i;
/*
* The per-controller shall be passed as argument.
* Read the HeartBeat of the controller.
* if the current heartbeat is the same as the one recorded earlier,
* the f/w has locked up!!!
*/
return;
/* CONTROLLER_LOCKUP */
"Please reboot the system");
}
}
/* CONTROLLER_LOCKUP */
for (i = 0; i < no_cmds; i++) {
if (!pktp)
continue;
continue;
}
/* This should always be the case */
(scsi_pktp);
continue;
}
}
}
}
}
}
/*
* Function : cpqary3_init_ctlr_resource
* Description : This routine initializes the command list, initializes
* the controller, enables the interrupt.
* Called By : cpqary3_attach()
* Parameters : per_controller
* Calls : cpqary3_init_ctlr(), cpqary3_meminit(),
* cpqary3_intr_onoff(),
* Return Values: SUCCESS / FAILURE
* [ Shall return failure if any of the mandatory
* initializations / setup of resources fail ]
*/
{
#ifdef CPQARY3_DEBUG_MEM
int8_t i = 0;
#endif
/*
* Initialize the Controller
* Alocate Memory Pool for driver supported number of Commands
* return if not successful
* Allocate target structure for controller and initialize the same
* Detect all existing targets and allocate target structure for each
* Determine geometry for all existing targets
* Initialize the condition variables
*/
return ((CPQARY3_FAILURE));
return ((CPQARY3_FAILURE));
#ifdef CPQARY3_DEBUG_MEM
/*
* This code is in place to test the memory management of this driver.
* This block of code allocates and de-allocates memory as many number
* of times as given in the for loop.
* After the for loop is executed, it returns a failure, which in turn
* would result in attach being failed.
*/
for (i = 0; i < 15; i++) {
"attempt %d \n", i);
return (CPQARY3_FAILURE);
}
"CPQary3 : INIT successful : attempt %d \n", i);
"CPQary3 : FINI successful : attempt %d \n", i);
}
return (CPQARY3_FAILURE);
#endif
return (CPQARY3_FAILURE);
}
/*
* Initialize all condition variables :
* for the immediate call back
* for the disable noe
* for fulsh cache
* for probe device
*/
return (CPQARY3_SUCCESS);
}
/*
* Function : cpqary3_target_geometry
* Description : This function returns the geometry for the target.
* Called By : cpqary3_getcap()
* Parameters : Target SCSI address
* Calls : None
* Return Values: Device Geometry
*/
int
{
/*
* The target CHS are stored in the per-target structure
* during attach time. Use these values
*/
}
/*
* Function : cpqary3_synccmd_alloc
* Description : This function allocates the DMA buffer for the commands
* Called By : cpqary3_ioctl_send_bmiccmd(),
* cpqary3_ioctl_send_scsicmd()
* cpqary3_send_abortcmd(), cpqary3_flush_cache(),
* cpqary3_probe4LVs(), cpqary3_probe4Tapes(),
* cpqary3_detect_target_geometry()
* Parameters : per_controller, buffer size
* Calls : cpqary3_alloc_phyctgs_mem(), cpqary3_cmdlist_occupy()
* Return Values: memp
*/
{
/* first, allocate any necessary dma buffers */
if (bufsz > 0) {
/* first, allocate the command's dma handle */
"no memory for cmddmah");
return (NULL);
}
/* next, allocate dma handle */
"no memory for dmah");
return (NULL);
}
/* now, allocate dma buffer */
"no memory for dma buf");
return (NULL);
}
/* attach dma buffer to command dma handle */
}
/* next, allocate a command packet */
}
"cannot get free command");
return (NULL);
}
memp->cmdpvt_flag = 0;
/* attach dma resources to command */
/* done */
return (memp);
}
/*
* Function : cpqary3_synccmd_cleanup
* Description : This routine cleans up the command
* Called By : cpqary3_process_pkt(), cpqary3_synccmd_free()
* Parameters : per_command_memory
* Calls : cpqary3_free_phyctgs_mem(), cpqary3_cmdlist_release()
* Return Values: none
*/
void
{
/*
* ordinary users should not call this routine
* (use cpqary3_synccmd_free() instead). this is
* for use ONLY by cpqary3_synccmd_free() and
* cpqary3_process_pkt().
*/
/* free dma resources */
}
/* release command */
memp->cmdpvt_flag = 0;
}
/*
* Function : cpqary3_synccmd_free
* Description : This routine frees the command and the
* associated resources.
* Called By : cpqary3_ioctl_send_bmiccmd(),
* cpqary3_ioctl_send_scsicmd()
* cpqary3_send_abortcmd(), cpqary3_flush_cache(),
* cpqary3_probe4LVs(), cpqary3_probe4Tapes(),
* cpqary3_detect_target_geometry()
* Parameters : per_controller, per_command_memory
* Calls : cpqary3_synccmd_cleanup()
* Return Values: NONE
*/
void
{
/*
* so, the user is done with this command packet.
* we have three possible scenarios here:
*
* 1) the command was never submitted to the controller
*
* or
*
* 2) the command has completed at the controller and has
* been fully processed by the interrupt processing
* mechanism and is no longer on the submitted or
* retrieve queues.
*
* or
*
* 3) the command is not yet complete at the controller,
* yet.
*
* For cases (1) and (2), we can go ahead and free the
* command and the associated resources. For case (3), we
* must mark the command as no longer needed, and let
* cpqary3_process_pkt() clean it up instead.
*/
/*
* command is still pending (case #3 above).
* mark the command as abandoned and let
* cpqary3_process_pkt() clean it up.
*/
return;
}
memp->cmdpvt_flag = 0;
/*
* command was either never submitted or has completed
* (cases #1 and #2 above). so, clean it up.
*/
/* done */
return;
} /* cpqary3_synccmd_free() */
/*
* Function : cpqary3_synccmd_send
* Description : This routine sends the command to the controller
* Called By : cpqary3_ioctl_send_bmiccmd(),
* cpqary3_ioctl_send_scsicmd()
* cpqary3_send_abortcmd(), cpqary3_flush_cache(),
* cpqary3_probe4LVs(), cpqary3_probe4Tapes(),
* cpqary3_detect_target_geometry()
* Parameters : per_controller, per_command_memory, timeout value,
* flag(wait for reply)
* Calls : cpqary3_submit(), cpqary3_add2submitted_cmdq()
* Return Values: SUCCESS / FAILURE
*/
int
{
int waitsig = 0;
int rc = 0;
kcondvar_t *cv = 0;
/* compute absolute timeout, if necessary */
if (timeoutms > 0)
/* heed signals during wait? */
waitsig = 1;
/* acquire the sw mutex for our wait */
/* submit command to controller */
rc = -1;
return (rc);
}
/* wait for command completion, timeout, or signal */
/* wait with the request behavior */
if (absto) {
if (waitsig) {
} else {
}
if (crc > 0)
rc = 0;
else
rc = (-1);
} else {
if (waitsig) {
if (rc > 0)
rc = 0;
else
rc = (-1);
} else {
rc = 0;
}
}
/*
* if our wait was interrupted (timeout),
* then break here
*/
if (rc) {
break;
}
}
/* our wait is done, so release the sw mutex */
/* return the results */
return (rc);
}
/*
* Function : cpqary3_detect_target_geometry
* Description : This function determines the geometry for all
* the existing targets for the controller.
* Called By : cpqary3_tgt_init()
* Parameters : per controller
* Calls : cpqary3_synccmd_alloc(), cpqary3_synccmd_send()
* cpqary3_synccmd_free()
* Return Values: SUCCESS / FAILURE
* [ Shall return failure only if Memory constraints exist
* or controller does not respond ]
*/
{
int i;
/*
* Occupy a Command List
* Allocate Memory for return data
* If error, RETURN 0.
* get the Request Block from the CommandList
* Fill in the Request Packet with the corresponding values
* Submit the Command and Poll for its completion
* If success, continue else RETURN 0
*/
/* Sync Changes */
if (cpqary3_cmdpvtp == NULL)
return (CPQARY3_FAILURE);
/* Sync Changes */
/* Update Cmd Header */
/* Cmd Reques */
/*
* For all the Targets that exist, issue an IDENTIFY LOGICAL DRIVE.
* That returns values which includes the dsired Geometry also.
* Update the Geometry in the per-target structure.
* NOTE : When the loop is executed for i=controller's SCSI ID, just
* increament by one so that we are talking to the next logical
* drive in our per-target structure.
*/
/*
* Depending upon the value of the variable legacy_mapping
* set in cpqary3_attach(),
* the target mapping algorithm to be used by the driver is decided.
*/
for (i = 0; i < loop_cnt; i++) {
if (i == CTLR_SCSI_ID) /* Go to Next logical target */
i++;
/* Always zero */
/*
* Logical volume Id numbering scheme is as follows
* 0x00000, 0x00001, ... - for Direct Attached
* 0x10000, 0x10001, ... - If 1st Port of HBA is
* connected to MSA20 / MSA500
* 0x20000, 0x20001, ... - If 2nd Port of HBA is
* connected to MSA20 / MSA500
*/
/*
* Submit the command
* Poll for its completion
* If polling is not successful, something is wrong
* with the controler
* Return FAILURE (No point in continuing if h/w is
* faulty !!!)
*/
/* PERF */
/* PERF */
/* Sync Changes */
CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
/* Timed out */
return (CPQARY3_FAILURE);
}
if ((cpqary3_cmdpvtp->
return (CPQARY3_FAILURE);
}
/* Sync Changes */
int, i, IdLogDrive *, idlogdrive);
}
} else {
/*
* Fix for QXCR1000446657: Logical drives are re numbered
* after deleting a Logical drive.
* introduced, new variable ld_count, which gets
* incremented when the Target ID is found.
* And for i=controller's SCSI ID and LDs with holes are found,
* we continue talking to
* the next logical drive in the per-target structure
*/
if (i == CTLR_SCSI_ID ||
/* Go to the Next logical target */
continue;
/* Always zero */
/*
* Logical volume Id numbering scheme is as follows
* 0x00000, 0x00001, ... - for Direct Attached
* 0x10000, 0x10001, ... - If 1st Port of HBA is
* connected to MSA20 / MSA500
* 0x20000, 0x20001, ... - If 2nd Port of HBA is
* connected to MSA20 / MSA500
*/
/* PERF */
/* PERF */
/*
* Submit the command
* Poll for its completion
* If polling is not successful, something is wrong
* with the controler
* Return FAILURE (No point in continuing if h/w is
* faulty !!!)
*/
/* Sync Changes */
CPQARY3_SYNCCMD_SEND_WAITSIG) != 0) {
/* Timed out */
return (CPQARY3_FAILURE);
}
if ((cpqary3_cmdpvtp->
return (CPQARY3_FAILURE);
}
/* Sync Changes */
int, i, IdLogDrive *, idlogdrive);
ld_count++;
}
}
/* Sync Changes */
/* Sync Changes */
return (CPQARY3_SUCCESS);
}