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

📄 mcd.c.txt

📁 Linux块设备驱动分析与模拟实现
💻 TXT
📖 第 1 页 / 共 3 页
字号:
821         if (check_region(mcd_port, 4)) {
822           printk("mcd: Init failed, I/O port (%X) already in use\n",
823                  mcd_port);
824           return mem_start;
825         }
826           
827         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
828         read_ahead[MAJOR_NR] = 4;
829 
830         /* check for card */
831 
832         outb(0, MCDPORT(1));                    /* send reset */
833         for (count = 0; count < 1000000; count++)
834                 (void) inb(MCDPORT(1));         /* delay a bit */
835 
836         outb(0x40, MCDPORT(0));                 /* send get-stat cmd */
837         for (count = 0; count < 1000000; count++)
838                 if (!(inb(MCDPORT(1)) & MFL_STATUS))
839                         break;
840 
841         if (count >= 1000000) {
842                 printk("mcd: Init failed. No mcd device at 0x%x irq %d\n",
843                      mcd_port, mcd_irq);
844                 return mem_start;
845         }
846         count = inb(MCDPORT(0));                /* pick up the status */
847         
848         outb(MCMD_GET_VERSION,MCDPORT(0));
849         for(count=0;count<3;count++)
850                 if(getValue(result+count)) {
851                         printk("mcd: mitsumi get version failed at 0x%d\n",
852                                mcd_port);
853                         return mem_start;
854                 }       
855 
856         if (result[0] == result[1] && result[1] == result[2])
857                 return mem_start;
858 
859         printk("mcd: Mitsumi version : %02X %c %x\n",
860                result[0],result[1],result[2]);
861 
862 
863         mcdVersion=result[2];
864 
865         if (mcdVersion >=4)
866                 outb(4,MCDPORT(2));     /* magic happens */
867 
868         /* don't get the IRQ until we know for sure the drive is there */
869 
870         if (irqaction(MCD_INTR_NR,  &mcd_sigaction))
871         {
872                 printk("mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", MCD_INTR_NR);
873                 return mem_start;
874         }
875         snarf_region(mcd_port, 4);
876         mcdPresent = 1;
877         printk("mcd: Mitsumi CD-ROM Drive present at addr %x, irq %d\n",
878                mcd_port, mcd_irq);
879         return mem_start;
880 }
881 
882 
883 static void
884 hsg2msf(long hsg, struct msf *msf)
885 {
886         hsg += 150;
887         msf -> min = hsg / 4500;
888         hsg %= 4500;
889         msf -> sec = hsg / 75;
890         msf -> frame = hsg % 75;
891 
892         bin2bcd(&msf -> min);           /* convert to BCD */
893         bin2bcd(&msf -> sec);
894         bin2bcd(&msf -> frame);
895 }
896 
897 
898 static void
899 bin2bcd(unsigned char *p)
900 {
901         int u, t;
902 
903         u = *p % 10;
904         t = *p / 10;
905         *p = u | (t << 4);
906 }
907 
908 static int
909 bcd2bin(unsigned char bcd)
910 {
911         return (bcd >> 4) * 10 + (bcd & 0xF);
912 }
913 
914 
915 /*
916  * See if a status is ready from the drive and return it
917  * if it is ready.
918  */
919 
920 static int
921 mcdStatus(void)
922 {
923         int i;
924         int st;
925 
926         st = inb(MCDPORT(1)) & MFL_STATUS;
927         if (!st)
928         {
929                 i = inb(MCDPORT(0)) & 0xFF;
930                 return i;
931         }
932         else
933                 return -1;
934 }
935 
936 
937 /*
938  * Send a play or read command to the drive
939  */
940 
941 static void
942 sendMcdCmd(int cmd, struct mcd_Play_msf *params)
943 {
944         outb(cmd, MCDPORT(0));
945         outb(params -> start.min, MCDPORT(0));
946         outb(params -> start.sec, MCDPORT(0));
947         outb(params -> start.frame, MCDPORT(0));
948         outb(params -> end.min, MCDPORT(0));
949         outb(params -> end.sec, MCDPORT(0));
950         outb(params -> end.frame, MCDPORT(0));
951 }
952 
953 
954 /*
955  * Timer interrupt routine to test for status ready from the drive.
956  * (see the next routine)
957  */
958 
959 static void
960 mcdStatTimer(void)
961 {
962         if (!(inb(MCDPORT(1)) & MFL_STATUS))
963         {
964                 wake_up(&mcd_waitq);
965                 return;
966         }
967 
968         McdTimeout--;
969         if (McdTimeout <= 0)
970         {
971                 wake_up(&mcd_waitq);
972                 return;
973         }
974 
975         SET_TIMER(mcdStatTimer, 1);
976 }
977 
978 
979 /*
980  * Wait for a status to be returned from the drive.  The actual test
981  * (see routine above) is done by the timer interrupt to avoid
982  * excessive rescheduling.
983  */
984 
985 static int
986 getMcdStatus(int timeout)
987 {
988         int st;
989 
990         McdTimeout = timeout;
991         SET_TIMER(mcdStatTimer, 1);
992         sleep_on(&mcd_waitq);
993         if (McdTimeout <= 0)
994                 return -1;
995 
996         st = inb(MCDPORT(0)) & 0xFF;
997         if (st == 0xFF)
998                 return -1;
999 
1000         if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)
1001                 /* XXX might be an error? look at q-channel? */
1002                 audioStatus = CDROM_AUDIO_COMPLETED;
1003 
1004         if (st & MST_DSK_CHG)
1005         {
1006                 mcdDiskChanged = 1;
1007                 tocUpToDate = 0;
1008                 audioStatus = CDROM_AUDIO_NO_STATUS;
1009         }
1010 
1011         return st;
1012 }
1013 
1014 
1015 /*
1016  * Read a value from the drive.  Should return quickly, so a busy wait
1017  * is used to avoid excessive rescheduling.
1018  */
1019 
1020 static int
1021 getValue(unsigned char *result)
1022 {
1023         int count;
1024         int s;
1025 
1026         for (count = 0; count < 2000; count++)
1027                 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1028                         break;
1029 
1030         if (count >= 2000)
1031         {
1032                 printk("mcd: getValue timeout\n");
1033                 return -1;
1034         }
1035 
1036         s = inb(MCDPORT(0)) & 0xFF;
1037         *result = (unsigned char) s;
1038         return 0;
1039 }
1040 
1041 
1042 /*
1043  * Read the current Q-channel info.  Also used for reading the
1044  * table of contents.
1045  */
1046 
1047 int
1048 GetQChannelInfo(struct mcd_Toc *qp)
1049 {
1050         unsigned char notUsed;
1051         int retry;
1052 
1053         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1054         {
1055                 outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));
1056                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1057                         break;
1058         }
1059 
1060         if (retry >= MCD_RETRY_ATTEMPTS)
1061                 return -1;
1062 
1063         if (getValue(&qp -> ctrl_addr) < 0) return -1;
1064         if (getValue(&qp -> track) < 0) return -1;
1065         if (getValue(&qp -> pointIndex) < 0) return -1;
1066         if (getValue(&qp -> trackTime.min) < 0) return -1;
1067         if (getValue(&qp -> trackTime.sec) < 0) return -1;
1068         if (getValue(&qp -> trackTime.frame) < 0) return -1;
1069         if (getValue(&notUsed) < 0) return -1;
1070         if (getValue(&qp -> diskTime.min) < 0) return -1;
1071         if (getValue(&qp -> diskTime.sec) < 0) return -1;
1072         if (getValue(&qp -> diskTime.frame) < 0) return -1;
1073 
1074         return 0;
1075 }
1076 
1077 
1078 /*
1079  * Read the table of contents (TOC) and TOC header if neccessary
1080  */
1081 
1082 static int
1083 updateToc()
1084 {
1085         if (tocUpToDate)
1086                 return 0;
1087 
1088         if (GetDiskInfo() < 0)
1089                 return -EIO;
1090 
1091         if (GetToc() < 0)
1092                 return -EIO;
1093 
1094         tocUpToDate = 1;
1095         return 0;
1096 }
1097 
1098 
1099 /*
1100  * Read the table of contents header
1101  */
1102 
1103 static int
1104 GetDiskInfo()
1105 {
1106         int retry;
1107 
1108         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1109         {
1110                 outb(MCMD_GET_DISK_INFO, MCDPORT(0));
1111                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1112                         break;
1113         }
1114 
1115         if (retry >= MCD_RETRY_ATTEMPTS)
1116                 return -1;
1117 
1118         if (getValue(&DiskInfo.first) < 0) return -1;
1119         if (getValue(&DiskInfo.last) < 0) return -1;
1120 
1121         DiskInfo.first = bcd2bin(DiskInfo.first);
1122         DiskInfo.last = bcd2bin(DiskInfo.last);
1123 
1124         if (getValue(&DiskInfo.diskLength.min) < 0) return -1;
1125         if (getValue(&DiskInfo.diskLength.sec) < 0) return -1;
1126         if (getValue(&DiskInfo.diskLength.frame) < 0) return -1;
1127         if (getValue(&DiskInfo.firstTrack.min) < 0) return -1;
1128         if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1;
1129         if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1;
1130 
1131 #ifdef MCD_DEBUG
1132 printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
1133         DiskInfo.first,
1134         DiskInfo.last,
1135         DiskInfo.diskLength.min,
1136         DiskInfo.diskLength.sec,
1137         DiskInfo.diskLength.frame,
1138         DiskInfo.firstTrack.min,
1139         DiskInfo.firstTrack.sec,
1140         DiskInfo.firstTrack.frame);
1141 #endif
1142 
1143         return 0;
1144 }
1145 
1146 
1147 /*
1148  * Read the table of contents (TOC)
1149  */
1150 
1151 static int
1152 GetToc()
1153 {
1154         int i, px;
1155         int limit;
1156         int retry;
1157         struct mcd_Toc qInfo;
1158 
1159         for (i = 0; i < MAX_TRACKS; i++)
1160                 Toc[i].pointIndex = 0;
1161 
1162         i = DiskInfo.last + 3;
1163 
1164         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1165         {
1166                 outb(MCMD_STOP, MCDPORT(0));
1167                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1168                         break;
1169         }
1170 
1171         if (retry >= MCD_RETRY_ATTEMPTS)
1172                 return -1;
1173 
1174         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1175         {
1176                 outb(MCMD_SET_MODE, MCDPORT(0));
1177                 outb(0x05, MCDPORT(0));                 /* mode: toc */
1178                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1179                         break;
1180         }
1181 
1182         if (retry >= MCD_RETRY_ATTEMPTS)
1183                 return -1;
1184 
1185         for (limit = 300; limit > 0; limit--)
1186         {
1187                 if (GetQChannelInfo(&qInfo) < 0)
1188                         break;
1189 
1190                 px = bcd2bin(qInfo.pointIndex);
1191                 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1192                         if (Toc[px].pointIndex == 0)
1193                         {
1194                                 Toc[px] = qInfo;
1195                                 i--;
1196                         }
1197 
1198                 if (i <= 0)
1199                         break;
1200         }
1201 
1202         Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1203 
1204         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1205         {
1206                 outb(MCMD_SET_MODE, MCDPORT(0));
1207                 outb(0x01, MCDPORT(0));
1208                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1209                         break;
1210         }
1211 
1212 #ifdef MCD_DEBUG
1213 for (i = 1; i <= DiskInfo.last; i++)
1214 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X    %02X:%02X.%02X\n",
1215 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1216 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1217 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1218 for (i = 100; i < 103; i++)
1219 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X    %02X:%02X.%02X\n",
1220 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1221 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1222 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1223 #endif
1224 
1225         return limit > 0 ? 0 : -1;
1226 }
1227 
1228 

⌨️ 快捷键说明

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