mirror of
https://github.com/freebsd/freebsd-src
synced 2024-11-05 18:22:52 +00:00
Implement tray closing and tray locking
Fix first open fails bug
This commit is contained in:
parent
2d091ecf19
commit
39c88daba9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=6604
2 changed files with 260 additions and 38 deletions
|
@ -2,7 +2,7 @@
|
|||
* Copyright 1993 by Holger Veit (data part)
|
||||
* Copyright 1993 by Brian Moore (audio part)
|
||||
* Changes Copyright 1993 by Gary Clark II
|
||||
* Changes Copyright (C) 1994 by Andrew A. Chernov
|
||||
* Changes Copyright (C) 1994-1995 by Andrey A. Chernov, Moscow, Russia
|
||||
*
|
||||
* Rewrote probe routine to work on newer Mitsumi drives.
|
||||
* Additional changes (C) 1994 by Jordan K. Hubbard
|
||||
|
@ -187,6 +187,8 @@ static int mcd_play(int unit, struct mcd_read2 *pb);
|
|||
static int mcd_playmsf(int unit, struct ioc_play_msf *pt);
|
||||
static int mcd_pause(int unit);
|
||||
static int mcd_resume(int unit);
|
||||
static int mcd_lock_door(int unit, int lock);
|
||||
static int mcd_close_tray(int unit);
|
||||
|
||||
extern int hz;
|
||||
extern int mcd_probe(struct isa_device *dev);
|
||||
|
@ -198,13 +200,17 @@ struct isa_driver mcddriver = { mcd_probe, mcd_attach, "mcd" };
|
|||
#define MCD_RETRYS 5
|
||||
#define MCD_RDRETRYS 8
|
||||
|
||||
#define CLOSE_TRAY_SECS 8
|
||||
#define DISK_SENSE_SECS 3
|
||||
#define WAIT_FRAC 4
|
||||
|
||||
/* several delays */
|
||||
#define RDELAY_WAITSTAT 300
|
||||
#define RDELAY_WAITMODE 300
|
||||
#define RDELAY_WAITREAD 800
|
||||
|
||||
#define MIN_DELAY 15
|
||||
#define DELAY_GETREPLY 1300000
|
||||
#define DELAY_GETREPLY 1400000
|
||||
|
||||
static struct kern_devconf kdc_mcd[NMCD] = { {
|
||||
0, 0, 0, /* filled in by dev_attach */
|
||||
|
@ -226,7 +232,6 @@ mcd_registerdev(struct isa_device *id)
|
|||
dev_attach(&kdc_mcd[id->id_unit]);
|
||||
}
|
||||
|
||||
|
||||
int mcd_attach(struct isa_device *dev)
|
||||
{
|
||||
struct mcd_data *cd = mcd_data + dev->id_unit;
|
||||
|
@ -249,7 +254,7 @@ int mcd_attach(struct isa_device *dev)
|
|||
|
||||
int mcdopen(dev_t dev)
|
||||
{
|
||||
int unit,part,phys;
|
||||
int unit,part,phys,r,retry;
|
||||
struct mcd_data *cd;
|
||||
|
||||
unit = mcd_unit(dev);
|
||||
|
@ -268,8 +273,18 @@ int mcdopen(dev_t dev)
|
|||
if (!(cd->flags & MCDVALID) && cd->openflags)
|
||||
return ENXIO;
|
||||
|
||||
if (mcd_getstat(unit,1) == -1) /* detect disk change too */
|
||||
return ENXIO;
|
||||
if (mcd_close_tray(unit) == EIO) /* detect disk change too */
|
||||
return EIO;
|
||||
|
||||
if ( (cd->status & (MCDDSKCHNG|MCDDOOROPEN))
|
||||
|| !(cd->status & MCDDSKIN))
|
||||
for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) {
|
||||
(void) tsleep((caddr_t)cd, PSOCK | PCATCH, "mcdsns", hz/WAIT_FRAC);
|
||||
if ((r = mcd_getstat(unit,1)) == -1)
|
||||
return EIO;
|
||||
if (r != -2)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cd->status & MCDDOOROPEN) {
|
||||
printf("mcd%d: door is open\n");
|
||||
|
@ -279,6 +294,10 @@ int mcdopen(dev_t dev)
|
|||
printf("mcd%d: no CD inside\n");
|
||||
return ENXIO;
|
||||
}
|
||||
if (cd->status & MCDDSKCHNG) {
|
||||
printf("mcd%d: CD not sensed\n");
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
if (mcdsize(dev) < 0) {
|
||||
printf("mcd%d: failed to get disk size\n",unit);
|
||||
|
@ -300,6 +319,9 @@ MCD_TRACE("open: partition=%d, disksize = %d, blksize=%d\n",
|
|||
if (part == RAW_PART && phys != 0)
|
||||
cd->partflags[part] |= MCDREADRAW;
|
||||
kdc_mcd[unit].kdc_state = DC_BUSY;
|
||||
(void) mcd_lock_door(unit, MCD_LK_LOCK);
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -323,7 +345,9 @@ int mcdclose(dev_t dev)
|
|||
return ENXIO;
|
||||
|
||||
kdc_mcd[unit].kdc_state = DC_IDLE;
|
||||
if (mcd_getstat(unit,1) == -2)
|
||||
(void) mcd_lock_door(unit, MCD_LK_UNLOCK);
|
||||
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return 0;
|
||||
|
||||
/* close channel */
|
||||
|
@ -463,19 +487,23 @@ int mcdioctl(dev_t dev, int cmd, caddr_t addr, int flags)
|
|||
part = mcd_part(dev);
|
||||
cd = mcd_data + unit;
|
||||
|
||||
if (mcd_getstat(unit, 1) < 0) /* detect disk change too */
|
||||
return EIO;
|
||||
if (!(cd->flags & MCDVALID))
|
||||
if (mcd_getstat(unit, 1) == -1) /* detect disk change too */
|
||||
return EIO;
|
||||
MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
||||
|
||||
switch (cmd) {
|
||||
case DIOCSBAD:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return EINVAL;
|
||||
case DIOCGDINFO:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
*(struct disklabel *) addr = cd->dlabel;
|
||||
return 0;
|
||||
case DIOCGPART:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
((struct partinfo *) addr)->disklab = &cd->dlabel;
|
||||
((struct partinfo *) addr)->part =
|
||||
&cd->dlabel.d_partitions[mcd_part(dev)];
|
||||
|
@ -487,6 +515,8 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
|||
*/
|
||||
case DIOCWDINFO:
|
||||
case DIOCSDINFO:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
if ((flags & FWRITE) == 0)
|
||||
return EBADF;
|
||||
else {
|
||||
|
@ -495,18 +525,32 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
|||
0);
|
||||
}
|
||||
case DIOCWLABEL:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return EBADF;
|
||||
case CDIOCPLAYTRACKS:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_playtracks(unit, (struct ioc_play_track *) addr);
|
||||
case CDIOCPLAYBLOCKS:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return EINVAL;
|
||||
case CDIOCPLAYMSF:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_playmsf(unit, (struct ioc_play_msf *) addr);
|
||||
case CDIOCREADSUBCHANNEL:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_subchan(unit, (struct ioc_read_subchannel *) addr);
|
||||
case CDIOREADTOCHEADER:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_toc_header(unit, (struct ioc_toc_header *) addr);
|
||||
case CDIOREADTOCENTRYS:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_toc_entrys(unit, (struct ioc_read_toc_entry *) addr);
|
||||
case CDIOCSETPATCH:
|
||||
case CDIOCGETVOL:
|
||||
|
@ -518,12 +562,20 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
|||
case CDIOCSETRIGHT:
|
||||
return EINVAL;
|
||||
case CDIOCRESUME:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_resume(unit);
|
||||
case CDIOCPAUSE:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_pause(unit);
|
||||
case CDIOCSTART:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return EINVAL;
|
||||
case CDIOCSTOP:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_stop(unit);
|
||||
case CDIOCEJECT:
|
||||
return mcd_eject(unit);
|
||||
|
@ -536,7 +588,7 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
|||
case CDIOCRESET:
|
||||
return mcd_hard_reset(unit);
|
||||
case CDIOCALLOW:
|
||||
return 0;
|
||||
return mcd_lock_door(unit, MCD_LK_UNLOCK);
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
|
@ -755,7 +807,10 @@ mcd_getstat(int unit,int sflg)
|
|||
if (sflg)
|
||||
outb(port+mcd_command, MCD_CMDGETSTAT);
|
||||
i = mcd_getreply(unit,DELAY_GETREPLY);
|
||||
if (i<0 || (i & MCD_ST_CMDCHECK)) return -1;
|
||||
if (i<0 || (i & MCD_ST_CMDCHECK)) {
|
||||
cd->curr_mode = MCD_MD_UNKNOWN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cd->status = i;
|
||||
|
||||
|
@ -874,7 +929,9 @@ mcd_volinfo(int unit)
|
|||
return EIO;
|
||||
}
|
||||
|
||||
if (cd->volinfo.trk_low != 0 || cd->volinfo.trk_high != 0) {
|
||||
if (cd->volinfo.trk_low > 0 &&
|
||||
cd->volinfo.trk_high >= cd->volinfo.trk_low
|
||||
) {
|
||||
cd->flags |= MCDVOLINFO; /* volinfo is OK */
|
||||
return 0;
|
||||
}
|
||||
|
@ -919,8 +976,8 @@ mcd_doread(int state, struct mcd_mbx *mbxin)
|
|||
mbx = mbxsave = mbxin;
|
||||
|
||||
case MCD_S_BEGIN1:
|
||||
/* get status */
|
||||
retry_status:
|
||||
/* get status */
|
||||
outb(com_port, MCD_CMDGETSTAT);
|
||||
mbx->count = RDELAY_WAITSTAT;
|
||||
timeout((timeout_func_t)mcd_doread,
|
||||
|
@ -946,6 +1003,7 @@ mcd_doread(int state, struct mcd_mbx *mbxin)
|
|||
printf("mcd%d: audio is active\n",unit);
|
||||
goto readerr;
|
||||
}
|
||||
|
||||
retry_mode:
|
||||
/* to check for raw/cooked mode */
|
||||
if (cd->flags & MCDREADRAW) {
|
||||
|
@ -986,7 +1044,7 @@ mcd_doread(int state, struct mcd_mbx *mbxin)
|
|||
}
|
||||
cd->status = inb(port+mcd_status) & 0xFF;
|
||||
if (cd->status & MCD_ST_CMDCHECK) {
|
||||
cd->curr_mode = MCD_MD_UNKNOWN;
|
||||
cd->curr_mode = MCD_MD_UNKNOWN;
|
||||
goto retry_mode;
|
||||
}
|
||||
if (mcd_setflags(unit,cd) < 0)
|
||||
|
@ -1120,13 +1178,58 @@ mcd_doread(int state, struct mcd_mbx *mbxin)
|
|||
}
|
||||
|
||||
static int
|
||||
mcd_eject(int unit)
|
||||
mcd_lock_door(int unit, int lock)
|
||||
{
|
||||
struct mcd_data *cd = mcd_data + unit;
|
||||
int port = cd->iobase;
|
||||
|
||||
outb(port+mcd_command, MCD_CMDLOCKDRV);
|
||||
outb(port+mcd_command, lock);
|
||||
if (mcd_getstat(unit,0) == -1)
|
||||
return EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mcd_close_tray(int unit)
|
||||
{
|
||||
struct mcd_data *cd = mcd_data + unit;
|
||||
int port = cd->iobase;
|
||||
int retry, r;
|
||||
|
||||
if (mcd_getstat(unit,1) == -1)
|
||||
return EIO;
|
||||
if (cd->status & MCDDOOROPEN) {
|
||||
outb(port+mcd_command, MCD_CMDCLOSETRAY);
|
||||
for (retry = 0; retry < CLOSE_TRAY_SECS * WAIT_FRAC; retry++) {
|
||||
if (inb(port+MCD_FLAGS) & MFL_STATUS_NOT_AVAIL)
|
||||
(void) tsleep((caddr_t)cd, PSOCK | PCATCH, "mcdcls", hz/WAIT_FRAC);
|
||||
else {
|
||||
if ((r = mcd_getstat(unit,0)) == -1)
|
||||
return EIO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return ENXIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mcd_eject(int unit)
|
||||
{
|
||||
struct mcd_data *cd = mcd_data + unit;
|
||||
int port = cd->iobase, r;
|
||||
|
||||
if (mcd_getstat(unit,1) == -1) /* detect disk change too */
|
||||
return EIO;
|
||||
if (cd->status & MCDDOOROPEN)
|
||||
return mcd_close_tray(unit);
|
||||
if ((r = mcd_stop(unit)) == EIO)
|
||||
return r;
|
||||
outb(port+mcd_command, MCD_CMDEJECTDISK);
|
||||
if (mcd_getstat(unit,0) == -1) return EIO;
|
||||
if (mcd_getstat(unit,0) == -1)
|
||||
return EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1332,8 +1435,16 @@ mcd_stop(int unit)
|
|||
{
|
||||
struct mcd_data *cd = mcd_data + unit;
|
||||
|
||||
if (mcd_send(unit, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0)
|
||||
return ENXIO;
|
||||
/* Verify current status */
|
||||
if (cd->audio_status != CD_AS_PLAY_IN_PROGRESS &&
|
||||
cd->audio_status != CD_AS_PLAY_PAUSED) {
|
||||
if (cd->debug)
|
||||
printf("mcd%d: stop attempted when not playing\n", unit);
|
||||
return EINVAL;
|
||||
}
|
||||
if (cd->audio_status == CD_AS_PLAY_IN_PROGRESS)
|
||||
if (mcd_send(unit, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0)
|
||||
return EIO;
|
||||
cd->audio_status = CD_AS_PLAY_COMPLETED;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright 1993 by Holger Veit (data part)
|
||||
* Copyright 1993 by Brian Moore (audio part)
|
||||
* Changes Copyright 1993 by Gary Clark II
|
||||
* Changes Copyright (C) 1994 by Andrew A. Chernov
|
||||
* Changes Copyright (C) 1994-1995 by Andrey A. Chernov, Moscow, Russia
|
||||
*
|
||||
* Rewrote probe routine to work on newer Mitsumi drives.
|
||||
* Additional changes (C) 1994 by Jordan K. Hubbard
|
||||
|
@ -187,6 +187,8 @@ static int mcd_play(int unit, struct mcd_read2 *pb);
|
|||
static int mcd_playmsf(int unit, struct ioc_play_msf *pt);
|
||||
static int mcd_pause(int unit);
|
||||
static int mcd_resume(int unit);
|
||||
static int mcd_lock_door(int unit, int lock);
|
||||
static int mcd_close_tray(int unit);
|
||||
|
||||
extern int hz;
|
||||
extern int mcd_probe(struct isa_device *dev);
|
||||
|
@ -198,13 +200,17 @@ struct isa_driver mcddriver = { mcd_probe, mcd_attach, "mcd" };
|
|||
#define MCD_RETRYS 5
|
||||
#define MCD_RDRETRYS 8
|
||||
|
||||
#define CLOSE_TRAY_SECS 8
|
||||
#define DISK_SENSE_SECS 3
|
||||
#define WAIT_FRAC 4
|
||||
|
||||
/* several delays */
|
||||
#define RDELAY_WAITSTAT 300
|
||||
#define RDELAY_WAITMODE 300
|
||||
#define RDELAY_WAITREAD 800
|
||||
|
||||
#define MIN_DELAY 15
|
||||
#define DELAY_GETREPLY 1300000
|
||||
#define DELAY_GETREPLY 1400000
|
||||
|
||||
static struct kern_devconf kdc_mcd[NMCD] = { {
|
||||
0, 0, 0, /* filled in by dev_attach */
|
||||
|
@ -226,7 +232,6 @@ mcd_registerdev(struct isa_device *id)
|
|||
dev_attach(&kdc_mcd[id->id_unit]);
|
||||
}
|
||||
|
||||
|
||||
int mcd_attach(struct isa_device *dev)
|
||||
{
|
||||
struct mcd_data *cd = mcd_data + dev->id_unit;
|
||||
|
@ -249,7 +254,7 @@ int mcd_attach(struct isa_device *dev)
|
|||
|
||||
int mcdopen(dev_t dev)
|
||||
{
|
||||
int unit,part,phys;
|
||||
int unit,part,phys,r,retry;
|
||||
struct mcd_data *cd;
|
||||
|
||||
unit = mcd_unit(dev);
|
||||
|
@ -268,8 +273,18 @@ int mcdopen(dev_t dev)
|
|||
if (!(cd->flags & MCDVALID) && cd->openflags)
|
||||
return ENXIO;
|
||||
|
||||
if (mcd_getstat(unit,1) == -1) /* detect disk change too */
|
||||
return ENXIO;
|
||||
if (mcd_close_tray(unit) == EIO) /* detect disk change too */
|
||||
return EIO;
|
||||
|
||||
if ( (cd->status & (MCDDSKCHNG|MCDDOOROPEN))
|
||||
|| !(cd->status & MCDDSKIN))
|
||||
for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) {
|
||||
(void) tsleep((caddr_t)cd, PSOCK | PCATCH, "mcdsns", hz/WAIT_FRAC);
|
||||
if ((r = mcd_getstat(unit,1)) == -1)
|
||||
return EIO;
|
||||
if (r != -2)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cd->status & MCDDOOROPEN) {
|
||||
printf("mcd%d: door is open\n");
|
||||
|
@ -279,6 +294,10 @@ int mcdopen(dev_t dev)
|
|||
printf("mcd%d: no CD inside\n");
|
||||
return ENXIO;
|
||||
}
|
||||
if (cd->status & MCDDSKCHNG) {
|
||||
printf("mcd%d: CD not sensed\n");
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
if (mcdsize(dev) < 0) {
|
||||
printf("mcd%d: failed to get disk size\n",unit);
|
||||
|
@ -300,6 +319,9 @@ MCD_TRACE("open: partition=%d, disksize = %d, blksize=%d\n",
|
|||
if (part == RAW_PART && phys != 0)
|
||||
cd->partflags[part] |= MCDREADRAW;
|
||||
kdc_mcd[unit].kdc_state = DC_BUSY;
|
||||
(void) mcd_lock_door(unit, MCD_LK_LOCK);
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -323,7 +345,9 @@ int mcdclose(dev_t dev)
|
|||
return ENXIO;
|
||||
|
||||
kdc_mcd[unit].kdc_state = DC_IDLE;
|
||||
if (mcd_getstat(unit,1) == -2)
|
||||
(void) mcd_lock_door(unit, MCD_LK_UNLOCK);
|
||||
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return 0;
|
||||
|
||||
/* close channel */
|
||||
|
@ -463,19 +487,23 @@ int mcdioctl(dev_t dev, int cmd, caddr_t addr, int flags)
|
|||
part = mcd_part(dev);
|
||||
cd = mcd_data + unit;
|
||||
|
||||
if (mcd_getstat(unit, 1) < 0) /* detect disk change too */
|
||||
return EIO;
|
||||
if (!(cd->flags & MCDVALID))
|
||||
if (mcd_getstat(unit, 1) == -1) /* detect disk change too */
|
||||
return EIO;
|
||||
MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
||||
|
||||
switch (cmd) {
|
||||
case DIOCSBAD:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return EINVAL;
|
||||
case DIOCGDINFO:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
*(struct disklabel *) addr = cd->dlabel;
|
||||
return 0;
|
||||
case DIOCGPART:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
((struct partinfo *) addr)->disklab = &cd->dlabel;
|
||||
((struct partinfo *) addr)->part =
|
||||
&cd->dlabel.d_partitions[mcd_part(dev)];
|
||||
|
@ -487,6 +515,8 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
|||
*/
|
||||
case DIOCWDINFO:
|
||||
case DIOCSDINFO:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
if ((flags & FWRITE) == 0)
|
||||
return EBADF;
|
||||
else {
|
||||
|
@ -495,18 +525,32 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
|||
0);
|
||||
}
|
||||
case DIOCWLABEL:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return EBADF;
|
||||
case CDIOCPLAYTRACKS:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_playtracks(unit, (struct ioc_play_track *) addr);
|
||||
case CDIOCPLAYBLOCKS:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return EINVAL;
|
||||
case CDIOCPLAYMSF:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_playmsf(unit, (struct ioc_play_msf *) addr);
|
||||
case CDIOCREADSUBCHANNEL:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_subchan(unit, (struct ioc_read_subchannel *) addr);
|
||||
case CDIOREADTOCHEADER:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_toc_header(unit, (struct ioc_toc_header *) addr);
|
||||
case CDIOREADTOCENTRYS:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_toc_entrys(unit, (struct ioc_read_toc_entry *) addr);
|
||||
case CDIOCSETPATCH:
|
||||
case CDIOCGETVOL:
|
||||
|
@ -518,12 +562,20 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
|||
case CDIOCSETRIGHT:
|
||||
return EINVAL;
|
||||
case CDIOCRESUME:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_resume(unit);
|
||||
case CDIOCPAUSE:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_pause(unit);
|
||||
case CDIOCSTART:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return EINVAL;
|
||||
case CDIOCSTOP:
|
||||
if (!(cd->flags & MCDVALID))
|
||||
return ENXIO;
|
||||
return mcd_stop(unit);
|
||||
case CDIOCEJECT:
|
||||
return mcd_eject(unit);
|
||||
|
@ -536,7 +588,7 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0);
|
|||
case CDIOCRESET:
|
||||
return mcd_hard_reset(unit);
|
||||
case CDIOCALLOW:
|
||||
return 0;
|
||||
return mcd_lock_door(unit, MCD_LK_UNLOCK);
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
|
@ -755,7 +807,10 @@ mcd_getstat(int unit,int sflg)
|
|||
if (sflg)
|
||||
outb(port+mcd_command, MCD_CMDGETSTAT);
|
||||
i = mcd_getreply(unit,DELAY_GETREPLY);
|
||||
if (i<0 || (i & MCD_ST_CMDCHECK)) return -1;
|
||||
if (i<0 || (i & MCD_ST_CMDCHECK)) {
|
||||
cd->curr_mode = MCD_MD_UNKNOWN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cd->status = i;
|
||||
|
||||
|
@ -874,7 +929,9 @@ mcd_volinfo(int unit)
|
|||
return EIO;
|
||||
}
|
||||
|
||||
if (cd->volinfo.trk_low != 0 || cd->volinfo.trk_high != 0) {
|
||||
if (cd->volinfo.trk_low > 0 &&
|
||||
cd->volinfo.trk_high >= cd->volinfo.trk_low
|
||||
) {
|
||||
cd->flags |= MCDVOLINFO; /* volinfo is OK */
|
||||
return 0;
|
||||
}
|
||||
|
@ -919,8 +976,8 @@ mcd_doread(int state, struct mcd_mbx *mbxin)
|
|||
mbx = mbxsave = mbxin;
|
||||
|
||||
case MCD_S_BEGIN1:
|
||||
/* get status */
|
||||
retry_status:
|
||||
/* get status */
|
||||
outb(com_port, MCD_CMDGETSTAT);
|
||||
mbx->count = RDELAY_WAITSTAT;
|
||||
timeout((timeout_func_t)mcd_doread,
|
||||
|
@ -946,6 +1003,7 @@ mcd_doread(int state, struct mcd_mbx *mbxin)
|
|||
printf("mcd%d: audio is active\n",unit);
|
||||
goto readerr;
|
||||
}
|
||||
|
||||
retry_mode:
|
||||
/* to check for raw/cooked mode */
|
||||
if (cd->flags & MCDREADRAW) {
|
||||
|
@ -986,7 +1044,7 @@ mcd_doread(int state, struct mcd_mbx *mbxin)
|
|||
}
|
||||
cd->status = inb(port+mcd_status) & 0xFF;
|
||||
if (cd->status & MCD_ST_CMDCHECK) {
|
||||
cd->curr_mode = MCD_MD_UNKNOWN;
|
||||
cd->curr_mode = MCD_MD_UNKNOWN;
|
||||
goto retry_mode;
|
||||
}
|
||||
if (mcd_setflags(unit,cd) < 0)
|
||||
|
@ -1120,13 +1178,58 @@ mcd_doread(int state, struct mcd_mbx *mbxin)
|
|||
}
|
||||
|
||||
static int
|
||||
mcd_eject(int unit)
|
||||
mcd_lock_door(int unit, int lock)
|
||||
{
|
||||
struct mcd_data *cd = mcd_data + unit;
|
||||
int port = cd->iobase;
|
||||
|
||||
outb(port+mcd_command, MCD_CMDLOCKDRV);
|
||||
outb(port+mcd_command, lock);
|
||||
if (mcd_getstat(unit,0) == -1)
|
||||
return EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mcd_close_tray(int unit)
|
||||
{
|
||||
struct mcd_data *cd = mcd_data + unit;
|
||||
int port = cd->iobase;
|
||||
int retry, r;
|
||||
|
||||
if (mcd_getstat(unit,1) == -1)
|
||||
return EIO;
|
||||
if (cd->status & MCDDOOROPEN) {
|
||||
outb(port+mcd_command, MCD_CMDCLOSETRAY);
|
||||
for (retry = 0; retry < CLOSE_TRAY_SECS * WAIT_FRAC; retry++) {
|
||||
if (inb(port+MCD_FLAGS) & MFL_STATUS_NOT_AVAIL)
|
||||
(void) tsleep((caddr_t)cd, PSOCK | PCATCH, "mcdcls", hz/WAIT_FRAC);
|
||||
else {
|
||||
if ((r = mcd_getstat(unit,0)) == -1)
|
||||
return EIO;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return ENXIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mcd_eject(int unit)
|
||||
{
|
||||
struct mcd_data *cd = mcd_data + unit;
|
||||
int port = cd->iobase, r;
|
||||
|
||||
if (mcd_getstat(unit,1) == -1) /* detect disk change too */
|
||||
return EIO;
|
||||
if (cd->status & MCDDOOROPEN)
|
||||
return mcd_close_tray(unit);
|
||||
if ((r = mcd_stop(unit)) == EIO)
|
||||
return r;
|
||||
outb(port+mcd_command, MCD_CMDEJECTDISK);
|
||||
if (mcd_getstat(unit,0) == -1) return EIO;
|
||||
if (mcd_getstat(unit,0) == -1)
|
||||
return EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1332,8 +1435,16 @@ mcd_stop(int unit)
|
|||
{
|
||||
struct mcd_data *cd = mcd_data + unit;
|
||||
|
||||
if (mcd_send(unit, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0)
|
||||
return ENXIO;
|
||||
/* Verify current status */
|
||||
if (cd->audio_status != CD_AS_PLAY_IN_PROGRESS &&
|
||||
cd->audio_status != CD_AS_PLAY_PAUSED) {
|
||||
if (cd->debug)
|
||||
printf("mcd%d: stop attempted when not playing\n", unit);
|
||||
return EINVAL;
|
||||
}
|
||||
if (cd->audio_status == CD_AS_PLAY_IN_PROGRESS)
|
||||
if (mcd_send(unit, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0)
|
||||
return EIO;
|
||||
cd->audio_status = CD_AS_PLAY_COMPLETED;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue