Import 1.3.75
[davej-history.git] / drivers / char / ftape / kernel-interface.c
blobfc44c965640889a38bed5e095fbab160422f25b0
1 /*
2 * Copyright (C) 1993-1995 Bas Laarhoven.
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.
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.
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.
19 * This file contains the code that interfaces the kernel
20 * for the QIC-40/80 floppy-tape driver for Linux.
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>
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"
45 /* Global vars.
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
53 byte *tape_buffer[NR_BUFFERS] = {NULL};
55 /* Local vars.
57 static int busy_flag =0;
58 static int old_sigmask;
60 static intftape_open(struct inode *ino,struct file *filep);
61 static voidftape_close(struct inode *ino,struct file *filep);
62 static intftape_ioctl(struct inode *ino,struct file *filep,
63 unsigned int command,unsigned long arg);
64 static intftape_read(struct inode *ino,struct file *fp,char*buff,
65 int req_len);
66 static intftape_write(struct inode *ino,struct file *fp,const char*buff,
67 int req_len);
69 static struct file_operations ftape_cdev =
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 */
84 * DMA'able memory allocation stuff.
87 /* Pure 2^n version of get_order */
88 staticinlineint__get_order(unsigned long size)
90 int order;
92 size >>= (PAGE_SHIFT-1);
93 order = -1;
94 do{
95 size >>=1;
96 order++;
97 }while(size);
98 return order;
101 staticinline
102 void*dmaalloc(int order)
104 return(void*)__get_dma_pages(GFP_KERNEL, order);
107 staticinline
108 voiddmafree(void*addr,int order)
110 free_pages((unsigned long) addr, order);
114 * Called by modules package when installing the driver
115 * or by kernel during the initialization phase
118 #ifdef MODULE
119 #define ftape_init init_module
120 #endif
122 intftape_init(void)
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@pip.dknet.dk)\n"
131 KERN_INFO " QIC-117 driver for QIC-40/80/3010/3020 tape drives\n"
132 KERN_INFO " Compiled for kernel version %s"
133 #ifdef MODVERSIONS
134 " with versioned symbols"
135 #endif
136 "\n", kernel_version);
137 #else/* !MODULE */
138 /* print a short no-nonsense boot message */
139 printk("ftape-2.08 960314 for Linux 1.3.70\n");
140 #endif/* MODULE */
141 TRACE(3,"installing QIC-117 ftape driver...");
142 if(register_chrdev(QIC117_TAPE_MAJOR,"ft", &ftape_cdev)) {
143 TRACE(1,"register_chrdev failed");
144 TRACE_EXIT;
145 return-EIO;
147 TRACEx1(3,"ftape_init @ 0x%p", ftape_init);
149 * Allocate the DMA buffers. They are deallocated at cleanup() time.
151 order =__get_order(BUFF_SIZE);
152 for(n =0; n < NR_BUFFERS; n++) {
153 tape_buffer[n] = (byte *)dmaalloc(order);
154 if(!tape_buffer[n]) {
155 TRACE(1,"dmaalloc() failed");
156 for(n =0; n < NR_BUFFERS; n++) {
157 if(tape_buffer[n]) {
158 dmafree(tape_buffer[n], order);
159 tape_buffer[n] = NULL;
162 current->blocked = old_sigmask;/* restore mask */
163 if(unregister_chrdev(QIC117_TAPE_MAJOR,"ft") !=0) {
164 TRACE(3,"unregister_chrdev failed");
166 TRACE_EXIT;
167 return-ENOMEM;
168 }else{
169 TRACEx2(3,"dma-buffer #%d @ %p", n, tape_buffer[n]);
172 busy_flag =0;
173 ftape_unit = -1;
174 ftape_failure =1;/* inhibit any operation but open */
175 udelay_calibrate();/* must be before fdc_wait_calibrate ! */
176 fdc_wait_calibrate();
177 TRACE_EXIT;
178 #ifdef MODULE
179 register_symtab(0);/* remove global ftape symbols */
180 #endif
181 return0;
185 #ifdef MODULE
186 /* Called by modules package when removing the driver
188 voidcleanup_module(void)
190 int n;
191 int order;
192 TRACE_FUN(5,"cleanup_module");
194 if(unregister_chrdev(QIC117_TAPE_MAJOR,"ft") !=0) {
195 TRACE(3,"failed");
196 }else{
197 TRACE(3,"successful");
199 order =__get_order(BUFF_SIZE);
200 for(n =0; n < NR_BUFFERS; n++) {
201 if(tape_buffer[n]) {
202 dmafree(tape_buffer[n], order);
203 tape_buffer[n] = NULL;
204 TRACEx1(3,"removed dma-buffer #%d", n);
205 }else{
206 TRACEx1(1,"dma-buffer #%d == NULL (bug?)", n);
209 TRACE_EXIT;
211 #endif/* MODULE */
213 /* Open ftape device
215 static intftape_open(struct inode *ino,struct file *filep)
217 TRACE_FUN(4,"ftape_open");
218 int result;
219 MOD_INC_USE_COUNT;/* lock module in memory */
221 TRACEi(5,"called for minor",MINOR(ino->i_rdev));
222 if(busy_flag) {
223 TRACE(1,"failed: already busy");
224 MOD_DEC_USE_COUNT;/* unlock module in memory */
225 TRACE_EXIT;
226 return-EBUSY;
228 if((MINOR(ino->i_rdev) & ~FTAPE_NO_REWIND) >3) {
229 TRACE(1,"failed: illegal unit nr");
230 MOD_DEC_USE_COUNT;/* unlock module in memory */
231 TRACE_EXIT;
232 return-ENXIO;
234 if(ftape_unit == -1|| FTAPE_UNIT != (MINOR(ino->i_rdev) &3)) {
235 /* Other selection than last time
237 ftape_init_driver();
239 ftape_unit =MINOR(ino->i_rdev);
240 ftape_failure =0;/* allow tape operations */
241 old_sigmask = current->blocked;
242 current->blocked = _BLOCK_ALL;
243 fdc_save_drive_specs();/* save Drive Specification regs on i82078-1's */
244 result =_ftape_open();
245 if(result <0) {
246 TRACE(1,"_ftape_open failed");
247 current->blocked = old_sigmask;/* restore mask */
248 MOD_DEC_USE_COUNT;/* unlock module in memory */
249 TRACE_EXIT;
250 return result;
251 }else{
252 busy_flag =1;
253 /* Mask signals that will disturb proper operation of the
254 * program that is calling.
256 current->blocked = old_sigmask | _DO_BLOCK;
257 TRACE_EXIT;
258 return0;
262 /* Close ftape device
264 static voidftape_close(struct inode *ino,struct file *filep)
266 TRACE_FUN(4,"ftape_close");
267 int result;
269 if(!busy_flag ||MINOR(ino->i_rdev) != ftape_unit) {
270 TRACE(1,"failed: not busy or wrong unit");
271 TRACE_EXIT;
272 return;/* keep busy_flag !(?) */
274 current->blocked = _BLOCK_ALL;
275 result =_ftape_close();
276 if(result <0) {
277 TRACE(1,"_ftape_close failed");
279 fdc_restore_drive_specs();/* restore original values */
280 ftape_failure =1;/* inhibit any operation but open */
281 busy_flag =0;
282 current->blocked = old_sigmask;/* restore before open state */
283 TRACE_EXIT;
284 MOD_DEC_USE_COUNT;/* unlock module in memory */
287 /* Ioctl for ftape device
289 static intftape_ioctl(struct inode *ino,struct file *filep,
290 unsigned int command,unsigned long arg)
292 TRACE_FUN(4,"ftape_ioctl");
293 int result = -EIO;
294 int old_sigmask;
296 if(!busy_flag ||MINOR(ino->i_rdev) != ftape_unit || ftape_failure) {
297 TRACE(1,"failed: not busy, failure or wrong unit");
298 TRACE_EXIT;
299 return-EIO;
301 old_sigmask = current->blocked;/* save mask */
302 current->blocked = _BLOCK_ALL;
303 /* This will work as long as sizeof( void*) == sizeof( long)
305 result =_ftape_ioctl(command, (void*) arg);
306 current->blocked = old_sigmask;/* restore mask */
307 TRACE_EXIT;
308 return result;
311 /* Read from tape device
313 static intftape_read(struct inode *ino,struct file *fp,char*buff,int req_len)
315 TRACE_FUN(5,"ftape_read");
316 int result = -EIO;
317 int old_sigmask;
319 TRACEi(5,"called with count:", req_len);
320 if(!busy_flag ||MINOR(ino->i_rdev) != ftape_unit || ftape_failure) {
321 TRACE(1,"failed: not busy, failure or wrong unit");
322 TRACE_EXIT;
323 return-EIO;
325 old_sigmask = current->blocked;/* save mask */
326 current->blocked = _BLOCK_ALL;
327 result =_ftape_read(buff, req_len);
328 TRACEi(7,"return with count:", result);
329 current->blocked = old_sigmask;/* restore mask */
330 TRACE_EXIT;
331 return result;
334 /* Write to tape device
336 static intftape_write(struct inode *ino,struct file *fp,const char*buff,int req_len)
338 TRACE_FUN(8,"ftape_write");
339 int result = -EIO;
340 int old_sigmask;
342 TRACEi(5,"called with count:", req_len);
343 if(!busy_flag ||MINOR(ino->i_rdev) != ftape_unit || ftape_failure) {
344 TRACE(1,"failed: not busy, failure or wrong unit");
345 TRACE_EXIT;
346 return-EIO;
348 old_sigmask = current->blocked;/* save mask */
349 current->blocked = _BLOCK_ALL;
350 result =_ftape_write(buff, req_len);
351 TRACEi(7,"return with count:", result);
352 current->blocked = old_sigmask;/* restore mask */
353 TRACE_EXIT;
354 return result;
close