*** linux/include/linux/mtio.h Sun Dec 6 19:10:13 1992 --- ../linux/include/linux/mtio.h Sun Dec 6 19:11:03 1992 *************** *** 46,54 **** #define MTSETBLK 20 /* set block length (SCSI) */ #define MTSETDENSITY 21 /* set tape density (SCSI) */ - /* structure for MTIOCGET - mag tape get status command */ struct mtget { --- 46,55 ---- #define MTSETBLK 20 /* set block length (SCSI) */ #define MTSETDENSITY 21 /* set tape density (SCSI) */ + #define MTSEEK 22 /* seek to block (Tandberg, etc.) */ + #define MTTELL 23 /* tell block (Tandber, etc.) */ /* structure for MTIOCGET - mag tape get status command */ struct mtget { *************** *** 105,113 **** --- 106,123 ---- } + /* structure for MTIOCPOS - mag tape get position command */ + + struct mtpos { + long mt_blkno; /* current block number */ + }; + + /* mag tape io control commands */ #define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */ #define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */ + #define MTIOCPOS _IOR('m', 3, struct mtpos) /* get tape position */ + /* Generic Mag Tape (device independent) status macros for examining * mt_gstat -- HP-UX compatible. *** linux/kernel/blk_drv/scsi/Makefile Wed Dec 2 14:56:18 1992 --- ../linux/kernel/blk_drv/scsi/Makefile Sun Dec 6 20:12:33 1992 *************** *** 82,87 **** --- 82,90 ---- figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c $(HOSTCC) -I$(KERNELHDRS) -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure + makefilter : makefilter.c + $(HOSTCC) -o makefilter makefilter.c + max_hosts.h : figure (echo "#ifndef _MAX_HOSTS_H"; echo "#define _MAX_HOSTS_H"; echo "#define MAX_SCSI_HOSTS `./figure`"; echo "#endif") > tmp_max *** linux/kernel/blk_drv/scsi/Makefile.in Sun Dec 6 19:21:24 1992 --- ../linux/kernel/blk_drv/scsi/Makefile.in Sun Dec 6 20:12:33 1992 *************** *** 80,85 **** --- 80,88 ---- figure : hosts.h $(KERNELHDRS)/linux/config.h hosts.c $(HOSTCC) -I$(KERNELHDRS) -DFIGURE_MAX_SCSI_HOSTS hosts.c -o figure + makefilter : makefilter.c + $(HOSTCC) -o makefilter makefilter.c + max_hosts.h : figure (echo "#ifndef _MAX_HOSTS_H"; \ echo "#define _MAX_HOSTS_H"; \ *** linux/kernel/blk_drv/scsi/makefilter.c Sun Dec 6 19:21:24 1992 --- ../linux/kernel/blk_drv/scsi/makefilter.c Sun Dec 6 20:12:33 1992 *************** *** 8,14 **** char buffer[16384]; ! main(){ int flag, cnt; while(!feof(stdin)){ fgets(buffer, sizeof(buffer), stdin); --- 8,14 ---- char buffer[16384]; ! int main(){ int flag, cnt; while(!feof(stdin)){ fgets(buffer, sizeof(buffer), stdin); *************** *** 22,25 **** --- 22,26 ---- if(feof(stdin)) break; fputs(buffer, stdout); }; + return 0; } *** linux/kernel/blk_drv/scsi/scsi.c Sat Nov 28 10:43:57 1992 --- ../linux/kernel/blk_drv/scsi/scsi.c Sun Dec 6 19:17:41 1992 *************** *** 104,109 **** --- 104,110 ---- char * revision; /* Latest revision known to be bad. Not used yet */ }; + #if 0 static struct blist blacklist[] = {{"TANDBERG","TDC 3600","U07"}, /* Locks up if polled for lun != 0 */ {"SEAGATE","ST296","921"}, /* Responds to all lun */ *************** *** 121,126 **** --- 122,128 ---- return 1; }; }; + #endif /* * As the actual SCSI command runs in the background, we must set up a *************** *** 291,296 **** --- 293,305 ---- break; }; + scsi_devices[NR_SCSI_DEVICES].scsi_level = + scsi_result[2] & 0x07; + if (scsi_devices[NR_SCSI_DEVICES].scsi_level >= 2 || + (scsi_devices[NR_SCSI_DEVICES].scsi_level == 1 && + (scsi_result[3] & 0x0f) == 1)) + scsi_devices[NR_SCSI_DEVICES].scsi_level++; + /* These devices need this "key" to unlock the device so we can use it */ if(strncmp("INSITE", &scsi_result[8], 6) == 0 && *************** *** 313,322 **** }; ++NR_SCSI_DEVICES; /* Some scsi devices cannot be polled for lun != 0 due to firmware bugs */ if(blacklisted(scsi_result)) break; ! /* Some scsi-1 peripherals do not handle lun != 0. I am assuming that scsi-2 peripherals do better */ if((scsi_result[2] & 0x07) == 1 && --- 322,332 ---- }; ++NR_SCSI_DEVICES; + #if 0 /* Some scsi devices cannot be polled for lun != 0 due to firmware bugs */ if(blacklisted(scsi_result)) break; ! #endif /* Some scsi-1 peripherals do not handle lun != 0. I am assuming that scsi-2 peripherals do better */ if((scsi_result[2] & 0x07) == 1 && *************** *** 836,842 **** #endif status = MAYREDO; ! exit = SUGGEST_RETRY; break; case SUGGEST_ABORT: #ifdef DEBUG --- 846,852 ---- #endif status = MAYREDO; ! exit = DRIVER_SENSE | SUGGEST_RETRY; break; case SUGGEST_ABORT: #ifdef DEBUG *************** *** 844,850 **** #endif status = FINISHED; ! exit = DRIVER_SENSE; break; default: printk ("Internal error %s %s \n", __FILE__, --- 854,860 ---- #endif status = FINISHED; ! exit = DRIVER_SENSE | SUGGEST_ABORT; break; default: printk ("Internal error %s %s \n", __FILE__, *** linux/kernel/blk_drv/scsi/scsi.h Sun Nov 29 17:46:59 1992 --- ../linux/kernel/blk_drv/scsi/scsi.h Sun Dec 6 19:16:25 1992 *************** *** 61,66 **** --- 61,67 ---- #define SEARCH_LOW 0x32 #define SET_LIMITS 0x33 #define PRE_FETCH 0x34 + #define READ_POSITION 0x34 #define SYNCRONIZE_CACHE 0x35 #define LOCK_UNLOCK_CACHE 0x36 #define READ_DEFECT_DATA 0x37 *************** *** 180,191 **** #define DRIVER_TIMEOUT 0x06 #define DRIVER_HARD 0x07 ! #define SUGGEST_RETRY 0x08 ! #define SUGGEST_ABORT 0x09 ! #define SUGGEST_REMAP 0x0a ! #define SUGGEST_DIE 0x0b ! #define DRIVER_SENSE 0x10 #define DRIVER_MASK 0x0f #define SUGGEST_MASK 0xf0 --- 181,192 ---- #define DRIVER_TIMEOUT 0x06 #define DRIVER_HARD 0x07 ! #define SUGGEST_RETRY 0x10 ! #define SUGGEST_ABORT 0x20 ! #define SUGGEST_REMAP 0x30 ! #define SUGGEST_DIE 0x40 ! #define DRIVER_SENSE 0x08 #define DRIVER_MASK 0x0f #define SUGGEST_MASK 0xf0 *************** *** 220,226 **** --- 221,238 ---- #define TYPE_WORM 0x04 /* Treated as ROM by our system */ #define TYPE_ROM 0x05 #define TYPE_NO_LUN 0x7f + /* + SCSI command sets + + */ + + #define SCSI_UNKNOWN 0 + #define SCSI_1 1 + #define SCSI_1_CCS 2 + #define SCSI_2 3 + + /* Every SCSI command starts with a one byte OP-code. The next byte's high three bits are the LUN of the device. Any multi-byte quantities are stored high byte *************** *** 239,244 **** --- 251,257 ---- int access_count; /* Count of open channels/mounts */ struct wait_queue * device_wait; /* Used to wait if device is busy */ char type; + char scsi_level; unsigned writeable:1; unsigned removable:1; unsigned random:1; *** linux/kernel/blk_drv/scsi/scsi_ioctl.c Sun Nov 29 17:45:28 1992 --- ../linux/kernel/blk_drv/scsi/scsi_ioctl.c Sun Dec 6 19:46:19 1992 *************** *** 14,20 **** #define MAX_RETRIES 5 #define MAX_TIMEOUT 200 ! #define MAX_BUF 8192 #define max(a,b) (((a) > (b)) ? (a) : (b)) --- 14,20 ---- #define MAX_RETRIES 5 #define MAX_TIMEOUT 200 ! #define MAX_BUF 4096 #define max(a,b) (((a) > (b)) ? (a) : (b)) *************** *** 51,56 **** --- 51,59 ---- * Note that no more than MAX_BUF data bytes will be transfered. Since * SCSI block device size is 512 bytes, I figured 1K was good. * but (WDE) changed it to 8192 to handle large bad track buffers. + * ERY: I changed this to a dynamic allocation using scsi_malloc - we were + * getting a kernel stack overflow which was crashing the system when we + * were using 8192 bytes. * * This size *does not* include the initial lengths that were passed. * *************** *** 133,144 **** static int ioctl_command(Scsi_Device *dev, void *buffer) { ! char buf[MAX_BUF]; char cmd[10]; char * cmd_in; Scsi_Cmnd * SCpnt; unsigned char opcode; int inlen, outlen, cmdlen, host; int result; if (!buffer) --- 136,148 ---- static int ioctl_command(Scsi_Device *dev, void *buffer) { ! char * buf; char cmd[10]; char * cmd_in; Scsi_Cmnd * SCpnt; unsigned char opcode; int inlen, outlen, cmdlen, host; + int needed; int result; if (!buffer) *************** *** 150,155 **** --- 154,168 ---- cmd_in = (char *) ( ((int *)buffer) + 2); opcode = get_fs_byte(cmd_in); + needed = (inlen > outlen ? inlen : outlen); + if(needed){ + needed = (needed + 511) & ~511; + if (needed > MAX_BUF) needed = MAX_BUF; + buf = scsi_malloc(needed); + if (!buf) return -ENOMEM; + } else + buf = NULL; + memcpy_fromfs ((void *) cmd, cmd_in, cmdlen = COMMAND_SIZE (opcode)); memcpy_fromfs ((void *) buf, (void *) (cmd_in + cmdlen), inlen); host = dev->host_no; *************** *** 172,177 **** --- 185,191 ---- memcpy_tofs ((void *) cmd_in, buf, (outlen > MAX_BUF) ? MAX_BUF : outlen); result = SCpnt->result; SCpnt->request.dev = -1; /* Mark as not busy */ + if (buf) scsi_free(buf, needed); wake_up(&scsi_devices[SCpnt->index].device_wait); return result; #else *** linux/kernel/blk_drv/scsi/sd.c Sun Dec 6 19:21:25 1992 --- ../linux/kernel/blk_drv/scsi/sd.c Fri Dec 4 19:52:00 1992 *************** *** 340,345 **** --- 340,346 ---- if (flag++ == 0) SCpnt = allocate_device(&CURRENT, rscsi_disks[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0); + else SCpnt = NULL; /* This is a performance enhancement. We dig down into the request list and try and find a queueable request (i.e. device not busy, and host able to *** linux/kernel/blk_drv/scsi/sr.c Sun Dec 6 19:21:26 1992 --- ../linux/kernel/blk_drv/scsi/sr.c Fri Dec 4 19:52:18 1992 *************** *** 286,291 **** --- 286,292 ---- if (flag++ == 0) SCpnt = allocate_device(&CURRENT, scsi_CDs[DEVICE_NR(MINOR(CURRENT->dev))].device->index, 0); + else SCpnt = NULL; /* This is a performance enhancement. We dig down into the request list and *** linux/kernel/blk_drv/scsi/st.c Sun Nov 29 20:01:57 1992 --- ../linux/kernel/blk_drv/scsi/st.c Sun Dec 6 19:11:05 1992 *************** *** 16,21 **** --- 16,22 ---- - one buffer if one drive, two buffers if more than one drive (limits the number of simultaneously open drives to two) - write behind + - seek and tell (Tandberg compatible and SCSI-2) Devices: Autorewind devices have minor numbers equal to the tape numbers (0 > ). *************** *** 29,35 **** Kai Makisara, Nov 9, 1992 email makisara@vtinsx.ins.vtt.fi or Kai.Makisara@vtt.fi ! Last changes Nov 29, 1992. */ #include --- 30,36 ---- Kai Makisara, Nov 9, 1992 email makisara@vtinsx.ins.vtt.fi or Kai.Makisara@vtt.fi ! Last changes Dec 6, 1992. */ #include *************** *** 51,59 **** #define MAX_RETRIES 5 #define NO_TAPE NOT_READY /* #define DEBUG */ ! #define ST_TIMEOUT 1000 #define ST_LONG_TIMEOUT 200000 /* Number of ST_BLOCK_SIZE blocks in the buffers */ --- 52,64 ---- #define MAX_RETRIES 5 #define NO_TAPE NOT_READY + /* Uncomment the following if you want the rewind, etc. commands return + before command completion. */ + /* #define ST_NOWAIT */ + /* #define DEBUG */ ! #define ST_TIMEOUT 2000 #define ST_LONG_TIMEOUT 200000 /* Number of ST_BLOCK_SIZE blocks in the buffers */ *************** *** 174,179 **** --- 179,280 ---- #endif + /* Flush the write buffer */ + static int flush_write_buffer(int dev) + { + int offset, transfer, blks; + int result; + unsigned char cmd[10]; + Scsi_Cmnd *SCpnt; + + #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS + if (scsi_tapes[dev].buffer->writing) { + write_behind_check(dev); + if (scsi_tapes[dev].buffer->last_result) { + #ifdef DEBUG + printk("st%d: Async write error %x.\n", dev, + scsi_tapes[dev].buffer->last_result); + #endif + return (-EIO); + } + } + #endif + + result = 0; + if (scsi_tapes[dev].dirty==1) { + SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); + + offset = scsi_tapes[dev].buffer->buffer_bytes; + transfer = ((offset + scsi_tapes[dev].block_size - 1) / + scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size; + #ifdef DEBUG + printk("st%d: Flushing %d bytes.\n", dev, transfer); + #endif + memset(scsi_tapes[dev].buffer->b_data + offset, 0, transfer - offset); + + SCpnt->sense_buffer[0] = 0; + memset(cmd, 0, 10); + cmd[0] = WRITE_6; + cmd[1] = 1; + blks = transfer / scsi_tapes[dev].block_size; + cmd[2] = blks >> 16; + cmd[3] = blks >> 8; + cmd[4] = blks; + SCpnt->request.dev = dev; + scsi_do_cmd (SCpnt, + (void *) cmd, scsi_tapes[dev].buffer->b_data, transfer, + st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + + if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); + + if (SCpnt->result != 0) { + printk("st%d: Error on flush:\n", dev); + #ifdef DEBUG + st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); + #endif + result = (-EIO); + } + else { + scsi_tapes[dev].dirty = 0; + scsi_tapes[dev].buffer->buffer_bytes = 0; + } + SCpnt->request.dev = -1; /* Mark as not busy */ + } + return result; + } + + + /* Flush the tape buffer. The tape will be positioned correctly unless + seek_next is true. */ + static int flush_buffer(struct inode * inode, struct file * filp, + int seek_next) + { + int dev; + int backspace, result; + + dev = inode->i_rdev & 127; + + if (scsi_tapes[dev].rw == 2) /* Writing */ + return flush_write_buffer(dev); + + backspace = (scsi_tapes[dev].buffer->buffer_bytes + + scsi_tapes[dev].buffer->read_pointer) / scsi_tapes[dev].block_size - + (scsi_tapes[dev].buffer->read_pointer + scsi_tapes[dev].block_size - 1) / + scsi_tapes[dev].block_size; + scsi_tapes[dev].buffer->buffer_bytes = 0; + scsi_tapes[dev].buffer->read_pointer = 0; + result = 0; + if (!seek_next && backspace > 0) { + result = st_int_ioctl(inode, filp, MTBSR, backspace); + if (!result) { + scsi_tapes[dev].eof = 0; + scsi_tapes[dev].eof_hit = 0; + } + } + return result; + + } + /* Open the device */ static int scsi_tape_open(struct inode * inode, struct file * filp) *************** *** 240,246 **** SCpnt->request.dev = dev; scsi_do_cmd(SCpnt, (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, ! ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); } --- 341,347 ---- SCpnt->request.dev = dev; scsi_do_cmd(SCpnt, (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, ! ST_BLOCK_SIZE, st_sleep_done, ST_LONG_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); } *************** *** 325,330 **** --- 426,439 ---- 65536 + scsi_tapes[dev].buffer->b_data[10] * 256 + scsi_tapes[dev].buffer->b_data[11]); #endif + if (scsi_tapes[dev].block_size > ST_BUFFER_SIZE) { + printk("st%d: Blocksize %d too large for buffer.\n", dev, + scsi_tapes[dev].block_size); + scsi_tapes[dev].buffer->in_use = 0; + scsi_tapes[dev].in_use = 0; + return (-EIO); + } + if (scsi_tapes[dev].block_size == 0) { printk("st%d: Fixing block size to 512 bytes.\n", dev); if (st_int_ioctl(inode, filp, MTSETBLK, ST_BLOCK_SIZE)) { *************** *** 366,372 **** static void scsi_tape_close(struct inode * inode, struct file * filp) { int dev; ! int offset, transfer, blks, rewind; static unsigned char cmd[10]; Scsi_Cmnd * SCpnt; --- 475,482 ---- static void scsi_tape_close(struct inode * inode, struct file * filp) { int dev; ! int result; ! int rewind; static unsigned char cmd[10]; Scsi_Cmnd * SCpnt; *************** *** 376,456 **** if ( scsi_tapes[dev].rw == 2) { ! #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS ! if (scsi_tapes[dev].buffer->writing) { ! write_behind_check(dev); ! if (scsi_tapes[dev].buffer->last_result) { ! /* What should actually be done here ? */ ! printk("st%d: Async write error %x.\n", dev, ! scsi_tapes[dev].buffer->last_result); ! } ! } ! #endif - SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); - - if (scsi_tapes[dev].dirty==1) { - offset = scsi_tapes[dev].buffer->buffer_bytes; - transfer = ((offset + scsi_tapes[dev].block_size - 1) / - scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size; #ifdef DEBUG ! printk("st%d: Final transfer %d bytes (length %d).\n", dev, ! transfer, filp->f_pos); #endif - memset(scsi_tapes[dev].buffer->b_data + offset, 0, transfer - offset); SCpnt->sense_buffer[0] = 0; memset(cmd, 0, 10); ! cmd[0] = WRITE_6; ! cmd[1] = 1; ! blks = transfer / scsi_tapes[dev].block_size; ! cmd[2] = blks >> 16; ! cmd[3] = blks >> 8; ! cmd[4] = blks; SCpnt->request.dev = dev; ! scsi_do_cmd (SCpnt, ! (void *) cmd, scsi_tapes[dev].buffer->b_data, transfer, ! st_sleep_done, ST_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); ! if (SCpnt->result != 0) { ! printk("st%d: Error on last write:\n", dev); #ifdef DEBUG st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); #endif - SCpnt->request.dev = -1; /* Mark as not busy */ - if (rewind) - st_int_ioctl(inode, filp, MTREW, 1); - scsi_tapes[dev].buffer->in_use = 0; - scsi_tapes[dev].in_use = 0; - return; } - } - - SCpnt->sense_buffer[0] = 0; - memset(cmd, 0, 10); - cmd[0] = WRITE_FILEMARKS; - cmd[4] = 1; - SCpnt->request.dev = dev; - scsi_do_cmd( SCpnt, - (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, ST_BLOCK_SIZE, - st_sleep_done, ST_TIMEOUT, MAX_RETRIES); - - if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); - if (SCpnt->result) { - printk("st%d: Error on write filemark:\n", dev); - #ifdef DEBUG - st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); - #endif SCpnt->request.dev = -1; /* Mark as not busy */ - if (rewind) - st_int_ioctl(inode, filp, MTREW, 1); - scsi_tapes[dev].buffer->in_use = 0; - scsi_tapes[dev].in_use = 0; - return; } - SCpnt->request.dev = -1; /* Mark as not busy */ #ifdef DEBUG printk("st%d: Buffer flushed, EOF written\n", dev); --- 486,519 ---- if ( scsi_tapes[dev].rw == 2) { ! result = flush_write_buffer(dev); #ifdef DEBUG ! printk("st%d: File length %d bytes.\n", dev, filp->f_pos); #endif + if (!result) { + SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); + SCpnt->sense_buffer[0] = 0; memset(cmd, 0, 10); ! cmd[0] = WRITE_FILEMARKS; ! cmd[4] = 1; SCpnt->request.dev = dev; ! scsi_do_cmd( SCpnt, ! (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, ! ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); ! if (SCpnt->result) { ! printk("st%d: Error on write filemark:\n", dev); #ifdef DEBUG st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); #endif } SCpnt->request.dev = -1; /* Mark as not busy */ } #ifdef DEBUG printk("st%d: Buffer flushed, EOF written\n", dev); *************** *** 491,498 **** return (-EACCES); if (scsi_tapes[dev].rw == 1) { ! printk("st%d: No write allowed after read.\n", dev); ! return (-EACCES); } #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS --- 554,563 ---- return (-EACCES); if (scsi_tapes[dev].rw == 1) { ! retval = flush_buffer(inode, filp, 0); ! if (retval) ! return retval; ! scsi_tapes[dev].rw = 2; } #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS *************** *** 625,632 **** #endif if (scsi_tapes[dev].rw == 2) { ! printk("st%d: No read allowed after write.\n", dev); ! return (-EACCES); } #ifdef DEBUG --- 690,699 ---- #endif if (scsi_tapes[dev].rw == 2) { ! transfer = flush_buffer(inode, filp, 0); ! if (transfer) ! return transfer; ! scsi_tapes[dev].rw = 1; } #ifdef DEBUG *************** *** 850,857 **** --- 917,926 ---- break; case MTREW: cmd[0] = REZERO_UNIT; + #ifdef ST_NOWAIT cmd[1] = 1; /* Don't wait for completion */ timeout = ST_TIMEOUT; + #endif #ifdef DEBUG printk("st%d: Rewinding tape.\n", dev); #endif *************** *** 858,865 **** --- 927,936 ---- break; case MTOFFL: cmd[0] = START_STOP; + #ifdef ST_NOWAIT cmd[1] = 1; /* Don't wait for completion */ timeout = ST_TIMEOUT; + #endif #ifdef DEBUG printk("st%d: Unloading tape.\n", dev); #endif *************** *** 872,880 **** break; case MTRETEN: cmd[0] = START_STOP; cmd[1] = 1; /* Don't wait for completion */ - cmd[4] = 3; timeout = ST_TIMEOUT; #ifdef DEBUG printk("st%d: Retensioning tape.\n", dev); #endif --- 943,953 ---- break; case MTRETEN: cmd[0] = START_STOP; + #ifdef ST_NOWAIT cmd[1] = 1; /* Don't wait for completion */ timeout = ST_TIMEOUT; + #endif + cmd[4] = 3; #ifdef DEBUG printk("st%d: Retensioning tape.\n", dev); #endif *************** *** 895,900 **** --- 968,997 ---- printk("st%d: Erasing tape.\n", dev); #endif break; + case MTSEEK: + if (scsi_tapes[dev].device->scsi_level < SCSI_2) { + cmd[0] = QFA_SEEK_BLOCK; + cmd[2] = (arg >> 16); + cmd[3] = (arg >> 8); + cmd[4] = arg; + cmd[5] = 0; + } + else { + cmd[0] = SEEK_10; + cmd[1] = 4; + cmd[3] = (arg >> 24); + cmd[4] = (arg >> 16); + cmd[5] = (arg >> 8); + cmd[6] = arg; + } + #ifdef ST_NOWAIT + cmd[1] |= 1; /* Don't wait for completion */ + timeout = ST_TIMEOUT; + #endif + #ifdef DEBUG + printk("st%d: Seeking tape to block %d.\n", dev, arg); + #endif + break; case MTSETBLK: /* Set block length */ case MTSETDENSITY: /* Set tape density */ if (scsi_tapes[dev].dirty || scsi_tapes[dev].buffer->buffer_bytes != 0) *************** *** 950,957 **** ioctl_result = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); ! if (!ioctl_result && cmd_in == MTBSFM) ! ioctl_result = st_int_ioctl(inode, file, MTFSF, 1); return ioctl_result ; } --- 1047,1073 ---- ioctl_result = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); ! if (!ioctl_result) { ! if (cmd_in == MTBSFM) ! ioctl_result = st_int_ioctl(inode, file, MTFSF, 1); ! else if (cmd_in == MTSETBLK) { ! scsi_tapes[dev].block_size = arg; ! scsi_tapes[dev].buffer->buffer_blocks = ! ST_BUFFER_SIZE / scsi_tapes[dev].block_size; ! scsi_tapes[dev].buffer->buffer_size = ! scsi_tapes[dev].buffer->buffer_blocks * scsi_tapes[dev].block_size; ! scsi_tapes[dev].buffer->buffer_bytes = ! scsi_tapes[dev].buffer->read_pointer = 0; ! } ! if (cmd_in == MTEOM || cmd_in == MTWEOF) { ! scsi_tapes[dev].eof = 2; ! scsi_tapes[dev].eof_hit = 0; ! } ! else if (cmd_in != MTSETBLK && cmd_in != MTNOP) { ! scsi_tapes[dev].eof = 0; ! scsi_tapes[dev].eof_hit = 0; ! } ! } return ioctl_result ; } *************** *** 963,971 **** unsigned int cmd_in, unsigned int arg) { int dev = inode->i_rdev; ! int i, cmd; struct mtop mtc; ! char *stp, *argp; dev = dev & 127; #ifdef DEBUG --- 1079,1089 ---- unsigned int cmd_in, unsigned int arg) { int dev = inode->i_rdev; ! int i, cmd, result; struct mtop mtc; ! struct mtpos mt_pos; ! unsigned char scmd[10]; ! Scsi_Cmnd *SCpnt; dev = dev & 127; #ifdef DEBUG *************** *** 980,992 **** if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc)) return (-EINVAL); verify_area((void *)arg, sizeof(mtc)); ! stp = (char *) &mtc; ! argp = (char *) arg; ! for (i=0; i < sizeof(mtc); i++) ! *stp++ = get_fs_byte(argp++); return st_int_ioctl(inode, file, mtc.mt_op, mtc.mt_count); } else if (cmd == (MTIOCGET & IOCCMD_MASK)) { --- 1098,1114 ---- if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc)) return (-EINVAL); + verify_area((void *)arg, sizeof(mtc)); ! memcpy_fromfs((char *) &mtc, (char *)arg, sizeof(struct mtop)); + i = flush_buffer(inode, file, mtc.mt_op == MTSEEK || + mtc.mt_op == MTREW || mtc.mt_op == MTOFFL || + mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM); + if (i < 0) + return i; + return st_int_ioctl(inode, file, mtc.mt_op, mtc.mt_count); } else if (cmd == (MTIOCGET & IOCCMD_MASK)) { *************** *** 995,1005 **** return (-EINVAL); verify_area((void *)arg, sizeof(struct mtget)); ! stp = (char *) scsi_tapes[dev].buffer->mt_status; ! argp = (char *) arg; ! for (i=0; i < sizeof(struct mtget); i++) ! put_fs_byte(*stp++, argp++); return 0; } else return (-EINVAL); --- 1117,1184 ---- return (-EINVAL); verify_area((void *)arg, sizeof(struct mtget)); ! memcpy_tofs((char *)arg, (char *)scsi_tapes[dev].buffer->mt_status, ! sizeof(struct mtget)); return 0; + } + else if (cmd == (MTIOCPOS & IOCCMD_MASK)) { + #ifdef DEBUG + printk("st%d: get tape position.\n", dev); + #endif + if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtpos)) + return (-EINVAL); + + i = flush_buffer(inode, file, 0); + if (i < 0) + return i; + + verify_area((void *)arg, sizeof(struct mtpos)); + + SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); + + SCpnt->sense_buffer[0]=0; + memset (scmd, 0, 10); + if (scsi_tapes[dev].device->scsi_level < SCSI_2) { + scmd[0] = QFA_REQUEST_BLOCK; + scmd[4] = 3; + } + else { + scmd[0] = READ_POSITION; + scmd[1] = 1; + } + SCpnt->request.dev = dev; + SCpnt->sense_buffer[0] = 0; + scsi_do_cmd(SCpnt, + (void *) scmd, (void *) scsi_tapes[dev].buffer->b_data, + ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); + + if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); + + if (SCpnt->result || SCpnt->sense_buffer[0]) { + mt_pos.mt_blkno = (-1); + #ifdef DEBUG + printk("st%d: Can't read tape position.\n", dev); + #endif + result = (-EIO); + } + else { + result = 0; + if (scsi_tapes[dev].device->scsi_level < SCSI_2) + mt_pos.mt_blkno = (scsi_tapes[dev].buffer->b_data[0] << 16) + + (scsi_tapes[dev].buffer->b_data[1] << 8) + + scsi_tapes[dev].buffer->b_data[2]; + else + mt_pos.mt_blkno = (scsi_tapes[dev].buffer->b_data[4] << 24) + + (scsi_tapes[dev].buffer->b_data[5] << 16) + + (scsi_tapes[dev].buffer->b_data[6] << 8) + + scsi_tapes[dev].buffer->b_data[7]; + + } + + SCpnt->request.dev = -1; /* Mark as not busy */ + + memcpy_tofs((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos)); + return result; } else return (-EINVAL); *** linux/kernel/blk_drv/scsi/st.h Thu Nov 12 12:01:31 1992 --- ../linux/kernel/blk_drv/scsi/st.h Sun Dec 6 19:11:05 1992 *************** *** 39,43 **** --- 39,47 ---- } Scsi_Tape; + /* Positioning SCSI-commands for Tandberg, etc. drives */ + #define QFA_REQUEST_BLOCK 0x02 + #define QFA_SEEK_BLOCK 0x0c + #endif