mcd.c (2395) | mcd.c (2477) |
---|---|
1/* 2 * Copyright 1993 by Holger Veit (data part) 3 * Copyright 1993 by Brian Moore (audio part) 4 * Changes Copyright 1993 by Gary Clark II 5 * 6 * Rewrote probe routine to work on newer Mitsumi drives. 7 * Additional changes (C) 1994 by Jordan K. Hubbard 8 * --- 25 unchanged lines hidden (view full) --- 34 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 35 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 36 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 37 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 38 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 * | 1/* 2 * Copyright 1993 by Holger Veit (data part) 3 * Copyright 1993 by Brian Moore (audio part) 4 * Changes Copyright 1993 by Gary Clark II 5 * 6 * Rewrote probe routine to work on newer Mitsumi drives. 7 * Additional changes (C) 1994 by Jordan K. Hubbard 8 * --- 25 unchanged lines hidden (view full) --- 34 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 35 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 36 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 37 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 38 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 * |
42 * $Id: mcd.c,v 1.21 1994/08/28 20:37:59 ache Exp $ | 42 * $Id: mcd.c,v 1.16 1994/04/30 17:03:33 gclarkii Exp $ |
43 */ 44static char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; 45 46#include "mcd.h" 47#if NMCD > 0 48#include <sys/types.h> 49#include <sys/param.h> 50#include <sys/systm.h> --- 6 unchanged lines hidden (view full) --- 57#include <sys/cdio.h> 58#include <sys/errno.h> 59#include <sys/dkbad.h> 60#include <sys/disklabel.h> 61#include <i386/isa/isa.h> 62#include <i386/isa/isa_device.h> 63#include <i386/isa/mcdreg.h> 64 | 43 */ 44static char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; 45 46#include "mcd.h" 47#if NMCD > 0 48#include <sys/types.h> 49#include <sys/param.h> 50#include <sys/systm.h> --- 6 unchanged lines hidden (view full) --- 57#include <sys/cdio.h> 58#include <sys/errno.h> 59#include <sys/dkbad.h> 60#include <sys/disklabel.h> 61#include <i386/isa/isa.h> 62#include <i386/isa/isa_device.h> 63#include <i386/isa/mcdreg.h> 64 |
65/* user definable options */ 66/*#define MCD_TO_WARNING_ON*/ /* define to get timeout messages */ 67/*#define MCDMINI*/ /* define for a mini configuration for boot kernel */ 68/*#define DEBUG*/ | 65#define MCD_TRACE(fmt,a,b,c,d) {if (mcd_data[unit].debug) {printf("mcd%d: status=0x%02x: ",unit,mcd_data[unit].status); printf(fmt,a,b,c,d);}} |
69 | 66 |
70#ifdef MCDMINI 71#define MCD_TRACE(fmt,a,b,c,d) 72#ifdef MCD_TO_WARNING_ON 73#undef MCD_TO_WARNING_ON 74#endif 75#else 76#define MCD_TRACE(fmt,a,b,c,d) {if (mcd_data[unit].debug) {printf("mcd%d st=%02x: ",unit,mcd_data[unit].status); printf(fmt,a,b,c,d);}} 77#endif 78 | |
79#define mcd_part(dev) ((minor(dev)) & 7) 80#define mcd_unit(dev) (((minor(dev)) & 0x38) >> 3) 81#define mcd_phys(dev) (((minor(dev)) & 0x40) >> 6) 82#define RAW_PART 2 83 84/* flags */ 85#define MCDOPEN 0x0001 /* device opened */ 86#define MCDVALID 0x0002 /* parameters loaded */ 87#define MCDINIT 0x0004 /* device is init'd */ | 67#define mcd_part(dev) ((minor(dev)) & 7) 68#define mcd_unit(dev) (((minor(dev)) & 0x38) >> 3) 69#define mcd_phys(dev) (((minor(dev)) & 0x40) >> 6) 70#define RAW_PART 2 71 72/* flags */ 73#define MCDOPEN 0x0001 /* device opened */ 74#define MCDVALID 0x0002 /* parameters loaded */ 75#define MCDINIT 0x0004 /* device is init'd */ |
88#define MCDWAIT 0x0008 /* waiting for something */ | 76#define MCDNEWMODEL 0x0008 /* device is new model */ |
89#define MCDLABEL 0x0010 /* label is read */ 90#define MCDPROBING 0x0020 /* probing */ 91#define MCDREADRAW 0x0040 /* read raw mode (2352 bytes) */ 92#define MCDVOLINFO 0x0080 /* already read volinfo */ 93#define MCDTOC 0x0100 /* already read toc */ 94#define MCDMBXBSY 0x0200 /* local mbx is busy */ 95 96/* status */ 97#define MCDAUDIOBSY MCD_ST_AUDIOBSY /* playing audio */ 98#define MCDDSKCHNG MCD_ST_DSKCHNG /* sensed change of disk */ 99#define MCDDSKIN MCD_ST_DSKIN /* sensed disk in drive */ 100#define MCDDOOROPEN MCD_ST_DOOROPEN /* sensed door open */ 101 102/* These are apparently the different states a mitsumi can get up to */ 103#define MCDCDABSENT 0x0030 104#define MCDCDPRESENT 0x0020 105#define MCDSCLOSED 0x0080 106#define MCDSOPEN 0x00a0 107 | 77#define MCDLABEL 0x0010 /* label is read */ 78#define MCDPROBING 0x0020 /* probing */ 79#define MCDREADRAW 0x0040 /* read raw mode (2352 bytes) */ 80#define MCDVOLINFO 0x0080 /* already read volinfo */ 81#define MCDTOC 0x0100 /* already read toc */ 82#define MCDMBXBSY 0x0200 /* local mbx is busy */ 83 84/* status */ 85#define MCDAUDIOBSY MCD_ST_AUDIOBSY /* playing audio */ 86#define MCDDSKCHNG MCD_ST_DSKCHNG /* sensed change of disk */ 87#define MCDDSKIN MCD_ST_DSKIN /* sensed disk in drive */ 88#define MCDDOOROPEN MCD_ST_DOOROPEN /* sensed door open */ 89 90/* These are apparently the different states a mitsumi can get up to */ 91#define MCDCDABSENT 0x0030 92#define MCDCDPRESENT 0x0020 93#define MCDSCLOSED 0x0080 94#define MCDSOPEN 0x00a0 95 |
96#define MCD_MD_UNKNOWN (-1) 97 |
|
108/* toc */ 109#define MCD_MAXTOCS 104 /* from the Linux driver */ 110#define MCD_LASTPLUS1 170 /* special toc entry */ 111 112struct mcd_mbx { 113 short unit; 114 short port; 115 short retry; 116 short nblk; 117 int sz; 118 u_long skip; 119 struct buf *bp; 120 int p_offset; 121 short count; | 98/* toc */ 99#define MCD_MAXTOCS 104 /* from the Linux driver */ 100#define MCD_LASTPLUS1 170 /* special toc entry */ 101 102struct mcd_mbx { 103 short unit; 104 short port; 105 short retry; 106 short nblk; 107 int sz; 108 u_long skip; 109 struct buf *bp; 110 int p_offset; 111 short count; |
112 short mode; |
|
122}; 123 124struct mcd_data { 125 short config; 126 short flags; 127 short status; 128 int blksize; 129 u_long disksize; 130 int iobase; 131 struct disklabel dlabel; 132 int partflags[MAXPARTITIONS]; 133 int openflags; 134 struct mcd_volinfo volinfo; | 113}; 114 115struct mcd_data { 116 short config; 117 short flags; 118 short status; 119 int blksize; 120 u_long disksize; 121 int iobase; 122 struct disklabel dlabel; 123 int partflags[MAXPARTITIONS]; 124 int openflags; 125 struct mcd_volinfo volinfo; |
135#ifndef MCDMINI | |
136 struct mcd_qchninfo toc[MCD_MAXTOCS]; 137 short audio_status; | 126 struct mcd_qchninfo toc[MCD_MAXTOCS]; 127 short audio_status; |
128 short curr_mode; |
|
138 struct mcd_read2 lastpb; | 129 struct mcd_read2 lastpb; |
139#endif | |
140 short debug; 141 struct buf head; /* head of buf queue */ 142 struct mcd_mbx mbx; 143} mcd_data[NMCD]; 144 145/* reader state machine */ 146#define MCD_S_BEGIN 0 147#define MCD_S_BEGIN1 1 --- 7 unchanged lines hidden (view full) --- 155void mcdstrategy(struct buf *bp); 156int mcdioctl(dev_t dev, int cmd, caddr_t addr, int flags); 157int mcdsize(dev_t dev); 158static void mcd_done(struct mcd_mbx *mbx); 159static void mcd_start(int unit); 160static int mcd_getdisklabel(int unit); 161static void mcd_configure(struct mcd_data *cd); 162static int mcd_get(int unit, char *buf, int nmax); | 130 short debug; 131 struct buf head; /* head of buf queue */ 132 struct mcd_mbx mbx; 133} mcd_data[NMCD]; 134 135/* reader state machine */ 136#define MCD_S_BEGIN 0 137#define MCD_S_BEGIN1 1 --- 7 unchanged lines hidden (view full) --- 145void mcdstrategy(struct buf *bp); 146int mcdioctl(dev_t dev, int cmd, caddr_t addr, int flags); 147int mcdsize(dev_t dev); 148static void mcd_done(struct mcd_mbx *mbx); 149static void mcd_start(int unit); 150static int mcd_getdisklabel(int unit); 151static void mcd_configure(struct mcd_data *cd); 152static int mcd_get(int unit, char *buf, int nmax); |
163static void mcd_setflags(int unit,struct mcd_data *cd); | 153static int mcd_setflags(int unit,struct mcd_data *cd); |
164static int mcd_getstat(int unit,int sflg); 165static int mcd_send(int unit, int cmd,int nretrys); 166static int bcd2bin(bcd_t b); 167static bcd_t bin2bcd(int b); 168static void hsg2msf(int hsg, bcd_t *msf); 169static int msf2hsg(bcd_t *msf); 170static int mcd_volinfo(int unit); 171static int mcd_waitrdy(int port,int dly); 172static void mcd_doread(int state, struct mcd_mbx *mbxin); | 154static int mcd_getstat(int unit,int sflg); 155static int mcd_send(int unit, int cmd,int nretrys); 156static int bcd2bin(bcd_t b); 157static bcd_t bin2bcd(int b); 158static void hsg2msf(int hsg, bcd_t *msf); 159static int msf2hsg(bcd_t *msf); 160static int mcd_volinfo(int unit); 161static int mcd_waitrdy(int port,int dly); 162static void mcd_doread(int state, struct mcd_mbx *mbxin); |
173#ifndef MCDMINI | 163static void mcd_soft_reset(int unit); 164static int mcd_hard_reset(int unit); |
174static int mcd_setmode(int unit, int mode); 175static int mcd_getqchan(int unit, struct mcd_qchninfo *q); 176static int mcd_subchan(int unit, struct ioc_read_subchannel *sc); 177static int mcd_toc_header(int unit, struct ioc_toc_header *th); 178static int mcd_read_toc(int unit); | 165static int mcd_setmode(int unit, int mode); 166static int mcd_getqchan(int unit, struct mcd_qchninfo *q); 167static int mcd_subchan(int unit, struct ioc_read_subchannel *sc); 168static int mcd_toc_header(int unit, struct ioc_toc_header *th); 169static int mcd_read_toc(int unit); |
179static int mcd_toc_entry(int unit, struct ioc_read_toc_entry *te); | 170static int mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te); |
180static int mcd_stop(int unit); | 171static int mcd_stop(int unit); |
172static int mcd_eject(int unit); |
|
181static int mcd_playtracks(int unit, struct ioc_play_track *pt); 182static int mcd_play(int unit, struct mcd_read2 *pb); | 173static int mcd_playtracks(int unit, struct ioc_play_track *pt); 174static int mcd_play(int unit, struct mcd_read2 *pb); |
175static int mcd_playmsf(int unit, struct ioc_play_msf *pt); |
|
183static int mcd_pause(int unit); 184static int mcd_resume(int unit); | 176static int mcd_pause(int unit); 177static int mcd_resume(int unit); |
185#endif | |
186 187extern int hz; 188extern int mcd_probe(struct isa_device *dev); 189extern int mcd_attach(struct isa_device *dev); 190struct isa_driver mcddriver = { mcd_probe, mcd_attach, "mcd" }; 191 192#define mcd_put(port,byte) outb(port,byte) 193 194#define MCD_RETRYS 5 195#define MCD_RDRETRYS 8 196 197#define MCDBLK 2048 /* for cooked mode */ 198#define MCDRBLK 2352 /* for raw mode */ 199 200/* several delays */ | 178 179extern int hz; 180extern int mcd_probe(struct isa_device *dev); 181extern int mcd_attach(struct isa_device *dev); 182struct isa_driver mcddriver = { mcd_probe, mcd_attach, "mcd" }; 183 184#define mcd_put(port,byte) outb(port,byte) 185 186#define MCD_RETRYS 5 187#define MCD_RDRETRYS 8 188 189#define MCDBLK 2048 /* for cooked mode */ 190#define MCDRBLK 2352 /* for raw mode */ 191 192/* several delays */ |
201#define RDELAY_WAITSTAT 300 202#define RDELAY_WAITMODE 300 | 193#define RDELAY_WAITSTAT 300 194#define RDELAY_WAITMODE 300 |
203#define RDELAY_WAITREAD 800 204 | 195#define RDELAY_WAITREAD 800 196 |
205#define DELAY_GETREPLY 200000l /* 200000 * 2us */ | 197#define MIN_DELAY 15 198#define DELAY_GETREPLY 1200000 |
206 207int mcd_attach(struct isa_device *dev) 208{ 209 struct mcd_data *cd = mcd_data + dev->id_unit; 210 int i; 211 212 cd->iobase = dev->id_iobase; 213 cd->flags |= MCDINIT; | 199 200int mcd_attach(struct isa_device *dev) 201{ 202 struct mcd_data *cd = mcd_data + dev->id_unit; 203 int i; 204 205 cd->iobase = dev->id_iobase; 206 cd->flags |= MCDINIT; |
214 cd->openflags = 0; 215 for (i=0; i<MAXPARTITIONS; i++) cd->partflags[i] = 0; | 207 mcd_soft_reset(dev->id_unit); |
216 217#ifdef NOTYET 218 /* wire controller for interrupts and dma */ 219 mcd_configure(cd); 220#endif 221 222 return 1; 223} --- 14 unchanged lines hidden (view full) --- 238 /* not initialized*/ 239 if (!(cd->flags & MCDINIT)) 240 return ENXIO; 241 242 /* invalidated in the meantime? mark all open part's invalid */ 243 if (!(cd->flags & MCDVALID) && cd->openflags) 244 return ENXIO; 245 | 208 209#ifdef NOTYET 210 /* wire controller for interrupts and dma */ 211 mcd_configure(cd); 212#endif 213 214 return 1; 215} --- 14 unchanged lines hidden (view full) --- 230 /* not initialized*/ 231 if (!(cd->flags & MCDINIT)) 232 return ENXIO; 233 234 /* invalidated in the meantime? mark all open part's invalid */ 235 if (!(cd->flags & MCDVALID) && cd->openflags) 236 return ENXIO; 237 |
246 if (mcd_getstat(unit,1) < 0) | 238 if (mcd_getstat(unit,1) == -1) /* detect disk change too */ |
247 return ENXIO; 248 | 239 return ENXIO; 240 |
249 /* XXX get a default disklabel */ 250 mcd_getdisklabel(unit); | 241 if (cd->status & MCDDOOROPEN) { 242 printf("mcd%d: door is open\n"); 243 return ENXIO; 244 } 245 if (!(cd->status & MCDDSKIN)) { 246 printf("mcd%d: no CD inside\n"); 247 return ENXIO; 248 } |
251 252 if (mcdsize(dev) < 0) { 253 printf("mcd%d: failed to get disk size\n",unit); 254 return ENXIO; 255 } else 256 cd->flags |= MCDVALID; 257 | 249 250 if (mcdsize(dev) < 0) { 251 printf("mcd%d: failed to get disk size\n",unit); 252 return ENXIO; 253 } else 254 cd->flags |= MCDVALID; 255 |
256 /* XXX get a default disklabel */ 257 mcd_getdisklabel(unit); 258 |
|
258MCD_TRACE("open: partition=%d, disksize = %d, blksize=%d\n", 259 part,cd->disksize,cd->blksize,0); 260 261 if (part == RAW_PART || 262 (part < cd->dlabel.d_npartitions && 263 cd->dlabel.d_partitions[part].p_fstype != FS_UNUSED)) { 264 cd->partflags[part] |= MCDOPEN; 265 cd->openflags |= (1<<part); --- 16 unchanged lines hidden (view full) --- 282 283 cd = mcd_data + unit; 284 part = mcd_part(dev); 285 phys = mcd_phys(dev); 286 287 if (!(cd->flags & MCDINIT)) 288 return ENXIO; 289 | 259MCD_TRACE("open: partition=%d, disksize = %d, blksize=%d\n", 260 part,cd->disksize,cd->blksize,0); 261 262 if (part == RAW_PART || 263 (part < cd->dlabel.d_npartitions && 264 cd->dlabel.d_partitions[part].p_fstype != FS_UNUSED)) { 265 cd->partflags[part] |= MCDOPEN; 266 cd->openflags |= (1<<part); --- 16 unchanged lines hidden (view full) --- 283 284 cd = mcd_data + unit; 285 part = mcd_part(dev); 286 phys = mcd_phys(dev); 287 288 if (!(cd->flags & MCDINIT)) 289 return ENXIO; 290 |
290 mcd_getstat(unit,1); /* get status */ | 291 if (mcd_getstat(unit,1) == -2) 292 return 0; |
291 292 /* close channel */ 293 cd->partflags[part] &= ~(MCDOPEN|MCDREADRAW); 294 cd->openflags &= ~(1<<part); 295 MCD_TRACE("close: partition=%d\n",part,0,0,0); 296 297 return 0; 298} --- 74 unchanged lines hidden (view full) --- 373static void mcd_start(int unit) 374{ 375 struct mcd_data *cd = mcd_data + unit; 376 struct buf *bp, *qp = &cd->head; 377 struct partition *p; 378 int part; 379 register s = splbio(); 380 | 293 294 /* close channel */ 295 cd->partflags[part] &= ~(MCDOPEN|MCDREADRAW); 296 cd->openflags &= ~(1<<part); 297 MCD_TRACE("close: partition=%d\n",part,0,0,0); 298 299 return 0; 300} --- 74 unchanged lines hidden (view full) --- 375static void mcd_start(int unit) 376{ 377 struct mcd_data *cd = mcd_data + unit; 378 struct buf *bp, *qp = &cd->head; 379 struct partition *p; 380 int part; 381 register s = splbio(); 382 |
381 if (cd->flags & MCDMBXBSY) | 383 if (cd->flags & MCDMBXBSY) { 384 splx(s); |
382 return; | 385 return; |
386 } |
|
383 384 if ((bp = qp->b_actf) != 0) { 385 /* block found to process, dequeue */ 386 /*MCD_TRACE("mcd_start: found block bp=0x%x\n",bp,0,0,0);*/ | 387 388 if ((bp = qp->b_actf) != 0) { 389 /* block found to process, dequeue */ 390 /*MCD_TRACE("mcd_start: found block bp=0x%x\n",bp,0,0,0);*/ |
387 qp->b_actf = bp->b_actf; | 391 qp->b_actf = bp->av_forw; |
388 splx(s); 389 } else { 390 /* nothing to do */ 391 splx(s); 392 return; 393 } 394 395 /* changed media? */ 396 if (!(cd->flags & MCDVALID)) { 397 MCD_TRACE("mcd_start: drive not valid\n",0,0,0,0); 398 return; 399 } 400 401 p = cd->dlabel.d_partitions + mcd_part(bp->b_dev); 402 403 cd->flags |= MCDMBXBSY; | 392 splx(s); 393 } else { 394 /* nothing to do */ 395 splx(s); 396 return; 397 } 398 399 /* changed media? */ 400 if (!(cd->flags & MCDVALID)) { 401 MCD_TRACE("mcd_start: drive not valid\n",0,0,0,0); 402 return; 403 } 404 405 p = cd->dlabel.d_partitions + mcd_part(bp->b_dev); 406 407 cd->flags |= MCDMBXBSY; |
408 if (cd->partflags[mcd_part(bp->b_dev)] & MCDREADRAW) 409 cd->flags |= MCDREADRAW; |
|
404 cd->mbx.unit = unit; 405 cd->mbx.port = cd->iobase; 406 cd->mbx.retry = MCD_RETRYS; 407 cd->mbx.bp = bp; 408 cd->mbx.p_offset = p->p_offset; 409 410 /* calling the read routine */ 411 mcd_doread(MCD_S_BEGIN,&(cd->mbx)); --- 5 unchanged lines hidden (view full) --- 417{ 418 struct mcd_data *cd; 419 int unit,part; 420 421 unit = mcd_unit(dev); 422 part = mcd_part(dev); 423 cd = mcd_data + unit; 424 | 410 cd->mbx.unit = unit; 411 cd->mbx.port = cd->iobase; 412 cd->mbx.retry = MCD_RETRYS; 413 cd->mbx.bp = bp; 414 cd->mbx.p_offset = p->p_offset; 415 416 /* calling the read routine */ 417 mcd_doread(MCD_S_BEGIN,&(cd->mbx)); --- 5 unchanged lines hidden (view full) --- 423{ 424 struct mcd_data *cd; 425 int unit,part; 426 427 unit = mcd_unit(dev); 428 part = mcd_part(dev); 429 cd = mcd_data + unit; 430 |
425#ifdef MCDMINI 426 return ENOTTY; 427#else | 431 if (mcd_getstat(unit, 1) < 0) /* detect disk change too */ 432 return EIO; |
428 if (!(cd->flags & MCDVALID)) 429 return EIO; 430MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0); 431 432 switch (cmd) { 433 case DIOCSBAD: 434 return EINVAL; 435 case DIOCGDINFO: | 433 if (!(cd->flags & MCDVALID)) 434 return EIO; 435MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0); 436 437 switch (cmd) { 438 case DIOCSBAD: 439 return EINVAL; 440 case DIOCGDINFO: |
441 *(struct disklabel *) addr = cd->dlabel; 442 return 0; |
|
436 case DIOCGPART: | 443 case DIOCGPART: |
444 ((struct partinfo *) addr)->disklab = &cd->dlabel; 445 ((struct partinfo *) addr)->part = 446 &cd->dlabel.d_partitions[mcd_part(dev)]; 447 return 0; 448 449 /* 450 * a bit silly, but someone might want to test something on a 451 * section of cdrom. 452 */ |
|
437 case DIOCWDINFO: 438 case DIOCSDINFO: | 453 case DIOCWDINFO: 454 case DIOCSDINFO: |
455 if ((flags & FWRITE) == 0) 456 return EBADF; 457 else { 458 return setdisklabel(&cd->dlabel, 459 (struct disklabel *) addr, 460 0, 461 0); 462 } |
|
439 case DIOCWLABEL: | 463 case DIOCWLABEL: |
440 return ENOTTY; | 464 return EBADF; |
441 case CDIOCPLAYTRACKS: 442 return mcd_playtracks(unit, (struct ioc_play_track *) addr); 443 case CDIOCPLAYBLOCKS: | 465 case CDIOCPLAYTRACKS: 466 return mcd_playtracks(unit, (struct ioc_play_track *) addr); 467 case CDIOCPLAYBLOCKS: |
444 return mcd_play(unit, (struct mcd_read2 *) addr); | 468 return EINVAL; 469 case CDIOCPLAYMSF: 470 return mcd_playmsf(unit, (struct ioc_play_msf *) addr); |
445 case CDIOCREADSUBCHANNEL: 446 return mcd_subchan(unit, (struct ioc_read_subchannel *) addr); 447 case CDIOREADTOCHEADER: 448 return mcd_toc_header(unit, (struct ioc_toc_header *) addr); 449 case CDIOREADTOCENTRYS: | 471 case CDIOCREADSUBCHANNEL: 472 return mcd_subchan(unit, (struct ioc_read_subchannel *) addr); 473 case CDIOREADTOCHEADER: 474 return mcd_toc_header(unit, (struct ioc_toc_header *) addr); 475 case CDIOREADTOCENTRYS: |
450 return mcd_toc_entry(unit, (struct ioc_read_toc_entry *) addr); | 476 return mcd_toc_entrys(unit, (struct ioc_read_toc_entry *) addr); |
451 case CDIOCSETPATCH: 452 case CDIOCGETVOL: 453 case CDIOCSETVOL: 454 case CDIOCSETMONO: 455 case CDIOCSETSTERIO: 456 case CDIOCSETMUTE: 457 case CDIOCSETLEFT: 458 case CDIOCSETRIGHT: 459 return EINVAL; 460 case CDIOCRESUME: 461 return mcd_resume(unit); 462 case CDIOCPAUSE: 463 return mcd_pause(unit); 464 case CDIOCSTART: 465 return EINVAL; 466 case CDIOCSTOP: 467 return mcd_stop(unit); 468 case CDIOCEJECT: | 477 case CDIOCSETPATCH: 478 case CDIOCGETVOL: 479 case CDIOCSETVOL: 480 case CDIOCSETMONO: 481 case CDIOCSETSTERIO: 482 case CDIOCSETMUTE: 483 case CDIOCSETLEFT: 484 case CDIOCSETRIGHT: 485 return EINVAL; 486 case CDIOCRESUME: 487 return mcd_resume(unit); 488 case CDIOCPAUSE: 489 return mcd_pause(unit); 490 case CDIOCSTART: 491 return EINVAL; 492 case CDIOCSTOP: 493 return mcd_stop(unit); 494 case CDIOCEJECT: |
469 return EINVAL; | 495 return mcd_eject(unit); |
470 case CDIOCSETDEBUG: 471 cd->debug = 1; 472 return 0; 473 case CDIOCCLRDEBUG: 474 cd->debug = 0; 475 return 0; 476 case CDIOCRESET: | 496 case CDIOCSETDEBUG: 497 cd->debug = 1; 498 return 0; 499 case CDIOCCLRDEBUG: 500 cd->debug = 0; 501 return 0; 502 case CDIOCRESET: |
477 return EINVAL; | 503 return mcd_hard_reset(unit); |
478 default: 479 return ENOTTY; 480 } 481 /*NOTREACHED*/ | 504 default: 505 return ENOTTY; 506 } 507 /*NOTREACHED*/ |
482#endif /*!MCDMINI*/ | |
483} 484 485/* this could have been taken from scsi/cd.c, but it is not clear 486 * whether the scsi cd driver is linked in 487 */ 488static int mcd_getdisklabel(int unit) 489{ 490 struct mcd_data *cd = mcd_data + unit; --- 26 unchanged lines hidden (view full) --- 517} 518 519int mcdsize(dev_t dev) 520{ 521 int size; 522 int unit = mcd_unit(dev); 523 struct mcd_data *cd = mcd_data + unit; 524 | 508} 509 510/* this could have been taken from scsi/cd.c, but it is not clear 511 * whether the scsi cd driver is linked in 512 */ 513static int mcd_getdisklabel(int unit) 514{ 515 struct mcd_data *cd = mcd_data + unit; --- 26 unchanged lines hidden (view full) --- 542} 543 544int mcdsize(dev_t dev) 545{ 546 int size; 547 int unit = mcd_unit(dev); 548 struct mcd_data *cd = mcd_data + unit; 549 |
525 if (mcd_volinfo(unit) >= 0) { | 550 if (mcd_volinfo(unit) == 0) { |
526 cd->blksize = MCDBLK; 527 size = msf2hsg(cd->volinfo.vol_msf); 528 cd->disksize = size * (MCDBLK/DEV_BSIZE); 529 return 0; 530 } 531 return -1; 532} 533 --- 26 unchanged lines hidden (view full) --- 560{ 561 int i; 562 563 for (i = 0; i < count; i++) { 564 if (!(inb(port+MCD_FLAGS) & MCD_ST_BUSY)) { 565 return 1; 566 } 567 } | 551 cd->blksize = MCDBLK; 552 size = msf2hsg(cd->volinfo.vol_msf); 553 cd->disksize = size * (MCDBLK/DEV_BSIZE); 554 return 0; 555 } 556 return -1; 557} 558 --- 26 unchanged lines hidden (view full) --- 585{ 586 int i; 587 588 for (i = 0; i < count; i++) { 589 if (!(inb(port+MCD_FLAGS) & MCD_ST_BUSY)) { 590 return 1; 591 } 592 } |
568#ifdef MCD_TO_WARNING_ON | |
569 printf("mcd%d: timeout %s\n", unit, whine); | 593 printf("mcd%d: timeout %s\n", unit, whine); |
570#endif | |
571 return 0; 572} 573 574/* check to see if a Mitsumi CD-ROM is attached to the ISA bus */ 575 576int 577mcd_probe(struct isa_device *dev) 578{ --- 14 unchanged lines hidden (view full) --- 593 594 /* send a reset */ 595 outb(port+MCD_FLAGS, M_RESET); 596 597 /* 598 * delay awhile by getting any pending garbage (old data) and 599 * throwing it away. 600 */ | 594 return 0; 595} 596 597/* check to see if a Mitsumi CD-ROM is attached to the ISA bus */ 598 599int 600mcd_probe(struct isa_device *dev) 601{ --- 14 unchanged lines hidden (view full) --- 616 617 /* send a reset */ 618 outb(port+MCD_FLAGS, M_RESET); 619 620 /* 621 * delay awhile by getting any pending garbage (old data) and 622 * throwing it away. 623 */ |
601 for (i = 1000000; i != 0; i--) { | 624 for (i = 1000000; i != 0; i--) |
602 inb(port+MCD_FLAGS); | 625 inb(port+MCD_FLAGS); |
603 } | |
604 605 /* Get status */ 606 outb(port+MCD_DATA, MCD_CMDGETSTAT); | 626 627 /* Get status */ 628 outb(port+MCD_DATA, MCD_CMDGETSTAT); |
607 if (!twiddle_thumbs(port, unit, 1000000, "getting status")) { | 629 if (!twiddle_thumbs(port, unit, 1000000, "getting status")) |
608 return 0; /* Timeout */ | 630 return 0; /* Timeout */ |
609 } | |
610 status = inb(port+MCD_DATA); 611 if (status != MCDCDABSENT && status != MCDCDPRESENT && 612 status != MCDSOPEN && status != MCDSCLOSED) 613 return 0; /* Not actually a Mitsumi drive here */ 614 /* Get version information */ 615 outb(port+MCD_DATA, MCD_CMDCONTINFO); 616 for (j = 0; j < 3; j++) { | 631 status = inb(port+MCD_DATA); 632 if (status != MCDCDABSENT && status != MCDCDPRESENT && 633 status != MCDSOPEN && status != MCDSCLOSED) 634 return 0; /* Not actually a Mitsumi drive here */ 635 /* Get version information */ 636 outb(port+MCD_DATA, MCD_CMDCONTINFO); 637 for (j = 0; j < 3; j++) { |
617 if (!twiddle_thumbs(port, unit, 3000, "getting version info")) { | 638 if (!twiddle_thumbs(port, unit, 3000, "getting version info")) |
618 return 0; | 639 return 0; |
619 } | |
620 stbytes[j] = (inb(port+MCD_DATA) & 0xFF); 621 } 622 printf("mcd%d: version information is %x %c %x\n", unit, 623 stbytes[0], stbytes[1], stbytes[2]); 624 if (stbytes[1] >= 4) { 625 outb(port+MCD_CTRL, M_PICKLE); | 640 stbytes[j] = (inb(port+MCD_DATA) & 0xFF); 641 } 642 printf("mcd%d: version information is %x %c %x\n", unit, 643 stbytes[0], stbytes[1], stbytes[2]); 644 if (stbytes[1] >= 4) { 645 outb(port+MCD_CTRL, M_PICKLE); |
646 mcd_data[unit].flags |= MCDNEWMODEL; |
|
626 printf("mcd%d: Adjusted for newer drive model\n", unit); 627 } 628 return 4; 629} 630 631 632static int 633mcd_waitrdy(int port,int dly) 634{ 635 int i; 636 637 /* wait until xfer port senses data ready */ | 647 printf("mcd%d: Adjusted for newer drive model\n", unit); 648 } 649 return 4; 650} 651 652 653static int 654mcd_waitrdy(int port,int dly) 655{ 656 int i; 657 658 /* wait until xfer port senses data ready */ |
638 for (i=0; i<dly; i++) { 639 if ((inb(port+mcd_xfer) & MCD_ST_BUSY)==0) { 640 DELAY(10); | 659 for (i=0; i<dly; i+=MIN_DELAY) { 660 if ((inb(port+mcd_xfer) & MCD_ST_BUSY)==0) |
641 return 0; | 661 return 0; |
642 } 643 DELAY(1); | 662 DELAY(MIN_DELAY); |
644 } 645 return -1; 646} 647 648static int 649mcd_getreply(int unit,int dly) 650{ 651 int i; 652 struct mcd_data *cd = mcd_data + unit; 653 int port = cd->iobase; 654 655 /* wait data to become ready */ 656 if (mcd_waitrdy(port,dly)<0) { | 663 } 664 return -1; 665} 666 667static int 668mcd_getreply(int unit,int dly) 669{ 670 int i; 671 struct mcd_data *cd = mcd_data + unit; 672 int port = cd->iobase; 673 674 /* wait data to become ready */ 675 if (mcd_waitrdy(port,dly)<0) { |
657#ifdef MCD_TO_WARNING_ON | |
658 printf("mcd%d: timeout getreply\n",unit); | 676 printf("mcd%d: timeout getreply\n",unit); |
659#endif | |
660 return -1; 661 } 662 663 /* get the data */ 664 return inb(port+mcd_status) & 0xFF; 665} 666 667static int --- 6 unchanged lines hidden (view full) --- 674 /* get the status */ 675 if (sflg) 676 outb(port+mcd_command, MCD_CMDGETSTAT); 677 i = mcd_getreply(unit,DELAY_GETREPLY); 678 if (i<0) return -1; 679 680 cd->status = i; 681 | 677 return -1; 678 } 679 680 /* get the data */ 681 return inb(port+mcd_status) & 0xFF; 682} 683 684static int --- 6 unchanged lines hidden (view full) --- 691 /* get the status */ 692 if (sflg) 693 outb(port+mcd_command, MCD_CMDGETSTAT); 694 i = mcd_getreply(unit,DELAY_GETREPLY); 695 if (i<0) return -1; 696 697 cd->status = i; 698 |
682 mcd_setflags(unit,cd); | 699 if (mcd_setflags(unit,cd) < 0) 700 return -2; |
683 return cd->status; 684} 685 | 701 return cd->status; 702} 703 |
686static void | 704static int |
687mcd_setflags(int unit, struct mcd_data *cd) 688{ 689 /* check flags */ | 705mcd_setflags(int unit, struct mcd_data *cd) 706{ 707 /* check flags */ |
690 if (cd->status & (MCDDSKCHNG|MCDDOOROPEN)) { 691 MCD_TRACE("getstat: sensed DSKCHNG or DOOROPEN\n",0,0,0,0); 692 cd->flags &= ~MCDVALID; | 708 if ( (cd->status & (MCDDSKCHNG|MCDDOOROPEN)) 709 || !(cd->status & MCDDSKIN)) { 710 MCD_TRACE("setflags: sensed DSKCHNG or DOOROPEN or !DSKIN\n",0,0,0,0); 711 mcd_soft_reset(unit); 712 return -1; |
693 } 694 | 713 } 714 |
695#ifndef MCDMINI | |
696 if (cd->status & MCDAUDIOBSY) 697 cd->audio_status = CD_AS_PLAY_IN_PROGRESS; 698 else if (cd->audio_status == CD_AS_PLAY_IN_PROGRESS) 699 cd->audio_status = CD_AS_PLAY_COMPLETED; | 715 if (cd->status & MCDAUDIOBSY) 716 cd->audio_status = CD_AS_PLAY_IN_PROGRESS; 717 else if (cd->audio_status == CD_AS_PLAY_IN_PROGRESS) 718 cd->audio_status = CD_AS_PLAY_COMPLETED; |
700#endif | 719 return 0; |
701} 702 703static int 704mcd_get(int unit, char *buf, int nmax) 705{ 706 int port = mcd_data[unit].iobase; 707 int i,k; 708 709 for (i=0; i<nmax; i++) { 710 /* wait for data */ 711 if ((k = mcd_getreply(unit,DELAY_GETREPLY)) < 0) { | 720} 721 722static int 723mcd_get(int unit, char *buf, int nmax) 724{ 725 int port = mcd_data[unit].iobase; 726 int i,k; 727 728 for (i=0; i<nmax; i++) { 729 /* wait for data */ 730 if ((k = mcd_getreply(unit,DELAY_GETREPLY)) < 0) { |
712#ifdef MCD_TO_WARNING_ON | |
713 printf("mcd%d: timeout mcd_get\n",unit); | 731 printf("mcd%d: timeout mcd_get\n",unit); |
714#endif | |
715 return -1; 716 } 717 buf[i] = k; 718 } 719 return i; 720} 721 722static int 723mcd_send(int unit, int cmd,int nretrys) 724{ | 732 return -1; 733 } 734 buf[i] = k; 735 } 736 return i; 737} 738 739static int 740mcd_send(int unit, int cmd,int nretrys) 741{ |
725 int i,k; | 742 int i,k=0; |
726 int port = mcd_data[unit].iobase; 727 | 743 int port = mcd_data[unit].iobase; 744 |
728/*MCD_TRACE("mcd_send: command = 0x%x\n",cmd,0,0,0);*/ | 745/*MCD_TRACE("mcd_send: command = 0x%02x\n",cmd,0,0,0);*/ |
729 for (i=0; i<nretrys; i++) { 730 outb(port+mcd_command, cmd); | 746 for (i=0; i<nretrys; i++) { 747 outb(port+mcd_command, cmd); |
731 if ((k=mcd_getstat(unit,0)) != -1) { | 748 if ((k=mcd_getstat(unit,0)) != -1) |
732 break; | 749 break; |
733 } | |
734 } | 750 } |
751 if (k == -2) { 752 printf("mcd%d: media changed\n",unit); 753 return -1; 754 } |
|
735 if (i == nretrys) { 736 printf("mcd%d: mcd_send retry cnt exceeded\n",unit); 737 return -1; 738 } | 755 if (i == nretrys) { 756 printf("mcd%d: mcd_send retry cnt exceeded\n",unit); 757 return -1; 758 } |
739/*MCD_TRACE("mcd_send: status = 0x%x\n",k,0,0,0);*/ | 759/*MCD_TRACE("mcd_send: done\n",0,0,0,0);*/ |
740 return 0; 741} 742 743static int 744bcd2bin(bcd_t b) 745{ 746 return (b >> 4) * 10 + (b & 15); 747} --- 23 unchanged lines hidden (view full) --- 771} 772 773static int 774mcd_volinfo(int unit) 775{ 776 struct mcd_data *cd = mcd_data + unit; 777 int i; 778 | 760 return 0; 761} 762 763static int 764bcd2bin(bcd_t b) 765{ 766 return (b >> 4) * 10 + (b & 15); 767} --- 23 unchanged lines hidden (view full) --- 791} 792 793static int 794mcd_volinfo(int unit) 795{ 796 struct mcd_data *cd = mcd_data + unit; 797 int i; 798 |
779/*MCD_TRACE("mcd_volinfo: enter\n",0,0,0,0);*/ 780 781 /* Get the status, in case the disc has been changed */ 782 if (mcd_getstat(unit, 1) < 0) return EIO; 783 | |
784 /* Just return if we already have it */ 785 if (cd->flags & MCDVOLINFO) return 0; 786 | 799 /* Just return if we already have it */ 800 if (cd->flags & MCDVOLINFO) return 0; 801 |
802/*MCD_TRACE("mcd_volinfo: enter\n",0,0,0,0);*/ 803 |
|
787 /* send volume info command */ 788 if (mcd_send(unit,MCD_CMDGETVOLINFO,MCD_RETRYS) < 0) | 804 /* send volume info command */ 805 if (mcd_send(unit,MCD_CMDGETVOLINFO,MCD_RETRYS) < 0) |
789 return -1; | 806 return EIO; |
790 791 /* get data */ 792 if (mcd_get(unit,(char*) &cd->volinfo,sizeof(struct mcd_volinfo)) < 0) { 793 printf("mcd%d: mcd_volinfo: error read data\n",unit); | 807 808 /* get data */ 809 if (mcd_get(unit,(char*) &cd->volinfo,sizeof(struct mcd_volinfo)) < 0) { 810 printf("mcd%d: mcd_volinfo: error read data\n",unit); |
794 return -1; | 811 return EIO; |
795 } 796 797 if (cd->volinfo.trk_low != 0 || cd->volinfo.trk_high != 0) { 798 cd->flags |= MCDVOLINFO; /* volinfo is OK */ 799 return 0; 800 } 801 | 812 } 813 814 if (cd->volinfo.trk_low != 0 || cd->volinfo.trk_high != 0) { 815 cd->flags |= MCDVOLINFO; /* volinfo is OK */ 816 return 0; 817 } 818 |
802 return -1; | 819 return EINVAL; |
803} 804 805void 806mcdintr(unit) 807 int unit; 808{ | 820} 821 822void 823mcdintr(unit) 824 int unit; 825{ |
809 int port = mcd_data[unit].iobase; 810 u_int i; 811 812 MCD_TRACE("stray interrupt xfer=0x%x\n",inb(port+mcd_xfer),0,0,0); 813 814 /* just read out status and ignore the rest */ 815 if ((inb(port+mcd_xfer)&0xFF) != 0xFF) { 816 i = inb(port+mcd_status); 817 } | 826 MCD_TRACE("stray interrupt\n",0,0,0,0); |
818} 819 820/* state machine to process read requests 821 * initialize with MCD_S_BEGIN: calculate sizes, and read status 822 * MCD_S_WAITSTAT: wait for status reply, set mode 823 * MCD_S_WAITMODE: waits for status reply from set mode, set read command 824 * MCD_S_WAITREAD: wait for read ready, read data 825 */ 826static struct mcd_mbx *mbxsave; 827 828static void 829mcd_doread(int state, struct mcd_mbx *mbxin) 830{ 831 struct mcd_mbx *mbx = (state!=MCD_S_BEGIN) ? mbxsave : mbxin; 832 int unit = mbx->unit; 833 int port = mbx->port; | 827} 828 829/* state machine to process read requests 830 * initialize with MCD_S_BEGIN: calculate sizes, and read status 831 * MCD_S_WAITSTAT: wait for status reply, set mode 832 * MCD_S_WAITMODE: waits for status reply from set mode, set read command 833 * MCD_S_WAITREAD: wait for read ready, read data 834 */ 835static struct mcd_mbx *mbxsave; 836 837static void 838mcd_doread(int state, struct mcd_mbx *mbxin) 839{ 840 struct mcd_mbx *mbx = (state!=MCD_S_BEGIN) ? mbxsave : mbxin; 841 int unit = mbx->unit; 842 int port = mbx->port; |
843 int com_port = mbx->port + mcd_command; 844 int data_port = mbx->port + mcd_rdata; |
|
834 struct buf *bp = mbx->bp; 835 struct mcd_data *cd = mcd_data + unit; 836 837 int rm,i,k; 838 struct mcd_read2 rbuf; 839 int blknum; 840 caddr_t addr; 841 842loop: 843 switch (state) { 844 case MCD_S_BEGIN: 845 mbx = mbxsave = mbxin; 846 847 case MCD_S_BEGIN1: 848 /* get status */ | 845 struct buf *bp = mbx->bp; 846 struct mcd_data *cd = mcd_data + unit; 847 848 int rm,i,k; 849 struct mcd_read2 rbuf; 850 int blknum; 851 caddr_t addr; 852 853loop: 854 switch (state) { 855 case MCD_S_BEGIN: 856 mbx = mbxsave = mbxin; 857 858 case MCD_S_BEGIN1: 859 /* get status */ |
849 outb(port+mcd_command, MCD_CMDGETSTAT); | 860 outb(com_port, MCD_CMDGETSTAT); |
850 mbx->count = RDELAY_WAITSTAT; 851 timeout((timeout_func_t)mcd_doread, 852 (caddr_t)MCD_S_WAITSTAT,hz/100); /* XXX */ 853 return; 854 case MCD_S_WAITSTAT: 855 untimeout((timeout_func_t)mcd_doread,(caddr_t)MCD_S_WAITSTAT); 856 if (mbx->count-- >= 0) { 857 if (inb(port+mcd_xfer) & MCD_ST_BUSY) { 858 timeout((timeout_func_t)mcd_doread, 859 (caddr_t)MCD_S_WAITSTAT,hz/100); /* XXX */ 860 return; 861 } | 861 mbx->count = RDELAY_WAITSTAT; 862 timeout((timeout_func_t)mcd_doread, 863 (caddr_t)MCD_S_WAITSTAT,hz/100); /* XXX */ 864 return; 865 case MCD_S_WAITSTAT: 866 untimeout((timeout_func_t)mcd_doread,(caddr_t)MCD_S_WAITSTAT); 867 if (mbx->count-- >= 0) { 868 if (inb(port+mcd_xfer) & MCD_ST_BUSY) { 869 timeout((timeout_func_t)mcd_doread, 870 (caddr_t)MCD_S_WAITSTAT,hz/100); /* XXX */ 871 return; 872 } |
862 mcd_setflags(unit,cd); | 873 cd->status = inb(port+mcd_status) & 0xFF; 874 if (mcd_setflags(unit,cd) < 0) 875 goto changed; |
863 MCD_TRACE("got WAITSTAT delay=%d\n", 864 RDELAY_WAITSTAT-mbx->count,0,0,0); 865 /* reject, if audio active */ 866 if (cd->status & MCDAUDIOBSY) { 867 printf("mcd%d: audio is active\n",unit); 868 goto readerr; 869 } 870 871 /* to check for raw/cooked mode */ 872 if (cd->flags & MCDREADRAW) { | 876 MCD_TRACE("got WAITSTAT delay=%d\n", 877 RDELAY_WAITSTAT-mbx->count,0,0,0); 878 /* reject, if audio active */ 879 if (cd->status & MCDAUDIOBSY) { 880 printf("mcd%d: audio is active\n",unit); 881 goto readerr; 882 } 883 884 /* to check for raw/cooked mode */ 885 if (cd->flags & MCDREADRAW) { |
873 rm = MCD_MD_RAW; | 886 rm = (cd->flags & MCDNEWMODEL) ? 887 MCD_MD_BIN_RAW : MCD_MD_RAW; |
874 mbx->sz = MCDRBLK; 875 } else { | 888 mbx->sz = MCDRBLK; 889 } else { |
876 rm = MCD_MD_COOKED; | 890 rm = (cd->flags & MCDNEWMODEL) ? 891 MCD_MD_BIN_COOKED : MCD_MD_COOKED; |
877 mbx->sz = cd->blksize; 878 } 879 | 892 mbx->sz = cd->blksize; 893 } 894 |
895 if (rm == cd->curr_mode) 896 goto modedone; 897 |
|
880 mbx->count = RDELAY_WAITMODE; | 898 mbx->count = RDELAY_WAITMODE; |
881 882 mcd_put(port+mcd_command, MCD_CMDSETMODE); 883 mcd_put(port+mcd_command, rm); | 899 900 cd->curr_mode = MCD_MD_UNKNOWN; 901 mbx->mode = rm; 902 mcd_put(com_port, MCD_CMDSETMODE); 903 mcd_put(com_port, rm); 904 |
884 timeout((timeout_func_t)mcd_doread, 885 (caddr_t)MCD_S_WAITMODE,hz/100); /* XXX */ 886 return; 887 } else { | 905 timeout((timeout_func_t)mcd_doread, 906 (caddr_t)MCD_S_WAITMODE,hz/100); /* XXX */ 907 return; 908 } else { |
888#ifdef MCD_TO_WARNING_ON | |
889 printf("mcd%d: timeout getstatus\n",unit); | 909 printf("mcd%d: timeout getstatus\n",unit); |
890#endif | |
891 goto readerr; 892 } 893 894 case MCD_S_WAITMODE: 895 untimeout((timeout_func_t)mcd_doread,(caddr_t)MCD_S_WAITMODE); 896 if (mbx->count-- < 0) { | 910 goto readerr; 911 } 912 913 case MCD_S_WAITMODE: 914 untimeout((timeout_func_t)mcd_doread,(caddr_t)MCD_S_WAITMODE); 915 if (mbx->count-- < 0) { |
897#ifdef MCD_TO_WARNING_ON | |
898 printf("mcd%d: timeout set mode\n",unit); | 916 printf("mcd%d: timeout set mode\n",unit); |
899#endif | |
900 goto readerr; 901 } 902 if (inb(port+mcd_xfer) & MCD_ST_BUSY) { 903 timeout((timeout_func_t)mcd_doread,(caddr_t)MCD_S_WAITMODE,hz/100); 904 return; 905 } | 917 goto readerr; 918 } 919 if (inb(port+mcd_xfer) & MCD_ST_BUSY) { 920 timeout((timeout_func_t)mcd_doread,(caddr_t)MCD_S_WAITMODE,hz/100); 921 return; 922 } |
906 mcd_setflags(unit,cd); | 923 cd->status = inb(port+mcd_status) & 0xFF; 924 if (mcd_setflags(unit,cd) < 0) 925 goto changed; 926 cd->curr_mode = mbx->mode; |
907 MCD_TRACE("got WAITMODE delay=%d\n", 908 RDELAY_WAITMODE-mbx->count,0,0,0); | 927 MCD_TRACE("got WAITMODE delay=%d\n", 928 RDELAY_WAITMODE-mbx->count,0,0,0); |
929modedone: |
|
909 /* for first block */ 910 mbx->nblk = (bp->b_bcount + (mbx->sz-1)) / mbx->sz; 911 mbx->skip = 0; 912 913nextblock: 914 blknum = (bp->b_blkno / (mbx->sz/DEV_BSIZE)) 915 + mbx->p_offset + mbx->skip/mbx->sz; 916 917 MCD_TRACE("mcd_doread: read blknum=%d for bp=0x%x\n", 918 blknum,bp,0,0); 919 920 /* build parameter block */ 921 hsg2msf(blknum,rbuf.start_msf); 922 923 /* send the read command */ | 930 /* for first block */ 931 mbx->nblk = (bp->b_bcount + (mbx->sz-1)) / mbx->sz; 932 mbx->skip = 0; 933 934nextblock: 935 blknum = (bp->b_blkno / (mbx->sz/DEV_BSIZE)) 936 + mbx->p_offset + mbx->skip/mbx->sz; 937 938 MCD_TRACE("mcd_doread: read blknum=%d for bp=0x%x\n", 939 blknum,bp,0,0); 940 941 /* build parameter block */ 942 hsg2msf(blknum,rbuf.start_msf); 943 944 /* send the read command */ |
924 mcd_put(port+mcd_command,MCD_CMDREAD2); 925 mcd_put(port+mcd_command,rbuf.start_msf[0]); 926 mcd_put(port+mcd_command,rbuf.start_msf[1]); 927 mcd_put(port+mcd_command,rbuf.start_msf[2]); 928 mcd_put(port+mcd_command,0); 929 mcd_put(port+mcd_command,0); 930 mcd_put(port+mcd_command,1); | 945 disable_intr(); 946 mcd_put(com_port,MCD_CMDREAD2); 947 mcd_put(com_port,rbuf.start_msf[0]); 948 mcd_put(com_port,rbuf.start_msf[1]); 949 mcd_put(com_port,rbuf.start_msf[2]); 950 mcd_put(com_port,0); 951 mcd_put(com_port,0); 952 mcd_put(com_port,1); 953 enable_intr(); 954 |
931 mbx->count = RDELAY_WAITREAD; 932 timeout((timeout_func_t)mcd_doread, 933 (caddr_t)MCD_S_WAITREAD,hz/100); /* XXX */ 934 return; 935 case MCD_S_WAITREAD: 936 untimeout((timeout_func_t)mcd_doread,(caddr_t)MCD_S_WAITREAD); 937 if (mbx->count-- > 0) { 938 k = inb(port+mcd_xfer); | 955 mbx->count = RDELAY_WAITREAD; 956 timeout((timeout_func_t)mcd_doread, 957 (caddr_t)MCD_S_WAITREAD,hz/100); /* XXX */ 958 return; 959 case MCD_S_WAITREAD: 960 untimeout((timeout_func_t)mcd_doread,(caddr_t)MCD_S_WAITREAD); 961 if (mbx->count-- > 0) { 962 k = inb(port+mcd_xfer); |
939 if ((k & 2)==0) { | 963 if (!(k & 2)) { /* XXX */ |
940 MCD_TRACE("got data delay=%d\n", 941 RDELAY_WAITREAD-mbx->count,0,0,0); 942 /* data is ready */ 943 addr = bp->b_un.b_addr + mbx->skip; | 964 MCD_TRACE("got data delay=%d\n", 965 RDELAY_WAITREAD-mbx->count,0,0,0); 966 /* data is ready */ 967 addr = bp->b_un.b_addr + mbx->skip; |
968 |
|
944 outb(port+mcd_ctl2,0x04); /* XXX */ 945 for (i=0; i<mbx->sz; i++) | 969 outb(port+mcd_ctl2,0x04); /* XXX */ 970 for (i=0; i<mbx->sz; i++) |
946 *addr++ = inb(port+mcd_rdata); | 971 *addr++ = inb(data_port); |
947 outb(port+mcd_ctl2,0x0c); /* XXX */ 948 | 972 outb(port+mcd_ctl2,0x0c); /* XXX */ 973 |
974 k = inb(port+mcd_xfer); 975 /* If we still have some junk, read it too */ 976 if (!(k & 2)) { 977 outb(port+mcd_ctl2,0x04); /* XXX */ 978 (void)inb(data_port); 979 (void)inb(data_port); 980 outb(port+mcd_ctl2,0x0c); /* XXX */ 981 } 982 |
|
949 if (--mbx->nblk > 0) { 950 mbx->skip += mbx->sz; 951 goto nextblock; 952 } 953 954 /* return buffer */ 955 bp->b_resid = 0; 956 biodone(bp); 957 | 983 if (--mbx->nblk > 0) { 984 mbx->skip += mbx->sz; 985 goto nextblock; 986 } 987 988 /* return buffer */ 989 bp->b_resid = 0; 990 biodone(bp); 991 |
958 cd->flags &= ~MCDMBXBSY; | 992 cd->flags &= ~(MCDMBXBSY|MCDREADRAW); |
959 mcd_start(mbx->unit); 960 return; 961 } | 993 mcd_start(mbx->unit); 994 return; 995 } |
962 if ((k & 4)==0) 963 mcd_getstat(unit,0); | 996 if (!(k & MCD_ST_BUSY)) { 997 cd->status = inb(port+mcd_status) & 0xFF; 998 if (mcd_setflags(unit,cd) < 0) 999 goto changed; 1000 } |
964 timeout((timeout_func_t)mcd_doread, 965 (caddr_t)MCD_S_WAITREAD,hz/100); /* XXX */ 966 return; 967 } else { | 1001 timeout((timeout_func_t)mcd_doread, 1002 (caddr_t)MCD_S_WAITREAD,hz/100); /* XXX */ 1003 return; 1004 } else { |
968#ifdef MCD_TO_WARNING_ON | |
969 printf("mcd%d: timeout read data\n",unit); | 1005 printf("mcd%d: timeout read data\n",unit); |
970#endif | |
971 goto readerr; 972 } 973 } 974 975readerr: 976 if (mbx->retry-- > 0) { | 1006 goto readerr; 1007 } 1008 } 1009 1010readerr: 1011 if (mbx->retry-- > 0) { |
977#ifdef MCD_TO_WARNING_ON | |
978 printf("mcd%d: retrying\n",unit); | 1012 printf("mcd%d: retrying\n",unit); |
979#endif | |
980 state = MCD_S_BEGIN1; 981 goto loop; 982 } | 1013 state = MCD_S_BEGIN1; 1014 goto loop; 1015 } |
983 | 1016harderr: |
984 /* invalidate the buffer */ 985 bp->b_flags |= B_ERROR; 986 bp->b_resid = bp->b_bcount; 987 biodone(bp); | 1017 /* invalidate the buffer */ 1018 bp->b_flags |= B_ERROR; 1019 bp->b_resid = bp->b_bcount; 1020 biodone(bp); |
1021 1022 cd->flags &= ~(MCDMBXBSY|MCDREADRAW); |
|
988 mcd_start(mbx->unit); 989 return; 990 | 1023 mcd_start(mbx->unit); 1024 return; 1025 |
1026changed: 1027 printf("mcd%d: media changed\n", unit); 1028 goto harderr; 1029 |
|
991#ifdef NOTDEF 992 printf("mcd%d: unit timeout, resetting\n",mbx->unit); 993 outb(mbx->port+mcd_reset,MCD_CMDRESET); 994 DELAY(300000); 995 (void)mcd_getstat(mbx->unit,1); 996 (void)mcd_getstat(mbx->unit,1); 997 /*cd->status &= ~MCDDSKCHNG; */ 998 cd->debug = 1; /* preventive set debug mode */ 999 1000#endif 1001 1002} 1003 | 1030#ifdef NOTDEF 1031 printf("mcd%d: unit timeout, resetting\n",mbx->unit); 1032 outb(mbx->port+mcd_reset,MCD_CMDRESET); 1033 DELAY(300000); 1034 (void)mcd_getstat(mbx->unit,1); 1035 (void)mcd_getstat(mbx->unit,1); 1036 /*cd->status &= ~MCDDSKCHNG; */ 1037 cd->debug = 1; /* preventive set debug mode */ 1038 1039#endif 1040 1041} 1042 |
1004#ifndef MCDMINI | |
1005static int | 1043static int |
1044mcd_eject(int unit) 1045{ 1046 struct mcd_data *cd = mcd_data + unit; 1047 int port = cd->iobase; 1048 1049 outb(port+mcd_command, MCD_CMDEJECTDISK); 1050 if (mcd_getstat(unit,0) == -1) return EIO; 1051 return 0; 1052} 1053 1054static int 1055mcd_hard_reset(int unit) 1056{ 1057 struct mcd_data *cd = mcd_data + unit; 1058 int port = cd->iobase; 1059 1060 outb(port+mcd_reset,MCD_CMDRESET); 1061 cd->curr_mode = MCD_MD_UNKNOWN; 1062 cd->audio_status = CD_AS_AUDIO_INVALID; 1063 return 0; 1064} 1065 1066static void 1067mcd_soft_reset(int unit) 1068{ 1069 struct mcd_data *cd = mcd_data + unit; 1070 int i; 1071 1072 cd->openflags = 0; 1073 cd->flags &= (MCDINIT|MCDPROBING|MCDNEWMODEL); 1074 cd->curr_mode = MCD_MD_UNKNOWN; 1075 for (i=0; i<MAXPARTITIONS; i++) cd->partflags[i] = 0; 1076 cd->audio_status = CD_AS_AUDIO_INVALID; 1077} 1078 1079static int |
|
1006mcd_setmode(int unit, int mode) 1007{ 1008 struct mcd_data *cd = mcd_data + unit; 1009 int port = cd->iobase; | 1080mcd_setmode(int unit, int mode) 1081{ 1082 struct mcd_data *cd = mcd_data + unit; 1083 int port = cd->iobase; |
1010 int retry; | 1084 int retry, st; |
1011 | 1085 |
1012#ifdef DEBUG 1013 printf("mcd%d: setting mode to %d\n", unit, mode); 1014#endif | 1086 if (cd->curr_mode == mode) 1087 return 0; 1088 if (cd->debug) 1089 printf("mcd%d: setting mode to %d\n", unit, mode); |
1015 for(retry=0; retry<MCD_RETRYS; retry++) 1016 { | 1090 for(retry=0; retry<MCD_RETRYS; retry++) 1091 { |
1092 cd->curr_mode = MCD_MD_UNKNOWN; |
|
1017 outb(port+mcd_command, MCD_CMDSETMODE); 1018 outb(port+mcd_command, mode); | 1093 outb(port+mcd_command, MCD_CMDSETMODE); 1094 outb(port+mcd_command, mode); |
1019 if (mcd_getstat(unit, 0) != -1) return 0; | 1095 if ((st = mcd_getstat(unit, 0)) >= 0) { 1096 cd->curr_mode = mode; 1097 return 0; 1098 } 1099 if (st == -2) { 1100 printf("mcd%d: media changed\n", unit); 1101 break; 1102 } |
1020 } 1021 1022 return -1; 1023} 1024 1025static int 1026mcd_toc_header(int unit, struct ioc_toc_header *th) 1027{ 1028 struct mcd_data *cd = mcd_data + unit; | 1103 } 1104 1105 return -1; 1106} 1107 1108static int 1109mcd_toc_header(int unit, struct ioc_toc_header *th) 1110{ 1111 struct mcd_data *cd = mcd_data + unit; |
1112 int r; |
|
1029 | 1113 |
1030 if (mcd_volinfo(unit) < 0) { 1031 return ENXIO; 1032 } | 1114 if ((r = mcd_volinfo(unit)) != 0) 1115 return r; |
1033 1034 th->len = msf2hsg(cd->volinfo.vol_msf); 1035 th->starting_track = bcd2bin(cd->volinfo.trk_low); 1036 th->ending_track = bcd2bin(cd->volinfo.trk_high); 1037 1038 return 0; 1039} 1040 1041static int 1042mcd_read_toc(int unit) 1043{ 1044 struct mcd_data *cd = mcd_data + unit; 1045 struct ioc_toc_header th; 1046 struct mcd_qchninfo q; 1047 int rc, trk, idx, retry; 1048 1049 /* Only read TOC if needed */ | 1116 1117 th->len = msf2hsg(cd->volinfo.vol_msf); 1118 th->starting_track = bcd2bin(cd->volinfo.trk_low); 1119 th->ending_track = bcd2bin(cd->volinfo.trk_high); 1120 1121 return 0; 1122} 1123 1124static int 1125mcd_read_toc(int unit) 1126{ 1127 struct mcd_data *cd = mcd_data + unit; 1128 struct ioc_toc_header th; 1129 struct mcd_qchninfo q; 1130 int rc, trk, idx, retry; 1131 1132 /* Only read TOC if needed */ |
1050 if (cd->flags & MCDTOC) { | 1133 if (cd->flags & MCDTOC) |
1051 return 0; | 1134 return 0; |
1052 } | |
1053 | 1135 |
1054#ifdef DEBUG 1055 printf("mcd%d: reading toc header\n", unit); 1056#endif 1057 if (mcd_toc_header(unit, &th) != 0) { 1058 return ENXIO; 1059 } | 1136 if (cd->debug) 1137 printf("mcd%d: reading toc header\n", unit); |
1060 | 1138 |
1061#ifdef DEBUG 1062 printf("mcd%d: stopping play\n", unit); 1063#endif 1064 if ((rc=mcd_stop(unit)) != 0) { | 1139 if ((rc = mcd_toc_header(unit, &th)) != 0) |
1065 return rc; | 1140 return rc; |
1066 } | |
1067 | 1141 |
1068 /* try setting the mode twice */ 1069 if (mcd_setmode(unit, MCD_MD_TOC) != 0) { | 1142 if (mcd_setmode(unit, MCD_MD_TOC) != 0) |
1070 return EIO; | 1143 return EIO; |
1071 } 1072 if (mcd_setmode(unit, MCD_MD_TOC) != 0) { 1073 return EIO; 1074 } | |
1075 | 1144 |
1076#ifdef DEBUG 1077 printf("mcd%d: get_toc reading qchannel info\n",unit); 1078#endif | 1145 if (cd->debug) 1146 printf("mcd%d: get_toc reading qchannel info\n",unit); 1147 |
1079 for(trk=th.starting_track; trk<=th.ending_track; trk++) 1080 cd->toc[trk].idx_no = 0; 1081 trk = th.ending_track - th.starting_track + 1; 1082 for(retry=0; retry<300 && trk>0; retry++) 1083 { 1084 if (mcd_getqchan(unit, &q) < 0) break; 1085 idx = bcd2bin(q.idx_no); | 1148 for(trk=th.starting_track; trk<=th.ending_track; trk++) 1149 cd->toc[trk].idx_no = 0; 1150 trk = th.ending_track - th.starting_track + 1; 1151 for(retry=0; retry<300 && trk>0; retry++) 1152 { 1153 if (mcd_getqchan(unit, &q) < 0) break; 1154 idx = bcd2bin(q.idx_no); |
1086 if (idx>0 && idx < MCD_MAXTOCS && q.trk_no==0) { | 1155 if (idx>=th.starting_track && idx<=th.ending_track && q.trk_no==0) { |
1087 if (cd->toc[idx].idx_no == 0) { 1088 cd->toc[idx] = q; 1089 trk--; 1090 } 1091 } 1092 } 1093 | 1156 if (cd->toc[idx].idx_no == 0) { 1157 cd->toc[idx] = q; 1158 trk--; 1159 } 1160 } 1161 } 1162 |
1094 if (mcd_setmode(unit, MCD_MD_COOKED) != 0) { | 1163 if (mcd_setmode(unit, MCD_MD_COOKED) != 0) |
1095 return EIO; | 1164 return EIO; |
1096 } | |
1097 | 1165 |
1098 if (trk != 0) { | 1166 if (trk != 0) |
1099 return ENXIO; | 1167 return ENXIO; |
1100 } | |
1101 1102 /* add a fake last+1 */ 1103 idx = th.ending_track + 1; 1104 cd->toc[idx].ctrl_adr = cd->toc[idx-1].ctrl_adr; 1105 cd->toc[idx].trk_no = 0; 1106 cd->toc[idx].idx_no = 0xAA; 1107 cd->toc[idx].hd_pos_msf[0] = cd->volinfo.vol_msf[0]; 1108 cd->toc[idx].hd_pos_msf[1] = cd->volinfo.vol_msf[1]; 1109 cd->toc[idx].hd_pos_msf[2] = cd->volinfo.vol_msf[2]; 1110 | 1168 1169 /* add a fake last+1 */ 1170 idx = th.ending_track + 1; 1171 cd->toc[idx].ctrl_adr = cd->toc[idx-1].ctrl_adr; 1172 cd->toc[idx].trk_no = 0; 1173 cd->toc[idx].idx_no = 0xAA; 1174 cd->toc[idx].hd_pos_msf[0] = cd->volinfo.vol_msf[0]; 1175 cd->toc[idx].hd_pos_msf[1] = cd->volinfo.vol_msf[1]; 1176 cd->toc[idx].hd_pos_msf[2] = cd->volinfo.vol_msf[2]; 1177 |
1178 if (cd->debug) 1179 { int i; 1180 for (i = th.starting_track; i <= idx; i++) 1181 printf("mcd%d: trk %d idx %d pos %d %d %d\n", 1182 unit, i, 1183 cd->toc[i].idx_no, 1184 bcd2bin(cd->toc[i].hd_pos_msf[0]), 1185 bcd2bin(cd->toc[i].hd_pos_msf[1]), 1186 bcd2bin(cd->toc[i].hd_pos_msf[2])); 1187 } 1188 |
|
1111 cd->flags |= MCDTOC; 1112 1113 return 0; 1114} 1115 1116static int | 1189 cd->flags |= MCDTOC; 1190 1191 return 0; 1192} 1193 1194static int |
1117mcd_toc_entry(int unit, struct ioc_read_toc_entry *te) | 1195mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te) |
1118{ 1119 struct mcd_data *cd = mcd_data + unit; | 1196{ 1197 struct mcd_data *cd = mcd_data + unit; |
1120 struct ret_toc { 1121 struct ioc_toc_header th; 1122 struct cd_toc_entry rt; 1123 } ret_toc; | 1198 struct cd_toc_entry entries[MCD_MAXTOCS]; |
1124 struct ioc_toc_header th; | 1199 struct ioc_toc_header th; |
1125 int rc, i; | 1200 int rc, i, len = te->data_len; |
1126 1127 /* Make sure we have a valid toc */ | 1201 1202 /* Make sure we have a valid toc */ |
1128 if ((rc=mcd_read_toc(unit)) != 0) { | 1203 if ((rc=mcd_read_toc(unit)) != 0) |
1129 return rc; | 1204 return rc; |
1130 } | |
1131 1132 /* find the toc to copy*/ 1133 i = te->starting_track; | 1205 1206 /* find the toc to copy*/ 1207 i = te->starting_track; |
1134 if (i == MCD_LASTPLUS1) { | 1208 if (i == MCD_LASTPLUS1) |
1135 i = bcd2bin(cd->volinfo.trk_high) + 1; | 1209 i = bcd2bin(cd->volinfo.trk_high) + 1; |
1136 } | |
1137 1138 /* verify starting track */ 1139 if (i < bcd2bin(cd->volinfo.trk_low) || 1140 i > bcd2bin(cd->volinfo.trk_high)+1) { 1141 return EINVAL; 1142 } 1143 1144 /* do we have room */ | 1210 1211 /* verify starting track */ 1212 if (i < bcd2bin(cd->volinfo.trk_low) || 1213 i > bcd2bin(cd->volinfo.trk_high)+1) { 1214 return EINVAL; 1215 } 1216 1217 /* do we have room */ |
1145 if (te->data_len < sizeof(struct ioc_toc_header) + 1146 sizeof(struct cd_toc_entry)) { | 1218 if ( len > sizeof(entries) 1219 || len < sizeof(struct cd_toc_entry) 1220 || (len % sizeof(struct cd_toc_entry)) != 0 1221 ) |
1147 return EINVAL; | 1222 return EINVAL; |
1148 } | |
1149 1150 /* Copy the toc header */ | 1223 1224 /* Copy the toc header */ |
1151 if (mcd_toc_header(unit, &th) < 0) { 1152 return EIO; 1153 } 1154 ret_toc.th = th; | 1225 if ((rc = mcd_toc_header(unit, &th)) != 0) 1226 return rc; |
1155 | 1227 |
1156 /* copy the toc data */ 1157 ret_toc.rt.control = cd->toc[i].ctrl_adr; 1158 ret_toc.rt.addr_type = te->address_format; 1159 ret_toc.rt.track = i; 1160 if (te->address_format == CD_MSF_FORMAT) { 1161 ret_toc.rt.addr.addr[1] = cd->toc[i].hd_pos_msf[0]; 1162 ret_toc.rt.addr.addr[2] = cd->toc[i].hd_pos_msf[1]; 1163 ret_toc.rt.addr.addr[3] = cd->toc[i].hd_pos_msf[2]; | 1228 do { 1229 /* copy the toc data */ 1230 entries[i-1].control = cd->toc[i].ctrl_adr; 1231 entries[i-1].addr_type = te->address_format; 1232 entries[i-1].track = i; 1233 if (te->address_format == CD_MSF_FORMAT) { 1234 entries[i-1].addr.msf.unused = 0; 1235 entries[i-1].addr.msf.minute = bcd2bin(cd->toc[i].hd_pos_msf[0]); 1236 entries[i-1].addr.msf.second = bcd2bin(cd->toc[i].hd_pos_msf[1]); 1237 entries[i-1].addr.msf.frame = bcd2bin(cd->toc[i].hd_pos_msf[2]); 1238 } 1239 len -= sizeof(struct cd_toc_entry); 1240 i++; |
1164 } | 1241 } |
1242 while (len > 0 && i <= th.ending_track + 2); |
|
1165 1166 /* copy the data back */ | 1243 1244 /* copy the data back */ |
1167 copyout(&ret_toc, te->data, sizeof(struct cd_toc_entry) 1168 + sizeof(struct ioc_toc_header)); | 1245 if (copyout(entries, te->data, (i - 1) * sizeof(struct cd_toc_entry)) != 0) 1246 return EFAULT; |
1169 1170 return 0; 1171} 1172 1173static int 1174mcd_stop(int unit) 1175{ 1176 struct mcd_data *cd = mcd_data + unit; 1177 | 1247 1248 return 0; 1249} 1250 1251static int 1252mcd_stop(int unit) 1253{ 1254 struct mcd_data *cd = mcd_data + unit; 1255 |
1178 if (mcd_send(unit, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0) { | 1256 if (mcd_send(unit, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0) |
1179 return ENXIO; | 1257 return ENXIO; |
1180 } | |
1181 cd->audio_status = CD_AS_PLAY_COMPLETED; 1182 return 0; 1183} 1184 1185static int 1186mcd_getqchan(int unit, struct mcd_qchninfo *q) 1187{ 1188 struct mcd_data *cd = mcd_data + unit; 1189 | 1258 cd->audio_status = CD_AS_PLAY_COMPLETED; 1259 return 0; 1260} 1261 1262static int 1263mcd_getqchan(int unit, struct mcd_qchninfo *q) 1264{ 1265 struct mcd_data *cd = mcd_data + unit; 1266 |
1190 if (mcd_send(unit, MCD_CMDGETQCHN, MCD_RETRYS) < 0) { | 1267 if (mcd_send(unit, MCD_CMDGETQCHN, MCD_RETRYS) < 0) |
1191 return -1; | 1268 return -1; |
1192 } 1193 if (mcd_get(unit, (char *) q, sizeof(struct mcd_qchninfo)) < 0) { | 1269 if (mcd_get(unit, (char *) q, sizeof(struct mcd_qchninfo)) < 0) |
1194 return -1; | 1270 return -1; |
1195 } 1196#ifdef DEBUG | |
1197 if (cd->debug) { | 1271 if (cd->debug) { |
1198 printf("mcd%d: qchannel ctl=%d, t=%d, i=%d, ttm=%d:%d.%d dtm=%d:%d.%d\n", | 1272 printf("mcd%d: qchannel ctl=%d trk=%d ind=%d pos=%d:%d.%d\n", |
1199 unit, | 1273 unit, |
1200 q->ctrl_adr, q->trk_no, q->idx_no, 1201 q->trk_size_msf[0], q->trk_size_msf[1], q->trk_size_msf[2], 1202 q->trk_size_msf[0], q->trk_size_msf[1], q->trk_size_msf[2]); | 1274 q->ctrl_adr, bcd2bin(q->trk_no), bcd2bin(q->idx_no), 1275 bcd2bin(q->hd_pos_msf[0]), bcd2bin(q->hd_pos_msf[1]), 1276 bcd2bin(q->hd_pos_msf[2])); |
1203 } | 1277 } |
1204#endif | |
1205 return 0; 1206} 1207 1208static int 1209mcd_subchan(int unit, struct ioc_read_subchannel *sc) 1210{ 1211 struct mcd_data *cd = mcd_data + unit; 1212 struct mcd_qchninfo q; 1213 struct cd_sub_channel_info data; 1214 | 1278 return 0; 1279} 1280 1281static int 1282mcd_subchan(int unit, struct ioc_read_subchannel *sc) 1283{ 1284 struct mcd_data *cd = mcd_data + unit; 1285 struct mcd_qchninfo q; 1286 struct cd_sub_channel_info data; 1287 |
1215#ifdef DEBUG 1216 printf("mcd%d: subchan af=%d, df=%d\n", unit, 1217 sc->address_format, 1218 sc->data_format); 1219#endif 1220 if (sc->address_format != CD_MSF_FORMAT) { | 1288 if (cd->debug) 1289 printf("mcd%d: subchan af=%d, df=%d\n", unit, 1290 sc->address_format, 1291 sc->data_format); 1292 1293 if (sc->address_format != CD_MSF_FORMAT) 1294 return EINVAL; 1295 1296 if (sc->data_format != CD_CURRENT_POSITION) 1297 return EINVAL; 1298 1299 if (mcd_setmode(unit, MCD_MD_COOKED) != 0) |
1221 return EIO; | 1300 return EIO; |
1222 } 1223 if (sc->data_format != CD_CURRENT_POSITION) { | 1301 1302 if (mcd_getqchan(unit, &q) < 0) |
1224 return EIO; | 1303 return EIO; |
1225 } 1226 if (mcd_getqchan(unit, &q) < 0) { 1227 return EIO; 1228 } | |
1229 1230 data.header.audio_status = cd->audio_status; 1231 data.what.position.data_format = CD_MSF_FORMAT; 1232 data.what.position.track_number = bcd2bin(q.trk_no); 1233 | 1304 1305 data.header.audio_status = cd->audio_status; 1306 data.what.position.data_format = CD_MSF_FORMAT; 1307 data.what.position.track_number = bcd2bin(q.trk_no); 1308 |
1234 if (copyout(&data, sc->data, sizeof(struct cd_sub_channel_info))!=0) { | 1309 if (copyout(&data, sc->data, sizeof(struct cd_sub_channel_info))!=0) |
1235 return EFAULT; | 1310 return EFAULT; |
1236 } | |
1237 return 0; 1238} 1239 1240static int | 1311 return 0; 1312} 1313 1314static int |
1315mcd_playmsf(int unit, struct ioc_play_msf *pt) 1316{ 1317 struct mcd_read2 pb; 1318 1319 if (mcd_setmode(unit, MCD_MD_COOKED) != 0) 1320 return EIO; 1321 1322 pb.start_msf[0] = bin2bcd(pt->start_m); 1323 pb.start_msf[1] = bin2bcd(pt->start_s); 1324 pb.start_msf[2] = bin2bcd(pt->start_f); 1325 pb.end_msf[0] = bin2bcd(pt->end_m); 1326 pb.end_msf[1] = bin2bcd(pt->end_s); 1327 pb.end_msf[2] = bin2bcd(pt->end_f); 1328 1329 return mcd_play(unit, &pb); 1330} 1331 1332static int |
|
1241mcd_playtracks(int unit, struct ioc_play_track *pt) 1242{ 1243 struct mcd_data *cd = mcd_data + unit; 1244 struct mcd_read2 pb; 1245 int a = pt->start_track; 1246 int z = pt->end_track; 1247 int rc; 1248 | 1333mcd_playtracks(int unit, struct ioc_play_track *pt) 1334{ 1335 struct mcd_data *cd = mcd_data + unit; 1336 struct mcd_read2 pb; 1337 int a = pt->start_track; 1338 int z = pt->end_track; 1339 int rc; 1340 |
1249 if ((rc = mcd_read_toc(unit)) != 0) { | 1341 if ((rc = mcd_read_toc(unit)) != 0) |
1250 return rc; | 1342 return rc; |
1251 } 1252#ifdef DEBUG 1253 printf("mcd%d: playtracks from %d:%d to %d:%d\n", unit, 1254 a, pt->start_index, z, pt->end_index); 1255#endif | |
1256 | 1343 |
1257 if (a < cd->volinfo.trk_low || a > cd->volinfo.trk_high || a > z || 1258 z < cd->volinfo.trk_low || z > cd->volinfo.trk_high) { | 1344 if (cd->debug) 1345 printf("mcd%d: playtracks from %d:%d to %d:%d\n", unit, 1346 a, pt->start_index, z, pt->end_index); 1347 1348 if ( a < bcd2bin(cd->volinfo.trk_low) 1349 || a > bcd2bin(cd->volinfo.trk_high) 1350 || a > z 1351 || z < bcd2bin(cd->volinfo.trk_low) 1352 || z > bcd2bin(cd->volinfo.trk_high)) |
1259 return EINVAL; | 1353 return EINVAL; |
1260 } | |
1261 1262 pb.start_msf[0] = cd->toc[a].hd_pos_msf[0]; 1263 pb.start_msf[1] = cd->toc[a].hd_pos_msf[1]; 1264 pb.start_msf[2] = cd->toc[a].hd_pos_msf[2]; 1265 pb.end_msf[0] = cd->toc[z+1].hd_pos_msf[0]; 1266 pb.end_msf[1] = cd->toc[z+1].hd_pos_msf[1]; 1267 pb.end_msf[2] = cd->toc[z+1].hd_pos_msf[2]; 1268 1269 return mcd_play(unit, &pb); 1270} 1271 1272static int 1273mcd_play(int unit, struct mcd_read2 *pb) 1274{ 1275 struct mcd_data *cd = mcd_data + unit; | 1354 1355 pb.start_msf[0] = cd->toc[a].hd_pos_msf[0]; 1356 pb.start_msf[1] = cd->toc[a].hd_pos_msf[1]; 1357 pb.start_msf[2] = cd->toc[a].hd_pos_msf[2]; 1358 pb.end_msf[0] = cd->toc[z+1].hd_pos_msf[0]; 1359 pb.end_msf[1] = cd->toc[z+1].hd_pos_msf[1]; 1360 pb.end_msf[2] = cd->toc[z+1].hd_pos_msf[2]; 1361 1362 return mcd_play(unit, &pb); 1363} 1364 1365static int 1366mcd_play(int unit, struct mcd_read2 *pb) 1367{ 1368 struct mcd_data *cd = mcd_data + unit; |
1276 int port = cd->iobase; 1277 int retry, st; | 1369 int com_port = cd->iobase + mcd_command; 1370 int retry, st = -1, status; |
1278 1279 cd->lastpb = *pb; 1280 for(retry=0; retry<MCD_RETRYS; retry++) { | 1371 1372 cd->lastpb = *pb; 1373 for(retry=0; retry<MCD_RETRYS; retry++) { |
1281 outb(port+mcd_command, MCD_CMDREAD2); 1282 outb(port+mcd_command, pb->start_msf[0]); 1283 outb(port+mcd_command, pb->start_msf[1]); 1284 outb(port+mcd_command, pb->start_msf[2]); 1285 outb(port+mcd_command, pb->end_msf[0]); 1286 outb(port+mcd_command, pb->end_msf[1]); 1287 outb(port+mcd_command, pb->end_msf[2]); 1288 if ((st=mcd_getstat(unit, 0)) != -1) { 1289 break; 1290 } 1291 } | |
1292 | 1374 |
1293#ifdef DEBUG 1294 if (cd->debug) { 1295 printf("mcd%d: mcd_play retry=%d, status=%d\n", unit, retry, st); | 1375 disable_intr(); 1376 outb(com_port, MCD_CMDREAD2); 1377 outb(com_port, pb->start_msf[0]); 1378 outb(com_port, pb->start_msf[1]); 1379 outb(com_port, pb->start_msf[2]); 1380 outb(com_port, pb->end_msf[0]); 1381 outb(com_port, pb->end_msf[1]); 1382 outb(com_port, pb->end_msf[2]); 1383 enable_intr(); 1384 1385 status=mcd_getstat(unit, 0); 1386 if (status == -1) 1387 continue; 1388 else if (status != -2) 1389 st = 0; 1390 break; |
1296 } | 1391 } |
1297#endif 1298 if (st == -1) { | 1392 1393 if (status == -2) { 1394 printf("mcd%d: media changed\n", unit); |
1299 return ENXIO; 1300 } | 1395 return ENXIO; 1396 } |
1397 if (cd->debug) 1398 printf("mcd%d: mcd_play retry=%d, status=0x%02x\n", unit, retry, status); 1399 if (st < 0) 1400 return ENXIO; |
|
1301 cd->audio_status = CD_AS_PLAY_IN_PROGRESS; 1302 return 0; 1303} 1304 1305static int 1306mcd_pause(int unit) 1307{ 1308 struct mcd_data *cd = mcd_data + unit; 1309 struct mcd_qchninfo q; 1310 int rc; 1311 1312 /* Verify current status */ 1313 if (cd->audio_status != CD_AS_PLAY_IN_PROGRESS) { | 1401 cd->audio_status = CD_AS_PLAY_IN_PROGRESS; 1402 return 0; 1403} 1404 1405static int 1406mcd_pause(int unit) 1407{ 1408 struct mcd_data *cd = mcd_data + unit; 1409 struct mcd_qchninfo q; 1410 int rc; 1411 1412 /* Verify current status */ 1413 if (cd->audio_status != CD_AS_PLAY_IN_PROGRESS) { |
1314#ifdef DEBUG 1315 printf("mcd%d: pause attempted when not playing\n", unit); 1316#endif | 1414 if (cd->debug) 1415 printf("mcd%d: pause attempted when not playing\n", unit); |
1317 return EINVAL; 1318 } 1319 1320 /* Get the current position */ | 1416 return EINVAL; 1417 } 1418 1419 /* Get the current position */ |
1321 if (mcd_getqchan(unit, &q) < 0) { | 1420 if (mcd_getqchan(unit, &q) < 0) |
1322 return EIO; | 1421 return EIO; |
1323 } | |
1324 1325 /* Copy it into lastpb */ 1326 cd->lastpb.start_msf[0] = q.hd_pos_msf[0]; 1327 cd->lastpb.start_msf[1] = q.hd_pos_msf[1]; 1328 cd->lastpb.start_msf[2] = q.hd_pos_msf[2]; 1329 1330 /* Stop playing */ | 1422 1423 /* Copy it into lastpb */ 1424 cd->lastpb.start_msf[0] = q.hd_pos_msf[0]; 1425 cd->lastpb.start_msf[1] = q.hd_pos_msf[1]; 1426 cd->lastpb.start_msf[2] = q.hd_pos_msf[2]; 1427 1428 /* Stop playing */ |
1331 if ((rc=mcd_stop(unit)) != 0) { | 1429 if ((rc=mcd_stop(unit)) != 0) |
1332 return rc; | 1430 return rc; |
1333 } | |
1334 1335 /* Set the proper status and exit */ 1336 cd->audio_status = CD_AS_PLAY_PAUSED; 1337 return 0; 1338} 1339 1340static int 1341mcd_resume(int unit) 1342{ 1343 struct mcd_data *cd = mcd_data + unit; 1344 | 1431 1432 /* Set the proper status and exit */ 1433 cd->audio_status = CD_AS_PLAY_PAUSED; 1434 return 0; 1435} 1436 1437static int 1438mcd_resume(int unit) 1439{ 1440 struct mcd_data *cd = mcd_data + unit; 1441 |
1345 if (cd->audio_status != CD_AS_PLAY_PAUSED) { | 1442 if (cd->audio_status != CD_AS_PLAY_PAUSED) |
1346 return EINVAL; | 1443 return EINVAL; |
1347 } | |
1348 return mcd_play(unit, &cd->lastpb); 1349} | 1444 return mcd_play(unit, &cd->lastpb); 1445} |
1350#endif /*!MCDMINI*/ 1351 | |
1352#endif /* NMCD > 0 */ | 1446#endif /* NMCD > 0 */ |