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