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