Messages in this thread Patch in this message | | | From | Martin Schwidefsky <> | Subject | [PATCH] s390 (5/8): old tape file. | Date | Thu, 12 Dec 2002 19:08:28 +0100 |
| |
Remove last remaining file of the old tape driver.
diffstat: tape.c | 1907 ----------------------------------------------------------------- 1 files changed, 1907 deletions(-)
diff -urN linux-2.5.51/drivers/s390/char/tape.c linux-2.5.51-s390/drivers/s390/char/tape.c --- linux-2.5.51/drivers/s390/char/tape.c Tue Dec 10 03:46:11 2002 +++ linux-2.5.51-s390/drivers/s390/char/tape.c Thu Jan 1 01:00:00 1970 @@ -1,1907 +0,0 @@ -/*********************************************************************** - * drivers/s390/char/tape.c - * tape device driver for S/390 and zSeries tapes. - * - * S390 and zSeries version - * Copyright (C) 2001 IBM Corporation - * Author(s): Carsten Otte <cotte@de.ibm.com> - * Michael Holzheu <holzheu@de.ibm.com> - * Tuan Ngo-Anh <ngoanh@de.ibm.com> - * - *********************************************************************** - */ - -#include "tapedefs.h" // kernel 2.2 compatibility defines - -#include <linux/stddef.h> // defines NULL -#include <linux/proc_fs.h> // for /proc/tapedevices -#include <linux/init.h> // for kernel parameters -#include <linux/kmod.h> // for requesting modules -#include <linux/spinlock.h> // for locks -#include <asm/types.h> // for variable types -#ifdef CONFIG_S390_TAPE_DYNAMIC -#include <asm/s390dyn.h> -#endif -#include "tape.h" -#ifdef CONFIG_S390_TAPE_3590 -#include "tape3590.h" -#endif -#ifdef CONFIG_S390_TAPE_3490 -#include "tape3490.h" -#endif -#ifdef CONFIG_S390_TAPE_3480 -#include "tape3480.h" -#endif -#ifdef CONFIG_S390_TAPE_BLOCK -#include "tapeblock.h" -#endif -#ifdef CONFIG_S390_TAPE_CHAR -#include "tapechar.h" -#endif -#ifdef CONFIG_PROC_FS -#include <linux/vmalloc.h> -#endif -#define PRINTK_HEADER "T390:" -#define TAPE_MAX_DEVREGS (256 / TAPE_MINORS_PER_DEV) - -#define TAPE_NO_IO 0 -#define TAPE_DO_IO 1 - -#define TAPE_CIO_PRIVATE_DATA - -#ifdef CONFIG_KMOD -#define tape_request_module(a) request_module(a) -#else -#define tape_request_module(a) -#endif - -/******************************************************************* - * Internal Prototypes - *******************************************************************/ - -static void tape_do_irq (int irq, void *int_parm, struct pt_regs *regs); -static inline int tape_halt_io(tape_dev_t* td); -static void tape_wait(tape_ccw_req_t* treq); -#ifdef CONFIG_S390_TAPE_DYNAMIC -/* functions for dyn. dev. attach/detach */ -static int tape_oper_handler ( int irq, struct _devreg *dreg); -static void tape_noper_handler ( int irq, int status ); -#endif -static inline void tape_disable_device(tape_dev_t* td); -static inline int tape_enable_device(tape_dev_t* td); - - -/******************************************************************* - * GLOBALS - *******************************************************************/ - -static devreg_t *tape_devreg[TAPE_MAX_DEVREGS]; -static int tape_devregct=0; -static int tape_autoprobe = 1; -static tape_discipline_t *tape_first_disc = NULL; -tape_dev_t *tape_first_dev = NULL; -tape_frontend_t *tape_first_front = NULL; -char *tape[256] = { NULL, }; - -/* - * Lock hirarchy: - * tape_discipline_lock > tape_dev_lock > td->lock - */ - -rwlock_t tape_dev_lock=RW_LOCK_UNLOCKED; -static rwlock_t tape_discipline_lock=RW_LOCK_UNLOCKED; - -#ifdef TAPE_DEBUG -debug_info_t *tape_dbf_area = NULL; -#endif - -const char* tape_med_st_verbose[MS_SIZE]={ - "UNKNOWN ", - "LOADED ", - "UNLOADED" -}; - -const char* tape_state_verbose[TS_SIZE]={ - "UNUSED", - "IN_USE", - "INIT ", - "NOT_OP" -}; - -const char* tape_op_verbose[TO_SIZE] = { - "BLK", - "BSB", - "BSF", - "DSE", - "EGA", - "FSB", - "FSF", - "LDI", - "LBL", - "MSE", - "NOP", - "RBA", - "RBI", - "RBU", - "RBL", - "RDC", - "RFO", - "RSD", - "REW", - "RUN", - "SEN", - "SID", - "SNP", - "SPG", - "SWI", - "SMR", - "SYN", - "TIO", - "UNA", - "WRI", - "WTM", - "MSN", - "LOA", - "RCF", /* 3590 */ - "RAT", /* 3590 */ - "NOT" -}; - -/******************************************************************* - * DEVFS Functions - *******************************************************************/ - -#ifdef CONFIG_DEVFS_FS - -/* - * Create devfs root entry (devno in hex) for device td - */ - -static inline devfs_handle_t -tape_mkdevfsroot (tape_dev_t* td) -{ - char devno [10]; - sprintf (devno,"tape/%04x",td->devinfo.devno); - return devfs_mk_dir(NULL, devno, NULL); -} - -/* - * Remove devfs root entry for device td - */ - -static inline void -tape_rmdevfsroot (tape_dev_t* td) -{ - devfs_remove("tape/%04x", td->devinfo.devno); -} - -#endif - -/******************************************************************* - * PROCFS Functions - *******************************************************************/ - -#ifdef CONFIG_PROC_FS -/* functions used in tape_proc_file_ops */ -static ssize_t tape_proc_devices_read (struct file *file, char *user_buf, size_t user_len, loff_t * offset); -static int tape_proc_devices_open (struct inode *inode, struct file *file); -static int tape_proc_devices_release (struct inode *inode, struct file *file); - -/* our proc tapedevices entry */ -static struct proc_dir_entry *tape_proc_devices; - -typedef struct { - char *data; - int len; -} tape_procinfo_t; - -static struct file_operations tape_proc_devices_file_ops = -{ - .owner = THIS_MODULE, - .read = tape_proc_devices_read, /* read */ - .open = tape_proc_devices_open, /* open */ - .release = tape_proc_devices_release, /* close */ -}; - -/* - * Initialize procfs stuff on startup - */ - -static inline void -tape_proc_init (void) { - tape_proc_devices = create_proc_entry ("tapedevices", - S_IFREG | S_IRUGO | S_IWUSR, - &proc_root); - if (tape_proc_devices == NULL) - goto error; - tape_proc_devices->proc_fops = &tape_proc_devices_file_ops; - tape_proc_devices->proc_iops = &tape_proc_devices_inode_ops; - return; - error: - PRINT_WARN ("tape: Cannot register procfs entry tapedevices\n"); - return; -} - -/* - * Open function for /proc/tapedevices - */ - -static int -tape_proc_devices_open (struct inode *inode, struct file *file) -{ - tape_dev_t* td; - tape_procinfo_t* procinfo; - char* data = NULL; - int size=0,check_size = -1; - int pos=0; - int rc=0; - long lockflags,lockflags2; - tape_ccw_req_t *treq; - - procinfo = kmalloc (sizeof(tape_procinfo_t),GFP_KERNEL); - if (!procinfo){ - rc = -ENOMEM; - goto out_no_lock; - } - - /* Find out mem size for output, ensure that after releasing lock */ - /* (vmalloc must not be called with interrupts disabled) no devices */ - /* have been added/removed */ - - do{ - size = 100; // Headline - read_lock_irqsave(&tape_dev_lock,lockflags); - - for (td=tape_first_dev;td!=NULL;td=td->next) - size+=100; // FIXME: Guess better! - - if(size == check_size) - break; - - read_unlock_irqrestore(&tape_dev_lock,lockflags); - - if(data) - vfree(data); - data=vmalloc(size); - if (!data) { - kfree (procinfo); - rc = -ENOMEM; - goto out_no_lock; - } - check_size = size; - }while (1); - - // We have the tape_dev lock now - -#ifdef CONFIG_S390_TAPE_CHAR - pos+=sprintf(data+pos,"TapeNo\tDevNo\tCuType\tCuModel\tDevType\tDevMod\tBlkSize\tState\tOp\tMedState\n"); -#else - pos+=sprintf(data+pos,"TapeNo\tDevNo\tCuType\tCuModel\tDevType\tDevMod\tState\tOp\tMedState\n"); -#endif - - for (td=tape_first_dev;td!=NULL;td=td->next) { - s390irq_spin_lock_irqsave (td->devinfo.irq,lockflags2); - treq = tape_get_active_ccw_req(td); - pos+=sprintf(data+pos,"%d\t",td->first_minor/TAPE_MINORS_PER_DEV); - pos+=sprintf(data+pos,"%04X\t",td->devinfo.devno); - pos+=sprintf(data+pos,"%04X\t",td->devinfo.sid_data.cu_type); - pos+=sprintf(data+pos,"%02X\t",td->devinfo.sid_data.cu_model); - pos+=sprintf(data+pos,"%04X\t",td->devinfo.sid_data.dev_type); - pos+=sprintf(data+pos,"%02X\t",td->devinfo.sid_data.dev_model); -#ifdef CONFIG_S390_TAPE_CHAR - if(td->char_data.block_size == 0) - pos+=sprintf(data+pos,"auto\t"); - else - pos+=sprintf(data+pos,"%i\t",td->char_data.block_size); -#endif - pos+=sprintf(data+pos,"%s\t",((tape_state_get(td) >= 0) && - (tape_state_get(td) < TS_SIZE)) ? - tape_state_verbose[tape_state_get (td)] : "UNKNOWN"); - pos+=sprintf(data+pos,"%s\t",(treq != NULL) ? - tape_op_verbose[treq->op] : "---"); - pos+=sprintf(data+pos,"%s\n",tape_med_st_verbose[td->medium_state]); - s390irq_spin_unlock_irqrestore (td->devinfo.irq,lockflags2); - } - - procinfo->data=data; - procinfo->len=pos; - if (pos>size) BUG(); // we've overwritten some memory - file->private_data= (void*) procinfo; - read_unlock_irqrestore(&tape_dev_lock,lockflags); -out_no_lock: - return rc; -} - -/* - * Read function for /proc/tapedevices - */ - -static ssize_t -tape_proc_devices_read (struct file *file, char *user_buf, size_t user_len, loff_t * offset) -{ - loff_t len = 0; - tape_procinfo_t *p_info = (tape_procinfo_t *) file->private_data; - - if (*offset >= p_info->len) { - goto out; /* EOF */ - } else { - len = user_len<(p_info->len - *offset)?user_len:(p_info->len - *offset); - if (copy_to_user (user_buf, &(p_info->data[*offset]), len)) - return -EFAULT; - (*offset) += len; - } -out: - return len; -} - -/* - * Close function for /proc/tapedevices - */ - -static int -tape_proc_devices_release (struct inode *inode, struct file *file) -{ - int rc = 0; - tape_procinfo_t *p_info = (tape_procinfo_t *) file->private_data; - vfree(p_info->data); - kfree (p_info); - return rc; -} - -/* - * Cleanup all stuff registered to the procfs - */ -static inline void -tape_proc_cleanup (void) -{ - if (tape_proc_devices != NULL) - remove_proc_entry ("tapedevices", &proc_root); -} - -#endif /* CONFIG_PROC_FS */ - -/******************************************************************* - * Wait/Wakeup Functions - *******************************************************************/ - -static void tape_wake_up_remove(tape_ccw_req_t* treq){ - tape_remove_ccw_req(treq->tape_dev,treq); - tape_free_ccw_req(treq); -} - -static void tape_wake_up(tape_ccw_req_t* treq){ - treq->wakeup = NULL; - wake_up(&treq->wq); -} - -static void tape_wake_up_interruptible(tape_ccw_req_t* treq){ - treq->wakeup = NULL; - wake_up_interruptible(&treq->wq); -} - -#ifdef CONFIG_S390_TAPE_BLOCK -static void tape_schedule_tapeblock(tape_ccw_req_t* treq){ - treq->wakeup = NULL; - tapeblock_schedule_exec_io((tape_dev_t*)(treq->tape_dev));; -} -#endif - -static void tape_wait_event(tape_ccw_req_t* treq){ - wait_event (treq->wq,(treq->wakeup == NULL)); -} - -static void tape_wait_event_interruptible(tape_ccw_req_t* treq){ - wait_event_interruptible(treq->wq,(treq->wakeup == NULL)); - if (signal_pending (current)) { - treq->rc = tape_halt_io(treq->tape_dev); - if(treq->rc == -ERESTARTSYS) - PRINT_INFO("IO stopped on irq %d\n",treq->tape_dev->devinfo.irq); /* FIXME: only put into dbf */ - else if(treq->rc == 0) - PRINT_INFO("could not stop IO,irq was faster on irq %d\n",treq->tape_dev->devinfo.irq); /* FIXME: only put into dbf */ - else - PRINT_WARN("IO error while stopping IO on irq %d\n",treq->tape_dev->devinfo.irq); - } -} - -static void tape_wait_event_interruptible_nohaltio(tape_ccw_req_t* treq){ - wait_event_interruptible(treq->wq,(treq->wakeup == NULL)); -} - -/******************************************************************* - * DYNAMIC ATTACH/DETACH Functions - *******************************************************************/ - -static inline void -tape_init_devregs(void) -{ - long lockflags; - write_lock_irqsave(&tape_dev_lock,lockflags); - memset(tape_devreg,0,sizeof(devreg_t*) * TAPE_MAX_DEVREGS); - write_unlock_irqrestore(&tape_dev_lock,lockflags); -} - -/* - * Alloc a devreg for a devno - */ - -static inline devreg_t * -tape_create_devno_devreg (int devno) -{ - devreg_t *devreg = kmalloc (sizeof (devreg_t), GFP_KERNEL); - if (devreg != NULL) { - memset (devreg, 0, sizeof (devreg_t)); - devreg->ci.devno = devno; - devreg->flag = DEVREG_TYPE_DEVNO; - devreg->oper_func = tape_oper_handler; - } - return devreg; -} - -/* - * Alloc a devreg for a cu-type - */ - -static inline devreg_t * -tape_create_cu_devreg (int cu_type) -{ - devreg_t *devreg = kmalloc (sizeof (devreg_t), GFP_KERNEL); - if (devreg != NULL) { - memset (devreg, 0, sizeof (devreg_t)); - devreg->ci.hc.ctype = cu_type; - devreg->flag = DEVREG_MATCH_CU_TYPE | DEVREG_TYPE_DEVCHARS; - devreg->oper_func = tape_oper_handler; - } - return devreg; -} - -/* - * Create devregs for device numbers from "from" to "to" - */ - -static inline void -tape_create_devregs_range(int from, int to) -{ - int i; - long lockflags; - - write_lock_irqsave(&tape_dev_lock,lockflags); - for (i=from;i<=to;i++) { - // register for attch/detach of a devno - if(tape_devregct >= TAPE_MAX_DEVREGS){ - PRINT_WARN ("Could not create devregs for devno range %04x - %04x.\n",i,to); - PRINT_WARN ("These devices cannot be used. Use autoprobe\n"); - PRINT_WARN ("or specify device ranges more precisely!\n"); - break; - } - tape_devreg[tape_devregct]=tape_create_devno_devreg(i); - if (tape_devreg[tape_devregct]!=NULL) { - s390_device_register (tape_devreg[tape_devregct++]); - } else { - PRINT_WARN ("Could not create devreg for devno %04x, dyn. attach for this devno deactivated.\n",i); - } - } - write_unlock_irqrestore(&tape_dev_lock,lockflags); - return; -} - -/* - * Create a devreg for a discipline - */ - -static inline void -tape_create_devreg_for_disc(tape_discipline_t *disc) -{ - int devreg_nr; - long lockflags; - - write_lock_irqsave(&tape_dev_lock,lockflags); - for(devreg_nr = 0; devreg_nr < TAPE_MAX_DEVREGS; devreg_nr++){ - if(tape_devreg[devreg_nr] == NULL) - break; - } - if(devreg_nr == TAPE_MAX_DEVREGS){ - PRINT_WARN ("Could not create devreg for discipline (%x), dyn. attach for this discipline deactivated.\n",disc->cu_type); - goto out_unlock; - } - tape_devreg[devreg_nr] = tape_create_cu_devreg(disc->cu_type); - if (tape_devreg[devreg_nr] != NULL) { - s390_device_register(tape_devreg[devreg_nr]); - } else { - PRINT_WARN("Could not alloc devreg: Out of memory\n"); - PRINT_WARN("Dynamic attach/detach will not work!\n"); - } -out_unlock: - write_unlock_irqrestore(&tape_dev_lock,lockflags); - return; -} - -/* - * Free all devregs - */ - -static inline void -tape_delete_all_devregs(void) -{ - int i; - long lockflags; - - write_lock_irqsave(&tape_dev_lock,lockflags); - - for(i = 0; i < TAPE_MAX_DEVREGS; i++){ - if(tape_devreg[i]){ - s390_device_unregister(tape_devreg[i]); - kfree(tape_devreg[i]); - } - } - memset(tape_devreg,0,sizeof(devreg_t*) * TAPE_MAX_DEVREGS); - write_unlock_irqrestore(&tape_dev_lock,lockflags); -} - -/* - * Free Devregs for a discipline - */ - -static inline void -tape_delete_devreg_for_disc(tape_discipline_t* disc) -{ - int i; - long lockflags; - - write_lock_irqsave(&tape_dev_lock,lockflags); - - for(i = 0; i < TAPE_MAX_DEVREGS; i++){ - if(tape_devreg[i]){ - if(tape_devreg[i]->ci.hc.ctype == disc->cu_type){ - s390_device_unregister(tape_devreg[i]); - kfree(tape_devreg[i]); - tape_devreg[i] = NULL; - } - } - } - - write_unlock_irqrestore(&tape_dev_lock,lockflags); -} - -/******************************************************************* - * Module/Kernel Parameter Handling - *******************************************************************/ - -#ifndef MODULE -static char tape_parm_string[1024] __initdata = { 0, }; - -/* - * Get Kernel parameters (str) seperated by "," - * and store them into the tape[] array - */ - -static void -tape_split_parm_string (char *str) -{ - char *tmp = str; - int count = 0; - while (tmp != NULL && *tmp != '\0') { - char *end; - int len; - end = strchr (tmp, ','); - if (end == NULL) { - len = strlen (tmp) + 1; - } else { - len = (long) end - (long) tmp + 1; - *end = '\0'; - end++; - } - tape[count] = kmalloc (len * sizeof (char), GFP_ATOMIC); - if (tape[count] == NULL) { - printk (KERN_WARNING PRINTK_HEADER - "can't store tape= parameter no %d\n", - count + 1); - break; - } - memcpy (tape[count], tmp, len * sizeof (char)); - count++; - tmp = end; - }; -} - -/* - * This function is called for each "tape=" Kernel parameter - * at Kernel initialization. We need tape_parm_setup because of - * 2.2 compatibility (At least I assume this :-)) - */ - -void __init -tape_parm_setup (char *str, int *ints) -{ - int len = strlen (tape_parm_string); - if (len != 0) { - strcat (tape_parm_string, ","); - } - strcat (tape_parm_string, str); -} - -int __init -tape_parm_call_setup (char *str) -{ - int dummy; - tape_parm_setup (str, &dummy); - return 1; -} - -__setup("tape=", tape_parm_call_setup); -#endif /* not defined MODULE */ - - -/* - * Convert string to int - */ - -static inline int -tape_parm_strtoul (char *str, char **stra) -{ - char *temp = str; - int val; - if (*temp == '0') { - temp++; /* strip leading zero */ - if (*temp == 'x') - temp++; /* strip leading x */ - } - val = simple_strtoul (temp, &temp, 16); /* interpret anything as hex */ - *stra = temp; - return val; -} - -/* - * Parse Kernel/Module Parameters and create devregs for dynamic attach/detach - */ - -static inline void -tape_parm_parse (char **str) -{ - char *temp; - int from, to; - - if (*str==NULL) { - /* no params present -> leave */ - return; - } - while (*str) { - temp = *str; - from = 0; - to = 0; - from = tape_parm_strtoul (temp, &temp); - to = from; - if (*temp == '-') { - temp++; - to = tape_parm_strtoul (temp, &temp); - } - tape_create_devregs_range(from,to); - str++; - } -} - -/******************************************************************* - * Tape device (td) functions for create, free, enq, deq, enable, - * disable, get and put - *******************************************************************/ - -/* - * Enable Device - */ - -static inline int -tape_enable_device(tape_dev_t* td) -{ -#ifdef CONFIG_DEVFS_FS - tape_frontend_t* frontend; -#endif - int rc = 0; - - if(td->discipline->setup_device(td) != 0){ - rc = -ENOMEM; - goto out; - } - - /* Register IRQ */ - -#ifdef TAPE_CIO_PRIVATE_DATA - #ifdef CONFIG_S390_TAPE_DYNAMIC - rc = s390_request_irq_special (td->devinfo.irq, tape_do_irq, - tape_noper_handler,0, TAPE_MAGIC, &(td->devstat)); - #else - rc = s390_request_irq (td->devinfo.irq, tape_do_irq, 0, TAPE_MAGIC, &(td->devstat)); - #endif -#else - #ifdef CONFIG_S390_TAPE_DYNAMIC - rc = s390_request_irq_special (td->devinfo.irq, tape_do_irq, - tape_noper_handler,0, (char*)td, &(td->devstat)); - #else - rc = s390_request_irq (td->devinfo.irq, tape_do_irq, 0, (char*)td, &(td->devstat)); - #endif -#endif /* TAPE_CIO_PRIVATE_DATA */ - if (rc){ - PRINT_WARN ("Cannot register irq %d, rc=%d\n", td->devinfo.irq, rc); - td->discipline->cleanup_device(td); - goto out; - } - /* Create devfs entries */ -#ifdef CONFIG_DEVFS_FS - if (tape_mkdevfsroot(td)==NULL){ - PRINT_WARN ("Cannot create a devfs directory for device %04x\n",td->devinfo.devno); - goto out_undo; - } - - for (frontend=tape_first_front;frontend!=NULL;frontend=frontend->next){ - if(frontend->mkdevfstree(td) == NULL){ - goto out_undo; - } - } -#endif -#ifdef TAPE_CIO_PRIVATE_DATA - s390_set_private_data(td->devinfo.irq,td); -#endif -out: - return rc; -out_undo: - tape_disable_device(td); - return -ENOMEM; -} - -/* - * Disable Device - */ - -static inline void -tape_disable_device(tape_dev_t* td) -{ -#ifdef CONFIG_DEVFS_FS - tape_frontend_t* frontend; -#endif - td->discipline->cleanup_device(td); -#ifdef TAPE_CIO_PRIVATE_DATA - s390_set_private_data(td->devinfo.irq,NULL); -#else - ioinfo[td->devinfo.irq]->irq_desc.name = NULL; -#endif - - free_irq (td->devinfo.irq, &(td->devstat)); -#ifdef CONFIG_DEVFS_FS - for (frontend=tape_first_front;frontend!=NULL;frontend=frontend->next) - frontend->rmdevfstree(td); - tape_rmdevfsroot(td); -#endif - tape_state_set(td,TS_NOT_OPER); -} - -/* - * Append Tape device (td) to our tape info list - * Must be called with hold tape_dev_lock - */ - -static inline void -tape_enq_device(tape_dev_t* td) -{ - tape_dev_t *temptd = NULL; - - if (tape_first_dev == NULL) { - tape_first_dev = td; - } else { - temptd = tape_first_dev; - while (temptd->next != NULL) - temptd = temptd->next; - temptd->next = td; - } -} - -/* - * Remove Tape device (td) from our tape info list - * Must be called with hold tape_dev_lock - */ - -static inline void -tape_deq_device(tape_dev_t* td) -{ - tape_dev_t* lasttd; - - if (td==tape_first_dev) { - tape_first_dev=td->next; - } else { - lasttd=tape_first_dev; - while (lasttd->next!=td) lasttd=lasttd->next; - lasttd->next=td->next; - } -} - - -/* - * Get Free minor number - * Must be called with held tape_dev_lock - */ - -static inline int -tape_get_new_minor(int devno) -{ - int i,tape_num = -1; - tape_dev_t* newtape; - - if(!tape_autoprobe){ - /* we have static device ranges, so fingure out the */ - /* tape_num of the attached tape */ - for (i=0;i<tape_devregct;i++){ - if (tape_devreg[i]->ci.devno==devno) { - tape_num=TAPE_MINORS_PER_DEV*i; - goto out; - } - } - } else { - /* we are running in autoprobe mode, find a free */ - /* tape_num */ - i = 0; - newtape=tape_first_dev; - while (newtape!=NULL) { - if (newtape->first_minor==i) { - /* tape num in use. try next one */ - i+=TAPE_MINORS_PER_DEV; - newtape=tape_first_dev; - } else { - /* tape num not used by newtape. look at next */ - /* tape info */ - newtape=newtape->next; - } - } - if(i>255) /* No more minor available */ - tape_num = -1; - else - tape_num = i; - } -out: - return tape_num; -} - - -/* - * Create device: Alloc, enable and enq device - */ - -static inline tape_dev_t* -tape_create_device(int irq, int devno, tape_discipline_t* disc) -{ - int rc = 0; - int tape_num; - tape_dev_t *td; - long lockflags; - - write_lock_irqsave(&tape_dev_lock,lockflags); - - td = kmalloc (sizeof (tape_dev_t), GFP_ATOMIC); - if (td == NULL) { - tape_sprintf_exception (tape_dbf_area,2,"ti:no mem \n"); - PRINT_INFO ("tape: can't allocate memory for " - "tape info structure\n"); - goto error; - } - memset(td,0,sizeof(tape_dev_t)); - tape_num = tape_get_new_minor(devno); - if(tape_num == -1){ - PRINT_WARN("tape: could not get minor for tape %x\n",devno); - goto error; - } - rc = get_dev_info_by_irq (irq, &(td->devinfo)); - if (rc == -ENODEV) { /* end of device list */ - goto error; - } - td->discipline = disc; - atomic_set(&(td->use_count),1); - td->first_minor = tape_num; - td->medium_state = MS_UNKNOWN; - td->next = NULL; - td->discdata = td->treq = NULL; - tape_state_set (td, TS_INIT); - td->discdata=NULL; - td->last_op = TO_NOTHING; - - if(td->discipline->setup_device(td) != 0) - goto error; - if(tape_enable_device(td) !=0) - goto error; - tape_enq_device(td); - PRINT_INFO ("using devno %04x with discipline %04x on irq %d as tape device %d\n",devno,disc->cu_type,irq,tape_num/2); - write_unlock_irqrestore(&tape_dev_lock,lockflags); - return td; -error: - tape_sprintf_event (tape_dbf_area,3,"tsetup err: %x\n",rc); - if(td) - kfree (td); - write_unlock_irqrestore(&tape_dev_lock,lockflags); - return NULL; -} - -/* - * Free Device storage - */ - -static void -tape_free_device(tape_dev_t* td) -{ - if (TAPE_BUSY(td)) - BUG(); /* one should _not_ free the device when a request is pending */ - tape_sprintf_event (tape_dbf_area,6,"free irq: %x\n",td->devinfo.irq); - kfree(td); -} - -/* - * Decrement use count of tape structure - * if use count == 0 tape structure is freed - */ - -inline void -tape_put_device(tape_dev_t* td) -{ - if (td==NULL) - BUG(); - if(atomic_dec_and_test(&(td->use_count))) - tape_free_device(td); -} - -/* - * Find the tape_dev_t structure associated with member - * and increase use count: - * - * member: TAPE_MEMB_IRQ, TAPE_MEMB_MINOR - */ - -tape_dev_t * -__tape_get_device_by_member(unsigned long value, int member) -{ - tape_dev_t *td = NULL; - long lockflags; - - read_lock_irqsave(&tape_dev_lock,lockflags); - td = tape_first_dev; - while(td != NULL) { - switch(member){ - case TAPE_MEMB_IRQ: - if(td->devinfo.irq == value) - goto out; - break; - case TAPE_MEMB_MINOR: - if((value >= td->first_minor) && - (value < (td->first_minor + TAPE_MINORS_PER_DEV)) ) - goto out; - break; - case TAPE_MEMB_QUEUE: - if(((unsigned long)(&td->blk_data.request_queue)) == value) - goto out; - break; - default: - BUG(); - } - td = td->next; - } -out: - if(td) // found! - atomic_inc(&(td->use_count)); - read_unlock_irqrestore(&tape_dev_lock,lockflags); - return td; -} - -/* - * Scan all irqs an create tape devices for all matching cu types - */ - -static inline void -tape_create_devs_for_disc(tape_discipline_t* disc) -{ - int irq,i; - tape_dev_t* td = NULL; - s390_dev_info_t dinfo; - - for (irq = get_irq_first(); irq!=-ENODEV; irq=get_irq_next(irq)) { - if(get_dev_info_by_irq (irq, &dinfo) == -ENODEV) - continue; - if(disc->cu_type != dinfo.sid_data.cu_type) - /* Wrong type - try next one */ - continue; - - tape_sprintf_event (tape_dbf_area,3,"det irq: %x\n",irq); - tape_sprintf_event (tape_dbf_area,3,"cu : %x\n",disc->cu_type); - - - if(!tape_autoprobe) { - for( i=0; i<tape_devregct; i++ ) { - if(tape_devreg[i]->ci.devno == dinfo.devno) { - td = tape_create_device(irq, dinfo.devno, disc); - if(!td) { - PRINT_WARN( "Could not initialize tape 0x%x\n",dinfo.devno); - continue; - } - if(disc->init_device) - disc->init_device(td); /* XXX */ - tape_state_set (td, TS_UNUSED); - break; - } - } - } - else { - td = tape_create_device(irq,dinfo.devno,disc); - - if(!td){ - PRINT_WARN( "Could not initialize tape 0x%x\n",dinfo.devno); - continue; - } - if(disc->init_device) - disc->init_device(td); /* XXX */ - tape_state_set (td, TS_UNUSED); - } - } -} - -/* - * Go through our tape info list and disable, deq and free all devices with - * matching cu type - */ - -static inline void -tape_delete_devs_for_disc(tape_discipline_t* disc) -{ - tape_dev_t *td; - long lockflags; - - write_lock_irqsave(&tape_dev_lock,lockflags); - td = tape_first_dev; - while (td !=NULL){ - if(td->discipline == disc){ - tape_deq_device(td); - write_unlock_irqrestore(&tape_dev_lock,lockflags); - tape_disable_device(td); - tape_put_device(td); - write_lock_irqsave(&tape_dev_lock,lockflags); - td = tape_first_dev; - } else { - td=td->next; - } - } - write_unlock_irqrestore(&tape_dev_lock,lockflags); -} - -/******************************************************************* - * TAPE Request and IO Functions - *******************************************************************/ - -/* - * Allocate a new tape ccw request - */ - -inline tape_ccw_req_t * -tape_alloc_ccw_req (int cplength, int datasize,int idal_buf_size, tape_op_t operation) -{ - tape_ccw_req_t* treq; - int kmalloc_flags; - if(in_interrupt()) - kmalloc_flags = GFP_ATOMIC; - else - kmalloc_flags = GFP_KERNEL; - - treq = (tape_ccw_req_t*) kmalloc(sizeof(tape_ccw_req_t),kmalloc_flags); - if(!treq) - goto error; - memset(treq,0,sizeof(tape_ccw_req_t)); - treq->kernbuf_size = datasize; - treq->userbuf_size = datasize; - treq->op = operation; - treq->cplength = cplength; - init_waitqueue_head (&treq->wq); - - // alloc small kernel buffer - - if(datasize > PAGE_SIZE) - BUG(); - if(datasize > 0){ - // the kernbuf must be below 2GB --> GFP_DMA - treq->kernbuf = kmalloc(datasize,kmalloc_flags | GFP_DMA); - if(!treq->kernbuf) - goto error; - memset(treq->kernbuf, 0, datasize); - } - - // alloc idal kernel buffer - - if(idal_buf_size > 0){ - treq->idal_buf = idalbuf_alloc(idal_buf_size); - if(!treq->idal_buf) - goto error; - } - - if(cplength < 0) - BUG(); - - // the channel program must be below 2GB --> GFP_DMA - treq->cpaddr = kmalloc(cplength * sizeof(ccw1_t), kmalloc_flags | GFP_DMA); - if(!treq->cpaddr) - goto error; - memset(treq->cpaddr, 0, cplength*sizeof(ccw1_t)); - return treq; -error: - tape_sprintf_exception (tape_dbf_area,1,"cqra nomem\n"); - if(treq) - tape_free_ccw_req(treq); - return NULL; -} - -/* - * Free tape ccw request - */ - -void -tape_free_ccw_req (tape_ccw_req_t * treq) -{ - if(!treq) - BUG(); - if(treq->cpaddr) - kfree(treq->cpaddr); - if(treq->kernbuf) - kfree(treq->kernbuf); - if(treq->idal_buf) - idalbuf_free(treq->idal_buf); - kfree(treq); -} - -/* - * Add request to request queue (At the moment queue length = 1) - */ - -static inline int -tape_add_ccw_req(tape_dev_t* td,tape_ccw_req_t* treq) -{ - if(td->treq) - return -1; - td->treq = treq; - treq->tape_dev = td; - return 0; -} - -/* - * Remove request from request queue (At the moment queue length = 1) - */ - -int -tape_remove_ccw_req(tape_dev_t* td,tape_ccw_req_t* treq) -{ - if(treq != td->treq) - BUG(); - td->last_op = treq->op; - td->treq=NULL; - treq->tape_dev=NULL; - return 0; -} - -/* - * Get the active ccw request - */ - -tape_ccw_req_t* -tape_get_active_ccw_req(tape_dev_t* td) -{ - return td->treq; -} - -/* - * Stop the active ccw request - */ - -static inline int -tape_halt_io(tape_dev_t* td) -{ - int retries = 0; - int irq = td->devinfo.irq; - int rc = 0; - long lockflags; - tape_ccw_req_t* treq; - - s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags); - treq = tape_get_active_ccw_req(td); - /* check if interrupt has already been processed */ - if(!treq) - goto out; - if(treq->wakeup == NULL) - goto out; - while (retries < 5){ - if ( retries < 2 ) - rc = halt_IO(irq, (long)treq, treq->options); - else - rc = clear_IO(irq, (long)treq, treq->options); - switch (rc) { - case 0: /* termination successful */ - rc = -ERESTARTSYS; - goto out; - case -ENODEV: - PRINT_INFO ("device gone, retry\n"); /* FIXME: s390dbf only */ - break; - case -EIO: - PRINT_INFO ("I/O error, retry\n"); /* FIXME: s390dbf only */ - break; - case -EBUSY: - PRINT_INFO ( "device busy, retry later\n"); /* FIXME: s390dbf only */ - break; - default: - PRINT_ERR ( "line %d unknown RC=%d, please report" - " to linux390@de.ibm.com\n", __LINE__, rc); - BUG (); - } - retries ++; - } -out: - s390irq_spin_unlock_irqrestore(td->devinfo.irq, lockflags); - return rc; -} - - -/* - * The tape IO function: - * tape_do_io MUST be called with locked td lock! - */ - -static inline int -__tape_do_io(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type,int io) -{ - int rc = 0; - - if ((td==NULL) || (treq==NULL)) - BUG(); - - if(tape_state_get(td) == TS_NOT_OPER){ - rc = -ENODEV; - goto out; - } - if(TAPE_BUSY(td)){ - tape_sprintf_event (tape_dbf_area,1,"tape: IRQ - Tape busy\n"); - rc = -EBUSY; - goto out; - } - tape_add_ccw_req(td,treq); - switch(type){ - case TAPE_REMOVE_REQ_ON_WAKEUP: - treq->wakeup = tape_wake_up_remove; - break; - case TAPE_NO_WAIT: - // needed for retry - break; - case TAPE_WAIT: - treq->wakeup = tape_wake_up; - treq->wait = tape_wait_event; - break; - case TAPE_WAIT_INTERRUPTIBLE: - treq->wakeup = tape_wake_up_interruptible; - treq->wait = tape_wait_event_interruptible; - break; - case TAPE_WAIT_INTERRUPTIBLE_NOHALTIO: - // neded for dummy load - treq->wakeup = tape_wake_up_interruptible; - treq->wait = tape_wait_event_interruptible_nohaltio; - break; -#ifdef CONFIG_S390_TAPE_BLOCK - case TAPE_SCHED_BLOCK: - treq->wakeup = tape_schedule_tapeblock; - treq->wait = NULL; - break; -#endif - default: - BUG(); - } - - if(io) - rc = do_IO(td->devinfo.irq,treq->cpaddr, - (unsigned long)treq, 0x00, treq->options); - - if(rc) { - tape_sprintf_event (tape_dbf_area,1,"tape: DOIO failed with er = %i\n",rc); - treq->wakeup = NULL; - treq->wait = NULL; /*XXX ??*/ - tape_remove_ccw_req(td,treq); - } -out: - return rc; -} - -/* - * Do the io request and wait for it - */ - -int -tape_do_io_and_wait(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type) -{ - int rc = 0; - long lockflags; - if (td==NULL) - BUG(); - s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags); - rc = __tape_do_io(td,treq,type,TAPE_DO_IO); - s390irq_spin_unlock_irqrestore (td->devinfo.irq, lockflags); - if(rc == 0) - tape_wait(treq); - return rc; -} - -/* - * Needed for MTLOAD: Just create a wait request without doing io - */ - -int -tape_do_wait_req(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type) -{ - int rc = 0; - long lockflags; - if (td==NULL) - BUG(); - s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags); - rc = __tape_do_io(td,treq,type,TAPE_NO_IO); - s390irq_spin_unlock_irqrestore (td->devinfo.irq, lockflags); - tape_wait(treq); - return rc; -} - -/* - * Just do the io - */ - -int -tape_do_io(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type) -{ - int rc = 0; - long lockflags; - s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags); - rc = __tape_do_io(td,treq,type,TAPE_DO_IO); - s390irq_spin_unlock_irqrestore (td->devinfo.irq, lockflags); - return rc; -} - -/* - * Just do the io, but we are already locked here (in irq) - */ - -int -tape_do_io_irq(tape_dev_t * td,tape_ccw_req_t *treq,tape_wait_t type) -{ - return __tape_do_io(td,treq,type,TAPE_DO_IO); -} - -/* - * Wait for an io request - */ - -static void -tape_wait(tape_ccw_req_t* treq) -{ - tape_dev_t* td; - if(treq==NULL) - BUG(); - td = treq->tape_dev; - if (td==NULL) - BUG(); - if(treq->wait==NULL) - BUG(); - treq->wait(treq); - tape_remove_ccw_req(td,treq); -} - -/* - * Tape interrupt routine, called from Ingo's I/O layer - */ - -static void -tape_do_irq (int irq, void *int_parm, struct pt_regs *regs) -{ - tape_dev_t *td; -#ifdef TAPE_CIO_PRIVATE_DATA - td = (tape_dev_t*)s390_get_private_data(irq); -#else - td = (tape_dev_t*)ioinfo[irq]->irq_desc.name; -#endif - if(!td) { - PRINT_ERR ("tape: could not get device structure for irq %d in interrupt\n",irq); - goto out; - } - if(td->devstat.dstat != 0x0c){ - tape_sprintf_event (tape_dbf_area,3,"-- Tape Interrupthandler --\n"); - tape_dump_sense_dbf(td); - } - if (tape_state_get(td) == TS_NOT_OPER) { - tape_sprintf_event (tape_dbf_area,6,"tape:device is not operational\n"); - goto out; - } - td->discipline->irq(td); -out: - return; -} - -/* - * Oper Handler is called from Ingo's I/O layer when a new tape device is - * attached. We create a new devinfo for the new device, enable and enq it. - */ - -static int -tape_oper_handler ( int irq, struct _devreg *dreg) { - tape_dev_t* td=tape_first_dev; - int rc=0; - s390_dev_info_t dinfo; - tape_discipline_t* disc; - long lockflags; - - td = tape_get_device_by_irq(irq); - if (td!=NULL) { - // irq is (still) used by tape. tell ingo to try again later - PRINT_ERR ("tape:Oper handler for irq %d called, but irq is still (internally) used.\n",irq); - rc = -EAGAIN; - goto out; - } - - rc = get_dev_info_by_irq (irq, &dinfo); - if (rc == -ENODEV) { - PRINT_ERR ("tape: Cannot get dev info for irq %d in the oper handler.\n",irq); - rc = -EAGAIN; - goto out; - } - - read_lock_irqsave(&tape_discipline_lock,lockflags); - - disc = tape_first_disc; - while ((disc != NULL) && (disc->cu_type != dinfo.sid_data.cu_type)) - disc = (tape_discipline_t *) (disc->next); - - if (disc == NULL){ - PRINT_WARN ("tape: No matching discipline for cu_type %x found in the oper handler, ignoring device %04x.\n",dinfo.sid_data.cu_type,dinfo.devno); - rc = -ENODEV; - goto out_unlock; - } - - /* Allocate tape structure */ - td = tape_create_device(irq,dinfo.devno,disc); - - if (td == NULL) { - PRINT_WARN( "Could not initialize tape 0x%x\n",dinfo.devno); - rc = -ENOBUFS; - goto out_unlock; - } else { - if(disc->init_device) - disc->init_device(td); - } - tape_state_set (td, TS_UNUSED); -out_unlock: - read_unlock_irqrestore(&tape_discipline_lock,lockflags); -out: - return rc; -} - -/* - * Not Oper Handler is called from Ingo's IO layer, when a tape device - * is detached. We deq, disable and free the tape info for this device - */ - -static void -tape_noper_handler ( int irq, int status ) { - tape_dev_t *td; - long lockflags; - tape_ccw_req_t *treq; - - td = tape_get_device_by_irq(irq); - if (td==NULL) { - PRINT_ERR("tape: not operational handler called for irq %x, but tape does not hold this irq.\n",irq); - goto error; - } - - write_lock_irqsave(&tape_dev_lock,lockflags); - tape_deq_device(td); - write_unlock_irqrestore(&tape_dev_lock,lockflags); - - tape_disable_device(td); - - s390irq_spin_lock_irqsave (td->devinfo.irq, lockflags); - treq = tape_get_active_ccw_req(td); - if (treq) { - // device is in use! - treq->rc= -ENODEV; - if(treq->wakeup) - treq->wakeup (treq); - PRINT_WARN ("Tape #%d is detached while it was busy.\n",td->first_minor/TAPE_MINORS_PER_DEV); - } else { - // device is unused! - PRINT_WARN ("Tape #%d is detached now.\n",td->first_minor/TAPE_MINORS_PER_DEV); - } - - s390irq_spin_unlock_irqrestore (td->devinfo.irq, lockflags); - - /* decrement use count twice ! */ - tape_put_device(td); - tape_put_device(td); -error: - return; -} - -/* - * Write sense data to dbf - */ - -void tape_dump_sense_dbf(tape_dev_t* td) -{ - devstat_t *stat = &td->devstat; - const char* op; - if(TAPE_BUSY(td)) - op = tape_op_verbose[tape_get_active_ccw_req(td)->op]; - else - op = "---"; - tape_sprintf_event (tape_dbf_area,3,"DSTAT : %02x CSTAT: %02x\n",stat->dstat,stat->cstat); - tape_sprintf_event (tape_dbf_area,3,"DEVICE: %04x OP : %s\n",td->devinfo.devno,op); - tape_sprintf_event (tape_dbf_area,3,"%08x %08x\n",*((unsigned int*)&stat->ii.sense.data[0]),*((unsigned int*)&stat->ii.sense.data[4])); - tape_sprintf_event (tape_dbf_area,3,"%08x %08x\n",*((unsigned int*)&stat->ii.sense.data[8]),*((unsigned int*)&stat->ii.sense.data[12])); - tape_sprintf_event (tape_dbf_area,3,"%08x %08x\n",*((unsigned int*)&stat->ii.sense.data[16]),*((unsigned int*)&stat->ii.sense.data[20])); - tape_sprintf_event (tape_dbf_area,3,"%08x %08x\n",*((unsigned int*)&stat->ii.sense.data[24]),*((unsigned int*)&stat->ii.sense.data[28])); -} - -/* - * Write sense data to console/dbf - */ - -void -tape_dump_sense (tape_dev_t* td) -{ - devstat_t *stat = &td->devstat; -#if 1 /* XXX */ - PRINT_INFO ("-------------------------------------------------\n"); - PRINT_INFO ("DSTAT : %02x CSTAT: %02x CPA: %04x\n",stat->dstat,stat->cstat,stat->cpa); - PRINT_INFO ("DEVICE: %04x\n",td->devinfo.devno); - if(TAPE_BUSY(td)) - PRINT_INFO("OP : %s\n",tape_op_verbose[tape_get_active_ccw_req(td)->op]); - - PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X " - " %02X%02X%02X%02X %02X%02X%02X%02X \n", - stat->ii.sense.data[0], stat->ii.sense.data[1], - stat->ii.sense.data[2], stat->ii.sense.data[3], - stat->ii.sense.data[4], stat->ii.sense.data[5], - stat->ii.sense.data[6], stat->ii.sense.data[7], - stat->ii.sense.data[8], stat->ii.sense.data[9], - stat->ii.sense.data[10], stat->ii.sense.data[11], - stat->ii.sense.data[12], stat->ii.sense.data[13], - stat->ii.sense.data[14], stat->ii.sense.data[15]); - PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X " - " %02X%02X%02X%02X %02X%02X%02X%02X \n", - stat->ii.sense.data[16], stat->ii.sense.data[17], - stat->ii.sense.data[18], stat->ii.sense.data[19], - stat->ii.sense.data[20], stat->ii.sense.data[21], - stat->ii.sense.data[22], stat->ii.sense.data[23], - stat->ii.sense.data[24], stat->ii.sense.data[25], - stat->ii.sense.data[26], stat->ii.sense.data[27], - stat->ii.sense.data[28], stat->ii.sense.data[29], - stat->ii.sense.data[30], stat->ii.sense.data[31]); - PRINT_INFO ("--------------------------------------------------\n"); -#endif -} - -/******************************************************************* - * TAPE Discipline functions - *******************************************************************/ - -/* - * Register backend discipline - */ - -int -tape_register_discipline(tape_discipline_t *disc) -{ - tape_discipline_t *disc_ptr; - long lockflags; - - disc->next = NULL; - - write_lock_irqsave(&tape_discipline_lock,lockflags); - - if (tape_first_disc == NULL) { - tape_first_disc = disc; - } else { - for(disc_ptr = tape_first_disc; disc_ptr->next!=NULL; disc_ptr=(tape_discipline_t*)disc_ptr->next); - disc_ptr->next = disc; - } - - tape_create_devs_for_disc(disc); - if(tape_autoprobe) - tape_create_devreg_for_disc(disc); - - write_unlock_irqrestore(&tape_discipline_lock,lockflags); - return 0; -} - -/* - * Unregister backend discipline - */ - -void -tape_unregister_discipline(tape_discipline_t* disc) -{ - tape_discipline_t* lastdisc; - long lockflags; - - write_lock_irqsave(&tape_discipline_lock,lockflags); - - tape_delete_devs_for_disc(disc); - if(tape_autoprobe) - tape_delete_devreg_for_disc(disc); - - if (disc==tape_first_disc) { - tape_first_disc=disc->next; - } else { - lastdisc=tape_first_disc; - while (lastdisc->next!=disc) lastdisc=lastdisc->next; - lastdisc->next=disc->next; - } - - disc->shutdown(); - - write_unlock_irqrestore(&tape_discipline_lock,lockflags); -} - -/* - * Cleanup all registered disciplines - */ - -static inline void -tape_cleanup_disciplines (void) -{ - long lockflags; - tape_discipline_t* disc; - /* Unregister all backend disciplines - this also deletes the devices */ - - write_lock_irqsave(&tape_discipline_lock,lockflags); - disc=tape_first_disc; - while (disc != NULL) { - write_unlock_irqrestore(&tape_discipline_lock,lockflags); - tape_unregister_discipline(disc); - kfree(disc); - write_lock_irqsave(&tape_discipline_lock,lockflags); - disc=tape_first_disc; - } - write_unlock_irqrestore(&tape_discipline_lock,lockflags); -} - - -/******************************************************************* - * TAPE Init Functions - *******************************************************************/ - -/* - * tape_print_banner will be called on initialisation and print a nice banner - */ - -static inline void -tape_print_banner (void) -{ - char *opt_char,*opt_block; - - /* print banner */ - PRINT_WARN ("IBM zSeries Tape Device Driver (v%d.%02d).\n",TAPE_VERSION_MAJOR,TAPE_VERSION_MINOR); - PRINT_WARN ("(C) IBM Deutschland Entwicklung GmbH, 2000 - 2001\n"); - opt_char=opt_block="not present"; -#ifdef CONFIG_S390_TAPE_CHAR - opt_char="built in"; -#endif -#ifdef CONFIG_S390_TAPE_BLOCK - opt_block="built in"; -#endif - /* print feature info */ - PRINT_WARN ("character device frontend : %s\n",opt_char); - PRINT_WARN ("block device frontend : %s\n",opt_block); -} - -/* - * tape_init will register the driver for each tape. - */ - -int -tape_init (void) -{ - static int initialized=0; - - if (initialized) // Only init the devices once - return 0; - initialized=1; - - tape_init_devregs(); -#ifdef TAPE_DEBUG - tape_dbf_area = debug_register ( "tape", 2, 2, 3*sizeof(long)); - debug_register_view(tape_dbf_area,&debug_sprintf_view); - tape_sprintf_event (tape_dbf_area,3,"begin init\n"); -#endif /* TAPE_DEBUG */ - tape_print_banner(); -#ifndef MODULE - tape_split_parm_string(tape_parm_string); -#endif -#ifdef CONFIG_DEVFS_FS - devfs_mk_dir (NULL, "tape", NULL); -#endif /* CONFIG_DEVFS_FS */ - - tape_sprintf_event (tape_dbf_area,3,"dev detect\n"); - /* Allocate the tape structures */ - if (*tape!=NULL) { /* if parameters are present */ - PRINT_INFO ("Using ranges supplied in parameters, disabling autoprobe mode.\n"); - tape_parm_parse (tape); - tape_autoprobe = 0; - } else { - PRINT_INFO ("No parameters supplied, enabling autoprobe mode for all supported devices.\n"); - tape_autoprobe = 1; - } -#ifdef CONFIG_PROC_FS - tape_proc_init(); -#endif /* CONFIG_PROC_FS */ -#ifdef CONFIG_S390_TAPE_3480 - tape_register_discipline(tape3480_init()); -#else -#ifndef CONFIG_S390_TAPE - tape_request_module("tape_3480_mod"); -#endif -#endif /* CONFIG_S390_TAPE_3480 */ - -#ifdef CONFIG_S390_TAPE_3490 - tape_register_discipline(tape3490_init()); -#else -#ifndef CONFIG_S390_TAPE - tape_request_module("tape_3490_mod"); -#endif -#endif /* CONFIG_S390_TAPE_3490 */ - -#ifdef CONFIG_S390_TAPE_3590 - tape_register_discipline(tape3590_init()); -#else -#ifndef CONFIG_S390_TAPE - tape_request_module("tape_3590_mod"); -#endif -#endif /* CONFIG_S390_TAPE_3590 */ - return 0; -} - -/******************************************************************* - * TAPE Module functions - *******************************************************************/ - -#ifdef MODULE -MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)"); -MODULE_DESCRIPTION("Linux on zSeries channel attached tape device driver"); -MODULE_PARM (tape, "1-" __MODULE_STRING (256) "s"); - -/* - * The famous init_module - */ - -int -init_module (void) -{ -#ifdef CONFIG_S390_TAPE_CHAR - tapechar_init (); -#endif -#ifdef CONFIG_S390_TAPE_BLOCK - tapeblock_init (); -#endif - return 0; -} - -/* - * Cleanup the frontends - */ -static inline void -tape_cleanup_frontends(void) -{ - tape_frontend_t* frontend, *tempfe; - - /* Now get rid of the frontends */ -#ifdef CONFIG_S390_TAPE_CHAR - tapechar_uninit(); -#endif -#ifdef CONFIG_S390_TAPE_BLOCK - tapeblock_uninit(); -#endif - frontend=tape_first_front; - while (frontend != NULL) { - tempfe = frontend; - frontend = frontend->next; - kfree (tempfe); - } -} - - -/* - * Cleanup module - */ - -void -cleanup_module (void) -{ - tape_sprintf_event (tape_dbf_area,6,"cleaup mod"); - tape_cleanup_disciplines(); -#ifdef CONFIG_DEVFS_FS - devfs_remove("tape"); /* devfs checks for NULL */ -#endif CONFIG_DEVFS_FS -#ifdef CONFIG_PROC_FS - tape_proc_cleanup(); -#endif - tape_cleanup_frontends(); - /* Deallocate devregs in case of not autoprobe */ - if(!tape_autoprobe) - tape_delete_all_devregs(); -#ifdef TAPE_DEBUG - debug_unregister (tape_dbf_area); -#endif /* TAPE_DEBUG */ -} -#endif /* MODULE */ - - -/******************************************************************* - * TAPE Tapestate functions - *******************************************************************/ - -inline void -tape_state_set (tape_dev_t * td, tape_state_t newstate) -{ - if (td->tape_state == TS_NOT_OPER) { - tape_sprintf_event(tape_dbf_area,3,"ts_set err: not oper\n"); - } else { - tape_sprintf_event(tape_dbf_area,4,"ts. dev: %x\n",td->first_minor); - tape_sprintf_event(tape_dbf_area,4,"old ts: %s\n",(((tape_state_get (td) < TO_SIZE) && (tape_state_get (td) >=0 )) ? tape_state_verbose[tape_state_get (td)] : "UNKNOWN TS")); - tape_sprintf_event(tape_dbf_area,4,"%s\n", - (((tape_state_get (td) < TO_SIZE) && - (tape_state_get (td) >=0 )) ? - tape_state_verbose[tape_state_get (td)] : - "UNKNOWN TS")); - tape_sprintf_event (tape_dbf_area,4,"new ts: \n"); - tape_sprintf_event (tape_dbf_area,4,"%s\n",(((newstate < TO_SIZE) && - (newstate >= 0)) ? - tape_state_verbose[newstate] : - "UNKNOWN TS")); - td->tape_state = newstate; - } -} - -inline tape_state_t -tape_state_get (tape_dev_t * td) -{ - return (td->tape_state); -} - -inline void -tape_med_state_set(tape_dev_t * td, tape_medium_state_t newstate) -{ - if(td->medium_state == newstate) - goto out; - switch(newstate){ - case MS_UNLOADED: - PRINT_INFO("(%x): Tape is unloaded\n",td->devstat.devno); - break; - case MS_LOADED: - PRINT_INFO("(%x): Tape has been mounted\n",td->devstat.devno); - break; - default: - // print nothing - break; - } - td->medium_state = newstate; -out: - return; -} - - -/******************************************************************* - * TAPE Exported Functions - *******************************************************************/ - -EXPORT_SYMBOL(tape_register_discipline); -EXPORT_SYMBOL(tape_unregister_discipline); -EXPORT_SYMBOL(tape_dbf_area); -EXPORT_SYMBOL(tape_alloc_ccw_req); -EXPORT_SYMBOL(tape_free_ccw_req); -EXPORT_SYMBOL(tape_state_set); -EXPORT_SYMBOL(tape_state_get); -EXPORT_SYMBOL(tape_med_state_set); -EXPORT_SYMBOL(tape_state_verbose); -EXPORT_SYMBOL(tape_op_verbose); -EXPORT_SYMBOL(tape_dump_sense); -EXPORT_SYMBOL(tape_dump_sense_dbf); -EXPORT_SYMBOL(tape_do_io); -EXPORT_SYMBOL(tape_do_io_irq); -EXPORT_SYMBOL(tape_do_io_and_wait); -EXPORT_SYMBOL(tape_remove_ccw_req); -EXPORT_SYMBOL(tape_get_active_ccw_req); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |