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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [block/] [paride/] [pf.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
        pf.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
3
                            Under the terms of the GNU public license.
4
 
5
 
6
        Special 2.0.34 version
7
 
8
 
9
        This is the high-level driver for parallel port ATAPI disk
10
        drives based on chips supported by the paride module.
11
 
12
        By default, the driver will autoprobe for a single parallel
13
        port ATAPI disk drive, but if their individual parameters are
14
        specified, the driver can handle up to 4 drives.
15
 
16
        The behaviour of the pf driver can be altered by setting
17
        some parameters from the insmod command line.  The following
18
        parameters are adjustable:
19
 
20
            drive0      These four arguments can be arrays of
21
            drive1      1-7 integers as follows:
22
            drive2
23
            drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<lun>,<dly>
24
 
25
                        Where,
26
 
27
                <prt>   is the base of the parallel port address for
28
                        the corresponding drive.  (required)
29
 
30
                <pro>   is the protocol number for the adapter that
31
                        supports this drive.  These numbers are
32
                        logged by 'paride' when the protocol modules
33
                        are initialised.  (0 if not given)
34
 
35
                <uni>   for those adapters that support chained
36
                        devices, this is the unit selector for the
37
                        chain of devices on the given port.  It should
38
                        be zero for devices that don't support chaining.
39
                        (0 if not given)
40
 
41
                <mod>   this can be -1 to choose the best mode, or one
42
                        of the mode numbers supported by the adapter.
43
                        (-1 if not given)
44
 
45
                <slv>   ATAPI CDroms can be jumpered to master or slave.
46
                        Set this to 0 to choose the master drive, 1 to
47
                        choose the slave, -1 (the default) to choose the
48
                        first drive found.
49
 
50
                <lun>   Some ATAPI devices support multiple LUNs.
51
                        One example is the ATAPI PD/CD drive from
52
                        Matshita/Panasonic.  This device has a
53
                        CD drive on LUN 0 and a PD drive on LUN 1.
54
                        By default, the driver will search for the
55
                        first LUN with a supported device.  Set
56
                        this parameter to force it to use a specific
57
                        LUN.  (default -1)
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 (47) 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 "pf").
75
 
76
            cluster     The driver will attempt to aggregate requests
77
                        for adjacent blocks into larger multi-block
78
                        clusters.  The maximum cluster size (in 512
79
                        byte sectors) is set with this parameter.
80
                        (default 64)
81
 
82
            verbose     This parameter controls the amount of logging
83
                        that is done while the driver probes for
84
                        devices.  Set it to 0 for a quiet load, or 1 to
85
                        see all the progress messages.  (default 0)
86
 
87
            nice        This parameter controls the driver's use of
88
                        idle CPU time, at the expense of some speed.
89
 
90
        If this driver is built into the kernel, you can use the
91
        following command line parameters, with the same values
92
        as the corresponding module parameters listed above:
93
 
94
            pf.drive0
95
            pf.drive1
96
            pf.drive2
97
            pf.drive3
98
            pf.cluster
99
            pf.nice
100
 
101
        In addition, you can use the parameter pf.disable to disable
102
        the driver entirely.
103
 
104
*/
105
 
106
/* Changes:
107
 
108
        1.01    GRG 1998.05.03  Changes for SMP.  Eliminate sti().
109
                                Fix for drives that don't clear STAT_ERR
110
                                until after next CDB delivered.
111
                                Small change in pf_completion to round
112
                                up transfer size.
113
        1.02    GRG 1998.06.16  Eliminated an Ugh
114
        1.03s   GRG 1998.09.24  Added jumbo support
115
                                Use HZ in loop timings, extra debugging
116
 
117
*/
118
 
119
#define PF_VERSION      "1.03s"
120
#define PF_MAJOR        47
121
#define PF_NAME         "pf"
122
#define PF_UNITS        4
123
 
124
/* Here are things one can override from the insmod command.
125
   Most are autoprobed by paride unless set here.  Verbose is off
126
   by default.
127
 
128
*/
129
 
130
static int      verbose = 0;
131
static int      major = PF_MAJOR;
132
static char     *name = PF_NAME;
133
static int      cluster = 64;
134
static int      nice = 0;
135
static int      disable = 0;
136
 
137
static int drive0[7] = {0,0,0,-1,-1,-1,-1};
138
static int drive1[7] = {0,0,0,-1,-1,-1,-1};
139
static int drive2[7] = {0,0,0,-1,-1,-1,-1};
140
static int drive3[7] = {0,0,0,-1,-1,-1,-1};
141
 
142
static int (*drives[4])[7] = {&drive0,&drive1,&drive2,&drive3};
143
static int pf_drive_count;
144
 
145
#define D_PRT   0
146
#define D_PRO   1
147
#define D_UNI   2
148
#define D_MOD   3
149
#define D_SLV   4
150
#define D_LUN   5
151
#define D_DLY   6
152
 
153
#define DU              (*drives[unit])
154
 
155
/* end of parameters */
156
 
157
 
158
#include <linux/module.h>
159
#include <linux/errno.h>
160
#include <linux/fs.h>
161
#include <linux/kernel.h>
162
#include <linux/delay.h>
163
#include <linux/genhd.h>
164
#include <linux/hdreg.h>
165
#include <linux/cdrom.h>
166
#include "spinlock.h"
167
 
168
#include <asm/segment.h>
169
 
170
#ifndef MODULE
171
 
172
#include "setup.h"
173
 
174
static STT pf_stt[7] = {{"drive0",7,drive0},
175
                        {"drive1",7,drive1},
176
                        {"drive2",7,drive2},
177
                        {"drive3",7,drive3},
178
                        {"disable",1,&disable},
179
                        {"cluster",1,&cluster},
180
                        {"nice",1,&nice}};
181
 
182
void pf_setup( char *str, int *ints)
183
 
184
{       generic_setup(pf_stt,7,str);
185
}
186
 
187
#endif
188
 
189
#include "paride.h"
190
 
191
/* set up defines for blk.h,  why don't all drivers do it this way ? */
192
 
193
#define MAJOR_NR   major
194
#define DEVICE_NAME "PF"
195
#define DEVICE_REQUEST do_pf_request
196
#define DEVICE_NR(device) MINOR(device)
197
#define DEVICE_ON(device)
198
#define DEVICE_OFF(device)
199
 
200
#include <linux/blk.h>
201
 
202
#include "pseudo.h"
203
 
204
/* constants for faking geometry numbers */
205
 
206
#define PF_FD_MAX       8192            /* use FD geometry under this size */
207
#define PF_FD_HDS       2
208
#define PF_FD_SPT       18
209
#define PF_HD_HDS       64
210
#define PF_HD_SPT       32
211
 
212
#define PF_MAX_RETRIES  5
213
#define PF_TMO          800             /* interrupt timeout in jiffies */
214
#define PF_SPIN_DEL     50              /* spin delay in micro-seconds  */
215
 
216
#define PF_SPIN         (1000000*PF_TMO)/(HZ*PF_SPIN_DEL)
217
 
218
#define STAT_ERR        0x00001
219
#define STAT_INDEX      0x00002
220
#define STAT_ECC        0x00004
221
#define STAT_DRQ        0x00008
222
#define STAT_SEEK       0x00010
223
#define STAT_WRERR      0x00020
224
#define STAT_READY      0x00040
225
#define STAT_BUSY       0x00080
226
 
227
#define ATAPI_REQ_SENSE         0x03
228
#define ATAPI_LOCK              0x1e
229
#define ATAPI_DOOR              0x1b
230
#define ATAPI_MODE_SENSE        0x5a
231
#define ATAPI_CAPACITY          0x25
232
#define ATAPI_IDENTIFY          0x12
233
#define ATAPI_READ_10           0x28
234
#define ATAPI_WRITE_10          0x2a
235
 
236
int pf_init(void);
237
#ifdef MODULE
238
void cleanup_module( void );
239
#endif
240
static int pf_open(struct inode *inode, struct file *file);
241
static void do_pf_request(void);
242
static int pf_ioctl(struct inode *inode,struct file *file,
243
                    unsigned int cmd, unsigned long arg);
244
 
245
static void pf_release (struct inode *inode, struct file *file);
246
 
247
static int pf_detect(void);
248
static void do_pf_read(void);
249
static void do_pf_read_start(void);
250
static void do_pf_write(void);
251
static void do_pf_write_start(void);
252
static void do_pf_read_drq( void );
253
static void do_pf_write_done( void );
254
 
255
static int pf_identify (int unit);
256
static void pf_lock(int unit, int func);
257
static void pf_eject(int unit);
258
static int pf_check_media(kdev_t dev);
259
 
260
static int pf_blocksizes[PF_UNITS];
261
 
262
#define PF_NM           0
263
#define PF_RO           1
264
#define PF_RW           2
265
 
266
#define PF_NAMELEN      8
267
 
268
struct pf_unit {
269
        struct pi_adapter pia;    /* interface to paride layer */
270
        struct pi_adapter *pi;
271
        int removable;            /* removable media device  ?  */
272
        int media_status;         /* media present ?  WP ? */
273
        int drive;                /* drive */
274
        int lun;
275
        int access;               /* count of active opens ... */
276
        int capacity;             /* Size of this volume in sectors */
277
        int present;              /* device present ? */
278
        char name[PF_NAMELEN];    /* pf0, pf1, ... */
279
        };
280
 
281
struct pf_unit pf[PF_UNITS];
282
 
283
/*  'unit' must be defined in all functions - either as a local or a param */
284
 
285
#define PF pf[unit]
286
#define PI PF.pi
287
 
288
static char pf_scratch[512];            /* scratch block buffer */
289
 
290
/* the variables below are used mainly in the I/O request engine, which
291
   processes only one request at a time.
292
*/
293
 
294
static int pf_retries = 0;              /* i/o error retry count */
295
static int pf_busy = 0;                 /* request being processed ? */
296
static int pf_block;                    /* address of next requested block */
297
static int pf_count;                    /* number of blocks still to do */
298
static int pf_run;                      /* sectors in current cluster */
299
static int pf_cmd;                      /* current command READ/WRITE */
300
static int pf_unit;                     /* unit of current request */
301
static int pf_mask;                     /* stopper for pseudo-int */
302
static char * pf_buf;                   /* buffer for request in progress */
303
 
304
/* kernel glue structures */
305
 
306
static struct file_operations pf_fops = {
307
        NULL,                   /* lseek - default */
308
        block_read,             /* read - general block-dev read */
309
        block_write,            /* write - general block-dev write */
310
        NULL,                   /* readdir - bad */
311
        NULL,                   /* select */
312
        pf_ioctl,               /* ioctl */
313
        NULL,                   /* mmap */
314
        pf_open,                /* open */
315
        pf_release,             /* release */
316
        block_fsync,            /* fsync */
317
        NULL,                   /* fasync */
318
        pf_check_media,         /* media change ? */
319
        NULL                    /* revalidate new media */
320
};
321
 
322
void pf_init_units( void )
323
 
324
{       int     unit, j;
325
 
326
        pf_drive_count = 0;
327
        for (unit=0;unit<PF_UNITS;unit++) {
328
                PF.pi = & PF.pia;
329
                PF.access = 0;
330
                PF.media_status = PF_NM;
331
                PF.capacity = 0;
332
                PF.present = 0;
333
                PF.drive = DU[D_SLV];
334
                PF.lun = DU[D_LUN];
335
                j = 0;
336
                while ((j < PF_NAMELEN-2) && (PF.name[j]=name[j])) j++;
337
                PF.name[j++] = '0' + unit;
338
                PF.name[j] = 0;
339
                if (DU[D_PRT]) pf_drive_count++;
340
        }
341
}
342
 
343
int pf_init (void)      /* preliminary initialisation */
344
 
345
{       int i;
346
 
347
        if (disable) return -1;
348
 
349
        pf_init_units();
350
 
351
        if (pf_detect()) return -1;
352
        pf_busy = 0;
353
 
354
        if (register_blkdev(MAJOR_NR,name,&pf_fops)) {
355
                printk("pf_init: unable to get major number %d\n",
356
                        major);
357
                return -1;
358
        }
359
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
360
        read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB) read ahead */
361
 
362
        for (i=0;i<PF_UNITS;i++) pf_blocksizes[i] = 1024;
363
        blksize_size[MAJOR_NR] = pf_blocksizes;
364
 
365
        return 0;
366
}
367
 
368
static int pf_open (struct inode *inode, struct file *file)
369
 
370
{       int     unit = DEVICE_NR(inode->i_rdev);
371
 
372
        if ((unit >= PF_UNITS) || (!PF.present)) return -ENODEV;
373
 
374
        MOD_INC_USE_COUNT;
375
 
376
        pf_identify(unit);
377
 
378
        if (PF.media_status == PF_NM) {
379
                MOD_DEC_USE_COUNT;
380
                return -ENODEV;
381
                }
382
 
383
        if ((PF.media_status == PF_RO) && (file ->f_mode & 2)) {
384
                MOD_DEC_USE_COUNT;
385
                return -EROFS;
386
                }
387
 
388
        PF.access++;
389
        if (PF.removable) pf_lock(unit,1);
390
 
391
        return 0;
392
}
393
 
394
static int pf_ioctl(struct inode *inode,struct file *file,
395
                    unsigned int cmd, unsigned long arg)
396
 
