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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [s390/] [char/] [tapechar.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
 
2
/***************************************************************************
3
 *
4
 *  drivers/s390/char/tapechar.c
5
 *    character device frontend for tape device driver
6
 *
7
 *  S390 and zSeries version
8
 *    Copyright (C) 2001 IBM Corporation
9
 *    Author(s): Carsten Otte <cotte@de.ibm.com>
10
 *               Tuan Ngo-Anh <ngoanh@de.ibm.com>
11
 *
12
 *
13
 ****************************************************************************
14
 */
15
 
16
#include "tapedefs.h"
17
#include <linux/config.h>
18
#include <linux/version.h>
19
#include <linux/types.h>
20
#include <linux/proc_fs.h>
21
#include <asm/ccwcache.h>       /* CCW allocations      */
22
#include <asm/s390dyn.h>
23
#include <asm/debug.h>
24
#include <linux/mtio.h>
25
#include <asm/uaccess.h>
26
#include <linux/compatmac.h>
27
#ifdef MODULE
28
#define __NO_VERSION__
29
#include <linux/module.h>
30
#endif
31
#include "tape.h"
32
#include "tapechar.h"
33
 
34
#define PRINTK_HEADER "TCHAR:"
35
 
36
/*
37
 * file operation structure for tape devices
38
 */
39
static struct file_operations tape_fops =
40
{
41
    //    owner   : THIS_MODULE,
42
        llseek:NULL,            /* lseek - default */
43
        read:tape_read,         /* read  */
44
        write:tape_write,       /* write */
45
        readdir:NULL,           /* readdir - bad */
46
        poll:NULL,              /* poll */
47
        ioctl:tape_ioctl,       /* ioctl */
48
        mmap:NULL,              /* mmap */
49
        open:tape_open,         /* open */
50
        flush:NULL,             /* flush */
51
        release:tape_release,   /* release */
52
        fsync:NULL,             /* fsync */
53
        fasync:NULL,            /* fasync */
54
        lock:NULL,
55
};
56
 
57
int tape_major = TAPE_MAJOR;
58
 
59
#ifdef CONFIG_DEVFS_FS
60
void
61
tapechar_mkdevfstree (tape_info_t* ti) {
62
    ti->devfs_char_dir=devfs_mk_dir (ti->devfs_dir, "char", ti);
63
    ti->devfs_nonrewinding=devfs_register(ti->devfs_char_dir, "nonrewinding",
64
                                            DEVFS_FL_DEFAULT,tape_major,
65
                                            ti->nor_minor, TAPECHAR_DEFAULTMODE,
66
                                            &tape_fops, ti);
67
    ti->devfs_rewinding=devfs_register(ti->devfs_char_dir, "rewinding",
68
                                         DEVFS_FL_DEFAULT, tape_major, ti->rew_minor,
69
                                         TAPECHAR_DEFAULTMODE, &tape_fops, ti);
70
}
71
 
72
void
73
tapechar_rmdevfstree (tape_info_t* ti) {
74
    devfs_unregister(ti->devfs_nonrewinding);
75
    devfs_unregister(ti->devfs_rewinding);
76
    devfs_unregister(ti->devfs_char_dir);
77
}
78
#endif
79
 
80
void
81
tapechar_setup (tape_info_t * ti)
82
{
83
#ifdef CONFIG_DEVFS_FS
84
    tapechar_mkdevfstree(ti);
85
#endif
86
}
87
 
88
void
89
tapechar_init (void)
90
{
91
        int result;
92
        tape_frontend_t *charfront,*temp;
93
        tape_info_t* ti;
94
 
95
        tape_init();
96
 
97
        /* Register the tape major number to the kernel */
98
#ifdef CONFIG_DEVFS_FS
99
        result = devfs_register_chrdev (tape_major, "tape", &tape_fops);
100
#else
101
        result = register_chrdev (tape_major, "tape", &tape_fops);
102
#endif
103
 
104
        if (result < 0) {
105
                PRINT_WARN (KERN_ERR "tape: can't get major %d\n", tape_major);
106
#ifdef TAPE_DEBUG
107
                debug_text_event (tape_debug_area,3,"c:initfail");
108
                debug_text_event (tape_debug_area,3,"regchrfail");
109
#endif /* TAPE_DEBUG */
110
                panic ("no major number available for tape char device");
111
        }
112
        if (tape_major == 0)
113
                tape_major = result;    /* accept dynamic major number */
114
        PRINT_WARN (KERN_ERR " tape gets major %d for character device\n", result);
115
        charfront = kmalloc (sizeof (tape_frontend_t), GFP_KERNEL);
116
        if (charfront == NULL) {
117
#ifdef TAPE_DEBUG
118
                debug_text_event (tape_debug_area,3,"c:initfail");
119
                debug_text_event (tape_debug_area,3,"no mem");
120
#endif /* TAPE_DEBUG */
121
                panic ("no major number available for tape char device");
122
        }
123
        charfront->device_setup = tapechar_setup;
124
#ifdef CONFIG_DEVFS_FS
125
        charfront->mkdevfstree = tapechar_mkdevfstree;
126
        charfront->rmdevfstree = tapechar_rmdevfstree;
127
#endif
128
#ifdef TAPE_DEBUG
129
        debug_text_event (tape_debug_area,3,"c:init ok");
130
#endif /* TAPE_DEBUG */
131
        charfront->next=NULL;
132
        if (first_frontend==NULL) {
133
            first_frontend=charfront;
134
        } else {
135
            temp=first_frontend;
136
            while (temp->next!=NULL)
137
                temp=temp->next;
138
            temp->next=charfront;
139
        }
140
        ti=first_tape_info;
141
        while (ti!=NULL) {
142
            tapechar_setup(ti);
143
            ti=ti->next;
144
        }
145
}
146
 
147
void
148
tapechar_uninit (void)
149
{
150
        unregister_chrdev (tape_major, "tape");
151
}
152
 
153
/*
154
 * Tape device read function
155
 */
156
ssize_t
157
tape_read (struct file *filp, char *data, size_t count, loff_t * ppos)
158
{
159
        long lockflags;
160
        tape_info_t *ti;
161
        size_t block_size;
162
        ccw_req_t *cqr;
163
        int rc;
164
#ifdef TAPE_DEBUG
165
        debug_text_event (tape_debug_area,6,"c:read");
166
#endif /* TAPE_DEBUG */
167
        ti = first_tape_info;
168
        while ((ti != NULL) && (ti->rew_filp != filp) && (ti->nor_filp != filp))
169
                ti = (tape_info_t *) ti->next;
170
        if (ti == NULL) {
171
#ifdef TAPE_DEBUG
172
                debug_text_event (tape_debug_area,6,"c:nodev");
173
#endif /* TAPE_DEBUG */
174
                return -ENODEV;
175
        }
176
        if (ppos != &filp->f_pos) {
177
                /* "A request was outside the capabilities of the device." */
178
#ifdef TAPE_DEBUG
179
                debug_text_event (tape_debug_area,6,"c:ppos wrong");
180
#endif /* TAPE_DEBUG */
181
                return -EOVERFLOW;      /* errno=75 Value too large for def. data type */
182
        }
183
        if (ti->block_size == 0) {
184
                block_size = count;
185
        } else {
186
                block_size = ti->block_size;
187
        }
188
#ifdef TAPE_DEBUG
189
        debug_text_event (tape_debug_area,6,"c:nbytes:");
190
        debug_int_event (tape_debug_area,6,block_size);
191
#endif
192
        cqr = ti->discipline->read_block (data, block_size, ti);
193
        if (!cqr) {
194
                return -ENOBUFS;
195
        }
196
        s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
197
        ti->cqr = cqr;
198
        ti->wanna_wakeup=0;
199
        rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
200
        if (rc) {
201
            tapestate_set(ti,TS_IDLE);
202
            kfree (cqr);
203
            s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
204
            return rc;
205
        }
206
        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
207
        wait_event (ti->wq,ti->wanna_wakeup);
208
        ti->cqr = NULL;
209
        ti->discipline->free_read_block (cqr, ti);
210
        s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
211
        if (tapestate_get (ti) == TS_FAILED) {
212
                tapestate_set (ti, TS_IDLE);
213
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
214
                return ti->rc;
215
        }
216
        if (tapestate_get (ti) == TS_NOT_OPER) {
217
            ti->blk_minor=ti->rew_minor=ti->nor_minor=-1;
218
            ti->devinfo.irq=-1;
219
            s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags);
220
            return -ENODEV;
221
        }
222
        if (tapestate_get (ti) != TS_DONE) {
223
                tapestate_set (ti, TS_IDLE);
224
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
225
                return -EIO;
226
        }
227
        tapestate_set (ti, TS_IDLE);
228
        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
229
#ifdef TAPE_DEBUG
230
        debug_text_event (tape_debug_area,6,"c:rbytes:");
231
        debug_int_event (tape_debug_area,6,block_size - ti->devstat.rescnt);
232
#endif  /* TAPE_DEBUG */
233
        filp->f_pos += block_size - ti->devstat.rescnt;
234
        return block_size - ti->devstat.rescnt;
235
}
236
 
237
/*
238
 * Tape device write function
239
 */
240
ssize_t
241
tape_write (struct file *filp, const char *data, size_t count, loff_t * ppos)
242
{
243
        long lockflags;
244
        tape_info_t *ti;
245
        size_t block_size;
246
        ccw_req_t *cqr;
247
        int nblocks, i, rc;
248
        size_t written = 0;
249
#ifdef TAPE_DEBUG
250
        debug_text_event (tape_debug_area,6,"c:write");
251
#endif
252
        ti = first_tape_info;
253
        while ((ti != NULL) && (ti->nor_filp != filp) && (ti->rew_filp != filp))
254
                ti = (tape_info_t *) ti->next;
255
        if (ti == NULL)
256
                return -ENODEV;
257
        if (ppos != &filp->f_pos) {
258
                /* "A request was outside the capabilities of the device." */
259
#ifdef TAPE_DEBUG
260
                debug_text_event (tape_debug_area,6,"c:ppos wrong");
261
#endif
262
                return -EOVERFLOW;      /* errno=75 Value too large for def. data type */
263
        }
264
        if ((ti->block_size != 0) && (count % ti->block_size != 0))
265
                return -EIO;
266
        if (ti->block_size == 0) {
267
                block_size = count;
268
                nblocks = 1;
269
        } else {
270
                block_size = ti->block_size;
271
                nblocks = count / (ti->block_size);
272
        }
273
#ifdef TAPE_DEBUG
274
                debug_text_event (tape_debug_area,6,"c:nbytes:");
275
                debug_int_event (tape_debug_area,6,block_size);
276
                debug_text_event (tape_debug_area,6,"c:nblocks:");
277
                debug_int_event (tape_debug_area,6,nblocks);
278
#endif
279
        for (i = 0; i < nblocks; i++) {
280
                cqr = ti->discipline->write_block (data + i * block_size, block_size, ti);
281
                if (!cqr) {
282
                        return -ENOBUFS;
283
                }
284
                s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
285
                ti->cqr = cqr;
286
                ti->wanna_wakeup=0;
287
                rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
288
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
289
                wait_event_interruptible (ti->wq,ti->wanna_wakeup);
290
                ti->cqr = NULL;
291
                ti->discipline->free_write_block (cqr, ti);
292
                if (signal_pending (current)) {
293
                        tapestate_set (ti, TS_IDLE);
294
                        return -ERESTARTSYS;
295
                }
296
                s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
297
                if (tapestate_get (ti) == TS_FAILED) {
298
                        tapestate_set (ti, TS_IDLE);
299
                        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
300
                        if ((ti->rc==-ENOSPC) && (i!=0))
301
                          return i*block_size;
302
                        return ti->rc;
303
                }
304
                if (tapestate_get (ti) == TS_NOT_OPER) {
305
                    ti->blk_minor=ti->rew_minor=ti->nor_minor=-1;
306
                    ti->devinfo.irq=-1;
307
                    s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags);
308
                    return -ENODEV;
309
                }
310
                if (tapestate_get (ti) != TS_DONE) {
311
                        tapestate_set (ti, TS_IDLE);
312
                        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
313
                        return -EIO;
314
                }
315
                tapestate_set (ti, TS_IDLE);
316
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
317
#ifdef TAPE_DEBUG
318
                debug_text_event (tape_debug_area,6,"c:wbytes:");
319
                debug_int_event (tape_debug_area,6,block_size - ti->devstat.rescnt);
320
#endif
321
                filp->f_pos += block_size - ti->devstat.rescnt;
322
                written += block_size - ti->devstat.rescnt;
323
                if (ti->devstat.rescnt > 0)
324
                        return written;
325
        }
326
#ifdef TAPE_DEBUG
327
        debug_text_event (tape_debug_area,6,"c:wtotal:");
328
        debug_int_event (tape_debug_area,6,written);
329
#endif
330
        return written;
331
}
332
 
333
static int
334
tape_mtioctop (struct file *filp, short mt_op, int mt_count)
335
{
336
        tape_info_t *ti;
337
        ccw_req_t *cqr = NULL;
338
        int rc;
339
        long lockflags;
340
#ifdef TAPE_DEBUG
341
        debug_text_event (tape_debug_area,6,"c:mtio");
342
        debug_text_event (tape_debug_area,6,"c:ioop:");
343
        debug_int_event (tape_debug_area,6,mt_op);
344
        debug_text_event (tape_debug_area,6,"c:arg:");
345
        debug_int_event (tape_debug_area,6,mt_count);
346
#endif
347
        ti = first_tape_info;
348
        while ((ti != NULL) && (ti->rew_filp != filp) && (ti->nor_filp != filp))
349
                ti = (tape_info_t *) ti->next;
350
        if (ti == NULL)
351
                return -ENODEV;
352
        switch (mt_op) {
353
        case MTREW:             // rewind
354
 
355
                cqr = ti->discipline->mtrew (ti, mt_count);
356
                break;
357
        case MTOFFL:            // put drive offline
358
 
359
                cqr = ti->discipline->mtoffl (ti, mt_count);
360
                break;
361
        case MTUNLOAD:          // unload the tape
362
 
363
                cqr = ti->discipline->mtunload (ti, mt_count);
364
                break;
365
        case MTWEOF:            // write tapemark
366
 
367
                cqr = ti->discipline->mtweof (ti, mt_count);
368
                break;
369
        case MTFSF:             // forward space file
370
 
371
                cqr = ti->discipline->mtfsf (ti, mt_count);
372
                break;
373
        case MTBSF:             // backward space file
374
 
375
                cqr = ti->discipline->mtbsf (ti, mt_count);
376
                break;
377
        case MTFSFM:            // forward space file, stop at BOT side
378
 
379
                cqr = ti->discipline->mtfsfm (ti, mt_count);
380
                break;
381
        case MTBSFM:            // backward space file, stop at BOT side
382
 
383
                cqr = ti->discipline->mtbsfm (ti, mt_count);
384
                break;
385
        case MTFSR:             // forward space file
386
 
387
                cqr = ti->discipline->mtfsr (ti, mt_count);
388
                break;
389
        case MTBSR:             // backward space file
390
 
391
                cqr = ti->discipline->mtbsr (ti, mt_count);
392
                break;
393
        case MTNOP:
394
                cqr = ti->discipline->mtnop (ti, mt_count);
395
                break;
396
        case MTEOM:             // postion at the end of portion
397
 
398
        case MTRETEN:           // retension the tape
399
 
400
                cqr = ti->discipline->mteom (ti, mt_count);
401
                break;
402
        case MTERASE:
403
                cqr = ti->discipline->mterase (ti, mt_count);
404
                break;
405
        case MTSETDENSITY:
406
                cqr = ti->discipline->mtsetdensity (ti, mt_count);
407
                break;
408
        case MTSEEK:
409
                cqr = ti->discipline->mtseek (ti, mt_count);
410
                break;
411
        case MTSETDRVBUFFER:
412
                cqr = ti->discipline->mtsetdrvbuffer (ti, mt_count);
413
                break;
414
        case MTLOCK:
415
                cqr = ti->discipline->mtsetdrvbuffer (ti, mt_count);
416
                break;
417
        case MTUNLOCK:
418
                cqr = ti->discipline->mtsetdrvbuffer (ti, mt_count);
419
                break;
420
        case MTLOAD:
421
                cqr = ti->discipline->mtload (ti, mt_count);
422
                if (cqr!=NULL) break; // if backend driver has an load function ->use it
423
                // if no medium is in, wait until it gets inserted
424
                if (ti->medium_is_unloaded) {
425
                    wait_event_interruptible (ti->wq,ti->medium_is_unloaded==0);
426
                }
427
                return 0;
428
        case MTCOMPRESSION:
429
                cqr = ti->discipline->mtcompression (ti, mt_count);
430
                break;
431
        case MTSETPART:
432
                cqr = ti->discipline->mtsetpart (ti, mt_count);
433
                break;
434
        case MTMKPART:
435
                cqr = ti->discipline->mtmkpart (ti, mt_count);
436
                break;
437
        case MTTELL:            // return number of block relative to current file
438
 
439
                cqr = ti->discipline->mttell (ti, mt_count);
440
                break;
441
        case MTSETBLK:
442
                s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
443
                ti->block_size = mt_count;
444
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
445
#ifdef TAPE_DEBUG
446
                debug_text_event (tape_debug_area,6,"c:setblk:");
447
                debug_int_event (tape_debug_area,6,mt_count);
448
#endif
449
                return 0;
450
        case MTRESET:
451
                s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
452
                ti->kernbuf = ti->userbuf = NULL;
453
                tapestate_set (ti, TS_IDLE);
454
                ti->block_size = 0;
455
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
456
#ifdef TAPE_DEBUG
457
                debug_text_event (tape_debug_area,6,"c:devreset:");
458
                debug_int_event (tape_debug_area,6,ti->blk_minor);
459
#endif
460
                return 0;
461
        default:
462
#ifdef TAPE_DEBUG
463
            debug_text_event (tape_debug_area,6,"c:inv.mtio");
464
#endif
465
                return -EINVAL;
466
        }
467
        if (cqr == NULL) {
468
#ifdef TAPE_DEBUG
469
                debug_text_event (tape_debug_area,6,"c:ccwg fail");
470
#endif
471
                return -ENOSPC;
472
        }
473
        s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
474
        ti->cqr = cqr;
475
        ti->wanna_wakeup=0;
476
        rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
477
        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
478
        wait_event_interruptible (ti->wq,ti->wanna_wakeup);
479
        ti->cqr = NULL;
480
        if (ti->kernbuf != NULL) {
481
                kfree (ti->kernbuf);
482
                ti->kernbuf = NULL;
483
        }
484
        tape_free_request (cqr);
485
        // if medium was unloaded, update the corresponding variable.
486
        switch (mt_op) {
487
        case MTOFFL:
488
        case MTUNLOAD:
489
            ti->medium_is_unloaded=1;
490
        }
491
        if (signal_pending (current)) {
492
                tapestate_set (ti, TS_IDLE);
493
                return -ERESTARTSYS;
494
        }
495
        s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
496
        if (((mt_op == MTEOM) || (mt_op == MTRETEN)) && (tapestate_get (ti) == TS_FAILED))
497
                tapestate_set (ti, TS_DONE);
498
        if (tapestate_get (ti) == TS_FAILED) {
499
                tapestate_set (ti, TS_IDLE);
500
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
501
                return ti->rc;
502
        }
503
        if (tapestate_get (ti) == TS_NOT_OPER) {
504
            ti->blk_minor=ti->rew_minor=ti->nor_minor=-1;
505
            ti->devinfo.irq=-1;
506
            s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags);
507
            return -ENODEV;
508
        }
509
        if (tapestate_get (ti) != TS_DONE) {
510
                tapestate_set (ti, TS_IDLE);
511
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
512
                return -EIO;
513
        }
514
        tapestate_set (ti, TS_IDLE);
515
        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
516
        switch (mt_op) {
517
        case MTRETEN:           //need to rewind the tape after moving to eom
518
 
519
                return tape_mtioctop (filp, MTREW, 1);
520
        case MTFSFM:            //need to skip back over the filemark
521
 
522
                return tape_mtioctop (filp, MTBSFM, 1);
523
        case MTBSF:             //need to skip forward over the filemark
524
 
525
                return tape_mtioctop (filp, MTFSF, 1);
526
        }
527
#ifdef TAPE_DEBUG
528
        debug_text_event (tape_debug_area,6,"c:mtio done");
529
#endif
530
        return 0;
531
}
532
 
533
/*
534
 * Tape device io controls.
535
 */
536
int
537
tape_ioctl (struct inode *inode, struct file *filp,
538
            unsigned int cmd, unsigned long arg)
539
{
540
        long lockflags;
541
        tape_info_t *ti;
542
        ccw_req_t *cqr;
543
        struct mtop op;         /* structure for MTIOCTOP */
544
        struct mtpos pos;       /* structure for MTIOCPOS */
545
        struct mtget get;
546
 
547
        int rc;
548
#ifdef TAPE_DEBUG
549
        debug_text_event (tape_debug_area,6,"c:ioct");
550
#endif
551
        ti = first_tape_info;
552
        while ((ti != NULL) &&
553
               (ti->rew_minor != MINOR (inode->i_rdev)) &&
554
               (ti->nor_minor != MINOR (inode->i_rdev)))
555
                ti = (tape_info_t *) ti->next;
556
        if (ti == NULL) {
557
#ifdef TAPE_DEBUG
558
                debug_text_event (tape_debug_area,6,"c:nodev");
559
#endif
560
                return -ENODEV;
561
        }
562
        // check for discipline ioctl overloading
563
        if ((rc = ti->discipline->discipline_ioctl_overload (inode, filp, cmd, arg))
564
            != -EINVAL) {
565
#ifdef TAPE_DEBUG
566
            debug_text_event (tape_debug_area,6,"c:ioverloa");
567
#endif
568
            return rc;
569
        }
570
 
571
        switch (cmd) {
572
        case MTIOCTOP:          /* tape op command */
573
                if (copy_from_user (&op, (char *) arg, sizeof (struct mtop))) {
574
                         return -EFAULT;
575
                }
576
                return (tape_mtioctop (filp, op.mt_op, op.mt_count));
577
        case MTIOCPOS:          /* query tape position */
578
                cqr = ti->discipline->mttell (ti, 0);
579
                s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
580
                ti->cqr = cqr;
581
                ti->wanna_wakeup=0;
582
                do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
583
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
584
                wait_event_interruptible (ti->wq,ti->wanna_wakeup);
585
                pos.mt_blkno = ti->rc;
586
                ti->cqr = NULL;
587
                if (ti->kernbuf != NULL) {
588
                        kfree (ti->kernbuf);
589
                        ti->kernbuf = NULL;
590
                }
591
                tape_free_request (cqr);
592
                if (signal_pending (current)) {
593
                        tapestate_set (ti, TS_IDLE);
594
                        return -ERESTARTSYS;
595
                }
596
                s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
597
                tapestate_set (ti, TS_IDLE);
598
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
599
                if (copy_to_user ((char *) arg, &pos, sizeof (struct mtpos)))
600
                         return -EFAULT;
601
                return 0;
602
        case MTIOCGET:
603
                get.mt_erreg = ti->rc;
604
                cqr = ti->discipline->mttell (ti, 0);
605
                s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
606
                ti->cqr = cqr;
607
                ti->wanna_wakeup=0;
608
                do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
609
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
610
                wait_event_interruptible (ti->wq,ti->wanna_wakeup);
611
                get.mt_blkno = ti->rc;
612
                get.mt_fileno = 0;
613
                get.mt_type = MT_ISUNKNOWN;
614
                get.mt_resid = ti->devstat.rescnt;
615
                get.mt_dsreg = ti->devstat.ii.sense.data[3];
616
                get.mt_gstat = 0;
617
                if (ti->devstat.ii.sense.data[1] & 0x08)
618
                        get.mt_gstat &= GMT_BOT (1);    // BOT
619
 
620
                if (ti->devstat.ii.sense.data[1] & 0x02)
621
                        get.mt_gstat &= GMT_WR_PROT (1);        // write protected
622
 
623
                if (ti->devstat.ii.sense.data[1] & 0x40)
624
                        get.mt_gstat &= GMT_ONLINE (1);         //drive online
625
 
626
                ti->cqr = NULL;
627
                if (ti->kernbuf != NULL) {
628
                        kfree (ti->kernbuf);
629
                        ti->kernbuf = NULL;
630
                }
631
                tape_free_request (cqr);
632
                if (signal_pending (current)) {
633
                        tapestate_set (ti, TS_IDLE);
634
                        return -ERESTARTSYS;
635
                }
636
                s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
637
                tapestate_set (ti, TS_IDLE);
638
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
639
                if (copy_to_user ((char *) arg, &get, sizeof (struct mtget)))
640
                         return -EFAULT;
641
                return 0;
642
        default:
643
#ifdef TAPE_DEBUG
644
                debug_text_event (tape_debug_area,3,"c:ioct inv");
645
#endif      
646
                return -EINVAL;
647
        }
648
}
649
 
650
/*
651
 * Tape device open function.
652
 */
653
int
654
tape_open (struct inode *inode, struct file *filp)
655
{
656
        tape_info_t *ti;
657
        kdev_t dev;
658
        long lockflags;
659
 
660
        inode = filp->f_dentry->d_inode;
661
        ti = first_tape_info;
662
        while ((ti != NULL) &&
663
               (ti->rew_minor != MINOR (inode->i_rdev)) &&
664
               (ti->nor_minor != MINOR (inode->i_rdev)))
665
                ti = (tape_info_t *) ti->next;
666
        if (ti == NULL)
667
                return -ENODEV;
668
#ifdef TAPE_DEBUG
669
        debug_text_event (tape_debug_area,6,"c:open:");
670
        debug_int_event (tape_debug_area,6,ti->blk_minor);
671
#endif
672
        s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
673
        if (tapestate_get (ti) != TS_UNUSED) {
674
                s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
675
#ifdef TAPE_DEBUG
676
                debug_text_event (tape_debug_area,6,"c:dbusy");
677
#endif
678
                return -EBUSY;
679
        }
680
        tapestate_set (ti, TS_IDLE);
681
        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
682
 
683
        dev = MKDEV (tape_major, MINOR (inode->i_rdev));        /* Get the device */
684
        s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
685
        if (ti->rew_minor == MINOR (inode->i_rdev))
686
                ti->rew_filp = filp;    /* save for later reference     */
687
        else
688
                ti->nor_filp = filp;
689
        filp->private_data = ti;        /* save the dev.info for later reference */
690
        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
691
 
692
#ifdef MODULE
693
        MOD_INC_USE_COUNT;
694
#endif                          /* MODULE */
695
        return 0;
696
}
697
 
698
/*
699
 * Tape device release function.
700
 */
701
int
702
tape_release (struct inode *inode, struct file *filp)
703
{
704
        long lockflags;
705
        tape_info_t *ti,*lastti;
706
        ccw_req_t *cqr = NULL;
707
        int rc = 0;
708
 
709
        ti = first_tape_info;
710
        while ((ti != NULL) && (ti->rew_minor != MINOR (inode->i_rdev)) && (ti->nor_minor != MINOR (inode->i_rdev)))
711
                ti = (tape_info_t *) ti->next;
712
        if ((ti != NULL) && (tapestate_get (ti) == TS_NOT_OPER)) {
713
            if (ti==first_tape_info) {
714
                first_tape_info=ti->next;
715
            } else {
716
                lastti=first_tape_info;
717
                while (lastti->next!=ti) lastti=lastti->next;
718
                lastti->next=ti->next;
719
            }
720
            kfree(ti);
721
            goto out;
722
        }
723
        if ((ti == NULL) || (tapestate_get (ti) != TS_IDLE)) {
724
#ifdef TAPE_DEBUG
725
        debug_text_event (tape_debug_area,6,"c:notidle!");
726
#endif
727
                rc = -ENXIO;    /* error in tape_release */
728
                goto out;
729
        }
730
#ifdef TAPE_DEBUG
731
        debug_text_event (tape_debug_area,6,"c:release:");
732
        debug_int_event (tape_debug_area,6,ti->blk_minor);
733
#endif
734
        if (ti->rew_minor == MINOR (inode->i_rdev)) {
735
                cqr = ti->discipline->mtrew (ti, 1);
736
                if (cqr != NULL) {
737
#ifdef TAPE_DEBUG
738
                        debug_text_event (tape_debug_area,6,"c:rewrelea");
739
#endif
740
                        s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
741
                        tapestate_set (ti, TS_REW_RELEASE_INIT);
742
                        ti->cqr = cqr;
743
                        ti->wanna_wakeup=0;
744
                        rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
745
                        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
746
                        wait_event (ti->wq,ti->wanna_wakeup);
747
                        ti->cqr = NULL;
748
                        tape_free_request (cqr);
749
                }
750
        }
751
        s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
752
        tapestate_set (ti, TS_UNUSED);
753
        s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
754
out:
755
#ifdef MODULE
756
        MOD_DEC_USE_COUNT;
757
#endif                          /* MODULE */
758
        return rc;
759
}

powered by: WebSVN 2.1.0

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