in megaraid/megaraid_mbox.c [1466:1845]
static DEF_SCSI_QCMD(megaraid_queue_command)
/**
* megaraid_mbox_build_cmd - transform the mid-layer scsi commands
* @adapter : controller's soft state
* @scp : mid-layer scsi command pointer
* @busy : set if request could not be completed because of lack of
* resources
*
* Transform the mid-layer scsi command to megaraid firmware lingua.
* Convert the command issued by mid-layer to format understood by megaraid
* firmware. We also complete certain commands without sending them to firmware.
*/
static scb_t *
megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
{
mraid_device_t *rdev = ADAP2RAIDDEV(adapter);
int channel;
int target;
int islogical;
mbox_ccb_t *ccb;
mraid_passthru_t *pthru;
mbox64_t *mbox64;
mbox_t *mbox;
scb_t *scb;
char skip[] = "skipping";
char scan[] = "scanning";
char *ss;
/*
* Get the appropriate device map for the device this command is
* intended for
*/
MRAID_GET_DEVICE_MAP(adapter, scp, channel, target, islogical);
/*
* Logical drive commands
*/
if (islogical) {
switch (scp->cmnd[0]) {
case TEST_UNIT_READY:
/*
* Do we support clustering and is the support enabled
* If no, return success always
*/
if (!adapter->ha) {
scp->result = (DID_OK << 16);
return NULL;
}
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
*busy = 1;
return NULL;
}
scb->dma_direction = scp->sc_data_direction;
scb->dev_channel = 0xFF;
scb->dev_target = target;
ccb = (mbox_ccb_t *)scb->ccb;
/*
* The command id will be provided by the command
* issuance routine
*/
ccb->raw_mbox[0] = CLUSTER_CMD;
ccb->raw_mbox[2] = RESERVATION_STATUS;
ccb->raw_mbox[3] = target;
return scb;
case MODE_SENSE:
{
struct scatterlist *sgl;
caddr_t vaddr;
sgl = scsi_sglist(scp);
if (sg_page(sgl)) {
vaddr = (caddr_t) sg_virt(&sgl[0]);
memset(vaddr, 0, scp->cmnd[4]);
}
else {
con_log(CL_ANN, (KERN_WARNING
"megaraid mailbox: invalid sg:%d\n",
__LINE__));
}
}
scp->result = (DID_OK << 16);
return NULL;
case INQUIRY:
/*
* Display the channel scan for logical drives
* Do not display scan for a channel if already done.
*/
if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
con_log(CL_ANN, (KERN_INFO
"scsi[%d]: scanning scsi channel %d",
adapter->host->host_no,
SCP2CHANNEL(scp)));
con_log(CL_ANN, (
" [virtual] for logical drives\n"));
rdev->last_disp |= (1L << SCP2CHANNEL(scp));
}
if (scp->cmnd[1] & MEGA_SCSI_INQ_EVPD) {
scsi_build_sense(scp, 0, ILLEGAL_REQUEST,
MEGA_INVALID_FIELD_IN_CDB, 0);
return NULL;
}
fallthrough;
case READ_CAPACITY:
/*
* Do not allow LUN > 0 for logical drives and
* requests for more than 40 logical drives
*/
if (SCP2LUN(scp)) {
scp->result = (DID_BAD_TARGET << 16);
return NULL;
}
if ((target % 0x80) >= MAX_LOGICAL_DRIVES_40LD) {
scp->result = (DID_BAD_TARGET << 16);
return NULL;
}
/* Allocate a SCB and initialize passthru */
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
*busy = 1;
return NULL;
}
ccb = (mbox_ccb_t *)scb->ccb;
scb->dev_channel = 0xFF;
scb->dev_target = target;
pthru = ccb->pthru;
mbox = ccb->mbox;
mbox64 = ccb->mbox64;
pthru->timeout = 0;
pthru->ars = 1;
pthru->reqsenselen = 14;
pthru->islogical = 1;
pthru->logdrv = target;
pthru->cdblen = scp->cmd_len;
memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
mbox->cmd = MBOXCMD_PASSTHRU64;
scb->dma_direction = scp->sc_data_direction;
pthru->dataxferlen = scsi_bufflen(scp);
pthru->dataxferaddr = ccb->sgl_dma_h;
pthru->numsge = megaraid_mbox_mksgl(adapter,
scb);
mbox->xferaddr = 0xFFFFFFFF;
mbox64->xferaddr_lo = (uint32_t )ccb->pthru_dma_h;
mbox64->xferaddr_hi = 0;
return scb;
case READ_6:
case WRITE_6:
case READ_10:
case WRITE_10:
case READ_12:
case WRITE_12:
/*
* Allocate a SCB and initialize mailbox
*/
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
*busy = 1;
return NULL;
}
ccb = (mbox_ccb_t *)scb->ccb;
scb->dev_channel = 0xFF;
scb->dev_target = target;
mbox = ccb->mbox;
mbox64 = ccb->mbox64;
mbox->logdrv = target;
/*
* A little HACK: 2nd bit is zero for all scsi read
* commands and is set for all scsi write commands
*/
mbox->cmd = (scp->cmnd[0] & 0x02) ? MBOXCMD_LWRITE64:
MBOXCMD_LREAD64 ;
/*
* 6-byte READ(0x08) or WRITE(0x0A) cdb
*/
if (scp->cmd_len == 6) {
mbox->numsectors = (uint32_t)scp->cmnd[4];
mbox->lba =
((uint32_t)scp->cmnd[1] << 16) |
((uint32_t)scp->cmnd[2] << 8) |
(uint32_t)scp->cmnd[3];
mbox->lba &= 0x1FFFFF;
}
/*
* 10-byte READ(0x28) or WRITE(0x2A) cdb
*/
else if (scp->cmd_len == 10) {
mbox->numsectors =
(uint32_t)scp->cmnd[8] |
((uint32_t)scp->cmnd[7] << 8);
mbox->lba =
((uint32_t)scp->cmnd[2] << 24) |
((uint32_t)scp->cmnd[3] << 16) |
((uint32_t)scp->cmnd[4] << 8) |
(uint32_t)scp->cmnd[5];
}
/*
* 12-byte READ(0xA8) or WRITE(0xAA) cdb
*/
else if (scp->cmd_len == 12) {
mbox->lba =
((uint32_t)scp->cmnd[2] << 24) |
((uint32_t)scp->cmnd[3] << 16) |
((uint32_t)scp->cmnd[4] << 8) |
(uint32_t)scp->cmnd[5];
mbox->numsectors =
((uint32_t)scp->cmnd[6] << 24) |
((uint32_t)scp->cmnd[7] << 16) |
((uint32_t)scp->cmnd[8] << 8) |
(uint32_t)scp->cmnd[9];
}
else {
con_log(CL_ANN, (KERN_WARNING
"megaraid: unsupported CDB length\n"));
megaraid_dealloc_scb(adapter, scb);
scp->result = (DID_ERROR << 16);
return NULL;
}
scb->dma_direction = scp->sc_data_direction;
// Calculate Scatter-Gather info
mbox64->xferaddr_lo = (uint32_t )ccb->sgl_dma_h;
mbox->numsge = megaraid_mbox_mksgl(adapter,
scb);
mbox->xferaddr = 0xFFFFFFFF;
mbox64->xferaddr_hi = 0;
return scb;
case RESERVE:
case RELEASE:
/*
* Do we support clustering and is the support enabled
*/
if (!adapter->ha) {
scp->result = (DID_BAD_TARGET << 16);
return NULL;
}
/*
* Allocate a SCB and initialize mailbox
*/
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
*busy = 1;
return NULL;
}
ccb = (mbox_ccb_t *)scb->ccb;
scb->dev_channel = 0xFF;
scb->dev_target = target;
ccb->raw_mbox[0] = CLUSTER_CMD;
ccb->raw_mbox[2] = (scp->cmnd[0] == RESERVE) ?
RESERVE_LD : RELEASE_LD;
ccb->raw_mbox[3] = target;
scb->dma_direction = scp->sc_data_direction;
return scb;
default:
scp->result = (DID_BAD_TARGET << 16);
return NULL;
}
}
else { // Passthru device commands
// Do not allow access to target id > 15 or LUN > 7
if (target > 15 || SCP2LUN(scp) > 7) {
scp->result = (DID_BAD_TARGET << 16);
return NULL;
}
// if fast load option was set and scan for last device is
// over, reset the fast_load flag so that during a possible
// next scan, devices can be made available
if (rdev->fast_load && (target == 15) &&
(SCP2CHANNEL(scp) == adapter->max_channel -1)) {
con_log(CL_ANN, (KERN_INFO
"megaraid[%d]: physical device scan re-enabled\n",
adapter->host->host_no));
rdev->fast_load = 0;
}
/*
* Display the channel scan for physical devices
*/
if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {
ss = rdev->fast_load ? skip : scan;
con_log(CL_ANN, (KERN_INFO
"scsi[%d]: %s scsi channel %d [Phy %d]",
adapter->host->host_no, ss, SCP2CHANNEL(scp),
channel));
con_log(CL_ANN, (
" for non-raid devices\n"));
rdev->last_disp |= (1L << SCP2CHANNEL(scp));
}
// disable channel sweep if fast load option given
if (rdev->fast_load) {
scp->result = (DID_BAD_TARGET << 16);
return NULL;
}
// Allocate a SCB and initialize passthru
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
*busy = 1;
return NULL;
}
ccb = (mbox_ccb_t *)scb->ccb;
scb->dev_channel = channel;
scb->dev_target = target;
scb->dma_direction = scp->sc_data_direction;
mbox = ccb->mbox;
mbox64 = ccb->mbox64;
// Does this firmware support extended CDBs
if (adapter->max_cdb_sz == 16) {
mbox->cmd = MBOXCMD_EXTPTHRU;
megaraid_mbox_prepare_epthru(adapter, scb, scp);
mbox64->xferaddr_lo = (uint32_t)ccb->epthru_dma_h;
mbox64->xferaddr_hi = 0;
mbox->xferaddr = 0xFFFFFFFF;
}
else {
mbox->cmd = MBOXCMD_PASSTHRU64;
megaraid_mbox_prepare_pthru(adapter, scb, scp);
mbox64->xferaddr_lo = (uint32_t)ccb->pthru_dma_h;
mbox64->xferaddr_hi = 0;
mbox->xferaddr = 0xFFFFFFFF;
}
return scb;
}
// NOT REACHED
}