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