nerd@percival.rain.com (Michael Galassi) (03/20/91)
Enclosed is a little program I wrote to check/change the block size of a
SCSI device. The SCSI demo served as a guide-line for some parts of this.
There is no cute interface, no documentation, no makefile. This for me
is a "use once and throw away" program. My disk drive is now formated
at 1 K blocks.
Results of using 1 K blocks are that my wren runner is now about 20 Meg
larger than it was. I can't tell if it is any faster in real use or not.
I have only tried this program with my wren runner and a wren V, it may
not work on any other drive. You use it at your risk etc etc etc...
How to use the program.
**************************
* back up your hard disk *
**************************
**************************
* back up your hard disk *
**************************
**************************
* back up your hard disk *
**************************
**************************
* back up your hard disk *
**************************
compile the program, I used cc -o scsi_bsize scsi_bsize.c.
copy the binary onto an optical disk.
reboot the system from the same optical disk.
type "scsi_bsize -t 0", this should tell you your current block size.
type scsi_bsize -t 0 -b 1024", this should set the block size to 1 K.
if you want to do a drive other than target 0, try -t <whatever>.
You have the source, play with it and read it carefully before you
use this. Remeber, its YOUR disk drive.
---- cut here and feed to /bin/sh or /bin/ksh ----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 02/26/1991 18:20 UTC by nerd@percy
# Source directory /usr/spool/uucppublic
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 4564 -rw-rw-rw- scsi_bsize.c
#
# ============= scsi_bsize.c ==============
if test -f 'scsi_bsize.c' -a X"$1" != X"-c"; then
echo 'x - skipping scsi_bsize.c (File already exists)'
else
echo 'x - extracting scsi_bsize.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'scsi_bsize.c' &&
/*
** If called without parameters this program will read and display the
** block size of the scsi device. If given a numeric parameter it will
** then set the block size of the device to that value (range 256 to 4096).
**
** by Michael Galassi (nerd@percival.rain.com) on 02/07/91 with some ideas
** taken from the scsi demo in /NextDeveloper/Expamples.
**
** This code worked for me, it is not guaranteed to work for anyone else.
** Feel free to use it as you wish at your own risk.
*/
X
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <nextdev/scsireg.h>
X
static char *dev_name="/dev/sg0"; /* generic scsi interface */
static int lun = 0;
X
void show_block_size(int target);
void set_block_size(int target, int block_size);
int gs_mode_sense(int fd, int ccode, int clen, u_char *data);
int gs_mode_select(int fd, int clen, u_char *data);
int scsi_open(int target);
X
main(int argc, char *argv[])
{
X extern int optind;
X extern char *optarg;
X
X char c;
X
X int target = -1;
X int blocksize = -1;
X
X while ((c = getopt(argc, argv, "t:b:")) != EOF) {
X switch (c) {
X case 't':
X target = atoi(optarg);
X break;
X case 'b':
X blocksize = atoi(optarg);
X break;
X }
X }
X if (target == -1) {
X fprintf(stderr,
X "usage: %s -t<target> [-b<blocksize>]\n",
X argv[0]);
X exit(1);
X }
/* if no blocksie given show current blocksize and exit */
X if (blocksize == -1) {
X show_block_size(target);
X exit(0);
X }
X
X set_block_size(target, blocksize);
X exit(0);
}
X
void show_block_size(int target)
{
X u_char data[12];
X int fd;
X int block_size;
X
X if ((fd = scsi_open(target)) < 0) {
X fputs("error opening scsi device\n", stderr);
X exit(1);
X }
X bzero(data, sizeof(data));
X if(gs_mode_sense(fd, 0, 12, data)) {
X fputs("error in mode sense\n", stderr);
X close(fd);
X exit(1);
X }
X block_size = (data[9] << 16) | (data[10] << 8) | data[11];
X fprintf(stdout, "Block size: %d bytes\n", block_size);
X close(fd);
}
X
int gs_mode_sense(int fd, int ccode, int clen, u_char *data)
{
X struct scsi_req sr;
X struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
X
X bzero((char *)&sr, sizeof(sr));
X cdbp->c6_opcode = C6OP_MODESENSE;
X cdbp->c6_lun = lun;
X cdbp->c6_lba = 0xc000 | ccode; /* pcf is 11 (binary) */
X cdbp->c6_len = clen;
X sr.sr_dma_dir = SR_DMA_RD;
X sr.sr_addr = (caddr_t)data;
X sr.sr_dma_max = clen;
X sr.sr_ioto = 10;
X return(do_ioc(fd, &sr));
}
X
void set_block_size(int target, int block_size)
{
X u_char data[12];
X int fd;
X
X if ((fd = scsi_open(target)) < 0) {
X fputs("error opening scsi device\n", stderr);
X exit(1);
X }
X bzero(data, 12);
X data[3] = 8; /* 8 bytes of block descriptor */
X data[9] = (block_size >> 16) & 0xff;
X data[10] = (block_size >> 8) & 0xff;
X data[11] = block_size & 0xff;
X if(gs_mode_select(fd, 12, data)) {
X close(fd);
X fputs("gs_mode_select failed\n", stderr);
X exit(1);
X }
X close(fd);
X show_block_size(target);
}
X
int gs_mode_select(int fd, int clen, u_char *data)
{
X struct scsi_req sr;
X struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
X
X bzero((char *)&sr, sizeof(sr)); /* clear struct out */
X
X cdbp->c6_opcode = C6OP_MODESELECT;
X cdbp->c6_lun = lun;
X cdbp->c6_lba = 0x110000; /* sets Save Mode Parameters bit */
X cdbp->c6_len = clen;
X sr.sr_dma_dir = SR_DMA_WR;
X sr.sr_dma_max = clen;
X sr.sr_addr = (caddr_t)data;
X sr.sr_ioto = 10;
X
X return(do_ioc(fd, &sr));
}
X
int do_ioc(int fd, struct scsi_req *sr)
{
X if (ioctl(fd, SGIOCREQ, sr) < 0) {
X perror("ioctl(SGIOCREQ)");
X return(-1);
X }
X if(sr->sr_io_status) {
X fprintf(stderr,"sr_io_status = 0x%02X\n",sr->sr_io_status);
X if(sr->sr_io_status == SR_IOST_CHKSV) {
X fprintf(stderr,
X "sense key = 0x%02X, sense code = 0x%02X\n",
X sr->sr_esense.er_sensekey,
X sr->sr_esense.er_addsensecode);
X }
X fprintf(stderr,"SCSI status = 0x%02X\n", sr->sr_scsi_status);
X return(-1);
X }
X return(0);
}
X
int scsi_open(int target)
{
X struct scsi_adr sa;
X int fd;
X
X if ((fd = open(dev_name, O_RDWR)) < 0) {
X fprintf(stderr,"\nCould not open %s\n",dev_name);
X return(-1);
X }
X
X sa.sa_target = target;
X sa.sa_lun = lun;
X if (ioctl(fd,SGIOCSTL,&sa) < 0) {
X fprintf(stderr,"Error setting target %d lun %d\n",target,lun);
X close(fd);
X return(-1);
X }
X
X if(gs_request_sense(fd)) { /* clear unit attention */
X close(fd);
X return(-1);
X }
X return(fd);
}
X
int gs_request_sense(int fd)
{
X struct scsi_req sr;
X struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
X u_char sbuf[128];
X
X bzero((char *)&sr, sizeof(sr));
X cdbp->c6_opcode = C6OP_REQSENSE;
X cdbp->c6_lun = lun;
X cdbp->c6_len = 18;
X sr.sr_dma_dir = SR_DMA_RD;
X sr.sr_addr = (caddr_t)sbuf;
X sr.sr_dma_max = 128;
X sr.sr_ioto = 10;
X return(do_ioc(fd, &sr));
}
SHAR_EOF
chmod 0666 scsi_bsize.c ||
echo 'restore of scsi_bsize.c failed'
Wc_c="`wc -c < 'scsi_bsize.c'`"
test 4564 -eq "$Wc_c" ||
echo 'scsi_bsize.c: original size 4567, current size' "$Wc_c"
fi
exit 0
--
Michael Galassi | nerd@percival.rain.com
MS-DOS: The ultimate PC virus. | ...!tektronix!percy!nerd