xref: /openbmc/linux/drivers/scsi/ps3rom.c (revision 4fe61364)
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