Commit 973ab2f4 authored by Andrew Morton's avatar Andrew Morton Committed by David S. Miller

[PATCH] cciss: add cmd_type to sendcmd parameters

Patch from Stephen Cameron <steve.cameron@hp.com>

* add cmd_type to sendcmd parameters to allow scsi messages to be
  sent down.
* factor out duplicated code into fill_cmd function.
parent f51e4f73
...@@ -120,7 +120,7 @@ static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c); ...@@ -120,7 +120,7 @@ static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c);
static void start_io( ctlr_info_t *h); static void start_io( ctlr_info_t *h);
static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
unsigned char *scsi3addr); unsigned char *scsi3addr, int cmd_type);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int cciss_proc_get_info(char *buffer, char **start, off_t offset, static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
...@@ -818,112 +818,152 @@ static int deregister_disk(int ctlr, int logvol) ...@@ -818,112 +818,152 @@ static int deregister_disk(int ctlr, int logvol)
h->drv[logvol].LunID = 0; h->drv[logvol].LunID = 0;
return(0); return(0);
} }
static int sendcmd_withirq(__u8 cmd, static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
int ctlr,
void *buff,
size_t size, size_t size,
unsigned int use_unit_num, unsigned int use_unit_num, /* 0: address the controller,
unsigned int log_unit, 1: address logical volume log_unit,
__u8 page_code ) 2: periph device address is scsi3addr */
unsigned int log_unit, __u8 page_code, unsigned char *scsi3addr,
int cmd_type)
{ {
ctlr_info_t *h = hba[ctlr]; ctlr_info_t *h= hba[ctlr];
CommandList_struct *c;
u64bit buff_dma_handle; u64bit buff_dma_handle;
unsigned long flags; int status = IO_OK;
int return_status = IO_OK;
DECLARE_COMPLETION(wait);
if ((c = cmd_alloc(h , 0)) == NULL)
{
return -ENOMEM;
}
// Fill in the command type
c->cmd_type = CMD_IOCTL_PEND; c->cmd_type = CMD_IOCTL_PEND;
// Fill in Command Header c->Header.ReplyQueue = 0;
c->Header.ReplyQueue = 0; // unused in simple mode if( buff != NULL) {
if( buff != NULL) // buffer to fill
{
c->Header.SGList = 1; c->Header.SGList = 1;
c->Header.SGTotal= 1; c->Header.SGTotal= 1;
} else // no buffers to fill } else {
{
c->Header.SGList = 0; c->Header.SGList = 0;
c->Header.SGTotal= 0; c->Header.SGTotal= 0;
} }
c->Header.Tag.lower = c->busaddr; // use the kernel address the cmd block for tag c->Header.Tag.lower = c->busaddr;
// Fill in Request block
switch(cmd) c->Request.Type.Type = cmd_type;
{ if (cmd_type == TYPE_CMD) {
switch(cmd) {
case CISS_INQUIRY: case CISS_INQUIRY:
/* If the logical unit number is 0 then, this is going /* If the logical unit number is 0 then, this is going
to controller so It's a physical command to controller so It's a physical command
mode = 0 target = 0. mode = 0 target = 0. So we have nothing to write.
So we have nothing to write. otherwise, if use_unit_num == 1,
Otherwise mode = 1(volume set addressing) target = LUNID
mode = 1 target = LUNID otherwise, if use_unit_num == 2,
*/ mode = 0(periph dev addr) target = scsi3addr */
if(use_unit_num != 0) if (use_unit_num == 1) {
{
c->Header.LUN.LogDev.VolId= c->Header.LUN.LogDev.VolId=
hba[ctlr]->drv[log_unit].LunID; h->drv[log_unit].LunID;
c->Header.LUN.LogDev.Mode = 1; c->Header.LUN.LogDev.Mode = 1;
} else if (use_unit_num == 2) {
memcpy(c->Header.LUN.LunAddrBytes,scsi3addr,8);
c->Header.LUN.LogDev.Mode = 0;
} }
if(page_code != 0) /* are we trying to read a vital product page */
{ if(page_code != 0) {
c->Request.CDB[1] = 0x01; c->Request.CDB[1] = 0x01;
c->Request.CDB[2] = page_code; c->Request.CDB[2] = page_code;
} }
c->Request.CDBLen = 6; c->Request.CDBLen = 6;
c->Request.Type.Type = TYPE_CMD; // It is a command.
c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_READ; // Read c->Request.Type.Direction = XFER_READ;
c->Request.Timeout = 0; // Don't time out c->Request.Timeout = 0;
c->Request.CDB[0] = CISS_INQUIRY; c->Request.CDB[0] = CISS_INQUIRY;
c->Request.CDB[4] = size & 0xFF; c->Request.CDB[4] = size & 0xFF;
break; break;
case CISS_REPORT_LOG: case CISS_REPORT_LOG:
case CISS_REPORT_PHYS:
/* Talking to controller so It's a physical command /* Talking to controller so It's a physical command
mode = 00 target = 0. mode = 00 target = 0. Nothing to write.
So we have nothing to write.
*/ */
c->Request.CDBLen = 12; c->Request.CDBLen = 12;
c->Request.Type.Type = TYPE_CMD; // It is a command.
c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_READ; // Read c->Request.Type.Direction = XFER_READ;
c->Request.Timeout = 0; // Don't time out c->Request.Timeout = 0;
c->Request.CDB[0] = CISS_REPORT_LOG; c->Request.CDB[0] = cmd;
c->Request.CDB[6] = (size >> 24) & 0xFF; //MSB c->Request.CDB[6] = (size >> 24) & 0xFF; //MSB
c->Request.CDB[7] = (size >> 16) & 0xFF; c->Request.CDB[7] = (size >> 16) & 0xFF;
c->Request.CDB[8] = (size >> 8) & 0xFF; c->Request.CDB[8] = (size >> 8) & 0xFF;
c->Request.CDB[9] = size & 0xFF; c->Request.CDB[9] = size & 0xFF;
break; break;
case CCISS_READ_CAPACITY: case CCISS_READ_CAPACITY:
c->Header.LUN.LogDev.VolId= c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID;
hba[ctlr]->drv[log_unit].LunID;
c->Header.LUN.LogDev.Mode = 1; c->Header.LUN.LogDev.Mode = 1;
c->Request.CDBLen = 10; c->Request.CDBLen = 10;
c->Request.Type.Type = TYPE_CMD; // It is a command.
c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_READ; // Read c->Request.Type.Direction = XFER_READ;
c->Request.Timeout = 0; // Don't time out c->Request.Timeout = 0;
c->Request.CDB[0] = CCISS_READ_CAPACITY; c->Request.CDB[0] = cmd;
break;
case CCISS_CACHE_FLUSH:
c->Request.CDBLen = 12;
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_WRITE;
c->Request.Timeout = 0;
c->Request.CDB[0] = BMIC_WRITE;
c->Request.CDB[6] = BMIC_CACHE_FLUSH;
break; break;
default: default:
printk(KERN_WARNING printk(KERN_WARNING
"cciss: Unknown Command 0x%c sent attempted\n", cmd); "cciss%d: Unknown Command 0x%c\n", ctlr, cmd);
cmd_free(h, c, 1);
return(IO_ERROR); return(IO_ERROR);
}; }
} else if (cmd_type == TYPE_MSG) {
// Fill in the scatter gather information switch (cmd) {
if (size > 0 ) case 3: /* No-Op message */
{ c->Request.CDBLen = 1;
buff_dma_handle.val = (__u64) pci_map_single( h->pdev, c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_WRITE;
c->Request.Timeout = 0;
c->Request.CDB[0] = cmd;
break;
default:
printk(KERN_WARNING
"cciss%d: unknown message type %d\n",
ctlr, cmd);
return IO_ERROR;
}
} else {
printk(KERN_WARNING
"cciss%d: unknown command type %d\n", ctlr, cmd_type);
return IO_ERROR;
}
/* Fill in the scatter gather information */
if (size > 0) {
buff_dma_handle.val = (__u64) pci_map_single(h->pdev,
buff, size, PCI_DMA_BIDIRECTIONAL); buff, size, PCI_DMA_BIDIRECTIONAL);
c->SG[0].Addr.lower = buff_dma_handle.val32.lower; c->SG[0].Addr.lower = buff_dma_handle.val32.lower;
c->SG[0].Addr.upper = buff_dma_handle.val32.upper; c->SG[0].Addr.upper = buff_dma_handle.val32.upper;
c->SG[0].Len = size; c->SG[0].Len = size;
c->SG[0].Ext = 0; // we are not chaining c->SG[0].Ext = 0; /* we are not chaining */
}
return status;
}
static int sendcmd_withirq(__u8 cmd,
int ctlr,
void *buff,
size_t size,
unsigned int use_unit_num,
unsigned int log_unit,
__u8 page_code,
int cmd_type)
{
ctlr_info_t *h = hba[ctlr];
CommandList_struct *c;
u64bit buff_dma_handle;
unsigned long flags;
int return_status;
DECLARE_COMPLETION(wait);
if ((c = cmd_alloc(h , 0)) == NULL)
return -ENOMEM;
return_status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
log_unit, page_code, NULL, cmd_type);
if (return_status != IO_OK) {
cmd_free(h, c, 0);
return return_status;
} }
resend_cmd2: resend_cmd2:
c->waiting = &wait; c->waiting = &wait;
...@@ -1028,10 +1068,10 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, ...@@ -1028,10 +1068,10 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
memset(inq_buff, 0, sizeof(InquiryData_struct)); memset(inq_buff, 0, sizeof(InquiryData_struct));
if (withirq) if (withirq)
return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1); inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1, TYPE_CMD);
else else
return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff, return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff,
sizeof(*inq_buff), 1, logvol ,0xC1, NULL); sizeof(*inq_buff), 1, logvol ,0xC1, NULL, TYPE_CMD);
if (return_code == IO_OK) { if (return_code == IO_OK) {
if(inq_buff->data_byte[8] == 0xFF) { if(inq_buff->data_byte[8] == 0xFF) {
printk(KERN_WARNING printk(KERN_WARNING
...@@ -1070,10 +1110,10 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, ...@@ -1070,10 +1110,10 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
memset(buf, 0, sizeof(*buf)); memset(buf, 0, sizeof(*buf));
if (withirq) if (withirq)
return_code = sendcmd_withirq(CCISS_READ_CAPACITY, return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
ctlr, buf, sizeof(*buf), 1, logvol, 0 ); ctlr, buf, sizeof(*buf), 1, logvol, 0, TYPE_CMD);
else else
return_code = sendcmd(CCISS_READ_CAPACITY, return_code = sendcmd(CCISS_READ_CAPACITY,
ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL ); ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL, TYPE_CMD);
if (return_code == IO_OK) { if (return_code == IO_OK) {
*total_size = be32_to_cpu(*((__u32 *) &buf->total_size[0]))+1; *total_size = be32_to_cpu(*((__u32 *) &buf->total_size[0]))+1;
*block_size = be32_to_cpu(*((__u32 *) &buf->block_size[0])); *block_size = be32_to_cpu(*((__u32 *) &buf->block_size[0]));
...@@ -1124,7 +1164,7 @@ static int register_new_disk(int ctlr) ...@@ -1124,7 +1164,7 @@ static int register_new_disk(int ctlr)
goto mem_msg; goto mem_msg;
return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
sizeof(ReportLunData_struct), 0, 0, 0 ); sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD);
if( return_code == IO_OK) if( return_code == IO_OK)
{ {
...@@ -1278,126 +1318,25 @@ static int sendcmd( ...@@ -1278,126 +1318,25 @@ static int sendcmd(
2: periph device address is scsi3addr */ 2: periph device address is scsi3addr */
unsigned int log_unit, unsigned int log_unit,
__u8 page_code, __u8 page_code,
unsigned char *scsi3addr) unsigned char *scsi3addr,
int cmd_type)
{ {
CommandList_struct *c; CommandList_struct *c;
int i; int i;
unsigned long complete; unsigned long complete;
ctlr_info_t *info_p= hba[ctlr]; ctlr_info_t *info_p= hba[ctlr];
u64bit buff_dma_handle; u64bit buff_dma_handle;
int status = IO_OK; int status;
c = cmd_alloc(info_p, 1); if ((c = cmd_alloc(info_p, 1)) == NULL) {
if (c == NULL)
{
printk(KERN_WARNING "cciss: unable to get memory"); printk(KERN_WARNING "cciss: unable to get memory");
return(IO_ERROR); return(IO_ERROR);
} }
// Fill in Command Header status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
c->Header.ReplyQueue = 0; // unused in simple mode log_unit, page_code, scsi3addr, cmd_type);
if( buff != NULL) // buffer to fill if (status != IO_OK) {
{
c->Header.SGList = 1;
c->Header.SGTotal= 1;
} else // no buffers to fill
{
c->Header.SGList = 0;
c->Header.SGTotal= 0;
}
c->Header.Tag.lower = c->busaddr; // use the kernel address the cmd block for tag
// Fill in Request block
switch(cmd)
{
case CISS_INQUIRY:
/* If the logical unit number is 0 then, this is going
to controller so It's a physical command
mode = 0 target = 0.
So we have nothing to write.
otherwise, if use_unit_num == 1,
mode = 1(volume set addressing) target = LUNID
otherwise, if use_unit_num == 2,
mode = 0(periph dev addr) target = scsi3addr
*/
if(use_unit_num == 1)
{
c->Header.LUN.LogDev.VolId=
hba[ctlr]->drv[log_unit].LunID;
c->Header.LUN.LogDev.Mode = 1;
}
else if (use_unit_num == 2)
{
memcpy(c->Header.LUN.LunAddrBytes,scsi3addr,8);
c->Header.LUN.LogDev.Mode = 0; // phys dev addr
}
/* are we trying to read a vital product page */
if(page_code != 0)
{
c->Request.CDB[1] = 0x01;
c->Request.CDB[2] = page_code;
}
c->Request.CDBLen = 6;
c->Request.Type.Type = TYPE_CMD; // It is a command.
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_READ; // Read
c->Request.Timeout = 0; // Don't time out
c->Request.CDB[0] = CISS_INQUIRY;
c->Request.CDB[4] = size & 0xFF;
break;
case CISS_REPORT_LOG:
case CISS_REPORT_PHYS:
/* Talking to controller so It's a physical command
mode = 00 target = 0.
So we have nothing to write.
*/
c->Request.CDBLen = 12;
c->Request.Type.Type = TYPE_CMD; // It is a command.
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_READ; // Read
c->Request.Timeout = 0; // Don't time out
c->Request.CDB[0] = cmd;
c->Request.CDB[6] = (size >> 24) & 0xFF; //MSB
c->Request.CDB[7] = (size >> 16) & 0xFF;
c->Request.CDB[8] = (size >> 8) & 0xFF;
c->Request.CDB[9] = size & 0xFF;
break;
case CCISS_READ_CAPACITY:
c->Header.LUN.LogDev.VolId=
hba[ctlr]->drv[log_unit].LunID;
c->Header.LUN.LogDev.Mode = 1;
c->Request.CDBLen = 10;
c->Request.Type.Type = TYPE_CMD; // It is a command.
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_READ; // Read
c->Request.Timeout = 0; // Don't time out
c->Request.CDB[0] = CCISS_READ_CAPACITY;
break;
case CCISS_CACHE_FLUSH:
c->Request.CDBLen = 12;
c->Request.Type.Type = TYPE_CMD; // It is a command.
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_WRITE; // No data
c->Request.Timeout = 0; // Don't time out
c->Request.CDB[0] = BMIC_WRITE; // BMIC Passthru
c->Request.CDB[6] = BMIC_CACHE_FLUSH;
break;
default:
printk(KERN_WARNING
"cciss: Unknown Command 0x%c sent attempted\n",
cmd);
cmd_free(info_p, c, 1); cmd_free(info_p, c, 1);
return(IO_ERROR); return status;
};
// Fill in the scatter gather information
if (size > 0 )
{
buff_dma_handle.val = (__u64) pci_map_single( info_p->pdev,
buff, size, PCI_DMA_BIDIRECTIONAL);
c->SG[0].Addr.lower = buff_dma_handle.val32.lower;
c->SG[0].Addr.upper = buff_dma_handle.val32.upper;
c->SG[0].Len = size;
c->SG[0].Ext = 0; // we are not chaining
} }
resend_cmd1: resend_cmd1:
/* /*
...@@ -2175,7 +2114,7 @@ static void cciss_getgeometry(int cntl_num) ...@@ -2175,7 +2114,7 @@ static void cciss_getgeometry(int cntl_num)
} }
/* Get the firmware version */ /* Get the firmware version */
return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
sizeof(InquiryData_struct), 0, 0 ,0, NULL ); sizeof(InquiryData_struct), 0, 0 ,0, NULL, TYPE_CMD);
if (return_code == IO_OK) if (return_code == IO_OK)
{ {
hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32]; hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32];
...@@ -2189,7 +2128,7 @@ static void cciss_getgeometry(int cntl_num) ...@@ -2189,7 +2128,7 @@ static void cciss_getgeometry(int cntl_num)
} }
/* Get the number of logical volumes */ /* Get the number of logical volumes */
return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff, return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff,
sizeof(ReportLunData_struct), 0, 0, 0, NULL ); sizeof(ReportLunData_struct), 0, 0, 0, NULL, TYPE_CMD);
if( return_code == IO_OK) if( return_code == IO_OK)
{ {
...@@ -2463,7 +2402,8 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) ...@@ -2463,7 +2402,8 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
/* sendcmd will turn off interrupt, and send the flush... /* sendcmd will turn off interrupt, and send the flush...
* To write all data in the battery backed cache to disks */ * To write all data in the battery backed cache to disks */
memset(flush_buf, 0, 4); memset(flush_buf, 0, 4);
return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL); return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
TYPE_CMD);
if(return_code != IO_OK) if(return_code != IO_OK)
{ {
printk(KERN_WARNING "Error Flushing cache on controller %d\n", printk(KERN_WARNING "Error Flushing cache on controller %d\n",
......
...@@ -47,7 +47,8 @@ static int sendcmd( ...@@ -47,7 +47,8 @@ static int sendcmd(
2: address is in scsi3addr */ 2: address is in scsi3addr */
unsigned int log_unit, unsigned int log_unit,
__u8 page_code, __u8 page_code,
unsigned char *scsi3addr ); unsigned char *scsi3addr,
int cmd_type);
int __init cciss_scsi_detect(Scsi_Host_Template *tpnt); int __init cciss_scsi_detect(Scsi_Host_Template *tpnt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment