diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-10-05 01:18:40 +0000 |
commit | 012bb3e61e5eced6c610f9e036372bf0c8def2d1 (patch) | |
tree | 87efc733f9b164e8c85c0336f92c8fb7eff6d183 /drivers/cdrom | |
parent | 625a1589d3d6464b5d90b8a0918789e3afffd220 (diff) |
Merge with Linux 2.4.0-test9. Please check DECstation, I had a number
of rejects to fixup while integrating Linus patches. I also found
that this kernel will only boot SMP on Origin; the UP kernel freeze
soon after bootup with SCSI timeout messages. I commit this anyway
since I found that the last CVS versions had the same problem.
Diffstat (limited to 'drivers/cdrom')
-rw-r--r-- | drivers/cdrom/cdrom.c | 72 | ||||
-rw-r--r-- | drivers/cdrom/mcd.c | 4 | ||||
-rw-r--r-- | drivers/cdrom/sbpcd.c | 117 | ||||
-rw-r--r-- | drivers/cdrom/sbpcd.h | 1 | ||||
-rw-r--r-- | drivers/cdrom/sonycd535.c | 12 |
5 files changed, 134 insertions, 72 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 4503bbfed..912402678 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -291,11 +291,13 @@ MODULE_PARM(check_media_type, "i"); #endif /* These are used to simplify getting data in from and back to user land */ -#define IOCTL_IN(arg, type, in) \ - copy_from_user_ret(&in, (type *) arg, sizeof in, -EFAULT) +#define IOCTL_IN(arg, type, in) \ + if (copy_from_user(&in, (type *) arg, sizeof in)) \ + return -EFAULT; #define IOCTL_OUT(arg, type, out) \ - copy_to_user_ret((type *) arg, &out, sizeof out, -EFAULT) + if (copy_to_user((type *) arg, &out, sizeof out)) \ + return -EFAULT; /* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in a lot of places. This macro makes the code more clear. */ @@ -784,6 +786,8 @@ int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) if (!CDROM_CAN(CDC_SELECT_DISC)) return -EDRIVE_CANT_DO_THIS; + (void) cdi->ops->media_changed(cdi, slot); + if (slot == CDSL_NONE) { /* set media changed bits, on both queues */ cdi->mc_flags = 0x3; @@ -851,8 +855,8 @@ static int cdrom_media_changed(kdev_t dev) if (cdi == NULL || cdi->ops->media_changed == NULL) return 0; if (!CDROM_CAN(CDC_MEDIA_CHANGED)) - return 0; - return (media_changed(cdi, 0)); + return 0; + return media_changed(cdi, 0); } /* badly broken, I know. Is due for a fixup anytime. */ @@ -872,8 +876,7 @@ void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks) return; } /* Grab the TOC header so we can see how many tracks there are */ - ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header); - if (ret) { + if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) { if (ret == -ENOMEDIUM) tracks->error = CDS_NO_DISC; else @@ -1115,6 +1118,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n"); setup_report_key(&cgc, 0, 8); memset(&rpc_state, 0, sizeof(rpc_state_t)); + cgc.buffer = (char *) &rpc_state; if ((ret = cdo->generic_packet(cdi, &cgc))) return ret; @@ -1516,12 +1520,13 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); if (!CDROM_CAN(CDC_MEDIA_CHANGED)) return -ENOSYS; + + /* cannot select disc or select current disc */ if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT) - /* cannot select disc or select current disc */ return media_changed(cdi, 1); - if ((unsigned int)arg >= cdi->capacity) { + + if ((unsigned int)arg >= cdi->capacity) return -EINVAL; - } if ((ret = cdrom_read_mech_status(cdi, &info))) return ret; @@ -1570,10 +1575,10 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_SELECT_DISC)) return -ENOSYS; - if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) { - if ((int)arg >= cdi->capacity) - return -EINVAL; - } + if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) + if ((int)arg >= cdi->capacity) + return -EINVAL; + /* cdo->select_disc is a hook to allow a driver-specific * way of seleting disc. However, since there is no * equiv hook for cdrom_slot_status this may not @@ -1601,8 +1606,9 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, if (!CDROM_CAN(CDC_LOCK)) return -EDRIVE_CANT_DO_THIS; keeplocked = arg ? 1 : 0; - /* don't unlock the door on multiple opens */ - if ((cdi->use_count != 1) && !arg) + /* don't unlock the door on multiple opens,but allow root + * to do so */ + if ((cdi->use_count != 1) && !arg && !capable(CAP_SYS_ADMIN)) return -EBUSY; return cdo->lock_door(cdi, arg); } @@ -1834,7 +1840,6 @@ static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size) struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_generic_command cgc; struct modesel_head mh; - int ret; memset(&mh, 0, sizeof(mh)); mh.block_desc_length = 0x08; @@ -1852,14 +1857,7 @@ static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size) mh.block_length_med = (size >> 8) & 0xff; mh.block_length_lo = size & 0xff; - ret = cdo->generic_packet(cdi, &cgc); - if (ret) { - printk("switch_blocksize failed, ret %x ", ret); - if (cgc.sense) - printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq); - printk("\n"); - } - return ret; + return cdo->generic_packet(cdi, &cgc); } static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, @@ -1916,16 +1914,10 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, } cgc.sense = NULL; ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1); - if (ret) { - printk("read_cd failed, ret %x ", ret); - if (cgc.sense) - printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq); - printk("\n"); - } ret |= cdrom_switch_blocksize(cdi, blocksize); } if (!ret && copy_to_user((char *)arg, cgc.buffer, blocksize)) - ret = -EFAULT; + ret = -EFAULT; kfree(cgc.buffer); return ret; } @@ -1990,19 +1982,6 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ return 0; } - case CDROMPLAYTRKIND: { - struct cdrom_ti ti; - - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n"); - IOCTL_IN(arg, struct cdrom_ti, ti); - - cgc.cmd[0] = GPCMD_PLAY_AUDIO_TI; - cgc.cmd[4] = ti.cdti_trk0; - cgc.cmd[5] = ti.cdti_ind0; - cgc.cmd[7] = ti.cdti_trk1; - cgc.cmd[8] = ti.cdti_ind1; - return cdo->generic_packet(cdi, &cgc); - } case CDROMPLAYMSF: { struct cdrom_msf msf; cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); @@ -2593,8 +2572,9 @@ static void cdrom_sysctl_register(void) return; cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1); +#ifdef CONFIG_PROC_FS cdrom_root_table->child->de->owner = THIS_MODULE; - +#endif /* CONFIG_PROC_FS */ /* set the defaults */ cdrom_sysctl_settings.autoclose = autoclose; cdrom_sysctl_settings.autoeject = autoeject; diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c index c44546274..b064b2e22 100644 --- a/drivers/cdrom/mcd.c +++ b/drivers/cdrom/mcd.c @@ -275,7 +275,7 @@ static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr) static int statusCmd(void) { - int st, retry; + int st = -1, retry; for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) { @@ -297,7 +297,7 @@ statusCmd(void) static int mcdPlay(struct mcd_Play_msf *arg) { - int retry, st; + int retry, st = -1; for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) { diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index df2174a8c..07e97a1d7 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -1,3 +1,5 @@ + + /* * sbpcd.c CD-ROM device driver for the whole family of traditional, * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives. @@ -13,7 +15,7 @@ * labelled E2550UA or MK4015 or 2800F). */ -#define VERSION "v4.61 Eberhard Moenkeberg <emoenke@gwdg.de>" +#define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000" /* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de> * @@ -46,7 +48,7 @@ * * 0.1 initial release, April/May 93, after mcd.c (Martin Harriss) * - * 0.2 the "repeat:"-loop in do_sbpcd_request did not check for + * 0.2 thek "repeat:"-loop in do_sbpcd_request did not check for * end-of-request_queue (resulting in kernel panic). * Flow control seems stable, but throughput is not better. * @@ -312,9 +314,20 @@ * module_init & module_exit. * Torben Mathiasen <tmm@image.dk> * + * 4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer. + * Annoying things fixed: + * TOC reread on automated disk changes + * TOC reread on manual cd changes + * Play IOCTL tries to play CD before it's actually ready... sometimes. + * CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play. + * Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000 + * * * TODO * implement "read all subchannel data" (96 bytes per frame) + * remove alot of the virtual status bits and deal with hardware status + * move the change of cd for audio to a better place + * add debug levels to insmod parameters (trivial) * * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine * elaborated speed-up experiments (and the fabulous results!), for @@ -637,9 +650,9 @@ static u_int maxtim_data= 9000; static u_int maxtim_data= 3000; #endif LONG_TIMING #if DISTRIBUTION -static int n_retries=3; +static int n_retries=6; #else -static int n_retries=1; +static int n_retries=6; #endif /*==========================================================================*/ @@ -2046,7 +2059,9 @@ static int DriveReset(void) do { i=GetStatus(); - if ((i<0)&&(i!=-ERR_DISKCHANGE)) return (-2); /* from sta2err */ + if ((i<0)&&(i!=-ERR_DISKCHANGE)) { + return (-2); /* from sta2err */ + } if (!st_caddy_in) break; sbp_sleep(1); } @@ -2343,16 +2358,21 @@ static int cc_CloseTray(void) static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position) { - int i; - i = MINOR(cdi->dev); - - switch_drive(i); - if (position == 1) { - cc_SpinDown(); - } else { - return cc_CloseTray(); - } - return 0; + int i; + int retval=0; + i = MINOR(cdi->dev); + switch_drive(i); + /* DUH! --AJK */ + if(D_S[d].CD_changed != 0xFF) { + D_S[d].CD_changed=0xFF; + D_S[d].diskstate_flags &= ~cd_size_bit; + } + if (position == 1) { + cc_SpinDown(); + } else { + retval=cc_CloseTray(); + } + return retval; } /*==========================================================================*/ @@ -4023,6 +4043,7 @@ static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok); msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning); msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); + #if 0 if (!(D_S[MINOR(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN; if (D_S[MINOR(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK; @@ -4031,8 +4052,11 @@ static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) return CDS_NO_DISC; #else if (D_S[MINOR(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK; - return CDS_TRAY_OPEN; +/* return CDS_TRAY_OPEN; */ + return CDS_NO_DISC; + #endif + } @@ -4500,7 +4524,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, void * arg) { - int i, st; + int i, st, j; msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)\n", MINOR(cdi->dev), cmd, arg); @@ -4696,19 +4720,68 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, case CDROMSUBCHNL: /* Get subchannel info */ msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n"); + /* Bogus, I can do better than this! --AJK if ((st_spinning)||(!subq_valid)) { i=cc_ReadSubQ(); if (i<0) RETURN_UP(-EIO); } + */ + i=cc_ReadSubQ(); + if (i<0) { + j=cc_ReadError(); /* clear out error status from drive */ + D_S[d].audio_state=CDROM_AUDIO_NO_STATUS; + /* get and set the disk state here, + probably not the right place, but who cares! + It makes it work properly! --AJK */ + if (D_S[d].CD_changed==0xFF) { + msg(DBG_000,"Disk changed detect\n"); + D_S[d].diskstate_flags &= ~cd_size_bit; + } + RETURN_UP(-EIO); + } + if (D_S[d].CD_changed==0xFF) { + /* reread the TOC because the disk has changed! --AJK */ + msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n"); + i=DiskInfo(); + if(i==0) { + D_S[d].CD_changed=0x00; /* cd has changed, procede, */ + RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */ + } else { + RETURN_UP(-EIO); /* we weren't ready yet! --AJK */ + } + } memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); + /* + This virtual crap is very bogus! + It doesn't detect when the cd is done playing audio! + Lets do this right with proper hardware register reading! + */ + cc_ReadStatus(); + i=ResponseStatus(); + msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked); + msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed); + msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in); + msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok); + msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning); + msg(DBG_000,"Drive Status: busy =%d.\n", st_busy); + /* st_busy indicates if it's _ACTUALLY_ playing audio */ switch (D_S[d].audio_state) { case audio_playing: - SC.cdsc_audiostatus=CDROM_AUDIO_PLAY; + if(st_busy==0) { + /* CD has stopped playing audio --AJK */ + D_S[d].audio_state=audio_completed; + SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED; + } else { + SC.cdsc_audiostatus=CDROM_AUDIO_PLAY; + } break; case audio_pausing: SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED; break; + case audio_completed: + SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED; + break; default: SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS; break; @@ -5883,6 +5956,14 @@ static int sbpcd_chk_disk_change(kdev_t full_dev) { D_S[i].CD_changed=0; msg(DBG_CHK,"medium changed (drive %d)\n", i); + /* BUG! Should invalidate buffers! --AJK */ + invalidate_buffers(full_dev); + D_S[d].diskstate_flags &= ~toc_bit; + D_S[d].diskstate_flags &= ~cd_size_bit; +#if SAFE_MIXED + D_S[d].has_data=0; +#endif SAFE_MIXED + return (1); } else diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h index 805e98a82..6632fa48c 100644 --- a/drivers/cdrom/sbpcd.h +++ b/drivers/cdrom/sbpcd.h @@ -412,6 +412,7 @@ /* * audio states: */ +#define audio_completed 3 /* Forgot this one! --AJK */ #define audio_playing 2 #define audio_pausing 1 diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c index 8349e5928..15bcacd85 100644 --- a/drivers/cdrom/sonycd535.c +++ b/drivers/cdrom/sonycd535.c @@ -217,16 +217,16 @@ static unsigned short command_reg; static unsigned short read_status_reg; static unsigned short data_reg; -static int initialized = 0; /* Has the drive been initialized? */ +static int initialized; /* Has the drive been initialized? */ static int sony_disc_changed = 1; /* Has the disk been changed since the last check? */ -static int sony_toc_read = 0; /* Has the table of contents been +static int sony_toc_read; /* Has the table of contents been read? */ static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead buffer. */ static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of the read-ahead buffer. */ -static unsigned int sony_usage = 0; /* How many processes have the +static unsigned int sony_usage; /* How many processes have the drive open. */ static int sony_first_block = -1; /* First OS block (512 byte) in @@ -242,7 +242,7 @@ static struct s535_sony_subcode *last_sony_subcode; /* Points to the last static Byte **sony_buffer; /* Points to the pointers to the sector buffers */ -static int sony_inuse = 0; /* is the drive in use? Only one +static int sony_inuse; /* is the drive in use? Only one open at a time allowed */ /* @@ -260,8 +260,8 @@ static int sony_audio_status = CDROM_AUDIO_NO_STATUS; * I just kept the CDU-31A driver behavior rather than using the PAUSE * command on the CDU-535. */ -static Byte cur_pos_msf[3] = {0, 0, 0}; -static Byte final_pos_msf[3] = {0, 0, 0}; +static Byte cur_pos_msf[3]; +static Byte final_pos_msf[3]; /* What IRQ is the drive using? 0 if none. */ static int sony535_irq_used = CDU535_INTERRUPT; |