Line |
Branch |
Exec |
Source |
1 |
|
|
/* GATE PROJECT LICENSE: |
2 |
|
|
+----------------------------------------------------------------------------+ |
3 |
|
|
| Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | |
4 |
|
|
| All rights reserved. | |
5 |
|
|
| | |
6 |
|
|
| Redistribution and use in source and binary forms, with or without | |
7 |
|
|
| modification, are permitted provided that the following conditions are met:| |
8 |
|
|
| | |
9 |
|
|
| 1. Redistributions of source code must retain the above copyright notice, | |
10 |
|
|
| this list of conditions and the following disclaimer. | |
11 |
|
|
| 2. Redistributions in binary form must reproduce the above copyright | |
12 |
|
|
| notice, this list of conditions and the following disclaimer in the | |
13 |
|
|
| documentation and/or other materials provided with the distribution. | |
14 |
|
|
| | |
15 |
|
|
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| |
16 |
|
|
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
17 |
|
|
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
18 |
|
|
| ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
19 |
|
|
| LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
20 |
|
|
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
21 |
|
|
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
22 |
|
|
| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
23 |
|
|
| CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
24 |
|
|
| ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
25 |
|
|
| THE POSSIBILITY OF SUCH DAMAGE. | |
26 |
|
|
+----------------------------------------------------------------------------+ |
27 |
|
|
*/ |
28 |
|
|
|
29 |
|
|
#include "gate/system/storagedrives.h" |
30 |
|
|
#include "gate/results.h" |
31 |
|
|
#include "gate/debugging.h" |
32 |
|
|
|
33 |
|
|
#if defined(GATE_SYS_WIN) && !defined(GATE_SYS_WIN16) |
34 |
|
|
# define GATE_SYSTEM_STORAGEDRIVES_WINAPI_IMPL 1 |
35 |
|
|
#elif defined(GATE_SYS_POSIX) |
36 |
|
|
# define GATE_SYSTEM_STORAGEDRIVES_POSIX_IMPL 1 |
37 |
|
|
#elif defined(GATE_SYS_DOS) |
38 |
|
|
# define GATE_SYSTEM_STORAGEDRIVES_DOS_IMPL 1 |
39 |
|
|
#else |
40 |
|
|
# define GATE_SYSTEM_STORAGEDRIVES_NO_IMPL 1 |
41 |
|
|
#endif |
42 |
|
|
|
43 |
|
|
|
44 |
|
|
struct gate_storagedrive_find_param |
45 |
|
|
{ |
46 |
|
|
gate_string_t const* field; |
47 |
|
|
gate_uint32_t field_type; |
48 |
|
|
gate_storagedrive_t* drive; |
49 |
|
|
gate_bool_t found; |
50 |
|
|
}; |
51 |
|
|
|
52 |
|
✗ |
static gate_bool_t gate_storagedrive_find_callback(gate_storagedrive_t const* drive, void* user_param) |
53 |
|
|
{ |
54 |
|
✗ |
struct gate_storagedrive_find_param* param = (struct gate_storagedrive_find_param*)user_param; |
55 |
|
|
gate_size_t length; |
56 |
|
✗ |
switch (param->field_type) |
57 |
|
|
{ |
58 |
|
✗ |
case GATE_STORAGEDRIVE_PATH: |
59 |
|
|
{ |
60 |
|
✗ |
length = gate_str_length(drive->path); |
61 |
|
✗ |
if ((length > 0) && (0 == gate_str_compare_ic(drive->path, length, param->field->str, param->field->length))) |
62 |
|
|
{ |
63 |
|
✗ |
gate_mem_copy(param->drive, drive, sizeof(gate_storagedrive_t)); |
64 |
|
✗ |
param->found = true; |
65 |
|
✗ |
return false; |
66 |
|
|
} |
67 |
|
|
} |
68 |
|
|
case GATE_STORAGEDRIVE_UID: |
69 |
|
|
{ |
70 |
|
✗ |
length = gate_str_length(drive->uid); |
71 |
|
✗ |
if ((length > 0) && (0 == gate_str_compare_ic(drive->uid, length, param->field->str, param->field->length))) |
72 |
|
|
{ |
73 |
|
✗ |
gate_mem_copy(param->drive, drive, sizeof(gate_storagedrive_t)); |
74 |
|
✗ |
param->found = true; |
75 |
|
✗ |
return false; |
76 |
|
|
} |
77 |
|
|
} |
78 |
|
|
case GATE_STORAGEDRIVE_NAME: |
79 |
|
|
{ |
80 |
|
✗ |
length = gate_str_length(drive->name); |
81 |
|
✗ |
if ((length > 0) && (0 == gate_str_compare_ic(drive->name, length, param->field->str, param->field->length))) |
82 |
|
|
{ |
83 |
|
✗ |
gate_mem_copy(param->drive, drive, sizeof(gate_storagedrive_t)); |
84 |
|
✗ |
param->found = true; |
85 |
|
✗ |
return false; |
86 |
|
|
} |
87 |
|
|
} |
88 |
|
|
case GATE_STORAGEDRIVE_DEVICEPATH: |
89 |
|
|
{ |
90 |
|
✗ |
length = gate_str_length(drive->devicepath); |
91 |
|
✗ |
if ((length > 0) && (0 == gate_str_compare_ic(drive->devicepath, length, param->field->str, param->field->length))) |
92 |
|
|
{ |
93 |
|
✗ |
gate_mem_copy(param->drive, drive, sizeof(gate_storagedrive_t)); |
94 |
|
✗ |
param->found = true; |
95 |
|
✗ |
return false; |
96 |
|
|
} |
97 |
|
|
} |
98 |
|
|
} |
99 |
|
|
|
100 |
|
✗ |
return true; |
101 |
|
|
|
102 |
|
|
} |
103 |
|
|
|
104 |
|
✗ |
gate_result_t gate_storagedrive_find(gate_string_t const* field, gate_uint32_t field_type, gate_storagedrive_t* drive) |
105 |
|
|
{ |
106 |
|
|
struct gate_storagedrive_find_param param; |
107 |
|
✗ |
param.field = field; |
108 |
|
✗ |
param.field_type = field_type; |
109 |
|
✗ |
param.drive = drive; |
110 |
|
✗ |
param.found = false; |
111 |
|
|
|
112 |
|
✗ |
gate_storagedrive_enum(GATE_STORAGEDRIVE_TYPE_ALL, &gate_storagedrive_find_callback, ¶m); |
113 |
|
|
|
114 |
|
✗ |
if (param.found) |
115 |
|
|
{ |
116 |
|
✗ |
return GATE_RESULT_OK; |
117 |
|
|
} |
118 |
|
✗ |
return GATE_RESULT_NOMATCH; |
119 |
|
|
} |
120 |
|
|
|
121 |
|
|
|
122 |
|
|
|
123 |
|
|
|
124 |
|
|
#if defined(GATE_SYSTEM_STORAGEDRIVES_WINAPI_IMPL) |
125 |
|
|
|
126 |
|
|
#include "gate/platforms.h" |
127 |
|
|
#include "gate/debugging.h" |
128 |
|
|
#include "gate/system/storagevolumes.h" |
129 |
|
|
|
130 |
|
|
#if defined(GATE_SYS_WINCE) |
131 |
|
|
|
132 |
|
|
gate_result_t gate_storagedrive_enum(gate_enumint_t drivetype, gate_storagedrive_enum_callback_t callback, void* user_param) |
133 |
|
|
{ |
134 |
|
|
GATE_UNUSED_ARG(drivetype); |
135 |
|
|
GATE_UNUSED_ARG(callback); |
136 |
|
|
GATE_UNUSED_ARG(user_param); |
137 |
|
|
return GATE_RESULT_NOTSUPPORTED; |
138 |
|
|
} |
139 |
|
|
gate_result_t gate_storagedrive_openstream(gate_storagedrive_t const* drive, gate_enumint_t open_flags, gate_controlstream_t** stream) |
140 |
|
|
{ |
141 |
|
|
GATE_UNUSED_ARG(drive); |
142 |
|
|
GATE_UNUSED_ARG(open_flags); |
143 |
|
|
GATE_UNUSED_ARG(stream); |
144 |
|
|
return GATE_RESULT_NOTSUPPORTED; |
145 |
|
|
} |
146 |
|
|
|
147 |
|
|
gate_result_t gate_storagedrive_queryattribs(gate_storagedrive_t const* drive, gate_enumint_t attrib_type, |
148 |
|
|
gate_storagedrive_attribs_callback_t callback, void* user_param) |
149 |
|
|
{ |
150 |
|
|
GATE_UNUSED_ARG(drive); |
151 |
|
|
GATE_UNUSED_ARG(attrib_type); |
152 |
|
|
GATE_UNUSED_ARG(callback); |
153 |
|
|
GATE_UNUSED_ARG(user_param); |
154 |
|
|
return GATE_RESULT_NOTSUPPORTED; |
155 |
|
|
} |
156 |
|
|
|
157 |
|
|
#else /* defined(GATE_SYS_WINCE) */ |
158 |
|
|
|
159 |
|
|
#include "gate/system/platform/storage_winapi.h" |
160 |
|
|
|
161 |
|
|
/*#include <setupapi.h>*/ |
162 |
|
|
|
163 |
|
|
|
164 |
|
|
static const GUID gate_GUID_DEVINTERFACE_DISK = { 0x53f56307L, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } }; |
165 |
|
|
static const GUID gate_GUID_DEVINTERFACE_CDROM = { 0x53f56308L, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } }; |
166 |
|
|
static const GUID gate_GUID_DEVINTERFACE_FLOPPY = { 0x53f56311L, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } }; |
167 |
|
|
|
168 |
|
|
|
169 |
|
|
|
170 |
|
|
struct gate_storagedrive_device_enum_param |
171 |
|
|
{ |
172 |
|
|
gate_storagedrive_enum_callback_t callback; |
173 |
|
|
void* user_param; |
174 |
|
|
}; |
175 |
|
|
|
176 |
|
|
static gate_bool_t gate_storagedrive_load_geometry(HANDLE hdevice, gate_storagedrive_t* ptr_drive) |
177 |
|
|
{ |
178 |
|
|
BYTE buffer[8192 + 4096]; |
179 |
|
|
GATE_DISK_GEOMETRY_EX* ptrgeometry = (GATE_DISK_GEOMETRY_EX*)&buffer[0]; |
180 |
|
|
DWORD reqsize = 0; |
181 |
|
|
|
182 |
|
|
if (FALSE != DeviceIoControl(hdevice, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, ptrgeometry, sizeof(buffer), &reqsize, NULL)) |
183 |
|
|
{ |
184 |
|
|
ptr_drive->blockcount = (gate_uint64_t)ptrgeometry->Geometry.Cylinders.QuadPart |
185 |
|
|
* (gate_uint64_t)ptrgeometry->Geometry.TracksPerCylinder |
186 |
|
|
* (gate_uint64_t)ptrgeometry->Geometry.SectorsPerTrack |
187 |
|
|
; |
188 |
|
|
ptr_drive->blocksize = (gate_uint64_t)ptrgeometry->Geometry.BytesPerSector; |
189 |
|
|
ptr_drive->size = (gate_uint64_t)ptrgeometry->DiskSize.QuadPart; |
190 |
|
|
return true; |
191 |
|
|
} |
192 |
|
|
else if (FALSE != DeviceIoControl(hdevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, ptrgeometry, sizeof(buffer), &reqsize, NULL)) |
193 |
|
|
{ |
194 |
|
|
ptr_drive->blockcount = (gate_uint64_t)ptrgeometry->Geometry.Cylinders.QuadPart |
195 |
|
|
* (gate_uint64_t)ptrgeometry->Geometry.TracksPerCylinder |
196 |
|
|
* (gate_uint64_t)ptrgeometry->Geometry.SectorsPerTrack |
197 |
|
|
; |
198 |
|
|
ptr_drive->blocksize = (gate_uint64_t)ptrgeometry->Geometry.BytesPerSector; |
199 |
|
|
ptr_drive->size = ptr_drive->blockcount * ptr_drive->blocksize; |
200 |
|
|
return true; |
201 |
|
|
} |
202 |
|
|
return false; |
203 |
|
|
} |
204 |
|
|
|
205 |
|
|
static gate_bool_t gate_storagedrive_load_device_properties(HANDLE hdevice, gate_storagedrive_t* ptr_drive) |
206 |
|
|
{ |
207 |
|
|
BYTE buffer[8192 + 4096]; |
208 |
|
|
DWORD reqsize = 0; |
209 |
|
|
GATE_STORAGE_DEVICE_DESCRIPTOR* storedescr; |
210 |
|
|
GATE_STORAGE_PROPERTY_QUERY propquery; |
211 |
|
|
|
212 |
|
|
gate_mem_clear(buffer, sizeof(buffer)); |
213 |
|
|
storedescr = (GATE_STORAGE_DEVICE_DESCRIPTOR*)&buffer[0]; |
214 |
|
|
storedescr->Size = sizeof(buffer); |
215 |
|
|
|
216 |
|
|
propquery.PropertyId = GateStorageDeviceProperty; |
217 |
|
|
propquery.QueryType = GatePropertyStandardQuery; |
218 |
|
|
propquery.AdditionalParameters[0] = 0; |
219 |
|
|
|
220 |
|
|
if (FALSE != DeviceIoControl(hdevice, IOCTL_STORAGE_QUERY_PROPERTY, &propquery, sizeof(propquery), storedescr, (DWORD)storedescr->Size, &reqsize, NULL)) |
221 |
|
|
{ |
222 |
|
|
if (storedescr->SerialNumberOffset > 0) |
223 |
|
|
{ |
224 |
|
|
if (storedescr->SerialNumberOffset < storedescr->Size) |
225 |
|
|
{ |
226 |
|
|
gate_str_print_text(ptr_drive->serial, sizeof(ptr_drive->serial), |
227 |
|
|
(char const*)&buffer[storedescr->SerialNumberOffset], |
228 |
|
|
gate_str_length((char const*)&buffer[storedescr->SerialNumberOffset])); |
229 |
|
|
} |
230 |
|
|
} |
231 |
|
|
if (storedescr->VendorIdOffset) |
232 |
|
|
{ |
233 |
|
|
if (storedescr->VendorIdOffset < storedescr->Size) |
234 |
|
|
{ |
235 |
|
|
gate_str_print_text(ptr_drive->vendor, sizeof(ptr_drive->vendor), |
236 |
|
|
(char const*)&buffer[storedescr->VendorIdOffset], |
237 |
|
|
gate_str_length((char const*)&buffer[storedescr->VendorIdOffset])); |
238 |
|
|
} |
239 |
|
|
} |
240 |
|
|
if (storedescr->ProductIdOffset) |
241 |
|
|
{ |
242 |
|
|
if (storedescr->ProductIdOffset < storedescr->Size) |
243 |
|
|
{ |
244 |
|
|
gate_str_print_text(ptr_drive->productname, sizeof(ptr_drive->productname), |
245 |
|
|
(char const*)&buffer[storedescr->ProductIdOffset], |
246 |
|
|
gate_str_length((char const*)&buffer[storedescr->ProductIdOffset])); |
247 |
|
|
} |
248 |
|
|
} |
249 |
|
|
return true; |
250 |
|
|
} |
251 |
|
|
return false; |
252 |
|
|
} |
253 |
|
|
|
254 |
|
|
|
255 |
|
|
static gate_bool_t gate_storagedrive_device_enum_standard_cb(LPCTSTR device_path, LPCTSTR friendly_name, void* user_param) |
256 |
|
|
{ |
257 |
|
|
struct gate_storagedrive_device_enum_param* param = (struct gate_storagedrive_device_enum_param*)user_param; |
258 |
|
|
gate_size_t len; |
259 |
|
|
gate_storagedrive_t drive = GATE_INIT_EMPTY; |
260 |
|
|
HANDLE hdisk; |
261 |
|
|
DWORD reqsize = 0; |
262 |
|
|
GATE_STORAGE_DEVICE_NUMBER storedevnum; |
263 |
|
|
|
264 |
|
|
do |
265 |
|
|
{ |
266 |
|
|
drive.drivetype = GATE_STORAGEDRIVE_TYPE_STANDARD; |
267 |
|
|
len = gate_win32_winstr_length(device_path); |
268 |
|
|
gate_win32_winstr_2_utf8(device_path, len, &drive.path[0], sizeof(drive.path)); |
269 |
|
|
gate_win32_winstr_2_utf8(device_path, len, &drive.devicepath[0], sizeof(drive.devicepath)); |
270 |
|
|
gate_win32_winstr_2_utf8(friendly_name, gate_win32_winstr_length(friendly_name), &drive.name[0], sizeof(drive.name)); |
271 |
|
|
|
272 |
|
|
hdisk = gate_win32_createfile(device_path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, 0, 0, NULL); |
273 |
|
|
/* hdisk = CreateFile(device_path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); */ |
274 |
|
|
if (INVALID_HANDLE_VALUE == hdisk) |
275 |
|
|
{ |
276 |
|
|
continue; |
277 |
|
|
} |
278 |
|
|
|
279 |
|
|
if (DeviceIoControl(hdisk, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storedevnum, sizeof(storedevnum), &reqsize, NULL)) |
280 |
|
|
{ |
281 |
|
|
gate_str_print_text(drive.uid, sizeof(drive.uid), "\\\\.\\PhysicalDrive", 17); |
282 |
|
|
gate_str_print_uint32(&drive.uid[17], sizeof(drive.uid) - 17, storedevnum.DeviceNumber); |
283 |
|
|
drive.deviceindex = (gate_uint32_t)storedevnum.DeviceNumber; |
284 |
|
|
} |
285 |
|
|
|
286 |
|
|
gate_storagedrive_load_geometry(hdisk, &drive); |
287 |
|
|
|
288 |
|
|
gate_storagedrive_load_device_properties(hdisk, &drive); |
289 |
|
|
|
290 |
|
|
} while (0); |
291 |
|
|
|
292 |
|
|
gate_win32_closehandle(hdisk); |
293 |
|
|
|
294 |
|
|
if (param->callback != NULL) |
295 |
|
|
{ |
296 |
|
|
return param->callback(&drive, param->user_param); |
297 |
|
|
} |
298 |
|
|
else |
299 |
|
|
{ |
300 |
|
|
return true; |
301 |
|
|
} |
302 |
|
|
} |
303 |
|
|
|
304 |
|
|
static gate_bool_t gate_storagedrive_device_enum_cdrom_cb(LPCTSTR device_path, LPCTSTR friendly_name, void* user_param) |
305 |
|
|
{ |
306 |
|
|
struct gate_storagedrive_device_enum_param* param = (struct gate_storagedrive_device_enum_param*)user_param; |
307 |
|
|
gate_size_t len; |
308 |
|
|
gate_storagedrive_t drive = GATE_INIT_EMPTY; |
309 |
|
|
HANDLE hdisk; |
310 |
|
|
DWORD reqsize = 0; |
311 |
|
|
GATE_STORAGE_DEVICE_NUMBER storedevnum; |
312 |
|
|
|
313 |
|
|
do |
314 |
|
|
{ |
315 |
|
|
drive.drivetype = GATE_STORAGEDRIVE_TYPE_ROM; |
316 |
|
|
len = gate_win32_winstr_length(device_path); |
317 |
|
|
gate_win32_winstr_2_utf8(device_path, len, &drive.path[0], sizeof(drive.path)); |
318 |
|
|
gate_win32_winstr_2_utf8(device_path, len, &drive.devicepath[0], sizeof(drive.devicepath)); |
319 |
|
|
gate_win32_winstr_2_utf8(friendly_name, gate_win32_winstr_length(friendly_name), &drive.name[0], sizeof(drive.name)); |
320 |
|
|
|
321 |
|
|
hdisk = gate_win32_createfile(device_path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, 0, 0, NULL); |
322 |
|
|
/* hdisk = CreateFile(device_path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); */ |
323 |
|
|
if (INVALID_HANDLE_VALUE == hdisk) |
324 |
|
|
{ |
325 |
|
|
continue; |
326 |
|
|
} |
327 |
|
|
|
328 |
|
|
if (DeviceIoControl(hdisk, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storedevnum, sizeof(storedevnum), &reqsize, NULL)) |
329 |
|
|
{ |
330 |
|
|
gate_str_print_text(drive.uid, sizeof(drive.uid), "\\\\.\\CdRom", 9); |
331 |
|
|
gate_str_print_uint32(&drive.uid[9], sizeof(drive.uid) - 9, storedevnum.DeviceNumber); |
332 |
|
|
drive.deviceindex = (gate_uint32_t)storedevnum.DeviceNumber; |
333 |
|
|
} |
334 |
|
|
|
335 |
|
|
gate_storagedrive_load_geometry(hdisk, &drive); |
336 |
|
|
|
337 |
|
|
gate_storagedrive_load_device_properties(hdisk, &drive); |
338 |
|
|
|
339 |
|
|
} while (0); |
340 |
|
|
|
341 |
|
|
gate_win32_closehandle(hdisk); |
342 |
|
|
|
343 |
|
|
if (param->callback != NULL) |
344 |
|
|
{ |
345 |
|
|
return param->callback(&drive, param->user_param); |
346 |
|
|
} |
347 |
|
|
else |
348 |
|
|
{ |
349 |
|
|
return true; |
350 |
|
|
} |
351 |
|
|
} |
352 |
|
|
|
353 |
|
|
static gate_bool_t gate_storagedrive_device_enum_floppy_cb(LPCTSTR device_path, LPCTSTR friendly_name, void* user_param) |
354 |
|
|
{ |
355 |
|
|
struct gate_storagedrive_device_enum_param* param = (struct gate_storagedrive_device_enum_param*)user_param; |
356 |
|
|
gate_size_t len; |
357 |
|
|
gate_storagedrive_t drive = GATE_INIT_EMPTY; |
358 |
|
|
HANDLE hdisk; |
359 |
|
|
/* |
360 |
|
|
DWORD reqsize = 0; |
361 |
|
|
GATE_STORAGE_DEVICE_NUMBER storedevnum; |
362 |
|
|
*/ |
363 |
|
|
|
364 |
|
|
do |
365 |
|
|
{ |
366 |
|
|
drive.drivetype = GATE_STORAGEDRIVE_TYPE_REMOVABLE; |
367 |
|
|
len = gate_win32_winstr_length(device_path); |
368 |
|
|
gate_win32_winstr_2_utf8(device_path, len, &drive.path[0], sizeof(drive.path)); |
369 |
|
|
gate_win32_winstr_2_utf8(device_path, len, &drive.devicepath[0], sizeof(drive.devicepath)); |
370 |
|
|
gate_win32_winstr_2_utf8(device_path, len, &drive.uid[0], sizeof(drive.uid)); |
371 |
|
|
gate_win32_winstr_2_utf8(friendly_name, gate_win32_winstr_length(friendly_name), &drive.name[0], sizeof(drive.name)); |
372 |
|
|
|
373 |
|
|
hdisk = gate_win32_createfile(device_path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, 0, 0, NULL); |
374 |
|
|
/* hdisk = CreateFile(device_path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); */ |
375 |
|
|
if (INVALID_HANDLE_VALUE == hdisk) |
376 |
|
|
{ |
377 |
|
|
continue; |
378 |
|
|
} |
379 |
|
|
|
380 |
|
|
/* |
381 |
|
|
if(DeviceIoControl(hdisk, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storedevnum, sizeof(storedevnum), &reqsize, NULL)) |
382 |
|
|
{ |
383 |
|
|
gate_str_print_text(drive.uid, sizeof(drive.uid), "\\\\.\\Floppy", 10); |
384 |
|
|
gate_str_print_uint32(&drive.uid[10], sizeof(drive.uid) - 10, storedevnum.DeviceNumber); |
385 |
|
|
drive.deviceindex = (gate_uint32_t)storedevnum.DeviceNumber; |
386 |
|
|
} |
387 |
|
|
*/ |
388 |
|
|
|
389 |
|
|
gate_storagedrive_load_geometry(hdisk, &drive); |
390 |
|
|
|
391 |
|
|
gate_storagedrive_load_device_properties(hdisk, &drive); |
392 |
|
|
|
393 |
|
|
} while (0); |
394 |
|
|
|
395 |
|
|
gate_win32_closehandle(hdisk); |
396 |
|
|
|
397 |
|
|
if (param->callback != NULL) |
398 |
|
|
{ |
399 |
|
|
return param->callback(&drive, param->user_param); |
400 |
|
|
} |
401 |
|
|
else |
402 |
|
|
{ |
403 |
|
|
return true; |
404 |
|
|
} |
405 |
|
|
} |
406 |
|
|
|
407 |
|
|
|
408 |
|
|
gate_result_t gate_storagedrive_enum(gate_enumint_t drivetype, gate_storagedrive_enum_callback_t callback, void* user_param) |
409 |
|
|
{ |
410 |
|
|
gate_result_t ret = GATE_RESULT_NOMATCH; |
411 |
|
|
|
412 |
|
|
struct gate_storagedrive_device_enum_param param; |
413 |
|
|
|
414 |
|
|
do |
415 |
|
|
{ |
416 |
|
|
param.callback = callback; |
417 |
|
|
param.user_param = user_param; |
418 |
|
|
|
419 |
|
|
if ((drivetype == GATE_STORAGEDRIVE_TYPE_ALL) || GATE_FLAG_ENABLED(drivetype, GATE_STORAGEDRIVE_TYPE_STANDARD)) |
420 |
|
|
{ |
421 |
|
|
ret = gate_win32_device_enum(&gate_GUID_DEVINTERFACE_DISK, &gate_storagedrive_device_enum_standard_cb, ¶m); |
422 |
|
|
GATE_BREAK_IF_FAILED(ret); |
423 |
|
|
} |
424 |
|
|
|
425 |
|
|
if ((drivetype == GATE_STORAGEDRIVE_TYPE_ALL) || GATE_FLAG_ENABLED(drivetype, GATE_STORAGEDRIVE_TYPE_ROM)) |
426 |
|
|
{ |
427 |
|
|
ret = gate_win32_device_enum(&gate_GUID_DEVINTERFACE_CDROM, &gate_storagedrive_device_enum_cdrom_cb, ¶m); |
428 |
|
|
GATE_BREAK_IF_FAILED(ret); |
429 |
|
|
} |
430 |
|
|
|
431 |
|
|
if ((drivetype == GATE_STORAGEDRIVE_TYPE_ALL) || GATE_FLAG_ENABLED(drivetype, GATE_STORAGEDRIVE_TYPE_REMOVABLE)) |
432 |
|
|
{ |
433 |
|
|
ret = gate_win32_device_enum(&gate_GUID_DEVINTERFACE_FLOPPY, &gate_storagedrive_device_enum_floppy_cb, ¶m); |
434 |
|
|
GATE_BREAK_IF_FAILED(ret); |
435 |
|
|
} |
436 |
|
|
|
437 |
|
|
} while (0); |
438 |
|
|
|
439 |
|
|
return ret; |
440 |
|
|
} |
441 |
|
|
|
442 |
|
|
|
443 |
|
|
|
444 |
|
|
static void drivestream_release(void* thisptr); |
445 |
|
|
static int drivestream_retain(void* thisptr); |
446 |
|
|
static char const* drivestream_get_interface_name(void* thisptr); |
447 |
|
|
|
448 |
|
|
static gate_result_t drivestream_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned); |
449 |
|
|
static gate_result_t drivestream_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned); |
450 |
|
|
static gate_result_t drivestream_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written); |
451 |
|
|
static gate_result_t drivestream_flush(void* thisptr); |
452 |
|
|
|
453 |
|
|
static gate_result_t drivestream_get_resource(void* thisptr, gate_enumint_t resource_type, gate_uintptr_t* resource); |
454 |
|
|
|
455 |
|
|
static gate_result_t drivestream_can_read(void* thisptr, gate_bool_t* return_value); |
456 |
|
|
static gate_result_t drivestream_can_write(void* thisptr, gate_bool_t* return_value); |
457 |
|
|
static gate_result_t drivestream_get_size(void* thisptr, gate_int64_t* return_value); |
458 |
|
|
static gate_result_t drivestream_get_available(void* thisptr, gate_int64_t* return_value); |
459 |
|
|
static gate_result_t drivestream_seek(void* thisptr, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position); |
460 |
|
|
static gate_result_t drivestream_reset(void* thisptr); |
461 |
|
|
static gate_result_t drivestream_close(void* thisptr, gate_enumint_t close_type); |
462 |
|
|
|
463 |
|
|
static GATE_INTERFACE_VTBL(gate_controlstream) gate_drivestream_vtbl; |
464 |
|
|
static void gate_init_drivestream_vtbl() |
465 |
|
|
{ |
466 |
|
|
if (!gate_drivestream_vtbl.get_interface_name) |
467 |
|
|
{ |
468 |
|
|
GATE_INTERFACE_VTBL(gate_controlstream) const local_vtbl = |
469 |
|
|
{ |
470 |
|
|
&drivestream_get_interface_name, |
471 |
|
|
&drivestream_release, |
472 |
|
|
&drivestream_retain, |
473 |
|
|
|
474 |
|
|
&drivestream_read, |
475 |
|
|
&drivestream_peek, |
476 |
|
|
&drivestream_write, |
477 |
|
|
&drivestream_flush, |
478 |
|
|
|
479 |
|
|
&drivestream_get_resource, |
480 |
|
|
|
481 |
|
|
&drivestream_can_read, |
482 |
|
|
&drivestream_can_write, |
483 |
|
|
&drivestream_get_size, |
484 |
|
|
&drivestream_get_available, |
485 |
|
|
&drivestream_seek, |
486 |
|
|
&drivestream_reset, |
487 |
|
|
&drivestream_close |
488 |
|
|
}; |
489 |
|
|
gate_drivestream_vtbl = local_vtbl; |
490 |
|
|
} |
491 |
|
|
} |
492 |
|
|
typedef struct gate_drivestream_class |
493 |
|
|
{ |
494 |
|
|
GATE_INTERFACE_VTBL(gate_controlstream) const* vtbl; |
495 |
|
|
|
496 |
|
|
gate_atomic_int_t ref_counter; |
497 |
|
|
gate_bool_t writeaccess; |
498 |
|
|
gate_size_t locked_handle_count; |
499 |
|
|
HANDLE locked_handles[128]; |
500 |
|
|
char devicepath[256]; |
501 |
|
|
|
502 |
|
|
gate_platform_stream_buffer_t block_stream; |
503 |
|
|
} gate_drivestream_t; |
504 |
|
|
|
505 |
|
|
static gate_bool_t gate_storagedrive_volume_cb(gate_storagevolume_t const* volume, void* user_param) |
506 |
|
|
{ |
507 |
|
|
gate_drivestream_t* drivestream = (gate_drivestream_t*)user_param; |
508 |
|
|
HANDLE handle; |
509 |
|
|
TCHAR volume_uid[128]; |
510 |
|
|
gate_size_t len; |
511 |
|
|
DWORD bytesreturned; |
512 |
|
|
BOOL succeeded; |
513 |
|
|
|
514 |
|
|
if (drivestream->locked_handle_count < (sizeof(drivestream->locked_handles) / sizeof(drivestream->locked_handles[0]))) |
515 |
|
|
{ |
516 |
|
|
if (gate_str_comp(drivestream->devicepath, volume->devicepath) == 0) |
517 |
|
|
{ |
518 |
|
|
/* this volume is part of the desired drive */ |
519 |
|
|
len = gate_win32_utf8_2_winstr(volume->uid, gate_str_length(volume->uid), volume_uid, sizeof(volume_uid) / sizeof(volume_uid[0])); |
520 |
|
|
if (len != 0) |
521 |
|
|
{ |
522 |
|
|
handle = gate_win32_createfile(volume_uid, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, 0, 0, NULL); |
523 |
|
|
/*handle = CreateFile(volume_uid, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);*/ |
524 |
|
|
if (INVALID_HANDLE_VALUE != handle) |
525 |
|
|
{ |
526 |
|
|
succeeded = DeviceIoControl(handle, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &bytesreturned, NULL); |
527 |
|
|
if (succeeded) |
528 |
|
|
{ |
529 |
|
|
drivestream->locked_handles[drivestream->locked_handle_count] = handle; |
530 |
|
|
++drivestream->locked_handle_count; |
531 |
|
|
succeeded = DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytesreturned, NULL); |
532 |
|
|
} |
533 |
|
|
else |
534 |
|
|
{ |
535 |
|
|
CloseHandle(handle); |
536 |
|
|
} |
537 |
|
|
} |
538 |
|
|
} |
539 |
|
|
} |
540 |
|
|
} |
541 |
|
|
return true; |
542 |
|
|
} |
543 |
|
|
|
544 |
|
|
gate_result_t gate_storagedrive_openstream(gate_storagedrive_t const* drive, gate_enumint_t open_flags, gate_controlstream_t** stream) |
545 |
|
|
{ |
546 |
|
|
gate_result_t ret; |
547 |
|
|
gate_drivestream_t* drivestream = NULL; |
548 |
|
|
gate_bool_t writable; |
549 |
|
|
TCHAR devpath[1024]; |
550 |
|
|
DWORD dwaccess; |
551 |
|
|
DWORD dwshare = (FILE_SHARE_READ | FILE_SHARE_WRITE); |
552 |
|
|
DWORD dwflags = 0; |
553 |
|
|
HANDLE hdrive = INVALID_HANDLE_VALUE; |
554 |
|
|
gate_size_t ndx; |
555 |
|
|
|
556 |
|
|
do |
557 |
|
|
{ |
558 |
|
|
if ((drive == NULL) || (stream == NULL)) |
559 |
|
|
{ |
560 |
|
|
ret = GATE_RESULT_INVALIDARG; |
561 |
|
|
break; |
562 |
|
|
} |
563 |
|
|
|
564 |
|
|
if (GATE_FLAG_ENABLED(open_flags, GATE_STREAM_OPEN_WRITE)) |
565 |
|
|
{ |
566 |
|
|
writable = true; |
567 |
|
|
dwaccess = GENERIC_WRITE; |
568 |
|
|
dwflags = (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH); |
569 |
|
|
} |
570 |
|
|
else if (GATE_FLAG_ENABLED(open_flags, GATE_STREAM_OPEN_READ)) |
571 |
|
|
{ |
572 |
|
|
writable = false; |
573 |
|
|
dwaccess = GENERIC_READ; |
574 |
|
|
dwflags = FILE_FLAG_SEQUENTIAL_SCAN; |
575 |
|
|
} |
576 |
|
|
else |
577 |
|
|
{ |
578 |
|
|
ret = GATE_RESULT_INVALIDARG; |
579 |
|
|
break; |
580 |
|
|
} |
581 |
|
|
|
582 |
|
|
ndx = gate_win32_utf8_2_winstr(drive->uid, gate_str_length(drive->uid), devpath, sizeof(devpath) / sizeof(devpath[0])); |
583 |
|
|
if (ndx == 0) |
584 |
|
|
{ |
585 |
|
|
ret = GATE_RESULT_INVALIDARG; |
586 |
|
|
} |
587 |
|
|
|
588 |
|
|
drivestream = gate_mem_alloc(sizeof(gate_drivestream_t) + (gate_size_t)drive->blocksize); |
589 |
|
|
if (drivestream == NULL) |
590 |
|
|
{ |
591 |
|
|
ret = GATE_RESULT_OUTOFMEMORY; |
592 |
|
|
break; |
593 |
|
|
} |
594 |
|
|
|
595 |
|
|
gate_init_drivestream_vtbl(); |
596 |
|
|
drivestream->vtbl = &gate_drivestream_vtbl; |
597 |
|
|
gate_atomic_int_init(&drivestream->ref_counter, 1); |
598 |
|
|
drivestream->writeaccess = writable; |
599 |
|
|
drivestream->locked_handle_count = 0; |
600 |
|
|
gate_str_print_text(drivestream->devicepath, sizeof(drivestream->devicepath), drive->uid, gate_str_length(drive->uid)); |
601 |
|
|
|
602 |
|
|
gate_storagevolume_enum(&gate_storagedrive_volume_cb, drivestream); |
603 |
|
|
|
604 |
|
|
hdrive = gate_win32_createfile(devpath, dwaccess, dwshare, OPEN_EXISTING, 0, dwflags, NULL); |
605 |
|
|
if (hdrive == INVALID_HANDLE_VALUE) |
606 |
|
|
{ |
607 |
|
|
gate_win32_print_lasterror(&ret, NULL, 0); |
608 |
|
|
break; |
609 |
|
|
} |
610 |
|
|
|
611 |
|
|
gate_platform_stream_buffer_init(&drivestream->block_stream, (gate_platform_stream_t)hdrive, |
612 |
|
|
(gate_int64_t)drive->size, 0, (gate_size_t)drive->blocksize); |
613 |
|
|
|
614 |
|
|
hdrive = INVALID_HANDLE_VALUE; |
615 |
|
|
*stream = (gate_controlstream_t*)drivestream; |
616 |
|
|
drivestream = NULL; |
617 |
|
|
ret = GATE_RESULT_OK; |
618 |
|
|
} while (0); |
619 |
|
|
|
620 |
|
|
if (GATE_FAILED(ret)) |
621 |
|
|
{ |
622 |
|
|
gate_win32_closehandle(hdrive); |
623 |
|
|
if (drivestream != NULL) |
624 |
|
|
{ |
625 |
|
|
for (ndx = 0; ndx != drivestream->locked_handle_count; ++ndx) |
626 |
|
|
{ |
627 |
|
|
gate_win32_closehandle(drivestream->locked_handles[ndx]); |
628 |
|
|
} |
629 |
|
|
|
630 |
|
|
gate_mem_dealloc(drivestream); |
631 |
|
|
} |
632 |
|
|
|
633 |
|
|
} |
634 |
|
|
|
635 |
|
|
|
636 |
|
|
return ret; |
637 |
|
|
} |
638 |
|
|
|
639 |
|
|
static void drivestream_release(void* thisptr) |
640 |
|
|
{ |
641 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
642 |
|
|
gate_size_t ndx; |
643 |
|
|
|
644 |
|
|
if (0 == gate_atomic_int_dec(&stream->ref_counter)) |
645 |
|
|
{ |
646 |
|
|
for (ndx = 0; ndx != stream->locked_handle_count; ++ndx) |
647 |
|
|
{ |
648 |
|
|
CloseHandle(stream->locked_handles[ndx]); |
649 |
|
|
} |
650 |
|
|
|
651 |
|
|
gate_platform_stream_close(&stream->block_stream.stream); |
652 |
|
|
|
653 |
|
|
gate_mem_dealloc(thisptr); |
654 |
|
|
} |
655 |
|
|
} |
656 |
|
|
static int drivestream_retain(void* thisptr) |
657 |
|
|
{ |
658 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
659 |
|
|
return gate_atomic_int_inc(&stream->ref_counter); |
660 |
|
|
} |
661 |
|
|
static char const* drivestream_get_interface_name(void* thisptr) |
662 |
|
|
{ |
663 |
|
|
GATE_UNUSED_ARG(thisptr); |
664 |
|
|
return GATE_INTERFACE_NAME_CONTROLSTREAM; |
665 |
|
|
} |
666 |
|
|
|
667 |
|
|
static gate_result_t drivestream_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned) |
668 |
|
|
{ |
669 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
670 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
671 |
|
|
|
672 |
|
|
do |
673 |
|
|
{ |
674 |
|
|
if (stream->writeaccess) |
675 |
|
|
{ |
676 |
|
|
ret = GATE_RESULT_INVALIDSTATE; |
677 |
|
|
break; |
678 |
|
|
} |
679 |
|
|
if ((bufferlength == 0) || (buffer == NULL)) |
680 |
|
|
{ |
681 |
|
|
ret = GATE_RESULT_INVALIDARG; |
682 |
|
|
break; |
683 |
|
|
} |
684 |
|
|
|
685 |
|
|
ret = gate_platform_stream_buffer_read(&stream->block_stream, buffer, bufferlength, returned); |
686 |
|
|
} while (0); |
687 |
|
|
|
688 |
|
|
return ret; |
689 |
|
|
} |
690 |
|
|
static gate_result_t drivestream_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned) |
691 |
|
|
{ |
692 |
|
|
GATE_UNUSED_ARG(thisptr); |
693 |
|
|
GATE_UNUSED_ARG(buffer); |
694 |
|
|
GATE_UNUSED_ARG(bufferlength); |
695 |
|
|
GATE_UNUSED_ARG(returned); |
696 |
|
|
return GATE_RESULT_NOTSUPPORTED; |
697 |
|
|
} |
698 |
|
|
static gate_result_t drivestream_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written) |
699 |
|
|
{ |
700 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
701 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
702 |
|
|
|
703 |
|
|
do |
704 |
|
|
{ |
705 |
|
|
if (!stream->writeaccess) |
706 |
|
|
{ |
707 |
|
|
ret = GATE_RESULT_INVALIDSTATE; |
708 |
|
|
break; |
709 |
|
|
} |
710 |
|
|
|
711 |
|
|
if ((bufferlength == 0) || (buffer == NULL)) |
712 |
|
|
{ |
713 |
|
|
ret = GATE_RESULT_INVALIDARG; |
714 |
|
|
break; |
715 |
|
|
} |
716 |
|
|
|
717 |
|
|
ret = gate_platform_stream_buffer_write(&stream->block_stream, buffer, bufferlength, written); |
718 |
|
|
} while (0); |
719 |
|
|
|
720 |
|
|
return ret; |
721 |
|
|
} |
722 |
|
|
static gate_result_t drivestream_flush(void* thisptr) |
723 |
|
|
{ |
724 |
|
|
gate_result_t ret = GATE_RESULT_OK; |
725 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
726 |
|
|
if (FALSE == gate_win32_flushfilebuffers(stream->block_stream.stream)) |
727 |
|
|
{ |
728 |
|
|
ret = GATE_RESULT_FAILED; |
729 |
|
|
} |
730 |
|
|
return ret; |
731 |
|
|
} |
732 |
|
|
|
733 |
|
|
static gate_result_t drivestream_get_resource(void* thisptr, gate_enumint_t resource_type, gate_uintptr_t* resource) |
734 |
|
|
{ |
735 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
736 |
|
|
GATE_UNUSED_ARG(resource_type); |
737 |
|
|
*resource = (gate_uintptr_t)(void*)stream->block_stream.stream; |
738 |
|
|
return GATE_RESULT_OK; |
739 |
|
|
} |
740 |
|
|
|
741 |
|
|
static gate_result_t drivestream_can_read(void* thisptr, gate_bool_t* return_value) |
742 |
|
|
{ |
743 |
|
|
gate_result_t ret = GATE_RESULT_OK; |
744 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
745 |
|
|
if (return_value) |
746 |
|
|
{ |
747 |
|
|
*return_value = stream->writeaccess ? false : true; |
748 |
|
|
} |
749 |
|
|
return ret; |
750 |
|
|
} |
751 |
|
|
static gate_result_t drivestream_can_write(void* thisptr, gate_bool_t* return_value) |
752 |
|
|
{ |
753 |
|
|
gate_result_t ret = GATE_RESULT_OK; |
754 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
755 |
|
|
if (return_value) |
756 |
|
|
{ |
757 |
|
|
*return_value = stream->writeaccess ? true : false; |
758 |
|
|
} |
759 |
|
|
return ret; |
760 |
|
|
} |
761 |
|
|
static gate_result_t drivestream_get_size(void* thisptr, gate_int64_t* return_value) |
762 |
|
|
{ |
763 |
|
|
gate_result_t ret = GATE_RESULT_OK; |
764 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
765 |
|
|
if (return_value) |
766 |
|
|
{ |
767 |
|
|
*return_value = (gate_int64_t)stream->block_stream.total_size; |
768 |
|
|
} |
769 |
|
|
return ret; |
770 |
|
|
} |
771 |
|
|
static gate_result_t drivestream_get_available(void* thisptr, gate_int64_t* return_value) |
772 |
|
|
{ |
773 |
|
|
gate_result_t ret = GATE_RESULT_OK; |
774 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
775 |
|
|
if (return_value) |
776 |
|
|
{ |
777 |
|
|
*return_value = (gate_int64_t)stream->block_stream.total_size - (gate_int64_t)stream->block_stream.position; |
778 |
|
|
} |
779 |
|
|
return ret; |
780 |
|
|
} |
781 |
|
|
static gate_result_t drivestream_seek(void* thisptr, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position) |
782 |
|
|
{ |
783 |
|
|
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
784 |
|
|
int stream_origin; |
785 |
|
|
switch (origin) |
786 |
|
|
{ |
787 |
|
|
case GATE_STREAM_SEEK_BEGIN: |
788 |
|
|
stream_origin = GATE_PLATFORM_STREAM_ORIGIN_BEGIN; |
789 |
|
|
break; |
790 |
|
|
case GATE_STREAM_SEEK_CURRENT: |
791 |
|
|
stream_origin = GATE_PLATFORM_STREAM_ORIGIN_CURRENT; |
792 |
|
|
break; |
793 |
|
|
case GATE_STREAM_SEEK_END: |
794 |
|
|
stream_origin = GATE_PLATFORM_STREAM_ORIGIN_END; |
795 |
|
|
break; |
796 |
|
|
default: |
797 |
|
|
return GATE_RESULT_INVALIDARG; |
798 |
|
|
} |
799 |
|
|
|
800 |
|
|
return gate_platform_stream_buffer_seek(&stream->block_stream, position, stream_origin, final_position); |
801 |
|
|
} |
802 |
|
|
static gate_result_t drivestream_reset(void* thisptr) |
803 |
|
|
{ |
804 |
|
|
GATE_UNUSED_ARG(thisptr); |
805 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
806 |
|
|
} |
807 |
|
|
static gate_result_t drivestream_close(void* thisptr, gate_enumint_t close_type) |
808 |
|
|
{ |
809 |
|
|
GATE_UNUSED_ARG(thisptr); |
810 |
|
|
GATE_UNUSED_ARG(close_type); |
811 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
812 |
|
|
} |
813 |
|
|
|
814 |
|
|
#ifndef DRIVE_HEAD_REG |
815 |
|
|
# define DRIVE_HEAD_REG 0xA0 |
816 |
|
|
#endif |
817 |
|
|
|
818 |
|
|
|
819 |
|
|
#include "gate/struct_pack_begin.h" |
820 |
|
|
GATE_STRUCT_PACK_BEGIN(_GATE_IDEREGS) |
821 |
|
|
{ |
822 |
|
|
BYTE bFeaturesReg; |
823 |
|
|
BYTE bSectorCountReg; |
824 |
|
|
BYTE bSectorNumberReg; |
825 |
|
|
BYTE bCylLowReg; |
826 |
|
|
BYTE bCylHighReg; |
827 |
|
|
BYTE bDriveHeadReg; |
828 |
|
|
BYTE bCommandReg; |
829 |
|
|
BYTE bReserved; |
830 |
|
|
} GATE_STRUCT_PACK_END; |
831 |
|
|
#include "gate/struct_pack_end.h" |
832 |
|
|
typedef struct _GATE_IDEREGS GATE_IDEREGS; |
833 |
|
|
|
834 |
|
|
|
835 |
|
|
#include "gate/struct_pack_begin.h" |
836 |
|
|
GATE_STRUCT_PACK_BEGIN(_GATE_SENDCMDINPARAMS) |
837 |
|
|
{ |
838 |
|
|
DWORD cBufferSize; |
839 |
|
|
GATE_IDEREGS irDriveRegs; |
840 |
|
|
BYTE bDriveNumber; |
841 |
|
|
BYTE bReserved[3]; |
842 |
|
|
DWORD dwReserved[4]; |
843 |
|
|
BYTE bBuffer[1]; |
844 |
|
|
} GATE_STRUCT_PACK_END; |
845 |
|
|
#include "gate/struct_pack_end.h" |
846 |
|
|
typedef struct _GATE_SENDCMDINPARAMS GATE_SENDCMDINPARAMS; |
847 |
|
|
|
848 |
|
|
|
849 |
|
|
#include "gate/struct_pack_begin.h" |
850 |
|
|
GATE_STRUCT_PACK_BEGIN(_GATE_DRIVERSTATUS) |
851 |
|
|
{ |
852 |
|
|
BYTE bDriverError; // Error code from driver, |
853 |
|
|
// or 0 if no error. |
854 |
|
|
BYTE bIDEError; // Contents of IDE Error register. |
855 |
|
|
// Only valid when bDriverError |
856 |
|
|
// is SMART_IDE_ERROR. |
857 |
|
|
BYTE bReserved[2]; // Reserved for future expansion. |
858 |
|
|
DWORD dwReserved[2]; // Reserved for future expansion. |
859 |
|
|
} GATE_STRUCT_PACK_END; |
860 |
|
|
#include "gate/struct_pack_end.h" |
861 |
|
|
typedef struct _GATE_DRIVERSTATUS GATE_DRIVERSTATUS; |
862 |
|
|
|
863 |
|
|
|
864 |
|
|
#include "gate/struct_pack_begin.h" |
865 |
|
|
GATE_STRUCT_PACK_BEGIN(_GATE_SENDCMDOUTPARAMS) |
866 |
|
|
{ |
867 |
|
|
DWORD cBufferSize; |
868 |
|
|
GATE_DRIVERSTATUS DriverStatus; |
869 |
|
|
BYTE bBuffer[1]; |
870 |
|
|
} GATE_STRUCT_PACK_END; |
871 |
|
|
#include "gate/struct_pack_end.h" |
872 |
|
|
typedef struct _GATE_SENDCMDOUTPARAMS GATE_SENDCMDOUTPARAMS; |
873 |
|
|
|
874 |
|
|
|
875 |
|
|
#include "gate/struct_pack_begin.h" |
876 |
|
|
GATE_STRUCT_PACK_BEGIN(_GATE_GETVERSIONINPARAMS) |
877 |
|
|
{ |
878 |
|
|
BYTE bVersion; // Binary driver version. |
879 |
|
|
BYTE bRevision; // Binary driver revision. |
880 |
|
|
BYTE bReserved; // Not used. |
881 |
|
|
BYTE bIDEDeviceMap; // Bit map of IDE devices. |
882 |
|
|
DWORD fCapabilities; // Bit mask of driver capabilities. |
883 |
|
|
DWORD dwReserved[4]; // For future use. |
884 |
|
|
} GATE_STRUCT_PACK_END; |
885 |
|
|
#include "gate/struct_pack_end.h" |
886 |
|
|
typedef struct _GATE_GETVERSIONINPARAMS GATE_GETVERSIONINPARAMS; |
887 |
|
|
|
888 |
|
|
|
889 |
|
|
|
890 |
|
|
#ifndef ENABLE_SMART |
891 |
|
|
#define ENABLE_SMART 0xD8 |
892 |
|
|
#endif |
893 |
|
|
|
894 |
|
|
#ifndef SMART_CYL_LOW |
895 |
|
|
#define SMART_CYL_LOW 0x4F |
896 |
|
|
#endif |
897 |
|
|
|
898 |
|
|
#ifndef SMART_CYL_HI |
899 |
|
|
#define SMART_CYL_HI 0xC2 |
900 |
|
|
#endif |
901 |
|
|
|
902 |
|
|
#ifndef SMART_CMD |
903 |
|
|
#define SMART_CMD 0xB0 |
904 |
|
|
#endif |
905 |
|
|
|
906 |
|
|
#ifndef READ_THRESHOLDS |
907 |
|
|
#define READ_THRESHOLDS 0xD1 |
908 |
|
|
#endif |
909 |
|
|
|
910 |
|
|
#ifndef READ_THRESHOLD_BUFFER_SIZE |
911 |
|
|
#define READ_THRESHOLD_BUFFER_SIZE 512 |
912 |
|
|
#endif |
913 |
|
|
|
914 |
|
|
#ifndef CAP_SMART_CMD |
915 |
|
|
#define CAP_SMART_CMD 4 |
916 |
|
|
#endif |
917 |
|
|
|
918 |
|
|
#ifndef SMART_SEND_DRIVE_COMMAND |
919 |
|
|
#define SMART_SEND_DRIVE_COMMAND CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) |
920 |
|
|
#endif |
921 |
|
|
|
922 |
|
|
#ifndef SMART_GET_VERSION |
923 |
|
|
#define SMART_GET_VERSION CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS) |
924 |
|
|
#endif |
925 |
|
|
|
926 |
|
|
#ifndef SMART_RCV_DRIVE_DATA |
927 |
|
|
#define SMART_RCV_DRIVE_DATA CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) |
928 |
|
|
#endif |
929 |
|
|
|
930 |
|
|
|
931 |
|
|
static gate_bool_t smart_enabled(HANDLE device, gate_uint8_t physical_drive_num) |
932 |
|
|
{ |
933 |
|
|
static char const* const FuncName = "DiskDriveImpl::smart_is_enabled"; |
934 |
|
|
GATE_SENDCMDINPARAMS inparams = { 0 }; |
935 |
|
|
GATE_SENDCMDOUTPARAMS outparams = { 0 }; |
936 |
|
|
DWORD dwRet = 0; |
937 |
|
|
|
938 |
|
|
inparams.cBufferSize = 0; |
939 |
|
|
inparams.bDriveNumber = physical_drive_num; |
940 |
|
|
inparams.irDriveRegs.bFeaturesReg = ENABLE_SMART; |
941 |
|
|
inparams.irDriveRegs.bSectorCountReg = 1; |
942 |
|
|
inparams.irDriveRegs.bSectorNumberReg = 1; |
943 |
|
|
inparams.irDriveRegs.bCylLowReg = SMART_CYL_LOW; |
944 |
|
|
inparams.irDriveRegs.bCylHighReg = SMART_CYL_HI; |
945 |
|
|
inparams.irDriveRegs.bDriveHeadReg = DRIVE_HEAD_REG; |
946 |
|
|
inparams.irDriveRegs.bCommandReg = SMART_CMD; |
947 |
|
|
|
948 |
|
|
if (!DeviceIoControl(device, SMART_SEND_DRIVE_COMMAND, &inparams, sizeof(inparams), &outparams, sizeof(outparams), &dwRet, NULL)) |
949 |
|
|
{ |
950 |
|
|
return false; |
951 |
|
|
} |
952 |
|
|
return true; |
953 |
|
|
} |
954 |
|
|
|
955 |
|
|
|
956 |
|
|
#ifndef READ_ATTRIBUTE_BUFFER_SIZE |
957 |
|
|
#define READ_ATTRIBUTE_BUFFER_SIZE 512 |
958 |
|
|
#endif |
959 |
|
|
|
960 |
|
|
typedef struct |
961 |
|
|
{ |
962 |
|
|
BYTE bDriverError; |
963 |
|
|
BYTE bIDEStatus; |
964 |
|
|
BYTE bReserved[2]; |
965 |
|
|
DWORD dwReserved[2]; |
966 |
|
|
} GATE_ST_DRIVERSTAT; |
967 |
|
|
|
968 |
|
|
typedef struct |
969 |
|
|
{ |
970 |
|
|
DWORD cBufferSize; |
971 |
|
|
GATE_ST_DRIVERSTAT DriverStatus; |
972 |
|
|
BYTE bBuffer[READ_ATTRIBUTE_BUFFER_SIZE]; |
973 |
|
|
} GATE_ST_ATAOUTPARAM; |
974 |
|
|
|
975 |
|
|
typedef struct _GATE_SMART_THRESHOLD |
976 |
|
|
{ |
977 |
|
|
BYTE Id; |
978 |
|
|
BYTE Value; |
979 |
|
|
BYTE Reserved[10]; |
980 |
|
|
} GATE_SMART_THRESHOLD; |
981 |
|
|
|
982 |
|
|
#ifndef READ_ATTRIBUTES |
983 |
|
|
#define READ_ATTRIBUTES 0xD0 |
984 |
|
|
#endif |
985 |
|
|
|
986 |
|
|
#define INDEX_ATTRIB_INDEX 0 |
987 |
|
|
#define INDEX_ATTRIB_UNKNOWN1 1 |
988 |
|
|
#define INDEX_ATTRIB_UNKNOWN2 2 |
989 |
|
|
#define INDEX_ATTRIB_VALUE 3 |
990 |
|
|
#define INDEX_ATTRIB_WORST 4 |
991 |
|
|
#define INDEX_ATTRIB_RAW 5 |
992 |
|
|
|
993 |
|
|
|
994 |
|
|
typedef struct gate_smart_entry_class |
995 |
|
|
{ |
996 |
|
|
gate_uint8_t id; |
997 |
|
|
gate_uint8_t value; |
998 |
|
|
gate_uint8_t worst; |
999 |
|
|
gate_uint8_t threshold; |
1000 |
|
|
gate_uint64_t raw; |
1001 |
|
|
} gate_smart_entry_t; |
1002 |
|
|
|
1003 |
|
|
typedef struct gate_smart_description_mapping_class |
1004 |
|
|
{ |
1005 |
|
|
gate_uint8_t id; |
1006 |
|
|
gate_int8_t direction; |
1007 |
|
|
char const* description; |
1008 |
|
|
} gate_smart_description_mapping_t; |
1009 |
|
|
|
1010 |
|
|
static gate_bool_t smart_resolve_description(gate_uint8_t id, char const** ptr_description, gate_int8_t* ptr_direction) |
1011 |
|
|
{ |
1012 |
|
|
static gate_smart_description_mapping_t const smart_id_mappings[] = { |
1013 |
|
|
{ 0x01, -1, "Read Error Rate" }, |
1014 |
|
|
{ 0x02, +1, "Throughput Performance" }, |
1015 |
|
|
{ 0x03, -1, "Spin-Up Time" }, |
1016 |
|
|
{ 0x04, 0, "Start/Stop Count" }, |
1017 |
|
|
{ 0x05, -1, "Reallocated Sectors Count" }, |
1018 |
|
|
{ 0x06, 0, "Read Channel Margin" }, |
1019 |
|
|
{ 0x07, 0, "Seek Error Rate" }, |
1020 |
|
|
{ 0x08, +1, "Seek Time Performance" }, |
1021 |
|
|
{ 0x09, 0, "Power-On Hours (POH)" }, |
1022 |
|
|
{ 0x0A, -1, "Spin Retry Count" }, |
1023 |
|
|
{ 0x0B, -1, "Recalibration Retries" }, // or Calibration Retry Count" }, |
1024 |
|
|
{ 0x0C, 0, "Power Cycle Count" }, |
1025 |
|
|
{ 0x0D, -1, "Soft Read Error Rate" }, |
1026 |
|
|
{ 0xAA, 0, "Available Reserved Space" }, |
1027 |
|
|
{ 0xAB, 0, "SSD Program Fail Count" }, |
1028 |
|
|
{ 0xAC, 0, "SSD Erase Fail Count" }, |
1029 |
|
|
{ 0xAD, 0, "SSD Wear Leveling Count" }, |
1030 |
|
|
{ 0xAE, 0, "Unexpected power loss count" }, |
1031 |
|
|
{ 0xAF, 0, "Power Loss Protection Failure" }, |
1032 |
|
|
{ 0xB0, 0, "Erase Fail Count" }, |
1033 |
|
|
{ 0xB1, 0, "Wear Range Delta" }, |
1034 |
|
|
{ 0xB3, 0, "Used Reserved Block Count Total" }, |
1035 |
|
|
{ 0xB4, 0, "Unused Reserved Block Count Total" }, |
1036 |
|
|
{ 0xB5, -1, "Program Fail Count Total or Non-4K Aligned Access Count" }, |
1037 |
|
|
{ 0xB6, 0, "Erase Fail Count" }, |
1038 |
|
|
{ 0xB7, -1, "SATA Downshift Error Count" }, |
1039 |
|
|
{ 0xB8, -1, "End-to-End error / IOEDC" }, |
1040 |
|
|
{ 0xB9, 0, "Head Stability" }, |
1041 |
|
|
{ 0xBA, 0, "Induced Op-Vibration Detection" }, |
1042 |
|
|
{ 0xBB, -1, "Reported Uncorrectable Errors" }, |
1043 |
|
|
{ 0xBC, -1, "Command Timeout" }, |
1044 |
|
|
{ 0xBD, -1, "High Fly Writes" }, |
1045 |
|
|
{ 0xBE, -1, "Airflow Temperature" }, // (WDC) resp. Airflow Temperature Celsius (HP)" }, |
1046 |
|
|
{ 0xBE, +1, "Temperature Difference from 100" }, |
1047 |
|
|
{ 0xBF, -1, "G-sense Error Rate" }, |
1048 |
|
|
{ 0xC0, -1, "Power-off Retract Count" }, // or Emergency Retract Cycle Count (Fujitsu)[22]" }, |
1049 |
|
|
{ 0xC1, -1, "Load Cycle Count" }, // or Load/Unload Cycle Count (Fujitsu)" }, |
1050 |
|
|
{ 0xC2, -1, "Temperature" }, // resp. Temperature Celsius" }, |
1051 |
|
|
{ 0xC3, 0, "Hardware ECC Recovered" }, |
1052 |
|
|
{ 0xC4, -1, "Reallocation Event Count" }, |
1053 |
|
|
{ 0xC5, -1, "Current Pending Sector Count" }, |
1054 |
|
|
{ 0xC6, -1, "Uncorrectable Sector Count" }, // or Offline Uncorrectable or Off-Line Scan Uncorrectable Sector Count[22]" }, |
1055 |
|
|
{ 0xC7, -1, "UltraDMA CRC Error Count" }, |
1056 |
|
|
{ 0xC8, -1, "Multi-Zone Error Rate [29]" }, |
1057 |
|
|
{ 0xC8, -1, "Write Error Rate (Fujitsu)" }, |
1058 |
|
|
{ 0xC9, -1, "Soft Read Error Rate" }, // or TA Counter Detected" }, |
1059 |
|
|
{ 0xCA, -1, "Data Address Mark errors" }, // or TA Counter Increased" }, |
1060 |
|
|
{ 0xCB, -1, "Run Out Cancel" }, |
1061 |
|
|
{ 0xCC, -1, "Soft ECC Correction" }, |
1062 |
|
|
{ 0xCD, -1, "Thermal Asperity Rate (TAR)" }, |
1063 |
|
|
{ 0xCE, 0, "Flying Height" }, |
1064 |
|
|
{ 0xCF, -1, "Spin High Current" }, |
1065 |
|
|
{ 0xD0, 0, "Spin Buzz" }, |
1066 |
|
|
{ 0xD1, 0, "Offline Seek Performance" }, |
1067 |
|
|
{ 0xD2, 0, "Vibration During Write" }, |
1068 |
|
|
{ 0xD3, 0, "Vibration During Write" }, |
1069 |
|
|
{ 0xD4, 0, "Shock During Write" }, |
1070 |
|
|
{ 0xDC, -1, "Disk Shift" }, |
1071 |
|
|
{ 0xDD, -1, "G-Sense Error Rate" }, |
1072 |
|
|
{ 0xDE, 0, "Loaded Hours" }, |
1073 |
|
|
{ 0xDF, 0, "Load/Unload Retry Count" }, |
1074 |
|
|
{ 0xE0, -1, "Load Friction" }, |
1075 |
|
|
{ 0xE1, -1, "Load/Unload Cycle Count" }, |
1076 |
|
|
{ 0xE2, 0, "Load 'In'-time" }, |
1077 |
|
|
{ 0xE3, -1, "Torque Amplification Count" }, |
1078 |
|
|
{ 0xE4, -1, "Power-Off Retract Cycle" }, |
1079 |
|
|
{ 0xE6, 0, "GMR Head Amplitude" }, |
1080 |
|
|
{ 0xE6, +1, "Drive Life Protection Status" }, |
1081 |
|
|
{ 0xE7, -1, "Temperature" }, |
1082 |
|
|
{ 0xE7, +1, "SSD Life Left" }, |
1083 |
|
|
{ 0xE8, 0, "Endurance Remaining" }, |
1084 |
|
|
{ 0xE8, 0, "Available Reserved Space" }, |
1085 |
|
|
{ 0xE9, 0, "Power-On Hours" }, |
1086 |
|
|
{ 0xE9, 0, "Media Wearout Indicator" }, |
1087 |
|
|
{ 0xEA, 0, "Average erase count AND Maximum Erase Count" }, |
1088 |
|
|
{ 0xEB, 0, "Good Block Count AND System(Free) Block Count" }, |
1089 |
|
|
{ 0xF0, 0, "Head Flying Hours" }, |
1090 |
|
|
{ 0xF0, 0, "Transfer Error Rate (Fujitsu)" }, |
1091 |
|
|
{ 0xF1, 0, "Total LBAs Written" }, |
1092 |
|
|
{ 0xF2, 0, "Total LBAs Read" }, |
1093 |
|
|
{ 0xF3, 0, "Total LBAs Written Expanded" }, |
1094 |
|
|
{ 0xF4, 0, "Total LBAs Read Expanded" }, |
1095 |
|
|
{ 0xF6, 0, "Total Host Sector Writes" }, |
1096 |
|
|
{ 0xF7, 0, "Host Program Page Count" }, |
1097 |
|
|
{ 0xF8, 0, "Background Program Page Count" }, |
1098 |
|
|
{ 0xF9, 0, "NAND Writes (1GiB)" }, |
1099 |
|
|
{ 0xFA, -1, "Read Error Retry Rate" }, |
1100 |
|
|
{ 0xFB, 0, "Minimum Spares Remaining" }, |
1101 |
|
|
{ 0xFC, 0, "Newly Added Bad Flash Block" }, |
1102 |
|
|
{ 0xFE, -1, "Free Fall Protection" } |
1103 |
|
|
}; |
1104 |
|
|
static gate_size_t const smart_id_mappings_count = sizeof(smart_id_mappings) / sizeof(smart_id_mappings[0]); |
1105 |
|
|
gate_size_t ndx; |
1106 |
|
|
for (ndx = 0; ndx != smart_id_mappings_count; ++ndx) |
1107 |
|
|
{ |
1108 |
|
|
if (id == smart_id_mappings[ndx].id) |
1109 |
|
|
{ |
1110 |
|
|
if (ptr_description) |
1111 |
|
|
{ |
1112 |
|
|
*ptr_description = smart_id_mappings[ndx].description; |
1113 |
|
|
} |
1114 |
|
|
if (ptr_direction) |
1115 |
|
|
{ |
1116 |
|
|
*ptr_direction = smart_id_mappings[ndx].direction; |
1117 |
|
|
} |
1118 |
|
|
return true; |
1119 |
|
|
} |
1120 |
|
|
} |
1121 |
|
|
return false; |
1122 |
|
|
} |
1123 |
|
|
|
1124 |
|
|
|
1125 |
|
|
|
1126 |
|
|
static gate_result_t gate_storagedrive_queryattribs_smart(gate_storagedrive_t const* drive, gate_storagedrive_attribs_callback_t callback, void* user_param) |
1127 |
|
|
{ |
1128 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
1129 |
|
|
GATE_GETVERSIONINPARAMS versionparams = GATE_INIT_EMPTY; |
1130 |
|
|
GATE_SENDCMDINPARAMS inparams = GATE_INIT_EMPTY; |
1131 |
|
|
GATE_ST_ATAOUTPARAM outparams = GATE_INIT_EMPTY; |
1132 |
|
|
TCHAR device_path[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY; |
1133 |
|
|
DWORD dwRetLen = 0; |
1134 |
|
|
|
1135 |
|
|
HANDLE physical_disk_handle = INVALID_HANDLE_VALUE; |
1136 |
|
|
BYTE physical_disk_num = (BYTE)drive->deviceindex; |
1137 |
|
|
BYTE n; |
1138 |
|
|
gate_int8_t direction; |
1139 |
|
|
BYTE* ptr; |
1140 |
|
|
gate_size_t ndx; |
1141 |
|
|
GATE_SMART_THRESHOLD* ptr_threshold; |
1142 |
|
|
gate_smart_entry_t smart_entries[30] = GATE_INIT_EMPTY; |
1143 |
|
|
static gate_size_t const smart_entries_max = 30; |
1144 |
|
|
gate_size_t smart_entries_used = 0; |
1145 |
|
|
gate_smart_entry_t* ptr_smart_entry; |
1146 |
|
|
gate_int64_t cb_values[6]; |
1147 |
|
|
char const* cb_texts[1]; |
1148 |
|
|
char tmp_buffer[8]; |
1149 |
|
|
|
1150 |
|
|
do |
1151 |
|
|
{ |
1152 |
|
|
gate_win32_utf8_2_winstr( |
1153 |
|
|
drive->devicepath, gate_str_length_max(drive->devicepath, sizeof(drive->devicepath)), |
1154 |
|
|
device_path, sizeof(device_path) / sizeof(device_path[0])); |
1155 |
|
|
physical_disk_handle = gate_win32_createfile(device_path, |
1156 |
|
|
GENERIC_READ | GENERIC_WRITE, |
1157 |
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, |
1158 |
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0, NULL); |
1159 |
|
|
if (INVALID_HANDLE_VALUE == physical_disk_handle) |
1160 |
|
|
{ |
1161 |
|
|
ret = GATE_RESULT_NOTAVAILABLE; |
1162 |
|
|
break; |
1163 |
|
|
} |
1164 |
|
|
|
1165 |
|
|
if (!DeviceIoControl(physical_disk_handle, SMART_GET_VERSION, NULL, 0, &versionparams, sizeof(versionparams), &dwRetLen, NULL)) |
1166 |
|
|
{ |
1167 |
|
|
ret = GATE_RESULT_NOTSUPPORTED; |
1168 |
|
|
break; |
1169 |
|
|
} |
1170 |
|
|
if (!GATE_FLAG_ENABLED(versionparams.fCapabilities, CAP_SMART_CMD)) |
1171 |
|
|
{ |
1172 |
|
|
ret = GATE_RESULT_NOTSUPPORTED; |
1173 |
|
|
break; |
1174 |
|
|
} |
1175 |
|
|
if (!smart_enabled(physical_disk_handle, physical_disk_num)) |
1176 |
|
|
{ |
1177 |
|
|
ret = GATE_RESULT_NOTSUPPORTED; |
1178 |
|
|
break; |
1179 |
|
|
} |
1180 |
|
|
|
1181 |
|
|
/* read SMART values */ |
1182 |
|
|
|
1183 |
|
|
inparams.cBufferSize = READ_ATTRIBUTE_BUFFER_SIZE; |
1184 |
|
|
inparams.bDriveNumber = physical_disk_num; |
1185 |
|
|
inparams.irDriveRegs.bFeaturesReg = READ_ATTRIBUTES; |
1186 |
|
|
inparams.irDriveRegs.bSectorCountReg = 1; |
1187 |
|
|
inparams.irDriveRegs.bSectorNumberReg = 1; |
1188 |
|
|
inparams.irDriveRegs.bCylLowReg = SMART_CYL_LOW; |
1189 |
|
|
inparams.irDriveRegs.bCylHighReg = SMART_CYL_HI; |
1190 |
|
|
inparams.irDriveRegs.bDriveHeadReg = DRIVE_HEAD_REG; |
1191 |
|
|
inparams.irDriveRegs.bCommandReg = SMART_CMD; |
1192 |
|
|
if (!DeviceIoControl(physical_disk_handle, SMART_RCV_DRIVE_DATA, |
1193 |
|
|
&inparams, sizeof(inparams), |
1194 |
|
|
&outparams, sizeof(outparams), |
1195 |
|
|
&dwRetLen, NULL)) |
1196 |
|
|
{ |
1197 |
|
|
ret = GATE_RESULT_INVALIDINPUT; |
1198 |
|
|
break; |
1199 |
|
|
} |
1200 |
|
|
|
1201 |
|
|
for (n = 0; n < smart_entries_max; ++n) |
1202 |
|
|
{ |
1203 |
|
|
ptr = &outparams.bBuffer[2 + n * 12]; |
1204 |
|
|
if (ptr[INDEX_ATTRIB_INDEX] != 0) |
1205 |
|
|
{ |
1206 |
|
|
ptr_smart_entry = &smart_entries[smart_entries_used]; |
1207 |
|
|
ptr_smart_entry->id = ptr[INDEX_ATTRIB_INDEX]; |
1208 |
|
|
ptr_smart_entry->value = ptr[INDEX_ATTRIB_VALUE]; |
1209 |
|
|
ptr_smart_entry->worst = ptr[INDEX_ATTRIB_WORST]; |
1210 |
|
|
ptr_smart_entry->threshold = 0; |
1211 |
|
|
ptr_smart_entry->raw = (((gate_uint64_t)ptr[INDEX_ATTRIB_RAW + 0])) |
1212 |
|
|
| (((gate_uint64_t)ptr[INDEX_ATTRIB_RAW + 1]) << 8) |
1213 |
|
|
| (((gate_uint64_t)ptr[INDEX_ATTRIB_RAW + 2]) << 16) |
1214 |
|
|
| (((gate_uint64_t)ptr[INDEX_ATTRIB_RAW + 3]) << 24) |
1215 |
|
|
| (((gate_uint64_t)ptr[INDEX_ATTRIB_RAW + 4]) << 32) |
1216 |
|
|
| (((gate_uint64_t)ptr[INDEX_ATTRIB_RAW + 5]) << 40); |
1217 |
|
|
++smart_entries_used; |
1218 |
|
|
} |
1219 |
|
|
} |
1220 |
|
|
|
1221 |
|
|
/* read SMART threshold values */ |
1222 |
|
|
inparams.irDriveRegs.bFeaturesReg = READ_THRESHOLDS; |
1223 |
|
|
inparams.cBufferSize = READ_THRESHOLD_BUFFER_SIZE; |
1224 |
|
|
gate_mem_clear(&outparams, sizeof(outparams)); |
1225 |
|
|
|
1226 |
|
|
if (DeviceIoControl(physical_disk_handle, SMART_RCV_DRIVE_DATA, &inparams, sizeof(inparams), |
1227 |
|
|
&outparams, sizeof(outparams), |
1228 |
|
|
&dwRetLen, NULL)) |
1229 |
|
|
{ |
1230 |
|
|
for (n = 0; n < smart_entries_max; ++n) |
1231 |
|
|
{ |
1232 |
|
|
ptr_threshold = (GATE_SMART_THRESHOLD*)&outparams.bBuffer[2 + n * 12]; |
1233 |
|
|
if (ptr_threshold->Id == 0) |
1234 |
|
|
{ |
1235 |
|
|
continue; |
1236 |
|
|
} |
1237 |
|
|
if (ptr_threshold->Id == smart_entries[n].id) |
1238 |
|
|
{ |
1239 |
|
|
ptr_smart_entry = &smart_entries[n]; |
1240 |
|
|
} |
1241 |
|
|
else |
1242 |
|
|
{ |
1243 |
|
|
/* smart thresholds are not coming in the same ID-order than before -> resolve by ID */ |
1244 |
|
|
ptr_smart_entry = NULL; |
1245 |
|
|
for (ndx = 0; ndx < smart_entries_used; ++ndx) |
1246 |
|
|
{ |
1247 |
|
|
if (ptr_threshold->Id == smart_entries[ndx].id) |
1248 |
|
|
{ |
1249 |
|
|
ptr_smart_entry = &smart_entries[ndx]; |
1250 |
|
|
break; |
1251 |
|
|
} |
1252 |
|
|
} |
1253 |
|
|
} |
1254 |
|
|
if (ptr_smart_entry) |
1255 |
|
|
{ |
1256 |
|
|
ptr_smart_entry->threshold = ptr_threshold->Value; |
1257 |
|
|
} |
1258 |
|
|
} |
1259 |
|
|
} |
1260 |
|
|
|
1261 |
|
|
/* send results to callback function */ |
1262 |
|
|
if (callback) |
1263 |
|
|
{ |
1264 |
|
|
for (ndx = 0; ndx < smart_entries_used; ++ndx) |
1265 |
|
|
{ |
1266 |
|
|
ptr_smart_entry = &smart_entries[ndx]; |
1267 |
|
|
direction = 0; |
1268 |
|
|
if (!smart_resolve_description(ptr_smart_entry->id, &cb_texts[0], &direction)) |
1269 |
|
|
{ |
1270 |
|
|
direction = 0; |
1271 |
|
|
tmp_buffer[0] = '#'; |
1272 |
|
|
gate_str_print_int16(&tmp_buffer[1], sizeof(tmp_buffer) - 1, ptr_smart_entry->id); |
1273 |
|
|
cb_texts[0] = tmp_buffer; |
1274 |
|
|
} |
1275 |
|
|
cb_values[GATE_STORAGEDRIVE_ATTRIBINDEX_SMART_ID] = ptr_smart_entry->id; |
1276 |
|
|
cb_values[GATE_STORAGEDRIVE_ATTRIBINDEX_SMART_VALUE] = ptr_smart_entry->value; |
1277 |
|
|
cb_values[GATE_STORAGEDRIVE_ATTRIBINDEX_SMART_WORST] = ptr_smart_entry->worst; |
1278 |
|
|
cb_values[GATE_STORAGEDRIVE_ATTRIBINDEX_SMART_RAW] = (gate_int64_t)ptr_smart_entry->raw; |
1279 |
|
|
cb_values[GATE_STORAGEDRIVE_ATTRIBINDEX_SMART_THRESHOLD] = ptr_smart_entry->threshold; |
1280 |
|
|
cb_values[GATE_STORAGEDRIVE_ATTRIBINDEX_SMART_DIRECTION] = direction; |
1281 |
|
|
if (!callback(drive, GATE_STORAGEDRIVE_ATTRIBTYPE_SMART, cb_values, 6, cb_texts, 1, user_param)) |
1282 |
|
|
{ |
1283 |
|
|
break; |
1284 |
|
|
} |
1285 |
|
|
} |
1286 |
|
|
} |
1287 |
|
|
ret = GATE_RESULT_OK; |
1288 |
|
|
} while (0); |
1289 |
|
|
|
1290 |
|
|
if (physical_disk_handle != INVALID_HANDLE_VALUE) |
1291 |
|
|
{ |
1292 |
|
|
gate_win32_closehandle(physical_disk_handle); |
1293 |
|
|
} |
1294 |
|
|
return ret; |
1295 |
|
|
} |
1296 |
|
|
|
1297 |
|
|
gate_result_t gate_storagedrive_queryattribs(gate_storagedrive_t const* drive, gate_enumint_t attrib_type, |
1298 |
|
|
gate_storagedrive_attribs_callback_t callback, void* user_param) |
1299 |
|
|
{ |
1300 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
1301 |
|
|
do |
1302 |
|
|
{ |
1303 |
|
|
if (!drive || !callback) |
1304 |
|
|
{ |
1305 |
|
|
ret = GATE_RESULT_INVALIDARG; |
1306 |
|
|
break; |
1307 |
|
|
} |
1308 |
|
|
switch (attrib_type) |
1309 |
|
|
{ |
1310 |
|
|
case GATE_STORAGEDRIVE_ATTRIBTYPE_SMART: |
1311 |
|
|
{ |
1312 |
|
|
ret = gate_storagedrive_queryattribs_smart(drive, callback, user_param); |
1313 |
|
|
break; |
1314 |
|
|
} |
1315 |
|
|
default: |
1316 |
|
|
{ |
1317 |
|
|
ret = GATE_RESULT_NOTSUPPORTED; |
1318 |
|
|
break; |
1319 |
|
|
} |
1320 |
|
|
} |
1321 |
|
|
} while (0); |
1322 |
|
|
|
1323 |
|
|
return ret; |
1324 |
|
|
} |
1325 |
|
|
|
1326 |
|
|
#endif /* !defined(GATE_SYS_WINCE) */ |
1327 |
|
|
|
1328 |
|
|
#endif /* defined(GATE_SYSTEM_STORAGEDRIVES_WINAPI_IMPL) */ |
1329 |
|
|
|
1330 |
|
|
|
1331 |
|
|
|
1332 |
|
|
#if defined(GATE_SYSTEM_STORAGEDRIVES_POSIX_IMPL) |
1333 |
|
|
|
1334 |
|
|
#include "gate/files.h" |
1335 |
|
|
#include "gate/platforms.h" |
1336 |
|
|
|
1337 |
|
|
#include <sys/stat.h> |
1338 |
|
|
#include <fcntl.h> |
1339 |
|
|
|
1340 |
|
|
struct gate_storagedrive_enum_param |
1341 |
|
|
{ |
1342 |
|
|
gate_storagedrive_enum_callback_t callback; |
1343 |
|
|
void* user_param; |
1344 |
|
|
gate_enumint_t drivetype; |
1345 |
|
|
}; |
1346 |
|
|
|
1347 |
|
✗ |
static gate_size_t read_file_line(char* destbuffer, gate_size_t destbuffersize, char const* basepath, char const* subpath) |
1348 |
|
|
{ |
1349 |
|
|
char path[GATE_MAX_FILEPATH_LENGTH]; |
1350 |
|
|
gate_size_t pathlen; |
1351 |
|
|
gate_string_t filepath; |
1352 |
|
✗ |
gate_size_t bytes_received = destbuffersize - 1; |
1353 |
|
|
gate_result_t result; |
1354 |
|
|
gate_size_t pos; |
1355 |
|
|
|
1356 |
|
✗ |
if (subpath == NULL) |
1357 |
|
|
{ |
1358 |
|
✗ |
pathlen = gate_str_print_text(path, sizeof(path), basepath, gate_str_length(basepath)); |
1359 |
|
|
} |
1360 |
|
|
else |
1361 |
|
|
{ |
1362 |
|
✗ |
pathlen = gate_file_build_path(path, sizeof(path), basepath, gate_str_length(basepath), subpath, gate_str_length(subpath)); |
1363 |
|
|
} |
1364 |
|
✗ |
gate_string_create_static_len(&filepath, path, pathlen); |
1365 |
|
✗ |
result = gate_file_get_content_buffer(&filepath, destbuffer, &bytes_received); |
1366 |
|
✗ |
if (GATE_SUCCEEDED(result)) |
1367 |
|
|
{ |
1368 |
|
✗ |
pos = gate_str_char_pos(destbuffer, bytes_received, '\n', 0); |
1369 |
|
✗ |
if (pos != GATE_STR_NPOS) |
1370 |
|
|
{ |
1371 |
|
✗ |
bytes_received = pos; |
1372 |
|
|
} |
1373 |
|
✗ |
destbuffer[bytes_received] = 0; |
1374 |
|
✗ |
return bytes_received; |
1375 |
|
|
} |
1376 |
|
|
else |
1377 |
|
|
{ |
1378 |
|
✗ |
destbuffer[0] = 0; |
1379 |
|
✗ |
return 0; |
1380 |
|
|
} |
1381 |
|
|
} |
1382 |
|
|
|
1383 |
|
✗ |
static gate_bool_t gate_storagedrive_enum_cb(gate_file_entry_t const* entry, void* userparam) |
1384 |
|
|
{ |
1385 |
|
✗ |
struct gate_storagedrive_enum_param* dispatcher = (struct gate_storagedrive_enum_param*)userparam; |
1386 |
|
✗ |
gate_bool_t ret = true; |
1387 |
|
✗ |
gate_string_t subdir = GATE_STRING_INIT_EMPTY; |
1388 |
|
|
gate_storagedrive_t drive; |
1389 |
|
|
char subpath[4096]; |
1390 |
|
|
char type[512]; |
1391 |
|
|
char blocks[512]; |
1392 |
|
✗ |
char removable[16] = GATE_INIT_EMPTY; |
1393 |
|
✗ |
char read_only[16] = GATE_INIT_EMPTY; |
1394 |
|
|
gate_size_t name_len; |
1395 |
|
|
gate_size_t prod_len; |
1396 |
|
|
gate_size_t vend_len; |
1397 |
|
|
gate_size_t type_len; |
1398 |
|
|
gate_size_t block_len; |
1399 |
|
|
gate_size_t dev_len; |
1400 |
|
|
gate_size_t removable_len; |
1401 |
|
|
gate_size_t read_only_len; |
1402 |
|
|
gate_strbuilder_t name_builder; |
1403 |
|
✗ |
gate_size_t path_len = gate_str_length(entry->path); |
1404 |
|
|
gate_size_t ndx; |
1405 |
|
|
gate_uint32_t index_factor; |
1406 |
|
|
struct stat filestat; |
1407 |
|
|
|
1408 |
|
✗ |
subdir.str = subpath; |
1409 |
|
✗ |
subdir.length = gate_file_build_path(subpath, sizeof(subpath), entry->path, path_len, "device", 6); |
1410 |
|
✗ |
if (GATE_SUCCEEDED(gate_file_dir_exists(&subdir))) |
1411 |
|
|
{ |
1412 |
|
|
/* storage block device */ |
1413 |
|
✗ |
gate_mem_clear(&drive, sizeof(drive)); |
1414 |
|
✗ |
drive.drivetype = GATE_STORAGEDRIVE_TYPE_STANDARD; |
1415 |
|
✗ |
gate_str_print_text(drive.path, sizeof(drive.path), subdir.str, subdir.length); |
1416 |
|
|
|
1417 |
|
✗ |
name_len = read_file_line(drive.name, sizeof(drive.name), entry->path, "device/model"); |
1418 |
|
✗ |
prod_len = read_file_line(drive.productname, sizeof(drive.productname), entry->path, "device/name"); |
1419 |
|
✗ |
vend_len = read_file_line(drive.vendor, sizeof(drive.vendor), entry->path, "device/vendor"); |
1420 |
|
✗ |
type_len = read_file_line(type, sizeof(type), entry->path, "device/type"); |
1421 |
|
✗ |
block_len = read_file_line(blocks, sizeof(blocks), entry->path, "size"); |
1422 |
|
✗ |
removable_len = read_file_line(removable, sizeof(removable), entry->path, "removable"); |
1423 |
|
✗ |
read_only_len = read_file_line(read_only, sizeof(read_only), entry->path, "ro"); |
1424 |
|
|
|
1425 |
|
✗ |
gate_strbuilder_create_static(&name_builder, drive.name, sizeof(drive.name), name_len); |
1426 |
|
|
|
1427 |
|
✗ |
if (name_len == 0) |
1428 |
|
|
{ |
1429 |
|
✗ |
if (prod_len > 0) |
1430 |
|
|
{ |
1431 |
|
✗ |
name_len = gate_strbuilder_append_text(&name_builder, drive.productname, prod_len); |
1432 |
|
|
} |
1433 |
|
✗ |
else if (vend_len > 0) |
1434 |
|
|
{ |
1435 |
|
✗ |
name_len = gate_strbuilder_append_text(&name_builder, drive.vendor, vend_len); |
1436 |
|
|
} |
1437 |
|
✗ |
name_len = gate_str_print_text(drive.name, sizeof(drive.name), drive.productname, prod_len); |
1438 |
|
|
} |
1439 |
|
|
|
1440 |
|
✗ |
if (gate_str_compare(removable, removable_len, "1", 1) == 0) |
1441 |
|
|
{ |
1442 |
|
✗ |
drive.drivetype = GATE_STORAGEDRIVE_TYPE_REMOVABLE; |
1443 |
|
|
} |
1444 |
|
✗ |
if (gate_str_compare(type, type_len, "SD", 2) == 0) |
1445 |
|
|
{ |
1446 |
|
✗ |
gate_strbuilder_append_cstr(&name_builder, " (MMC/SD)"); |
1447 |
|
|
} |
1448 |
|
✗ |
else if (gate_str_compare(type, type_len, "5", 1) == 0) |
1449 |
|
|
{ |
1450 |
|
✗ |
gate_strbuilder_append_cstr(&name_builder, " (CD/DVD/BR-ROM)"); |
1451 |
|
✗ |
drive.drivetype = GATE_STORAGEDRIVE_TYPE_ROM; |
1452 |
|
|
} |
1453 |
|
|
|
1454 |
|
✗ |
drive.blockcount = 0; |
1455 |
|
✗ |
gate_str_parse_uint64(blocks, block_len, &drive.blockcount); |
1456 |
|
✗ |
drive.blocksize = 512; |
1457 |
|
✗ |
drive.size = drive.blockcount * drive.blocksize; |
1458 |
|
✗ |
gate_str_print_text(drive.uid, sizeof(drive.uid), entry->path, path_len); |
1459 |
|
|
|
1460 |
|
✗ |
dev_len = gate_str_length(entry->name); |
1461 |
|
✗ |
gate_file_build_path(drive.devicepath, sizeof(drive.devicepath), "/dev/", 5, entry->name, dev_len); |
1462 |
|
|
|
1463 |
|
✗ |
if (0 == stat(drive.devicepath, &filestat)) |
1464 |
|
|
{ |
1465 |
|
✗ |
if (0 != (filestat.st_mode & (S_IFBLK | S_IFCHR))) |
1466 |
|
|
{ |
1467 |
|
✗ |
if (dev_len <= 4) |
1468 |
|
|
{ |
1469 |
|
✗ |
drive.deviceindex = 0; |
1470 |
|
✗ |
index_factor = 1; |
1471 |
|
✗ |
for (ndx = 0; ndx < dev_len; ++ndx) |
1472 |
|
|
{ |
1473 |
|
✗ |
drive.deviceindex += ((gate_uint32_t)entry->name[dev_len - ndx - 1]) * index_factor; |
1474 |
|
✗ |
index_factor *= 256; |
1475 |
|
|
} |
1476 |
|
|
} |
1477 |
|
|
} |
1478 |
|
|
else |
1479 |
|
|
{ |
1480 |
|
✗ |
drive.devicepath[0] = 0; |
1481 |
|
|
} |
1482 |
|
|
} |
1483 |
|
|
else |
1484 |
|
|
{ |
1485 |
|
✗ |
drive.devicepath[0] = 0; |
1486 |
|
|
} |
1487 |
|
|
|
1488 |
|
✗ |
if ((dispatcher->drivetype == GATE_STORAGEDRIVE_TYPE_ALL) || ((dispatcher->drivetype & drive.drivetype) != 0)) |
1489 |
|
|
{ |
1490 |
|
✗ |
ret = dispatcher->callback(&drive, dispatcher->user_param); |
1491 |
|
|
} |
1492 |
|
|
else |
1493 |
|
|
{ |
1494 |
|
✗ |
ret = true; |
1495 |
|
|
} |
1496 |
|
|
} |
1497 |
|
✗ |
return ret; |
1498 |
|
|
} |
1499 |
|
|
|
1500 |
|
|
|
1501 |
|
✗ |
gate_result_t gate_storagedrive_enum(gate_enumint_t drivetype, gate_storagedrive_enum_callback_t callback, void* user_param) |
1502 |
|
|
{ |
1503 |
|
✗ |
gate_result_t ret = GATE_RESULT_FAILED; |
1504 |
|
|
static gate_string_t const sysfs_path = { "/sys/block", 10, NULL }; |
1505 |
|
|
struct gate_storagedrive_enum_param dispatcher; |
1506 |
|
✗ |
dispatcher.callback = callback; |
1507 |
|
✗ |
dispatcher.user_param = user_param; |
1508 |
|
✗ |
dispatcher.drivetype = drivetype; |
1509 |
|
|
|
1510 |
|
✗ |
ret = gate_file_list(&sysfs_path, &gate_storagedrive_enum_cb, &dispatcher); |
1511 |
|
|
|
1512 |
|
✗ |
return ret; |
1513 |
|
|
} |
1514 |
|
|
|
1515 |
|
|
|
1516 |
|
|
|
1517 |
|
|
static void drivestream_release(void* thisptr); |
1518 |
|
|
static int drivestream_retain(void* thisptr); |
1519 |
|
|
static char const* drivestream_get_interface_name(void* thisptr); |
1520 |
|
|
|
1521 |
|
|
static gate_result_t drivestream_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned); |
1522 |
|
|
static gate_result_t drivestream_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned); |
1523 |
|
|
static gate_result_t drivestream_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written); |
1524 |
|
|
static gate_result_t drivestream_flush(void* thisptr); |
1525 |
|
|
|
1526 |
|
|
static gate_result_t drivestream_get_resource(void* thisptr, gate_enumint_t resource_type, gate_uintptr_t* resource); |
1527 |
|
|
|
1528 |
|
|
static gate_result_t drivestream_can_read(void* thisptr, gate_bool_t* return_value); |
1529 |
|
|
static gate_result_t drivestream_can_write(void* thisptr, gate_bool_t* return_value); |
1530 |
|
|
static gate_result_t drivestream_get_size(void* thisptr, gate_int64_t* return_value); |
1531 |
|
|
static gate_result_t drivestream_get_available(void* thisptr, gate_int64_t* return_value); |
1532 |
|
|
static gate_result_t drivestream_seek(void* thisptr, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position); |
1533 |
|
|
static gate_result_t drivestream_reset(void* thisptr); |
1534 |
|
|
static gate_result_t drivestream_close(void* thisptr, gate_enumint_t close_type); |
1535 |
|
|
|
1536 |
|
|
static GATE_INTERFACE_VTBL(gate_controlstream) gate_drivestream_vtbl; |
1537 |
|
✗ |
static void gate_init_drivestream_vtbl() |
1538 |
|
|
{ |
1539 |
|
✗ |
if (!gate_drivestream_vtbl.get_interface_name) |
1540 |
|
|
{ |
1541 |
|
|
GATE_INTERFACE_VTBL(gate_controlstream) const local_vtbl = |
1542 |
|
|
{ |
1543 |
|
|
&drivestream_get_interface_name, |
1544 |
|
|
&drivestream_release, |
1545 |
|
|
&drivestream_retain, |
1546 |
|
|
|
1547 |
|
|
&drivestream_read, |
1548 |
|
|
&drivestream_peek, |
1549 |
|
|
&drivestream_write, |
1550 |
|
|
&drivestream_flush, |
1551 |
|
|
|
1552 |
|
|
&drivestream_get_resource, |
1553 |
|
|
|
1554 |
|
|
&drivestream_can_read, |
1555 |
|
|
&drivestream_can_write, |
1556 |
|
|
&drivestream_get_size, |
1557 |
|
|
&drivestream_get_available, |
1558 |
|
|
&drivestream_seek, |
1559 |
|
|
&drivestream_reset, |
1560 |
|
|
&drivestream_close, |
1561 |
|
|
}; |
1562 |
|
✗ |
gate_drivestream_vtbl = local_vtbl; |
1563 |
|
|
} |
1564 |
|
✗ |
} |
1565 |
|
|
|
1566 |
|
|
typedef struct gate_drivestream_class |
1567 |
|
|
{ |
1568 |
|
|
GATE_INTERFACE_VTBL(gate_controlstream) const* vtbl; |
1569 |
|
|
|
1570 |
|
|
gate_atomic_int_t ref_counter; |
1571 |
|
|
gate_bool_t writeaccess; |
1572 |
|
|
gate_size_t locked_handle_count; |
1573 |
|
|
|
1574 |
|
|
gate_platform_stream_buffer_t block_stream; |
1575 |
|
|
} gate_drivestream_t; |
1576 |
|
|
|
1577 |
|
|
|
1578 |
|
✗ |
gate_result_t gate_storagedrive_openstream(gate_storagedrive_t const* drive, gate_enumint_t open_flags, gate_controlstream_t** stream) |
1579 |
|
|
{ |
1580 |
|
|
gate_result_t ret; |
1581 |
|
✗ |
gate_drivestream_t* drivestream = NULL; |
1582 |
|
|
gate_bool_t writable; |
1583 |
|
|
|
1584 |
|
✗ |
int fd = -1; |
1585 |
|
|
int o_flags; |
1586 |
|
|
|
1587 |
|
|
do |
1588 |
|
|
{ |
1589 |
|
✗ |
if ((drive == NULL) || (stream == NULL)) |
1590 |
|
|
{ |
1591 |
|
✗ |
ret = GATE_RESULT_INVALIDARG; |
1592 |
|
✗ |
break; |
1593 |
|
|
} |
1594 |
|
|
|
1595 |
|
✗ |
if (open_flags == GATE_STREAM_OPEN_READ) |
1596 |
|
|
{ |
1597 |
|
✗ |
o_flags = O_RDONLY; |
1598 |
|
✗ |
writable = false; |
1599 |
|
|
} |
1600 |
|
✗ |
else if (open_flags == GATE_STREAM_OPEN_WRITE) |
1601 |
|
|
{ |
1602 |
|
✗ |
o_flags = O_WRONLY; |
1603 |
|
✗ |
writable = true; |
1604 |
|
|
} |
1605 |
|
|
else |
1606 |
|
|
{ |
1607 |
|
✗ |
ret = GATE_RESULT_INVALIDARG; |
1608 |
|
✗ |
break; |
1609 |
|
|
} |
1610 |
|
|
|
1611 |
|
✗ |
fd = gate_posix_open(drive->devicepath, o_flags, 0); |
1612 |
|
✗ |
if (fd == -1) |
1613 |
|
|
{ |
1614 |
|
✗ |
ret = gate_platform_print_last_error(NULL, 0); |
1615 |
|
✗ |
break; |
1616 |
|
|
} |
1617 |
|
|
|
1618 |
|
✗ |
drivestream = gate_mem_alloc(sizeof(gate_drivestream_t) + (gate_size_t)drive->blocksize); |
1619 |
|
✗ |
if (drivestream == NULL) |
1620 |
|
|
{ |
1621 |
|
✗ |
ret = GATE_RESULT_OUTOFMEMORY; |
1622 |
|
✗ |
break; |
1623 |
|
|
} |
1624 |
|
|
|
1625 |
|
✗ |
gate_init_drivestream_vtbl(); |
1626 |
|
✗ |
drivestream->vtbl = &gate_drivestream_vtbl; |
1627 |
|
✗ |
gate_atomic_int_init(&drivestream->ref_counter, 1); |
1628 |
|
✗ |
drivestream->writeaccess = writable; |
1629 |
|
|
|
1630 |
|
✗ |
gate_platform_stream_buffer_init(&drivestream->block_stream, (gate_platform_stream_t)(gate_intptr_t)fd, |
1631 |
|
✗ |
(gate_int64_t)drive->size, 0, (gate_size_t)drive->blocksize); |
1632 |
|
|
|
1633 |
|
✗ |
fd = -1; |
1634 |
|
✗ |
*stream = (gate_controlstream_t*)drivestream; |
1635 |
|
✗ |
drivestream = NULL; |
1636 |
|
✗ |
ret = GATE_RESULT_OK; |
1637 |
|
|
} while (0); |
1638 |
|
|
|
1639 |
|
✗ |
if (GATE_FAILED(ret)) |
1640 |
|
|
{ |
1641 |
|
✗ |
if (fd != -1) |
1642 |
|
|
{ |
1643 |
|
✗ |
gate_posix_close(fd); |
1644 |
|
|
} |
1645 |
|
✗ |
if (drivestream != NULL) |
1646 |
|
|
{ |
1647 |
|
✗ |
gate_mem_dealloc(drivestream); |
1648 |
|
|
} |
1649 |
|
|
} |
1650 |
|
✗ |
return ret; |
1651 |
|
|
} |
1652 |
|
|
|
1653 |
|
✗ |
static void drivestream_release(void* thisptr) |
1654 |
|
|
{ |
1655 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1656 |
|
|
|
1657 |
|
✗ |
if (0 == gate_atomic_int_dec(&stream->ref_counter)) |
1658 |
|
|
{ |
1659 |
|
✗ |
gate_platform_stream_close(&stream->block_stream.stream); |
1660 |
|
|
|
1661 |
|
✗ |
gate_mem_dealloc(thisptr); |
1662 |
|
|
} |
1663 |
|
✗ |
} |
1664 |
|
✗ |
static int drivestream_retain(void* thisptr) |
1665 |
|
|
{ |
1666 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1667 |
|
✗ |
return gate_atomic_int_inc(&stream->ref_counter); |
1668 |
|
|
} |
1669 |
|
✗ |
static char const* drivestream_get_interface_name(void* thisptr) |
1670 |
|
|
{ |
1671 |
|
|
(void)thisptr; |
1672 |
|
✗ |
return GATE_INTERFACE_NAME_CONTROLSTREAM; |
1673 |
|
|
} |
1674 |
|
|
|
1675 |
|
✗ |
static gate_result_t drivestream_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned) |
1676 |
|
|
{ |
1677 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1678 |
|
✗ |
gate_result_t ret = GATE_RESULT_FAILED; |
1679 |
|
|
|
1680 |
|
|
do |
1681 |
|
|
{ |
1682 |
|
✗ |
if (stream->writeaccess) |
1683 |
|
|
{ |
1684 |
|
✗ |
ret = GATE_RESULT_INVALIDSTATE; |
1685 |
|
✗ |
break; |
1686 |
|
|
} |
1687 |
|
✗ |
if ((bufferlength == 0) || (buffer == NULL)) |
1688 |
|
|
{ |
1689 |
|
✗ |
ret = GATE_RESULT_INVALIDARG; |
1690 |
|
✗ |
break; |
1691 |
|
|
} |
1692 |
|
|
|
1693 |
|
✗ |
ret = gate_platform_stream_buffer_read(&stream->block_stream, buffer, bufferlength, returned); |
1694 |
|
|
} while (0); |
1695 |
|
|
|
1696 |
|
✗ |
return ret; |
1697 |
|
|
} |
1698 |
|
✗ |
static gate_result_t drivestream_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned) |
1699 |
|
|
{ |
1700 |
|
|
(void)thisptr; |
1701 |
|
|
(void)buffer; |
1702 |
|
|
(void)bufferlength; |
1703 |
|
|
(void)returned; |
1704 |
|
✗ |
return GATE_RESULT_NOTSUPPORTED; |
1705 |
|
|
} |
1706 |
|
✗ |
static gate_result_t drivestream_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written) |
1707 |
|
|
{ |
1708 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1709 |
|
✗ |
gate_result_t ret = GATE_RESULT_FAILED; |
1710 |
|
|
|
1711 |
|
|
do |
1712 |
|
|
{ |
1713 |
|
✗ |
if (!stream->writeaccess) |
1714 |
|
|
{ |
1715 |
|
✗ |
ret = GATE_RESULT_INVALIDSTATE; |
1716 |
|
✗ |
break; |
1717 |
|
|
} |
1718 |
|
|
|
1719 |
|
✗ |
if ((bufferlength == 0) || (buffer == NULL)) |
1720 |
|
|
{ |
1721 |
|
✗ |
ret = GATE_RESULT_INVALIDARG; |
1722 |
|
✗ |
break; |
1723 |
|
|
} |
1724 |
|
|
|
1725 |
|
✗ |
ret = gate_platform_stream_buffer_write(&stream->block_stream, buffer, bufferlength, written); |
1726 |
|
|
} while (0); |
1727 |
|
|
|
1728 |
|
✗ |
return ret; |
1729 |
|
|
} |
1730 |
|
✗ |
static gate_result_t drivestream_flush(void* thisptr) |
1731 |
|
|
{ |
1732 |
|
✗ |
gate_result_t ret = GATE_RESULT_OK; |
1733 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1734 |
|
✗ |
if (-1 == fsync((int)(gate_intptr_t)stream->block_stream.stream)) |
1735 |
|
|
{ |
1736 |
|
✗ |
ret = GATE_RESULT_FAILED; |
1737 |
|
|
} |
1738 |
|
✗ |
return ret; |
1739 |
|
|
} |
1740 |
|
|
|
1741 |
|
✗ |
static gate_result_t drivestream_get_resource(void* thisptr, gate_enumint_t resource_type, gate_uintptr_t* resource) |
1742 |
|
|
{ |
1743 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1744 |
|
|
(void)resource_type; |
1745 |
|
✗ |
*resource = (gate_uintptr_t)(void*)stream->block_stream.stream; |
1746 |
|
✗ |
return GATE_RESULT_OK; |
1747 |
|
|
} |
1748 |
|
|
|
1749 |
|
✗ |
static gate_result_t drivestream_can_read(void* thisptr, gate_bool_t* return_value) |
1750 |
|
|
{ |
1751 |
|
✗ |
gate_result_t ret = GATE_RESULT_OK; |
1752 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1753 |
|
✗ |
if (return_value) |
1754 |
|
|
{ |
1755 |
|
✗ |
*return_value = stream->writeaccess ? false : true; |
1756 |
|
|
} |
1757 |
|
✗ |
return ret; |
1758 |
|
|
} |
1759 |
|
✗ |
static gate_result_t drivestream_can_write(void* thisptr, gate_bool_t* return_value) |
1760 |
|
|
{ |
1761 |
|
✗ |
gate_result_t ret = GATE_RESULT_OK; |
1762 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1763 |
|
✗ |
if (return_value) |
1764 |
|
|
{ |
1765 |
|
✗ |
*return_value = stream->writeaccess ? true : false; |
1766 |
|
|
} |
1767 |
|
✗ |
return ret; |
1768 |
|
|
} |
1769 |
|
✗ |
static gate_result_t drivestream_get_size(void* thisptr, gate_int64_t* return_value) |
1770 |
|
|
{ |
1771 |
|
✗ |
gate_result_t ret = GATE_RESULT_OK; |
1772 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1773 |
|
✗ |
if (return_value) |
1774 |
|
|
{ |
1775 |
|
✗ |
*return_value = (gate_int64_t)stream->block_stream.total_size; |
1776 |
|
|
} |
1777 |
|
✗ |
return ret; |
1778 |
|
|
} |
1779 |
|
✗ |
static gate_result_t drivestream_get_available(void* thisptr, gate_int64_t* return_value) |
1780 |
|
|
{ |
1781 |
|
✗ |
gate_result_t ret = GATE_RESULT_OK; |
1782 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1783 |
|
✗ |
if (return_value) |
1784 |
|
|
{ |
1785 |
|
✗ |
*return_value = (gate_int64_t)stream->block_stream.total_size - (gate_int64_t)stream->block_stream.position; |
1786 |
|
|
} |
1787 |
|
✗ |
return ret; |
1788 |
|
|
} |
1789 |
|
✗ |
static gate_result_t drivestream_seek(void* thisptr, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position) |
1790 |
|
|
{ |
1791 |
|
✗ |
gate_drivestream_t* stream = (gate_drivestream_t*)thisptr; |
1792 |
|
|
int stream_origin; |
1793 |
|
✗ |
switch (origin) |
1794 |
|
|
{ |
1795 |
|
✗ |
case GATE_STREAM_SEEK_BEGIN: |
1796 |
|
✗ |
stream_origin = GATE_PLATFORM_STREAM_ORIGIN_BEGIN; |
1797 |
|
✗ |
break; |
1798 |
|
✗ |
case GATE_STREAM_SEEK_CURRENT: |
1799 |
|
✗ |
stream_origin = GATE_PLATFORM_STREAM_ORIGIN_CURRENT; |
1800 |
|
✗ |
break; |
1801 |
|
✗ |
case GATE_STREAM_SEEK_END: |
1802 |
|
✗ |
stream_origin = GATE_PLATFORM_STREAM_ORIGIN_END; |
1803 |
|
✗ |
break; |
1804 |
|
✗ |
default: |
1805 |
|
✗ |
return GATE_RESULT_INVALIDARG; |
1806 |
|
|
} |
1807 |
|
|
|
1808 |
|
✗ |
return gate_platform_stream_buffer_seek(&stream->block_stream, position, stream_origin, final_position); |
1809 |
|
|
} |
1810 |
|
✗ |
static gate_result_t drivestream_reset(void* thisptr) |
1811 |
|
|
{ |
1812 |
|
|
(void)thisptr; |
1813 |
|
✗ |
return GATE_RESULT_NOTIMPLEMENTED; |
1814 |
|
|
} |
1815 |
|
✗ |
static gate_result_t drivestream_close(void* thisptr, gate_enumint_t close_type) |
1816 |
|
|
{ |
1817 |
|
|
(void)thisptr; |
1818 |
|
|
(void)close_type; |
1819 |
|
✗ |
return GATE_RESULT_NOTIMPLEMENTED; |
1820 |
|
|
} |
1821 |
|
|
|
1822 |
|
✗ |
gate_result_t gate_storagedrive_queryattribs(gate_storagedrive_t const* drive, gate_enumint_t attrib_type, |
1823 |
|
|
gate_storagedrive_attribs_callback_t callback, void* user_param) |
1824 |
|
|
{ |
1825 |
|
|
GATE_UNUSED_ARG(drive); |
1826 |
|
|
GATE_UNUSED_ARG(attrib_type); |
1827 |
|
|
GATE_UNUSED_ARG(callback); |
1828 |
|
|
GATE_UNUSED_ARG(user_param); |
1829 |
|
✗ |
return GATE_RESULT_NOTIMPLEMENTED; |
1830 |
|
|
} |
1831 |
|
|
|
1832 |
|
|
#endif /* defined(GATE_SYSTEM_STORAGEDRIVES_POSIX_IMPL) */ |
1833 |
|
|
|
1834 |
|
|
|
1835 |
|
|
#if defined(GATE_SYSTEM_STORAGEDRIVES_DOS_IMPL) |
1836 |
|
|
|
1837 |
|
|
#include "gate/platforms.h" |
1838 |
|
|
|
1839 |
|
|
typedef struct bios_chs_class |
1840 |
|
|
{ |
1841 |
|
|
unsigned cylinder; /* 0 - last-cyl or amount of cyls (geometry) */ |
1842 |
|
|
unsigned head; /* 0 - last-head or amount of heads (geometry) */ |
1843 |
|
|
unsigned sector; /* 0 - last-sector or amount of sectors (geometry) */ |
1844 |
|
|
} bios_chs_t; |
1845 |
|
|
|
1846 |
|
|
static void lba_2_chs(gate_uint64_t lba_input, bios_chs_t const* geometry, bios_chs_t* ptr_output) |
1847 |
|
|
{ |
1848 |
|
|
gate_uint64_t sector; |
1849 |
|
|
gate_uint64_t head; |
1850 |
|
|
gate_uint64_t cyl; |
1851 |
|
|
|
1852 |
|
|
sector = lba_input % (gate_uint64_t)geometry->sector; |
1853 |
|
|
cyl = lba_input / (gate_uint64_t)geometry->sector; |
1854 |
|
|
if (geometry->head > 1) |
1855 |
|
|
{ |
1856 |
|
|
head = cyl % (gate_uint64_t)geometry->head; |
1857 |
|
|
cyl = cyl / (gate_uint64_t)geometry->head; |
1858 |
|
|
} |
1859 |
|
|
else |
1860 |
|
|
{ |
1861 |
|
|
head = 0; |
1862 |
|
|
} |
1863 |
|
|
ptr_output->cylinder = (unsigned)cyl; |
1864 |
|
|
ptr_output->head = (unsigned)head; |
1865 |
|
|
ptr_output->sector = (unsigned)sector; |
1866 |
|
|
} |
1867 |
|
|
|
1868 |
|
|
/* |
1869 |
|
|
static void chs_2_lba(bios_chs_t* ptr_input, bios_chs_t const* geometry, gate_uint64_t* ptr_output) |
1870 |
|
|
{ |
1871 |
|
|
gate_uint64_t sectors_per_cyl = (gate_uint64_t)geometry->sector * (gate_uint64_t)geometry->head; |
1872 |
|
|
gate_uint64_t lba = (gate_uint64_t)ptr_input->cylinder * sectors_per_cyl; |
1873 |
|
|
lba += (gate_uint64_t)ptr_input->head * (gate_uint64_t)geometry->sector; |
1874 |
|
|
lba += (gate_uint64_t)ptr_input->sector; |
1875 |
|
|
*ptr_output = lba; |
1876 |
|
|
} |
1877 |
|
|
*/ |
1878 |
|
|
|
1879 |
|
|
static unsigned bios_reset_disk(unsigned char drive_index) |
1880 |
|
|
{ |
1881 |
|
|
gate_dos_gpregs_t gpregs = GATE_INIT_EMPTY; |
1882 |
|
|
gpregs.a.h = 0x00; |
1883 |
|
|
gpregs.d.l = drive_index; |
1884 |
|
|
gate_dos_intr(0x13, &gpregs, NULL); |
1885 |
|
|
if (GATE_FLAG_ENABLED(gpregs.flags, gate_dos_cpuflags_CF)) |
1886 |
|
|
{ |
1887 |
|
|
/* error */ |
1888 |
|
|
return 1; |
1889 |
|
|
} |
1890 |
|
|
/* success */ |
1891 |
|
|
return 0; |
1892 |
|
|
} |
1893 |
|
|
|
1894 |
|
|
static unsigned bios_access_disk_sectors(unsigned char drive_index, bios_chs_t const* ptr_chs, gate_bool_t write_access, void* ptr_buffer) |
1895 |
|
|
{ |
1896 |
|
|
unsigned const max_try_count = write_access ? 2 : 3; |
1897 |
|
|
unsigned try_counter; |
1898 |
|
|
gate_bool_t error_mode = false; |
1899 |
|
|
gate_dos_gpregs_t gpregs = GATE_INIT_EMPTY; |
1900 |
|
|
gate_dos_memregs_t memregs = GATE_INIT_EMPTY; |
1901 |
|
|
|
1902 |
|
|
/* retry read on errors is recommended |
1903 |
|
|
* see: https://stanislavs.org/helppc/int_13-2.html |
1904 |
|
|
*/ |
1905 |
|
|
for (try_counter = 0; try_counter < max_try_count; ++try_counter) |
1906 |
|
|
{ |
1907 |
|
|
if (error_mode) |
1908 |
|
|
{ |
1909 |
|
|
bios_reset_disk(drive_index); |
1910 |
|
|
error_mode = false; |
1911 |
|
|
} |
1912 |
|
|
|
1913 |
|
|
gpregs.a.h = write_access ? 0x03 : 0x02; |
1914 |
|
|
gpregs.a.l = 1; |
1915 |
|
|
gpregs.c.h = ptr_chs->cylinder & 0xff; |
1916 |
|
|
gpregs.c.l = (gate_uint8_t)((ptr_chs->cylinder >> 2) & 0xc0) | (gate_uint8_t)((ptr_chs->sector + 1) & 0x3f); |
1917 |
|
|
gpregs.d.h = (gate_uint8_t)(ptr_chs->head & 0xff); |
1918 |
|
|
gpregs.d.l = drive_index; |
1919 |
|
|
memregs.es = gate_dos_farptr_seg(ptr_buffer); |
1920 |
|
|
gpregs.b.x = gate_dos_farptr_off(ptr_buffer); |
1921 |
|
|
gpregs.flags = 0; |
1922 |
|
|
gate_dos_intr(0x13, &gpregs, &memregs); |
1923 |
|
|
|
1924 |
|
|
if (GATE_FLAG_ENABLED(gpregs.flags, gate_dos_cpuflags_CF)) |
1925 |
|
|
{ |
1926 |
|
|
/* error */ |
1927 |
|
|
error_mode = true; |
1928 |
|
|
} |
1929 |
|
|
else |
1930 |
|
|
{ |
1931 |
|
|
/* success */ |
1932 |
|
|
break; |
1933 |
|
|
} |
1934 |
|
|
} |
1935 |
|
|
|
1936 |
|
|
if (GATE_FLAG_ENABLED(gpregs.flags, gate_dos_cpuflags_CF)) |
1937 |
|
|
{ |
1938 |
|
|
/* error */ |
1939 |
|
|
gate_mem_clear(&gpregs, sizeof(gpregs)); |
1940 |
|
|
gpregs.a.h = 0x01; |
1941 |
|
|
gpregs.d.l = drive_index; |
1942 |
|
|
gate_dos_intr(0x13, &gpregs, NULL); |
1943 |
|
|
return gpregs.a.h; |
1944 |
|
|
} |
1945 |
|
|
|
1946 |
|
|
/* success */ |
1947 |
|
|
return 0; |
1948 |
|
|
} |
1949 |
|
|
|
1950 |
|
|
static gate_bool_t bios_get_driveinfo(unsigned char drive_index, bios_chs_t* ptr_chs, gate_storagedrive_t* ptr_drive) |
1951 |
|
|
{ |
1952 |
|
|
gate_dos_gpregs_t gpregs = GATE_INIT_EMPTY; |
1953 |
|
|
gate_dos_memregs_t memregs = GATE_INIT_EMPTY; |
1954 |
|
|
bios_chs_t chs = GATE_INIT_EMPTY; |
1955 |
|
|
int result; |
1956 |
|
|
char path_buffer[] = "drive00"; |
1957 |
|
|
gate_size_t path_buffer_len = 7; |
1958 |
|
|
|
1959 |
|
|
gpregs.a.h = 0x08; |
1960 |
|
|
gpregs.d.l = drive_index; |
1961 |
|
|
result = gate_dos_intr(0x13, &gpregs, &memregs); |
1962 |
|
|
if (GATE_FLAG_ENABLED(gpregs.flags, gate_dos_cpuflags_CF)) |
1963 |
|
|
{ |
1964 |
|
|
return false; |
1965 |
|
|
} |
1966 |
|
|
|
1967 |
|
|
chs.cylinder = (((gpregs.c.x & 0xc0) << 2) | ((gpregs.c.x & 0xff00) >> 8)) + 1; |
1968 |
|
|
chs.head = gpregs.d.h + 1; |
1969 |
|
|
chs.sector = gpregs.c.x & 0x3f; |
1970 |
|
|
|
1971 |
|
|
if (ptr_chs) |
1972 |
|
|
{ |
1973 |
|
|
gate_mem_copy(ptr_chs, &chs, sizeof(chs)); |
1974 |
|
|
} |
1975 |
|
|
|
1976 |
|
|
if (ptr_drive) |
1977 |
|
|
{ |
1978 |
|
|
gate_mem_clear(ptr_drive, sizeof(gate_storagedrive_t)); |
1979 |
|
|
ptr_drive->blockcount = (gate_uint32_t)chs.cylinder * (gate_uint32_t)chs.head * (gate_uint32_t)chs.sector; |
1980 |
|
|
ptr_drive->blocksize = 512; |
1981 |
|
|
ptr_drive->deviceindex = drive_index; |
1982 |
|
|
ptr_drive->size = ptr_drive->blockcount * ptr_drive->blocksize; |
1983 |
|
|
|
1984 |
|
|
gate_str_print_hex_byte(&path_buffer[path_buffer_len - 2], 2, drive_index, false); |
1985 |
|
|
|
1986 |
|
|
gate_str_print_text(ptr_drive->devicepath, sizeof(ptr_drive->devicepath), path_buffer, path_buffer_len); |
1987 |
|
|
gate_str_print_text(ptr_drive->name, sizeof(ptr_drive->name), path_buffer, path_buffer_len); |
1988 |
|
|
gate_str_print_text(ptr_drive->path, sizeof(ptr_drive->path), path_buffer, path_buffer_len); |
1989 |
|
|
gate_str_print_text(ptr_drive->uid, sizeof(ptr_drive->uid), path_buffer, path_buffer_len); |
1990 |
|
|
|
1991 |
|
|
ptr_drive->drivetype = (drive_index < 0x80) ? GATE_STORAGEDRIVE_TYPE_REMOVABLE : GATE_STORAGEDRIVE_TYPE_STANDARD; |
1992 |
|
|
ptr_drive->flags = 0; |
1993 |
|
|
|
1994 |
|
|
gate_str_print_text(ptr_drive->productname, sizeof(ptr_drive->productname), "BIOS drive", 10); |
1995 |
|
|
ptr_drive->serial[0] = 0; |
1996 |
|
|
ptr_drive->vendor[0] = 0; |
1997 |
|
|
} |
1998 |
|
|
return true; |
1999 |
|
|
} |
2000 |
|
|
|
2001 |
|
|
gate_result_t gate_storagedrive_enum(gate_enumint_t drivetype, gate_storagedrive_enum_callback_t callback, void* user_param) |
2002 |
|
|
{ |
2003 |
|
|
unsigned char ndx; |
2004 |
|
|
gate_storagedrive_t drive; |
2005 |
|
|
const gate_bool_t list_floppies = GATE_FLAG_ENABLED(drivetype, GATE_STORAGEDRIVE_TYPE_REMOVABLE) || (drivetype == GATE_STORAGEDRIVE_TYPE_ALL); |
2006 |
|
|
const gate_bool_t list_harddisks = GATE_FLAG_ENABLED(drivetype, GATE_STORAGEDRIVE_TYPE_STANDARD) || (drivetype == GATE_STORAGEDRIVE_TYPE_ALL); |
2007 |
|
|
|
2008 |
|
|
if (list_floppies) |
2009 |
|
|
{ |
2010 |
|
|
for (ndx = 0; ndx < 4; ++ndx) |
2011 |
|
|
{ |
2012 |
|
|
if (bios_get_driveinfo(ndx, NULL, &drive)) |
2013 |
|
|
{ |
2014 |
|
|
if (!callback(&drive, user_param)) |
2015 |
|
|
{ |
2016 |
|
|
return GATE_RESULT_OK; |
2017 |
|
|
} |
2018 |
|
|
} |
2019 |
|
|
} |
2020 |
|
|
} |
2021 |
|
|
|
2022 |
|
|
if (list_harddisks) |
2023 |
|
|
{ |
2024 |
|
|
for (ndx = 0x80; ndx < 0x90; ++ndx) |
2025 |
|
|
{ |
2026 |
|
|
if (bios_get_driveinfo(ndx, NULL, &drive)) |
2027 |
|
|
{ |
2028 |
|
|
if (!callback(&drive, user_param)) |
2029 |
|
|
{ |
2030 |
|
|
return GATE_RESULT_OK; |
2031 |
|
|
} |
2032 |
|
|
} |
2033 |
|
|
} |
2034 |
|
|
} |
2035 |
|
|
|
2036 |
|
|
return GATE_RESULT_OK; |
2037 |
|
|
} |
2038 |
|
|
|
2039 |
|
|
|
2040 |
|
|
typedef struct sd_stream_class |
2041 |
|
|
{ |
2042 |
|
|
GATE_INTERFACE_VTBL(gate_controlstream) const* vtbl; |
2043 |
|
|
|
2044 |
|
|
gate_atomic_int_t ref_counter; |
2045 |
|
|
unsigned char drive_index; |
2046 |
|
|
gate_bool_t write_access; |
2047 |
|
|
|
2048 |
|
|
bios_chs_t geometry; |
2049 |
|
|
gate_uint64_t block_count; |
2050 |
|
|
gate_uint64_t block_offset; |
2051 |
|
|
gate_size_t block_size; |
2052 |
|
|
|
2053 |
|
|
gate_size_t buffer_pos; /* read: position in buffer[] where next read-transfer will start, write: amount of data already written to buffer */ |
2054 |
|
|
char buffer[512]; /* internal buffer holding last sector-read data, or data for next sector-write operation */ |
2055 |
|
|
} sd_stream_t; |
2056 |
|
|
|
2057 |
|
|
|
2058 |
|
|
static char const* sd_get_interface_name(void* obj) |
2059 |
|
|
{ |
2060 |
|
|
GATE_UNUSED_ARG(obj); |
2061 |
|
|
return GATE_INTERFACE_NAME_CONTROLSTREAM; |
2062 |
|
|
} |
2063 |
|
|
static void sd_release(void* obj) |
2064 |
|
|
{ |
2065 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2066 |
|
|
if (gate_atomic_int_dec(&self->ref_counter) == 0) |
2067 |
|
|
{ |
2068 |
|
|
gate_mem_dealloc(self); |
2069 |
|
|
} |
2070 |
|
|
} |
2071 |
|
|
static int sd_retain(void* obj) |
2072 |
|
|
{ |
2073 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2074 |
|
|
return gate_atomic_int_inc(&self->ref_counter); |
2075 |
|
|
} |
2076 |
|
|
|
2077 |
|
|
static gate_result_t sd_peek(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned) |
2078 |
|
|
{ |
2079 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
2080 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2081 |
|
|
bios_chs_t chs; |
2082 |
|
|
unsigned result; |
2083 |
|
|
gate_size_t available; |
2084 |
|
|
|
2085 |
|
|
do |
2086 |
|
|
{ |
2087 |
|
|
if (self->write_access) |
2088 |
|
|
{ |
2089 |
|
|
ret = GATE_RESULT_INVALIDSTATE; |
2090 |
|
|
break; |
2091 |
|
|
} |
2092 |
|
|
if (self->buffer_pos >= self->block_size) |
2093 |
|
|
{ |
2094 |
|
|
if (self->block_offset >= self->block_count) |
2095 |
|
|
{ |
2096 |
|
|
/* end of stream reached */ |
2097 |
|
|
if (returned) |
2098 |
|
|
{ |
2099 |
|
|
*returned = 0; |
2100 |
|
|
} |
2101 |
|
|
ret = GATE_RESULT_OK; |
2102 |
|
|
break; |
2103 |
|
|
} |
2104 |
|
|
lba_2_chs(self->block_offset, &self->geometry, &chs); |
2105 |
|
|
result = bios_access_disk_sectors(self->drive_index, &chs, false, &self->buffer[0]); |
2106 |
|
|
if (result != 0) |
2107 |
|
|
{ |
2108 |
|
|
ret = GATE_RESULT_FAILED; |
2109 |
|
|
break; |
2110 |
|
|
} |
2111 |
|
|
++self->block_offset; |
2112 |
|
|
self->buffer_pos = 0; |
2113 |
|
|
} |
2114 |
|
|
available = self->block_size - self->buffer_pos; |
2115 |
|
|
if (bufferlength > available) |
2116 |
|
|
{ |
2117 |
|
|
bufferlength = available; |
2118 |
|
|
} |
2119 |
|
|
gate_mem_copy(buffer, &self->buffer[self->buffer_pos], bufferlength); |
2120 |
|
|
if (returned) |
2121 |
|
|
{ |
2122 |
|
|
*returned = bufferlength; |
2123 |
|
|
} |
2124 |
|
|
ret = GATE_RESULT_OK; |
2125 |
|
|
} while (0); |
2126 |
|
|
return ret; |
2127 |
|
|
} |
2128 |
|
|
|
2129 |
|
|
static gate_result_t sd_read(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned) |
2130 |
|
|
{ |
2131 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
2132 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2133 |
|
|
gate_size_t extracted = 0; |
2134 |
|
|
|
2135 |
|
|
do |
2136 |
|
|
{ |
2137 |
|
|
if (self->write_access) |
2138 |
|
|
{ |
2139 |
|
|
ret = GATE_RESULT_INVALIDSTATE; |
2140 |
|
|
break; |
2141 |
|
|
} |
2142 |
|
|
ret = sd_peek(obj, buffer, bufferlength, &extracted); |
2143 |
|
|
GATE_BREAK_IF_FAILED(ret); |
2144 |
|
|
self->buffer_pos += extracted; |
2145 |
|
|
if (returned) |
2146 |
|
|
{ |
2147 |
|
|
*returned = extracted; |
2148 |
|
|
} |
2149 |
|
|
} while (0); |
2150 |
|
|
return ret; |
2151 |
|
|
} |
2152 |
|
|
|
2153 |
|
|
static gate_result_t sd_write(void* obj, char const* buffer, gate_size_t bufferlength, gate_size_t* written) |
2154 |
|
|
{ |
2155 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
2156 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2157 |
|
|
bios_chs_t chs; |
2158 |
|
|
unsigned result; |
2159 |
|
|
gate_size_t avail; |
2160 |
|
|
gate_size_t bufferused; |
2161 |
|
|
gate_size_t processed = 0; |
2162 |
|
|
|
2163 |
|
|
do |
2164 |
|
|
{ |
2165 |
|
|
if (!self->write_access) |
2166 |
|
|
{ |
2167 |
|
|
ret = GATE_RESULT_INVALIDSTATE; |
2168 |
|
|
break; |
2169 |
|
|
} |
2170 |
|
|
|
2171 |
|
|
if (self->buffer_pos != 0) |
2172 |
|
|
{ |
2173 |
|
|
avail = self->block_size - self->buffer_pos; |
2174 |
|
|
bufferused = bufferlength; |
2175 |
|
|
if (bufferused > avail) |
2176 |
|
|
{ |
2177 |
|
|
bufferused = avail; |
2178 |
|
|
} |
2179 |
|
|
gate_mem_copy(&self->buffer[self->buffer_pos], buffer, bufferused); |
2180 |
|
|
self->buffer_pos += bufferused; |
2181 |
|
|
processed = bufferused; |
2182 |
|
|
buffer += processed; |
2183 |
|
|
bufferlength -= processed; |
2184 |
|
|
ret = GATE_RESULT_OK; |
2185 |
|
|
|
2186 |
|
|
if (self->buffer_pos < self->block_size) |
2187 |
|
|
{ |
2188 |
|
|
/* not enough data to fill a complete sector */ |
2189 |
|
|
break; |
2190 |
|
|
} |
2191 |
|
|
|
2192 |
|
|
lba_2_chs(self->block_offset, &self->geometry, &chs); |
2193 |
|
|
result = bios_access_disk_sectors(self->drive_index, &chs, true, &self->buffer[0]); |
2194 |
|
|
if (result != 0) |
2195 |
|
|
{ |
2196 |
|
|
ret = GATE_RESULT_FAILED; |
2197 |
|
|
break; |
2198 |
|
|
} |
2199 |
|
|
++self->block_offset; |
2200 |
|
|
self->buffer_pos = 0; |
2201 |
|
|
gate_mem_clear(&self->buffer[0], self->block_size); |
2202 |
|
|
ret = GATE_RESULT_OK; |
2203 |
|
|
} |
2204 |
|
|
|
2205 |
|
|
if (bufferlength > 0) |
2206 |
|
|
{ |
2207 |
|
|
/* still something in the input buffer: */ |
2208 |
|
|
if (bufferlength < self->block_size) |
2209 |
|
|
{ |
2210 |
|
|
/* not a full sector, but we can internally buffer, what we got */ |
2211 |
|
|
gate_mem_copy(self->buffer, buffer, bufferlength); |
2212 |
|
|
self->buffer_pos = bufferlength; |
2213 |
|
|
processed += bufferlength; |
2214 |
|
|
ret = GATE_RESULT_OK; |
2215 |
|
|
} |
2216 |
|
|
else |
2217 |
|
|
{ |
2218 |
|
|
/* we can write a whole sector, let's do it */ |
2219 |
|
|
lba_2_chs(self->block_offset, &self->geometry, &chs); |
2220 |
|
|
result = bios_access_disk_sectors(self->drive_index, &chs, true, (void*)buffer); |
2221 |
|
|
if (result != 0) |
2222 |
|
|
{ |
2223 |
|
|
/* return state of previous operation (or default-ERROR if no operation was performed) */ |
2224 |
|
|
break; |
2225 |
|
|
} |
2226 |
|
|
++self->block_offset; |
2227 |
|
|
processed += self->block_size; |
2228 |
|
|
ret = GATE_RESULT_OK; |
2229 |
|
|
} |
2230 |
|
|
} |
2231 |
|
|
if (written) |
2232 |
|
|
{ |
2233 |
|
|
*written = processed; |
2234 |
|
|
} |
2235 |
|
|
} while (0); |
2236 |
|
|
return ret; |
2237 |
|
|
} |
2238 |
|
|
static gate_result_t sd_flush(void* obj) |
2239 |
|
|
{ |
2240 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
2241 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2242 |
|
|
bios_chs_t chs; |
2243 |
|
|
unsigned result; |
2244 |
|
|
|
2245 |
|
|
do |
2246 |
|
|
{ |
2247 |
|
|
if (!self->write_access) |
2248 |
|
|
{ |
2249 |
|
|
ret = GATE_RESULT_INVALIDSTATE; |
2250 |
|
|
break; |
2251 |
|
|
} |
2252 |
|
|
|
2253 |
|
|
if (self->buffer_pos != 0) |
2254 |
|
|
{ |
2255 |
|
|
lba_2_chs(self->block_offset, &self->geometry, &chs); |
2256 |
|
|
result = bios_access_disk_sectors(self->drive_index, &chs, true, &self->buffer[0]); |
2257 |
|
|
if (result != 0) |
2258 |
|
|
{ |
2259 |
|
|
ret = GATE_RESULT_FAILED; |
2260 |
|
|
break; |
2261 |
|
|
} |
2262 |
|
|
++self->block_offset; |
2263 |
|
|
self->buffer_pos = 0; |
2264 |
|
|
} |
2265 |
|
|
ret = GATE_RESULT_OK; |
2266 |
|
|
} while (0); |
2267 |
|
|
|
2268 |
|
|
return ret; |
2269 |
|
|
} |
2270 |
|
|
|
2271 |
|
|
static gate_result_t sd_get_resource(void* obj, gate_enumint_t resource_type, gate_uintptr_t* resource) |
2272 |
|
|
{ |
2273 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2274 |
|
|
GATE_UNUSED_ARG(resource_type); |
2275 |
|
|
if (resource) |
2276 |
|
|
{ |
2277 |
|
|
*resource = self->drive_index; |
2278 |
|
|
} |
2279 |
|
|
return GATE_RESULT_OK; |
2280 |
|
|
} |
2281 |
|
|
|
2282 |
|
|
static gate_result_t sd_can_read(void* obj, gate_bool_t* return_value) |
2283 |
|
|
{ |
2284 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2285 |
|
|
if (return_value) |
2286 |
|
|
{ |
2287 |
|
|
*return_value = !self->write_access; |
2288 |
|
|
} |
2289 |
|
|
return GATE_RESULT_OK; |
2290 |
|
|
} |
2291 |
|
|
|
2292 |
|
|
static gate_result_t sd_can_write(void* obj, gate_bool_t* return_value) |
2293 |
|
|
{ |
2294 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2295 |
|
|
if (return_value) |
2296 |
|
|
{ |
2297 |
|
|
*return_value = self->write_access; |
2298 |
|
|
} |
2299 |
|
|
return GATE_RESULT_OK; |
2300 |
|
|
} |
2301 |
|
|
|
2302 |
|
|
static gate_result_t sd_get_size(void* obj, gate_int64_t* return_value) |
2303 |
|
|
{ |
2304 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2305 |
|
|
if (return_value) |
2306 |
|
|
{ |
2307 |
|
|
*return_value = (gate_int64_t)self->block_count * (gate_int64_t)self->block_size; |
2308 |
|
|
} |
2309 |
|
|
return GATE_RESULT_OK; |
2310 |
|
|
} |
2311 |
|
|
|
2312 |
|
|
static gate_result_t sd_get_available(void* obj, gate_int64_t* return_value) |
2313 |
|
|
{ |
2314 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2315 |
|
|
gate_int64_t total = (gate_int64_t)self->block_count * (gate_int64_t)self->block_size; |
2316 |
|
|
gate_int64_t pos = (gate_int64_t)self->block_offset * (gate_int64_t)self->block_size; |
2317 |
|
|
if (self->write_access) |
2318 |
|
|
{ |
2319 |
|
|
pos += self->buffer_pos; |
2320 |
|
|
} |
2321 |
|
|
else |
2322 |
|
|
{ |
2323 |
|
|
pos += (self->block_size - self->buffer_pos); |
2324 |
|
|
} |
2325 |
|
|
if (return_value) |
2326 |
|
|
{ |
2327 |
|
|
*return_value = total - pos; |
2328 |
|
|
} |
2329 |
|
|
return GATE_RESULT_OK; |
2330 |
|
|
} |
2331 |
|
|
|
2332 |
|
|
static gate_result_t sd_seek(void* obj, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position) |
2333 |
|
|
{ |
2334 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
2335 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2336 |
|
|
gate_int64_t pos; |
2337 |
|
|
gate_bool_t need_update = false; |
2338 |
|
|
do |
2339 |
|
|
{ |
2340 |
|
|
/* TODO: Seek inside blocks, currently everything is block-aligned */ |
2341 |
|
|
switch (origin) |
2342 |
|
|
{ |
2343 |
|
|
case GATE_STREAM_SEEK_BEGIN: |
2344 |
|
|
{ |
2345 |
|
|
pos = position; |
2346 |
|
|
need_update = true; |
2347 |
|
|
break; |
2348 |
|
|
} |
2349 |
|
|
case GATE_STREAM_SEEK_CURRENT: |
2350 |
|
|
{ |
2351 |
|
|
pos = (gate_int64_t)self->block_offset * (gate_int64_t)self->block_size + position; |
2352 |
|
|
need_update = (position != 0); |
2353 |
|
|
break; |
2354 |
|
|
} |
2355 |
|
|
case GATE_STREAM_SEEK_END: |
2356 |
|
|
{ |
2357 |
|
|
pos = (gate_int64_t)self->block_count * (gate_int64_t)self->block_size + position; |
2358 |
|
|
need_update = (position != 0); |
2359 |
|
|
break; |
2360 |
|
|
} |
2361 |
|
|
default: |
2362 |
|
|
{ |
2363 |
|
|
ret = GATE_RESULT_INVALIDARG; |
2364 |
|
|
break; |
2365 |
|
|
} |
2366 |
|
|
} |
2367 |
|
|
if (need_update) |
2368 |
|
|
{ |
2369 |
|
|
if (pos < 0) pos = 0; |
2370 |
|
|
self->block_offset = (gate_uint64_t)pos % (gate_uint64_t)self->block_size; |
2371 |
|
|
self->buffer_pos = self->write_access ? 0 : self->block_size; |
2372 |
|
|
pos = (gate_int64_t)self->block_offset * (gate_int64_t)self->block_size; |
2373 |
|
|
} |
2374 |
|
|
if (final_position) |
2375 |
|
|
{ |
2376 |
|
|
*final_position = pos; |
2377 |
|
|
} |
2378 |
|
|
ret = GATE_RESULT_OK; |
2379 |
|
|
} while (0); |
2380 |
|
|
|
2381 |
|
|
return ret; |
2382 |
|
|
} |
2383 |
|
|
|
2384 |
|
|
static gate_result_t sd_reset(void* obj) |
2385 |
|
|
{ |
2386 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2387 |
|
|
self->block_offset = 0; |
2388 |
|
|
self->buffer_pos = self->write_access ? 0 : self->block_size; |
2389 |
|
|
return GATE_RESULT_OK; |
2390 |
|
|
} |
2391 |
|
|
|
2392 |
|
|
static gate_result_t sd_close(void* obj, gate_enumint_t close_type) |
2393 |
|
|
{ |
2394 |
|
|
sd_stream_t* self = (sd_stream_t*)obj; |
2395 |
|
|
GATE_UNUSED_ARG(self); |
2396 |
|
|
GATE_UNUSED_ARG(close_type); |
2397 |
|
|
/* TODO: introduce a close-flag */ |
2398 |
|
|
return GATE_RESULT_OK; |
2399 |
|
|
} |
2400 |
|
|
|
2401 |
|
|
static GATE_INTERFACE_VTBL(gate_controlstream) sd_vtbl; |
2402 |
|
|
|
2403 |
|
|
static void gate_storagedrive_stream_init_vtbl() |
2404 |
|
|
{ |
2405 |
|
|
if (sd_vtbl.get_interface_name == NULL) |
2406 |
|
|
{ |
2407 |
|
|
GATE_INTERFACE_VTBL(gate_controlstream) const local_vtbl = { |
2408 |
|
|
&sd_get_interface_name, |
2409 |
|
|
&sd_release, |
2410 |
|
|
&sd_retain, |
2411 |
|
|
|
2412 |
|
|
&sd_read, |
2413 |
|
|
&sd_peek, |
2414 |
|
|
&sd_write, |
2415 |
|
|
&sd_flush, |
2416 |
|
|
|
2417 |
|
|
&sd_get_resource, |
2418 |
|
|
|
2419 |
|
|
&sd_can_read, |
2420 |
|
|
&sd_can_write, |
2421 |
|
|
&sd_get_size, |
2422 |
|
|
&sd_get_available, |
2423 |
|
|
&sd_seek, |
2424 |
|
|
&sd_reset, |
2425 |
|
|
&sd_close |
2426 |
|
|
}; |
2427 |
|
|
|
2428 |
|
|
sd_vtbl = local_vtbl; |
2429 |
|
|
} |
2430 |
|
|
} |
2431 |
|
|
|
2432 |
|
|
|
2433 |
|
|
gate_result_t gate_storagedrive_openstream(gate_storagedrive_t const* drive, gate_enumint_t open_flags, gate_controlstream_t** stream) |
2434 |
|
|
{ |
2435 |
|
|
gate_result_t ret = GATE_RESULT_FAILED; |
2436 |
|
|
sd_stream_t* ptr_sd = NULL; |
2437 |
|
|
bios_chs_t chs; |
2438 |
|
|
|
2439 |
|
|
do |
2440 |
|
|
{ |
2441 |
|
|
ptr_sd = (sd_stream_t*)gate_mem_alloc(sizeof(sd_stream_t)); |
2442 |
|
|
if (ptr_sd == NULL) |
2443 |
|
|
{ |
2444 |
|
|
ret = GATE_RESULT_FAILED; |
2445 |
|
|
break; |
2446 |
|
|
} |
2447 |
|
|
|
2448 |
|
|
gate_mem_clear(ptr_sd, sizeof(sd_stream_t)); |
2449 |
|
|
gate_storagedrive_stream_init_vtbl(); |
2450 |
|
|
ptr_sd->vtbl = &sd_vtbl; |
2451 |
|
|
gate_atomic_int_init(&ptr_sd->ref_counter, 1); |
2452 |
|
|
ptr_sd->drive_index = (unsigned char)drive->deviceindex; |
2453 |
|
|
bios_get_driveinfo(ptr_sd->drive_index, &chs, NULL); |
2454 |
|
|
gate_mem_copy(&ptr_sd->geometry, &chs, sizeof(chs)); |
2455 |
|
|
ptr_sd->block_offset = 0; |
2456 |
|
|
ptr_sd->block_count = (gate_uint64_t)chs.cylinder * (gate_uint64_t)chs.head * (gate_uint64_t)chs.sector; |
2457 |
|
|
ptr_sd->block_size = 512; |
2458 |
|
|
if (open_flags == GATE_STREAM_OPEN_READ) |
2459 |
|
|
{ |
2460 |
|
|
ptr_sd->write_access = false; |
2461 |
|
|
ptr_sd->buffer_pos = ptr_sd->block_size; |
2462 |
|
|
} |
2463 |
|
|
else if (open_flags == GATE_STREAM_OPEN_WRITE) |
2464 |
|
|
{ |
2465 |
|
|
ptr_sd->write_access = true; |
2466 |
|
|
ptr_sd->buffer_pos = 0; |
2467 |
|
|
} |
2468 |
|
|
else |
2469 |
|
|
{ |
2470 |
|
|
ret = GATE_RESULT_INVALIDARG; |
2471 |
|
|
break; |
2472 |
|
|
} |
2473 |
|
|
|
2474 |
|
|
bios_reset_disk(ptr_sd->drive_index); |
2475 |
|
|
|
2476 |
|
|
if (stream) |
2477 |
|
|
{ |
2478 |
|
|
*stream = (gate_controlstream_t*)ptr_sd; |
2479 |
|
|
ptr_sd = NULL; |
2480 |
|
|
} |
2481 |
|
|
ret = GATE_RESULT_OK; |
2482 |
|
|
} while (0); |
2483 |
|
|
|
2484 |
|
|
if (ptr_sd) |
2485 |
|
|
{ |
2486 |
|
|
gate_object_release(ptr_sd); |
2487 |
|
|
} |
2488 |
|
|
|
2489 |
|
|
return ret; |
2490 |
|
|
} |
2491 |
|
|
|
2492 |
|
|
gate_result_t gate_storagedrive_queryattribs(gate_storagedrive_t const* drive, gate_enumint_t attrib_type, |
2493 |
|
|
gate_storagedrive_attribs_callback_t callback, void* user_param) |
2494 |
|
|
{ |
2495 |
|
|
GATE_UNUSED_ARG(drive); |
2496 |
|
|
GATE_UNUSED_ARG(attrib_type); |
2497 |
|
|
GATE_UNUSED_ARG(callback); |
2498 |
|
|
GATE_UNUSED_ARG(user_param); |
2499 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
2500 |
|
|
} |
2501 |
|
|
|
2502 |
|
|
#endif |
2503 |
|
|
|
2504 |
|
|
|
2505 |
|
|
#if defined(GATE_SYSTEM_STORAGEDRIVES_NO_IMPL) |
2506 |
|
|
|
2507 |
|
|
gate_result_t gate_storagedrive_enum(gate_enumint_t drivetype, gate_storagedrive_enum_callback_t callback, void* user_param) |
2508 |
|
|
{ |
2509 |
|
|
GATE_UNUSED_ARG(drivetype); |
2510 |
|
|
GATE_UNUSED_ARG(callback); |
2511 |
|
|
GATE_UNUSED_ARG(user_param); |
2512 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
2513 |
|
|
} |
2514 |
|
|
|
2515 |
|
|
gate_result_t gate_storagedrive_openstream(gate_storagedrive_t const* drive, gate_enumint_t open_flags, gate_controlstream_t** stream) |
2516 |
|
|
{ |
2517 |
|
|
GATE_UNUSED_ARG(drive); |
2518 |
|
|
GATE_UNUSED_ARG(open_flags); |
2519 |
|
|
GATE_UNUSED_ARG(stream); |
2520 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
2521 |
|
|
} |
2522 |
|
|
|
2523 |
|
|
gate_result_t gate_storagedrive_queryattribs(gate_storagedrive_t const* drive, gate_enumint_t attrib_type, |
2524 |
|
|
gate_storagedrive_attribs_callback_t callback, void* user_param) |
2525 |
|
|
{ |
2526 |
|
|
GATE_UNUSED_ARG(drive); |
2527 |
|
|
GATE_UNUSED_ARG(attrib_type); |
2528 |
|
|
GATE_UNUSED_ARG(callback); |
2529 |
|
|
GATE_UNUSED_ARG(user_param); |
2530 |
|
|
return GATE_RESULT_NOTIMPLEMENTED; |
2531 |
|
|
} |
2532 |
|
|
|
2533 |
|
|
|
2534 |
|
|
#endif /* GATE_SYSTEM_STORAGEDRIVES_NO_IMPL */ |
2535 |
|
|
|
2536 |
|
|
|