patch-1.3.72 linux/drivers/char/ftape/kernel-interface.c
Next file: linux/drivers/char/ftape/kernel-interface.h
Previous file: linux/drivers/char/ftape/ftape-write.h
Back to the patch index
Back to the overall index
- Lines: 385
- Date:
Wed Mar 6 15:07:20 1996
- Orig file:
v1.3.71/linux/drivers/char/ftape/kernel-interface.c
- Orig date:
Thu Jan 1 02:00:00 1970
diff -u --recursive --new-file v1.3.71/linux/drivers/char/ftape/kernel-interface.c linux/drivers/char/ftape/kernel-interface.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 1993-1995 Bas Laarhoven.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ *
+ * This file contains the code that interfaces the kernel
+ * for the QIC-40/80 floppy-tape driver for Linux.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <asm/segment.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/ftape.h>
+#include <asm/dma.h>
+
+#include "tracing.h"
+#include "kernel-interface.h"
+#include "ftape-read.h"
+#include "ftape-write.h"
+#include "ftape-io.h"
+#include "ftape-ctl.h"
+#include "ftape-rw.h"
+#include "fdc-io.h"
+
+
+/* Global vars.
+ */
+
+/* Allocating a 96Kb DMAable buffer in one chunk wont work due to
+ * memory fragmentation. To avoid this, it is broken up into
+ * NR_BUFFERS chunks of 32Kbyte. --khp
+ */
+
+byte *tape_buffer[NR_BUFFERS] =
+{NULL};
+
+#ifdef MODULE
+char kernel_version[] = UTS_RELEASE;
+#endif
+
+/* Local vars.
+ */
+static int busy_flag = 0;
+static int old_sigmask;
+
+static int ftape_open(struct inode *ino, struct file *filep);
+static void ftape_close(struct inode *ino, struct file *filep);
+static int ftape_ioctl(struct inode *ino, struct file *filep,
+ unsigned int command, unsigned long arg);
+static int ftape_read(struct inode *ino, struct file *fp, char *buff,
+ int req_len);
+static int ftape_write(struct inode *ino, struct file *fp, const char *buff,
+ int req_len);
+static int ftape_lseek(struct inode *ino, struct file *filep,
+ off_t offset, int origin);
+#if 0
+static int ftape_select(void);
+static int ftape_mmap(int dev, unsigned off, int prot);
+#else
+#define ftape_select NULL
+#define ftape_mmap NULL
+#endif
+
+static struct file_operations ftape_cdev =
+{
+ ftape_lseek, /* lseek */
+ ftape_read, /* read */
+ ftape_write, /* write */
+ NULL, /* readdir */
+ ftape_select, /* select */
+ ftape_ioctl, /* ioctl */
+ ftape_mmap, /* mmap */
+ ftape_open, /* open */
+ ftape_close, /* release */
+ NULL, /* fsync */
+};
+
+/*
+ * DMA'able memory allocation stuff.
+ */
+
+static inline
+int __get_order(int size)
+{
+ int order;
+
+ for (order = 0; order < NR_MEM_LISTS; ++order)
+ if (size <= (PAGE_SIZE << order))
+ return order;
+ return -1;
+}
+
+static inline
+void *dmaalloc(int order)
+{
+ return (void *) __get_dma_pages(GFP_KERNEL, order);
+}
+
+static inline
+void dmafree(void *addr, int order)
+{
+ free_pages((unsigned long) addr, order);
+}
+
+/*
+ * Called by modules package when installing the driver
+ * or by kernel during the initialization phase
+ */
+
+#ifdef MODULE
+#define ftape_init init_module
+#endif
+
+int ftape_init(void)
+{
+ int n;
+ int order;
+ TRACE_FUN(5, "init_module");
+#ifdef MODULE
+ printk(KERN_INFO "ftape-2.07 960304\n"
+ KERN_INFO " (c) 1993-1995 Bas Laarhoven (bas@vimec.nl)\n"
+ KERN_INFO " (c) 1995-1996 Kai Harrekilde-Petersen (khp@pip.dknet.dk)\n"
+ KERN_INFO " QIC-117 driver for QIC-40/80/3010/3020 tape drives\n"
+ KERN_INFO " Compiled for kernel version %s"
+#ifdef MODVERSIONS
+ " with versioned symbols"
+#endif
+ "\n", kernel_version);
+#else /* !MODULE */
+ /* print a short no-nonsense boot message */
+ printk("ftape-2.07 960304 for Linux 1.3.70\n");
+#endif /* MODULE */
+ TRACE(3, "installing QIC-117 ftape driver...");
+ if (register_chrdev(QIC117_TAPE_MAJOR, "ftape", &ftape_cdev)) {
+ TRACE(1, "register_chrdev failed");
+ TRACE_EXIT;
+ return -EIO;
+ }
+ TRACEx1(3, "init_module @ 0x%p", init_module);
+ /*
+ * Allocate the DMA buffers. They are deallocated at cleanup() time.
+ */
+ order = __get_order(BUFF_SIZE);
+ if (order < 0) {
+ TRACE(1, "__get_order failed (no memory?)");
+ if (unregister_chrdev(QIC117_TAPE_MAJOR, "ftape") != 0) {
+ TRACE(3, "unregister_chrdev failed");
+ }
+ return -ENOMEM;
+ }
+ for (n = 0; n < NR_BUFFERS; n++) {
+ tape_buffer[n] = (byte *) dmaalloc(order);
+ if (!tape_buffer[n]) {
+ TRACE(1, "dmaalloc() failed");
+ for (n = 0; n < NR_BUFFERS; n++) {
+ if (tape_buffer[n]) {
+ dmafree(tape_buffer[n], order);
+ tape_buffer[n] = NULL;
+ }
+ }
+ current->blocked = old_sigmask; /* restore mask */
+ if (unregister_chrdev(QIC117_TAPE_MAJOR, "ftape") != 0) {
+ TRACE(3, "unregister_chrdev failed");
+ }
+ TRACE_EXIT;
+ return -ENOMEM;
+ } else {
+ TRACEx2(3, "dma-buffer #%d @ %p", n, tape_buffer[n]);
+ }
+ }
+ busy_flag = 0;
+ ftape_unit = -1;
+ ftape_failure = 1; /* inhibit any operation but open */
+ udelay_calibrate(); /* must be before fdc_wait_calibrate ! */
+ fdc_wait_calibrate();
+ TRACE_EXIT;
+#ifdef MODULE
+ register_symtab(0); /* remove global ftape symbols */
+#endif
+ return 0;
+}
+
+
+#ifdef MODULE
+/* Called by modules package when removing the driver
+ */
+void cleanup_module(void)
+{
+ int n;
+ int order;
+ TRACE_FUN(5, "cleanup_module");
+
+ if (unregister_chrdev(QIC117_TAPE_MAJOR, "ftape") != 0) {
+ TRACE(3, "failed");
+ } else {
+ TRACE(3, "successful");
+ }
+ order = __get_order(BUFF_SIZE);
+ if (order < 0) {
+ TRACE(1, "__get_order failed (but why?!)");
+ } else {
+ for (n = 0; n < NR_BUFFERS; n++) {
+ if (tape_buffer[n]) {
+ dmafree(tape_buffer[n], order);
+ tape_buffer[n] = NULL;
+ TRACEx1(3, "removed dma-buffer #%d", n);
+ } else {
+ TRACEx1(1, "dma-buffer #%d == NULL (bug?)", n);
+ }
+ }
+ }
+ TRACE_EXIT;
+}
+#endif /* MODULE */
+
+/* Open ftape device
+ */
+static int ftape_open(struct inode *ino, struct file *filep)
+{
+ TRACE_FUN(4, "ftape_open");
+ int result;
+ MOD_INC_USE_COUNT; /* lock module in memory */
+
+ TRACEi(5, "called for minor", MINOR(ino->i_rdev));
+ if (busy_flag) {
+ TRACE(1, "failed: already busy");
+ MOD_DEC_USE_COUNT; /* unlock module in memory */
+ TRACE_EXIT;
+ return -EBUSY;
+ }
+ if ((MINOR(ino->i_rdev) & ~FTAPE_NO_REWIND) > 3) {
+ TRACE(1, "failed: illegal unit nr");
+ MOD_DEC_USE_COUNT; /* unlock module in memory */
+ TRACE_EXIT;
+ return -ENXIO;
+ }
+ if (ftape_unit == -1 || FTAPE_UNIT != (MINOR(ino->i_rdev) & 3)) {
+ /* Other selection than last time
+ */
+ ftape_init_driver();
+ }
+ ftape_unit = MINOR(ino->i_rdev);
+ ftape_failure = 0; /* allow tape operations */
+ old_sigmask = current->blocked;
+ current->blocked = _BLOCK_ALL;
+ fdc_save_drive_specs(); /* save Drive Specification regs on i82078-1's */
+ result = _ftape_open();
+ if (result < 0) {
+ TRACE(1, "_ftape_open failed");
+ current->blocked = old_sigmask; /* restore mask */
+ MOD_DEC_USE_COUNT; /* unlock module in memory */
+ TRACE_EXIT;
+ return result;
+ } else {
+ busy_flag = 1;
+ /* Mask signals that will disturb proper operation of the
+ * program that is calling.
+ */
+ current->blocked = old_sigmask | _DO_BLOCK;
+ TRACE_EXIT;
+ return 0;
+ }
+}
+
+/* Close ftape device
+ */
+static void ftape_close(struct inode *ino, struct file *filep)
+{
+ TRACE_FUN(4, "ftape_close");
+ int result;
+
+ if (!busy_flag || MINOR(ino->i_rdev) != ftape_unit) {
+ TRACE(1, "failed: not busy or wrong unit");
+ TRACE_EXIT;
+ return; /* keep busy_flag !(?) */
+ }
+ current->blocked = _BLOCK_ALL;
+ result = _ftape_close();
+ if (result < 0) {
+ TRACE(1, "_ftape_close failed");
+ }
+ fdc_restore_drive_specs(); /* restore original values */
+ ftape_failure = 1; /* inhibit any operation but open */
+ busy_flag = 0;
+ current->blocked = old_sigmask; /* restore before open state */
+ TRACE_EXIT;
+ MOD_DEC_USE_COUNT; /* unlock module in memory */
+}
+
+/* Ioctl for ftape device
+ */
+static int ftape_ioctl(struct inode *ino, struct file *filep,
+ unsigned int command, unsigned long arg)
+{
+ TRACE_FUN(4, "ftape_ioctl");
+ int result = -EIO;
+ int old_sigmask;
+
+ if (!busy_flag || MINOR(ino->i_rdev) != ftape_unit || ftape_failure) {
+ TRACE(1, "failed: not busy, failure or wrong unit");
+ TRACE_EXIT;
+ return -EIO;
+ }
+ old_sigmask = current->blocked; /* save mask */
+ current->blocked = _BLOCK_ALL;
+ /* This will work as long as sizeof( void*) == sizeof( long)
+ */
+ result = _ftape_ioctl(command, (void *) arg);
+ current->blocked = old_sigmask; /* restore mask */
+ TRACE_EXIT;
+ return result;
+}
+
+/* Read from tape device
+ */
+static int ftape_read(struct inode *ino, struct file *fp, char *buff, int req_len)
+{
+ TRACE_FUN(5, "ftape_read");
+ int result = -EIO;
+ int old_sigmask;
+
+ TRACEi(5, "called with count:", req_len);
+ if (!busy_flag || MINOR(ino->i_rdev) != ftape_unit || ftape_failure) {
+ TRACE(1, "failed: not busy, failure or wrong unit");
+ TRACE_EXIT;
+ return -EIO;
+ }
+ old_sigmask = current->blocked; /* save mask */
+ current->blocked = _BLOCK_ALL;
+ result = _ftape_read(buff, req_len);
+ TRACEi(7, "return with count:", result);
+ current->blocked = old_sigmask; /* restore mask */
+ TRACE_EXIT;
+ return result;
+}
+
+/* Write to tape device
+ */
+static int ftape_write(struct inode *ino, struct file *fp, const char *buff, int req_len)
+{
+ TRACE_FUN(8, "ftape_write");
+ int result = -EIO;
+ int old_sigmask;
+
+ TRACEi(5, "called with count:", req_len);
+ if (!busy_flag || MINOR(ino->i_rdev) != ftape_unit || ftape_failure) {
+ TRACE(1, "failed: not busy, failure or wrong unit");
+ TRACE_EXIT;
+ return -EIO;
+ }
+ old_sigmask = current->blocked; /* save mask */
+ current->blocked = _BLOCK_ALL;
+ result = _ftape_write(buff, req_len);
+ TRACEi(7, "return with count:", result);
+ current->blocked = old_sigmask; /* restore mask */
+ TRACE_EXIT;
+ return result;
+}
+
+/* Seek tape device - not implemented !
+ */
+static int ftape_lseek(struct inode *ino, struct file *filep, off_t offset, int origin)
+{
+ return -ESPIPE;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this