2 * Copyright 2007, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
8 #include <KernelExport.h>
12 #include <util/AutoLock.h>
13 #include <util/kernel_cpp.h>
15 #include "RemoteDisk.h"
18 //#define TRACE_REMOTE_DISK
19 #ifdef TRACE_REMOTE_DISK
20 # define TRACE(x) dprintf x
22 # define TRACE(x) do {} while (false)
26 const bigtime_t kInitRetryDelay
= 10 * 1000000LL; // 10 s
33 struct RemoteDiskDevice
: recursive_lock
{
34 RemoteDisk
* remoteDisk
;
35 bigtime_t lastInitRetryTime
;
52 recursive_lock_init(this, "remote disk device");
58 recursive_lock_destroy(this);
61 status_t
LazyInitDisk()
66 // don't try to init, if the last attempt wasn't long enough ago
67 if (lastInitRetryTime
>= 0
68 && system_time() < lastInitRetryTime
+ kInitRetryDelay
) {
73 remoteDisk
= new(nothrow
) RemoteDisk
;
75 lastInitRetryTime
= system_time();
80 TRACE(("remote_disk: FindAnyRemoteDisk()\n"));
81 status_t error
= remoteDisk
->FindAnyRemoteDisk();
85 lastInitRetryTime
= system_time();
92 void GetGeometry(device_geometry
* geometry
, bool bios
)
94 // TODO: Respect "bios" argument!
95 geometry
->bytes_per_sector
= REMOTE_DISK_BLOCK_SIZE
;
96 geometry
->sectors_per_track
= 1;
97 geometry
->cylinder_count
= remoteDisk
->Size() / REMOTE_DISK_BLOCK_SIZE
;
98 geometry
->head_count
= 1;
99 geometry
->device_type
= B_DISK
;
100 geometry
->removable
= true;
101 geometry
->read_only
= remoteDisk
->IsReadOnly();
102 geometry
->write_once
= false;
106 typedef RecursiveLocker DeviceLocker
;
109 static const char* kPublishedNames
[] = {
110 "disk/virtual/remote_disk/0/raw",
111 // "misc/remote_disk_control",
115 static RemoteDiskDevice
* sDevices
;
118 // #pragma mark - internal functions
122 static RemoteDiskDevice
*
123 device_for_name(const char* name
)
125 for (int i
= 0; i
< MAX_REMOTE_DISKS
; i
++) {
126 if (strcmp(name
, kPublishedNames
[i
]) == 0)
133 // #pragma mark - data device hooks
137 remote_disk_open(const char* name
, uint32 flags
, void** cookie
)
139 RemoteDiskDevice
* device
= device_for_name(name
);
140 TRACE(("remote_disk_open(\"%s\") -> %p\n", name
, device
));
144 DeviceLocker
locker(device
);
145 status_t error
= device
->LazyInitDisk();
156 remote_disk_close(void* cookie
)
158 TRACE(("remote_disk_close(%p)\n", cookie
));
166 remote_disk_read(void* cookie
, off_t position
, void* buffer
, size_t* numBytes
)
168 TRACE(("remote_disk_read(%p, %lld, %p, %lu)\n", cookie
, position
, buffer
,
171 RemoteDiskDevice
* device
= (RemoteDiskDevice
*)cookie
;
172 DeviceLocker
locker(device
);
174 ssize_t bytesRead
= device
->remoteDisk
->ReadAt(position
, buffer
, *numBytes
);
177 TRACE(("remote_disk_read() failed: %s\n", strerror(bytesRead
)));
181 *numBytes
= bytesRead
;
182 TRACE(("remote_disk_read() done: %ld\n", bytesRead
));
188 remote_disk_write(void* cookie
, off_t position
, const void* buffer
,
191 TRACE(("remote_disk_write(%p, %lld, %p, %lu)\n", cookie
, position
, buffer
,
194 RemoteDiskDevice
* device
= (RemoteDiskDevice
*)cookie
;
195 DeviceLocker
locker(device
);
197 ssize_t bytesWritten
= device
->remoteDisk
->WriteAt(position
, buffer
,
199 if (bytesWritten
< 0) {
201 TRACE(("remote_disk_write() failed: %s\n", strerror(bytesRead
)));
205 *numBytes
= bytesWritten
;
206 TRACE(("remote_disk_written() done: %ld\n", bytesWritten
));
212 remote_disk_control(void* cookie
, uint32 op
, void* arg
, size_t len
)
214 TRACE(("remote_disk_control(%p, %lu, %p, %lu)\n", cookie
, op
, arg
, len
));
216 RemoteDiskDevice
* device
= (RemoteDiskDevice
*)cookie
;
217 DeviceLocker
locker(device
);
221 case B_GET_DEVICE_SIZE
:
222 TRACE(("remote_disk: B_GET_DEVICE_SIZE\n"));
223 *(size_t*)arg
= device
->remoteDisk
->Size();
226 case B_SET_NONBLOCKING_IO
:
227 TRACE(("remote_disk: B_SET_NONBLOCKING_IO\n"));
230 case B_SET_BLOCKING_IO
:
231 TRACE(("remote_disk: B_SET_BLOCKING_IO\n"));
234 case B_GET_READ_STATUS
:
235 TRACE(("remote_disk: B_GET_READ_STATUS\n"));
239 case B_GET_WRITE_STATUS
:
240 TRACE(("remote_disk: B_GET_WRITE_STATUS\n"));
246 TRACE(("remote_disk: B_GET_ICON\n"));
251 TRACE(("remote_disk: B_GET_GEOMETRY\n"));
252 device
->GetGeometry((device_geometry
*)arg
, false);
255 case B_GET_BIOS_GEOMETRY
:
257 TRACE(("remote_disk: B_GET_BIOS_GEOMETRY\n"));
258 device
->GetGeometry((device_geometry
*)arg
, true);
262 case B_GET_MEDIA_STATUS
:
263 TRACE(("remote_disk: B_GET_MEDIA_STATUS\n"));
264 *(status_t
*)arg
= B_NO_ERROR
;
267 case B_SET_UNINTERRUPTABLE_IO
:
268 TRACE(("remote_disk: B_SET_UNINTERRUPTABLE_IO\n"));
271 case B_SET_INTERRUPTABLE_IO
:
272 TRACE(("remote_disk: B_SET_INTERRUPTABLE_IO\n"));
275 case B_FLUSH_DRIVE_CACHE
:
276 TRACE(("remote_disk: B_FLUSH_DRIVE_CACHE\n"));
279 case B_GET_BIOS_DRIVE_ID
:
280 TRACE(("remote_disk: B_GET_BIOS_DRIVE_ID\n"));
284 case B_GET_DRIVER_FOR_DEVICE
:
285 case B_SET_DEVICE_SIZE
:
286 case B_SET_PARTITION
:
287 case B_FORMAT_DEVICE
:
290 case B_GET_NEXT_OPEN_DEVICE
:
291 TRACE(("remote_disk: another ioctl: %lx (%lu)\n", op
, op
));
295 TRACE(("remote_disk: unknown ioctl: %lx (%lu)\n", op
, op
));
302 remote_disk_free(void* cookie
)
304 TRACE(("remote_disk_free(%p)\n", cookie
));
311 static device_hooks sDataDeviceHooks
= {
321 // #pragma mark - public API
324 int32 api_version
= B_CUR_DRIVER_API_VERSION
;
330 TRACE(("remote_disk: init_hardware()\n"));
339 TRACE(("remote_disk: init_driver()\n"));
341 sDevices
= new(nothrow
) RemoteDiskDevice
[MAX_REMOTE_DISKS
];
345 status_t error
= B_OK
;
346 for (int i
= 0; error
== B_OK
&& i
< MAX_REMOTE_DISKS
; i
++)
347 error
= sDevices
[i
].Init();
362 TRACE(("remote_disk: uninit_driver()\n"));
369 publish_devices(void)
371 TRACE(("remote_disk: publish_devices()\n"));
372 return kPublishedNames
;
377 find_device(const char* name
)
379 TRACE(("remote_disk: find_device(%s)\n", name
));
380 return &sDataDeviceHooks
;