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

📄 sjcd.c

📁 还有没有人研究过cdrom 的驱动源码啊
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif						sjcd_transfer_state =						    SJCD_S_STOP;						goto ReSwitch;					}					if (sjcd_mode != SCMD_MODE_COOKED) {#if defined( SJCD_TRACE )						printk						    ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n");#endif						sjcd_transfer_state =						    SJCD_S_STOP;						goto ReSwitch;					}				}				if (CURRENT_IS_VALID) {					struct sjcd_play_msf msf;					sjcd_next_bn = CURRENT->sector / 4;					hsg2msf(sjcd_next_bn, &msf.start);					msf.end.min = 0;					msf.end.sec = 0;					msf.end.frame = sjcd_read_count =					    SJCD_BUF_SIZ;#if defined( SJCD_TRACE )					printk					    ("SJCD: ---reading msf-address %x:%x:%x  %x:%x:%x\n",					     msf.start.min, msf.start.sec,					     msf.start.frame, msf.end.min,					     msf.end.sec, msf.end.frame);					printk					    ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n",					     sjcd_next_bn, sjcd_buf_in,					     sjcd_buf_out,					     sjcd_buf_bn[sjcd_buf_in]);#endif					sjcd_send_6_cmd(SCMD_DATA_READ,							&msf);					sjcd_transfer_state = SJCD_S_DATA;					sjcd_transfer_timeout = 500;#if defined( SJCD_TRACE )					printk					    ("SJCD_S_READ: go to SJCD_S_DATA mode\n");#endif				} else {#if defined( SJCD_TRACE )					printk					    ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n");#endif					sjcd_transfer_state = SJCD_S_STOP;					goto ReSwitch;				}			}#if defined( SJCD_GATHER_STAT )			else				statistic.read_ticks++;#endif			break;		}	case SJCD_S_DATA:{			unsigned char stat;		      sjcd_s_data:stat =			    inb(SJCDPORT				(1));#if defined( SJCD_TRACE )			printk("SJCD_S_DATA: status = 0x%02x\n", stat);#endif			if (SJCD_STATUS_AVAILABLE(stat)) {				/*				 * No data is waiting for us in the drive buffer. Status of operation				 * completion is available. Read and parse it.				 */				sjcd_load_status();				if (!sjcd_status_valid				    || sjcd_command_failed) {#if defined( SJCD_TRACE )					printk					    ("SJCD: read block %d failed, maybe audio disk? Giving up\n",					     sjcd_next_bn);#endif					if (CURRENT_IS_VALID)						end_request(0);#if defined( SJCD_TRACE )					printk					    ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n");#endif					sjcd_transfer_state = SJCD_S_STOP;					goto ReSwitch;				}				if (!sjcd_media_is_available) {					printk					    ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n");					sjcd_transfer_state = SJCD_S_STOP;					goto ReSwitch;				}				sjcd_transfer_state = SJCD_S_READ;				goto ReSwitch;			} else if (SJCD_DATA_AVAILABLE(stat)) {				/*				 * One frame is read into device buffer. We must copy it to our memory.				 * Otherwise cdrom hangs up. Check to see if we have something to copy				 * to.				 */				if (!CURRENT_IS_VALID				    && sjcd_buf_in == sjcd_buf_out) {#if defined( SJCD_TRACE )					printk					    ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n");					printk					    (" ... all the date would be discarded\n");#endif					sjcd_transfer_state = SJCD_S_STOP;					goto ReSwitch;				}				/*				 * Everything seems to be OK. Just read the frame and recalculate				 * indices.				 */				sjcd_buf_bn[sjcd_buf_in] = -1;	/* ??? */				insb(SJCDPORT(2),				     sjcd_buf + 2048 * sjcd_buf_in, 2048);#if defined( SJCD_TRACE )				printk				    ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",				     sjcd_next_bn, sjcd_buf_in,				     sjcd_buf_out,				     sjcd_buf_bn[sjcd_buf_in]);#endif				sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++;				if (sjcd_buf_out == -1)					sjcd_buf_out = sjcd_buf_in;				if (++sjcd_buf_in == SJCD_BUF_SIZ)					sjcd_buf_in = 0;				/*				 * Only one frame is ready at time. So we should turn over to wait for				 * another frame. If we need that, of course.				 */				if (--sjcd_read_count == 0) {					/*					 * OK, request seems to be precessed. Continue transferring...					 */					if (!sjcd_transfer_is_active) {						while (CURRENT_IS_VALID) {							/*							 * Continue transferring.							 */							sjcd_transfer();							if (CURRENT->							    nr_sectors ==							    0)								end_request								    (1);							else								break;						}					}					if (CURRENT_IS_VALID &&					    (CURRENT->sector / 4 <					     sjcd_next_bn					     || CURRENT->sector / 4 >					     sjcd_next_bn +					     SJCD_BUF_SIZ)) {#if defined( SJCD_TRACE )						printk						    ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n");#endif						sjcd_transfer_state =						    SJCD_S_STOP;						goto ReSwitch;					}				}				/*				 * Now we should turn around rather than wait for while.				 */				goto sjcd_s_data;			}#if defined( SJCD_GATHER_STAT )			else				statistic.data_ticks++;#endif			break;		}	case SJCD_S_STOP:{			sjcd_read_count = 0;			sjcd_send_cmd(SCMD_STOP);			sjcd_transfer_state = SJCD_S_STOPPING;			sjcd_transfer_timeout = 500;#if defined( SJCD_GATHER_STAT )			statistic.stop_ticks++;#endif			break;		}	case SJCD_S_STOPPING:{			unsigned char stat;			stat = inb(SJCDPORT(1));#if defined( SJCD_TRACE )			printk("SJCD_S_STOP: status = 0x%02x\n", stat);#endif			if (SJCD_DATA_AVAILABLE(stat)) {				int i;#if defined( SJCD_TRACE )				printk("SJCD_S_STOP: discard data\n");#endif				/*				 * Discard all the data from the pipe. Foolish method.				 */				for (i = 2048; i--;				     (void) inb(SJCDPORT(2)));				sjcd_transfer_timeout = 500;			} else if (SJCD_STATUS_AVAILABLE(stat)) {				sjcd_load_status();				if (sjcd_status_valid				    && sjcd_media_is_changed) {					sjcd_toc_uptodate = 0;					sjcd_invalidate_buffers();				}				if (CURRENT_IS_VALID) {					if (sjcd_status_valid)						sjcd_transfer_state =						    SJCD_S_READ;					else						sjcd_transfer_state =						    SJCD_S_START;				} else					sjcd_transfer_state = SJCD_S_IDLE;				goto ReSwitch;			}#if defined( SJCD_GATHER_STAT )			else				statistic.stopping_ticks++;#endif			break;		}	default:		printk("SJCD: poll: invalid state %d\n",		       sjcd_transfer_state);		return;	}	if (--sjcd_transfer_timeout == 0) {		printk("SJCD: timeout in state %d\n", sjcd_transfer_state);		while (CURRENT_IS_VALID)			end_request(0);		sjcd_send_cmd(SCMD_STOP);		sjcd_transfer_state = SJCD_S_IDLE;		goto ReSwitch;	}	/*	 * Get back in some time. 1 should be replaced with count variable to	 * avoid unnecessary testings.	 */	SJCD_SET_TIMER(sjcd_poll, 1);}static void do_sjcd_request(request_queue_t * q){#if defined( SJCD_TRACE )	printk("SJCD: do_sjcd_request(%ld+%ld)\n",	       CURRENT->sector, CURRENT->nr_sectors);#endif	sjcd_transfer_is_active = 1;	while (CURRENT_IS_VALID) {		/*		 * Who of us are paranoiac?		 */		if (CURRENT->bh && !buffer_locked(CURRENT->bh))			panic(DEVICE_NAME ": block not locked");		sjcd_transfer();		if (CURRENT->nr_sectors == 0)			end_request(1);		else {			sjcd_buf_out = -1;	/* Want to read a block not in buffer */			if (sjcd_transfer_state == SJCD_S_IDLE) {				if (!sjcd_toc_uptodate) {					if (sjcd_update_toc() < 0) {						printk						    ("SJCD: transfer: discard\n");						while (CURRENT_IS_VALID)							end_request(0);						break;					}				}				sjcd_transfer_state = SJCD_S_START;				SJCD_SET_TIMER(sjcd_poll, HZ / 100);			}			break;		}	}	sjcd_transfer_is_active = 0;#if defined( SJCD_TRACE )	printk	    ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",	     sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,	     sjcd_buf_bn[sjcd_buf_in]);	printk("do_sjcd_request ends\n");#endif}/* * Open the device special file. Check disk is in. */int sjcd_open(struct inode *ip, struct file *fp){	/*	 * Check the presence of device.	 */	if (!sjcd_present)		return (-ENXIO);	/*	 * Only read operations are allowed. Really? (:-)	 */	if (fp->f_mode & 2)		return (-EROFS);	if (sjcd_open_count == 0) {		int s, sjcd_open_tries;/* We don't know that, do we? *//*    sjcd_audio_status = CDROM_AUDIO_NO_STATUS;*/		sjcd_mode = 0;		sjcd_door_was_open = 0;		sjcd_transfer_state = SJCD_S_IDLE;		sjcd_invalidate_buffers();		sjcd_status_valid = 0;		/*		 * Strict status checking.		 */		for (sjcd_open_tries = 4; --sjcd_open_tries;) {			if (!sjcd_status_valid)				sjcd_get_status();			if (!sjcd_status_valid) {#if defined( SJCD_DIAGNOSTIC )				printk				    ("SJCD: open: timed out when check status.\n");#endif				goto err_out;			} else if (!sjcd_media_is_available) {#if defined( SJCD_DIAGNOSTIC )				printk("SJCD: open: no disk in drive\n");#endif				if (!sjcd_door_closed) {					sjcd_door_was_open = 1;#if defined( SJCD_TRACE )					printk					    ("SJCD: open: close the tray\n");#endif					s = sjcd_tray_close();					if (s < 0 || !sjcd_status_valid					    || sjcd_command_failed) {#if defined( SJCD_DIAGNOSTIC )						printk						    ("SJCD: open: tray close attempt failed\n");#endif						goto err_out;					}					continue;				} else					goto err_out;			}			break;		}		s = sjcd_tray_lock();		if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {#if defined( SJCD_DIAGNOSTIC )			printk("SJCD: open: tray lock attempt failed\n");#endif			goto err_out;		}#if defined( SJCD_TRACE )		printk("SJCD: open: done\n");#endif	}	++sjcd_open_count;	return (0);      err_out:	return (-EIO);}/* * On close, we flush all sjcd blocks from the buffer cache. */static int sjcd_release(struct inode *inode, struct file *file){	int s;#if defined( SJCD_TRACE )	printk("SJCD: release\n");#endif	if (--sjcd_open_count == 0) {		sjcd_invalidate_buffers();		s = sjcd_tray_unlock();		if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {#if defined( SJCD_DIAGNOSTIC )			printk			    ("SJCD: release: tray unlock attempt failed.\n");#endif		}		if (sjcd_door_was_open) {			s = sjcd_tray_open();			if (s < 0 || !sjcd_status_valid			    || sjcd_command_failed) {#if defined( SJCD_DIAGNOSTIC )				printk				    ("SJCD: release: tray unload attempt failed.\n");#endif			}		}	}	return 0;}/* * A list of file operations allowed for this cdrom. */static struct block_device_operations sjcd_fops = {	owner:THIS_MODULE,	open:sjcd_open,	release:sjcd_release,	ioctl:sjcd_ioctl,	check_media_change:sjcd_disk_change,};static int blksize = 2048;static int secsize = 2048;/* * Following stuff is intended for initialization of the cdrom. It * first looks for presence of device. If the device is present, it * will be reset. Then read the version of the drive and load status. * The version is two BCD-coded bytes. */static struct {	unsigned char major, minor;} sjcd_version;/* * Test for presence of drive and initialize it. Called at boot time. * Probe cdrom, find out version and status. */int __init sjcd_init(void){	int i;	printk(KERN_INFO	       "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n",	       SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);#if defined( SJCD_TRACE )	printk("SJCD: sjcd=0x%x: ", sjcd_base);#endif	hardsect_size[MAJOR_NR] = &secsize;	blksize_size[MAJOR_NR] = &blksize;	if (devfs_register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) {		printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n",		       MAJOR_NR);		return (-EIO);	}	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);	read_ahead[MAJOR_NR] = 4;	register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &sjcd_fops, 0);	if (check_region(sjcd_base, 4)) {		printk		    ("SJCD: Init failed, I/O port (%X) is already in use\n",		     sjcd_base);		sjcd_cleanup();		return (-EIO);	}	/*	 * Check for card. Since we are booting now, we can't use standard	 * wait algorithm.	 */	printk(KERN_INFO "SJCD: Resetting: ");	sjcd_send_cmd(SCMD_RESET);	for (i = 1000; i > 0 && !sjcd_status_valid; --i) {		unsigned long timer;		/*		 * Wait 10ms approx.		 */		for (timer = jiffies; time_before_eq(jiffies, timer););		if ((i % 100) == 0)			printk(".");		(void) sjcd_check_status();	}	if (i == 0 || sjcd_command_failed) {		printk(" reset failed, no drive found.\n");		sjcd_cleanup();		return (-EIO);	} else		printk("\n");	/*	 * Get and print out cdrom version.	 */	printk(KERN_INFO "SJCD: Getting version: ");	sjcd_send_cmd(SCMD_GET_VERSION);	for (i = 1000; i > 0 && !sjcd_status_valid; --i) {		unsigned long timer;		/*		 * Wait 10ms approx.		 */		for (timer = jiffies; time_before_eq(jiffies, timer););		if ((i % 100) == 0)			printk(".");		(void) sjcd_check_status();	}	if (i == 0 || sjcd_command_failed) {		printk(" get version failed, no drive found.\n");		sjcd_cleanup();		return (-EIO);	}	if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {		printk(" %1x.%02x\n", (int) sjcd_version.major,		       (int) sjcd_version.minor);	} else {		printk(" read version failed, no drive found.\n");		sjcd_cleanup();		return (-EIO);	}	/*	 * Check and print out the tray state. (if it is needed?).	 */	if (!sjcd_status_valid) {		printk(KERN_INFO "SJCD: Getting status: ");		sjcd_send_cmd(SCMD_GET_STATUS);		for (i = 1000; i > 0 && !sjcd_status_valid; --i) {			unsigned long timer;			/*			 * Wait 10ms approx.			 */			for (timer = jiffies;			     time_before_eq(jiffies, timer););			if ((i % 100) == 0)				printk(".");			(void) sjcd_check_status();		}		if (i == 0 || sjcd_command_failed) {			printk(" get status failed, no drive found.\n");			sjcd_cleanup();			return (-EIO);		} else			printk("\n");	}	printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);	devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,		       S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL);	sjcd_present++;	return (0);}static int sjcd_cleanup(void){	if ((devfs_unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))		printk("SJCD: cannot unregister device.\n");	else {		release_region(sjcd_base, 4);		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));	}	return (0);}void __exit sjcd_exit(void){	devfs_unregister(devfs_find_handle			 (NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0));	if (sjcd_cleanup())		printk("SJCD: module: cannot be removed.\n");	else		printk(KERN_INFO "SJCD: module: removed.\n");}#ifdef MODULEmodule_init(sjcd_init);#endifmodule_exit(sjcd_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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