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

📄 tapeblock.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** * *  drivers/s390/char/tapeblock.c *    block 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/blkdev.h>#include <linux/blk.h>#include <linux/version.h>#include <linux/interrupt.h>#include <asm/ccwcache.h>	/* CCW allocations      */#include <asm/debug.h>#include <asm/s390dyn.h>#include <linux/compatmac.h>#ifdef MODULE#define __NO_VERSION__#include <linux/module.h>#endif#include "tape.h"#include "tapeblock.h"#define PRINTK_HEADER "TBLOCK:"/* * file operation structure for tape devices */#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))static struct block_device_operations tapeblock_fops = {#elsestatic struct file_operations tapeblock_fops = {#endif    owner   : THIS_MODULE,    open    : tapeblock_open,      /* open */    release : tapeblock_release,   /* release */        };int    tapeblock_major = 0;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))static void tape_request_fn (request_queue_t * queue);#elsestatic void tape_request_fn (void);#endifstatic request_queue_t* tapeblock_getqueue (kdev_t kdev);#ifdef CONFIG_DEVFS_FSvoidtapeblock_mkdevfstree (tape_info_t* ti) {    ti->devfs_block_dir=devfs_mk_dir (ti->devfs_dir, "block", ti);    ti->devfs_disc=devfs_register(ti->devfs_block_dir, "disc",DEVFS_FL_DEFAULT,				    tapeblock_major, ti->blk_minor,				    TAPEBLOCK_DEFAULTMODE, &tapeblock_fops, ti);}voidtapeblock_rmdevfstree (tape_info_t* ti) {    devfs_unregister(ti->devfs_disc);    devfs_unregister(ti->devfs_block_dir);}#endifvoid tapeblock_setup(tape_info_t* ti) {    blk_size[tapeblock_major][ti->blk_minor]=0; // this will be detected    blksize_size[tapeblock_major][ti->blk_minor]=2048; // blocks are 2k by default.    hardsect_size[tapeblock_major][ti->blk_minor]=512;    blk_init_queue (&ti->request_queue, tape_request_fn);     blk_queue_headactive (&ti->request_queue, 0); #ifdef CONFIG_DEVFS_FS    tapeblock_mkdevfstree(ti);#endif}inttapeblock_init(void) {    int result;    tape_frontend_t* blkfront,*temp;    tape_info_t* ti;    tape_init();    /* Register the tape major number to the kernel */#ifdef CONFIG_DEVFS_FS    result = devfs_register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops);#else    result = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops);#endif    if (result < 0) {        PRINT_WARN(KERN_ERR "tape: can't get major %d for block device\n", tapeblock_major);        panic ("cannot get major number for tape block device");    }    if (tapeblock_major == 0) tapeblock_major = result;   /* accept dynamic major number*/    INIT_BLK_DEV(tapeblock_major,tape_request_fn,tapeblock_getqueue,NULL);    read_ahead[tapeblock_major]=TAPEBLOCK_READAHEAD;    PRINT_WARN(KERN_ERR " tape gets major %d for block device\n", result);    blk_size[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC);    memset(blk_size[tapeblock_major],0,256*sizeof(int));    blksize_size[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC);    memset(blksize_size[tapeblock_major],0,256*sizeof(int));    hardsect_size[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC);    memset(hardsect_size[tapeblock_major],0,256*sizeof(int));    max_sectors[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC);    memset(max_sectors[tapeblock_major],0,256*sizeof(int));    blkfront = kmalloc(sizeof(tape_frontend_t),GFP_KERNEL);    if (blkfront==NULL) panic ("no mem for tape block device structure");    blkfront->device_setup=tapeblock_setup;#ifdef CONFIG_DEVFS_FS    blkfront->mkdevfstree = tapeblock_mkdevfstree;    blkfront->rmdevfstree = tapeblock_rmdevfstree;#endif    blkfront->next=NULL;    if (first_frontend==NULL) {	first_frontend=blkfront;    } else {	temp=first_frontend;	while (temp->next!=NULL)	temp=temp->next;	temp->next=blkfront;    }    ti=first_tape_info;    while (ti!=NULL) {	tapeblock_setup(ti);	ti=ti->next;    }    return 0;}void tapeblock_uninit(void) {    unregister_blkdev(tapeblock_major, "tBLK");}inttapeblock_open(struct inode *inode, struct file *filp) {    tape_info_t *ti;    kdev_t dev;    int rc;    long lockflags;    inode = filp->f_dentry->d_inode;    ti = first_tape_info;    while ((ti != NULL) && (ti->blk_minor != MINOR (inode->i_rdev)))		ti = (tape_info_t *) ti->next;	if (ti == NULL)		return -ENODEV;#ifdef TAPE_DEBUG	debug_text_event (tape_debug_area,6,"b:open:");	debug_int_event (tape_debug_area,6,ti->blk_minor);#endif	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);	if (tapestate_get (ti) != TS_UNUSED) {		s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);#ifdef TAPE_DEBUG		debug_text_event (tape_debug_area,6,"b:dbusy");#endif		return -EBUSY;	}	tapestate_set (ti, TS_IDLE);        ti->position=-1;        	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);        rc=tapeblock_mediumdetect(ti);        if (rc) {	    s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);	    tapestate_set (ti, TS_UNUSED);	    s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);	    return rc; // in case of errors, we don't have a size of the medium	}	dev = MKDEV (tapeblock_major, MINOR (inode->i_rdev));	/* Get the device */	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);	ti->blk_filp = filp;	filp->private_data = ti;	/* save the dev.info for later reference */        ti->cqr=NULL;	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);    	return 0;}inttapeblock_release(struct inode *inode, struct file *filp) {	long lockflags;	tape_info_t *ti,*lastti;	ti = first_tape_info;	while ((ti != NULL) && (ti->blk_minor != MINOR (inode->i_rdev)))		ti = (tape_info_t *) ti->next;	if ((ti != NULL) && (tapestate_get (ti) == TS_NOT_OPER)) {	    if (ti==first_tape_info) {		first_tape_info=ti->next;	    } else {		lastti=first_tape_info;		while (lastti->next!=ti) lastti=lastti->next;		lastti->next=ti->next;	    }	    kfree(ti);    	    return 0;	}	if ((ti == NULL) || (tapestate_get (ti) != TS_IDLE)) {#ifdef TAPE_DEBUG	debug_text_event (tape_debug_area,3,"b:notidle!");#endif		return -ENXIO;	/* error in tape_release */	}#ifdef TAPE_DEBUG	debug_text_event (tape_debug_area,6,"b:release:");	debug_int_event (tape_debug_area,6,ti->blk_minor);#endif	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);	tapestate_set (ti, TS_UNUSED);	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);	invalidate_buffers(inode->i_rdev);	return 0;}static voidtapeblock_end_request(tape_info_t* ti) {    struct buffer_head *bh;    int uptodate;    if ((tapestate_get(ti)!=TS_FAILED) &&	(tapestate_get(ti)!=TS_DONE))       BUG(); // A request has to be completed to end it    uptodate=(tapestate_get(ti)==TS_DONE); // is the buffer up to date?#ifdef TAPE_DEBUG    if (uptodate) {	debug_text_event (tape_debug_area,6,"b:done:");	debug_int_event (tape_debug_area,6,(long)ti->cqr);    } else {	debug_text_event (tape_debug_area,3,"b:failed:");	debug_int_event (tape_debug_area,3,(long)ti->cqr);    }#endif    // now inform ll_rw_block about a request status    while ((bh = ti->current_request->bh) != NULL) {	ti->current_request->bh = bh->b_reqnext;	bh->b_reqnext = NULL;	bh->b_end_io (bh, uptodate);    }    if (!end_that_request_first (ti->current_request, uptodate, "tBLK")) {#ifndef DEVICE_NO_RANDOM	add_blkdev_randomness (MAJOR (ti->current_request->rq_dev));#endif	end_that_request_last (ti->current_request);    }    ti->discipline->free_bread(ti->cqr,ti);    ti->cqr=NULL;    ti->current_request=NULL;    if (tapestate_get(ti)!=TS_NOT_OPER) tapestate_set(ti,TS_IDLE);    return;}static voidtapeblock_exec_IO (tape_info_t* ti) {    int rc;    struct request* req;    if (ti->cqr) { // process done/failed request	while ((tapestate_get(ti)==TS_FAILED) &&	    ti->blk_retries>0) {	    ti->blk_retries--;	    ti->position=-1;	    tapestate_set(ti,TS_BLOCK_INIT);#ifdef TAPE_DEBUG	    debug_text_event (tape_debug_area,3,"b:retryreq:");	    debug_int_event (tape_debug_area,3,(long)ti->cqr);#endif	    rc = do_IO (ti->devinfo.irq, ti->cqr->cpaddr, (unsigned long) ti->cqr, 			0x00, ti->cqr->options);	    if (rc) {#ifdef TAPE_DEBUG		debug_text_event (tape_debug_area,3,"b:doIOfail:");		debug_int_event (tape_debug_area,3,(long)ti->cqr);#endif 		continue; // one retry lost 'cause doIO failed	    }	    return;	}	tapeblock_end_request (ti); // check state, inform user, free mem, dev=idl    }    if (ti->cqr!=NULL) BUG(); // tape should be idle now, request should be freed!    if (tapestate_get (ti) == TS_NOT_OPER) {	ti->blk_minor=ti->rew_minor=ti->nor_minor=-1;	ti->devinfo.irq=-1;	return;    }#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))	if (list_empty (&ti->request_queue.queue_head)) {#else

⌨️ 快捷键说明

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