📄 tape34xx.c
字号:
/*************************************************************************** * * drivers/s390/char/tape34xx.c * common tape device discipline for 34xx tapes. * * S390 and zSeries version * Copyright (C) 2001 IBM Corporation * Author(s): Carsten Otte <cotte@de.ibm.com> * Tuan Ngo-Anh <ngoanh@de.ibm.com> * **************************************************************************** */#include "tapedefs.h"#include <linux/config.h>#include <linux/version.h>#include <linux/stddef.h>#include <linux/kernel.h>#include <asm/types.h>#include <asm/uaccess.h>#include <linux/stat.h>#include <linux/proc_fs.h>#include <asm/ccwcache.h> #include <asm/idals.h> #ifdef CONFIG_S390_TAPE_DYNAMIC#include <asm/s390dyn.h>#endif#include <asm/debug.h>#include <linux/compatmac.h>#include "tape.h"#include "tape34xx.h"#define PRINTK_HEADER "T34xx:"tape_event_handler_t tape34xx_event_handler_table[TS_SIZE][TE_SIZE] ={ /* {START , DONE, FAILED, ERROR, OTHER } */ {NULL, tape34xx_unused_done, NULL, NULL, NULL}, /* TS_UNUSED */ {NULL, tape34xx_idle_done, NULL, NULL, NULL}, /* TS_IDLE */ {NULL, NULL, NULL, NULL, NULL}, /* TS_DONE */ {NULL, NULL, NULL, NULL, NULL}, /* TS_FAILED */ {NULL, tape34xx_block_done, NULL, NULL, NULL}, /* TS_BLOCK_INIT */ {NULL, tape34xx_bsb_init_done, NULL, NULL, NULL}, /* TS_BSB_INIT */ {NULL, tape34xx_bsf_init_done, NULL, NULL, NULL}, /* TS_BSF_INIT */ {NULL, tape34xx_dse_init_done, NULL, NULL, NULL}, /* TS_DSE_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_EGA_INIT */ {NULL, tape34xx_fsb_init_done, NULL, NULL, NULL}, /* TS_FSB_INIT */ {NULL, tape34xx_fsf_init_done, NULL, NULL, NULL}, /* TS_FSF_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_LDI_INIT */ {NULL, tape34xx_lbl_init_done, NULL, NULL, NULL}, /* TS_LBL_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_MSE_INIT */ {NULL, tape34xx_nop_init_done, NULL, NULL, NULL}, /* TS_NOP_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_RBA_INIT */ {NULL, tape34xx_rbi_init_done, NULL, NULL, NULL}, /* TS_RBI_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_RBU_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_RBL_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_RDC_INIT */ {NULL, tape34xx_rfo_init_done, NULL, NULL, NULL}, /* TS_RFO_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_RSD_INIT */ {NULL, tape34xx_rew_init_done, NULL, NULL, NULL}, /* TS_REW_INIT */ {NULL, tape34xx_rew_release_init_done, NULL, NULL, NULL}, /* TS_REW_RELEASE_IMIT */ {NULL, tape34xx_run_init_done, NULL, NULL, NULL}, /* TS_RUN_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_SEN_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_SID_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_SNP_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_SPG_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_SWI_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_SMR_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_SYN_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_TIO_INIT */ {NULL, NULL, NULL, NULL, NULL}, /* TS_UNA_INIT */ {NULL, tape34xx_wri_init_done, NULL, NULL, NULL}, /* TS_WRI_INIT */ {NULL, tape34xx_wtm_init_done, NULL, NULL, NULL}, /* TS_WTM_INIT */ {NULL, NULL, NULL, NULL, NULL}}; /* TS_NOT_OPER */inttape34xx_ioctl_overload (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ return -EINVAL; // no additional ioctls}ccw_req_t *tape34xx_write_block (const char *data, size_t count, tape_info_t * ti){ long lockflags; ccw_req_t *cqr; ccw1_t *ccw; void *mem; cqr = tape_alloc_ccw_req (ti, 2, 0); if (!cqr) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xwbl nomem");#endif /* TAPE_DEBUG */ return NULL; } mem = kmalloc (count, GFP_KERNEL); if (!mem) { tape_free_request (cqr);#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xwbl nomem");#endif /* TAPE_DEBUG */ return NULL; } if (copy_from_user (mem, data, count)) { kfree (mem); tape_free_request (cqr);#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xwbl segf.");#endif /* TAPE_DEBUG */ 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))); ccw++; ccw->cmd_code = WRITE_CMD; ccw->flags = 0; ccw->count = count; set_normalized_cda (ccw, (unsigned long) mem); if ((ccw->cda) == 0) { kfree (mem); tape_free_request (cqr); return NULL; } s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); ti->kernbuf = mem; ti->userbuf = (void *) data; tapestate_set (ti, TS_WRI_INIT); s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xwbl ccwg");#endif /* TAPE_DEBUG */ return cqr;}void tape34xx_free_write_block (ccw_req_t * cqr, tape_info_t * ti){ unsigned long lockflags; ccw1_t *ccw; s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); ccw = cqr->cpaddr; ccw++; clear_normalized_cda (ccw); kfree (ti->kernbuf); tape_free_request (cqr); ti->kernbuf = ti->userbuf = NULL; s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xfwb free");#endif /* TAPE_DEBUG */}ccw_req_t *tape34xx_read_block (const char *data, size_t count, tape_info_t * ti){ long lockflags; ccw_req_t *cqr; ccw1_t *ccw; void *mem; cqr = tape_alloc_ccw_req (ti, 2, 0); if (!cqr) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xrbl nomem");#endif /* TAPE_DEBUG */ return NULL; } mem = kmalloc (count, GFP_KERNEL); if (!mem) { tape_free_request (cqr);#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xrbl nomem");#endif /* TAPE_DEBUG */ 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))); ccw++; ccw->cmd_code = READ_FORWARD; ccw->flags = 0; ccw->count = count; set_normalized_cda (ccw, (unsigned long) mem); if ((ccw->cda) == 0) { kfree (mem); tape_free_request (cqr); return NULL; } s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); ti->kernbuf = mem; ti->userbuf = (void *) data; tapestate_set (ti, TS_RFO_INIT); s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xrbl ccwg");#endif /* TAPE_DEBUG */ return cqr;}ccw_req_t *tape34xx_read_opposite (tape_info_t * ti,int novalue){ ccw_req_t *cqr; ccw1_t *ccw; size_t count; // first, retrieve the count from the old cqr. cqr = ti->cqr; ccw = cqr->cpaddr; ccw++; count=ccw->count; // free old cqr. clear_normalized_cda (ccw); tape_free_request (cqr); // build new cqr cqr = tape_alloc_ccw_req (ti, 3, 0); if (!cqr) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xrop nomem");#endif /* TAPE_DEBUG */ 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))); ccw++; ccw->cmd_code = READ_BACKWARD; ccw->flags = CCW_FLAG_CC; ccw->count = count; set_normalized_cda (ccw, (unsigned long) ti->kernbuf); if ((ccw->cda) == 0) { tape_free_request (cqr); return NULL; } ccw++; ccw->cmd_code = FORSPACEBLOCK; ccw->flags = CCW_FLAG_CC; ccw->count = 1; ccw->cda = (unsigned long)ccw; ccw++; ccw->cmd_code = NOP; ccw->flags = 0; ccw->count = 1; ccw->cda = (unsigned long)ccw; tapestate_set (ti, TS_RBA_INIT);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xrop ccwg");#endif /* TAPE_DEBUG */ return cqr;}void tape34xx_free_read_block (ccw_req_t * cqr, tape_info_t * ti){ unsigned long lockflags; size_t cpysize; ccw1_t *ccw; s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); ccw = cqr->cpaddr; ccw++; cpysize = ccw->count - ti->devstat.rescnt; s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); if (copy_to_user (ti->userbuf, ti->kernbuf, cpysize)) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xfrb segf.");#endif /* TAPE_DEBUG */ } s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); clear_normalized_cda (ccw); kfree (ti->kernbuf); tape_free_request (cqr); ti->kernbuf = ti->userbuf = NULL; s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xfrb free");#endif /* TAPE_DEBUG */}/* * The IOCTL interface is implemented in the following section, * excepted the MTRESET, MTSETBLK which are handled by tapechar.c *//* * MTFSF: Forward space over 'count' file marks. The tape is positioned * at the EOT (End of Tape) side of the file mark. */ccw_req_t *tape34xx_mtfsf (tape_info_t * ti, int count){ long lockflags; int i; ccw_req_t *cqr; ccw1_t *ccw; if ((count == 0) || (count > 510)) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xfsf parm");#endif /* TAPE_DEBUG */ return NULL; } cqr = tape_alloc_ccw_req (ti, 2 + count, 0); if (!cqr) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xfsf nomem");#endif /* TAPE_DEBUG */ 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))); ccw++; for (i = 0; i < count; i++) { ccw->cmd_code = FORSPACEFILE; ccw->flags = CCW_FLAG_CC; ccw->count = 0; ccw->cda = (unsigned long) (&(ccw->cmd_code)); ccw++; } ccw->cmd_code = NOP; ccw->flags = 0; ccw->count = 0; ccw->cda = (unsigned long) (&(ccw->cmd_code)); s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); ti->kernbuf = NULL; ti->userbuf = NULL; tapestate_set (ti, TS_FSF_INIT); s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xfsf ccwg");#endif /* TAPE_DEBUG */ return cqr;}/* * MTBSF: Backward space over 'count' file marks. The tape is positioned at * the EOT (End of Tape) side of the last skipped file mark. */ccw_req_t *tape34xx_mtbsf (tape_info_t * ti, int count){ long lockflags; int i; ccw_req_t *cqr; ccw1_t *ccw; if ((count == 0) || (count > 510)) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xbsf parm");#endif /* TAPE_DEBUG */ return NULL; } cqr = tape_alloc_ccw_req (ti, 2 + count, 0); if (!cqr) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xbsf nomem");#endif /* TAPE_DEBUG */ 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))); ccw++; for (i = 0; i < count; i++) { ccw->cmd_code = BACKSPACEFILE; ccw->flags = CCW_FLAG_CC; ccw->count = 0; ccw->cda = (unsigned long) (&(ccw->cmd_code)); ccw++; } ccw->cmd_code = NOP; ccw->flags = 0; ccw->count = 0; ccw->cda = (unsigned long) (&(ccw->cmd_code)); s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); ti->kernbuf = NULL; ti->userbuf = NULL; tapestate_set (ti, TS_BSF_INIT); s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xbsf ccwg");#endif /* TAPE_DEBUG */ return cqr;}/* * MTFSR: Forward space over 'count' tape blocks (blocksize is set * via MTSETBLK. */ccw_req_t *tape34xx_mtfsr (tape_info_t * ti, int count){ long lockflags; int i; ccw_req_t *cqr; ccw1_t *ccw; if ((count == 0) || (count > 510)) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xfsr parm");#endif /* TAPE_DEBUG */ return NULL; } cqr = tape_alloc_ccw_req (ti, 2 + count, 0); if (!cqr) {#ifdef TAPE_DEBUG debug_text_exception (tape_debug_area,6,"xfsr nomem");#endif /* TAPE_DEBUG */ 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))); ccw++; for (i = 0; i < count; i++) { ccw->cmd_code = FORSPACEBLOCK; ccw->flags = CCW_FLAG_CC; ccw->count = 0; ccw->cda = (unsigned long) (&(ccw->cmd_code)); ccw++; } ccw->cmd_code = NOP; ccw->flags = 0; ccw->count = 0; ccw->cda = (unsigned long) (&(ccw->cmd_code)); s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); ti->kernbuf = NULL; ti->userbuf = NULL; tapestate_set (ti, TS_FSB_INIT); s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG debug_text_event (tape_debug_area,6,"xfsr ccwgen");#endif /* TAPE_DEBUG */ return cqr;}/* * MTBSR: Backward space over 'count' tape blocks.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -