| File: | modules/mcd/../../dev/mcd/mcd.c |
| Warning: | line 1480, column 10 Copies out a struct with a union element with different sizes |
| 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 | } |