📄 cdu31a.c.txt
字号:
929 {
930 log = log + LOG_START_OFFSET;
931 msf[0] = int_to_bcd(log / 4500);
932 log = log % 4500;
933 msf[1] = int_to_bcd(log / 75);
934 msf[2] = int_to_bcd(log % 75);
935 }
936
937
938 /*
939 * Convert an MSF format to a logical sector.
940 */
941 static unsigned int
942 msf_to_log(unsigned char *msf)
943 {
944 unsigned int log;
945
946
947 log = bcd_to_int(msf[2]);
948 log += bcd_to_int(msf[1]) * 75;
949 log += bcd_to_int(msf[0]) * 4500;
950 log = log - LOG_START_OFFSET;
951
952 return log;
953 }
954
955
956 /*
957 * Take in integer size value and put it into a buffer like
958 * the drive would want to see a number-of-sector value.
959 */
960 static void
961 size_to_buf(unsigned int size,
962 unsigned char *buf)
963 {
964 buf[0] = size / 65536;
965 size = size % 65536;
966 buf[1] = size / 256;
967 buf[2] = size % 256;
968 }
969
970
971 /*
972 * The OS calls this to perform a read or write operation to the drive.
973 * Write obviously fail. Reads to a read ahead of sony_buffer_size
974 * bytes to help speed operations. This especially helps since the OS
975 * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most
976 * data access on a CD is done sequentially, this saves a lot of operations.
977 */
978 static void
979 do_cdu31a_request(void)
980 {
981 int block;
982 unsigned int dev;
983 int nsect;
984 unsigned char params[10];
985 unsigned char res_reg[2];
986 unsigned int res_size;
987 int copyoff;
988 int spin_up_retry;
989 unsigned int read_size;
990
991
992 if (!sony_spun_up)
993 {
994 scd_open (NULL,NULL);
995 }
996
997 while (1)
998 {
999 cdu31a_request_startover:
1000 /*
1001 * The beginning here is stolen from the hard disk driver. I hope
1002 * its right.
1003 */
1004 if (!(CURRENT) || CURRENT->dev < 0)
1005 {
1006 return;
1007 }
1008
1009 INIT_REQUEST;
1010 dev = MINOR(CURRENT->dev);
1011 block = CURRENT->sector;
1012 nsect = CURRENT->nr_sectors;
1013 if (dev != 0)
1014 {
1015 end_request(0);
1016 goto cdu31a_request_startover;
1017 }
1018
1019 switch(CURRENT->cmd)
1020 {
1021 case READ:
1022 /*
1023 * If the block address is invalid or the request goes beyond the end of
1024 * the media, return an error.
1025 */
1026 if ((block / 4) >= sony_toc->lead_out_start_lba)
1027 {
1028 end_request(0);
1029 goto cdu31a_request_startover;
1030 }
1031 if (((block + nsect) / 4) >= sony_toc->lead_out_start_lba)
1032 {
1033 end_request(0);
1034 goto cdu31a_request_startover;
1035 }
1036
1037 while (nsect > 0)
1038 {
1039 /*
1040 * If the requested sector is not currently in the read-ahead buffer,
1041 * it must be read in.
1042 */
1043 if ((block < sony_first_block) || (block > sony_last_block))
1044 {
1045 sony_first_block = (block / 4) * 4;
1046 log_to_msf(block/4, params);
1047
1048 /*
1049 * If the full read-ahead would go beyond the end of the media, trim
1050 * it back to read just till the end of the media.
1051 */
1052 if (((block / 4) + sony_buffer_sectors) >= sony_toc->lead_out_start_lba)
1053 {
1054 read_size = sony_toc->lead_out_start_lba - (block / 4);
1055 }
1056 else
1057 {
1058 read_size = sony_buffer_sectors;
1059 }
1060 size_to_buf(read_size, ¶ms[3]);
1061
1062 /*
1063 * Read the data. If the drive was not spinning, spin it up and try
1064 * once more. I know, the goto is ugly, but I am too lazy to fix it.
1065 */
1066 spin_up_retry = 0;
1067 try_read_again:
1068 sony_last_block = sony_first_block
1069 + (get_data(sony_buffer,
1070 params,
1071 (read_size * 2048),
1072 res_reg,
1073 &res_size) * 4) - 1;
1074 if ((res_size < 2) || (res_reg[0] != 0))
1075 {
1076 if ((res_reg[1] == SONY_NOT_SPIN_ERR) && (!spin_up_retry))
1077 {
1078 do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1079 spin_up_retry = 1;
1080 goto try_read_again;
1081 }
1082
1083 printk("Sony CDROM Read error: 0x%2.2x\n", res_reg[1]);
1084 sony_first_block = -1;
1085 sony_last_block = -1;
1086 end_request(0);
1087 goto cdu31a_request_startover;
1088 }
1089 }
1090
1091 /*
1092 * The data is in memory now, copy it to the buffer and advance to the
1093 * next block to read.
1094 */
1095 copyoff = (block - sony_first_block) * 512;
1096 memcpy(CURRENT->buffer, sony_buffer+copyoff, 512);
1097
1098 block += 1;
1099 nsect -= 1;
1100 CURRENT->buffer += 512;
1101 }
1102
1103 end_request(1);
1104 break;
1105
1106 case WRITE:
1107 end_request(0);
1108 break;
1109
1110 default:
1111 panic("Unkown SONY CD cmd");
1112 }
1113 }
1114 }
1115
1116
1117 /*
1118 * Read the table of contents from the drive and set sony_toc_read if
1119 * successful.
1120 */
1121 static void
1122 sony_get_toc(void)
1123 {
1124 unsigned int res_size;
1125
1126
1127 if (!sony_toc_read)
1128 {
1129 do_sony_cd_cmd(SONY_REQ_TOC_DATA_CMD,
1130 NULL,
1131 0,
1132 (unsigned char *) sony_toc,
1133 &res_size);
1134 if ((res_size < 2) || ((sony_toc->exec_status[0] & 0x20) == 0x20))
1135 {
1136 return;
1137 }
1138 sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
1139 sony_toc_read = 1;
1140 }
1141 }
1142
1143
1144 /*
1145 * Search for a specific track in the table of contents.
1146 */
1147 static int
1148 find_track(int track)
1149 {
1150 int i;
1151 int num_tracks;
1152
1153
1154 num_tracks = sony_toc->last_track_num + sony_toc->first_track_num + 1;
1155 for (i = 0; i < num_tracks; i++)
1156 {
1157 if (sony_toc->tracks[i].track == track)
1158 {
1159 return i;
1160 }
1161 }
1162
1163 return -1;
1164 }
1165
1166
1167 /*
1168 * Read the subcode and put it int last_sony_subcode for future use.
1169 */
1170 static int
1171 read_subcode(void)
1172 {
1173 unsigned int res_size;
1174
1175
1176 do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,
1177 NULL,
1178 0,
1179 (unsigned char *) last_sony_subcode,
1180 &res_size);
1181 if ((res_size < 2) || ((last_sony_subcode->exec_status[0] & 0x20) == 0x20))
1182 {
1183 printk("Sony CDROM error 0x%2.2x (read_subcode)\n",
1184 last_sony_subcode->exec_status[1]);
1185 return -EIO;
1186 }
1187
1188 return 0;
1189 }
1190
1191
1192 /*
1193 * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If
1194 * the drive is playing, the subchannel needs to be read (since it would be
1195 * changing). If the drive is paused or completed, the subcode information has
1196 * already been stored, just use that. The ioctl call wants things in decimal
1197 * (not BCD), so all the conversions are done.
1198 */
1199 static int
1200 sony_get_subchnl_info(long arg)
1201 {
1202 struct cdrom_subchnl schi;
1203
1204
1205 /* Get attention stuff */
1206 while (handle_sony_cd_attention())
1207 ;
1208
1209 sony_get_toc();
1210 if (!sony_toc_read)
1211 {
1212 return -EIO;
1213 }
1214
1215 verify_area(VERIFY_READ, (char *) arg, sizeof(schi));
1216 verify_area(VERIFY_WRITE, (char *) arg, sizeof(schi));
1217
1218 memcpy_fromfs(&schi, (char *) arg, sizeof(schi));
1219
1220 switch (sony_audio_status)
1221 {
1222 case CDROM_AUDIO_PLAY:
1223 if (read_subcode() < 0)
1224 {
1225 return -EIO;
1226 }
1227 break;
1228
1229 case CDROM_AUDIO_PAUSED:
1230 case CDROM_AUDIO_COMPLETED:
1231 break;
1232
1233 case CDROM_AUDIO_NO_STATUS:
1234 schi.cdsc_audiostatus = sony_audio_status;
1235 memcpy_tofs((char *) arg, &schi, sizeof(schi));
1236 return 0;
1237 break;
1238
1239 case CDROM_AUDIO_INVALID:
1240 case CDROM_AUDIO_ERROR:
1241 default:
1242 return -EIO;
1243 }
1244
1245 schi.cdsc_audiostatus = sony_audio_status;
1246 schi.cdsc_adr = last_sony_subcode->address;
1247 schi.cdsc_ctrl = last_sony_subcode->control;
1248 schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
1249 schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
1250 if (schi.cdsc_format == CDROM_MSF)
1251 {
1252 schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
1253 schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
1254 schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
1255
1256 schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
1257 schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
1258 schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
1259 }
1260 else if (schi.cdsc_format == CDROM_LBA)
1261 {
1262 schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
1263 schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
1264 }
1265
1266 memcpy_tofs((char *) arg, &schi, sizeof(schi));
1267 return 0;
1268 }
1269
1270
1271 /*
1272 * The big ugly ioctl handler.
1273 */
1274 static int
1275 scd_ioctl(struct inode *inode,
1276 struct file *file,
1277 unsigned int cmd,
1278 unsigned long arg)
1279 {
1280 unsigned int dev;
1281 unsigned char res_reg[2];
1282 unsigned int res_size;
1283 unsigned char params[7];
1284 int i;
1285
1286
1287 if (!inode)
1288 {
1289 return -EINVAL;
1290 }
1291 dev = MINOR(inode->i_rdev) >> 6;
1292 if (dev != 0)
1293 {
1294 return -EINVAL;
1295 }
1296
1297 switch (cmd)
1298 {
1299 case CDROMSTART: /* Spin up the drive */
1300 do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1301 if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1302 {
1303 printk("Sony CDROM error 0x%2.2x (CDROMSTART)\n", res_reg[1]);
1304 return -EIO;
1305 }
1306 return 0;
1307 break;
1308
1309 case CDROMSTOP: /* Spin down the drive */
1310 do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
1311
1312 /*
1313 * Spin the drive down, ignoring the error if the disk was
1314 * already not spinning.
1315 */
1316 sony_audio_status = CDROM_AUDIO_NO_STATUS;
1317 do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);
1318 if ( ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1319 && (res_reg[1] != SONY_NOT_SPIN_ERR))
1320 {
1321 printk("Sony CDROM error 0x%2.2x (CDROMSTOP)\n", res_reg[1]);
1322 return -EIO;
1323 }
1324
1325 return 0;
1326 break;
1327
1328 case CDROMPAUSE: /* Pause the drive */
1329 do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);
1330 if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1331 {
1332 printk("Sony CDROM error 0x%2.2x (CDROMPAUSE)\n", res_reg[1]);
1333 return -EIO;
1334 }
1335
1336 /* Get the current position and save it for resuming */
1337 if (read_subcode() < 0)
1338 {
1339 return -EIO;
1340 }
1341 cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
1342 cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
1343 cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
1344 sony_audio_status = CDROM_AUDIO_PAUSED;
1345 return 0;
1346 break;
1347
1348 case CDROMRESUME: /* Start the drive after being paused */
1349 if (sony_audio_status != CDROM_AUDIO_PAUSED)
1350 {
1351 return -EINVAL;
1352 }
1353
1354 do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1355
1356 /* Start the drive at the saved position. */
1357 params[1] = cur_pos_msf[0];
1358 params[2] = cur_pos_msf[1];
1359 params[3] = cur_pos_msf[2];
1360 params[4] = final_pos_msf[0];
1361 params[5] = final_pos_msf[1];
1362 params[6] = final_pos_msf[2];
1363 params[0] = 0x03;
1364 do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);
1365 if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1366 {
1367 printk("Sony CDROM error 0x%2.2x (CDROMRESUME)\n", res_reg[1]);
1368 return -EIO;
1369 }
1370 sony_audio_status = CDROM_AUDIO_PLAY;
1371 return 0;
1372 break;
1373
1374 case CDROMPLAYMSF: /* Play starting at the given MSF address. */
1375 verify_area(VERIFY_READ, (char *) arg, 6);
1376 do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
1377 memcpy_fromfs(&(params[1]), (void *) arg, 6);
1378
1379 /* The parameters are given in int, must be converted */
1380 for (i=1; i<7; i++)
1381 {
1382 params[i] = int_to_bcd(params[i]);
1383 }
1384 params[0] = 0x03;
1385 do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);
1386 if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))
1387 {
1388 printk("Sony CDROM error 0x%2.2x (CDROMPLAYMSF)\n", res_reg[1]);
1389 return -EIO;
1390 }
1391
1392 /* Save the final position for pauses and resumes */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -