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

📄 cdu31a.c

📁 cdrom device drive for linux.
💻 C
📖 第 1 页 / 共 5 页
字号:
				     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 + -