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

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