sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
bdm.c
1#include <bdm.h>
2#include <stdio.h>
3#include <thbase.h>
4#include <thevent.h>
5
6#include <bd_cache.h>
7
8// #define DEBUG //comment out this line when not debugging
9#include "module_debug.h"
10
12{
13 struct block_device *bd; // real block device
14 struct block_device *cbd; // cached block device
15 struct file_system *fs;
16};
17
18#define MAX_CONNECTIONS 20
19static struct bdm_mounts g_mount[MAX_CONNECTIONS];
20static struct file_system *g_fs[MAX_CONNECTIONS];
21static bdm_cb g_cb = NULL;
22static int bdm_event = -1;
23static int bdm_thread_id = -1;
24
25/* Event flag bits */
26#define BDM_EVENT_CB_MOUNT 0x01
27#define BDM_EVENT_CB_UMOUNT 0x02
28#define BDM_EVENT_MOUNT 0x04
29
30void bdm_RegisterCallback(bdm_cb cb)
31{
32 int i;
33
34 M_DEBUG("%s\n", __func__);
35
36 g_cb = cb;
37
38 if (g_cb == NULL)
39 return;
40
41 // Trigger a mount callback if we already have mounts
42 for (i = 0; i < MAX_CONNECTIONS; ++i) {
43 if ((g_mount[i].bd != NULL) && (g_mount[i].fs != NULL)) {
44 SetEventFlag(bdm_event, BDM_EVENT_CB_MOUNT);
45 break;
46 }
47 }
48}
49
50void bdm_connect_bd(struct block_device *bd)
51{
52 int i;
53
54 M_PRINTF("connecting device %s%dp%d size=%luMB id=0x%x\n", bd->name, bd->devNr, bd->parNr,
55 (u32)(bd->sectorCount / ((1000 * 1000) / bd->sectorSize)), bd->parId);
56
57 for (i = 0; i < MAX_CONNECTIONS; ++i) {
58 if (g_mount[i].bd == NULL) {
59 g_mount[i].bd = bd;
60 // Create cache for entire device only (not for the partitions on it)
61 g_mount[i].cbd = (bd->parNr == 0) ? bd_cache_create(bd) : NULL;
62 // New block device, try to mount it to a filesystem
63 SetEventFlag(bdm_event, BDM_EVENT_MOUNT);
64 break;
65 }
66 }
67}
68
69void bdm_disconnect_bd(struct block_device *bd)
70{
71 int i;
72
73 M_PRINTF("disconnecting device %s%dp%d\n", bd->name, bd->devNr, bd->parNr);
74
75 for (i = 0; i < MAX_CONNECTIONS; ++i) {
76 if (g_mount[i].bd == bd) {
77 if (g_mount[i].fs != NULL) {
78 // Unmount filesystem
79 g_mount[i].fs->disconnect_bd(g_mount[i].cbd != NULL ? g_mount[i].cbd : g_mount[i].bd);
80 M_PRINTF("%s%dp%d unmounted from %s\n", bd->name, bd->devNr, bd->parNr, g_mount[i].fs->name);
81 g_mount[i].fs = NULL;
82 }
83
84 if (g_mount[i].cbd != NULL) {
85 bd_cache_destroy(g_mount[i].cbd);
86 g_mount[i].cbd = NULL;
87 }
88
89 g_mount[i].bd = NULL;
90
91 if (g_cb != NULL)
92 SetEventFlag(bdm_event, BDM_EVENT_CB_UMOUNT);
93 }
94 }
95}
96
97void bdm_connect_fs(struct file_system *fs)
98{
99 int i;
100
101 M_PRINTF("connecting fs %s\n", fs->name);
102
103 for (i = 0; i < MAX_CONNECTIONS; ++i) {
104 if (g_fs[i] == NULL) {
105 g_fs[i] = fs;
106 break;
107 }
108 }
109
110 // New filesystem, try to mount it to the block devices
111 SetEventFlag(bdm_event, BDM_EVENT_MOUNT);
112}
113
114void bdm_disconnect_fs(struct file_system *fs)
115{
116 int i;
117
118 M_PRINTF("disconnecting fs %s\n", fs->name);
119
120 // Unmount fs from block devices
121 for (i = 0; i < MAX_CONNECTIONS; ++i) {
122 if (g_mount[i].fs == fs) {
123 g_mount[i].fs = NULL;
124 if (g_cb != NULL)
125 SetEventFlag(bdm_event, BDM_EVENT_CB_UMOUNT);
126 }
127 }
128
129 // Remove fs from list
130 for (i = 0; i < MAX_CONNECTIONS; ++i) {
131 if (g_fs[i] == fs) {
132 g_fs[i] = NULL;
133 break;
134 }
135 }
136}
137
138void bdm_get_bd(struct block_device **pbd, unsigned int count)
139{
140 int i;
141
142 M_DEBUG("%s\n", __func__);
143
144 // Fill pointer array with block device pointers
145 for (i = 0; (unsigned int)i < count && i < MAX_CONNECTIONS; i++)
146 pbd[i] = g_mount[i].bd;
147}
148
149static void bdm_try_mount(struct bdm_mounts *mount)
150{
151 int i;
152
153 M_DEBUG("%s(%s%dp%d)\n", __func__, mount->bd->name, mount->bd->devNr, mount->bd->parNr);
154
155 for (i = 0; i < MAX_CONNECTIONS; ++i) {
156 if (g_fs[i] != NULL) {
157 if (g_fs[i]->connect_bd(mount->cbd != NULL ? mount->cbd : mount->bd) == 0) {
158 M_PRINTF("%s%dp%d mounted to %s\n", mount->bd->name, mount->bd->devNr, mount->bd->parNr, g_fs[i]->name);
159 mount->fs = g_fs[i];
160 if (g_cb != NULL)
161 SetEventFlag(bdm_event, BDM_EVENT_CB_MOUNT);
162 break;
163 }
164 }
165 }
166}
167
168static void bdm_thread(void *arg)
169{
170 u32 EFBits;
171 int i;
172
173 (void)arg;
174
175 M_PRINTF("BDM event thread running\n");
176
177 while (1) {
178 WaitEventFlag(bdm_event, BDM_EVENT_CB_MOUNT | BDM_EVENT_CB_UMOUNT | BDM_EVENT_MOUNT, WEF_OR | WEF_CLEAR, &EFBits);
179
180 if (EFBits & BDM_EVENT_MOUNT) {
181 // Try to mount any unmounted block devices
182 for (i = 0; i < MAX_CONNECTIONS; ++i) {
183 if ((g_mount[i].bd != NULL) && (g_mount[i].fs == NULL))
184 bdm_try_mount(&g_mount[i]);
185 }
186 }
187
188 if (EFBits & BDM_EVENT_CB_MOUNT) {
189 // Notify callback about changes
190 if (g_cb != NULL)
191 g_cb(1);
192 }
193
194 if (EFBits & BDM_EVENT_CB_UMOUNT) {
195 // Notify callback about changes
196 if (g_cb != NULL)
197 g_cb(0);
198 }
199 }
200}
201
202int bdm_init()
203{
204 int i, result;
205 iop_event_t EventFlagData;
206 iop_thread_t ThreadData;
207
208 M_DEBUG("%s\n", __func__);
209
210 for (i = 0; i < MAX_CONNECTIONS; ++i) {
211 g_mount[i].bd = NULL;
212 g_mount[i].cbd = NULL;
213 g_mount[i].fs = NULL;
214 g_fs[i] = NULL;
215 }
216
217 EventFlagData.attr = 0;
218 EventFlagData.option = 0;
219 EventFlagData.bits = 0;
220 result = bdm_event = CreateEventFlag(&EventFlagData);
221 if (result < 0) {
222 M_DEBUG("ERROR: CreateEventFlag %d\n", result);
223 return result;
224 }
225
226 ThreadData.attr = TH_C;
227 ThreadData.thread = bdm_thread;
228 ThreadData.option = 0;
229 ThreadData.priority = 0x30; // Low priority
230 ThreadData.stacksize = 0x1000; // 4KiB
231 result = bdm_thread_id = CreateThread(&ThreadData);
232 if (result < 0) {
233 M_DEBUG("ERROR: CreateThread %d\n", result);
234 DeleteEventFlag(bdm_event);
235 return result;
236 }
237
238 result = StartThread(bdm_thread_id, NULL);
239 if (result < 0) {
240 M_DEBUG("ERROR: StartThread %d\n", result);
241 DeleteThread(bdm_thread_id);
242 DeleteEventFlag(bdm_event);
243 return result;
244 }
245
246 return 0;
247}
u32 count
start sector of fragmented bd/file