linux/drivers/scsi/aacraid/aachba.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *	Adaptec AAC series RAID controller driver
 *	(c) Copyright 2001 Red Hat Inc.
 *
 * based on the old aacraid driver that is..
 * Adaptec aacraid device driver for Linux.
 *
 * Copyright (c) 2000-2010 Adaptec, Inc.
 *               2010-2015 PMC-Sierra, Inc. ([email protected])
 *		 2016-2017 Microsemi Corp. ([email protected])
 *
 * Module Name:
 *  aachba.c
 *
 * Abstract: Contains Interfaces to manage IOs.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/blkdev.h>
#include <linux/uaccess.h>
#include <linux/module.h>

#include <linux/unaligned.h>

#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>

#include "aacraid.h"

/* values for inqd_pdt: Peripheral device type in plain English */
#define INQD_PDT_DA
#define INQD_PDT_PROC
#define INQD_PDT_CHNGR
#define INQD_PDT_COMM
#define INQD_PDT_NOLUN2
#define INQD_PDT_NOLUN

#define INQD_PDT_DMASK
#define INQD_PDT_QMASK

/*
 *	Sense codes
 */

#define SENCODE_NO_SENSE
#define SENCODE_END_OF_DATA
#define SENCODE_BECOMING_READY
#define SENCODE_INIT_CMD_REQUIRED
#define SENCODE_UNRECOVERED_READ_ERROR
#define SENCODE_PARAM_LIST_LENGTH_ERROR
#define SENCODE_INVALID_COMMAND
#define SENCODE_LBA_OUT_OF_RANGE
#define SENCODE_INVALID_CDB_FIELD
#define SENCODE_LUN_NOT_SUPPORTED
#define SENCODE_INVALID_PARAM_FIELD
#define SENCODE_PARAM_NOT_SUPPORTED
#define SENCODE_PARAM_VALUE_INVALID
#define SENCODE_RESET_OCCURRED
#define SENCODE_LUN_NOT_SELF_CONFIGURED_YET
#define SENCODE_INQUIRY_DATA_CHANGED
#define SENCODE_SAVING_PARAMS_NOT_SUPPORTED
#define SENCODE_DIAGNOSTIC_FAILURE
#define SENCODE_INTERNAL_TARGET_FAILURE
#define SENCODE_INVALID_MESSAGE_ERROR
#define SENCODE_LUN_FAILED_SELF_CONFIG
#define SENCODE_OVERLAPPED_COMMAND

/*
 *	Additional sense codes
 */

#define ASENCODE_NO_SENSE
#define ASENCODE_END_OF_DATA
#define ASENCODE_BECOMING_READY
#define ASENCODE_INIT_CMD_REQUIRED
#define ASENCODE_PARAM_LIST_LENGTH_ERROR
#define ASENCODE_INVALID_COMMAND
#define ASENCODE_LBA_OUT_OF_RANGE
#define ASENCODE_INVALID_CDB_FIELD
#define ASENCODE_LUN_NOT_SUPPORTED
#define ASENCODE_INVALID_PARAM_FIELD
#define ASENCODE_PARAM_NOT_SUPPORTED
#define ASENCODE_PARAM_VALUE_INVALID
#define ASENCODE_RESET_OCCURRED
#define ASENCODE_LUN_NOT_SELF_CONFIGURED_YET
#define ASENCODE_INQUIRY_DATA_CHANGED
#define ASENCODE_SAVING_PARAMS_NOT_SUPPORTED
#define ASENCODE_DIAGNOSTIC_FAILURE
#define ASENCODE_INTERNAL_TARGET_FAILURE
#define ASENCODE_INVALID_MESSAGE_ERROR
#define ASENCODE_LUN_FAILED_SELF_CONFIG
#define ASENCODE_OVERLAPPED_COMMAND

#define BYTE0(x)
#define BYTE1(x)
#define BYTE2(x)
#define BYTE3(x)

/* MODE_SENSE data format */
aac_modep_data;

/* MODE_SENSE_10 data format */
aac_modep10_data;

/*------------------------------------------------------------------------------
 *              S T R U C T S / T Y P E D E F S
 *----------------------------------------------------------------------------*/
/* SCSI inquiry data */
struct inquiry_data {};

/* Added for VPD 0x83 */
struct  tvpd_id_descriptor_type_1 {};

struct tvpd_id_descriptor_type_2 {};

struct tvpd_id_descriptor_type_3 {};

struct tvpd_page83 {};

/*
 *              M O D U L E   G L O B A L S
 */

static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *sgmap);
static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg);
static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg);
static long aac_build_sgraw2(struct scsi_cmnd *scsicmd,
				struct aac_raw_io2 *rio2, int sg_max);
static long aac_build_sghba(struct scsi_cmnd *scsicmd,
				struct aac_hba_cmd_req *hbacmd,
				int sg_max, u64 sg_address);
static int aac_convert_sgraw2(struct aac_raw_io2 *rio2,
				int pages, int nseg, int nseg_new);
static void aac_probe_container_scsi_done(struct scsi_cmnd *scsi_cmnd);
static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
static int aac_send_hba_fib(struct scsi_cmnd *scsicmd);
#ifdef AAC_DETAILED_STATUS_INFO
static char *aac_get_status_string(u32 status);
#endif

/*
 *	Non dasd selection is handled entirely in aachba now
 */

static int nondasd =;
static int aac_cache =;	/* WCE=0 to avoid performance problems */
static int dacmode =;
int aac_msi;
int aac_commit =;
int startup_timeout =;
int aif_timeout =;
int aac_sync_mode;  /* Only Sync. transfer - disabled */
static int aac_convert_sgl =;	/* convert non-conformable s/g list - enabled */

module_param(aac_sync_mode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();
module_param(aac_convert_sgl, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();
module_param(nondasd, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();
module_param_named(cache, aac_cache, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();
module_param(dacmode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();
module_param_named(commit, aac_commit, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();
module_param_named(msi, aac_msi, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();
module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();
module_param(aif_timeout, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

int aac_fib_dump;
module_param(aac_fib_dump, int, 0644);
MODULE_PARM_DESC();

int numacb =;
module_param(numacb, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

static int acbsize =;
module_param(acbsize, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

int update_interval =;
module_param(update_interval, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

int check_interval =;
module_param(check_interval, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

int aac_check_reset =;
module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

int expose_physicals =;
module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

int aac_reset_devices;
module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

static int aac_wwn =;
module_param_named(wwn, aac_wwn, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();


static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
		struct fib *fibptr) {}

/**
 *	aac_get_config_status	-	check the adapter configuration
 *	@dev: aac driver data
 *	@commit_flag: force sending CT_COMMIT_CONFIG
 *
 *	Query config status, and commit the configuration if needed.
 */
int aac_get_config_status(struct aac_dev *dev, int commit_flag)
{}

static void aac_expose_phy_device(struct scsi_cmnd *scsicmd)
{}

/**
 *	aac_get_containers	-	list containers
 *	@dev: aac driver data
 *
 *	Make a list of all containers on this controller
 */
int aac_get_containers(struct aac_dev *dev)
{}

static void aac_scsi_done(struct scsi_cmnd *scmd)
{}

static void get_container_name_callback(void *context, struct fib * fibptr)
{}

/*
 *	aac_get_container_name	-	get container name, none blocking.
 */
static int aac_get_container_name(struct scsi_cmnd * scsicmd)
{}

static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd)
{}

static void _aac_probe_container2(void * context, struct fib * fibptr)
{}

static void _aac_probe_container1(void * context, struct fib * fibptr)
{}

static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
{}

/**
 *	aac_probe_container_callback1	-	query a logical volume
 *	@scsicmd: the scsi command block
 *
 *	Queries the controller about the given volume. The volume information
 *	is updated in the struct fsa_dev_info structure rather than returned.
 */
static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd)
{}

static void aac_probe_container_scsi_done(struct scsi_cmnd *scsi_cmnd)
{}

int aac_probe_container(struct aac_dev *dev, int cid)
{}

/* Local Structure to set SCSI inquiry data strings */
struct scsi_inq {};

/**
 *	inqstrcpy	-	string merge
 *	@a:	string to copy from
 *	@b:	string to copy to
 *
 *	Copy a String from one location to another
 *	without copying \0
 */

static void inqstrcpy(char *a, char *b)
{}

static char *container_types[] =;

char * get_container_type(unsigned tindex)
{}

/* Function: setinqstr
 *
 * Arguments: [1] pointer to void [1] int
 *
 * Purpose: Sets SCSI inquiry data strings for vendor, product
 * and revision level. Allows strings to be set in platform dependent
 * files instead of in OS dependent driver source.
 */

static void setinqstr(struct aac_dev *dev, void *data, int tindex)
{}

static void build_vpd83_type3(struct tvpd_page83 *vpdpage83data,
		struct aac_dev *dev, struct scsi_cmnd *scsicmd)
{}

static void get_container_serial_callback(void *context, struct fib * fibptr)
{}

/*
 *	aac_get_container_serial - get container serial, none blocking.
 */
static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
{}

/* Function: setinqserial
 *
 * Arguments: [1] pointer to void [1] int
 *
 * Purpose: Sets SCSI Unit Serial number.
 *          This is a fake. We should read a proper
 *          serial number from the container. <SuSE>But
 *          without docs it's quite hard to do it :-)
 *          So this will have to do in the meantime.</SuSE>
 */

static int setinqserial(struct aac_dev *dev, void *data, int cid)
{}

static inline void set_sense(struct sense_data *sense_data, u8 sense_key,
	u8 sense_code, u8 a_sense_code, u8 bit_pointer, u16 field_pointer)
{}

static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
{}

static int aac_bounds_64(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
{}

static void io_callback(void *context, struct fib * fibptr);

static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
{}

static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
{}

static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
{}

static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
{}

static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
{}

static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
{}

static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd)
{}

static struct aac_hba_cmd_req *aac_construct_hbacmd(struct fib *fib,
							struct scsi_cmnd *cmd)
{}

static void aac_srb_callback(void *context, struct fib * fibptr);

static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd)
{}

static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd)
{}

static int aac_scsi_32_64(struct fib * fib, struct scsi_cmnd * cmd)
{}

static int aac_adapter_hba(struct fib *fib, struct scsi_cmnd *cmd)
{}

static int aac_send_safw_bmic_cmd(struct aac_dev *dev,
	struct aac_srb_unit *srbu, void *xfer_buf, int xfer_len)
{}

static void aac_set_safw_target_qd(struct aac_dev *dev, int bus, int target)
{}

static int aac_issue_safw_bmic_identify(struct aac_dev *dev,
	struct aac_ciss_identify_pd **identify_resp, u32 bus, u32 target)
{}

static inline void aac_free_safw_ciss_luns(struct aac_dev *dev)
{}

/**
 *	aac_get_safw_ciss_luns() - Process topology change
 *	@dev:		aac_dev structure
 *
 *	Execute a CISS REPORT PHYS LUNS and process the results into
 *	the current hba_map.
 */
static int aac_get_safw_ciss_luns(struct aac_dev *dev)
{}

static inline u32 aac_get_safw_phys_lun_count(struct aac_dev *dev)
{}

static inline u32 aac_get_safw_phys_bus(struct aac_dev *dev, int lun)
{}

static inline u32 aac_get_safw_phys_target(struct aac_dev *dev, int lun)
{}

static inline u32 aac_get_safw_phys_expose_flag(struct aac_dev *dev, int lun)
{}

static inline u32 aac_get_safw_phys_attribs(struct aac_dev *dev, int lun)
{}

static inline u32 aac_get_safw_phys_nexus(struct aac_dev *dev, int lun)
{}

static inline void aac_free_safw_identify_resp(struct aac_dev *dev,
						int bus, int target)
{}

static inline void aac_free_safw_all_identify_resp(struct aac_dev *dev,
	int lun_count)
{}

static int aac_get_safw_attr_all_targets(struct aac_dev *dev)
{}

/**
 *	aac_set_safw_attr_all_targets-	update current hba map with data from FW
 *	@dev:	aac_dev structure
 *
 *	Update our hba map with the information gathered from the FW
 */
static void aac_set_safw_attr_all_targets(struct aac_dev *dev)
{}

static int aac_setup_safw_targets(struct aac_dev *dev)
{}

int aac_setup_safw_adapter(struct aac_dev *dev)
{}

int aac_get_adapter_info(struct aac_dev* dev)
{}


static void io_callback(void *context, struct fib * fibptr)
{}

static int aac_read(struct scsi_cmnd * scsicmd)
{}

static int aac_write(struct scsi_cmnd * scsicmd)
{}

static void synchronize_callback(void *context, struct fib *fibptr)
{}

static int aac_synchronize(struct scsi_cmnd *scsicmd)
{}

static void aac_start_stop_callback(void *context, struct fib *fibptr)
{}

static int aac_start_stop(struct scsi_cmnd *scsicmd)
{}

/**
 *	aac_scsi_cmd()		-	Process SCSI command
 *	@scsicmd:		SCSI command block
 *
 *	Emulate a SCSI command and queue the required request for the
 *	aacraid firmware.
 */

int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
{}

static int query_disk(struct aac_dev *dev, void __user *arg)
{}

static int force_delete_disk(struct aac_dev *dev, void __user *arg)
{}

static int delete_disk(struct aac_dev *dev, void __user *arg)
{}

int aac_dev_ioctl(struct aac_dev *dev, unsigned int cmd, void __user *arg)
{}

/**
 * aac_srb_callback
 * @context: the context set in the fib - here it is scsi cmd
 * @fibptr: pointer to the fib
 *
 * Handles the completion of a scsi command to a non dasd device
 */
static void aac_srb_callback(void *context, struct fib * fibptr)
{}

static void hba_resp_task_complete(struct aac_dev *dev,
					struct scsi_cmnd *scsicmd,
					struct aac_hba_resp *err) {}

static void hba_resp_task_failure(struct aac_dev *dev,
					struct scsi_cmnd *scsicmd,
					struct aac_hba_resp *err)
{}

/**
 * aac_hba_callback
 * @context: the context set in the fib - here it is scsi cmd
 * @fibptr: pointer to the fib
 *
 * Handles the completion of a native HBA scsi command
 */
void aac_hba_callback(void *context, struct fib *fibptr)
{}

/**
 * aac_send_srb_fib
 * @scsicmd: the scsi command block
 *
 * This routine will form a FIB and fill in the aac_srb from the
 * scsicmd passed in.
 */
static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
{}

/**
 * aac_send_hba_fib
 * @scsicmd: the scsi command block
 *
 * This routine will form a FIB and fill in the aac_hba_cmd_req from the
 * scsicmd passed in.
 */
static int aac_send_hba_fib(struct scsi_cmnd *scsicmd)
{}


static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *psg)
{}


static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg)
{}

static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg)
{}

static long aac_build_sgraw2(struct scsi_cmnd *scsicmd,
				struct aac_raw_io2 *rio2, int sg_max)
{}

static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int nseg_new)
{}

static long aac_build_sghba(struct scsi_cmnd *scsicmd,
			struct aac_hba_cmd_req *hbacmd,
			int sg_max,
			u64 sg_address)
{}

#ifdef AAC_DETAILED_STATUS_INFO

struct aac_srb_status_info {
	u32	status;
	char	*str;
};


static struct aac_srb_status_info srb_status_info[] = {
	{ SRB_STATUS_PENDING,		"Pending Status"},
	{ SRB_STATUS_SUCCESS,		"Success"},
	{ SRB_STATUS_ABORTED,		"Aborted Command"},
	{ SRB_STATUS_ABORT_FAILED,	"Abort Failed"},
	{ SRB_STATUS_ERROR,		"Error Event"},
	{ SRB_STATUS_BUSY,		"Device Busy"},
	{ SRB_STATUS_INVALID_REQUEST,	"Invalid Request"},
	{ SRB_STATUS_INVALID_PATH_ID,	"Invalid Path ID"},
	{ SRB_STATUS_NO_DEVICE,		"No Device"},
	{ SRB_STATUS_TIMEOUT,		"Timeout"},
	{ SRB_STATUS_SELECTION_TIMEOUT,	"Selection Timeout"},
	{ SRB_STATUS_COMMAND_TIMEOUT,	"Command Timeout"},
	{ SRB_STATUS_MESSAGE_REJECTED,	"Message Rejected"},
	{ SRB_STATUS_BUS_RESET,		"Bus Reset"},
	{ SRB_STATUS_PARITY_ERROR,	"Parity Error"},
	{ SRB_STATUS_REQUEST_SENSE_FAILED,"Request Sense Failed"},
	{ SRB_STATUS_NO_HBA,		"No HBA"},
	{ SRB_STATUS_DATA_OVERRUN,	"Data Overrun/Data Underrun"},
	{ SRB_STATUS_UNEXPECTED_BUS_FREE,"Unexpected Bus Free"},
	{ SRB_STATUS_PHASE_SEQUENCE_FAILURE,"Phase Error"},
	{ SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"},
	{ SRB_STATUS_REQUEST_FLUSHED,	"Request Flushed"},
	{ SRB_STATUS_DELAYED_RETRY,	"Delayed Retry"},
	{ SRB_STATUS_INVALID_LUN,	"Invalid LUN"},
	{ SRB_STATUS_INVALID_TARGET_ID,	"Invalid TARGET ID"},
	{ SRB_STATUS_BAD_FUNCTION,	"Bad Function"},
	{ SRB_STATUS_ERROR_RECOVERY,	"Error Recovery"},
	{ SRB_STATUS_NOT_STARTED,	"Not Started"},
	{ SRB_STATUS_NOT_IN_USE,	"Not In Use"},
	{ SRB_STATUS_FORCE_ABORT,	"Force Abort"},
	{ SRB_STATUS_DOMAIN_VALIDATION_FAIL,"Domain Validation Failure"},
	{ 0xff,				"Unknown Error"}
};

char *aac_get_status_string(u32 status)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(srb_status_info); i++)
		if (srb_status_info[i].status == status)
			return srb_status_info[i].str;

	return "Bad Status Code";
}

#endif