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

📄 sbpcd.c

📁 LINUX 1.0 内核c源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      return (i);
    }
  i=xx_ReadTocEntry(DS[d].n_first_track);
  if (i<0)
    {
      DPRINTF((DBG_INF,"SBPCD: DiskInfo: xx_ReadTocEntry(1) returns %d\n", i));
      return (i);
    }
  i=xx_ReadUPC();
  if (i<0)
    {
      DPRINTF((DBG_INF,"SBPCD: DiskInfo: xx_ReadUPC returns %d\n", i));
      return (i);
    }
  return (0);
}
/*==========================================================================*/
/*
 *  called always if driver gets entered
 *  returns 0 or ERROR2 or ERROR15
 */
static int prepare(u_char func, u_char subfunc)
{
  int i;

  if (!new_drive)
    {
      i=inb(CDi_status);
      if (i&s_attention) GetStatus();
    }
  else GetStatus();
  if (DS[d].CD_changed==0xFF)
    {
#if MANY_SESSION
#else
      DS[d].diskstate_flags=0;
#endif MANY_SESSION
      DS[d].audio_state=0;
      if (!st_diskok)
	{
	  i=check_allowed1(func,subfunc);
	  if (i<0) return (-2);
	}
      else 
	{
	  i=check_allowed3(func,subfunc);
	  if (i<0)
	    {
	      DS[d].CD_changed=1;
	      return (-15);
	    }
	}
    }
  else
    {
      if (!st_diskok)
	{
#if MANY_SESSION
#else
	  DS[d].diskstate_flags=0;
#endif MANY_SESSION
	  DS[d].audio_state=0;
	  i=check_allowed1(func,subfunc);
	  if (i<0) return (-2);
	}
      else
	{ 
	  if (st_busy)
	    {
	      if (DS[d].audio_state!=audio_pausing)
		{
		  i=check_allowed2(func,subfunc);
		  if (i<0) return (-2);
		}
	    }
	  else
	    {
	      if (DS[d].audio_state==audio_playing) seek_pos_audio_end();
	      DS[d].audio_state=0;
	    }
	  if (!frame_size_valid)
	    {
	      i=DiskInfo();
	      if (i<0)
		{
#if MANY_SESSION
#else
		  DS[d].diskstate_flags=0;
#endif MANY_SESSION
		  DS[d].audio_state=0;
		  i=check_allowed1(func,subfunc);
		  if (i<0) return (-2);
		}
	    }
	}
    }
  return (0);
}
/*==========================================================================*/
static int xx_PlayAudioMSF(int pos_audio_start,int pos_audio_end)
{
  int i;

  if (DS[d].audio_state==audio_playing) return (-EINVAL);
  clr_cmdbuf();
  if (new_drive)
    {
      drvcmd[0]=0x0E;
      flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
                       f_obey_p_check | f_wait_if_busy;
    }
  else
    {
      drvcmd[0]=0x0B;
      flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
                       f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
    }
  drvcmd[1]=(pos_audio_start>>16)&0x00FF;
  drvcmd[2]=(pos_audio_start>>8)&0x00FF;
  drvcmd[3]=pos_audio_start&0x00FF;
  drvcmd[4]=(pos_audio_end>>16)&0x00FF;
  drvcmd[5]=(pos_audio_end>>8)&0x00FF;
  drvcmd[6]=pos_audio_end&0x00FF;
  response_count=0;
  i=cmd_out();
  return (i);
}
/*==========================================================================*/
/*==========================================================================*/

/*==========================================================================*/
/*==========================================================================*/
/*
 * ioctl support, adopted from scsi/sr_ioctl.c and mcd.c
 */
