📄 cdu31a.c
字号:
single_toc.dummyb0_2);
if (res_size > 36 && single_toc.pointb2 > 0xaf)
printk
("addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressb2,
single_toc.controlb2,
single_toc.pointb2,
single_toc.tracksb2[0],
single_toc.tracksb2[1],
single_toc.tracksb2[2],
single_toc.tracksb2[3],
single_toc.tracksb2[4],
single_toc.tracksb2[5],
single_toc.tracksb2[6]);
if (res_size > 45 && single_toc.pointb3 > 0xaf)
printk
("addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressb3,
single_toc.controlb3,
single_toc.pointb3,
single_toc.tracksb3[0],
single_toc.tracksb3[1],
single_toc.tracksb3[2],
single_toc.tracksb3[3],
single_toc.tracksb3[4],
single_toc.tracksb3[5],
single_toc.tracksb3[6]);
if (res_size > 54 && single_toc.pointb4 > 0xaf)
printk
("addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressb4,
single_toc.controlb4,
single_toc.pointb4,
single_toc.tracksb4[0],
single_toc.tracksb4[1],
single_toc.tracksb4[2],
single_toc.tracksb4[3],
single_toc.tracksb4[4],
single_toc.tracksb4[5],
single_toc.tracksb4[6]);
if (res_size > 63 && single_toc.pointc0 > 0xaf)
printk
("addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressc0,
single_toc.controlc0,
single_toc.pointc0,
single_toc.dummyc0[0],
single_toc.dummyc0[1],
single_toc.dummyc0[2],
single_toc.dummyc0[3],
single_toc.dummyc0[4],
single_toc.dummyc0[5],
single_toc.dummyc0[6]);
#endif
#undef DEBUG
#define DEBUG 0
sony_toc.lead_out_start_msf[0] =
bcd_to_int(single_toc.lead_out_start_msf[0]);
sony_toc.lead_out_start_msf[1] =
bcd_to_int(single_toc.lead_out_start_msf[1]);
sony_toc.lead_out_start_msf[2] =
bcd_to_int(single_toc.lead_out_start_msf[2]);
sony_toc.lead_out_start_lba =
single_toc.lead_out_start_lba =
msf_to_log(sony_toc.lead_out_start_msf);
/* For points that do not exist, move the data over them
to the right location. */
if (single_toc.pointb0 != 0xb0) {
memmove(((char *) &single_toc) + 27,
((char *) &single_toc) + 18,
res_size - 18);
res_size += 9;
} else if (res_size > 18) {
sony_toc.lead_out_start_msf[0] =
bcd_to_int(single_toc.
max_start_outer_leadout_msf
[0]);
sony_toc.lead_out_start_msf[1] =
bcd_to_int(single_toc.
max_start_outer_leadout_msf
[1]);
sony_toc.lead_out_start_msf[2] =
bcd_to_int(single_toc.
max_start_outer_leadout_msf
[2]);
sony_toc.lead_out_start_lba =
msf_to_log(sony_toc.
lead_out_start_msf);
}
if (single_toc.pointb1 != 0xb1) {
memmove(((char *) &single_toc) + 36,
((char *) &single_toc) + 27,
res_size - 27);
res_size += 9;
}
if (single_toc.pointb2 != 0xb2) {
memmove(((char *) &single_toc) + 45,
((char *) &single_toc) + 36,
res_size - 36);
res_size += 9;
}
if (single_toc.pointb3 != 0xb3) {
memmove(((char *) &single_toc) + 54,
((char *) &single_toc) + 45,
res_size - 45);
res_size += 9;
}
if (single_toc.pointb4 != 0xb4) {
memmove(((char *) &single_toc) + 63,
((char *) &single_toc) + 54,
res_size - 54);
res_size += 9;
}
if (single_toc.pointc0 != 0xc0) {
memmove(((char *) &single_toc) + 72,
((char *) &single_toc) + 63,
res_size - 63);
res_size += 9;
}
#if DEBUG
printk
("start track lba %u, leadout start lba %u\n",
single_toc.start_track_lba,
single_toc.lead_out_start_lba);
{
int i;
for (i = 0;
i <
1 +
bcd_to_int(single_toc.last_track_num)
-
bcd_to_int(single_toc.
first_track_num); i++) {
printk
("trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n",
i,
single_toc.tracks[i].address,
single_toc.tracks[i].control,
bcd_to_int(single_toc.
tracks[i].track),
bcd_to_int(single_toc.
tracks[i].
track_start_msf
[0]),
bcd_to_int(single_toc.
tracks[i].
track_start_msf
[1]),
bcd_to_int(single_toc.
tracks[i].
track_start_msf
[2]));
if (mint >
bcd_to_int(single_toc.
tracks[i].track))
mint =
bcd_to_int(single_toc.
tracks[i].
track);
if (maxt <
bcd_to_int(single_toc.
tracks[i].track))
maxt =
bcd_to_int(single_toc.
tracks[i].
track);
}
printk
("min track number %d, max track number %d\n",
mint, maxt);
}
#endif
/* prepare a special table of contents for a CD-I disc. They don't have one. */
if (single_toc.disk_type == 0x10 &&
single_toc.first_track_num == 2 &&
single_toc.last_track_num == 2 /* CD-I */ ) {
sony_toc.tracks[totaltracks].address = 1;
sony_toc.tracks[totaltracks].control = 4; /* force data tracks */
sony_toc.tracks[totaltracks].track = 1;
sony_toc.tracks[totaltracks].
track_start_msf[0] = 0;
sony_toc.tracks[totaltracks].
track_start_msf[1] = 2;
sony_toc.tracks[totaltracks].
track_start_msf[2] = 0;
mint = maxt = 1;
totaltracks++;
} else
/* gather track entries from this session */
{
int i;
for (i = 0;
i <
1 +
bcd_to_int(single_toc.last_track_num)
-
bcd_to_int(single_toc.
first_track_num);
i++, totaltracks++) {
sony_toc.tracks[totaltracks].
address =
single_toc.tracks[i].address;
sony_toc.tracks[totaltracks].
control =
single_toc.tracks[i].control;
sony_toc.tracks[totaltracks].
track =
bcd_to_int(single_toc.
tracks[i].track);
sony_toc.tracks[totaltracks].
track_start_msf[0] =
bcd_to_int(single_toc.
tracks[i].
track_start_msf[0]);
sony_toc.tracks[totaltracks].
track_start_msf[1] =
bcd_to_int(single_toc.
tracks[i].
track_start_msf[1]);
sony_toc.tracks[totaltracks].
track_start_msf[2] =
bcd_to_int(single_toc.
tracks[i].
track_start_msf[2]);
if (i == 0)
single_toc.
start_track_lba =
msf_to_log(sony_toc.
tracks
[totaltracks].
track_start_msf);
if (mint >
sony_toc.tracks[totaltracks].
track)
mint =
sony_toc.
tracks[totaltracks].
track;
if (maxt <
sony_toc.tracks[totaltracks].
track)
maxt =
sony_toc.
tracks[totaltracks].
track;
}
}
sony_toc.first_track_num = mint;
sony_toc.last_track_num = maxt;
/* Disk type of last session wins. For example:
CD-Extra has disk type 0 for the first session, so
a dumb HiFi CD player thinks it is a plain audio CD.
We are interested in the disk type of the last session,
which is 0x20 (XA) for CD-Extra, so we can access the
data track ... */
sony_toc.disk_type = single_toc.disk_type;
sony_toc.sessions = session;
/* don't believe everything :-) */
if (session == 1)
single_toc.start_track_lba = 0;
sony_toc.start_track_lba =
single_toc.start_track_lba;
if (session > 1 && single_toc.pointb0 == 0xb0 &&
sony_toc.lead_out_start_lba ==
single_toc.lead_out_start_lba) {
break;
}
/* Let's not get carried away... */
if (session > 40) {
printk("cdu31a: too many sessions: %d\n",
session);
break;
}
session++;
}
sony_toc.track_entries = totaltracks;
/* add one entry for the LAST track with track number CDROM_LEADOUT */
sony_toc.tracks[totaltracks].address = single_toc.address2;
sony_toc.tracks[totaltracks].control = single_toc.control2;
sony_toc.tracks[totaltracks].track = CDROM_LEADOUT;
sony_toc.tracks[totaltracks].track_start_msf[0] =
sony_toc.lead_out_start_msf[0];
sony_toc.tracks[totaltracks].track_start_msf[1] =
sony_toc.lead_out_start_msf[1];
sony_toc.tracks[totaltracks].track_start_msf[2] =
sony_toc.lead_out_start_msf[2];
sony_toc_read = 1;
#undef DEBUG
#if DEBUG
printk
("Disk session %d, start track: %d, stop track: %d\n",
session, single_toc.start_track_lba,
single_toc.lead_out_start_lba);
#endif
}
#if DEBUG
printk("Leaving sony_get_toc\n");
#endif
}
/*
* Uniform cdrom interface function
* return multisession offset and sector information
*/
static int scd_get_last_session(struct cdrom_device_info *cdi,
struct cdrom_multisession *ms_info)
{
if (ms_info == NULL)
return 1;
if (!sony_toc_read)
sony_get_toc();
ms_info->addr_format = CDROM_LBA;
ms_info->addr.lba = sony_toc.start_track_lba;
ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE ||
sony_toc.disk_type == 0x10 /* CDI */ ;
return 0;
}
/*
* Search for a specific track in the table of contents.
*/
static int find_track(int track)
{
int i;
for (i = 0; i <= sony_toc.track_entries; i++) {
if (sony_toc.tracks[i].track == track) {
return i;
}
}
return -1;
}
/*
* Read the subcode and put it in last_sony_subcode for future use.
*/
static int read_subcode(void)
{
unsigned int res_size;
do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,
NULL,
0, (unsigned char *) &last_sony_subcode, &res_size);
if ((res_size < 2)
|| ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) {
printk("Sony CDROM error %s (read_subcode)\n",
translate_error(last_sony_subcode.exec_status[1]));
return -EIO;
}
last_sony_subcode.track_num =
bcd_to_int(last_sony_subcode.track_num);
last_sony_subcode.index_num =
bcd_to_int(last_sony_subcode.index_num);
last_sony_subcode.abs_msf[0] =
bcd_to_int(last_sony_subcode.abs_msf[0]);
last_sony_subcode.abs_msf[1] =
bcd_to_int(last_sony_subcode.abs_msf[1]);
last_sony_subcode.abs_msf[2] =
bcd_to_int(last_sony_subcode.abs_msf[2]);
last_sony_subcode.rel_msf[0] =
bcd_to_int(last_sony_subcode.rel_msf[0]);
last_sony_subcode.rel_msf[1] =
bcd_to_int(last_sony_subcode.rel_msf[1]);
last_sony_subcode.rel_msf[2] =
bcd_to_int(last_sony_subcode.rel_msf[2]);
return 0;
}
/*
* Uniform cdrom interface function
* return the media catalog number found on some older audio cds
*/
static int
scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
{
unsigned char resbuffer[2 + 14];
unsigned char *mcnp = mcn->medium_catalog_number;
unsigned char *resp = resbuffer + 3;
unsigned int res_size;
memset(mcn->medium_catalog_number, 0, 14);
do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
NULL, 0, resbuffer, &res_size);
if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20));
else {
/* packed bcd to single ASCII digits */
*mcnp++ = (*resp >> 4) + '0';
*mcnp++ = (*resp++ & 0x0f) + '0';
*mcnp++ = (*resp >> 4) + '0';
*mcnp++ = (*resp++ & 0x0f) + '0';
*mcnp++ = (*resp >> 4) + '0';
*mcnp++ = (*resp++ & 0x0f) + '0';
*mcnp++ = (*resp >> 4) + '0';
*mcnp++ = (*resp++ & 0x0f) + '0';
*mcnp++ = (*resp >> 4) + '0';
*mcnp++ = (*resp++ & 0x0f) + '0';
*mcnp++ = (*resp >> 4) + '0';
*mcnp++ = (*resp++ & 0x0f) + '0';
*mcnp++ = (*resp >> 4) + '0';
}
*mcnp = '\0';
return 0;
}
/*
* Get the subchannel info like the CDROMSUBCHNL command wants to see it. If
* the drive is playing, the subchannel needs to be read (since it would be
* changing). If the drive is paused or completed, the subcode information has
* already been stored, just use that. The ioctl call wants things in decimal
* (not BCD), so all the conversions are done.
*/
static int sony_get_subchnl_info(struct cdrom_subchnl *schi)
{
/* Get attention stuff */
while (handle_sony_cd_attention());
sony_get_toc();
if (!sony_toc_read) {
return -EIO;
}
switch (sony_audio_status) {
case CDROM_AUDIO_NO_STATUS:
case CDROM_AUDIO_PLAY:
if (read_subcode() < 0) {
return -EIO;
}
break;
case CDROM_AUDIO_PAUSED:
case CDROM_AUDIO_COMPLETED:
break;
#if 0
case CDROM_AUDIO_NO_STATUS:
schi->cdsc_audiostatus = sony_audio_status;
return 0;
break;
#endif
case CDROM_AUDIO_INVALID:
case CDROM_AUDIO_ERROR:
default:
return -EIO;
}
schi->cdsc_audiostatus = sony_audio_status;
schi->cdsc_adr = last_sony_subcode.address;
schi->cdsc_ctrl = last_sony_subcode.control;
schi->cdsc_trk = last_sony_subcode.track_num;
schi->cdsc_ind = last_sony_subcode.index_num;
if (schi->cdsc_format == CDROM_MSF) {
schi->cdsc_absaddr.msf.minute =
last_sony_subcode.abs_msf[0];
schi->cdsc_absaddr.msf.second =
last_sony_subcode.abs_msf[1];
schi->cdsc_absaddr.msf.frame =
last_sony_subcode.abs_msf[2];
schi->cdsc_reladdr.msf.minute =
last_sony_subcode.rel_msf[0];
schi->cdsc_reladdr.ms
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -