Creating SCSI 10 byte CDB

2.1k Views Asked by At

I am new to SCSI CDB programming . I have some piece of code written for write command using 6byte CDB

ccb = (Exec_IO_CCB *)(buffer + header_size);   
ccb->ccb_length = sizeof(Exec_IO_CCB);          
ccb->cam_opcode = 0x1;    
ccb->connect_id = 0;    
ccb->data_buf_ptr = (long)(header_size + ccb->ccb_length + MAX_SENSE_LEN);    
ccb->data_xfer_length = (long)(XFER_BUFSIZE - ccb->data_buf_ptr);    
ccb->sense_buf_ptr = (long)(header_size + ccb->ccb_length);    
ccb->sense_buf_length = MAX_SENSE_LEN;    
ccb->time_out = CAM_TIMEOUT;    
ccb->cdb_length = 6;    
ccb->cam_flags = DATA_OUT;    
ccb->cdb[0] = 0xA;   /*  0xA SCSI Opcode for write operation */    
ccb->cdb[1] = 0;    
ccb->cdb[2] = (ccb->data_xfer_length & 0xFF0000) >> 16;    
ccb->cdb[3] = (ccb->data_xfer_length & 0xFF00) >> 8;    
ccb->cdb[4] = (ccb->data_xfer_length & 0xFF);    
ccb->cdb[5] = 0;

From the above code I did not understand how cdb[2] and cdb[3] are derived ?

On a similar line, I am trying to develope 10 Byte CDB for write command. How to fill in the data for cdb[2-5] which accounts for LBA?

ccb->cam_flags = DATA_OUT;    
ccb->cdb[0] = 0x2A;     /*  0x2A SCSI Opcode for write10  CDB */    
ccb->cdb[1] = 0;    
ccb->cdb[2] =  ??    
ccb->cdb[3] =  ??    
ccb->cdb[4] =  ??    
ccb->cdb[5] =  ??    
ccb->cdb[6] = 0;    
ccb->cdb[7] = (ccb->data_xfer_length & 0xFF);    
ccb->cdb[8] = (ccb->data_xfer_length & 0xFF);    
ccb->cdb[9] = 0;
4

There are 4 best solutions below

0
On

You can't put 2048 into byte 5 because byte 5 is a byte and 2048 is a short. Instead use cdb[4]=((2048 & 0xFF00) >> 8) and cdb[5]=(2048 & 0xFF). Also for cdb[7] you have assigned the low order byte of data_xfer_length but it should be the high order byte.

4
On

Have a look at the SCSI SBC standard. Here's SBC-3 in draft form, but WRITE (6) and (10) haven't changed in quite some time: http://www.t10.org/ftp/t10/document.05/05-344r0.pdf.

For WRITE (6), cdb[2] and cdb[3] are the lower 16 bits of the logical block address, not the transfer length. The transfer length is the number of blocks you're going to write. The address is the place on the device where you're going to start writing them. If it's at the very beginning of the disk, it's LBA 0. If the device has 512-byte blocks, and you want to start writing 1 MiB in, your address is LBA 2048.

0
On

Come to see http://en.wikipedia.org/wiki/SCSI_Write_Commands, it is very simple.

0
On

To easily form CDB commands you can use libscsicmd it can both form the cdbs and parse the results of SCSI replies such as the sense buffers. It may not include all of the commands and replies as I work through it as I need it but I get to things slowly but surely.