⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 floppy.c.txt

📁 Linux块设备驱动分析与模拟实现
💻 TXT
📖 第 1 页 / 共 4 页
字号:
697         request_done(1);
698         redo_fd_request();
699 }
700 
701 /*
702  * We try to read tracks, but if we get too many errors, we
703  * go back to reading just one sector at a time.
704  *
705  * This means we should be able to read a sector even if there
706  * are other bad sectors on this track.
707  */
708 inline void setup_rw_floppy(void)
709 {
710         setup_DMA();
711         do_floppy = rw_interrupt;
712         output_byte(command);
713         if (command != FD_FORMAT) {
714                 if (read_track) {
715                         output_byte(current_drive);
716                         output_byte(track);
717                         output_byte(0);
718                         output_byte(1);
719                 } else {
720                         output_byte(head<<2 | current_drive);
721                         output_byte(track);
722                         output_byte(head);
723                         output_byte(sector);
724                 }
725                 output_byte(2);         /* sector size = 512 */
726                 output_byte(floppy->sect);
727                 output_byte(floppy->gap);
728                 output_byte(0xFF);      /* sector size (0xff when n!=0 ?) */
729         } else {
730                 output_byte(head<<2 | current_drive);
731                 output_byte(2);
732                 output_byte(floppy->sect);
733                 output_byte(floppy->fmt_gap);
734                 output_byte(FD_FILL_BYTE);
735         }
736         if (reset)
737                 redo_fd_request();
738 }
739 
740 /*
741  * This is the routine called after every seek (or recalibrate) interrupt
742  * from the floppy controller. Note that the "unexpected interrupt" routine
743  * also does a recalibrate, but doesn't come here.
744  */
745 static void seek_interrupt(void)
746 {
747 /* sense drive status */
748         output_byte(FD_SENSEI);
749         if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {
750                 printk(DEVICE_NAME ": seek failed\n");
751                 recalibrate = 1;
752                 bad_flp_intr();
753                 redo_fd_request();
754                 return;
755         }
756         current_track = ST1;
757         setup_rw_floppy();
758 }
759 
760 
761 /*
762  * This routine is called when everything should be correctly set up
763  * for the transfer (ie floppy motor is on and the correct floppy is
764  * selected).
765  */
766 static void transfer(void)
767 {
768         read_track = (command == FD_READ) && (CURRENT_ERRORS < 4) &&
769             (floppy->sect <= MAX_BUFFER_SECTORS);
770 
771         configure_fdc_mode();
772 
773         if (reset) {
774                 redo_fd_request();
775                 return;
776         }
777         if (!seek) {
778                 setup_rw_floppy();
779                 return;
780         }
781 
782         do_floppy = seek_interrupt;
783         output_byte(FD_SEEK);
784         if (read_track)
785                 output_byte(current_drive);
786         else
787                 output_byte((head<<2) | current_drive);
788         output_byte(seek_track);
789         if (reset)
790                 redo_fd_request();
791 }
792 
793 /*
794  * Special case - used after a unexpected interrupt (or reset)
795  */
796 
797 static void recalibrate_floppy(void);
798 
799 static void recal_interrupt(void)
800 {
801         output_byte(FD_SENSEI);
802         current_track = NO_TRACK;
803         if (result()!=2 || (ST0 & 0xE0) == 0x60)
804                 reset = 1;
805 /* Recalibrate until track 0 is reached. Might help on some errors. */
806         if ((ST0 & 0x10) == 0x10)
807                 recalibrate_floppy();   /* FIXME: should limit nr of recalibrates */
808         else
809                 redo_fd_request();
810 }
811 
812 static void unexpected_floppy_interrupt(void)
813 {
814         current_track = NO_TRACK;
815         output_byte(FD_SENSEI);
816         printk(DEVICE_NAME ": unexpected interrupt\n");
817         if (result()!=2 || (ST0 & 0xE0) == 0x60)
818                 reset = 1;
819         else
820                 recalibrate = 1;
821 }
822 
823 static void recalibrate_floppy(void)
824 {
825         recalibrate = 0;
826         current_track = 0;
827         do_floppy = recal_interrupt;
828         output_byte(FD_RECALIBRATE);
829         output_byte(head<<2 | current_drive);
830         if (reset)
831                 redo_fd_request();
832 }
833 
834 /*
835  * Must do 4 FD_SENSEIs after reset because of ``drive polling''.
836  */
837 static void reset_interrupt(void)
838 {
839         short i;
840 
841         for (i=0; i<4; i++) {
842                 output_byte(FD_SENSEI);
843                 (void) result();
844         }
845         output_byte(FD_SPECIFY);
846         output_byte(cur_spec1);         /* hut etc */
847         output_byte(6);                 /* Head load time =6ms, DMA */
848         configure_fdc_mode();           /* reprogram fdc */
849         if (initial_reset_flag) {
850                 initial_reset_flag = 0;
851                 recalibrate = 1;
852                 reset = 0;
853                 return;
854         }
855         if (!recover)
856                 redo_fd_request();
857         else {
858                 recalibrate_floppy();
859                 recover = 0;
860         }
861 }
862 
863 /*
864  * reset is done by pulling bit 2 of DOR low for a while.
865  */
866 static void reset_floppy(void)
867 {
868         int i;
869 
870         do_floppy = reset_interrupt;
871         reset = 0;
872         current_track = NO_TRACK;
873         cur_spec1 = -1;
874         cur_rate = -1;
875         recalibrate = 1;
876         need_configure = 1;
877         if (!initial_reset_flag)
878                 printk("Reset-floppy called\n");
879         cli();
880         outb_p(current_DOR & ~0x04, FD_DOR);
881         for (i=0 ; i<1000 ; i++)
882                 __asm__("nop");
883         outb(current_DOR, FD_DOR);
884         sti();
885 }
886 
887 static void floppy_shutdown(void)
888 {
889         cli();
890         do_floppy = NULL;
891         request_done(0);
892         recover = 1;
893         reset_floppy();
894         sti();
895         redo_fd_request();
896 }
897 
898 static void shake_done(void)
899 {
900         current_track = NO_TRACK;
901         if (inb(FD_DIR) & 0x80)
902                 request_done(0);
903         redo_fd_request();
904 }
905 
906 static int retry_recal(void (*proc)(void))
907 {
908         output_byte(FD_SENSEI);
909         if (result() == 2 && (ST0 & 0x10) != 0x10) return 0;
910         do_floppy = proc;
911         output_byte(FD_RECALIBRATE);
912         output_byte(head<<2 | current_drive);
913         return 1;
914 }
915 
916 static void shake_zero(void)
917 {
918         if (!retry_recal(shake_zero)) shake_done();
919 }
920 
921 static void shake_one(void)
922 {
923         if (retry_recal(shake_one)) return;
924         do_floppy = shake_done;
925         output_byte(FD_SEEK);
926         output_byte(head << 2 | current_drive);
927         output_byte(1);
928 }
929 
930 static void floppy_ready(void)
931 {
932         if (inb(FD_DIR) & 0x80) {
933                 changed_floppies |= 1<<current_drive;
934                 buffer_track = -1;
935                 if (keep_data[current_drive]) {
936                         if (keep_data[current_drive] > 0)
937                                 keep_data[current_drive]--;
938                 } else {
939                         if (ftd_msg[current_drive] && current_type[current_drive] != NULL)
940                                 printk("Disk type is undefined after disk "
941                                     "change in fd%d\n",current_drive);
942                         current_type[current_drive] = NULL;
943                         floppy_sizes[current_drive] = MAX_DISK_SIZE;
944                 }
945 /* Forcing the drive to seek makes the "media changed" condition go away.
946  * There should be a cleaner solution for that ...
947  */
948                 if (!reset && !recalibrate) {
949                         if (current_track && current_track != NO_TRACK)
950                                 do_floppy = shake_zero;
951                         else
952                                 do_floppy = shake_one;
953                         output_byte(FD_RECALIBRATE);
954                         output_byte(head<<2 | current_drive);
955                         return;
956                 }
957         }
958         if (reset) {
959                 reset_floppy();
960                 return;
961         }
962         if (recalibrate) {
963                 recalibrate_floppy();
964                 return;
965         }
966         transfer();
967 }
968 
969 static void setup_format_params(void)
970 {
971     unsigned char *here = (unsigned char *) tmp_floppy_area;
972     int count,head_shift,track_shift,total_shift;
973 
974     /* allow for about 30ms for data transport per track */
975     head_shift  = floppy->sect / 6;
976     /* a ``cylinder'' is two tracks plus a little stepping time */
977     track_shift = 2 * head_shift + 1; 
978     /* count backwards */
979     total_shift = floppy->sect - 
980         ((track_shift * track + head_shift * head) % floppy->sect);
981 
982     /* XXX: should do a check to see this fits in tmp_floppy_area!! */
983     for (count = 0; count < floppy->sect; count++) {
984         *here++ = track;
985         *here++ = head;
986         *here++ = 1 + (( count + total_shift ) % floppy->sect);
987         *here++ = 2; /* 512 bytes */
988     }
989 }
990 
991 static void redo_fd_request(void)
992 {
993         unsigned int block;
994         char * buffer_area;
995         int device;
996 
997         if (CURRENT && CURRENT->dev < 0) return;
998 
999 repeat:
1000         if (format_status == FORMAT_WAIT)
1001                 format_status = FORMAT_BUSY;
1002         if (format_status != FORMAT_BUSY) {
1003                 if (!CURRENT) {
1004                         if (!fdc_busy)
1005                                 printk("FDC access conflict!");
1006                         fdc_busy = 0;
1007                         wake_up(&fdc_wait);
1008                         CLEAR_INTR;
1009                         return;
1010                 }
1011                 if (MAJOR(CURRENT->dev) != MAJOR_NR)
1012                         panic(DEVICE_NAME ": request list destroyed"); \
1013                 if (CURRENT->bh) {
1014                         if (!CURRENT->bh->b_lock)
1015                                 panic(DEVICE_NAME ": block not locked");
1016                 }
1017         }
1018         seek = 0;
1019         probing = 0;
1020         device = MINOR(CURRENT_DEVICE);
1021         if (device > 3)
1022                 floppy = (device >> 2) + floppy_type;
1023         else { /* Auto-detection */
1024                 floppy = current_type[device & 3];
1025                 if (!floppy) {
1026                         probing = 1;
1027                         floppy = base_type[device & 3];
1028                         if (!floppy) {
1029                                 request_done(0);
1030                                 goto repeat;
1031                         }
1032                         if (CURRENT_ERRORS & 1)
1033                                 floppy++;
1034                 }
1035         }
1036         if (format_status != FORMAT_BUSY) {
1037                 if (current_drive != CURRENT_DEV) {
1038                         current_track = NO_TRACK;
1039                         current_drive = CURRENT_DEV;
1040                 }
1041                 block = CURRENT->sector;
1042                 if (block+2 > floppy->size) {
1043                         request_done(0);
1044                         goto repeat;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -