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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1626 jcastillo
/*
2
        pg.c    (c) 1998  Grant R. Guenther <grant@torque.net>
3
                          Under the terms of the GNU public license.
4
 
5
 
6
        Special 2.0.35 version
7
 
8
 
9
        The pg driver provides a simple character device interface for
10
        sending ATAPI commands to a device.  With the exception of the
11
        ATAPI reset operation, all operations are performed by a pair
12
        of read and write operations to the appropriate /dev/pgN device.
13
        A write operation delivers a command and any outbound data in
14
        a single buffer.  Normally, the write will succeed unless the
15
        device is offline or malfunctioning, or there is already another
16
        command pending.  If the write succeeds, it should be followed
17
        immediately by a read operation, to obtain any returned data and
18
        status information.  A read will fail if there is no operation
19
        in progress.
20
 
21
        As a special case, the device can be reset with a write operation,
22
        and in this case, no following read is expected, or permitted.
23
 
24
        There are no ioctl() operations.  Any single operation
25
        may transfer at most PG_MAX_DATA bytes.  Note that the driver must
26
        copy the data through an internal buffer.  In keeping with all
27
        current ATAPI devices, command packets are assumed to be exactly
28
        12 bytes in length.
29
 
30
        To permit future changes to this interface, the headers in the
31
        read and write buffers contain a single character "magic" flag.
32
        Currently this flag must be the character "P".
33
 
34
        By default, the driver will autoprobe for a single parallel
35
        port ATAPI device, but if their individual parameters are
36
        specified, the driver can handle up to 4 devices.
37
 
38
        To use this device, you must have the following device
39
        special files defined:
40
 
41
                /dev/pg0 c 97 0
42
                /dev/pg1 c 97 1
43
                /dev/pg2 c 97 2
44
                /dev/pg3 c 97 3
45
 
46
        (You'll need to change the 97 to something else if you use
47
        the 'major' parameter to install the driver on a different
48
        major number.)
49
 
50
        The behaviour of the pg driver can be altered by setting
51
        some parameters from the insmod command line.  The following
52
        parameters are adjustable:
53
 
54
            drive0      These four arguments can be arrays of
55
            drive1      1-6 integers as follows:
56
            drive2
57
            drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
58
 
59
                        Where,
60
 
61
                <prt>   is the base of the parallel port address for
62
                        the corresponding drive.  (required)
63
 
64
                <pro>   is the protocol number for the adapter that
65
                        supports this drive.  These numbers are
66
                        logged by 'paride' when the protocol modules
67
                        are initialised.  (0 if not given)
68
 
69
                <uni>   for those adapters that support chained
70
                        devices, this is the unit selector for the
71
                        chain of devices on the given port.  It should
72
                        be zero for devices that don't support chaining.
73
                        (0 if not given)
74
 
75
                <mod>   this can be -1 to choose the best mode, or one
76
                        of the mode numbers supported by the adapter.
77
                        (-1 if not given)
78
 
79
                <slv>   ATAPI devices can be jumpered to master or slave.
80
                        Set this to 0 to choose the master drive, 1 to
81
                        choose the slave, -1 (the default) to choose the
82
                        first drive found.
83
 
84
                <dly>   some parallel ports require the driver to
85
                        go more slowly.  -1 sets a default value that
86
                        should work with the chosen protocol.  Otherwise,
87
                        set this to a small integer, the larger it is
88
                        the slower the port i/o.  In some cases, setting
89
                        this to zero will speed up the device. (default -1)
90
 
91
            major       You may use this parameter to overide the
92
                        default major number (97) that this driver
93
                        will use.  Be sure to change the device
94
                        name as well.
95
 
96
            name        This parameter is a character string that
97
                        contains the name the kernel will use for this
98
                        device (in /proc output, for instance).
99
                        (default "pg").
100
 
101
            verbose     This parameter controls the amount of logging
102
                        that is done by the driver.  Set it to 0 for
103
                        quiet operation, to 1 to enable progress
104
                        messages while the driver probes for devices,
105
                        or to 2 for full debug logging.  (default 0)
106
 
107
        If this driver is built into the kernel, you can use
108
        the following command line parameters, with the same values
109
        as the corresponding module parameters listed above:
110
 
111
            pg.drive0
112
            pg.drive1
113
            pg.drive2
114
            pg.drive3
115
 
116
        In addition, you can use the parameter pg.disable to disable
117
        the driver entirely.
118
 
119
*/
120
 
121
/* Changes:
122
 
123
        1.01    GRG 1998.06.16  Bug fixes
124
        1.02    GRG 1998.09.24  Added jumbo support
125
 
126
*/
127
 
128
#define PG_VERSION      "1.02s"
129
#define PG_MAJOR        97
130
#define PG_NAME         "pg"
131
#define PG_UNITS        4
132
 
133
#ifndef PI_PG
134
#define PI_PG   4
135
#endif
136
 
137
/* Here are things one can override from the insmod command.
138
   Most are autoprobed by paride unless set here.  Verbose is 0
139
   by default.
140
 
141
*/
142
 
143
static int      verbose = 0;
144
static int      major = PG_MAJOR;
145
static char     *name = PG_NAME;
146
static int      disable = 0;
147
 
148
static int drive0[6] = {0,0,0,-1,-1,-1};
149
static int drive1[6] = {0,0,0,-1,-1,-1};
150
static int drive2[6] = {0,0,0,-1,-1,-1};
151
static int drive3[6] = {0,0,0,-1,-1,-1};
152
 
153
static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
154
static int pg_drive_count;
155
 
156
#define D_PRT   0
157
#define D_PRO   1
158
#define D_UNI   2
159
#define D_MOD   3
160
#define D_SLV   4
161
#define D_DLY   5
162
 
163
#define DU              (*drives[unit])
164
 
165
/* end of parameters */
166
 
167
 
168
#include <linux/module.h>
169
#include <linux/errno.h>
170
#include <linux/fs.h>
171
#include <linux/kernel.h>
172
#include <linux/delay.h>
173
#include <linux/malloc.h>
174
#include <linux/mtio.h>
175
#include <linux/pg.h>
176
 
177
#include <asm/segment.h>
178
 
179
#ifndef MODULE
180
 
181
#include "setup.h"
182
 
183
static STT pg_stt[5] = {{"drive0",6,drive0},
184
                        {"drive1",6,drive1},
185
                        {"drive2",6,drive2},
186
                        {"drive3",6,drive3},
187
                        {"disable",1,&disable}};
188
 
189
void pg_setup( char *str, int *ints)
190
 
191
{       generic_setup(pg_stt,5,str);
192
}
193
 
194
#endif
195
 
196
#include "paride.h"
197
 
198
#define PG_SPIN_DEL     50              /* spin delay in micro-seconds  */
199
#define PG_SPIN         200
200
#define PG_TMO          HZ
201
#define PG_CMD_TMO      3*HZ
202
#define PG_RESET_TMO    10*HZ
203
 
204
#define STAT_ERR        0x01
205
#define STAT_INDEX      0x02
206
#define STAT_ECC        0x04
207
#define STAT_DRQ        0x08
208
#define STAT_SEEK       0x10
209
#define STAT_WRERR      0x20
210
#define STAT_READY      0x40
211
#define STAT_BUSY       0x80
212
 
213
#define ATAPI_IDENTIFY          0x12
214
 
215
int pg_init(void);
216
#ifdef MODULE
217
void cleanup_module( void );
218
#endif
219
 
220
static int pg_open(struct inode *inode, struct file *file);
221
static void pg_release (struct inode *inode, struct file *file);
222
static int pg_read(struct inode *inode, struct file *filp, char *buf, int count);
223
static int pg_write(struct inode *inode, struct file *filp,
224
                        const char *buf, int count);
225
static int pg_detect(void);
226
 
227
static int pg_identify (int unit, int log);
228
 
229
#define PG_NAMELEN      8
230
 
231
struct pg_unit {
232
        struct pi_adapter pia;    /* interface to paride layer */
233
        struct pi_adapter *pi;
234
        int busy;                 /* write done, read expected */
235
        int start;                /* jiffies at command start */
236
        int dlen;                 /* transfer size requested */
237
        int timeout;              /* timeout requested */
238
        int status;               /* last sense key */
239
        int drive;                /* drive */
240
        int access;               /* count of active opens ... */
241
        int present;              /* device present ? */
242
        char *bufptr;
243
        char name[PG_NAMELEN];    /* pg0, pg1, ... */
244
        };
245
 
246
struct pg_unit pg[PG_UNITS];
247
 
248
/*  'unit' must be defined in all functions - either as a local or a param */
249
 
250
#define PG pg[unit]
251
#define PI PG.pi
252
 
253
static char pg_scratch[512];            /* scratch block buffer */
254
 
255
/* kernel glue structures */
256
 
257
static struct file_operations pg_fops = {
258
        NULL,                   /* lseek - default */
259
        pg_read,                /* read */
260
        pg_write,               /* write */
261
        NULL,                   /* readdir - bad */
262
        NULL,                   /* select */
263
        NULL,                   /* ioctl */
264
        NULL,                   /* mmap */
265
        pg_open,                /* open */
266
        pg_release,             /* release */
267
        NULL,                   /* fsync */
268
        NULL,                   /* fasync */
269
        NULL,                   /* media change ? */
270
        NULL                    /* revalidate new media */
271
};
272
 
273
void pg_init_units( void )
274
 
275
{       int     unit, j;
276
 
277
        pg_drive_count = 0;
278
        for (unit=0;unit<PG_UNITS;unit++) {
279
                PG.pi = & PG.pia;
280
                PG.access = 0;
281
                PG.busy = 0;
282
                PG.present = 0;
283
                PG.bufptr = NULL;
284
                PG.drive = DU[D_SLV];
285
                j = 0;
286
                while ((j < PG_NAMELEN-2) && (PG.name[j]=name[j])) j++;
287
                PG.name[j++] = '0' + unit;
288
                PG.name[j] = 0;
289
                if (DU[D_PRT]) pg_drive_count++;
290
        }
291
}
292
 
293
int pg_init (void)      /* preliminary initialisation */
294
 
295
{       int unit;
296
 
297
        if (disable) return -1;
298
 
299
        pg_init_units();
300
 
301
        if (pg_detect()) return -1;
302
 
303
        if (register_chrdev(major,name,&pg_fops)) {
304
                printk("pg_init: unable to get major number %d\n",
305
                        major);
306
                for (unit=0;unit<PG_UNITS;unit++)
307
                  if (PG.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 = pg_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<PG_UNITS;unit++)
342
          if (PG.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*PG.drive)
351
 
352
static void pg_sleep( int cs )
353
 
354
{       current->state = TASK_INTERRUPTIBLE;
355
        current->timeout = jiffies + cs;
356
        schedule();
357
}
358
 
359
static int pg_wait( int unit, int go, int stop, int tmo, char * msg )
360
 
361
{       int j, r, e, s, p;
362
 
363
        PG.status = 0;
364
 
365
        j = 0;
366
        while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(jiffies<tmo)) {
367
                if (j++ < PG_SPIN) udelay(PG_SPIN_DEL);
368
                else pg_sleep(1);
369
        }
370
 
371
        if ((r&(STAT_ERR&stop))||(jiffies>=tmo)) {
372
           s = RR(0,7);
373
           e = RR(0,1);
374
           p = RR(0,2);
375
           if (verbose > 1)
376
             printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n",
377
                   PG.name,msg,s,e,p,(jiffies>=tmo)?" timeout":"");
378
 
379
 
380
           if (jiffies>=tmo) e |= 0x100;
381
           PG.status = (e >> 4) & 0xff;
382
           return -1;
383
        }
384
        return 0;
385
}
386
 
387
static int pg_command( int unit, char * cmd, int dlen, int tmo )
388
 
389
{       int k;
390
 
391
        pi_connect(PI);
392
 
393
        WR(0,6,DRIVE);
394
 
395
        if (pg_wait(unit,STAT_BUSY|STAT_DRQ,0,tmo,"before command")) {
396
                pi_disconnect(PI);
397
                return -1;
398
        }
399
 
400
        WR(0,4,dlen % 256);
401
        WR(0,5,dlen / 256);
402
        WR(0,7,0xa0);          /* ATAPI packet command */
403
 
404
        if (pg_wait(unit,STAT_BUSY,STAT_DRQ,tmo,"command DRQ")) {
405
                pi_disconnect(PI);
406
                return -1;
407
        }
408
 
409
        if (RR(0,2) != 1) {
410
           printk("%s: command phase error\n",PG.name);
411
           pi_disconnect(PI);
412
           return -1;
413
        }
414
 
415
        pi_write_block(PI,cmd,12);
416
 
417
        if (verbose > 1) {
418
                printk("%s: Command sent, dlen=%d packet= ", PG.name,dlen);
419
                for (k=0;k<12;k++) printk("%02x ",cmd[k]&0xff);
420
                printk("\n");
421
        }
422
        return 0;
423
}
424
 
425
static int pg_completion( int unit, char * buf, int tmo)
426
 
427
{       int r, d, n, p;
428
 
429
        r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
430
                        tmo,"completion");
431
 
432
        PG.dlen = 0;
433
 
434
        while (RR(0,7)&STAT_DRQ) {
435
           d = (RR(0,4)+256*RR(0,5));
436
           n = ((d+3)&0xfffc);
437
           p = RR(0,2)&3;
438
           if (p == 0) pi_write_block(PI,buf,n);
439
           if (p == 2) pi_read_block(PI,buf,n);
440
           if (verbose > 1) printk("%s: %s %d bytes\n",PG.name,
441
                                    p?"Read":"Write",n);
442
           PG.dlen += (1-p)*d;
443
           buf += d;
444
           r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
445
                        tmo,"completion");
446
        }
447
 
448
        pi_disconnect(PI);
449
 
450
        return r;
451
}
452
 
453
static int pg_reset( int unit )
454
 
455
{       int     i, k, flg;
456
        int     expect[5] = {1,1,1,0x14,0xeb};
457
 
458
        pi_connect(PI);
459
        WR(0,6,DRIVE);
460
        WR(0,7,8);
461
 
462
        pg_sleep(2);
463
 
464
        k = 0;
465
        while ((k++ < PG_RESET_TMO) && (RR(1,6)&STAT_BUSY))
466
                pg_sleep(1);
467
 
468
        flg = 1;
469
        for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
470
 
471
        if (verbose) {
472
                printk("%s: Reset (%d) signature = ",PG.name,k);
473
                for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
474
                if (!flg) printk(" (incorrect)");
475
                printk("\n");
476
        }
477
 
478
        pi_disconnect(PI);
479
        return flg-1;
480
}
481
 
482
static void xs( char *buf, char *targ, int offs, int len )
483
 
484
{       int     j,k,l;
485
 
486
        j=0; l=0;
487
        for (k=0;k<len;k++)
488
           if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
489
                l=targ[j++]=buf[k+offs];
490
        if (l==0x20) j--; targ[j]=0;
491
}
492
 
493
static int pg_identify( int unit, int log )
494
 
495
{       int     s;
496
        char    *ms[2] = {"master","slave"};
497
        char    mf[10], id[18];
498
        char    id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
499
        char    buf[36];
500
 
501
        s = pg_command(unit,id_cmd,36,jiffies+PG_TMO);
502
        if (s) return -1;
503
        s = pg_completion(unit,buf,jiffies+PG_TMO);
504
        if (s) return -1;
505
 
506
        if (log) {
507
                xs(buf,mf,8,8);
508
                xs(buf,id,16,16);
509
                printk("%s: %s %s, %s\n",PG.name,mf,id,ms[PG.drive]);
510
        }
511
 
512
        return 0;
513
}
514
 
515
static int pg_probe( int unit )
516
 
517
/*      returns  0, with id set if drive is detected
518
                -1, if drive detection failed
519
*/
520
 
521
{       if (PG.drive == -1) {
522
           for (PG.drive=0;PG.drive<=1;PG.drive++)
523
                if (!pg_reset(unit)) return pg_identify(unit,1);
524
        } else {
525
           if (!pg_reset(unit)) return pg_identify(unit,1);
526
        }
527
        return -1;
528
}
529
 
530
static int pg_detect( void )
531
 
532
{       int     k, unit;
533
 
534
        printk("%s: %s version %s, major %d\n",
535
                name,name,PG_VERSION,major);
536
 
537
        k = 0;
538
        if (pg_drive_count == 0) {
539
            unit = 0;
540
            if (pi_init(PI,1,-1,-1,-1,-1,-1,pg_scratch,
541
                        PI_PG,verbose,PG.name)) {
542
                if (!pg_probe(unit)) {
543
                        PG.present = 1;
544
                        k++;
545
                } else pi_release(PI);
546
            }
547
 
548
        } else for (unit=0;unit<PG_UNITS;unit++) if (DU[D_PRT])
549
            if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
550
                        DU[D_PRO],DU[D_DLY],pg_scratch,PI_PG,verbose,
551
                        PG.name)) {
552
                if (!pg_probe(unit)) {
553
                        PG.present = 1;
554
                        k++;
555
                } else pi_release(PI);
556
            }
557
 
558
        if (k) return 0;
559
 
560
        printk("%s: No ATAPI device detected\n",name);
561
        return -1;
562
}
563
 
