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