1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117#define PD_VERSION "1.05"
118#define PD_MAJOR 45
119#define PD_NAME "pd"
120#define PD_UNITS 4
121
122
123
124
125
126
127
128static int verbose = 0;
129static int major = PD_MAJOR;
130static char *name = PD_NAME;
131static int cluster = 64;
132static int nice = 0;
133static int disable = 0;
134
135static int drive0[8] = {0,0,0,-1,0,1,-1,-1};
136static int drive1[8] = {0,0,0,-1,0,1,-1,-1};
137static int drive2[8] = {0,0,0,-1,0,1,-1,-1};
138static int drive3[8] = {0,0,0,-1,0,1,-1,-1};
139
140static int (*drives[4])[8] = {&drive0,&drive1,&drive2,&drive3};
141static int pd_drive_count;
142
143#define D_PRT 0
144#define D_PRO 1
145#define D_UNI 2
146#define D_MOD 3
147#define D_GEO 4
148#define D_SBY 5
149#define D_DLY 6
150#define D_SLV 7
151
152#define DU (*drives[unit])
153
154
155
156#include <linux/module.h>
157#include <linux/errno.h>
158#include <linux/fs.h>
159#include <linux/devfs_fs_kernel.h>
160#include <linux/kernel.h>
161#include <linux/delay.h>
162#include <linux/genhd.h>
163#include <linux/hdreg.h>
164#include <linux/cdrom.h>
165#include <linux/spinlock.h>
166
167#include <asm/uaccess.h>
168
169#ifndef MODULE
170
171#include "setup.h"
172
173static STT pd_stt[7] = {{"drive0",8,drive0},
174 {"drive1",8,drive1},
175 {"drive2",8,drive2},
176 {"drive3",8,drive3},
177 {"disable",1,&disable},
178 {"cluster",1,&cluster},
179 {"nice",1,&nice}};
180
181void pd_setup( char *str, int *ints)
182
183{
184 generic_setup(pd_stt,7,str);
185}
186
187#endif
188
189MODULE_PARM(verbose,"i");
190MODULE_PARM(major,"i");
191MODULE_PARM(name,"s");
192MODULE_PARM(cluster,"i");
193MODULE_PARM(nice,"i");
194MODULE_PARM(drive0,"1-8i");
195MODULE_PARM(drive1,"1-8i");
196MODULE_PARM(drive2,"1-8i");
197MODULE_PARM(drive3,"1-8i");
198
199#include "paride.h"
200
201#define PD_BITS 4
202
203
204
205#define MAJOR_NR major
206#define DEVICE_NAME "PD"
207#define DEVICE_REQUEST do_pd_request
208#define DEVICE_NR(device) (MINOR(device)>>PD_BITS)
209#define DEVICE_ON(device)
210#define DEVICE_OFF(device)
211
212#include <linux/blk.h>
213#include <linux/blkpg.h>
214
215#include "pseudo.h"
216
217#define PD_PARTNS (1<<PD_BITS)
218#define PD_DEVS PD_PARTNS*PD_UNITS
219
220
221
222#define PD_LOG_HEADS 64
223#define PD_LOG_SECTS 32
224
225#define PD_ID_OFF 54
226#define PD_ID_LEN 14
227
228#define PD_MAX_RETRIES 5
229#define PD_TMO 800
230#define PD_SPIN_DEL 50
231
232#define PD_SPIN (1000000*PD_TMO)/(HZ*PD_SPIN_DEL)
233
234#define STAT_ERR 0x00001
235#define STAT_INDEX 0x00002
236#define STAT_ECC 0x00004
237#define STAT_DRQ 0x00008
238#define STAT_SEEK 0x00010
239#define STAT_WRERR 0x00020
240#define STAT_READY 0x00040
241#define STAT_BUSY 0x00080
242
243#define ERR_AMNF 0x00100
244#define ERR_TK0NF 0x00200
245#define ERR_ABRT 0x00400
246#define ERR_MCR 0x00800
247#define ERR_IDNF 0x01000
248#define ERR_MC 0x02000
249#define ERR_UNC 0x04000
250#define ERR_TMO 0x10000
251
252#define IDE_READ 0x20
253#define IDE_WRITE 0x30
254#define IDE_READ_VRFY 0x40
255#define IDE_INIT_DEV_PARMS 0x91
256#define IDE_STANDBY 0x96
257#define IDE_ACKCHANGE 0xdb
258#define IDE_DOORLOCK 0xde
259#define IDE_DOORUNLOCK 0xdf
260#define IDE_IDENTIFY 0xec
261#define IDE_EJECT 0xed
262
263int pd_init(void);
264void pd_setup(char * str, int * ints);
265#ifdef MODULE
266void cleanup_module( void );
267#endif
268static int pd_open(struct inode *inode, struct file *file);
269static void do_pd_request(request_queue_t * q);
270static int pd_ioctl(struct inode *inode,struct file *file,
271 unsigned int cmd, unsigned long arg);
272static int pd_release (struct inode *inode, struct file *file);
273static int pd_revalidate(kdev_t dev);
274static int pd_detect(void);
275static void do_pd_read(void);
276static void do_pd_read_start(void);
277static void do_pd_write(void);
278static void do_pd_write_start(void);
279static void do_pd_read_drq( void );
280static void do_pd_write_done( void );
281
282static int pd_identify (int unit);
283static void pd_media_check(int unit);
284static void pd_doorlock(int unit, int func);
285static int pd_check_media(kdev_t dev);
286static void pd_eject( int unit);
287
288static struct hd_struct pd_hd[PD_DEVS];
289static int pd_sizes[PD_DEVS];
290static int pd_blocksizes[PD_DEVS];
291static int pd_maxsectors[PD_DEVS];
292
293#define PD_NAMELEN 8
294
295struct pd_unit {
296 struct pi_adapter pia;
297 struct pi_adapter *pi;
298 int access;
299 int capacity;
300 int heads;
301 int sectors;
302 int cylinders;
303 int can_lba;
304 int drive;
305 int changed;
306 int removable;
307 int standby;
308 int alt_geom;
309 int present;
310 char name[PD_NAMELEN];
311};
312
313struct pd_unit pd[PD_UNITS];
314
315
316
317#define PD pd[unit]
318#define PI PD.pi
319
320static int pd_valid = 1;
321static char pd_scratch[512];
322
323
324
325
326
327static int pd_retries = 0;
328static int pd_busy = 0;
329static int pd_block;
330static int pd_count;
331static int pd_run;
332static int pd_cmd;
333static int pd_unit;
334static int pd_dev;
335static int pd_poffs;
336static char * pd_buf;
337
338static DECLARE_WAIT_QUEUE_HEAD(pd_wait_open);
339
340static char *pd_errs[17] = { "ERR","INDEX","ECC","DRQ","SEEK","WRERR",
341 "READY","BUSY","AMNF","TK0NF","ABRT","MCR",
342 "IDNF","MC","UNC","???","TMO"};
343
344
345
346extern struct block_device_operations pd_fops;
347
348static struct gendisk pd_gendisk = {
349 major: PD_MAJOR,
350 major_name: PD_NAME,
351 minor_shift: PD_BITS,
352 max_p: PD_PARTNS,
353 part: pd_hd,
354 sizes: pd_sizes,
355 fops: &pd_fops,
356};
357
358static struct block_device_operations pd_fops = {
359 owner: THIS_MODULE,
360 open: pd_open,
361 release: pd_release,
362 ioctl: pd_ioctl,
363 check_media_change: pd_check_media,
364 revalidate: pd_revalidate
365};
366
367void pd_init_units( void )
368
369{ int unit, j;
370
371 pd_drive_count = 0;
372 for (unit=0;unit<PD_UNITS;unit++) {
373 PD.pi = & PD.pia;
374 PD.access = 0;
375 PD.changed = 1;
376 PD.capacity = 0;
377 PD.drive = DU[D_SLV];
378 PD.present = 0;
379 j = 0;
380 while ((j < PD_NAMELEN-2) && (PD.name[j]=name[j])) j++;
381 PD.name[j++] = 'a' + unit;
382 PD.name[j] = 0;
383 PD.alt_geom = DU[D_GEO];
384 PD.standby = DU[D_SBY];
385 if (DU[D_PRT]) pd_drive_count++;
386 }
387}
388
389int pd_init (void)
390
391{ int i;
392 request_queue_t * q;
393
394 if (disable) return -1;
395 if (devfs_register_blkdev(MAJOR_NR,name,&pd_fops)) {
396 printk("%s: unable to get major number %d\n",
397 name,major);
398 return -1;
399 }
400 q = BLK_DEFAULT_QUEUE(MAJOR_NR);
401 blk_init_queue(q, DEVICE_REQUEST);
402 read_ahead[MAJOR_NR] = 8;
403
404 pd_gendisk.major = major;
405 pd_gendisk.major_name = name;
406 add_gendisk(&pd_gendisk);
407
408 for(i=0;i<PD_DEVS;i++) pd_blocksizes[i] = 1024;
409 blksize_size[MAJOR_NR] = pd_blocksizes;
410
411 for(i=0;i<PD_DEVS;i++) pd_maxsectors[i] = cluster;
412 max_sectors[MAJOR_NR] = pd_maxsectors;
413
414 printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
415 name,name,PD_VERSION,major,cluster,nice);
416 pd_init_units();
417 pd_valid = 0;
418 pd_gendisk.nr_real = pd_detect();
419 pd_valid = 1;
420
421#ifdef MODULE
422 if (!pd_gendisk.nr_real) {
423 cleanup_module();
424 return -1;
425 }
426#endif
427 return 0;
428}
429
430static int pd_open (struct inode *inode, struct file *file)
431
432{ int unit = DEVICE_NR(inode->i_rdev);
433
434 if ((unit >= PD_UNITS) || (!PD.present)) return -ENODEV;
435
436 wait_event (pd_wait_open, pd_valid);
437
438 PD.access++;
439
440 if (PD.removable) {
441 pd_media_check(unit);
442 pd_doorlock(unit,IDE_DOORLOCK);
443 }
444 return 0;
445}
446
447static int pd_ioctl(struct inode *inode,struct file *file,
448 unsigned int cmd, unsigned long arg)
449
450{ struct hd_geometry *geo = (struct hd_geometry *) arg;
451 int dev, err, unit;
452
453 if ((!inode) || (!inode->i_rdev)) return -EINVAL;
454 dev = MINOR(inode->i_rdev);
455 unit = DEVICE_NR(inode->i_rdev);
456 if (dev >= PD_DEVS) return -EINVAL;
457 if (!PD.present) return -ENODEV;
458
459 switch (cmd) {
460 case CDROMEJECT:
461 if (PD.access == 1) pd_eject(unit);
462 return 0;
463 case HDIO_GETGEO:
464 if (!geo) return -EINVAL;
465 err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
466 if (err) return err;
467
468 if (PD.alt_geom) {
469 put_user(PD.capacity/(PD_LOG_HEADS*PD_LOG_SECTS),
470 (short *) &geo->cylinders);
471 put_user(PD_LOG_HEADS, (char *) &geo->heads);
472 put_user(PD_LOG_SECTS, (char *) &geo->sectors);
473 } else {
474 put_user(PD.cylinders, (short *) &geo->cylinders);
475 put_user(PD.heads, (char *) &geo->heads);
476 put_user(PD.sectors, (char *) &geo->sectors);
477 }
478 put_user(pd_hd[dev].start_sect,(long *)&geo->start);
479 return 0;
480 case BLKRRPART:
481 if (!capable(CAP_SYS_ADMIN))
482 return -EACCES;
483 return pd_revalidate(inode->i_rdev);
484 case BLKGETSIZE:
485 case BLKGETSIZE64:
486 case BLKROSET:
487 case BLKROGET:
488 case BLKRASET:
489 case BLKRAGET:
490 case BLKFLSBUF:
491 case BLKPG:
492 return blk_ioctl(inode->i_rdev, cmd, arg);
493 default:
494 return -EINVAL;
495 }
496}
497
498static int pd_release (struct inode *inode, struct file *file)
499
500{ kdev_t devp;
501 int unit;
502
503 devp = inode->i_rdev;
504 unit = DEVICE_NR(devp);
505
506 if ((unit >= PD_UNITS) || (PD.access <= 0))
507 return -EINVAL;
508
509 PD.access--;
510
511 if (!PD.access && PD.removable)
512 pd_doorlock(unit,IDE_DOORUNLOCK);
513
514 return 0;
515}
516
517static int pd_check_media( kdev_t dev)
518
519{ int r, unit;
520
521 unit = DEVICE_NR(dev);
522 if ((unit >= PD_UNITS) || (!PD.present)) return -ENODEV;
523 if (!PD.removable) return 0;
524 pd_media_check(unit);
525 r = PD.changed;
526 PD.changed = 0;
527 return r;
528}
529
530static int pd_revalidate(kdev_t dev)
531
532{ int p, unit, minor;
533 long flags;
534
535 unit = DEVICE_NR(dev);
536 if ((unit >= PD_UNITS) || (!PD.present)) return -ENODEV;
537
538 save_flags(flags);
539 cli();
540 if (PD.access > 1) {
541 restore_flags(flags);
542 return -EBUSY;
543 }
544 pd_valid = 0;
545 restore_flags(flags);
546
547 for (p=(PD_PARTNS-1);p>=0;p--) {
548 minor = p + unit*PD_PARTNS;
549 invalidate_device(MKDEV(MAJOR_NR, minor), 1);
550 pd_hd[minor].start_sect = 0;
551 pd_hd[minor].nr_sects = 0;
552 }
553
554 if (pd_identify(unit))
555 grok_partitions(&pd_gendisk,unit,1<<PD_BITS,PD.capacity);
556
557 pd_valid = 1;
558 wake_up(&pd_wait_open);
559
560 return 0;
561}
562
563#ifdef MODULE
564
565
566
567void cleanup_module(void);
568
569int init_module(void)
570
571{
572
573#ifdef PARIDE_JUMBO
574 { extern paride_init();
575 paride_init();
576 }
577#endif
578 return pd_init();
579}
580
581void cleanup_module(void)
582{
583 int unit;
584
585 devfs_unregister_blkdev(MAJOR_NR,name);
586 del_gendisk(&pd_gendisk);
587
588 for (unit=0;unit<PD_UNITS;unit++)
589 if (PD.present) pi_release(PI);
590
591 max_sectors[MAJOR_NR] = NULL;
592}
593
594#endif
595
596#define WR(c,r,v) pi_write_regr(PI,c,r,v)
597#define RR(c,r) (pi_read_regr(PI,c,r))
598
599#define DRIVE (0xa0+0x10*PD.drive)
600
601
602
603static void pd_print_error( int unit, char * msg, int status )
604
605{ int i;
606
607 printk("%s: %s: status = 0x%x =",PD.name,msg,status);
608 for(i=0;i<18;i++) if (status & (1<<i)) printk(" %s",pd_errs[i]);
609 printk("\n");
610}
611
612static void pd_reset( int unit )
613
614{ pi_connect(PI);
615 WR(1,6,4);
616 udelay(50);
617 WR(1,6,0);
618 pi_disconnect(PI);
619 udelay(250);
620}
621
622#define DBMSG(msg) ((verbose>1)?(msg):NULL)
623
624static int pd_wait_for( int unit, int w, char * msg )
625
626{ int k, r, e;
627
628 k=0;
629 while(k < PD_SPIN) {
630 r = RR(1,6);
631 k++;
632 if (((r & w) == w) && !(r & STAT_BUSY)) break;
633 udelay(PD_SPIN_DEL);
634 }
635 e = (RR(0,1)<<8) + RR(0,7);
636 if (k >= PD_SPIN) e |= ERR_TMO;
637 if ((e & (STAT_ERR|ERR_TMO)) && (msg != NULL))
638 pd_print_error(unit,msg,e);
639 return e;
640}
641
642static void pd_send_command( int unit, int n, int s, int h,
643 int c0, int c1, int func )
644
645{
646 WR(0,6,DRIVE+h);
647 WR(0,1,0);
648 WR(0,2,n);
649 WR(0,3,s);
650 WR(0,4,c0);
651 WR(0,5,c1);
652 WR(0,7,func);
653
654 udelay(1);
655}
656
657static void pd_ide_command( int unit, int func, int block, int count )
658
659
660
661{
662 int c1, c0, h, s;
663 if (PD.can_lba) {
664 s = block & 255;
665 c0 = (block >>= 8) & 255;
666 c1 = (block >>= 8) & 255;
667 h = ((block >>= 8) & 15) + 0x40;
668 } else {
669 s = ( block % PD.sectors) + 1;
670 h = ( block /= PD.sectors) % PD.heads;
671 c0 = ( block /= PD.heads) % 256;
672 c1 = (block >>= 8);
673 }
674 pd_send_command(unit,count,s,h,c0,c1,func);
675}
676
677
678
679
680
681
682
683static void pd_init_dev_parms( int unit )
684
685{ pi_connect(PI);
686 pd_wait_for(unit,0,DBMSG("before init_dev_parms"));
687 pd_send_command(unit,PD.sectors,0,PD.heads-1,0,0,IDE_INIT_DEV_PARMS);
688 udelay(300);
689 pd_wait_for(unit,0,"Initialise device parameters");
690 pi_disconnect(PI);
691}
692
693static void pd_doorlock( int unit, int func )
694
695{ pi_connect(PI);
696 if (pd_wait_for(unit,STAT_READY,"Lock") & STAT_ERR) {
697 pi_disconnect(PI);
698 return;
699 }
700 pd_send_command(unit,1,0,0,0,0,func);
701 pd_wait_for(unit,STAT_READY,"Lock done");
702 pi_disconnect(PI);
703}
704
705static void pd_eject( int unit )
706
707{ pi_connect(PI);
708 pd_wait_for(unit,0,DBMSG("before unlock on eject"));
709 pd_send_command(unit,1,0,0,0,0,IDE_DOORUNLOCK);
710 pd_wait_for(unit,0,DBMSG("after unlock on eject"));
711 pd_wait_for(unit,0,DBMSG("before eject"));
712 pd_send_command(unit,0,0,0,0,0,IDE_EJECT);
713 pd_wait_for(unit,0,DBMSG("after eject"));
714 pi_disconnect(PI);
715}
716
717static void pd_media_check( int unit )
718
719{ int r;
720
721 pi_connect(PI);
722 r = pd_wait_for(unit,STAT_READY,DBMSG("before media_check"));
723 if (!(r & STAT_ERR)) {
724 pd_send_command(unit,1,1,0,0,0,IDE_READ_VRFY);
725 r = pd_wait_for(unit,STAT_READY,DBMSG("RDY after READ_VRFY"));
726 } else PD.changed = 1;
727 if (r & ERR_MC) {
728 PD.changed = 1;
729 pd_send_command(unit,1,0,0,0,0,IDE_ACKCHANGE);
730 pd_wait_for(unit,STAT_READY,DBMSG("RDY after ACKCHANGE"));
731 pd_send_command(unit,1,1,0,0,0,IDE_READ_VRFY);
732 r = pd_wait_for(unit,STAT_READY,DBMSG("RDY after VRFY"));
733 }
734 pi_disconnect(PI);
735
736}
737
738static void pd_standby_off( int unit )
739
740{ pi_connect(PI);
741 pd_wait_for(unit,0,DBMSG("before STANDBY"));
742 pd_send_command(unit,0,0,0,0,0,IDE_STANDBY);
743 pd_wait_for(unit,0,DBMSG("after STANDBY"));
744 pi_disconnect(PI);
745}
746
747#define word_val(n) ((pd_scratch[2*n]&0xff)+256*(pd_scratch[2*n+1]&0xff))
748
749static int pd_identify( int unit )
750
751{ int j;
752 char id[PD_ID_LEN+1];
753
754
755
756
757
758
759
760 if (PD.drive == 0) pd_reset(unit);
761
762 pi_connect(PI);
763 WR(0,6,DRIVE);
764 pd_wait_for(unit,0,DBMSG("before IDENT"));
765 pd_send_command(unit,1,0,0,0,0,IDE_IDENTIFY);
766
767 if (pd_wait_for(unit,STAT_DRQ,DBMSG("IDENT DRQ")) & STAT_ERR) {
768 pi_disconnect(PI);
769 return 0;
770 }
771 pi_read_block(PI,pd_scratch,512);
772 pi_disconnect(PI);
773 PD.can_lba = pd_scratch[99] & 2;
774 PD.sectors = le16_to_cpu(*(u16*)(pd_scratch+12));
775 PD.heads = le16_to_cpu(*(u16*)(pd_scratch+6));
776 PD.cylinders = le16_to_cpu(*(u16*)(pd_scratch+2));
777 if (PD.can_lba)
778 PD.capacity = le32_to_cpu(*(u32*)(pd_scratch + 120));
779 else
780 PD.capacity = PD.sectors*PD.heads*PD.cylinders;
781
782 for(j=0;j<PD_ID_LEN;j++) id[j^1] = pd_scratch[j+PD_ID_OFF];
783 j = PD_ID_LEN-1;
784 while ((j >= 0) && (id[j] <= 0x20)) j--;
785 j++; id[j] = 0;
786
787 PD.removable = (word_val(0) & 0x80);
788
789 printk("%s: %s, %s, %d blocks [%dM], (%d/%d/%d), %s media\n",
790 PD.name,id,
791 PD.drive?"slave":"master",
792 PD.capacity,PD.capacity/2048,
793 PD.cylinders,PD.heads,PD.sectors,
794 PD.removable?"removable":"fixed");
795
796 if (PD.capacity) pd_init_dev_parms(unit);
797 if (!PD.standby) pd_standby_off(unit);
798
799 return 1;
800}
801
802static int pd_probe_drive( int unit )
803{
804 if (PD.drive == -1) {
805 for (PD.drive=0;PD.drive<=1;PD.drive++)
806 if (pd_identify(unit))
807 return 1;
808 return 0;
809 }
810 return pd_identify(unit);
811}
812
813static int pd_detect( void )
814
815{ int k, unit;
816
817 k = 0;
818 if (pd_drive_count == 0) {
819 unit = 0;
820 if (pi_init(PI,1,-1,-1,-1,-1,-1,pd_scratch,
821 PI_PD,verbose,PD.name)) {
822 if (pd_probe_drive(unit)) {
823 PD.present = 1;
824 k = 1;
825 } else pi_release(PI);
826 }
827
828 } else for (unit=0;unit<PD_UNITS;unit++) if (DU[D_PRT])
829 if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
830 DU[D_PRO],DU[D_DLY],pd_scratch,
831 PI_PD,verbose,PD.name)) {
832 if (pd_probe_drive(unit)) {
833 PD.present = 1;
834 k = unit+1;
835 } else pi_release(PI);
836 }
837 for (unit=0;unit<PD_UNITS;unit++)
838 register_disk(&pd_gendisk,MKDEV(MAJOR_NR,unit<<PD_BITS),
839 PD_PARTNS,&pd_fops,
840 PD.present?PD.capacity:0);
841
842
843
844
845
846
847 if (k)
848 return k;
849 printk("%s: no valid drive found\n",name);
850 return 0;
851}
852
853
854
855static int pd_ready( void )
856
857{ int unit = pd_unit;
858
859 return (!(RR(1,6) & STAT_BUSY)) ;
860}
861
862static void do_pd_request (request_queue_t * q)
863
864{ struct buffer_head * bh;
865 int unit;
866
867 if (pd_busy) return;
868repeat:
869 if (QUEUE_EMPTY || (CURRENT->rq_status == RQ_INACTIVE)) return;
870 INIT_REQUEST;
871
872 pd_dev = MINOR(CURRENT->rq_dev);
873 pd_unit = unit = DEVICE_NR(CURRENT->rq_dev);
874 pd_block = CURRENT->sector;
875 pd_run = CURRENT->nr_sectors;
876 pd_count = CURRENT->current_nr_sectors;
877
878 bh = CURRENT->bh;
879
880 if ((pd_dev >= PD_DEVS) ||
881 ((pd_block+pd_count) > pd_hd[pd_dev].nr_sects)) {
882 end_request(0);
883 goto repeat;
884 }
885
886 pd_cmd = CURRENT->cmd;
887 pd_poffs = pd_hd[pd_dev].start_sect;
888 pd_block += pd_poffs;
889 pd_buf = CURRENT->buffer;
890 pd_retries = 0;
891
892 pd_busy = 1;
893 if (pd_cmd == READ) pi_do_claimed(PI,do_pd_read);
894 else if (pd_cmd == WRITE) pi_do_claimed(PI,do_pd_write);
895 else { pd_busy = 0;
896 end_request(0);
897 goto repeat;
898 }
899}
900
901static void pd_next_buf( int unit )
902
903{ unsigned long saved_flags;
904
905 spin_lock_irqsave(&io_request_lock,saved_flags);
906 end_request(1);
907 if (!pd_run) { spin_unlock_irqrestore(&io_request_lock,saved_flags);
908 return;
909 }
910
911
912
913 if (QUEUE_EMPTY ||
914 (CURRENT->cmd != pd_cmd) ||
915 (MINOR(CURRENT->rq_dev) != pd_dev) ||
916 (CURRENT->rq_status == RQ_INACTIVE) ||
917 (CURRENT->sector+pd_poffs != pd_block))
918 printk("%s: OUCH: request list changed unexpectedly\n",
919 PD.name);
920
921 pd_count = CURRENT->current_nr_sectors;
922 pd_buf = CURRENT->buffer;
923 spin_unlock_irqrestore(&io_request_lock,saved_flags);
924}
925
926static void do_pd_read( void )
927
928{ ps_set_intr(do_pd_read_start,0,0,nice);
929}
930
931static void do_pd_read_start( void )
932
933{ int unit = pd_unit;
934 unsigned long saved_flags;
935
936 pd_busy = 1;
937
938 pi_connect(PI);
939 if (pd_wait_for(unit,STAT_READY,"do_pd_read") & STAT_ERR) {
940 pi_disconnect(PI);
941 if (pd_retries < PD_MAX_RETRIES) {
942 pd_retries++;
943 pi_do_claimed(PI,do_pd_read_start);
944 return;
945 }
946 spin_lock_irqsave(&io_request_lock,saved_flags);
947 end_request(0);
948 pd_busy = 0;
949 do_pd_request(NULL);
950 spin_unlock_irqrestore(&io_request_lock,saved_flags);
951 return;
952 }
953 pd_ide_command(unit,IDE_READ,pd_block,pd_run);
954 ps_set_intr(do_pd_read_drq,pd_ready,PD_TMO,nice);
955}
956
957static void do_pd_read_drq( void )
958
959{ int unit = pd_unit;
960 unsigned long saved_flags;
961
962 while (1) {
963 if (pd_wait_for(unit,STAT_DRQ,"do_pd_read_drq") & STAT_ERR) {
964 pi_disconnect(PI);
965 if (pd_retries < PD_MAX_RETRIES) {
966 pd_retries++;
967 pi_do_claimed(PI,do_pd_read_start);
968 return;
969 }
970 spin_lock_irqsave(&io_request_lock,saved_flags);
971 end_request(0);
972 pd_busy = 0;
973 do_pd_request(NULL);
974 spin_unlock_irqrestore(&io_request_lock,saved_flags);
975 return;
976 }
977 pi_read_block(PI,pd_buf,512);
978 pd_count--; pd_run--;
979 pd_buf += 512;
980 pd_block++;
981 if (!pd_run) break;
982 if (!pd_count) pd_next_buf(unit);
983 }
984 pi_disconnect(PI);
985 spin_lock_irqsave(&io_request_lock,saved_flags);
986 end_request(1);
987 pd_busy = 0;
988 do_pd_request(NULL);
989 spin_unlock_irqrestore(&io_request_lock,saved_flags);
990}
991
992static void do_pd_write( void )
993
994{ ps_set_intr(do_pd_write_start,0,0,nice);
995}
996
997static void do_pd_write_start( void )
998
999{ int unit = pd_unit;
1000 unsigned long saved_flags;
1001
1002 pd_busy = 1;
1003
1004 pi_connect(PI);
1005 if (pd_wait_for(unit,STAT_READY,"do_pd_write") & STAT_ERR) {
1006 pi_disconnect(PI);
1007 if (pd_retries < PD_MAX_RETRIES) {
1008 pd_retries++;
1009 pi_do_claimed(PI,do_pd_write_start);
1010 return;
1011 }
1012 spin_lock_irqsave(&io_request_lock,saved_flags);
1013 end_request(0);
1014 pd_busy = 0;
1015 do_pd_request(NULL);
1016 spin_unlock_irqrestore(&io_request_lock,saved_flags);
1017 return;
1018 }
1019 pd_ide_command(unit,IDE_WRITE,pd_block,pd_run);
1020 while (1) {
1021 if (pd_wait_for(unit,STAT_DRQ,"do_pd_write_drq") & STAT_ERR) {
1022 pi_disconnect(PI);
1023 if (pd_retries < PD_MAX_RETRIES) {
1024 pd_retries++;
1025 pi_do_claimed(PI,do_pd_write_start);
1026 return;
1027 }
1028 spin_lock_irqsave(&io_request_lock,saved_flags);
1029 end_request(0);
1030 pd_busy = 0;
1031 do_pd_request(NULL);
1032 spin_unlock_irqrestore(&io_request_lock,saved_flags);
1033 return;
1034 }
1035 pi_write_block(PI,pd_buf,512);
1036 pd_count--; pd_run--;
1037 pd_buf += 512;
1038 pd_block++;
1039 if (!pd_run) break;
1040 if (!pd_count) pd_next_buf(unit);
1041 }
1042 ps_set_intr(do_pd_write_done,pd_ready,PD_TMO,nice);
1043}
1044
1045static void do_pd_write_done( void )
1046
1047{ int unit = pd_unit;
1048 unsigned long saved_flags;
1049
1050 if (pd_wait_for(unit,STAT_READY,"do_pd_write_done") & STAT_ERR) {
1051 pi_disconnect(PI);
1052 if (pd_retries < PD_MAX_RETRIES) {
1053 pd_retries++;
1054 pi_do_claimed(PI,do_pd_write_start);
1055 return;
1056 }
1057 spin_lock_irqsave(&io_request_lock,saved_flags);
1058 end_request(0);
1059 pd_busy = 0;
1060 do_pd_request(NULL);
1061 spin_unlock_irqrestore(&io_request_lock,saved_flags);
1062 return;
1063 }
1064 pi_disconnect(PI);
1065 spin_lock_irqsave(&io_request_lock,saved_flags);
1066 end_request(1);
1067 pd_busy = 0;
1068 do_pd_request(NULL);
1069 spin_unlock_irqrestore(&io_request_lock,saved_flags);
1070}
1071
1072
1073
1074MODULE_LICENSE("GPL");
1075