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

📄 mcd.c

📁 powerpc内核 mpc8241芯片 linux系统下cdrom驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		subchnl->cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);		subchnl->cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);		subchnl->cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);		subchnl->cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);		subchnl->cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);		return(0);	case CDROMVOLCTRL:   /* Volume control */		volctrl=(struct cdrom_volctrl *) arg;		outb(MCMD_SET_VOLUME, MCDPORT(0));		outb(volctrl->channel0, MCDPORT(0));		outb(255, MCDPORT(0));		outb(volctrl->channel1, MCDPORT(0));		outb(255, MCDPORT(0));		i = getMcdStatus(MCD_STATUS_DELAY);		if (i < 0)			return -EIO;		{			char a, b, c, d;			getValue(&a);			getValue(&b);			getValue(&c);			getValue(&d);		}		return 0;	default:		return -EINVAL;	}}/* * Take care of the different block sizes between cdrom and Linux. * When Linux gets variable block sizes this will probably go away. */static voidmcd_transfer(void){  if (CURRENT_VALID) {    while (CURRENT -> nr_sectors) {      int bn = CURRENT -> sector / 4;      int i;      for (i = 0; i < MCD_BUF_SIZ && mcd_buf_bn[i] != bn; ++i)	;      if (i < MCD_BUF_SIZ) {	int offs = (i * 4 + (CURRENT -> sector & 3)) * 512;	int nr_sectors = 4 - (CURRENT -> sector & 3);	if (mcd_buf_out != i) {	  mcd_buf_out = i;	  if (mcd_buf_bn[i] != bn) {	    mcd_buf_out = -1;	    continue;	  }	}	if (nr_sectors > CURRENT -> nr_sectors)	  nr_sectors = CURRENT -> nr_sectors;	memcpy(CURRENT -> buffer, mcd_buf + offs, nr_sectors * 512);	CURRENT -> nr_sectors -= nr_sectors;	CURRENT -> sector += nr_sectors;	CURRENT -> buffer += nr_sectors * 512;      } else {	mcd_buf_out = -1;	break;      }    }  }}/* * We only seem to get interrupts after an error. * Just take the interrupt and clear out the status reg. */static voidmcd_interrupt(int irq, void *dev_id, struct pt_regs * regs){	int st;	st = inb(MCDPORT(1)) & 0xFF;#ifdef TEST1		printk("<int1-%02X>", st);#endif	if (!(st & MFL_STATUS))	{		st = inb(MCDPORT(0)) & 0xFF;#ifdef TEST1		printk("<int0-%02X>", st);#endif		if ((st & 0xFF) != 0xFF)		  mcd_error = st ? st & 0xFF : -1;	}}static voiddo_mcd_request(void){#ifdef TEST2  printk(" do_mcd_request(%ld+%ld)\n", CURRENT -> sector, CURRENT -> nr_sectors);#endif  mcd_transfer_is_active = 1;  while (CURRENT_VALID) {    if (CURRENT->bh) {      if (!buffer_locked(CURRENT->bh))	panic(DEVICE_NAME ": block not locked");    }    mcd_transfer();    if (CURRENT -> nr_sectors == 0) {      end_request(1);    } else {      mcd_buf_out = -1;		/* Want to read a block not in buffer */      if (mcd_state == MCD_S_IDLE) {	if (!tocUpToDate) {	  if (updateToc() < 0) {	    while (CURRENT_VALID)	      end_request(0);	    break;	  }	}	mcd_state = MCD_S_START;	McdTries = 5;	SET_TIMER(mcd_poll, 1);      }      break;    }  }  mcd_transfer_is_active = 0;#ifdef TEST2  printk(" do_mcd_request ends\n");#endif}static voidmcd_poll(void){  int st;  if (mcd_error)   {    if (mcd_error & 0xA5)     {      printk("mcd: I/O error 0x%02x", mcd_error);      if (mcd_error & 0x80)	printk(" (Door open)");      if (mcd_error & 0x20)	printk(" (Disk changed)");      if (mcd_error & 0x04)	{	printk(" (Read error)"); /* Bitch about the problem. */		/* Time to get fancy! If at 2x speed and 1 error, drop to 1x speed! */	/* Interesting how it STAYS at MCD_RETRY_ATTEMPTS on first error! */	/* But I find that rather HANDY!!! */	/* Neat! it REALLY WORKS on those LOW QUALITY CD's!!! Smile! :) */	/* AJK [06/17/95] */		/* Slap the CD down to single speed! */	if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_2X_READ) 		{		MCMD_DATA_READ = MCMD_PLAY_READ; /* Uhhh, Ummmm, muhuh-huh! */		mcd1xhold = SINGLE_HOLD_SECTORS; /* Hey Beavis! */		printk(" Speed now 1x");	 /* Pull my finger! */		}	}      printk("\n");      mcd_invalidate_buffers();#ifdef WARN_IF_READ_FAILURE      if (McdTries == MCD_RETRY_ATTEMPTS)	printk("mcd: read of block %d failed\n", mcd_next_bn);#endif      if (!McdTries--)         {	/* Nuts! This cd is ready for recycling! */	/* When WAS the last time YOU cleaned it CORRECTLY?! */	printk("mcd: read of block %d failed, giving up\n", mcd_next_bn);	if (mcd_transfer_is_active) 	{	  McdTries = 0;	  goto ret;	}	if (CURRENT_VALID)	  end_request(0);	McdTries = MCD_RETRY_ATTEMPTS;      }    }    mcd_error = 0;    mcd_state = MCD_S_STOP;  }	/* Switch back to Double speed if enough GOOD sectors were read! */		/* Are we a double speed with a crappy CD?! */    if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_PLAY_READ)    	{	/* We ARE a double speed and we ARE bitching! */	if (mcd1xhold == 0) /* Okay, Like are we STILL at single speed? */		{ /* We need to switch back to double speed now... */		MCMD_DATA_READ = MCMD_2X_READ; /* Uhhh... BACK You GO! */		printk("mcd: Switching back to 2X speed!\n"); /* Tell 'em! */		}	else mcd1xhold--; /* No?! Count down the good reads some more... */				/* and try, try again! */    	} immediately:  switch (mcd_state) {  case MCD_S_IDLE:#ifdef TEST3    printk("MCD_S_IDLE\n");#endif    return;  case MCD_S_START:#ifdef TEST3    printk("MCD_S_START\n");#endif    outb(MCMD_GET_STATUS, MCDPORT(0));    mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE;    McdTimeout = 3000;    break;  case MCD_S_MODE:#ifdef TEST3    printk("MCD_S_MODE\n");#endif    if ((st = mcdStatus()) != -1) {      if (st & MST_DSK_CHG) {	mcdDiskChanged = 1;	tocUpToDate = 0;	mcd_invalidate_buffers();      }    set_mode_immediately:      if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {	mcdDiskChanged = 1;	tocUpToDate = 0;	if (mcd_transfer_is_active) {	  mcd_state = MCD_S_START;	  goto immediately;	}	printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n");	mcd_state = MCD_S_IDLE;	while (CURRENT_VALID)	  end_request(0);	return;      }      outb(MCMD_SET_MODE, MCDPORT(0));      outb(1, MCDPORT(0));      mcd_mode = 1;      mcd_state = MCD_S_READ;      McdTimeout = 3000;    }    break;  case MCD_S_READ:#ifdef TEST3    printk("MCD_S_READ\n");#endif    if ((st = mcdStatus()) != -1) {      if (st & MST_DSK_CHG) {	mcdDiskChanged = 1;	tocUpToDate = 0;	mcd_invalidate_buffers();      }    read_immediately:      if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {	mcdDiskChanged = 1;	tocUpToDate = 0;	if (mcd_transfer_is_active) {	  mcd_state = MCD_S_START;	  goto immediately;	}	printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n");	mcd_state = MCD_S_IDLE;	while (CURRENT_VALID)	  end_request(0);	return;      }      if (CURRENT_VALID) {	struct mcd_Play_msf msf;	mcd_next_bn = CURRENT -> sector / 4;	hsg2msf(mcd_next_bn, &msf.start);	msf.end.min = ~0;	msf.end.sec = ~0;	msf.end.frame = ~0;	sendMcdCmd(MCMD_DATA_READ, &msf);	mcd_state = MCD_S_DATA;	McdTimeout = READ_TIMEOUT;      } else {	mcd_state = MCD_S_STOP;	goto immediately;      }    }    break;  case MCD_S_DATA:#ifdef TEST3    printk("MCD_S_DATA\n");#endif    st = inb(MCDPORT(1)) & (MFL_STATUSorDATA);  data_immediately:#ifdef TEST5    printk("Status %02x\n",st);#endif    switch (st) {    case MFL_DATA:#ifdef WARN_IF_READ_FAILURE      if (McdTries == 5)	printk("mcd: read of block %d failed\n", mcd_next_bn);#endif      if (!McdTries--) {	printk("mcd: read of block %d failed, giving up\n", mcd_next_bn);	if (mcd_transfer_is_active) {	  McdTries = 0;	  break;	}	if (CURRENT_VALID)	  end_request(0);	McdTries = 5;      }      mcd_state = MCD_S_START;      McdTimeout = READ_TIMEOUT;      goto immediately;    case MFL_STATUSorDATA:      break;    default:      McdTries = 5;      if (!CURRENT_VALID && mcd_buf_in == mcd_buf_out) {	mcd_state = MCD_S_STOP;	goto immediately;      }      mcd_buf_bn[mcd_buf_in] = -1;      READ_DATA(MCDPORT(0), mcd_buf + 2048 * mcd_buf_in, 2048);      mcd_buf_bn[mcd_buf_in] = mcd_next_bn++;      if (mcd_buf_out == -1)	mcd_buf_out = mcd_buf_in;      mcd_buf_in = mcd_buf_in + 1 == MCD_BUF_SIZ ? 0 : mcd_buf_in + 1;      if (!mcd_transfer_is_active) {	while (CURRENT_VALID) {	  mcd_transfer();	  if (CURRENT -> nr_sectors == 0)	    end_request(1);	  else	    break;	}      }      if (CURRENT_VALID	  && (CURRENT -> sector / 4 < mcd_next_bn || 	      CURRENT -> sector / 4 > mcd_next_bn + 16)) {	mcd_state = MCD_S_STOP;	goto immediately;      }      McdTimeout = READ_TIMEOUT;#ifdef DOUBLE_QUICK_ONLY      if (MCMD_DATA_READ != MCMD_PLAY_READ)#endif      {	int count= QUICK_LOOP_COUNT;	while (count--) {          QUICK_LOOP_DELAY;	  if ((st = (inb(MCDPORT(1))) & (MFL_STATUSorDATA)) != (MFL_STATUSorDATA)) {#   ifdef TEST4/*	    printk("Quickloop success at %d\n",QUICK_LOOP_COUNT-count); */	    printk(" %d ",QUICK_LOOP_COUNT-count);#   endif	    goto data_immediately;	  }	}#   ifdef TEST4/*      printk("Quickloop ended at %d\n",QUICK_LOOP_COUNT); */	printk("ended ");#   endif      }      break;    }    break;  case MCD_S_STOP:#ifdef TEST3    printk("MCD_S_STOP\n");#endif#ifdef WORK_AROUND_MITSUMI_BUG_93    if (!mitsumi_bug_93_wait)      goto do_not_work_around_mitsumi_bug_93_1;    McdTimeout = mitsumi_bug_93_wait;    mcd_state = 9+3+1;    break;  case 9+3+1:    if (McdTimeout)      break;  do_not_work_around_mitsumi_bug_93_1:#endif /* WORK_AROUND_MITSUMI_BUG_93 */    outb(MCMD_STOP, MCDPORT(0));#ifdef WORK_AROUND_MITSUMI_BUG_92    if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {      int i = 4096;      do {	inb(MCDPORT(0));      } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);      outb(MCMD_STOP, MCDPORT(0));      if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {	i = 4096;	do {	  inb(MCDPORT(0));	} while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);	outb(MCMD_STOP, MCDPORT(0));      }    }#endif /* WORK_AROUND_MITSUMI_BUG_92 */    mcd_state = MCD_S_STOPPING;    McdTimeout = 1000;    break;  case MCD_S_STOPPING:#ifdef TEST3    printk("MCD_S_STOPPING\n");#endif    if ((st = mcdStatus()) == -1 && McdTimeout)      break;    if ((st != -1) && (st & MST_DSK_CHG)) {      mcdDiskChanged = 1;      tocUpToDate = 0;      mcd_invalidate_buffers();    }#ifdef WORK_AROUND_MITSUMI_BUG_93    if (!mitsumi_bug_93_wait)      goto do_not_work_around_mitsumi_bug_93_2;    McdTimeout = mitsumi_bug_93_wait;    mcd_state = 9+3+2;    break;  case 9+3+2:    if (McdTimeout)      break;    st = -1;  do_not_work_around_mitsumi_bug_93_2:#endif /* WORK_AROUND_MITSUMI_BUG_93 */#ifdef TEST3    printk("CURRENT_VALID %d mcd_mode %d\n",	   CURRENT_VALID, mcd_mode);#endif    if (CURRENT_VALID) {      if (st != -1) {	if (mcd_mode == 1)	  goto read_immediately;	else	  goto set_mode_immediately;      } else {	mcd_state = MCD_S_START;	McdTimeout = 1;      }    } else {      mcd_state = MCD_S_IDLE;      return;    }    break;  default:    printk("mcd: invalid state %d\n", mcd_state);    return;  } ret:  if (!McdTimeout--) {    printk("mcd: timeout in state %d\n", mcd_state);    mcd_state = MCD_S_STOP;  }  SET_TIMER(mcd_poll, 1);}static voidmcd_invalidate_buffers(void){  int i;  for (i = 0; i < MCD_BUF_SIZ; ++i)    mcd_buf_bn[i] = -1;  mcd_buf_out = -1;}/* * Open the device special file.  Check that a disk is in. */static int mcd_open(struct cdrom_device_info * cdi, int purpose){	int st, count=0;	if (mcdPresent == 0)		return -ENXIO;			/* no hardware */        if (!mcd_open_count && mcd_state == MCD_S_IDLE) {        mcd_invalidate_buffers();        do {                st = statusCmd();               /* check drive status */

⌨️ 快捷键说明

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