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