?? sbpcd.c
字號:
{#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 + -