📄 mcd.c.txt
字号:
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(¬Used) < 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 + -