1 1.42 christos /* $NetBSD: gdrom.c,v 1.42 2016/03/13 17:59:20 christos Exp $ */ 2 1.1 marcus 3 1.1 marcus /*- 4 1.1 marcus * Copyright (c) 2001 Marcus Comstedt 5 1.1 marcus * All rights reserved. 6 1.1 marcus * 7 1.1 marcus * Redistribution and use in source and binary forms, with or without 8 1.1 marcus * modification, are permitted provided that the following conditions 9 1.1 marcus * are met: 10 1.1 marcus * 1. Redistributions of source code must retain the above copyright 11 1.1 marcus * notice, this list of conditions and the following disclaimer. 12 1.1 marcus * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 marcus * notice, this list of conditions and the following disclaimer in the 14 1.1 marcus * documentation and/or other materials provided with the distribution. 15 1.1 marcus * 3. All advertising materials mentioning features or use of this software 16 1.1 marcus * must display the following acknowledgement: 17 1.1 marcus * This product includes software developed by Marcus Comstedt. 18 1.1 marcus * 4. Neither the name of The NetBSD Foundation nor the names of its 19 1.1 marcus * contributors may be used to endorse or promote products derived 20 1.1 marcus * from this software without specific prior written permission. 21 1.1 marcus * 22 1.1 marcus * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 1.1 marcus * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 1.1 marcus * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 1.1 marcus * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 1.1 marcus * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 1.1 marcus * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 1.1 marcus * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 1.1 marcus * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 1.1 marcus * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 1.1 marcus * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 1.1 marcus * POSSIBILITY OF SUCH DAMAGE. 33 1.1 marcus */ 34 1.1 marcus 35 1.1 marcus #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 36 1.42 christos __KERNEL_RCSID(0, "$NetBSD: gdrom.c,v 1.42 2016/03/13 17:59:20 christos Exp $"); 37 1.1 marcus 38 1.1 marcus #include <sys/param.h> 39 1.1 marcus #include <sys/systm.h> 40 1.1 marcus #include <sys/device.h> 41 1.1 marcus 42 1.1 marcus #include <sys/buf.h> 43 1.30 tsutsui #include <sys/bufq.h> 44 1.1 marcus #include <sys/ioctl.h> 45 1.1 marcus #include <sys/fcntl.h> 46 1.1 marcus #include <sys/disklabel.h> 47 1.1 marcus #include <sys/disk.h> 48 1.2 marcus #include <sys/cdio.h> 49 1.3 marcus #include <sys/proc.h> 50 1.10 gehenna #include <sys/conf.h> 51 1.1 marcus 52 1.4 marcus #include <machine/sysasicvar.h> 53 1.1 marcus 54 1.28 tsutsui #include "ioconf.h" 55 1.28 tsutsui 56 1.33 tsutsui static int gdrommatch(device_t, cfdata_t, void *); 57 1.33 tsutsui static void gdromattach(device_t, device_t, void *); 58 1.10 gehenna 59 1.10 gehenna dev_type_open(gdromopen); 60 1.10 gehenna dev_type_close(gdromclose); 61 1.10 gehenna dev_type_read(gdromread); 62 1.10 gehenna dev_type_write(gdromwrite); 63 1.10 gehenna dev_type_ioctl(gdromioctl); 64 1.10 gehenna dev_type_strategy(gdromstrategy); 65 1.10 gehenna 66 1.10 gehenna const struct bdevsw gdrom_bdevsw = { 67 1.37 dholland .d_open = gdromopen, 68 1.37 dholland .d_close = gdromclose, 69 1.38 martin .d_strategy = gdromstrategy, 70 1.37 dholland .d_ioctl = gdromioctl, 71 1.37 dholland .d_dump = nodump, 72 1.37 dholland .d_psize = nosize, 73 1.39 dholland .d_discard = nodiscard, 74 1.37 dholland .d_flag = D_DISK 75 1.10 gehenna }; 76 1.10 gehenna 77 1.10 gehenna const struct cdevsw gdrom_cdevsw = { 78 1.37 dholland .d_open = gdromopen, 79 1.37 dholland .d_close = gdromclose, 80 1.37 dholland .d_read = gdromread, 81 1.37 dholland .d_write = gdromwrite, 82 1.37 dholland .d_ioctl = gdromioctl, 83 1.37 dholland .d_stop = nostop, 84 1.37 dholland .d_tty = notty, 85 1.37 dholland .d_poll = nopoll, 86 1.37 dholland .d_mmap = nommap, 87 1.37 dholland .d_kqfilter = nokqfilter, 88 1.40 dholland .d_discard = nodiscard, 89 1.37 dholland .d_flag = D_DISK 90 1.10 gehenna }; 91 1.1 marcus 92 1.1 marcus struct gdrom_softc { 93 1.28 tsutsui device_t sc_dev; /* generic device info */ 94 1.30 tsutsui struct disk sc_dk; /* generic disk info */ 95 1.30 tsutsui struct bufq_state *sc_bufq; /* device buffer queue */ 96 1.1 marcus struct buf curbuf; /* state of current I/O operation */ 97 1.1 marcus 98 1.32 tsutsui bool is_open; 99 1.32 tsutsui bool is_busy; 100 1.30 tsutsui bool is_active; 101 1.1 marcus int openpart_start; /* start sector of currently open partition */ 102 1.3 marcus 103 1.3 marcus int cmd_active; 104 1.3 marcus void *cmd_result_buf; /* where to store result data (16 bit aligned) */ 105 1.3 marcus int cmd_result_size; /* number of bytes allocated for buf */ 106 1.3 marcus int cmd_actual; /* number of bytes actually read */ 107 1.3 marcus int cmd_cond; /* resulting condition of command */ 108 1.1 marcus }; 109 1.1 marcus 110 1.28 tsutsui CFATTACH_DECL_NEW(gdrom, sizeof(struct gdrom_softc), 111 1.13 thorpej gdrommatch, gdromattach, NULL, NULL); 112 1.1 marcus 113 1.41 mlelstv struct dkdriver gdromdkdriver = { 114 1.41 mlelstv .d_strategy = gdromstrategy 115 1.41 mlelstv }; 116 1.1 marcus 117 1.1 marcus 118 1.1 marcus struct gd_toc { 119 1.8 uch unsigned int entry[99]; 120 1.8 uch unsigned int first, last; 121 1.8 uch unsigned int leadout; 122 1.1 marcus }; 123 1.1 marcus 124 1.34 tsutsui #ifdef GDROMDEBUG 125 1.34 tsutsui #define DPRINTF(x) printf x 126 1.34 tsutsui #else 127 1.34 tsutsui #define DPRINTF(x) /**/ 128 1.34 tsutsui #endif 129 1.34 tsutsui 130 1.8 uch #define TOC_LBA(n) ((n) & 0xffffff00) 131 1.8 uch #define TOC_ADR(n) ((n) & 0x0f) 132 1.8 uch #define TOC_CTRL(n) (((n) & 0xf0) >> 4) 133 1.8 uch #define TOC_TRACK(n) (((n) & 0x0000ff00) >> 8) 134 1.8 uch 135 1.42 christos #define GDROM(o) (*(volatile uint8_t *)(0xa05f7000U + (o))) 136 1.8 uch 137 1.8 uch #define GDSTATSTAT(n) ((n) & 0xf) 138 1.8 uch #define GDSTATDISK(n) (((n) >> 4) & 0xf) 139 1.8 uch 140 1.8 uch #define GDROM_BUSY GDROM(0x18) 141 1.32 tsutsui #define GDROM_DATA (*(volatile uint16_t *)(&GDROM(0x80))) 142 1.8 uch #define GDROM_REGX GDROM(0x84) 143 1.8 uch #define GDROM_STAT GDROM(0x8c) 144 1.8 uch #define GDROM_CNTLO GDROM(0x90) 145 1.8 uch #define GDROM_CNTHI GDROM(0x94) 146 1.8 uch #define GDROM_COND GDROM(0x9c) 147 1.8 uch 148 1.33 tsutsui #if 0 149 1.33 tsutsui static int gdrom_getstat(void); 150 1.33 tsutsui #endif 151 1.33 tsutsui static int gdrom_do_command(struct gdrom_softc *, void *, void *, 152 1.33 tsutsui unsigned int, int *); 153 1.33 tsutsui static int gdrom_command_sense(struct gdrom_softc *, void *, void *, 154 1.33 tsutsui unsigned int, int *); 155 1.33 tsutsui static int gdrom_read_toc(struct gdrom_softc *, struct gd_toc *); 156 1.33 tsutsui static int gdrom_read_sectors(struct gdrom_softc *, void *, int, int, 157 1.33 tsutsui int *); 158 1.33 tsutsui static int gdrom_mount_disk(struct gdrom_softc *); 159 1.33 tsutsui static int gdrom_intr(void *); 160 1.33 tsutsui static void gdrom_start(struct gdrom_softc *); 161 1.1 marcus 162 1.33 tsutsui #if 0 163 1.33 tsutsui int 164 1.33 tsutsui gdrom_getstat(void) 165 1.1 marcus { 166 1.32 tsutsui uint8_t s1, s2, s3; 167 1.1 marcus 168 1.8 uch if (GDROM_BUSY & 0x80) 169 1.17 tsutsui return -1; 170 1.1 marcus s1 = GDROM_STAT; 171 1.1 marcus s2 = GDROM_STAT; 172 1.1 marcus s3 = GDROM_STAT; 173 1.17 tsutsui if (GDROM_BUSY & 0x80) 174 1.17 tsutsui return -1; 175 1.17 tsutsui if (s1 == s2) 176 1.17 tsutsui return s1; 177 1.17 tsutsui else if (s2 == s3) 178 1.17 tsutsui return s2; 179 1.1 marcus else 180 1.17 tsutsui return -1; 181 1.1 marcus } 182 1.33 tsutsui #endif 183 1.1 marcus 184 1.3 marcus int 185 1.8 uch gdrom_intr(void *arg) 186 1.1 marcus { 187 1.3 marcus struct gdrom_softc *sc = arg; 188 1.32 tsutsui int s; 189 1.32 tsutsui uint8_t cond; 190 1.3 marcus 191 1.3 marcus s = splbio(); 192 1.3 marcus cond = GDROM_COND; 193 1.34 tsutsui DPRINTF(("GDROM: cond = %x\n", cond)); 194 1.17 tsutsui if (!sc->cmd_active) { 195 1.34 tsutsui DPRINTF(("GDROM: inactive IRQ!?\n")); 196 1.8 uch splx(s); 197 1.17 tsutsui return 0; 198 1.3 marcus } 199 1.3 marcus 200 1.34 tsutsui if ((cond & 0x08) != 0) { 201 1.8 uch int cnt = (GDROM_CNTHI << 8) | GDROM_CNTLO; 202 1.34 tsutsui DPRINTF(("GDROM: cnt = %d\n", cnt)); 203 1.3 marcus sc->cmd_actual += cnt; 204 1.17 tsutsui if (cnt > 0 && sc->cmd_result_size > 0) { 205 1.8 uch int subcnt = (cnt > sc->cmd_result_size ? 206 1.8 uch sc->cmd_result_size : cnt); 207 1.32 tsutsui uint16_t *ptr = sc->cmd_result_buf; 208 1.32 tsutsui sc->cmd_result_buf = ((uint8_t *)sc->cmd_result_buf) + 209 1.8 uch subcnt; 210 1.3 marcus sc->cmd_result_size -= subcnt; 211 1.3 marcus cnt -= subcnt; 212 1.8 uch while (subcnt > 0) { 213 1.8 uch *ptr++ = GDROM_DATA; 214 1.8 uch subcnt -= 2; 215 1.3 marcus } 216 1.3 marcus } 217 1.8 uch while (cnt > 0) { 218 1.32 tsutsui (void)GDROM_DATA; 219 1.8 uch cnt -= 2; 220 1.3 marcus } 221 1.3 marcus } 222 1.34 tsutsui while ((GDROM_BUSY & 0x80) != 0); 223 1.3 marcus 224 1.34 tsutsui if ((cond & 0x08) == 0) { 225 1.3 marcus sc->cmd_cond = cond; 226 1.3 marcus sc->cmd_active = 0; 227 1.3 marcus wakeup(&sc->cmd_active); 228 1.3 marcus } 229 1.1 marcus 230 1.3 marcus splx(s); 231 1.17 tsutsui return 1; 232 1.1 marcus } 233 1.1 marcus 234 1.3 marcus 235 1.34 tsutsui int 236 1.34 tsutsui gdrom_do_command(struct gdrom_softc *sc, void *req, void *buf, 237 1.27 tsutsui unsigned int nbyt, int *resid) 238 1.1 marcus { 239 1.3 marcus int i, s; 240 1.32 tsutsui uint16_t *ptr = req; 241 1.3 marcus 242 1.8 uch while (GDROM_BUSY & 0x88) 243 1.8 uch ; 244 1.8 uch if (buf != NULL) { 245 1.8 uch GDROM_CNTLO = nbyt & 0xff; 246 1.8 uch GDROM_CNTHI = (nbyt >> 8) & 0xff; 247 1.8 uch GDROM_REGX = 0; 248 1.3 marcus } 249 1.3 marcus sc->cmd_result_buf = buf; 250 1.3 marcus sc->cmd_result_size = nbyt; 251 1.1 marcus 252 1.34 tsutsui if (GDSTATSTAT(GDROM_STAT) == 0x06) 253 1.17 tsutsui return -1; 254 1.1 marcus 255 1.1 marcus GDROM_COND = 0xa0; 256 1.31 tsutsui DELAY(1); 257 1.34 tsutsui while ((GDROM_BUSY & 0x88) != 0x08) 258 1.8 uch ; 259 1.3 marcus 260 1.3 marcus s = splbio(); 261 1.3 marcus 262 1.3 marcus sc->cmd_actual = 0; 263 1.3 marcus sc->cmd_active = 1; 264 1.3 marcus 265 1.34 tsutsui for (i = 0; i < 6; i++) 266 1.8 uch GDROM_DATA = ptr[i]; 267 1.1 marcus 268 1.8 uch while (sc->cmd_active) 269 1.8 uch tsleep(&sc->cmd_active, PRIBIO, "gdrom", 0); 270 1.3 marcus 271 1.3 marcus splx(s); 272 1.3 marcus 273 1.27 tsutsui if (resid != NULL) 274 1.27 tsutsui *resid = sc->cmd_result_size; 275 1.27 tsutsui 276 1.17 tsutsui return sc->cmd_cond; 277 1.1 marcus } 278 1.1 marcus 279 1.3 marcus 280 1.8 uch int gdrom_command_sense(struct gdrom_softc *sc, void *req, void *buf, 281 1.27 tsutsui unsigned int nbyt, int *resid) 282 1.1 marcus { 283 1.34 tsutsui /* 284 1.34 tsutsui * 76543210 76543210 285 1.34 tsutsui * 0 0x13 - 286 1.34 tsutsui * 2 - bufsz(hi) 287 1.34 tsutsui * 4 bufsz(lo) - 288 1.34 tsutsui * 6 - - 289 1.34 tsutsui * 8 - - 290 1.34 tsutsui * 10 - - 291 1.34 tsutsui */ 292 1.32 tsutsui uint16_t sense_data[5]; 293 1.32 tsutsui uint8_t cmd[12]; 294 1.34 tsutsui int cond, sense_key, sense_specific; 295 1.1 marcus 296 1.34 tsutsui cond = gdrom_do_command(sc, req, buf, nbyt, resid); 297 1.3 marcus 298 1.8 uch if (cond < 0) { 299 1.34 tsutsui DPRINTF(("GDROM: not ready (2:58)\n")); 300 1.17 tsutsui return EIO; 301 1.1 marcus } 302 1.1 marcus 303 1.8 uch if ((cond & 1) == 0) { 304 1.34 tsutsui DPRINTF(("GDROM: no sense. 0:0\n")); 305 1.17 tsutsui return 0; 306 1.1 marcus } 307 1.1 marcus 308 1.5 wiz memset(cmd, 0, sizeof(cmd)); 309 1.1 marcus 310 1.1 marcus cmd[0] = 0x13; 311 1.1 marcus cmd[4] = sizeof(sense_data); 312 1.1 marcus 313 1.27 tsutsui gdrom_do_command(sc, cmd, sense_data, sizeof(sense_data), NULL); 314 1.1 marcus 315 1.1 marcus sense_key = sense_data[1] & 0xf; 316 1.1 marcus sense_specific = sense_data[4]; 317 1.8 uch if (sense_key == 11 && sense_specific == 0) { 318 1.34 tsutsui DPRINTF(("GDROM: aborted (ignored). 0:0\n")); 319 1.17 tsutsui return 0; 320 1.1 marcus } 321 1.1 marcus 322 1.34 tsutsui DPRINTF(("GDROM: SENSE %d:", sense_key)); 323 1.34 tsutsui DPRINTF(("GDROM: %d\n", sense_specific)); 324 1.1 marcus 325 1.17 tsutsui return sense_key == 0 ? 0 : EIO; 326 1.1 marcus } 327 1.1 marcus 328 1.8 uch int gdrom_read_toc(struct gdrom_softc *sc, struct gd_toc *toc) 329 1.1 marcus { 330 1.34 tsutsui /* 331 1.34 tsutsui * 76543210 76543210 332 1.34 tsutsui * 0 0x14 - 333 1.34 tsutsui * 2 - bufsz(hi) 334 1.34 tsutsui * 4 bufsz(lo) - 335 1.34 tsutsui * 6 - - 336 1.34 tsutsui * 8 - - 337 1.34 tsutsui * 10 - - 338 1.34 tsutsui */ 339 1.32 tsutsui uint8_t cmd[12]; 340 1.1 marcus 341 1.5 wiz memset(cmd, 0, sizeof(cmd)); 342 1.1 marcus 343 1.1 marcus cmd[0] = 0x14; 344 1.8 uch cmd[3] = sizeof(struct gd_toc) >> 8; 345 1.8 uch cmd[4] = sizeof(struct gd_toc) & 0xff; 346 1.1 marcus 347 1.27 tsutsui return gdrom_command_sense(sc, cmd, toc, sizeof(struct gd_toc), NULL); 348 1.1 marcus } 349 1.1 marcus 350 1.27 tsutsui int gdrom_read_sectors(struct gdrom_softc *sc, void *buf, int sector, int cnt, 351 1.27 tsutsui int *resid) 352 1.1 marcus { 353 1.34 tsutsui /* 354 1.34 tsutsui * 76543210 76543210 355 1.34 tsutsui * 0 0x30 datafmt 356 1.34 tsutsui * 2 sec(hi) sec(mid) 357 1.34 tsutsui * 4 sec(lo) - 358 1.34 tsutsui * 6 - - 359 1.34 tsutsui * 8 cnt(hi) cnt(mid) 360 1.34 tsutsui * 10 cnt(lo) - 361 1.34 tsutsui */ 362 1.32 tsutsui uint8_t cmd[12]; 363 1.1 marcus 364 1.5 wiz memset(cmd, 0, sizeof(cmd)); 365 1.1 marcus 366 1.34 tsutsui cmd[0] = 0x30; 367 1.34 tsutsui cmd[1] = 0x20; 368 1.34 tsutsui cmd[2] = sector >> 16; 369 1.34 tsutsui cmd[3] = sector >> 8; 370 1.34 tsutsui cmd[4] = sector; 371 1.34 tsutsui cmd[8] = cnt >> 16; 372 1.34 tsutsui cmd[9] = cnt >> 8; 373 1.1 marcus cmd[10] = cnt; 374 1.1 marcus 375 1.27 tsutsui return gdrom_command_sense(sc, cmd, buf, cnt << 11, resid); 376 1.1 marcus } 377 1.1 marcus 378 1.8 uch int gdrom_mount_disk(struct gdrom_softc *sc) 379 1.1 marcus { 380 1.34 tsutsui /* 381 1.34 tsutsui * 76543210 76543210 382 1.34 tsutsui * 0 0x70 - 383 1.34 tsutsui * 2 0x1f - 384 1.34 tsutsui * 4 - - 385 1.34 tsutsui * 6 - - 386 1.34 tsutsui * 8 - - 387 1.34 tsutsui * 10 - - 388 1.34 tsutsui */ 389 1.32 tsutsui uint8_t cmd[12]; 390 1.1 marcus 391 1.5 wiz memset(cmd, 0, sizeof(cmd)); 392 1.1 marcus 393 1.1 marcus cmd[0] = 0x70; 394 1.1 marcus cmd[1] = 0x1f; 395 1.1 marcus 396 1.27 tsutsui return gdrom_command_sense(sc, cmd, NULL, 0, NULL); 397 1.1 marcus } 398 1.1 marcus 399 1.1 marcus int 400 1.28 tsutsui gdrommatch(device_t parent, cfdata_t cf, void *aux) 401 1.1 marcus { 402 1.1 marcus static int gdrom_matched = 0; 403 1.1 marcus 404 1.1 marcus /* Allow only once instance. */ 405 1.11 thorpej if (gdrom_matched) 406 1.17 tsutsui return 0; 407 1.1 marcus gdrom_matched = 1; 408 1.7 uch 409 1.17 tsutsui return 1; 410 1.1 marcus } 411 1.1 marcus 412 1.1 marcus void 413 1.28 tsutsui gdromattach(device_t parent, device_t self, void *aux) 414 1.1 marcus { 415 1.1 marcus struct gdrom_softc *sc; 416 1.36 martin uint32_t p; 417 1.1 marcus 418 1.28 tsutsui sc = device_private(self); 419 1.28 tsutsui sc->sc_dev = self; 420 1.1 marcus 421 1.30 tsutsui bufq_alloc(&sc->sc_bufq, "disksort", BUFQ_SORT_RAWBLOCK); 422 1.30 tsutsui 423 1.1 marcus /* 424 1.1 marcus * Initialize and attach the disk structure. 425 1.1 marcus */ 426 1.30 tsutsui disk_init(&sc->sc_dk, device_xname(self), &gdromdkdriver); 427 1.30 tsutsui disk_attach(&sc->sc_dk); 428 1.1 marcus 429 1.1 marcus /* 430 1.1 marcus * reenable disabled drive 431 1.1 marcus */ 432 1.19 perry *((volatile uint32_t *)0xa05f74e4) = 0x1fffff; 433 1.8 uch for (p = 0; p < 0x200000 / 4; p++) 434 1.36 martin (void)((volatile uint32_t *)0xa0000000)[p]; 435 1.1 marcus 436 1.26 marcus printf(": %s\n", sysasic_intr_string(SYSASIC_IRL9)); 437 1.21 tsutsui sysasic_intr_establish(SYSASIC_EVENT_GDROM, IPL_BIO, SYSASIC_IRL9, 438 1.21 tsutsui gdrom_intr, sc); 439 1.1 marcus } 440 1.1 marcus 441 1.1 marcus int 442 1.18 christos gdromopen(dev_t dev, int flags, int devtype, struct lwp *l) 443 1.1 marcus { 444 1.1 marcus struct gdrom_softc *sc; 445 1.3 marcus int s, error, unit, cnt; 446 1.1 marcus struct gd_toc toc; 447 1.1 marcus 448 1.34 tsutsui DPRINTF(("GDROM: open\n")); 449 1.1 marcus 450 1.1 marcus unit = DISKUNIT(dev); 451 1.1 marcus 452 1.25 tsutsui sc = device_lookup_private(&gdrom_cd, unit); 453 1.1 marcus if (sc == NULL) 454 1.17 tsutsui return ENXIO; 455 1.1 marcus 456 1.1 marcus if (sc->is_open) 457 1.17 tsutsui return EBUSY; 458 1.1 marcus 459 1.3 marcus s = splbio(); 460 1.17 tsutsui while (sc->is_busy) 461 1.8 uch tsleep(&sc->is_busy, PRIBIO, "gdbusy", 0); 462 1.32 tsutsui sc->is_busy = true; 463 1.3 marcus splx(s); 464 1.3 marcus 465 1.1 marcus for (cnt = 0; cnt < 5; cnt++) 466 1.8 uch if ((error = gdrom_mount_disk(sc)) == 0) 467 1.8 uch break; 468 1.1 marcus 469 1.34 tsutsui if (error == 0) 470 1.3 marcus error = gdrom_read_toc(sc, &toc); 471 1.3 marcus 472 1.32 tsutsui sc->is_busy = false; 473 1.3 marcus wakeup(&sc->is_busy); 474 1.3 marcus 475 1.34 tsutsui if (error != 0) 476 1.1 marcus return error; 477 1.1 marcus 478 1.32 tsutsui sc->is_open = true; 479 1.2 marcus sc->openpart_start = 150; 480 1.1 marcus 481 1.34 tsutsui DPRINTF(("GDROM: open OK\n")); 482 1.17 tsutsui return 0; 483 1.1 marcus } 484 1.1 marcus 485 1.1 marcus int 486 1.18 christos gdromclose(dev_t dev, int flags, int devtype, struct lwp *l) 487 1.1 marcus { 488 1.1 marcus struct gdrom_softc *sc; 489 1.1 marcus int unit; 490 1.34 tsutsui 491 1.34 tsutsui DPRINTF(("GDROM: close\n")); 492 1.34 tsutsui 493 1.1 marcus unit = DISKUNIT(dev); 494 1.25 tsutsui sc = device_lookup_private(&gdrom_cd, unit); 495 1.1 marcus 496 1.32 tsutsui sc->is_open = false; 497 1.1 marcus 498 1.17 tsutsui return 0; 499 1.1 marcus } 500 1.1 marcus 501 1.1 marcus void 502 1.8 uch gdromstrategy(struct buf *bp) 503 1.1 marcus { 504 1.1 marcus struct gdrom_softc *sc; 505 1.30 tsutsui int s, unit; 506 1.34 tsutsui 507 1.34 tsutsui DPRINTF(("GDROM: strategy\n")); 508 1.1 marcus 509 1.1 marcus unit = DISKUNIT(bp->b_dev); 510 1.25 tsutsui sc = device_lookup_private(&gdrom_cd, unit); 511 1.1 marcus 512 1.1 marcus if (bp->b_bcount == 0) 513 1.8 uch goto done; 514 1.1 marcus 515 1.1 marcus bp->b_rawblkno = bp->b_blkno / (2048 / DEV_BSIZE) + sc->openpart_start; 516 1.1 marcus 517 1.34 tsutsui DPRINTF(("GDROM: read_sectors(%p, %lld, %d) [%d bytes]\n", 518 1.8 uch bp->b_data, bp->b_rawblkno, 519 1.34 tsutsui bp->b_bcount >> 11, bp->b_bcount)); 520 1.34 tsutsui 521 1.3 marcus s = splbio(); 522 1.30 tsutsui bufq_put(sc->sc_bufq, bp); 523 1.3 marcus splx(s); 524 1.30 tsutsui if (!sc->is_active) 525 1.30 tsutsui gdrom_start(sc); 526 1.27 tsutsui return; 527 1.3 marcus 528 1.8 uch done: 529 1.1 marcus bp->b_resid = bp->b_bcount; 530 1.1 marcus biodone(bp); 531 1.1 marcus } 532 1.1 marcus 533 1.30 tsutsui void 534 1.30 tsutsui gdrom_start(struct gdrom_softc *sc) 535 1.30 tsutsui { 536 1.30 tsutsui struct buf *bp; 537 1.30 tsutsui int error, resid, s; 538 1.30 tsutsui 539 1.30 tsutsui sc->is_active = true; 540 1.30 tsutsui 541 1.30 tsutsui for (;;) { 542 1.30 tsutsui s = splbio(); 543 1.30 tsutsui bp = bufq_get(sc->sc_bufq); 544 1.30 tsutsui if (bp == NULL) { 545 1.30 tsutsui splx(s); 546 1.30 tsutsui break; 547 1.30 tsutsui } 548 1.30 tsutsui 549 1.30 tsutsui while (sc->is_busy) 550 1.30 tsutsui tsleep(&sc->is_busy, PRIBIO, "gdbusy", 0); 551 1.32 tsutsui sc->is_busy = true; 552 1.30 tsutsui disk_busy(&sc->sc_dk); 553 1.30 tsutsui splx(s); 554 1.30 tsutsui 555 1.30 tsutsui error = gdrom_read_sectors(sc, bp->b_data, bp->b_rawblkno, 556 1.30 tsutsui bp->b_bcount >> 11, &resid); 557 1.30 tsutsui bp->b_error = error; 558 1.30 tsutsui bp->b_resid = resid; 559 1.30 tsutsui if (error != 0) 560 1.30 tsutsui bp->b_resid = bp->b_bcount; 561 1.30 tsutsui 562 1.32 tsutsui sc->is_busy = false; 563 1.30 tsutsui wakeup(&sc->is_busy); 564 1.30 tsutsui 565 1.30 tsutsui s = splbio(); 566 1.30 tsutsui disk_unbusy(&sc->sc_dk, bp->b_bcount - bp->b_resid, 567 1.30 tsutsui (bp->b_flags & B_READ) != 0); 568 1.30 tsutsui splx(s); 569 1.30 tsutsui biodone(bp); 570 1.30 tsutsui } 571 1.30 tsutsui 572 1.30 tsutsui sc->is_active = false; 573 1.30 tsutsui } 574 1.30 tsutsui 575 1.1 marcus int 576 1.20 christos gdromioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 577 1.1 marcus { 578 1.2 marcus struct gdrom_softc *sc; 579 1.2 marcus int unit, error; 580 1.34 tsutsui 581 1.34 tsutsui DPRINTF(("GDROM: ioctl %lx\n", cmd)); 582 1.2 marcus 583 1.2 marcus unit = DISKUNIT(dev); 584 1.25 tsutsui sc = device_lookup_private(&gdrom_cd, unit); 585 1.2 marcus 586 1.2 marcus switch (cmd) { 587 1.2 marcus case CDIOREADMSADDR: { 588 1.8 uch int s, track, sessno = *(int *)addr; 589 1.2 marcus struct gd_toc toc; 590 1.2 marcus 591 1.2 marcus if (sessno != 0) 592 1.17 tsutsui return EINVAL; 593 1.2 marcus 594 1.3 marcus s = splbio(); 595 1.8 uch while (sc->is_busy) 596 1.8 uch tsleep(&sc->is_busy, PRIBIO, "gdbusy", 0); 597 1.32 tsutsui sc->is_busy = true; 598 1.3 marcus splx(s); 599 1.3 marcus 600 1.3 marcus error = gdrom_read_toc(sc, &toc); 601 1.3 marcus 602 1.32 tsutsui sc->is_busy = false; 603 1.3 marcus wakeup(&sc->is_busy); 604 1.3 marcus 605 1.34 tsutsui if (error != 0) 606 1.8 uch return error; 607 1.35 abs #ifdef GDROMDEBUGTOC 608 1.35 abs { /* Dump the GDROM TOC */ 609 1.35 abs unsigned char *ptr = (unsigned char *)&toc; 610 1.35 abs int i; 611 1.35 abs 612 1.35 abs printf("gdrom: TOC\n"); 613 1.35 abs for(i = 0; i < sizeof(toc); ++i) { 614 1.35 abs printf("%02x", *ptr++); 615 1.35 abs if( i%32 == 31) 616 1.35 abs printf("\n"); 617 1.35 abs else if( i%4 == 3) 618 1.35 abs printf(","); 619 1.35 abs } 620 1.35 abs printf("\n"); 621 1.35 abs } 622 1.35 abs #endif 623 1.2 marcus for (track = TOC_TRACK(toc.last); 624 1.8 uch track >= TOC_TRACK(toc.first); 625 1.35 abs --track) { 626 1.35 abs if (track < 1 || track > 100) 627 1.35 abs return ENXIO; 628 1.34 tsutsui if (TOC_CTRL(toc.entry[track - 1])) 629 1.8 uch break; 630 1.35 abs } 631 1.2 marcus 632 1.35 abs #ifdef GDROMDEBUGTOC 633 1.35 abs printf("gdrom: Using track %d, LBA %u\n", track, 634 1.35 abs TOC_LBA(toc.entry[track - 1])); 635 1.35 abs #endif 636 1.2 marcus 637 1.34 tsutsui *(int *)addr = htonl(TOC_LBA(toc.entry[track - 1])) - 638 1.8 uch sc->openpart_start; 639 1.2 marcus 640 1.17 tsutsui return 0; 641 1.2 marcus } 642 1.8 uch default: 643 1.29 tsutsui return ENOTTY; 644 1.2 marcus } 645 1.2 marcus 646 1.2 marcus #ifdef DIAGNOSTIC 647 1.2 marcus panic("gdromioctl: impossible"); 648 1.2 marcus #endif 649 1.1 marcus } 650 1.1 marcus 651 1.1 marcus 652 1.1 marcus int 653 1.8 uch gdromread(dev_t dev, struct uio *uio, int flags) 654 1.1 marcus { 655 1.34 tsutsui 656 1.34 tsutsui DPRINTF(("GDROM: read\n")); 657 1.17 tsutsui return physio(gdromstrategy, NULL, dev, B_READ, minphys, uio); 658 1.1 marcus } 659 1.1 marcus 660 1.1 marcus int 661 1.8 uch gdromwrite(dev_t dev, struct uio *uio, int flags) 662 1.1 marcus { 663 1.8 uch 664 1.17 tsutsui return EROFS; 665 1.1 marcus } 666