1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2010 Nathan Whitehorn 5 * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer, 13 * without modification, immediately at the beginning of the file. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/module.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/ata.h> 38 #include <sys/bus.h> 39 #include <sys/conf.h> 40 #include <sys/kthread.h> 41 #include <sys/lock.h> 42 #include <sys/malloc.h> 43 #include <sys/mutex.h> 44 45 #include <vm/vm.h> 46 #include <vm/pmap.h> 47 48 #include <machine/pio.h> 49 #include <machine/bus.h> 50 #include <machine/platform.h> 51 #include <machine/resource.h> 52 #include <sys/bus.h> 53 #include <sys/rman.h> 54 55 #include <cam/cam.h> 56 #include <cam/cam_ccb.h> 57 #include <cam/cam_sim.h> 58 #include <cam/cam_xpt_sim.h> 59 #include <cam/cam_debug.h> 60 #include <cam/scsi/scsi_all.h> 61 62 #include "ps3bus.h" 63 #include "ps3-hvcall.h" 64 65 #define PS3CDROM_LOCK_INIT(_sc) \ 66 mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3cdrom", \ 67 MTX_DEF) 68 #define PS3CDROM_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 69 #define PS3CDROM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 70 #define PS3CDROM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 71 #define PS3CDROM_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); 72 #define PS3CDROM_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); 73 74 #define PS3CDROM_MAX_XFERS 3 75 76 #define LV1_STORAGE_SEND_ATAPI_COMMAND 0x01 77 78 struct ps3cdrom_softc; 79 80 struct ps3cdrom_xfer { 81 TAILQ_ENTRY(ps3cdrom_xfer) x_queue; 82 struct ps3cdrom_softc *x_sc; 83 union ccb *x_ccb; 84 bus_dmamap_t x_dmamap; 85 uint64_t x_tag; 86 }; 87 88 TAILQ_HEAD(ps3cdrom_xferq, ps3cdrom_xfer); 89 90 struct ps3cdrom_softc { 91 device_t sc_dev; 92 93 struct mtx sc_mtx; 94 95 uint64_t sc_blksize; 96 uint64_t sc_nblocks; 97 98 int sc_irqid; 99 struct resource *sc_irq; 100 void *sc_irqctx; 101 102 bus_dma_tag_t sc_dmatag; 103 104 struct cam_sim *sc_sim; 105 struct cam_path *sc_path; 106 107 struct ps3cdrom_xfer sc_xfer[PS3CDROM_MAX_XFERS]; 108 struct ps3cdrom_xferq sc_active_xferq; 109 struct ps3cdrom_xferq sc_free_xferq; 110 }; 111 112 enum lv1_ata_proto { 113 NON_DATA_PROTO = 0x00, 114 PIO_DATA_IN_PROTO = 0x01, 115 PIO_DATA_OUT_PROTO = 0x02, 116 DMA_PROTO = 0x03 117 }; 118 119 enum lv1_ata_in_out { 120 DIR_WRITE = 0x00, 121 DIR_READ = 0x01 122 }; 123 124 struct lv1_atapi_cmd { 125 uint8_t pkt[32]; 126 uint32_t pktlen; 127 uint32_t nblocks; 128 uint32_t blksize; 129 uint32_t proto; /* enum lv1_ata_proto */ 130 uint32_t in_out; /* enum lv1_ata_in_out */ 131 uint64_t buf; 132 uint32_t arglen; 133 }; 134 135 static void ps3cdrom_action(struct cam_sim *sim, union ccb *ccb); 136 static void ps3cdrom_poll(struct cam_sim *sim); 137 static void ps3cdrom_async(void *callback_arg, u_int32_t code, 138 struct cam_path* path, void *arg); 139 140 static void ps3cdrom_intr(void *arg); 141 142 static void ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, 143 int error); 144 145 static int ps3cdrom_decode_lv1_status(uint64_t status, 146 u_int8_t *sense_key, u_int8_t *asc, u_int8_t *ascq); 147 148 static int 149 ps3cdrom_probe(device_t dev) 150 { 151 if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE || 152 ps3bus_get_devtype(dev) != PS3_DEVTYPE_CDROM) 153 return (ENXIO); 154 155 device_set_desc(dev, "Playstation 3 CDROM"); 156 157 return (BUS_PROBE_SPECIFIC); 158 } 159 160 static int 161 ps3cdrom_attach(device_t dev) 162 { 163 struct ps3cdrom_softc *sc = device_get_softc(dev); 164 struct cam_devq *devq; 165 struct ps3cdrom_xfer *xp; 166 struct ccb_setasync csa; 167 int i, err; 168 169 sc->sc_dev = dev; 170 171 PS3CDROM_LOCK_INIT(sc); 172 173 /* Setup interrupt handler */ 174 175 sc->sc_irqid = 0; 176 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid, 177 RF_ACTIVE); 178 if (!sc->sc_irq) { 179 device_printf(dev, "Could not allocate IRQ\n"); 180 err = ENXIO; 181 goto fail_destroy_lock; 182 } 183 184 err = bus_setup_intr(dev, sc->sc_irq, 185 INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY, 186 NULL, ps3cdrom_intr, sc, &sc->sc_irqctx); 187 if (err) { 188 device_printf(dev, "Could not setup IRQ\n"); 189 err = ENXIO; 190 goto fail_release_intr; 191 } 192 193 /* Setup DMA */ 194 195 err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0, 196 BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 197 BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0, 198 busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag); 199 if (err) { 200 device_printf(dev, "Could not create DMA tag\n"); 201 err = ENXIO; 202 goto fail_teardown_intr; 203 } 204 205 /* Setup transfer queues */ 206 207 TAILQ_INIT(&sc->sc_active_xferq); 208 TAILQ_INIT(&sc->sc_free_xferq); 209 210 for (i = 0; i < PS3CDROM_MAX_XFERS; i++) { 211 xp = &sc->sc_xfer[i]; 212 xp->x_sc = sc; 213 214 err = bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT, 215 &xp->x_dmamap); 216 if (err) { 217 device_printf(dev, "Could not create DMA map (%d)\n", 218 err); 219 goto fail_destroy_dmamap; 220 } 221 222 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 223 } 224 225 /* Setup CAM */ 226 227 devq = cam_simq_alloc(PS3CDROM_MAX_XFERS - 1); 228 if (!devq) { 229 device_printf(dev, "Could not allocate SIM queue\n"); 230 err = ENOMEM; 231 goto fail_destroy_dmatag; 232 } 233 234 sc->sc_sim = cam_sim_alloc(ps3cdrom_action, ps3cdrom_poll, "ps3cdrom", 235 sc, device_get_unit(dev), &sc->sc_mtx, PS3CDROM_MAX_XFERS - 1, 0, 236 devq); 237 if (!sc->sc_sim) { 238 device_printf(dev, "Could not allocate SIM\n"); 239 cam_simq_free(devq); 240 err = ENOMEM; 241 goto fail_destroy_dmatag; 242 } 243 244 /* Setup XPT */ 245 246 PS3CDROM_LOCK(sc); 247 248 err = xpt_bus_register(sc->sc_sim, dev, 0); 249 if (err != CAM_SUCCESS) { 250 device_printf(dev, "Could not register XPT bus\n"); 251 err = ENXIO; 252 PS3CDROM_UNLOCK(sc); 253 goto fail_free_sim; 254 } 255 256 err = xpt_create_path(&sc->sc_path, NULL, cam_sim_path(sc->sc_sim), 257 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 258 if (err != CAM_REQ_CMP) { 259 device_printf(dev, "Could not create XPT path\n"); 260 err = ENOMEM; 261 PS3CDROM_UNLOCK(sc); 262 goto fail_unregister_xpt_bus; 263 } 264 265 memset(&csa, 0, sizeof(csa)); 266 xpt_setup_ccb(&csa.ccb_h, sc->sc_path, 5); 267 csa.ccb_h.func_code = XPT_SASYNC_CB; 268 csa.event_enable = AC_LOST_DEVICE; 269 csa.callback = ps3cdrom_async; 270 csa.callback_arg = sc->sc_sim; 271 xpt_action((union ccb *) &csa); 272 273 CAM_DEBUG(sc->sc_path, CAM_DEBUG_TRACE, 274 ("registered SIM for ps3cdrom%d\n", device_get_unit(dev))); 275 276 PS3CDROM_UNLOCK(sc); 277 278 return (BUS_PROBE_SPECIFIC); 279 280 fail_unregister_xpt_bus: 281 282 xpt_bus_deregister(cam_sim_path(sc->sc_sim)); 283 284 fail_free_sim: 285 286 cam_sim_free(sc->sc_sim, TRUE); 287 288 fail_destroy_dmamap: 289 290 while ((xp = TAILQ_FIRST(&sc->sc_free_xferq))) { 291 TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue); 292 bus_dmamap_destroy(sc->sc_dmatag, xp->x_dmamap); 293 } 294 295 fail_destroy_dmatag: 296 297 bus_dma_tag_destroy(sc->sc_dmatag); 298 299 fail_teardown_intr: 300 301 bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx); 302 303 fail_release_intr: 304 305 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq); 306 307 fail_destroy_lock: 308 309 PS3CDROM_LOCK_DESTROY(sc); 310 311 return (err); 312 } 313 314 static int 315 ps3cdrom_detach(device_t dev) 316 { 317 struct ps3cdrom_softc *sc = device_get_softc(dev); 318 int i; 319 320 xpt_async(AC_LOST_DEVICE, sc->sc_path, NULL); 321 xpt_free_path(sc->sc_path); 322 xpt_bus_deregister(cam_sim_path(sc->sc_sim)); 323 cam_sim_free(sc->sc_sim, TRUE); 324 325 for (i = 0; i < PS3CDROM_MAX_XFERS; i++) 326 bus_dmamap_destroy(sc->sc_dmatag, sc->sc_xfer[i].x_dmamap); 327 328 bus_dma_tag_destroy(sc->sc_dmatag); 329 330 bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx); 331 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq); 332 333 PS3CDROM_LOCK_DESTROY(sc); 334 335 return (0); 336 } 337 338 static void 339 ps3cdrom_action(struct cam_sim *sim, union ccb *ccb) 340 { 341 struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *)cam_sim_softc(sim); 342 device_t dev = sc->sc_dev; 343 struct ps3cdrom_xfer *xp; 344 int err; 345 346 PS3CDROM_ASSERT_LOCKED(sc); 347 348 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 349 ("function code 0x%02x\n", ccb->ccb_h.func_code)); 350 351 switch (ccb->ccb_h.func_code) { 352 case XPT_SCSI_IO: 353 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) 354 break; 355 356 if(ccb->ccb_h.target_id > 0) { 357 ccb->ccb_h.status = CAM_TID_INVALID; 358 break; 359 } 360 361 if(ccb->ccb_h.target_lun > 0) { 362 ccb->ccb_h.status = CAM_LUN_INVALID; 363 break; 364 } 365 366 xp = TAILQ_FIRST(&sc->sc_free_xferq); 367 368 KASSERT(xp != NULL, ("no free transfers")); 369 370 xp->x_ccb = ccb; 371 372 TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue); 373 374 err = bus_dmamap_load_ccb(sc->sc_dmatag, xp->x_dmamap, 375 ccb, ps3cdrom_transfer, xp, 0); 376 if (err && err != EINPROGRESS) { 377 device_printf(dev, "Could not load DMA map (%d)\n", 378 err); 379 380 xp->x_ccb = NULL; 381 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 382 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 383 break; 384 } 385 return; 386 case XPT_SET_TRAN_SETTINGS: 387 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 388 break; 389 case XPT_GET_TRAN_SETTINGS: 390 { 391 struct ccb_trans_settings *cts = &ccb->cts; 392 393 cts->protocol = PROTO_SCSI; 394 cts->protocol_version = SCSI_REV_2; 395 cts->transport = XPORT_SPI; 396 cts->transport_version = 2; 397 cts->proto_specific.valid = 0; 398 cts->xport_specific.valid = 0; 399 ccb->ccb_h.status = CAM_REQ_CMP; 400 break; 401 } 402 case XPT_RESET_BUS: 403 case XPT_RESET_DEV: 404 ccb->ccb_h.status = CAM_REQ_CMP; 405 break; 406 case XPT_CALC_GEOMETRY: 407 cam_calc_geometry(&ccb->ccg, 1); 408 break; 409 case XPT_PATH_INQ: 410 { 411 struct ccb_pathinq *cpi = &ccb->cpi; 412 413 cpi->version_num = 1; 414 cpi->hba_inquiry = 0; 415 cpi->target_sprt = 0; 416 cpi->hba_inquiry = PI_SDTR_ABLE; 417 cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN | PIM_NO_6_BYTE; 418 cpi->hba_eng_cnt = 0; 419 bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags)); 420 cpi->max_target = 0; 421 cpi->max_lun = 0; 422 cpi->initiator_id = 7; 423 cpi->bus_id = cam_sim_bus(sim); 424 cpi->unit_number = cam_sim_unit(sim); 425 cpi->base_transfer_speed = 150000; 426 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 427 strlcpy(cpi->hba_vid, "Sony", HBA_IDLEN); 428 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 429 cpi->transport = XPORT_SPI; 430 cpi->transport_version = 2; 431 cpi->protocol = PROTO_SCSI; 432 cpi->protocol_version = SCSI_REV_2; 433 cpi->maxio = PAGE_SIZE; 434 cpi->ccb_h.status = CAM_REQ_CMP; 435 break; 436 } 437 default: 438 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 439 ("unsupported function code 0x%02x\n", 440 ccb->ccb_h.func_code)); 441 ccb->ccb_h.status = CAM_REQ_INVALID; 442 break; 443 } 444 445 xpt_done(ccb); 446 } 447 448 static void 449 ps3cdrom_poll(struct cam_sim *sim) 450 { 451 ps3cdrom_intr(cam_sim_softc(sim)); 452 } 453 454 static void 455 ps3cdrom_async(void *callback_arg, u_int32_t code, 456 struct cam_path* path, void *arg) 457 { 458 switch (code) { 459 case AC_LOST_DEVICE: 460 xpt_print_path(path); 461 break; 462 default: 463 break; 464 } 465 } 466 467 static void 468 ps3cdrom_intr(void *arg) 469 { 470 struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *) arg; 471 device_t dev = sc->sc_dev; 472 uint64_t devid = ps3bus_get_device(dev); 473 struct ps3cdrom_xfer *xp; 474 union ccb *ccb; 475 u_int8_t *cdb, sense_key, asc, ascq; 476 uint64_t tag, status; 477 478 if (lv1_storage_get_async_status(devid, &tag, &status) != 0) 479 return; 480 481 PS3CDROM_LOCK(sc); 482 483 /* Find transfer with the returned tag */ 484 485 TAILQ_FOREACH(xp, &sc->sc_active_xferq, x_queue) { 486 if (xp->x_tag == tag) 487 break; 488 } 489 490 if (xp) { 491 ccb = xp->x_ccb; 492 cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ? 493 ccb->csio.cdb_io.cdb_ptr : 494 ccb->csio.cdb_io.cdb_bytes; 495 496 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 497 ("ATAPI command 0x%02x tag 0x%016lx completed (0x%016lx)\n", 498 cdb[0], tag, status)); 499 500 if (!status) { 501 ccb->csio.scsi_status = SCSI_STATUS_OK; 502 ccb->csio.resid = 0; 503 ccb->ccb_h.status = CAM_REQ_CMP; 504 } else { 505 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 506 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 507 508 if (!ps3cdrom_decode_lv1_status(status, &sense_key, 509 &asc, &ascq)) { 510 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 511 ("sense key 0x%02x asc 0x%02x ascq 0x%02x\n", 512 sense_key, asc, ascq)); 513 514 scsi_set_sense_data(&ccb->csio.sense_data, 515 /*sense_format*/ SSD_TYPE_NONE, 516 /*current_error*/ 1, 517 sense_key, 518 asc, 519 ascq, 520 SSD_ELEM_NONE); 521 ccb->csio.sense_len = SSD_FULL_SIZE; 522 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | 523 CAM_AUTOSNS_VALID; 524 } 525 526 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) 527 ccb->csio.resid = ccb->csio.dxfer_len; 528 } 529 530 if (ccb->ccb_h.flags & CAM_DIR_IN) 531 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap, 532 BUS_DMASYNC_POSTREAD); 533 534 bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap); 535 536 xp->x_ccb = NULL; 537 TAILQ_REMOVE(&sc->sc_active_xferq, xp, x_queue); 538 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 539 540 xpt_done(ccb); 541 } else { 542 device_printf(dev, 543 "Could not find transfer with tag 0x%016lx\n", tag); 544 } 545 546 PS3CDROM_UNLOCK(sc); 547 } 548 549 static void 550 ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 551 { 552 struct ps3cdrom_xfer *xp = (struct ps3cdrom_xfer *) arg; 553 struct ps3cdrom_softc *sc = xp->x_sc; 554 device_t dev = sc->sc_dev; 555 uint64_t devid = ps3bus_get_device(dev); 556 union ccb *ccb = xp->x_ccb; 557 u_int8_t *cdb; 558 uint64_t start_sector, block_count; 559 int err; 560 561 KASSERT(nsegs == 1 || nsegs == 0, 562 ("ps3cdrom_transfer: invalid number of DMA segments %d", nsegs)); 563 KASSERT(error == 0, ("ps3cdrom_transfer: DMA error %d", error)); 564 565 PS3CDROM_ASSERT_LOCKED(sc); 566 567 if (error) { 568 device_printf(dev, "Could not load DMA map (%d)\n", error); 569 570 xp->x_ccb = NULL; 571 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 572 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 573 xpt_done(ccb); 574 return; 575 } 576 577 cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ? 578 ccb->csio.cdb_io.cdb_ptr : 579 ccb->csio.cdb_io.cdb_bytes; 580 581 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 582 ("ATAPI command 0x%02x cdb_len %d dxfer_len %d\n ", cdb[0], 583 ccb->csio.cdb_len, ccb->csio.dxfer_len)); 584 585 switch (cdb[0]) { 586 case READ_10: 587 KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to read")); 588 start_sector = (cdb[2] << 24) | (cdb[3] << 16) | 589 (cdb[4] << 8) | cdb[5]; 590 block_count = (cdb[7] << 8) | cdb[8]; 591 592 err = lv1_storage_read(devid, 0 /* region id */, 593 start_sector, block_count, 0 /* flags */, segs[0].ds_addr, 594 &xp->x_tag); 595 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap, 596 BUS_DMASYNC_POSTREAD); 597 break; 598 case WRITE_10: 599 KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to write")); 600 start_sector = (cdb[2] << 24) | (cdb[3] << 16) | 601 (cdb[4] << 8) | cdb[5]; 602 block_count = (cdb[7] << 8) | cdb[8]; 603 604 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap, 605 BUS_DMASYNC_PREWRITE); 606 err = lv1_storage_write(devid, 0 /* region id */, 607 start_sector, block_count, 0 /* flags */, 608 segs[0].ds_addr, &xp->x_tag); 609 break; 610 default: 611 { 612 struct lv1_atapi_cmd atapi_cmd; 613 614 bzero(&atapi_cmd, sizeof(atapi_cmd)); 615 atapi_cmd.pktlen = 12; 616 bcopy(cdb, atapi_cmd.pkt, ccb->csio.cdb_len); 617 618 if (ccb->ccb_h.flags & CAM_DIR_IN) { 619 atapi_cmd.in_out = DIR_READ; 620 atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ? 621 DMA_PROTO : PIO_DATA_IN_PROTO; 622 } else if (ccb->ccb_h.flags & CAM_DIR_OUT) { 623 atapi_cmd.in_out = DIR_WRITE; 624 atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ? 625 DMA_PROTO : PIO_DATA_OUT_PROTO; 626 } else { 627 atapi_cmd.proto = NON_DATA_PROTO; 628 } 629 630 atapi_cmd.nblocks = atapi_cmd.arglen = 631 (nsegs == 0) ? 0 : segs[0].ds_len; 632 atapi_cmd.blksize = 1; 633 atapi_cmd.buf = (nsegs == 0) ? 0 : segs[0].ds_addr; 634 635 if (ccb->ccb_h.flags & CAM_DIR_OUT) 636 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap, 637 BUS_DMASYNC_PREWRITE); 638 639 err = lv1_storage_send_device_command(devid, 640 LV1_STORAGE_SEND_ATAPI_COMMAND, vtophys(&atapi_cmd), 641 sizeof(atapi_cmd), atapi_cmd.buf, atapi_cmd.arglen, 642 &xp->x_tag); 643 644 break; 645 } 646 } 647 648 if (err) { 649 device_printf(dev, "ATAPI command 0x%02x failed (%d)\n", 650 cdb[0], err); 651 652 bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap); 653 654 xp->x_ccb = NULL; 655 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 656 657 bzero(&ccb->csio.sense_data, sizeof(ccb->csio.sense_data)); 658 /* Invalid field in parameter list */ 659 scsi_set_sense_data(&ccb->csio.sense_data, 660 /*sense_format*/ SSD_TYPE_NONE, 661 /*current_error*/ 1, 662 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 663 /*asc*/ 0x26, 664 /*ascq*/ 0x00, 665 SSD_ELEM_NONE); 666 667 ccb->csio.sense_len = SSD_FULL_SIZE; 668 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 669 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; 670 xpt_done(ccb); 671 } else { 672 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 673 ("ATAPI command 0x%02x tag 0x%016lx submitted\n ", cdb[0], 674 xp->x_tag)); 675 676 TAILQ_INSERT_TAIL(&sc->sc_active_xferq, xp, x_queue); 677 ccb->ccb_h.status |= CAM_SIM_QUEUED; 678 } 679 } 680 681 static int 682 ps3cdrom_decode_lv1_status(uint64_t status, u_int8_t *sense_key, u_int8_t *asc, 683 u_int8_t *ascq) 684 { 685 if (((status >> 24) & 0xff) != SCSI_STATUS_CHECK_COND) 686 return -1; 687 688 *sense_key = (status >> 16) & 0xff; 689 *asc = (status >> 8) & 0xff; 690 *ascq = status & 0xff; 691 692 return (0); 693 } 694 695 static device_method_t ps3cdrom_methods[] = { 696 DEVMETHOD(device_probe, ps3cdrom_probe), 697 DEVMETHOD(device_attach, ps3cdrom_attach), 698 DEVMETHOD(device_detach, ps3cdrom_detach), 699 {0, 0}, 700 }; 701 702 static driver_t ps3cdrom_driver = { 703 "ps3cdrom", 704 ps3cdrom_methods, 705 sizeof(struct ps3cdrom_softc), 706 }; 707 708 static devclass_t ps3cdrom_devclass; 709 710 DRIVER_MODULE(ps3cdrom, ps3bus, ps3cdrom_driver, ps3cdrom_devclass, 0, 0); 711 MODULE_DEPEND(ps3cdrom, cam, 1, 1, 1); 712