static int sbpcd_ioctl(struct inode *inode,struct file *file,
		       u_int cmd, u_long arg)
{
  int i, st;

  DPRINTF((DBG_IO2,"SBPCD: ioctl(%d, 0x%08lX, 0x%08lX)\n",
				MINOR(inode->i_rdev), cmd, arg));
  if (!inode) return (-EINVAL);
  i=MINOR(inode->i_rdev);
  if ( (i<0) || (i>=NR_SBPCD) )
    {
      printk("SBPCD: ioctl: bad device: %d\n", i);
      return (-ENODEV);             /* no such drive */
    }
  switch_drive(i);

  st=GetStatus();
  if (st<0) return (-EIO);
  
  if (!toc_valid)
    {
      i=DiskInfo();
      if (i<0) return (-EIO);	/* error reading TOC */
    }
  
  DPRINTF((DBG_IO2,"SBPCD: ioctl: device %d, request %04X\n",i,cmd));
  switch (cmd) 		/* Sun-compatible */
    {
    case DDIOCSDBG:		/* DDI Debug */
      if (! suser()) return (-EPERM);
      i = verify_area(VERIFY_READ, (int *) arg, sizeof(int));
      if (i>=0) i=sbpcd_dbg_ioctl(arg,1);
      return (i);

    case CDROMPAUSE:     /* Pause the drive */
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPAUSE entered.\n"));
      /* pause the drive unit when it is currently in PLAY mode,         */
      /* or reset the starting and ending locations when in PAUSED mode. */
      /* If applicable, at the next stopping point it reaches            */
      /* the drive will discontinue playing.                             */
      switch (DS[d].audio_state)
	{
	case audio_playing:
	  i=xx_Pause_Resume(1);
	  if (i<0) return (-EIO);
	  DS[d].audio_state=audio_pausing;
	  i=xx_ReadSubQ();
	  if (i<0) return (-EIO);
	  DS[d].pos_audio_start=DS[d].SubQ_run_tot;
	  return (0);
	case audio_pausing:
	  i=xx_Seek(DS[d].pos_audio_start,1);
	  if (i<0) return (-EIO);
	  return (0);
	default:
	  return (-EINVAL);
	}
      
    case CDROMRESUME: /* resume paused audio play */
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMRESUME entered.\n"));
      /* resume playing audio tracks when a previous PLAY AUDIO call has  */
      /* been paused with a PAUSE command.                                */
      /* It will resume playing from the location saved in SubQ_run_tot.  */
      if (DS[d].audio_state!=audio_pausing) return -EINVAL;
      i=xx_Pause_Resume(3);
      if (i<0) return (-EIO);
      DS[d].audio_state=audio_playing;
      return (0);

    case CDROMPLAYMSF:
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPLAYMSF entered.\n"));
      if (DS[d].audio_state==audio_playing)
	{
	  i=xx_Pause_Resume(1);
	  if (i<0) return (-EIO);
	  i=xx_ReadSubQ();
	  if (i<0) return (-EIO);
	  DS[d].pos_audio_start=DS[d].SubQ_run_tot;
	  i=xx_Seek(DS[d].pos_audio_start,1);
	}
      st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf));
      if (st) return (st);
      memcpy_fromfs(&msf, (void *) arg, sizeof(struct cdrom_msf));
      /* values come as msf-bin */
      DS[d].pos_audio_start = (msf.cdmsf_min0<<16) |
                        (msf.cdmsf_sec0<<8) |
                        msf.cdmsf_frame0;
      DS[d].pos_audio_end = (msf.cdmsf_min1<<16) |
                      (msf.cdmsf_sec1<<8) |
                      msf.cdmsf_frame1;
      DPRINTF((DBG_IOX,"SBPCD: ioctl: CDROMPLAYMSF %08X %08X\n",
	                       DS[d].pos_audio_start,DS[d].pos_audio_end));
      i=xx_PlayAudioMSF(DS[d].pos_audio_start,DS[d].pos_audio_end);
      DPRINTF((DBG_IOC,"SBPCD: ioctl: xx_PlayAudioMSF returns %d\n",i));
#if 0
      if (i<0) return (-EIO);
#endif 0
      DS[d].audio_state=audio_playing;
      return (0);

    case CDROMPLAYTRKIND: /* Play a track.  This currently ignores index. */
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPLAYTRKIND entered.\n"));
      if (DS[d].audio_state==audio_playing)
	{
	  DPRINTF((DBG_IOX,"SBPCD: CDROMPLAYTRKIND: already audio_playing.\n"));
	  return (0);
	  return (-EINVAL);
	}
      st=verify_area(VERIFY_READ,(void *) arg,sizeof(struct cdrom_ti));
      if (st<0)
	{
	  DPRINTF((DBG_IOX,"SBPCD: CDROMPLAYTRKIND: verify_area error.\n"));
	  return (st);
	}
      memcpy_fromfs(&ti,(void *) arg,sizeof(struct cdrom_ti));
      DPRINTF((DBG_IOX,"SBPCD: ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
	     ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1));
      if (ti.cdti_trk0<DS[d].n_first_track) return (-EINVAL);
      if (ti.cdti_trk0>DS[d].n_last_track) return (-EINVAL);
      if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
      if (ti.cdti_trk1>DS[d].n_last_track) ti.cdti_trk1=DS[d].n_last_track;
      DS[d].pos_audio_start=DS[d].TocBuffer[ti.cdti_trk0].address;
      DS[d].pos_audio_end=DS[d].TocBuffer[ti.cdti_trk1+1].address;
      i=xx_PlayAudioMSF(DS[d].pos_audio_start,DS[d].pos_audio_end);
#if 0
      if (i<0) return (-EIO);
#endif 0
      DS[d].audio_state=audio_playing;
      return (0);
	    
    case CDROMREADTOCHDR:        /* Read the table of contents header */
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADTOCHDR entered.\n"));
      tochdr.cdth_trk0=DS[d].n_first_track;
      tochdr.cdth_trk1=DS[d].n_last_track;
      st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_tochdr));
      if (st) return (st);
      memcpy_tofs((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
      return (0);

    case CDROMREADTOCENTRY:      /* Read an entry in the table of contents */
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADTOCENTRY entered.\n"));
      st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_tocentry));
      if (st) return (st);
      memcpy_fromfs(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
      i=tocentry.cdte_track;
      if (i==CDROM_LEADOUT) i=DS[d].n_last_track+1;
      else if (i<DS[d].n_first_track||i>DS[d].n_last_track) return (-EINVAL);
      tocentry.cdte_adr=DS[d].TocBuffer[i].ctl_adr&0x0F;
      tocentry.cdte_ctrl=(DS[d].TocBuffer[i].ctl_adr>>4)&0x0F;
      tocentry.cdte_datamode=DS[d].TocBuffer[i].format;
      if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
	{ tocentry.cdte_addr.msf.minute=(DS[d].TocBuffer[i].address>>16)&0x00FF;
	  tocentry.cdte_addr.msf.second=(DS[d].TocBuffer[i].address>>8)&0x00FF;
	  tocentry.cdte_addr.msf.frame=DS[d].TocBuffer[i].address&0x00FF;
	}
      else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
	tocentry.cdte_addr.lba=msf2blk(DS[d].TocBuffer[i].address);
      else return (-EINVAL);
      st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry));
      if (st) return (st);
      memcpy_tofs((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
      return (0);

    case CDROMSTOP:      /* Spin down the drive */
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMSTOP entered.\n"));
      i=DriveReset();
#if WORKMAN
      DS[d].CD_changed=0xFF;
      DS[d].diskstate_flags=0;
#endif WORKMAN
      DPRINTF((DBG_IOC,"SBPCD: ioctl: DriveReset returns %d\n",i));
      DS[d].audio_state=0;
      i=DiskInfo();
      return (0);

    case CDROMSTART:  /* Spin up the drive */
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMSTART entered.\n"));
      i=xx_SpinUp();
      DS[d].audio_state=0;
      return (0);
      
    case CDROMEJECT:
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMEJECT entered.\n"));
      if (!new_drive) return (0);
#if WORKMAN
      DS[d].CD_changed=0xFF;
      DS[d].diskstate_flags=0;
#endif WORKMAN
      i=yy_SpinDown();
      if (i<0) return (-EIO);
      DS[d].audio_state=0;
      return (0);
      
    case CDROMVOLCTRL:   /* Volume control */
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMVOLCTRL entered.\n"));
      st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl));
      if (st) return (st);
      memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl));
      DS[d].vol_chan0=0;
      DS[d].vol_ctrl0=volctrl.channel0;
      DS[d].vol_chan1=1;
      DS[d].vol_ctrl1=volctrl.channel1;
      i=xx_SetVolume();
      return (0);

    case CDROMSUBCHNL:   /* Get subchannel info */
      DPRINTF((DBG_IOS,"SBPCD: ioctl: CDROMSUBCHNL entered.\n"));
      if ((st_spinning)||(!subq_valid)) { i=xx_ReadSubQ();
					  if (i<0) return (-EIO);
					}
      st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
      if (st)	return (st);
      memcpy_fromfs(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
#if 0
      if (DS[d].SubQ_audio==0x80) DS[d].SubQ_audio=CDROM_AUDIO_NO_STATUS;
#endif
      switch (DS[d].audio_state)
	{
	case audio_playing:
	  SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
	  break;
	case audio_pausing:
	  SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
	  break;
	default:
	  SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
	  break;
	}
      SC.cdsc_adr=DS[d].SubQ_ctl_adr;
      SC.cdsc_ctrl=DS[d].SubQ_ctl_adr>>4;
      SC.cdsc_trk=bcd2bin(DS[d].SubQ_trk);
      SC.cdsc_ind=bcd2bin(DS[d].SubQ_pnt_idx);
      if (SC.cdsc_format==CDROM_LBA)
	{
	  SC.cdsc_absaddr.lba=msf2blk(DS[d].SubQ_run_tot);
	  SC.cdsc_reladdr.lba=msf2blk(DS[d].SubQ_run_trk);
	}
      else /* not only if (SC.cdsc_format==CDROM_MSF) */
	{
	  SC.cdsc_absaddr.msf.minute=(DS[d].SubQ_run_tot>>16)&0x00FF;
	  SC.cdsc_absaddr.msf.second=(DS[d].SubQ_run_tot>>8)&0x00FF;
	  SC.cdsc_absaddr.msf.frame=DS[d].SubQ_run_tot&0x00FF;
	  SC.cdsc_reladdr.msf.minute=(DS[d].SubQ_run_trk>>16)&0x00FF;
	  SC.cdsc_reladdr.msf.second=(DS[d].SubQ_run_trk>>8)&0x00FF;
	  SC.cdsc_reladdr.msf.frame=DS[d].SubQ_run_trk&0x00FF;
	}
      memcpy_tofs((void *) arg, &SC, sizeof(struct cdrom_subchnl));
      DPRINTF((DBG_IOS,"SBPCD: CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
	       SC.cdsc_format,SC.cdsc_audiostatus,
	       SC.cdsc_adr,SC.cdsc_ctrl,
	       SC.cdsc_trk,SC.cdsc_ind,
	       SC.cdsc_absaddr,SC.cdsc_reladdr));
      return (0);

    case CDROMREADMODE2:
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADMODE2 requested.\n"));
      return (-EINVAL);

    case CDROMREADMODE1:
      DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADMODE1 requested.\n"));
      return (-EINVAL);
      
    default:
      DPRINTF((DBG_IOC,"SBPCD: ioctl: unknown function request %04X\n", cmd));
      return (-EINVAL);
    } /* end switch(cmd) */
}
/*==========================================================================*/
/*
 *  Take care of the different block sizes between cdrom and Linux.
 *  When Linux gets variable block sizes this will probably go away.
 */
static void sbp_transfer(void)
{
  long offs;
  
  while ( (CURRENT->nr_sectors > 0) &&
	  (CURRENT->sector/4 >= DS[d].sbp_first_frame) &&
	  (CURRENT->sector/4 <= DS[d].sbp_last_frame) )
    {
      offs = (CURRENT->sector - DS[d].sbp_first_frame * 4) * 512;
      memcpy(CURRENT->buffer, DS[d].sbp_buf + offs, 512);
      CURRENT->nr_sectors--;
      CURRENT->sector++;
      CURRENT->buffer += 512;
    }
}
/*==========================================================================*/
/*
 *  We seem to get never an interrupt.
 */
#if SBPCD_USE_IRQ
static void sbpcd_interrupt(int unused)
{
  int st;
  
  st = inb(CDi_status) & 0xFF;
  DPRINTF((DBG_IRQ,"SBPCD: INTERRUPT received - CDi_status=%02X\n", st));
}
#endif SBPCD_USE_IRQ
/*==========================================================================*/
/*
 * Called from the timer to check the results of the get-status cmd.
 */
static int sbp_status(void)
{
  int st;

  st=ResponseStatus();
  if (st<0)
    {
      DPRINTF((DBG_INF,"SBPCD: sbp_status: timeout.\n"));
      return (0);
    }

  if (!st_spinning) DPRINTF((DBG_SPI,"SBPCD: motor got off - ignoring.\n"));

  if (st_check) 
    {
      DPRINTF((DBG_INF,"SBPCD: st_check detected - retrying.\n"));
      return (0);
    }
  if (!st_door_closed)
    {
    

⌨️ 快捷键说明

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