2 * Copyright 2006-2011, Axel Dörfler, axeld@pinc-software.de.
3 * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Distributed under the terms of the MIT License.
8 #include "KDiskDevice.h"
15 #include <KernelExport.h>
18 #include "ddm_userland_interface.h"
19 #include "KDiskDeviceUtils.h"
21 #include "UserDataWriter.h"
30 KDiskDevice::KDiskDevice(partition_id id
)
37 rw_lock_init(&fLocker
, "disk device");
41 fPublishedName
= (char*)"raw";
45 KDiskDevice::~KDiskDevice()
52 KDiskDevice::SetTo(const char* path
)
54 // check initialization and parameter
55 status_t error
= InitCheck();
62 error
= set_string(fDeviceData
.path
, path
);
66 fFD
= open(path
, O_RDONLY
);
70 error
= GetMediaStatus(&fMediaStatus
);
73 if (fMediaStatus
== B_DEV_MEDIA_CHANGED
)
75 // get device geometry
76 if (fMediaStatus
== B_OK
) {
77 error
= GetGeometry(&fDeviceData
.geometry
);
81 // no media present: reset the geometry
87 // update partition data
100 fMediaStatus
= B_ERROR
;
102 fDeviceData
.flags
= 0;
103 if (fDeviceData
.path
) {
104 free(fDeviceData
.path
);
105 fDeviceData
.path
= NULL
;
112 KDiskDevice::InitCheck() const
119 KDiskDevice::ReadLock()
121 return rw_lock_read_lock(&fLocker
) == B_OK
;
126 KDiskDevice::ReadUnlock()
128 rw_lock_read_unlock(&fLocker
);
133 KDiskDevice::WriteLock()
135 return rw_lock_write_lock(&fLocker
) == B_OK
;
140 KDiskDevice::WriteUnlock()
142 rw_lock_write_unlock(&fLocker
);
147 KDiskDevice::SetID(partition_id id
)
149 KPartition::SetID(id
);
155 KDiskDevice::PublishDevice()
157 // PublishDevice(), UnpublishDevice() and Republish are no-ops
158 // for KDiskDevices, since they are always published.
164 KDiskDevice::UnpublishDevice()
166 // PublishDevice(), UnpublishDevice() and Republish are no-ops
167 // for KDiskDevices, since they are always published.
173 KDiskDevice::RepublishDevice()
175 // PublishDevice(), UnpublishDevice() and Republish are no-ops
176 // for KDiskDevices, since they are always published.
182 KDiskDevice::SetDeviceFlags(uint32 flags
)
184 fDeviceData
.flags
= flags
;
189 KDiskDevice::DeviceFlags() const
191 return fDeviceData
.flags
;
196 KDiskDevice::IsReadOnlyMedia() const
198 return fDeviceData
.geometry
.read_only
;
203 KDiskDevice::IsWriteOnce() const
205 return fDeviceData
.geometry
.write_once
;
210 KDiskDevice::IsRemovable() const
212 return fDeviceData
.geometry
.removable
;
217 KDiskDevice::HasMedia() const
219 return fMediaStatus
== B_OK
|| fMediaStatus
== B_DEV_MEDIA_CHANGED
;
224 KDiskDevice::MediaChanged() const
226 return fMediaStatus
== B_DEV_MEDIA_CHANGED
;
231 KDiskDevice::UpdateMediaStatusIfNeeded()
233 // TODO: allow a device to notify us about its media status!
234 // This will then also need to clear any B_DEV_MEDIA_CHANGED
235 GetMediaStatus(&fMediaStatus
);
240 KDiskDevice::UninitializeMedia()
242 UninitializeContents();
244 _UpdateDeviceFlags();
245 _InitPartitionData();
250 KDiskDevice::UpdateGeometry()
252 if (GetGeometry(&fDeviceData
.geometry
) != B_OK
)
255 _UpdateDeviceFlags();
256 _InitPartitionData();
261 KDiskDevice::SetPath(const char* path
)
263 return set_string(fDeviceData
.path
, path
);
268 KDiskDevice::Path() const
270 return fDeviceData
.path
;
275 KDiskDevice::GetFileName(char* buffer
, size_t size
) const
277 if (strlcpy(buffer
, "raw", size
) >= size
)
278 return B_NAME_TOO_LONG
;
284 KDiskDevice::GetPath(KPath
* path
) const
286 if (!path
|| path
->InitCheck() != B_OK
)
288 if (!fDeviceData
.path
)
290 return path
->SetPath(fDeviceData
.path
);
295 KDiskDevice::SetFD(int fd
)
302 KDiskDevice::FD() const
309 KDiskDevice::DeviceData()
315 const disk_device_data
*
316 KDiskDevice::DeviceData() const
323 KDiskDevice::WriteUserData(UserDataWriter
& writer
, user_partition_data
* data
)
325 return KPartition::WriteUserData(writer
, data
);
330 KDiskDevice::WriteUserData(UserDataWriter
& writer
)
332 KPartition
* partition
= this;
333 user_disk_device_data
* data
334 = writer
.AllocateDeviceData(partition
->CountChildren());
335 char* path
= writer
.PlaceString(Path());
337 data
->device_flags
= DeviceFlags();
339 writer
.AddRelocationEntry(&data
->path
);
340 partition
->WriteUserData(writer
, &data
->device_partition_data
);
342 partition
->WriteUserData(writer
, NULL
);
347 KDiskDevice::Dump(bool deep
, int32 level
)
349 OUT("device %" B_PRId32
": %s\n", ID(), Path());
350 OUT(" media status: %s\n", strerror(fMediaStatus
));
351 OUT(" device flags: %" B_PRIx32
"\n", DeviceFlags());
352 if (fMediaStatus
== B_OK
)
353 KPartition::Dump(deep
, 0);
358 KDiskDevice::GetMediaStatus(status_t
* mediaStatus
)
360 status_t error
= B_OK
;
361 if (ioctl(fFD
, B_GET_MEDIA_STATUS
, mediaStatus
) != 0)
363 // maybe the device driver doesn't implement this ioctl -- see, if getting
364 // the device geometry succeeds
366 device_geometry geometry
;
367 if (GetGeometry(&geometry
) == B_OK
) {
368 // if the device is not removable, we can ignore the failed ioctl
369 // and return a media status of B_OK
370 if (!geometry
.removable
) {
381 KDiskDevice::GetGeometry(device_geometry
* geometry
)
383 if (ioctl(fFD
, B_GET_GEOMETRY
, geometry
) != 0)
390 KDiskDevice::_InitPartitionData()
392 fDeviceData
.id
= fPartitionData
.id
;
393 fPartitionData
.block_size
= fDeviceData
.geometry
.bytes_per_sector
;
394 fPartitionData
.offset
= 0;
395 fPartitionData
.size
= (off_t
)fPartitionData
.block_size
396 * fDeviceData
.geometry
.sectors_per_track
397 * fDeviceData
.geometry
.cylinder_count
398 * fDeviceData
.geometry
.head_count
;
399 fPartitionData
.flags
|= B_PARTITION_IS_DEVICE
;
401 char name
[B_FILE_NAME_LENGTH
];
402 if (ioctl(fFD
, B_GET_DEVICE_NAME
, name
, sizeof(name
)) == B_OK
)
403 fPartitionData
.name
= strdup(name
);
408 KDiskDevice::_ResetGeometry()
410 fDeviceData
.geometry
.bytes_per_sector
= 0;
411 fDeviceData
.geometry
.sectors_per_track
= 0;
412 fDeviceData
.geometry
.cylinder_count
= 0;
413 fDeviceData
.geometry
.head_count
= 0;
414 fDeviceData
.geometry
.device_type
= B_DISK
;
415 fDeviceData
.geometry
.removable
= true;
416 fDeviceData
.geometry
.read_only
= true;
417 fDeviceData
.geometry
.write_once
= false;
422 KDiskDevice::_UpdateDeviceFlags()
424 if (fDeviceData
.geometry
.removable
)
425 SetDeviceFlags(DeviceFlags() | B_DISK_DEVICE_REMOVABLE
);
427 SetDeviceFlags(DeviceFlags() | B_DISK_DEVICE_HAS_MEDIA
);
429 SetDeviceFlags(DeviceFlags() & ~B_DISK_DEVICE_HAS_MEDIA
);
431 if (fDeviceData
.geometry
.read_only
)
432 SetDeviceFlags(DeviceFlags() | B_DISK_DEVICE_READ_ONLY
);
433 if (fDeviceData
.geometry
.write_once
)
434 SetDeviceFlags(DeviceFlags() | B_DISK_DEVICE_WRITE_ONCE
);