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