|
|
1.1 ! root 1: /* Copyright (c) 1993 NeXT Computer, Inc. All rights reserved. ! 2: * ! 3: * stblocksize.c ! 4: * ! 5: * Read and set the native block size for a SCSI tape device. ! 6: * ! 7: * HISTORY ! 8: * 18-Oct-93 Phillip Dibner at NeXT ! 9: * Created. ! 10: */ ! 11: ! 12: #include <errno.h> ! 13: #include <sys/types.h> ! 14: #include <sys/file.h> ! 15: #include <bsd/dev/scsireg.h> ! 16: #include "stblocksize.h" /* XXX merge this file with scsireg.h */ ! 17: #include <bsd/libc.h> ! 18: #include <bsd/sys/fcntl.h> ! 19: #include <ctype.h> ! 20: #include <objc/objc.h> ! 21: ! 22: int fd; ! 23: int read_block_limits(), do_ioc(); ! 24: void usage(); ! 25: ! 26: int ! 27: main(int argc, char **argv) ! 28: { ! 29: int i, j, len; ! 30: int maxblocksize, minblocksize, blocksize; ! 31: BOOL verbose = NO, manualsize = NO; ! 32: int last = argc - 1; ! 33: ! 34: /* ! 35: * Check argument count ! 36: */ ! 37: if (argc < 2 || argc > 5) { ! 38: usage(); ! 39: return -1; ! 40: } ! 41: ! 42: for (i = 1; i < argc-1; i++) { ! 43: ! 44: /* ! 45: * See if we have been asked to print the device's blocksize... ! 46: */ ! 47: if (strcmp (argv [i], "-v") == 0) { ! 48: verbose = YES; ! 49: } ! 50: ! 51: /* ! 52: * ... or if we are setting the blocksize from the command line. ! 53: */ ! 54: else if ((strcmp (argv[i], "-s")) == 0) { ! 55: manualsize = YES; ! 56: ! 57: /* ! 58: * Check that next argument is a number, and convert it. ! 59: */ ! 60: i++; ! 61: len = strlen (argv [i]); ! 62: for (j=0; j<len; j++) { ! 63: if (!isdigit(argv[i][j])) { ! 64: usage(); ! 65: return -1; ! 66: } ! 67: } ! 68: blocksize = atoi (argv[i]); ! 69: } ! 70: ! 71: else { ! 72: usage(); ! 73: return -1; ! 74: } ! 75: } ! 76: ! 77: /* ! 78: * Open the tape device, which should be the last argument ! 79: */ ! 80: if ((fd = open(argv[last], O_RDWR, 777)) < 0) { ! 81: printf ("Cannot open %s\n", argv[last]); ! 82: return -1; ! 83: } ! 84: ! 85: /* ! 86: * Read block size. ! 87: * ! 88: * We don't read it if we're setting it manually. This may allow us to ! 89: * use a device that implements the READ_BLOCK_LIMITS command improperly. ! 90: */ ! 91: if (!manualsize) { ! 92: if (read_block_limits(&maxblocksize, &minblocksize)) { ! 93: printf ("Error reading block size parameters for %s\n", ! 94: argv[last]); ! 95: return -1; ! 96: } ! 97: ! 98: /* ! 99: * Equal max and min blocksize mean the device requires transfers ! 100: * with a fixed block size. ! 101: */ ! 102: if (maxblocksize == minblocksize) { ! 103: blocksize = minblocksize; ! 104: } ! 105: else { ! 106: blocksize = 0; ! 107: } ! 108: } ! 109: ! 110: if (verbose) { ! 111: if (!manualsize) ! 112: printf ("Tape device %s block limits: min = %d, max = %d\n", ! 113: argv[last], minblocksize, maxblocksize); ! 114: printf ("Setting %s blocksize to %d.\n", argv[last], blocksize); ! 115: } ! 116: ! 117: /* ! 118: * Set the block size that the device will use for data transfers. ! 119: */ ! 120: if (ioctl(fd, MTIOCFIXBLK, &blocksize)) ! 121: { ! 122: printf ("Cannot set block size 0x%x for %s\n", ! 123: blocksize, argv[last]); ! 124: return -1; ! 125: } ! 126: close (fd); ! 127: return 0; ! 128: } /* main() */ ! 129: ! 130: int ! 131: read_block_limits (int *maxp, int *minp) ! 132: { ! 133: struct scsi_req sr; ! 134: struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6; ! 135: struct read_blk_sz_reply rbsr; ! 136: ! 137: bzero ((char *) cdbp, sizeof (union cdb)); ! 138: cdbp->c6_opcode = C6OP_RDBLKLIMS; ! 139: ! 140: /* ! 141: * NB: The lun is set by the driver, since we don't know what ! 142: * it is from the user level. ! 143: */ ! 144: ! 145: sr.sr_dma_dir = SR_DMA_RD; ! 146: sr.sr_addr = (caddr_t) &rbsr; ! 147: sr.sr_dma_max = sizeof (struct read_blk_sz_reply); ! 148: sr.sr_ioto = 10; ! 149: if (do_ioc(&sr)) { ! 150: return -1; ! 151: } ! 152: else { ! 153: ! 154: #if __BIG_ENDIAN__ ! 155: *maxp = rbsr.rsbr_max_bll; ! 156: *minp = rbsr.rsbr_min_bll; ! 157: #elif __LITTLE_ENDIAN__ ! 158: *maxp = (rbsr.rbsr_max_bll2 << 16) + (rbsr.rbsr_max_bll1 << 8) + ! 159: rbsr.rbsr_max_bll0; ! 160: *minp = (rbsr.rbsr_min_bll1 << 8) + (rbsr.rbsr_min_bll0); ! 161: #else ! 162: #error byte order? ! 163: #endif ! 164: ! 165: } ! 166: return 0; ! 167: } /* read_block_limits() */ ! 168: ! 169: int ! 170: do_ioc(srp) ! 171: struct scsi_req *srp; ! 172: { ! 173: ! 174: if (ioctl(fd,MTIOCSRQ,srp) < 0) { ! 175: printf("..Error executing ioctl\n"); ! 176: printf("errno = %d\n",errno); ! 177: perror("ioctl (MTIOCSRQ)"); ! 178: return 1; ! 179: } ! 180: if(srp->sr_io_status) { ! 181: printf("sr_io_status = 0x%X\n",srp->sr_io_status); ! 182: if(srp->sr_io_status == SR_IOST_CHKSV) { ! 183: printf(" sense key = %02XH sense code = %02XH\n", ! 184: srp->sr_esense.er_sensekey, ! 185: srp->sr_esense.er_addsensecode); ! 186: } ! 187: printf("SCSI status = %02XH\n", srp->sr_scsi_status); ! 188: return 1; ! 189: } ! 190: return 0; ! 191: } /* do_ioc() */ ! 192: ! 193: ! 194: void ! 195: usage() ! 196: { ! 197: printf ("Usage: stblocksize [-v] [-s <blocksize>] " ! 198: "<dev-full-pathname>\n"); ! 199: return; ! 200: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.