Beispiel #1
0
static void do_mcd_request(request_queue_t * q)
{
	test2(printk(" do_mcd_request(%ld+%ld)\n", CURRENT->sector,
	       CURRENT->nr_sectors));

		mcd_transfer_is_active = 1;
	while (current_valid()) {
		mcd_transfer();
		if (CURRENT->nr_sectors == 0) {
			end_request(CURRENT, 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(CURRENT, 0);
						break;
					}
				}
				mcd_state = MCD_S_START;
				McdTries = 5;
				mcd_timer.function = mcd_poll;
				mod_timer(&mcd_timer, jiffies + 1);
			}
			break;
		}
	}
	mcd_transfer_is_active = 0;
	test2(printk(" do_mcd_request ends\n"));
}
Beispiel #2
0
static void
do_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
}
Beispiel #3
0
static void
mcd_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);
}