📄 tape34xx.c
字号:
if (bh->b_size > blksize_size[tapeblock_major][ti->blk_minor]) for (size = 0; size < bh->b_size; size += blksize_size[tapeblock_major][ti->blk_minor]) bhct++; else bhct++; } if ((data = kmalloc (4 * sizeof (__u8), GFP_ATOMIC)) == NULL) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,3,"xBREDnomem");#endif /* TAPE_DEBUG */ return NULL; } data[0] = 0x01; data[1] = data[2] = data[3] = 0x00; realcount=req->sector/s2b; if (((tape34xx_disc_data_t *) ti->discdata)->modeset_byte & 0x08) // IDRC on data[1] = data[1] | 0x80; data[3] += realcount % 256; data[2] += (realcount / 256) % 256; data[1] += (realcount / 65536);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xBREDid:"); debug_int_event (tape_debug_area,6,realcount);#endif /* TAPE_DEBUG */ cqr = tape_alloc_ccw_req (ti, 2+bhct+1, 0); if (!cqr) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xBREDnomem");#endif /* TAPE_DEBUG */ kfree(data); return NULL; } ccw = cqr->cpaddr; ccw->cmd_code = MODE_SET_DB; ccw->flags = CCW_FLAG_CC; ccw->count = 1; set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) ti->discdata)->modeset_byte))); if (realcount!=ti->position) { ccw++; ccw->cmd_code = LOCATE; ccw->flags = CCW_FLAG_CC; ccw->count = 4; set_normalized_cda (ccw, (unsigned long) data); } ti->position=realcount+req->nr_sectors/s2b; for (bh=req->bh;bh!=NULL;) { ccw->flags = CCW_FLAG_CC; if (bh->b_size >= blksize_size[tapeblock_major][ti->blk_minor]) { for (size = 0; size < bh->b_size; size += blksize_size[tapeblock_major][ti->blk_minor]) { ccw++; ccw->flags = CCW_FLAG_CC; ccw->cmd_code = READ_FORWARD; ccw->count = blksize_size[tapeblock_major][ti->blk_minor]; set_normalized_cda (ccw, __pa (bh->b_data + size)); } bh = bh->b_reqnext; } else { /* group N bhs to fit into byt_per_blk */ for (size = 0; bh != NULL && size < blksize_size[tapeblock_major][ti->blk_minor];) { ccw++; ccw->flags = CCW_FLAG_DC; ccw->cmd_code = READ_FORWARD; ccw->count = bh->b_size; set_normalized_cda (ccw, __pa (bh->b_data)); size += bh->b_size; bh = bh->b_reqnext; } if (size != blksize_size[tapeblock_major][ti->blk_minor]) { PRINT_WARN ("Cannot fulfill small request %d vs. %d (%ld sects)\n", size, blksize_size[tapeblock_major][ti->blk_minor], req->nr_sectors); kfree(data); tape_free_request (cqr); return NULL; } } } ccw -> flags &= ~(CCW_FLAG_DC); ccw -> flags |= (CCW_FLAG_CC); ccw++; ccw->cmd_code = NOP; ccw->flags = 0; ccw->count = 0; ccw->cda = (unsigned long) (&(ccw->cmd_code)); ti->kernbuf = data; ti->userbuf = NULL; tapestate_set (ti, TS_BLOCK_INIT);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xBREDccwg");#endif /* TAPE_DEBUG */ return cqr;}void tape34xx_free_bread (ccw_req_t* cqr,struct _tape_info_t* ti) { ccw1_t* ccw; for (ccw=(ccw1_t*)cqr->cpaddr;(ccw->flags & CCW_FLAG_CC)||(ccw->flags & CCW_FLAG_DC);ccw++) if ((ccw->cmd_code == MODE_SET_DB) || (ccw->cmd_code == LOCATE) || (ccw->cmd_code == READ_FORWARD)) clear_normalized_cda(ccw); tape_free_request(cqr); kfree(ti->kernbuf); ti->kernbuf=NULL;}/* event handlers */voidtape34xx_default_handler (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xdefhandle");#endif /* TAPE_DEBUG */ PRINT_ERR ("TAPE34XX: An unexpected Unit Check occurred.\n"); PRINT_ERR ("TAPE34XX: Please read Documentation/s390/TAPE and report it!\n"); PRINT_ERR ("TAPE34XX: Current state is: %s", (((tapestate_get (ti) < TS_SIZE) && (tapestate_get (ti) >= 0)) ? state_verbose[tapestate_get (ti)] : "->UNKNOWN STATE<-")); tape_dump_sense (&ti->devstat); ti->rc = -EIO; ti->wanna_wakeup=1; switch (tapestate_get(ti)) { case TS_REW_RELEASE_INIT: tapestate_set(ti,TS_FAILED); wake_up (&ti->wq); break; case TS_BLOCK_INIT: tapestate_set(ti,TS_FAILED); schedule_tapeblock_exec_IO(ti); break; default: tapestate_set(ti,TS_FAILED); wake_up_interruptible (&ti->wq); } }voidtape34xx_unexpect_uchk_handler (tape_info_t * ti){ if ((ti->devstat.ii.sense.data[0] == 0x40) && (ti->devstat.ii.sense.data[1] == 0x40) && (ti->devstat.ii.sense.data[3] == 0x43)) { // no tape in the drive PRINT_INFO ("Drive %d not ready. No volume loaded.\n", ti->rew_minor / 2);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"xuuh nomed");#endif /* TAPE_DEBUG */ tapestate_set (ti, TS_FAILED); ti->rc = -ENOMEDIUM; ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq); } else if ((ti->devstat.ii.sense.data[0] == 0x42) && (ti->devstat.ii.sense.data[1] == 0x44) && (ti->devstat.ii.sense.data[3] == 0x3b)) { PRINT_INFO ("Media in drive %d was changed!\n", ti->rew_minor / 2);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"xuuh medchg");#endif /* nothing to do. chan end & dev end will be reported when io is finished */ } else {#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"xuuh unexp"); debug_text_event (tape_debug_area,3,"state:"); debug_text_event (tape_debug_area,3,((tapestate_get (ti) < TS_SIZE) && (tapestate_get (ti) >= 0)) ? state_verbose[tapestate_get (ti)] : "TS UNKNOWN");#endif /* TAPE_DEBUG */ tape34xx_default_handler (ti); }}voidtape34xx_unused_done (tape_info_t * ti){ if (ti->medium_is_unloaded) { // A medium was inserted in the drive!#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xuui med");#endif /* TAPE_DEBUG */ PRINT_WARN ("A medium was inserted into the tape.\n"); ti->medium_is_unloaded=0; } else {#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"unsol.irq!"); debug_text_event (tape_debug_area,3,"dev end"); debug_int_exception (tape_debug_area,3,ti->devinfo.irq);#endif /* TAPE_DEBUG */ PRINT_WARN ("Unsolicited IRQ (Device End) caught in unused state.\n"); tape_dump_sense (&ti->devstat); }}voidtape34xx_idle_done (tape_info_t * ti){ if (ti->medium_is_unloaded) { // A medium was inserted in the drive!#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xuud med");#endif /* TAPE_DEBUG */ PRINT_WARN ("A medium was inserted into the tape.\n"); ti->medium_is_unloaded=0; wake_up_interruptible (&ti->wq); } else {#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"unsol.irq!"); debug_text_event (tape_debug_area,3,"dev end"); debug_int_exception (tape_debug_area,3,ti->devinfo.irq);#endif /* TAPE_DEBUG */ PRINT_WARN ("Unsolicited IRQ (Device End) caught in idle state.\n"); tape_dump_sense (&ti->devstat); }}voidtape34xx_block_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"x:bREQdone");#endif /* TAPE_DEBUG */ tapestate_set(ti,TS_DONE); schedule_tapeblock_exec_IO(ti);}voidtape34xx_bsf_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"bsf done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq);}voidtape34xx_dse_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"dse done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq);}voidtape34xx_fsf_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"fsf done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq);}voidtape34xx_fsb_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"fsb done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq);}voidtape34xx_bsb_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"bsb done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; ti->wanna_wakeup=1; wake_up (&ti->wq);}voidtape34xx_lbl_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"lbl done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; //s390irq_spin_unlock(tape->devinfo.irq); ti->wanna_wakeup=1; wake_up (&ti->wq);}voidtape34xx_nop_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"nop done.."); debug_text_exception (tape_debug_area,6,"or rew/rel");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; //s390irq_spin_unlock(tape->devinfo.irq); ti->wanna_wakeup=1; wake_up (&ti->wq);}voidtape34xx_rfo_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"rfo done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; ti->wanna_wakeup=1; wake_up (&ti->wq);}voidtape34xx_rbi_init_done (tape_info_t * ti){ __u8 *data;#ifdef TAPE_DEBUG int i;#endif tapestate_set (ti, TS_FAILED); data = ti->kernbuf; ti->rc = data[3]; ti->rc += 256 * data[2]; ti->rc += 65536 * (data[1] & 0x3F);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"rbi done"); debug_text_event (tape_debug_area,6,"data:"); for (i=0;i<8;i++) debug_int_event (tape_debug_area,6,data[i]);#endif ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq);}voidtape34xx_rew_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"rew done");#endif //BH: use irqsave //s390irq_spin_lock(tape->devinfo.irq); tapestate_set (ti, TS_DONE); ti->rc = 0; //s390irq_spin_unlock(tape->devinfo.irq); ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq);}voidtape34xx_rew_release_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"rewR done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; //s390irq_spin_unlock(tape->devinfo.irq); ti->wanna_wakeup=1; wake_up (&ti->wq);}voidtape34xx_run_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"rew done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq);}voidtape34xx_wri_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"wri done");#endif //BH: use irqsave //s390irq_spin_lock(ti->devinfo.irq); tapestate_set (ti, TS_DONE); ti->rc = 0; //s390irq_spin_unlock(ti->devinfo.irq); ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq);}voidtape34xx_wtm_init_done (tape_info_t * ti){#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,3,"wtm done");#endif tapestate_set (ti, TS_DONE); ti->rc = 0; ti->wanna_wakeup=1; wake_up_interruptible (&ti->wq);}/* This function analyses the tape's sense-data in case of a unit-check. If possible, it tries to recover from the error. Else the user is informed about the problem. */voidtape34xx_error_recovery (tape_info_t* ti){ __u8* sense=ti->devstat.ii.sense.data; int inhibit_cu_recovery=0; int cu_type=ti->discipline->cu_type; if ((((tape34xx_disc_data_t *) ti->discdata)->modeset_byte)&0x80) inhibit_cu_recovery=1; if (tapestate_get(ti)==TS_BLOCK_INIT) { // no recovery for block device, bottom half will retry... tape34xx_error_recovery_has_failed(ti,EIO); return; } if (sense[0]&SENSE_COMMAND_REJECT) switch (tapestate_get(ti)) { case TS_BLOCK_INIT: case TS_DSE_INIT: case TS_EGA_INIT: case TS_WRI_INIT: case TS_WTM_INIT: if (sense[1]&SENSE_WRITE_PROTECT) { // trying to write, but medium is write protected tape34xx_error_recovery_has_failed(ti,EACCES); return; } default: tape34xx_error_recovery_HWBUG(ti,1); return; } // special cases for various tape-states when reaching end of recorded area if (((sense[0]==0x08) || (sense[0]==0x10) || (sense[0]==0x12)) && ((sense[1]==0x40) || (sense[1]==0x0c))) switch (tapestate_get(ti)) { case TS_FSF_INIT: // Trying to seek beyond end of recorded area
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -