File: | modules/mcd/../../dev/mcd/mcd.c |
Warning: | line 1363, column 9 Copies out a struct with untouched element(s): , |
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 | * Changes Copyright (C) 1994-1995 by Andrey A. Chernov, Moscow, Russia | |||
6 | * | |||
7 | * Rewrote probe routine to work on newer Mitsumi drives. | |||
8 | * Additional changes (C) 1994 by Jordan K. Hubbard | |||
9 | * | |||
10 | * All rights reserved. | |||
11 | * | |||
12 | * Redistribution and use in source and binary forms, with or without | |||
13 | * modification, are permitted provided that the following conditions | |||
14 | * are met: | |||
15 | * 1. Redistributions of source code must retain the above copyright | |||
16 | * notice, this list of conditions and the following disclaimer. | |||
17 | * 2. Redistributions in binary form must reproduce the above copyright | |||
18 | * notice, this list of conditions and the following disclaimer in the | |||
19 | * documentation and/or other materials provided with the distribution. | |||
20 | * 3. All advertising materials mentioning features or use of this software | |||
21 | * must display the following acknowledgement: | |||
22 | * This software was developed by Holger Veit and Brian Moore | |||
23 | * for use with "386BSD" and similar operating systems. | |||
24 | * "Similar operating systems" includes mainly non-profit oriented | |||
25 | * systems for research and education, including but not restricted to | |||
26 | * "NetBSD", "FreeBSD", "Mach" (by CMU). | |||
27 | * 4. Neither the name of the developer(s) nor the name "386BSD" | |||
28 | * may be used to endorse or promote products derived from this | |||
29 | * software without specific prior written permission. | |||
30 | * | |||
31 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER(S) ``AS IS'' AND ANY | |||
32 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
33 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
34 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER(S) BE | |||
35 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, | |||
36 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |||
37 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
38 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |||
39 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||
40 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||
41 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
42 | * | |||
43 | */ | |||
44 | ||||
45 | #include <sys/cdefs.h> | |||
46 | __FBSDID("$FreeBSD: releng/11.0/sys/dev/mcd/mcd.c 298646 2016-04-26 15:03:15Z pfg $")__asm__(".ident\t\"" "$FreeBSD: releng/11.0/sys/dev/mcd/mcd.c 298646 2016-04-26 15:03:15Z pfg $" "\""); | |||
47 | static const char __used__attribute__((__used__)) COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; | |||
48 | ||||
49 | #include <sys/param.h> | |||
50 | #include <sys/systm.h> | |||
51 | #include <sys/kernel.h> | |||
52 | #include <sys/conf.h> | |||
53 | #include <sys/fcntl.h> | |||
54 | #include <sys/bio.h> | |||
55 | #include <sys/cdio.h> | |||
56 | #include <sys/disk.h> | |||
57 | #include <sys/bus.h> | |||
58 | ||||
59 | #include <machine/bus.h> | |||
60 | #include <machine/resource.h> | |||
61 | #include <sys/rman.h> | |||
62 | ||||
63 | #include <isa/isavar.h> | |||
64 | ||||
65 | #include <dev/mcd/mcdreg.h> | |||
66 | #include <dev/mcd/mcdvar.h> | |||
67 | ||||
68 | #define MCD_TRACE(format, args...){ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf(format, args...); } } \ | |||
69 | { \ | |||
70 | if (sc->debug) { \ | |||
71 | device_printf(sc->dev, "status=0x%02x: ", \ | |||
72 | sc->data.status); \ | |||
73 | printf(format, ## args); \ | |||
74 | } \ | |||
75 | } | |||
76 | ||||
77 | #define RAW_PART2 2 | |||
78 | ||||
79 | /* flags */ | |||
80 | #define MCDVALID0x0001 0x0001 /* parameters loaded */ | |||
81 | #define MCDINIT0x0002 0x0002 /* device is init'd */ | |||
82 | #define MCDNEWMODEL0x0004 0x0004 /* device is new model */ | |||
83 | #define MCDLABEL0x0008 0x0008 /* label is read */ | |||
84 | #define MCDPROBING0x0010 0x0010 /* probing */ | |||
85 | #define MCDREADRAW0x0020 0x0020 /* read raw mode (2352 bytes) */ | |||
86 | #define MCDVOLINFO0x0040 0x0040 /* already read volinfo */ | |||
87 | #define MCDTOC0x0080 0x0080 /* already read toc */ | |||
88 | #define MCDMBXBSY0x0100 0x0100 /* local mbx is busy */ | |||
89 | ||||
90 | /* status */ | |||
91 | #define MCDAUDIOBSY0x02 MCD_ST_AUDIOBSY0x02 /* playing audio */ | |||
92 | #define MCDDSKCHNG0x20 MCD_ST_DSKCHNG0x20 /* sensed change of disk */ | |||
93 | #define MCDDSKIN0x40 MCD_ST_DSKIN0x40 /* sensed disk in drive */ | |||
94 | #define MCDDOOROPEN0x80 MCD_ST_DOOROPEN0x80 /* sensed door open */ | |||
95 | ||||
96 | /* These are apparently the different states a mitsumi can get up to */ | |||
97 | #define MCDCDABSENT0x0030 0x0030 | |||
98 | #define MCDCDPRESENT0x0020 0x0020 | |||
99 | #define MCDSCLOSED0x0080 0x0080 | |||
100 | #define MCDSOPEN0x00a0 0x00a0 | |||
101 | ||||
102 | #define MCD_MD_UNKNOWN(-1) (-1) | |||
103 | ||||
104 | #define MCD_TYPE_UNKNOWN0 0 | |||
105 | #define MCD_TYPE_LU002S1 1 | |||
106 | #define MCD_TYPE_LU005S2 2 | |||
107 | #define MCD_TYPE_LU006S3 3 | |||
108 | #define MCD_TYPE_FX0014 4 | |||
109 | #define MCD_TYPE_FX001D5 5 | |||
110 | ||||
111 | /* reader state machine */ | |||
112 | #define MCD_S_BEGIN0 0 | |||
113 | #define MCD_S_BEGIN11 1 | |||
114 | #define MCD_S_WAITSTAT2 2 | |||
115 | #define MCD_S_WAITMODE3 3 | |||
116 | #define MCD_S_WAITREAD4 4 | |||
117 | ||||
118 | /* prototypes */ | |||
119 | static void mcd_start(struct mcd_softc *); | |||
120 | #ifdef NOTYET | |||
121 | static void mcd_configure(struct mcd_softc *sc); | |||
122 | #endif | |||
123 | static int mcd_get(struct mcd_softc *, char *buf, int nmax); | |||
124 | static int mcd_setflags(struct mcd_softc *); | |||
125 | static int mcd_getstat(struct mcd_softc *,int sflg); | |||
126 | static int mcd_send(struct mcd_softc *, int cmd,int nretrys); | |||
127 | static void hsg2msf(int hsg, bcd_t *msf); | |||
128 | static int msf2hsg(bcd_t *msf, int relative); | |||
129 | static int mcd_volinfo(struct mcd_softc *); | |||
130 | static int mcd_waitrdy(struct mcd_softc *,int dly); | |||
131 | static void mcd_timeout(void *arg); | |||
132 | static void mcd_doread(struct mcd_softc *, int state, struct mcd_mbx *mbxin); | |||
133 | static void mcd_soft_reset(struct mcd_softc *); | |||
134 | static int mcd_hard_reset(struct mcd_softc *); | |||
135 | static int mcd_setmode(struct mcd_softc *, int mode); | |||
136 | static int mcd_getqchan(struct mcd_softc *, struct mcd_qchninfo *q); | |||
137 | static int mcd_subchan(struct mcd_softc *, struct ioc_read_subchannel *sc, | |||
138 | int nocopyout); | |||
139 | static int mcd_toc_header(struct mcd_softc *, struct ioc_toc_header *th); | |||
140 | static int mcd_read_toc(struct mcd_softc *); | |||
141 | static int mcd_toc_entrys(struct mcd_softc *, struct ioc_read_toc_entry *te); | |||
142 | #if 0 | |||
143 | static int mcd_toc_entry(struct mcd_softc *, struct ioc_read_toc_single_entry *te); | |||
144 | #endif | |||
145 | static int mcd_stop(struct mcd_softc *); | |||
146 | static int mcd_eject(struct mcd_softc *); | |||
147 | static int mcd_inject(struct mcd_softc *); | |||
148 | static int mcd_playtracks(struct mcd_softc *, struct ioc_play_track *pt); | |||
149 | static int mcd_play(struct mcd_softc *, struct mcd_read2 *pb); | |||
150 | static int mcd_playmsf(struct mcd_softc *, struct ioc_play_msf *pt); | |||
151 | static int mcd_playblocks(struct mcd_softc *, struct ioc_play_blocks *); | |||
152 | static int mcd_pause(struct mcd_softc *); | |||
153 | static int mcd_resume(struct mcd_softc *); | |||
154 | static int mcd_lock_door(struct mcd_softc *, int lock); | |||
155 | static int mcd_close_tray(struct mcd_softc *); | |||
156 | static int mcd_size(struct cdev *dev); | |||
157 | ||||
158 | static d_open_t mcdopen; | |||
159 | static d_close_t mcdclose; | |||
160 | static d_ioctl_t mcdioctl; | |||
161 | static d_strategy_t mcdstrategy; | |||
162 | ||||
163 | static struct cdevsw mcd_cdevsw = { | |||
164 | .d_version = D_VERSION0x17122009, | |||
165 | .d_open = mcdopen, | |||
166 | .d_close = mcdclose, | |||
167 | .d_read = physreadphysio, | |||
168 | .d_ioctl = mcdioctl, | |||
169 | .d_strategy = mcdstrategy, | |||
170 | .d_name = "mcd", | |||
171 | .d_flags = D_DISK0x0002, | |||
172 | }; | |||
173 | ||||
174 | #define MCD_RETRYS5 5 | |||
175 | #define MCD_RDRETRYS8 8 | |||
176 | ||||
177 | #define CLOSE_TRAY_SECS8 8 | |||
178 | #define DISK_SENSE_SECS3 3 | |||
179 | #define WAIT_FRAC4 4 | |||
180 | ||||
181 | /* several delays */ | |||
182 | #define RDELAY_WAITSTAT300 300 | |||
183 | #define RDELAY_WAITMODE300 300 | |||
184 | #define RDELAY_WAITREAD800 800 | |||
185 | ||||
186 | #define MIN_DELAY15 15 | |||
187 | #define DELAY_GETREPLY5000000 5000000 | |||
188 | ||||
189 | int | |||
190 | mcd_attach(struct mcd_softc *sc) | |||
191 | { | |||
192 | int unit; | |||
193 | ||||
194 | unit = device_get_unit(sc->dev); | |||
195 | ||||
196 | MCD_LOCK(sc)__mtx_lock_flags(&((((&sc->mtx))))->mtx_lock, ( (0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (196) ); | |||
197 | sc->data.flags |= MCDINIT0x0002; | |||
198 | mcd_soft_reset(sc); | |||
199 | bioq_init(&sc->data.head); | |||
200 | ||||
201 | #ifdef NOTYET | |||
202 | /* wire controller for interrupts and dma */ | |||
203 | mcd_configure(sc); | |||
204 | #endif | |||
205 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (205 )); | |||
206 | /* name filled in probe */ | |||
207 | sc->mcd_dev_t = make_dev(&mcd_cdevsw, 8 * unit, | |||
208 | UID_ROOT0, GID_OPERATOR5, 0640, "mcd%d", unit); | |||
209 | ||||
210 | sc->mcd_dev_t->si_drv1 = (void *)sc; | |||
211 | callout_init_mtx(&sc->timer, &sc->mtx, 0)_callout_init_lock((&sc->timer), ((&sc->mtx) != ((void *)0)) ? &(&sc->mtx)->lock_object : ((void *)0), (0)); | |||
212 | ||||
213 | return (0); | |||
214 | } | |||
215 | ||||
216 | static int | |||
217 | mcdopen(struct cdev *dev, int flags, int fmt, struct thread *td) | |||
218 | { | |||
219 | struct mcd_softc *sc; | |||
220 | int r,retry; | |||
221 | ||||
222 | sc = (struct mcd_softc *)dev->si_drv1; | |||
223 | ||||
224 | /* invalidated in the meantime? mark all open part's invalid */ | |||
225 | MCD_LOCK(sc)__mtx_lock_flags(&((((&sc->mtx))))->mtx_lock, ( (0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (225) ); | |||
226 | if (!(sc->data.flags & MCDVALID0x0001) && sc->data.openflags) { | |||
227 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (227 )); | |||
228 | return (ENXIO6); | |||
229 | } | |||
230 | ||||
231 | if (mcd_getstat(sc, 1) == -1) { | |||
232 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (232 )); | |||
233 | return (EIO5); | |||
234 | } | |||
235 | ||||
236 | if ( (sc->data.status & (MCDDSKCHNG0x20|MCDDOOROPEN0x80)) | |||
237 | || !(sc->data.status & MCDDSKIN0x40)) | |||
238 | for (retry = 0; retry < DISK_SENSE_SECS3 * WAIT_FRAC4; retry++) { | |||
239 | (void) mtx_sleep(sc, &sc->mtx, PSOCK | PCATCH,_sleep((sc), &(&sc->mtx)->lock_object, (((80) + 24) | 0x100), ("mcdsn1"), tick_sbt * (hz/4), 0, 0x0100) | |||
240 | "mcdsn1", hz/WAIT_FRAC)_sleep((sc), &(&sc->mtx)->lock_object, (((80) + 24) | 0x100), ("mcdsn1"), tick_sbt * (hz/4), 0, 0x0100); | |||
241 | if ((r = mcd_getstat(sc, 1)) == -1) { | |||
242 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (242 )); | |||
243 | return (EIO5); | |||
244 | } | |||
245 | if (r != -2) | |||
246 | break; | |||
247 | } | |||
248 | ||||
249 | if (sc->data.status & MCDDOOROPEN0x80) { | |||
250 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (250 )); | |||
251 | device_printf(sc->dev, "door is open\n"); | |||
252 | return (ENXIO6); | |||
253 | } | |||
254 | if (!(sc->data.status & MCDDSKIN0x40)) { | |||
255 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (255 )); | |||
256 | device_printf(sc->dev, "no CD inside\n"); | |||
257 | return (ENXIO6); | |||
258 | } | |||
259 | if (sc->data.status & MCDDSKCHNG0x20) { | |||
260 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (260 )); | |||
261 | device_printf(sc->dev, "CD not sensed\n"); | |||
262 | return (ENXIO6); | |||
263 | } | |||
264 | ||||
265 | if (mcd_size(dev) < 0) { | |||
266 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (266 )); | |||
267 | device_printf(sc->dev, "failed to get disk size\n"); | |||
268 | return (ENXIO6); | |||
269 | } | |||
270 | ||||
271 | sc->data.openflags = 1; | |||
272 | sc->data.partflags |= MCDREADRAW0x0020; | |||
273 | sc->data.flags |= MCDVALID0x0001; | |||
274 | ||||
275 | (void) mcd_lock_door(sc, MCD_LK_LOCK0x01); | |||
276 | if (!(sc->data.flags & MCDVALID0x0001)) { | |||
277 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (277 )); | |||
278 | return (ENXIO6); | |||
279 | } | |||
280 | ||||
281 | r = mcd_read_toc(sc); | |||
282 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (282 )); | |||
283 | return (r); | |||
284 | } | |||
285 | ||||
286 | static int | |||
287 | mcdclose(struct cdev *dev, int flags, int fmt, struct thread *td) | |||
288 | { | |||
289 | struct mcd_softc *sc; | |||
290 | ||||
291 | sc = (struct mcd_softc *)dev->si_drv1; | |||
292 | ||||
293 | MCD_LOCK(sc)__mtx_lock_flags(&((((&sc->mtx))))->mtx_lock, ( (0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (293) ); | |||
294 | KASSERT(sc->data.openflags, ("device not open"))do { } while (0); | |||
295 | ||||
296 | (void) mcd_lock_door(sc, MCD_LK_UNLOCK0x00); | |||
297 | sc->data.openflags = 0; | |||
298 | sc->data.partflags &= ~MCDREADRAW0x0020; | |||
299 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (299 )); | |||
300 | ||||
301 | return (0); | |||
302 | } | |||
303 | ||||
304 | static void | |||
305 | mcdstrategy(struct bio *bp) | |||
306 | { | |||
307 | struct mcd_softc *sc; | |||
308 | ||||
309 | sc = (struct mcd_softc *)bp->bio_dev->si_drv1; | |||
310 | ||||
311 | /* if device invalidated (e.g. media change, door open), error */ | |||
312 | MCD_LOCK(sc)__mtx_lock_flags(&((((&sc->mtx))))->mtx_lock, ( (0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (312) ); | |||
313 | if (!(sc->data.flags & MCDVALID0x0001)) { | |||
314 | device_printf(sc->dev, "media changed\n"); | |||
315 | bp->bio_error = EIO5; | |||
316 | goto bad; | |||
317 | } | |||
318 | ||||
319 | /* read only */ | |||
320 | if (!(bp->bio_cmd == BIO_READ0x01)) { | |||
321 | bp->bio_error = EROFS30; | |||
322 | goto bad; | |||
323 | } | |||
324 | ||||
325 | /* no data to read */ | |||
326 | if (bp->bio_bcount == 0) | |||
327 | goto done; | |||
328 | ||||
329 | if (!(sc->data.flags & MCDTOC0x0080)) { | |||
330 | bp->bio_error = EIO5; | |||
331 | goto bad; | |||
332 | } | |||
333 | ||||
334 | bp->bio_resid = 0; | |||
335 | ||||
336 | /* queue it */ | |||
337 | bioq_disksort(&sc->data.head, bp); | |||
338 | ||||
339 | /* now check whether we can perform processing */ | |||
340 | mcd_start(sc); | |||
341 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (341 )); | |||
342 | return; | |||
343 | ||||
344 | bad: | |||
345 | bp->bio_flags |= BIO_ERROR0x01; | |||
346 | done: | |||
347 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (347 )); | |||
348 | bp->bio_resid = bp->bio_bcount; | |||
349 | biodone(bp); | |||
350 | return; | |||
351 | } | |||
352 | ||||
353 | static void | |||
354 | mcd_start(struct mcd_softc *sc) | |||
355 | { | |||
356 | struct bio *bp; | |||
357 | ||||
358 | MCD_ASSERT_LOCKED(sc)(void)0; | |||
359 | if (sc->data.flags & MCDMBXBSY0x0100) { | |||
360 | return; | |||
361 | } | |||
362 | ||||
363 | bp = bioq_takefirst(&sc->data.head); | |||
364 | if (bp != 0) { | |||
365 | /* block found to process, dequeue */ | |||
366 | /*MCD_TRACE("mcd_start: found block bp=0x%x\n",bp,0,0,0);*/ | |||
367 | sc->data.flags |= MCDMBXBSY0x0100; | |||
368 | } else { | |||
369 | /* nothing to do */ | |||
370 | return; | |||
371 | } | |||
372 | ||||
373 | sc->data.mbx.retry = MCD_RETRYS5; | |||
374 | sc->data.mbx.bp = bp; | |||
375 | ||||
376 | mcd_doread(sc, MCD_S_BEGIN0,&(sc->data.mbx)); | |||
377 | return; | |||
378 | } | |||
379 | ||||
380 | static int | |||
381 | mcdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) | |||
382 | { | |||
383 | struct mcd_softc *sc; | |||
384 | int retry,r; | |||
385 | ||||
386 | sc = (struct mcd_softc *)dev->si_drv1; | |||
387 | ||||
388 | MCD_LOCK(sc)__mtx_lock_flags(&((((&sc->mtx))))->mtx_lock, ( (0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (388) ); | |||
389 | if (mcd_getstat(sc, 1) == -1) { /* detect disk change too */ | |||
| ||||
390 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (390 )); | |||
391 | return (EIO5); | |||
392 | } | |||
393 | MCD_TRACE("ioctl called 0x%lx\n", cmd){ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("ioctl called 0x%lx\n", cmd); } }; | |||
394 | ||||
395 | switch (cmd) { | |||
396 | case CDIOCSETPATCH((unsigned long) ((0x80000000) | (((sizeof(struct ioc_patch)) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((9)))): | |||
397 | case CDIOCGETVOL((unsigned long) ((0x40000000) | (((sizeof(struct ioc_vol)) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((10)))): | |||
398 | case CDIOCSETVOL((unsigned long) ((0x80000000) | (((sizeof(struct ioc_vol)) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((11)))): | |||
399 | case CDIOCSETMONO((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((12)))): | |||
400 | case CDIOCSETSTERIO((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((13)))): | |||
401 | case CDIOCSETMUTE((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((14)))): | |||
402 | case CDIOCSETLEFT((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((15)))): | |||
403 | case CDIOCSETRIGHT((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((16)))): | |||
404 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (404 )); | |||
405 | return (EINVAL22); | |||
406 | case CDIOCEJECT((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((24)))): | |||
407 | r = mcd_eject(sc); | |||
408 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (408 )); | |||
409 | return (r); | |||
410 | case CDIOCSETDEBUG((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((17)))): | |||
411 | sc->data.debug = 1; | |||
412 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (412 )); | |||
413 | return (0); | |||
414 | case CDIOCCLRDEBUG((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((18)))): | |||
415 | sc->data.debug = 0; | |||
416 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (416 )); | |||
417 | return (0); | |||
418 | case CDIOCRESET((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((21)))): | |||
419 | r = mcd_hard_reset(sc); | |||
420 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (420 )); | |||
421 | return (r); | |||
422 | case CDIOCALLOW((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((26)))): | |||
423 | r = mcd_lock_door(sc, MCD_LK_UNLOCK0x00); | |||
424 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (424 )); | |||
425 | return (r); | |||
426 | case CDIOCPREVENT((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((27)))): | |||
427 | r = mcd_lock_door(sc, MCD_LK_LOCK0x01); | |||
428 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (428 )); | |||
429 | return (r); | |||
430 | case CDIOCCLOSE((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((28)))): | |||
431 | r = mcd_inject(sc); | |||
432 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (432 )); | |||
433 | return (r); | |||
434 | } | |||
435 | ||||
436 | if (!(sc->data.flags & MCDVALID0x0001)) { | |||
437 | if ( (sc->data.status & (MCDDSKCHNG0x20|MCDDOOROPEN0x80)) | |||
438 | || !(sc->data.status & MCDDSKIN0x40)) | |||
439 | for (retry = 0; retry < DISK_SENSE_SECS3 * WAIT_FRAC4; retry++) { | |||
440 | (void) mtx_sleep(sc, &sc->mtx, PSOCK | PCATCH,_sleep((sc), &(&sc->mtx)->lock_object, (((80) + 24) | 0x100), ("mcdsn2"), tick_sbt * (hz/4), 0, 0x0100) | |||
441 | "mcdsn2", hz/WAIT_FRAC)_sleep((sc), &(&sc->mtx)->lock_object, (((80) + 24) | 0x100), ("mcdsn2"), tick_sbt * (hz/4), 0, 0x0100); | |||
442 | if ((r = mcd_getstat(sc, 1)) == -1) { | |||
443 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (443 )); | |||
444 | return (EIO5); | |||
445 | } | |||
446 | if (r != -2) | |||
447 | break; | |||
448 | } | |||
449 | if ( (sc->data.status & (MCDDOOROPEN0x80|MCDDSKCHNG0x20)) | |||
450 | || !(sc->data.status & MCDDSKIN0x40) | |||
451 | || mcd_size(dev) < 0 | |||
452 | ) { | |||
453 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (453 )); | |||
454 | return (ENXIO6); | |||
455 | } | |||
456 | sc->data.flags |= MCDVALID0x0001; | |||
457 | sc->data.partflags |= MCDREADRAW0x0020; | |||
458 | (void) mcd_lock_door(sc, MCD_LK_LOCK0x01); | |||
459 | if (!(sc->data.flags & MCDVALID0x0001)) { | |||
460 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (460 )); | |||
461 | return (ENXIO6); | |||
462 | } | |||
463 | } | |||
464 | ||||
465 | switch (cmd) { | |||
466 | case DIOCGMEDIASIZE((unsigned long) ((0x40000000) | (((sizeof(off_t)) & ((1 << 13) - 1)) << 16) | ((('d')) << 8) | ((129)))): | |||
467 | *(off_t *)addr = (off_t)sc->data.disksize * sc->data.blksize; | |||
468 | r = 0; | |||
469 | break; | |||
470 | case DIOCGSECTORSIZE((unsigned long) ((0x40000000) | (((sizeof(u_int)) & ((1 << 13) - 1)) << 16) | ((('d')) << 8) | ((128)))): | |||
471 | *(u_int *)addr = sc->data.blksize; | |||
472 | r = 0; | |||
473 | break; | |||
474 | case CDIOCPLAYTRACKS((unsigned long) ((0x80000000) | (((sizeof(struct ioc_play_track )) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((1)))): | |||
475 | r = mcd_playtracks(sc, (struct ioc_play_track *) addr); | |||
476 | break; | |||
477 | case CDIOCPLAYBLOCKS((unsigned long) ((0x80000000) | (((sizeof(struct ioc_play_blocks )) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((2)))): | |||
478 | r = mcd_playblocks(sc, (struct ioc_play_blocks *) addr); | |||
479 | break; | |||
480 | case CDIOCPLAYMSF((unsigned long) ((0x80000000) | (((sizeof(struct ioc_play_msf )) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((25)))): | |||
481 | r = mcd_playmsf(sc, (struct ioc_play_msf *) addr); | |||
482 | break; | |||
483 | case CDIOCREADSUBCHANNEL_SYSSPACE((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct ioc_read_subchannel)) & ((1 << 13) - 1)) << 16 ) | ((('c')) << 8) | ((31)))): | |||
484 | return mcd_subchan(sc, (struct ioc_read_subchannel *) addr, 1); | |||
485 | case CDIOCREADSUBCHANNEL((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct ioc_read_subchannel)) & ((1 << 13) - 1)) << 16 ) | ((('c')) << 8) | ((3)))): | |||
486 | return mcd_subchan(sc, (struct ioc_read_subchannel *) addr, 0); | |||
487 | case CDIOREADTOCHEADER((unsigned long) ((0x40000000) | (((sizeof(struct ioc_toc_header )) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((4)))): | |||
488 | r = mcd_toc_header(sc, (struct ioc_toc_header *) addr); | |||
489 | break; | |||
490 | case CDIOREADTOCENTRYS((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct ioc_read_toc_entry)) & ((1 << 13) - 1)) << 16 ) | ((('c')) << 8) | ((5)))): | |||
491 | return mcd_toc_entrys(sc, (struct ioc_read_toc_entry *) addr); | |||
492 | case CDIOCRESUME((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((20)))): | |||
493 | r = mcd_resume(sc); | |||
494 | break; | |||
495 | case CDIOCPAUSE((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((19)))): | |||
496 | r = mcd_pause(sc); | |||
497 | break; | |||
498 | case CDIOCSTART((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((22)))): | |||
499 | if (mcd_setmode(sc, MCD_MD_COOKED(0x01)) != 0) | |||
500 | r = EIO5; | |||
501 | else | |||
502 | r = 0; | |||
503 | break; | |||
504 | case CDIOCSTOP((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((23)))): | |||
505 | r = mcd_stop(sc); | |||
506 | break; | |||
507 | default: | |||
508 | r = ENOTTY25; | |||
509 | } | |||
510 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (510 )); | |||
511 | return (r); | |||
512 | } | |||
513 | ||||
514 | static int | |||
515 | mcd_size(struct cdev *dev) | |||
516 | { | |||
517 | struct mcd_softc *sc; | |||
518 | int size; | |||
519 | ||||
520 | sc = (struct mcd_softc *)dev->si_drv1; | |||
521 | ||||
522 | if (mcd_volinfo(sc) == 0) { | |||
523 | sc->data.blksize = MCDBLK2048; | |||
524 | size = msf2hsg(sc->data.volinfo.vol_msf, 0); | |||
525 | sc->data.disksize = size * (MCDBLK2048/DEV_BSIZE(1<<9)); | |||
526 | return (0); | |||
527 | } | |||
528 | return (-1); | |||
529 | } | |||
530 | ||||
531 | /*************************************************************** | |||
532 | * lower level of driver starts here | |||
533 | **************************************************************/ | |||
534 | ||||
535 | #ifdef NOTDEF | |||
536 | static char | |||
537 | irqs[] = { | |||
538 | 0x00,0x00,0x10,0x20,0x00,0x30,0x00,0x00, | |||
539 | 0x00,0x10,0x40,0x50,0x00,0x00,0x00,0x00 | |||
540 | }; | |||
541 | ||||
542 | static char | |||
543 | drqs[] = { | |||
544 | 0x00,0x01,0x00,0x03,0x00,0x05,0x06,0x07, | |||
545 | }; | |||
546 | #endif | |||
547 | ||||
548 | #ifdef NOT_YET | |||
549 | static void | |||
550 | mcd_configure(struct mcd_softc *sc) | |||
551 | { | |||
552 | MCD_WRITE(sc, MCD_REG_CONFIG, sc->data.config)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (3), (sc->data.config)); | |||
553 | } | |||
554 | #endif | |||
555 | ||||
556 | /* Wait for non-busy - return 0 on timeout */ | |||
557 | static int | |||
558 | twiddle_thumbs(struct mcd_softc *sc, int count, char *whine) | |||
559 | { | |||
560 | int i; | |||
561 | ||||
562 | for (i = 0; i < count; i++) { | |||
563 | if (!(MCD_READ(sc, MCD_FLAGS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1)) & MFL_STATUS_NOT_AVAIL0x04)) | |||
564 | return (1); | |||
565 | } | |||
566 | if (bootverbose) | |||
567 | device_printf(sc->dev, "timeout %s\n", whine); | |||
568 | return (0); | |||
569 | } | |||
570 | ||||
571 | /* check to see if a Mitsumi CD-ROM is attached to the ISA bus */ | |||
572 | ||||
573 | int | |||
574 | mcd_probe(struct mcd_softc *sc) | |||
575 | { | |||
576 | int i, j; | |||
577 | unsigned char stbytes[3]; | |||
578 | ||||
579 | sc->data.flags = MCDPROBING0x0010; | |||
580 | ||||
581 | #ifdef NOTDEF | |||
582 | /* get irq/drq configuration word */ | |||
583 | sc->data.config = irqs[dev->id_irq]; /* | drqs[dev->id_drq];*/ | |||
584 | #else | |||
585 | sc->data.config = 0; | |||
586 | #endif | |||
587 | ||||
588 | /* send a reset */ | |||
589 | MCD_WRITE(sc, MCD_FLAGS, M_RESET)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1), (0x00)); | |||
590 | ||||
591 | /* | |||
592 | * delay awhile by getting any pending garbage (old data) and | |||
593 | * throwing it away. | |||
594 | */ | |||
595 | for (i = 1000000; i != 0; i--) | |||
596 | (void)MCD_READ(sc, MCD_FLAGS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1)); | |||
597 | ||||
598 | /* Get status */ | |||
599 | MCD_WRITE(sc, MCD_DATA, MCD_CMDGETSTAT)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0x40)); | |||
600 | if (!twiddle_thumbs(sc, 1000000, "getting status")) | |||
601 | return (ENXIO6); /* Timeout */ | |||
602 | /* Get version information */ | |||
603 | MCD_WRITE(sc, MCD_DATA, MCD_CMDCONTINFO)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0xDC)); | |||
604 | for (j = 0; j < 3; j++) { | |||
605 | if (!twiddle_thumbs(sc, 3000, "getting version info")) | |||
606 | return (ENXIO6); | |||
607 | stbytes[j] = (MCD_READ(sc, MCD_DATA)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0)) & 0xFF); | |||
608 | } | |||
609 | if (stbytes[1] == stbytes[2]) | |||
610 | return (ENXIO6); | |||
611 | if (stbytes[2] >= 4 || stbytes[1] != 'M') { | |||
612 | MCD_WRITE(sc, MCD_CTRL, M_PICKLE)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (2), (0x04)); | |||
613 | sc->data.flags |= MCDNEWMODEL0x0004; | |||
614 | } | |||
615 | sc->data.read_command = MCD_CMDSINGLESPEEDREAD0xC0; | |||
616 | switch (stbytes[1]) { | |||
617 | case 'M': | |||
618 | if (stbytes[2] <= 2) { | |||
619 | sc->data.type = MCD_TYPE_LU002S1; | |||
620 | sc->data.name = "Mitsumi LU002S"; | |||
621 | } else if (stbytes[2] <= 5) { | |||
622 | sc->data.type = MCD_TYPE_LU005S2; | |||
623 | sc->data.name = "Mitsumi LU005S"; | |||
624 | } else { | |||
625 | sc->data.type = MCD_TYPE_LU006S3; | |||
626 | sc->data.name = "Mitsumi LU006S"; | |||
627 | } | |||
628 | break; | |||
629 | case 'F': | |||
630 | sc->data.type = MCD_TYPE_FX0014; | |||
631 | sc->data.name = "Mitsumi FX001"; | |||
632 | break; | |||
633 | case 'D': | |||
634 | sc->data.type = MCD_TYPE_FX001D5; | |||
635 | sc->data.name = "Mitsumi FX001D"; | |||
636 | sc->data.read_command = MCD_CMDDOUBLESPEEDREAD0xC1; | |||
637 | break; | |||
638 | default: | |||
639 | sc->data.type = MCD_TYPE_UNKNOWN0; | |||
640 | sc->data.name = "Mitsumi ???"; | |||
641 | break; | |||
642 | } | |||
643 | ||||
644 | if (bootverbose) | |||
645 | device_printf(sc->dev, "type %s, version info: %c %x\n", | |||
646 | sc->data.name, stbytes[1], stbytes[2]); | |||
647 | ||||
648 | return (0); | |||
649 | } | |||
650 | ||||
651 | ||||
652 | static int | |||
653 | mcd_waitrdy(struct mcd_softc *sc, int dly) | |||
654 | { | |||
655 | int i; | |||
656 | ||||
657 | /* wait until flag port senses status ready */ | |||
658 | for (i=0; i<dly; i+=MIN_DELAY15) { | |||
659 | if (!(MCD_READ(sc, MCD_FLAGS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1)) & MFL_STATUS_NOT_AVAIL0x04)) | |||
660 | return (0); | |||
661 | DELAY(MIN_DELAY15); | |||
662 | } | |||
663 | return (-1); | |||
664 | } | |||
665 | ||||
666 | static int | |||
667 | mcd_getreply(struct mcd_softc *sc, int dly) | |||
668 | { | |||
669 | ||||
670 | /* wait data to become ready */ | |||
671 | if (mcd_waitrdy(sc, dly)<0) { | |||
672 | device_printf(sc->dev, "timeout getreply\n"); | |||
673 | return (-1); | |||
674 | } | |||
675 | ||||
676 | /* get the data */ | |||
677 | return (MCD_READ(sc, MCD_REG_STATUS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0)) & 0xFF); | |||
678 | } | |||
679 | ||||
680 | static int | |||
681 | mcd_getstat(struct mcd_softc *sc, int sflg) | |||
682 | { | |||
683 | int i; | |||
684 | ||||
685 | /* get the status */ | |||
686 | if (sflg) | |||
687 | MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDGETSTAT)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0x40)); | |||
688 | i = mcd_getreply(sc, DELAY_GETREPLY5000000); | |||
689 | if (i<0 || (i & MCD_ST_CMDCHECK0x01)) { | |||
690 | sc->data.curr_mode = MCD_MD_UNKNOWN(-1); | |||
691 | return (-1); | |||
692 | } | |||
693 | ||||
694 | sc->data.status = i; | |||
695 | ||||
696 | if (mcd_setflags(sc) < 0) | |||
697 | return (-2); | |||
698 | return (sc->data.status); | |||
699 | } | |||
700 | ||||
701 | static int | |||
702 | mcd_setflags(struct mcd_softc *sc) | |||
703 | { | |||
704 | ||||
705 | /* check flags */ | |||
706 | if ( (sc->data.status & (MCDDSKCHNG0x20|MCDDOOROPEN0x80)) | |||
707 | || !(sc->data.status & MCDDSKIN0x40)) { | |||
708 | MCD_TRACE("setflags: sensed DSKCHNG or DOOROPEN or !DSKIN\n"){ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("setflags: sensed DSKCHNG or DOOROPEN or !DSKIN\n" ); } }; | |||
709 | mcd_soft_reset(sc); | |||
710 | return (-1); | |||
711 | } | |||
712 | ||||
713 | if (sc->data.status & MCDAUDIOBSY0x02) | |||
714 | sc->data.audio_status = CD_AS_PLAY_IN_PROGRESS0x11; | |||
715 | else if (sc->data.audio_status == CD_AS_PLAY_IN_PROGRESS0x11) | |||
716 | sc->data.audio_status = CD_AS_PLAY_COMPLETED0x13; | |||
717 | return (0); | |||
718 | } | |||
719 | ||||
720 | static int | |||
721 | mcd_get(struct mcd_softc *sc, char *buf, int nmax) | |||
722 | { | |||
723 | int i,k; | |||
724 | ||||
725 | for (i=0; i<nmax; i++) { | |||
726 | /* wait for data */ | |||
727 | if ((k = mcd_getreply(sc, DELAY_GETREPLY5000000)) < 0) { | |||
728 | device_printf(sc->dev, "timeout mcd_get\n"); | |||
729 | return (-1); | |||
730 | } | |||
731 | buf[i] = k; | |||
732 | } | |||
733 | return (i); | |||
734 | } | |||
735 | ||||
736 | static int | |||
737 | mcd_send(struct mcd_softc *sc, int cmd,int nretrys) | |||
738 | { | |||
739 | int i,k=0; | |||
740 | ||||
741 | /*MCD_TRACE("mcd_send: command = 0x%02x\n",cmd,0,0,0);*/ | |||
742 | for (i=0; i<nretrys; i++) { | |||
743 | MCD_WRITE(sc, MCD_REG_COMMAND, cmd)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (cmd)); | |||
744 | if ((k=mcd_getstat(sc, 0)) != -1) | |||
745 | break; | |||
746 | } | |||
747 | if (k == -2) { | |||
748 | device_printf(sc->dev, "media changed\n"); | |||
749 | return (-1); | |||
750 | } | |||
751 | if (i == nretrys) { | |||
752 | device_printf(sc->dev, "mcd_send retry cnt exceeded\n"); | |||
753 | return (-1); | |||
754 | } | |||
755 | /*MCD_TRACE("mcd_send: done\n",0,0,0,0);*/ | |||
756 | return (0); | |||
757 | } | |||
758 | ||||
759 | static void | |||
760 | hsg2msf(int hsg, bcd_t *msf) | |||
761 | { | |||
762 | hsg += 150; | |||
763 | F_msf(msf)msf[2] = bin2bcd(hsg % 75)(bin2bcd_data[hsg % 75]); | |||
764 | hsg /= 75; | |||
765 | S_msf(msf)msf[1] = bin2bcd(hsg % 60)(bin2bcd_data[hsg % 60]); | |||
766 | hsg /= 60; | |||
767 | M_msf(msf)msf[0] = bin2bcd(hsg)(bin2bcd_data[hsg]); | |||
768 | } | |||
769 | ||||
770 | static int | |||
771 | msf2hsg(bcd_t *msf, int relative) | |||
772 | { | |||
773 | return (bcd2bin(M_msf(msf))(bcd2bin_data[msf[0]]) * 60 + bcd2bin(S_msf(msf))(bcd2bin_data[msf[1]])) * 75 + | |||
774 | bcd2bin(F_msf(msf))(bcd2bin_data[msf[2]]) - (!relative) * 150; | |||
775 | } | |||
776 | ||||
777 | static int | |||
778 | mcd_volinfo(struct mcd_softc *sc) | |||
779 | { | |||
780 | ||||
781 | /* Just return if we already have it */ | |||
782 | if (sc->data.flags & MCDVOLINFO0x0040) return (0); | |||
783 | ||||
784 | /*MCD_TRACE("mcd_volinfo: enter\n",0,0,0,0);*/ | |||
785 | ||||
786 | /* send volume info command */ | |||
787 | if (mcd_send(sc, MCD_CMDGETVOLINFO0x10,MCD_RETRYS5) < 0) | |||
788 | return (EIO5); | |||
789 | ||||
790 | /* get data */ | |||
791 | if (mcd_get(sc, (char*) &sc->data.volinfo,sizeof(struct mcd_volinfo)) < 0) { | |||
792 | device_printf(sc->dev, "mcd_volinfo: error read data\n"); | |||
793 | return (EIO5); | |||
794 | } | |||
795 | ||||
796 | if (sc->data.volinfo.trk_low > 0 && | |||
797 | sc->data.volinfo.trk_high >= sc->data.volinfo.trk_low | |||
798 | ) { | |||
799 | sc->data.flags |= MCDVOLINFO0x0040; /* volinfo is OK */ | |||
800 | return (0); | |||
801 | } | |||
802 | ||||
803 | return (EINVAL22); | |||
804 | } | |||
805 | ||||
806 | /* state machine to process read requests | |||
807 | * initialize with MCD_S_BEGIN: calculate sizes, and read status | |||
808 | * MCD_S_WAITSTAT: wait for status reply, set mode | |||
809 | * MCD_S_WAITMODE: waits for status reply from set mode, set read command | |||
810 | * MCD_S_WAITREAD: wait for read ready, read data | |||
811 | */ | |||
812 | static void | |||
813 | mcd_timeout(void *arg) | |||
814 | { | |||
815 | struct mcd_softc *sc; | |||
816 | ||||
817 | sc = (struct mcd_softc *)arg; | |||
818 | ||||
819 | MCD_ASSERT_LOCKED(sc)(void)0; | |||
820 | mcd_doread(sc, sc->ch_state, sc->ch_mbxsave); | |||
821 | } | |||
822 | ||||
823 | static void | |||
824 | mcd_doread(struct mcd_softc *sc, int state, struct mcd_mbx *mbxin) | |||
825 | { | |||
826 | struct mcd_mbx *mbx; | |||
827 | struct bio *bp; | |||
828 | int rm, i, k; | |||
829 | struct mcd_read2 rbuf; | |||
830 | int blknum; | |||
831 | caddr_t addr; | |||
832 | ||||
833 | MCD_ASSERT_LOCKED(sc)(void)0; | |||
834 | mbx = (state!=MCD_S_BEGIN0) ? sc->ch_mbxsave : mbxin; | |||
835 | bp = mbx->bp; | |||
836 | ||||
837 | loop: | |||
838 | switch (state) { | |||
839 | case MCD_S_BEGIN0: | |||
840 | mbx = sc->ch_mbxsave = mbxin; | |||
841 | ||||
842 | case MCD_S_BEGIN11: | |||
843 | retry_status: | |||
844 | /* get status */ | |||
845 | MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDGETSTAT)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0x40)); | |||
846 | mbx->count = RDELAY_WAITSTAT300; | |||
847 | sc->ch_state = MCD_S_WAITSTAT2; | |||
848 | callout_reset(&sc->timer, hz/100, mcd_timeout, sc)callout_reset_sbt_on(((&sc->timer)), tick_sbt * ((hz/100 )), 0, ((mcd_timeout)), ((sc)), (-1), 0x0100); /* XXX */ | |||
849 | return; | |||
850 | case MCD_S_WAITSTAT2: | |||
851 | sc->ch_state = MCD_S_WAITSTAT2; | |||
852 | callout_stop(&sc->timer)_callout_stop_safe(&sc->timer, 0, ((void *)0)); | |||
853 | if (mbx->count-- >= 0) { | |||
854 | if (MCD_READ(sc, MCD_FLAGS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1)) & MFL_STATUS_NOT_AVAIL0x04) { | |||
855 | sc->ch_state = MCD_S_WAITSTAT2; | |||
856 | callout_reset(&sc->timer, hz/100,callout_reset_sbt_on(((&sc->timer)), tick_sbt * ((hz/100 )), 0, ((mcd_timeout)), ((sc)), (-1), 0x0100) | |||
857 | mcd_timeout, sc)callout_reset_sbt_on(((&sc->timer)), tick_sbt * ((hz/100 )), 0, ((mcd_timeout)), ((sc)), (-1), 0x0100); /* XXX */ | |||
858 | return; | |||
859 | } | |||
860 | sc->data.status = MCD_READ(sc, MCD_REG_STATUS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0)) & 0xFF; | |||
861 | if (sc->data.status & MCD_ST_CMDCHECK0x01) | |||
862 | goto retry_status; | |||
863 | if (mcd_setflags(sc) < 0) | |||
864 | goto changed; | |||
865 | MCD_TRACE("got WAITSTAT delay=%d\n",{ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("got WAITSTAT delay=%d\n", 300 - mbx->count); } } | |||
866 | RDELAY_WAITSTAT-mbx->count){ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("got WAITSTAT delay=%d\n", 300 - mbx->count); } }; | |||
867 | /* reject, if audio active */ | |||
868 | if (sc->data.status & MCDAUDIOBSY0x02) { | |||
869 | device_printf(sc->dev, "audio is active\n"); | |||
870 | goto readerr; | |||
871 | } | |||
872 | ||||
873 | retry_mode: | |||
874 | /* to check for raw/cooked mode */ | |||
875 | if (sc->data.flags & MCDREADRAW0x0020) { | |||
876 | rm = MCD_MD_RAW(0x40|0x20|0x01); | |||
877 | mbx->sz = MCDRBLKsizeof(struct mcd_rawsector); | |||
878 | } else { | |||
879 | rm = MCD_MD_COOKED(0x01); | |||
880 | mbx->sz = sc->data.blksize; | |||
881 | } | |||
882 | ||||
883 | if (rm == sc->data.curr_mode) | |||
884 | goto modedone; | |||
885 | ||||
886 | mbx->count = RDELAY_WAITMODE300; | |||
887 | ||||
888 | sc->data.curr_mode = MCD_MD_UNKNOWN(-1); | |||
889 | mbx->mode = rm; | |||
890 | MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDSETMODE)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0x50)); | |||
891 | MCD_WRITE(sc, MCD_REG_COMMAND, rm)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (rm)); | |||
892 | ||||
893 | sc->ch_state = MCD_S_WAITMODE3; | |||
894 | callout_reset(&sc->timer, hz / 100, mcd_timeout, sc)callout_reset_sbt_on(((&sc->timer)), tick_sbt * ((hz / 100)), 0, ((mcd_timeout)), ((sc)), (-1), 0x0100); /* XXX */ | |||
895 | return; | |||
896 | } else { | |||
897 | device_printf(sc->dev, "timeout getstatus\n"); | |||
898 | goto readerr; | |||
899 | } | |||
900 | ||||
901 | case MCD_S_WAITMODE3: | |||
902 | sc->ch_state = MCD_S_WAITMODE3; | |||
903 | callout_stop(&sc->timer)_callout_stop_safe(&sc->timer, 0, ((void *)0)); | |||
904 | if (mbx->count-- < 0) { | |||
905 | device_printf(sc->dev, "timeout set mode\n"); | |||
906 | goto readerr; | |||
907 | } | |||
908 | if (MCD_READ(sc, MCD_FLAGS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1)) & MFL_STATUS_NOT_AVAIL0x04) { | |||
909 | sc->ch_state = MCD_S_WAITMODE3; | |||
910 | callout_reset(&sc->timer, hz / 100, mcd_timeout, sc)callout_reset_sbt_on(((&sc->timer)), tick_sbt * ((hz / 100)), 0, ((mcd_timeout)), ((sc)), (-1), 0x0100); | |||
911 | return; | |||
912 | } | |||
913 | sc->data.status = MCD_READ(sc, MCD_REG_STATUS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0)) & 0xFF; | |||
914 | if (sc->data.status & MCD_ST_CMDCHECK0x01) { | |||
915 | sc->data.curr_mode = MCD_MD_UNKNOWN(-1); | |||
916 | goto retry_mode; | |||
917 | } | |||
918 | if (mcd_setflags(sc) < 0) | |||
919 | goto changed; | |||
920 | sc->data.curr_mode = mbx->mode; | |||
921 | MCD_TRACE("got WAITMODE delay=%d\n",{ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("got WAITMODE delay=%d\n", 300 - mbx->count); } } | |||
922 | RDELAY_WAITMODE-mbx->count){ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("got WAITMODE delay=%d\n", 300 - mbx->count); } }; | |||
923 | modedone: | |||
924 | /* for first block */ | |||
925 | mbx->nblk = howmany(bp->bio_bcount, mbx->sz)(((bp->bio_bcount)+((mbx->sz)-1))/(mbx->sz)); | |||
926 | mbx->skip = 0; | |||
927 | ||||
928 | nextblock: | |||
929 | blknum = bp->bio_offset / mbx->sz + mbx->skip/mbx->sz; | |||
930 | ||||
931 | MCD_TRACE("mcd_doread: read blknum=%d for bp=%p\n",{ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("mcd_doread: read blknum=%d for bp=%p\n" , blknum, bp); } } | |||
932 | blknum, bp){ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("mcd_doread: read blknum=%d for bp=%p\n" , blknum, bp); } }; | |||
933 | ||||
934 | /* build parameter block */ | |||
935 | hsg2msf(blknum,rbuf.start_msf); | |||
936 | retry_read: | |||
937 | /* send the read command */ | |||
938 | MCD_WRITE(sc, MCD_REG_COMMAND, sc->data.read_command)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (sc->data.read_command)); | |||
939 | MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[0])bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (rbuf.start_msf[0])); | |||
940 | MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[1])bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (rbuf.start_msf[1])); | |||
941 | MCD_WRITE(sc, MCD_REG_COMMAND, rbuf.start_msf[2])bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (rbuf.start_msf[2])); | |||
942 | MCD_WRITE(sc, MCD_REG_COMMAND, 0)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0)); | |||
943 | MCD_WRITE(sc, MCD_REG_COMMAND, 0)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0)); | |||
944 | MCD_WRITE(sc, MCD_REG_COMMAND, 1)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (1)); | |||
945 | ||||
946 | /* Spin briefly (<= 2ms) to avoid missing next block */ | |||
947 | for (i = 0; i < 20; i++) { | |||
948 | k = MCD_READ(sc, MCD_FLAGS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1)); | |||
949 | if (!(k & MFL_DATA_NOT_AVAIL0x02)) | |||
950 | goto got_it; | |||
951 | DELAY(100); | |||
952 | } | |||
953 | ||||
954 | mbx->count = RDELAY_WAITREAD800; | |||
955 | sc->ch_state = MCD_S_WAITREAD4; | |||
956 | callout_reset(&sc->timer, hz / 100, mcd_timeout, sc)callout_reset_sbt_on(((&sc->timer)), tick_sbt * ((hz / 100)), 0, ((mcd_timeout)), ((sc)), (-1), 0x0100); /* XXX */ | |||
957 | return; | |||
958 | case MCD_S_WAITREAD4: | |||
959 | sc->ch_state = MCD_S_WAITREAD4; | |||
960 | callout_stop(&sc->timer)_callout_stop_safe(&sc->timer, 0, ((void *)0)); | |||
961 | if (mbx->count-- > 0) { | |||
962 | k = MCD_READ(sc, MCD_FLAGS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1)); | |||
963 | if (!(k & MFL_DATA_NOT_AVAIL0x02)) { /* XXX */ | |||
964 | MCD_TRACE("got data delay=%d\n",{ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("got data delay=%d\n", 800 -mbx ->count); } } | |||
965 | RDELAY_WAITREAD-mbx->count){ if (sc->debug) { device_printf(sc->dev, "status=0x%02x: " , sc->data.status); printf("got data delay=%d\n", 800 -mbx ->count); } }; | |||
966 | got_it: | |||
967 | /* data is ready */ | |||
968 | addr = bp->bio_data + mbx->skip; | |||
969 | ||||
970 | MCD_WRITE(sc, MCD_REG_CTL2,0x04)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (2), (0x04)); /* XXX */ | |||
971 | for (i=0; i<mbx->sz; i++) | |||
972 | *addr++ = MCD_READ(sc, MCD_REG_RDATA)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0)); | |||
973 | MCD_WRITE(sc, MCD_REG_CTL2,0x0c)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (2), (0x0c)); /* XXX */ | |||
974 | ||||
975 | k = MCD_READ(sc, MCD_FLAGS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1)); | |||
976 | /* If we still have some junk, read it too */ | |||
977 | if (!(k & MFL_DATA_NOT_AVAIL0x02)) { | |||
978 | MCD_WRITE(sc, MCD_REG_CTL2, 0x04)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (2), (0x04)); /* XXX */ | |||
979 | (void)MCD_READ(sc, MCD_REG_RDATA)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0)); | |||
980 | (void)MCD_READ(sc, MCD_REG_RDATA)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0)); | |||
981 | MCD_WRITE(sc, MCD_REG_CTL2, 0x0c)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (2), (0x0c)); /* XXX */ | |||
982 | } | |||
983 | ||||
984 | if (--mbx->nblk > 0) { | |||
985 | mbx->skip += mbx->sz; | |||
986 | goto nextblock; | |||
987 | } | |||
988 | ||||
989 | /* return buffer */ | |||
990 | bp->bio_resid = 0; | |||
991 | biodone(bp); | |||
992 | ||||
993 | sc->data.flags &= ~(MCDMBXBSY0x0100|MCDREADRAW0x0020); | |||
994 | mcd_start(sc); | |||
995 | return; | |||
996 | } | |||
997 | if (!(k & MFL_STATUS_NOT_AVAIL0x04)) { | |||
998 | sc->data.status = MCD_READ(sc, MCD_REG_STATUS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0)) & 0xFF; | |||
999 | if (sc->data.status & MCD_ST_CMDCHECK0x01) | |||
1000 | goto retry_read; | |||
1001 | if (mcd_setflags(sc) < 0) | |||
1002 | goto changed; | |||
1003 | } | |||
1004 | sc->ch_state = MCD_S_WAITREAD4; | |||
1005 | callout_reset(&sc->timer, hz / 100, mcd_timeout, sc)callout_reset_sbt_on(((&sc->timer)), tick_sbt * ((hz / 100)), 0, ((mcd_timeout)), ((sc)), (-1), 0x0100); /* XXX */ | |||
1006 | return; | |||
1007 | } else { | |||
1008 | device_printf(sc->dev, "timeout read data\n"); | |||
1009 | goto readerr; | |||
1010 | } | |||
1011 | } | |||
1012 | ||||
1013 | readerr: | |||
1014 | if (mbx->retry-- > 0) { | |||
1015 | device_printf(sc->dev, "retrying\n"); | |||
1016 | state = MCD_S_BEGIN11; | |||
1017 | goto loop; | |||
1018 | } | |||
1019 | harderr: | |||
1020 | /* invalidate the buffer */ | |||
1021 | bp->bio_flags |= BIO_ERROR0x01; | |||
1022 | bp->bio_resid = bp->bio_bcount; | |||
1023 | biodone(bp); | |||
1024 | ||||
1025 | sc->data.flags &= ~(MCDMBXBSY0x0100|MCDREADRAW0x0020); | |||
1026 | mcd_start(sc); | |||
1027 | return; | |||
1028 | ||||
1029 | changed: | |||
1030 | device_printf(sc->dev, "media changed\n"); | |||
1031 | goto harderr; | |||
1032 | ||||
1033 | #ifdef NOTDEF | |||
1034 | device_printf(sc->dev, "unit timeout, resetting\n"); | |||
1035 | MCD_WRITE(sc, MCD_REG_RESET, MCD_CMDRESET)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1), (0x00)); | |||
1036 | DELAY(300000); | |||
1037 | (void)mcd_getstat(sc, 1); | |||
1038 | (void)mcd_getstat(sc, 1); | |||
1039 | /*sc->data.status &= ~MCDDSKCHNG; */ | |||
1040 | sc->data.debug = 1; /* preventive set debug mode */ | |||
1041 | ||||
1042 | #endif | |||
1043 | ||||
1044 | } | |||
1045 | ||||
1046 | static int | |||
1047 | mcd_lock_door(struct mcd_softc *sc, int lock) | |||
1048 | { | |||
1049 | ||||
1050 | MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDLOCKDRV)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0xFE)); | |||
1051 | MCD_WRITE(sc, MCD_REG_COMMAND, lock)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (lock)); | |||
1052 | if (mcd_getstat(sc, 0) == -1) | |||
1053 | return (EIO5); | |||
1054 | return (0); | |||
1055 | } | |||
1056 | ||||
1057 | static int | |||
1058 | mcd_close_tray(struct mcd_softc *sc) | |||
1059 | { | |||
1060 | int retry, r; | |||
1061 | ||||
1062 | if (mcd_getstat(sc, 1) == -1) | |||
1063 | return (EIO5); | |||
1064 | if (sc->data.status & MCDDOOROPEN0x80) { | |||
1065 | MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDCLOSETRAY)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0xF8)); | |||
1066 | for (retry = 0; retry < CLOSE_TRAY_SECS8 * WAIT_FRAC4; retry++) { | |||
1067 | if (MCD_READ(sc, MCD_FLAGS)bus_space_read_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1)) & MFL_STATUS_NOT_AVAIL0x04) | |||
1068 | (void) mtx_sleep(sc, &sc->mtx, PSOCK | PCATCH,_sleep((sc), &(&sc->mtx)->lock_object, (((80) + 24) | 0x100), ("mcdcls"), tick_sbt * (hz/4), 0, 0x0100) | |||
1069 | "mcdcls", hz/WAIT_FRAC)_sleep((sc), &(&sc->mtx)->lock_object, (((80) + 24) | 0x100), ("mcdcls"), tick_sbt * (hz/4), 0, 0x0100); | |||
1070 | else { | |||
1071 | if ((r = mcd_getstat(sc, 0)) == -1) | |||
1072 | return (EIO5); | |||
1073 | return (0); | |||
1074 | } | |||
1075 | } | |||
1076 | return (ENXIO6); | |||
1077 | } | |||
1078 | return (0); | |||
1079 | } | |||
1080 | ||||
1081 | static int | |||
1082 | mcd_eject(struct mcd_softc *sc) | |||
1083 | { | |||
1084 | int r; | |||
1085 | ||||
1086 | if (mcd_getstat(sc, 1) == -1) /* detect disk change too */ | |||
1087 | return (EIO5); | |||
1088 | if (sc->data.status & MCDDOOROPEN0x80) | |||
1089 | return (0); | |||
1090 | if ((r = mcd_stop(sc)) == EIO5) | |||
1091 | return (r); | |||
1092 | MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDEJECTDISK)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0xF6)); | |||
1093 | if (mcd_getstat(sc, 0) == -1) | |||
1094 | return (EIO5); | |||
1095 | return (0); | |||
1096 | } | |||
1097 | ||||
1098 | static int | |||
1099 | mcd_inject(struct mcd_softc *sc) | |||
1100 | { | |||
1101 | ||||
1102 | if (mcd_getstat(sc, 1) == -1) /* detect disk change too */ | |||
1103 | return (EIO5); | |||
1104 | if (sc->data.status & MCDDOOROPEN0x80) | |||
1105 | return mcd_close_tray(sc); | |||
1106 | return (0); | |||
1107 | } | |||
1108 | ||||
1109 | static int | |||
1110 | mcd_hard_reset(struct mcd_softc *sc) | |||
1111 | { | |||
1112 | ||||
1113 | MCD_WRITE(sc, MCD_REG_RESET, MCD_CMDRESET)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (1), (0x00)); | |||
1114 | sc->data.curr_mode = MCD_MD_UNKNOWN(-1); | |||
1115 | sc->data.audio_status = CD_AS_AUDIO_INVALID0x00; | |||
1116 | return (0); | |||
1117 | } | |||
1118 | ||||
1119 | static void | |||
1120 | mcd_soft_reset(struct mcd_softc *sc) | |||
1121 | { | |||
1122 | ||||
1123 | sc->data.flags &= (MCDINIT0x0002|MCDPROBING0x0010|MCDNEWMODEL0x0004); | |||
1124 | sc->data.curr_mode = MCD_MD_UNKNOWN(-1); | |||
1125 | sc->data.partflags = 0; | |||
1126 | sc->data.audio_status = CD_AS_AUDIO_INVALID0x00; | |||
1127 | } | |||
1128 | ||||
1129 | static int | |||
1130 | mcd_setmode(struct mcd_softc *sc, int mode) | |||
1131 | { | |||
1132 | int retry, st; | |||
1133 | ||||
1134 | if (sc->data.curr_mode == mode) | |||
1135 | return (0); | |||
1136 | if (sc->data.debug) | |||
1137 | device_printf(sc->dev, "setting mode to %d\n", mode); | |||
1138 | for(retry=0; retry<MCD_RETRYS5; retry++) | |||
1139 | { | |||
1140 | sc->data.curr_mode = MCD_MD_UNKNOWN(-1); | |||
1141 | MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDSETMODE)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0x50)); | |||
1142 | MCD_WRITE(sc, MCD_REG_COMMAND, mode)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (mode)); | |||
1143 | if ((st = mcd_getstat(sc, 0)) >= 0) { | |||
1144 | sc->data.curr_mode = mode; | |||
1145 | return (0); | |||
1146 | } | |||
1147 | if (st == -2) { | |||
1148 | device_printf(sc->dev, "media changed\n"); | |||
1149 | break; | |||
1150 | } | |||
1151 | } | |||
1152 | ||||
1153 | return (-1); | |||
1154 | } | |||
1155 | ||||
1156 | static int | |||
1157 | mcd_toc_header(struct mcd_softc *sc, struct ioc_toc_header *th) | |||
1158 | { | |||
1159 | int r; | |||
1160 | ||||
1161 | if ((r = mcd_volinfo(sc)) != 0) | |||
1162 | return (r); | |||
1163 | ||||
1164 | th->starting_track = bcd2bin(sc->data.volinfo.trk_low)(bcd2bin_data[sc->data.volinfo.trk_low]); | |||
1165 | th->ending_track = bcd2bin(sc->data.volinfo.trk_high)(bcd2bin_data[sc->data.volinfo.trk_high]); | |||
1166 | th->len = 2 * sizeof(u_char) /* start & end tracks */ + | |||
1167 | (th->ending_track + 1 - th->starting_track + 1) * | |||
1168 | sizeof(struct cd_toc_entry); | |||
1169 | ||||
1170 | return (0); | |||
1171 | } | |||
1172 | ||||
1173 | static int | |||
1174 | mcd_read_toc(struct mcd_softc *sc) | |||
1175 | { | |||
1176 | struct ioc_toc_header th; | |||
1177 | struct mcd_qchninfo q; | |||
1178 | int rc, trk, idx, retry; | |||
1179 | ||||
1180 | /* Only read TOC if needed */ | |||
1181 | if (sc->data.flags & MCDTOC0x0080) | |||
1182 | return (0); | |||
1183 | ||||
1184 | if (sc->data.debug) | |||
1185 | device_printf(sc->dev, "reading toc header\n"); | |||
1186 | ||||
1187 | if ((rc = mcd_toc_header(sc, &th)) != 0) | |||
1188 | return (rc); | |||
1189 | ||||
1190 | if (mcd_send(sc, MCD_CMDSTOPAUDIO0x70, MCD_RETRYS5) < 0) | |||
1191 | return (EIO5); | |||
1192 | ||||
1193 | if (mcd_setmode(sc, MCD_MD_TOC(0x04|0x01)) != 0) | |||
1194 | return (EIO5); | |||
1195 | ||||
1196 | if (sc->data.debug) | |||
1197 | device_printf(sc->dev, "get_toc reading qchannel info\n"); | |||
1198 | ||||
1199 | for(trk=th.starting_track; trk<=th.ending_track; trk++) | |||
1200 | sc->data.toc[trk].idx_no = 0; | |||
1201 | trk = th.ending_track - th.starting_track + 1; | |||
1202 | for(retry=0; retry<600 && trk>0; retry++) | |||
1203 | { | |||
1204 | if (mcd_getqchan(sc, &q) < 0) break; | |||
1205 | idx = bcd2bin(q.idx_no)(bcd2bin_data[q.idx_no]); | |||
1206 | if (idx>=th.starting_track && idx<=th.ending_track && q.trk_no==0) { | |||
1207 | if (sc->data.toc[idx].idx_no == 0) { | |||
1208 | sc->data.toc[idx] = q; | |||
1209 | trk--; | |||
1210 | } | |||
1211 | } | |||
1212 | } | |||
1213 | ||||
1214 | if (mcd_setmode(sc, MCD_MD_COOKED(0x01)) != 0) | |||
1215 | return (EIO5); | |||
1216 | ||||
1217 | if (trk != 0) | |||
1218 | return (ENXIO6); | |||
1219 | ||||
1220 | /* add a fake last+1 */ | |||
1221 | idx = th.ending_track + 1; | |||
1222 | sc->data.toc[idx].control = sc->data.toc[idx-1].control; | |||
1223 | sc->data.toc[idx].addr_type = sc->data.toc[idx-1].addr_type; | |||
1224 | sc->data.toc[idx].trk_no = 0; | |||
1225 | sc->data.toc[idx].idx_no = MCD_LASTPLUS1170; | |||
1226 | sc->data.toc[idx].hd_pos_msf[0] = sc->data.volinfo.vol_msf[0]; | |||
1227 | sc->data.toc[idx].hd_pos_msf[1] = sc->data.volinfo.vol_msf[1]; | |||
1228 | sc->data.toc[idx].hd_pos_msf[2] = sc->data.volinfo.vol_msf[2]; | |||
1229 | ||||
1230 | if (sc->data.debug) | |||
1231 | { int i; | |||
1232 | for (i = th.starting_track; i <= idx; i++) | |||
1233 | device_printf(sc->dev, "trk %d idx %d pos %d %d %d\n", | |||
1234 | i, | |||
1235 | sc->data.toc[i].idx_no > 0x99 ? sc->data.toc[i].idx_no : | |||
1236 | bcd2bin(sc->data.toc[i].idx_no)(bcd2bin_data[sc->data.toc[i].idx_no]), | |||
1237 | bcd2bin(sc->data.toc[i].hd_pos_msf[0])(bcd2bin_data[sc->data.toc[i].hd_pos_msf[0]]), | |||
1238 | bcd2bin(sc->data.toc[i].hd_pos_msf[1])(bcd2bin_data[sc->data.toc[i].hd_pos_msf[1]]), | |||
1239 | bcd2bin(sc->data.toc[i].hd_pos_msf[2])(bcd2bin_data[sc->data.toc[i].hd_pos_msf[2]])); | |||
1240 | } | |||
1241 | ||||
1242 | sc->data.flags |= MCDTOC0x0080; | |||
1243 | ||||
1244 | return (0); | |||
1245 | } | |||
1246 | ||||
1247 | #if 0 | |||
1248 | static int | |||
1249 | mcd_toc_entry(struct mcd_softc *sc, struct ioc_read_toc_single_entry *te) | |||
1250 | { | |||
1251 | struct ioc_toc_header th; | |||
1252 | int rc, trk; | |||
1253 | ||||
1254 | if (te->address_format != CD_MSF_FORMAT2 | |||
1255 | && te->address_format != CD_LBA_FORMAT1) | |||
1256 | return (EINVAL22); | |||
1257 | ||||
1258 | /* Copy the toc header */ | |||
1259 | if ((rc = mcd_toc_header(sc, &th)) != 0) | |||
1260 | return (rc); | |||
1261 | ||||
1262 | /* verify starting track */ | |||
1263 | trk = te->track; | |||
1264 | if (trk == 0) | |||
1265 | trk = th.starting_track; | |||
1266 | else if (trk == MCD_LASTPLUS1170) | |||
1267 | trk = th.ending_track + 1; | |||
1268 | else if (trk < th.starting_track || trk > th.ending_track + 1) | |||
1269 | return (EINVAL22); | |||
1270 | ||||
1271 | /* Make sure we have a valid toc */ | |||
1272 | if ((rc=mcd_read_toc(sc)) != 0) | |||
1273 | return (rc); | |||
1274 | ||||
1275 | /* Copy the TOC data. */ | |||
1276 | if (sc->data.toc[trk].idx_no == 0) | |||
1277 | return (EIO5); | |||
1278 | ||||
1279 | te->entry.control = sc->data.toc[trk].control; | |||
1280 | te->entry.addr_type = sc->data.toc[trk].addr_type; | |||
1281 | te->entry.track = | |||
1282 | sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no : | |||
1283 | bcd2bin(sc->data.toc[trk].idx_no)(bcd2bin_data[sc->data.toc[trk].idx_no]); | |||
1284 | switch (te->address_format) { | |||
1285 | case CD_MSF_FORMAT2: | |||
1286 | te->entry.addr.msf.unused = 0; | |||
1287 | te->entry.addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0])(bcd2bin_data[sc->data.toc[trk].hd_pos_msf[0]]); | |||
1288 | te->entry.addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1])(bcd2bin_data[sc->data.toc[trk].hd_pos_msf[1]]); | |||
1289 | te->entry.addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2])(bcd2bin_data[sc->data.toc[trk].hd_pos_msf[2]]); | |||
1290 | break; | |||
1291 | case CD_LBA_FORMAT1: | |||
1292 | te->entry.addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0))(__builtin_constant_p(msf2hsg(sc->data.toc[trk].hd_pos_msf , 0)) ? (((__uint32_t)((__uint16_t)(__builtin_constant_p(((__uint32_t )(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0))) & 0xffff) ? (__uint16_t)(((__uint16_t)(((__uint32_t)(msf2hsg(sc->data .toc[trk].hd_pos_msf, 0))) & 0xffff)) << 8 | ((__uint16_t )(((__uint32_t)(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0))) & 0xffff)) >> 8) : __bswap16_var(((__uint32_t)(msf2hsg (sc->data.toc[trk].hd_pos_msf, 0))) & 0xffff))) << 16) | ((__uint16_t)(__builtin_constant_p(((__uint32_t)(msf2hsg (sc->data.toc[trk].hd_pos_msf, 0))) >> 16) ? (__uint16_t )(((__uint16_t)(((__uint32_t)(msf2hsg(sc->data.toc[trk].hd_pos_msf , 0))) >> 16)) << 8 | ((__uint16_t)(((__uint32_t) (msf2hsg(sc->data.toc[trk].hd_pos_msf, 0))) >> 16)) >> 8) : __bswap16_var(((__uint32_t)(msf2hsg(sc->data.toc[trk ].hd_pos_msf, 0))) >> 16)))) : __bswap32_var(msf2hsg(sc ->data.toc[trk].hd_pos_msf, 0))); | |||
1293 | break; | |||
1294 | } | |||
1295 | return (0); | |||
1296 | } | |||
1297 | #endif | |||
1298 | ||||
1299 | static int | |||
1300 | mcd_toc_entrys(struct mcd_softc *sc, struct ioc_read_toc_entry *te) | |||
1301 | { | |||
1302 | struct cd_toc_entry entries[MCD_MAXTOCS104]; | |||
1303 | struct ioc_toc_header th; | |||
1304 | int rc, n, trk, len; | |||
1305 | ||||
1306 | if ( te->data_len < sizeof(entries[0]) | |||
1307 | || (te->data_len % sizeof(entries[0])) != 0 | |||
1308 | || (te->address_format != CD_MSF_FORMAT2 | |||
1309 | && te->address_format != CD_LBA_FORMAT1) | |||
1310 | ) | |||
1311 | return (EINVAL22); | |||
1312 | ||||
1313 | /* Copy the toc header */ | |||
1314 | if ((rc = mcd_toc_header(sc, &th)) != 0) | |||
1315 | return (rc); | |||
1316 | ||||
1317 | /* verify starting track */ | |||
1318 | trk = te->starting_track; | |||
1319 | if (trk == 0) | |||
1320 | trk = th.starting_track; | |||
1321 | else if (trk == MCD_LASTPLUS1170) | |||
1322 | trk = th.ending_track + 1; | |||
1323 | else if (trk < th.starting_track || trk > th.ending_track + 1) | |||
1324 | return (EINVAL22); | |||
1325 | ||||
1326 | len = ((th.ending_track + 1 - trk) + 1) * | |||
1327 | sizeof(entries[0]); | |||
1328 | if (te->data_len < len) | |||
1329 | len = te->data_len; | |||
1330 | if (len > sizeof(entries)) | |||
1331 | return (EINVAL22); | |||
1332 | ||||
1333 | /* Make sure we have a valid toc */ | |||
1334 | if ((rc=mcd_read_toc(sc)) != 0) | |||
1335 | return (rc); | |||
1336 | ||||
1337 | /* Copy the TOC data. */ | |||
1338 | for (n = 0; len > 0 && trk <= th.ending_track + 1; trk++) { | |||
1339 | if (sc->data.toc[trk].idx_no == 0) | |||
1340 | continue; | |||
1341 | entries[n].control = sc->data.toc[trk].control; | |||
1342 | entries[n].addr_type = sc->data.toc[trk].addr_type; | |||
1343 | entries[n].track = | |||
1344 | sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no : | |||
1345 | bcd2bin(sc->data.toc[trk].idx_no)(bcd2bin_data[sc->data.toc[trk].idx_no]); | |||
1346 | switch (te->address_format) { | |||
1347 | case CD_MSF_FORMAT2: | |||
1348 | entries[n].addr.msf.unused = 0; | |||
1349 | entries[n].addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0])(bcd2bin_data[sc->data.toc[trk].hd_pos_msf[0]]); | |||
1350 | entries[n].addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1])(bcd2bin_data[sc->data.toc[trk].hd_pos_msf[1]]); | |||
1351 | entries[n].addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2])(bcd2bin_data[sc->data.toc[trk].hd_pos_msf[2]]); | |||
1352 | break; | |||
1353 | case CD_LBA_FORMAT1: | |||
1354 | entries[n].addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0))(__builtin_constant_p(msf2hsg(sc->data.toc[trk].hd_pos_msf , 0)) ? (((__uint32_t)((__uint16_t)(__builtin_constant_p(((__uint32_t )(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0))) & 0xffff) ? (__uint16_t)(((__uint16_t)(((__uint32_t)(msf2hsg(sc->data .toc[trk].hd_pos_msf, 0))) & 0xffff)) << 8 | ((__uint16_t )(((__uint32_t)(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0))) & 0xffff)) >> 8) : __bswap16_var(((__uint32_t)(msf2hsg (sc->data.toc[trk].hd_pos_msf, 0))) & 0xffff))) << 16) | ((__uint16_t)(__builtin_constant_p(((__uint32_t)(msf2hsg (sc->data.toc[trk].hd_pos_msf, 0))) >> 16) ? (__uint16_t )(((__uint16_t)(((__uint32_t)(msf2hsg(sc->data.toc[trk].hd_pos_msf , 0))) >> 16)) << 8 | ((__uint16_t)(((__uint32_t) (msf2hsg(sc->data.toc[trk].hd_pos_msf, 0))) >> 16)) >> 8) : __bswap16_var(((__uint32_t)(msf2hsg(sc->data.toc[trk ].hd_pos_msf, 0))) >> 16)))) : __bswap32_var(msf2hsg(sc ->data.toc[trk].hd_pos_msf, 0))); | |||
1355 | break; | |||
1356 | } | |||
1357 | len -= sizeof(struct cd_toc_entry); | |||
1358 | n++; | |||
1359 | } | |||
1360 | ||||
1361 | /* copy the data back */ | |||
1362 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (1362 )); | |||
1363 | return copyout(entries, te->data, n * sizeof(struct cd_toc_entry)); | |||
| ||||
1364 | } | |||
1365 | ||||
1366 | static int | |||
1367 | mcd_stop(struct mcd_softc *sc) | |||
1368 | { | |||
1369 | ||||
1370 | /* Verify current status */ | |||
1371 | if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS0x11 && | |||
1372 | sc->data.audio_status != CD_AS_PLAY_PAUSED0x12 && | |||
1373 | sc->data.audio_status != CD_AS_PLAY_COMPLETED0x13) { | |||
1374 | if (sc->data.debug) | |||
1375 | device_printf(sc->dev, | |||
1376 | "stop attempted when not playing, audio status %d\n", | |||
1377 | sc->data.audio_status); | |||
1378 | return (EINVAL22); | |||
1379 | } | |||
1380 | if (sc->data.audio_status == CD_AS_PLAY_IN_PROGRESS0x11) | |||
1381 | if (mcd_send(sc, MCD_CMDSTOPAUDIO0x70, MCD_RETRYS5) < 0) | |||
1382 | return (EIO5); | |||
1383 | sc->data.audio_status = CD_AS_PLAY_COMPLETED0x13; | |||
1384 | return (0); | |||
1385 | } | |||
1386 | ||||
1387 | static int | |||
1388 | mcd_getqchan(struct mcd_softc *sc, struct mcd_qchninfo *q) | |||
1389 | { | |||
1390 | ||||
1391 | if (mcd_send(sc, MCD_CMDGETQCHN0x20, MCD_RETRYS5) < 0) | |||
1392 | return (-1); | |||
1393 | if (mcd_get(sc, (char *) q, sizeof(struct mcd_qchninfo)) < 0) | |||
1394 | return (-1); | |||
1395 | if (sc->data.debug) { | |||
1396 | device_printf(sc->dev, | |||
1397 | "getqchan control=0x%x addr_type=0x%x trk=%d ind=%d ttm=%d:%d.%d dtm=%d:%d.%d\n", | |||
1398 | q->control, q->addr_type, | |||
1399 | bcd2bin(q->trk_no)(bcd2bin_data[q->trk_no]), | |||
1400 | bcd2bin(q->idx_no)(bcd2bin_data[q->idx_no]), | |||
1401 | bcd2bin(q->trk_size_msf[0])(bcd2bin_data[q->trk_size_msf[0]]), | |||
1402 | bcd2bin(q->trk_size_msf[1])(bcd2bin_data[q->trk_size_msf[1]]), | |||
1403 | bcd2bin(q->trk_size_msf[2])(bcd2bin_data[q->trk_size_msf[2]]), | |||
1404 | bcd2bin(q->hd_pos_msf[0])(bcd2bin_data[q->hd_pos_msf[0]]), | |||
1405 | bcd2bin(q->hd_pos_msf[1])(bcd2bin_data[q->hd_pos_msf[1]]), | |||
1406 | bcd2bin(q->hd_pos_msf[2])(bcd2bin_data[q->hd_pos_msf[2]])); | |||
1407 | } | |||
1408 | return (0); | |||
1409 | } | |||
1410 | ||||
1411 | static int | |||
1412 | mcd_subchan(struct mcd_softc *sc, struct ioc_read_subchannel *sch, int nocopyout) | |||
1413 | { | |||
1414 | struct mcd_qchninfo q; | |||
1415 | struct cd_sub_channel_info data; | |||
1416 | int lba; | |||
1417 | ||||
1418 | if (sc->data.debug) | |||
1419 | device_printf(sc->dev, "subchan af=%d, df=%d\n", | |||
1420 | sch->address_format, | |||
1421 | sch->data_format); | |||
1422 | ||||
1423 | if (sch->address_format != CD_MSF_FORMAT2 && | |||
1424 | sch->address_format != CD_LBA_FORMAT1) | |||
1425 | return (EINVAL22); | |||
1426 | ||||
1427 | if (sch->data_format != CD_CURRENT_POSITION1 && | |||
1428 | sch->data_format != CD_MEDIA_CATALOG2) | |||
1429 | return (EINVAL22); | |||
1430 | ||||
1431 | if (mcd_setmode(sc, MCD_MD_COOKED(0x01)) != 0) | |||
1432 | return (EIO5); | |||
1433 | ||||
1434 | if (mcd_getqchan(sc, &q) < 0) | |||
1435 | return (EIO5); | |||
1436 | ||||
1437 | data.header.audio_status = sc->data.audio_status; | |||
1438 | data.what.position.data_format = sch->data_format; | |||
1439 | ||||
1440 | switch (sch->data_format) { | |||
1441 | case CD_MEDIA_CATALOG2: | |||
1442 | data.what.media_catalog.mc_valid = 1; | |||
1443 | data.what.media_catalog.mc_number[0] = '\0'; | |||
1444 | break; | |||
1445 | ||||
1446 | case CD_CURRENT_POSITION1: | |||
1447 | data.what.position.control = q.control; | |||
1448 | data.what.position.addr_type = q.addr_type; | |||
1449 | data.what.position.track_number = bcd2bin(q.trk_no)(bcd2bin_data[q.trk_no]); | |||
1450 | data.what.position.index_number = bcd2bin(q.idx_no)(bcd2bin_data[q.idx_no]); | |||
1451 | switch (sch->address_format) { | |||
1452 | case CD_MSF_FORMAT2: | |||
1453 | data.what.position.reladdr.msf.unused = 0; | |||
1454 | data.what.position.reladdr.msf.minute = bcd2bin(q.trk_size_msf[0])(bcd2bin_data[q.trk_size_msf[0]]); | |||
1455 | data.what.position.reladdr.msf.second = bcd2bin(q.trk_size_msf[1])(bcd2bin_data[q.trk_size_msf[1]]); | |||
1456 | data.what.position.reladdr.msf.frame = bcd2bin(q.trk_size_msf[2])(bcd2bin_data[q.trk_size_msf[2]]); | |||
1457 | data.what.position.absaddr.msf.unused = 0; | |||
1458 | data.what.position.absaddr.msf.minute = bcd2bin(q.hd_pos_msf[0])(bcd2bin_data[q.hd_pos_msf[0]]); | |||
1459 | data.what.position.absaddr.msf.second = bcd2bin(q.hd_pos_msf[1])(bcd2bin_data[q.hd_pos_msf[1]]); | |||
1460 | data.what.position.absaddr.msf.frame = bcd2bin(q.hd_pos_msf[2])(bcd2bin_data[q.hd_pos_msf[2]]); | |||
1461 | break; | |||
1462 | case CD_LBA_FORMAT1: | |||
1463 | lba = msf2hsg(q.trk_size_msf, 1); | |||
1464 | /* | |||
1465 | * Pre-gap has index number of 0, and decreasing MSF | |||
1466 | * address. Must be converted to negative LBA, per | |||
1467 | * SCSI spec. | |||
1468 | */ | |||
1469 | if (data.what.position.index_number == 0) | |||
1470 | lba = -lba; | |||
1471 | data.what.position.reladdr.lba = htonl(lba)(__builtin_constant_p(lba) ? (((__uint32_t)((__uint16_t)(__builtin_constant_p (((__uint32_t)(lba)) & 0xffff) ? (__uint16_t)(((__uint16_t )(((__uint32_t)(lba)) & 0xffff)) << 8 | ((__uint16_t )(((__uint32_t)(lba)) & 0xffff)) >> 8) : __bswap16_var (((__uint32_t)(lba)) & 0xffff))) << 16) | ((__uint16_t )(__builtin_constant_p(((__uint32_t)(lba)) >> 16) ? (__uint16_t )(((__uint16_t)(((__uint32_t)(lba)) >> 16)) << 8 | ((__uint16_t)(((__uint32_t)(lba)) >> 16)) >> 8) : __bswap16_var(((__uint32_t)(lba)) >> 16)))) : __bswap32_var (lba)); | |||
1472 | data.what.position.absaddr.lba = htonl(msf2hsg(q.hd_pos_msf, 0))(__builtin_constant_p(msf2hsg(q.hd_pos_msf, 0)) ? (((__uint32_t )((__uint16_t)(__builtin_constant_p(((__uint32_t)(msf2hsg(q.hd_pos_msf , 0))) & 0xffff) ? (__uint16_t)(((__uint16_t)(((__uint32_t )(msf2hsg(q.hd_pos_msf, 0))) & 0xffff)) << 8 | ((__uint16_t )(((__uint32_t)(msf2hsg(q.hd_pos_msf, 0))) & 0xffff)) >> 8) : __bswap16_var(((__uint32_t)(msf2hsg(q.hd_pos_msf, 0))) & 0xffff))) << 16) | ((__uint16_t)(__builtin_constant_p( ((__uint32_t)(msf2hsg(q.hd_pos_msf, 0))) >> 16) ? (__uint16_t )(((__uint16_t)(((__uint32_t)(msf2hsg(q.hd_pos_msf, 0))) >> 16)) << 8 | ((__uint16_t)(((__uint32_t)(msf2hsg(q.hd_pos_msf , 0))) >> 16)) >> 8) : __bswap16_var(((__uint32_t )(msf2hsg(q.hd_pos_msf, 0))) >> 16)))) : __bswap32_var( msf2hsg(q.hd_pos_msf, 0))); | |||
1473 | break; | |||
1474 | } | |||
1475 | break; | |||
1476 | } | |||
1477 | ||||
1478 | MCD_UNLOCK(sc)__mtx_unlock_flags(&((((&sc->mtx))))->mtx_lock, ((0)), ("/usr/src/sys/modules/mcd/../../dev/mcd/mcd.c"), (1478 )); | |||
1479 | if (nocopyout == 0) | |||
1480 | return copyout(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len)); | |||
1481 | bcopy(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len)); | |||
1482 | return (0); | |||
1483 | } | |||
1484 | ||||
1485 | static int | |||
1486 | mcd_playmsf(struct mcd_softc *sc, struct ioc_play_msf *p) | |||
1487 | { | |||
1488 | struct mcd_read2 pb; | |||
1489 | ||||
1490 | if (sc->data.debug) | |||
1491 | device_printf(sc->dev, "playmsf: from %d:%d.%d to %d:%d.%d\n", | |||
1492 | p->start_m, p->start_s, p->start_f, | |||
1493 | p->end_m, p->end_s, p->end_f); | |||
1494 | ||||
1495 | if ((p->start_m * 60 * 75 + p->start_s * 75 + p->start_f) >= | |||
1496 | (p->end_m * 60 * 75 + p->end_s * 75 + p->end_f) || | |||
1497 | (p->end_m * 60 * 75 + p->end_s * 75 + p->end_f) > | |||
1498 | M_msf(sc->data.volinfo.vol_msf)sc->data.volinfo.vol_msf[0] * 60 * 75 + | |||
1499 | S_msf(sc->data.volinfo.vol_msf)sc->data.volinfo.vol_msf[1] * 75 + | |||
1500 | F_msf(sc->data.volinfo.vol_msf)sc->data.volinfo.vol_msf[2]) | |||
1501 | return (EINVAL22); | |||
1502 | ||||
1503 | pb.start_msf[0] = bin2bcd(p->start_m)(bin2bcd_data[p->start_m]); | |||
1504 | pb.start_msf[1] = bin2bcd(p->start_s)(bin2bcd_data[p->start_s]); | |||
1505 | pb.start_msf[2] = bin2bcd(p->start_f)(bin2bcd_data[p->start_f]); | |||
1506 | pb.end_msf[0] = bin2bcd(p->end_m)(bin2bcd_data[p->end_m]); | |||
1507 | pb.end_msf[1] = bin2bcd(p->end_s)(bin2bcd_data[p->end_s]); | |||
1508 | pb.end_msf[2] = bin2bcd(p->end_f)(bin2bcd_data[p->end_f]); | |||
1509 | ||||
1510 | if (mcd_setmode(sc, MCD_MD_COOKED(0x01)) != 0) | |||
1511 | return (EIO5); | |||
1512 | ||||
1513 | return mcd_play(sc, &pb); | |||
1514 | } | |||
1515 | ||||
1516 | static int | |||
1517 | mcd_playtracks(struct mcd_softc *sc, struct ioc_play_track *pt) | |||
1518 | { | |||
1519 | struct mcd_read2 pb; | |||
1520 | int a = pt->start_track; | |||
1521 | int z = pt->end_track; | |||
1522 | int rc, i; | |||
1523 | ||||
1524 | if ((rc = mcd_read_toc(sc)) != 0) | |||
1525 | return (rc); | |||
1526 | ||||
1527 | if (sc->data.debug) | |||
1528 | device_printf(sc->dev, "playtracks from %d:%d to %d:%d\n", | |||
1529 | a, pt->start_index, z, pt->end_index); | |||
1530 | ||||
1531 | if ( a < bcd2bin(sc->data.volinfo.trk_low)(bcd2bin_data[sc->data.volinfo.trk_low]) | |||
1532 | || a > bcd2bin(sc->data.volinfo.trk_high)(bcd2bin_data[sc->data.volinfo.trk_high]) | |||
1533 | || a > z | |||
1534 | || z < bcd2bin(sc->data.volinfo.trk_low)(bcd2bin_data[sc->data.volinfo.trk_low]) | |||
1535 | || z > bcd2bin(sc->data.volinfo.trk_high)(bcd2bin_data[sc->data.volinfo.trk_high])) | |||
1536 | return (EINVAL22); | |||
1537 | ||||
1538 | for (i = 0; i < 3; i++) { | |||
1539 | pb.start_msf[i] = sc->data.toc[a].hd_pos_msf[i]; | |||
1540 | pb.end_msf[i] = sc->data.toc[z+1].hd_pos_msf[i]; | |||
1541 | } | |||
1542 | ||||
1543 | if (mcd_setmode(sc, MCD_MD_COOKED(0x01)) != 0) | |||
1544 | return (EIO5); | |||
1545 | ||||
1546 | return mcd_play(sc, &pb); | |||
1547 | } | |||
1548 | ||||
1549 | static int | |||
1550 | mcd_playblocks(struct mcd_softc *sc, struct ioc_play_blocks *p) | |||
1551 | { | |||
1552 | struct mcd_read2 pb; | |||
1553 | ||||
1554 | if (sc->data.debug) | |||
1555 | device_printf(sc->dev, "playblocks: blkno %d length %d\n", | |||
1556 | p->blk, p->len); | |||
1557 | ||||
1558 | if (p->blk > sc->data.disksize || p->len > sc->data.disksize || | |||
1559 | p->blk < 0 || p->len < 0 || | |||
1560 | (p->blk + p->len) > sc->data.disksize) | |||
1561 | return (EINVAL22); | |||
1562 | ||||
1563 | hsg2msf(p->blk, pb.start_msf); | |||
1564 | hsg2msf(p->blk + p->len, pb.end_msf); | |||
1565 | ||||
1566 | if (mcd_setmode(sc, MCD_MD_COOKED(0x01)) != 0) | |||
1567 | return (EIO5); | |||
1568 | ||||
1569 | return mcd_play(sc, &pb); | |||
1570 | } | |||
1571 | ||||
1572 | static int | |||
1573 | mcd_play(struct mcd_softc *sc, struct mcd_read2 *pb) | |||
1574 | { | |||
1575 | int retry, st = -1, status; | |||
1576 | ||||
1577 | sc->data.lastpb = *pb; | |||
1578 | for(retry=0; retry<MCD_RETRYS5; retry++) { | |||
1579 | ||||
1580 | critical_enter(); | |||
1581 | MCD_WRITE(sc, MCD_REG_COMMAND, MCD_CMDSINGLESPEEDREAD)bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (0xC0)); | |||
1582 | MCD_WRITE(sc, MCD_REG_COMMAND, pb->start_msf[0])bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (pb->start_msf[0])); | |||
1583 | MCD_WRITE(sc, MCD_REG_COMMAND, pb->start_msf[1])bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (pb->start_msf[1])); | |||
1584 | MCD_WRITE(sc, MCD_REG_COMMAND, pb->start_msf[2])bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (pb->start_msf[2])); | |||
1585 | MCD_WRITE(sc, MCD_REG_COMMAND, pb->end_msf[0])bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (pb->end_msf[0])); | |||
1586 | MCD_WRITE(sc, MCD_REG_COMMAND, pb->end_msf[1])bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (pb->end_msf[1])); | |||
1587 | MCD_WRITE(sc, MCD_REG_COMMAND, pb->end_msf[2])bus_space_write_1((sc->port)->r_bustag, (sc->port)-> r_bushandle, (0), (pb->end_msf[2])); | |||
1588 | critical_exit(); | |||
1589 | ||||
1590 | status=mcd_getstat(sc, 0); | |||
1591 | if (status == -1) | |||
1592 | continue; | |||
1593 | else if (status != -2) | |||
1594 | st = 0; | |||
1595 | break; | |||
1596 | } | |||
1597 | ||||
1598 | if (status == -2) { | |||
1599 | device_printf(sc->dev, "media changed\n"); | |||
1600 | return (ENXIO6); | |||
1601 | } | |||
1602 | if (sc->data.debug) | |||
1603 | device_printf(sc->dev, | |||
1604 | "mcd_play retry=%d, status=0x%02x\n", retry, status); | |||
1605 | if (st < 0) | |||
1606 | return (ENXIO6); | |||
1607 | sc->data.audio_status = CD_AS_PLAY_IN_PROGRESS0x11; | |||
1608 | return (0); | |||
1609 | } | |||
1610 | ||||
1611 | static int | |||
1612 | mcd_pause(struct mcd_softc *sc) | |||
1613 | { | |||
1614 | struct mcd_qchninfo q; | |||
1615 | int rc; | |||
1616 | ||||
1617 | /* Verify current status */ | |||
1618 | if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS0x11 && | |||
1619 | sc->data.audio_status != CD_AS_PLAY_PAUSED0x12) { | |||
1620 | if (sc->data.debug) | |||
1621 | device_printf(sc->dev, | |||
1622 | "pause attempted when not playing, audio status %d\n", | |||
1623 | sc->data.audio_status); | |||
1624 | return (EINVAL22); | |||
1625 | } | |||
1626 | ||||
1627 | /* Get the current position */ | |||
1628 | if (mcd_getqchan(sc, &q) < 0) | |||
1629 | return (EIO5); | |||
1630 | ||||
1631 | /* Copy it into lastpb */ | |||
1632 | sc->data.lastpb.start_msf[0] = q.hd_pos_msf[0]; | |||
1633 | sc->data.lastpb.start_msf[1] = q.hd_pos_msf[1]; | |||
1634 | sc->data.lastpb.start_msf[2] = q.hd_pos_msf[2]; | |||
1635 | ||||
1636 | /* Stop playing */ | |||
1637 | if ((rc=mcd_stop(sc)) != 0) | |||
1638 | return (rc); | |||
1639 | ||||
1640 | /* Set the proper status and exit */ | |||
1641 | sc->data.audio_status = CD_AS_PLAY_PAUSED0x12; | |||
1642 | return (0); | |||
1643 | } | |||
1644 | ||||
1645 | static int | |||
1646 | mcd_resume(struct mcd_softc *sc) | |||
1647 | { | |||
1648 | ||||
1649 | if (sc->data.audio_status != CD_AS_PLAY_PAUSED0x12) | |||
1650 | return (EINVAL22); | |||
1651 | return mcd_play(sc, &sc->data.lastpb); | |||
1652 | } |