Commit 00988a35 authored by Mike Miller (OS Dev)'s avatar Mike Miller (OS Dev) Committed by Linus Torvalds

[PATCH] cciss: support for >2TB logical volumes

Add support for logical volumes >2TB.  All SAS/SATA controllers support
large volumes.
Signed-off-by: default avatarMike Miller <mike.miller@hp.com>
Cc: Jens Axboe <axboe@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 82b0547c
...@@ -144,13 +144,13 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk); ...@@ -144,13 +144,13 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
int clear_all); int clear_all);
static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, static void cciss_read_capacity(int ctlr, int logvol, int withirq,
int withirq, unsigned int *total_size, sector_t *total_size, unsigned int *block_size);
unsigned int *block_size); static void cciss_read_capacity_16(int ctlr, int logvol, int withirq,
static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size);
unsigned int total_size, static void cciss_geometry_inquiry(int ctlr, int logvol,
unsigned int block_size, int withirq, sector_t total_size,
InquiryData_struct *inq_buff, unsigned int block_size, InquiryData_struct *inq_buff,
drive_info_struct *drv); drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num); static void cciss_getgeometry(int cntl_num);
static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
...@@ -1325,10 +1325,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index) ...@@ -1325,10 +1325,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
{ {
ctlr_info_t *h = hba[ctlr]; ctlr_info_t *h = hba[ctlr];
struct gendisk *disk; struct gendisk *disk;
ReadCapdata_struct *size_buff = NULL;
InquiryData_struct *inq_buff = NULL; InquiryData_struct *inq_buff = NULL;
unsigned int block_size; unsigned int block_size;
unsigned int total_size; sector_t total_size;
unsigned long flags = 0; unsigned long flags = 0;
int ret = 0; int ret = 0;
...@@ -1347,15 +1346,25 @@ static void cciss_update_drive_info(int ctlr, int drv_index) ...@@ -1347,15 +1346,25 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
return; return;
/* Get information about the disk and modify the driver structure */ /* Get information about the disk and modify the driver structure */
size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
if (size_buff == NULL)
goto mem_msg;
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) if (inq_buff == NULL)
goto mem_msg; goto mem_msg;
cciss_read_capacity(ctlr, drv_index, size_buff, 1, cciss_read_capacity(ctlr, drv_index, 1,
&total_size, &block_size); &total_size, &block_size);
/* total size = last LBA + 1 */
/* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */
/* so we assume this volume this must be >2TB in size */
if (total_size == (__u32) 0) {
cciss_read_capacity_16(ctlr, drv_index, 1,
&total_size, &block_size);
h->cciss_read = CCISS_READ_16;
h->cciss_write = CCISS_WRITE_16;
} else {
h->cciss_read = CCISS_READ_10;
h->cciss_write = CCISS_WRITE_10;
}
cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
inq_buff, &h->drv[drv_index]); inq_buff, &h->drv[drv_index]);
...@@ -1391,7 +1400,6 @@ static void cciss_update_drive_info(int ctlr, int drv_index) ...@@ -1391,7 +1400,6 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
} }
freeret: freeret:
kfree(size_buff);
kfree(inq_buff); kfree(inq_buff);
return; return;
mem_msg: mem_msg:
...@@ -1716,6 +1724,22 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ ...@@ -1716,6 +1724,22 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_
c->Request.Timeout = 0; c->Request.Timeout = 0;
c->Request.CDB[0] = cmd; c->Request.CDB[0] = cmd;
break; break;
case CCISS_READ_CAPACITY_16:
c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID;
c->Header.LUN.LogDev.Mode = 1;
c->Request.CDBLen = 16;
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_READ;
c->Request.Timeout = 0;
c->Request.CDB[0] = cmd;
c->Request.CDB[1] = 0x10;
c->Request.CDB[10] = (size >> 24) & 0xFF;
c->Request.CDB[11] = (size >> 16) & 0xFF;
c->Request.CDB[12] = (size >> 8) & 0xFF;
c->Request.CDB[13] = size & 0xFF;
c->Request.Timeout = 0;
c->Request.CDB[0] = cmd;
break;
case CCISS_CACHE_FLUSH: case CCISS_CACHE_FLUSH:
c->Request.CDBLen = 12; c->Request.CDBLen = 12;
c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Attribute = ATTR_SIMPLE;
...@@ -1749,6 +1773,7 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ ...@@ -1749,6 +1773,7 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
c->Request.CDB[0] = cmd; /* reset */ c->Request.CDB[0] = cmd; /* reset */
c->Request.CDB[1] = 0x04; /* reset a LUN */ c->Request.CDB[1] = 0x04; /* reset a LUN */
break;
case 3: /* No-Op message */ case 3: /* No-Op message */
c->Request.CDBLen = 1; c->Request.CDBLen = 1;
c->Request.Type.Attribute = ATTR_SIMPLE; c->Request.Type.Attribute = ATTR_SIMPLE;
...@@ -1892,12 +1917,15 @@ static int sendcmd_withirq(__u8 cmd, ...@@ -1892,12 +1917,15 @@ static int sendcmd_withirq(__u8 cmd,
} }
static void cciss_geometry_inquiry(int ctlr, int logvol, static void cciss_geometry_inquiry(int ctlr, int logvol,
int withirq, unsigned int total_size, int withirq, sector_t total_size,
unsigned int block_size, unsigned int block_size,
InquiryData_struct *inq_buff, InquiryData_struct *inq_buff,
drive_info_struct *drv) drive_info_struct *drv)
{ {
int return_code; int return_code;
unsigned long t;
unsigned long rem;
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,
...@@ -1916,10 +1944,10 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, ...@@ -1916,10 +1944,10 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
drv->nr_blocks = total_size; drv->nr_blocks = total_size;
drv->heads = 255; drv->heads = 255;
drv->sectors = 32; // Sectors per track drv->sectors = 32; // Sectors per track
drv->cylinders = total_size / 255 / 32; t = drv->heads * drv->sectors;
drv->cylinders = total_size;
rem = do_div(drv->cylinders, t);
} else { } else {
unsigned int t;
drv->block_size = block_size; drv->block_size = block_size;
drv->nr_blocks = total_size; drv->nr_blocks = total_size;
drv->heads = inq_buff->data_byte[6]; drv->heads = inq_buff->data_byte[6];
...@@ -1929,7 +1957,8 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, ...@@ -1929,7 +1957,8 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
drv->raid_level = inq_buff->data_byte[8]; drv->raid_level = inq_buff->data_byte[8];
t = drv->heads * drv->sectors; t = drv->heads * drv->sectors;
if (t > 1) { if (t > 1) {
drv->cylinders = total_size / t; drv->cylinders = total_size;
rem = do_div(drv->cylinders, t);
} }
} }
} else { /* Get geometry failed */ } else { /* Get geometry failed */
...@@ -1940,31 +1969,72 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, ...@@ -1940,31 +1969,72 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
} }
static void static void
cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
int withirq, unsigned int *total_size,
unsigned int *block_size) unsigned int *block_size)
{ {
ReadCapdata_struct *buf;
int return_code; int return_code;
memset(buf, 0, sizeof(*buf)); buf = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
if (buf == NULL) {
printk(KERN_WARNING "cciss: out of memory\n");
return;
}
memset(buf, 0, sizeof(ReadCapdata_struct));
if (withirq) if (withirq)
return_code = sendcmd_withirq(CCISS_READ_CAPACITY, return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
ctlr, buf, sizeof(*buf), 1, ctlr, buf, sizeof(ReadCapdata_struct),
logvol, 0, TYPE_CMD); 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, ctlr, buf, sizeof(ReadCapdata_struct),
NULL, TYPE_CMD); 1, logvol, 0, NULL, TYPE_CMD);
if (return_code == IO_OK) { if (return_code == IO_OK) {
*total_size = *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1;
be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1; *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
*block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0]));
} else { /* read capacity command failed */ } else { /* read capacity command failed */
printk(KERN_WARNING "cciss: read capacity failed\n"); printk(KERN_WARNING "cciss: read capacity failed\n");
*total_size = 0; *total_size = 0;
*block_size = BLOCK_SIZE; *block_size = BLOCK_SIZE;
} }
printk(KERN_INFO " blocks= %u block_size= %d\n", if (*total_size != (__u32) 0)
printk(KERN_INFO " blocks= %lld block_size= %d\n",
*total_size, *block_size);
kfree(buf);
return;
}
static void
cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size)
{
ReadCapdata_struct_16 *buf;
int return_code;
buf = kmalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL);
if (buf == NULL) {
printk(KERN_WARNING "cciss: out of memory\n");
return;
}
memset(buf, 0, sizeof(ReadCapdata_struct_16));
if (withirq) {
return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
ctlr, buf, sizeof(ReadCapdata_struct_16),
1, logvol, 0, TYPE_CMD);
}
else {
return_code = sendcmd(CCISS_READ_CAPACITY_16,
ctlr, buf, sizeof(ReadCapdata_struct_16),
1, logvol, 0, NULL, TYPE_CMD);
}
if (return_code == IO_OK) {
*total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1;
*block_size = be32_to_cpu(*(__u32 *) buf->block_size);
} else { /* read capacity command failed */
printk(KERN_WARNING "cciss: read capacity failed\n");
*total_size = 0;
*block_size = BLOCK_SIZE;
}
printk(KERN_INFO " blocks= %lld block_size= %d\n",
*total_size, *block_size); *total_size, *block_size);
kfree(buf);
return; return;
} }
...@@ -1975,8 +2045,7 @@ static int cciss_revalidate(struct gendisk *disk) ...@@ -1975,8 +2045,7 @@ static int cciss_revalidate(struct gendisk *disk)
int logvol; int logvol;
int FOUND = 0; int FOUND = 0;
unsigned int block_size; unsigned int block_size;
unsigned int total_size; sector_t total_size;
ReadCapdata_struct *size_buff = NULL;
InquiryData_struct *inq_buff = NULL; InquiryData_struct *inq_buff = NULL;
for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
...@@ -1989,27 +2058,24 @@ static int cciss_revalidate(struct gendisk *disk) ...@@ -1989,27 +2058,24 @@ static int cciss_revalidate(struct gendisk *disk)
if (!FOUND) if (!FOUND)
return 1; return 1;
size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
if (size_buff == NULL) {
printk(KERN_WARNING "cciss: out of memory\n");
return 1;
}
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) { if (inq_buff == NULL) {
printk(KERN_WARNING "cciss: out of memory\n"); printk(KERN_WARNING "cciss: out of memory\n");
kfree(size_buff);
return 1; return 1;
} }
if (h->cciss_read == CCISS_READ_10) {
cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, cciss_read_capacity(h->ctlr, logvol, 1,
&block_size); &total_size, &block_size);
} else {
cciss_read_capacity_16(h->ctlr, logvol, 1,
&total_size, &block_size);
}
cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
inq_buff, drv); inq_buff, drv);
blk_queue_hardsect_size(drv->queue, drv->block_size); blk_queue_hardsect_size(drv->queue, drv->block_size);
set_capacity(disk, drv->nr_blocks); set_capacity(disk, drv->nr_blocks);
kfree(size_buff);
kfree(inq_buff); kfree(inq_buff);
return 0; return 0;
} }
...@@ -2418,7 +2484,8 @@ static void do_cciss_request(request_queue_t *q) ...@@ -2418,7 +2484,8 @@ static void do_cciss_request(request_queue_t *q)
{ {
ctlr_info_t *h = q->queuedata; ctlr_info_t *h = q->queuedata;
CommandList_struct *c; CommandList_struct *c;
int start_blk, seg; sector_t start_blk;
int seg;
struct request *creq; struct request *creq;
u64bit temp64; u64bit temp64;
struct scatterlist tmp_sg[MAXSGENTRIES]; struct scatterlist tmp_sg[MAXSGENTRIES];
...@@ -2462,10 +2529,10 @@ static void do_cciss_request(request_queue_t *q) ...@@ -2462,10 +2529,10 @@ static void do_cciss_request(request_queue_t *q)
c->Request.Type.Type = TYPE_CMD; // It is a command. 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 = c->Request.Type.Direction =
(rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE; (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
c->Request.Timeout = 0; // Don't time out c->Request.Timeout = 0; // Don't time out
c->Request.CDB[0] = c->Request.CDB[0] =
(rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE; (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
start_blk = creq->sector; start_blk = creq->sector;
#ifdef CCISS_DEBUG #ifdef CCISS_DEBUG
printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector, printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector,
...@@ -2499,15 +2566,33 @@ static void do_cciss_request(request_queue_t *q) ...@@ -2499,15 +2566,33 @@ static void do_cciss_request(request_queue_t *q)
#endif /* CCISS_DEBUG */ #endif /* CCISS_DEBUG */
c->Header.SGList = c->Header.SGTotal = seg; c->Header.SGList = c->Header.SGTotal = seg;
c->Request.CDB[1] = 0; if(h->cciss_read == CCISS_READ_10) {
c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB c->Request.CDB[1] = 0;
c->Request.CDB[3] = (start_blk >> 16) & 0xff; c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB
c->Request.CDB[4] = (start_blk >> 8) & 0xff; c->Request.CDB[3] = (start_blk >> 16) & 0xff;
c->Request.CDB[5] = start_blk & 0xff; c->Request.CDB[4] = (start_blk >> 8) & 0xff;
c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB c->Request.CDB[5] = start_blk & 0xff;
c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff; c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB
c->Request.CDB[8] = creq->nr_sectors & 0xff; c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; c->Request.CDB[8] = creq->nr_sectors & 0xff;
c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
} else {
c->Request.CDBLen = 16;
c->Request.CDB[1]= 0;
c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB
c->Request.CDB[3]= (start_blk >> 48) & 0xff;
c->Request.CDB[4]= (start_blk >> 40) & 0xff;
c->Request.CDB[5]= (start_blk >> 32) & 0xff;
c->Request.CDB[6]= (start_blk >> 24) & 0xff;
c->Request.CDB[7]= (start_blk >> 16) & 0xff;
c->Request.CDB[8]= (start_blk >> 8) & 0xff;
c->Request.CDB[9]= start_blk & 0xff;
c->Request.CDB[10]= (creq->nr_sectors >> 24) & 0xff;
c->Request.CDB[11]= (creq->nr_sectors >> 16) & 0xff;
c->Request.CDB[12]= (creq->nr_sectors >> 8) & 0xff;
c->Request.CDB[13]= creq->nr_sectors & 0xff;
c->Request.CDB[14] = c->Request.CDB[15] = 0;
}
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
...@@ -2517,9 +2602,9 @@ static void do_cciss_request(request_queue_t *q) ...@@ -2517,9 +2602,9 @@ static void do_cciss_request(request_queue_t *q)
h->maxQsinceinit = h->Qdepth; h->maxQsinceinit = h->Qdepth;
goto queue; goto queue;
full: full:
blk_stop_queue(q); blk_stop_queue(q);
startio: startio:
/* We will already have the driver lock here so not need /* We will already have the driver lock here so not need
* to lock it. * to lock it.
*/ */
...@@ -2947,31 +3032,23 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) ...@@ -2947,31 +3032,23 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
static void cciss_getgeometry(int cntl_num) static void cciss_getgeometry(int cntl_num)
{ {
ReportLunData_struct *ld_buff; ReportLunData_struct *ld_buff;
ReadCapdata_struct *size_buff;
InquiryData_struct *inq_buff; InquiryData_struct *inq_buff;
int return_code; int return_code;
int i; int i;
int listlength = 0; int listlength = 0;
__u32 lunid = 0; __u32 lunid = 0;
int block_size; int block_size;
int total_size; sector_t total_size;
ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
if (ld_buff == NULL) { if (ld_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n"); printk(KERN_ERR "cciss: out of memory\n");
return; return;
} }
size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
if (size_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
return;
}
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) { if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n"); printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff); kfree(ld_buff);
kfree(size_buff);
return; return;
} }
/* Get the firmware version */ /* Get the firmware version */
...@@ -3026,7 +3103,6 @@ static void cciss_getgeometry(int cntl_num) ...@@ -3026,7 +3103,6 @@ static void cciss_getgeometry(int cntl_num)
#endif /* CCISS_DEBUG */ #endif /* CCISS_DEBUG */
hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1; hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1;
// for(i=0; i< hba[cntl_num]->num_luns; i++)
for (i = 0; i < CISS_MAX_LUN; i++) { for (i = 0; i < CISS_MAX_LUN; i++) {
if (i < hba[cntl_num]->num_luns) { if (i < hba[cntl_num]->num_luns) {
lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
...@@ -3045,8 +3121,26 @@ static void cciss_getgeometry(int cntl_num) ...@@ -3045,8 +3121,26 @@ static void cciss_getgeometry(int cntl_num)
ld_buff->LUN[i][2], ld_buff->LUN[i][3], ld_buff->LUN[i][2], ld_buff->LUN[i][3],
hba[cntl_num]->drv[i].LunID); hba[cntl_num]->drv[i].LunID);
#endif /* CCISS_DEBUG */ #endif /* CCISS_DEBUG */
cciss_read_capacity(cntl_num, i, size_buff, 0,
/* testing to see if 16-byte CDBs are already being used */
if(hba[cntl_num]->cciss_read == CCISS_READ_16) {
cciss_read_capacity_16(cntl_num, i, 0,
&total_size, &block_size); &total_size, &block_size);
goto geo_inq;
}
cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size);
/* total_size = last LBA + 1 */
if(total_size == (__u32) 0) {
cciss_read_capacity_16(cntl_num, i, 0,
&total_size, &block_size);
hba[cntl_num]->cciss_read = CCISS_READ_16;
hba[cntl_num]->cciss_write = CCISS_WRITE_16;
} else {
hba[cntl_num]->cciss_read = CCISS_READ_10;
hba[cntl_num]->cciss_write = CCISS_WRITE_10;
}
geo_inq:
cciss_geometry_inquiry(cntl_num, i, 0, total_size, cciss_geometry_inquiry(cntl_num, i, 0, total_size,
block_size, inq_buff, block_size, inq_buff,
&hba[cntl_num]->drv[i]); &hba[cntl_num]->drv[i]);
...@@ -3056,7 +3150,6 @@ static void cciss_getgeometry(int cntl_num) ...@@ -3056,7 +3150,6 @@ static void cciss_getgeometry(int cntl_num)
} }
} }
kfree(ld_buff); kfree(ld_buff);
kfree(size_buff);
kfree(inq_buff); kfree(inq_buff);
} }
......
...@@ -76,6 +76,9 @@ struct ctlr_info ...@@ -76,6 +76,9 @@ struct ctlr_info
unsigned int intr[4]; unsigned int intr[4];
unsigned int msix_vector; unsigned int msix_vector;
unsigned int msi_vector; unsigned int msi_vector;
BYTE cciss_read;
BYTE cciss_write;
BYTE cciss_read_capacity;
// information about each logical volume // information about each logical volume
drive_info_struct drv[CISS_MAX_LUN]; drive_info_struct drv[CISS_MAX_LUN];
......
...@@ -118,11 +118,34 @@ typedef struct _ReadCapdata_struct ...@@ -118,11 +118,34 @@ typedef struct _ReadCapdata_struct
BYTE block_size[4]; // Size of blocks in bytes BYTE block_size[4]; // Size of blocks in bytes
} ReadCapdata_struct; } ReadCapdata_struct;
// 12 byte commands not implemented in firmware yet. #define CCISS_READ_CAPACITY_16 0x9e /* Read Capacity 16 */
// #define CCISS_READ 0xa8 // Read(12)
// #define CCISS_WRITE 0xaa // Write(12) /* service action to differentiate a 16 byte read capacity from
#define CCISS_READ 0x28 // Read(10) other commands that use the 0x9e SCSI op code */
#define CCISS_WRITE 0x2a // Write(10)
#define CCISS_READ_CAPACITY_16_SERVICE_ACT 0x10
typedef struct _ReadCapdata_struct_16
{
BYTE total_size[8]; /* Total size in blocks */
BYTE block_size[4]; /* Size of blocks in bytes */
BYTE prot_en:1; /* protection enable bit */
BYTE rto_en:1; /* reference tag own enable bit */
BYTE reserved:6; /* reserved bits */
BYTE reserved2[18]; /* reserved bytes per spec */
} ReadCapdata_struct_16;
/* Define the supported read/write commands for cciss based controllers */
#define CCISS_READ_10 0x28 /* Read(10) */
#define CCISS_WRITE_10 0x2a /* Write(10) */
#define CCISS_READ_16 0x88 /* Read(16) */
#define CCISS_WRITE_16 0x8a /* Write(16) */
/* Define the CDB lengths supported by cciss based controllers */
#define CDB_LEN10 10
#define CDB_LEN16 16
// BMIC commands // BMIC commands
#define BMIC_READ 0x26 #define BMIC_READ 0x26
......
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