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

📄 tapechar.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** * *  drivers/s390/char/tapechar.c *    character device frontend for tape device driver * *  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/types.h>#include <linux/proc_fs.h>#include <asm/ccwcache.h>	/* CCW allocations      */#include <asm/s390dyn.h>#include <asm/debug.h>#include <linux/mtio.h>#include <asm/uaccess.h>#include <linux/compatmac.h>#ifdef MODULE#define __NO_VERSION__#include <linux/module.h>#endif#include "tape.h"#include "tapechar.h"#define PRINTK_HEADER "TCHAR:"/* * file operation structure for tape devices */static struct file_operations tape_fops ={    //    owner   : THIS_MODULE,	llseek:NULL,		/* lseek - default */	read:tape_read,		/* read  */	write:tape_write,	/* write */	readdir:NULL,		/* readdir - bad */	poll:NULL,		/* poll */	ioctl:tape_ioctl,	/* ioctl */	mmap:NULL,		/* mmap */	open:tape_open,		/* open */	flush:NULL,		/* flush */	release:tape_release,	/* release */	fsync:NULL,		/* fsync */	fasync:NULL,		/* fasync */	lock:NULL,};int tape_major = TAPE_MAJOR;#ifdef CONFIG_DEVFS_FSvoidtapechar_mkdevfstree (tape_info_t* ti) {    ti->devfs_char_dir=devfs_mk_dir (ti->devfs_dir, "char", ti);    ti->devfs_nonrewinding=devfs_register(ti->devfs_char_dir, "nonrewinding",					    DEVFS_FL_DEFAULT,tape_major, 					    ti->nor_minor, TAPECHAR_DEFAULTMODE, 					    &tape_fops, ti);    ti->devfs_rewinding=devfs_register(ti->devfs_char_dir, "rewinding",					 DEVFS_FL_DEFAULT, tape_major, ti->rew_minor,					 TAPECHAR_DEFAULTMODE, &tape_fops, ti);}voidtapechar_rmdevfstree (tape_info_t* ti) {    devfs_unregister(ti->devfs_nonrewinding);    devfs_unregister(ti->devfs_rewinding);    devfs_unregister(ti->devfs_char_dir);}#endifvoidtapechar_setup (tape_info_t * ti){#ifdef CONFIG_DEVFS_FS    tapechar_mkdevfstree(ti);#endif}voidtapechar_init (void){	int result;	tape_frontend_t *charfront,*temp;	tape_info_t* ti;	tape_init();	/* Register the tape major number to the kernel */#ifdef CONFIG_DEVFS_FS	result = devfs_register_chrdev (tape_major, "tape", &tape_fops);#else	result = register_chrdev (tape_major, "tape", &tape_fops);#endif	if (result < 0) {		PRINT_WARN (KERN_ERR "tape: can't get major %d\n", tape_major);#ifdef TAPE_DEBUG		debug_text_event (tape_debug_area,3,"c:initfail");		debug_text_event (tape_debug_area,3,"regchrfail");#endif /* TAPE_DEBUG */		panic ("no major number available for tape char device");	}	if (tape_major == 0)		tape_major = result;	/* accept dynamic major number */	PRINT_WARN (KERN_ERR " tape gets major %d for character device\n", result);	charfront = kmalloc (sizeof (tape_frontend_t), GFP_KERNEL);	if (charfront == NULL) {#ifdef TAPE_DEBUG                debug_text_event (tape_debug_area,3,"c:initfail");		debug_text_event (tape_debug_area,3,"no mem");#endif /* TAPE_DEBUG */		panic ("no major number available for tape char device");			}	charfront->device_setup = tapechar_setup;#ifdef CONFIG_DEVFS_FS	charfront->mkdevfstree = tapechar_mkdevfstree;	charfront->rmdevfstree = tapechar_rmdevfstree;#endif#ifdef TAPE_DEBUG        debug_text_event (tape_debug_area,3,"c:init ok");#endif /* TAPE_DEBUG */	charfront->next=NULL;	if (first_frontend==NULL) {	    first_frontend=charfront;	} else {	    temp=first_frontend;	    while (temp->next!=NULL)		temp=temp->next;	    temp->next=charfront;	}	ti=first_tape_info;	while (ti!=NULL) {	    tapechar_setup(ti);	    ti=ti->next;	}}voidtapechar_uninit (void){	unregister_chrdev (tape_major, "tape");}/* * Tape device read function */ssize_ttape_read (struct file *filp, char *data, size_t count, loff_t * ppos){	long lockflags;	tape_info_t *ti;	size_t block_size;	ccw_req_t *cqr;	int rc;#ifdef TAPE_DEBUG        debug_text_event (tape_debug_area,6,"c:read");#endif /* TAPE_DEBUG */	ti = first_tape_info;	while ((ti != NULL) && (ti->rew_filp != filp) && (ti->nor_filp != filp))		ti = (tape_info_t *) ti->next;	if (ti == NULL) {#ifdef TAPE_DEBUG	        debug_text_event (tape_debug_area,6,"c:nodev");#endif /* TAPE_DEBUG */		return -ENODEV;	}	if (ppos != &filp->f_pos) {		/* "A request was outside the capabilities of the device." */#ifdef TAPE_DEBUG	        debug_text_event (tape_debug_area,6,"c:ppos wrong");#endif /* TAPE_DEBUG */		return -EOVERFLOW;	/* errno=75 Value too large for def. data type */	}	if (ti->block_size == 0) {		block_size = count;	} else {		block_size = ti->block_size;	}#ifdef TAPE_DEBUG	debug_text_event (tape_debug_area,6,"c:nbytes:");	debug_int_event (tape_debug_area,6,block_size);#endif	cqr = ti->discipline->read_block (data, block_size, ti);	if (!cqr) {		return -ENOBUFS;	}	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);	ti->cqr = cqr;	ti->wanna_wakeup=0;	rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);	if (rc) {	    tapestate_set(ti,TS_IDLE);	    kfree (cqr);	    s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);	    return rc;	}	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);	wait_event (ti->wq,ti->wanna_wakeup);	ti->cqr = NULL;	ti->discipline->free_read_block (cqr, ti);	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);	if (tapestate_get (ti) == TS_FAILED) {		tapestate_set (ti, TS_IDLE);		s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);		return ti->rc;	}	if (tapestate_get (ti) == TS_NOT_OPER) {	    ti->blk_minor=ti->rew_minor=ti->nor_minor=-1;	    ti->devinfo.irq=-1;	    s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags);	    return -ENODEV;	}	if (tapestate_get (ti) != TS_DONE) {		tapestate_set (ti, TS_IDLE);		s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);		return -EIO;	}	tapestate_set (ti, TS_IDLE);	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG	debug_text_event (tape_debug_area,6,"c:rbytes:");	debug_int_event (tape_debug_area,6,block_size - ti->devstat.rescnt);#endif	/* TAPE_DEBUG */	filp->f_pos += block_size - ti->devstat.rescnt;	return block_size - ti->devstat.rescnt;}/* * Tape device write function */ssize_ttape_write (struct file *filp, const char *data, size_t count, loff_t * ppos){	long lockflags;	tape_info_t *ti;	size_t block_size;	ccw_req_t *cqr;	int nblocks, i, rc;	size_t written = 0;#ifdef TAPE_DEBUG	debug_text_event (tape_debug_area,6,"c:write");#endif	ti = first_tape_info;	while ((ti != NULL) && (ti->nor_filp != filp) && (ti->rew_filp != filp))		ti = (tape_info_t *) ti->next;	if (ti == NULL)		return -ENODEV;	if (ppos != &filp->f_pos) {		/* "A request was outside the capabilities of the device." */#ifdef TAPE_DEBUG	        debug_text_event (tape_debug_area,6,"c:ppos wrong");#endif		return -EOVERFLOW;	/* errno=75 Value too large for def. data type */	}	if ((ti->block_size != 0) && (count % ti->block_size != 0))		return -EIO;	if (ti->block_size == 0) {		block_size = count;		nblocks = 1;	} else {		block_size = ti->block_size;		nblocks = count / (ti->block_size);	}#ifdef TAPE_DEBUG	        debug_text_event (tape_debug_area,6,"c:nbytes:");		debug_int_event (tape_debug_area,6,block_size);	        debug_text_event (tape_debug_area,6,"c:nblocks:");	        debug_int_event (tape_debug_area,6,nblocks);#endif	for (i = 0; i < nblocks; i++) {		cqr = ti->discipline->write_block (data + i * block_size, block_size, ti);		if (!cqr) {			return -ENOBUFS;		}		s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);		ti->cqr = cqr;		ti->wanna_wakeup=0;		rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);		s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);		wait_event_interruptible (ti->wq,ti->wanna_wakeup);		ti->cqr = NULL;		ti->discipline->free_write_block (cqr, ti);		if (signal_pending (current)) {			tapestate_set (ti, TS_IDLE);			return -ERESTARTSYS;		}		s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);		if (tapestate_get (ti) == TS_FAILED) {			tapestate_set (ti, TS_IDLE);			s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);                        if ((ti->rc==-ENOSPC) && (i!=0))			  return i*block_size;			return ti->rc;		}		if (tapestate_get (ti) == TS_NOT_OPER) {		    ti->blk_minor=ti->rew_minor=ti->nor_minor=-1;		    ti->devinfo.irq=-1;		    s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags);		    return -ENODEV;		}		if (tapestate_get (ti) != TS_DONE) {			tapestate_set (ti, TS_IDLE);			s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);			return -EIO;		}		tapestate_set (ti, TS_IDLE);		s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG	        debug_text_event (tape_debug_area,6,"c:wbytes:"); 		debug_int_event (tape_debug_area,6,block_size - ti->devstat.rescnt);#endif		filp->f_pos += block_size - ti->devstat.rescnt;		written += block_size - ti->devstat.rescnt;		if (ti->devstat.rescnt > 0)			return written;	}#ifdef TAPE_DEBUG	debug_text_event (tape_debug_area,6,"c:wtotal:");	debug_int_event (tape_debug_area,6,written);#endif	return written;}static inttape_mtioctop (struct file *filp, short mt_op, int mt_count){	tape_info_t *ti;	ccw_req_t *cqr = NULL;	int rc;	long lockflags;#ifdef TAPE_DEBUG	debug_text_event (tape_debug_area,6,"c:mtio");	debug_text_event (tape_debug_area,6,"c:ioop:");	debug_int_event (tape_debug_area,6,mt_op); 	debug_text_event (tape_debug_area,6,"c:arg:");	debug_int_event (tape_debug_area,6,mt_count);#endif	ti = first_tape_info;	while ((ti != NULL) && (ti->rew_filp != filp) && (ti->nor_filp != filp))		ti = (tape_info_t *) ti->next;	if (ti == NULL)		return -ENODEV;	switch (mt_op) {	case MTREW:		// rewind		cqr = ti->discipline->mtrew (ti, mt_count);		break;	case MTOFFL:		// put drive offline		cqr = ti->discipline->mtoffl (ti, mt_count);		break;	case MTUNLOAD:		// unload the tape		cqr = ti->discipline->mtunload (ti, mt_count);		break;	case MTWEOF:		// write tapemark		cqr = ti->discipline->mtweof (ti, mt_count);		break;	case MTFSF:		// forward space file		cqr = ti->discipline->mtfsf (ti, mt_count);		break;	case MTBSF:		// backward space file		cqr = ti->discipline->mtbsf (ti, mt_count);		break;	case MTFSFM:		// forward space file, stop at BOT side		cqr = ti->discipline->mtfsfm (ti, mt_count);		break;

⌨️ 快捷键说明

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