Subject: Re: SCSI utility to reset the sector size on a SCSI disk
To: None <current-users@netbsd.org>
From: Brian Buhrow <buhrow@lothlorien.nfbcal.org>
List: current-users
Date: 10/31/2001 01:46:11
	Hello folks.  Mat was able to point me at the format utility under Solaris
which did the trick nicely.  However, I decided I really wanted to add this
functionality to scsictl.  To that end, I modified the device_format()
routine to send amode select command to the drive with the new block size
before issuing the format_unit command, which the SCSI spec says is how you
change the block size of a device.  (I plan to add arguments to the format
command to let you specify new block sizes.)
	In running my new function, I get errors saying that my SCSI mode select 
parameter list is invalid, and that the offset where the error is is 0.
However, the first byte of data in the parameter list, is the first byte of
the mode_header data, which is the length of the  attached descriptor
blocks plus the length of the mode page we're selecting, right?  If so,
then this number is correct, I think.
	I'm wondering if someone might take pity on me and take a quick
look at the below output from gdb, as well as the modified format_device
function and tell me what it is that I don't understand.  I feel victory is
near, but could use a little more understanding.  

Many thanks in advance for anyone help any might offer.
-Brian

testsun# gdb scsictl
GNU gdb 4.17
(gdb) run /dev/rsd1c identify
Starting program: /usr/src/sbin/scsictl/scsictl /dev/rsd1c identify
/dev/rsd1c: scsibus0 target 1 lun 0 <TANDEM, 4575-5, 03A1>
8867027 blocks of 514 bytes each

Program exited normally.
(gdb) run /dev/rsd1c format
Starting program: /usr/src/sbin/scsictl/scsictl /dev/rsd1c format
Block count: 8867028, block length: 514
/dev/rsd1c: SCSI command timed out
/dev/rsd1c: device is busy
/dev/rsd1c: Check Condition on CDB: 15 11 00 00 23 00
    SENSE KEY: Illegal Request
     ASC/ASCQ: Invalid Field In Parameter List
         SKSV: Error in Parameters, Offset 0

 Additional Sense Information (byte 18 out...):

        18: 0x00 0x00 0x01 0x38 0x00 0x00
        24: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00


Program exited with code 01.
(gdb) break scsictl.c:232
Breakpoint 3 at 0x10838: file scsictl.c, line 232.
(gdb) run /dev/rsd1c format
Starting program: /usr/src/sbin/scsictl/scsictl /dev/rsd1c format
Block count: 8867028, block length: 514

Breakpoint 3, device_format (argc=0, argv=0xeffffa20) at scsictl.c:232
232             scsi_mode_select(fd, 0x03, SMS_SP|SMS_PF, &data, sizeof(data));
(gdb) print data
$1 = {header = {data_length = 30 '\036', medium_type = 0 '\000', 
    dev_spec = 16 '\020', blk_desc_len = 8 '\b'}, blk_desc = {
    density = 0 '\000', nblocks = "\207LÔ", reserved = 0 '\000', 
    blklen = "\000\002\002"}, format_page = {pg_code = 131 '\203', 
    pg_length = 22 '\026', trk_z = "\000\005", alt_sec = "\000\001", 
    alt_trk_z = "\000", alt_trk_v = "\000", ph_sec_t = "\001\027", 
    bytes_s = "\002\002", interleave = "\000\001", trk_skew = "\000\034", 
    cyl_skew = "\000H", flags = 64 '@', reserved2 = 0 '\000', 
    reserved3 = 0 '\000'}}

<modified device_format function>

void
device_format(argc, argv)
	int argc;
	char *argv[];
{
	u_int32_t blklen; /*allow for optional alternate block length formatting*/
	struct scsi_format_unit cmd;
	struct {
		struct scsipi_mode_header header;
		struct scsi_blk_desc blk_desc;
		struct page_disk_format format_page;
	} data;

	/* No arguments. */
	if (argc != 0)
		usage();

	/*
	 * Get the DISK FORMAT mode page.  SCSI-2 recommends specifying the
	 * interleave read from this page in the FORMAT UNIT command.
	 */
	scsi_mode_sense(fd, 0x03, 0x00, &data, sizeof(data));
	/*print the value of the blklen from the block descriptor*/
	printf("Block count: %u, block length: %u\n",
	_3btol(data.blk_desc.nblocks),_3btol(data.blk_desc.blklen));
	blklen = 512; /*temporary hack*/

	/*Perform a mode select to set the new block size*/
	data.header.data_length = sizeof(struct scsi_blk_desc) + data.format_page.pg_length;
	_lto3b((u_int32_t)0, data.blk_desc.nblocks);
	_lto3b(blklen, data.format_page.bytes_s);
	_lto3b(blklen, data.blk_desc.blklen);
	scsi_mode_select(fd, 0x03, SMS_SP|SMS_PF, &data, sizeof(data));

	printf("Formatting %u blocks of %u bytes each\n",
	_3btol(data.blk_desc.nblocks),_3btol(data.blk_desc.blklen));


	memset(&cmd, 0, sizeof(cmd));

	cmd.opcode = SCSI_FORMAT_UNIT;
	memcpy(cmd.interleave, data.format_page.interleave,
	    sizeof(cmd.interleave));

	/*scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 21600000, 0);*/

	return;
}