diff options
Diffstat (limited to 'drivers/cdrom/sbpcd.c')
-rw-r--r-- | drivers/cdrom/sbpcd.c | 879 |
1 files changed, 532 insertions, 347 deletions
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 401dbc657..08de5a794 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -13,7 +13,7 @@ * labelled E2550UA or MK4015 or 2800F). */ -#define VERSION "v4.6 Eberhard Moenkeberg <emoenke@gwdg.de>" +#define VERSION "v4.61 Eberhard Moenkeberg <emoenke@gwdg.de>" /* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de> * @@ -300,6 +300,10 @@ * Experiments to speed up the CD-55A; again with help of Rob Riggs * (to be true, he gave both, idea & code. ;-) * + * 4.61 Ported to Uniform CD-ROM driver by + * Heiko Eissfeldt <heiko@colossus.escape.de> with additional + * changes by Erik Andersen <andersee@debian.org> + * * * TODO * implement "read all subchannel data" (96 bytes per frame) @@ -334,8 +338,8 @@ #include <asm/io.h> #include <asm/uaccess.h> #include <stdarg.h> -#include <linux/sbpcd.h> #include <linux/config.h> +#include "sbpcd.h" #if !(SBPCD_ISSUE-1) #define MAJOR_NR MATSUSHITA_CDROM_MAJOR @@ -404,6 +408,7 @@ static int sbpcd[] = CDROM_PORT, SBPRO, /* probe with user's setup first */ #if DISTRIBUTION 0x230, 1, /* Soundblaster Pro and 16 (default) */ +#if 0 0x300, 0, /* CI-101P (default), WDH-7001C (default), Galaxy (default), Reveal (one default) */ 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */ @@ -438,6 +443,7 @@ static int sbpcd[] = 0x290, 1, /* Soundblaster 16 */ 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */ #endif MODULE +#endif #endif DISTRIBUTION }; #else @@ -523,7 +529,7 @@ static int sbpcd_chk_disk_change(kdev_t); #if DISTRIBUTION static int sbpcd_debug = (1<<DBG_INF); #else -static int sbpcd_debug = ((1<<DBG_INF) | +static int sbpcd_debug = 0 & ((1<<DBG_INF) | (1<<DBG_TOC) | (1<<DBG_MUL) | (1<<DBG_UPC)); @@ -558,7 +564,7 @@ static const char *str_ss = "SoundScape"; static const char *str_ss_l = "soundscape"; static const char *str_t16 = "Teac16bit"; static const char *str_t16_l = "teac16bit"; -const char *type; +static const char *type; #if !(SBPCD_ISSUE-1) static const char *major_name="sbpcd"; @@ -736,7 +742,8 @@ static struct { u_char mode_yb_7; u_char mode_xb_8; u_char delay; - + struct cdrom_device_info *sbpcd_infop; + } D_S[NR_SBPCD]; /* @@ -1990,6 +1997,7 @@ static int cc_DriveReset(void) if (D_S[d].error_byte!=aud_12) return -501; return (0); } + /*==========================================================================*/ static int SetSpeed(void) { @@ -2005,6 +2013,19 @@ static int SetSpeed(void) i=cc_SetSpeed(speed,0,0); return (i); } + +static void switch_drive(int i); + +static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed) +{ + int i = MINOR(cdi->dev); + + if (i != d) + switch_drive(i); + + return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0); +} + /*==========================================================================*/ static int DriveReset(void) { @@ -2030,6 +2051,17 @@ static int DriveReset(void) } return (0); } + +static int sbpcd_reset(struct cdrom_device_info *cdi) +{ + int i = MINOR(cdi->dev); + + if (i != d) + switch_drive(i); + + return DriveReset(); +} + /*==========================================================================*/ static int cc_PlayAudio(int pos_audio_start,int pos_audio_end) { @@ -2220,6 +2252,12 @@ static int LockDoor(void) } return (i); } + +static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock) +{ + return lock ? LockDoor() : UnLockDoor(); +} + /*==========================================================================*/ static int cc_CloseTray(void) { @@ -2261,6 +2299,12 @@ static int cc_CloseTray(void) msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed); return (i); } + +static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position) +{ + return position ? cc_CloseTray() : 0; +} + /*==========================================================================*/ static int cc_ReadSubQ(void) { @@ -2956,6 +3000,79 @@ static int cc_ReadUPC(void) D_S[d].diskstate_flags |= upc_bit; return (0); } + +static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) +{ + int i; + unsigned char *mcnp = mcn->medium_catalog_number; + unsigned char *resp; + + D_S[d].diskstate_flags &= ~upc_bit; + clr_cmdbuf(); + if (fam1_drive) + { + drvcmd[0]=CMD1_READ_UPC; + response_count=8; + flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check; + } + else if (fam0L_drive) + { + drvcmd[0]=CMD0_READ_UPC; + response_count=0; + flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1; + } + else if (fam2_drive) + { + return (-1); + } + else if (famT_drive) + { + return (-1); + } + i=cmd_out(); + if (i<0) + { + msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i); + return (i); + } + if (fam0L_drive) + { + response_count=16; + if (famL_drive) flags_cmd_out=f_putcmd; + i=cc_ReadPacket(); + if (i<0) + { + msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i); + return (i); + } + } + D_S[d].UPC_ctl_adr=0; + if (fam1_drive) i=0; + else i=2; + + resp = infobuf + i; + if (*resp++ == 0x80) { + /* packed bcd to single ASCII digits */ + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + *mcnp++ = (*resp++ & 0x0f) + '0'; + *mcnp++ = (*resp >> 4) + '0'; + } + *mcnp = '\0'; + + D_S[d].diskstate_flags |= upc_bit; + return (0); +} + /*==========================================================================*/ static int cc_CheckMultiSession(void) { @@ -3716,6 +3833,21 @@ static int ReadToC(void) int i, j; D_S[d].diskstate_flags &= ~toc_bit; D_S[d].ored_ctl_adr=0; + /* special handling of CD-I HE */ + if ((D_S[d].n_first_track == 2 && D_S[d].n_last_track == 2) || + D_S[d].xa_byte == 0x10) + { + D_S[d].TocBuffer[1].nixbyte=0; + D_S[d].TocBuffer[1].ctl_adr=0x40; + D_S[d].TocBuffer[1].number=1; + D_S[d].TocBuffer[1].format=0; + D_S[d].TocBuffer[1].address=blk2msf(0); + D_S[d].ored_ctl_adr |= 0x40; + D_S[d].n_first_track = 1; + D_S[d].n_last_track = 1; + D_S[d].xa_byte = 0x10; + j = 2; + } else for (j=D_S[d].n_first_track;j<=D_S[d].n_last_track;j++) { i=cc_ReadTocEntry(j); @@ -3801,7 +3933,7 @@ static int DiskInfo(void) } i=cc_ReadUPC(); if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i); - if ((fam0L_drive) && (D_S[d].xa_byte==0x20)) + if ((fam0L_drive) && (D_S[d].xa_byte==0x20 || D_S[d].xa_byte == 0x10)) { /* XA disk with old drive */ cc_ModeSelect(CD_FRAMESIZE_RAW1); @@ -3811,6 +3943,18 @@ static int DiskInfo(void) msg(DBG_000,"DiskInfo done.\n"); return (0); } + +static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) +{ + if (CDSL_CURRENT != slot_nr) { + /* we have no changer support */ + return -EINVAL; + } + + return D_S[d].status_bits & p1_disk_ok ? CDS_DISC_OK : CDS_DRIVE_NOT_READY; +} + + /*==========================================================================*/ #if FUTURE /* @@ -3934,40 +4078,40 @@ static int sbp_status(void) return (1); } /*==========================================================================*/ + +static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp) +{ + ms_infp->addr_format = CDROM_LBA; + ms_infp->addr.lba = D_S[d].lba_multi; + if (D_S[d].f_multisession) + ms_infp->xa_flag=1; /* valid redirection address */ + else + ms_infp->xa_flag=0; /* invalid redirection address */ + + return 1; +} /*==========================================================================*/ /*==========================================================================*/ /* * ioctl support */ -static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg) +static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, + u_long arg) { - int i, st; + int i; msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08lX)\n", - MINOR(inode->i_rdev), cmd, arg); - if (!inode) return (-EINVAL); - i=MINOR(inode->i_rdev); + MINOR(cdi->dev), cmd, arg); + i=MINOR(cdi->dev); if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) { - msg(DBG_INF, "ioctl: bad device: %04X\n", inode->i_rdev); + msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev); return (-ENXIO); /* no such drive */ } down(&ioctl_read_sem); if (d!=i) switch_drive(i); -#if 0 - st=GetStatus(); - if (st<0) RETURN_UP(-EIO); - - if (!toc_valid) - { - i=DiskInfo(); - if (i<0) RETURN_UP(-EIO); /* error reading TOC */ - } -#endif - msg(DBG_IO2,"ioctl: device %d, request %04X\n",i,cmd); switch (cmd) /* Sun-compatible */ { @@ -3975,271 +4119,12 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, if (!suser()) RETURN_UP(-EPERM); i=sbpcd_dbg_ioctl(arg,1); RETURN_UP(i); - - case CDROMPAUSE: /* Pause the drive */ - msg(DBG_IOC,"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 (D_S[d].audio_state) - { - case audio_playing: - if (famL_drive) i=cc_ReadSubQ(); - else i=cc_Pause_Resume(1); - if (i<0) RETURN_UP(-EIO); - if (famL_drive) i=cc_Pause_Resume(1); - else i=cc_ReadSubQ(); - if (i<0) RETURN_UP(-EIO); - D_S[d].pos_audio_start=D_S[d].SubQ_run_tot; - D_S[d].audio_state=audio_pausing; - RETURN_UP(0); - case audio_pausing: - i=cc_Seek(D_S[d].pos_audio_start,1); - if (i<0) RETURN_UP(-EIO); - RETURN_UP(0); - default: - RETURN_UP(-EINVAL); - } - - case CDROMRESUME: /* resume paused audio play */ - msg(DBG_IOC,"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 (D_S[d].audio_state!=audio_pausing) return -EINVAL; - if (famL_drive) - i=cc_PlayAudio(D_S[d].pos_audio_start, - D_S[d].pos_audio_end); - else i=cc_Pause_Resume(3); - if (i<0) RETURN_UP(-EIO); - D_S[d].audio_state=audio_playing; - RETURN_UP(0); - - case CDROMPLAYMSF: - msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); -#if SAFE_MIXED - if (D_S[d].has_data>1) RETURN_UP(-EBUSY); -#endif SAFE_MIXED - if (D_S[d].audio_state==audio_playing) - { - i=cc_Pause_Resume(1); - if (i<0) RETURN_UP(-EIO); - i=cc_ReadSubQ(); - if (i<0) RETURN_UP(-EIO); - D_S[d].pos_audio_start=D_S[d].SubQ_run_tot; - i=cc_Seek(D_S[d].pos_audio_start,1); - } - st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf)); - if (st) RETURN_UP(st); - copy_from_user(&msf, (void *) arg, sizeof(struct cdrom_msf)); - /* values come as msf-bin */ - D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) | - (msf.cdmsf_sec0<<8) | - msf.cdmsf_frame0; - D_S[d].pos_audio_end = (msf.cdmsf_min1<<16) | - (msf.cdmsf_sec1<<8) | - msf.cdmsf_frame1; - msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", - D_S[d].pos_audio_start,D_S[d].pos_audio_end); - i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end); - if (i<0) - { - msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); - DriveReset(); - D_S[d].audio_state=0; - RETURN_UP(-EIO); - } - D_S[d].audio_state=audio_playing; - RETURN_UP(0); - - case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ - msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); -#if SAFE_MIXED - if (D_S[d].has_data>1) RETURN_UP(-EBUSY); -#endif SAFE_MIXED - if (D_S[d].audio_state==audio_playing) - { - msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); -#if 1 - RETURN_UP(0); /* just let us play on */ -#else - RETURN_UP(-EINVAL); /* play on, but say "error" */ -#endif - } - st=verify_area(VERIFY_READ,(void *) arg,sizeof(struct cdrom_ti)); - if (st<0) - { - msg(DBG_IOX,"CDROMPLAYTRKIND: verify_area error.\n"); - RETURN_UP(st); - } - copy_from_user(&ti,(void *) arg,sizeof(struct cdrom_ti)); - msg(DBG_IOX,"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<D_S[d].n_first_track) RETURN_UP(-EINVAL); - if (ti.cdti_trk0>D_S[d].n_last_track) RETURN_UP(-EINVAL); - if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0; - if (ti.cdti_trk1>D_S[d].n_last_track) ti.cdti_trk1=D_S[d].n_last_track; - D_S[d].pos_audio_start=D_S[d].TocBuffer[ti.cdti_trk0].address; - D_S[d].pos_audio_end=D_S[d].TocBuffer[ti.cdti_trk1+1].address; - i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end); - if (i<0) - { - msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); - DriveReset(); - D_S[d].audio_state=0; - RETURN_UP(-EIO); - } - D_S[d].audio_state=audio_playing; - RETURN_UP(0); - - case CDROMREADTOCHDR: /* Read the table of contents header */ - msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); - tochdr.cdth_trk0=D_S[d].n_first_track; - tochdr.cdth_trk1=D_S[d].n_last_track; - st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_tochdr)); - if (st) RETURN_UP(st); - copy_to_user((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); - RETURN_UP(0); - - case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ - msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); - st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry)); - if (st) RETURN_UP(st); - copy_from_user(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); - i=tocentry.cdte_track; - if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1; - else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track) - RETURN_UP(-EINVAL); - tocentry.cdte_adr=D_S[d].TocBuffer[i].ctl_adr&0x0F; - tocentry.cdte_ctrl=(D_S[d].TocBuffer[i].ctl_adr>>4)&0x0F; - tocentry.cdte_datamode=D_S[d].TocBuffer[i].format; - if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ - { - tocentry.cdte_addr.msf.minute=(D_S[d].TocBuffer[i].address>>16)&0x00FF; - tocentry.cdte_addr.msf.second=(D_S[d].TocBuffer[i].address>>8)&0x00FF; - tocentry.cdte_addr.msf.frame=D_S[d].TocBuffer[i].address&0x00FF; - } - else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ - tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address); - else RETURN_UP(-EINVAL); - copy_to_user((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); - RETURN_UP(0); - case CDROMRESET: /* hard reset the drive */ msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); i=DriveReset(); D_S[d].audio_state=0; RETURN_UP(i); - case CDROMSTOP: /* Spin down the drive */ - msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); -#if SAFE_MIXED - if (D_S[d].has_data>1) RETURN_UP(-EBUSY); -#endif SAFE_MIXED - i=cc_Pause_Resume(1); - D_S[d].audio_state=0; - RETURN_UP(i); - - case CDROMSTART: /* Spin up the drive */ - msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); - cc_SpinUp(); - D_S[d].audio_state=0; - RETURN_UP(0); - - case CDROMEJECT: - msg(DBG_IOC,"ioctl: CDROMEJECT entered.\n"); - if (fam0_drive) return (0); - if (D_S[d].open_count>1) RETURN_UP(-EBUSY); - i=UnLockDoor(); - D_S[d].open_count=-9; /* to get it locked next time again */ - i=cc_SpinDown(); - msg(DBG_IOX,"ioctl: cc_SpinDown returned %d.\n", i); - msg(DBG_TEA,"ioctl: cc_SpinDown returned %d.\n", i); - if (i<0) RETURN_UP(-EIO); - D_S[d].CD_changed=0xFF; - D_S[d].diskstate_flags=0; - D_S[d].audio_state=0; - RETURN_UP(0); - - case CDROMEJECT_SW: - msg(DBG_IOC,"ioctl: CDROMEJECT_SW entered.\n"); - if (fam0_drive) RETURN_UP(0); - D_S[d].f_eject=arg; - RETURN_UP(0); - - case CDROMVOLCTRL: /* Volume control */ - msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); - st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl)); - if (st) RETURN_UP(st); - copy_from_user(&volctrl,(char *) arg,sizeof(volctrl)); - D_S[d].vol_chan0=0; - D_S[d].vol_ctrl0=volctrl.channel0; - D_S[d].vol_chan1=1; - D_S[d].vol_ctrl1=volctrl.channel1; - i=cc_SetVolume(); - RETURN_UP(0); - - case CDROMVOLREAD: /* read Volume settings from drive */ - msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); - st=verify_area(VERIFY_WRITE,(void *)arg,sizeof(volctrl)); - if (st) RETURN_UP(st); - st=cc_GetVolume(); - if (st<0) return (st); - volctrl.channel0=D_S[d].vol_ctrl0; - volctrl.channel1=D_S[d].vol_ctrl1; - volctrl.channel2=0; - volctrl.channel2=0; - copy_to_user((void *)arg,&volctrl,sizeof(volctrl)); - RETURN_UP(0); - - case CDROMSUBCHNL: /* Get subchannel info */ - msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n"); - if ((st_spinning)||(!subq_valid)) { - i=cc_ReadSubQ(); - if (i<0) RETURN_UP(-EIO); - } - st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl)); - if (st) RETURN_UP(st); - copy_from_user(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); - switch (D_S[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=D_S[d].SubQ_ctl_adr; - SC.cdsc_ctrl=D_S[d].SubQ_ctl_adr>>4; - SC.cdsc_trk=bcd2bin(D_S[d].SubQ_trk); - SC.cdsc_ind=bcd2bin(D_S[d].SubQ_pnt_idx); - if (SC.cdsc_format==CDROM_LBA) - { - SC.cdsc_absaddr.lba=msf2blk(D_S[d].SubQ_run_tot); - SC.cdsc_reladdr.lba=msf2blk(D_S[d].SubQ_run_trk); - } - else /* not only if (SC.cdsc_format==CDROM_MSF) */ - { - SC.cdsc_absaddr.msf.minute=(D_S[d].SubQ_run_tot>>16)&0x00FF; - SC.cdsc_absaddr.msf.second=(D_S[d].SubQ_run_tot>>8)&0x00FF; - SC.cdsc_absaddr.msf.frame=D_S[d].SubQ_run_tot&0x00FF; - SC.cdsc_reladdr.msf.minute=(D_S[d].SubQ_run_trk>>16)&0x00FF; - SC.cdsc_reladdr.msf.second=(D_S[d].SubQ_run_trk>>8)&0x00FF; - SC.cdsc_reladdr.msf.frame=D_S[d].SubQ_run_trk&0x00FF; - } - copy_to_user((void *) arg, &SC, sizeof(struct cdrom_subchnl)); - msg(DBG_IOS,"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_UP(0); - case CDROMREADMODE1: msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); #if SAFE_MIXED @@ -4265,6 +4150,7 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, if (D_S[d].sbp_audsiz>0) vfree(D_S[d].aud_buf); D_S[d].aud_buf=NULL; D_S[d].sbp_audsiz=arg; + if (D_S[d].sbp_audsiz>0) { D_S[d].aud_buf=(u_char *) vmalloc(D_S[d].sbp_audsiz*CD_FRAMESIZE_RAW); @@ -4496,28 +4382,277 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, RETURN_UP(0); } /* end of CDROMREADAUDIO */ - case CDROMMULTISESSION: /* tell start-of-last-session */ - msg(DBG_IOC,"ioctl: CDROMMULTISESSION entered.\n"); - st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession)); - if (st) RETURN_UP(st); - copy_from_user(&ms_info, (void *) arg, sizeof(struct cdrom_multisession)); - if (ms_info.addr_format==CDROM_MSF) /* MSF-bin requested */ - lba2msf(D_S[d].lba_multi,&ms_info.addr.msf.minute); - else if (ms_info.addr_format==CDROM_LBA) /* lba requested */ - ms_info.addr.lba=D_S[d].lba_multi; - else RETURN_UP(-EINVAL); - if (D_S[d].f_multisession) ms_info.xa_flag=1; /* valid redirection address */ - else ms_info.xa_flag=0; /* invalid redirection address */ - copy_to_user((void *) arg, &ms_info, sizeof(struct cdrom_multisession)); - msg(DBG_MUL,"ioctl: CDROMMULTISESSION done (%d, %08X).\n", - ms_info.xa_flag, ms_info.addr.lba); - RETURN_UP(0); - case BLKRASET: if(!suser()) RETURN_UP(-EACCES); - if(!(inode->i_rdev)) RETURN_UP(-EINVAL); + if(!(cdi->dev)) RETURN_UP(-EINVAL); if(arg > 0xff) RETURN_UP(-EINVAL); - read_ahead[MAJOR(inode->i_rdev)] = arg; + read_ahead[MAJOR(cdi->dev)] = arg; + RETURN_UP(0); +#if 0 + case CDROMEJECT: + msg(DBG_IOC,"ioctl: CDROMEJECT entered.\n"); + if (fam0_drive) return (0); + if (D_S[d].open_count>1) RETURN_UP(-EBUSY); + i=UnLockDoor(); + D_S[d].open_count=-9; /* to get it locked next time again */ + i=cc_SpinDown(); + msg(DBG_IOX,"ioctl: cc_SpinDown returned %d.\n", i); + msg(DBG_TEA,"ioctl: cc_SpinDown returned %d.\n", i); + if (i<0) RETURN_UP(-EIO); + D_S[d].CD_changed=0xFF; + D_S[d].diskstate_flags=0; + D_S[d].audio_state=0; + RETURN_UP(0); + + case CDROMEJECT_SW: + msg(DBG_IOC,"ioctl: CDROMEJECT_SW entered.\n"); + if (fam0_drive) RETURN_UP(0); + D_S[d].f_eject=arg; + RETURN_UP(0); +#endif + default: + msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); + RETURN_UP(-EINVAL); + } /* end switch(cmd) */ +} + +static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, + void * arg) +{ + int i, st; + + msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)\n", + MINOR(cdi->dev), cmd, arg); + i=MINOR(cdi->dev); + if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) + { + msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev); + return (-ENXIO); /* no such drive */ + } + down(&ioctl_read_sem); + if (d!=i) switch_drive(i); + + msg(DBG_IO2,"ioctl: device %d, request %04X\n",i,cmd); + switch (cmd) /* Sun-compatible */ + { + + case CDROMPAUSE: /* Pause the drive */ + msg(DBG_IOC,"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 (D_S[d].audio_state) + { + case audio_playing: + if (famL_drive) i=cc_ReadSubQ(); + else i=cc_Pause_Resume(1); + if (i<0) RETURN_UP(-EIO); + if (famL_drive) i=cc_Pause_Resume(1); + else i=cc_ReadSubQ(); + if (i<0) RETURN_UP(-EIO); + D_S[d].pos_audio_start=D_S[d].SubQ_run_tot; + D_S[d].audio_state=audio_pausing; + RETURN_UP(0); + case audio_pausing: + i=cc_Seek(D_S[d].pos_audio_start,1); + if (i<0) RETURN_UP(-EIO); + RETURN_UP(0); + default: + RETURN_UP(-EINVAL); + } + + case CDROMRESUME: /* resume paused audio play */ + msg(DBG_IOC,"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 (D_S[d].audio_state!=audio_pausing) return -EINVAL; + if (famL_drive) + i=cc_PlayAudio(D_S[d].pos_audio_start, + D_S[d].pos_audio_end); + else i=cc_Pause_Resume(3); + if (i<0) RETURN_UP(-EIO); + D_S[d].audio_state=audio_playing; + RETURN_UP(0); + + case CDROMPLAYMSF: + msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); +#if SAFE_MIXED + if (D_S[d].has_data>1) RETURN_UP(-EBUSY); +#endif SAFE_MIXED + if (D_S[d].audio_state==audio_playing) + { + i=cc_Pause_Resume(1); + if (i<0) RETURN_UP(-EIO); + i=cc_ReadSubQ(); + if (i<0) RETURN_UP(-EIO); + D_S[d].pos_audio_start=D_S[d].SubQ_run_tot; + i=cc_Seek(D_S[d].pos_audio_start,1); + } + memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf)); + /* values come as msf-bin */ + D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) | + (msf.cdmsf_sec0<<8) | + msf.cdmsf_frame0; + D_S[d].pos_audio_end = (msf.cdmsf_min1<<16) | + (msf.cdmsf_sec1<<8) | + msf.cdmsf_frame1; + msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n", + D_S[d].pos_audio_start,D_S[d].pos_audio_end); + i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end); + if (i<0) + { + msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); + DriveReset(); + D_S[d].audio_state=0; + RETURN_UP(-EIO); + } + D_S[d].audio_state=audio_playing; + RETURN_UP(0); + + case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ + msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); +#if SAFE_MIXED + if (D_S[d].has_data>1) RETURN_UP(-EBUSY); +#endif SAFE_MIXED + if (D_S[d].audio_state==audio_playing) + { + msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); +#if 1 + RETURN_UP(0); /* just let us play on */ +#else + RETURN_UP(-EINVAL); /* play on, but say "error" */ +#endif + } + memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti)); + msg(DBG_IOX,"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<D_S[d].n_first_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk0>D_S[d].n_last_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0; + if (ti.cdti_trk1>D_S[d].n_last_track) ti.cdti_trk1=D_S[d].n_last_track; + D_S[d].pos_audio_start=D_S[d].TocBuffer[ti.cdti_trk0].address; + D_S[d].pos_audio_end=D_S[d].TocBuffer[ti.cdti_trk1+1].address; + i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end); + if (i<0) + { + msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i); + DriveReset(); + D_S[d].audio_state=0; + RETURN_UP(-EIO); + } + D_S[d].audio_state=audio_playing; + RETURN_UP(0); + + case CDROMREADTOCHDR: /* Read the table of contents header */ + msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n"); + tochdr.cdth_trk0=D_S[d].n_first_track; + tochdr.cdth_trk1=D_S[d].n_last_track; + memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr)); + RETURN_UP(0); + + case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ + msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n"); + memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry)); + i=tocentry.cdte_track; + if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1; + else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track) + RETURN_UP(-EINVAL); + tocentry.cdte_adr=D_S[d].TocBuffer[i].ctl_adr&0x0F; + tocentry.cdte_ctrl=(D_S[d].TocBuffer[i].ctl_adr>>4)&0x0F; + tocentry.cdte_datamode=D_S[d].TocBuffer[i].format; + if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */ + { + tocentry.cdte_addr.msf.minute=(D_S[d].TocBuffer[i].address>>16)&0x00FF; + tocentry.cdte_addr.msf.second=(D_S[d].TocBuffer[i].address>>8)&0x00FF; + tocentry.cdte_addr.msf.frame=D_S[d].TocBuffer[i].address&0x00FF; + } + else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ + tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address); + else RETURN_UP(-EINVAL); + memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry)); + RETURN_UP(0); + + case CDROMSTOP: /* Spin down the drive */ + msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n"); +#if SAFE_MIXED + if (D_S[d].has_data>1) RETURN_UP(-EBUSY); +#endif SAFE_MIXED + i=cc_Pause_Resume(1); + D_S[d].audio_state=0; + RETURN_UP(i); + + case CDROMSTART: /* Spin up the drive */ + msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); + cc_SpinUp(); + D_S[d].audio_state=0; + RETURN_UP(0); + + case CDROMVOLCTRL: /* Volume control */ + msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); + memcpy(&volctrl,(char *) arg,sizeof(volctrl)); + D_S[d].vol_chan0=0; + D_S[d].vol_ctrl0=volctrl.channel0; + D_S[d].vol_chan1=1; + D_S[d].vol_ctrl1=volctrl.channel1; + i=cc_SetVolume(); + RETURN_UP(0); + + case CDROMVOLREAD: /* read Volume settings from drive */ + msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); + st=cc_GetVolume(); + if (st<0) return (st); + volctrl.channel0=D_S[d].vol_ctrl0; + volctrl.channel1=D_S[d].vol_ctrl1; + volctrl.channel2=0; + volctrl.channel2=0; + memcpy((void *)arg,&volctrl,sizeof(volctrl)); + RETURN_UP(0); + + case CDROMSUBCHNL: /* Get subchannel info */ + msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n"); + if ((st_spinning)||(!subq_valid)) { + i=cc_ReadSubQ(); + if (i<0) RETURN_UP(-EIO); + } + memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); + switch (D_S[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=D_S[d].SubQ_ctl_adr; + SC.cdsc_ctrl=D_S[d].SubQ_ctl_adr>>4; + SC.cdsc_trk=bcd2bin(D_S[d].SubQ_trk); + SC.cdsc_ind=bcd2bin(D_S[d].SubQ_pnt_idx); + if (SC.cdsc_format==CDROM_LBA) + { + SC.cdsc_absaddr.lba=msf2blk(D_S[d].SubQ_run_tot); + SC.cdsc_reladdr.lba=msf2blk(D_S[d].SubQ_run_trk); + } + else /* not only if (SC.cdsc_format==CDROM_MSF) */ + { + SC.cdsc_absaddr.msf.minute=(D_S[d].SubQ_run_tot>>16)&0x00FF; + SC.cdsc_absaddr.msf.second=(D_S[d].SubQ_run_tot>>8)&0x00FF; + SC.cdsc_absaddr.msf.frame=D_S[d].SubQ_run_tot&0x00FF; + SC.cdsc_reladdr.msf.minute=(D_S[d].SubQ_run_trk>>16)&0x00FF; + SC.cdsc_reladdr.msf.second=(D_S[d].SubQ_run_trk>>8)&0x00FF; + SC.cdsc_reladdr.msf.frame=D_S[d].SubQ_run_trk&0x00FF; + } + memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl)); + msg(DBG_IOS,"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_UP(0); default: @@ -5104,19 +5239,18 @@ static int sbp_data(struct request *req) /* * Open the device special file. Check that a disk is in. Read TOC. */ -static int sbpcd_open(struct inode *ip, struct file *fp) +static int sbpcd_open(struct cdrom_device_info *cdi, int purpose) { int i; - i = MINOR(ip->i_rdev); + i = MINOR(cdi->dev); if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) { - msg(DBG_INF, "open: bad device: %04X\n", ip->i_rdev); + msg(DBG_INF, "open: bad device: %04X\n", cdi->dev); return (-ENXIO); /* no such drive */ } - if (fp->f_mode & 2) - return -EROFS; + MOD_INC_USE_COUNT; down(&ioctl_read_sem); switch_drive(i); @@ -5136,21 +5270,13 @@ static int sbpcd_open(struct inode *ip, struct file *fp) if (i<0) { msg(DBG_INF,"sbpcd_open: ResponseStatus timed out (%d).\n",i); + MOD_DEC_USE_COUNT; RETURN_UP(-EIO); /* drive doesn't respond */ } if (famT_drive) msg(DBG_TEA,"sbpcd_open: ResponseStatus=%02X\n", i); - if (!st_door_closed) - { - if (famT_drive) msg(DBG_TEA,"sbpcd_open: !st_door_closed.\n"); - cc_CloseTray(); - flags_cmd_out |= f_respo2; - cc_ReadStatus(); - i=ResponseStatus(); - } if (!(famT_drive)) if (!st_spinning) { - if (famT_drive) msg(DBG_TEA,"sbpcd_open: !st_spinning.\n"); cc_SpinUp(); flags_cmd_out |= f_respo2; cc_ReadStatus(); @@ -5161,19 +5287,12 @@ static int sbpcd_open(struct inode *ip, struct file *fp) { msg(DBG_INF, "sbpcd_open: no disk in drive.\n"); D_S[d].open_count=0; -#if JUKEBOX - if (!fam0_drive) - { - i=UnLockDoor(); - cc_SpinDown(); /* eject tray */ - } -#endif + MOD_DEC_USE_COUNT; RETURN_UP(-ENXIO); } /* * try to keep an "open" counter here and lock the door if 0->1. */ - MOD_INC_USE_COUNT; msg(DBG_LCK,"open_count: %d -> %d\n", D_S[d].open_count,D_S[d].open_count+1); if (++D_S[d].open_count<=1) @@ -5201,22 +5320,21 @@ static int sbpcd_open(struct inode *ip, struct file *fp) /* * On close, we flush all sbp blocks from the buffer cache. */ -static int sbpcd_release(struct inode * ip, struct file * file) +static void sbpcd_release(struct cdrom_device_info * cdi) { int i; - i = MINOR(ip->i_rdev); + i = MINOR(cdi->dev); if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) { - msg(DBG_INF, "release: bad device: %04X\n", ip->i_rdev); - return 0; + msg(DBG_INF, "release: bad device: %04X\n", cdi->dev); + return ; } down(&ioctl_read_sem); switch_drive(i); /* * try to keep an "open" counter here and unlock the door if 1->0. */ - MOD_DEC_USE_COUNT; msg(DBG_LCK,"open_count: %d -> %d\n", D_S[d].open_count,D_S[d].open_count-1); if (D_S[d].open_count>-2) /* CDROMEJECT may have been done */ @@ -5224,9 +5342,7 @@ static int sbpcd_release(struct inode * ip, struct file * file) if (--D_S[d].open_count<=0) { D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; - sync_dev(ip->i_rdev); /* nonsense if read only device? */ - invalidate_buffers(ip->i_rdev); - i=UnLockDoor(); + invalidate_buffers(cdi->dev); if (D_S[d].audio_state!=audio_playing) if (D_S[d].f_eject) cc_SpinDown(); D_S[d].diskstate_flags &= ~cd_size_bit; @@ -5237,12 +5353,14 @@ static int sbpcd_release(struct inode * ip, struct file * file) } } up(&ioctl_read_sem); - return 0; + MOD_DEC_USE_COUNT; + return ; } /*==========================================================================*/ /* * */ +#if 0 static struct file_operations sbpcd_fops = { NULL, /* lseek - default */ @@ -5259,6 +5377,39 @@ static struct file_operations sbpcd_fops = sbpcd_chk_disk_change, /* media_change */ NULL /* revalidate */ }; +#endif +static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr); +static struct cdrom_device_ops sbpcd_dops = { + sbpcd_open, /* open */ + sbpcd_release, /* release */ + sbpcd_drive_status, /* drive status */ + sbpcd_media_changed, /* media changed */ + sbpcd_tray_move, /* tray move */ + sbpcd_lock_door, /* lock door */ + sbpcd_select_speed, /* select speed */ + NULL, /* select disc */ + sbpcd_get_last_session, /* get last session */ + sbpcd_get_mcn, /* get universal product code */ + sbpcd_reset, /* hard reset */ + sbpcd_audio_ioctl, /* audio ioctl */ + sbpcd_dev_ioctl, /* device-specific ioctl */ + CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION | + CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO, /* capability */ + 1, /* number of minor devices */ +}; + +static struct cdrom_device_info sbpcd_info = { + &sbpcd_dops, /* device operations */ + NULL, /* link */ + NULL, /* handle */ + MKDEV(MAJOR_NR,0), /* dev */ + 0, /* mask */ + 2, /* maximum speed */ + 1, /* number of discs */ + 0, /* options, not owned */ + 0, /* mc_flags, not owned */ + 0 /* use count, not owned */ +}; /*==========================================================================*/ /* * accept "kernel command line" parameters @@ -5495,15 +5646,15 @@ __initfunc(int SBPCD_INIT(void)) if (!famL_drive) cc_DriveReset(); #endif 0 if (!st_spinning) cc_SpinUp(); - D_S[d].sbp_first_frame = -1; /* First frame in buffer */ - D_S[d].sbp_last_frame = -1; /* Last frame in buffer */ - D_S[d].sbp_read_frames = 0; /* Number of frames being read to buffer */ - D_S[d].sbp_current = 0; /* Frame being currently read */ - D_S[d].CD_changed=1; - D_S[d].frame_size=CD_FRAMESIZE; - D_S[d].f_eject=0; + D_S[j].sbp_first_frame = -1; /* First frame in buffer */ + D_S[j].sbp_last_frame = -1; /* Last frame in buffer */ + D_S[j].sbp_read_frames = 0; /* Number of frames being read to buffer */ + D_S[j].sbp_current = 0; /* Frame being currently read */ + D_S[j].CD_changed=1; + D_S[j].frame_size=CD_FRAMESIZE; + D_S[j].f_eject=0; #if EJECT - if (!fam0_drive) D_S[d].f_eject=1; + if (!fam0_drive) D_S[j].f_eject=1; #endif EJECT cc_ReadStatus(); i=ResponseStatus(); /* returns orig. status or p_busy_new */ @@ -5521,8 +5672,8 @@ __initfunc(int SBPCD_INIT(void)) } msg(DBG_INI,"init: first GetStatus: %d\n",i); msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n", - D_S[d].error_byte); - if (D_S[d].error_byte==aud_12) + D_S[j].error_byte); + if (D_S[j].error_byte==aud_12) { timeout=jiffies+2*HZ; do @@ -5531,14 +5682,14 @@ __initfunc(int SBPCD_INIT(void)) msg(DBG_INI,"init: second GetStatus: %02X\n",i); msg(DBG_LCS, "init: second GetStatus: error_byte=%d\n", - D_S[d].error_byte); + D_S[j].error_byte); if (i<0) break; if (!st_caddy_in) break; } while ((!st_diskok)||(timeout<jiffies)); } i=SetSpeed(); - if (i>=0) D_S[d].CD_changed=1; + if (i>=0) D_S[j].CD_changed=1; } /* @@ -5550,7 +5701,7 @@ __initfunc(int SBPCD_INIT(void)) OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ #endif SOUND_BASE - if (register_blkdev(MAJOR_NR, major_name, &sbpcd_fops) != 0) + if (register_blkdev(MAJOR_NR, major_name, &cdrom_fops) != 0) { msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR); #ifdef MODULE @@ -5566,6 +5717,8 @@ __initfunc(int SBPCD_INIT(void)) for (j=0;j<NR_SBPCD;j++) { + struct cdrom_device_info * sbpcd_infop; + if (D_S[j].drv_id==-1) continue; switch_drive(j); #if SAFE_MIXED @@ -5583,6 +5736,11 @@ __initfunc(int SBPCD_INIT(void)) if (D_S[j].sbp_buf==NULL) { msg(DBG_INF,"data buffer (%d frames) not available.\n",D_S[j].sbp_bufsiz); + if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL)) + { + printk("Can't unregister %s\n", major_name); + } + release_region(CDo_command,4); return -EIO; } #ifdef MODULE @@ -5594,13 +5752,29 @@ __initfunc(int SBPCD_INIT(void)) if (D_S[j].aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",D_S[j].sbp_audsiz); else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[j].sbp_audsiz); } + sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info)); + if (sbpcd_infop == NULL) + { + release_region(CDo_command,4); + return -ENOMEM; + } + D_S[j].sbpcd_infop = sbpcd_infop; + memcpy (sbpcd_infop, &sbpcd_info, sizeof(struct cdrom_device_info)); + sbpcd_infop->dev = MKDEV(MAJOR_NR, j); + strncpy(sbpcd_infop->name,major_name, sizeof(sbpcd_infop->name)); + + if (register_cdrom(sbpcd_infop)) + { + printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); + } + /* * set the block size */ sbpcd_blocksizes[j]=CD_FRAMESIZE; } blksize_size[MAJOR_NR]=sbpcd_blocksizes; - + #ifndef MODULE init_done: #if !(SBPCD_ISSUE-1) @@ -5635,6 +5809,12 @@ void cleanup_module(void) if (D_S[j].drv_id==-1) continue; vfree(D_S[j].sbp_buf); if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf); + if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL)) + { + msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name); + return; + } + vfree(D_S[j].sbpcd_infop); } msg(DBG_INF, "%s module released.\n", major_name); } @@ -5665,6 +5845,11 @@ static int sbpcd_chk_disk_change(kdev_t full_dev) else return (0); } + +static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr) +{ + return sbpcd_chk_disk_change(cdi->dev); +} /*==========================================================================*/ /* * Overrides for Emacs so that we follow Linus's tabbing style. |