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

📄 sonycd535.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
					 * spin it up and try some more.					 */					for (spin_up_retry=0 ;; ++spin_up_retry) {						/* This loop has been modified to support the Sony						 * CDU-510/515 series, thanks to Claudio Porfiri 						 * <C.Porfiri@nisms.tei.ericsson.se>.						 */						/*						 * This part is to deal with very slow hardware.  We						 * try at most MAX_SPINUP_RETRY times to read the same						 * block.  A check for seek_and_read_N_blocks' result is						 * performed; if the result is wrong, the CDROM's engine						 * is restarted and the operation is tried again.						 */						/*						 * 1995-06-01: The system got problems when downloading						 * from Slackware CDROM, the problem seems to be:						 * seek_and_read_N_blocks returns BAD_STATUS and we						 * should wait for a while before retrying, so a new						 * part was added to discriminate the return value from						 * seek_and_read_N_blocks for the various cases.						 */						int readStatus = seek_and_read_N_blocks(params, read_size,									status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));						if (0 <= readStatus)	/* Good data; common case, placed first */							break;						if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {							/* give up */							if (readStatus == NO_ROOM)								printk(CDU535_MESSAGE_NAME " No room to read from CD\n");							else								printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",										status[0]);							sony_first_block = -1;							sony_last_block = -1;							end_request(0);							return;						}						if (readStatus == BAD_STATUS) {							/* Sleep for a while, then retry */							current->state = TASK_INTERRUPTIBLE;							schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);						}#if DEBUG > 0						printk(CDU535_MESSAGE_NAME							" debug: calling spin up when reading data!\n");#endif						cmd[0] = SONY535_SPIN_UP;						do_sony_cmd(cmd, 1, status, NULL, 0, 0);					}				}				/*				 * The data is in memory now, copy it to the buffer and advance to the				 * next block to read.				 */				copyoff = block - sony_first_block;				memcpy(CURRENT->buffer,					   sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);				block += 1;				nsect -= 1;				CURRENT->buffer += 512;			}			end_request(1);			break;		case WRITE:			end_request(0);			break;		default:			panic("Unknown SONY CD cmd");		}	}}/* * Read the table of contents from the drive and set sony_toc_read if * successful. */static voidsony_get_toc(void){	Byte status[2];	if (!sony_toc_read) {		/* do not call check_drive_status() from here since it can call this routine */		if (request_toc_data(status, sony_toc) < 0)			return;		sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);		sony_toc_read = 1;	}}/* * Search for a specific track in the table of contents.  track is * passed in bcd format */static intfind_track(int track){	int i;	int num_tracks;	num_tracks = bcd_to_int(sony_toc->last_track_num) -		bcd_to_int(sony_toc->first_track_num) + 1;	for (i = 0; i < num_tracks; i++) {		if (sony_toc->tracks[i].track == track) {			return i;		}	}	return -1;}/* * Read the subcode and put it int last_sony_subcode for future use. */static intread_subcode(void){	Byte cmd = SONY535_REQUEST_SUB_Q_DATA;	Byte status[2];	int  dsc_status;	if (check_drive_status() != 0)		return -EIO;	if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,							   sizeof(struct s535_sony_subcode), 1)) != 0) {		printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",				status[0], dsc_status);		return -EIO;	}	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 intsony_get_subchnl_info(long arg){	struct cdrom_subchnl schi;	int err;	/* Get attention stuff */	if (check_drive_status() != 0)		return -EIO;	sony_get_toc();	if (!sony_toc_read) {		return -EIO;	}	err = verify_area(VERIFY_WRITE /* and read */ , (char *)arg, sizeof schi);	if (err)		return err;	copy_from_user(&schi, (char *)arg, sizeof schi);	switch (sony_audio_status) {	case CDROM_AUDIO_PLAY:		if (read_subcode() < 0) {			return -EIO;		}		break;	case CDROM_AUDIO_PAUSED:	case CDROM_AUDIO_COMPLETED:		break;	case CDROM_AUDIO_NO_STATUS:		schi.cdsc_audiostatus = sony_audio_status;		copy_to_user((char *)arg, &schi, sizeof schi);		return 0;		break;	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 = bcd_to_int(last_sony_subcode->track_num);	schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);	if (schi.cdsc_format == CDROM_MSF) {		schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);		schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);		schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);		schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);		schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);		schi.cdsc_reladdr.msf.frame = bcd_to_int(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);	}	copy_to_user((char *)arg, &schi, sizeof schi);	return 0;}/* * The big ugly ioctl handler. */static intcdu_ioctl(struct inode *inode,		  struct file *file,		  unsigned int cmd,		  unsigned long arg){	unsigned int dev;	Byte status[2];	Byte cmd_buff[10], params[10];	int  i;	int  dsc_status;	int  err;	if (!inode) {		return -EINVAL;	}	dev = MINOR(inode->i_rdev) >> 6;	if (dev != 0) {		return -EINVAL;	}	if (check_drive_status() != 0)		return -EIO;	switch (cmd) {	case CDROMSTART:			/* Spin up the drive */		if (spin_up_drive(status) < 0) {			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",					status[0]);			return -EIO;		}		return 0;		break;	case CDROMSTOP:			/* Spin down the drive */		cmd_buff[0] = SONY535_HOLD;		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);		/*		 * Spin the drive down, ignoring the error if the disk was		 * already not spinning.		 */		sony_audio_status = CDROM_AUDIO_NO_STATUS;		cmd_buff[0] = SONY535_SPIN_DOWN;		dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);		if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||			((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",					status[0]);			return -EIO;		}		return 0;		break;	case CDROMPAUSE:			/* Pause the drive */		cmd_buff[0] = SONY535_HOLD;		/* CDU-31 driver uses AUDIO_STOP, not pause */		if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",					status[0]);			return -EIO;		}		/* Get the current position and save it for resuming */		if (read_subcode() < 0) {			return -EIO;		}		cur_pos_msf[0] = last_sony_subcode->abs_msf[0];		cur_pos_msf[1] = last_sony_subcode->abs_msf[1];		cur_pos_msf[2] = last_sony_subcode->abs_msf[2];		sony_audio_status = CDROM_AUDIO_PAUSED;		return 0;		break;	case CDROMRESUME:			/* Start the drive after being paused */		set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);		if (sony_audio_status != CDROM_AUDIO_PAUSED) {			return -EINVAL;		}		spin_up_drive(status);		/* Start the drive at the saved position. */		cmd_buff[0] = SONY535_PLAY_AUDIO;		cmd_buff[1] = 0;		/* play back starting at this address */		cmd_buff[2] = cur_pos_msf[0];		cmd_buff[3] = cur_pos_msf[1];		cmd_buff[4] = cur_pos_msf[2];		cmd_buff[5] = SONY535_PLAY_AUDIO;		cmd_buff[6] = 2;		/* set ending address */		cmd_buff[7] = final_pos_msf[0];		cmd_buff[8] = final_pos_msf[1];		cmd_buff[9] = final_pos_msf[2];		if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||			(do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",					status[0]);			return -EIO;		}		sony_audio_status = CDROM_AUDIO_PLAY;		return 0;		break;	case CDROMPLAYMSF:			/* Play starting at the given MSF address. */		err = verify_area(VERIFY_READ, (char *)arg, 6);		if (err)			return err;		spin_up_drive(status);		set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);		copy_from_user(params, (void *)arg, 6);		/* The parameters are given in int, must be converted */		for (i = 0; i < 3; i++) {			cmd_buff[2 + i] = int_to_bcd(params[i]);			cmd_buff[7 + i] = int_to_bcd(params[i + 3]);		}		cmd_buff[0] = SONY535_PLAY_AUDIO;		cmd_buff[1] = 0;		/* play back starting at this address */		/* cmd_buff[2-4] are filled in for loop above */		cmd_buff[5] = SONY535_PLAY_AUDIO;		cmd_buff[6] = 2;		/* set ending address */		/* cmd_buff[7-9] are filled in for loop above */		if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||			(do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",					status[0]);			return -EIO;		}		/* Save the final position for pauses and resumes */		final_pos_msf[0] = cmd_buff[7];		final_pos_msf[1] = cmd_buff[8];		final_pos_msf[2] = cmd_buff[9];		sony_audio_status = CDROM_AUDIO_PLAY;		return 0;		break;	case CDROMREADTOCHDR:		/* Read the table of contents header */		{			struct cdrom_tochdr *hdr;			struct cdrom_tochdr loc_hdr;			sony_get_toc();			if (!sony_toc_read)				return -EIO;			hdr = (struct cdrom_tochdr *)arg;			err = verify_area(VERIFY_WRITE, hdr, sizeof *hdr);			if (err)				return err;			loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);			loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);			copy_to_user(hdr, &loc_hdr, sizeof *hdr);		}		return 0;		break;	case CDROMREADTOCENTRY:	/* Read a given table of contents entry */		{			struct cdrom_tocentry *entry;			struct cdrom_tocentry loc_entry;			int  track_idx;			Byte *msf_val = NULL;			sony_get_toc();			if (!sony_toc_read) {				return -EIO;			}			entry = (struct cdrom_tocentry *)arg;			err = verify_area(VERIFY_WRITE /* and read */ , entry, sizeof *entry);			if (err)				return err;			copy_from_user(&loc_entry, entry, sizeof loc_entry);			/* Lead out is handled separately since it is special. */			if (loc_entry.cdte_track == CDROM_LEADOUT) {				loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ;				loc_entry.cdte_ctrl = sony_toc->control2;				msf_val = sony_toc->lead_out_start_msf;			} else {				track_idx = find_track(int_to_bcd(loc_entry.cdte_track));				if (track_idx < 0)					return -EINVAL;				loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ;				loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;				msf_val = sony_toc->tracks[track_idx].track_start_msf;			}			/* Logical buffer address or MSF format requested? */			if (loc_entry.cdte_format == CDROM_LBA) {				loc_entry.cdte_addr.lba = msf_to_log(msf_val);			} else if (loc_entry.cdte_format == CDROM_MSF) {				loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);				loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));				loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));			}			copy_to_user(entry, &loc_entry, sizeof *entry);		}		return 0;		break;	case CDROMPLAYTRKIND:		/* Play a track.  This currently ignores index. */		{			struct cdrom_ti ti;			int track_idx;			sony_get_toc();			if (!sony_toc_read)				return -EIO;			err = verify_area(VERIFY_READ, (char *)arg, sizeof ti);			if (err)				return err;			copy_from_user(&ti, (char *)arg, sizeof ti);			if ((ti.cdti_trk0 < sony_toc->first_track_num)				|| (sony_toc->last_track_num < ti.cdti_trk0)

⌨️ 快捷键说明

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