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

📄 mcdx.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
		/* audio status? */		if (stuffp->audiostatus == CDROM_AUDIO_INVALID)			stuffp->audiostatus =			    e_audiobusy(st) ? CDROM_AUDIO_PLAY :			    CDROM_AUDIO_NO_STATUS;		else if (stuffp->audiostatus == CDROM_AUDIO_PLAY			 && e_audiobusy(st) == 0)			stuffp->audiostatus = CDROM_AUDIO_COMPLETED;		/* media change? */		if (e_changed(st)) {			xinfo("talk() media changed\n");			stuffp->xxx = stuffp->yyy = 1;		}		/* now actually get the data */		while (sz--) {			if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {				xinfo("talk() %02x timed out (data), %d tr%s left\n",				     cmd[0], tries - 1,				     tries == 2 ? "y" : "ies");				st = -1;				break;			}			if (!discard)				bp++;			xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1));		}	}#if !MCDX_QUIET	if (!tries && st == -1)		xinfo("talk() giving up\n");#endif	stuffp->lock = 0;	wake_up_interruptible(&stuffp->lockq);	xtrace(TALK, "talk() done with 0x%02x\n", st);	return st;}/* MODULE STUFF ***********************************************************/EXPORT_NO_SYMBOLS;int __mcdx_init(void){	int i;	int drives = 0;	mcdx_init();	for (i = 0; i < MCDX_NDRIVES; i++) {		if (mcdx_stuffp[i]) {			xtrace(INIT, "init_module() drive %d stuff @ %p\n",			       i, mcdx_stuffp[i]);			drives++;		}	}	if (!drives)		return -EIO;	return 0;}void __exit mcdx_exit(void){	int i;	xinfo("cleanup_module called\n");	for (i = 0; i < MCDX_NDRIVES; i++) {		struct s_drive_stuff *stuffp;		if (unregister_cdrom(&mcdx_info)) {			printk(KERN_WARNING "Can't unregister cdrom mcdx\n");			return;		}		stuffp = mcdx_stuffp[i];		if (!stuffp)			continue;		release_region((unsigned long) stuffp->wreg_data,			       MCDX_IO_SIZE);		free_irq(stuffp->irq, NULL);		if (stuffp->toc) {			xtrace(MALLOC, "cleanup_module() free toc @ %p\n",			       stuffp->toc);			kfree(stuffp->toc);		}		xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n",		       stuffp);		mcdx_stuffp[i] = NULL;		kfree(stuffp);	}	if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) {		xwarn("cleanup() unregister_blkdev() failed\n");	}	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));#if !MCDX_QUIET	else	xinfo("cleanup() succeeded\n");#endif}#ifdef MODULEmodule_init(__mcdx_init);#endifmodule_exit(mcdx_exit);/* Support functions ************************************************/int __init mcdx_init_drive(int drive){	struct s_version version;	struct s_drive_stuff *stuffp;	int size = sizeof(*stuffp);	char msg[80];	mcdx_blocksizes[drive] = 0;	xtrace(INIT, "init() try drive %d\n", drive);	xtrace(INIT, "kmalloc space for stuffpt's\n");	xtrace(MALLOC, "init() malloc %d bytes\n", size);	if (!(stuffp = kmalloc(size, GFP_KERNEL))) {		xwarn("init() malloc failed\n");		return 1;	}	xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",	       sizeof(*stuffp), stuffp);	/* set default values */	memset(stuffp, 0, sizeof(*stuffp));	stuffp->present = 0;	/* this should be 0 already */	stuffp->toc = NULL;	/* this should be NULL already */	/* setup our irq and i/o addresses */	stuffp->irq = irq(mcdx_drive_map[drive]);	stuffp->wreg_data = stuffp->rreg_data =	    port(mcdx_drive_map[drive]);	stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;	stuffp->wreg_hcon = stuffp->wreg_reset + 1;	stuffp->wreg_chn = stuffp->wreg_hcon + 1;	init_waitqueue_head(&stuffp->busyq);	init_waitqueue_head(&stuffp->lockq);	init_waitqueue_head(&stuffp->sleepq);	/* check if i/o addresses are available */	if (check_region((unsigned int) stuffp->wreg_data, MCDX_IO_SIZE)) {		xwarn("0x%3p,%d: Init failed. "		      "I/O ports (0x%3p..0x%3p) already in use.\n",		      stuffp->wreg_data, stuffp->irq,		      stuffp->wreg_data,		      stuffp->wreg_data + MCDX_IO_SIZE - 1);		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);		kfree(stuffp);		xtrace(INIT, "init() continue at next drive\n");		return 0;	/* next drive */	}	xtrace(INIT, "init() i/o port is available at 0x%3p\n",	       stuffp->wreg_data);	xtrace(INIT, "init() hardware reset\n");	mcdx_reset(stuffp, HARD, 1);	xtrace(INIT, "init() get version\n");	if (-1 == mcdx_requestversion(stuffp, &version, 4)) {		/* failed, next drive */		xwarn("%s=0x%3p,%d: Init failed. Can't get version.\n",		      MCDX, stuffp->wreg_data, stuffp->irq);		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);		kfree(stuffp);		xtrace(INIT, "init() continue at next drive\n");		return 0;	}	switch (version.code) {	case 'D':		stuffp->readcmd = READ2X;		stuffp->present = DOUBLE | DOOR | MULTI;		break;	case 'F':		stuffp->readcmd = READ1X;		stuffp->present = SINGLE | DOOR | MULTI;		break;	case 'M':		stuffp->readcmd = READ1X;		stuffp->present = SINGLE;		break;	default:		stuffp->present = 0;		break;	}	stuffp->playcmd = READ1X;	if (!stuffp->present) {		xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n",		      MCDX, stuffp->wreg_data, stuffp->irq);		kfree(stuffp);		return 0;	/* next drive */	}	xtrace(INIT, "init() register blkdev\n");	if (devfs_register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) {		xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",		      MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR);		kfree(stuffp);		return 1;	}	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);	read_ahead[MAJOR_NR] = READ_AHEAD;	blksize_size[MAJOR_NR] = mcdx_blocksizes;	xtrace(INIT, "init() subscribe irq and i/o\n");	mcdx_irq_map[stuffp->irq] = stuffp;	if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, "mcdx", NULL)) {		xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",		      MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);		stuffp->irq = 0;		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));		kfree(stuffp);		return 0;	}	request_region((unsigned int) stuffp->wreg_data,		       MCDX_IO_SIZE, "mcdx");	xtrace(INIT, "init() get garbage\n");	{		int i;		mcdx_delay(stuffp, HZ / 2);		for (i = 100; i; i--)			(void) inb((unsigned int) stuffp->rreg_status);	}#if WE_KNOW_WHY	/* irq 11 -> channel register */	outb(0x50, (unsigned int) stuffp->wreg_chn);#endif	xtrace(INIT, "init() set non dma but irq mode\n");	mcdx_config(stuffp, 1);	stuffp->minor = drive;	sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."		" (Firmware version %c %x)\n",		stuffp->wreg_data, stuffp->irq, version.code, version.ver);	mcdx_stuffp[drive] = stuffp;	xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);	mcdx_info.dev = MKDEV(MAJOR_NR, 0);	if (register_cdrom(&mcdx_info) != 0) {		printk("Cannot register Mitsumi CD-ROM!\n");		release_region((unsigned long) stuffp->wreg_data,			       MCDX_IO_SIZE);		free_irq(stuffp->irq, NULL);		kfree(stuffp);		if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0)			xwarn("cleanup() unregister_blkdev() failed\n");		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));		return 2;	}	devfs_plain_cdrom(&mcdx_info, &mcdx_bdops);	printk(msg);	return 0;}int __init mcdx_init(void){	int drive;#ifdef MODULE	xwarn("Version 2.14(hs) for " UTS_RELEASE "\n");#else	xwarn("Version 2.14(hs) \n");#endif	xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");	/* zero the pointer array */	for (drive = 0; drive < MCDX_NDRIVES; drive++)		mcdx_stuffp[drive] = NULL;	/* do the initialisation */	for (drive = 0; drive < MCDX_NDRIVES; drive++) {		switch (mcdx_init_drive(drive)) {		case 2:			return -EIO;		case 1:			break;		}	}	return 0;}static int mcdx_transfer(struct s_drive_stuff *stuffp,	      char *p, int sector, int nr_sectors)/*	This seems to do the actually transfer.  But it does more.  It	keeps track of errors occurred and will (if possible) fall back	to single speed on error.	Return:	-1 on timeout or other error			else status byte (as in stuff->st) */{	int ans;	ans = mcdx_xfer(stuffp, p, sector, nr_sectors);	return ans;#if FALLBACK	if (-1 == ans)		stuffp->readerrs++;	else		return ans;	if (stuffp->readerrs && stuffp->readcmd == READ1X) {		xwarn("XXX Already reading 1x -- no chance\n");		return -1;	}	xwarn("XXX Fallback to 1x\n");	stuffp->readcmd = READ1X;	return mcdx_transfer(stuffp, p, sector, nr_sectors);#endif}static int mcdx_xfer(struct s_drive_stuff *stuffp,		     char *p, int sector, int nr_sectors)/*	This does actually the transfer from the drive.	Return:	-1 on timeout or other error			else status byte (as in stuff->st) */{	int border;	int done = 0;	long timeout;	if (stuffp->audio) {		xwarn("Attempt to read from audio CD.\n");		return -1;	}	if (!stuffp->readcmd) {		xinfo("Can't transfer from missing disk.\n");		return -1;	}	while (stuffp->lock) {		interruptible_sleep_on(&stuffp->lockq);	}	if (stuffp->valid && (sector >= stuffp->pending)	    && (sector < stuffp->low_border)) {		/* All (or at least a part of the sectors requested) seems		   * to be already requested, so we don't need to bother the		   * drive with new requests ...		   * Wait for the drive become idle, but first		   * check for possible occurred errors --- the drive		   * seems to report them asynchronously */		border = stuffp->high_border < (border =						sector + nr_sectors)		    ? stuffp->high_border : border;		stuffp->lock = current->pid;		do {			while (stuffp->busy) {				timeout =				    interruptible_sleep_on_timeout				    (&stuffp->busyq, 5 * HZ);				if (!stuffp->introk) {					xtrace(XFER,					       "error via interrupt\n");				} else if (!timeout) {					xtrace(XFER, "timeout\n");				} else if (signal_pending(current)) {					xtrace(XFER, "signal\n");				} else					continue;				stuffp->lock = 0;				stuffp->busy = 0;				stuffp->valid = 0;				wake_up_interruptible(&stuffp->lockq);				xtrace(XFER, "transfer() done (-1)\n");				return -1;			}			/* check if we need to set the busy flag (as we			 * expect an interrupt */			stuffp->busy = (3 == (stuffp->pending & 3));			/* Test if it's the first sector of a block,			 * there we have to skip some bytes as we read raw data */			if (stuffp->xa && (0 == (stuffp->pending & 3))) {				const int HEAD =				    CD_FRAMESIZE_RAW - CD_XA_TAIL -				    CD_FRAMESIZE;				insb((unsigned int) stuffp->rreg_data, p,				     HEAD);			}			/* now actually read the data */			insb((unsigned int) stuffp->rreg_data, p, 512);			/* test if it's the last sector of a block,			 * if so, we have to handle XA special */			if ((3 == (stuffp->pending & 3)) && stuffp->xa) {				char dummy[CD_XA_TAIL];				insb((unsigned int) stuffp->rreg_data,				     &dummy[0], CD_XA_TAIL);			}			if (stuffp->pending == sector) {				p += 512;				done++;				sector++;			}		} while (++(stuffp->pending) < border);		stuffp->lock = 0;		wake_up_interruptible(&stuffp->lockq);	} else {		/* The requested sector(s) is/are out of the		 * already requested range, so we have to bother the drive		 * with a new request. */		static unsigned char cmd[] = {			0,			0, 0, 0,			0, 0, 0		};		cmd[0] = stuffp->readcmd;		/* The numbers held in ->pending, ..., should be valid */		stuffp->valid = 1;		stuffp->pending = sector & ~3;		/* do some sanity checks */		if (stuffp->pending > stuffp->lastsector) {			xwarn			    ("transfer() sector %d from nirvana requested.\n",			     stuffp->pending);			stuffp->status = MCDX_ST_EOM;			stuffp->valid = 0;			xtrace(XFER, "transfer() done (-1)\n");			return -1;		}		if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)		    > stuffp->lastsector + 1) {			xtrace(XFER, "cut low_border\n");			stuffp->low_border = stuffp->lastsector + 1;		}		if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)		    > stuffp->lastsector + 1) {			xtrace(XFER, "cut high_border\n");			stuffp->high_border = stuffp->lastsector + 1;		}		{		/* Convert the sector to be requested to MSF format */			struct cdrom_msf0 pending;			log2msf(stuffp->pending / 4, &pending);			cmd[1] = pending.minute;			cmd[2] = pending.second;			cmd[3] = pending.frame;		}		cmd[6] =

⌨️ 快捷键说明

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