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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [viotape.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* -*- linux-c -*-
2
 *  drivers/char/viotape.c
3
 *
4
 *  iSeries Virtual Tape
5
 *
6
 *  Authors: Dave Boutcher <boutcher@us.ibm.com>
7
 *           Ryan Arnold <ryanarn@us.ibm.com>
8
 *           Colin Devilbiss <devilbis@us.ibm.com>
9
 *           Stephen Rothwell <sfr@au1.ibm.com>
10
 *
11
 * (C) Copyright 2000-2004 IBM Corporation
12
 *
13
 * This program is free software;  you can redistribute it and/or
14
 * modify it under the terms of the GNU General Public License as
15
 * published by the Free Software Foundation; either version 2 of the
16
 * License, or (at your option) anyu later version.
17
 *
18
 * This program is distributed in the hope that it will be useful, but
19
 * WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21
 * General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software Foundation,
25
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
 *
27
 * This routine provides access to tape drives owned and managed by an OS/400
28
 * partition running on the same box as this Linux partition.
29
 *
30
 * All tape operations are performed by sending messages back and forth to
31
 * the OS/400 partition.  The format of the messages is defined in
32
 * iseries/vio.h
33
 */
34
#include <linux/module.h>
35
#include <linux/kernel.h>
36
#include <linux/errno.h>
37
#include <linux/init.h>
38
#include <linux/wait.h>
39
#include <linux/spinlock.h>
40
#include <linux/mtio.h>
41
#include <linux/device.h>
42
#include <linux/dma-mapping.h>
43
#include <linux/fs.h>
44
#include <linux/cdev.h>
45
#include <linux/major.h>
46
#include <linux/completion.h>
47
#include <linux/proc_fs.h>
48
#include <linux/seq_file.h>
49
 
50
#include <asm/uaccess.h>
51
#include <asm/ioctls.h>
52
#include <asm/firmware.h>
53
#include <asm/vio.h>
54
#include <asm/iseries/vio.h>
55
#include <asm/iseries/hv_lp_event.h>
56
#include <asm/iseries/hv_call_event.h>
57
#include <asm/iseries/hv_lp_config.h>
58
 
59
#define VIOTAPE_VERSION         "1.2"
60
#define VIOTAPE_MAXREQ          1
61
 
62
#define VIOTAPE_KERN_WARN       KERN_WARNING "viotape: "
63
#define VIOTAPE_KERN_INFO       KERN_INFO "viotape: "
64
 
65
static int viotape_numdev;
66
 
67
/*
68
 * The minor number follows the conventions of the SCSI tape drives.  The
69
 * rewind and mode are encoded in the minor #.  We use this struct to break
70
 * them out
71
 */
72
struct viot_devinfo_struct {
73
        int devno;
74
        int mode;
75
        int rewind;
76
};
77
 
78
#define VIOTAPOP_RESET          0
79
#define VIOTAPOP_FSF            1
80
#define VIOTAPOP_BSF            2
81
#define VIOTAPOP_FSR            3
82
#define VIOTAPOP_BSR            4
83
#define VIOTAPOP_WEOF           5
84
#define VIOTAPOP_REW            6
85
#define VIOTAPOP_NOP            7
86
#define VIOTAPOP_EOM            8
87
#define VIOTAPOP_ERASE          9
88
#define VIOTAPOP_SETBLK        10
89
#define VIOTAPOP_SETDENSITY    11
90
#define VIOTAPOP_SETPOS        12
91
#define VIOTAPOP_GETPOS        13
92
#define VIOTAPOP_SETPART       14
93
#define VIOTAPOP_UNLOAD        15
94
 
95
enum viotaperc {
96
        viotape_InvalidRange = 0x0601,
97
        viotape_InvalidToken = 0x0602,
98
        viotape_DMAError = 0x0603,
99
        viotape_UseError = 0x0604,
100
        viotape_ReleaseError = 0x0605,
101
        viotape_InvalidTape = 0x0606,
102
        viotape_InvalidOp = 0x0607,
103
        viotape_TapeErr = 0x0608,
104
 
105
        viotape_AllocTimedOut = 0x0640,
106
        viotape_BOTEnc = 0x0641,
107
        viotape_BlankTape = 0x0642,
108
        viotape_BufferEmpty = 0x0643,
109
        viotape_CleanCartFound = 0x0644,
110
        viotape_CmdNotAllowed = 0x0645,
111
        viotape_CmdNotSupported = 0x0646,
112
        viotape_DataCheck = 0x0647,
113
        viotape_DecompressErr = 0x0648,
114
        viotape_DeviceTimeout = 0x0649,
115
        viotape_DeviceUnavail = 0x064a,
116
        viotape_DeviceBusy = 0x064b,
117
        viotape_EndOfMedia = 0x064c,
118
        viotape_EndOfTape = 0x064d,
119
        viotape_EquipCheck = 0x064e,
120
        viotape_InsufficientRs = 0x064f,
121
        viotape_InvalidLogBlk = 0x0650,
122
        viotape_LengthError = 0x0651,
123
        viotape_LibDoorOpen = 0x0652,
124
        viotape_LoadFailure = 0x0653,
125
        viotape_NotCapable = 0x0654,
126
        viotape_NotOperational = 0x0655,
127
        viotape_NotReady = 0x0656,
128
        viotape_OpCancelled = 0x0657,
129
        viotape_PhyLinkErr = 0x0658,
130
        viotape_RdyNotBOT = 0x0659,
131
        viotape_TapeMark = 0x065a,
132
        viotape_WriteProt = 0x065b
133
};
134
 
135
static const struct vio_error_entry viotape_err_table[] = {
136
        { viotape_InvalidRange, EIO, "Internal error" },
137
        { viotape_InvalidToken, EIO, "Internal error" },
138
        { viotape_DMAError, EIO, "DMA error" },
139
        { viotape_UseError, EIO, "Internal error" },
140
        { viotape_ReleaseError, EIO, "Internal error" },
141
        { viotape_InvalidTape, EIO, "Invalid tape device" },
142
        { viotape_InvalidOp, EIO, "Invalid operation" },
143
        { viotape_TapeErr, EIO, "Tape error" },
144
        { viotape_AllocTimedOut, EBUSY, "Allocate timed out" },
145
        { viotape_BOTEnc, EIO, "Beginning of tape encountered" },
146
        { viotape_BlankTape, EIO, "Blank tape" },
147
        { viotape_BufferEmpty, EIO, "Buffer empty" },
148
        { viotape_CleanCartFound, ENOMEDIUM, "Cleaning cartridge found" },
149
        { viotape_CmdNotAllowed, EIO, "Command not allowed" },
150
        { viotape_CmdNotSupported, EIO, "Command not supported" },
151
        { viotape_DataCheck, EIO, "Data check" },
152
        { viotape_DecompressErr, EIO, "Decompression error" },
153
        { viotape_DeviceTimeout, EBUSY, "Device timeout" },
154
        { viotape_DeviceUnavail, EIO, "Device unavailable" },
155
        { viotape_DeviceBusy, EBUSY, "Device busy" },
156
        { viotape_EndOfMedia, ENOSPC, "End of media" },
157
        { viotape_EndOfTape, ENOSPC, "End of tape" },
158
        { viotape_EquipCheck, EIO, "Equipment check" },
159
        { viotape_InsufficientRs, EOVERFLOW, "Insufficient tape resources" },
160
        { viotape_InvalidLogBlk, EIO, "Invalid logical block location" },
161
        { viotape_LengthError, EOVERFLOW, "Length error" },
162
        { viotape_LibDoorOpen, EBUSY, "Door open" },
163
        { viotape_LoadFailure, ENOMEDIUM, "Load failure" },
164
        { viotape_NotCapable, EIO, "Not capable" },
165
        { viotape_NotOperational, EIO, "Not operational" },
166
        { viotape_NotReady, EIO, "Not ready" },
167
        { viotape_OpCancelled, EIO, "Operation cancelled" },
168
        { viotape_PhyLinkErr, EIO, "Physical link error" },
169
        { viotape_RdyNotBOT, EIO, "Ready but not beginning of tape" },
170
        { viotape_TapeMark, EIO, "Tape mark" },
171
        { viotape_WriteProt, EROFS, "Write protection error" },
172
        { 0, 0, NULL },
173
};
174
 
175
/* Maximum number of tapes we support */
176
#define VIOTAPE_MAX_TAPE        HVMAXARCHITECTEDVIRTUALTAPES
177
#define MAX_PARTITIONS          4
178
 
179
/* defines for current tape state */
180
#define VIOT_IDLE               0
181
#define VIOT_READING            1
182
#define VIOT_WRITING            2
183
 
184
/* Our info on the tapes */
185
static struct {
186
        const char *rsrcname;
187
        const char *type;
188
        const char *model;
189
} viotape_unitinfo[VIOTAPE_MAX_TAPE];
190
 
191
static struct mtget viomtget[VIOTAPE_MAX_TAPE];
192
 
193
static struct class *tape_class;
194
 
195
static struct device *tape_device[VIOTAPE_MAX_TAPE];
196
 
197
/*
198
 * maintain the current state of each tape (and partition)
199
 * so that we know when to write EOF marks.
200
 */
201
static struct {
202
        unsigned char   cur_part;
203
        unsigned char   part_stat_rwi[MAX_PARTITIONS];
204
} state[VIOTAPE_MAX_TAPE];
205
 
206
/* We single-thread */
207
static struct semaphore reqSem;
208
 
209
/*
210
 * When we send a request, we use this struct to get the response back
211
 * from the interrupt handler
212
 */
213
struct op_struct {
214
        void                    *buffer;
215
        dma_addr_t              dmaaddr;
216
        size_t                  count;
217
        int                     rc;
218
        int                     non_blocking;
219
        struct completion       com;
220
        struct device           *dev;
221
        struct op_struct        *next;
222
};
223
 
224
static spinlock_t       op_struct_list_lock;
225
static struct op_struct *op_struct_list;
226
 
227
/* forward declaration to resolve interdependence */
228
static int chg_state(int index, unsigned char new_state, struct file *file);
229
 
230
/* procfs support */
231
static int proc_viotape_show(struct seq_file *m, void *v)
232
{
233
        int i;
234
 
235
        seq_printf(m, "viotape driver version " VIOTAPE_VERSION "\n");
236
        for (i = 0; i < viotape_numdev; i++) {
237
                seq_printf(m, "viotape device %d is iSeries resource %10.10s"
238
                                "type %4.4s, model %3.3s\n",
239
                                i, viotape_unitinfo[i].rsrcname,
240
                                viotape_unitinfo[i].type,
241
                                viotape_unitinfo[i].model);
242
        }
243
        return 0;
244
}
245
 
246
static int proc_viotape_open(struct inode *inode, struct file *file)
247
{
248
        return single_open(file, proc_viotape_show, NULL);
249
}
250
 
251
static const struct file_operations proc_viotape_operations = {
252
        .open           = proc_viotape_open,
253
        .read           = seq_read,
254
        .llseek         = seq_lseek,
255
        .release        = single_release,
256
};
257
 
258
/* Decode the device minor number into its parts */
259
void get_dev_info(struct inode *ino, struct viot_devinfo_struct *devi)
260
{
261
        devi->devno = iminor(ino) & 0x1F;
262
        devi->mode = (iminor(ino) & 0x60) >> 5;
263
        /* if bit is set in the minor, do _not_ rewind automatically */
264
        devi->rewind = (iminor(ino) & 0x80) == 0;
265
}
266
 
267
/* This is called only from the exit and init paths, so no need for locking */
268
static void clear_op_struct_pool(void)
269
{
270
        while (op_struct_list) {
271
                struct op_struct *toFree = op_struct_list;
272
                op_struct_list = op_struct_list->next;
273
                kfree(toFree);
274
        }
275
}
276
 
277
/* Likewise, this is only called from the init path */
278
static int add_op_structs(int structs)
279
{
280
        int i;
281
 
282
        for (i = 0; i < structs; ++i) {
283
                struct op_struct *new_struct =
284
                        kmalloc(sizeof(*new_struct), GFP_KERNEL);
285
                if (!new_struct) {
286
                        clear_op_struct_pool();
287
                        return -ENOMEM;
288
                }
289
                new_struct->next = op_struct_list;
290
                op_struct_list = new_struct;
291
        }
292
        return 0;
293
}
294
 
295
/* Allocate an op structure from our pool */
296
static struct op_struct *get_op_struct(void)
297
{
298
        struct op_struct *retval;
299
        unsigned long flags;
300
 
301
        spin_lock_irqsave(&op_struct_list_lock, flags);
302
        retval = op_struct_list;
303
        if (retval)
304
                op_struct_list = retval->next;
305
        spin_unlock_irqrestore(&op_struct_list_lock, flags);
306
        if (retval) {
307
                memset(retval, 0, sizeof(*retval));
308
                init_completion(&retval->com);
309
        }
310
 
311
        return retval;
312
}
313
 
314
/* Return an op structure to our pool */
315
static void free_op_struct(struct op_struct *op_struct)
316
{
317
        unsigned long flags;
318
 
319
        spin_lock_irqsave(&op_struct_list_lock, flags);
320
        op_struct->next = op_struct_list;
321
        op_struct_list = op_struct;
322
        spin_unlock_irqrestore(&op_struct_list_lock, flags);
323
}
324
 
325
/* Map our tape return codes to errno values */
326
int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
327
{
328
        const struct vio_error_entry *err;
329
 
330
        if (tape_rc == 0)
331
                return 0;
332
 
333
        err = vio_lookup_rc(viotape_err_table, tape_rc);
334
        printk(VIOTAPE_KERN_WARN "error(%s) 0x%04x on Device %d (%-10s): %s\n",
335
                        operation, tape_rc, tapeno,
336
                        viotape_unitinfo[tapeno].rsrcname, err->msg);
337
        return -err->errno;
338
}
339
 
340
/* Write */
341
static ssize_t viotap_write(struct file *file, const char *buf,
342
                size_t count, loff_t * ppos)
343
{
344
        HvLpEvent_Rc hvrc;
345
        unsigned short flags = file->f_flags;
346
        int noblock = ((flags & O_NONBLOCK) != 0);
347
        ssize_t ret;
348
        struct viot_devinfo_struct devi;
349
        struct op_struct *op = get_op_struct();
350
 
351
        if (op == NULL)
352
                return -ENOMEM;
353
 
354
        get_dev_info(file->f_path.dentry->d_inode, &devi);
355
 
356
        /*
357
         * We need to make sure we can send a request.  We use
358
         * a semaphore to keep track of # requests in use.  If
359
         * we are non-blocking, make sure we don't block on the
360
         * semaphore
361
         */
362
        if (noblock) {
363
                if (down_trylock(&reqSem)) {
364
                        ret = -EWOULDBLOCK;
365
                        goto free_op;
366
                }
367
        } else
368
                down(&reqSem);
369
 
370
        /* Allocate a DMA buffer */
371
        op->dev = tape_device[devi.devno];
372
        op->buffer = dma_alloc_coherent(op->dev, count, &op->dmaaddr,
373
                        GFP_ATOMIC);
374
 
375
        if (op->buffer == NULL) {
376
                printk(VIOTAPE_KERN_WARN
377
                                "error allocating dma buffer for len %ld\n",
378
                                count);
379
                ret = -EFAULT;
380
                goto up_sem;
381
        }
382
 
383
        /* Copy the data into the buffer */
384
        if (copy_from_user(op->buffer, buf, count)) {
385
                printk(VIOTAPE_KERN_WARN "tape: error on copy from user\n");
386
                ret = -EFAULT;
387
                goto free_dma;
388
        }
389
 
390
        op->non_blocking = noblock;
391
        init_completion(&op->com);
392
        op->count = count;
393
 
394
        hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
395
                        HvLpEvent_Type_VirtualIo,
396
                        viomajorsubtype_tape | viotapewrite,
397
                        HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
398
                        viopath_sourceinst(viopath_hostLp),
399
                        viopath_targetinst(viopath_hostLp),
400
                        (u64)(unsigned long)op, VIOVERSION << 16,
401
                        ((u64)devi.devno << 48) | op->dmaaddr, count, 0, 0);
402
        if (hvrc != HvLpEvent_Rc_Good) {
403
                printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
404
                                (int)hvrc);
405
                ret = -EIO;
406
                goto free_dma;
407
        }
408
 
409
        if (noblock)
410
                return count;
411
 
412
        wait_for_completion(&op->com);
413
 
414
        if (op->rc)
415
                ret = tape_rc_to_errno(op->rc, "write", devi.devno);
416
        else {
417
                chg_state(devi.devno, VIOT_WRITING, file);
418
                ret = op->count;
419
        }
420
 
421
free_dma:
422
        dma_free_coherent(op->dev, count, op->buffer, op->dmaaddr);
423
up_sem:
424
        up(&reqSem);
425
free_op:
426
        free_op_struct(op);
427
        return ret;
428
}
429
 
430
/* read */
431
static ssize_t viotap_read(struct file *file, char *buf, size_t count,
432
                loff_t *ptr)
433
{
434
        HvLpEvent_Rc hvrc;
435
        unsigned short flags = file->f_flags;
436
        struct op_struct *op = get_op_struct();
437
        int noblock = ((flags & O_NONBLOCK) != 0);
438
        ssize_t ret;
439
        struct viot_devinfo_struct devi;
440
 
441
        if (op == NULL)
442
                return -ENOMEM;
443
 
444
        get_dev_info(file->f_path.dentry->d_inode, &devi);
445
 
446
        /*
447
         * We need to make sure we can send a request.  We use
448
         * a semaphore to keep track of # requests in use.  If
449
         * we are non-blocking, make sure we don't block on the
450
         * semaphore
451
         */
452
        if (noblock) {
453
                if (down_trylock(&reqSem)) {
454
                        ret = -EWOULDBLOCK;
455
                        goto free_op;
456
                }
457
        } else
458
                down(&reqSem);
459
 
460
        chg_state(devi.devno, VIOT_READING, file);
461
 
462
        /* Allocate a DMA buffer */
463
        op->dev = tape_device[devi.devno];
464
        op->buffer = dma_alloc_coherent(op->dev, count, &op->dmaaddr,
465
                        GFP_ATOMIC);
466
        if (op->buffer == NULL) {
467
                ret = -EFAULT;
468
                goto up_sem;
469
        }
470
 
471
        op->count = count;
472
        init_completion(&op->com);
473
 
474
        hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
475
                        HvLpEvent_Type_VirtualIo,
476
                        viomajorsubtype_tape | viotaperead,
477
                        HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
478
                        viopath_sourceinst(viopath_hostLp),
479
                        viopath_targetinst(viopath_hostLp),
480
                        (u64)(unsigned long)op, VIOVERSION << 16,
481
                        ((u64)devi.devno << 48) | op->dmaaddr, count, 0, 0);
482
        if (hvrc != HvLpEvent_Rc_Good) {
483
                printk(VIOTAPE_KERN_WARN "tape hv error on op %d\n",
484
                                (int)hvrc);
485
                ret = -EIO;
486
                goto free_dma;
487
        }
488
 
489
        wait_for_completion(&op->com);
490
 
491
        if (op->rc)
492
                ret = tape_rc_to_errno(op->rc, "read", devi.devno);
493
        else {
494
                ret = op->count;
495
                if (ret && copy_to_user(buf, op->buffer, ret)) {
496
                        printk(VIOTAPE_KERN_WARN "error on copy_to_user\n");
497
                        ret = -EFAULT;
498
                }
499
        }
500
 
501
free_dma:
502
        dma_free_coherent(op->dev, count, op->buffer, op->dmaaddr);
503
up_sem:
504
        up(&reqSem);
505
free_op:
506
        free_op_struct(op);
507
        return ret;
508
}
509
 
510
/* ioctl */
511
static int viotap_ioctl(struct inode *inode, struct file *file,
512
                unsigned int cmd, unsigned long arg)
513
{
514
        HvLpEvent_Rc hvrc;
515
        int ret;
516
        struct viot_devinfo_struct devi;
517
        struct mtop mtc;
518
        u32 myOp;
519
        struct op_struct *op = get_op_struct();
520
 
521
        if (op == NULL)
522
                return -ENOMEM;
523
 
524
        get_dev_info(file->f_path.dentry->d_inode, &devi);
525
 
526
        down(&reqSem);
527
 
528
        ret = -EINVAL;
529
 
530
        switch (cmd) {
531
        case MTIOCTOP:
532
                ret = -EFAULT;
533
                /*
534
                 * inode is null if and only if we (the kernel)
535
                 * made the request
536
                 */
537
                if (inode == NULL)
538
                        memcpy(&mtc, (void *) arg, sizeof(struct mtop));
539
                else if (copy_from_user((char *)&mtc, (char *)arg,
540
                                        sizeof(struct mtop)))
541
                        goto free_op;
542
 
543
                ret = -EIO;
544
                switch (mtc.mt_op) {
545
                case MTRESET:
546
                        myOp = VIOTAPOP_RESET;
547
                        break;
548
                case MTFSF:
549
                        myOp = VIOTAPOP_FSF;
550
                        break;
551
                case MTBSF:
552
                        myOp = VIOTAPOP_BSF;
553
                        break;
554
                case MTFSR:
555
                        myOp = VIOTAPOP_FSR;
556
                        break;
557
                case MTBSR:
558
                        myOp = VIOTAPOP_BSR;
559
                        break;
560
                case MTWEOF:
561
                        myOp = VIOTAPOP_WEOF;
562
                        break;
563
                case MTREW:
564
                        myOp = VIOTAPOP_REW;
565
                        break;
566
                case MTNOP:
567
                        myOp = VIOTAPOP_NOP;
568
                        break;
569
                case MTEOM:
570
                        myOp = VIOTAPOP_EOM;
571
                        break;
572
                case MTERASE:
573
                        myOp = VIOTAPOP_ERASE;
574
                        break;
575
                case MTSETBLK:
576
                        myOp = VIOTAPOP_SETBLK;
577
                        break;
578
                case MTSETDENSITY:
579
                        myOp = VIOTAPOP_SETDENSITY;
580
                        break;
581
                case MTTELL:
582
                        myOp = VIOTAPOP_GETPOS;
583
                        break;
584
                case MTSEEK:
585
                        myOp = VIOTAPOP_SETPOS;
586
                        break;
587
                case MTSETPART:
588
                        myOp = VIOTAPOP_SETPART;
589
                        break;
590
                case MTOFFL:
591
                        myOp = VIOTAPOP_UNLOAD;
592
                        break;
593
                default:
594
                        printk(VIOTAPE_KERN_WARN "MTIOCTOP called "
595
                                        "with invalid op 0x%x\n", mtc.mt_op);
596
                        goto free_op;
597
                }
598
 
599
                /*
600
                 * if we moved the head, we are no longer
601
                 * reading or writing
602
                 */
603
                switch (mtc.mt_op) {
604
                case MTFSF:
605
                case MTBSF:
606
                case MTFSR:
607
                case MTBSR:
608
                case MTTELL:
609
                case MTSEEK:
610
                case MTREW:
611
                        chg_state(devi.devno, VIOT_IDLE, file);
612
                }
613
 
614
                init_completion(&op->com);
615
                hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
616
                                HvLpEvent_Type_VirtualIo,
617
                                viomajorsubtype_tape | viotapeop,
618
                                HvLpEvent_AckInd_DoAck,
619
                                HvLpEvent_AckType_ImmediateAck,
620
                                viopath_sourceinst(viopath_hostLp),
621
                                viopath_targetinst(viopath_hostLp),
622
                                (u64)(unsigned long)op,
623
                                VIOVERSION << 16,
624
                                ((u64)devi.devno << 48), 0,
625
                                (((u64)myOp) << 32) | mtc.mt_count, 0);
626
                if (hvrc != HvLpEvent_Rc_Good) {
627
                        printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
628
                                        (int)hvrc);
629
                        goto free_op;
630
                }
631
                wait_for_completion(&op->com);
632
                ret = tape_rc_to_errno(op->rc, "tape operation", devi.devno);
633
                goto free_op;
634
 
635
        case MTIOCGET:
636
                ret = -EIO;
637
                init_completion(&op->com);
638
                hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
639
                                HvLpEvent_Type_VirtualIo,
640
                                viomajorsubtype_tape | viotapegetstatus,
641
                                HvLpEvent_AckInd_DoAck,
642
                                HvLpEvent_AckType_ImmediateAck,
643
                                viopath_sourceinst(viopath_hostLp),
644
                                viopath_targetinst(viopath_hostLp),
645
                                (u64)(unsigned long)op, VIOVERSION << 16,
646
                                ((u64)devi.devno << 48), 0, 0, 0);
647
                if (hvrc != HvLpEvent_Rc_Good) {
648
                        printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
649
                                        (int)hvrc);
650
                        goto free_op;
651
                }
652
                wait_for_completion(&op->com);
653
 
654
                /* Operation is complete - grab the error code */
655
                ret = tape_rc_to_errno(op->rc, "get status", devi.devno);
656
                free_op_struct(op);
657
                up(&reqSem);
658
 
659
                if ((ret == 0) && copy_to_user((void *)arg,
660
                                        &viomtget[devi.devno],
661
                                        sizeof(viomtget[0])))
662
                        ret = -EFAULT;
663
                return ret;
664
        case MTIOCPOS:
665
                printk(VIOTAPE_KERN_WARN "Got an (unsupported) MTIOCPOS\n");
666
                break;
667
        default:
668
                printk(VIOTAPE_KERN_WARN "got an unsupported ioctl 0x%0x\n",
669
                                cmd);
670
                break;
671
        }
672
 
673
free_op:
674
        free_op_struct(op);
675
        up(&reqSem);
676
        return ret;
677
}
678
 
679
static int viotap_open(struct inode *inode, struct file *file)
680
{
681
        HvLpEvent_Rc hvrc;
682
        struct viot_devinfo_struct devi;
683
        int ret;
684
        struct op_struct *op = get_op_struct();
685
 
686
        if (op == NULL)
687
                return -ENOMEM;
688
 
689
        get_dev_info(file->f_path.dentry->d_inode, &devi);
690
 
691
        /* Note: We currently only support one mode! */
692
        if ((devi.devno >= viotape_numdev) || (devi.mode)) {
693
                ret = -ENODEV;
694
                goto free_op;
695
        }
696
 
697
        init_completion(&op->com);
698
 
699
        hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
700
                        HvLpEvent_Type_VirtualIo,
701
                        viomajorsubtype_tape | viotapeopen,
702
                        HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
703
                        viopath_sourceinst(viopath_hostLp),
704
                        viopath_targetinst(viopath_hostLp),
705
                        (u64)(unsigned long)op, VIOVERSION << 16,
706
                        ((u64)devi.devno << 48), 0, 0, 0);
707
        if (hvrc != 0) {
708
                printk(VIOTAPE_KERN_WARN "bad rc on signalLpEvent %d\n",
709
                                (int) hvrc);
710
                ret = -EIO;
711
                goto free_op;
712
        }
713
 
714
        wait_for_completion(&op->com);
715
        ret = tape_rc_to_errno(op->rc, "open", devi.devno);
716
 
717
free_op:
718
        free_op_struct(op);
719
        return ret;
720
}
721
 
722
 
723
static int viotap_release(struct inode *inode, struct file *file)
724
{
725
        HvLpEvent_Rc hvrc;
726
        struct viot_devinfo_struct devi;
727
        int ret = 0;
728
        struct op_struct *op = get_op_struct();
729
 
730
        if (op == NULL)
731
                return -ENOMEM;
732
        init_completion(&op->com);
733
 
734
        get_dev_info(file->f_path.dentry->d_inode, &devi);
735
 
736
        if (devi.devno >= viotape_numdev) {
737
                ret = -ENODEV;
738
                goto free_op;
739
        }
740
 
741
        chg_state(devi.devno, VIOT_IDLE, file);
742
 
743
        if (devi.rewind) {
744
                hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
745
                                HvLpEvent_Type_VirtualIo,
746
                                viomajorsubtype_tape | viotapeop,
747
                                HvLpEvent_AckInd_DoAck,
748
                                HvLpEvent_AckType_ImmediateAck,
749
                                viopath_sourceinst(viopath_hostLp),
750
                                viopath_targetinst(viopath_hostLp),
751
                                (u64)(unsigned long)op, VIOVERSION << 16,
752
                                ((u64)devi.devno << 48), 0,
753
                                ((u64)VIOTAPOP_REW) << 32, 0);
754
                wait_for_completion(&op->com);
755
 
756
                tape_rc_to_errno(op->rc, "rewind", devi.devno);
757
        }
758
 
759
        hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
760
                        HvLpEvent_Type_VirtualIo,
761
                        viomajorsubtype_tape | viotapeclose,
762
                        HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
763
                        viopath_sourceinst(viopath_hostLp),
764
                        viopath_targetinst(viopath_hostLp),
765
                        (u64)(unsigned long)op, VIOVERSION << 16,
766
                        ((u64)devi.devno << 48), 0, 0, 0);
767
        if (hvrc != 0) {
768
                printk(VIOTAPE_KERN_WARN "bad rc on signalLpEvent %d\n",
769
                                (int) hvrc);
770
                ret = -EIO;
771
                goto free_op;
772
        }
773
 
774
        wait_for_completion(&op->com);
775
 
776
        if (op->rc)
777
                printk(VIOTAPE_KERN_WARN "close failed\n");
778
 
779
free_op:
780
        free_op_struct(op);
781
        return ret;
782
}
783
 
784
const struct file_operations viotap_fops = {
785
        .owner =        THIS_MODULE,
786
        .read =         viotap_read,
787
        .write =        viotap_write,
788
        .ioctl =        viotap_ioctl,
789
        .open =         viotap_open,
790
        .release =      viotap_release,
791
};
792
 
793
/* Handle interrupt events for tape */
794
static void vioHandleTapeEvent(struct HvLpEvent *event)
795
{
796
        int tapeminor;
797
        struct op_struct *op;
798
        struct viotapelpevent *tevent = (struct viotapelpevent *)event;
799
 
800
        if (event == NULL) {
801
                /* Notification that a partition went away! */
802
                if (!viopath_isactive(viopath_hostLp)) {
803
                        /* TODO! Clean up */
804
                }
805
                return;
806
        }
807
 
808
        tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
809
        op = (struct op_struct *)event->xCorrelationToken;
810
        switch (tapeminor) {
811
        case viotapeopen:
812
        case viotapeclose:
813
                op->rc = tevent->sub_type_result;
814
                complete(&op->com);
815
                break;
816
        case viotaperead:
817
                op->rc = tevent->sub_type_result;
818
                op->count = tevent->len;
819
                complete(&op->com);
820
                break;
821
        case viotapewrite:
822
                if (op->non_blocking) {
823
                        dma_free_coherent(op->dev, op->count,
824
                                        op->buffer, op->dmaaddr);
825
                        free_op_struct(op);
826
                        up(&reqSem);
827
                } else {
828
                        op->rc = tevent->sub_type_result;
829
                        op->count = tevent->len;
830
                        complete(&op->com);
831
                }
832
                break;
833
        case viotapeop:
834
        case viotapegetpos:
835
        case viotapesetpos:
836
        case viotapegetstatus:
837
                if (op) {
838
                        op->count = tevent->u.op.count;
839
                        op->rc = tevent->sub_type_result;
840
                        if (!op->non_blocking)
841
                                complete(&op->com);
842
                }
843
                break;
844
        default:
845
                printk(VIOTAPE_KERN_WARN "weird ack\n");
846
        }
847
}
848
 
849
static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
850
{
851
        int i = vdev->unit_address;
852
        int j;
853
        struct device_node *node = vdev->dev.archdata.of_node;
854
 
855
        if (i > VIOTAPE_MAX_TAPE)
856
                return -ENODEV;
857
        if (!node)
858
                return -ENODEV;
859
 
860
        if (i >= viotape_numdev)
861
                viotape_numdev = i + 1;
862
 
863
        tape_device[i] = &vdev->dev;
864
        viotape_unitinfo[i].rsrcname = of_get_property(node,
865
                                        "linux,vio_rsrcname", NULL);
866
        viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
867
                                        NULL);
868
        viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
869
                                        NULL);
870
 
871
        state[i].cur_part = 0;
872
        for (j = 0; j < MAX_PARTITIONS; ++j)
873
                state[i].part_stat_rwi[j] = VIOT_IDLE;
874
        device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
875
                        "iseries!vt%d", i);
876
        device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
877
                        "iseries!nvt%d", i);
878
        printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
879
                        "resource %10.10s type %4.4s, model %3.3s\n",
880
                        i, viotape_unitinfo[i].rsrcname,
881
                        viotape_unitinfo[i].type, viotape_unitinfo[i].model);
882
        return 0;
883
}
884
 
885
static int viotape_remove(struct vio_dev *vdev)
886
{
887
        int i = vdev->unit_address;
888
 
889
        device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
890
        device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
891
        return 0;
892
}
893
 
894
/**
895
 * viotape_device_table: Used by vio.c to match devices that we
896
 * support.
897
 */
898
static struct vio_device_id viotape_device_table[] __devinitdata = {
899
        { "byte", "IBM,iSeries-viotape" },
900
        { "", "" }
901
};
902
MODULE_DEVICE_TABLE(vio, viotape_device_table);
903
 
904
static struct vio_driver viotape_driver = {
905
        .id_table = viotape_device_table,
906
        .probe = viotape_probe,
907
        .remove = viotape_remove,
908
        .driver = {
909
                .name = "viotape",
910
                .owner = THIS_MODULE,
911
        }
912
};
913
 
914
 
915
int __init viotap_init(void)
916
{
917
        int ret;
918
        struct proc_dir_entry *e;
919
 
920
        if (!firmware_has_feature(FW_FEATURE_ISERIES))
921
                return -ENODEV;
922
 
923
        op_struct_list = NULL;
924
        if ((ret = add_op_structs(VIOTAPE_MAXREQ)) < 0) {
925
                printk(VIOTAPE_KERN_WARN "couldn't allocate op structs\n");
926
                return ret;
927
        }
928
        spin_lock_init(&op_struct_list_lock);
929
 
930
        sema_init(&reqSem, VIOTAPE_MAXREQ);
931
 
932
        if (viopath_hostLp == HvLpIndexInvalid) {
933
                vio_set_hostlp();
934
                if (viopath_hostLp == HvLpIndexInvalid) {
935
                        ret = -ENODEV;
936
                        goto clear_op;
937
                }
938
        }
939
 
940
        ret = viopath_open(viopath_hostLp, viomajorsubtype_tape,
941
                        VIOTAPE_MAXREQ + 2);
942
        if (ret) {
943
                printk(VIOTAPE_KERN_WARN
944
                                "error on viopath_open to hostlp %d\n", ret);
945
                ret = -EIO;
946
                goto clear_op;
947
        }
948
 
949
        printk(VIOTAPE_KERN_INFO "vers " VIOTAPE_VERSION
950
                        ", hosting partition %d\n", viopath_hostLp);
951
 
952
        vio_setHandler(viomajorsubtype_tape, vioHandleTapeEvent);
953
 
954
        ret = register_chrdev(VIOTAPE_MAJOR, "viotape", &viotap_fops);
955
        if (ret < 0) {
956
                printk(VIOTAPE_KERN_WARN "Error registering viotape device\n");
957
                goto clear_handler;
958
        }
959
 
960
        tape_class = class_create(THIS_MODULE, "tape");
961
        if (IS_ERR(tape_class)) {
962
                printk(VIOTAPE_KERN_WARN "Unable to allocat class\n");
963
                ret = PTR_ERR(tape_class);
964
                goto unreg_chrdev;
965
        }
966
 
967
        ret = vio_register_driver(&viotape_driver);
968
        if (ret)
969
                goto unreg_class;
970
 
971
        e = create_proc_entry("iSeries/viotape", S_IFREG|S_IRUGO, NULL);
972
        if (e) {
973
                e->owner = THIS_MODULE;
974
                e->proc_fops = &proc_viotape_operations;
975
        }
976
 
977
        return 0;
978
 
979
unreg_class:
980
        class_destroy(tape_class);
981
unreg_chrdev:
982
        unregister_chrdev(VIOTAPE_MAJOR, "viotape");
983
clear_handler:
984
        vio_clearHandler(viomajorsubtype_tape);
985
        viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
986
clear_op:
987
        clear_op_struct_pool();
988
        return ret;
989
}
990
 
991
/* Give a new state to the tape object */
992
static int chg_state(int index, unsigned char new_state, struct file *file)
993
{
994
        unsigned char *cur_state =
995
            &state[index].part_stat_rwi[state[index].cur_part];
996
        int rc = 0;
997
 
998
        /* if the same state, don't bother */
999
        if (*cur_state == new_state)
1000
                return 0;
1001
 
1002
        /* write an EOF if changing from writing to some other state */
1003
        if (*cur_state == VIOT_WRITING) {
1004
                struct mtop write_eof = { MTWEOF, 1 };
1005
 
1006
                rc = viotap_ioctl(NULL, file, MTIOCTOP,
1007
                                  (unsigned long)&write_eof);
1008
        }
1009
        *cur_state = new_state;
1010
        return rc;
1011
}
1012
 
1013
/* Cleanup */
1014
static void __exit viotap_exit(void)
1015
{
1016
        remove_proc_entry("iSeries/viotape", NULL);
1017
        vio_unregister_driver(&viotape_driver);
1018
        class_destroy(tape_class);
1019
        unregister_chrdev(VIOTAPE_MAJOR, "viotape");
1020
        viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
1021
        vio_clearHandler(viomajorsubtype_tape);
1022
        clear_op_struct_pool();
1023
}
1024
 
1025
MODULE_LICENSE("GPL");
1026
module_init(viotap_init);
1027
module_exit(viotap_exit);

powered by: WebSVN 2.1.0

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