Deleted Added
full compact
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 */