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

📄 mcd.c

📁 powerpc内核 mpc8241芯片 linux系统下cdrom驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
                if (st == -1)                        return -EIO;            /* drive doesn't respond */                if ((st & MST_READY) == 0) {    /* no disk? wait a sec... */                        current->state = TASK_INTERRUPTIBLE;                        schedule_timeout(HZ);                }        } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);        if (updateToc() < 0)                       return -EIO;        }	++mcd_open_count;        MOD_INC_USE_COUNT;	return 0;}/* * On close, we flush all mcd blocks from the buffer cache. */static void mcd_release(struct cdrom_device_info * cdi){ MOD_DEC_USE_COUNT;  if (!--mcd_open_count) {	mcd_invalidate_buffers();  }}/* This routine gets called during initialization if things go wrong, * and is used in cleanup_module as well. */static void cleanup(int level){  switch (level) {  case 3:    if (unregister_cdrom(&mcd_info)) {      printk(KERN_WARNING "Can't unregister cdrom mcd\n");      return;    }    free_irq(mcd_irq, NULL);  case 2:    release_region(mcd_port,4);  case 1:    if (unregister_blkdev(MAJOR_NR, "mcd")) {      printk(KERN_WARNING "Can't unregister major mcd\n");      return;    }  default:  }}/* * Test for presence of drive and initialize it.  Called at boot time. */__initfunc(int mcd_init(void)){	int count;	unsigned char result[3];	char msg[80];	if (mcd_port <= 0 || mcd_irq <= 0) {	  printk("skip mcd_init\n");          return -EIO;	}	if (register_blkdev(MAJOR_NR, "mcd", &cdrom_fops) != 0)	{		printk("Unable to get major %d for Mitsumi CD-ROM\n",		       MAJOR_NR);                return -EIO;	}        if (check_region(mcd_port, 4)) {	  cleanup(1);	  printk("Init failed, I/O port (%X) already in use\n",		 mcd_port);          return -EIO;	}	blksize_size[MAJOR_NR] = mcd_blocksizes;	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 < 2000000; count++)		(void) inb(MCDPORT(1));		/* delay a bit */	outb(0x40, MCDPORT(0));	                /* send get-stat cmd */	for (count = 0; count < 2000000; count++)		if (!(inb(MCDPORT(1)) & MFL_STATUS))			break;	if (count >= 2000000) {		printk("Init failed. No mcd device at 0x%x irq %d\n",		     mcd_port, mcd_irq);		cleanup(1);                return -EIO;	}	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("mitsumi get version failed at 0x%d\n",			       mcd_port);                        cleanup(1);                        return -EIO;		}		if (result[0] == result[1] && result[1] == result[2]) {		cleanup(1);                return -EIO;	}	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 (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL))	{		printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);		cleanup(1);                return -EIO;	}        if (result[1] == 'D') 	{		sprintf(msg, " mcd: Mitsumi Double Speed CD-ROM at port=0x%x,"			     " irq=%d\n", mcd_port, mcd_irq);		MCMD_DATA_READ = MCMD_2X_READ;		mcd_info.speed = 2;		/* Added flag to drop to 1x speed if too many errors */		mcdDouble = 1;        } else {		sprintf(msg, " mcd: Mitsumi Single Speed CD-ROM at port=0x%x,"			     " irq=%d\n", mcd_port, mcd_irq);		mcd_info.speed = 2;	}	request_region(mcd_port, 4, "mcd");	outb(MCMD_CONFIG_DRIVE, MCDPORT(0));	outb(0x02,MCDPORT(0));	outb(0x00,MCDPORT(0));	getValue(result);	outb(MCMD_CONFIG_DRIVE, MCDPORT(0));	outb(0x10,MCDPORT(0));	outb(0x04,MCDPORT(0));	getValue(result);	mcd_invalidate_buffers();	mcdPresent = 1;	mcd_info.dev = MKDEV(MAJOR_NR,0);        if (register_cdrom(&mcd_info) != 0) {              printk("Cannot register Mitsumi CD-ROM!\n");              cleanup(3);              return -EIO;        }        printk(msg);	return 0;}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;}/* gives current state of the drive This function is quite unreliable,    and should probably be rewritten by someone, eventually... */int mcd_drive_status(struct cdrom_device_info * cdi, int slot_nr){  int st;  st = statusCmd();               /* check drive status */  if (st == -1)      return -EIO;            /* drive doesn't respond */  if ((st & MST_READY)) return CDS_DISC_OK;  if ((st & MST_DOOR_OPEN)) return CDS_TRAY_OPEN;  if ((st & MST_DSK_CHG)) return CDS_NO_DISC;  if ((st & MST_BUSY)) return CDS_DRIVE_NOT_READY;  return -EIO;}/* * Read a value from the drive. */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 necessary */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);#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	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;	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 */		mcd_mode = 0x05;		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));		mcd_mode = 1;                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;}#ifdef MODULEint init_module(void){	return mcd_init();}void cleanup_module(void){  cleanup(3);}#endif MODULE

⌨️ 快捷键说明

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