⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tape_std.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  drivers/s390/char/tape_std.c *    standard tape device functions for ibm tapes. * *  S390 and zSeries version *    Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation *    Author(s): Carsten Otte <cotte@de.ibm.com> *		 Michael Holzheu <holzheu@de.ibm.com> *		 Tuan Ngo-Anh <ngoanh@de.ibm.com> *		 Martin Schwidefsky <schwidefsky@de.ibm.com> *		 Stefan Bader <shbader@de.ibm.com> */#include <linux/config.h>#include <linux/stddef.h>#include <linux/kernel.h>#include <linux/bio.h>#include <linux/timer.h>#include <asm/types.h>#include <asm/idals.h>#include <asm/ebcdic.h>#include <asm/tape390.h>#define TAPE_DBF_AREA	tape_core_dbf#include "tape.h"#include "tape_std.h"#define PRINTK_HEADER "TAPE_STD: "/* * tape_std_assign */static voidtape_std_assign_timeout(unsigned long data){	struct tape_request *	request;	struct tape_device *	device;	request = (struct tape_request *) data;	if ((device = request->device) == NULL)		BUG();	spin_lock_irq(get_ccwdev_lock(device->cdev));	if (request->callback != NULL) {		DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n",			device->cdev_id);		PRINT_ERR("%s: Assignment timeout. Device busy.\n",			device->cdev->dev.bus_id);		ccw_device_clear(device->cdev, (long) request);	}	spin_unlock_irq(get_ccwdev_lock(device->cdev));}inttape_std_assign(struct tape_device *device){	int                  rc;	struct timer_list    timeout;	struct tape_request *request;	request = tape_alloc_request(2, 11);	if (IS_ERR(request))		return PTR_ERR(request);	request->op = TO_ASSIGN;	tape_ccw_cc(request->cpaddr, ASSIGN, 11, request->cpdata);	tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);	/*	 * The assign command sometimes blocks if the device is assigned	 * to another host (actually this shouldn't happen but it does).	 * So we set up a timeout for this call.	 */	init_timer(&timeout);	timeout.function = tape_std_assign_timeout;	timeout.data     = (unsigned long) request;	timeout.expires  = jiffies + 2 * HZ;	add_timer(&timeout);	rc = tape_do_io_interruptible(device, request);	del_timer(&timeout);	if (rc != 0) {		PRINT_WARN("%s: assign failed - device might be busy\n",			device->cdev->dev.bus_id);		DBF_EVENT(3, "%08x: assign failed - device might be busy\n",			device->cdev_id);	} else {		DBF_EVENT(3, "%08x: Tape assigned\n", device->cdev_id);	}	tape_free_request(request);	return rc;}/* * tape_std_unassign */inttape_std_unassign (struct tape_device *device){	int                  rc;	struct tape_request *request;	if (device->tape_state == TS_NOT_OPER) {		DBF_EVENT(3, "(%08x): Can't unassign device\n",			device->cdev_id);		PRINT_WARN("(%s): Can't unassign device - device gone\n",			device->cdev->dev.bus_id);		return -EIO;	}	request = tape_alloc_request(2, 11);	if (IS_ERR(request))		return PTR_ERR(request);	request->op = TO_UNASSIGN;	tape_ccw_cc(request->cpaddr, UNASSIGN, 11, request->cpdata);	tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);	if ((rc = tape_do_io(device, request)) != 0) {		DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id);		PRINT_WARN("%s: Unassign failed\n", device->cdev->dev.bus_id);	} else {		DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id);	}	tape_free_request(request);	return rc;}/* * TAPE390_DISPLAY: Show a string on the tape display. */inttape_std_display(struct tape_device *device, struct display_struct *disp){	struct tape_request *request;	int rc;	request = tape_alloc_request(2, 17);	if (IS_ERR(request)) {		DBF_EVENT(3, "TAPE: load display failed\n");		return PTR_ERR(request);	}	request->op = TO_DIS;	*(unsigned char *) request->cpdata = disp->cntrl;	DBF_EVENT(5, "TAPE: display cntrl=%04x\n", disp->cntrl);	memcpy(((unsigned char *) request->cpdata) + 1, disp->message1, 8);	memcpy(((unsigned char *) request->cpdata) + 9, disp->message2, 8);	ASCEBC(((unsigned char*) request->cpdata) + 1, 16);	tape_ccw_cc(request->cpaddr, LOAD_DISPLAY, 17, request->cpdata);	tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);	rc = tape_do_io_interruptible(device, request);	tape_free_request(request);	return rc;}/* * Read block id. */inttape_std_read_block_id(struct tape_device *device, __u64 *id){	struct tape_request *request;	int rc;	request = tape_alloc_request(3, 8);	if (IS_ERR(request))		return PTR_ERR(request);	request->op = TO_RBI;	/* setup ccws */	tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);	tape_ccw_cc(request->cpaddr + 1, READ_BLOCK_ID, 8, request->cpdata);	tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);	/* execute it */	rc = tape_do_io(device, request);	if (rc == 0)		/* Get result from read buffer. */		*id = *(__u64 *) request->cpdata;	tape_free_request(request);	return rc;}inttape_std_terminate_write(struct tape_device *device){	int rc;	if(device->required_tapemarks == 0)		return 0;	DBF_LH(5, "tape%d: terminate write %dxEOF\n", device->first_minor,		device->required_tapemarks);	rc = tape_mtop(device, MTWEOF, device->required_tapemarks);	if (rc)		return rc;	device->required_tapemarks = 0;	return tape_mtop(device, MTBSR, 1);}/* * MTLOAD: Loads the tape. * The default implementation just wait until the tape medium state changes * to MS_LOADED. */inttape_std_mtload(struct tape_device *device, int count){	return wait_event_interruptible(device->state_change_wq,		(device->medium_state == MS_LOADED));}/* * MTSETBLK: Set block size. */inttape_std_mtsetblk(struct tape_device *device, int count){	struct idal_buffer *new;	DBF_LH(6, "tape_std_mtsetblk(%d)\n", count);	if (count <= 0) {		/*		 * Just set block_size to 0. tapechar_read/tapechar_write		 * will realloc the idal buffer if a bigger one than the		 * current is needed.		 */		device->char_data.block_size = 0;		return 0;	}	if (device->char_data.idal_buf != NULL &&	    device->char_data.idal_buf->size == count)		/* We already have a idal buffer of that size. */		return 0;	if (count > MAX_BLOCKSIZE) {		DBF_EVENT(3, "Invalid block size (%d > %d) given.\n",			count, MAX_BLOCKSIZE);		PRINT_ERR("Invalid block size (%d > %d) given.\n",			count, MAX_BLOCKSIZE);		return -EINVAL;	}	/* Allocate a new idal buffer. */	new = idal_buffer_alloc(count, 0);	if (new == NULL)		return -ENOMEM;	if (device->char_data.idal_buf != NULL)		idal_buffer_free(device->char_data.idal_buf);	device->char_data.idal_buf = new;	device->char_data.block_size = count;	DBF_LH(6, "new blocksize is %d\n", device->char_data.block_size);	return 0;}/* * MTRESET: Set block size to 0. */inttape_std_mtreset(struct tape_device *device, int count){	DBF_EVENT(6, "TCHAR:devreset:\n");	device->char_data.block_size = 0;	return 0;}/* * MTFSF: Forward space over 'count' file marks. The tape is positioned * at the EOT (End of Tape) side of the file mark. */inttape_std_mtfsf(struct tape_device *device, int mt_count){	struct tape_request *request;	struct ccw1 *ccw;	request = tape_alloc_request(mt_count + 2, 0);	if (IS_ERR(request))		return PTR_ERR(request);	request->op = TO_FSF;	/* setup ccws */	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,			  device->modeset_byte);	ccw = tape_ccw_repeat(ccw, FORSPACEFILE, mt_count);	ccw = tape_ccw_end(ccw, NOP, 0, NULL);	/* execute it */	return tape_do_io_free(device, request);}/* * MTFSR: Forward space over 'count' tape blocks (blocksize is set * via MTSETBLK. */inttape_std_mtfsr(struct tape_device *device, int mt_count){	struct tape_request *request;	struct ccw1 *ccw;	int rc;	request = tape_alloc_request(mt_count + 2, 0);	if (IS_ERR(request))		return PTR_ERR(request);	request->op = TO_FSB;	/* setup ccws */	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,			  device->modeset_byte);	ccw = tape_ccw_repeat(ccw, FORSPACEBLOCK, mt_count);	ccw = tape_ccw_end(ccw, NOP, 0, NULL);	/* execute it */	rc = tape_do_io(device, request);	if (rc == 0 && request->rescnt > 0) {		DBF_LH(3, "FSR over tapemark\n");		rc = 1;	}	tape_free_request(request);	return rc;}/* * MTBSR: Backward space over 'count' tape blocks. * (blocksize is set via MTSETBLK. */inttape_std_mtbsr(struct tape_device *device, int mt_count){	struct tape_request *request;	struct ccw1 *ccw;	int rc;	request = tape_alloc_request(mt_count + 2, 0);	if (IS_ERR(request))		return PTR_ERR(request);	request->op = TO_BSB;	/* setup ccws */	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,			  device->modeset_byte);	ccw = tape_ccw_repeat(ccw, BACKSPACEBLOCK, mt_count);	ccw = tape_ccw_end(ccw, NOP, 0, NULL);	/* execute it */	rc = tape_do_io(device, request);	if (rc == 0 && request->rescnt > 0) {		DBF_LH(3, "BSR over tapemark\n");		rc = 1;	}	tape_free_request(request);	return rc;}/* * MTWEOF: Write 'count' file marks at the current position. */inttape_std_mtweof(struct tape_device *device, int mt_count){	struct tape_request *request;	struct ccw1 *ccw;	request = tape_alloc_request(mt_count + 2, 0);	if (IS_ERR(request))		return PTR_ERR(request);	request->op = TO_WTM;	/* setup ccws */	ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,			  device->modeset_byte);	ccw = tape_ccw_repeat(ccw, WRITETAPEMARK, mt_count);	ccw = tape_ccw_end(ccw, NOP, 0, NULL);	/* execute it */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -