Want more features on Pastebin? Sign Up, it's FREE!
Guest

PS3 STEP 3 Sony a New Hacking Dev

By: a guest on Sep 30th, 2012  |  syntax: None  |  size: 15.38 KB  |  views: 161  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. Step 3 :
  2.  
  3. Welcome to the world of Sony
  4.  
  5. I just want to say a hello to Geo (no the one you are thinking) and tell him that
  6.  
  7. Remember 2OFive ? Are you making a new dongle, the first commercial one was not enough ? Sony Still keep the dongle plan alive (win money with commercial hacking/piracy) ? SONY MAKE.BELIEVE PIRACY ;)
  8.  
  9. Anyway
  10.  
  11. Back to the past
  12.  
  13. +#define DEVICE_NAME            "ps3disk"
  14. +
  15. +#define BOUNCE_SIZE            (64*1024)
  16. +
  17. +#define PS3DISK_MAX_DISKS      16
  18. +#define PS3DISK_MINORS         16
  19. +
  20. +#define KERNEL_SECTOR_SIZE     512
  21. +
  22. +
  23. +#define PS3DISK_NAME           "ps3d%c"
  24. +
  25. +
  26. +struct ps3disk_private {
  27. +       spinlock_t lock;                /* Request queue spinlock */
  28. +       struct request_queue *queue;
  29. +       struct gendisk *gendisk;
  30. +       unsigned int blocking_factor;
  31. +       struct request *req;
  32. +       u64 raw_capacity;
  33. +       unsigned char model[ATA_ID_PROD_LEN+1];
  34. +};
  35. +#define ps3disk_priv(dev)      ((dev)->sbd.core.driver_data)
  36. +
  37. +
  38. +#define LV1_STORAGE_SEND_ATA_COMMAND   (2)
  39. +#define LV1_STORAGE_ATA_HDDOUT         (0x23)
  40. +
  41. +struct lv1_ata_cmnd_block {
  42. +       u16     features;
  43. +       u16     sector_count;
  44. +       u16     LBA_low;
  45. +       u16     LBA_mid;
  46. +       u16     LBA_high;
  47. +       u8      device;
  48. +       u8      command;
  49. +       u32     is_ext;
  50. +       u32     proto;
  51. +       u32     in_out;
  52. +       u32     size;
  53. +       u64     buffer;
  54. +       u32     arglen;
  55. +};
  56. +
  57. +enum lv1_ata_proto {
  58. +       NON_DATA_PROTO     = 0,
  59. +       PIO_DATA_IN_PROTO  = 1,
  60. +       PIO_DATA_OUT_PROTO = 2,
  61. +       DMA_PROTO = 3
  62. +};
  63. +
  64. +enum lv1_ata_in_out {
  65. +       DIR_WRITE = 0,                  /* memory -> device */
  66. +       DIR_READ = 1                    /* device -> memory */
  67. +};
  68. +
  69. +static int ps3disk_major;
  70. +
  71. +
  72. +static struct block_device_operations ps3disk_fops = {
  73. +       .owner          = THIS_MODULE,
  74. +};
  75. +
  76. +
  77. +static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
  78. +                                  struct request *req, int gather)
  79. +{
  80. +       unsigned int sectors = 0, offset = 0;
  81. +       struct bio *bio;
  82. +       sector_t sector;
  83. +       struct bio_vec *bvec;
  84. +       unsigned int i = 0, j;
  85. +       size_t size;
  86. +       void *buf;
  87. +
  88. +       rq_for_each_bio(bio, req) {
  89. +               sector = bio->bi_sector;
  90. +               dev_dbg(&dev->sbd.core,
  91. +                       "%s:%u: bio %u: %u segs %u sectors from %lu\n",
  92. +                       __func__, __LINE__, i, bio_segments(bio),
  93. +                       bio_sectors(bio), sector);
  94. +               bio_for_each_segment(bvec, bio, j) {
  95. +                       size = bio_cur_sectors(bio)*KERNEL_SECTOR_SIZE;
  96. +                       buf = __bio_kmap_atomic(bio, j, KM_IRQ0);
  97. +                       if (gather)
  98. +                               memcpy(dev->bounce_buf+offset, buf, size);
  99. +                       else
  100. +                               memcpy(buf, dev->bounce_buf+offset, size);
  101. +                       offset += size;
  102. +                       flush_kernel_dcache_page(bio_iovec_idx(bio, j)->bv_page);
  103. +                       __bio_kunmap_atomic(bio, KM_IRQ0);
  104. +               }
  105. +               sectors += bio_sectors(bio);
  106. +               i++;
  107. +       }
  108. +}
  109. +
  110. +static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
  111. +                                    struct request *req)
  112. +{
  113. +       struct ps3disk_private *priv = ps3disk_priv(dev);
  114. +       int write = rq_data_dir(req), res;
  115. +       const char *op = write ? "write" : "read";
  116. +       u64 start_sector, sectors;
  117. +       unsigned int region_id = dev->regions[dev->region_idx].id;
  118. +
  119. +#ifdef DEBUG
  120. +       unsigned int n = 0;
  121. +       struct bio *bio;
  122. +       rq_for_each_bio(bio, req)
  123. +               n++;
  124. +       dev_dbg(&dev->sbd.core,
  125. +               "%s:%u: %s req has %u bios for %lu sectors %lu hard sectors\n",
  126. +               __func__, __LINE__, op, n, req->nr_sectors,
  127. +               req->hard_nr_sectors);
  128. +#endif
  129. +
  130. +       start_sector = req->sector*priv->blocking_factor;
  131. +       sectors = req->nr_sectors*priv->blocking_factor;
  132. +       dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
  133. +               __func__, __LINE__, op, sectors, start_sector);
  134. +
  135. +       if (write) {
  136. +               ps3disk_scatter_gather(dev, req, 1);
  137. +
  138. +               res = lv1_storage_write(dev->sbd.dev_id, region_id,
  139. +                                       start_sector, sectors, 0,
  140. +                                       dev->bounce_lpar, &dev->tag);
  141. +       } else {
  142. +               res = lv1_storage_read(dev->sbd.dev_id, region_id,
  143. +                                      start_sector, sectors, 0,
  144. +                                      dev->bounce_lpar, &dev->tag);
  145. +       }
  146. +       if (res) {
  147. +               dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
  148. +                       __LINE__, op, res);
  149. +               end_request(req, 0);
  150. +               return 0;
  151. +       }
  152. +
  153. +       priv->req = req;
  154. +       return 1;
  155. +}
  156. +
  157. +static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
  158. +                                       struct request *req)
  159. +{
  160. +       struct ps3disk_private *priv = ps3disk_priv(dev);
  161. +       u64 res;
  162. +
  163. +       dev_dbg(&dev->sbd.core, "%s:%u: flush request\n", __func__, __LINE__);
  164. +
  165. +       res = lv1_storage_send_device_command(dev->sbd.dev_id,
  166. +                                             LV1_STORAGE_ATA_HDDOUT, 0, 0, 0,
  167. +                                             0, &dev->tag);
  168. +       if (res) {
  169. +               dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%lx\n",
  170. +                       __func__, __LINE__, res);
  171. +               end_request(req, 0);
  172. +               return 0;
  173. +       }
  174. +
  175. +       priv->req = req;
  176. +       return 1;
  177. +}
  178. +
  179. +static void ps3disk_do_request(struct ps3_storage_device *dev,
  180. +                              request_queue_t *q)
  181. +{
  182. +       struct request *req;
  183. +
  184. +       dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
  185. +
  186. +       while ((req = elv_next_request(q))) {
  187. +               if (blk_fs_request(req)) {
  188. +                       if (ps3disk_submit_request_sg(dev, req))
  189. +                               break;
  190. +               } else if (req->cmd_type == REQ_TYPE_FLUSH) {
  191. +                       if (ps3disk_submit_flush_request(dev, req))
  192. +                               break;
  193. +               } else {
  194. +                       blk_dump_rq_flags(req, DEVICE_NAME " bad request");
  195. +                       end_request(req, 0);
  196. +                       continue;
  197. +               }
  198. +       }
  199. +}
  200. +
  201. +static void ps3disk_request(request_queue_t *q)
  202. +{
  203. +       struct ps3_storage_device *dev = q->queuedata;
  204. +       struct ps3disk_private *priv = ps3disk_priv(dev);
  205. +
  206. +       if (priv->req) {
  207. +               dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__);
  208. +               return;
  209. +       }
  210. +
  211. +       ps3disk_do_request(dev, q);
  212. +}
  213. +
  214. +static irqreturn_t ps3disk_interrupt(int irq, void *data)
  215. +{
  216. +       struct ps3_storage_device *dev = data;
  217. +       struct ps3disk_private *priv;
  218. +       struct request *req;
  219. +       int res, read, uptodate;
  220. +       u64 tag, status;
  221. +       unsigned long num_sectors;
  222. +       const char *op;
  223. +
  224. +       res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
  225. +
  226. +       if (tag != dev->tag)
  227. +               dev_err(&dev->sbd.core,
  228. +                       "%s:%u: tag mismatch, got %lx, expected %lx\n",
  229. +                       __func__, __LINE__, tag, dev->tag);
  230. +
  231. +       if (res) {
  232. +               dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n",
  233. +                       __func__, __LINE__, res, status);
  234. +               return IRQ_HANDLED;
  235. +       }
  236. +
  237. +       priv = ps3disk_priv(dev);
  238. +       req = priv->req;
  239. +       if (!req) {
  240. +               dev_dbg(&dev->sbd.core,
  241. +                       "%s:%u non-block layer request completed\n", __func__,
  242. +                       __LINE__);
  243. +               dev->lv1_status = status;
  244. +               complete(&dev->done);
  245. +               return IRQ_HANDLED;
  246. +       }
  247. +
  248. +       if (req->cmd_type == REQ_TYPE_FLUSH) {
  249. +               read = 0;
  250. +               num_sectors = req->hard_cur_sectors;
  251. +               op = "flush";
  252. +       } else {
  253. +               read = !rq_data_dir(req);
  254. +               num_sectors = req->nr_sectors;
  255. +               op = read ? "read" : "write";
  256. +       }
  257. +       if (status) {
  258. +               dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
  259. +                       __LINE__, op, status);
  260. +               uptodate = 0;
  261. +       } else {
  262. +               dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
  263. +                       __LINE__, op);
  264. +               uptodate = 1;
  265. +               if (read)
  266. +                       ps3disk_scatter_gather(dev, req, 0);
  267. +       }
  268. +
  269. +       spin_lock(&priv->lock);
  270. +       if (!end_that_request_first(req, uptodate, num_sectors)) {
  271. +               add_disk_randomness(req->rq_disk);
  272. +               blkdev_dequeue_request(req);
  273. +               end_that_request_last(req, uptodate);
  274. +       }
  275. +       priv->req = NULL;
  276. +       ps3disk_do_request(dev, priv->queue);
  277. +       spin_unlock(&priv->lock);
  278. +
  279. +       return IRQ_HANDLED;
  280. +}
  281. +
  282. +static int ps3disk_sync_cache(struct ps3_storage_device *dev)
  283. +{
  284. +       u64 res;
  285. +
  286. +       dev_dbg(&dev->sbd.core, "%s:%u: sync cache\n", __func__, __LINE__);
  287. +
  288. +       res = ps3stor_send_command(dev, LV1_STORAGE_ATA_HDDOUT, 0, 0, 0, 0);
  289. +       if (res) {
  290. +               dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%lx\n",
  291. +                       __func__, __LINE__, res);
  292. +               return -EIO;
  293. +       }
  294. +       return 0;
  295. +}
  296. +
  297. +
  298. +/* ATA helpers copied from drivers/ata/libata-core.c */
  299. +
  300. +static void swap_buf_le16(u16 *buf, unsigned int buf_words)
  301. +{
  302. +#ifdef __BIG_ENDIAN
  303. +       unsigned int i;
  304. +
  305. +       for (i = 0; i < buf_words; i++)
  306. +               buf[i] = le16_to_cpu(buf[i]);
  307. +#endif /* __BIG_ENDIAN */
  308. +}
  309. +
  310. +static u64 ata_id_n_sectors(const u16 *id)
  311. +{
  312. +       if (ata_id_has_lba(id)) {
  313. +               if (ata_id_has_lba48(id))
  314. +                       return ata_id_u64(id, 100);
  315. +               else
  316. +                       return ata_id_u32(id, 60);
  317. +       } else {
  318. +               if (ata_id_current_chs_valid(id))
  319. +                       return ata_id_u32(id, 57);
  320. +               else
  321. +                       return id[1] * id[3] * id[6];
  322. +       }
  323. +}
  324. +
  325. +static void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs,
  326. +                         unsigned int len)
  327. +{
  328. +       unsigned int c;
  329. +
  330. +       while (len > 0) {
  331. +               c = id[ofs] >> 8;
  332. +               *s = c;
  333. +               s++;
  334. +
  335. +               c = id[ofs] & 0xff;
  336. +               *s = c;
  337. +               s++;
  338. +
  339. +               ofs++;
  340. +               len -= 2;
  341. +       }
  342. +}
  343. +
  344. +static void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs,
  345. +                           unsigned int len)
  346. +{
  347. +       unsigned char *p;
  348. +
  349. +       WARN_ON(!(len & 1));
  350. +
  351. +       ata_id_string(id, s, ofs, len - 1);
  352. +
  353. +       p = s + strnlen(s, len - 1);
  354. +       while (p > s && p[-1] == ' ')
  355. +               p--;
  356. +       *p = '\0';
  357. +}
  358. +
  359. +static int ps3disk_identify(struct ps3_storage_device *dev)
  360. +{
  361. +       struct ps3disk_private *priv = ps3disk_priv(dev);
  362. +       struct lv1_ata_cmnd_block ata_cmnd;
  363. +       u16 *id = dev->bounce_buf;
  364. +       u64 res;
  365. +
  366. +       dev_dbg(&dev->sbd.core, "%s:%u: identify disk\n", __func__, __LINE__);
  367. +
  368. +       memset(&ata_cmnd, 0, sizeof(struct lv1_ata_cmnd_block));
  369. +       ata_cmnd.command = ATA_CMD_ID_ATA;
  370. +       ata_cmnd.sector_count = 1;
  371. +       ata_cmnd.size = ata_cmnd.arglen = ATA_ID_WORDS * 2;
  372. +       ata_cmnd.buffer = dev->bounce_lpar;
  373. +       ata_cmnd.proto = PIO_DATA_IN_PROTO;
  374. +       ata_cmnd.in_out = DIR_READ;
  375. +
  376. +       res = ps3stor_send_command(dev, LV1_STORAGE_SEND_ATA_COMMAND,
  377. +                                  ps3_mm_phys_to_lpar(__pa(&ata_cmnd)),
  378. +                                  sizeof(ata_cmnd), ata_cmnd.buffer,
  379. +                                  ata_cmnd.arglen);
  380. +       if (res) {
  381. +               dev_err(&dev->sbd.core, "%s:%u: identify disk failed 0x%lx\n",
  382. +                       __func__, __LINE__, res);
  383. +               return -EIO;
  384. +       }
  385. +
  386. +       swap_buf_le16(id, ATA_ID_WORDS);
  387. +
  388. +       /* All we're interested in are raw capacity and model name */
  389. +       priv->raw_capacity = ata_id_n_sectors(id);
  390. +       ata_id_c_string(id, priv->model, ATA_ID_PROD, sizeof(priv->model));
  391. +       return 0;
  392. +}
  393. +
  394. +static void ps3disk_prepare_flush(request_queue_t *q, struct request *req)
  395. +{
  396. +       struct ps3_storage_device *dev = q->queuedata;
  397. +
  398. +       dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
  399. +
  400. +       memset(req->cmd, 0, sizeof(req->cmd));
  401. +       req->cmd_type = REQ_TYPE_FLUSH;
  402. +}
  403. +
  404. +static int ps3disk_issue_flush(request_queue_t *q, struct gendisk *gendisk,
  405. +                              sector_t *sector)
  406. +{
  407. +       struct ps3_storage_device *dev = q->queuedata;
  408. +       struct request *req;
  409. +       int res;
  410. +
  411. +       dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
  412. +
  413. +       req = blk_get_request(q, WRITE, __GFP_WAIT);
  414. +       ps3disk_prepare_flush(q, req);
  415. +       res = blk_execute_rq(q, gendisk, req, 0);
  416. +       if (res)
  417. +               dev_err(&dev->sbd.core, "%s:%u: flush request failed %d\n",
  418. +                       __func__, __LINE__, res);
  419. +       blk_put_request(req);
  420. +       return res;
  421. +}
  422. +
  423. +
  424. +static unsigned long ps3disk_mask;
  425. +
  426. +static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
  427. +{
  428. +       struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
  429. +       struct ps3disk_private *priv;
  430. +       int error;
  431. +       unsigned int devidx;
  432. +       struct request_queue *queue;
  433. +       struct gendisk *gendisk;
  434. +
  435. +       if (dev->blk_size < KERNEL_SECTOR_SIZE) {
  436. +               dev_err(&dev->sbd.core,
  437. +                       "%s:%u: cannot handle block size %lu\n", __func__,
  438. +                       __LINE__, dev->blk_size);
  439. +               return -EINVAL;
  440. +       }
  441. +
  442. +       BUILD_BUG_ON(PS3DISK_MAX_DISKS > BITS_PER_LONG);
  443. +       devidx = find_first_zero_bit(&ps3disk_mask, PS3DISK_MAX_DISKS);
  444. +       if (devidx >= PS3DISK_MAX_DISKS) {
  445. +               dev_err(&dev->sbd.core, "%s:%u: Too many disks\n", __func__,
  446. +                       __LINE__);
  447. +               return -ENOSPC;
  448. +       }
  449. +       __set_bit(devidx, &ps3disk_mask);
  450. +
  451. +       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  452. +       if (!priv) {
  453. +               error = -ENOMEM;
  454. +               goto fail;
  455. +       }
  456. +
  457. +       ps3disk_priv(dev) = priv;
  458. +       spin_lock_init(&priv->lock);
  459. +
  460. +       dev->bounce_size = BOUNCE_SIZE;
  461. +       dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
  462. +       if (!dev->bounce_buf) {
  463. +               error = -ENOMEM;
  464. +               goto fail_free_priv;
  465. +       }
  466. +
  467. +       error = ps3stor_setup(dev, ps3disk_interrupt);
  468. +       if (error)
  469. +               goto fail_free_bounce;
  470. +
  471. +       ps3disk_identify(dev);
  472. +
  473. +       queue = blk_init_queue(ps3disk_request, &priv->lock);
  474. +       if (!queue) {
  475. +               dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n",
  476. +                       __func__, __LINE__);
  477. +               error = -ENOMEM;
  478. +               goto fail_teardown;
  479. +       }
  480. +
  481. +       priv->queue = queue;
  482. +       queue->queuedata = dev;
  483. +
  484. +       blk_queue_bounce_limit(queue, BLK_BOUNCE_HIGH);
  485. +
  486. +       blk_queue_max_sectors(queue, dev->bounce_size/KERNEL_SECTOR_SIZE);
  487. +       blk_queue_segment_boundary(queue, -1UL);
  488. +       blk_queue_dma_alignment(queue, dev->blk_size-1);
  489. +       blk_queue_hardsect_size(queue, dev->blk_size);
  490. +
  491. +       blk_queue_issue_flush_fn(queue, ps3disk_issue_flush);
  492. +       blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH,
  493. +                         ps3disk_prepare_flush);
  494. +
  495. +       blk_queue_max_phys_segments(queue, -1);
  496. +       blk_queue_max_hw_segments(queue, -1);
  497. +       blk_queue_max_segment_size(queue, dev->bounce_size);
  498. +
  499. +       gendisk = alloc_disk(PS3DISK_MINORS);
  500. +       if (!gendisk) {
  501. +               dev_err(&dev->sbd.core, "%s:%u: alloc_disk failed\n", __func__,
  502. +                       __LINE__);
  503. +               error = -ENOMEM;
  504. +               goto fail_cleanup_queue;
  505. +       }
  506. +
  507. +       priv->gendisk = gendisk;
  508. +       gendisk->major = ps3disk_major;
  509. +       gendisk->first_minor = devidx * PS3DISK_MINORS;
  510. +       gendisk->fops = &ps3disk_fops;
  511. +       gendisk->queue = queue;
  512. +       gendisk->private_data = dev;
  513. +       gendisk->driverfs_dev = &dev->sbd.core;
  514. +       snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME,
  515. +                devidx+'a');
  516. +       priv->blocking_factor = dev->blk_size/KERNEL_SECTOR_SIZE;
  517. +       set_capacity(gendisk,
  518. +                    dev->regions[dev->region_idx].size*priv->blocking_factor);
  519. +
  520. +       dev_info(&dev->sbd.core,
  521. +                "%s is a %s (%lu MiB total, %lu MiB for OtherOS)\n",
  522. +                gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
  523. +                get_capacity(gendisk) >> 11);
  524. +
  525. +       add_disk(gendisk);
  526. +       return 0;
  527. +
  528. +fail_cleanup_queue:
  529. +       blk_cleanup_queue(queue);
  530. +fail_teardown:
  531. +       ps3stor_teardown(dev);
  532. +fail_free_bounce:
  533. +       kfree(dev->bounce_buf);
  534. +fail_free_priv:
  535. +       kfree(priv);
  536. +       ps3disk_priv(dev) = NULL;
  537. +fail:
  538. +       __clear_bit(devidx, &ps3disk_mask);
  539. +       return error;
  540. +}
  541. +
  542. +static int ps3disk_remove(struct ps3_system_bus_device *_dev)
  543. +{
  544. +       struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
  545. +       struct ps3disk_private *priv = ps3disk_priv(dev);
  546. +
  547. +       __clear_bit(priv->gendisk->first_minor / PS3DISK_MINORS,
  548. +                   &ps3disk_mask);
  549. +       del_gendisk(priv->gendisk);
  550. +       blk_cleanup_queue(priv->queue);
  551. +       put_disk(priv->gendisk);
  552. +       dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
  553. +       ps3disk_sync_cache(dev);
  554. +       ps3stor_teardown(dev);
  555. +       kfree(dev->bounce_buf);
  556. +       kfree(priv);
  557. +       ps3disk_priv(dev) = NULL;
  558. +       return 0;
  559. +}
  560. +
  561. +static struct ps3_system_bus_driver ps3disk = {
  562. +       .match_id       = PS3_MATCH_ID_STOR_DISK,
  563. +       .core.name      = DEVICE_NAME,
  564. +       .core.owner     = THIS_MODULE,
  565. +       .probe          = ps3disk_probe,
  566. +       .remove         = ps3disk_remove,
  567. +       .shutdown       = ps3disk_remove,
  568. +};
  569. +
  570. +
  571. +static int __init ps3disk_init(void)
  572. +{
  573. +       int error;
  574. +
  575. +       if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
  576. +               return -ENODEV;
  577. +
  578. +       error = register_blkdev(0, DEVICE_NAME);
  579. +       if (error <= 0) {
  580. +               printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__,
  581. +                      __LINE__, error);
  582. +               return error;
  583. +       }
  584. +       ps3disk_major = error;
  585. +
  586. +       pr_info("%s:%u: registered block device major %d\n", __func__,
  587. +               __LINE__, ps3disk_major);
  588. +
  589. +       error = ps3_system_bus_driver_register(&ps3disk);
  590. +       if (error)
  591. +               unregister_blkdev(ps3disk_major, DEVICE_NAME);
  592. +
  593. +       return error;
  594. +}
  595. +
  596. +static void __exit ps3disk_exit(void)
  597. +{
  598. +       ps3_system_bus_driver_unregister(&ps3disk);
  599. +       unregister_blkdev(ps3disk_major, DEVICE_NAME);
  600. +}
  601. +
  602. +module_init(ps3disk_init);
  603. +module_exit(ps3disk_exit);
  604. +
  605. +MODULE_LICENSE("GPL");
  606. +MODULE_DESCRIPTION("PS3 Disk Storage Driver");
  607. +MODULE_AUTHOR("Sony Corporation");
  608. +MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_DISK);
clone this paste RAW Paste Data