/*------------------------------------------------------------------------------ * S T R U C T S / T Y P E D E F S
*----------------------------------------------------------------------------*/ /* SCSI inquiry data */ struct inquiry_data {
u8 inqd_pdt; /* Peripheral qualifier | Peripheral Device Type */
u8 inqd_dtq; /* RMB | Device Type Qualifier */
u8 inqd_ver; /* ISO version | ECMA version | ANSI-approved version */
u8 inqd_rdf; /* AENC | TrmIOP | Response data format */
u8 inqd_len; /* Additional length (n-4) */
u8 inqd_pad1[2];/* Reserved - must be zero */
u8 inqd_pad2; /* RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */
u8 inqd_vid[8]; /* Vendor ID */
u8 inqd_pid[16];/* Product ID */
u8 inqd_prl[4]; /* Product Revision Level */
};
struct tvpd_id_descriptor_type_2 {
u8 codeset:4; /* VPD_CODE_SET */
u8 reserved:4;
u8 identifiertype:4; /* VPD_IDENTIFIER_TYPE */
u8 reserved2:4;
u8 reserved3;
u8 identifierlength; struct teu64id {
u32 Serial; /* The serial number supposed to be 40 bits,
* bit we only support 32, so make the last byte zero. */
u8 reserved;
u8 venid[3];
} eu64id;
/* * Non dasd selection is handled entirely in aachba now
*/
staticint nondasd = -1; staticint aac_cache = 2; /* WCE=0 to avoid performance problems */ staticint dacmode = -1; int aac_msi; int aac_commit = -1; int startup_timeout = 180; int aif_timeout = 120; int aac_sync_mode; /* Only Sync. transfer - disabled */ staticint aac_convert_sgl = 1; /* convert non-conformable s/g list - enabled */
module_param(aac_sync_mode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(aac_sync_mode, "Force sync. transfer mode" " 0=off, 1=on");
module_param(aac_convert_sgl, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(aac_convert_sgl, "Convert non-conformable s/g list" " 0=off, 1=on");
module_param(nondasd, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices." " 0=off, 1=on");
module_param_named(cache, aac_cache, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(cache, "Disable Queue Flush commands:\n" "\tbit 0 - Disable FUA in WRITE SCSI commands\n" "\tbit 1 - Disable SYNCHRONIZE_CACHE SCSI command\n" "\tbit 2 - Disable only if Battery is protecting Cache");
module_param(dacmode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC." " 0=off, 1=on");
module_param_named(commit, aac_commit, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the" " adapter for foreign arrays.\n" "This is typically needed in systems that do not have a BIOS." " 0=off, 1=on");
module_param_named(msi, aac_msi, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(msi, "IRQ handling." " 0=PIC(default), 1=MSI, 2=MSI-X)");
module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for" " adapter to have its kernel up and\n" "running. This is typically adjusted for large systems that do not" " have a BIOS.");
module_param(aif_timeout, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(aif_timeout, "The duration of time in seconds to wait for" " applications to pick up AIFs before\n" "deregistering them. This is typically adjusted for heavily burdened" " systems.");
int aac_fib_dump;
module_param(aac_fib_dump, int, 0644);
MODULE_PARM_DESC(aac_fib_dump, "Dump controller fibs prior to IOP_RESET 0=off, 1=on");
int numacb = -1;
module_param(numacb, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control" " blocks (FIB) allocated. Valid values are 512 and down. Default is" " to use suggestion from Firmware.");
staticint acbsize = -1;
module_param(acbsize, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB)" " size. Valid values are 512, 2048, 4096 and 8192. Default is to use" " suggestion from Firmware.");
int update_interval = 30 * 60;
module_param(update_interval, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(update_interval, "Interval in seconds between time sync" " updates issued to adapter.");
int check_interval = 60;
module_param(check_interval, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health" " checks.");
int aac_check_reset = 1;
module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the" " adapter. a value of -1 forces the reset to adapters programmed to" " ignore it.");
int expose_physicals = -1;
module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays." " -1=protect 0=off, 1=on");
int aac_reset_devices;
module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization.");
staticint aac_wwn = 1;
module_param_named(wwn, aac_wwn, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(wwn, "Select a WWN type for the arrays:\n" "\t0 - Disable\n" "\t1 - Array Meta Data Signature (default)\n" "\t2 - Adapter Serial Number");
/** * 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)
{ int status = 0; struct fib * fibptr;
if (!(fibptr = aac_fib_alloc(dev))) return -ENOMEM;
status = aac_fib_send(ContainerCommand,
fibptr, sizeof (struct aac_commit_config),
FsaNormal,
1, 1,
NULL, NULL); /* Do not set XferState to zero unless
* receives a response from F/W */ if (status >= 0)
aac_fib_complete(fibptr);
} elseif (aac_commit == 0) {
printk(KERN_WARNING "aac_get_config_status: Foreign device configurations are being ignored\n");
}
} /* FIB should be freed only after getting the response from the F/W */ if (status != -ERESTARTSYS)
aac_fib_free(fibptr); return status;
}
/** * 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)
{ struct fsa_dev_info *fsa_dev_ptr;
u32 index; int status = 0; struct fib * fibptr; struct aac_get_container_count *dinfo; struct aac_get_container_count_resp *dresp; int maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
if (!(fibptr = aac_fib_alloc(dev))) return -ENOMEM;
status = aac_fib_send(ContainerCommand,
fibptr, sizeof (struct aac_get_container_count),
FsaNormal,
1, 1,
NULL, NULL); if (status >= 0) {
dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);
maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); if (fibptr->dev->supplement_adapter_info.supported_options2 &
AAC_OPTION_SUPPORTED_240_VOLUMES) {
maximum_num_containers =
le32_to_cpu(dresp->MaxSimpleVolumes);
}
aac_fib_complete(fibptr);
} /* FIB should be freed only after getting the response from the F/W */ if (status != -ERESTARTSYS)
aac_fib_free(fibptr);
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
maximum_num_containers = MAXIMUM_NUM_CONTAINERS; if (dev->fsa_dev == NULL ||
dev->maximum_num_containers != maximum_num_containers) {
staticvoid aac_scsi_done(struct scsi_cmnd *scmd)
{ if (scmd->device->request_queue) { /* SCSI command has been submitted by the SCSI mid-layer. */
scsi_done(scmd);
} else { /* SCSI command has been submitted by aac_probe_container(). */
aac_probe_container_scsi_done(scmd);
}
}
status = aac_fib_send(ContainerCommand,
fibptr, sizeof(struct aac_query_mount),
FsaNormal,
0, 1,
_aac_probe_container2,
(void *) scsicmd); /* * Check that the command queued to the controller
*/ if (status < 0 && status != -EINPROGRESS) { /* Inherit results from VM_NameServe, if any */
dresp->status = cpu_to_le32(ST_OK);
_aac_probe_container2(context, fibptr);
}
}
staticint _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
{ struct aac_cmd_priv *cmd_priv = aac_priv(scsicmd); struct fib * fibptr; int status = -ENOMEM;
if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) { struct aac_query_mount *dinfo;
status = aac_fib_send(ContainerCommand,
fibptr, sizeof(struct aac_query_mount),
FsaNormal,
0, 1,
_aac_probe_container1,
(void *) scsicmd); /* * Check that the command queued to the controller
*/ if (status == -EINPROGRESS) return 0;
/** * 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.
*/ staticint aac_probe_container_callback1(struct scsi_cmnd * scsicmd)
{
scsicmd->device = NULL; return 0;
}
if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0) while (scsicmd->device == scsidev)
schedule();
kfree(scsidev);
cmd_priv = aac_priv(scsicmd);
status = cmd_priv->status;
kfree(scsicmd); return status;
}
/* Local Structure to set SCSI inquiry data strings */ struct scsi_inq { char vid[8]; /* Vendor ID */ char pid[16]; /* Product ID */ char prl[4]; /* Product Revision Level */
};
/** * inqstrcpy - string merge * @a: string to copy from * @b: string to copy to * * Copy a String from one location to another * without copying \0
*/
/* 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.
*/
inqstrcpy (mp->vname, str->vid); /* last six chars reserved for vol type */
inqstrcpy (mp->model, str->pid);
}
if (tindex < ARRAY_SIZE(container_types)){ char *findit = str->pid;
for ( ; *findit != ' '; findit++); /* walk till we find a space */ /* RAID is superfluous in the context of a RAID device */ if (memcmp(findit-4, "RAID", 4) == 0)
*(findit -= 4) = ' '; if (((findit - str->pid) + strlen(container_types[tindex]))
< (sizeof(str->pid) + sizeof(str->prl)))
inqstrcpy (container_types[tindex], findit + 1);
}
inqstrcpy ("V1.0", str->prl);
}
scsicmd = (struct scsi_cmnd *) context; if (!aac_valid_context(scsicmd, fibptr)) return;
get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); /* Failure is irrelevant, using default value instead */ if (le32_to_cpu(get_serial_reply->status) == CT_OK) { /*Check to see if it's for VPD 0x83 or 0x80 */ if (scsicmd->cmnd[2] == 0x83) { /* vpd page 0x83 - Device Identification Page */ struct aac_dev *dev; int i; struct tvpd_page83 vpdpage83data;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
/* 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>
*/
aac_fib_init(fib);
writecmd = (struct aac_write *) fib_data(fib);
writecmd->command = cpu_to_le32(VM_CtBlockWrite);
writecmd->cid = cpu_to_le32(scmd_id(cmd));
writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
writecmd->count = cpu_to_le32(count *
dev->fsa_dev[scmd_id(cmd)].block_size);
writecmd->sg.count = cpu_to_le32(1); /* ->stable is not used - it did mean which type of write */
ret = aac_build_sg(cmd, &writecmd->sg); if (ret < 0) return ret;
fibsize = sizeof(struct aac_write) +
(le32_to_cpu(writecmd->sg.count) * sizeof (struct sgentry));
BUG_ON (fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr))); /* * Now send the Fib to the adapter
*/ return aac_fib_send(ContainerCommand,
fib,
fibsize,
FsaNormal,
0, 1,
(fib_callback) io_callback,
(void *) cmd);
}
aac_fib_init(fib); switch(cmd->sc_data_direction){ case DMA_TO_DEVICE:
flag = SRB_DataOut; break; case DMA_BIDIRECTIONAL:
flag = SRB_DataIn | SRB_DataOut; break; case DMA_FROM_DEVICE:
flag = SRB_DataIn; break; case DMA_NONE: default: /* shuts up some versions of gcc */
flag = SRB_NoDataXfer; break;
}
dev = (struct aac_dev *)cmd->device->host->hostdata;
hbacmd = (struct aac_hba_cmd_req *)fib->hw_fib_va;
memset(hbacmd, 0, 96); /* sizeof(*hbacmd) is not necessary */ /* iu_type is a parameter of aac_hba_send */ switch (cmd->sc_data_direction) { case DMA_TO_DEVICE:
hbacmd->byte1 = 2; break; case DMA_FROM_DEVICE: case DMA_BIDIRECTIONAL:
hbacmd->byte1 = 1; break; case DMA_NONE: default: break;
}
hbacmd->lun[1] = cpu_to_le32(cmd->device->lun);
bus = aac_logical_to_phys(scmd_channel(cmd));
target = scmd_id(cmd);
hbacmd->it_nexus = dev->hba_map[bus][target].rmw_nexus;
/* we fill in reply_qid later in aac_src_deliver_message */ /* we fill in iu_type, request_id later in aac_hba_send */ /* we fill in emb_data_desc_count later in aac_build_sghba */
/** * 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.
*/ staticint aac_get_safw_ciss_luns(struct aac_dev *dev)
{ int rcode = -ENOMEM; int datasize; struct aac_srb *srbcmd; struct aac_srb_unit srbu; struct aac_ciss_phys_luns_resp *phys_luns;
/** * 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
*/ staticvoid aac_set_safw_attr_all_targets(struct aac_dev *dev)
{ /* ok and extended reporting */
u32 lun_count, nexus;
u32 i, bus, target;
u8 expose_flag, attribs;
if (!(fibptr = aac_fib_alloc(dev))) return -ENOMEM;
aac_fib_init(fibptr);
info = (struct aac_adapter_info *) fib_data(fibptr);
memset(info,0,sizeof(*info));
rcode = aac_fib_send(RequestAdapterInfo,
fibptr, sizeof(*info),
FsaNormal,
-1, 1, /* First `interrupt' command uses special wait */
NULL,
NULL);
if (rcode < 0) { /* FIB should be freed only after
* getting the response from the F/W */ if (rcode != -ERESTARTSYS) {
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
} return rcode;
}
memcpy(&dev->adapter_info, info, sizeof(*info));
/* * If the firmware supports ROMB RAID/SCSI mode and we are currently * in RAID/SCSI mode, set the flag. For now if in this mode we will * force nondasd support on. If we decide to allow the non-dasd flag * additional changes changes will have to be made to support * RAID/SCSI. the function aac_scsi_cmd in this module will have to be * changed to support the new dev->raid_scsi_mode flag instead of * leaching off of the dev->nondasd_support flag. Also in linit.c the * function aac_detect will have to be modified where it sets up the * max number of channels based on the aac->nondasd_support flag only.
*/ if ((dev->adapter_info.options & AAC_OPT_SCSI_MANAGED) &&
(dev->adapter_info.options & AAC_OPT_RAID_SCSI_MODE)) {
dev->nondasd_support = 1;
dev->raid_scsi_mode = 1;
} if (dev->raid_scsi_mode != 0)
printk(KERN_INFO "%s%d: ROMB RAID/SCSI mode enabled\n",
dev->name, dev->id);
if (nondasd != -1)
dev->nondasd_support = (nondasd!=0); if (dev->nondasd_support && !dev->in_reset)
printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id);
if (dma_get_required_mask(&dev->pdev->dev) > DMA_BIT_MASK(32))
dev->needs_dac = 1;
dev->dac_support = 0; if ((sizeof(dma_addr_t) > 4) && dev->needs_dac &&
(dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)) { if (!dev->in_reset)
printk(KERN_INFO "%s%d: 64bit support enabled.\n",
dev->name, dev->id);
dev->dac_support = 1;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.