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

📄 mcd.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 2 页
字号:
		SET_TIMER(mcd_status, 1);		return;	}	if (st & MST_DSK_CHG)	{		mcdDiskChanged = 1;	}		if ((st & MST_READY) == 0)	{		printk("mcd: disk removed\n");		mcdDiskChanged = 1;				end_request(0);		do_mcd_request();		return;	}	outb(0x50, MCDPORT(0));	/* set mode */	outb(0x01, MCDPORT(0));	/* mode = cooked data */	McdTimeout = 100;	SET_TIMER(mcd_read_cmd, 1);}/* * Check the result of the set-mode command.  On success, send the * read-data command. */static voidmcd_read_cmd(){	int st;	long block;	struct mcd_Play_msf mcdcmd;	McdTimeout--;	st = mcdStatus();	if (st & MST_DSK_CHG)	{		mcdDiskChanged = 1;	}		if (st == -1)	{		if (McdTimeout == 0)		{			printk("mcd: set mode timed out\n");			SET_TIMER(mcd_start, 1);	/* wait a bit, try again */			return;		}		SET_TIMER(mcd_read_cmd, 1);		return;	}	mcd_bn = -1;			/* purge our buffer */	block = CURRENT -> sector / 4;	hsg2msf(block, &mcdcmd.start);	/* cvt to msf format */	mcdcmd.end.min = 0;	mcdcmd.end.sec = 0;	mcdcmd.end.frame = 1;	sendMcdCmd(MCMD_PLAY_READ, &mcdcmd);	/* read command */	McdTimeout = 200;	SET_TIMER(mcd_data, 1);}/* * Check the completion of the read-data command.  On success, read * the 2048 bytes of data from the disk into our buffer. */static voidmcd_data(){	int i;	McdTimeout--;	cli();	i =inb(MCDPORT(1)) & (MFL_STATUS | MFL_DATA);	if (i == MFL_DATA)	{		printk("mcd: read failed\n");#ifdef MCD_DEBUG		printk("got 0xB %02X\n", inb(MCDPORT(0)) & 0xFF);#endif		SET_TIMER(mcd_start, 1);		sti();		return;	}		if (i == (MFL_STATUS | MFL_DATA))	{		if (McdTimeout == 0)		{			printk("mcd: data timeout, retrying\n");			SET_TIMER(mcd_start, 1);		}				else			SET_TIMER(mcd_data, 1);				sti();		return;	}	CLEAR_TIMER;	READ_DATA(MCDPORT(0), &mcd_buf[0], 2048);	sti();	mcd_bn = CURRENT -> sector / 4;	mcd_transfer();	end_request(1);	SET_TIMER(do_mcd_request, 1);}/* * Open the device special file.  Check that a disk is in. */intmcd_open(struct inode *ip, struct file *fp){	int st;	if (mcdPresent == 0)		return -ENXIO;			/* no hardware */	st = statusCmd();			/* check drive status */	if (st == -1)		return -EIO;			/* drive doesn't respond */	if ((st & MST_READY) == 0)		/* no disk in drive */	{		printk("mcd: no disk in drive\n");		return -EIO;	}	if (updateToc() < 0)		return -EIO;	return 0;}/* * On close, we flush all mcd blocks from the buffer cache. */static voidmcd_release(struct inode * inode, struct file * file){	mcd_bn = -1;	sync_dev(inode->i_rdev);	invalidate_buffers(inode -> i_rdev);}static struct file_operations mcd_fops = {	NULL,			/* lseek - default */	block_read,		/* read - general block-dev read */	block_write,		/* write - general block-dev write */	NULL,			/* readdir - bad */	NULL,			/* select */	mcd_ioctl,		/* ioctl */	NULL,			/* mmap */	mcd_open,		/* open */	mcd_release		/* release */};/* * MCD interrupt descriptor */static struct sigaction mcd_sigaction = {	mcd_interrupt,	0,	SA_INTERRUPT,	NULL};/* * Test for presence of drive and initialize it.  Called at boot time. */unsigned longmcd_init(unsigned long mem_start, unsigned long mem_end){	int count;	unsigned char result[3];	if (register_blkdev(MAJOR_NR, "mcd", &mcd_fops) != 0)	{		printk("mcd: Unable to get major %d for Mitsumi CD-ROM\n",		       MAJOR_NR);		return mem_start;	}        if (check_region(mcd_port, 4)) {	  printk("mcd: Init failed, I/O port (%X) already in use\n",		 mcd_port);	  return mem_start;	}	  	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;	read_ahead[MAJOR_NR] = 4;	/* check for card */	outb(0, MCDPORT(1));			/* send reset */	for (count = 0; count < 1000000; count++)		(void) inb(MCDPORT(1));		/* delay a bit */	outb(0x40, MCDPORT(0));			/* send get-stat cmd */	for (count = 0; count < 1000000; count++)		if (!(inb(MCDPORT(1)) & MFL_STATUS))			break;	if (count >= 1000000) {		printk("mcd: Init failed. No mcd device at 0x%x irq %d\n",		     mcd_port, mcd_irq);		return mem_start;	}	count = inb(MCDPORT(0));		/* pick up the status */		outb(MCMD_GET_VERSION,MCDPORT(0));	for(count=0;count<3;count++)		if(getValue(result+count)) {			printk("mcd: mitsumi get version failed at 0x%d\n",			       mcd_port);			return mem_start;		}		if (result[0] == result[1] && result[1] == result[2])		return mem_start;	printk("mcd: Mitsumi version : %02X %c %x\n",	       result[0],result[1],result[2]);	mcdVersion=result[2];	if (mcdVersion >=4)		outb(4,MCDPORT(2)); 	/* magic happens */	/* don't get the IRQ until we know for sure the drive is there */	if (irqaction(MCD_INTR_NR,  &mcd_sigaction))	{		printk("mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", MCD_INTR_NR);		return mem_start;	}	snarf_region(mcd_port, 4);	mcdPresent = 1;	printk("mcd: Mitsumi CD-ROM Drive present at addr %x, irq %d\n",	       mcd_port, mcd_irq);	return mem_start;}static voidhsg2msf(long hsg, struct msf *msf){	hsg += 150;	msf -> min = hsg / 4500;	hsg %= 4500;	msf -> sec = hsg / 75;	msf -> frame = hsg % 75;	bin2bcd(&msf -> min);		/* convert to BCD */	bin2bcd(&msf -> sec);	bin2bcd(&msf -> frame);}static voidbin2bcd(unsigned char *p){	int u, t;	u = *p % 10;	t = *p / 10;	*p = u | (t << 4);}static intbcd2bin(unsigned char bcd){	return (bcd >> 4) * 10 + (bcd & 0xF);}/* * See if a status is ready from the drive and return it * if it is ready. */static intmcdStatus(void){	int i;	int st;	st = inb(MCDPORT(1)) & MFL_STATUS;	if (!st)	{		i = inb(MCDPORT(0)) & 0xFF;		return i;	}	else		return -1;}/* * Send a play or read command to the drive */static voidsendMcdCmd(int cmd, struct mcd_Play_msf *params){	outb(cmd, MCDPORT(0));	outb(params -> start.min, MCDPORT(0));	outb(params -> start.sec, MCDPORT(0));	outb(params -> start.frame, MCDPORT(0));	outb(params -> end.min, MCDPORT(0));	outb(params -> end.sec, MCDPORT(0));	outb(params -> end.frame, MCDPORT(0));}/* * Timer interrupt routine to test for status ready from the drive. * (see the next routine) */static voidmcdStatTimer(void){	if (!(inb(MCDPORT(1)) & MFL_STATUS))	{		wake_up(&mcd_waitq);		return;	}	McdTimeout--;	if (McdTimeout <= 0)	{		wake_up(&mcd_waitq);		return;	}	SET_TIMER(mcdStatTimer, 1);}/* * Wait for a status to be returned from the drive.  The actual test * (see routine above) is done by the timer interrupt to avoid * excessive rescheduling. */static intgetMcdStatus(int timeout){	int st;	McdTimeout = timeout;	SET_TIMER(mcdStatTimer, 1);	sleep_on(&mcd_waitq);	if (McdTimeout <= 0)		return -1;	st = inb(MCDPORT(0)) & 0xFF;	if (st == 0xFF)		return -1;	if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)		/* XXX might be an error? look at q-channel? */		audioStatus = CDROM_AUDIO_COMPLETED;	if (st & MST_DSK_CHG)	{		mcdDiskChanged = 1;		tocUpToDate = 0;		audioStatus = CDROM_AUDIO_NO_STATUS;	}	return st;}/* * Read a value from the drive.  Should return quickly, so a busy wait * is used to avoid excessive rescheduling. */static intgetValue(unsigned char *result){	int count;	int s;	for (count = 0; count < 2000; count++)		if (!(inb(MCDPORT(1)) & MFL_STATUS))			break;	if (count >= 2000)	{		printk("mcd: getValue timeout\n");		return -1;	}	s = inb(MCDPORT(0)) & 0xFF;	*result = (unsigned char) s;	return 0;}/* * Read the current Q-channel info.  Also used for reading the * table of contents. */intGetQChannelInfo(struct mcd_Toc *qp){	unsigned char notUsed;	int retry;	for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)	{		outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));		if (getMcdStatus(MCD_STATUS_DELAY) != -1)			break;	}	if (retry >= MCD_RETRY_ATTEMPTS)		return -1;	if (getValue(&qp -> ctrl_addr) < 0) return -1;	if (getValue(&qp -> track) < 0) return -1;	if (getValue(&qp -> pointIndex) < 0) return -1;	if (getValue(&qp -> trackTime.min) < 0) return -1;	if (getValue(&qp -> trackTime.sec) < 0) return -1;	if (getValue(&qp -> trackTime.frame) < 0) return -1;	if (getValue(&notUsed) < 0) return -1;	if (getValue(&qp -> diskTime.min) < 0) return -1;	if (getValue(&qp -> diskTime.sec) < 0) return -1;	if (getValue(&qp -> diskTime.frame) < 0) return -1;	return 0;}/* * Read the table of contents (TOC) and TOC header if neccessary */static intupdateToc(){	if (tocUpToDate)		return 0;	if (GetDiskInfo() < 0)		return -EIO;	if (GetToc() < 0)		return -EIO;	tocUpToDate = 1;	return 0;}/* * Read the table of contents header */static intGetDiskInfo(){	int retry;	for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)	{		outb(MCMD_GET_DISK_INFO, MCDPORT(0));		if (getMcdStatus(MCD_STATUS_DELAY) != -1)			break;	}	if (retry >= MCD_RETRY_ATTEMPTS)		return -1;	if (getValue(&DiskInfo.first) < 0) return -1;	if (getValue(&DiskInfo.last) < 0) return -1;	DiskInfo.first = bcd2bin(DiskInfo.first);	DiskInfo.last = bcd2bin(DiskInfo.last);	if (getValue(&DiskInfo.diskLength.min) < 0) return -1;	if (getValue(&DiskInfo.diskLength.sec) < 0) return -1;	if (getValue(&DiskInfo.diskLength.frame) < 0) return -1;	if (getValue(&DiskInfo.firstTrack.min) < 0) return -1;	if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1;	if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1;#ifdef MCD_DEBUGprintk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",	DiskInfo.first,	DiskInfo.last,	DiskInfo.diskLength.min,	DiskInfo.diskLength.sec,	DiskInfo.diskLength.frame,	DiskInfo.firstTrack.min,	DiskInfo.firstTrack.sec,	DiskInfo.firstTrack.frame);#endif	return 0;}/* * Read the table of contents (TOC) */static intGetToc(){	int i, px;	int limit;	int retry;	struct mcd_Toc qInfo;	for (i = 0; i < MAX_TRACKS; i++)		Toc[i].pointIndex = 0;	i = DiskInfo.last + 3;	for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)	{		outb(MCMD_STOP, MCDPORT(0));		if (getMcdStatus(MCD_STATUS_DELAY) != -1)			break;	}	if (retry >= MCD_RETRY_ATTEMPTS)		return -1;	for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)	{		outb(MCMD_SET_MODE, MCDPORT(0));		outb(0x05, MCDPORT(0));			/* mode: toc */		if (getMcdStatus(MCD_STATUS_DELAY) != -1)			break;	}	if (retry >= MCD_RETRY_ATTEMPTS)		return -1;	for (limit = 300; limit > 0; limit--)	{		if (GetQChannelInfo(&qInfo) < 0)			break;		px = bcd2bin(qInfo.pointIndex);		if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)			if (Toc[px].pointIndex == 0)			{				Toc[px] = qInfo;				i--;			}		if (i <= 0)			break;	}	Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;	for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)	{                outb(MCMD_SET_MODE, MCDPORT(0));                outb(0x01, MCDPORT(0));                if (getMcdStatus(MCD_STATUS_DELAY) != -1)                        break;	}#ifdef MCD_DEBUGfor (i = 1; i <= DiskInfo.last; i++)printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X    %02X:%02X.%02X\n",i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);for (i = 100; i < 103; i++)printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X    %02X:%02X.%02X\n",i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);#endif	return limit > 0 ? 0 : -1;}

⌨️ 快捷键说明

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