564
#define DEVICE_NR(dev)  (MINOR(dev) % 128)
565
 
566
static int pg_open (struct inode *inode, struct file *file)
567
 
568
{       int     unit = DEVICE_NR(inode->i_rdev);
569
 
570
        if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV;
571
 
572
        PG.access++;
573
 
574
        if (PG.access > 1) {
575
                PG.access--;
576
                return -EBUSY;
577
        }
578
 
579
        MOD_INC_USE_COUNT;
580
 
581
        if (PG.busy) {
582
                pg_reset(unit);
583
                PG.busy = 0;
584
        }
585
 
586
        pg_identify(unit,(verbose>1));
587
 
588
 
589
        PG.bufptr = kmalloc(PG_MAX_DATA,GFP_KERNEL);
590
        if (PG.bufptr == NULL) {
591
                PG.access--;
592
                MOD_DEC_USE_COUNT;
593
                printk("%s: buffer allocation failed\n",PG.name);
594
                return -ENOMEM;
595
        }
596
 
597
        return 0;
598
}
599
 
600
static void pg_release (struct inode *inode, struct file *file)
601
{
602
        int     unit = DEVICE_NR(inode->i_rdev);
603
 
604
        if ((unit >= PG_UNITS) || (PG.access <= 0))
605
                return;
606
 
607
        PG.access--;
608
 
609
        kfree(PG.bufptr);
610
        PG.bufptr = NULL;
611
 
612
        MOD_DEC_USE_COUNT;
613
 
614
}
615
 
616
static int pg_write(struct inode *inode, struct file *filp,
617
                const char *buf, int count)
618
 
619
{       int                     unit = DEVICE_NR(inode->i_rdev);
620
        struct pg_write_hdr     hdr;
621
        int                     hs = sizeof(hdr);
622
 
623
        if (PG.busy) return -EBUSY;
624
        if (count < hs) return -EINVAL;
625
 
626
        memcpy_fromfs((char *)&hdr,buf,hs);
627
 
628
        if (hdr.magic != PG_MAGIC) return -EINVAL;
629
        if (hdr.dlen > PG_MAX_DATA) return -EINVAL;
630
        if ((count - hs) > PG_MAX_DATA) return -EINVAL;
631
 
632
        if (hdr.func == PG_RESET) {
633
                if (count != hs) return -EINVAL;
634
                if (pg_reset(unit)) return -EIO;
635
                return count;
636
        }
637
 
638
        if (hdr.func != PG_COMMAND) return -EINVAL;
639
 
640
        PG.start = jiffies;
641
        PG.timeout = hdr.timeout*HZ + HZ/2 + jiffies;
642
 
643
        if (pg_command(unit,hdr.packet,hdr.dlen,jiffies+PG_CMD_TMO)) {
644
                if (PG.status & 0x10) return -ETIME;
645
                return -EIO;
646
        }
647
 
648
        PG.busy = 1;
649
 
650
        memcpy_fromfs(PG.bufptr,buf+hs,count-hs);
651
 
652
        return count;
653
}
654
 
655
static int pg_read(struct inode *inode, struct file *filp, char *buf, int count)
656
 
657
{       int                     unit = DEVICE_NR(inode->i_rdev);
658
        struct pg_read_hdr      hdr;
659
        int                     hs = sizeof(hdr);
660
        int                     copy;
661
 
662
        if (!PG.busy) return -EINVAL;
663
        if (count < hs) return -EINVAL;
664
 
665
        PG.busy = 0;
666
 
667
        if (pg_completion(unit,PG.bufptr,PG.timeout))
668
          if (PG.status & 0x10) return -ETIME;
669
 
670
        hdr.magic = PG_MAGIC;
671
        hdr.dlen = PG.dlen;
672
        copy = 0;
673
 
674
        if (hdr.dlen < 0) {
675
                hdr.dlen = -1 * hdr.dlen;
676
                copy = hdr.dlen;
677
                if (copy > (count - hs)) copy = count - hs;
678
        }
679
 
680
        hdr.duration = (jiffies - PG.start + HZ/2) / HZ;
681
        hdr.scsi = PG.status & 0x0f;
682
 
683
        memcpy_tofs(buf,(char *)&hdr,hs);
684
        if (copy > 0) memcpy_tofs(buf+hs,PG.bufptr,copy);
685
 
686
        return copy+hs;
687
}
688
 
689
/* end of pg.c */
690
 

powered by: WebSVN 2.1.0

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