patch-2.4.4 linux/drivers/s390/char/tapechar.c

Next file: linux/drivers/s390/char/tapechar.h
Previous file: linux/drivers/s390/char/tapeblock.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.3/linux/drivers/s390/char/tapechar.c linux/drivers/s390/char/tapechar.c
@@ -4,16 +4,17 @@
  *  drivers/s390/char/tapechar.c
  *    character device frontend for tape device driver
  *
- *  S390 version
- *    Copyright (C) 2000 IBM Corporation
- *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
- *               Carsten Otte <cotte@de.ibm.com>
+ *  S390 and zSeries version
+ *    Copyright (C) 2001 IBM Corporation
+ *    Author(s): Carsten Otte <cotte@de.ibm.com>
+ *               Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *
  *
- *  UNDER CONSTRUCTION: Work in progress...:-)
  ****************************************************************************
  */
 
 #include "tapedefs.h"
+#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
@@ -24,6 +25,7 @@
 #include <asm/uaccess.h>
 #include <linux/compatmac.h>
 #ifdef MODULE
+#define __NO_VERSION__
 #include <linux/module.h>
 #endif
 #include "tape.h"
@@ -54,10 +56,33 @@
 
 int tape_major = TAPE_MAJOR;
 
+#ifdef CONFIG_DEVFS_FS
+void
+tapechar_mkdevfstree (tape_info_t* tape) {
+    tape->devfs_char_dir=devfs_mk_dir (tape->devfs_dir, "char", tape);
+    tape->devfs_nonrewinding=devfs_register(tape->devfs_char_dir, "nonrewinding",
+					    DEVFS_FL_DEFAULT,tape_major, 
+					    tape->nor_minor, TAPECHAR_DEFAULTMODE, 
+					    &tape_fops, tape);
+    tape->devfs_rewinding=devfs_register(tape->devfs_char_dir, "rewinding",
+					 DEVFS_FL_DEFAULT, tape_major, tape->rew_minor,
+					 TAPECHAR_DEFAULTMODE, &tape_fops, tape);
+}
+
+void
+tapechar_rmdevfstree (tape_info_t* tape) {
+    devfs_unregister(tape->devfs_nonrewinding);
+    devfs_unregister(tape->devfs_rewinding);
+    devfs_unregister(tape->devfs_char_dir);
+}
+#endif
+
 void
 tapechar_setup (tape_info_t * tape)
 {
-    // nothing to do
+#ifdef CONFIG_DEVFS_FS
+    tapechar_mkdevfstree(tape);
+#endif
 }
 
 void
@@ -70,7 +95,11 @@
 	tape_init();
 
 	/* Register the tape major number to the kernel */
+#ifdef CONFIG_DEVFS_FS
+	result = devfs_register_chrdev (tape_major, "tape", &tape_fops);
+#else
 	result = register_chrdev (tape_major, "tape", &tape_fops);
+#endif
 
 	if (result < 0) {
 		PRINT_WARN (KERN_ERR "tape: can't get major %d\n", tape_major);
@@ -92,6 +121,10 @@
 		panic ("no major number available for tape char device");		
 	}
 	charfront->device_setup = tapechar_setup;
+#ifdef CONFIG_DEVFS_FS
+	charfront->mkdevfstree = tapechar_mkdevfstree;
+	charfront->rmdevfstree = tapechar_rmdevfstree;
+#endif
 #ifdef TAPE_DEBUG
         debug_text_event (tape_debug_area,3,"c:init ok");
 #endif /* TAPE_DEBUG */
@@ -120,7 +153,7 @@
 /*
  * Tape device read function
  */
-static ssize_t
+ssize_t
 tape_read (struct file *filp, char *data, size_t count, loff_t * ppos)
 {
 	long lockflags;
@@ -184,6 +217,12 @@
 		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
 		return tape->rc;
 	}
+	if (tapestate_get (tape) == TS_NOT_OPER) {
+	    tape->blk_minor=tape->rew_minor=tape->nor_minor=-1;
+	    tape->devinfo.irq=-1;
+	    s390irq_spin_unlock_irqrestore (tape->devinfo.irq,lockflags);
+	    return -ENODEV;
+	}
 	if (tapestate_get (tape) != TS_DONE) {
 		tapestate_set (tape, TS_IDLE);
 		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
@@ -202,7 +241,7 @@
 /*
  * Tape device write function
  */
-static ssize_t
+ssize_t
 tape_write (struct file *filp, const char *data, size_t count, loff_t * ppos)
 {
 	long lockflags;
@@ -262,8 +301,16 @@
 		if (tapestate_get (tape) == TS_FAILED) {
 			tapestate_set (tape, TS_IDLE);
 			s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+                        if ((tape->rc==-ENOSPC) && (i!=0))
+			  return i*block_size;
 			return tape->rc;
 		}
+		if (tapestate_get (tape) == TS_NOT_OPER) {
+		    tape->blk_minor=tape->rew_minor=tape->nor_minor=-1;
+		    tape->devinfo.irq=-1;
+		    s390irq_spin_unlock_irqrestore (tape->devinfo.irq,lockflags);
+		    return -ENODEV;
+		}
 		if (tapestate_get (tape) != TS_DONE) {
 			tapestate_set (tape, TS_IDLE);
 			s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
@@ -446,6 +493,12 @@
 		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
 		return tape->rc;
 	}
+	if (tapestate_get (tape) == TS_NOT_OPER) {
+	    tape->blk_minor=tape->rew_minor=tape->nor_minor=-1;
+	    tape->devinfo.irq=-1;
+	    s390irq_spin_unlock_irqrestore (tape->devinfo.irq,lockflags);
+	    return -ENODEV;
+	}
 	if (tapestate_get (tape) != TS_DONE) {
 		tapestate_set (tape, TS_IDLE);
 		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
@@ -473,7 +526,7 @@
 /*
  * Tape device io controls.
  */
-static int
+int
 tape_ioctl (struct inode *inode, struct file *filp,
 	    unsigned int cmd, unsigned long arg)
 {
@@ -589,7 +642,7 @@
 /*
  * Tape device open function.
  */
-static int
+int
 tape_open (struct inode *inode, struct file *filp)
 {
 	tape_info_t *ti;
@@ -637,7 +690,7 @@
 /*
  * Tape device release function.
  */
-static int
+int
 tape_release (struct inode *inode, struct file *filp)
 {
 	long lockflags;
@@ -645,7 +698,6 @@
 	ccw_req_t *cqr = NULL;
 	int rc;
 
-	inode = filp->f_dentry->d_inode;
 	ti = first_tape_info;
 	while ((ti != NULL) && (ti->rew_minor != MINOR (inode->i_rdev)) && (ti->nor_minor != MINOR (inode->i_rdev)))
 		ti = (tape_info_t *) ti->next;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)