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