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

📄 sonycd535.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
				|| (ti.cdti_trk1 < ti.cdti_trk0)) {				return -EINVAL;			}			track_idx = find_track(int_to_bcd(ti.cdti_trk0));			if (track_idx < 0)				return -EINVAL;			params[1] = sony_toc->tracks[track_idx].track_start_msf[0];			params[2] = sony_toc->tracks[track_idx].track_start_msf[1];			params[3] = sony_toc->tracks[track_idx].track_start_msf[2];			/*			 * If we want to stop after the last track, use the lead-out			 * MSF to do that.			 */			if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {				log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,						   &(params[4]));			} else {				track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));				if (track_idx < 0)					return -EINVAL;				log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,						   &(params[4]));			}			params[0] = 0x03;			spin_up_drive(status);			set_drive_mode(SONY535_AUDIO_DRIVE_MODE, 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] = params[1];			cmd_buff[3] = params[2];			cmd_buff[4] = params[3];			cmd_buff[5] = SONY535_PLAY_AUDIO;			cmd_buff[6] = 2;	/* set ending address */			cmd_buff[7] = params[4];			cmd_buff[8] = params[5];			cmd_buff[9] = params[6];			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 (CDROMPLAYTRKIND)\n",						status[0]);				printk("... Params: %x %x %x %x %x %x %x\n",						params[0], params[1], params[2],						params[3], params[4], params[5], params[6]);				return -EIO;			}			/* Save the final position for pauses and resumes */			final_pos_msf[0] = params[4];			final_pos_msf[1] = params[5];			final_pos_msf[2] = params[6];			sony_audio_status = CDROM_AUDIO_PLAY;			return 0;		}	case CDROMSUBCHNL:			/* Get subchannel info */		return sony_get_subchnl_info(arg);	case CDROMVOLCTRL:			/* Volume control.  What volume does this change, anyway? */		{			struct cdrom_volctrl volctrl;			err = verify_area(VERIFY_READ, (char *)arg, sizeof volctrl);			if (err)				return err;			copy_from_user(&volctrl, (char *)arg, sizeof volctrl);			cmd_buff[0] = SONY535_SET_VOLUME;			cmd_buff[1] = volctrl.channel0;			cmd_buff[2] = volctrl.channel1;			if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {				printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",						status[0]);				return -EIO;			}		}		return 0;	case CDROMEJECT:			/* Eject the drive */		cmd_buff[0] = SONY535_STOP;		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);		cmd_buff[0] = SONY535_SPIN_DOWN;		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);		sony_audio_status = CDROM_AUDIO_INVALID;		cmd_buff[0] = SONY535_EJECT_CADDY;		if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",					status[0]);			return -EIO;		}		return 0;		break;	default:		return -EINVAL;	}}/* * Open the drive for operations.  Spin the drive up and read the table of * contents if these have not already been done. */static intcdu_open(struct inode *inode,		 struct file *filp){	Byte status[2], cmd_buff[2];	if (sony_inuse)		return -EBUSY;	if (check_drive_status() != 0)		return -EIO;	sony_inuse = 1;	if (spin_up_drive(status) != 0) {		printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",				status[0]);		sony_inuse = 0;		return -EIO;	}	sony_get_toc();	if (!sony_toc_read) {		cmd_buff[0] = SONY535_SPIN_DOWN;		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);		sony_inuse = 0;		return -EIO;	}	if (inode) {		check_disk_change(inode->i_rdev);	}	sony_usage++;#ifdef LOCK_DOORS	/* disable the eject button while mounted */	cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;	do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);#endif	return 0;}/* * Close the drive.  Spin it down if no task is using it.  The spin * down will fail if playing audio, so audio play is OK. */static intcdu_release(struct inode *inode,			struct file *filp){	Byte status[2], cmd_no;	sony_inuse = 0;	if (0 < sony_usage) {		sony_usage--;	}	if (sony_usage == 0) {		check_drive_status();		if (sony_audio_status != CDROM_AUDIO_PLAY) {			cmd_no = SONY535_SPIN_DOWN;			do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);		}#ifdef LOCK_DOORS		/* enable the eject button after umount */		cmd_no = SONY535_ENABLE_EJECT_BUTTON;		do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);#endif	}	return 0;}static struct block_device_operations cdu_fops ={	owner:			THIS_MODULE,	open:			cdu_open,	release:		cdu_release,	ioctl:			cdu_ioctl,	check_media_change:	cdu535_check_media_change,};static int sonycd535_block_size = CDU535_BLOCK_SIZE;/* * Initialize the driver. */int __init sony535_init(void){	struct s535_sony_drive_config drive_config;	Byte cmd_buff[3];	Byte ret_buff[2];	Byte status[2];	unsigned long snap;	int  got_result = 0;	int  tmp_irq;	int  i;	/* Setting the base I/O address to 0 will disable it. */	if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))		return 0;	/* Set up all the register locations */	result_reg = sony535_cd_base_io;	command_reg = sony535_cd_base_io;	data_reg = sony535_cd_base_io + 1;	read_status_reg = sony535_cd_base_io + 2;	select_unit_reg = sony535_cd_base_io + 3;#ifndef USE_IRQ	sony535_irq_used = 0;	/* polling only until this is ready... */#endif	/* we need to poll until things get initialized */	tmp_irq = sony535_irq_used;	sony535_irq_used = 0;#if DEBUG > 0	printk(KERN_INFO CDU535_MESSAGE_NAME ": probing base address %03X\n",			sony535_cd_base_io);#endif	if (check_region(sony535_cd_base_io,4)) {		printk(CDU535_MESSAGE_NAME ": my base address is not free!\n");		return -EIO;	}	/* look for the CD-ROM, follows the procedure in the DOS driver */	inb(select_unit_reg);	/* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */	current->state = TASK_INTERRUPTIBLE;	schedule_timeout((HZ+17)*40/18);	inb(result_reg);	outb(0, read_status_reg);	/* does a reset? */	snap = jiffies;	while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {		select_unit(0);		if (inb(result_reg) != 0xff) {			got_result = 1;			break;		}		sony_sleep();	}	if (got_result && (check_drive_status() != TIME_OUT)) {		/* CD-ROM drive responded --  get the drive configuration */		cmd_buff[0] = SONY535_INQUIRY;		if (do_sony_cmd(cmd_buff, 1, status,						(Byte *)&drive_config, 28, 1) == 0) {			/* was able to get the configuration,			 * set drive mode as rest of init			 */#if DEBUG > 0			/* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */			if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )				printk(CDU535_MESSAGE_NAME						"Inquiry command returned status = 0x%x\n", status[0]);#endif			/* now ready to use interrupts, if available */			sony535_irq_used = tmp_irq;#ifndef MODULE/* This code is not in MODULEs by default, since the autoirq stuff might * not be in the module-accessible symbol table. */			/* A negative sony535_irq_used will attempt an autoirq. */			if (sony535_irq_used < 0) {				autoirq_setup(0);				enable_interrupts();				outb(0, read_status_reg);	/* does a reset? */				sony535_irq_used = autoirq_report(10);				disable_interrupts();			}#endif			if (sony535_irq_used > 0) {			    if (request_irq(sony535_irq_used, cdu535_interrupt,								SA_INTERRUPT, CDU535_HANDLE, NULL)) {					printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME							" driver; polling instead.\n", sony535_irq_used);					sony535_irq_used = 0;				}			}			cmd_buff[0] = SONY535_SET_DRIVE_MODE;			cmd_buff[1] = 0x0;	/* default audio */			if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) {				/* set the drive mode successful, we are set! */				sony_buffer_size = SONY535_BUFFER_SIZE;				sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;				printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",					   drive_config.vendor_id,					   drive_config.product_id,					   drive_config.product_rev_level);				printk("  base address %03X, ", sony535_cd_base_io);				if (tmp_irq > 0)					printk("IRQ%d, ", tmp_irq);				printk("using %d byte buffer\n", sony_buffer_size);				devfs_register (NULL, CDU535_HANDLE,						DEVFS_FL_DEFAULT,						MAJOR_NR, 0,						S_IFBLK | S_IRUGO | S_IWUGO,						&cdu_fops, NULL);				if (devfs_register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {					printk("Unable to get major %d for %s\n",							MAJOR_NR, CDU535_MESSAGE_NAME);					return -EIO;				}				blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);				blksize_size[MAJOR_NR] = &sonycd535_block_size;				read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB) read-ahead */				sony_toc = (struct s535_sony_toc *)					kmalloc(sizeof *sony_toc, GFP_KERNEL);				if (sony_toc == NULL) {					blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));					return -ENOMEM;				}				last_sony_subcode = (struct s535_sony_subcode *)					kmalloc(sizeof *last_sony_subcode, GFP_KERNEL);				if (last_sony_subcode == NULL) {					blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));					kfree(sony_toc);					return -ENOMEM;				}				sony_buffer = (Byte **)					kmalloc(4 * sony_buffer_sectors, GFP_KERNEL);				if (sony_buffer == NULL) {					blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));					kfree(sony_toc);					kfree(last_sony_subcode);					return -ENOMEM;				}				for (i = 0; i < sony_buffer_sectors; i++) {					sony_buffer[i] =								(Byte *)kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);					if (sony_buffer[i] == NULL) {						while (--i>=0)							kfree(sony_buffer[i]);						blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));						kfree(sony_buffer);						kfree(sony_toc);						kfree(last_sony_subcode);						return -ENOMEM;					}				}				initialized = 1;			}		}	}	if (!initialized) {		printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");		return -EIO;	}	request_region(sony535_cd_base_io, 4, CDU535_HANDLE);	register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &cdu_fops, 0);	return 0;}#ifndef MODULE/* * accept "kernel command line" parameters * (added by emoenke@gwdg.de) * * use: tell LILO: *                 sonycd535=0x320 * * the address value has to be the existing CDROM port address. */static int __initsonycd535_setup(char *strings){	int ints[3];	(void)get_options(strings, ARRAY_SIZE(ints), ints);	/* if IRQ change and default io base desired,	 * then call with io base of 0	 */	if (ints[0] > 0)		if (ints[1] != 0)			sony535_cd_base_io = ints[1];	if (ints[0] > 1)		sony535_irq_used = ints[2];	if ((strings != NULL) && (*strings != '\0'))		printk(CDU535_MESSAGE_NAME				": Warning: Unknown interface type: %s\n", strings);					return 1;}__setup("sonycd535=", sonycd535_setup);#endif /* MODULE */void __exitsony535_exit(void){	int i;	release_region(sony535_cd_base_io, 4);	for (i = 0; i < sony_buffer_sectors; i++)		kfree(sony_buffer[i]);	kfree(sony_buffer);	kfree(last_sony_subcode);	kfree(sony_toc);	devfs_unregister(devfs_find_handle(NULL, CDU535_HANDLE, 0, 0,					   DEVFS_SPECIAL_BLK, 0));	if (devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)		printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");	else		printk(KERN_INFO CDU535_HANDLE " module released\n");}#ifdef MODULEmodule_init(sony535_init);#endifmodule_exit(sony535_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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