397
{       int err, unit;
398
        struct hd_geometry *geo = (struct hd_geometry *) arg;
399
 
400
        if ((!inode) || (!inode->i_rdev)) return -EINVAL;
401
        unit = DEVICE_NR(inode->i_rdev);
402
        if (unit >= PF_UNITS) return -EINVAL;
403
        if (!PF.present) return -ENODEV;
404
 
405
        switch (cmd) {
406
            case CDROMEJECT:
407
                if (PF.access == 1) {
408
                        pf_eject(unit);
409
                        return 0;
410
                        }
411
            case HDIO_GETGEO:
412
                if (!geo) return -EINVAL;
413
                err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
414
                if (err) return err;
415
                if (PF.capacity < PF_FD_MAX) {
416
                    put_user(PF.capacity/(PF_FD_HDS*PF_FD_SPT),
417
                                (short *) &geo->cylinders);
418
                    put_user(PF_FD_HDS, (char *) &geo->heads);
419
                    put_user(PF_FD_SPT, (char *) &geo->sectors);
420
                } else {
421
                    put_user(PF.capacity/(PF_HD_HDS*PF_HD_SPT),
422
                                (short *) &geo->cylinders);
423
                    put_user(PF_HD_HDS, (char *) &geo->heads);
424
                    put_user(PF_HD_SPT, (char *) &geo->sectors);
425
                }
426
                put_user(0,(long *)&geo->start);
427
                return 0;
428
            case BLKRASET:
429
                if(!suser()) return -EACCES;
430
                if(!(inode->i_rdev)) return -EINVAL;
431
                if(arg > 0xff) return -EINVAL;
432
                read_ahead[MAJOR(inode->i_rdev)] = arg;
433
                return 0;
434
            case BLKRAGET:
435
                if (!arg) return -EINVAL;
436
                err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long));
437
                if (err) return (err);
438
                put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
439
                return (0);
440
            case BLKGETSIZE:
441
                if (!arg) return -EINVAL;
442
                err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long));
443
                if (err) return (err);
444
                put_user(PF.capacity,(long *) arg);
445
                return (0);
446
            case BLKFLSBUF:
447
                if(!suser())  return -EACCES;
448
                if(!(inode->i_rdev)) return -EINVAL;
449
                fsync_dev(inode->i_rdev);
450
                invalidate_buffers(inode->i_rdev);
451
                return 0;
452
            RO_IOCTLS(inode->i_rdev,arg);
453
            default:
454
                return -EINVAL;
455
        }
456
}
457
 
458
 
459
static void pf_release (struct inode *inode, struct file *file)
460
 
461
{       kdev_t devp;
462
        int     unit;
463
 
464
        devp = inode->i_rdev;
465
        unit = DEVICE_NR(devp);
466
 
467
        if ((unit >= PF_UNITS) || (PF.access <= 0))
468
                return;
469
 
470
        PF.access--;
471
 
472
        if (!PF.access) {
473
                fsync_dev(devp);
474
 
475
                invalidate_inodes(devp);
476
 
477
                invalidate_buffers(devp);
478
                if (PF.removable) pf_lock(unit,0);
479
        }
480
 
481
        MOD_DEC_USE_COUNT;
482
 
483
}
484
 
485
static int pf_check_media( kdev_t dev)
486
 
487
{       return 1;
488
}
489
 
490
#ifdef MODULE
491
 
492
/* Glue for modules ... */
493
 
494
void    cleanup_module(void);
495
 
496
int     init_module(void)
497
 
498
{       int     err;
499
 
500
#ifdef PARIDE_JUMBO
501
       { extern paride_init();
502
         paride_init();
503
       }
504
#endif
505
 
506
        err = pf_init();
507
 
508
        return err;
509
}
510
 
511
void    cleanup_module(void)
512
 
513
{       int unit;
514
 
515
        unregister_blkdev(MAJOR_NR,name);
516
 
517
        for (unit=0;unit<PF_UNITS;unit++)
518
          if (PF.present) pi_release(PI);
519
}
520
 
521
#endif
522
 
523
#define WR(c,r,v)       pi_write_regr(PI,c,r,v)
524
#define RR(c,r)         (pi_read_regr(PI,c,r))
525
 
526
#define LUN             (0x20*PF.lun)
527
#define DRIVE           (0xa0+0x10*PF.drive)
528
 
529
static int pf_wait( int unit, int go, int stop, char * fun, char * msg )
530
 
531
{       int j, r, e, s, p;
532
 
533
        j = 0;
534
        while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PF_SPIN))
535
                udelay(PF_SPIN_DEL);
536
 
537
        if ((r&(STAT_ERR&stop))||(j>=PF_SPIN)) {
538
           s = RR(0,7);
539
           e = RR(0,1);
540
           p = RR(0,2);
541
           if (j >= PF_SPIN) e |= 0x100;
542
           if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
543
                           " loop=%d phase=%d\n",
544
                            PF.name,fun,msg,r,s,e,j,p);
545
           return (e<<8)+s;
546
        }
547
        return 0;
548
}
549
 
550
static int pf_command( int unit, char * cmd, int dlen, char * fun )
551
 
552
{       pi_connect(PI);
553
 
554
        WR(0,6,DRIVE);
555
 
556
        if (pf_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) {
557
                pi_disconnect(PI);
558
                return -1;
559
        }
560
 
561
        WR(0,4,dlen % 256);
562
        WR(0,5,dlen / 256);
563
        WR(0,7,0xa0);          /* ATAPI packet command */
564
 
565
        if (pf_wait(unit,STAT_BUSY,STAT_DRQ,fun,"command DRQ")) {
566
                pi_disconnect(PI);
567
                return -1;
568
        }
569
 
570
        if (RR(0,2) != 1) {
571
           printk("%s: %s: command phase error\n",PF.name,fun);
572
           pi_disconnect(PI);
573
           return -1;
574
        }
575
 
576
        pi_write_block(PI,cmd,12);
577
 
578
        return 0;
579
}
580
 
581
static int pf_completion( int unit, char * buf, char * fun )
582
 
583
{       int r, s, n;
584
 
585
        r = pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
586
                        fun,"completion");
587
 
588
        if ((RR(0,2)&2) && (RR(0,7)&STAT_DRQ)) {
589
                n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
590
                pi_read_block(PI,buf,n);
591
        }
592
 
593
        s = pf_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done");
594
 
595
        pi_disconnect(PI);
596
 
597
        return (r?r:s);
598
}
599
 
600
static void pf_req_sense( int unit, int quiet )
601
 
602
{       char    rs_cmd[12] = { ATAPI_REQ_SENSE,LUN,0,0,16,0,0,0,0,0,0,0 };
603
        char    buf[16];
604
        int     r;
605
 
606
        r = pf_command(unit,rs_cmd,16,"Request sense");
607
        udelay(1000);
608
        if (!r) pf_completion(unit,buf,"Request sense");
609
 
610
        if ((!r)&&(!quiet))
611
                printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
612
                       PF.name,buf[2]&0xf,buf[12],buf[13]);
613
}
614
 
615
static int pf_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
616
 
617
{       int r;
618
 
619
        r = pf_command(unit,cmd,dlen,fun);
620
        udelay(1000);
621
        if (!r) r = pf_completion(unit,buf,fun);
622
        if (r) pf_req_sense(unit,!fun);
623
 
624
        return r;
625
}
626
 
627
#define DBMSG(msg)      ((verbose>1)?(msg):NULL)
628
 
629
static void pf_lock(int unit, int func)
630
 
631
{       char    lo_cmd[12] = { ATAPI_LOCK,LUN,0,0,func,0,0,0,0,0,0,0 };
632
 
633
        pf_atapi(unit,lo_cmd,0,pf_scratch,func?"unlock":"lock");
634
}
635
 
636
 
637
static void pf_eject( int unit )
638
 
639
{       char    ej_cmd[12] = { ATAPI_DOOR,LUN,0,0,2,0,0,0,0,0,0,0 };
640
 
641
        pf_lock(unit,0);
642
        pf_atapi(unit,ej_cmd,0,pf_scratch,"eject");
643
}
644
 
645
#define PF_RESET_TMO   30              /* in tenths of a second */
646
 
647
static void pf_sleep( int cs )
648
 
649
{       current->state = TASK_INTERRUPTIBLE;
650
        current->timeout = jiffies + cs;
651
        schedule();
652
}
653
 
654
 
655
static int pf_reset( int unit )
656
 
657
/* the ATAPI standard actually specifies the contents of all 7 registers
658
   after a reset, but the specification is ambiguous concerning the last
659
   two bytes, and different drives interpret the standard differently.
660
*/
661
 
662
{       int     i, k, flg;
663
        int     expect[5] = {1,1,1,0x14,0xeb};
664
 
665
        pi_connect(PI);
666
        WR(0,6,DRIVE);
667
        WR(0,7,8);
668
 
669
        pf_sleep(2);
670
 
671
        k = 0;
672
        while ((k++ < PF_RESET_TMO) && (RR(1,6)&STAT_BUSY))
673
                pf_sleep(10);
674
 
675
        flg = 1;
676
        for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
677
 
678
        if (verbose) {
679
                printk("%s: Reset (%d) signature = ",PF.name,k);
680
                for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
681
                if (!flg) printk(" (incorrect)");
682
                printk("\n");
683
        }
684
 
685
        pi_disconnect(PI);
686
        return flg-1;
687
}
688
 
689
static void pf_mode_sense( int unit )
690
 
691
{       char    ms_cmd[12] = { ATAPI_MODE_SENSE,LUN,0,0,0,0,0,0,8,0,0,0};
692
        char    buf[8];
693
 
694
        pf_atapi(unit,ms_cmd,8,buf,DBMSG("mode sense"));
695
        PF.media_status = PF_RW;
696
        if (buf[3] & 0x80) PF.media_status = PF_RO;
697
}
698
 
699
static void xs( char *buf, char *targ, int offs, int len )
700
 
701
{       int     j,k,l;
702
 
703
        j=0; l=0;
704
        for (k=0;k<len;k++)
705
           if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
706
                l=targ[j++]=buf[k+offs];
707
        if (l==0x20) j--; targ[j]=0;
708
}
709
 
710
static int xl( char *buf, int offs )
711
 
712
{       int     v,k;
713
 
714
        v=0;
715
        for(k=0;k<4;k++) v=v*256+(buf[k+offs]&0xff);
716
        return v;
717
}
718
 
719
static void pf_get_capacity( int unit )
720
 
721
{       char    rc_cmd[12] = { ATAPI_CAPACITY,LUN,0,0,0,0,0,0,0,0,0,0};
722
        char    buf[8];
723
        int     bs;
724
 
725
        if (pf_atapi(unit,rc_cmd,8,buf,DBMSG("get capacity"))) {
726
                PF.media_status = PF_NM;
727
                return;
728
        }
729
        PF.capacity = xl(buf,0) + 1;
730
        bs = xl(buf,4);
731
        if (bs != 512) {
732
                PF.capacity = 0;
733
                if (verbose) printk("%s: Drive %d, LUN %d,"
734
                                    " unsupported block size %d\n",
735
                                    PF.name,PF.drive,PF.lun,bs);
736
                }
737
}
738
 
739
static int pf_identify( int unit )
740
 
741
{       int     dt, s;
742
        char    *ms[2] = {"master","slave"};
743
        char    mf[10], id[18];
744
        char    id_cmd[12] = { ATAPI_IDENTIFY,LUN,0,0,36,0,0,0,0,0,0,0};
745
        char    buf[36];
746
 
747
        s = pf_atapi(unit,id_cmd,36,buf,"identify");
748
        if (s) return -1;
749
 
750
        dt = buf[0] & 0x1f;
751
        if ((dt != 0) && (dt != 7)) {
752
                if (verbose)
753
                   printk("%s: Drive %d, LUN %d, unsupported type %d\n",
754
                                PF.name,PF.drive,PF.lun,dt);
755
                return -1;
756
        }
757
 
758
        xs(buf,mf,8,8);
759
        xs(buf,id,16,16);
760
 
761
        PF.removable = (buf[1] & 0x80);
762
 
763
        pf_mode_sense(unit);
764
        pf_mode_sense(unit);
765
        pf_mode_sense(unit);
766
 
767
        pf_get_capacity(unit);
768
 
769
        printk("%s: %s %s, %s LUN %d, type %d",
770
                PF.name,mf,id,ms[PF.drive],PF.lun,dt);
771
        if (PF.removable) printk(", removable");
772
        if (PF.media_status == PF_NM)
773
                printk(", no media\n");
774
        else {  if (PF.media_status == PF_RO) printk(", RO");
775
                printk(", %d blocks\n",PF.capacity);
776
        }
777
 
778
        return 0;
779
}
780
 
781
static int pf_probe( int unit )
782
 
783
/*      returns  0, with id set if drive is detected
784
                -1, if drive detection failed
785
*/
786
 
787
{       if (PF.drive == -1) {
788
           for (PF.drive=0;PF.drive<=1;PF.drive++)
789
                if (!pf_reset(unit)) {
790
                   if (PF.lun != -1) return pf_identify(unit);
791
                   else for (PF.lun=0;PF.lun<8;PF.lun++)
792
                           if (!pf_identify(unit)) return 0;
793
                }
794
        } else {
795
           if (pf_reset(unit)) return -1;
796
           if (PF.lun != -1) return pf_identify(unit);
797
           for (PF.lun=0;PF.lun<8;PF.lun++)
798
              if (!pf_identify(unit)) return 0;
799
        }
800
        return -1;
801
}
802
 
803
static int pf_detect( void )
804
 
805
{       int     k, unit;
806
 
807
        printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
808
                name,name,PF_VERSION,major,cluster,nice);
809
 
810
        k = 0;
811
        if (pf_drive_count == 0) {
812
            unit = 0;
813
            if (pi_init(PI,1,-1,-1,-1,-1,-1,pf_scratch,
814
                        PI_PF,verbose,PF.name)) {
815
                if (!pf_probe(unit)) {
816
                        PF.present = 1;
817
                        k++;
818
                } else pi_release(PI);
819
            }
820
 
821
        } else for (unit=0;unit<PF_UNITS;unit++) if (DU[D_PRT])
822
            if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
823
                        DU[D_PRO],DU[D_DLY],pf_scratch,PI_PF,verbose,
824
                        PF.name)) {
825
                if (!pf_probe(unit)) {
826
                        PF.present = 1;
827
                        k++;
828
                } else pi_release(PI);
829
            }
830
 
831
        if (k) return 0;
832
 
833
        printk("%s: No ATAPI disk detected\n",name);
834
        return -1;
835
}
836
 
837
/* The i/o request engine */
838
 
839
static int pf_start( int unit, int cmd, int b, int c )
840
 
841
{       int     i;
842
        char    io_cmd[12] = {cmd,LUN,0,0,0,0,0,0,0,0,0,0};
843
 
844
        for(i=0;i<4;i++) {
845
           io_cmd[5-i] = b & 0xff;
846
           b = b >> 8;
847
        }
848
 
849
        io_cmd[8] = c & 0xff;
850
        io_cmd[7] = (c >> 8) & 0xff;
851
 
852
        i = pf_command(unit,io_cmd,c*512,"start i/o");
853
 
854
        udelay(1000);
855
 
856
        return i;
857
}
858
 
859
static int pf_ready( void )
860
 
861
{       int     unit = pf_unit;
862
 
863
        return (((RR(1,6)&(STAT_BUSY|pf_mask)) == pf_mask));
864
}
865
 
866
static void do_pf_request (void)
867
 
868
{       struct buffer_head * bh;
869
        struct request * req;
870
        int unit;
871
 
872
        if (pf_busy) return;
873
repeat:
874
        if ((!CURRENT) || (CURRENT->rq_status == RQ_INACTIVE)) return;
875
        INIT_REQUEST;
876
 
877
        pf_unit = unit = DEVICE_NR(CURRENT->rq_dev);
878
        pf_block = CURRENT->sector;
879
        pf_count = CURRENT->nr_sectors;
880
 
881
        bh = CURRENT->bh;
882
        req = CURRENT;
883
        if (bh->b_reqnext)
884
                printk("%s: OUCH: b_reqnext != NULL\n",PF.name);
885
 
886
        if ((pf_unit >= PF_UNITS) || (pf_block+pf_count > PF.capacity)) {
887
                end_request(0);
888
                goto repeat;
889
        }
890
 
891
        pf_cmd = CURRENT->cmd;
892
        pf_run = pf_count;
893
        while ((pf_run <= cluster) &&
894
               (req = req->next) &&
895
               (pf_block+pf_run == req->sector) &&
896
               (pf_cmd == req->cmd) &&
897
               (pf_unit == DEVICE_NR(req->rq_dev)))
898
                        pf_run += req->nr_sectors;
899
 
900
        pf_buf = CURRENT->buffer;
901
        pf_retries = 0;
902
 
903
        pf_busy = 1;
904
        if (pf_cmd == READ) pi_do_claimed(PI,do_pf_read);
905
        else if (pf_cmd == WRITE) pi_do_claimed(PI,do_pf_write);
906
        else {  pf_busy = 0;
907
                end_request(0);
908
                goto repeat;
909
        }
910
}
911
 
912
static void pf_next_buf( int unit )
913
 
914
{       long    saved_flags;
915
 
916
        spin_lock_irqsave(&io_request_lock,saved_flags);
917
        end_request(1);
918
        if (!pf_run) { spin_unlock_irqrestore(&io_request_lock,saved_flags);
919
                       return;
920
        }
921
 
922
/* paranoia */
923
 
924
        if ((!CURRENT) ||
925
            (CURRENT->cmd != pf_cmd) ||
926
            (DEVICE_NR(CURRENT->rq_dev) != pf_unit) ||
927
            (CURRENT->rq_status == RQ_INACTIVE) ||
928
            (CURRENT->sector != pf_block))
929
                printk("%s: OUCH: request list changed unexpectedly\n",
930
                        PF.name);
931
 
932
        pf_count = CURRENT->nr_sectors;
933
        pf_buf = CURRENT->buffer;
934
        spin_unlock_irqrestore(&io_request_lock,saved_flags);
935
}
936
 
937
static void do_pf_read( void )
938
 
939
/* detach from the calling context - in case the spinlock is held */
940
 
941
{       ps_set_intr(do_pf_read_start,0,0,nice);
942
}
943
 
944
static void do_pf_read_start( void )
945
 
946
{       int     unit = pf_unit;
947
        long    saved_flags;
948
 
949
        pf_busy = 1;
950
 
951
        if (pf_start(unit,ATAPI_READ_10,pf_block,pf_run)) {
952
                pi_disconnect(PI);
953
                if (pf_retries < PF_MAX_RETRIES) {
954
                        pf_retries++;
955
                        pi_do_claimed(PI,do_pf_read_start);
956
                        return;
957
                }
958
                spin_lock_irqsave(&io_request_lock,saved_flags);
959
                end_request(0);
960
                pf_busy = 0;
961
                do_pf_request();
962
                spin_unlock_irqrestore(&io_request_lock,saved_flags);
963
                return;
964
        }
965
        pf_mask = STAT_DRQ;
966
        ps_set_intr(do_pf_read_drq,pf_ready,PF_TMO,nice);
967
}
968
 
969
static void do_pf_read_drq( void )
970
 
971
{       int     unit = pf_unit;
972
        long    saved_flags;
973
 
974
        while (1) {
975
            if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,
976
                        "read block","completion") & STAT_ERR) {
977
                pi_disconnect(PI);
978
                if (pf_retries < PF_MAX_RETRIES) {
979
                        pf_req_sense(unit,0);
980
                        pf_retries++;
981
                        pi_do_claimed(PI,do_pf_read_start);
982
                        return;
983
                }
984
                spin_lock_irqsave(&io_request_lock,saved_flags);
985
                end_request(0);
986
                pf_busy = 0;
987
                do_pf_request();
988
                spin_unlock_irqrestore(&io_request_lock,saved_flags);
989
                return;
990
            }
991
            pi_read_block(PI,pf_buf,512);
992
            pf_count--; pf_run--;
993
            pf_buf += 512;
994
            pf_block++;
995
            if (!pf_run) break;
996
            if (!pf_count) pf_next_buf(unit);
997
        }
998
        pi_disconnect(PI);
999
        spin_lock_irqsave(&io_request_lock,saved_flags);
1000
        end_request(1);
1001
        pf_busy = 0;
1002
        do_pf_request();
1003
        spin_unlock_irqrestore(&io_request_lock,saved_flags);
1004
}
1005
 
1006
static void do_pf_write( void )
1007
 
1008
{       ps_set_intr(do_pf_write_start,0,0,nice);
1009
}
1010
 
1011
static void do_pf_write_start( void )
1012
 
1013
{       int     unit = pf_unit;
1014
        long    saved_flags;
1015
 
1016
        pf_busy = 1;
1017
 
1018
        if (pf_start(unit,ATAPI_WRITE_10,pf_block,pf_run)) {
1019
                pi_disconnect(PI);
1020
                if (pf_retries < PF_MAX_RETRIES) {
1021
                        pf_retries++;
1022
                        pi_do_claimed(PI,do_pf_write_start);
1023
                        return;
1024
                }
1025
                spin_lock_irqsave(&io_request_lock,saved_flags);
1026
                end_request(0);
1027
                pf_busy = 0;
1028
                do_pf_request();
1029
                spin_unlock_irqrestore(&io_request_lock,saved_flags);
1030
                return;
1031
        }
1032
 
1033
        while (1) {
1034
            if (pf_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,
1035
                        "write block","data wait") & STAT_ERR) {
1036
                pi_disconnect(PI);
1037
                if (pf_retries < PF_MAX_RETRIES) {
1038
                        pf_retries++;
1039
                        pi_do_claimed(PI,do_pf_write_start);
1040
                        return;
1041
                }
1042
                spin_lock_irqsave(&io_request_lock,saved_flags);
1043
                end_request(0);
1044
                pf_busy = 0;
1045
                do_pf_request();
1046
                spin_unlock_irqrestore(&io_request_lock,saved_flags);
1047
                return;
1048
            }
1049
            pi_write_block(PI,pf_buf,512);
1050
            pf_count--; pf_run--;
1051
            pf_buf += 512;
1052
            pf_block++;
1053
            if (!pf_run) break;
1054
            if (!pf_count) pf_next_buf(unit);
1055
        }
1056
        pf_mask = 0;
1057
        ps_set_intr(do_pf_write_done,pf_ready,PF_TMO,nice);
1058
}
1059
 
1060
static void do_pf_write_done( void )
1061
 
1062
{       int     unit = pf_unit;
1063
        long    saved_flags;
1064
 
1065
        if (pf_wait(unit,STAT_BUSY,0,"write block","done") & STAT_ERR) {
1066
                pi_disconnect(PI);
1067
                if (pf_retries < PF_MAX_RETRIES) {
1068
                        pf_retries++;
1069
                        pi_do_claimed(PI,do_pf_write_start);
1070
                        return;
1071
                }
1072
                spin_lock_irqsave(&io_request_lock,saved_flags);
1073
                end_request(0);
1074
                pf_busy = 0;
1075
                do_pf_request();
1076
                spin_unlock_irqrestore(&io_request_lock,saved_flags);
1077
                return;
1078
        }
1079
        pi_disconnect(PI);
1080
        spin_lock_irqsave(&io_request_lock,saved_flags);
1081
        end_request(1);
1082
        pf_busy = 0;
1083
        do_pf_request();
1084
        spin_unlock_irqrestore(&io_request_lock,saved_flags);
1085
}
1086
 
1087
/* end of pf.c */
1088
 

powered by: WebSVN 2.1.0

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