?? st.c
字號:
printk( "st%d: Density %x, tape length: %x, blocksize: %d, drv buffer: %d\n", dev, STp->density, (STp->buffer)->b_data[5] * 65536 + (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7], STp->block_size, STp->drv_buffer);#endif if (STp->block_size > ST_BUFFER_SIZE) { printk("st%d: Blocksize %d too large for buffer.\n", dev, STp->block_size); (STp->buffer)->in_use = 0; STp->in_use = 0; return (-EIO); } } else STp->block_size = ST_BLOCK_SIZE; if (STp->block_size > 0) { (STp->buffer)->buffer_blocks = ST_BUFFER_SIZE / STp->block_size; (STp->buffer)->buffer_size = (STp->buffer)->buffer_blocks * STp->block_size; } else { (STp->buffer)->buffer_blocks = 1; (STp->buffer)->buffer_size = ST_BUFFER_SIZE; } (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;#ifdef DEBUG printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev, STp->block_size, (STp->buffer)->buffer_size, (STp->buffer)->buffer_blocks);#endif if ((STp->buffer)->b_data[2] & 0x80) { STp->write_prot = 1;#ifdef DEBUG printk( "st%d: Write protected\n", dev);#endif } return 0;}/* Close the device*/ static voidscsi_tape_close(struct inode * inode, struct file * filp){ int dev; int result; int rewind; static unsigned char cmd[10]; Scsi_Cmnd * SCpnt; Scsi_Tape * STp; dev = MINOR(inode->i_rdev); rewind = (dev & 0x80) == 0; dev = dev & 127; STp = &(scsi_tapes[dev]); if ( STp->rw == ST_WRITING) { result = flush_write_buffer(dev);#ifdef DEBUG printk("st%d: File length %d bytes.\n", dev, filp->f_pos);#endif if (result == 0 || result == (-ENOSPC)) { SCpnt = allocate_device(NULL, (STp->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 *) (STp->buffer)->b_data, ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) ); if ((STp->buffer)->last_result_fatal != 0) printk("st%d: Error on write filemark.\n", dev); SCpnt->request.dev = -1; /* Mark as not busy */ }#ifdef DEBUG printk("st%d: Buffer flushed, EOF written\n", dev);#endif } else if (!rewind) {#ifndef ST_IN_FILE_POS if ((STp->eof == ST_FM) && !STp->eof_hit) st_int_ioctl(inode, filp, MTBSF, 1); /* Back over the EOF hit */#else flush_buffer(inode, filp, 0);#endif } if (rewind) st_int_ioctl(inode, filp, MTREW, 1); (STp->buffer)->in_use = 0; STp->in_use = 0; return;}/* Write command */ static intst_write(struct inode * inode, struct file * filp, char * buf, int count){ int dev; int total, do_count, blks, retval, transfer; int write_threshold; static unsigned char cmd[10]; char *b_point; Scsi_Cmnd * SCpnt; Scsi_Tape * STp; dev = MINOR(inode->i_rdev) & 127; STp = &(scsi_tapes[dev]);#ifdef DEBUG if (!STp->in_use) { printk("st%d: Incorrect device.\n", dev); return (-EIO); }#endif if (STp->write_prot) return (-EACCES); if (STp->block_size == 0 && count > ST_BUFFER_SIZE) return (-EOVERFLOW); if (STp->rw == ST_READING) { retval = flush_buffer(inode, filp, 0); if (retval) return retval; STp->rw = ST_WRITING; }#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS if ((STp->buffer)->writing) { write_behind_check(dev); if ((STp->buffer)->last_result_fatal) {#ifdef DEBUG printk("st%d: Async write error %x.\n", dev, (STp->buffer)->last_result);#endif if ((STp->buffer)->last_result == INT_MAX) { retval = (-ENOSPC); /* All has been written */ STp->eof = ST_EOM_OK; } else retval = (-EIO); return retval; } }#endif if (STp->eof == ST_EOM_OK) return (-ENOSPC); else if (STp->eof == ST_EOM_ERROR) return (-EIO);#ifdef ST_NO_DELAYED_WRITES if (STp->block_size != 0 && (count % STp->block_size) != 0) return (-EIO); /* Write must be integral number of blocks */ write_threshold = 1;#else write_threshold = (STp->buffer)->buffer_size;#endif SCpnt = allocate_device(NULL, (STp->device)->index, 1); total = count; memset(cmd, 0, 10); cmd[0] = WRITE_6; cmd[1] = (STp->block_size != 0); STp->rw = ST_WRITING; b_point = buf; while(#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS STp->block_size != 0 && ((STp->buffer)->buffer_bytes + count) > write_threshold)#else (STp->block_size == 0 && count > 0) || ((STp->buffer)->buffer_bytes + count) >= write_threshold)#endif { if (STp->block_size == 0) do_count = count; else { do_count = (STp->buffer)->buffer_size - (STp->buffer)->buffer_bytes; if (do_count > count) do_count = count; } memcpy_fromfs((STp->buffer)->b_data + (STp->buffer)->buffer_bytes, b_point, do_count); if (STp->block_size == 0) blks = do_count; else blks = ((STp->buffer)->buffer_bytes + do_count) / STp->block_size; 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, (STp->buffer)->b_data, (STp->buffer)->buffer_size, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) ); if ((STp->buffer)->last_result_fatal != 0) {#ifdef DEBUG printk("st%d: Error on write:\n", dev);#endif if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 && (SCpnt->sense_buffer[2] & 0x40)) { if (STp->block_size != 0 && (SCpnt->sense_buffer[0] & 0x80) != 0) transfer = (SCpnt->sense_buffer[3] << 24) | (SCpnt->sense_buffer[4] << 16) | (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6]; else if (STp->block_size == 0 && (SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW) transfer = do_count; else transfer = 0; if (STp->block_size != 0) transfer *= STp->block_size; if (transfer <= do_count) { filp->f_pos += do_count - transfer; count -= do_count - transfer; STp->eof = ST_EOM_OK; retval = (-ENOSPC); /* EOM within current request */#ifdef DEBUG printk("st%d: EOM with %d bytes unwritten.\n", dev, transfer);#endif } else { STp->eof = ST_EOM_ERROR; retval = (-EIO); /* EOM for old data */#ifdef DEBUG printk("st%d: EOM with lost data.\n", dev);#endif } } else retval = (-EIO); SCpnt->request.dev = -1; /* Mark as not busy */ (STp->buffer)->buffer_bytes = 0; STp->dirty = 0; if (count < total) return total - count; else return retval; } filp->f_pos += do_count; b_point += do_count; count -= do_count; (STp->buffer)->buffer_bytes = 0; STp->dirty = 0; } if (count != 0) { STp->dirty = 1; memcpy_fromfs((STp->buffer)->b_data + (STp->buffer)->buffer_bytes,b_point,count); filp->f_pos += count; (STp->buffer)->buffer_bytes += count; count = 0; } if ((STp->buffer)->last_result_fatal != 0) { SCpnt->request.dev = -1; return (STp->buffer)->last_result_fatal; }#if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS if ((STp->buffer)->buffer_bytes >= ST_WRITE_THRESHOLD || STp->block_size == 0) { /* Schedule an asynchronous write */ if (STp->block_size == 0) (STp->buffer)->writing = (STp->buffer)->buffer_bytes; else (STp->buffer)->writing = ((STp->buffer)->buffer_bytes / STp->block_size) * STp->block_size; STp->dirty = 0; if (STp->block_size == 0) blks = (STp->buffer)->writing; else blks = (STp->buffer)->writing / STp->block_size; cmd[2] = blks >> 16; cmd[3] = blks >> 8; cmd[4] = blks; SCpnt->result = (STp->buffer)->last_result = -1; SCpnt->sense_buffer[0] = 0; SCpnt->request.dev = dev; scsi_do_cmd (SCpnt, (void *) cmd, (STp->buffer)->b_data, (STp->buffer)->writing, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); } else#endif SCpnt->request.dev = -1; /* Mark as not busy */ return( total);} /* Read command */ static intst_read(struct inode * inode, struct file * filp, char * buf, int count){ int dev; int total; int transfer, blks, bytes; static unsigned char cmd[10]; Scsi_Cmnd * SCpnt; Scsi_Tape * STp; dev = MINOR(inode->i_rdev) & 127; STp = &(scsi_tapes[dev]);#ifdef DEBUG if (!STp->in_use) { printk("st%d: Incorrect device.\n", dev); return (-EIO); }#endif if (STp->block_size == 0 && count > ST_BUFFER_SIZE) return (-EOVERFLOW); if (STp->rw == ST_WRITING) { transfer = flush_buffer(inode, filp, 0); if (transfer) return transfer; STp->rw = ST_READING; }#ifdef DEBUG if (STp->eof != ST_NOEOF) printk("st%d: EOF flag up. Bytes %d\n", dev, (STp->buffer)->buffer_bytes);#endif if (((STp->buffer)->buffer_bytes == 0) && STp->eof == ST_EOM_OK) /* EOM or Blank Check */ return (-EIO); STp->rw = ST_READING; SCpnt = allocate_device(NULL, (STp->device)->index, 1); for (total = 0; total < count; ) { if ((STp->buffer)->buffer_bytes == 0 && STp->eof == ST_NOEOF) { memset(cmd, 0, 10); cmd[0] = READ_6; cmd[1] = (STp->block_size != 0); if (STp->block_size == 0) blks = bytes = count; else { blks = (STp->buffer)->buffer_blocks; bytes = blks * STp->block_size; } 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, (STp->buffer)->b_data, (STp->buffer)->buffer_size, st_sleep_done, ST_TIMEOUT, MAX_RETRIES); if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) ); (STp->buffer)->read_pointer = 0; STp->eof_hit = 0; if ((STp->buffer)->last_result_fatal) {#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 */ if ((SCpnt->sense_buffer[0] & 0x80) != 0) transfer = (SCpnt->sense_buffer[3] << 24) | (SCpnt->sense_buffer[4] << 16) | (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6]; else transfer = 0; if (STp->block_size == 0 && (SCpnt->sense_buffer[2] & 0x0f) == MEDIUM_ERROR) transfer = bytes; if (SCpnt->sense_buffer[2] & 0x20) { if (STp->block_size == 0) { if (transfer <= 0) transfer = 0; (STp->buffer)->buffer_bytes = count - transfer; } else { 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) { STp->eof = ST_EOM_OK; if (STp->block_size == 0) (STp->buffer)->buffer_bytes = count - transfer; else (STp->buffer)->buffer_bytes = ((STp->buffer)->buffer_blocks - transfer) * STp->block_size;#ifdef DEBUG printk("st%d: EOM detected (%d bytes read).\n", dev, (STp->buffer)->buffer_bytes);#endif } else if (SCpnt->sense_buffer[2] & 0x80) { STp->eof = ST_FM; if (STp->block_size == 0) (STp->buffer)->buffer_bytes = 0; else (STp->buffer)->buffer_bytes = ((STp->buffer)->buffer_blocks - transfer) * STp->block_size;#ifdef DEBUG printk( "st%d: EOF detected (%d bytes read, transferred %d bytes).\n", dev, (STp->buffer)->buffer_bytes, total);#endif } /* end of EOF, EOM, ILI test */ } else { /* nonzero sense key */#ifdef DEBUG printk("st%d: Tape error while reading.\n", dev);#endif SCpnt->request.dev = -1; if (total) return total; else return -EIO; } } else { transfer = (STp->buffer)->last_result_fatal; SCpnt->request.dev = -1; /* Mark as not busy */ return transfer; } } else /* Read successful */ (STp->buffer)->buffer_bytes = bytes; } /* if ((STp->buffer)->buffer_bytes == 0 && STp->eof == ST_NOEOF) */ if ((STp->buffer)->buffer_bytes > 0) {#ifdef DEBUG if (STp->eof != ST_NOEOF) printk("st%d: EOF up. Left %d, needed %d.\n", dev, (STp->buffer)->buffer_bytes, count - total);#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -