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

📄 sbpcd.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 5 页
字号:
		{#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_IRQstatic 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)    {      DPRINTF((DBG_INF,"SBPCD: door is open - retrying.\n"));      return (0);    }  if (!st_caddy_in)    {      DPRINTF((DBG_INF,"SBPCD: disk removed - retrying.\n"));      return (0);    }  if (!st_diskok)     {      DPRINTF((DBG_INF,"SBPCD: !st_diskok detected - retrying.\n"));      return (0);    }  if (st_busy)     {      DPRINTF((DBG_INF,"SBPCD: st_busy detected - retrying.\n"));      return (0);    }  return (1);}/*==========================================================================*//* *  I/O request routine, called from Linux kernel. */static void do_sbpcd_request(void){  u_int block;  int dev;  u_int nsect;  int i, status_tries, data_tries;  request_loop:  sti();  if ((CURRENT==NULL)||(CURRENT->dev<0)) return;  if (CURRENT -> sector == -1)	return;  dev = MINOR(CURRENT->dev);  if ( (dev<0) || (dev>=NR_SBPCD) )    {      printk("SBPCD: do_request: bad device: %d\n", dev);      return;    }  switch_drive(dev);  INIT_REQUEST;  block = CURRENT->sector;  nsect = CURRENT->nr_sectors;  if (CURRENT->cmd != READ)    {      printk("SBPCD: bad cmd %d\n", CURRENT->cmd);      end_request(0);      goto request_loop;    }  DPRINTF((DBG_MUL,"SBPCD: read LBA %d\n", block/4));  sbp_transfer();  /* if we satisfied the request from the buffer, we're done. */  if (CURRENT->nr_sectors == 0)    {      end_request(1);      goto request_loop;    }  i=prepare(0,0); /* at moment not really a hassle check, but ... */  if (i!=0) DPRINTF((DBG_INF,"SBPCD: \"prepare\" tells error %d -- ignored\n", i));  if (!st_spinning) xx_SpinUp();  for (data_tries=3; data_tries > 0; data_tries--)    {      for (status_tries=3; status_tries > 0; status_tries--)	{	  flags_cmd_out |= f_respo3;	  xx_ReadStatus();	  if (sbp_status() != 0) break;	  sbp_sleep(1);    /* wait a bit, try again */	}      if (status_tries == 0)	{	  DPRINTF((DBG_INF,"SBPCD: sbp_status: failed after 3 tries\n"));	  break;	}      sbp_read_cmd();      sbp_sleep(0);      if (sbp_data() != 0)	{	  end_request(1);	  goto request_loop;	}    }    end_request(0);  sbp_sleep(10);    /* wait a bit, try again */  goto request_loop;}/*==========================================================================*//* *  build and send the READ comm

⌨️ 快捷键说明

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