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

📄 cdu31a.c

📁 还有没有人研究过cdrom 的驱动源码啊
💻 C
📖 第 1 页 / 共 5 页
字号:
			/* 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 intscd_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.msf.second =		    last_sony_subcode.rel_msf[1];		schi->cdsc_reladdr.msf.frame =		    last_sony_subcode.rel_msf[2];	} else if (schi->cdsc_format == CDROM_LBA) {		schi->cdsc_absaddr.lba =		    msf_to_log(last_sony_subcode.abs_msf);		schi->cdsc_reladdr.lba =		    msf_to_log(last_sony_subcode.rel_msf);	}	return 0;}/* Get audio data from the drive.  This is fairly complex because I   am looking for status and data at the same time, but if I get status   then I just look for data.  I need to get the status immediately so   the switch from audio to data tracks will happen quickly. */static voidread_audio_data(char *buffer, unsigned char res_reg[], int *res_size){	unsigned int retry_count;	int result_read;	res_reg[0] = 0;	res_reg[1] = 0;	*res_size = 0;	result_read = 0;	/* Wait for the drive to tell us we have something */	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;      continue_read_audio_wait:	while (time_before(jiffies, retry_count) && !(is_data_ready())	       && !(is_result_ready() || result_read)) {		while (handle_sony_cd_attention());		sony_sleep();	}	if (!(is_data_ready())) {		if (is_result_ready() && !result_read) {			get_result(res_reg, res_size);			/* Read block status and continue waiting for data. */			if ((res_reg[0] & 0xf0) == 0x50) {				result_read = 1;				goto continue_read_audio_wait;			}			/* Invalid data from the drive.  Shut down the operation. */			else if ((res_reg[0] & 0xf0) != 0x20) {				printk				    ("CDU31A: Got result that should have been error: %d\n",				     res_reg[0]);				res_reg[0] = 0x20;				res_reg[1] = SONY_BAD_DATA_ERR;				*res_size = 2;			}			abort_read();		} else {#if DEBUG			printk("CDU31A timeout out %d\n", __LINE__);#endif			res_reg[0] = 0x20;			res_reg[1] = SONY_TIMEOUT_OP_ERR;			*res_size = 2;			abort_read();		}	} else {		clear_data_ready();		/* If data block, then get 2340 bytes offset by 12. */		if (sony_raw_data_mode) {			insb(sony_cd_read_reg, buffer + CD_XA_HEAD,			     CD_FRAMESIZE_RAW1);		} else {			/* Audio gets the whole 2352 bytes. */			insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW);		}		/* If I haven't already gotten the result, get it now. */		if (!result_read) {			/* Wait for the drive to tell us we have something */			retry_count

⌨️ 快捷键说明

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