patch-2.4.8 linux/drivers/s390/char/tape.c
Next file: linux/drivers/s390/char/tape.h
Previous file: linux/drivers/s390/char/hwc_tty.c
Back to the patch index
Back to the overall index
- Lines: 785
- Date:
Wed Jul 25 14:12:02 2001
- Orig file:
v2.4.7/linux/drivers/s390/char/tape.c
- Orig date:
Wed Apr 11 19:02:28 2001
diff -u --recursive --new-file v2.4.7/linux/drivers/s390/char/tape.c linux/drivers/s390/char/tape.c
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
+#include <linux/init.h>
#include <asm/types.h>
#include <asm/ccwcache.h>
#include <asm/idals.h>
@@ -26,9 +27,7 @@
#ifdef MODULE
#include <linux/module.h>
#endif
-#ifdef TAPE_DEBUG
#include <asm/debug.h>
-#endif
#ifdef CONFIG_S390_TAPE_DYNAMIC
#include <asm/s390dyn.h>
#endif
@@ -50,15 +49,19 @@
#endif
#define PRINTK_HEADER "T390:"
+
/* state handling routines */
-inline void tapestate_set (tape_info_t * tape, int newstate);
-inline int tapestate_get (tape_info_t * tape);
-void tapestate_event (tape_info_t * tape, int event);
+inline void tapestate_set (tape_info_t * ti, int newstate);
+inline int tapestate_get (tape_info_t * ti);
+void tapestate_event (tape_info_t * ti, int event);
/* our globals */
tape_info_t *first_tape_info = NULL;
tape_discipline_t *first_discipline = NULL;
tape_frontend_t *first_frontend = NULL;
+devreg_t* tape_devreg[128];
+int devregct=0;
+
#ifdef TAPE_DEBUG
debug_info_t *tape_debug_area = NULL;
#endif
@@ -107,17 +110,17 @@
devfs_handle_t tape_devfs_root_entry;
inline void
-tape_mkdevfsroots (tape_info_t* tape)
+tape_mkdevfsroots (tape_info_t* ti)
{
char devno [5];
- sprintf (devno,"%04X",tape->devinfo.devno);
- tape->devfs_dir=devfs_mk_dir (tape_devfs_root_entry, devno, tape);
+ sprintf (devno,"%04x",ti->devinfo.devno);
+ ti->devfs_dir=devfs_mk_dir (tape_devfs_root_entry, devno, ti);
}
inline void
-tape_rmdevfsroots (tape_info_t* tape)
+tape_rmdevfsroots (tape_info_t* ti)
{
- devfs_unregister (tape->devfs_dir);
+ devfs_unregister (ti->devfs_dir);
}
#endif
@@ -135,14 +138,14 @@
tape_devices_open (struct inode *inode, struct file *file)
{
int size=80;
- tape_info_t* tape;
+ tape_info_t* ti;
tempinfo_t* tempinfo;
char* data;
int pos=0;
tempinfo = kmalloc (sizeof(tempinfo_t),GFP_KERNEL);
if (!tempinfo)
return -ENOMEM;
- for (tape=first_tape_info;tape!=NULL;tape=tape->next)
+ for (ti=first_tape_info;ti!=NULL;ti=ti->next)
size+=80; // FIXME: Guess better!
data=vmalloc(size);
if (!data) {
@@ -150,13 +153,13 @@
return -ENOMEM;
}
pos+=sprintf(data+pos,"TapeNo\tDevNo\tCuType\tCuModel\tDevType\tDevModel\tState\n");
- for (tape=first_tape_info;tape!=NULL;tape=tape->next) {
- pos+=sprintf(data+pos,"%d\t%04X\t%04X\t%02X\t%04X\t%02X\t\t%s\n",tape->rew_minor/2,
- tape->devinfo.devno,tape->devinfo.sid_data.cu_type,
- tape->devinfo.sid_data.cu_model,tape->devinfo.sid_data.dev_type,
- tape->devinfo.sid_data.dev_model,((tapestate_get(tape) >= 0) &&
- (tapestate_get(tape) < TS_SIZE)) ?
- state_verbose[tapestate_get (tape)] : "TS UNKNOWN");
+ for (ti=first_tape_info;ti!=NULL;ti=ti->next) {
+ pos+=sprintf(data+pos,"%d\t%04X\t%04X\t%02X\t%04X\t%02X\t\t%s\n",ti->rew_minor/2,
+ ti->devinfo.devno,ti->devinfo.sid_data.cu_type,
+ ti->devinfo.sid_data.cu_model,ti->devinfo.sid_data.dev_type,
+ ti->devinfo.sid_data.dev_model,((tapestate_get(ti) >= 0) &&
+ (tapestate_get(ti) < TS_SIZE)) ?
+ state_verbose[tapestate_get (ti)] : "TS UNKNOWN");
}
tempinfo->len=pos;
tempinfo->data=data;
@@ -215,6 +218,183 @@
};
#endif /* CONFIG_PROC_FS */
+/* SECTION: Parameters for tape */
+char *tape[256] = { NULL, };
+
+#ifndef MODULE
+static char tape_parm_string[1024] __initdata = { 0, };
+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;
+ }
+ memset (tape[count], 0, len * sizeof (char));
+ memcpy (tape[count], tmp, len * sizeof (char));
+ count++;
+ tmp = end;
+ };
+}
+
+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;
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,2,16))
+__setup("tape=", tape_parm_call_setup);
+#endif /* kernel <2.2.19 */
+#endif /* not defined MODULE */
+
+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;
+}
+
+static inline devreg_t *
+tape_create_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;
+}
+
+static inline void
+tape_parm_parse (char **str)
+{
+ char *temp;
+ int from, to,i,irq=0,rc,retries=0,tape_num=0;
+ s390_dev_info_t dinfo;
+ tape_info_t* ti,*tempti;
+ tape_discipline_t* disc;
+ long lockflags;
+ if (*str==NULL) {
+ /* no params present -> leave */
+ return;
+ }
+ while (*str) {
+ temp = *str;
+ from = 0;
+ to = 0;
+
+ /* turn off autodetect mode, if any range is present */
+ from = tape_parm_strtoul (temp, &temp);
+ to = from;
+ if (*temp == '-') {
+ temp++;
+ to = tape_parm_strtoul (temp, &temp);
+ }
+ for (i=from;i<=to;i++) {
+ retries=0;
+ // register for attch/detach of a devno
+ tape_devreg[devregct]=tape_create_devreg(i);
+ if (tape_devreg[devregct]==NULL) {
+ PRINT_WARN ("Could not create devreg for devno %04x, dyn. attach for this devno deactivated.\n",i);
+ } else {
+ s390_device_register (tape_devreg[devregct++]);
+ }
+ // we are activating a device if it is present
+ for (irq = get_irq_first(); irq!=-ENODEV; irq=get_irq_next(irq)) {
+ rc = get_dev_info_by_irq (irq, &dinfo);
+
+ disc = first_discipline;
+ while ((dinfo.devno == i) && (disc != NULL) && (disc->cu_type != dinfo.sid_data.cu_type))
+ disc = (tape_discipline_t *) (disc->next);
+ if ((disc == NULL) || (rc == -ENODEV) || (i!=dinfo.devno)) {
+ continue;
+ }
+#ifdef TAPE_DEBUG
+ debug_text_event (tape_debug_area,3,"det irq: ");
+ debug_int_event (tape_debug_area,3,irq);
+ debug_text_event (tape_debug_area,3,"cu: ");
+ debug_int_event (tape_debug_area,3,disc->cu_type);
+#endif /* TAPE_DEBUG */
+ PRINT_INFO ("using devno %04x with discipline %04x on irq %d as tape device %d\n",dinfo.devno,dinfo.sid_data.cu_type,irq,tape_num/2);
+ /* Allocate tape structure */
+ ti = kmalloc (sizeof (tape_info_t), GFP_ATOMIC);
+ if (ti == NULL) {
+#ifdef TAPE_DEBUG
+ debug_text_exception (tape_debug_area,3,"ti:no mem ");
+#endif /* TAPE_DEBUG */
+ PRINT_INFO ("tape: can't allocate memory for "
+ "tape info structure\n");
+ continue;
+ }
+ memset(ti,0,sizeof(tape_info_t));
+ ti->discipline = disc;
+ disc->tape = ti;
+ rc = tape_setup (ti, irq, tape_num);
+ if (rc) {
+#ifdef TAPE_DEBUG
+ debug_text_event (tape_debug_area,3,"tsetup err");
+ debug_int_exception (tape_debug_area,3,rc);
+#endif /* TAPE_DEBUG */
+ kfree (ti);
+ } else {
+ s390irq_spin_lock_irqsave (irq, lockflags);
+ if (first_tape_info == NULL) {
+ first_tape_info = ti;
+ } else {
+ tempti = first_tape_info;
+ while (tempti->next != NULL)
+ tempti = tempti->next;
+ tempti->next = ti;
+ }
+ s390irq_spin_unlock_irqrestore (irq, lockflags);
+ }
+ }
+ tape_num+=2;
+ }
+ str++;
+ }
+}
+
+
/* SECTION: Managing wrappers for ccwcache */
#define TAPE_EMERGENCY_REQUESTS 16
@@ -286,7 +466,6 @@
*((ccw_req_t **) (request->cache)) = request;
} else {
clear_normalized_cda ((ccw1_t *) (request->cpaddr)); // avoid memory leak caused by modeset_byte
-
ccw_free_request (request);
}
}
@@ -296,12 +475,12 @@
*/
inline
ccw_req_t *
-tape_alloc_ccw_req (tape_info_t * tape, int cplength, int datasize)
+tape_alloc_ccw_req (tape_info_t * ti, int cplength, int datasize)
{
char tape_magic_id[] = "tape";
ccw_req_t *cqr = NULL;
- if (!tape)
+ if (!ti)
return NULL;
cqr = tape_alloc_request (tape_magic_id, cplength, datasize);
@@ -311,7 +490,7 @@
#endif
}
cqr->magic = TAPE_MAGIC; /* sets an identifier for tape driver */
- cqr->device = tape; /* save pointer to tape info */
+ cqr->device = ti; /* save pointer to tape info */
return cqr;
}
@@ -321,15 +500,15 @@
static inline tape_info_t *
tapedev_find_info (int irq)
{
- tape_info_t *tape;
+ tape_info_t *ti;
- tape = first_tape_info;
- if (tape != NULL)
+ ti = first_tape_info;
+ if (ti != NULL)
do {
- if (tape->devinfo.irq == irq)
+ if (ti->devinfo.irq == irq)
break;
- } while ((tape = (tape_info_t *) tape->next) != NULL);
- return tape;
+ } while ((ti = (tape_info_t *) ti->next) != NULL);
+ return ti;
}
#define QUEUE_THRESHOLD 5
@@ -340,32 +519,31 @@
void
tape_irq (int irq, void *int_parm, struct pt_regs *regs)
{
- tape_info_t *tape = tapedev_find_info (irq);
+ tape_info_t *ti = tapedev_find_info (irq);
/* analyse devstat and fire event */
- if (tape->devstat.dstat & DEV_STAT_UNIT_CHECK) {
- tapestate_event (tape, TE_ERROR);
- } else if (tape->devstat.dstat & (DEV_STAT_DEV_END)) {
- tapestate_event (tape, TE_DONE);
+ if (ti->devstat.dstat & DEV_STAT_UNIT_CHECK) {
+ tapestate_event (ti, TE_ERROR);
+ } else if (ti->devstat.dstat & (DEV_STAT_DEV_END)) {
+ tapestate_event (ti, TE_DONE);
} else
- tapestate_event (tape, TE_OTHER);
+ tapestate_event (ti, TE_OTHER);
}
int
tape_oper_handler ( int irq, struct _devreg *dreg) {
- tape_info_t* tape=first_tape_info;
+ tape_info_t* ti=first_tape_info;
tape_info_t* newtape;
- int rc,tape_num,retries=0;
+ int rc,tape_num,retries=0,i;
s390_dev_info_t dinfo;
tape_discipline_t* disc;
#ifdef CONFIG_DEVFS_FS
tape_frontend_t* frontend;
#endif
long lockflags;
- PRINT_WARN ("oper handler was called\n");
- while ((tape!=NULL) && (tape->devinfo.irq!=irq))
- tape=tape->next;
- if (tape!=NULL) {
+ while ((ti!=NULL) && (ti->devinfo.irq!=irq))
+ ti=ti->next;
+ if (ti!=NULL) {
// irq is (still) used by tape. tell ingo to try again later
PRINT_WARN ("Oper handler for irq %d called while irq still (internaly?) used.\n",irq);
return -EAGAIN;
@@ -384,51 +562,61 @@
while ((disc != NULL) && (disc->cu_type != dinfo.sid_data.cu_type))
disc = (tape_discipline_t *) (disc->next);
if (disc == NULL)
- PRINT_WARN ("No matching discipline for cu_type %x found\n",dinfo.sid_data.cu_type);
+ PRINT_WARN ("No matching discipline for cu_type %x found, ignoring device %04x.\n",dinfo.sid_data.cu_type,dinfo.devno);
if (rc == -ENODEV)
PRINT_WARN ("No device information for new dev. could be retrieved.\n");
if ((disc == NULL) || (rc == -ENODEV))
return -ENODEV;
/* Allocate tape structure */
- tape = kmalloc (sizeof (tape_info_t), GFP_ATOMIC);
- if (tape == NULL) {
- PRINT_INFO (KERN_ERR "tape: can't allocate memory for "
+ ti = kmalloc (sizeof (tape_info_t), GFP_ATOMIC);
+ if (ti == NULL) {
+ PRINT_INFO ( "tape: can't allocate memory for "
"tape info structure\n");
return -ENOBUFS;
}
- memset(tape,0,sizeof(tape_info_t));
- tape->discipline = disc;
- disc->tape = tape;
+ memset(ti,0,sizeof(tape_info_t));
+ ti->discipline = disc;
+ disc->tape = ti;
tape_num=0;
- newtape=first_tape_info;
- while (newtape!=NULL) {
- if (newtape->rew_minor==tape_num) {
- // tape num in use. try next one
- tape_num+=2;
- newtape=first_tape_info;
- } else {
- // tape num not used by newtape. look at next tape info
- newtape=newtape->next;
+ if (*tape) {
+ // we have static device ranges, so fingure out the tape_num of the attached tape
+ for (i=0;i<devregct;i++)
+ if (tape_devreg[i]->ci.devno==dinfo.devno) {
+ tape_num=2*i;
+ break;
+ }
+ } else {
+ // we are running in autoprobe mode, find a free tape_num
+ newtape=first_tape_info;
+ while (newtape!=NULL) {
+ if (newtape->rew_minor==tape_num) {
+ // tape num in use. try next one
+ tape_num+=2;
+ newtape=first_tape_info;
+ } else {
+ // tape num not used by newtape. look at next tape info
+ newtape=newtape->next;
+ }
}
}
- rc = tape_setup (tape, irq, tape_num);
+ rc = tape_setup (ti, irq, tape_num);
if (rc) {
- kfree (tape);
+ kfree (ti);
return -ENOBUFS;
}
#ifdef CONFIG_DEVFS_FS
for (frontend=first_frontend;frontend!=NULL;frontend=frontend->next)
- frontend->mkdevfstree(tape);
+ frontend->mkdevfstree(ti);
#endif
s390irq_spin_lock_irqsave (irq,lockflags);
if (first_tape_info == NULL) {
- first_tape_info = tape;
+ first_tape_info = ti;
} else {
newtape = first_tape_info;
while (newtape->next != NULL)
newtape = newtape->next;
- newtape->next = tape;
+ newtape->next = ti;
}
s390irq_spin_unlock_irqrestore (irq, lockflags);
return 0;
@@ -492,8 +680,11 @@
void
tape_dump_sense (devstat_t * stat)
{
- int sl;
+#ifdef TAPE_DEBUG
+ int sl;
+#endif
#if 0
+
PRINT_WARN ("------------I/O resulted in unit check:-----------\n");
for (sl = 0; sl < 4; sl++) {
PRINT_WARN ("Sense:");
@@ -542,6 +733,10 @@
long lockflags;
int rc = 0;
+ if (minor>254) {
+ PRINT_WARN ("Device id %d on irq %d will not be accessible since this driver is restricted to 128 devices.\n",minor/2,irq);
+ return -EINVAL;
+ }
rc = get_dev_info_by_irq (irq, &(ti->devinfo));
if (rc == -ENODEV) { /* end of device list */
return rc;
@@ -560,10 +755,8 @@
#endif
s390irq_spin_lock_irqsave (irq, lockflags);
ti->next = NULL;
- if (rc) {
- PRINT_WARN ("Cannot register irq %d, rc=%d\n", irq, rc);
- } else
- PRINT_WARN ("Register irq %d for using with discipline %x dev #%d\n", irq, ti->discipline->cu_type,ti->blk_minor/2);
+ if (rc)
+ PRINT_WARN ("Cannot register irq %d, rc=%d\n", irq, rc);
init_waitqueue_head (&ti->wq);
ti->kernbuf = ti->userbuf = ti->discdata = NULL;
tapestate_set (ti, TS_UNUSED);
@@ -599,7 +792,7 @@
#endif /* TAPE_DEBUG */
/* print banner */
- PRINT_WARN ("IBM S/390 Tape Device Driver (BETA).\n");
+ PRINT_WARN ("IBM S/390 Tape Device Driver (v1.01).\n");
PRINT_WARN ("(C) IBM Deutschland Entwicklung GmbH, 2000\n");
opt_char=opt_block=opt_3480=opt_3490="not present";
#ifdef CONFIG_S390_TAPE_CHAR
@@ -620,18 +813,33 @@
PRINT_WARN ("support for 3480 compatible : %s\n",opt_3480);
PRINT_WARN ("support for 3490 compatible : %s\n",opt_3490);
-
+#ifndef MODULE
+ tape_split_parm_string(tape_parm_string);
+#endif
+ if (*tape)
+ PRINT_INFO ("Using ranges supplied in parameters, disabling autoprobe mode.\n");
+ else
+ PRINT_INFO ("No parameters supplied, enabling autoprobe mode for all supported devices.\n");
#ifdef CONFIG_S390_TAPE_3490
- first_discipline = tape3490_init ();
+ if (*tape)
+ first_discipline = tape3490_init (0); // no autoprobe for devices
+ else
+ first_discipline = tape3490_init (1); // do autoprobe since no parm specified
first_discipline->next = NULL;
#endif
#ifdef CONFIG_S390_TAPE_3480
if (first_discipline == NULL) {
- first_discipline = tape3480_init ();
+ if (*tape)
+ first_discipline = tape3480_init (0); // no autoprobe for devices
+ else
+ first_discipline = tape3480_init (1); // do autoprobe since no parm specified
first_discipline->next = NULL;
} else {
- first_discipline->next = tape3480_init ();
+ if (*tape)
+ first_discipline->next = tape3480_init (0); // no autoprobe for devices
+ else
+ first_discipline->next = tape3480_init (1); // do autoprobe since no parm specified
((tape_discipline_t*) (first_discipline->next))->next=NULL;
}
#endif
@@ -643,33 +851,32 @@
debug_text_event (tape_debug_area,3,"dev detect");
#endif /* TAPE_DEBUG */
/* Allocate the tape structures */
- for (irq = 0; irq < NR_IRQS; irq++) {
+ if (*tape!=NULL) {
+ // we have parameters, continue with parsing the parameters and set the devices online
+ tape_parm_parse (tape);
+ } else {
+ // we are running in autodetect mode, search all devices for compatibles
+ for (irq = get_irq_first(); irq!=-ENODEV; irq=get_irq_next(irq)) {
rc = get_dev_info_by_irq (irq, &dinfo);
-
- if (rc == -ENODEV) {
- retries++;
- if (retries > 5)
- irq = NR_IRQS;
- }
disc = first_discipline;
while ((disc != NULL) && (disc->cu_type != dinfo.sid_data.cu_type))
- disc = (tape_discipline_t *) (disc->next);
-
+ disc = (tape_discipline_t *) (disc->next);
if ((disc == NULL) || (rc == -ENODEV))
- continue;
+ continue;
#ifdef TAPE_DEBUG
debug_text_event (tape_debug_area,3,"det irq: ");
debug_int_event (tape_debug_area,3,irq);
debug_text_event (tape_debug_area,3,"cu: ");
debug_int_event (tape_debug_area,3,disc->cu_type);
#endif /* TAPE_DEBUG */
+ PRINT_INFO ("using devno %04x with discipline %04x on irq %d as tape device %d\n",dinfo.devno,dinfo.sid_data.cu_type,irq,tape_num/2);
/* Allocate tape structure */
ti = kmalloc (sizeof (tape_info_t), GFP_ATOMIC);
if (ti == NULL) {
#ifdef TAPE_DEBUG
debug_text_exception (tape_debug_area,3,"ti:no mem ");
#endif /* TAPE_DEBUG */
- PRINT_INFO (KERN_ERR "tape: can't allocate memory for "
+ PRINT_INFO ("tape: can't allocate memory for "
"tape info structure\n");
continue;
}
@@ -679,25 +886,26 @@
rc = tape_setup (ti, irq, tape_num);
if (rc) {
#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"tsetup err");
- debug_int_exception (tape_debug_area,3,rc);
+ debug_text_event (tape_debug_area,3,"tsetup err");
+ debug_int_exception (tape_debug_area,3,rc);
#endif /* TAPE_DEBUG */
- kfree (ti);
+ kfree (ti);
} else {
- s390irq_spin_lock_irqsave (irq, lockflags);
- if (first_tape_info == NULL) {
- first_tape_info = ti;
- } else {
- tempti = first_tape_info;
- while (tempti->next != NULL)
- tempti = tempti->next;
- tempti->next = ti;
- }
- tape_num += 2;
- s390irq_spin_unlock_irqrestore (irq, lockflags);
+ s390irq_spin_lock_irqsave (irq, lockflags);
+ if (first_tape_info == NULL) {
+ first_tape_info = ti;
+ } else {
+ tempti = first_tape_info;
+ while (tempti->next != NULL)
+ tempti = tempti->next;
+ tempti->next = ti;
+ }
+ tape_num += 2;
+ s390irq_spin_unlock_irqrestore (irq, lockflags);
}
- }
-
+ }
+ }
+
/* Allocate local buffer for the ccwcache */
tape_init_emergency_req ();
#ifdef CONFIG_PROC_FS
@@ -733,6 +941,7 @@
#ifdef MODULE
MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte (cotte@de.ibm.com)");
MODULE_DESCRIPTION("Linux for S/390 channel attached tape device driver");
+MODULE_PARM (tape, "1-" __MODULE_STRING (256) "s");
int
init_module (void)
@@ -749,17 +958,24 @@
void
cleanup_module (void)
{
- tape_info_t *tape ,*temp;
+ tape_info_t *ti ,*temp;
tape_frontend_t* frontend, *tempfe;
tape_discipline_t* disc ,*tempdi;
+ int i;
#ifdef TAPE_DEBUG
debug_text_event (tape_debug_area,6,"cleaup mod");
#endif /* TAPE_DEBUG */
- tape = first_tape_info;
- while (tape != NULL) {
- temp = tape;
- tape = tape->next;
+ if (*tape) {
+ // we are running with parameters. we'll now deregister from our devno's
+ for (i=0;i<devregct;i++) {
+ s390_device_unregister(tape_devreg[devregct]);
+ }
+ }
+ ti = first_tape_info;
+ while (ti != NULL) {
+ temp = ti;
+ ti = ti->next;
//cleanup a device
#ifdef TAPE_DEBUG
debug_text_event (tape_debug_area,6,"free irq:");
@@ -781,7 +997,7 @@
#endif CONFIG_DEVFS_FS
#ifdef CONFIG_PROC_FS
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
- remove_proc_entry ("devices", &proc_root);
+ remove_proc_entry ("tapedevices", &proc_root);
#else
proc_unregister (&proc_root, tape_devices_entry->low_ino);
kfree (tape_devices_entry);
@@ -801,6 +1017,10 @@
}
disc=first_discipline;
while (disc != NULL) {
+ if (*tape)
+ disc->shutdown(0);
+ else
+ disc->shutdown(1);
tempdi = disc;
disc = disc->next;
kfree (tempdi);
@@ -814,9 +1034,9 @@
#endif /* MODULE */
inline void
-tapestate_set (tape_info_t * tape, int newstate)
+tapestate_set (tape_info_t * ti, int newstate)
{
- if (tape->tape_state == TS_NOT_OPER) {
+ if (ti->tape_state == TS_NOT_OPER) {
#ifdef TAPE_DEBUG
debug_text_event (tape_debug_area,3,"ts_set err");
debug_text_exception (tape_debug_area,3,"dev n.oper");
@@ -824,11 +1044,11 @@
} else {
#ifdef TAPE_DEBUG
debug_text_event (tape_debug_area,4,"ts. dev: ");
- debug_int_event (tape_debug_area,4,tape->blk_minor);
+ debug_int_event (tape_debug_area,4,ti->blk_minor);
debug_text_event (tape_debug_area,4,"old ts: ");
- debug_text_event (tape_debug_area,4,(((tapestate_get (tape) < TS_SIZE) &&
- (tapestate_get (tape) >=0 )) ?
- state_verbose[tapestate_get (tape)] :
+ debug_text_event (tape_debug_area,4,(((tapestate_get (ti) < TS_SIZE) &&
+ (tapestate_get (ti) >=0 )) ?
+ state_verbose[tapestate_get (ti)] :
"UNKNOWN TS"));
debug_text_event (tape_debug_area,4,"new ts: ");
debug_text_event (tape_debug_area,4,(((newstate < TS_SIZE) &&
@@ -836,46 +1056,46 @@
state_verbose[newstate] :
"UNKNOWN TS"));
#endif /* TAPE_DEBUG */
- tape->tape_state = newstate;
+ ti->tape_state = newstate;
}
}
inline int
-tapestate_get (tape_info_t * tape)
+tapestate_get (tape_info_t * ti)
{
- return (tape->tape_state);
+ return (ti->tape_state);
}
void
-tapestate_event (tape_info_t * tape, int event)
+tapestate_event (tape_info_t * ti, int event)
{
#ifdef TAPE_DEBUG
debug_text_event (tape_debug_area,6,"te! dev: ");
- debug_int_event (tape_debug_area,6,tape->blk_minor);
+ debug_int_event (tape_debug_area,6,ti->blk_minor);
debug_text_event (tape_debug_area,6,"event:");
debug_text_event (tape_debug_area,6,((event >=0) &&
(event < TE_SIZE)) ?
event_verbose[event] : "TE UNKNOWN");
debug_text_event (tape_debug_area,6,"state:");
- debug_text_event (tape_debug_area,6,((tapestate_get(tape) >= 0) &&
- (tapestate_get(tape) < TS_SIZE)) ?
- state_verbose[tapestate_get (tape)] :
+ debug_text_event (tape_debug_area,6,((tapestate_get(ti) >= 0) &&
+ (tapestate_get(ti) < TS_SIZE)) ?
+ state_verbose[tapestate_get (ti)] :
"TS UNKNOWN");
#endif /* TAPE_DEBUG */
if (event == TE_ERROR) {
- tape->discipline->error_recovery(tape);
+ ti->discipline->error_recovery(ti);
} else {
if ((event >= 0) &&
(event < TE_SIZE) &&
- (tapestate_get (tape) >= 0) &&
- (tapestate_get (tape) < TS_SIZE) &&
- ((*(tape->discipline->event_table))[tapestate_get (tape)][event] != NULL))
- ((*(tape->discipline->event_table))[tapestate_get (tape)][event]) (tape);
+ (tapestate_get (ti) >= 0) &&
+ (tapestate_get (ti) < TS_SIZE) &&
+ ((*(ti->discipline->event_table))[tapestate_get (ti)][event] != NULL))
+ ((*(ti->discipline->event_table))[tapestate_get (ti)][event]) (ti);
else {
#ifdef TAPE_DEBUG
debug_text_exception (tape_debug_area,3,"TE UNEXPEC");
#endif /* TAPE_DEBUG */
- tape->discipline->default_handler (tape);
+ ti->discipline->default_handler (ti);
}
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)