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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [block/] [paride/] [pt.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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