1935912c5SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29aea8cbfSGeert Uytterhoeven /*
39aea8cbfSGeert Uytterhoeven * PS3 BD/DVD/CD-ROM Storage Driver
49aea8cbfSGeert Uytterhoeven *
59aea8cbfSGeert Uytterhoeven * Copyright (C) 2007 Sony Computer Entertainment Inc.
69aea8cbfSGeert Uytterhoeven * Copyright 2007 Sony Corp.
79aea8cbfSGeert Uytterhoeven */
89aea8cbfSGeert Uytterhoeven
99aea8cbfSGeert Uytterhoeven #include <linux/cdrom.h>
109aea8cbfSGeert Uytterhoeven #include <linux/highmem.h>
11acf3368fSPaul Gortmaker #include <linux/module.h>
125a0e3ad6STejun Heo #include <linux/slab.h>
139aea8cbfSGeert Uytterhoeven
149aea8cbfSGeert Uytterhoeven #include <scsi/scsi.h>
159aea8cbfSGeert Uytterhoeven #include <scsi/scsi_cmnd.h>
169aea8cbfSGeert Uytterhoeven #include <scsi/scsi_dbg.h>
179aea8cbfSGeert Uytterhoeven #include <scsi/scsi_device.h>
189aea8cbfSGeert Uytterhoeven #include <scsi/scsi_host.h>
1953df8ba8SFUJITA Tomonori #include <scsi/scsi_eh.h>
209aea8cbfSGeert Uytterhoeven
219aea8cbfSGeert Uytterhoeven #include <asm/lv1call.h>
229aea8cbfSGeert Uytterhoeven #include <asm/ps3stor.h>
239aea8cbfSGeert Uytterhoeven
249aea8cbfSGeert Uytterhoeven
259aea8cbfSGeert Uytterhoeven #define DEVICE_NAME "ps3rom"
269aea8cbfSGeert Uytterhoeven
279aea8cbfSGeert Uytterhoeven #define BOUNCE_SIZE (64*1024)
289aea8cbfSGeert Uytterhoeven
2951883b5eSAegis Lin #define PS3ROM_MAX_SECTORS (BOUNCE_SIZE >> 9)
309aea8cbfSGeert Uytterhoeven
319aea8cbfSGeert Uytterhoeven
329aea8cbfSGeert Uytterhoeven struct ps3rom_private {
339aea8cbfSGeert Uytterhoeven struct ps3_storage_device *dev;
349aea8cbfSGeert Uytterhoeven struct scsi_cmnd *curr_cmd;
359aea8cbfSGeert Uytterhoeven };
369aea8cbfSGeert Uytterhoeven
379aea8cbfSGeert Uytterhoeven
389aea8cbfSGeert Uytterhoeven #define LV1_STORAGE_SEND_ATAPI_COMMAND (1)
399aea8cbfSGeert Uytterhoeven
409aea8cbfSGeert Uytterhoeven struct lv1_atapi_cmnd_block {
419aea8cbfSGeert Uytterhoeven u8 pkt[32]; /* packet command block */
429aea8cbfSGeert Uytterhoeven u32 pktlen; /* should be 12 for ATAPI 8020 */
439aea8cbfSGeert Uytterhoeven u32 blocks;
449aea8cbfSGeert Uytterhoeven u32 block_size;
459aea8cbfSGeert Uytterhoeven u32 proto; /* transfer mode */
469aea8cbfSGeert Uytterhoeven u32 in_out; /* transfer direction */
479aea8cbfSGeert Uytterhoeven u64 buffer; /* parameter except command block */
489aea8cbfSGeert Uytterhoeven u32 arglen; /* length above */
499aea8cbfSGeert Uytterhoeven };
509aea8cbfSGeert Uytterhoeven
519aea8cbfSGeert Uytterhoeven enum lv1_atapi_proto {
529aea8cbfSGeert Uytterhoeven NON_DATA_PROTO = 0,
539aea8cbfSGeert Uytterhoeven PIO_DATA_IN_PROTO = 1,
549aea8cbfSGeert Uytterhoeven PIO_DATA_OUT_PROTO = 2,
559aea8cbfSGeert Uytterhoeven DMA_PROTO = 3
569aea8cbfSGeert Uytterhoeven };
579aea8cbfSGeert Uytterhoeven
589aea8cbfSGeert Uytterhoeven enum lv1_atapi_in_out {
599aea8cbfSGeert Uytterhoeven DIR_WRITE = 0, /* memory -> device */
609aea8cbfSGeert Uytterhoeven DIR_READ = 1 /* device -> memory */
619aea8cbfSGeert Uytterhoeven };
629aea8cbfSGeert Uytterhoeven
639aea8cbfSGeert Uytterhoeven
ps3rom_slave_configure(struct scsi_device * scsi_dev)649aea8cbfSGeert Uytterhoeven static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
659aea8cbfSGeert Uytterhoeven {
669aea8cbfSGeert Uytterhoeven struct ps3rom_private *priv = shost_priv(scsi_dev->host);
679aea8cbfSGeert Uytterhoeven struct ps3_storage_device *dev = priv->dev;
689aea8cbfSGeert Uytterhoeven
699cb78c16SHannes Reinecke dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %llu, channel %u\n", __func__,
709aea8cbfSGeert Uytterhoeven __LINE__, scsi_dev->id, scsi_dev->lun, scsi_dev->channel);
719aea8cbfSGeert Uytterhoeven
729aea8cbfSGeert Uytterhoeven /*
739aea8cbfSGeert Uytterhoeven * ATAPI SFF8020 devices use MODE_SENSE_10,
749aea8cbfSGeert Uytterhoeven * so we can prohibit MODE_SENSE_6
759aea8cbfSGeert Uytterhoeven */
769aea8cbfSGeert Uytterhoeven scsi_dev->use_10_for_ms = 1;
779aea8cbfSGeert Uytterhoeven
789aea8cbfSGeert Uytterhoeven /* we don't support {READ,WRITE}_6 */
799aea8cbfSGeert Uytterhoeven scsi_dev->use_10_for_rw = 1;
809aea8cbfSGeert Uytterhoeven
819aea8cbfSGeert Uytterhoeven return 0;
829aea8cbfSGeert Uytterhoeven }
839aea8cbfSGeert Uytterhoeven
ps3rom_atapi_request(struct ps3_storage_device * dev,struct scsi_cmnd * cmd)849aea8cbfSGeert Uytterhoeven static int ps3rom_atapi_request(struct ps3_storage_device *dev,
859aea8cbfSGeert Uytterhoeven struct scsi_cmnd *cmd)
869aea8cbfSGeert Uytterhoeven {
879aea8cbfSGeert Uytterhoeven struct lv1_atapi_cmnd_block atapi_cmnd;
889aea8cbfSGeert Uytterhoeven unsigned char opcode = cmd->cmnd[0];
899aea8cbfSGeert Uytterhoeven int res;
909aea8cbfSGeert Uytterhoeven u64 lpar;
919aea8cbfSGeert Uytterhoeven
929aea8cbfSGeert Uytterhoeven dev_dbg(&dev->sbd.core, "%s:%u: send ATAPI command 0x%02x\n", __func__,
939aea8cbfSGeert Uytterhoeven __LINE__, opcode);
949aea8cbfSGeert Uytterhoeven
959aea8cbfSGeert Uytterhoeven memset(&atapi_cmnd, 0, sizeof(struct lv1_atapi_cmnd_block));
969aea8cbfSGeert Uytterhoeven memcpy(&atapi_cmnd.pkt, cmd->cmnd, 12);
979aea8cbfSGeert Uytterhoeven atapi_cmnd.pktlen = 12;
989aea8cbfSGeert Uytterhoeven atapi_cmnd.block_size = 1; /* transfer size is block_size * blocks */
9935814740SFUJITA Tomonori atapi_cmnd.blocks = atapi_cmnd.arglen = scsi_bufflen(cmd);
1009aea8cbfSGeert Uytterhoeven atapi_cmnd.buffer = dev->bounce_lpar;
1019aea8cbfSGeert Uytterhoeven
1029aea8cbfSGeert Uytterhoeven switch (cmd->sc_data_direction) {
1039aea8cbfSGeert Uytterhoeven case DMA_FROM_DEVICE:
10435814740SFUJITA Tomonori if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
1059aea8cbfSGeert Uytterhoeven atapi_cmnd.proto = DMA_PROTO;
1069aea8cbfSGeert Uytterhoeven else
1079aea8cbfSGeert Uytterhoeven atapi_cmnd.proto = PIO_DATA_IN_PROTO;
1089aea8cbfSGeert Uytterhoeven atapi_cmnd.in_out = DIR_READ;
1099aea8cbfSGeert Uytterhoeven break;
1109aea8cbfSGeert Uytterhoeven
1119aea8cbfSGeert Uytterhoeven case DMA_TO_DEVICE:
11235814740SFUJITA Tomonori if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
1139aea8cbfSGeert Uytterhoeven atapi_cmnd.proto = DMA_PROTO;
1149aea8cbfSGeert Uytterhoeven else
1159aea8cbfSGeert Uytterhoeven atapi_cmnd.proto = PIO_DATA_OUT_PROTO;
1169aea8cbfSGeert Uytterhoeven atapi_cmnd.in_out = DIR_WRITE;
117944cf8b4SFUJITA Tomonori scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
1189aea8cbfSGeert Uytterhoeven break;
1199aea8cbfSGeert Uytterhoeven
1209aea8cbfSGeert Uytterhoeven default:
1219aea8cbfSGeert Uytterhoeven atapi_cmnd.proto = NON_DATA_PROTO;
1229aea8cbfSGeert Uytterhoeven break;
1239aea8cbfSGeert Uytterhoeven }
1249aea8cbfSGeert Uytterhoeven
1259aea8cbfSGeert Uytterhoeven lpar = ps3_mm_phys_to_lpar(__pa(&atapi_cmnd));
1269aea8cbfSGeert Uytterhoeven res = lv1_storage_send_device_command(dev->sbd.dev_id,
1279aea8cbfSGeert Uytterhoeven LV1_STORAGE_SEND_ATAPI_COMMAND,
1289aea8cbfSGeert Uytterhoeven lpar, sizeof(atapi_cmnd),
1299aea8cbfSGeert Uytterhoeven atapi_cmnd.buffer,
1309aea8cbfSGeert Uytterhoeven atapi_cmnd.arglen, &dev->tag);
1319aea8cbfSGeert Uytterhoeven if (res == LV1_DENIED_BY_POLICY) {
1329aea8cbfSGeert Uytterhoeven dev_dbg(&dev->sbd.core,
1339aea8cbfSGeert Uytterhoeven "%s:%u: ATAPI command 0x%02x denied by policy\n",
1349aea8cbfSGeert Uytterhoeven __func__, __LINE__, opcode);
1359aea8cbfSGeert Uytterhoeven return DID_ERROR << 16;
1369aea8cbfSGeert Uytterhoeven }
1379aea8cbfSGeert Uytterhoeven
1389aea8cbfSGeert Uytterhoeven if (res) {
1399aea8cbfSGeert Uytterhoeven dev_err(&dev->sbd.core,
1409aea8cbfSGeert Uytterhoeven "%s:%u: ATAPI command 0x%02x failed %d\n", __func__,
1419aea8cbfSGeert Uytterhoeven __LINE__, opcode, res);
1429aea8cbfSGeert Uytterhoeven return DID_ERROR << 16;
1439aea8cbfSGeert Uytterhoeven }
1449aea8cbfSGeert Uytterhoeven
1459aea8cbfSGeert Uytterhoeven return 0;
1469aea8cbfSGeert Uytterhoeven }
1479aea8cbfSGeert Uytterhoeven
srb10_lba(const struct scsi_cmnd * cmd)1489aea8cbfSGeert Uytterhoeven static inline unsigned int srb10_lba(const struct scsi_cmnd *cmd)
1499aea8cbfSGeert Uytterhoeven {
1509aea8cbfSGeert Uytterhoeven return cmd->cmnd[2] << 24 | cmd->cmnd[3] << 16 | cmd->cmnd[4] << 8 |
1519aea8cbfSGeert Uytterhoeven cmd->cmnd[5];
1529aea8cbfSGeert Uytterhoeven }
1539aea8cbfSGeert Uytterhoeven
srb10_len(const struct scsi_cmnd * cmd)1549aea8cbfSGeert Uytterhoeven static inline unsigned int srb10_len(const struct scsi_cmnd *cmd)
1559aea8cbfSGeert Uytterhoeven {
1569aea8cbfSGeert Uytterhoeven return cmd->cmnd[7] << 8 | cmd->cmnd[8];
1579aea8cbfSGeert Uytterhoeven }
1589aea8cbfSGeert Uytterhoeven
ps3rom_read_request(struct ps3_storage_device * dev,struct scsi_cmnd * cmd,u32 start_sector,u32 sectors)1599aea8cbfSGeert Uytterhoeven static int ps3rom_read_request(struct ps3_storage_device *dev,
1609aea8cbfSGeert Uytterhoeven struct scsi_cmnd *cmd, u32 start_sector,
1619aea8cbfSGeert Uytterhoeven u32 sectors)
1629aea8cbfSGeert Uytterhoeven {
1639aea8cbfSGeert Uytterhoeven int res;
1649aea8cbfSGeert Uytterhoeven
1659aea8cbfSGeert Uytterhoeven dev_dbg(&dev->sbd.core, "%s:%u: read %u sectors starting at %u\n",
1669aea8cbfSGeert Uytterhoeven __func__, __LINE__, sectors, start_sector);
1679aea8cbfSGeert Uytterhoeven
1689aea8cbfSGeert Uytterhoeven res = lv1_storage_read(dev->sbd.dev_id,
1699aea8cbfSGeert Uytterhoeven dev->regions[dev->region_idx].id, start_sector,
1709aea8cbfSGeert Uytterhoeven sectors, 0, dev->bounce_lpar, &dev->tag);
1719aea8cbfSGeert Uytterhoeven if (res) {
1729aea8cbfSGeert Uytterhoeven dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__,
1739aea8cbfSGeert Uytterhoeven __LINE__, res);
1749aea8cbfSGeert Uytterhoeven return DID_ERROR << 16;
1759aea8cbfSGeert Uytterhoeven }
1769aea8cbfSGeert Uytterhoeven
1779aea8cbfSGeert Uytterhoeven return 0;
1789aea8cbfSGeert Uytterhoeven }
1799aea8cbfSGeert Uytterhoeven
ps3rom_write_request(struct ps3_storage_device * dev,struct scsi_cmnd * cmd,u32 start_sector,u32 sectors)1809aea8cbfSGeert Uytterhoeven static int ps3rom_write_request(struct ps3_storage_device *dev,
1819aea8cbfSGeert Uytterhoeven struct scsi_cmnd *cmd, u32 start_sector,
1829aea8cbfSGeert Uytterhoeven u32 sectors)
1839aea8cbfSGeert Uytterhoeven {
1849aea8cbfSGeert Uytterhoeven int res;
1859aea8cbfSGeert Uytterhoeven
1869aea8cbfSGeert Uytterhoeven dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n",
1879aea8cbfSGeert Uytterhoeven __func__, __LINE__, sectors, start_sector);
1889aea8cbfSGeert Uytterhoeven
189944cf8b4SFUJITA Tomonori scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
1909aea8cbfSGeert Uytterhoeven
1919aea8cbfSGeert Uytterhoeven res = lv1_storage_write(dev->sbd.dev_id,
1929aea8cbfSGeert Uytterhoeven dev->regions[dev->region_idx].id, start_sector,
1939aea8cbfSGeert Uytterhoeven sectors, 0, dev->bounce_lpar, &dev->tag);
1949aea8cbfSGeert Uytterhoeven if (res) {
1959aea8cbfSGeert Uytterhoeven dev_err(&dev->sbd.core, "%s:%u: write failed %d\n", __func__,
1969aea8cbfSGeert Uytterhoeven __LINE__, res);
1979aea8cbfSGeert Uytterhoeven return DID_ERROR << 16;
1989aea8cbfSGeert Uytterhoeven }
1999aea8cbfSGeert Uytterhoeven
2009aea8cbfSGeert Uytterhoeven return 0;
2019aea8cbfSGeert Uytterhoeven }
2029aea8cbfSGeert Uytterhoeven
ps3rom_queuecommand_lck(struct scsi_cmnd * cmd)203af049dfdSBart Van Assche static int ps3rom_queuecommand_lck(struct scsi_cmnd *cmd)
2049aea8cbfSGeert Uytterhoeven {
2059aea8cbfSGeert Uytterhoeven struct ps3rom_private *priv = shost_priv(cmd->device->host);
2069aea8cbfSGeert Uytterhoeven struct ps3_storage_device *dev = priv->dev;
2079aea8cbfSGeert Uytterhoeven unsigned char opcode;
2089aea8cbfSGeert Uytterhoeven int res;
2099aea8cbfSGeert Uytterhoeven
2109aea8cbfSGeert Uytterhoeven priv->curr_cmd = cmd;
2119aea8cbfSGeert Uytterhoeven
2129aea8cbfSGeert Uytterhoeven opcode = cmd->cmnd[0];
2139aea8cbfSGeert Uytterhoeven /*
2149aea8cbfSGeert Uytterhoeven * While we can submit READ/WRITE SCSI commands as ATAPI commands,
2159aea8cbfSGeert Uytterhoeven * it's recommended for various reasons (performance, error handling,
2169aea8cbfSGeert Uytterhoeven * ...) to use lv1_storage_{read,write}() instead
2179aea8cbfSGeert Uytterhoeven */
2189aea8cbfSGeert Uytterhoeven switch (opcode) {
2199aea8cbfSGeert Uytterhoeven case READ_10:
2209aea8cbfSGeert Uytterhoeven res = ps3rom_read_request(dev, cmd, srb10_lba(cmd),
2219aea8cbfSGeert Uytterhoeven srb10_len(cmd));
2229aea8cbfSGeert Uytterhoeven break;
2239aea8cbfSGeert Uytterhoeven
2249aea8cbfSGeert Uytterhoeven case WRITE_10:
2259aea8cbfSGeert Uytterhoeven res = ps3rom_write_request(dev, cmd, srb10_lba(cmd),
2269aea8cbfSGeert Uytterhoeven srb10_len(cmd));
2279aea8cbfSGeert Uytterhoeven break;
2289aea8cbfSGeert Uytterhoeven
2299aea8cbfSGeert Uytterhoeven default:
2309aea8cbfSGeert Uytterhoeven res = ps3rom_atapi_request(dev, cmd);
2319aea8cbfSGeert Uytterhoeven break;
2329aea8cbfSGeert Uytterhoeven }
2339aea8cbfSGeert Uytterhoeven
2349aea8cbfSGeert Uytterhoeven if (res) {
235f2b1e9c6SHannes Reinecke scsi_build_sense(cmd, 0, ILLEGAL_REQUEST, 0, 0);
2369aea8cbfSGeert Uytterhoeven cmd->result = res;
2379aea8cbfSGeert Uytterhoeven priv->curr_cmd = NULL;
2383ca2385aSBart Van Assche scsi_done(cmd);
2399aea8cbfSGeert Uytterhoeven }
2409aea8cbfSGeert Uytterhoeven
2419aea8cbfSGeert Uytterhoeven return 0;
2429aea8cbfSGeert Uytterhoeven }
2439aea8cbfSGeert Uytterhoeven
DEF_SCSI_QCMD(ps3rom_queuecommand)244f281233dSJeff Garzik static DEF_SCSI_QCMD(ps3rom_queuecommand)
245f281233dSJeff Garzik
2469aea8cbfSGeert Uytterhoeven static int decode_lv1_status(u64 status, unsigned char *sense_key,
2479aea8cbfSGeert Uytterhoeven unsigned char *asc, unsigned char *ascq)
2489aea8cbfSGeert Uytterhoeven {
2499aea8cbfSGeert Uytterhoeven if (((status >> 24) & 0xff) != SAM_STAT_CHECK_CONDITION)
2509aea8cbfSGeert Uytterhoeven return -1;
2519aea8cbfSGeert Uytterhoeven
2529aea8cbfSGeert Uytterhoeven *sense_key = (status >> 16) & 0xff;
2539aea8cbfSGeert Uytterhoeven *asc = (status >> 8) & 0xff;
2549aea8cbfSGeert Uytterhoeven *ascq = status & 0xff;
2559aea8cbfSGeert Uytterhoeven return 0;
2569aea8cbfSGeert Uytterhoeven }
2579aea8cbfSGeert Uytterhoeven
ps3rom_interrupt(int irq,void * data)2589aea8cbfSGeert Uytterhoeven static irqreturn_t ps3rom_interrupt(int irq, void *data)
2599aea8cbfSGeert Uytterhoeven {
2609aea8cbfSGeert Uytterhoeven struct ps3_storage_device *dev = data;
2619aea8cbfSGeert Uytterhoeven struct Scsi_Host *host;
2629aea8cbfSGeert Uytterhoeven struct ps3rom_private *priv;
2639aea8cbfSGeert Uytterhoeven struct scsi_cmnd *cmd;
2649aea8cbfSGeert Uytterhoeven int res;
2659aea8cbfSGeert Uytterhoeven u64 tag, status;
2669aea8cbfSGeert Uytterhoeven unsigned char sense_key, asc, ascq;
2679aea8cbfSGeert Uytterhoeven
2689aea8cbfSGeert Uytterhoeven res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
2699aea8cbfSGeert Uytterhoeven /*
2709aea8cbfSGeert Uytterhoeven * status = -1 may mean that ATAPI transport completed OK, but
2719aea8cbfSGeert Uytterhoeven * ATAPI command itself resulted CHECK CONDITION
2729aea8cbfSGeert Uytterhoeven * so, upper layer should issue REQUEST_SENSE to check the sense data
2739aea8cbfSGeert Uytterhoeven */
2749aea8cbfSGeert Uytterhoeven
2759aea8cbfSGeert Uytterhoeven if (tag != dev->tag)
2769aea8cbfSGeert Uytterhoeven dev_err(&dev->sbd.core,
2777ad489e3SStephen Rothwell "%s:%u: tag mismatch, got %llx, expected %llx\n",
2789aea8cbfSGeert Uytterhoeven __func__, __LINE__, tag, dev->tag);
2799aea8cbfSGeert Uytterhoeven
2809aea8cbfSGeert Uytterhoeven if (res) {
2817ad489e3SStephen Rothwell dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
2829aea8cbfSGeert Uytterhoeven __func__, __LINE__, res, status);
2839aea8cbfSGeert Uytterhoeven return IRQ_HANDLED;
2849aea8cbfSGeert Uytterhoeven }
2859aea8cbfSGeert Uytterhoeven
286c4b512bcSGeert Uytterhoeven host = ps3_system_bus_get_drvdata(&dev->sbd);
2879aea8cbfSGeert Uytterhoeven priv = shost_priv(host);
2889aea8cbfSGeert Uytterhoeven cmd = priv->curr_cmd;
2899aea8cbfSGeert Uytterhoeven
2909aea8cbfSGeert Uytterhoeven if (!status) {
2919aea8cbfSGeert Uytterhoeven /* OK, completed */
2929aea8cbfSGeert Uytterhoeven if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
293944cf8b4SFUJITA Tomonori int len;
294944cf8b4SFUJITA Tomonori
295944cf8b4SFUJITA Tomonori len = scsi_sg_copy_from_buffer(cmd,
296944cf8b4SFUJITA Tomonori dev->bounce_buf,
297944cf8b4SFUJITA Tomonori dev->bounce_size);
298944cf8b4SFUJITA Tomonori
299944cf8b4SFUJITA Tomonori scsi_set_resid(cmd, scsi_bufflen(cmd) - len);
3009aea8cbfSGeert Uytterhoeven }
3019aea8cbfSGeert Uytterhoeven cmd->result = DID_OK << 16;
3029aea8cbfSGeert Uytterhoeven goto done;
3039aea8cbfSGeert Uytterhoeven }
3049aea8cbfSGeert Uytterhoeven
3059aea8cbfSGeert Uytterhoeven if (cmd->cmnd[0] == REQUEST_SENSE) {
3069aea8cbfSGeert Uytterhoeven /* SCSI spec says request sense should never get error */
3079aea8cbfSGeert Uytterhoeven dev_err(&dev->sbd.core, "%s:%u: end error without autosense\n",
3089aea8cbfSGeert Uytterhoeven __func__, __LINE__);
3099aea8cbfSGeert Uytterhoeven cmd->result = DID_ERROR << 16 | SAM_STAT_CHECK_CONDITION;
3109aea8cbfSGeert Uytterhoeven goto done;
3119aea8cbfSGeert Uytterhoeven }
3129aea8cbfSGeert Uytterhoeven
3139aea8cbfSGeert Uytterhoeven if (decode_lv1_status(status, &sense_key, &asc, &ascq)) {
3149aea8cbfSGeert Uytterhoeven cmd->result = DID_ERROR << 16;
3159aea8cbfSGeert Uytterhoeven goto done;
3169aea8cbfSGeert Uytterhoeven }
3179aea8cbfSGeert Uytterhoeven
318f2b1e9c6SHannes Reinecke scsi_build_sense(cmd, 0, sense_key, asc, ascq);
3199aea8cbfSGeert Uytterhoeven
3209aea8cbfSGeert Uytterhoeven done:
3219aea8cbfSGeert Uytterhoeven priv->curr_cmd = NULL;
3223ca2385aSBart Van Assche scsi_done(cmd);
3239aea8cbfSGeert Uytterhoeven return IRQ_HANDLED;
3249aea8cbfSGeert Uytterhoeven }
3259aea8cbfSGeert Uytterhoeven
326*4fe61364SBart Van Assche static const struct scsi_host_template ps3rom_host_template = {
3279aea8cbfSGeert Uytterhoeven .name = DEVICE_NAME,
3289aea8cbfSGeert Uytterhoeven .slave_configure = ps3rom_slave_configure,
3299aea8cbfSGeert Uytterhoeven .queuecommand = ps3rom_queuecommand,
3309aea8cbfSGeert Uytterhoeven .can_queue = 1,
3319aea8cbfSGeert Uytterhoeven .this_id = 7,
3329aea8cbfSGeert Uytterhoeven .sg_tablesize = SG_ALL,
3339aea8cbfSGeert Uytterhoeven .emulated = 1, /* only sg driver uses this */
3349aea8cbfSGeert Uytterhoeven .max_sectors = PS3ROM_MAX_SECTORS,
3359aea8cbfSGeert Uytterhoeven .module = THIS_MODULE,
3369aea8cbfSGeert Uytterhoeven };
3379aea8cbfSGeert Uytterhoeven
3389aea8cbfSGeert Uytterhoeven
ps3rom_probe(struct ps3_system_bus_device * _dev)3396f039790SGreg Kroah-Hartman static int ps3rom_probe(struct ps3_system_bus_device *_dev)
3409aea8cbfSGeert Uytterhoeven {
3419aea8cbfSGeert Uytterhoeven struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
3429aea8cbfSGeert Uytterhoeven int error;
3439aea8cbfSGeert Uytterhoeven struct Scsi_Host *host;
3449aea8cbfSGeert Uytterhoeven struct ps3rom_private *priv;
3459aea8cbfSGeert Uytterhoeven
3469aea8cbfSGeert Uytterhoeven if (dev->blk_size != CD_FRAMESIZE) {
3479aea8cbfSGeert Uytterhoeven dev_err(&dev->sbd.core,
3487ad489e3SStephen Rothwell "%s:%u: cannot handle block size %llu\n", __func__,
3499aea8cbfSGeert Uytterhoeven __LINE__, dev->blk_size);
3509aea8cbfSGeert Uytterhoeven return -EINVAL;
3519aea8cbfSGeert Uytterhoeven }
3529aea8cbfSGeert Uytterhoeven
3539aea8cbfSGeert Uytterhoeven dev->bounce_size = BOUNCE_SIZE;
3549aea8cbfSGeert Uytterhoeven dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
3559aea8cbfSGeert Uytterhoeven if (!dev->bounce_buf)
3569aea8cbfSGeert Uytterhoeven return -ENOMEM;
3579aea8cbfSGeert Uytterhoeven
3589aea8cbfSGeert Uytterhoeven error = ps3stor_setup(dev, ps3rom_interrupt);
3599aea8cbfSGeert Uytterhoeven if (error)
3609aea8cbfSGeert Uytterhoeven goto fail_free_bounce;
3619aea8cbfSGeert Uytterhoeven
3629aea8cbfSGeert Uytterhoeven host = scsi_host_alloc(&ps3rom_host_template,
3639aea8cbfSGeert Uytterhoeven sizeof(struct ps3rom_private));
3649aea8cbfSGeert Uytterhoeven if (!host) {
3659aea8cbfSGeert Uytterhoeven dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed\n",
3669aea8cbfSGeert Uytterhoeven __func__, __LINE__);
367af222097SJulia Lawall error = -ENOMEM;
3689aea8cbfSGeert Uytterhoeven goto fail_teardown;
3699aea8cbfSGeert Uytterhoeven }
3709aea8cbfSGeert Uytterhoeven
3719aea8cbfSGeert Uytterhoeven priv = shost_priv(host);
372c4b512bcSGeert Uytterhoeven ps3_system_bus_set_drvdata(&dev->sbd, host);
3739aea8cbfSGeert Uytterhoeven priv->dev = dev;
3749aea8cbfSGeert Uytterhoeven
3759aea8cbfSGeert Uytterhoeven /* One device/LUN per SCSI bus */
3769aea8cbfSGeert Uytterhoeven host->max_id = 1;
3779aea8cbfSGeert Uytterhoeven host->max_lun = 1;
3789aea8cbfSGeert Uytterhoeven
3799aea8cbfSGeert Uytterhoeven error = scsi_add_host(host, &dev->sbd.core);
3809aea8cbfSGeert Uytterhoeven if (error) {
3819aea8cbfSGeert Uytterhoeven dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed %d\n",
3829aea8cbfSGeert Uytterhoeven __func__, __LINE__, error);
3839aea8cbfSGeert Uytterhoeven error = -ENODEV;
3849aea8cbfSGeert Uytterhoeven goto fail_host_put;
3859aea8cbfSGeert Uytterhoeven }
3869aea8cbfSGeert Uytterhoeven
3879aea8cbfSGeert Uytterhoeven scsi_scan_host(host);
3889aea8cbfSGeert Uytterhoeven return 0;
3899aea8cbfSGeert Uytterhoeven
3909aea8cbfSGeert Uytterhoeven fail_host_put:
3919aea8cbfSGeert Uytterhoeven scsi_host_put(host);
392c4b512bcSGeert Uytterhoeven ps3_system_bus_set_drvdata(&dev->sbd, NULL);
3939aea8cbfSGeert Uytterhoeven fail_teardown:
3949aea8cbfSGeert Uytterhoeven ps3stor_teardown(dev);
3959aea8cbfSGeert Uytterhoeven fail_free_bounce:
3969aea8cbfSGeert Uytterhoeven kfree(dev->bounce_buf);
3979aea8cbfSGeert Uytterhoeven return error;
3989aea8cbfSGeert Uytterhoeven }
3999aea8cbfSGeert Uytterhoeven
ps3rom_remove(struct ps3_system_bus_device * _dev)4006d247e4dSUwe Kleine-König static void ps3rom_remove(struct ps3_system_bus_device *_dev)
4019aea8cbfSGeert Uytterhoeven {
4029aea8cbfSGeert Uytterhoeven struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
403c4b512bcSGeert Uytterhoeven struct Scsi_Host *host = ps3_system_bus_get_drvdata(&dev->sbd);
4049aea8cbfSGeert Uytterhoeven
4059aea8cbfSGeert Uytterhoeven scsi_remove_host(host);
4069aea8cbfSGeert Uytterhoeven ps3stor_teardown(dev);
4079aea8cbfSGeert Uytterhoeven scsi_host_put(host);
408c4b512bcSGeert Uytterhoeven ps3_system_bus_set_drvdata(&dev->sbd, NULL);
4099aea8cbfSGeert Uytterhoeven kfree(dev->bounce_buf);
4109aea8cbfSGeert Uytterhoeven }
4119aea8cbfSGeert Uytterhoeven
4129aea8cbfSGeert Uytterhoeven static struct ps3_system_bus_driver ps3rom = {
4139aea8cbfSGeert Uytterhoeven .match_id = PS3_MATCH_ID_STOR_ROM,
4149aea8cbfSGeert Uytterhoeven .core.name = DEVICE_NAME,
4159aea8cbfSGeert Uytterhoeven .core.owner = THIS_MODULE,
4169aea8cbfSGeert Uytterhoeven .probe = ps3rom_probe,
4179aea8cbfSGeert Uytterhoeven .remove = ps3rom_remove
4189aea8cbfSGeert Uytterhoeven };
4199aea8cbfSGeert Uytterhoeven
4209aea8cbfSGeert Uytterhoeven
ps3rom_init(void)4219aea8cbfSGeert Uytterhoeven static int __init ps3rom_init(void)
4229aea8cbfSGeert Uytterhoeven {
4239aea8cbfSGeert Uytterhoeven return ps3_system_bus_driver_register(&ps3rom);
4249aea8cbfSGeert Uytterhoeven }
4259aea8cbfSGeert Uytterhoeven
ps3rom_exit(void)4269aea8cbfSGeert Uytterhoeven static void __exit ps3rom_exit(void)
4279aea8cbfSGeert Uytterhoeven {
4289aea8cbfSGeert Uytterhoeven ps3_system_bus_driver_unregister(&ps3rom);
4299aea8cbfSGeert Uytterhoeven }
4309aea8cbfSGeert Uytterhoeven
4319aea8cbfSGeert Uytterhoeven module_init(ps3rom_init);
4329aea8cbfSGeert Uytterhoeven module_exit(ps3rom_exit);
4339aea8cbfSGeert Uytterhoeven
4349aea8cbfSGeert Uytterhoeven MODULE_LICENSE("GPL");
4359aea8cbfSGeert Uytterhoeven MODULE_DESCRIPTION("PS3 BD/DVD/CD-ROM Storage Driver");
4369aea8cbfSGeert Uytterhoeven MODULE_AUTHOR("Sony Corporation");
4379aea8cbfSGeert Uytterhoeven MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_ROM);
438