]> err.no Git - linux-2.6/blob - drivers/scsi/ps3rom.c
[SCSI] ps3rom: Simplify fill_from_dev_buffer()
[linux-2.6] / 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
30 #include <asm/lv1call.h>
31 #include <asm/ps3stor.h>
32
33
34 #define DEVICE_NAME                     "ps3rom"
35
36 #define BOUNCE_SIZE                     (64*1024)
37
38 #define PS3ROM_MAX_SECTORS              (BOUNCE_SIZE >> 9)
39
40
41 struct ps3rom_private {
42         struct ps3_storage_device *dev;
43         struct scsi_cmnd *curr_cmd;
44 };
45
46
47 #define LV1_STORAGE_SEND_ATAPI_COMMAND  (1)
48
49 struct lv1_atapi_cmnd_block {
50         u8      pkt[32];        /* packet command block           */
51         u32     pktlen;         /* should be 12 for ATAPI 8020    */
52         u32     blocks;
53         u32     block_size;
54         u32     proto;          /* transfer mode                  */
55         u32     in_out;         /* transfer direction             */
56         u64     buffer;         /* parameter except command block */
57         u32     arglen;         /* length above                   */
58 };
59
60 enum lv1_atapi_proto {
61         NON_DATA_PROTO     = 0,
62         PIO_DATA_IN_PROTO  = 1,
63         PIO_DATA_OUT_PROTO = 2,
64         DMA_PROTO = 3
65 };
66
67 enum lv1_atapi_in_out {
68         DIR_WRITE = 0,          /* memory -> device */
69         DIR_READ = 1            /* device -> memory */
70 };
71
72
73 static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
74 {
75         struct ps3rom_private *priv = shost_priv(scsi_dev->host);
76         struct ps3_storage_device *dev = priv->dev;
77
78         dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %u, channel %u\n", __func__,
79                 __LINE__, scsi_dev->id, scsi_dev->lun, scsi_dev->channel);
80
81         /*
82          * ATAPI SFF8020 devices use MODE_SENSE_10,
83          * so we can prohibit MODE_SENSE_6
84          */
85         scsi_dev->use_10_for_ms = 1;
86
87         /* we don't support {READ,WRITE}_6 */
88         scsi_dev->use_10_for_rw = 1;
89
90         return 0;
91 }
92
93 /*
94  * copy data from device into scatter/gather buffer
95  */
96 static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
97 {
98         int k, req_len, len, fin;
99         void *kaddr;
100         struct scatterlist *sgpnt;
101         unsigned int buflen;
102
103         buflen = scsi_bufflen(cmd);
104         if (!buflen)
105                 return 0;
106
107         if (!scsi_sglist(cmd))
108                 return -1;
109
110         req_len = fin = 0;
111         scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
112                 kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
113                 len = sgpnt->length;
114                 if ((req_len + len) > buflen) {
115                         len = buflen - req_len;
116                         fin = 1;
117                 }
118                 memcpy(kaddr + sgpnt->offset, buf + req_len, len);
119                 flush_kernel_dcache_page(sg_page(sgpnt));
120                 kunmap_atomic(kaddr, KM_IRQ0);
121                 req_len += len;
122                 if (fin)
123                         break;
124         }
125         scsi_set_resid(cmd, buflen - req_len);
126         return 0;
127 }
128
129 /*
130  * copy data from scatter/gather into device's buffer
131  */
132 static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf)
133 {
134         int k, req_len, len, fin;
135         void *kaddr;
136         struct scatterlist *sgpnt;
137         unsigned int buflen;
138
139         buflen = scsi_bufflen(cmd);
140         if (!buflen)
141                 return 0;
142
143         if (!scsi_sglist(cmd))
144                 return -1;
145
146         req_len = fin = 0;
147         scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) {
148                 kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0);
149                 len = sgpnt->length;
150                 if ((req_len + len) > buflen) {
151                         len = buflen - req_len;
152                         fin = 1;
153                 }
154                 memcpy(buf + req_len, kaddr + sgpnt->offset, len);
155                 kunmap_atomic(kaddr, KM_IRQ0);
156                 if (fin)
157                         return req_len + len;
158                 req_len += sgpnt->length;
159         }
160         return req_len;
161 }
162
163 static int ps3rom_atapi_request(struct ps3_storage_device *dev,
164                                 struct scsi_cmnd *cmd)
165 {
166         struct lv1_atapi_cmnd_block atapi_cmnd;
167         unsigned char opcode = cmd->cmnd[0];
168         int res;
169         u64 lpar;
170
171         dev_dbg(&dev->sbd.core, "%s:%u: send ATAPI command 0x%02x\n", __func__,
172                 __LINE__, opcode);
173
174         memset(&atapi_cmnd, 0, sizeof(struct lv1_atapi_cmnd_block));
175         memcpy(&atapi_cmnd.pkt, cmd->cmnd, 12);
176         atapi_cmnd.pktlen = 12;
177         atapi_cmnd.block_size = 1; /* transfer size is block_size * blocks */
178         atapi_cmnd.blocks = atapi_cmnd.arglen = scsi_bufflen(cmd);
179         atapi_cmnd.buffer = dev->bounce_lpar;
180
181         switch (cmd->sc_data_direction) {
182         case DMA_FROM_DEVICE:
183                 if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
184                         atapi_cmnd.proto = DMA_PROTO;
185                 else
186                         atapi_cmnd.proto = PIO_DATA_IN_PROTO;
187                 atapi_cmnd.in_out = DIR_READ;
188                 break;
189
190         case DMA_TO_DEVICE:
191                 if (scsi_bufflen(cmd) >= CD_FRAMESIZE)
192                         atapi_cmnd.proto = DMA_PROTO;
193                 else
194                         atapi_cmnd.proto = PIO_DATA_OUT_PROTO;
195                 atapi_cmnd.in_out = DIR_WRITE;
196                 res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
197                 if (res < 0)
198                         return DID_ERROR << 16;
199                 break;
200
201         default:
202                 atapi_cmnd.proto = NON_DATA_PROTO;
203                 break;
204         }
205
206         lpar = ps3_mm_phys_to_lpar(__pa(&atapi_cmnd));
207         res = lv1_storage_send_device_command(dev->sbd.dev_id,
208                                               LV1_STORAGE_SEND_ATAPI_COMMAND,
209                                               lpar, sizeof(atapi_cmnd),
210                                               atapi_cmnd.buffer,
211                                               atapi_cmnd.arglen, &dev->tag);
212         if (res == LV1_DENIED_BY_POLICY) {
213                 dev_dbg(&dev->sbd.core,
214                         "%s:%u: ATAPI command 0x%02x denied by policy\n",
215                         __func__, __LINE__, opcode);
216                 return DID_ERROR << 16;
217         }
218
219         if (res) {
220                 dev_err(&dev->sbd.core,
221                         "%s:%u: ATAPI command 0x%02x failed %d\n", __func__,
222                         __LINE__, opcode, res);
223                 return DID_ERROR << 16;
224         }
225
226         return 0;
227 }
228
229 static inline unsigned int srb10_lba(const struct scsi_cmnd *cmd)
230 {
231         return cmd->cmnd[2] << 24 | cmd->cmnd[3] << 16 | cmd->cmnd[4] << 8 |
232                cmd->cmnd[5];
233 }
234
235 static inline unsigned int srb10_len(const struct scsi_cmnd *cmd)
236 {
237         return cmd->cmnd[7] << 8 | cmd->cmnd[8];
238 }
239
240 static int ps3rom_read_request(struct ps3_storage_device *dev,
241                                struct scsi_cmnd *cmd, u32 start_sector,
242                                u32 sectors)
243 {
244         int res;
245
246         dev_dbg(&dev->sbd.core, "%s:%u: read %u sectors starting at %u\n",
247                 __func__, __LINE__, sectors, start_sector);
248
249         res = lv1_storage_read(dev->sbd.dev_id,
250                                dev->regions[dev->region_idx].id, start_sector,
251                                sectors, 0, dev->bounce_lpar, &dev->tag);
252         if (res) {
253                 dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__,
254                         __LINE__, res);
255                 return DID_ERROR << 16;
256         }
257
258         return 0;
259 }
260
261 static int ps3rom_write_request(struct ps3_storage_device *dev,
262                                 struct scsi_cmnd *cmd, u32 start_sector,
263                                 u32 sectors)
264 {
265         int res;
266
267         dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n",
268                 __func__, __LINE__, sectors, start_sector);
269
270         res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
271         if (res < 0)
272                 return DID_ERROR << 16;
273
274         res = lv1_storage_write(dev->sbd.dev_id,
275                                 dev->regions[dev->region_idx].id, start_sector,
276                                 sectors, 0, dev->bounce_lpar, &dev->tag);
277         if (res) {
278                 dev_err(&dev->sbd.core, "%s:%u: write failed %d\n", __func__,
279                         __LINE__, res);
280                 return DID_ERROR << 16;
281         }
282
283         return 0;
284 }
285
286 static int ps3rom_queuecommand(struct scsi_cmnd *cmd,
287                                void (*done)(struct scsi_cmnd *))
288 {
289         struct ps3rom_private *priv = shost_priv(cmd->device->host);
290         struct ps3_storage_device *dev = priv->dev;
291         unsigned char opcode;
292         int res;
293
294 #ifdef DEBUG
295         scsi_print_command(cmd);
296 #endif
297
298         priv->curr_cmd = cmd;
299         cmd->scsi_done = done;
300
301         opcode = cmd->cmnd[0];
302         /*
303          * While we can submit READ/WRITE SCSI commands as ATAPI commands,
304          * it's recommended for various reasons (performance, error handling,
305          * ...) to use lv1_storage_{read,write}() instead
306          */
307         switch (opcode) {
308         case READ_10:
309                 res = ps3rom_read_request(dev, cmd, srb10_lba(cmd),
310                                           srb10_len(cmd));
311                 break;
312
313         case WRITE_10:
314                 res = ps3rom_write_request(dev, cmd, srb10_lba(cmd),
315                                            srb10_len(cmd));
316                 break;
317
318         default:
319                 res = ps3rom_atapi_request(dev, cmd);
320                 break;
321         }
322
323         if (res) {
324                 memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
325                 cmd->result = res;
326                 cmd->sense_buffer[0] = 0x70;
327                 cmd->sense_buffer[2] = ILLEGAL_REQUEST;
328                 priv->curr_cmd = NULL;
329                 cmd->scsi_done(cmd);
330         }
331
332         return 0;
333 }
334
335 static int decode_lv1_status(u64 status, unsigned char *sense_key,
336                              unsigned char *asc, unsigned char *ascq)
337 {
338         if (((status >> 24) & 0xff) != SAM_STAT_CHECK_CONDITION)
339                 return -1;
340
341         *sense_key = (status >> 16) & 0xff;
342         *asc       = (status >>  8) & 0xff;
343         *ascq      =  status        & 0xff;
344         return 0;
345 }
346
347 static irqreturn_t ps3rom_interrupt(int irq, void *data)
348 {
349         struct ps3_storage_device *dev = data;
350         struct Scsi_Host *host;
351         struct ps3rom_private *priv;
352         struct scsi_cmnd *cmd;
353         int res;
354         u64 tag, status;
355         unsigned char sense_key, asc, ascq;
356
357         res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
358         /*
359          * status = -1 may mean that ATAPI transport completed OK, but
360          * ATAPI command itself resulted CHECK CONDITION
361          * so, upper layer should issue REQUEST_SENSE to check the sense data
362          */
363
364         if (tag != dev->tag)
365                 dev_err(&dev->sbd.core,
366                         "%s:%u: tag mismatch, got %lx, expected %lx\n",
367                         __func__, __LINE__, tag, dev->tag);
368
369         if (res) {
370                 dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n",
371                         __func__, __LINE__, res, status);
372                 return IRQ_HANDLED;
373         }
374
375         host = dev->sbd.core.driver_data;
376         priv = shost_priv(host);
377         cmd = priv->curr_cmd;
378
379         if (!status) {
380                 /* OK, completed */
381                 if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
382                         res = fill_from_dev_buffer(cmd, dev->bounce_buf);
383                         if (res) {
384                                 cmd->result = DID_ERROR << 16;
385                                 goto done;
386                         }
387                 }
388                 cmd->result = DID_OK << 16;
389                 goto done;
390         }
391
392         if (cmd->cmnd[0] == REQUEST_SENSE) {
393                 /* SCSI spec says request sense should never get error */
394                 dev_err(&dev->sbd.core, "%s:%u: end error without autosense\n",
395                         __func__, __LINE__);
396                 cmd->result = DID_ERROR << 16 | SAM_STAT_CHECK_CONDITION;
397                 goto done;
398         }
399
400         if (decode_lv1_status(status, &sense_key, &asc, &ascq)) {
401                 cmd->result = DID_ERROR << 16;
402                 goto done;
403         }
404
405         cmd->sense_buffer[0]  = 0x70;
406         cmd->sense_buffer[2]  = sense_key;
407         cmd->sense_buffer[7]  = 16 - 6;
408         cmd->sense_buffer[12] = asc;
409         cmd->sense_buffer[13] = ascq;
410         cmd->result = SAM_STAT_CHECK_CONDITION;
411
412 done:
413         priv->curr_cmd = NULL;
414         cmd->scsi_done(cmd);
415         return IRQ_HANDLED;
416 }
417
418 static struct scsi_host_template ps3rom_host_template = {
419         .name =                 DEVICE_NAME,
420         .slave_configure =      ps3rom_slave_configure,
421         .queuecommand =         ps3rom_queuecommand,
422         .can_queue =            1,
423         .this_id =              7,
424         .sg_tablesize =         SG_ALL,
425         .cmd_per_lun =          1,
426         .emulated =             1,              /* only sg driver uses this */
427         .max_sectors =          PS3ROM_MAX_SECTORS,
428         .use_clustering =       DISABLE_CLUSTERING,
429         .module =               THIS_MODULE,
430 };
431
432
433 static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev)
434 {
435         struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
436         int error;
437         struct Scsi_Host *host;
438         struct ps3rom_private *priv;
439
440         if (dev->blk_size != CD_FRAMESIZE) {
441                 dev_err(&dev->sbd.core,
442                         "%s:%u: cannot handle block size %lu\n", __func__,
443                         __LINE__, dev->blk_size);
444                 return -EINVAL;
445         }
446
447         dev->bounce_size = BOUNCE_SIZE;
448         dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
449         if (!dev->bounce_buf)
450                 return -ENOMEM;
451
452         error = ps3stor_setup(dev, ps3rom_interrupt);
453         if (error)
454                 goto fail_free_bounce;
455
456         host = scsi_host_alloc(&ps3rom_host_template,
457                                sizeof(struct ps3rom_private));
458         if (!host) {
459                 dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed\n",
460                         __func__, __LINE__);
461                 goto fail_teardown;
462         }
463
464         priv = shost_priv(host);
465         dev->sbd.core.driver_data = host;
466         priv->dev = dev;
467
468         /* One device/LUN per SCSI bus */
469         host->max_id = 1;
470         host->max_lun = 1;
471
472         error = scsi_add_host(host, &dev->sbd.core);
473         if (error) {
474                 dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed %d\n",
475                         __func__, __LINE__, error);
476                 error = -ENODEV;
477                 goto fail_host_put;
478         }
479
480         scsi_scan_host(host);
481         return 0;
482
483 fail_host_put:
484         scsi_host_put(host);
485         dev->sbd.core.driver_data = NULL;
486 fail_teardown:
487         ps3stor_teardown(dev);
488 fail_free_bounce:
489         kfree(dev->bounce_buf);
490         return error;
491 }
492
493 static int ps3rom_remove(struct ps3_system_bus_device *_dev)
494 {
495         struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
496         struct Scsi_Host *host = dev->sbd.core.driver_data;
497
498         scsi_remove_host(host);
499         ps3stor_teardown(dev);
500         scsi_host_put(host);
501         dev->sbd.core.driver_data = NULL;
502         kfree(dev->bounce_buf);
503         return 0;
504 }
505
506 static struct ps3_system_bus_driver ps3rom = {
507         .match_id       = PS3_MATCH_ID_STOR_ROM,
508         .core.name      = DEVICE_NAME,
509         .core.owner     = THIS_MODULE,
510         .probe          = ps3rom_probe,
511         .remove         = ps3rom_remove
512 };
513
514
515 static int __init ps3rom_init(void)
516 {
517         return ps3_system_bus_driver_register(&ps3rom);
518 }
519
520 static void __exit ps3rom_exit(void)
521 {
522         ps3_system_bus_driver_unregister(&ps3rom);
523 }
524
525 module_init(ps3rom_init);
526 module_exit(ps3rom_exit);
527
528 MODULE_LICENSE("GPL");
529 MODULE_DESCRIPTION("PS3 BD/DVD/CD-ROM Storage Driver");
530 MODULE_AUTHOR("Sony Corporation");
531 MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_ROM);