diff --git a/headers/build/os/drivers/Drivers.h b/headers/build/os/drivers/Drivers.h index 2093eac83c..fa506ea0b3 100644 --- a/headers/build/os/drivers/Drivers.h +++ b/headers/build/os/drivers/Drivers.h @@ -144,6 +144,7 @@ typedef struct { bool removable; /* non-zero if removable */ bool read_only; /* non-zero if read only */ bool write_once; /* non-zero if write-once */ + uint32 bytes_per_physical_sector; /* physical sector size in bytes */ } device_geometry; @@ -174,6 +175,7 @@ typedef struct { off_t offset; /* offset (in bytes) */ off_t size; /* size (in bytes) */ int32 logical_block_size; /* logical block size of partition */ + int32 physical_block_size; /* physical block size of partition */ int32 session; /* id of session */ int32 partition; /* id of partition */ char device[256]; /* path to the physical device */ diff --git a/headers/os/drivers/Drivers.h b/headers/os/drivers/Drivers.h index a854305b38..ec7d7fd2bd 100644 --- a/headers/os/drivers/Drivers.h +++ b/headers/os/drivers/Drivers.h @@ -130,6 +130,7 @@ typedef struct { bool removable; /* non-zero if removable */ bool read_only; /* non-zero if read only */ bool write_once; /* non-zero if write-once */ + uint32 bytes_per_physical_sector; /* physical sector size in bytes */ } device_geometry; enum { @@ -151,6 +152,7 @@ typedef struct { off_t offset; /* offset (in bytes) */ off_t size; /* size (in bytes) */ int32 logical_block_size; /* logical block size of partition */ + int32 physical_block_size; /* physical block size of partition */ int32 session; /* id of session */ int32 partition; /* id of partition */ char device[256]; /* path to the physical device */ diff --git a/headers/os/drivers/disk_device_manager.h b/headers/os/drivers/disk_device_manager.h index 17c1b782c2..6d3508cff4 100644 --- a/headers/os/drivers/disk_device_manager.h +++ b/headers/os/drivers/disk_device_manager.h @@ -25,6 +25,7 @@ typedef struct partition_data { off_t size; off_t content_size; uint32 block_size; + uint32 physical_block_size; int32 child_count; int32 index; // [sys] uint32 status; diff --git a/headers/private/drivers/scsi_periph.h b/headers/private/drivers/scsi_periph.h index a6e78f2a37..e2ad93cbd1 100644 --- a/headers/private/drivers/scsi_periph.h +++ b/headers/private/drivers/scsi_periph.h @@ -63,7 +63,7 @@ typedef struct scsi_periph_callbacks { // informs of new size of medium // (set to NULL if not a block device) void (*set_capacity)(periph_device_cookie cookie, uint64 capacity, - uint32 blockSize); + uint32 blockSize, uint32 physicalBlockSize); // *** removable devices // called when media got changed (can be NULL if medium is not changable) diff --git a/headers/private/kernel/disk_device_manager/KPartition.h b/headers/private/kernel/disk_device_manager/KPartition.h index 577d23a893..9b43d7f0db 100644 --- a/headers/private/kernel/disk_device_manager/KPartition.h +++ b/headers/private/kernel/disk_device_manager/KPartition.h @@ -70,6 +70,9 @@ public: void SetBlockSize(uint32 blockSize); uint32 BlockSize() const; + void SetPhysicalBlockSize(uint32 blockSize); + uint32 PhysicalBlockSize() const; + void SetIndex(int32 index); int32 Index() const; // 0 for devices diff --git a/headers/private/storage/Partition.h b/headers/private/storage/Partition.h index aff04da79c..8f49a0ccc9 100644 --- a/headers/private/storage/Partition.h +++ b/headers/private/storage/Partition.h @@ -38,6 +38,7 @@ public: off_t Size() const; off_t ContentSize() const; // 0 if uninitialized uint32 BlockSize() const; + uint32 PhysicalBlockSize() const; int32 Index() const; // 0 for devices uint32 Status() const; diff --git a/headers/private/system/ddm_userland_interface_defs.h b/headers/private/system/ddm_userland_interface_defs.h index df6c5388a1..8bc493c3da 100644 --- a/headers/private/system/ddm_userland_interface_defs.h +++ b/headers/private/system/ddm_userland_interface_defs.h @@ -22,6 +22,7 @@ struct user_partition_data { off_t size; off_t content_size; uint32 block_size; + uint32 physical_block_size; uint32 status; uint32 flags; dev_t volume; diff --git a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp index ae8fd000e3..8a043e7e26 100644 --- a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp @@ -608,7 +608,7 @@ mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length) case B_GET_GEOMETRY: { - if (buffer == NULL || length < sizeof(device_geometry)) + if (buffer == NULL || length > sizeof(device_geometry)) return B_BAD_VALUE; if (info->geometry.bytes_per_sector == 0) { @@ -619,8 +619,7 @@ mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length) } } - return user_memcpy(buffer, &info->geometry, - sizeof(device_geometry)); + return user_memcpy(buffer, &info->geometry, length); } case B_GET_ICON_NAME: diff --git a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp index 486ffd5ba1..4db54c91df 100644 --- a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp @@ -116,6 +116,7 @@ get_geometry(nvme_disk_handle* handle, device_geometry* geometry) nvme_disk_driver_info* info = handle->info; devfs_compute_geometry_size(geometry, info->capacity, info->block_size); + geometry->bytes_per_physical_sector = info->block_size; geometry->device_type = B_DISK; geometry->removable = false; @@ -950,7 +951,7 @@ nvme_disk_ioctl(void* cookie, uint32 op, void* buffer, size_t length) case B_GET_GEOMETRY: { - if (buffer == NULL /*|| length != sizeof(device_geometry)*/) + if (buffer == NULL || length > sizeof(device_geometry)) return B_BAD_VALUE; device_geometry geometry; @@ -958,7 +959,7 @@ nvme_disk_ioctl(void* cookie, uint32 op, void* buffer, size_t length) if (status != B_OK) return status; - return user_memcpy(buffer, &geometry, sizeof(device_geometry)); + return user_memcpy(buffer, &geometry, length); } case B_GET_ICON_NAME: diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp index 60ad4e0e65..c1c265d9d1 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp @@ -131,7 +131,7 @@ test_capacity(cd_driver_info *info) PAGE_STATE_WIRED | VM_PAGE_ALLOC_BUSY); entries[numEntries].address = page->physical_page_number * B_PAGE_SIZE; - entries[numEntries].size = bytes;; + entries[numEntries].size = bytes; left -= bytes; } @@ -207,6 +207,7 @@ get_geometry(cd_handle *handle, device_geometry *geometry) return B_DEV_MEDIA_CHANGED; devfs_compute_geometry_size(geometry, info->capacity, info->block_size); + geometry->bytes_per_physical_sector = info->physical_block_size; geometry->device_type = info->device_type; geometry->removable = info->removable; @@ -843,7 +844,7 @@ cd_ioctl(void* cookie, uint32 op, void* buffer, size_t length) case B_GET_GEOMETRY: { - if (buffer == NULL /*|| length != sizeof(device_geometry)*/) + if (buffer == NULL || length > sizeof(device_geometry)) return B_BAD_VALUE; device_geometry geometry; @@ -851,7 +852,7 @@ cd_ioctl(void* cookie, uint32 op, void* buffer, size_t length) if (status != B_OK) return status; - return user_memcpy(buffer, &geometry, sizeof(device_geometry)); + return user_memcpy(buffer, &geometry, length); } case B_GET_ICON_NAME: @@ -955,7 +956,7 @@ cd_ioctl(void* cookie, uint32 op, void* buffer, size_t length) static void -cd_set_capacity(cd_driver_info* info, uint64 capacity, uint32 blockSize) +cd_set_capacity(cd_driver_info* info, uint64 capacity, uint32 blockSize, uint32 physicalBlockSize) { TRACE("cd_set_capacity(info = %p, capacity = %Ld, blockSize = %ld)\n", info, capacity, blockSize); @@ -1006,6 +1007,7 @@ cd_set_capacity(cd_driver_info* info, uint64 capacity, uint32 blockSize) info->io_scheduler->SetCallback(do_io, info); info->block_size = blockSize; + info->physical_block_size = physicalBlockSize; } if (info->original_capacity != capacity && info->io_scheduler != NULL) { @@ -1036,7 +1038,7 @@ cd_media_changed(cd_driver_info* info, scsi_ccb* request) scsi_periph_callbacks callbacks = { - (void (*)(periph_device_cookie, uint64, uint32))cd_set_capacity, + (void (*)(periph_device_cookie, uint64, uint32, uint32))cd_set_capacity, (void (*)(periph_device_cookie, scsi_ccb *))cd_media_changed }; diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h index 6ee0d26aee..2d0a6ac595 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h @@ -34,6 +34,7 @@ struct cd_driver_info { uint64 capacity; uint64 original_capacity; uint32 block_size; + uint32 physical_block_size; bool removable; uint8 device_type; diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp index eba0d5ccf4..0245e6c54a 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp @@ -99,6 +99,7 @@ get_geometry(das_handle* handle, device_geometry* geometry) return status; devfs_compute_geometry_size(geometry, info->capacity, info->block_size); + geometry->bytes_per_physical_sector = info->physical_block_size; geometry->device_type = B_DISK; geometry->removable = info->removable; @@ -112,10 +113,11 @@ get_geometry(das_handle* handle, device_geometry* geometry) geometry->write_once = false; TRACE("scsi_disk: get_geometry(): %" B_PRId32 ", %" B_PRId32 ", %" B_PRId32 - ", %" B_PRId32 ", %d, %d, %d, %d\n", geometry->bytes_per_sector, + ", %" B_PRId32 ", %d, %d, %d, %d, %" B_PRId32 "\n", geometry->bytes_per_sector, geometry->sectors_per_track, geometry->cylinder_count, geometry->head_count, geometry->device_type, - geometry->removable, geometry->read_only, geometry->write_once); + geometry->removable, geometry->read_only, geometry->write_once, + geometry->bytes_per_physical_sector); return B_OK; } @@ -403,7 +405,7 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t length) case B_GET_GEOMETRY: { - if (buffer == NULL /*|| length != sizeof(device_geometry)*/) + if (buffer == NULL || length > sizeof(device_geometry)) return B_BAD_VALUE; device_geometry geometry; @@ -411,7 +413,7 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t length) if (status != B_OK) return status; - return user_memcpy(buffer, &geometry, sizeof(device_geometry)); + return user_memcpy(buffer, &geometry, length); } case B_GET_ICON_NAME: @@ -468,7 +470,7 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t length) static void -das_set_capacity(das_driver_info* info, uint64 capacity, uint32 blockSize) +das_set_capacity(das_driver_info* info, uint64 capacity, uint32 blockSize, uint32 physicalBlockSize) { TRACE("das_set_capacity(device = %p, capacity = %" B_PRIu64 ", blockSize = %" B_PRIu32 ")\n", info, capacity, blockSize); @@ -508,6 +510,7 @@ das_set_capacity(das_driver_info* info, uint64 capacity, uint32 blockSize) } info->block_size = blockSize; + info->physical_block_size = physicalBlockSize; } @@ -521,7 +524,7 @@ das_media_changed(das_driver_info *device, scsi_ccb *request) scsi_periph_callbacks callbacks = { - (void (*)(periph_device_cookie, uint64, uint32))das_set_capacity, + (void (*)(periph_device_cookie, uint64, uint32, uint32))das_set_capacity, (void (*)(periph_device_cookie, scsi_ccb *))das_media_changed }; diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.h b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.h index be92f22019..b5c0c36275 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.h +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.h @@ -30,6 +30,7 @@ struct das_driver_info { uint64 capacity; uint32 block_size; + uint32 physical_block_size; bool removable; }; diff --git a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp index f14f0ff57c..30d585c3a3 100644 --- a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp @@ -1196,6 +1196,7 @@ usb_disk_update_capacity_16(device_lun *lun) lun->media_present = true; lun->media_changed = false; lun->block_size = B_BENDIAN_TO_HOST_INT32(parameter.logical_block_length); + lun->physical_block_size = lun->block_size; lun->block_count = B_BENDIAN_TO_HOST_INT64(parameter.last_logical_block_address) + 1; return B_OK; @@ -1248,6 +1249,7 @@ usb_disk_update_capacity(device_lun *lun) lun->media_present = true; lun->media_changed = false; lun->block_size = B_BENDIAN_TO_HOST_INT32(parameter.logical_block_length); + lun->physical_block_size = lun->block_size; lun->block_count = B_BENDIAN_TO_HOST_INT32(parameter.last_logical_block_address) + 1; if (lun->block_count == 0) { @@ -1910,6 +1912,8 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length) case B_GET_GEOMETRY: { + if (buffer == NULL || length > sizeof(device_geometry)) + return B_BAD_VALUE; if (lun->media_changed) { status_t result = usb_disk_update_capacity(lun); if (result != B_OK) @@ -1919,6 +1923,7 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length) device_geometry geometry; devfs_compute_geometry_size(&geometry, lun->block_count, lun->block_size); + geometry.bytes_per_physical_sector = lun->physical_block_size; geometry.device_type = lun->device_type; geometry.removable = lun->removable; @@ -1927,7 +1932,7 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length) TRACE("B_GET_GEOMETRY: %" B_PRId32 " sectors at %" B_PRId32 " bytes per sector\n", geometry.cylinder_count, geometry.bytes_per_sector); - return user_memcpy(buffer, &geometry, sizeof(device_geometry)); + return user_memcpy(buffer, &geometry, length); } case B_FLUSH_DRIVE_CACHE: diff --git a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.h b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.h index 4b2a78bafc..8a5495904f 100644 --- a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.h +++ b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.h @@ -70,6 +70,7 @@ struct device_lun_s { bool media_changed; uint64 block_count; uint32 block_size; + uint32 physical_block_size; uint8 device_type; bool removable; bool write_protected; diff --git a/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c b/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c index ad63193a41..60c853e42d 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c +++ b/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c @@ -588,17 +588,18 @@ status_t nbd_control(cookie_t *cookie, uint32 op, void *data, size_t len) { return EINVAL; case B_GET_GEOMETRY: case B_GET_BIOS_GEOMETRY: - if (data) { - device_geometry *geom = (device_geometry *)data; - geom->bytes_per_sector = BLKSIZE; - geom->sectors_per_track = 1; - geom->cylinder_count = cookie->dev->size / BLKSIZE; - geom->head_count = 1; - geom->device_type = B_DISK; - geom->removable = false; - geom->read_only = cookie->dev->readonly; - geom->write_once = false; - return B_OK; + if (data != NULL && len <= sizeof(device_geometry)) { + device_geometry geometry; + geometry.bytes_per_sector = BLKSIZE; + geometry.sectors_per_track = 1; + geometry.cylinder_count = cookie->dev->size / BLKSIZE; + geometry.head_count = 1; + geometry.device_type = B_DISK; + geometry.removable = false; + geometry.read_only = cookie->dev->readonly; + geometry.write_once = false; + geometry.bytes_per_physical_sector = BLKSIZE; + return user_memcpy(data, &geometry, len); } return EINVAL; case B_GET_MEDIA_STATUS: diff --git a/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp b/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp index 0b09ecc510..ae9e38383c 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp @@ -1435,6 +1435,9 @@ ram_disk_raw_device_control(void* _cookie, uint32 op, void* buffer, case B_GET_GEOMETRY: case B_GET_BIOS_GEOMETRY: { + if (buffer == NULL || length > sizeof(device_geometry)) + return B_BAD_VALUE; + device_geometry geometry; geometry.bytes_per_sector = B_PAGE_SIZE; geometry.sectors_per_track = 1; @@ -1446,8 +1449,9 @@ ram_disk_raw_device_control(void* _cookie, uint32 op, void* buffer, geometry.removable = true; geometry.read_only = false; geometry.write_once = false; + geometry.bytes_per_physical_sector = B_PAGE_SIZE; - return user_memcpy(buffer, &geometry, sizeof(device_geometry)); + return user_memcpy(buffer, &geometry, length); } case B_GET_MEDIA_STATUS: diff --git a/src/add-ons/kernel/drivers/disk/virtual/remote_disk/remote_disk.cpp b/src/add-ons/kernel/drivers/disk/virtual/remote_disk/remote_disk.cpp index 193811c081..f7d1c96e6e 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/remote_disk/remote_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/virtual/remote_disk/remote_disk.cpp @@ -100,6 +100,7 @@ struct RemoteDiskDevice : recursive_lock { geometry->removable = true; geometry->read_only = remoteDisk->IsReadOnly(); geometry->write_once = false; + geometry->bytes_per_physical_sector = REMOTE_DISK_BLOCK_SIZE; } }; @@ -247,17 +248,15 @@ remote_disk_control(void* cookie, uint32 op, void* arg, size_t len) return B_BAD_VALUE; } - case B_GET_GEOMETRY: - TRACE(("remote_disk: B_GET_GEOMETRY\n")); - device->GetGeometry((device_geometry*)arg, false); - return B_OK; - case B_GET_BIOS_GEOMETRY: - { - TRACE(("remote_disk: B_GET_BIOS_GEOMETRY\n")); - device->GetGeometry((device_geometry*)arg, true); - return B_OK; - } + case B_GET_GEOMETRY: + TRACE(("remote_disk: %s\n", + op == B_GET_BIOS_GEOMETRY ? "B_GET_BIOS_GEOMETRY" : "B_GET_GEOMETRY")); + if (buffer == NULL || length > sizeof(device_geometry)) + return B_BAD_VALUE; + device_geometry geometry; + device->GetGeometry(&geometry, op == B_GET_BIOS_GEOMETRY); + return user_memcpy(buffer, &geometry, length); case B_GET_MEDIA_STATUS: TRACE(("remote_disk: B_GET_MEDIA_STATUS\n")); diff --git a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp index 835694c0b8..0e7cdcdb10 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp +++ b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp @@ -130,6 +130,7 @@ get_geometry(virtio_block_handle* handle, device_geometry* geometry) virtio_block_driver_info* info = handle->info; devfs_compute_geometry_size(geometry, info->capacity, info->block_size); + geometry->bytes_per_physical_sector = info->block_size; geometry->device_type = B_DISK; geometry->removable = false; @@ -435,7 +436,7 @@ virtio_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length) case B_GET_GEOMETRY: { - if (buffer == NULL /*|| length != sizeof(device_geometry)*/) + if (buffer == NULL || length > sizeof(device_geometry)) return B_BAD_VALUE; device_geometry geometry; @@ -443,7 +444,7 @@ virtio_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length) if (status != B_OK) return status; - return user_memcpy(buffer, &geometry, sizeof(device_geometry)); + return user_memcpy(buffer, &geometry, length); } case B_GET_ICON_NAME: diff --git a/src/add-ons/kernel/generic/scsi_periph/block.cpp b/src/add-ons/kernel/generic/scsi_periph/block.cpp index e9b4d2dc73..92cb1fad8e 100644 --- a/src/add-ons/kernel/generic/scsi_periph/block.cpp +++ b/src/add-ons/kernel/generic/scsi_periph/block.cpp @@ -38,8 +38,9 @@ struct CapacityInfo { bool capacityFilled; uint64 lastLba; uint32 blockSize; + uint32 physicalBlockSize; - // Provisioining info from READ CAPACITY + // Provisioning info from READ CAPACITY bool provisioningFilled; bool lbpme; bool lbprz; @@ -135,6 +136,7 @@ read_capacity_10(scsi_periph_device_info* device, scsi_ccb* request, = (uint32)B_BENDIAN_TO_HOST_INT32(capacityResult.lba); capacityInfo->blockSize = B_BENDIAN_TO_HOST_INT32(capacityResult.block_size); + capacityInfo->physicalBlockSize = capacityInfo->blockSize; } return res; @@ -177,6 +179,8 @@ read_capacity_16(scsi_periph_device_info* device, scsi_ccb* request, = B_BENDIAN_TO_HOST_INT64(capacityLongResult.lba); capacityInfo->blockSize = B_BENDIAN_TO_HOST_INT32(capacityLongResult.block_size); + capacityInfo->physicalBlockSize = capacityInfo->blockSize + * (1 << capacityLongResult.logical_blocks_per_physical_block_exponent); } if (res == B_OK && request->data_resid @@ -359,14 +363,16 @@ periph_check_capacity(scsi_periph_device_info* device, scsi_ccb* request) } uint64 capacity; - uint32 blockSize; + uint32 blockSize, physicalBlockSize; if (capacityInfo.capacityFilled) { capacity = capacityInfo.lastLba + 1; blockSize = capacityInfo.blockSize; + physicalBlockSize = capacityInfo.physicalBlockSize; } else { capacity = 0; blockSize = 0; + physicalBlockSize = 0; } enum trim_command unmapCommand = TRIM_NONE; @@ -435,9 +441,10 @@ periph_check_capacity(scsi_periph_device_info* device, scsi_ccb* request) device->max_unmap_descriptor_count = maxDescriptorCount; device->block_size = blockSize; + device->physical_block_size = physicalBlockSize; device->callbacks->set_capacity(device->periph_device, - capacity, blockSize); + capacity, blockSize, physicalBlockSize); /* device->byte2blk_shift = log2( device->block_size ); if( device->byte2blk_shift < 0 ) { diff --git a/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h index 8a25e1f5b9..932f323567 100644 --- a/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h +++ b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h @@ -41,6 +41,7 @@ typedef struct scsi_periph_device_info { uint32 max_unmap_descriptor_count; // max. number of ranges in one command uint32 block_size; + uint32 physical_block_size; int32 preferred_ccb_size; int32 rw10_enabled; // 10 byte r/w commands supported; access must be atomic int32 next_tag_action; // queuing flag for next r/w command; access must be atomic diff --git a/src/kits/storage/disk_device/MutablePartition.cpp b/src/kits/storage/disk_device/MutablePartition.cpp index 3c2325cfe5..75d96f17d6 100644 --- a/src/kits/storage/disk_device/MutablePartition.cpp +++ b/src/kits/storage/disk_device/MutablePartition.cpp @@ -583,6 +583,7 @@ BMutablePartition::Init(const user_partition_data* partitionData, fData->size = partitionData->size; fData->content_size = partitionData->content_size; fData->block_size = partitionData->block_size; + fData->physical_block_size = partitionData->physical_block_size; fData->status = partitionData->status; fData->flags = partitionData->flags; fData->volume = partitionData->volume; diff --git a/src/kits/storage/disk_device/Partition.cpp b/src/kits/storage/disk_device/Partition.cpp index a7158dba7a..c31be1c77d 100644 --- a/src/kits/storage/disk_device/Partition.cpp +++ b/src/kits/storage/disk_device/Partition.cpp @@ -141,6 +141,16 @@ BPartition::BlockSize() const } +/*! \brief Returns the physical block size of the device. + \return The physical block size of the device in bytes. +*/ +uint32 +BPartition::PhysicalBlockSize() const +{ + return _PartitionData()->physical_block_size; +} + + /*! \brief Returns the index of the partition in its session's list of partitions. \return The index of the partition in its session's list of partitions. @@ -1353,6 +1363,7 @@ BPartition::_Update(user_partition_data* data, bool* updated) if (data->offset != oldData->offset || data->size != oldData->size || data->block_size != oldData->block_size + || data->physical_block_size != oldData->physical_block_size || data->status != oldData->status || data->flags != oldData->flags || data->volume != oldData->volume diff --git a/src/system/kernel/disk_device_manager/KDiskDevice.cpp b/src/system/kernel/disk_device_manager/KDiskDevice.cpp index 1756026497..a2c71cb983 100644 --- a/src/system/kernel/disk_device_manager/KDiskDevice.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDevice.cpp @@ -391,6 +391,7 @@ KDiskDevice::_InitPartitionData() { fDeviceData.id = fPartitionData.id; fPartitionData.block_size = fDeviceData.geometry.bytes_per_sector; + fPartitionData.physical_block_size = fDeviceData.geometry.bytes_per_physical_sector; fPartitionData.offset = 0; fPartitionData.size = (off_t)fPartitionData.block_size * fDeviceData.geometry.sectors_per_track diff --git a/src/system/kernel/disk_device_manager/KPartition.cpp b/src/system/kernel/disk_device_manager/KPartition.cpp index cfe4263c3a..1679367d80 100644 --- a/src/system/kernel/disk_device_manager/KPartition.cpp +++ b/src/system/kernel/disk_device_manager/KPartition.cpp @@ -73,6 +73,7 @@ KPartition::KPartition(partition_id id) fPartitionData.size = 0; fPartitionData.content_size = 0; fPartitionData.block_size = 0; + fPartitionData.physical_block_size = 0; fPartitionData.child_count = 0; fPartitionData.index = -1; fPartitionData.status = B_PARTITION_UNRECOGNIZED; @@ -202,6 +203,7 @@ KPartition::PublishDevice() info.offset = Offset(); info.size = Size(); info.logical_block_size = BlockSize(); + info.physical_block_size = PhysicalBlockSize(); info.session = 0; info.partition = ID(); if (strlcpy(info.device, Device()->Path(), sizeof(info.device)) @@ -453,6 +455,21 @@ KPartition::BlockSize() const } +uint32 +KPartition::PhysicalBlockSize() const +{ + return fPartitionData.physical_block_size; +} + + +void +KPartition::SetPhysicalBlockSize(uint32 blockSize) +{ + if (fPartitionData.physical_block_size != blockSize) + fPartitionData.physical_block_size = blockSize; +} + + void KPartition::SetIndex(int32 index) { @@ -870,6 +887,7 @@ KPartition::AddChild(KPartition* partition, int32 index) partition->SetParent(this); partition->SetDevice(Device()); + partition->SetPhysicalBlockSize(PhysicalBlockSize()); // publish to devfs partition->PublishDevice(); @@ -1271,6 +1289,7 @@ KPartition::WriteUserData(UserDataWriter& writer, user_partition_data* data) data->size = Size(); data->content_size = ContentSize(); data->block_size = BlockSize(); + data->physical_block_size = PhysicalBlockSize(); data->status = Status(); data->flags = Flags(); data->volume = VolumeID(); @@ -1322,6 +1341,7 @@ KPartition::Dump(bool deep, int32 level) Size() / (1024.0*1024)); OUT("%s content size: %" B_PRIdOFF "\n", prefix, ContentSize()); OUT("%s block size: %" B_PRIu32 "\n", prefix, BlockSize()); + OUT("%s physical block size: %" B_PRIu32 "\n", prefix, PhysicalBlockSize()); OUT("%s child count: %" B_PRId32 "\n", prefix, CountChildren()); OUT("%s index: %" B_PRId32 "\n", prefix, Index()); OUT("%s status: %" B_PRIu32 "\n", prefix, Status());