]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/scsi/ps3rom.c
powerpc/ps3: Printing fixups for l64 to ll64 conversion drivers/scsi
[linux-2.6-omap-h63xx.git] / drivers / scsi / ps3rom.c
1 /*
2  * PS3 BD/DVD/CD-ROM Storage Driver
3  *
4  * Copyright (C) 2007 Sony Computer Entertainment Inc.
5  * Copyright 2007 Sony Corp.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published
9  * by the Free Software Foundation; version 2 of the License.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <linux/cdrom.h>
22 #include <linux/highmem.h>
23
24 #include <scsi/scsi.h>
25 #include <scsi/scsi_cmnd.h>
26 #include <scsi/scsi_dbg.h>
27 #include <scsi/scsi_device.h>
28 #include <scsi/scsi_host.h>
29 #include <scsi/scsi_eh.h>
30
31 #include <asm/lv1call.h>
32 #include <asm/ps3stor.h>
33
34
35 #define DEVICE_NAME                     "ps3rom"
36
37 #define BOUNCE_SIZE                     (64*1024)
38
39 #define PS3ROM_MAX_SECTORS              (BOUNCE_SIZE >> 9)
40
41
42 struct ps3rom_private {
43         struct ps3_storage_device *dev;
44         struct scsi_cmnd *curr_cmd;
45 };
46
47
48 #define LV1_STORAGE_SEND_ATAPI_COMMAND  (1)
49
50 struct lv1_atapi_cmnd_block {
51         u8      pkt[32];        /* packet command block           */
52         u32     pktlen;         /* should be 12 for ATAPI 8020    */
53         u32     blocks;
54         u32     block_size;
55         u32     proto;          /* transfer mode                  */
56         u32     in_out;         /* transfer direction             */
57         u64     buffer;         /* parameter except command block */
58         u32     arglen;         /* length above                   */
59 };
60
61 enum lv1_atapi_proto {
62         NON_DATA_PROTO     = 0,
63         PIO_DATA_IN_PROTO  = 1,
64         PIO_DATA_OUT_PROTO = 2,
65         DMA_PROTO = 3
66 };
67
68 enum lv1_atapi_in_out {
69         DIR_WRITE = 0,          /* memory -> device */
70         DIR_READ = 1            /* device -> memory */
71 };
72
73
74 static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
75 {
76         struct ps3rom_private *priv = shost_priv(scsi_dev->host);
77         struct ps3_storage_device *dev = priv->dev;
78
79         dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %u, channel %u\n", __func__,
80                 __LINE__, scsi_dev->id, scsi_dev->lun, scsi_dev->channel);
81
82         /*
83          * ATAPI SFF8020 devices use MODE_SENSE_10,
84          * so we can prohibit MODE_SENSE_6
85          */
86         scsi_dev->use_10_for_ms = 1;
87
88         /* we don't support {READ,WRITE}_6 */
89         scsi_dev->use_10_for_rw = 1;
90
91         return 0;
92 }
93
94 static int ps3rom_atapi_request(struct ps3_storage_device *dev,
95                                 struct scsi_cmnd *cmd)
96 {
97         struct lv1_atapi_cmnd_block atapi_cmnd;
98         unsigned char opcode = cmd->cmnd[0];
99         int res;
100         u64 lpar;
101
102         dev_dbg(&dev->sbd.core, "%s:%u: send ATAPI command 0x%02x\n", __func__,
103                 __LINE__, opcode);
104
105         memset(&atapi_cmnd, 0, sizeof(struct lv1_atapi_cmnd_block));
106         memcpy(&atapi_cmnd.pkt, cmd->cmnd, 12);
107         atapi_cmnd.pktlen = 12;
108         atapi_cmnd.block_size = 1; /* transfer size is block_size * blocks */
109         atapi_cmnd.blocks = atapi_cmnd.arglen = scsi_bufflen(cmd);
110         atapi_cmnd.buffer = dev->bounce_lpar;
111
112         switch (cmd->sc_data_direction) {
113         case DMA_FROM_DEVICE:
114                 if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
115                         atapi_cmnd.proto = DMA_PROTO;
116                 else
117                         atapi_cmnd.proto = PIO_DATA_IN_PROTO;
118                 atapi_cmnd.in_out = DIR_READ;
119                 break;
120
121         case DMA_TO_DEVICE:
122                 if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
123                         atapi_cmnd.proto = DMA_PROTO;
124                 else
125                         atapi_cmnd.proto = PIO_DATA_OUT_PROTO;
126                 atapi_cmnd.in_out = DIR_WRITE;
127                 scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
128                 break;
129
130         default:
131                 atapi_cmnd.proto = NON_DATA_PROTO;
132                 break;
133         }
134
135         lpar = ps3_mm_phys_to_lpar(__pa(&atapi_cmnd));
136         res = lv1_storage_send_device_command(dev->sbd.dev_id,
137                                               LV1_STORAGE_SEND_ATAPI_COMMAND,
138                                               lpar, sizeof(atapi_cmnd),
139                                               atapi_cmnd.buffer,
140                                               atapi_cmnd.arglen, &dev->tag);
141         if (res == LV1_DENIED_BY_POLICY) {
142                 dev_dbg(&dev->sbd.core,
143                         "%s:%u: ATAPI command 0x%02x denied by policy\n",
144                         __func__, __LINE__, opcode);
145                 return DID_ERROR << 16;
146         }
147
148         if (res) {
149                 dev_err(&dev->sbd.core,
150                         "%s:%u: ATAPI command 0x%02x failed %d\n", __func__,
151                         __LINE__, opcode, res);
152                 return DID_ERROR << 16;
153         }
154
155         return 0;
156 }
157
158 static inline unsigned int srb10_lba(const struct scsi_cmnd *cmd)
159 {
160         return cmd->cmnd[2] << 24 | cmd->cmnd[3] << 16 | cmd->cmnd[4] << 8 |
161                cmd->cmnd[5];
162 }
163
164 static inline unsigned int srb10_len(const struct scsi_cmnd *cmd)
165 {
166         return cmd->cmnd[7] << 8 | cmd->cmnd[8];
167 }
168
169 static int ps3rom_read_request(struct ps3_storage_device *dev,
170                                struct scsi_cmnd *cmd, u32 start_sector,
171                                u32 sectors)
172 {
173         int res;
174
175         dev_dbg(&dev->sbd.core, "%s:%u: read %u sectors starting at %u\n",
176                 __func__, __LINE__, sectors, start_sector);
177
178         res = lv1_storage_read(dev->sbd.dev_id,
179                                dev->regions[dev->region_idx].id, start_sector,
180                                sectors, 0, dev->bounce_lpar, &dev->tag);
181         if (res) {
182                 dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__,
183                         __LINE__, res);
184                 return DID_ERROR << 16;
185         }
186
187         return 0;
188 }
189
190 static int ps3rom_write_request(struct ps3_storage_device *dev,
191                                 struct scsi_cmnd *cmd, u32 start_sector,
192                                 u32 sectors)
193 {
194         int res;
195
196         dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n",
197                 __func__, __LINE__, sectors, start_sector);
198
199         scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
200
201         res = lv1_storage_write(dev->sbd.dev_id,
202                                 dev->regions[dev->region_idx].id, start_sector,
203                                 sectors, 0, dev->bounce_lpar, &dev->tag);
204         if (res) {
205                 dev_err(&dev->sbd.core, "%s:%u: write failed %d\n", __func__,
206                         __LINE__, res);
207                 return DID_ERROR << 16;
208         }
209
210         return 0;
211 }
212
213 static int ps3rom_queuecommand(struct scsi_cmnd *cmd,
214                                void (*done)(struct scsi_cmnd *))
215 {
216         struct ps3rom_private *priv = shost_priv(cmd->device->host);
217         struct ps3_storage_device *dev = priv->dev;
218         unsigned char opcode;
219         int res;
220
221 #ifdef DEBUG
222         scsi_print_command(cmd);
223 #endif
224
225         priv->curr_cmd = cmd;
226         cmd->scsi_done = done;
227
228         opcode = cmd->cmnd[0];
229         /*
230          * While we can submit READ/WRITE SCSI commands as ATAPI commands,
231          * it's recommended for various reasons (performance, error handling,
232          * ...) to use lv1_storage_{read,write}() instead
233          */
234         switch (opcode) {
235         case READ_10:
236                 res = ps3rom_read_request(dev, cmd, srb10_lba(cmd),
237                                           srb10_len(cmd));
238                 break;
239
240         case WRITE_10:
241                 res = ps3rom_write_request(dev, cmd, srb10_lba(cmd),
242                                            srb10_len(cmd));
243                 break;
244
245         default:
246                 res = ps3rom_atapi_request(dev, cmd);
247                 break;
248         }
249
250         if (res) {
251                 memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
252                 cmd->result = res;
253                 cmd->sense_buffer[0] = 0x70;
254                 cmd->sense_buffer[2] = ILLEGAL_REQUEST;
255                 priv->curr_cmd = NULL;
256                 cmd->scsi_done(cmd);
257         }
258
259         return 0;
260 }
261
262 static int decode_lv1_status(u64 status, unsigned char *sense_key,
263                              unsigned char *asc, unsigned char *ascq)
264 {
265         if (((status >> 24) & 0xff) != SAM_STAT_CHECK_CONDITION)
266                 return -1;
267
268         *sense_key = (status >> 16) & 0xff;
269         *asc       = (status >>  8) & 0xff;
270         *ascq      =  status        & 0xff;
271         return 0;
272 }
273
274 static irqreturn_t ps3rom_interrupt(int irq, void *data)
275 {
276         struct ps3_storage_device *dev = data;
277         struct Scsi_Host *host;
278         struct ps3rom_private *priv;
279         struct scsi_cmnd *cmd;
280         int res;
281         u64 tag, status;
282         unsigned char sense_key, asc, ascq;
283
284         res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
285         /*
286          * status = -1 may mean that ATAPI transport completed OK, but
287          * ATAPI command itself resulted CHECK CONDITION
288          * so, upper layer should issue REQUEST_SENSE to check the sense data
289          */
290
291         if (tag != dev->tag)
292                 dev_err(&dev->sbd.core,
293                         "%s:%u: tag mismatch, got %llx, expected %llx\n",
294                         __func__, __LINE__, tag, dev->tag);
295
296         if (res) {
297                 dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
298                         __func__, __LINE__, res, status);
299                 return IRQ_HANDLED;
300         }
301
302         host = dev->sbd.core.driver_data;
303         priv = shost_priv(host);
304         cmd = priv->curr_cmd;
305
306         if (!status) {
307                 /* OK, completed */
308                 if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
309                         int len;
310
311                         len = scsi_sg_copy_from_buffer(cmd,
312                                                        dev->bounce_buf,
313                                                        dev->bounce_size);
314
315                         scsi_set_resid(cmd, scsi_bufflen(cmd) - len);
316                 }
317                 cmd->result = DID_OK << 16;
318                 goto done;
319         }
320
321         if (cmd->cmnd[0] == REQUEST_SENSE) {
322                 /* SCSI spec says request sense should never get error */
323                 dev_err(&dev->sbd.core, "%s:%u: end error without autosense\n",
324                         __func__, __LINE__);
325                 cmd->result = DID_ERROR << 16 | SAM_STAT_CHECK_CONDITION;
326                 goto done;
327         }
328
329         if (decode_lv1_status(status, &sense_key, &asc, &ascq)) {
330                 cmd->result = DID_ERROR << 16;
331                 goto done;
332         }
333
334         scsi_build_sense_buffer(0, cmd->sense_buffer, sense_key, asc, ascq);
335         cmd->result = SAM_STAT_CHECK_CONDITION;
336
337 done:
338         priv->curr_cmd = NULL;
339         cmd->scsi_done(cmd);
340         return IRQ_HANDLED;
341 }
342
343 static struct scsi_host_template ps3rom_host_template = {
344         .name =                 DEVICE_NAME,
345         .slave_configure =      ps3rom_slave_configure,
346         .queuecommand =         ps3rom_queuecommand,
347         .can_queue =            1,
348         .this_id =              7,
349         .sg_tablesize =         SG_ALL,
350         .cmd_per_lun =          1,
351         .emulated =             1,              /* only sg driver uses this */
352         .max_sectors =          PS3ROM_MAX_SECTORS,
353         .use_clustering =       ENABLE_CLUSTERING,
354         .module =               THIS_MODULE,
355 };
356
357
358 static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev)
359 {
360         struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
361         int error;
362         struct Scsi_Host *host;
363         struct ps3rom_private *priv;
364
365         if (dev->blk_size != CD_FRAMESIZE) {
366                 dev_err(&dev->sbd.core,
367                         "%s:%u: cannot handle block size %llu\n", __func__,
368                         __LINE__, dev->blk_size);
369                 return -EINVAL;
370         }
371
372         dev->bounce_size = BOUNCE_SIZE;
373         dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
374         if (!dev->bounce_buf)
375                 return -ENOMEM;
376
377         error = ps3stor_setup(dev, ps3rom_interrupt);
378         if (error)
379                 goto fail_free_bounce;
380
381         host = scsi_host_alloc(&ps3rom_host_template,
382                                sizeof(struct ps3rom_private));
383         if (!host) {
384                 dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed\n",
385                         __func__, __LINE__);
386                 goto fail_teardown;
387         }
388
389         priv = shost_priv(host);
390         dev->sbd.core.driver_data = host;
391         priv->dev = dev;
392
393         /* One device/LUN per SCSI bus */
394         host->max_id = 1;
395         host->max_lun = 1;
396
397         error = scsi_add_host(host, &dev->sbd.core);
398         if (error) {
399                 dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed %d\n",
400                         __func__, __LINE__, error);
401                 error = -ENODEV;
402                 goto fail_host_put;
403         }
404
405         scsi_scan_host(host);
406         return 0;
407
408 fail_host_put:
409         scsi_host_put(host);
410         dev->sbd.core.driver_data = NULL;
411 fail_teardown:
412         ps3stor_teardown(dev);
413 fail_free_bounce:
414         kfree(dev->bounce_buf);
415         return error;
416 }
417
418 static int ps3rom_remove(struct ps3_system_bus_device *_dev)
419 {
420         struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
421         struct Scsi_Host *host = dev->sbd.core.driver_data;
422
423         scsi_remove_host(host);
424         ps3stor_teardown(dev);
425         scsi_host_put(host);
426         dev->sbd.core.driver_data = NULL;
427         kfree(dev->bounce_buf);
428         return 0;
429 }
430
431 static struct ps3_system_bus_driver ps3rom = {
432         .match_id       = PS3_MATCH_ID_STOR_ROM,
433         .core.name      = DEVICE_NAME,
434         .core.owner     = THIS_MODULE,
435         .probe          = ps3rom_probe,
436         .remove         = ps3rom_remove
437 };
438
439
440 static int __init ps3rom_init(void)
441 {
442         return ps3_system_bus_driver_register(&ps3rom);
443 }
444
445 static void __exit ps3rom_exit(void)
446 {
447         ps3_system_bus_driver_unregister(&ps3rom);
448 }
449
450 module_init(ps3rom_init);
451 module_exit(ps3rom_exit);
452
453 MODULE_LICENSE("GPL");
454 MODULE_DESCRIPTION("PS3 BD/DVD/CD-ROM Storage Driver");
455 MODULE_AUTHOR("Sony Corporation");
456 MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_ROM);