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

📄 tpqic02.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: tpqic02.c,v 1.10 1997/01/26 07:13:20 davem Exp $ * * Driver for tape drive support for Linux-i386 * * Copyright (c) 1992--1996 by H. H. Bergman. All rights reserved. * Current e-mail address: hennus@cybercomm.nl * * Distribution of this program in executable form is only allowed if * all of the corresponding source files are made available through the same * medium at no extra cost. * * I will not accept any responsibility for damage caused directly or * indirectly by this program, or code derived from this program. * * Use this code at your own risk. Don't blame me if it destroys your data! * Make sure you have a backup before you try this code. * * If you make changes to my code and redistribute it in source or binary * form you must make it clear to even casual users of your code that you * have modified my code, clearly point out what the changes exactly are * (preferably in the form of a context diff file), how to undo your changes, * where the original can be obtained, and that complaints/requests about the * modified code should be directed to you instead of me. * * This driver was partially inspired by the 'wt' driver in the 386BSD * source distribution, which carries the following copyright notice: * *  Copyright (c) 1991 The Regents of the University of California. *  All rights reserved. * * You are not allowed to change this line nor the text above. * * 2001/02/26	Minor s/suser/capable/ * * 1996/10/10   Emerald changes * * 1996/05/21	Misc changes+merges+cleanups + I/O reservations * * 1996/05/20	Module support patches submitted by Brian McCauley. * * 1994/05/03	Initial attempt at Mountain support for the Mountain 7150. * Based on patches provided by Erik Jacobson. Still incomplete, I suppose. * * 1994/02/07	Archive changes & some cleanups by Eddy Olk. * * 1994/01/19	Speed measuring stuff moved from aperf.h to delay.h. *		BogoMips (tm) introduced by Linus. * * 1993/01/25	Kernel udelay. Eof fixups. *  * 1992/09/19	Some changes based on patches by Eddy Olk to support * 		Archive SC402/SC499R controller cards. * * 1992/05/27	First release. * * 1992/05/26	Initial version. Copyright H. H. Bergman 1992 *//* After the legalese, now the important bits: *  * This is a driver for the Wangtek 5150 tape drive with  * a QIC-02 controller for ISA-PC type computers. * Hopefully it will work with other QIC-02 tape drives as well. * * Make sure your setup matches the configuration parameters. * Also, be careful to avoid IO conflicts with other devices! *//*#define TDEBUG*/#define REALLY_SLOW_IO		/* it sure is ... */#include <linux/module.h>#include <linux/config.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/errno.h>#include <linux/mtio.h>#include <linux/fcntl.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/tpqic02.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/smp_lock.h>#include <linux/devfs_fs_kernel.h>#include <asm/dma.h>#include <asm/system.h>#include <asm/io.h>#include <asm/uaccess.h>/* check existence of required configuration parameters */#if !defined(QIC02_CMD_PORT) || !defined(QIC02_TAPE_IRQ) || !defined(QIC02_TAPE_DMA)# error qic02_tape configuration error#endif#define TPQIC02_NAME	"tpqic02"/* Linux outb() commands have (value,port) as parameters. * One might expect (port,value) instead, so beware! */#ifdef CONFIG_QIC02_DYNCONF/* This holds the dynamic configuration info for the interface * card+drive info if runtime configuration has been selected. */static struct mtconfiginfo qic02_tape_dynconf =	/* user settable */{ 0, 0, BOGUS_IRQ, 0, 0, TPQD_DEFAULT_FLAGS, };static struct qic02_ccb qic02_tape_ccb;	/* private stuff */#elseunsigned long qic02_tape_debug = TPQD_DEFAULT_FLAGS;# if ((QIC02_TAPE_IFC!=WANGTEK) && (QIC02_TAPE_IFC!=ARCHIVE) && (QIC02_TAPE_IFC!=MOUNTAIN))#  error No valid interface card specified# endif#endif				/* CONFIG_QIC02_DYNCONF */static volatile int ctlbits;	/* control reg bits for tape interface */static wait_queue_head_t qic02_tape_transfer;	/* sync rw with interrupts */static volatile struct mtget ioctl_status;	/* current generic status */static volatile struct tpstatus tperror;	/* last drive status */static char rcs_revision[] = "$Revision: 1.10 $";static char rcs_date[] = "$Date: 1997/01/26 07:13:20 $";/* Flag bits for status and outstanding requests. * (Could all be put in one bit-field-struct.) * Some variables need `volatile' because they may be modified * by an interrupt. */static volatile flag status_dead = YES;	/* device is legally dead until proven alive */static flag status_zombie = YES;	/* it's `zombie' until irq/dma allocated */static volatile flag status_bytes_wr = NO;	/* write FM at close or not */static volatile flag status_bytes_rd = NO;	/* (rd|wr) used for rewinding */static volatile unsigned long status_cmd_pending;	/* cmd in progress */static volatile flag status_expect_int = NO;	/* ready for interrupts */static volatile flag status_timer_on = NO;	/* using time-out */static volatile int status_error;	/* int handler may detect error */static volatile flag status_eof_detected = NO;	/* end of file */static volatile flag status_eom_detected = NO;	/* end of recorded media */static volatile flag status_eot_detected = NO;	/* end of tape */static volatile flag doing_read = NO;static volatile flag doing_write = NO;static volatile unsigned long dma_bytes_todo;static volatile unsigned long dma_bytes_done;static volatile unsigned dma_mode;	/* !=0 also means DMA in use */static flag need_rewind = YES;static kdev_t current_tape_dev;static int extra_blocks_left = BLOCKS_BEYOND_EW;static struct timer_list tp_timer;/* return_*_eof: *	NO:	not at EOF, *	YES:	tell app EOF was reached (return 0). * * return_*_eof==YES && reported_*_eof==NO  ==> *	return current buffer, next time(s) return EOF. * * return_*_eof==YES && reported_*_eof==YES  ==> *	at EOF and application knows it, so we can *	move on to the next file. * */static flag return_read_eof = NO;	/* set to signal app EOF was reached */static flag return_write_eof = NO;static flag reported_read_eof = NO;	/* set when we've done that */static flag reported_write_eof = NO;/* This is for doing `mt seek <blocknr>' */static char seek_addr_buf[AR_SEEK_BUF_SIZE];/* In write mode, we have to write a File Mark after the last block written,  * when the tape device is closed. Tape repositioning and reading in write * mode is allowed as long as no actual writing has been done. After writing * the File Mark, repositioning and reading are allowed again. */static int mode_access;		/* access mode: READ or WRITE */static int qic02_get_resources(void);static void qic02_release_resources(void);/* This is a pointer to the actual kernel buffer where the interrupt routines * read from/write to. It is needed because the DMA channels 1 and 3 cannot * always access the user buffers. [The kernel buffer must reside in the * lower 16MBytes of system memory because of the DMA controller.] The user * must ensure that a large enough buffer is passed to the kernel, in order * to reduce tape repositioning wear and tear. */static void *buffaddr;		/* virtual address of buffer *//* This translates minor numbers to the corresponding recording format: */static const char *format_names[] = {	"not set",		/* for dumb drives unable to handle format selection */	"11",			/* extinct */	"24",	"120",	"150",	"300",			/* untested. */	"600"			/* untested. */};/* `exception_list' is needed for exception status reporting. * Exceptions 1..14 are defined by QIC-02 rev F. * The drive status is matched sequentially to each entry, * ignoring irrelevant bits, until a match is found. If no * match is found, exception number 0 is used. (That should of * course never happen...) The original table was based on the * "Exception Status Summary" in QIC-02 rev F, but some changes * were required to make it work with real-world drives. * * Exception 2 (CNI) is changed to also cover status 0x00e0 (mask USL), * Exception 4 (EOM) is changed to also cover status 0x8288 (mask EOR), * Exception 11 (FIL) is changed to also cover status 0x0089 (mask EOM). * Exception 15 (EOR) is added for seek-to-end-of-data (catch EOR), * Exception 16 (BOM) is added for beginning-of-media (catch BOM). * * Had to swap EXC_NDRV and EXC_NCART to ensure that extended EXC_NCART * (because of the incorrect Wangtek status code) doesn't catch the * EXC_NDRV first. */static struct exception_list_type {	unsigned short mask, code;	const char *msg;	/* EXC_nr attribute should match with tpqic02.h */} exception_list[] = {	{	0, 0, "Unknown exception status code", /* extra: 0 */ },	{	~(0), TP_ST0 | TP_CNI | TP_USL | TP_WRP,		    "Drive not online" /* 1 */ },	    /* Drive presence goes before cartridge presence. */	{		~(TP_WRP | TP_USL), TP_ST0 | TP_CNI,		    /* My Wangtek 5150EQ sometimes reports a status code		     * of 0x00e0, which is not a valid exception code, but		     * I think it should be recognized as "NO CARTRIDGE".		     */	"Cartridge not in place" /* 2 */ },	{	(unsigned short) ~(TP_ST1 | TP_BOM), (TP_ST0 | TP_WRP),		    "Write protected cartridge" /* 3 */ },	{	(unsigned short) ~(TP_ST1 | TP_EOR), (TP_ST0 | TP_EOM),		    "End of media" /* 4 */ },	{	~TP_WRP, TP_ST0 | TP_UDA | TP_ST1 | TP_BOM,		    "Read or Write abort. Rewind tape." /* 5 */ },	{	~TP_WRP, TP_ST0 | TP_UDA,		    "Read error. Bad block transferred." /* 6 */ },	{	~TP_WRP, TP_ST0 | TP_UDA | TP_BNL,		    "Read error. Filler block transferred." /* 7 */ },	{	~TP_WRP, TP_ST0 | TP_UDA | TP_BNL | TP_ST1 | TP_NDT,		    "Read error. No data detected." /* 8 */ },	{	~TP_WRP,		    TP_ST0 | TP_EOM | TP_UDA | TP_BNL | TP_ST1 |		    TP_NDT, "Read error. No data detected. EOM." /* 9 */ },	{	~(TP_WRP | TP_MBD | TP_PAR | TP_EOR),		    TP_ST0 | TP_UDA | TP_BNL | TP_ST1 | TP_NDT |		    TP_BOM,		    "Read error. No data detected. BOM." /* 10 */ },	{		~(TP_WRP | TP_EOM), TP_ST0 | TP_FIL,		    /* Status 0x0089 (EOM & FM) is viewed as an FM,		     * because it can only happen during a read.		     * EOM is checked separately for an FM condition.		     */	"File mark detected" /* 11 */ },	{	~(TP_ST0 | TP_CNI | TP_USL | TP_WRP | TP_BOM),		    TP_ST1 | TP_ILL, "Illegal command" /* 12 */ },	{	~(TP_ST0 | TP_CNI | TP_USL | TP_WRP | TP_BOM),		    TP_ST1 | TP_POR, "Reset occurred" /* 13 */ },	{		~TP_WRP, TP_ST0 | TP_FIL | TP_MBD,	/* NOTE: ST1 not set! */	"Marginal block detected" /* 14 */ },	{		~(TP_ST0 | TP_WRP | TP_EOM | TP_UDA | TP_BNL | TP_FIL |		  TP_NDT), TP_ST1 | TP_EOR,		/********** Is the extra TP_NDT really needed Eddy? **********/	"End of recorded media" /* extra: 15 */ },	    /* 15 is returned when SEEKEOD completes successfully */	{	~(TP_WRP | TP_ST0), TP_ST1 | TP_BOM, "Beginning of media" /* extra: 16 */ }};#define NR_OF_EXC	(sizeof(exception_list)/sizeof(struct exception_list_type))/* Compare expected struct size and actual struct size. This * is useful to catch programs compiled with old #includes. */#define CHECK_IOC_SIZE(structure) \	if (_IOC_SIZE(iocmd) != sizeof(struct structure)) { \		tpqputs(TPQD_ALWAYS, "sizeof(struct " #structure \			") does not match!"); \		return -EFAULT; \	} \static void tpqputs(unsigned long flags, const char *s){	if ((flags & TPQD_ALWAYS) || (flags & QIC02_TAPE_DEBUG))		printk(TPQIC02_NAME ": %s\n", s);}				/* tpqputs *//* Perform byte order swapping for a 16-bit word. * * [FIXME] This should probably be in include/asm/ * ([FIXME] i486 can do this faster) */static inline void byte_swap_w(volatile unsigned short *w){	int t = *w;	*w = (t >> 8) | ((t & 0xff) << 8);}/* Init control register bits on interface card. * For Archive, interrupts must be enabled explicitly. * Wangtek interface card requires ONLINE to be set, Archive SC402/SC499R * cards keep it active all the time. */static void ifc_init(void){	if (QIC02_TAPE_IFC == WANGTEK) {	/* || (QIC02_TAPE_IFC == EVEREX) */		ctlbits = WT_CTL_ONLINE;	/* online */		outb_p(ctlbits, QIC02_CTL_PORT);	} else if (QIC02_TAPE_IFC == ARCHIVE) {		ctlbits = 0;	/* no interrupts yet */		outb_p(ctlbits, QIC02_CTL_PORT);		outb_p(0, AR_RESET_DMA_PORT);	/* dummy write to reset DMA */	} else {		/* MOUNTAIN */		ctlbits = MTN_CTL_ONLINE;	/* online, and logic enabled */		outb_p(ctlbits, QIC02_CTL_PORT);	}}				/* ifc_init */static void report_qic_exception(unsigned n){	if (n >= NR_OF_EXC) {		tpqputs(TPQD_ALWAYS, "Oops -- report_qic_exception");		n = 0;	}	if (TPQDBG(SENSE_TEXT) || n == 0) {		printk(TPQIC02_NAME ": sense: %s\n",		       exception_list[n].msg);	}}				/* report_qic_exception *//* Try to map the drive-exception bits `s' to a predefined "exception number", * by comparing the significant exception bits for each entry in the * exception table (`exception_list[]'). * It is assumed that s!=0. */static int decode_qic_exception_nr(unsigned s){	int i;	for (i = 1; i < NR_OF_EXC; i++) {		if ((s & exception_list[i].mask) == exception_list[i].code) {			return i;		}	}	printk(TPQIC02_NAME	       ": decode_qic_exception_nr: exception(%x) not recognized\n",	       s);	return 0;}				/* decode_qic_exception_nr *//* Perform appropriate action for certain exceptions. * should return a value to indicate stop/continue (in case of bad blocks) */static void handle_qic_exception(int exnr, int exbits){	if (exnr == EXC_NCART) {		/* Cartridge was changed. Redo sense().		 * EXC_NCART should be handled in open().		 * It is not permitted to remove the tape while		 * the tape driver has open files. 		 */		need_rewind = YES;		status_eof_detected = NO;		status_eom_detected = NO;	} else if (exnr == EXC_XFILLER) {		tpqputs(TPQD_ALWAYS,			"[Bad block -- filler data transferred.]");	} else if (exnr == EXC_XBAD) {		tpqputs(TPQD_ALWAYS, "[CRC failed!]");	} else if (exnr == EXC_MARGINAL) {

⌨️ 快捷键说明

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