📄 osst.c
字号:
return;}/* Onstream specific Routines *//* * Initialize the OnStream AUX */static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int logical_blk_num){ os_aux_t *aux = STp->buffer->aux; os_partition_t *par = &aux->partition; os_dat_t *dat = &aux->dat; if (STp->raw) return; memset(aux, 0, sizeof(*aux)); aux->format_id = htonl(0); memcpy(aux->application_sig, "LIN4", 4); aux->hdwr = htonl(0); aux->frame_type = frame_type; switch (frame_type) { case OS_FRAME_TYPE_HEADER: aux->update_frame_cntr = htonl(STp->update_frame_cntr); par->partition_num = OS_CONFIG_PARTITION; par->par_desc_ver = OS_PARTITION_VERSION; par->wrt_pass_cntr = htons(0xffff); /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */ par->first_frame_ppos = htonl(0); par->last_frame_ppos = htonl(0xbb7); aux->frame_seq_num = htonl(0); aux->logical_blk_num_high = htonl(0); aux->logical_blk_num = htonl(0); aux->next_mark_ppos = htonl(STp->first_mark_ppos); break; case OS_FRAME_TYPE_DATA: case OS_FRAME_TYPE_MARKER: dat->dat_sz = 8; dat->reserved1 = 0; dat->entry_cnt = 1; dat->reserved3 = 0; dat->dat_list[0].blk_sz = htonl(frame_type==OS_FRAME_TYPE_DATA?STp->block_size:0); dat->dat_list[0].blk_cnt = htons(1); dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA; dat->dat_list[0].reserved = 0; case OS_FRAME_TYPE_EOD: aux->update_frame_cntr = htonl(0); par->partition_num = OS_DATA_PARTITION; par->par_desc_ver = OS_PARTITION_VERSION; par->wrt_pass_cntr = htons(STp->wrt_pass_cntr); par->first_frame_ppos = htonl(STp->first_data_ppos); par->last_frame_ppos = htonl(STp->capacity); aux->frame_seq_num = htonl(logical_blk_num); aux->logical_blk_num_high = htonl(0); aux->logical_blk_num = htonl(logical_blk_num); break; default: ; /* probably FILL */ } aux->filemark_cnt = ntohl(STp->filemark_cnt); /* FIXME -- violates ADR spec */ aux->phys_fm = ntohl(0xffffffff); aux->last_mark_ppos = ntohl(STp->last_mark_ppos);}/* * Verify that we have the correct tape frame */static int osst_verify_frame(OS_Scsi_Tape * STp, int logical_blk_num, int quiet){ os_aux_t * aux = STp->buffer->aux; os_partition_t * par = &(aux->partition); ST_partstat * STps = &(STp->ps[STp->partition]); int i; int dev = TAPE_NR(STp->devt); if (STp->raw) { if (STp->buffer->syscall_result) { for (i=0; i < STp->buffer->sg_segs; i++) memset(STp->buffer->sg[i].address, 0, STp->buffer->sg[i].length); strcpy(STp->buffer->b_data, "READ ERROR ON FRAME"); } return 1; } if (STp->buffer->syscall_result) { printk(KERN_INFO "osst%d: Skipping frame, read error\n", dev); return 0; } if (ntohl(aux->format_id) != 0) { printk(KERN_INFO "osst%d: Skipping frame, format_id %u\n", dev, ntohl(aux->format_id)); return 0; } if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 && (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) { printk(KERN_INFO "osst%d: Skipping frame, incorrect application signature\n", dev); return 0; } if (par->partition_num != OS_DATA_PARTITION) { if (!STp->linux_media || STp->linux_media_version != 2) { printk(KERN_INFO "osst%d: Skipping frame, partition num %d\n", dev, par->partition_num); return 0; } } if (par->par_desc_ver != OS_PARTITION_VERSION) { printk(KERN_INFO "osst%d: Skipping frame, partition version %d\n", dev, par->par_desc_ver); return 0; } if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) { printk(KERN_INFO "osst%d: Skipping frame, wrt_pass_cntr %d (expected %d)\n", dev, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr); return 0; } if (aux->frame_seq_num != aux->logical_blk_num) { printk(KERN_INFO "osst%d: Skipping frame, seq != logical\n", dev); return 0; } if (aux->frame_type != OS_FRAME_TYPE_DATA && aux->frame_type != OS_FRAME_TYPE_EOD && aux->frame_type != OS_FRAME_TYPE_MARKER) { if (!quiet) printk(KERN_INFO "osst%d: Skipping frame, frame type %x\n", dev, aux->frame_type); return 0; } if (aux->frame_type == OS_FRAME_TYPE_EOD && STp->first_frame_position < STp->eod_frame_ppos) { printk(KERN_INFO "osst%d: Skipping premature EOD frame %d\n", dev, STp->first_frame_position); return 0; } STp->logical_blk_in_buffer = 1; if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) { if (!quiet) printk(KERN_INFO "osst%d: Skipping frame, logical_blk_num %u (expected %d)\n", dev, ntohl(aux->logical_blk_num), logical_blk_num); return 0; } if (aux->frame_type == OS_FRAME_TYPE_MARKER) { STps->eof = ST_FM_HIT; i = ntohl(aux->filemark_cnt); if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt || STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {#if 1 //DEBUG printk(OSST_DEB_MSG "osst%i: %s filemark %d at frame %d\n", dev, STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected", i, STp->first_frame_position - 1);#endif STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1); if (i >= STp->filemark_cnt) STp->filemark_cnt = i+1; } } if (aux->frame_type == OS_FRAME_TYPE_EOD) { STps->eof = ST_EOD_1; } if (aux->frame_type == OS_FRAME_TYPE_DATA) { STps->eof = ST_NOEOF; } return 1;}/* * Wait for the unit to become Ready */static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout){ unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; long startwait = jiffies;#if DEBUG int dbg = debugging; int dev = TAPE_NR(STp->devt); printk(OSST_DEB_MSG "osst%d: Reached onstream wait ready\n", dev);#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE); *aSRpnt = SRpnt; if (!SRpnt) return (-EBUSY); while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) && SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 && (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) {#if DEBUG if (debugging) { printk(OSST_DEB_MSG "osst%d: Sleeping in onstream wait ready\n", dev); printk(OSST_DEB_MSG "osst%d: Turning off debugging for a while\n", dev); debugging = 0; }#endif current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ / 10); memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = TEST_UNIT_READY; SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE); } *aSRpnt = SRpnt;#if DEBUG debugging = dbg;#endif if ( STp->buffer->syscall_result && osst_write_error_recovery(STp, aSRpnt, 0) ) {#if DEBUG printk(OSST_DEB_MSG "osst%d: Abnormal exit from onstream wait ready\n", dev);printk(OSST_DEB_MSG "osst%d: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev,STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);#endif return (-EIO); }#if DEBUG printk(OSST_DEB_MSG "osst%d: Normal exit from onstream wait ready\n", dev);#endif return 0;}static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame){ int retval; osst_wait_ready(STp, aSRpnt, 15 * 60); /* TODO - can this catch a write error? */ retval = osst_set_frame_position(STp, aSRpnt, frame, 0); if (retval) return (retval); osst_wait_ready(STp, aSRpnt, 15 * 60); return (osst_get_frame_position(STp, aSRpnt));}/* * Wait for write(s) to complete */static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt){ unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; int result = 0;#if DEBUG int dev = TAPE_NR(STp->devt); printk(OSST_DEB_MSG "osst%d: Reached onstream flush drive buffer (write filemark)\n", dev);#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_FILEMARKS; cmd[1] = 1; SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE); *aSRpnt = SRpnt; if (!SRpnt) return (-EBUSY); if ((STp->buffer)->syscall_result) result = osst_write_error_recovery(STp, aSRpnt, 0); result |= osst_wait_ready(STp, aSRpnt, 5 * 60); STp->ps[STp->partition].rw = ST_IDLE; return (result);}#define OSST_POLL_PER_SEC 10static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to){ long startwait = jiffies; int dev = TAPE_NR(STp->devt);#if DEBUG char notyetprinted = 1;#endif if ((minlast >= 0 && STp->ps[STp->partition].rw != ST_READING) || (minlast < 0 && STp->ps[STp->partition].rw != ST_WRITING) ) printk(KERN_ERR "osst%i: waiting for frame without having initialized %s!\n", dev, minlast<0?"write":"read"); while (time_before (jiffies, startwait + to*HZ)) { int result; result = osst_get_frame_position (STp, aSRpnt); if (result == -EIO) if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0) return 0; /* successfull recovery leaves drive ready for frame */ if (result < 0) break; if (STp->first_frame_position == curr && ((minlast < 0 && (signed)STp->last_frame_position > (signed)curr + minlast) || (minlast >= 0 && STp->cur_frames > minlast) ) && result >= 0) {#if DEBUG if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC) printk (OSST_DEB_MSG "osst%i: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n", dev, curr, curr+minlast, STp->first_frame_position, STp->last_frame_position, STp->cur_frames, result, (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);#endif return 0; }#if DEBUG if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted) { printk (OSST_DEB_MSG "osst%i: Wait for frame %i (>%i): %i-%i %i (%i)\n", dev, curr, curr+minlast, STp->first_frame_position, STp->last_frame_position, STp->cur_frames, result); notyetprinted--; }#endif current->state = TASK_INTERRUPTIBLE; schedule_timeout (HZ / OSST_POLL_PER_SEC); }#if DEBUG printk (OSST_DEB_MSG "osst%i: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n", dev, curr, curr+minlast, STp->first_frame_position, STp->last_frame_position, STp->cur_frames, (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);#endif return -EBUSY;}/* * Read the next OnStream tape block at the current location */static int osst_read_block(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout){ unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request * SRpnt; int retval = 0;#if DEBUG os_aux_t * aux = STp->buffer->aux; int dev = TAPE_NR(STp->devt);#endif /* TODO: Error handling */ if (STp->poll) retval = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout);#if 0// DEBUG printk ("osst_read: wait for frame returned %i\n", retval);#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = READ_6; cmd[1] = 1; cmd[4] = 1;#if DEBUG if (debugging) printk(OSST_DEB_MSG "osst%i: Reading block from OnStream tape\n", dev);#endif SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ, STp->timeout, MAX_RETRIES, TRUE); *aSRpnt = SRpnt; if (!SRpnt) return (-EBUSY); if ((STp->buffer)->syscall_result) { retval = 1; if (STp->read_error_frame == 0) { STp->read_error_frame = STp->first_frame_position; printk(OSST_DEB_MSG "osst: recording read error at %d\n", STp->read_error_frame);/*FIXME*/ }#if DEBUG if (debugging) printk(OSST_DEB_MSG "osst%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1], SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3], SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5], SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]);#endif } else STp->first_frame_position++;#if DEBUG if (debugging) { printk(OSST_DEB_MSG "osst%i: AUX: %c%c%c%c UpdFrCt#%d %s FrSeq#%d LogBlk#%d\n", dev, aux->application_sig[0], aux->application_sig[1], aux->application_sig[2], aux->application_sig[3], ntohl(aux->update_frame_cntr), aux->frame_type==1?"EOD":aux->frame_type==2?"MARK": aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL", ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num) ); if (aux->frame_type==2) printk(OSST_DEB_MSG "osst%i: mark_cnt=%d, last_mark=%d, next_mark=%d\n", dev, ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->next_mark_ppos)); printk(OSST_DEB_MSG "osst%i: Exit read block from OnStream tape with code %d\n", dev, retval); }#endif return (retval);}static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt){ ST_partstat * STps = &(STp->ps[STp->partition]); Scsi_Request * SRpnt ; unsigned char cmd[MAX_COMMAND_SIZE]; int retval = 0;#if DEBUG int dev = TAPE_NR(STp->devt);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -