root/drivers/char/ftape/kernel-interface.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __get_order
  2. dmaalloc
  3. dmafree
  4. ftape_init
  5. cleanup_module
  6. ftape_open
  7. ftape_close
  8. ftape_ioctl
  9. ftape_read
  10. ftape_write
  11. ftape_lseek

   1 /*
   2  *      Copyright (C) 1993-1995 Bas Laarhoven.
   3 
   4  This program is free software; you can redistribute it and/or modify
   5  it under the terms of the GNU General Public License as published by
   6  the Free Software Foundation; either version 2, or (at your option)
   7  any later version.
   8 
   9  This program is distributed in the hope that it will be useful,
  10  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  GNU General Public License for more details.
  13 
  14  You should have received a copy of the GNU General Public License
  15  along with this program; see the file COPYING.  If not, write to
  16  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17 
  18  *
  19  *      This file contains the code that interfaces the kernel
  20  *      for the QIC-40/80 floppy-tape driver for Linux.
  21  */
  22 
  23 #include <linux/module.h>
  24 #include <linux/version.h>
  25 #include <linux/errno.h>
  26 #include <linux/fs.h>
  27 #include <asm/segment.h>
  28 #include <linux/kernel.h>
  29 #include <linux/signal.h>
  30 #include <linux/major.h>
  31 #include <linux/malloc.h>
  32 #include <linux/ftape.h>
  33 #include <asm/dma.h>
  34 
  35 #include "tracing.h"
  36 #include "kernel-interface.h"
  37 #include "ftape-read.h"
  38 #include "ftape-write.h"
  39 #include "ftape-io.h"
  40 #include "ftape-ctl.h"
  41 #include "ftape-rw.h"
  42 #include "fdc-io.h"
  43 
  44 
  45 /*      Global vars.
  46  */
  47 
  48 /* Allocating a 96Kb DMAable buffer in one chunk wont work due to
  49  * memory fragmentation.  To avoid this, it is broken up into
  50  * NR_BUFFERS chunks of 32Kbyte. --khp
  51  */
  52 
  53 byte *tape_buffer[NR_BUFFERS] =
  54 {NULL};
  55 
  56 /*      Local vars.
  57  */
  58 static int busy_flag = 0;
  59 static int old_sigmask;
  60 
  61 static int ftape_open(struct inode *ino, struct file *filep);
  62 static void ftape_close(struct inode *ino, struct file *filep);
  63 static int ftape_ioctl(struct inode *ino, struct file *filep,
  64                        unsigned int command, unsigned long arg);
  65 static int ftape_read(struct inode *ino, struct file *fp, char *buff,
  66                       int req_len);
  67 static int ftape_write(struct inode *ino, struct file *fp, const char *buff,
  68                        int req_len);
  69 static int ftape_lseek(struct inode *ino, struct file *filep,
  70                        off_t offset, int origin);
  71 #if 0
  72 static int ftape_select(void);
  73 static int ftape_mmap(int dev, unsigned off, int prot);
  74 #else
  75 #define ftape_select NULL
  76 #define ftape_mmap NULL
  77 #endif
  78 
  79 static struct file_operations ftape_cdev =
  80 {
  81         ftape_lseek,            /* lseek */
  82         ftape_read,             /* read */
  83         ftape_write,            /* write */
  84         NULL,                   /* readdir */
  85         ftape_select,           /* select */
  86         ftape_ioctl,            /* ioctl */
  87         ftape_mmap,             /* mmap */
  88         ftape_open,             /* open */
  89         ftape_close,            /* release */
  90         NULL,                   /* fsync */
  91 };
  92 
  93 /*
  94  * DMA'able memory allocation stuff.
  95  */
  96 
  97 static inline
  98 int __get_order(int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100         int order;
 101 
 102         for (order = 0; order < NR_MEM_LISTS; ++order)
 103                 if (size <= (PAGE_SIZE << order))
 104                         return order;
 105         return -1;
 106 }
 107 
 108 static inline
 109 void *dmaalloc(int order)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         return (void *) __get_dma_pages(GFP_KERNEL, order);
 112 }
 113 
 114 static inline
 115 void dmafree(void *addr, int order)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         free_pages((unsigned long) addr, order);
 118 }
 119 
 120 /*
 121  * Called by modules package when installing the driver
 122  * or by kernel during the initialization phase
 123  */
 124 
 125 #ifdef MODULE
 126 #define ftape_init init_module
 127 #endif
 128 
 129 int ftape_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         int n;
 132         int order;
 133         TRACE_FUN(5, "init_module");
 134 #ifdef MODULE
 135         printk(KERN_INFO "ftape-2.07 960304\n"
 136                KERN_INFO " (c) 1993-1995 Bas Laarhoven (bas@vimec.nl)\n"
 137                KERN_INFO " (c) 1995-1996 Kai Harrekilde-Petersen (khp@pip.dknet.dk)\n"
 138         KERN_INFO " QIC-117 driver for QIC-40/80/3010/3020 tape drives\n"
 139                KERN_INFO " Compiled for kernel version %s"
 140 #ifdef MODVERSIONS
 141                " with versioned symbols"
 142 #endif
 143                "\n", kernel_version);
 144 #else                           /* !MODULE */
 145         /* print a short no-nonsense boot message */
 146         printk("ftape-2.07 960304 for Linux 1.3.70\n");
 147 #endif                          /* MODULE */
 148         TRACE(3, "installing QIC-117 ftape driver...");
 149         if (register_chrdev(QIC117_TAPE_MAJOR, "ftape", &ftape_cdev)) {
 150                 TRACE(1, "register_chrdev failed");
 151                 TRACE_EXIT;
 152                 return -EIO;
 153         }
 154         TRACEx1(3, "init_module @ 0x%p", init_module);
 155         /*
 156          * Allocate the DMA buffers. They are deallocated at cleanup() time.
 157          */
 158         order = __get_order(BUFF_SIZE);
 159         if (order < 0) {
 160                 TRACE(1, "__get_order failed (no memory?)");
 161                 if (unregister_chrdev(QIC117_TAPE_MAJOR, "ftape") != 0) {
 162                         TRACE(3, "unregister_chrdev failed");
 163                 }
 164                 return -ENOMEM;
 165         }
 166         for (n = 0; n < NR_BUFFERS; n++) {
 167                 tape_buffer[n] = (byte *) dmaalloc(order);
 168                 if (!tape_buffer[n]) {
 169                         TRACE(1, "dmaalloc() failed");
 170                         for (n = 0; n < NR_BUFFERS; n++) {
 171                                 if (tape_buffer[n]) {
 172                                         dmafree(tape_buffer[n], order);
 173                                         tape_buffer[n] = NULL;
 174                                 }
 175                         }
 176                         current->blocked = old_sigmask;         /* restore mask */
 177                         if (unregister_chrdev(QIC117_TAPE_MAJOR, "ftape") != 0) {
 178                                 TRACE(3, "unregister_chrdev failed");
 179                         }
 180                         TRACE_EXIT;
 181                         return -ENOMEM;
 182                 } else {
 183                         TRACEx2(3, "dma-buffer #%d @ %p", n, tape_buffer[n]);
 184                 }
 185         }
 186         busy_flag = 0;
 187         ftape_unit = -1;
 188         ftape_failure = 1;      /* inhibit any operation but open */
 189         udelay_calibrate();     /* must be before fdc_wait_calibrate ! */
 190         fdc_wait_calibrate();
 191         TRACE_EXIT;
 192 #ifdef MODULE
 193         register_symtab(0);     /* remove global ftape symbols */
 194 #endif
 195         return 0;
 196 }
 197 
 198 
 199 #ifdef MODULE
 200 /*      Called by modules package when removing the driver
 201  */
 202 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204         int n;
 205         int order;
 206         TRACE_FUN(5, "cleanup_module");
 207 
 208         if (unregister_chrdev(QIC117_TAPE_MAJOR, "ftape") != 0) {
 209                 TRACE(3, "failed");
 210         } else {
 211                 TRACE(3, "successful");
 212         }
 213         order = __get_order(BUFF_SIZE);
 214         if (order < 0) {
 215                 TRACE(1, "__get_order failed (but why?!)");
 216         } else {
 217                 for (n = 0; n < NR_BUFFERS; n++) {
 218                         if (tape_buffer[n]) {
 219                                 dmafree(tape_buffer[n], order);
 220                                 tape_buffer[n] = NULL;
 221                                 TRACEx1(3, "removed dma-buffer #%d", n);
 222                         } else {
 223                                 TRACEx1(1, "dma-buffer #%d == NULL (bug?)", n);
 224                         }
 225                 }
 226         }
 227         TRACE_EXIT;
 228 }
 229 #endif                          /* MODULE */
 230 
 231 /*      Open ftape device
 232  */
 233 static int ftape_open(struct inode *ino, struct file *filep)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235         TRACE_FUN(4, "ftape_open");
 236         int result;
 237         MOD_INC_USE_COUNT;      /* lock module in memory */
 238 
 239         TRACEi(5, "called for minor", MINOR(ino->i_rdev));
 240         if (busy_flag) {
 241                 TRACE(1, "failed: already busy");
 242                 MOD_DEC_USE_COUNT;      /* unlock module in memory */
 243                 TRACE_EXIT;
 244                 return -EBUSY;
 245         }
 246         if ((MINOR(ino->i_rdev) & ~FTAPE_NO_REWIND) > 3) {
 247                 TRACE(1, "failed: illegal unit nr");
 248                 MOD_DEC_USE_COUNT;      /* unlock module in memory */
 249                 TRACE_EXIT;
 250                 return -ENXIO;
 251         }
 252         if (ftape_unit == -1 || FTAPE_UNIT != (MINOR(ino->i_rdev) & 3)) {
 253                 /*  Other selection than last time
 254                  */
 255                 ftape_init_driver();
 256         }
 257         ftape_unit = MINOR(ino->i_rdev);
 258         ftape_failure = 0;      /* allow tape operations */
 259         old_sigmask = current->blocked;
 260         current->blocked = _BLOCK_ALL;
 261         fdc_save_drive_specs(); /* save Drive Specification regs on i82078-1's */
 262         result = _ftape_open();
 263         if (result < 0) {
 264                 TRACE(1, "_ftape_open failed");
 265                 current->blocked = old_sigmask;         /* restore mask */
 266                 MOD_DEC_USE_COUNT;      /* unlock module in memory */
 267                 TRACE_EXIT;
 268                 return result;
 269         } else {
 270                 busy_flag = 1;
 271                 /*  Mask signals that will disturb proper operation of the
 272                  *  program that is calling.
 273                  */
 274                 current->blocked = old_sigmask | _DO_BLOCK;
 275                 TRACE_EXIT;
 276                 return 0;
 277         }
 278 }
 279 
 280 /*      Close ftape device
 281  */
 282 static void ftape_close(struct inode *ino, struct file *filep)
     /* [previous][next][first][last][top][bottom][index][help] */
 283 {
 284         TRACE_FUN(4, "ftape_close");
 285         int result;
 286 
 287         if (!busy_flag || MINOR(ino->i_rdev) != ftape_unit) {
 288                 TRACE(1, "failed: not busy or wrong unit");
 289                 TRACE_EXIT;
 290                 return;         /* keep busy_flag !(?) */
 291         }
 292         current->blocked = _BLOCK_ALL;
 293         result = _ftape_close();
 294         if (result < 0) {
 295                 TRACE(1, "_ftape_close failed");
 296         }
 297         fdc_restore_drive_specs();      /* restore original values */
 298         ftape_failure = 1;      /* inhibit any operation but open */
 299         busy_flag = 0;
 300         current->blocked = old_sigmask;         /* restore before open state */
 301         TRACE_EXIT;
 302         MOD_DEC_USE_COUNT;      /* unlock module in memory */
 303 }
 304 
 305 /*      Ioctl for ftape device
 306  */
 307 static int ftape_ioctl(struct inode *ino, struct file *filep,
     /* [previous][next][first][last][top][bottom][index][help] */
 308                        unsigned int command, unsigned long arg)
 309 {
 310         TRACE_FUN(4, "ftape_ioctl");
 311         int result = -EIO;
 312         int old_sigmask;
 313 
 314         if (!busy_flag || MINOR(ino->i_rdev) != ftape_unit || ftape_failure) {
 315                 TRACE(1, "failed: not busy, failure or wrong unit");
 316                 TRACE_EXIT;
 317                 return -EIO;
 318         }
 319         old_sigmask = current->blocked;         /* save mask */
 320         current->blocked = _BLOCK_ALL;
 321         /* This will work as long as sizeof( void*) == sizeof( long)
 322          */
 323         result = _ftape_ioctl(command, (void *) arg);
 324         current->blocked = old_sigmask;         /* restore mask */
 325         TRACE_EXIT;
 326         return result;
 327 }
 328 
 329 /*      Read from tape device
 330  */
 331 static int ftape_read(struct inode *ino, struct file *fp, char *buff, int req_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 332 {
 333         TRACE_FUN(5, "ftape_read");
 334         int result = -EIO;
 335         int old_sigmask;
 336 
 337         TRACEi(5, "called with count:", req_len);
 338         if (!busy_flag || MINOR(ino->i_rdev) != ftape_unit || ftape_failure) {
 339                 TRACE(1, "failed: not busy, failure or wrong unit");
 340                 TRACE_EXIT;
 341                 return -EIO;
 342         }
 343         old_sigmask = current->blocked;         /* save mask */
 344         current->blocked = _BLOCK_ALL;
 345         result = _ftape_read(buff, req_len);
 346         TRACEi(7, "return with count:", result);
 347         current->blocked = old_sigmask;         /* restore mask */
 348         TRACE_EXIT;
 349         return result;
 350 }
 351 
 352 /*      Write to tape device
 353  */
 354 static int ftape_write(struct inode *ino, struct file *fp, const char *buff, int req_len)
     /* [previous][next][first][last][top][bottom][index][help] */
 355 {
 356         TRACE_FUN(8, "ftape_write");
 357         int result = -EIO;
 358         int old_sigmask;
 359 
 360         TRACEi(5, "called with count:", req_len);
 361         if (!busy_flag || MINOR(ino->i_rdev) != ftape_unit || ftape_failure) {
 362                 TRACE(1, "failed: not busy, failure or wrong unit");
 363                 TRACE_EXIT;
 364                 return -EIO;
 365         }
 366         old_sigmask = current->blocked;         /* save mask */
 367         current->blocked = _BLOCK_ALL;
 368         result = _ftape_write(buff, req_len);
 369         TRACEi(7, "return with count:", result);
 370         current->blocked = old_sigmask;         /* restore mask */
 371         TRACE_EXIT;
 372         return result;
 373 }
 374 
 375 /*      Seek tape device - not implemented !
 376  */
 377 static int ftape_lseek(struct inode *ino, struct file *filep, off_t offset, int origin)
     /* [previous][next][first][last][top][bottom][index][help] */
 378 {
 379         return -ESPIPE;
 380 }

/* [previous][next][first][last][top][bottom][index][help] */