This source file includes following definitions.
- select_callback
- floppy_select
- motor_on_callback
- motor_off_callback
- floppy_on
- floppy_off
- request_done
- floppy_change
- setup_DMA
- output_byte
- result
- bad_flp_intr
- perpendicular_mode
- configure_fdc_mode
- tell_sector
- rw_interrupt
- setup_rw_floppy
- seek_interrupt
- transfer
- recal_interrupt
- unexpected_floppy_interrupt
- recalibrate_floppy
- reset_interrupt
- reset_floppy
- floppy_shutdown
- shake_done
- retry_recal
- shake_zero
- shake_one
- floppy_ready
- setup_format_params
- redo_fd_request
- do_fd_request
- fd_ioctl
- find_base
- config_types
- floppy_open
- floppy_release
- ignore_interrupt
- floppy_interrupt
- floppy_init
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 #define REALLY_SLOW_IO
68 #define FLOPPY_IRQ 6
69 #define FLOPPY_DMA 2
70
71 #include <linux/sched.h>
72 #include <linux/fs.h>
73 #include <linux/kernel.h>
74 #include <linux/timer.h>
75 #include <linux/fdreg.h>
76 #include <linux/fd.h>
77 #include <linux/errno.h>
78
79 #include <asm/dma.h>
80 #include <asm/system.h>
81 #include <asm/io.h>
82 #include <asm/segment.h>
83
84 #define MAJOR_NR 2
85 #include "blk.h"
86
87 static unsigned int changed_floppies = 0, fake_change = 0;
88
89 static int initial_reset_flag = 0;
90 static int need_configure = 1;
91 static int recalibrate = 0;
92 static int reset = 0;
93 static int recover = 0;
94 static int seek = 0;
95
96 static unsigned char current_DOR = 0x0C;
97 static unsigned char running = 0;
98
99 #define TYPE(x) ((x)>>2)
100 #define DRIVE(x) ((x)&0x03)
101
102
103
104
105
106
107 #define MAX_ERRORS 12
108
109
110
111
112
113 #define MAX_DISK_SIZE 1440
114
115
116
117
118
119 #define MAX_BUFFER_SECTORS 18
120
121
122
123
124
125 #define LAST_DMA_ADDR (0x1000000 - BLOCK_SIZE)
126
127
128
129
130 #define MAX_REPLIES 7
131 static unsigned char reply_buffer[MAX_REPLIES];
132 #define ST0 (reply_buffer[0])
133 #define ST1 (reply_buffer[1])
134 #define ST2 (reply_buffer[2])
135 #define ST3 (reply_buffer[3])
136
137
138
139
140
141
142
143
144 static struct floppy_struct floppy_type[] = {
145 { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL },
146 { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,NULL },
147 { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,NULL },
148 { 720, 9,2,40,1,0x2A,0x02,0xDF,0x50,NULL },
149 { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,NULL },
150 { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,NULL },
151 { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,NULL },
152 { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL },
153 };
154
155
156
157
158
159
160 static struct floppy_struct floppy_types[] = {
161 { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" },
162 { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" },
163 { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"1.2M" },
164 { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"360k/AT" },
165 { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k" },
166 { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k" },
167 { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"1.44M" },
168 { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k/AT" },
169 };
170
171
172 struct floppy_struct *current_type[4] = { NULL, NULL, NULL, NULL };
173
174
175 struct floppy_struct *base_type[4];
176
177
178
179
180
181 struct floppy_struct user_params[4];
182
183 static int floppy_sizes[] ={
184 MAX_DISK_SIZE, MAX_DISK_SIZE, MAX_DISK_SIZE, MAX_DISK_SIZE,
185 360, 360 ,360, 360,
186 1200,1200,1200,1200,
187 360, 360, 360, 360,
188 720, 720, 720, 720,
189 360, 360, 360, 360,
190 720, 720, 720, 720,
191 1440,1440,1440,1440
192 };
193
194
195
196
197
198
199 static int probing = 0;
200
201
202
203
204
205
206 static int keep_data[4] = { 0,0,0,0 };
207
208
209
210
211
212
213 static ftd_msg[4] = { 0,0,0,0 };
214
215
216
217 static fd_ref[4] = { 0,0,0,0 };
218 static fd_device[4] = { 0,0,0,0 };
219
220
221 static volatile int format_status = FORMAT_NONE, fdc_busy = 0;
222 static struct wait_queue *fdc_wait = NULL, *format_done = NULL;
223
224
225 static int format_errors;
226
227
228 static struct format_descr format_req;
229
230
231
232
233
234 #define CURRENT_DEVICE (format_status == FORMAT_BUSY ? format_req.device : \
235 (CURRENT->dev))
236
237
238 #define CURRENT_ERRORS (format_status == FORMAT_BUSY ? format_errors : \
239 (CURRENT->errors))
240
241
242
243
244
245
246 static unsigned short min_report_error_cnt[4] = {2, 2, 2, 2};
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264 extern char tmp_floppy_area[BLOCK_SIZE];
265 extern char floppy_track_buffer[512*2*MAX_BUFFER_SECTORS];
266
267 static void redo_fd_request(void);
268
269
270
271
272
273
274 #define NO_TRACK 255
275
276 static int read_track = 0;
277 static int buffer_track = -1;
278 static int buffer_drive = -1;
279 static int cur_spec1 = -1;
280 static int cur_rate = -1;
281 static struct floppy_struct * floppy = floppy_type;
282 static unsigned char current_drive = 255;
283 static unsigned char sector = 0;
284 static unsigned char head = 0;
285 static unsigned char track = 0;
286 static unsigned char seek_track = 0;
287 static unsigned char current_track = NO_TRACK;
288 static unsigned char command = 0;
289 static unsigned char fdc_version = FDC_TYPE_STD;
290
291 static void floppy_ready(void);
292
293 static void select_callback(unsigned long unused)
294 {
295 floppy_ready();
296 }
297
298 static void floppy_select(unsigned int nr)
299 {
300 static struct timer_list select = { NULL, 0, 0, select_callback };
301
302 if (current_drive == (current_DOR & 3)) {
303 floppy_ready();
304 return;
305 }
306 seek = 1;
307 current_track = NO_TRACK;
308 current_DOR &= 0xFC;
309 current_DOR |= current_drive;
310 outb(current_DOR,FD_DOR);
311 del_timer(&select);
312 select.expires = 2;
313 add_timer(&select);
314 }
315
316 static void motor_on_callback(unsigned long nr)
317 {
318 running |= 0x10 << nr;
319 floppy_select(nr);
320 }
321
322 static struct timer_list motor_on_timer[4] = {
323 { NULL, 0, 0, motor_on_callback },
324 { NULL, 0, 1, motor_on_callback },
325 { NULL, 0, 2, motor_on_callback },
326 { NULL, 0, 3, motor_on_callback }
327 };
328
329 static void motor_off_callback(unsigned long nr)
330 {
331 unsigned char mask = ~(0x10 << nr);
332 cli();
333 running &= mask;
334 current_DOR &= mask;
335 outb(current_DOR,FD_DOR);
336 sti();
337 }
338
339 static struct timer_list motor_off_timer[4] = {
340 { NULL, 0, 0, motor_off_callback },
341 { NULL, 0, 1, motor_off_callback },
342 { NULL, 0, 2, motor_off_callback },
343 { NULL, 0, 3, motor_off_callback }
344 };
345
346 static void floppy_on(unsigned int nr)
347 {
348 unsigned char mask = 0x10 << nr;
349
350 del_timer(motor_off_timer + nr);
351 if (mask & running)
352 floppy_select(nr);
353 if (!(mask & current_DOR)) {
354 del_timer(motor_on_timer + nr);
355 motor_on_timer[nr].expires = HZ;
356 add_timer(motor_on_timer + nr);
357 }
358 current_DOR &= 0xFC;
359 current_DOR |= mask;
360 current_DOR |= nr;
361 outb(current_DOR,FD_DOR);
362 }
363
364 static void floppy_off(unsigned int nr)
365 {
366 del_timer(motor_off_timer+nr);
367 motor_off_timer[nr].expires = 3*HZ;
368 add_timer(motor_off_timer+nr);
369 }
370
371 void request_done(int uptodate)
372 {
373 timer_active &= ~(1 << FLOPPY_TIMER);
374 if (format_status != FORMAT_BUSY)
375 end_request(uptodate);
376 else {
377 format_status = uptodate ? FORMAT_OKAY : FORMAT_ERROR;
378 wake_up(&format_done);
379 }
380 }
381
382
383
384
385
386
387
388 int floppy_change(struct buffer_head * bh)
389 {
390 unsigned int mask = 1 << (bh->b_dev & 0x03);
391
392 if (MAJOR(bh->b_dev) != 2) {
393 printk("floppy_changed: not a floppy\n");
394 return 0;
395 }
396 if (fake_change & mask) {
397 fake_change &= ~mask;
398
399 changed_floppies &= ~mask;
400 return 1;
401 }
402 if (changed_floppies & mask) {
403 changed_floppies &= ~mask;
404 recalibrate = 1;
405 return 1;
406 }
407 if (!bh)
408 return 0;
409 if (bh->b_dirt)
410 ll_rw_block(WRITE, 1, &bh);
411 else {
412 buffer_track = -1;
413 bh->b_uptodate = 0;
414 ll_rw_block(READ, 1, &bh);
415 }
416 cli();
417 while (bh->b_lock)
418 sleep_on(&bh->b_wait);
419 sti();
420 if (changed_floppies & mask) {
421 changed_floppies &= ~mask;
422 recalibrate = 1;
423 return 1;
424 }
425 return 0;
426 }
427
428 #define copy_buffer(from,to) \
429 __asm__("cld ; rep ; movsl" \
430 : \
431 :"c" (BLOCK_SIZE/4),"S" ((long)(from)),"D" ((long)(to)) \
432 :"cx","di","si")
433
434 static void setup_DMA(void)
435 {
436 unsigned long addr,count;
437 unsigned char dma_code;
438
439 dma_code = DMA_WRITE;
440 if (command == FD_READ)
441 dma_code = DMA_READ;
442 if (command == FD_FORMAT) {
443 addr = (long) tmp_floppy_area;
444 count = floppy->sect*4;
445 } else {
446 addr = (long) CURRENT->buffer;
447 count = 1024;
448 }
449 if (read_track) {
450
451 buffer_drive = buffer_track = -1;
452 count = floppy->sect*2*512;
453 addr = (long) floppy_track_buffer;
454 } else if (addr >= LAST_DMA_ADDR) {
455 addr = (long) tmp_floppy_area;
456 if (command == FD_WRITE)
457 copy_buffer(CURRENT->buffer,tmp_floppy_area);
458 }
459 cli();
460 disable_dma(FLOPPY_DMA);
461 clear_dma_ff(FLOPPY_DMA);
462 set_dma_mode(FLOPPY_DMA, (command == FD_READ)? DMA_MODE_READ : DMA_MODE_WRITE);
463 set_dma_addr(FLOPPY_DMA, addr);
464 set_dma_count(FLOPPY_DMA, count);
465 enable_dma(FLOPPY_DMA);
466 sti();
467 }
468
469 static void output_byte(char byte)
470 {
471 int counter;
472 unsigned char status;
473
474 if (reset)
475 return;
476 for(counter = 0 ; counter < 10000 ; counter++) {
477 status = inb_p(FD_STATUS) & (STATUS_READY | STATUS_DIR);
478 if (status == STATUS_READY) {
479 outb(byte,FD_DATA);
480 return;
481 }
482 }
483 current_track = NO_TRACK;
484 reset = 1;
485 printk("Unable to send byte to FDC\n");
486 }
487
488 static int result(void)
489 {
490 int i = 0, counter, status;
491
492 if (reset)
493 return -1;
494 for (counter = 0 ; counter < 10000 ; counter++) {
495 status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY);
496 if (status == STATUS_READY) {
497 return i;
498 }
499 if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
500 if (i >= MAX_REPLIES) {
501 printk("floppy_stat reply overrun\n");
502 break;
503 }
504 reply_buffer[i++] = inb_p(FD_DATA);
505 }
506 }
507 reset = 1;
508 current_track = NO_TRACK;
509 printk("Getstatus times out\n");
510 return -1;
511 }
512
513 static void bad_flp_intr(void)
514 {
515 int errors;
516
517 current_track = NO_TRACK;
518 if (format_status == FORMAT_BUSY)
519 errors = ++format_errors;
520 else if (!CURRENT) {
521 printk(DEVICE_NAME ": no current request\n");
522 reset = recalibrate = 1;
523 return;
524 } else
525 errors = ++CURRENT->errors;
526 if (errors > MAX_ERRORS) {
527 request_done(0);
528 }
529 if (errors > MAX_ERRORS/2)
530 reset = 1;
531 else
532 recalibrate = 1;
533 }
534
535
536
537
538
539
540 static inline void perpendicular_mode(unsigned char rate)
541 {
542 if (fdc_version == FDC_TYPE_82077) {
543 output_byte(FD_PERPENDICULAR);
544 if (rate & 0x40) {
545 unsigned char r = rate & 0x03;
546 if (r == 0)
547 output_byte(2);
548 else if (r == 3)
549 output_byte(3);
550 else {
551 printk(DEVICE_NAME ": Invalid data rate for perpendicular mode!\n");
552 reset = 1;
553 }
554 } else
555 output_byte(0);
556 } else {
557 if (rate & 0x40) {
558 printk(DEVICE_NAME ": perpendicular mode not supported by this FDC.\n");
559 reset = 1;
560 }
561 }
562 }
563
564
565
566
567
568
569
570
571 static void configure_fdc_mode(void)
572 {
573 if (need_configure && (fdc_version == FDC_TYPE_82077)) {
574
575 output_byte(FD_CONFIGURE);
576 output_byte(0);
577 output_byte(0x1A);
578 output_byte(0);
579 need_configure = 0;
580 printk(DEVICE_NAME ": FIFO enabled\n");
581 }
582 if (cur_spec1 != floppy->spec1) {
583 cur_spec1 = floppy->spec1;
584 output_byte(FD_SPECIFY);
585 output_byte(cur_spec1);
586 output_byte(6);
587 }
588 if (cur_rate != floppy->rate) {
589
590 perpendicular_mode(floppy->rate);
591 outb_p((cur_rate = (floppy->rate)) & ~0x40, FD_DCR);
592 }
593 }
594
595
596 static void tell_sector(int nr)
597 {
598 if (nr!=7) {
599 printk(" -- FDC reply errror");
600 reset = 1;
601 } else
602 printk(": track %d, head %d, sector %d", reply_buffer[3],
603 reply_buffer[4], reply_buffer[5]);
604 }
605
606
607
608
609
610
611
612 static void rw_interrupt(void)
613 {
614 char * buffer_area;
615 int nr;
616 char bad;
617
618 nr = result();
619
620 switch ((ST0 & ST0_INTR)>>6) {
621 case 1:
622 bad = 1;
623 if (ST1 & ST1_WP) {
624 printk(DEVICE_NAME ": Drive %d is write protected\n", current_drive);
625 request_done(0);
626 bad = 0;
627 } else if (ST1 & ST1_OR) {
628 if (ftd_msg[ST0 & ST0_DS])
629 printk(DEVICE_NAME ": Over/Underrun - retrying\n");
630
631 bad = 0;
632 } else if (CURRENT_ERRORS > min_report_error_cnt[ST0 & ST0_DS]) {
633 printk(DEVICE_NAME " %d: ", ST0 & ST0_DS);
634 if (ST0 & ST0_ECE) {
635 printk("Recalibrate failed!");
636 } else if (ST2 & ST2_CRC) {
637 printk("data CRC error");
638 tell_sector(nr);
639 } else if (ST1 & ST1_CRC) {
640 printk("CRC error");
641 tell_sector(nr);
642 } else if ((ST1 & (ST1_MAM|ST1_ND)) || (ST2 & ST2_MAM)) {
643 if (!probing) {
644 printk("sector not found");
645 tell_sector(nr);
646 } else
647 printk("probe failed...");
648 } else if (ST2 & ST2_WC) {
649 printk("wrong cylinder");
650 } else if (ST2 & ST2_BC) {
651 printk("bad cylinder");
652 } else {
653 printk("unknown error. ST[0..3] are: 0x%x 0x%x 0x%x 0x%x\n", ST0, ST1, ST2, ST3);
654 }
655 printk("\n");
656
657 }
658 if (bad)
659 bad_flp_intr();
660 redo_fd_request();
661 return;
662 case 2:
663 printk(DEVICE_NAME ": Invalid FDC command given!\n");
664 request_done(0);
665 return;
666 case 3:
667 printk(DEVICE_NAME ": Abnormal termination caused by polling\n");
668 bad_flp_intr();
669 redo_fd_request();
670 return;
671 default:
672 break;
673 }
674
675 if (probing) {
676 int drive = MINOR(CURRENT->dev);
677
678 if (ftd_msg[drive])
679 printk("Auto-detected floppy type %s in fd%d\n",
680 floppy->name,drive);
681 current_type[drive] = floppy;
682 floppy_sizes[drive] = floppy->size >> 1;
683 probing = 0;
684 }
685 if (read_track) {
686 buffer_track = seek_track;
687 buffer_drive = current_drive;
688 buffer_area = floppy_track_buffer +
689 ((sector-1 + head*floppy->sect)<<9);
690 copy_buffer(buffer_area,CURRENT->buffer);
691 } else if (command == FD_READ &&
692 (unsigned long)(CURRENT->buffer) >= LAST_DMA_ADDR)
693 copy_buffer(tmp_floppy_area,CURRENT->buffer);
694 request_done(1);
695 redo_fd_request();
696 }
697
698
699
700
701
702
703
704
705 inline void setup_rw_floppy(void)
706 {
707 setup_DMA();
708 do_floppy = rw_interrupt;
709 output_byte(command);
710 if (command != FD_FORMAT) {
711 if (read_track) {
712 output_byte(current_drive);
713 output_byte(track);
714 output_byte(0);
715 output_byte(1);
716 } else {
717 output_byte(head<<2 | current_drive);
718 output_byte(track);
719 output_byte(head);
720 output_byte(sector);
721 }
722 output_byte(2);
723 output_byte(floppy->sect);
724 output_byte(floppy->gap);
725 output_byte(0xFF);
726 } else {
727 output_byte(head<<2 | current_drive);
728 output_byte(2);
729 output_byte(floppy->sect);
730 output_byte(floppy->fmt_gap);
731 output_byte(FD_FILL_BYTE);
732 }
733 if (reset)
734 redo_fd_request();
735 }
736
737
738
739
740
741
742 static void seek_interrupt(void)
743 {
744
745 output_byte(FD_SENSEI);
746 if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {
747 printk(DEVICE_NAME ": seek failed\n");
748 recalibrate = 1;
749 bad_flp_intr();
750 redo_fd_request();
751 return;
752 }
753 current_track = ST1;
754 setup_rw_floppy();
755 }
756
757
758
759
760
761
762
763 static void transfer(void)
764 {
765 read_track = (command == FD_READ) && (CURRENT_ERRORS < 4) &&
766 (floppy->sect <= MAX_BUFFER_SECTORS);
767
768 configure_fdc_mode();
769
770 if (reset) {
771 redo_fd_request();
772 return;
773 }
774 if (!seek) {
775 setup_rw_floppy();
776 return;
777 }
778
779 do_floppy = seek_interrupt;
780 output_byte(FD_SEEK);
781 if (read_track)
782 output_byte(current_drive);
783 else
784 output_byte((head<<2) | current_drive);
785 output_byte(seek_track);
786 if (reset)
787 redo_fd_request();
788 }
789
790
791
792
793
794 static void recalibrate_floppy(void);
795
796 static void recal_interrupt(void)
797 {
798 output_byte(FD_SENSEI);
799 current_track = NO_TRACK;
800 if (result()!=2 || (ST0 & 0xE0) == 0x60)
801 reset = 1;
802
803 if ((ST0 & 0x10) == 0x10)
804 recalibrate_floppy();
805 else
806 redo_fd_request();
807 }
808
809 static void unexpected_floppy_interrupt(void)
810 {
811 current_track = NO_TRACK;
812 output_byte(FD_SENSEI);
813 printk(DEVICE_NAME ": unexpected interrupt\n");
814 if (result()!=2 || (ST0 & 0xE0) == 0x60)
815 reset = 1;
816 else
817 recalibrate = 1;
818 }
819
820 static void recalibrate_floppy(void)
821 {
822 recalibrate = 0;
823 current_track = 0;
824 do_floppy = recal_interrupt;
825 output_byte(FD_RECALIBRATE);
826 output_byte(head<<2 | current_drive);
827 if (reset)
828 redo_fd_request();
829 }
830
831
832
833
834 static void reset_interrupt(void)
835 {
836 short i;
837
838 for (i=0; i<4; i++) {
839 output_byte(FD_SENSEI);
840 (void) result();
841 }
842 output_byte(FD_SPECIFY);
843 output_byte(cur_spec1);
844 output_byte(6);
845 configure_fdc_mode();
846 if (initial_reset_flag) {
847 initial_reset_flag = 0;
848 recalibrate = 1;
849 reset = 0;
850 return;
851 }
852 if (!recover)
853 redo_fd_request();
854 else {
855 recalibrate_floppy();
856 recover = 0;
857 }
858 }
859
860
861
862
863 static void reset_floppy(void)
864 {
865 int i;
866
867 do_floppy = reset_interrupt;
868 reset = 0;
869 current_track = NO_TRACK;
870 cur_spec1 = -1;
871 cur_rate = -1;
872 recalibrate = 1;
873 need_configure = 1;
874 if (!initial_reset_flag)
875 printk("Reset-floppy called\n");
876 cli();
877 outb_p(current_DOR & ~0x04, FD_DOR);
878 for (i=0 ; i<1000 ; i++)
879 __asm__("nop");
880 outb(current_DOR, FD_DOR);
881 sti();
882 }
883
884 static void floppy_shutdown(void)
885 {
886 cli();
887 do_floppy = NULL;
888 request_done(0);
889 recover = 1;
890 reset_floppy();
891 sti();
892 redo_fd_request();
893 }
894
895 static void shake_done(void)
896 {
897 current_track = NO_TRACK;
898 if (inb(FD_DIR) & 0x80)
899 request_done(0);
900 redo_fd_request();
901 }
902
903 static int retry_recal(void (*proc)(void))
904 {
905 output_byte(FD_SENSEI);
906 if (result() == 2 && (ST0 & 0x10) != 0x10) return 0;
907 do_floppy = proc;
908 output_byte(FD_RECALIBRATE);
909 output_byte(head<<2 | current_drive);
910 return 1;
911 }
912
913 static void shake_zero(void)
914 {
915 if (!retry_recal(shake_zero)) shake_done();
916 }
917
918 static void shake_one(void)
919 {
920 if (retry_recal(shake_one)) return;
921 do_floppy = shake_done;
922 output_byte(FD_SEEK);
923 output_byte(head << 2 | current_drive);
924 output_byte(1);
925 }
926
927 static void floppy_ready(void)
928 {
929 if (inb(FD_DIR) & 0x80) {
930 changed_floppies |= 1<<current_drive;
931 buffer_track = -1;
932 if (keep_data[current_drive]) {
933 if (keep_data[current_drive] > 0)
934 keep_data[current_drive]--;
935 } else {
936 if (ftd_msg[current_drive] && current_type[current_drive] != NULL)
937 printk("Disk type is undefined after disk "
938 "change in fd%d\n",current_drive);
939 current_type[current_drive] = NULL;
940 floppy_sizes[current_drive] = MAX_DISK_SIZE;
941 }
942
943
944
945 if (!reset && !recalibrate) {
946 if (current_track && current_track != NO_TRACK)
947 do_floppy = shake_zero;
948 else
949 do_floppy = shake_one;
950 output_byte(FD_RECALIBRATE);
951 output_byte(head<<2 | current_drive);
952 return;
953 }
954 }
955 if (reset) {
956 reset_floppy();
957 return;
958 }
959 if (recalibrate) {
960 recalibrate_floppy();
961 return;
962 }
963 transfer();
964 }
965
966 static void setup_format_params(void)
967 {
968 unsigned char *here = (unsigned char *) tmp_floppy_area;
969 int count,head_shift,track_shift,total_shift;
970
971
972 head_shift = floppy->sect / 6;
973
974 track_shift = 2 * head_shift + 1;
975
976 total_shift = floppy->sect -
977 ((track_shift * track + head_shift * head) % floppy->sect);
978
979
980 for (count = 0; count < floppy->sect; count++) {
981 *here++ = track;
982 *here++ = head;
983 *here++ = 1 + (( count + total_shift ) % floppy->sect);
984 *here++ = 2;
985 }
986 }
987
988 static void redo_fd_request(void)
989 {
990 unsigned int block;
991 char * buffer_area;
992 int device;
993
994 if (CURRENT && CURRENT->dev < 0) return;
995
996 repeat:
997 if (format_status == FORMAT_WAIT)
998 format_status = FORMAT_BUSY;
999 if (format_status != FORMAT_BUSY) {
1000 if (!CURRENT) {
1001 if (!fdc_busy)
1002 printk("FDC access conflict!");
1003 fdc_busy = 0;
1004 wake_up(&fdc_wait);
1005 CLEAR_INTR;
1006 return;
1007 }
1008 if (MAJOR(CURRENT->dev) != MAJOR_NR)
1009 panic(DEVICE_NAME ": request list destroyed"); \
1010 if (CURRENT->bh) {
1011 if (!CURRENT->bh->b_lock)
1012 panic(DEVICE_NAME ": block not locked");
1013 }
1014 }
1015 seek = 0;
1016 probing = 0;
1017 device = MINOR(CURRENT_DEVICE);
1018 if (device > 3)
1019 floppy = (device >> 2) + floppy_type;
1020 else {
1021 floppy = current_type[device & 3];
1022 if (!floppy) {
1023 probing = 1;
1024 floppy = base_type[device & 3];
1025 if (!floppy) {
1026 request_done(0);
1027 goto repeat;
1028 }
1029 if (CURRENT_ERRORS & 1)
1030 floppy++;
1031 }
1032 }
1033 if (format_status != FORMAT_BUSY) {
1034 if (current_drive != CURRENT_DEV) {
1035 current_track = NO_TRACK;
1036 current_drive = CURRENT_DEV;
1037 }
1038 block = CURRENT->sector;
1039 if (block+2 > floppy->size) {
1040 request_done(0);
1041 goto repeat;
1042 }
1043 sector = block % floppy->sect;
1044 block /= floppy->sect;
1045 head = block % floppy->head;
1046 track = block / floppy->head;
1047 seek_track = track << floppy->stretch;
1048 if (CURRENT->cmd == READ)
1049 command = FD_READ;
1050 else if (CURRENT->cmd == WRITE)
1051 command = FD_WRITE;
1052 else {
1053 printk("do_fd_request: unknown command\n");
1054 request_done(0);
1055 goto repeat;
1056 }
1057 } else {
1058 if (current_drive != (format_req.device & 3))
1059 current_track = NO_TRACK;
1060 current_drive = format_req.device & 3;
1061 if (((unsigned) format_req.track) >= floppy->track ||
1062 (format_req.head & 0xfffe) || probing) {
1063 request_done(0);
1064 goto repeat;
1065 }
1066 head = format_req.head;
1067 track = format_req.track;
1068 seek_track = track << floppy->stretch;
1069 if (seek_track == buffer_track) buffer_track = -1;
1070 command = FD_FORMAT;
1071 setup_format_params();
1072 }
1073 timer_table[FLOPPY_TIMER].expires = jiffies+10*HZ;
1074 timer_active |= 1 << FLOPPY_TIMER;
1075 if ((seek_track == buffer_track) &&
1076 (current_drive == buffer_drive)) {
1077 buffer_area = floppy_track_buffer +
1078 ((sector + head*floppy->sect)<<9);
1079 if (command == FD_READ) {
1080 copy_buffer(buffer_area,CURRENT->buffer);
1081 request_done(1);
1082 goto repeat;
1083 } else if (command == FD_WRITE)
1084 copy_buffer(CURRENT->buffer,buffer_area);
1085 }
1086 if (seek_track != current_track)
1087 seek = 1;
1088 sector++;
1089 del_timer(motor_off_timer + current_drive);
1090 floppy_on(current_drive);
1091 }
1092
1093 void do_fd_request(void)
1094 {
1095 cli();
1096 while (fdc_busy) sleep_on(&fdc_wait);
1097 fdc_busy = 1;
1098 sti();
1099 redo_fd_request();
1100 }
1101
1102 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1103 unsigned long param)
1104 {
1105 int i,drive,cnt,okay;
1106 struct floppy_struct *this_floppy;
1107
1108 switch (cmd) {
1109 RO_IOCTLS(inode->i_rdev,param);
1110 }
1111 drive = MINOR(inode->i_rdev);
1112 switch (cmd) {
1113 case FDFMTBEG:
1114 if (!suser())
1115 return -EPERM;
1116 return 0;
1117 case FDFMTEND:
1118 if (!suser())
1119 return -EPERM;
1120 cli();
1121 fake_change |= 1 << (drive & 3);
1122 sti();
1123 drive &= 3;
1124 cmd = FDCLRPRM;
1125 break;
1126 case FDGETPRM:
1127 if (drive > 3) this_floppy = &floppy_type[drive >> 2];
1128 else if ((this_floppy = current_type[drive & 3]) == NULL)
1129 return -ENODEV;
1130 i = verify_area(VERIFY_WRITE,(void *) param,sizeof(struct floppy_struct));
1131 if (i)
1132 return i;
1133 for (cnt = 0; cnt < sizeof(struct floppy_struct); cnt++)
1134 put_fs_byte(((char *) this_floppy)[cnt],
1135 (char *) param+cnt);
1136 return 0;
1137 case FDFMTTRK:
1138 if (!suser())
1139 return -EPERM;
1140 cli();
1141 while (format_status != FORMAT_NONE)
1142 sleep_on(&format_done);
1143 for (cnt = 0; cnt < sizeof(struct format_descr); cnt++)
1144 ((char *) &format_req)[cnt] = get_fs_byte(
1145 (char *) param+cnt);
1146 format_req.device = drive;
1147 format_status = FORMAT_WAIT;
1148 format_errors = 0;
1149 while (format_status != FORMAT_OKAY && format_status !=
1150 FORMAT_ERROR) {
1151 if (fdc_busy) sleep_on(&fdc_wait);
1152 else {
1153 fdc_busy = 1;
1154 redo_fd_request();
1155 }
1156 }
1157 while (format_status != FORMAT_OKAY && format_status !=
1158 FORMAT_ERROR)
1159 sleep_on(&format_done);
1160 sti();
1161 okay = format_status == FORMAT_OKAY;
1162 format_status = FORMAT_NONE;
1163 wake_up(&format_done);
1164 return okay ? 0 : -EIO;
1165 case FDFLUSH:
1166 if (!permission(inode, 2))
1167 return -EPERM;
1168 cli();
1169 fake_change |= 1 << (drive & 3);
1170 sti();
1171 check_disk_change(inode->i_rdev);
1172 return 0;
1173 }
1174 if (!suser())
1175 return -EPERM;
1176 if (drive < 0 || drive > 3)
1177 return -EINVAL;
1178 switch (cmd) {
1179 case FDCLRPRM:
1180 current_type[drive] = NULL;
1181 floppy_sizes[drive] = MAX_DISK_SIZE;
1182 keep_data[drive] = 0;
1183 break;
1184 case FDSETPRM:
1185 case FDDEFPRM:
1186 memcpy_fromfs(user_params+drive,
1187 (void *) param,
1188 sizeof(struct floppy_struct));
1189 current_type[drive] = &user_params[drive];
1190 floppy_sizes[drive] = user_params[drive].size >> 1;
1191 if (cmd == FDDEFPRM)
1192 keep_data[drive] = -1;
1193 else {
1194 cli();
1195 while (fdc_busy) sleep_on(&fdc_wait);
1196 fdc_busy = 1;
1197 sti();
1198 outb_p((current_DOR & 0xfc) | drive |
1199 (0x10 << drive),FD_DOR);
1200 for (cnt = 0; cnt < 1000; cnt++) __asm__("nop");
1201 if (inb(FD_DIR) & 0x80)
1202 keep_data[drive] = 1;
1203 else
1204 keep_data[drive] = 0;
1205 outb_p(current_DOR,FD_DOR);
1206 fdc_busy = 0;
1207 wake_up(&fdc_wait);
1208 }
1209 break;
1210 case FDMSGON:
1211 ftd_msg[drive] = 1;
1212 break;
1213 case FDMSGOFF:
1214 ftd_msg[drive] = 0;
1215 break;
1216 case FDSETEMSGTRESH:
1217 min_report_error_cnt[drive] = (unsigned short) (param & 0x0f);
1218 break;
1219 default:
1220 return -EINVAL;
1221 }
1222 return 0;
1223 }
1224
1225 #define CMOS_READ(addr) ({ \
1226 outb_p(addr,0x70); \
1227 inb_p(0x71); \
1228 })
1229
1230 static struct floppy_struct *find_base(int drive,int code)
1231 {
1232 struct floppy_struct *base;
1233
1234 if (code > 0 && code < 5) {
1235 base = &floppy_types[(code-1)*2];
1236 printk("fd%d is %s",drive,base->name);
1237 return base;
1238 }
1239 printk("fd%d is unknown type %d",drive,code);
1240 return NULL;
1241 }
1242
1243 static void config_types(void)
1244 {
1245 printk("Floppy drive(s): ");
1246 base_type[0] = find_base(0,(CMOS_READ(0x10) >> 4) & 15);
1247 if (((CMOS_READ(0x14) >> 6) & 1) == 0)
1248 base_type[1] = NULL;
1249 else {
1250 printk(", ");
1251 base_type[1] = find_base(1,CMOS_READ(0x10) & 15);
1252 }
1253 base_type[2] = base_type[3] = NULL;
1254 printk("\n");
1255 }
1256
1257
1258
1259
1260
1261
1262 static int floppy_open(struct inode * inode, struct file * filp)
1263 {
1264 int drive;
1265 int old_dev;
1266
1267 drive = inode->i_rdev & 3;
1268 old_dev = fd_device[drive];
1269 if (fd_ref[drive])
1270 if (old_dev != inode->i_rdev)
1271 return -EBUSY;
1272 fd_ref[drive]++;
1273 fd_device[drive] = inode->i_rdev;
1274 buffer_drive = buffer_track = -1;
1275 if (old_dev && old_dev != inode->i_rdev)
1276 invalidate_buffers(old_dev);
1277 if (filp && filp->f_mode)
1278 check_disk_change(inode->i_rdev);
1279 return 0;
1280 }
1281
1282 static void floppy_release(struct inode * inode, struct file * filp)
1283 {
1284 sync_dev(inode->i_rdev);
1285 if (!fd_ref[inode->i_rdev & 3]--) {
1286 printk("floppy_release with fd_ref == 0");
1287 fd_ref[inode->i_rdev & 3] = 0;
1288 }
1289 }
1290
1291 static struct file_operations floppy_fops = {
1292 NULL,
1293 block_read,
1294 block_write,
1295 NULL,
1296 NULL,
1297 fd_ioctl,
1298 NULL,
1299 floppy_open,
1300 floppy_release,
1301 block_fsync
1302 };
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 static void ignore_interrupt(void)
1314 {
1315 printk(DEVICE_NAME ": weird interrupt ignored (%d)\n", result());
1316 reset = 1;
1317 CLEAR_INTR;
1318 }
1319
1320
1321 static void floppy_interrupt(int unused)
1322 {
1323 void (*handler)(void) = DEVICE_INTR;
1324
1325 DEVICE_INTR = NULL;
1326 if (!handler)
1327 handler = unexpected_floppy_interrupt;
1328 handler();
1329 }
1330
1331
1332
1333
1334
1335 static struct sigaction floppy_sigaction = {
1336 floppy_interrupt,
1337 0,
1338 SA_INTERRUPT,
1339 NULL
1340 };
1341
1342 void floppy_init(void)
1343 {
1344 outb(current_DOR,FD_DOR);
1345 if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
1346 printk("Unable to get major %d for floppy\n",MAJOR_NR);
1347 return;
1348 }
1349 blk_size[MAJOR_NR] = floppy_sizes;
1350 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1351 timer_table[FLOPPY_TIMER].fn = floppy_shutdown;
1352 timer_active &= ~(1 << FLOPPY_TIMER);
1353 config_types();
1354 if (irqaction(FLOPPY_IRQ,&floppy_sigaction))
1355 printk("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ);
1356 if (request_dma(FLOPPY_DMA))
1357 printk("Unable to grab DMA%d for the floppy driver\n", FLOPPY_DMA);
1358
1359 DEVICE_INTR = ignore_interrupt;
1360 output_byte(FD_VERSION);
1361 if (result() != 1) {
1362 printk(DEVICE_NAME ": FDC failed to return version byte\n");
1363 fdc_version = FDC_TYPE_STD;
1364 } else
1365 fdc_version = reply_buffer[0];
1366 if (fdc_version != FDC_TYPE_STD)
1367 printk(DEVICE_NAME ": FDC version 0x%x\n", fdc_version);
1368 #ifndef FDC_FIFO_UNTESTED
1369 fdc_version = FDC_TYPE_STD;
1370 #endif
1371
1372
1373
1374
1375
1376
1377 if (fdc_version == FDC_TYPE_STD) {
1378 initial_reset_flag = 1;
1379 reset_floppy();
1380 }
1381 }