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

📄 sjcd.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
#if defined( SJCD_TRACE )	printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min,	       sjcd_disk_length.sec, sjcd_disk_length.frame);#endif	return (0);}/* * Load subchannel information. */static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp){	int s;#if defined( SJCD_TRACE )	printk("SJCD: load sub q\n");#endif	sjcd_send_cmd(SCMD_GET_QINFO);	s = sjcd_receive_status();	if (s < 0 || sjcd_command_failed || !sjcd_status_valid) {		sjcd_send_cmd(0xF2);		s = sjcd_receive_status();		if (s < 0 || sjcd_command_failed || !sjcd_status_valid)			return (-1);		sjcd_send_cmd(SCMD_GET_QINFO);		s = sjcd_receive_status();		if (s < 0 || sjcd_command_failed || !sjcd_status_valid)			return (-1);	}	if (sjcd_media_is_available)		if (sjcd_load_response(qp, sizeof(*qp)) == 0)			return (0);	return (-1);}/* * Start playing from the specified position. */static int sjcd_play(struct sjcd_play_msf *mp){	struct sjcd_play_msf msf;	/*	 * Turn the device to play mode.	 */	sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY);	if (sjcd_receive_status() < 0)		return (-1);	/*	 * Seek to the starting point.	 */	msf.start = mp->start;	msf.end.min = msf.end.sec = msf.end.frame = 0x00;	sjcd_send_6_cmd(SCMD_SEEK, &msf);	if (sjcd_receive_status() < 0)		return (-1);	/*	 * Start playing.	 */	sjcd_send_6_cmd(SCMD_PLAY, mp);	return (sjcd_receive_status());}/* * Tray control functions. */static int sjcd_tray_close(void){#if defined( SJCD_TRACE )	printk("SJCD: tray_close\n");#endif	sjcd_send_cmd(SCMD_CLOSE_TRAY);	return (sjcd_receive_status());}static int sjcd_tray_lock(void){#if defined( SJCD_TRACE )	printk("SJCD: tray_lock\n");#endif	sjcd_send_cmd(SCMD_LOCK_TRAY);	return (sjcd_receive_status());}static int sjcd_tray_unlock(void){#if defined( SJCD_TRACE )	printk("SJCD: tray_unlock\n");#endif	sjcd_send_cmd(SCMD_UNLOCK_TRAY);	return (sjcd_receive_status());}static int sjcd_tray_open(void){#if defined( SJCD_TRACE )	printk("SJCD: tray_open\n");#endif	sjcd_send_cmd(SCMD_EJECT_TRAY);	return (sjcd_receive_status());}/* * Do some user commands. */static int sjcd_ioctl(struct inode *ip, struct file *fp,		      unsigned int cmd, unsigned long arg){#if defined( SJCD_TRACE )	printk("SJCD:ioctl\n");#endif	if (ip == NULL)		return (-EINVAL);	sjcd_get_status();	if (!sjcd_status_valid)		return (-EIO);	if (sjcd_update_toc() < 0)		return (-EIO);	switch (cmd) {	case CDROMSTART:{#if defined( SJCD_TRACE )			printk("SJCD: ioctl: start\n");#endif			return (0);		}	case CDROMSTOP:{#if defined( SJCD_TRACE )			printk("SJCD: ioctl: stop\n");#endif			sjcd_send_cmd(SCMD_PAUSE);			(void) sjcd_receive_status();			sjcd_audio_status = CDROM_AUDIO_NO_STATUS;			return (0);		}	case CDROMPAUSE:{			struct sjcd_hw_qinfo q_info;#if defined( SJCD_TRACE )			printk("SJCD: ioctl: pause\n");#endif			if (sjcd_audio_status == CDROM_AUDIO_PLAY) {				sjcd_send_cmd(SCMD_PAUSE);				(void) sjcd_receive_status();				if (sjcd_get_q_info(&q_info) < 0) {					sjcd_audio_status =					    CDROM_AUDIO_NO_STATUS;				} else {					sjcd_audio_status =					    CDROM_AUDIO_PAUSED;					sjcd_playing.start = q_info.abs;				}				return (0);			} else				return (-EINVAL);		}	case CDROMRESUME:{#if defined( SJCD_TRACE )			printk("SJCD: ioctl: resume\n");#endif			if (sjcd_audio_status == CDROM_AUDIO_PAUSED) {				/*				 * continue play starting at saved location				 */				if (sjcd_play(&sjcd_playing) < 0) {					sjcd_audio_status =					    CDROM_AUDIO_ERROR;					return (-EIO);				} else {					sjcd_audio_status =					    CDROM_AUDIO_PLAY;					return (0);				}			} else				return (-EINVAL);		}	case CDROMPLAYTRKIND:{			struct cdrom_ti ti;			int s;#if defined( SJCD_TRACE )			printk("SJCD: ioctl: playtrkind\n");#endif			if ((s =			     verify_area(VERIFY_READ, (void *) arg,					 sizeof(ti))) == 0) {				copy_from_user(&ti, (void *) arg,					       sizeof(ti));				if (ti.cdti_trk0 < sjcd_first_track_no)					return (-EINVAL);				if (ti.cdti_trk1 > sjcd_last_track_no)					ti.cdti_trk1 = sjcd_last_track_no;				if (ti.cdti_trk0 > ti.cdti_trk1)					return (-EINVAL);				sjcd_playing.start =				    sjcd_table_of_contents[ti.cdti_trk0].				    un.track_msf;				sjcd_playing.end =				    (ti.cdti_trk1 <				     sjcd_last_track_no) ?				    sjcd_table_of_contents[ti.cdti_trk1 +							   1].un.				    track_msf : sjcd_table_of_contents[0].				    un.track_msf;				if (sjcd_play(&sjcd_playing) < 0) {					sjcd_audio_status =					    CDROM_AUDIO_ERROR;					return (-EIO);				} else					sjcd_audio_status =					    CDROM_AUDIO_PLAY;			}			return (s);		}	case CDROMPLAYMSF:{			struct cdrom_msf sjcd_msf;			int s;#if defined( SJCD_TRACE )			printk("SJCD: ioctl: playmsf\n");#endif			if ((s =			     verify_area(VERIFY_READ, (void *) arg,					 sizeof(sjcd_msf))) == 0) {				if (sjcd_audio_status == CDROM_AUDIO_PLAY) {					sjcd_send_cmd(SCMD_PAUSE);					(void) sjcd_receive_status();					sjcd_audio_status =					    CDROM_AUDIO_NO_STATUS;				}				copy_from_user(&sjcd_msf, (void *) arg,					       sizeof(sjcd_msf));				sjcd_playing.start.min =				    bin2bcd(sjcd_msf.cdmsf_min0);				sjcd_playing.start.sec =				    bin2bcd(sjcd_msf.cdmsf_sec0);				sjcd_playing.start.frame =				    bin2bcd(sjcd_msf.cdmsf_frame0);				sjcd_playing.end.min =				    bin2bcd(sjcd_msf.cdmsf_min1);				sjcd_playing.end.sec =				    bin2bcd(sjcd_msf.cdmsf_sec1);				sjcd_playing.end.frame =				    bin2bcd(sjcd_msf.cdmsf_frame1);				if (sjcd_play(&sjcd_playing) < 0) {					sjcd_audio_status =					    CDROM_AUDIO_ERROR;					return (-EIO);				} else					sjcd_audio_status =					    CDROM_AUDIO_PLAY;			}			return (s);		}	case CDROMREADTOCHDR:{			struct cdrom_tochdr toc_header;			int s;#if defined (SJCD_TRACE )			printk("SJCD: ioctl: readtocheader\n");#endif			if ((s =			     verify_area(VERIFY_WRITE, (void *) arg,					 sizeof(toc_header))) == 0) {				toc_header.cdth_trk0 = sjcd_first_track_no;				toc_header.cdth_trk1 = sjcd_last_track_no;				copy_to_user((void *) arg, &toc_header,					     sizeof(toc_header));			}			return (s);		}	case CDROMREADTOCENTRY:{			struct cdrom_tocentry toc_entry;			int s;#if defined( SJCD_TRACE )			printk("SJCD: ioctl: readtocentry\n");#endif			if ((s =			     verify_area(VERIFY_WRITE, (void *) arg,					 sizeof(toc_entry))) == 0) {				struct sjcd_hw_disk_info *tp;				copy_from_user(&toc_entry, (void *) arg,					       sizeof(toc_entry));				if (toc_entry.cdte_track == CDROM_LEADOUT)					tp = &sjcd_table_of_contents[0];				else if (toc_entry.cdte_track <					 sjcd_first_track_no)					return (-EINVAL);				else if (toc_entry.cdte_track >					 sjcd_last_track_no)					return (-EINVAL);				else					tp = &sjcd_table_of_contents					    [toc_entry.cdte_track];				toc_entry.cdte_adr =				    tp->track_control & 0x0F;				toc_entry.cdte_ctrl =				    tp->track_control >> 4;				switch (toc_entry.cdte_format) {				case CDROM_LBA:					toc_entry.cdte_addr.lba =					    msf2hsg(&(tp->un.track_msf));					break;				case CDROM_MSF:					toc_entry.cdte_addr.msf.minute =					    bcd2bin(tp->un.track_msf.min);					toc_entry.cdte_addr.msf.second =					    bcd2bin(tp->un.track_msf.sec);					toc_entry.cdte_addr.msf.frame =					    bcd2bin(tp->un.track_msf.						    frame);					break;				default:					return (-EINVAL);				}				copy_to_user((void *) arg, &toc_entry,					     sizeof(toc_entry));			}			return (s);		}	case CDROMSUBCHNL:{			struct cdrom_subchnl subchnl;			int s;#if defined( SJCD_TRACE )			printk("SJCD: ioctl: subchnl\n");#endif			if ((s =			     verify_area(VERIFY_WRITE, (void *) arg,					 sizeof(subchnl))) == 0) {				struct sjcd_hw_qinfo q_info;				copy_from_user(&subchnl, (void *) arg,					       sizeof(subchnl));				if (sjcd_get_q_info(&q_info) < 0)					return (-EIO);				subchnl.cdsc_audiostatus =				    sjcd_audio_status;				subchnl.cdsc_adr =				    q_info.track_control & 0x0F;				subchnl.cdsc_ctrl =				    q_info.track_control >> 4;				subchnl.cdsc_trk =				    bcd2bin(q_info.track_no);				subchnl.cdsc_ind = bcd2bin(q_info.x);				switch (subchnl.cdsc_format) {				case CDROM_LBA:					subchnl.cdsc_absaddr.lba =					    msf2hsg(&(q_info.abs));					subchnl.cdsc_reladdr.lba =					    msf2hsg(&(q_info.rel));					break;				case CDROM_MSF:					subchnl.cdsc_absaddr.msf.minute =					    bcd2bin(q_info.abs.min);					subchnl.cdsc_absaddr.msf.second =					    bcd2bin(q_info.abs.sec);					subchnl.cdsc_absaddr.msf.frame =					    bcd2bin(q_info.abs.frame);					subchnl.cdsc_reladdr.msf.minute =					    bcd2bin(q_info.rel.min);					subchnl.cdsc_reladdr.msf.second =					    bcd2bin(q_info.rel.sec);					subchnl.cdsc_reladdr.msf.frame =					    bcd2bin(q_info.rel.frame);					break;				default:					return (-EINVAL);				}				copy_to_user((void *) arg, &subchnl,					     sizeof(subchnl));			}			return (s);		}	case CDROMVOLCTRL:{			struct cdrom_volctrl vol_ctrl;			int s;#if defined( SJCD_TRACE )			printk("SJCD: ioctl: volctrl\n");#endif			if ((s =			     verify_area(VERIFY_READ, (void *) arg,					 sizeof(vol_ctrl))) == 0) {				unsigned char dummy[4];				copy_from_user(&vol_ctrl, (void *) arg,					       sizeof(vol_ctrl));				sjcd_send_4_cmd(SCMD_SET_VOLUME,						vol_ctrl.channel0, 0xFF,						vol_ctrl.channel1, 0xFF);				if (sjcd_receive_status() < 0)					return (-EIO);				(void) sjcd_load_response(dummy, 4);			}			return (s);		}	case CDROMEJECT:{#if defined( SJCD_TRACE )			printk("SJCD: ioctl: eject\n");#endif			if (!sjcd_command_is_in_progress) {				sjcd_tray_unlock();				sjcd_send_cmd(SCMD_EJECT_TRAY);				(void) sjcd_receive_status();			}			return (0);		}#if defined( SJCD_GATHER_STAT )	case 0xABCD:{			int s;#if defined( SJCD_TRACE )			printk("SJCD: ioctl: statistic\n");#endif			if ((s =			     verify_area(VERIFY_WRITE, (void *) arg,					 sizeof(statistic))) == 0)				copy_to_user((void *) arg, &statistic,					     sizeof(statistic));			return (s);		}#endif	default:		return (-EINVAL);	}}/* * Invalidate internal buffers of the driver. */static void sjcd_invalidate_buffers(void){	int i;	for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1);	sjcd_buf_out = -1;}/* * Take care of the different block sizes between cdrom and Linux. * When Linux gets variable block sizes this will probably go away. */#define CURRENT_IS_VALID                                      \    ( !QUEUE_EMPTY && MAJOR( CURRENT->rq_dev ) == MAJOR_NR && \      CURRENT->cmd == READ && CURRENT->sector != -1 )static void sjcd_transfer(void){#if defined( SJCD_TRACE )	printk("SJCD: transfer:\n");#endif	if (CURRENT_IS_VALID) {		while (CURRENT->nr_sectors) {			int i, bn = CURRENT->sector / 4;			for (i = 0;			     i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn;			     i++);			if (i < SJCD_BUF_SIZ) {				int offs =				    (i * 4 + (CURRENT->sector & 3)) * 512;				int nr_sectors = 4 - (CURRENT->sector & 3);				if (sjcd_buf_out != i) {					sjcd_buf_out = i;					if (sjcd_buf_bn[i] != bn) {						sjcd_buf_out = -1;						continue;					}				}				if (nr_sectors > CURRENT->nr_sectors)					nr_sectors = CURRENT->nr_sectors;#if defined( SJCD_TRACE )				printk("SJCD: copy out\n");#endif				memcpy(CURRENT->buffer, sjcd_buf + offs,				       nr_sectors * 512);				CURRENT->nr_sectors -= nr_sectors;				CURRENT->sector += nr_sectors;				CURRENT->buffer += nr_sectors * 512;			} else {				sjcd_buf_out = -1;				break;			}		}	}#if defined( SJCD_TRACE )	printk("SJCD: transfer: done\n");#endif}static void sjcd_poll(void){#if defined( SJCD_GATHER_STAT )	/*	 * Update total number of ticks.	 */	statistic.ticks++;	statistic.tticks[sjcd_transfer_state]++;#endif      ReSwitch:switch (sjcd_transfer_state) {	case SJCD_S_IDLE:{#if defined( SJCD_GATHER_STAT )			statistic.idle_ticks++;#endif#if defined( SJCD_TRACE )			printk("SJCD_S_IDLE\n");#endif			return;		}	case SJCD_S_START:{#if defined( SJCD_GATHER_STAT )			statistic.start_ticks++;#endif			sjcd_send_cmd(SCMD_GET_STATUS);			sjcd_transfer_state =			    sjcd_mode ==			    SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;			sjcd_transfer_timeout = 500;#if defined( SJCD_TRACE )			printk("SJCD_S_START: goto SJCD_S_%s mode\n",			       sjcd_transfer_state ==			       SJCD_S_READ ? "READ" : "MODE");#endif			break;		}	case SJCD_S_MODE:{			if (sjcd_check_status()) {				/*				 * Previous command is completed.				 */				if (!sjcd_status_valid				    || sjcd_command_failed) {#if defined( SJCD_TRACE )					printk					    ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n");#endif					sjcd_transfer_state = SJCD_S_STOP;					goto ReSwitch;				}				sjcd_mode = 0;	/* unknown mode; should not be valid when failed */				sjcd_send_1_cmd(SCMD_SET_MODE,						SCMD_MODE_COOKED);				sjcd_transfer_state = SJCD_S_READ;				sjcd_transfer_timeout = 1000;#if defined( SJCD_TRACE )				printk				    ("SJCD_S_MODE: goto SJCD_S_READ mode\n");#endif			}#if defined( SJCD_GATHER_STAT )			else				statistic.mode_ticks++;#endif			break;		}	case SJCD_S_READ:{			if (sjcd_status_valid ? 1 : sjcd_check_status()) {				/*				 * Previous command is completed.				 */				if (!sjcd_status_valid				    || sjcd_command_failed) {#if defined( SJCD_TRACE )					printk					    ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n");#endif					sjcd_transfer_state = SJCD_S_STOP;					goto ReSwitch;				}				if (!sjcd_media_is_available) {#if defined( SJCD_TRACE )					printk					    ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n");#endif					sjcd_transfer_state = SJCD_S_STOP;					goto ReSwitch;				}				if (sjcd_mode != SCMD_MODE_COOKED) {					/*					 * We seem to come from set mode. So discard one byte of result.					 */					if (sjcd_load_response					    (&sjcd_mode, 1) != 0) {#if defined( SJCD_TRACE )						printk						    ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n");

⌨️ 快捷键说明

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