static DEFINE_MUTEX(megadev_mutex); staticunsignedint max_cmd_per_lun = DEF_CMD_PER_LUN;
module_param(max_cmd_per_lun, uint, 0);
MODULE_PARM_DESC(max_cmd_per_lun, "Maximum number of commands which can be issued to a single LUN (default=DEF_CMD_PER_LUN=63)");
staticunsignedshortint max_sectors_per_io = MAX_SECTORS_PER_IO;
module_param(max_sectors_per_io, ushort, 0);
MODULE_PARM_DESC(max_sectors_per_io, "Maximum number of sectors per I/O request (default=MAX_SECTORS_PER_IO=128)");
staticunsignedshortint max_mbox_busy_wait = MBOX_BUSY_WAIT;
module_param(max_mbox_busy_wait, ushort, 0);
MODULE_PARM_DESC(max_mbox_busy_wait, "Maximum wait for mailbox in microseconds if busy (default=MBOX_BUSY_WAIT=10)");
/* * The File Operations structure for the serial/ioctl interface of the driver
*/ staticconststruct file_operations megadev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = megadev_unlocked_ioctl,
.open = megadev_open,
.llseek = noop_llseek,
};
/* * Array to structures for storing the information about the controllers. This * information is sent to the user level applications, when they do an ioctl * for this information.
*/ staticstruct mcontroller mcontroller[MAX_CONTROLLERS];
/* The current driver version */ static u32 driver_ver = 0x02000000;
/* major number used by the device for character interface */ staticint major;
/* * mega_query_adapter() * @adapter - pointer to our soft state * * Issue the adapter inquiry commands to the controller and find out * information and parameter about the devices attached
*/ staticint
mega_query_adapter(adapter_t *adapter)
{
dma_addr_t prod_info_dma_handle;
mega_inquiry3 *inquiry3; struct mbox_out mbox;
u8 *raw_mbox = (u8 *)&mbox; int retval;
/* * Try to issue Inquiry3 command * if not succeeded, then issue MEGA_MBOXCMD_ADAPTERINQ command and * update enquiry3 structure
*/
mbox.xferaddr = (u32)adapter->buf_dma_handle;
inquiry3 = (mega_inquiry3 *)adapter->mega_buffer;
raw_mbox[0] = FC_NEW_CONFIG; /* i.e. mbox->cmd=0xA1 */
raw_mbox[2] = NC_SUBOP_ENQUIRY3; /* i.e. 0x0F */
raw_mbox[3] = ENQ3_GET_SOLICITED_FULL; /* i.e. 0x02 */
/* Issue a blocking command to the card */ if (issue_scb_block(adapter, raw_mbox)) { /* the adapter does not support 40ld */
/* * get product_info, which is static information and will be * unchanged
*/
prod_info_dma_handle = dma_map_single(&adapter->dev->dev,
(void *)&adapter->product_info, sizeof(mega_product_info),
DMA_FROM_DEVICE);
mbox.xferaddr = prod_info_dma_handle;
raw_mbox[0] = FC_NEW_CONFIG; /* i.e. mbox->cmd=0xA1 */
raw_mbox[2] = NC_SUBOP_PRODUCT_INFO; /* i.e. 0x0E */
if ((retval = issue_scb_block(adapter, raw_mbox)))
dev_warn(&adapter->dev->dev, "Product_info cmd failed with error: %d\n",
retval);
/* * Get the maximum number of scatter-gather elements supported by this * firmware
*/
mega_get_max_sgl(adapter);
adapter->host->sg_tablesize = adapter->sglen;
/* use HP firmware and bios version encoding Note: fw_version[0|1] and bios_version[0|1] were originally shifted right 8 bits making them zero. This 0 value was hardcoded to fix
sparse warnings. */ if (adapter->product_info.subsysvid == PCI_VENDOR_ID_HP) {
snprintf(adapter->fw_version, sizeof(adapter->fw_version), "%c%d%d.%d%d",
adapter->product_info.fw_version[2],
0,
adapter->product_info.fw_version[1] & 0x0f,
0,
adapter->product_info.fw_version[0] & 0x0f);
snprintf(adapter->bios_version, sizeof(adapter->fw_version), "%c%d%d.%d%d",
adapter->product_info.bios_version[2],
0,
adapter->product_info.bios_version[1] & 0x0f,
0,
adapter->product_info.bios_version[0] & 0x0f);
} else {
memcpy(adapter->fw_version,
(char *)adapter->product_info.fw_version, 4);
adapter->fw_version[4] = 0;
/* * Do we support extended (>10 bytes) cdbs
*/
adapter->support_ext_cdb = mega_support_ext_cdb(adapter); if (adapter->support_ext_cdb)
dev_notice(&adapter->dev->dev, "supports extended CDBs\n");
return 0;
}
/** * mega_runpendq() * @adapter: pointer to our soft state * * Runs through the list of pending requests.
*/ staticinlinevoid
mega_runpendq(adapter_t *adapter)
{ if(!list_empty(&adapter->pending_list))
__mega_runpendq(adapter);
}
/* * megaraid_queue() * @scmd - Issue this scsi command * @done - the callback hook into the scsi mid-layer * * The command queuing entry point for the mid-layer.
*/ staticint megaraid_queue_lck(struct scsi_cmnd *scmd)
{
adapter_t *adapter;
scb_t *scb; int busy=0; unsignedlong flags;
/* * Allocate and build a SCB request * busy flag will be set if mega_build_cmd() command could not * allocate scb. We will return non-zero status in that case. * NOTE: scb can be null even though certain commands completed * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, we would * return 0 in that case.
*/
/* * Check if the HBA is in quiescent state, e.g., during a * delete logical drive opertion. If it is, don't run * the pending_list.
*/ if (atomic_read(&adapter->quiescent) == 0)
mega_runpendq(adapter);
/** * mega_allocate_scb() * @adapter: pointer to our soft state * @cmd: scsi command from the mid-layer * * Allocate a SCB structure. This is the central structure for controller * commands.
*/ staticinline scb_t *
mega_allocate_scb(adapter_t *adapter, struct scsi_cmnd *cmd)
{ struct list_head *head = &adapter->free_list;
scb_t *scb;
/* Unlink command from Free List */ if( !list_empty(head) ) {
/** * mega_get_ldrv_num() * @adapter: pointer to our soft state * @cmd: scsi mid layer command * @channel: channel on the controller * * Calculate the logical drive number based on the information in scsi command * and the channel number.
*/ staticinlineint
mega_get_ldrv_num(adapter_t *adapter, struct scsi_cmnd *cmd, int channel)
{ int tgt; int ldrv_num;
tgt = cmd->device->id;
if ( tgt > adapter->this_id )
tgt--; /* we do not get inquires for initiator id */
ldrv_num = (channel * 15) + tgt;
/* * If we have a logical drive with boot enabled, project it first
*/ if( adapter->boot_ldrv_enabled ) { if( ldrv_num == 0 ) {
ldrv_num = adapter->boot_ldrv;
} else { if( ldrv_num <= adapter->boot_ldrv ) {
ldrv_num--;
}
}
}
/* * If "delete logical drive" feature is enabled on this controller. * Do only if at least one delete logical drive operation was done. * * Also, after logical drive deletion, instead of logical drive number, * the value returned should be 0x80+logical drive id. * * These is valid only for IO commands.
*/
if (adapter->support_random_del && adapter->read_ldidmap ) switch (cmd->cmnd[0]) { case READ_6: case WRITE_6: case READ_10: case WRITE_10:
ldrv_num += 0x80;
}
return ldrv_num;
}
/** * mega_build_cmd() * @adapter: pointer to our soft state * @cmd: Prepare using this scsi command * @busy: busy flag if no resources * * Prepares a command and scatter gather list for the controller. This routine * also finds out if the commands is intended for a logical drive or a * physical device and prepares the controller command accordingly. * * We also re-order the logical drives and physical devices based on their * boot settings.
*/ static scb_t *
mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy)
{
mega_passthru *pthru;
scb_t *scb;
mbox_t *mbox;
u32 seg; char islogical; int max_ldrv_num; int channel = 0; int target = 0; int ldrv_num = 0; /* logical drive number */
/* * We know what channels our logical drives are on - mega_find_card()
*/
islogical = adapter->logdrv_chan[cmd->device->channel];
/* * The theory: If physical drive is chosen for boot, all the physical * devices are exported before the logical drives, otherwise physical * devices are pushed after logical drives, in which case - Kernel sees * the physical devices on virtual channel which is obviously converted * to actual channel on the HBA.
*/ if( adapter->boot_pdrv_enabled ) { if( islogical ) { /* logical channel */
channel = cmd->device->channel -
adapter->product_info.nchannels;
} else { /* this is physical channel */
channel = cmd->device->channel;
target = cmd->device->id;
/* * boot from a physical disk, that disk needs to be * exposed first IF both the channels are SCSI, then * booting from the second channel is not allowed.
*/ if( target == 0 ) {
target = adapter->boot_pdrv_tgt;
} elseif( target == adapter->boot_pdrv_tgt ) {
target = 0;
}
}
} else { if( islogical ) { /* this is the logical channel */
channel = cmd->device->channel;
} else { /* physical channel */
channel = cmd->device->channel - NVIRT_CHAN;
target = cmd->device->id;
}
}
if(islogical) {
/* have just LUN 0 for each target on virtual channels */ if (cmd->device->lun) {
cmd->result = (DID_BAD_TARGET << 16);
scsi_done(cmd); return NULL;
}
} else { if( cmd->device->lun > 7) { /* * Do not support lun >7 for physically accessed * devices
*/
cmd->result = (DID_BAD_TARGET << 16);
scsi_done(cmd); return NULL;
}
}
/* * * Logical drive commands *
*/ if(islogical) { switch (cmd->cmnd[0]) { case TEST_UNIT_READY: #if MEGA_HAVE_CLUSTERING /* * Do we support clustering and is the support enabled * If no, return success always
*/ if( !adapter->has_cluster ) {
cmd->result = (DID_OK << 16);
scsi_done(cmd); return NULL;
}
/* * A little hack: 2nd bit is zero for all scsi read * commands and is set for all scsi write commands
*/ if( adapter->has_64bit_addr ) {
mbox->m_out.cmd = (*cmd->cmnd & 0x02) ?
MEGA_MBOXCMD_LWRITE64:
MEGA_MBOXCMD_LREAD64 ;
} else {
mbox->m_out.cmd = (*cmd->cmnd & 0x02) ?
MEGA_MBOXCMD_LWRITE:
MEGA_MBOXCMD_LREAD ;
}
#if MEGA_HAVE_STATS /* * Take modulo 0x80, since the logical drive * number increases by 0x80 when a logical * drive was deleted
*/ if (*cmd->cmnd == READ_6) {
adapter->nreads[ldrv_num%0x80]++;
adapter->nreadblocks[ldrv_num%0x80] +=
mbox->m_out.numsectors;
} else {
adapter->nwrites[ldrv_num%0x80]++;
adapter->nwriteblocks[ldrv_num%0x80] +=
mbox->m_out.numsectors;
} #endif
}
/** * mega_prepare_passthru() * @adapter: pointer to our soft state * @scb: our scsi control block * @cmd: scsi command from the mid-layer * @channel: actual channel on the controller * @target: actual id on the controller. * * prepare a command for the scsi physical devices.
*/ static mega_passthru *
mega_prepare_passthru(adapter_t *adapter, scb_t *scb, struct scsi_cmnd *cmd, int channel, int target)
{
mega_passthru *pthru;
/* Not sure about the direction */
scb->dma_direction = DMA_BIDIRECTIONAL;
/* Special Code for Handling READ_CAPA/ INQ using bounce buffers */ switch (cmd->cmnd[0]) { case INQUIRY: case READ_CAPACITY: if(!(adapter->flag & (1L << cmd->device->channel))) {
/** * mega_prepare_extpassthru() * @adapter: pointer to our soft state * @scb: our scsi control block * @cmd: scsi command from the mid-layer * @channel: actual channel on the controller * @target: actual id on the controller. * * prepare a command for the scsi physical devices. This rountine prepares * commands for devices which can take extended CDBs (>10 bytes)
*/ static mega_ext_passthru *
mega_prepare_extpassthru(adapter_t *adapter, scb_t *scb, struct scsi_cmnd *cmd, int channel, int target)
{
mega_ext_passthru *epthru;
/* Issue any pending commands to the card */
list_for_each_safe(pos, next, &adapter->pending_list) {
scb = list_entry(pos, scb_t, list);
if( !(scb->state & SCB_ISSUED) ) {
if( issue_scb(adapter, scb) != 0 ) return;
}
}
return;
}
/** * issue_scb() * @adapter: pointer to our soft state * @scb: scsi control block * * Post a command to the card if the mailbox is available, otherwise return * busy. We also take the scb from the pending list if the mailbox is * available.
*/ staticint
issue_scb(adapter_t *adapter, scb_t *scb)
{ volatile mbox64_t *mbox64 = adapter->mbox64; volatile mbox_t *mbox = adapter->mbox; unsignedint i = 0;
if(unlikely(mbox->m_in.busy)) { do {
udelay(1);
i++;
} while( mbox->m_in.busy && (i < max_mbox_busy_wait) );
if(mbox->m_in.busy) return -1;
}
/* Copy mailbox data into host structure */
memcpy((char *)&mbox->m_out, (char *)scb->raw_mbox, sizeof(struct mbox_out));
mbox->m_out.cmdid = scb->idx; /* Set cmdid */
mbox->m_in.busy = 1; /* Set busy */
/* * Increment the pending queue counter
*/
atomic_inc(&adapter->pend_cmds);
switch (mbox->m_out.cmd) { case MEGA_MBOXCMD_LREAD64: case MEGA_MBOXCMD_LWRITE64: case MEGA_MBOXCMD_PASSTHRU64: case MEGA_MBOXCMD_EXTPTHRU:
mbox64->xfer_segment_lo = mbox->m_out.xferaddr;
mbox64->xfer_segment_hi = 0;
mbox->m_out.xferaddr = 0xFFFFFFFF; break; default:
mbox64->xfer_segment_lo = 0;
mbox64->xfer_segment_hi = 0;
}
/* * post the command
*/
scb->state |= SCB_ISSUED;
/* * Wait until the controller's mailbox is available
*/ staticinlineint
mega_busywait_mbox (adapter_t *adapter)
{ if (adapter->mbox->m_in.busy) return __mega_busywait_mbox(adapter); return 0;
}
/** * issue_scb_block() * @adapter: pointer to our soft state * @raw_mbox: the mailbox * * Issue a scb in synchronous and non-interrupt mode
*/ staticint
issue_scb_block(adapter_t *adapter, u_char *raw_mbox)
{ volatile mbox64_t *mbox64 = adapter->mbox64; volatile mbox_t *mbox = adapter->mbox;
u8 byte;
/* Wait until mailbox is free */ if(mega_busywait_mbox (adapter)) goto bug_blocked_mailbox;
/* Copy mailbox data into host structure */
memcpy((char *) mbox, raw_mbox, sizeof(struct mbox_out));
mbox->m_out.cmdid = 0xFE;
mbox->m_in.busy = 1;
switch (raw_mbox[0]) { case MEGA_MBOXCMD_LREAD64: case MEGA_MBOXCMD_LWRITE64: case MEGA_MBOXCMD_PASSTHRU64: case MEGA_MBOXCMD_EXTPTHRU:
mbox64->xfer_segment_lo = mbox->m_out.xferaddr;
mbox64->xfer_segment_hi = 0;
mbox->m_out.xferaddr = 0xFFFFFFFF; break; default:
mbox64->xfer_segment_lo = 0;
mbox64->xfer_segment_hi = 0;
}
/* Loop through any pending requests */ if(atomic_read(&adapter->quiescent) == 0) {
mega_runpendq(adapter);
}
} while(1);
out_unlock:
spin_unlock_irqrestore(&adapter->lock, flags);
return IRQ_RETVAL(handled);
}
/** * megaraid_isr_memmapped() * @irq: irq * @devp: pointer to our soft state * * Interrupt service routine for memory-mapped controllers. * Find out if our device is interrupting. If yes, acknowledge the interrupt * and service the completed commands.
*/ static irqreturn_t
megaraid_isr_memmapped(int irq, void *devp)
{
adapter_t *adapter = devp; unsignedlong flags;
u8 status;
u32 dword = 0;
u8 nstatus;
u8 completed[MAX_FIRMWARE_STATUS]; int handled = 0;
/* * loop till F/W has more commands for us to complete.
*/
spin_lock_irqsave(&adapter->lock, flags);
do { /* Check if a valid interrupt is pending */
dword = RDOUTDOOR(adapter); if(dword != 0x10001234) { /* * No more pending commands
*/ goto out_unlock;
}
WROUTDOOR(adapter, 0x10001234);
/* Loop through any pending requests */ if(atomic_read(&adapter->quiescent) == 0) {
mega_runpendq(adapter);
}
} while(1);
out_unlock:
spin_unlock_irqrestore(&adapter->lock, flags);
return IRQ_RETVAL(handled);
} /** * mega_cmd_done() * @adapter: pointer to our soft state * @completed: array of ids of completed commands * @nstatus: number of completed commands * @status: status of the last command completed * * Complete the commands and call the scsi mid-layer callback hooks.
*/ staticvoid
mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
{
mega_ext_passthru *epthru = NULL; struct scatterlist *sgl; struct scsi_cmnd *cmd = NULL;
mega_passthru *pthru = NULL;
mbox_t *mbox = NULL;
u8 c;
scb_t *scb; int islogical; int cmdid; int i;
/* * for all the commands completed, call the mid-layer callback routine * and free the scb.
*/ for( i = 0; i < nstatus; i++ ) {
cmdid = completed[i];
/* * Only free SCBs for the commands coming down from the * mid-layer, not for which were issued internally * * For internal command, restore the status returned by the * firmware so that user can interpret it.
*/ if (cmdid == CMDID_INT_CMDS) {
scb = &adapter->int_scb;
cmd = scb->cmd;
islogical = adapter->logdrv_chan[cmd->channel]; /* * Maintain an error counter for the logical drive. * Some application like SNMP agent need such * statistics
*/ if( status && islogical && (cmd->cmnd[0] == READ_6 ||
cmd->cmnd[0] == READ_10 ||
cmd->cmnd[0] == READ_12)) { /* * Logical drive number increases by 0x80 when * a logical drive is deleted
*/
adapter->rd_errors[logdrv%0x80]++;
}
if( status && islogical && (cmd->cmnd[0] == WRITE_6 ||
cmd->cmnd[0] == WRITE_10 ||
cmd->cmnd[0] == WRITE_12)) { /* * Logical drive number increases by 0x80 when * a logical drive is deleted
*/
adapter->wr_errors[logdrv%0x80]++;
}
} #endif
}
/* * Do not return the presence of hard disk on the channel so, * inquiry sent, and returned data==hard disk or removable * hard disk and not logical, request should return failure! - * PJ
*/
islogical = adapter->logdrv_chan[cmd->device->channel]; if( cmd->cmnd[0] == INQUIRY && !islogical ) {
/* Add Scsi_Command to end of completed queue */
list_add_tail(SCSI_LIST(cmd), &adapter->completed_list);
}
}
/* * mega_runpendq() * * Run through the list of completed requests and finish it
*/ staticvoid
mega_rundoneq (adapter_t *adapter)
{ struct megaraid_cmd_priv *cmd_priv;
/* * Free a SCB structure * Note: We assume the scsi commands associated with this scb is not free yet.
*/ staticvoid
mega_free_scb(adapter_t *adapter, scb_t *scb)
{ switch( scb->dma_type ) {
case MEGA_DMA_TYPE_NONE: break;
case MEGA_SGLIST:
scsi_dma_unmap(scb->cmd); break; default: break;
}
/* * Remove from the pending list
*/
list_del_init(&scb->list);
/* Link the scb back into free list */
scb->state = SCB_FREE;
scb->cmd = NULL;
for (counter = 0; counter < 10000; counter++) { if (!mbox->m_in.busy) return 0;
udelay(100);
cond_resched();
} return -1; /* give up after 1 second */
}
/* * Copies data to SGLIST * Note: For 64 bit cards, we need a minimum of one SG element for read/write
*/ staticint
mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len)
{ struct scatterlist *sg; struct scsi_cmnd *cmd; int sgcnt; int idx;
cmd = scb->cmd;
/* * Copy Scatter-Gather list info into controller structure. * * The number of sg elements returned must not exceed our limit
*/
sgcnt = scsi_dma_map(cmd);
/* Reset pointer and length fields */
*buf = scb->sgl_dma_addr;
/* Return count of SG requests */ return sgcnt;
}
/* * mega_8_to_40ld() * * takes all info in AdapterInquiry structure and puts it into ProductInfo and * Enquiry3 structures for later use
*/ staticvoid
mega_8_to_40ld(mraid_inquiry *inquiry, mega_inquiry3 *enquiry3,
mega_product_info *product_info)
{ int i;
/* * Abort a previous SCSI request. Only commands on the pending list can be * aborted. All the commands issued to the F/W must complete.
*/ staticint
megaraid_abort(struct scsi_cmnd *cmd)
{
adapter_t *adapter; int rval;
/* * This is required here to complete any completed requests * to be communicated over to the mid layer.
*/
mega_rundoneq(adapter);
spin_unlock_irq(&adapter->lock);
return rval;
}
/** * megaraid_abort_and_reset() * @adapter: megaraid soft state * @cmd: scsi command to be aborted or reset * @aor: abort or reset flag * * Try to locate the scsi command in the pending queue. If found and is not * issued to the controller, abort/reset it. Otherwise return failure
*/ staticint
megaraid_abort_and_reset(adapter_t *adapter, struct scsi_cmnd *cmd, int aor)
{ struct list_head *pos, *next;
scb_t *scb;
if (!cmd || scb->cmd == cmd) { /* Found command */
scb->state |= aor;
/* * Check if this command has firmware ownership. If * yes, we cannot reset this command. Whenever f/w * completes this command, we will return appropriate * status from ISR.
*/ if( scb->state & SCB_ISSUED ) {
/** * proc_show_stat() * @m: Synthetic file construction data * @v: File iterator * * Display statistical information about the I/O activity.
*/ staticint
proc_show_stat(struct seq_file *m, void *v)
{
adapter_t *adapter = m->private; #if MEGA_HAVE_STATS int i; #endif
seq_puts(m, "Statistical Information for this controller\n");
seq_printf(m, "pend_cmds = %d\n", atomic_read(&adapter->pend_cmds)); #if MEGA_HAVE_STATS for(i = 0; i < adapter->numldrv; i++) {
seq_printf(m, "Logical Drive %d:\n", i);
seq_printf(m, "\tReads Issued = %lu, Writes Issued = %lu\n",
adapter->nreads[i], adapter->nwrites[i]);
seq_printf(m, "\tSectors Read = %lu, Sectors Written = %lu\n",
adapter->nreadblocks[i], adapter->nwriteblocks[i]);
seq_printf(m, "\tRead errors = %lu, Write errors = %lu\n\n",
adapter->rd_errors[i], adapter->wr_errors[i]);
} #else
seq_puts(m, "IO and error counters not compiled in driver.\n"); #endif return 0;
}
/** * proc_show_mbox() * @m: Synthetic file construction data * @v: File iterator * * Display mailbox information for the last command issued. This information * is good for debugging.
*/ staticint
proc_show_mbox(struct seq_file *m, void *v)
{
adapter_t *adapter = m->private; volatile mbox_t *mbox = adapter->mbox;
seq_puts(m, "Contents of Mail Box Structure\n");
seq_printf(m, " Fw Command = 0x%02x\n", mbox->m_out.cmd);
seq_printf(m, " Cmd Sequence = 0x%02x\n", mbox->m_out.cmdid);
seq_printf(m, " No of Sectors= %04d\n", mbox->m_out.numsectors);
seq_printf(m, " LBA = 0x%02x\n", mbox->m_out.lba);
seq_printf(m, " DTA = 0x%08x\n", mbox->m_out.xferaddr);
seq_printf(m, " Logical Drive= 0x%02x\n", mbox->m_out.logdrv);
seq_printf(m, " No of SG Elmt= 0x%02x\n", mbox->m_out.numsgelements);
seq_printf(m, " Busy = %01x\n", mbox->m_in.busy);
seq_printf(m, " Status = 0x%02x\n", mbox->m_in.status); return 0;
}
/** * proc_show_pdrv_ch0() * @m: Synthetic file construction data * @v: File iterator * * Display information about the physical drives on physical channel 0.
*/ staticint
proc_show_pdrv_ch0(struct seq_file *m, void *v)
{ return proc_show_pdrv(m, m->private, 0);
}
/** * proc_show_pdrv_ch1() * @m: Synthetic file construction data * @v: File iterator * * Display information about the physical drives on physical channel 1.
*/ staticint
proc_show_pdrv_ch1(struct seq_file *m, void *v)
{ return proc_show_pdrv(m, m->private, 1);
}
/** * proc_show_pdrv_ch2() * @m: Synthetic file construction data * @v: File iterator * * Display information about the physical drives on physical channel 2.
*/ staticint
proc_show_pdrv_ch2(struct seq_file *m, void *v)
{ return proc_show_pdrv(m, m->private, 2);
}
/** * proc_show_pdrv_ch3() * @m: Synthetic file construction data * @v: File iterator * * Display information about the physical drives on physical channel 3.
*/ staticint
proc_show_pdrv_ch3(struct seq_file *m, void *v)
{ return proc_show_pdrv(m, m->private, 3);
}
/** * proc_show_rdrv() * @m: Synthetic file construction data * @adapter: pointer to our soft state * @start: starting logical drive to display * @end: ending logical drive to display * * We do not print the inquiry information since its already available through * /proc/scsi/scsi interface
*/ staticint
proc_show_rdrv(struct seq_file *m, adapter_t *adapter, int start, int end )
{
dma_addr_t dma_handle;
logdrv_param *lparam;
megacmd_t mc; char *disk_array;
dma_addr_t disk_array_dma_handle;
caddr_t inquiry; struct pci_dev *pdev;
u8 *rdrv_state; int num_ldrv;
u32 array_sz; int i;
/** * proc_show_rdrv_10() * @m: Synthetic file construction data * @v: File iterator * * Display real time information about the logical drives 0 through 9.
*/ staticint
proc_show_rdrv_10(struct seq_file *m, void *v)
{ return proc_show_rdrv(m, m->private, 0, 9);
}
/** * proc_show_rdrv_20() * @m: Synthetic file construction data * @v: File iterator * * Display real time information about the logical drives 0 through 9.
*/ staticint
proc_show_rdrv_20(struct seq_file *m, void *v)
{ return proc_show_rdrv(m, m->private, 10, 19);
}
/** * proc_show_rdrv_30() * @m: Synthetic file construction data * @v: File iterator * * Display real time information about the logical drives 0 through 9.
*/ staticint
proc_show_rdrv_30(struct seq_file *m, void *v)
{ return proc_show_rdrv(m, m->private, 20, 29);
}
/** * proc_show_rdrv_40() * @m: Synthetic file construction data * @v: File iterator * * Display real time information about the logical drives 0 through 9.
*/ staticint
proc_show_rdrv_40(struct seq_file *m, void *v)
{ return proc_show_rdrv(m, m->private, 30, 39);
}
/** * mega_create_proc_entry() * @index: index in soft state array * @parent: parent node for this /proc entry * * Creates /proc entries for our controllers.
*/ staticvoid
mega_create_proc_entry(int index, struct proc_dir_entry *parent)
{
adapter_t *adapter = hba_soft_state[index]; struct proc_dir_entry *dir;
u8 string[16];
sprintf(string, "hba%d", adapter->host->host_no);
dir = proc_mkdir_data(string, 0, parent, adapter); if (!dir) {
dev_warn(&adapter->dev->dev, "proc_mkdir failed\n"); return;
}
/* * megaraid_biosparam() * * Return the disk geometry for a particular disk
*/ staticint
megaraid_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
adapter_t *adapter; int heads; int sectors; int cylinders;
/* Get pointer to host config structure */
adapter = (adapter_t *)sdev->host->hostdata;
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.