OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [char/] [ftape/] [kernel-interface.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.