/modules/iopcore/cddev/cddev.c

https://bitbucket.org/ifcaro/open-ps2-loader/ · C · 295 lines · 220 code · 56 blank · 19 comment · 18 complexity · c933513c14168aca2c1c6706229b8c51 MD5 · raw file

  1. /*
  2. Copyright 2009, jimmikaelkael
  3. Licenced under Academic Free License version 3.0
  4. Review Open-ps2-loader README & LICENSE files for further details.
  5. */
  6. #include <stdio.h>
  7. #include <loadcore.h>
  8. #include <ioman.h>
  9. #include <io_common.h>
  10. #include <thsemap.h>
  11. #include <sysclib.h>
  12. #include <errno.h>
  13. #define MODNAME "cddev"
  14. IRX_ID(MODNAME, 1, 1);
  15. typedef struct {
  16. u32 lsn;
  17. u32 size;
  18. char name[16];
  19. u8 date[8];
  20. u32 flag;
  21. } cdl_file_t;
  22. typedef struct {
  23. u8 trycount;
  24. u8 spindlctrl;
  25. u8 datapattern;
  26. u8 pad;
  27. } cd_read_mode_t;
  28. // cdvdman imports
  29. int sceCdInit(int init_mode); // #4
  30. int sceCdRead(u32 lsn, u32 sectors, void *buf, cd_read_mode_t *mode); // #6
  31. int sceCdSync(int mode); // #11
  32. int sceCdDiskReady(int mode); // #13
  33. int sceCdLayerSearchFile(cdl_file_t *fp, const char *name, int layer); // #84
  34. // driver ops protypes
  35. int cddev_dummy(void);
  36. int cddev_init(iop_device_t *dev);
  37. int cddev_deinit(iop_device_t *dev);
  38. int cddev_open(iop_file_t *f, char *filename, int mode);
  39. int cddev_close(iop_file_t *f);
  40. int cddev_read(iop_file_t *f, void *buf, u32 size);
  41. int cddev_lseek(iop_file_t *f, u32 offset, int where);
  42. // driver ops func tab
  43. void *cddev_ops[17] = {
  44. (void*)cddev_init,
  45. (void*)cddev_deinit,
  46. (void*)cddev_dummy,
  47. (void*)cddev_open,
  48. (void*)cddev_close,
  49. (void*)cddev_read,
  50. (void*)cddev_dummy,
  51. (void*)cddev_lseek,
  52. (void*)cddev_dummy,
  53. (void*)cddev_dummy,
  54. (void*)cddev_dummy,
  55. (void*)cddev_dummy,
  56. (void*)cddev_dummy,
  57. (void*)cddev_dummy,
  58. (void*)cddev_dummy,
  59. (void*)cddev_dummy,
  60. (void*)cddev_dummy
  61. };
  62. // driver descriptor
  63. static iop_device_t cddev_dev = {
  64. "cddev",
  65. IOP_DT_FS,
  66. 1,
  67. "cddev",
  68. (struct _iop_device_ops *)&cddev_ops
  69. };
  70. typedef struct {
  71. iop_file_t *f;
  72. u32 lsn;
  73. u32 filesize;
  74. u32 position;
  75. } FHANDLE;
  76. #define MAX_FDHANDLES 64
  77. FHANDLE cddev_fdhandles[MAX_FDHANDLES];
  78. static int cddev_io_sema;
  79. #define CDDEV_FS_SECTORS 30
  80. #define CDDEV_FS_BUFSIZE CDDEV_FS_SECTORS * 2048
  81. static u8 cddev_fs_buf[CDDEV_FS_BUFSIZE + 2*2048] __attribute__((aligned(64)));
  82. //--------------------------------------------------------------
  83. int _start(int argc, char** argv)
  84. {
  85. DelDrv("cddev");
  86. AddDrv((iop_device_t *)&cddev_dev);
  87. sceCdInit(0);
  88. return MODULE_RESIDENT_END;
  89. }
  90. //--------------------------------------------------------------
  91. int cddev_dummy(void)
  92. {
  93. return -EPERM;
  94. }
  95. //--------------------------------------------------------------
  96. int cddev_init(iop_device_t *dev)
  97. {
  98. iop_sema_t smp;
  99. smp.initial = 1;
  100. smp.max = 1;
  101. smp.attr = 1;
  102. smp.option = 0;
  103. cddev_io_sema = CreateSema(&smp);
  104. return 0;
  105. }
  106. //--------------------------------------------------------------
  107. int cddev_deinit(iop_device_t *dev)
  108. {
  109. DeleteSema(cddev_io_sema);
  110. return 0;
  111. }
  112. //--------------------------------------------------------------
  113. FHANDLE *cddev_getfilefreeslot(void)
  114. {
  115. register int i;
  116. FHANDLE *fh;
  117. for (i=0; i<MAX_FDHANDLES; i++) {
  118. fh = (FHANDLE *)&cddev_fdhandles[i];
  119. if (fh->f == NULL)
  120. return fh;
  121. }
  122. return 0;
  123. }
  124. //--------------------------------------------------------------
  125. int cddev_open(iop_file_t *f, char *filename, int mode)
  126. {
  127. register int r = 0;
  128. FHANDLE *fh;
  129. cdl_file_t cdfile;
  130. if (!filename)
  131. return -ENOENT;
  132. WaitSema(cddev_io_sema);
  133. fh = cddev_getfilefreeslot();
  134. if (fh) {
  135. sceCdDiskReady(0);
  136. r = sceCdLayerSearchFile(&cdfile, filename, 0);
  137. if (r != 1) {
  138. r = sceCdLayerSearchFile(&cdfile, filename, 1);
  139. if (r != 1) {
  140. r = -ENOENT;
  141. SignalSema(cddev_io_sema);
  142. return r;
  143. }
  144. }
  145. f->privdata = fh;
  146. fh->f = f;
  147. fh->lsn = cdfile.lsn;
  148. fh->filesize = cdfile.size;
  149. fh->position = 0;
  150. r = 0;
  151. }
  152. else
  153. r = -EMFILE;
  154. SignalSema(cddev_io_sema);
  155. return r;
  156. }
  157. //--------------------------------------------------------------
  158. int cddev_close(iop_file_t *f)
  159. {
  160. FHANDLE *fh = (FHANDLE *)f->privdata;
  161. WaitSema(cddev_io_sema);
  162. if (fh)
  163. memset(fh, 0, sizeof(FHANDLE));
  164. SignalSema(cddev_io_sema);
  165. return 0;
  166. }
  167. //--------------------------------------------------------------
  168. int cddev_read(iop_file_t *f, void *buf, u32 size)
  169. {
  170. FHANDLE *fh = (FHANDLE *)f->privdata;
  171. register int rpos, sectorpos;
  172. register u32 nsectors, nbytes;
  173. rpos = 0;
  174. if ((fh->position + size) > fh->filesize)
  175. size = fh->filesize - fh->position;
  176. WaitSema(cddev_io_sema);
  177. sceCdDiskReady(0);
  178. while (size) {
  179. nbytes = CDDEV_FS_BUFSIZE;
  180. if (size < nbytes)
  181. nbytes = size;
  182. nsectors = nbytes >> 11;
  183. sectorpos = fh->position & 2047;
  184. if (sectorpos)
  185. nsectors++;
  186. if (nbytes & 2047)
  187. nsectors++;
  188. sceCdRead(fh->lsn + ((fh->position & -2048) >> 11), nsectors, cddev_fs_buf, NULL);
  189. sceCdSync(0);
  190. memcpy(buf, &cddev_fs_buf[sectorpos], nbytes);
  191. rpos += nbytes;
  192. buf += nbytes;
  193. size -= nbytes;
  194. fh->position += nbytes;
  195. }
  196. SignalSema(cddev_io_sema);
  197. return rpos;
  198. }
  199. //--------------------------------------------------------------
  200. int cddev_lseek(iop_file_t *f, u32 offset, int where)
  201. {
  202. register int r;
  203. FHANDLE *fh = (FHANDLE *)f->privdata;
  204. WaitSema(cddev_io_sema);
  205. switch (where) {
  206. case SEEK_CUR:
  207. r = fh->position + offset;
  208. if (r > fh->filesize) {
  209. r = -EINVAL;
  210. goto ssema;
  211. }
  212. break;
  213. case SEEK_SET:
  214. r = offset;
  215. if (fh->filesize < offset) {
  216. r = -EINVAL;
  217. goto ssema;
  218. }
  219. break;
  220. case SEEK_END:
  221. r = fh->filesize;
  222. break;
  223. default:
  224. r = -EINVAL;
  225. goto ssema;
  226. }
  227. fh->position = r;
  228. ssema:
  229. SignalSema(cddev_io_sema);
  230. return r;
  231. }
  232. //-------------------------------------------------------------------------
  233. DECLARE_IMPORT_TABLE(cdvdman, 1, 1)
  234. DECLARE_IMPORT(4, sceCdInit)
  235. DECLARE_IMPORT(6, sceCdRead)
  236. DECLARE_IMPORT(11, sceCdSync)
  237. DECLARE_IMPORT(13, sceCdDiskReady)
  238. DECLARE_IMPORT(84, sceCdLayerSearchFile)
  239. END_IMPORT_TABLE