📄 st.c
字号:
scsi_tapes[dev].buffer->b_data[10] * 256 + scsi_tapes[dev].buffer->b_data[11];#ifdef DEBUG printk("st%d: Density %x, tape length: %x, blocksize: %d\n", dev, scsi_tapes[dev].buffer->b_data[4], scsi_tapes[dev].buffer->b_data[5] * 65536 + scsi_tapes[dev].buffer->b_data[6] * 256 + scsi_tapes[dev].buffer->b_data[7], scsi_tapes[dev].buffer->b_data[9] * 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)) { printk("st%d: Can't set fixed block size.\n", dev); scsi_tapes[dev].buffer->in_use = 0; scsi_tapes[dev].in_use = 0; return (-EIO); } scsi_tapes[dev].block_size = ST_BLOCK_SIZE; } } else scsi_tapes[dev].block_size = ST_BLOCK_SIZE; 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;#ifdef DEBUG printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev, scsi_tapes[dev].block_size, scsi_tapes[dev].buffer->buffer_size, scsi_tapes[dev].buffer->buffer_blocks);#endif if (scsi_tapes[dev].buffer->b_data[2] & 0x80) { scsi_tapes[dev].write_prot = 1;#ifdef DEBUG printk( "st%d: Write protected\n", dev);#endif } return 0;}/* Close the device*/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; dev = inode->i_rdev; rewind = (dev & 0x80) == 0; dev = dev & 127; 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);#endif } else if (!rewind && scsi_tapes[dev].eof && !scsi_tapes[dev].eof_hit) st_int_ioctl(inode, filp, MTBSF, 1); /* Back over the EOF hit inadvertently */ if (rewind) st_int_ioctl(inode, filp, MTREW, 1); scsi_tapes[dev].buffer->in_use = 0; scsi_tapes[dev].in_use = 0; return;}/* Write command */int st_write(struct inode * inode, struct file * filp, char * buf, int count){ int dev; int total, do_count, blks, retval; static unsigned char cmd[10]; char *b_point; Scsi_Cmnd * SCpnt; dev = inode->i_rdev & 127;#ifdef DEBUG if (!scsi_tapes[dev].in_use) { printk("st%d: Incorrect device.\n", dev); return (-EIO); }#endif if (scsi_tapes[dev].write_prot) 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 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 /*if (scsi_tapes[dev].buffer->last_result = 0x7fffffff) retval = (-ENOSPC); else */ retval = (-EIO); return retval; } }#endif SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); total = count; memset(cmd, 0, 10); cmd[0] = WRITE_6; cmd[1] = 1; scsi_tapes[dev].rw = 2; b_point = buf; while((scsi_tapes[dev].buffer->buffer_bytes + count) >= scsi_tapes[dev].buffer->buffer_size) { do_count = scsi_tapes[dev].buffer->buffer_size - scsi_tapes[dev].buffer->buffer_bytes; memcpy_fromfs(scsi_tapes[dev].buffer->b_data + scsi_tapes[dev].buffer->buffer_bytes,b_point,do_count); blks = scsi_tapes[dev].buffer->buffer_blocks; cmd[2] = blks >> 16; cmd[3] = blks >> 8; cmd[4] = blks; SCpnt->sense_buffer[0] = 0; SCpnt->request.dev = dev; scsi_do_cmd (SCpnt, (void *) cmd, scsi_tapes[dev].buffer->b_data, scsi_tapes[dev].buffer->buffer_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] != 0) {#ifdef DEBUG printk("st%d: Error on write:\n", dev); st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);#endif if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 && (SCpnt->sense_buffer[2] & 0x40)) retval = (-ENOSPC); /* EOM */ else retval = (-EIO); SCpnt->request.dev = -1; /* Mark as not busy */ if (count < total) return total - count; else return retval; } filp->f_pos += do_count; b_point += do_count; count -= do_count; scsi_tapes[dev].buffer->buffer_bytes = 0; scsi_tapes[dev].dirty = 0; } if (count != 0) { scsi_tapes[dev].dirty = 1; memcpy_fromfs(scsi_tapes[dev].buffer->b_data + scsi_tapes[dev].buffer->buffer_bytes,b_point,count); filp->f_pos += count; scsi_tapes[dev].buffer->buffer_bytes += count; count = 0; } do_count = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); if (do_count) { SCpnt->request.dev = -1; return do_count; }#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS if (scsi_tapes[dev].buffer->buffer_bytes >= ST_WRITE_THRESHOLD) { /* Schedule an asynchronous write */ scsi_tapes[dev].buffer->writing = (scsi_tapes[dev].buffer->buffer_bytes / scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size; scsi_tapes[dev].dirty = 0; blks = scsi_tapes[dev].buffer->writing / scsi_tapes[dev].block_size; cmd[2] = blks >> 16; cmd[3] = blks >> 8; cmd[4] = blks; SCpnt->result = scsi_tapes[dev].buffer->last_result = -1; SCpnt->sense_buffer[0] = 0; SCpnt->request.dev = dev; scsi_do_cmd (SCpnt, (void *) cmd, scsi_tapes[dev].buffer->b_data, scsi_tapes[dev].buffer->writing, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); } else#endif SCpnt->request.dev = -1; /* Mark as not busy */ return( total);} /* Read command */int st_read(struct inode * inode, struct file * filp, char * buf, int count){ int dev; int total; int transfer, blks; static unsigned char cmd[10]; Scsi_Cmnd * SCpnt; dev = inode->i_rdev & 127;#ifdef DEBUG if (!scsi_tapes[dev].in_use) { printk("st%d: Incorrect device.\n", dev); return (-EIO); }#endif if (scsi_tapes[dev].rw == 2) { transfer = flush_buffer(inode, filp, 0); if (transfer) return transfer; scsi_tapes[dev].rw = 1; }#ifdef DEBUG if (scsi_tapes[dev].eof) printk("st%d: EOF flag up. Bytes %d\n", dev, scsi_tapes[dev].buffer->buffer_bytes);#endif if ((scsi_tapes[dev].buffer->buffer_bytes == 0) && scsi_tapes[dev].eof) { if (scsi_tapes[dev].eof == 1) return 0; else /* EOM or blank check */ return (-EIO); } scsi_tapes[dev].rw = 1; SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1); for (total = 0; total < count; ) { if (scsi_tapes[dev].buffer->buffer_bytes == 0 && scsi_tapes[dev].eof == 0) { memset(cmd, 0, 10); cmd[0] = READ_6; cmd[1] = 1; blks = scsi_tapes[dev].buffer->buffer_blocks; cmd[2] = blks >> 16; cmd[3] = blks >> 8; cmd[4] = blks; SCpnt->sense_buffer[0] = 0; SCpnt->request.dev = dev; scsi_do_cmd (SCpnt, (void *) cmd, scsi_tapes[dev].buffer->b_data, scsi_tapes[dev].buffer->buffer_size, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting ); scsi_tapes[dev].buffer->read_pointer = 0; if (SCpnt->result != 0 || SCpnt->sense_buffer[0] != 0) {#ifdef DEBUG printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev, SCpnt->sense_buffer[0], SCpnt->sense_buffer[1], SCpnt->sense_buffer[2], SCpnt->sense_buffer[3], SCpnt->sense_buffer[4], SCpnt->sense_buffer[5], SCpnt->sense_buffer[6], SCpnt->sense_buffer[7]);#endif if ((SCpnt->sense_buffer[0] & 0x70) == 0x70) { /* extended sense */ if ((SCpnt->sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */ transfer = (SCpnt->sense_buffer[3] << 24) | (SCpnt->sense_buffer[4] << 16) | (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6]; if (SCpnt->sense_buffer[2] & 0x20) { printk("st%d: Incorrect block size.\n", dev); SCpnt->request.dev = -1; /* Mark as not busy */ return (-EIO); } else if (SCpnt->sense_buffer[2] & 0x40) { scsi_tapes[dev].eof = 2; /* What should be done at EOM ? */ scsi_tapes[dev].buffer->buffer_bytes = (scsi_tapes[dev].buffer->buffer_blocks - transfer) * scsi_tapes[dev].block_size;#ifdef DEBUG printk("st%d: EOM detected (%d blocks read).\n", dev, scsi_tapes[dev].buffer->buffer_blocks - transfer);#endif } else if (SCpnt->sense_buffer[2] & 0x80) { scsi_tapes[dev].eof = 1; scsi_tapes[dev].buffer->buffer_bytes = (scsi_tapes[dev].buffer->buffer_blocks - transfer) * scsi_tapes[dev].block_size;#ifdef DEBUG printk("st%d: EOF detected (%d blocks read, transferred %d bytes).\n", dev, scsi_tapes[dev].buffer->buffer_blocks - transfer, total);#endif } /* end of EOF, EOM, ILI test */ } else { /* nonzero sense key */#ifdef DEBUG printk("st%d: Tape error. Sense key %x\n", dev, SCpnt->sense_buffer[2] & 0x0f); decode_sns(dev, SCpnt->sense_buffer);#endif SCpnt->request.dev = -1; if (total) return total; else return -EIO; } } else { transfer = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer); SCpnt->request.dev = -1; /* Mark as not busy */ return transfer; } } else scsi_tapes[dev].buffer->buffer_bytes = scsi_tapes[dev].buffer->buffer_size; } /* if (SCpnt->result != 0 || SCpnt->sense_buffer[0] != 0) */ if (scsi_tapes[dev].buffer->buffer_bytes > 0) {#ifdef DEBUG if (scsi_tapes[dev].eof) printk("st%d: EOF up. Left %d, needed %d.\n", dev, scsi_tapes[dev].buffer->buffer_bytes, count - total);#endif transfer = scsi_tapes[dev].buffer->buffer_bytes < count - total ? scsi_tapes[dev].buffer->buffer_bytes : count - total; memcpy_tofs(buf, scsi_tapes[dev].buffer->b_data + scsi_tapes[dev].buffer->read_pointer,transfer); filp->f_pos += transfer; buf += transfer; total += transfer; scsi_tapes[dev].buffer->buffer_bytes -= transfer; scsi_tapes[dev].buffer->read_pointer += transfer; } else if (scsi_tapes[dev].eof) { scsi_tapes[dev].eof_hit = 1; SCpnt->request.dev = -1; /* Mark as not busy */ if (total) return total; else return (-EIO); } } /* for (total = 0; total < count; ) */ SCpnt->request.dev = -1; /* Mark as not busy */ return total;}/* Internal ioctl function */static int st_int_ioctl(struct inode * inode,struct file * file, unsigned int cmd_in, unsigned int arg){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -