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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [block/] [paride/] [pt.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
        pt.c    (c) 1998  Grant R. Guenther <grant@torque.net>
3
                          Under the terms of the GNU General Public License.
4
 
5
        This is the high-level driver for parallel port ATAPI tape
6
        drives based on chips supported by the paride module.
7
 
8
        The driver implements both rewinding and non-rewinding
9
        devices, filemarks, and the rewind ioctl.  It allocates
10
        a small internal "bounce buffer" for each open device, but
11
        otherwise expects buffering and blocking to be done at the
12
        user level.  As with most block-structured tapes, short
13
        writes are padded to full tape blocks, so reading back a file
14
        may return more data than was actually written.
15
 
16
        By default, the driver will autoprobe for a single parallel
17
        port ATAPI tape drive, but if their individual parameters are
18
        specified, the driver can handle up to 4 drives.
19
 
20
        The rewinding devices are named /dev/pt0, /dev/pt1, ...
21
        while the non-rewinding devices are /dev/npt0, /dev/npt1, etc.
22
 
23
        The behaviour of the pt driver can be altered by setting
24
        some parameters from the insmod command line.  The following
25
        parameters are adjustable:
26
 
27
            drive0      These four arguments can be arrays of
28
            drive1      1-6 integers as follows:
29
            drive2
30
            drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
31
 
32
                        Where,
33
 
34
                <prt>   is the base of the parallel port address for
35
                        the corresponding drive.  (required)
36
 
37
                <pro>   is the protocol number for the adapter that
38
                        supports this drive.  These numbers are
39
                        logged by 'paride' when the protocol modules
40
                        are initialised.  (0 if not given)
41
 
42
                <uni>   for those adapters that support chained
43
                        devices, this is the unit selector for the
44
                        chain of devices on the given port.  It should
45
                        be zero for devices that don't support chaining.
46
                        (0 if not given)
47
 
48
                <mod>   this can be -1 to choose the best mode, or one
49
                        of the mode numbers supported by the adapter.
50
                        (-1 if not given)
51
 
52
                <slv>   ATAPI devices can be jumpered to master or slave.
53
                        Set this to 0 to choose the master drive, 1 to
54
                        choose the slave, -1 (the default) to choose the
55
                        first drive found.
56
 
57
                <dly>   some parallel ports require the driver to
58
                        go more slowly.  -1 sets a default value that
59
                        should work with the chosen protocol.  Otherwise,
60
                        set this to a small integer, the larger it is
61
                        the slower the port i/o.  In some cases, setting
62
                        this to zero will speed up the device. (default -1)
63
 
64
            major       You may use this parameter to overide the
65
                        default major number (96) that this driver
66
                        will use.  Be sure to change the device
67
                        name as well.
68
 
69
            name        This parameter is a character string that
70
                        contains the name the kernel will use for this
71
                        device (in /proc output, for instance).
72
                        (default "pt").
73
 
74
            verbose     This parameter controls the amount of logging
75
                        that the driver will do.  Set it to 0 for
76
                        normal operation, 1 to see autoprobe progress
77
                        messages, or 2 to see additional debugging
78
                        output.  (default 0)
79
 
80
        If this driver is built into the kernel, you can use
81
        the following command line parameters, with the same values
82
        as the corresponding module parameters listed above:
83
 
84
            pt.drive0
85
            pt.drive1
86
            pt.drive2
87
            pt.drive3
88
 
89
        In addition, you can use the parameter pt.disable to disable
90
        the driver entirely.
91
 
92
*/
93
 
94
/*   Changes:
95
 
96
        1.01    GRG 1998.05.06  Round up transfer size, fix ready_wait,
97
                                loosed interpretation of ATAPI standard
98
                                for clearing error status.
99
                                Eliminate sti();
100
        1.02    GRG 1998.06.16  Eliminate an Ugh.
101
        1.03    GRG 1998.08.15  Adjusted PT_TMO, use HZ in loop timing,
102
                                extra debugging
103
        1.04    GRG 1998.09.24  Repair minor coding error, added jumbo support
104
 
105
*/
106
 
107
#define PT_VERSION      "1.04"
108
#define PT_MAJOR        96
109
#define PT_NAME         "pt"
110
#define PT_UNITS        4
111
 
112
/* Here are things one can override from the insmod command.
113
   Most are autoprobed by paride unless set here.  Verbose is on
114
   by default.
115
 
116
*/
117
 
118
static int      verbose = 0;
119
static int      major = PT_MAJOR;
120
static char     *name = PT_NAME;
121
static int      disable = 0;
122
 
123
static int drive0[6] = {0,0,0,-1,-1,-1};
124
static int drive1[6] = {0,0,0,-1,-1,-1};
125
static int drive2[6] = {0,0,0,-1,-1,-1};
126
static int drive3[6] = {0,0,0,-1,-1,-1};
127
 
128
static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
129
static int pt_drive_count;
130
 
131
#define D_PRT   0
132
#define D_PRO   1
133
#define D_UNI   2
134
#define D_MOD   3
135
#define D_SLV   4
136
#define D_DLY   5
137
 
138
#define DU              (*drives[unit])
139
 
140
/* end of parameters */
141
 
142
 
143
#include <linux/module.h>
144
#include <linux/errno.h>
145
#include <linux/fs.h>
146
#include <linux/devfs_fs_kernel.h>
147
#include <linux/kernel.h>
148
#include <linux/delay.h>
149
#include <linux/slab.h>
150
#include <linux/mtio.h>
151
#include <linux/wait.h>
152
#include <linux/smp_lock.h>
153
 
154
#include <asm/uaccess.h>
155
 
156
#ifndef MODULE
157
 
158
#include "setup.h"
159
 
160
static STT pt_stt[5] = {{"drive0",6,drive0},
161
                        {"drive1",6,drive1},
162
                        {"drive2",6,drive2},
163
                        {"drive3",6,drive3},
164
                        {"disable",1,&disable}};
165
 
166
void pt_setup( char *str, int *ints)
167
 
168
{       generic_setup(pt_stt,5,str);
169
}
170
 
171
#endif
172
 
173
MODULE_PARM(verbose,"i");
174
MODULE_PARM(major,"i");
175
MODULE_PARM(name,"s");
176
MODULE_PARM(drive0,"1-6i");
177
MODULE_PARM(drive1,"1-6i");
178
MODULE_PARM(drive2,"1-6i");
179
MODULE_PARM(drive3,"1-6i");
180
 
181
#include "paride.h"
182
 
183
#define PT_MAX_RETRIES  5
184
#define PT_TMO          3000            /* interrupt timeout in jiffies */
185
#define PT_SPIN_DEL     50              /* spin delay in micro-seconds  */
186
#define PT_RESET_TMO    30              /* 30 seconds */
187
#define PT_READY_TMO    60              /* 60 seconds */
188
#define PT_REWIND_TMO   1200            /* 20 minutes */
189
 
190
#define PT_SPIN         ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)  
191
 
192
#define STAT_ERR        0x00001
193
#define STAT_INDEX      0x00002
194
#define STAT_ECC        0x00004
195
#define STAT_DRQ        0x00008
196
#define STAT_SEEK       0x00010
197
#define STAT_WRERR      0x00020
198
#define STAT_READY      0x00040
199
#define STAT_BUSY       0x00080
200
#define STAT_SENSE      0x1f000
201
 
202
#define ATAPI_TEST_READY        0x00
203
#define ATAPI_REWIND            0x01
204
#define ATAPI_REQ_SENSE         0x03
205
#define ATAPI_READ_6            0x08
206
#define ATAPI_WRITE_6           0x0a
207
#define ATAPI_WFM               0x10
208
#define ATAPI_IDENTIFY          0x12
209
#define ATAPI_MODE_SENSE        0x1a
210
#define ATAPI_LOG_SENSE         0x4d
211
 
212
int pt_init(void);
213
#ifdef MODULE
214
void cleanup_module( void );
215
#endif
216
 
217
static int pt_open(struct inode *inode, struct file *file);
218
static int pt_ioctl(struct inode *inode,struct file *file,
219
                    unsigned int cmd, unsigned long arg);
220
static int pt_release (struct inode *inode, struct file *file);
221
static ssize_t pt_read(struct file * filp, char * buf,
222
                       size_t count, loff_t *ppos);
223
static ssize_t pt_write(struct file * filp, const char * buf,
224
                        size_t count, loff_t *ppos);
225
static int pt_detect(void);
226
 
227
static int pt_identify (int unit);
228
 
229
/* bits in PT.flags */
230
 
231
#define PT_MEDIA        1
232
#define PT_WRITE_OK     2
233
#define PT_REWIND       4
234
#define PT_WRITING      8
235
#define PT_READING     16
236
#define PT_EOF         32
237
 
238
#define PT_NAMELEN      8
239
#define PT_BUFSIZE  16384
240
 
241
struct pt_unit {
242
        struct pi_adapter pia;    /* interface to paride layer */
243
        struct pi_adapter *pi;
244
        int flags;                /* various state flags */
245
        int last_sense;           /* result of last request sense */
246
        int drive;                /* drive */
247
        int access;               /* count of active opens ... */
248
        int bs;                   /* block size */
249
        int capacity;             /* Size of tape in KB */
250
        int present;              /* device present ? */
251
        char *bufptr;
252
        char name[PT_NAMELEN];    /* pf0, pf1, ... */
253
        };
254
 
255
struct pt_unit pt[PT_UNITS];
256
 
257
/*  'unit' must be defined in all functions - either as a local or a param */
258
 
259
#define PT pt[unit]
260
#define PI PT.pi
261
 
262
static char pt_scratch[512];            /* scratch block buffer */
263
 
264
/* kernel glue structures */
265
 
266
static struct file_operations pt_fops = {
267
        owner:          THIS_MODULE,
268
        read:           pt_read,
269
        write:          pt_write,
270
        ioctl:          pt_ioctl,
271
        open:           pt_open,
272
        release:        pt_release,
273
};
274
 
275
void pt_init_units( void )
276
 
277
{       int     unit, j;
278
 
279
        pt_drive_count = 0;
280
        for (unit=0;unit<PT_UNITS;unit++) {
281
                PT.pi = & PT.pia;
282
                PT.access = 0;
283
                PT.flags = 0;
284
                PT.last_sense = 0;
285
                PT.present = 0;
286
                PT.bufptr = NULL;
287
                PT.drive = DU[D_SLV];
288
                j = 0;
289
                while ((j < PT_NAMELEN-2) && (PT.name[j]=name[j])) j++;
290
                PT.name[j++] = '0' + unit;
291
                PT.name[j] = 0;
292
                if (DU[D_PRT]) pt_drive_count++;
293
        }
294
}
295
 
296
static devfs_handle_t devfs_handle;
297
 
298
int pt_init (void)      /* preliminary initialisation */
299
 
300
{       int unit;
301
 
302
        if (disable) return -1;
303
 
304
        pt_init_units();
305
 
306
        if (pt_detect()) return -1;
307
 
308
        if (devfs_register_chrdev(major,name,&pt_fops)) {
309
                printk("pt_init: unable to get major number %d\n",
310
                        major);
311
                for (unit=0;unit<PT_UNITS;unit++)
312
                  if (PT.present) pi_release(PI);
313
                return -1;
314
        }
315
 
316
        devfs_handle = devfs_mk_dir (NULL, "pt", NULL);
317
        devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT,
318
                               major, 0, S_IFCHR | S_IRUSR | S_IWUSR,
319
                               &pt_fops, NULL);
320
        devfs_register_series (devfs_handle, "%un", 4, DEVFS_FL_DEFAULT,
321
                               major, 128, S_IFCHR | S_IRUSR | S_IWUSR,
322
                               &pt_fops, NULL);
323
        return 0;
324
}
325
 
326
#ifdef MODULE
327
 
328
/* Glue for modules ... */
329
 
330
void    cleanup_module(void);
331
 
332
int     init_module(void)
333
 
334
{       int     err;
335
 
336
#ifdef PARIDE_JUMBO
337
       { extern paride_init();
338
         paride_init();
339
       }
340
#endif
341
 
342
        err = pt_init();
343
 
344
        return err;
345
}
346
 
347
void    cleanup_module(void)
348
 
349
{       int unit;
350
 
351
        devfs_unregister (devfs_handle);
352
        devfs_unregister_chrdev(major,name);
353
 
354
        for (unit=0;unit<PT_UNITS;unit++)
355
          if (PT.present) pi_release(PI);
356
}
357
 
358
#endif
359
 
360
#define WR(c,r,v)       pi_write_regr(PI,c,r,v)
361
#define RR(c,r)         (pi_read_regr(PI,c,r))
362
 
363
#define DRIVE           (0xa0+0x10*PT.drive)
364
 
365
static int pt_wait( int unit, int go, int stop, char * fun, char * msg )
366
 
367
{       int j, r, e, s, p;
368
 
369
        j = 0;
370
        while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PT_SPIN))
371
                udelay(PT_SPIN_DEL);
372
 
373
        if ((r&(STAT_ERR&stop))||(j>=PT_SPIN)) {
374
           s = RR(0,7);
375
           e = RR(0,1);
376
           p = RR(0,2);
377
           if (j >= PT_SPIN) e |= 0x100;
378
           if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
379
                           " loop=%d phase=%d\n",
380
                            PT.name,fun,msg,r,s,e,j,p);
381
           return (e<<8)+s;
382
        }
383
        return 0;
384
}
385
 
386
static int pt_command( int unit, char * cmd, int dlen, char * fun )
387
 
388
{       pi_connect(PI);
389
 
390
        WR(0,6,DRIVE);
391
 
392
        if (pt_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) {
393
                pi_disconnect(PI);
394
                return -1;
395
        }
396
 
397
        WR(0,4,dlen % 256);
398
        WR(0,5,dlen / 256);
399
        WR(0,7,0xa0);          /* ATAPI packet command */
400
 
401
        if (pt_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) {
402
                pi_disconnect(PI);
403
                return -1;
404
        }
405
 
406
        if (RR(0,2) != 1) {
407
           printk("%s: %s: command phase error\n",PT.name,fun);
408
           pi_disconnect(PI);
409
           return -1;
410
        }
411
 
412
        pi_write_block(PI,cmd,12);
413
 
414
        return 0;
415
}
416
 
417
static int pt_completion( int unit, char * buf, char * fun )
418
 
419
{       int r, s, n, p;
420
 
421
        r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
422
                        fun,"completion");
423
 
424
        if (RR(0,7)&STAT_DRQ) {
425
           n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
426
           p = RR(0,2)&3;
427
           if (p == 0) pi_write_block(PI,buf,n);
428
           if (p == 2) pi_read_block(PI,buf,n);
429
        }
430
 
431
        s = pt_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done");
432
 
433
        pi_disconnect(PI);
434
 
435
        return (r?r:s);
436
}
437
 
438
static void pt_req_sense( int unit, int quiet )
439
 
440
{       char    rs_cmd[12] = { ATAPI_REQ_SENSE,0,0,0,16,0,0,0,0,0,0,0 };
441
        char    buf[16];
442
        int     r;
443
 
444
        r = pt_command(unit,rs_cmd,16,"Request sense");
445
        mdelay(1);
446
        if (!r) pt_completion(unit,buf,"Request sense");
447
 
448
        PT.last_sense = -1;
449
        if (!r) {
450
            if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
451
                                    PT.name,buf[2]&0xf,buf[12],buf[13]);
452
            PT.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8)
453
                                         | ((buf[13]&0xff)<<16) ;
454
        }
455
}
456
 
457
static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
458
 
459
{       int r;
460
 
461
        r = pt_command(unit,cmd,dlen,fun);
462
        mdelay(1);
463
        if (!r) r = pt_completion(unit,buf,fun);
464
        if (r) pt_req_sense(unit,!fun);
465
 
466
        return r;
467
}
468
 
469
static void pt_sleep( int cs )
470
 
471
{       current->state = TASK_INTERRUPTIBLE;
472
        schedule_timeout(cs);
473
}
474
 
475
static int pt_poll_dsc( int unit, int pause, int tmo, char *msg )
476
 
477
{       int     k, e, s;
478
 
479
        k = 0; e = 0; s = 0;
480
        while (k < tmo) {
481
                pt_sleep(pause);
482
                k++;
483
                pi_connect(PI);
484
                WR(0,6,DRIVE);
485
                s = RR(0,7);
486
                e = RR(0,1);
487
                pi_disconnect(PI);
488
                if (s & (STAT_ERR|STAT_SEEK)) break;
489
        }
490
        if ((k >= tmo) || (s & STAT_ERR)) {
491
           if (k >= tmo) printk("%s: %s DSC timeout\n",PT.name,msg);
492
             else printk("%s: %s stat=0x%x err=0x%x\n",PT.name,msg,s,e);
493
           pt_req_sense(unit,0);
494
           return 0;
495
        }
496
        return 1;
497
}
498
 
499
static void pt_media_access_cmd( int unit, int tmo, char *cmd, char *fun)
500
 
501
{       if (pt_command(unit,cmd,0,fun)) {
502
                pt_req_sense(unit,0);
503
                return;
504
        }
505
        pi_disconnect(PI);
506
        pt_poll_dsc(unit,HZ,tmo,fun);
507
}
508
 
509
static void pt_rewind( int unit )
510
 
511
{       char    rw_cmd[12] = {ATAPI_REWIND,0,0,0,0,0,0,0,0,0,0,0};
512
 
513
        pt_media_access_cmd(unit,PT_REWIND_TMO,rw_cmd,"rewind");
514
}
515
 
516
static void pt_write_fm( int unit )
517
 
518
{       char    wm_cmd[12] = {ATAPI_WFM,0,0,0,1,0,0,0,0,0,0,0};
519
 
520
        pt_media_access_cmd(unit,PT_TMO,wm_cmd,"write filemark");
521
}
522
 
523
#define DBMSG(msg)      ((verbose>1)?(msg):NULL)
524
 
525
static int pt_reset( int unit )
526
 
527
{       int     i, k, flg;
528
        int     expect[5] = {1,1,1,0x14,0xeb};
529
 
530
        pi_connect(PI);
531
        WR(0,6,DRIVE);
532
        WR(0,7,8);
533
 
534
        pt_sleep(20*HZ/1000);
535
 
536
        k = 0;
537
        while ((k++ < PT_RESET_TMO) && (RR(1,6)&STAT_BUSY))
538
                pt_sleep(HZ/10);
539
 
540
        flg = 1;
541
        for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
542
 
543
        if (verbose) {
544
                printk("%s: Reset (%d) signature = ",PT.name,k);
545
                for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
546
                if (!flg) printk(" (incorrect)");
547
                printk("\n");
548
        }
549
 
550
        pi_disconnect(PI);
551
        return flg-1;
552
}
553
 
554
static int pt_ready_wait( int unit, int tmo )
555
 
556
{       char    tr_cmd[12] = {ATAPI_TEST_READY,0,0,0,0,0,0,0,0,0,0,0};
557
        int     k, p;
558
 
559
        k = 0;
560
        while (k < tmo) {
561
          PT.last_sense = 0;
562
          pt_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
563
          p = PT.last_sense;
564
          if (!p) return 0;
565
          if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p;
566
          k++;
567
          pt_sleep(HZ);
568
        }
569
        return 0x000020;        /* timeout */
570
}
571
 
572
static void xs( char *buf, char *targ, int offs, int len )
573
 
574
{       int     j,k,l;
575
 
576
        j=0; l=0;
577
        for (k=0;k<len;k++)
578
           if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
579
                l=targ[j++]=buf[k+offs];
580
        if (l==0x20) j--;
581
        targ[j]=0;
582
}
583
 
584
static int xn( char *buf, int offs, int size )
585
 
586
{       int     v,k;
587
 
588
        v=0;
589
        for(k=0;k<size;k++) v=v*256+(buf[k+offs]&0xff);
590
        return v;
591
}
592
 
593
static int pt_identify( int unit )
594
 
595
{       int     dt, s;
596
        char    *ms[2] = {"master","slave"};
597
        char    mf[10], id[18];
598
        char    id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
599
        char    ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,36,0,0,0,0,0,0,0};
600
        char    ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,36,0,0,0};
601
        char    buf[36];
602
 
603
        s = pt_atapi(unit,id_cmd,36,buf,"identify");
604
        if (s) return -1;
605
 
606
        dt = buf[0] & 0x1f;
607
        if (dt != 1) {
608
                if (verbose)
609
                   printk("%s: Drive %d, unsupported type %d\n",
610
                                PT.name,PT.drive,dt);
611
                return -1;
612
        }
613
 
614
        xs(buf,mf,8,8);
615
        xs(buf,id,16,16);
616
 
617
        PT.flags = 0;
618
        PT.capacity = 0;
619
        PT.bs = 0;
620
 
621
        if (!pt_ready_wait(unit,PT_READY_TMO)) PT.flags |= PT_MEDIA;
622
 
623
        if (!pt_atapi(unit,ms_cmd,36,buf,"mode sense")) {
624
          if (!(buf[2] & 0x80)) PT.flags |= PT_WRITE_OK;
625
          PT.bs = xn(buf,10,2);
626
        }
627
 
628
        if (!pt_atapi(unit,ls_cmd,36,buf,"log sense"))
629
                PT.capacity = xn(buf,24,4);
630
 
631
        printk("%s: %s %s, %s",
632
                PT.name,mf,id,ms[PT.drive]);
633
        if (!(PT.flags & PT_MEDIA))
634
                printk(", no media\n");
635
        else {  if (!(PT.flags & PT_WRITE_OK)) printk(", RO");
636
                printk(", blocksize %d, %d MB\n",
637
                       PT.bs,PT.capacity/1024);
638
        }
639
 
640
        return 0;
641
}
642
 
643
static int pt_probe( int unit )
644
 
645
/*      returns  0, with id set if drive is detected
646
                -1, if drive detection failed
647
*/
648
 
649
{       if (PT.drive == -1) {
650
           for (PT.drive=0;PT.drive<=1;PT.drive++)
651
                if (!pt_reset(unit)) return pt_identify(unit);
652
        } else {
653
           if (!pt_reset(unit)) return pt_identify(unit);
654
        }
655
        return -1;
656
}
657
 
658
static int pt_detect( void )
659
 
660
{       int     k, unit;
661
 
662
        printk("%s: %s version %s, major %d\n",
663
                name,name,PT_VERSION,major);
664
 
665
        k = 0;
666
        if (pt_drive_count == 0) {
667
            unit = 0;
668
            if (pi_init(PI,1,-1,-1,-1,-1,-1,pt_scratch,
669
                        PI_PT,verbose,PT.name)) {
670
                if (!pt_probe(unit)) {
671
                        PT.present = 1;
672
                        k++;
673
                } else pi_release(PI);
674
            }
675
 
676
        } else for (unit=0;unit<PT_UNITS;unit++) if (DU[D_PRT])
677
            if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
678
                        DU[D_PRO],DU[D_DLY],pt_scratch,PI_PT,verbose,
679
                        PT.name)) {
680
                if (!pt_probe(unit)) {
681
                        PT.present = 1;
682
                        k++;
683
                } else pi_release(PI);
684
            }
685
 
686
        if (k) return 0;
687
 
688
        printk("%s: No ATAPI tape drive detected\n",name);
689
        return -1;
690
}
691
 
692
#define DEVICE_NR(dev)  (MINOR(dev) % 128)
693
 
694
static int pt_open (struct inode *inode, struct file *file)
695
 
696
{       int     unit = DEVICE_NR(inode->i_rdev);
697
 
698
        if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV;
699
 
700
        PT.access++;
701
 
702
        if (PT.access > 1) {
703
                PT.access--;
704
                return -EBUSY;
705
        }
706
 
707
        pt_identify(unit);
708
 
709
        if (!PT.flags & PT_MEDIA) {
710
                PT.access--;
711
                return -ENODEV;
712
                }
713
 
714
        if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) {
715
                PT.access--;
716
                return -EROFS;
717
                }
718
 
719
        if (!(MINOR(inode->i_rdev) & 128))
720
                PT.flags |= PT_REWIND;
721
 
722
        PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL);
723
        if (PT.bufptr == NULL) {
724
                PT.access--;
725
                printk("%s: buffer allocation failed\n",PT.name);
726
                return -ENOMEM;
727
        }
728
 
729
        return 0;
730
}
731
 
732
static int pt_ioctl(struct inode *inode,struct file *file,
733
                    unsigned int cmd, unsigned long arg)
734
{
735
        int unit;
736
        struct mtop mtop;
737
 
738
        if (!inode || !inode->i_rdev)
739
                return -EINVAL;
740
        unit = DEVICE_NR(inode->i_rdev);
741
        if (unit >= PT_UNITS)
742
                return -EINVAL;
743
        if (!PT.present)
744
                return -ENODEV;
745
 
746
        switch (cmd) {
747
            case MTIOCTOP:
748
                if (copy_from_user((char *)&mtop, (char *)arg,
749
                                   sizeof(struct mtop))) return -EFAULT;
750
 
751
                switch (mtop.mt_op) {
752
 
753
                    case MTREW:
754
                        pt_rewind(unit);
755
                        return 0;
756
 
757
                    case MTWEOF:
758
                        pt_write_fm(unit);
759
                        return 0;
760
 
761
                    default:
762
                        printk("%s: Unimplemented mt_op %d\n",PT.name,
763
                                        mtop.mt_op);
764
                        return -EINVAL;
765
                }
766
 
767
            default:
768
                printk("%s: Unimplemented ioctl 0x%x\n",PT.name,cmd);
769
                return -EINVAL;
770
 
771
        }
772
}
773
 
774
 
775
static int pt_release (struct inode *inode, struct file *file)
776
{
777
        int     unit = DEVICE_NR(inode->i_rdev);
778
 
779
        if ((unit >= PT_UNITS) || (PT.access <= 0))
780
                return -EINVAL;
781
 
782
        lock_kernel();
783
        if (PT.flags & PT_WRITING) pt_write_fm(unit);
784
 
785
        if (PT.flags & PT_REWIND) pt_rewind(unit);
786
 
787
        PT.access--;
788
 
789
        kfree(PT.bufptr);
790
        PT.bufptr = NULL;
791
        unlock_kernel();
792
 
793
        return 0;
794
 
795
}
796
 
797
static ssize_t pt_read(struct file * filp, char * buf,
798
                       size_t count, loff_t *ppos)
799
{
800
        struct  inode *ino = filp->f_dentry->d_inode;
801
        int     unit = DEVICE_NR(ino->i_rdev);
802
        char    rd_cmd[12] = {ATAPI_READ_6,1,0,0,0,0,0,0,0,0,0,0};
803
        int     k, n, r, p, s, t, b;
804
 
805
        if (!(PT.flags & (PT_READING|PT_WRITING))) {
806
            PT.flags |= PT_READING;
807
            if (pt_atapi(unit,rd_cmd,0,NULL,"start read-ahead"))
808
                        return -EIO;
809
        } else if (PT.flags & PT_WRITING) return -EIO;
810
 
811
        if (PT.flags & PT_EOF) return 0;
812
 
813
        t = 0;
814
 
815
        while (count > 0) {
816
 
817
            if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"read")) return -EIO;
818
 
819
            n = count;
820
            if (n > 32768) n = 32768;   /* max per command */
821
            b = (n-1+PT.bs)/PT.bs;
822
            n = b*PT.bs;                /* rounded up to even block */
823
 
824
            rd_cmd[4] = b;
825
 
826
            r = pt_command(unit,rd_cmd,n,"read");
827
 
828
            mdelay(1);
829
 
830
            if (r) {
831
                pt_req_sense(unit,0);
832
                return -EIO;
833
            }
834
 
835
            while (1) {
836
 
837
                r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
838
                                           DBMSG("read DRQ"),"");
839
 
840
                if (r & STAT_SENSE) {
841
                    pi_disconnect(PI);
842
                    pt_req_sense(unit,0);
843
                    return -EIO;
844
                }
845
 
846
                if (r) PT.flags |= PT_EOF;
847
 
848
                s = RR(0,7);
849
 
850
                if (!(s & STAT_DRQ)) break;
851
 
852
                n = (RR(0,4)+256*RR(0,5));
853
                p = (RR(0,2)&3);
854
                if (p != 2) {
855
                    pi_disconnect(PI);
856
                    printk("%s: Phase error on read: %d\n",PT.name,p);
857
                    return -EIO;
858
                }
859
 
860
                while (n > 0) {
861
                    k = n;
862
                    if (k > PT_BUFSIZE) k = PT_BUFSIZE;
863
                    pi_read_block(PI,PT.bufptr,k);
864
                    n -= k;
865
                    b = k;
866
                    if (b > count) b = count;
867
                    if (copy_to_user(buf + t, PT.bufptr, b)) {
868
                        pi_disconnect(PI);
869
                        return -EFAULT;
870
                    }
871
                    t += b;
872
                    count -= b;
873
                }
874
 
875
            }
876
            pi_disconnect(PI);
877
            if (PT.flags & PT_EOF) break;
878
        }
879
 
880
        return t;
881
 
882
}
883
 
884
static ssize_t pt_write(struct file * filp, const char * buf,
885
                        size_t count, loff_t *ppos)
886
{
887
        struct inode *ino = filp->f_dentry->d_inode;
888
        int unit = DEVICE_NR(ino->i_rdev);
889
        char    wr_cmd[12] = {ATAPI_WRITE_6,1,0,0,0,0,0,0,0,0,0,0};
890
        int     k, n, r, p, s, t, b;
891
 
892
        if (!(PT.flags & PT_WRITE_OK)) return -EROFS;
893
 
894
        if (!(PT.flags & (PT_READING|PT_WRITING))) {
895
            PT.flags |= PT_WRITING;
896
            if (pt_atapi(unit,wr_cmd,0,NULL,"start buffer-available mode"))
897
                        return -EIO;
898
        } else if (PT.flags&PT_READING) return -EIO;
899
 
900
        if (PT.flags & PT_EOF) return -ENOSPC;
901
 
902
        t = 0;
903
 
904
        while (count > 0) {
905
 
906
            if (!pt_poll_dsc(unit,HZ/100,PT_TMO,"write")) return -EIO;
907
 
908
            n = count;
909
            if (n > 32768) n = 32768;   /* max per command */
910
            b = (n-1+PT.bs)/PT.bs;
911
            n = b*PT.bs;                /* rounded up to even block */
912
 
913
            wr_cmd[4] = b;
914
 
915
            r = pt_command(unit,wr_cmd,n,"write");
916
 
917
            mdelay(1);
918
 
919
            if (r) {                    /* error delivering command only */
920
                pt_req_sense(unit,0);
921
                return -EIO;
922
            }
923
 
924
            while (1) {
925
 
926
                r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
927
                                                DBMSG("write DRQ"),NULL);
928
 
929
                if (r & STAT_SENSE) {
930
                    pi_disconnect(PI);
931
                    pt_req_sense(unit,0);
932
                    return -EIO;
933
                }
934
 
935
                if (r) PT.flags |= PT_EOF;
936
 
937
                s = RR(0,7);
938
 
939
                if (!(s & STAT_DRQ)) break;
940
 
941
                n = (RR(0,4)+256*RR(0,5));
942
                p = (RR(0,2)&3);
943
                if (p != 0) {
944
                    pi_disconnect(PI);
945
                    printk("%s: Phase error on write: %d \n",PT.name,p);
946
                    return -EIO;
947
                }
948
 
949
                while (n > 0) {
950
                    k = n;
951
                    if (k > PT_BUFSIZE) k = PT_BUFSIZE;
952
                    b = k;
953
                    if (b > count) b = count;
954
                    if (copy_from_user(PT.bufptr, buf + t, b)) {
955
                        pi_disconnect(PI);
956
                        return -EFAULT;
957
                    }
958
                    pi_write_block(PI,PT.bufptr,k);
959
                    t += b;
960
                    count -= b;
961
                    n -= k;
962
                }
963
 
964
            }
965
            pi_disconnect(PI);
966
            if (PT.flags & PT_EOF) break;
967
        }
968
 
969
        return t;
970
}
971
 
972
/* end of pt.c */
973
 
974
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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